System Design

Comparing Verilog to VHDL Syntactically and Semantically

The way to a designer's heart is through HDL.

by Johan Sandstrom


With the advent of Verilog/VHDL co-simulators (Verilog = commercial and VHDL = DoD lines blurring) I thought I should hedge my bets by learning Verilog. I'm quite competent in VHDL, so armed with the Verilog-XL Reference Manual, the Digital Design with Verilog HDL book, and the free Wellspring Verilog simulator, I started my education.

The basics of each language seem common enough, but soon I was into nuances that I couldn't relate to. So, I decided I needed a summary of the language differences­here it is.

The crux of the article is a cross-reference table indexed by Verilog (.v suffix) and VHDL (.vhd suffix) keywords. I don't show how to create designs using both languages, because Larry Saunders and Yatin Trivedi do a wonderful job. Nor do I show the BNF (Bachus-Naur Format) for language constructs, because the Language Reference Manuals and various "third-party" books cover the languages just fine. This table is merely a pointer into the other language.

Find the keyword of your favorite language in the "Keyword" column, then read along that row to find the other language equivalent keyword/construct/command in the "Equivalent" column. On the same row, in the "Verilog" and "VHDL" columns, are brief code fragments to illustrate a simple keyword usage with the keyword in bold type and names of user-created objects in italics.

I omitted the Verilog built-in compiler/simulator commands (+, -, $) because there are no VHDL equivalent commands, since the various VHDL tools have their own commands. I added the new VITAL (VHDL Initiative Towards ASIC Libraries) primitives that cross-reference to the Verilog primitives for netlisting purposes.

I suppose everybody knows that Verilog is patterned after "C" and VHDL is patterned after Ada. What that basically means is that Verilog is terse and doesn't take its type-checking seriously, whereas VHDL is verbose and strongly typed.





Figure 1. A view of the relative abstraction levels of the two languages.

It would appear that the HDL benefits of Designing-in-English (if this ... else that), robust simulation capability, and logic synthesis can be achieved by either language. Being conversant in both languages allows access to a wide variety of models and tools to achieve maximum design efficiency and verification.



Johan Sandstrom (johan@sandstrom.org) is a system/logic design consultant who started out hand-drawing schematics and has evolved up the abstraction/tool chain.

Rob Antman (rob1a@aol.com) knows both languages and helped me over the rough spots in the table.


Table 1
Verilog/VHDL equivalent keywords
Keyword Equivalent Verilog VHDL
abs.vhd ?: // expression needed out1 = (in1 < 0) ? -in1 : in1; out1 <= abs(in1);
access.vhd // no counterpart // no counterpart type pointer is access memory;
after.vhd # #10 out1 = in1; out1 <= in1 after 10 ns;
alias.vhd `define `define status word[13] alias status : std_logic is word(13);
all.vhd +lib ... // command line option use libname.pkgname.all;
always.v process always begin ... end process begin ... end process;
and.v // gate vitaland and (out1, in1, in2); vitaland(out1, in1, in2);
and.vhd &, && out1 = in1 & in2; out1 <= in1 and in2;
architecture.vhd module module name; endmodule architecture name of entityname is ... end name;
array.vhd reg[range] memory [range] reg[0:3] memory [0:7] type memory is array(0 to 3) of std_logic_vector(0 to 7);
assert.vhd $display if (not condition) $display("string"); assert condition report "string" severity level;
assign.v when ... else if ... assign out1 = 0; else deassign out1; when ... out1 <= '0'; else out1 <= 'Z';
attribute.vhd // no counterpart // no counterpart attribute capacitance : farads;
begin.v begin begin multiple statements end name begin ... end name;
begin.vhd begin begin multiple statements end name begin ... end name;
block.vhd begin ... end begin multiple statements end alu : block ... end block alu;
body.vhd // hierarchical path names pkgname.definitions package body pkgname is ... end pkgname;
buf.v // gate vitalbuf buf (out1, in1); vitalbuf(out1, in1);
buffer.vhd out out out1; port(out1 : buffer std_logic);
bufif0.v // gate vitalbufif0 bufif0(out1, in1, control1); vitalbufif0(out1, in1, control1);
bufif1.v // gate vitalbufif1 bufif1(out1, in1, control1); vitalbufif1(out1, in1, control1);
bus.vhd tri tri name; signal name : std_logic bus;
case.v case case (expression) choices endcase case expression is when choice => out1 <= in1; end case;
case.vhd case case (expression) choices endcase case expression is when choice => out1 <= in1; end case;
casex.v ­ no direct counterpart casex (expression) choices endcase ­ no direct counterpart
casez.v ­ no direct counterpart casez (expression) choices endcase ­ no direct counterpart
cmos.v // gate ­ no standard counterpart cmos(out1, in1, ncontrol, pcontrol); ­ no standard counterpart
component.vhd // structural instantiation inverter u1 (out1, in1); componentinverter port(out1 : out std_logic; in1 : in std_logic);
configuration.vhd // no counterpart // no counterpart configuration name of EntityName is ... end name;
constant.vhd parameter parameter maxsize = 64; constant maxsize : positive := 64;
deassign.v when ... else if ... assign out1 = 0; else deassign out1; when ... out1 <= '0'; else out1 <= 'Z';
default.v others case (expression) ... default : out1 = in2; case expression is ... when others => out1 <= in2; end case;
defparam.v generic map defparam maxsize = 32; generic map(maxsize => 32);
disable.v exit, next, return for ... disable name ... loop ... next when ... end loop;
disconnect.vhd ?: // expression needed out1 = guard ? in1 : 'bz; disconnect GuardedSignalName : std_logic after 10 ns;
downto.vhd // [higher:lower] [15:0] (15 downto 0)
else.v else if ... else if ... else if ... then ... elsif ... then ... else ... end if;
else.vhd else if ... else if ... else if ... then ... elsif ... then ... else ... end if;
elsif.vhd else, if if ... else if ... else if ... then ... elsif ... then ... else ... end if;
end.v end begin multiple statements end ... end ... ;
end.vhd end begin multiple statements end ... end ... ;
endcase.v case ... end case; case (expression) choices endcase case expression is when choice => out1 <= in1; end case;
endfunction.v function ... end; function name; ... endfunction function name(...) return std_logic is ... end name;
endmodule.v entity/architecture module name; ... endmodule entity name is ... end name; architecture ...
endprimitive.v // gate VitalTruthTable primitive name ... endprimitive procedure VitalTruthTable(...);
endspecify.v generic specify specparem setup=10; endspecify entity name is generic(setup : time := 10 ns); ...
endtable.v // gate VitalTruthTable table ... endtable procedure VitalTruthTable(...);
endtask.v procedure ... end; task name; ... endtask procedure name(...) is ... end name;
entity.vhd module module name; ... endmodule entity name is ... end name;
event.v signal event name; signal name : sync_type;
exit.vhd disable for ... disable name ... loop ... exit when ... end loop;
file.vhd $input $input("source.txt"); file source_code : text is in "source.txt";
for.v for for (i = 1; i <= 10; i = i + 1) for i in 1 to 10 loop
for.vhd for, repeat for (i = 1; i <= 10; i = i + 1) for i in 1 to 10 loop
force.v ­ user defined resolution function if ... force out1 = 0; else release out1; out1 <= stomp_value; ­ perhaps in an error_injector component.
forever.v wait forever @(posedge clock) out1 = in1; wait until rising_edge(clock); out1 <= in1;
fork.v ­ user defined synchronization ... fork concurrent_execution join ... wait on sync'transaction until sync = 300;
function.v function function name; ... endfunction function name(...) return std_logic is ... end name;
function.vhd function function name; ... endfunction function name(...) return std_logic is ... end name;
generate.vhd // no counterpart // no counterpart generate_label : if expression generate ... end generate;
generic.vhd defparam, specparem defparam maxsize = 32; entity name is generic(maxsize : natural := 32); ...
group.vhd // no counterpart // no counterpart attribute rising_delay of c2q : group is 7.2 ns;
guarded.vhd ?: // expression needed out1 = guard ? in1 : 'bz; block (guard-expression) ... out1 <= guarded in1 after 10 ns;
highz0.v // strength 'Z' in std_logic_1164 buf(highz0) out1; out1 <= 'Z';
highz1.v // strength 'Z' in std_logic_1164 buf(highz1) out1; out1 <= 'Z';
if.v if if ... else if ... else if ... then ... elsif ... then ... else ... end if;
if.vhd if if ... else if ... else if ... then ... elsif ... then ... else ... end if;
impure.vhd // no counterpart // no counterpart impure function ...
in.vhd input output out1; input in1; port(out1 : out std_logic; in1 : in std_logic);
inertial.vhd // inertial by default #10 out1 = in1; out1 <= reject 5 ns inertial in1 after 10 ns;
initial.v process initial begin ... end process begin ... wait; end process;
inout.v inout inout inout1; port(inout1 : inout std_logic);
inout.vhd inout inout inout1; port(inout1 : inout std_logic);
input.v in output out1; input in1; port(out1 : out std_logic; in1 : in std_logic);
integer.v ­ predefined type integer name; signal name : integer;
is.vhd // unnecessary module name; ... endmodule entity name is ... end name;
join.v ­ user defined synchronization ... fork concurrent_execution join ... wait on sync'transaction until sync = 300;
label.vhd // no counterpart // no counterpart attribute location of adder1 : label is (10, 15);
large.v // charge ­ enumerated type trireg(large) out1; type strength is (small, medium, large);
library.vhd +lib ... // command line option library libname;
linkage.vhd // no counterpart // no counterpart port(out1 : linkage std_logic; in1 : in std_logic);
literal.vhd // no counterpart // no counterpart attribute areaof others : literal is 7;
loop.vhd while, for, etc. while (condition) while (condition) loop
macromodule.v // gate entity/architecture macromodule name; ... endmodule entity name is ... end name; architecture ...
map.vhd // structural instantiation inverter u1 (out1, in1); u1 : inverter port map(out1 => out1, in1 => in1);
medium.v // charge ­ enumerated type trireg(medium) out1; type strength is (small, medium, large);
mod.vhd % out1 = in1 % in2; out1 <= in1 mod in2;
module.v entity/architecture module name; ... endmodule entity name is ... end name; architecture ...
nand.v // gate vitalnand nand (out1, in1, in2); vitalnand(out1, in1, in2);
nand.vhd ~, & out1 = ~(in1 & in2); out1 <= in1 nand in2;
negedge.v falling_edge ­ std_logic_1164 always @ (negedge clk) begin ... end wait until falling_edge(clk);
new.vhd // no counterpart // no counterpart pointer := new name ... deallocate(name);
next.vhd disable for ... disable name ... loop ... next when ... end loop;
nmos.v // gate vitalbufif1 nmos(out1, in1, control1); vitalbufif1(out1, in1, control1, ... ResultMap);
nor.v // gate vitalnor nor (out1, in1, in2); vitalnor(out1, in1, in2);
nor.vhd ~, | out1 = ~(in1 | in2); out1 <= in1 nor in2;
not.v // gate vitalinv not (out1, in1); vitalinv(out1, in1);
not.vhd ~ out1 = ~in1; out1 <= not(in1);
notif0.v // gate vitalinvif0 notif0(out1, in1, control1); vitalinvif0(out1, in1, control1);
notif1.v // gate vitalinvif1 notif1(out1, in1, control1); vitalinvif1(out1, in1, control1);
null.vhd // no direct counterpart // no direct counterpart case expression is when choice => out1 <= null; end case;
of.vhd // unnecessary module name; ... endmodule architecture name of entityname is ... end name;
on.vhd @ @(posedge in1) ... wait on in1;
open.vhd // no counterpart // no counterpart u1 : inverter port map(out1 => open, in1 => in1);
or.v // gate vitalor or (out1, in1, in2); vitalor(out1, in1, in2);
or.vhd |, || out1 = in1 | in2; out1 <= in2 or in2;
others.vhd default case (expression) ... default : out1 = in2; case expression is ... when others => out1 <= in2; end case;
out.vhd output output out1; input in1; port(out1 : out std_logic; in1 : in std_logic);
output.v out output out1; input in1; port(out1 : out std_logic; in1 : in std_logic);
package.vhd // hierarchical path names pkgname.definitions package pkgname is ... end pkgname;
parameter.v constant parameter maxsize = 64; constant maxsize : positive := 64;
pmos.v // gate vitalbufif0 pmos(out1, in1, control1); vitalbufif0(out1, in1, control1, ... ResultMap);
port.vhd module name (port signals); module name (out1, in1); ... endmodule port(out1 : out std_logic; in1 : in std_logic);
posedge.v rising_edge ­ std_logic_1164 always @ (posedge clk) begin ... end wait until rising_edge(clk);
postponed.vhd #0 #0 ... postponed process ...
primitive.v // gate VitalTruthTable primitive name ... endprimitive procedure VitalTruthTable(...);
procedure.vhd task task name; ... endtask procedure name(...) is ... end name;
process.vhd always always begin ... end process begin ... end process;
pull0.v // strength 'L' in std_logic_1164 buf(pull0) out1; out1 <= 'L';
pull1.v // strength 'H' in std_logic_1164 buf(pull1) out1; out1 <= 'H';
pulldown.v // gate vitalbuf pulldown(pull0) (out1); out1 <= 'L';
pullup.v // gate vitalbuf pullup(pull1) (out1); out1 <= 'H';
pure.vhd // no counterpart // no counterpart pure function ...
range.vhd // no counterpart // no counterpart for i in inputs'range loop ... end loop;
rcmos.v // gate ­ no standard counterpart rcmos(out1, in1, ncontrol, pcontrol); ­ no standard counterpart
record.vhd // hierarchical path names module record_name ... endmodule type name is record ... end record;
reg.v variable, signal reg name; variable name : std_logic;
register.vhd trireg trireg name; signal name: std_logic register;
reject.vhd // no counterpart // no counterpart out1 <= reject 5 ns inertial in1 after 10 ns;
release.v ­ user defined resolution function if ... force out1 = 0; else release out1; out1 <= stomp_value; ­ perhaps in an error_injector component.
rem.vhd % out1 = in1 % in2; out1 <= in1 rem in2;
repeat.v for repeat (10) for i in 1 to 10 loop ...
report.vhd $display if (not condition) $display("string"); assert condition report "string" severity level;
return.vhd disable task name; ... disable name; function name(...) return std_logic is ... end name;
rnmos.v // gate vitalbufif1 rnmos(out1, in1, control1); vitalbufif1(out1, in1, control1, ... ResultMap);
rol.vhd {} // expression needed alu_data = {alu_data[5:0], alu_data[7:6]}; alu_data <= alu_data rol 2;
ror.vhd {} // expression needed alu_data = {alu_data[1:0], alu_data[7:2]}; alu_data <= alu_data ror 2;
rpmos.v // gate vitalbufif0 rpmos(out1, in1, control1); vitalbufif0(out1, in1, control1, ... ResultMap);
rtran.v // gate ­ no standard counterpart rtran(inout1, inout2); ­ no standard counterpart
rtranif0.v // gate ­ no standard counterpart rtranif0(inout1, inout2, control); ­ no standard counterpart
rtranif1.v // gate ­ no standard counterpart rtranif1(inout1, inout2, control); ­ no standard counterpart
scalared.v std_logic_vector tri1 scalared[63:0] name; signal name : std_logic_vector(63 downto 0);
select.vhd ?: // expression needed cond_expr ? true_expr : false_expr with expression select choices
severity.vhd $stop, $finish $stop(1); assert condition report "string" severity level;
shared.vhd // no counterpart // no counterpart shared variable ...
signal.vhd wire wire in1; signal in1 : std_logic;
sla.vhd // sla function needed alu_data = sla(alu_data, 2); alu_data <= alu_data sla 2;
sll.vhd << alu_data = alu_data << 2; alu_data <= alu_data sll 2;
small.v // charge ­ enumerated type trireg(small) out1; type strength is (small, medium, large);
specify.v generic specify specparem setup=10; endspecify entity name is generic(setup : time := 10 ns); ...
specparam.v generic specify specparem setup=10; endspecify entity name is generic(setup : time := 10 ns); ...
sra.vhd // sra function needed alu_data = sra(alu_data, 2); alu_data <= alu_data sra 2;
srl.vhd >> alu_data = alu_data >> 2; alu_data <= alu_data srl 2;
strong0.v // strength '0' in std_logic_1164 buf(strong0) out1; out1 <= '0';
strong1.v // strength '1' in std_logic_1164 buf(strong1) out1; out1 <= '1';
subtype.vhd // predefined types // predefined types subtype subtypename is typename range ... ;
supply0.v // strength '0' in std_logic_1164 buf(supply0) out1; out1 <= '0';
supply1.v // strength '1' in std_logic_1164 buf(supply1) out1; out1 <= '1';
table.v // gate VitalTruthTable table ... endtable procedure VitalTruthTable(...);
task.v procedure task name; ... endtask procedure name is ... end name;
then.vhd // unnecessary if ... else if ... else if ... then ... elsif ... then ... else ... end if;
time.v ­ predefined type time setup; generic(setup: time := 3 ns);
to.vhd // [lower:higher] [0:15] (0 to 15)
tran.v // gate ­ no standard counterpart tran(inout1, inout2); ­ no standard counterpart
tranif0.v // gate ­ no standard counterpart tranif0(inout1, inout2, control); ­ no standard counterpart
tranif1.v // gate ­ no standard counterpart tranif1(inout1, inout2, control); ­ no standard counterpart
transport.vhd // inertial only // no counterpart out1 <= transport in1 after 10 ns;
tri.v // net bus, ­ resolved signal tri out1; signal out1 : resolved_tri;
tri0.v // net ­ resolved signal tri0 out1; signal out1 : resolved_tri0;
tri1.v // net ­ resolved signal tri1 out1; signal out1 : resolved_tri1;
triand.v // net ­ resolved signal triand out1; signal out1 : resolved_triand;
trior.v // net ­ resolved signal trior out1; signal out1 : resolved_trior;
trireg.v // net register, ­ resolved signal trireg out1; signal out1 : resolved_trireg;
type.vhd // predefined types // predefined types type typename ... enumerate;
unaffected.vhd ?: // expression needed #delay_value out1 = condition ? out1 : in1; out1 <= unaffected when condition else in1 after delay_value;
units.vhd // no counterpart // no counterpart physical type ... units ...
until.vhd wait wait (condition); wait until condition;
use.vhd +lib ... // command line option use libname.pkgname.all;
variable.vhd reg reg name; variable name : std_logic;
vectored.v ­ enumerated type tri vectored[31:0] name; signal name : enumerated_type;
wait.v wait wait (condition); wait [on] [until] [for] ... ;
wait.vhd wait wait (condition); wait [on] [until] [for] ... ;
wand.v // net ­ resolved signal wand out1; signal out1 : resolved_wand;
weak0.v // strength 'L' in std_logic_1164 buf(weak0) out1; out1 <= 'L';
weak1.v // strength 'H' in std_logic_1164 buf(weak1) out1; out1 <= 'H';
when.vhd case case (expression) choices case expression is when choice => out1 <= in1; end case;
while.v while while (condition) while (condition) loop
while.vhd while while (condition) while (condition) loop
wire.v // net ­ resolved signal wire out1; signal out1 : resolved_wire;
with.vhd ?: // expression needed cond_expr ? true_expr : false_expr with expression select choices
wor.v // net ­ resolved signal wor out1; signal out1 : resolved_wor;
xnor.v // gate vitalxnor xnor (out1, in1, in2); vitalxnor(out1, in1, in2);
xnor.vhd ^~ out1 = in1 ^~ in2; out1 <= in1 xnor in2;
xor.v // gate vitalxor xor (out1, in1, in2); vitalxor(out1, in1, in2);
xor.vhd ^ out1 = in1 ^ in2; out1 <= in1 xor in2;

integrated system design  October 1995

Home | About Us | Demo | Products | Articles | Methodology | Vocation | Avocation