VHDL is:
Part of a line that comes after a --
.
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 |
&
)-- 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
<=
assign value to a signal
:=
assign value to a variable
-- variable var_name : type
: std_logic_vector (7 downto 0); variable outvector
struct
.Syntax:
type <type-name> is record
<attr1> : <type>;
<attr2> : <type>;
...
<attrn> : <type>;
end record <type-name>;
Example:
type rec_typ is record: std_logic;
in_en : std_logic_vector (7 downto 0);
data : std_logic;
out_en
end record rec_typ;
-- use the record
: rec_typ := (in_en => '0',
constant inst_rec_type => '00001001',
data => '1); out_en
Another example:
<= (oldver => "00",
nstate => '0'); curst
, START, FINISH); type state_t is (IDLE
Code that can be reused.
Helps to organize the code.
Reference: link (pdf)
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 |
Example:
process is
begin<= sign + 1;
sign
wait for 10 ns; end process;
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
.
: std_logic_vector (7 downto 0);
bv <= (2 => '1',
bv => '1',
0 => '0');
others -- bit 2 and 0 are set to 1 and all others to 0.
-- ie, bv now has 00000101 as its value.
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(
: in std_logic;
clk: in std_logic_vector (7 downto 0);
d: out std_logic_vector (7 downto 0);
q
);end count8;
is
architecture count8_arch 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
:= d;
tmp elsif count = '1' then
:= r + 1;
tmp else
:= r;
tmp end if;
<= tmp;
r_in <= r;
q end process;
seq: process(clk)
begin
if rising_edge(clk) then
<= r_in;
r end if;
end process;
end count8_arch;
We can do the same using record types:
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;
Syntax:
<expression> is
case <const> =>
when ...
<const> =>
when ...
end case;
Example:
case a_const is"00" =>
when := 0;
a_var "01" =>
when := 1;
a_var "10" =>
when := 2;
a_var end case;
out~/~in
) needn't be mentioned.Syntax:
function function_name (args: arg_types) ret_type is
declarations
begin
sequential statements
end function_name;
Example:
-- Boolean NOT
: std_logic)
function cust_not (val
return std_logic is
begin= '1' then
if val '0';
return
else'1';
return
end if; end function cust_not;
VHDL | C |
---|---|
elsif |
else if |
= |
== |
:= & <= |
= |
if
statementExample:
= '1' then
if load := r + 1;
tmp = '1' then
elsif count := r - 1;
tmp
else:= 1;
tmp end if;
-- find first set bit
: std_logic_vector(7 downto 0);
variable vec : natural;
variable first
'range loop
for i in vec= '1' then
if vec(i) := i;
first -- break statement
exit;
end if; end loop;
std_logic_1164
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
: std_logic_vector (7 downto 0);
signal a
-- MSB is at the end.
: std_logic_vector (0 to 7);
signal b
-- Indexing a bitvector
-- Get 4th element of a vector
b(4)
vec(0)
: bit 0vec(9 downto 7)
: bits 9,8,7vec(1 to 3)
: bits 1,2,3Ref: link
U
: uninitializedX
: forcing unknown0
: forcing 01
: forcing 1Z
: high impedance (tri-state)W
: weak unknownL
: weak 0H
: weak 1-
: don't careU | 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
Z
find practical use in synthesis these days.numeric_std
+
, -
, comparison, etc.Although practically, it is quite impossible to construct a circuit with an exact delay since many factors are at play:
<= a + b + 1 after 10 ns;
y -- 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.
<= (q and (not en)) or (d and en);
q -- keep value of q unchanged if en is 0.
-- Otherwise use d to set q
signal_name <= value_expr_1 when boolean_expr_1 else
value_expr_2 when boolean_expr_2 else
...
value_expr_n;
library ieee;
use ieee.std_logic_1164.all;
entity mux41 is
port(
, b, c, d: in std_logic_vector(7 downto 0); -- input lines
a: in std_logic_vector(1 downto 0); -- select lines (2)
s: out std_logic_vector(7 downto 0) -- output line
o
);end mux41;
is
architecture mux41_arch begin
<= a when (s="00") else
o when (s="01") else
b when (s="10") else
c
d;end mux41_arch;
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(
: in std_logic_vector(1 downto 0);
s: out std_logic_vector(3 downto 0)
o
);end decoder;
is
architecture decoder_arch begin
<= "0001" when (s="00") else
o "0010" when (s="01") else
"0100" when (s="10") else
"1000";
end decoder_arch;
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(
: in std_logic_vector(3 downto 0);
r: out std_logic_vector(1 downto 0);
code: out std_logic
active
);end piro42;
is
architecture prio42_arch begin
<= "11" when (r(3)='1') else
code "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';
<= r(3) or r(2) or r(1) or r(0);
active end prio42_arch;
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(
: in std_logic_vector(2 downto 0);
ctrl, src0: in std_logic_vector(7 downto 0);
src1: out std_logic_vector(7 downto 0);
result
);end alu;
is
architecture alu_arch signal sum, diff, inc: std_logic_vector(7 downto 0);
begin
<= src0 + 1
inc <= src0 + 1 when
ctrl end alu_arch;
package
Three phases in simulation of VHDL code:
wait
statement cannot appear outside process
-es.if
statements cannot appear outside process
-es.Ports can be left disconnected while doing port map
on components. Use open
.
: HALFADD port map
ADDER2=>Y,A=>X,SUM=>S,CARRY=>open); (B
Reference: https://www.ics.uci.edu/~jmoorkan/vhdlref/compinst.html
Don't use | Instead use |
---|---|
ieee.std_logic_unsigned |
ieee.numeric_std.all |
ieee.std_logic_arith |
use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all;
std_logic_vector
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
ghdl -s --std=08 file.vhdl
wait for 10 ns
) are not synthesisable though they can be used during simulation.