VHDL

  • Very high speed integrated circuits Hardware Description Language
    • Describes what the hardware looks like, not what it does
  • Goals
    • Simulation
    • IC synthesis
  • Description is done under the aspects
    • Behavior
    • Structure
    • Hierarchy
    • Parallelism
  • Only synthesizable subset is considered
  • Modern design is done using CAD or EDA (electronic design automation tools)
    • FPGA: Xilinx Vivado, Intel Quartus
    • VLSI: Synopsys DC, Cadence
  • Design Flow
    • Design entry
    • Functional simulation
    • Synthesis (pins and library assignment, compilation)
    • Post-synthesis simulation (timing analysis, verification)
    • Place and route (layout)
    • Fabrication (manufactured) / Bitstream download (FPGA)

Syntax

Prefix

  • Imports libraries made by others
LIBRARY ieee;
USE ieee.std_logic_1164.all;

Entity

  • Wrapper and interface definition
  • Black boxes when viewed from the outside
  • Logic encapsulation of a unit interface
  • Definition: Port X
  • Ports are defined through Identifier, direction, and data-type
    • Direction: in, out, inout, buffer
    • Data-type: bit, std_logic, std_vector, ADT
ENTITY two_gate IS
PORT (
	x1, x2 : IN  std_logic;
	y      : OUT std_logic
);
END two_gate;

Architecture

  • The behavior of an entity
  • Has
    • A unique name
    • Signals and components that can be internally declared
    • Is assigned to a unique entity
ARCHITECTURE two_gate_nand OF two_gate IS
BEGIN
	y <= NOT ( x1 AND x2 );
END two_gate_nand;
  • Operators: AND, OR, NAND, NOR, XOR, XNOR
  • Parallel statements
    • All signal assignments take place simultaneously

Signals

  • A signal defines a connections in hardware
  • Can be used to connect components within an entity
  • A signal has a datatype, which is the possible values and operations on those values
  • Declaration: SIGNAL name1[, name_2, ...] : type;
  • Can be declared in
    • Package
    • Post-section of an entity
    • Declaration section of an entity
  • Assignment: a <= b OR c

Internal signals:

ENTITY Position IS  
PORT(
	A : in std_logic_vector( 2 downto 0 );  
	B : out std_logic_vector( 0 to 2 )
);  
END Position;  
 
ARCHITECTURE behv OF Position IS  
	SIGNAL signal1, signal2: std_logic;  
	SIGNAL signal3 : std_logic_vector(4 downto 0);  
BEGIN  
	signal1 <= A(0) AND B(2);  
	B(0) <= signal1 XOR A(1);  
	...
END behv;

Variables

  • Defines a memory location
  • A variable has a datatype, which is the set of all possible values + operations on those values
    • Declaration: VARIABLE name1[, name2, ...] : type;`` • Declaration can be done exclusively in a process • Assignment: a := b OR c`

Datatypes

  • Define a set of values a signal or a variable can take, along with operations on those values
  • Predefined datatype
    • bit (std_logic): ‘0’, ‘1’
    • bit_vector(std_logic_vector): “00101”, “001001”
    • integer: 10, 123, 56
    • character: ‘a’, ‘v’, ‘n’
    • string: “anmggzem”
    • Boolean: FALSE, TRUE
    • real: 1.23, 234.6, -0.34
  • Usage
    • std_logic
      • U not initialized
      • X unknown
      • 0 Logic 0
      • 1 Logic 1
      • Z high impedance
      • W unknown (weak signal)
      • L logic 0 (weak signal)
      • H Logic 1 (weak signal)
      • - Don’t care
    • std_logic_vector
      • Multiple std_logic stored together
      • Endianness
        • downto MSB first (big endian)
        • to LSB first (little endian)
      • Assignment
        • By position: z_bus(3) <= c_bus(3)
        • Concatenation: z_bus <= A & B & C;
        • Aggregation: z_bus <= (A, B, C);
        • Specifying by element index : z_bus <= (3 => '1', 1 downto 0 => '1', 2 => '0');
        • Others: z_bus <= (others => 0);

Hierarchy

  • Allows us to include components in other components
  • When using an entity in another entity, add it to the start of the architecture definition
architecture structural of fulladd is
	component halfadd is
		port (
			a, b: in bit;
			sum, carry: out bit
		);
	end component;
	component or is
		port (
			a, b: in bit;
			z: out bit
		);
	end component;
	signal i1, i2, i3: bit;
begin
	h1: halfadd port map(a, b, i1, i2);  
	h2: Halfadd port map(cin, i1, sum, i3);  
	or1: or port map(a => i3, b => i2, c => carry);
end structural;
  • can also do it with literal wiring

Process

  • Parallel statements
  • Section (module) in the architecture where instructions execute sequentially
  • Multiple processes in same architecture execute in parallel
-- inside archicture
begin
	[label:] process (x1, x2, ...) -- activate the process on change of any
	begin
		assignments; -- evaluated in parallel
	end process [label];
end;

Control Flow

-- if statements
if cond1 then
	sequential instructions
elsif cond2
	sequential instructios
else cond3
	sequential instructios
end if;
 
-- branching
case object is  
	when value 1 => instructions  
	when value 2 => instructions
	.....  
	when value n => instructions  
end case;
 
-- intervals
case object is  
	when 0 to 2  => instructions  
	when value 1 => instructions  
	.....  
	when value n => instructions  
end case;
 
-- subset
case object is  
	when 0 to 2  => instructions  
	when value 1 => instructions  
	.....  
	when value n => instructions  
	when others  => instructions  
end case;

Events

  • Can detect when a value changes
-- rising edge
((clock'event) AND (clock = '1')
 
-- falling edge
((clock'event) AND (clock = '0')

Implementing

Finite State Machine

architecture behaviour of fsm is
 
TYPE state_type IS ( S0, S1 ) ;  
SIGNAL current_state, next_state: state_type ;  
 
-- find the next state
Comb : PROCESS ( current_state )  
BEGIN  
	CASE current_state IS  
		WHEN S0 => next_state <= S1; 
		WHEN S1 => next_state <= S0; 
	END CASE;  
END PROCESS Comb;
 
-- set the next state when the clock changes
Synch : PROCESS ( CLK, RESET )  
BEGIN  
	IF ( RESET = '1' ) THEN -- define an asynchronous reset  
		CURRENT_STATE <= S0;  
	ELSIF ( CLK'EVENT and CLK = '1' ) THEN  
		CURRENT_STATE <= NEXT_STATE;  
	END IF;  
END PROCESS Synch;
 
end behaviour;

Ripple Carry

architecture ripple_carry of add is  
	constant n : integer := ... ;  
	signal X, Y, S, C : std_logic_vector (n-1 downto 0);  
	signal OVL, CARRY_IN : Std_logic;  
begin  
	for i in 1 to n-1 loop  
		S(i) <= X(i) xor Y(i) xor C(i-1);  
		C(i) <= (X(i) and Y(i)) or (X(i) and C (i-1)) or (Y(i) and C(i-1));  
	end loop;
	  
	S(0) <= X(0) xor Y(0) xor CARRY_IN;  
	C(0) <= (X(0) and Y(0)) or (X(0) and CARRY_IN) or (Y(0) and CARRY_IN);  
	OVL <= C(n-1);  
end ripple_carry;

Sequential Multiplier

constant n : integer := . . .  
variable X, Y : std_logic_vector (n-1 downto 0);  
variable P : std_logic_vector (n-1 downto 0);  
variable C : std_logic;  
begin  
	P :=0 ... 0“; C := ́0 ́  
	for i in 0 to n-1 loop  
		if Y(0) =1then  
			P := (P(n-1 downto 0) + X);  
		else NULL;  
		end if;  
		P := C & P(n-1 downto 1);  
		C := ́0 ́  
		Y := P(0) & Y (n-1 downto 1);  
	end loop;  
end;

Signed

constant n : integer := ...;  
variable P, X, Y : std_logic_vector (n-1 downto 0); variable YS, C : std_logic;  
begin
	P := 0; C := 0; YS := Y (n-1);
	
	for i in 0 to n-1 loop
		if Y (0) = '1' then  
			C & P := (P(n-1 downto n) + X);
		else null;
		end if;
	
		P & Y := (C or P (n-1)) & P & Y (n-1 downto 1);
	end loop;  
	
	if YS =1then
		P := P - X;
	else null;
	end if;
end;

Restoring Division

constant n : integer := . . .;  
	signal X, Y, AC, Q : std_logic_vector (n-1 downto 0); begin
 
	AC <= 0; Q <= X;
	
	for iin1tonloop
		AC & Q <= (AC & Q) sll 1;
		AC <= AC -Y;
		 
		if AC < 0 then
			AC <= AC + Y ; else Q(0) <=1‘ ;
		end if;
	end loop;
end ;
 
-- sll: shift logic left**