작성일: 2008.03.31
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 differenceshere 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.
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
(jsandstrom@mcimail.com)
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) ; | component inverter 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 area of 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 ; |
To voice an opinion on this or any Integrated System Design article, please e-mail your message to michael@asic.com.