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 initializedX
unknown0
Logic 01
Logic 1Z
high impedanceW
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);
- By position:
- std_logic
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) = ‘1‘ then
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 = ‘1‘ then
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**