Hardware Description
Languages : VHDL and Verilog
David Nguyen, Duy-Ky Nguyen, PhD
1. Introduction
VHDL was first created by DOD contractors IBM, Texas Intruments and Intermetrics to document a large discrete digital project in 1980. Verilog was created by an engineer named Phil Moorby at a CAE company called Gateway Design Automation to verify a large discrete digital projects in 1981.
VHDL is a Pascal/Ada-like language (case insensitive) while Verilog is C-like language (case sensitive).
VHDL is more programming language than Verilog as it has many data types for signal and variable. Verilog is better to describe hardware and 2 basic data types, 1 for combinatory digital (memory-less like gate, decoder, mux, ...) and 1 for sequential digital (memory like flip-flop). It has only signal, not variable (signal is also variable, anyway).
2. Comparison
This notes presents only HDL sufficient enough for synthesis and basic simulation for verification.
2.1. Data Type
VHDL | Verilog |
Many data types, each for both combinatory and sequential
|
Only 2 data types separately for comb` and seq`
|
Logic
| Logic
|
Number 196 decimal
| Number 196 decimal
|
Digital Hw has nothing else but 1-bit (binary digit) combinatory and sequential digital. Verilog uses only these information to create its data types while VHDL has much more data types.
Verilog has
wire comb_sig; // combinatory signal reg [7:0] data_bus; // sequential data busWhile
signal comb_sig : std_logic; signal data_bus : std_logic_vector (7 downto 0);
So, Verilog is more efficient in describing digital HW in term of data type and number as it focus on
2.2. Operators
VHDL | Verilog |
Concatenation: & ()
signal sel_vec : std_logic_vector (1 downto 0); Sel_vec = (sel_bit_1, sel_bit_0); case sel_vec when "00" => . . . |
Concatenation: { }
case ({sel_bit_1, sel_bit_0}) 0 : . . . |
Replication : None | Replication : { { } }
{ 4 {vector } } = { vector, vector, vector, vector} |
Reduction :None | Reduction & | ^
& {bit_3, bit_2, bit_1, bit_0} = bit_3 & bit_2 & bit_1 &bit_0 |
So, Verilog is again more efficient to describe digital HW for its clean bit and vector (multi-bit) representations while bit is the only object in digital HW, nothing else.
2.3. IO Interface
VHDL | Verilog |
In, out, inout However, out cannot be read, it requires extra signal declaration in doing so Out_sig : out std_logic; signal out_tmp : std_logic; Out <= out_tmp; . . . out_tmp <= sig_1; sig2 <= out_tmp; |
Input, output, inout Out can be read output out_sig; Out_sig <= sig1; Sig2 <= out_sig; |
For some unknown reason, VHDL has unrealistic write-only feature for OUT, while, in real digital HW, there`s read-only (ROM - Read Only Memory), but not write-only.
2.4. Function and Procedure/Task
VHDL | Verilog |
function name (arguments) return std_logic_vector (7 downto 0) is -- variable Begin -- function body End name; |
function [7:0] name; // input only (arguments); begin; -- function body end; endfunction; |
Procedure name (in-out list) is -- variable; begin -- procedure body end name; |
task name; // in/out list; begin -- task body end endtask |
To return single value, both VHDL and Verilog use function. However, VHDL uses arguments as inputs like high-level programming language, but Verilog uses regular input-list.
To include timing control, VHDL uses procedure while Verilog uses task. Both use IO list.
So, once again, Verilog has more consistent approach for function, task/procedure than VHDL.
2.5. RAM Simulation Model
VHDL | Verilog |
type RAM is array (0 to 31) of std_logic_vector (7 downto 0); begin process (clk) variable RAMa : RAM; variable aa : integer := 0; begin aa := conv_integer(addr); if rising_edge(clk) and en='1' then if (we='1') then RAMa(aa) := din; end if; dout <= RAMa(aa); end if; end process; |
reg [7:0] RAMa [0:31; always @ (posedge clk) begin if (we) RAMa[addr] <= din; dout <= RAMa[addr]; end |
2.6. Brief Summary on VHDL and Verilog
VHDL (case Insensitive) | Verilog (case Sensitive) |
-- VHDL line comment | // Verilog line comment |
Block comment: None | /* Block comment */ |
Architecture:library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity name is port ( -- IO interface and list);end name; architecture name of name is -- signal for both combinatory and sequential -- component begin -- architecture body -- combinatory assignment process (sensitive list) -- sequential -- variable begin -- body end process;end name; |
module name ( // like VHDL entity //IO interface); // IO list (separate IO interface and list) // No architecture section // wire for combinatory (gate, mux, ...) // reg for sequential (flip-flop) // combinatory assignment always @(sensitive list) begin -- sequential // body, like VHDL process end endmodule |
Vector: ()signal a_vec: std_logic_vector (7 downto 0); A_vec(0) for bit 0 |
[]reg [7:0] a_vec; a_vec[0] for bit 0 |
Assignments: <= :=<= for signal (both comb` and seq`) := for variable X_bit <= `1`; -- 1-bit X_vec <= "0000" -- 4-bit X_vec <= x"0" -- hex for 4-muliple only X_vec <= "000000" -- 6-bit, no hex avail. X_vec <= "ZZZZ" -- no hex avail. It`s hard to type 32 Z`s for 32-bit data |
= <= = for combinatory <= for sequential X_bit = 1`b1; // or x_bit = 1 X_vec = 4`b0; // or x_vec = 0 X_vec = `h0; // drop size # (4) X_vec = 6`b0 // or x_vec = 0 X_vec = `hZ; // |
Gates: not and nand or nor xor xnorX <= not a; X <= a and (not b); X <= not (a and b); X <= a or b; X <= not (a or b); X <= a xor b; X <= a xnor b; |
~ & ~& | ~| ^ ~^x = ~a; x = a & (~b); x = ~(a & b); x = a | b; x = ~(a | b); x = a ^ b; x = a ~^ b; // x = a ^~ b; |
Shift: sll srlX <= a sll 3; |
<< >>x = a << 2; |
Concat: &X <= a_vec(5 downto 0) & a_vec(6) |
{}x = {a_vec[5:0], a_vec[6]}; |
Aggregate: (, )-- bit onlyX <= (a_bit, b_bit) |
{}x = {a_bit, b_bit}; |
Replica: None |
{{}}x = {a_bit, a_bit, a_bit, b_vec, b_vec};=> x = {3{a_bit}, 2{b_vec}}; |
Relational: = /= < <= > >= X <= `1` when a=b else `0`; -- comb` only if (a=b) then -- seq` only X <= `1`; else X <= `0`; end if; |
== != < <= > >= X = (a == b); // both comb` and seq` |
Logical: not and or(a=b) and (c/=d) |
! && ||(a==b) && (c!=d) |
Reduction: NoneX <= a_vec(2) and a_vec(1) and a_vec(0) |
& | ~& ~|x = &a_vec[2:0]; |
Conditional: when else --For combinatory only!X <= "00" when S="00" else "01" when S="01" else "10" when S="10" else "11"; |
? : //For both combinatory and sequentialX = (s==0) ? 0 : (==1) ? 1 : (s==2) ? 2 : 3; |
if () then -- block statement (no begin end) Elsif then -- else -- end if; |
if () // block statement (begin end) else if // else // |
function name (arguments) return std_logic_vector (7 downto 0) is -- variable Begin End name; |
function [7:0] name;// input only (arguments) begin End endfunction |
procedure name (in-out list) is -- variable begin end name; |
task name;// in/out list begin end endtask |
3. Conclusion
Programming languages, like Pascal/Ada or C, basically deals with numbers and character using computer while computers know nothing but binary digit (bit). These bits are interpreted as numbers or character depending on their usages. That's why programming langaues do require type to fulfil this task. For example, the bits 01100101 (65 decimal) is the number 65 for integer type, but character 'A' for character type. Even a number could be an integer number or a real number with decimal point. Even more, a real number could be single precision or double precision (more digits after decimal point).
However, Hardware Description langguages, like VHDL or Verilog, deals with nothing but logic bits, like 0, 1 or tristate 'Z' in digital electronics. They should also describe 2 types of digital electronics combinatrory (memoryless) and sequential (memory).
VHDL is a strong-type language with many types like programming language, probably because it was created by SW engineers, unlike Verilog created by HW engineers?
Verilog has only 2 types wire for combinatory digital and reg for sequential digital.
Verilog deals with bit and array of bits of a bus far more efficient than VHDL. Strong-type feature makes programming language more efficient, but makes VHDL very clumsy.
At some point, it's usual to deal with with bitwise like below
VHDL | Verilog |
ABC_A : ABC PORT MAP( IN(0) => IN0, IN(1) => IN1, IN(2) => IN2, IN(3) => IN3, IN(4) => IN4, IN(5) => IN5, IN(6) => IN6, IN(7) => IN7, OUT => X ); |
ABC ABC_A ( .IN({IN7, IN6, In5, In4, IN3, IN2, IN1, IN0}), .OUT(X) ); |
Just imagine if we have 32 bits instead of 8 bits above, we'll see how painful in using VHDL.
In fact, there's a way to make thing easier in VHDL in dealing with this issue by using extra signal or variable as below
VHDL | Verilog |
. . . signal IN_8x: std_logic_vector(7 downto 0); . . . IN_8x <= (IN7, IN6, In5, In4, IN3, IN2, IN1, IN0); ABC_A : ABC PORT MAP( IN => IN_8x, OUT => X ); |
ABC ABC_A ( .IN({IN7, IN6, In5, In4, IN3, IN2, IN1, IN0}), .OUT(X) ); |
However, extra signals will make debugging more difficult.
Verilog has cleaner, more consistent and convenient constructions to represent digital HW than VHDL. These are very reasons why Verilog has some greater features below vs VHDL
- shorter training time;
- faster simulation/verification and implementation, hence shorter time-to-market development;