VHDL


VHDL is:

Comments

Part of a line that comes after a --.

Reserved words

Reference: https://www.seas.upenn.edu/~ese171/vhdl/keywordlist.html (95 words here)

abs access after alias all
and architecture array assert attribute
begin block body buffer bus
case component configuration constant disconnect
downto else elsif end entity
exit file for function generate
generic group guarded if impure
in inertial inout is label
library linkage literal loop map
mod nand new next nor
not null of on open
or others out package port
postponed procedure process pure range
record register reject return rol
ror select severity signal shared
sla sli sra srl subtype
then to transport type unaffected
units until use variable wait
when while with xnor xor

Operators

Concatenation (&)

-- If
a : std_logic_vector (2 downto 0)
b : std_logic_vector (1 downto 0)

-- then
a & b 
-- is of type std_logic_vector (5 downto 0)

Ref: https://www.nandland.com/vhdl/examples/example-concatenation-operator.html

Assignment

<=

assign value to a signal

  • Takes effect in the next cycle.
:=

assign value to a variable

  • Takes effect immediately.

Variables

-- variable var_name : type
variable outvector : std_logic_vector (7 downto 0); 

Records

Syntax:

type <type-name> is record
  <attr1> : <type>;
  <attr2> : <type>;
  ...
  <attrn> : <type>;
end record <type-name>;

Example:

type rec_typ is record
  in_en : std_logic;
  data  : std_logic_vector (7 downto 0);
  out_en: std_logic;
end record rec_typ;

-- use the record
constant inst_rec_type : rec_typ := (in_en  => '0',
                                     data   => '00001001',
                                     out_en => '1);

Another example:

nstate <= (oldver => "00",
           curst => '0');

enum type

type state_t is (IDLE, START, FINISH);

Components

Code that can be reused.

Helps to organize the code.

Reference: link (pdf)

Signals vs variables

Reference

Signal Variable
Assign with <= Assign with :=
Usable inside/outside processes Usable only inside processes
Visible in many processes Visible only in one process
(but assigned only in one)
May get value only on next Immediately gets value on
clock on assignment (in seq circuits) assignment
Easier to sythesize Can be harder to synthesize

Process

Example:

process is
begin
  sign <= sign + 1;
  wait for 10 ns;
end process;

Sensitivity list

others

We can set/reset values of a few bits of a bit-vector and then set/reset the remaining bits to some value at once using others.

bv : std_logic_vector (7 downto 0);
bv <= (2      => '1',
       0      => '1',
       others => '0');
-- bit 2 and 0 are set to 1 and all others to 0.
-- ie, bv now has 00000101 as its value.

Gaisler style

Ref: link

            Combinational
        +-----------------+
 d--→-->|   q = fq(d, r)  |-------> q
    +-->| r_in = fr(d, r) |--→--+
    |   +-----------------+     |
  r ↑                           ↓ r_in
    |   +-----------------+     |
    +-←-|     r = r_in    |--←--+
clk--->-|                 |
        +-----------------+
             Sequential

The sequential component merely copies the value of rin generated by the combinational process to the register at the start of the next clock cycle.

Consider an example of an 8 bit counter, where:

library ieee;
use ieee.std_logic_1164.all;

entity count8 is
  port(
    clk: in std_logic;
    d: in std_logic_vector (7 downto 0);
    q: out std_logic_vector (7 downto 0);
  );
end count8;

architecture count8_arch is
  signal r, r_in : std_logic_vector (7 downto 0);
begin
  comb: process(load, count, d, r) is
    variable tmp : std_logic_vector (7 downto 0);
  begin
    if load = '1' then
      tmp := d;
    elsif count = '1' then
      tmp := r + 1;
    else
      tmp := r;
    end if;
    r_in <= tmp;
    q <= r;
  end process;

  seq: process(clk)
  begin
    if rising_edge(clk) then
      r <= r_in;
    end if;
  end process;
end count8_arch;

We can do the same using record types:

Packages

An example:

-- https://www.ics.uci.edu/~jmoorkan/vhdlref/function.html
package refpack is
  function parity (x : std_logic_vector)
                  return std_logic;
end refpack;

package body refpack is
  function parity (x : std_logic_vector)
                  return std_logic is
  begin
    -- function body
  end parity;

end refpack;

case ('switch') statement

Syntax:

case <expression> is
  when <const> => 
    ...
  when <const> => 
     ...
end case;

Example:

case a_const is
  when "00" =>
    a_var := 0;
  when "01" =>
    a_var := 1;
  when "10" =>
    a_var := 2;
end case;

Procedure

Functions

Syntax:

function function_name (args: arg_types) ret_type is
  declarations
begin
  sequential statements
end function_name;

Example:

-- Boolean NOT
function cust_not (val: std_logic)
                  return std_logic is
begin
  if val = '1' then
    return '0';
  else
    return '1';
  end if;
end function cust_not;

VHDL vs C

VHDL C
elsif else if
= ==
:= & <= =

if statement

Example:

if load = '1' then
  tmp := r + 1;
elsif count = '1' then
  tmp := r - 1;
else
  tmp := 1;
end if;

Loops

-- find first set bit
variable vec : std_logic_vector(7 downto 0);
variable first : natural;

for i in vec'range loop
  if vec(i) = '1' then
    first := i;
    exit;  -- break statement
  end if;
end loop;

std_logic_1164

Operations

Operators available in this package include:

and or xor
nand nor nxor

std_logic_vector

Like an array of std_logic elements.

-- Vector of 8 bits in each case

-- MSB is in the beginning.
-- Better use this form to avoid confusion
signal a : std_logic_vector (7 downto 0);

-- MSB is at the end.
signal b : std_logic_vector (0 to 7);

-- Indexing a bitvector
-- Get 4th element of a vector
b(4)

Extract specific bit positions

Ref: link

Types

U X 0 1 Z W L H -
U U U U U U U U U U
X U X X X X X X X X
0 U X 0 X 0 0 0 0 X
1 U X X 1 1 1 1 1 X
Z U X 0 1 Z W L H X
W U X 0 1 W W W W X
L U X 0 1 L W L W X
H U X 0 1 H W W H X
- U X X X X X X X X

Source: http://people.sabanciuniv.edu/erkays/el310/ch09.pdf

Explained

Moore machine

Bit vector representation

numeric_std

Syntax examples

Assignment after a delay

Although practically, it is quite impossible to construct a circuit with an exact delay since many factors are at play:

y <= a + b + 1 after 10 ns;
-- means that whenever a or b changes, the expression a+b+1 is evaluated
-- and its value is assigned to y after a delay of 10ns.

Closed feedback loop (bad!)

q <= (q and (not en)) or (d and en);
-- keep value of q unchanged if en is 0.
-- Otherwise use d to set q

Conditional assignment

signal_name <= value_expr_1 when boolean_expr_1 else
               value_expr_2 when boolean_expr_2 else
               ...
               value_expr_n;

Examples

4:1 MUX
library ieee;
use ieee.std_logic_1164.all;

entity mux41 is
  port(
    a, b, c, d: in std_logic_vector(7 downto 0);  -- input lines
    s: in std_logic_vector(1 downto 0);           -- select lines (2)
    o: out std_logic_vector(7 downto 0)           -- output line
  );
end mux41;

architecture mux41_arch is
begin
  o <= a when (s="00") else
       b when (s="01") else
       c when (s="10") else
       d;
end mux41_arch;
2:4 decoder
s0 s1 out
0 0 0001
0 1 0010
0 1 0100
1 1 1000
library ieee;
use ieee.std_logic_1164.all;

entity decoder is
  port(
    s: in std_logic_vector(1 downto 0);
    o: out std_logic_vector(3 downto 0)
  );
end decoder;

architecture decoder_arch is
begin
  o <= "0001" when (s="00") else
       "0010" when (s="01") else
       "0100" when (s="10") else
       "1000";
end decoder_arch;
4:2 priority encoder
r (in) code (out) active (out)
1xxx 11 1
01xx 10 1
001x 01 1
0001 00 1
0000 00 0
library ieee;
use ieee.std_logic_1164.all;

entity prio42 is
  port(
    r: in std_logic_vector(3 downto 0);
    code: out std_logic_vector(1 downto 0);
    active: out std_logic
  );
end piro42;

architecture prio42_arch is
begin
    code <= "11" when (r(3)='1') else
        "10" when (r(2)='1') else
        "01" when (r(1)='1')
        "00";

    -- Not sure if the following line would've been okay.
    -- active <= '0' when (r="0000") else '1';

    active <= r(3) or r(2) or r(1) or r(0);
end prio42_arch;
Simple ALU
ctrl result
0xx src0 + 1
100 src0 + src1
101 src0 - src1
110 src0 and src1
111 src0 or src1
library ieee;
use ieee.std_logic_1164.all;

entity alu is
  port(
    ctrl: in std_logic_vector(2 downto 0);
    src1, src0: in std_logic_vector(7 downto 0);
    result: out std_logic_vector(7 downto 0);
  );
end alu;

architecture alu_arch is
  signal sum, diff, inc: std_logic_vector(7 downto 0);
begin
  inc <= src0 + 1
  ctrl <= src0 + 1 when
end alu_arch;

Terms

Compilation and simulation

Three phases in simulation of VHDL code:

  1. Analysis (compilation)
  2. Elaboration
  3. Simulation

Analysis

Elaboration

Simulation

Tips

Leave a component port disconnected

Ports can be left disconnected while doing port map on components. Use open.

ADDER2: HALFADD port map
  (B=>Y,A=>X,SUM=>S,CARRY=>open);

Reference: https://www.ics.uci.edu/~jmoorkan/vhdlref/compinst.html

Non-standard packages to avoid

Don't use Instead use
ieee.std_logic_unsigned ieee.numeric_std.all
ieee.std_logic_arith

See more

use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all;

Type conversion for std_logic_vector

Reference

       to_integer()  +--------+   std_logic_vector()           
     +---------------| signed |-------------------+            
     |               +--------+                   |            
     |                ^      ^                    |                
     |                |      |                    |                
     |     to_signed()|      |signed()            |                
     |                |      |                    |                
     V                |      |                    V                
+---------+           |      |           +------------------+
|         |-----------+      +-----------|                  |
| integer |                              | std_logic_vector |
|         |-----------+      +-----------|                  |
+---------+           |      |           +------------------+
     ^                |      |                    ^                
     |                |      |                    |                
     |   to_unsigned()|      |unsigned()          |                
     |                |      |                    |                
     |                V      V                    |                
     |              +----------+                  |             
     +--------------| unsigned |------------------+             
       to_integer() +----------+  std_logic_vector()

<------------------------>  <-------------------------------->
   Conversion functions                Type cast

Acronyms

More

Glossary

General

ASIC
Application Specific Integrated Circuit

Synthesis

Register Transfer Notation (RTL)

References

Doubts