VHDL2Verilog translates input VHDL to Verilog. This release supports a subset of VHDL (see Appendix A for comprehensive listing).
The rest of the chapter is organized as follows: For every construct supported by VHDL2Verilog, the general translation rules are given, followed by an example illustrating the construct in both languages. Special notes are given when required. The user is advised to refer to the VHDL LRM and Verilog LRM for detailed explanations.
Entities and Architectures
The basic design unit in VHDL is the ENTITY and ARCHITECTURE pair. An entity and architecture pair is translated to a Verilog MODULE description. An entity can have multiple architectures. Multiple architectures per entity are translated to multiple modules. VHDL2Verilog creates module names based on the following criteria:
•Module name is the same as the entity name in input VHDL file.
•Module name is the concatenation of the entity and architecture name in input VHDL file. For e.g., if an entity aha has two architectures, structural and behavioral, the Verilog modules are aha_structural and aha_behavioral.
Example
VHDL |
Verilog |
library ieee; use ieee.std_logic_1164.all
entity test is port(a : in std_logic; b : out std_logic) end entity;
architecture behave of test is begin end behave; |
module test(a,b); input a; output b;
endmodule |
Special Note: Verilog files can be imported for VHDL Entity and Architecture pairs by using tool-specific attribute VHDL2V_MODULE in the entity declaration. See Importing (parts of) Verilog files for detailed explanation.
Packages and Package Bodies
Most VHDL designs reference one or more PACKAGEs through USE statements. These packages can contain pre-defined constants, types, components, or subprograms (functions or procedures). VHDL2Verilog will translate the packages if they are used, and includes this translation either in the output file, or in one or more separate files.
Example
VHDL |
Verilog |
package my_package is constant width : integer := 16; end my_package;
use ieee.my_package.all; entity test is port(a : in std_logic; b : out std_logic); end entity;
architecture behave of test is begin end behave; |
module test(a,b); parameter width = 16; input a; output b; endmodule |
The translated package can also be included in a separate file using the -Include Package files switch. In that case VHDL2Verilog will produce a file called:
<package>_package.v
If there are components in the package, and the corresponding entity - architecture pairs of the components have been read in as well, another file will be produced called:
<package>_modules.v
Both files are included in the Verilog code with an `include statement.
NOTE: Subprograms in the package get translated only when they are used in the design and when Function mapping and translation has been activated.
Data Types
VHDL has three classes of data objects: SIGNAL, VARIABLE and CONSTANT. Verilog does not make any such distinction in its two data types: NETS and REGISTERS. Verilog NETS are used for driving signals, and REGISTERS are an abstraction of the hardware register. VHDL2Verilog translates VHDL objects to Verilog NETS or REGISTERS based on the following rules:
1.If the signal is an input, it is translated to an implicitly declared WIRE.
2.Signals corresponding to output ports get translated to Verilog REGISTERS.
3.If a signal is used as the target in a VHDL concurrent assignment or an actual designator in the port mapping of a component instantiation, the Verilog translation of VHDL signal is a WIRE. Note that in this particular case, outputs get declared as WIRES.
Example
VHDL |
Verilog |
library ieee; use ieee.std.logic_1164.all;
entity test is port(a : in std_logic; b : out std_logic; c : out std_logic) end entity;
architecture behave of test is begin b <= '1'; end behave; |
module test(a,b,c); input a; output b; output c;
wire b; reg c; assign b = 1; endmodule; |
Generics
VHDL GENERICs are used to construct parameterized components. Verilog offers similar capabilities in the form of parameter declarations. VHDL generics are translated to Verilog parameters.
Example
VHDL
|
Verilog |
library ieee; use ieee.std_logic_1164.all; entity test is generic(gen_a : in natural := 20; datapath : in integer := 11); port(a : in std_logic; b : out std_logic_vector(datapath downto 0); c : out std_logic); end entity
architecture behave of test is begin end behave; |
module test(a,b,c);
parameter gen_a = 20; parameter datapath = 11;
input a; output [datapath:0[ b; output c;
wire [datapath:0] b; reg c;
endmodule; |
Sequential Statements
VHDL sequential statements occur in VHDL PROCESS or SUBPROGRAM bodies. These statements execute in the order they appear. VHDL2Verilog translates sequential statements outlined in the following sections.
Wait Statements (Sequential Statement)
The WAIT statement is used to suspend the execution of a process or subprogram body. The VHDL LRM defines three types of WAIT statements:
4.Wait with sensitivity clause
5.Wait with condition clause 3. Wait with timeout clause
The current version of VHDL2Verilog supports WAITs with timeout clauses. WAITs with sensitivity clauses are supported only if appearing as the first (or last) item of the sequential body.
Example
VHDL |
Verilog |
process_l : process constant tpd : std_logic := '1'; constant tpd1 : std_logic := '0'; begin wait on a, enable; if (enable = '0') then q <= '0'; elsif a'event and a'last_value = 0 then q <= d; q <= '1' after 2ns; q <= '0'; end if; end process process_1; |
always @(posedge a or negedge enable) parameter tpd = 'b1; parameter tpd1 = 'b0;
if (enable == 'b0) q <= 'b0; else begin q <= d; q <= #2 'b1; q <= 'b0; end end |
Signal Assignments (Sequential Statement)
SIGNAL ASSIGNMENTs are used to modify the output waveform of the target. Verilog signal assignments (known as PROCEDURAL ASSIGNMENTS) can be of two types:
1.BLOCKING procedural assignment: A blocking procedural assignment MUST be executed before the execution of the statements that follow.
2.NON-BLOCKING procedural assignment: Verilog non-blocking procedural assignments allow scheduling of assignments without blocking the procedural flow. Typically, they are used when multiple assignments need to be made in the same simulation cycle.
All VHDL signal assignments are translated to Verilog NON-BLOCKING procedural assignments.
Example
VHDL |
Verilog |
architecture diffeq of diffeq is begin
p0 : process begin Xoutport <= 0; Youtport <= 0; Uoutport <= 0; wait; end process p0;
p1 : process(Aport,DXport,Xinport, Yinport,Uinport) variable x_var, y_var, u_var : std_logic; begin Xoutport <= x_var after 2 ns; Youtport <= transport y_var; //will occur Xoutport <= u_var after 5ns; -- above will cancel prev assignment end process P1; |
module diffeq;
initial begin : p0 Xoutport <= 0; Youtport <= 0; Uoutport <= 0; end
always @(Aport or DXport or Xinport or Yinport or Uinport) begin : p1 reg x_var, y_var, u_var;
Xoutport <= #2 x_var; Youtport <= y_var; //fully non-blocking Xoutport <= #5 u_var; // above will not cancel prev assignment end |
NOTE: Verilog non-blocking assignments differ from VHDL signal assignments in one important respect. Verilog non-blocking assignments ALWAYS occur. However, VHDL signal assignments with INERTIAL delay generate projected events which can be cancelled by future events. Verilog non-blocking assignments execute without cancelling a previous non-blocking assignment to the same register. Therefore, delays in Verilog non-blocking assignments are handled as TRANSPORT delays. If the delay type in VHDL signal assignments were specified to be TRANSPORT, then it would be equivalent to Verilog non-blocking assignment.
Variable Assignments (Sequential Statement)
VARIABLE ASSIGNMENTS are used to replace the current value of the variable with the new value specified on the right hand side of the assignment without any delay. They are mapped to Verilog non-blocking register assignments.
Example
VHDL |
Verilog |
process_2 : process(dummy) variable q_1 : std_logic_vector(3 downto 0); variable q_2 : std_logic_vector(3 downto 0); begin if (dummy = '1') then q_1 := "0001" end if; end process process_2; |
always @(dummy) begin : process_2 reg [3:0] q_1; reg [3:0] q_2; if (dummy == 'b1) q_1 = 'b0001; end |
If Statements (Sequential Statements)
The IF statement chooses to execute one (or none) of many sequence of statements based on the value of corresponding condition. The semantics of the Verilog IF statement are the same, barring the VHDL requirement that an IF (ELSIF) expression be boolean. VHDL IFs are mapped to Verilog IFs.
Example
VHDL |
Verilog |
process_1 : process begin wait on a,enable; if (enable = '0') then q <= '0' elsif a = '0' then q <= d; q <= '1' after 2 ns; q <= 0; end if; end process process_1; |
always @(a or enable) begin : process_1; if (enable == 'b0) q <= 'b0; else if (a == 'b0) begin q <= d; q <= #2 'b1; q <= 'b0; end end |
Case Statements (Sequential Statements)
CASE statements in VHDL have the same semantics as CASE statements in Verilog and are mapped to the same.
Example
VHDL |
Verilog |
process begin wait on sel_output; V2V_d_en <= '0'; case sel_output is when(B"000")=> x <= B"00000001" after 2 ns; when(B"001")=> x <= B"00000010"; when(B"010")=> x <= B"00000011"; when(B"011")=> x <= B"00000100"; when(B"100")=> x <= B"00000101"; when(B"101")=> x <= B"00000110"; when(B"110")=> x <= B"00000111"; when(B"111")=> x <= B"00001000"; when others => x <= "ZZZZZZZZ"; end case; end process; |
always @(sel_output) begin
V2V_d_en <= 'b0; case (sel_output) 'b000 : x <= #2 'b00000001; 'b001 : x <= 'b00000010; 'b010 : x <= 'b00000011; 'b011 : x <= 'b00000100; 'b100 : x <= 'b00000101; 'b101 : x <= 'b00000110; 'b110 : x <= 'b00000111; 'b111 : x <= 'b00001000; default : x <= 'bzzzzzzzz; endcase end |
Loop Statements (Sequential Statements)
VHDL defines LOOP statements, that are a collection of sequential statements. The execution is specified by the iteration scheme (e.g FOR, WHILE) used. Loop statements without iteration schemes are equivalent to Verilog FOREVER statements, iteration scheme FOR is translated to Verilog FOR loop and VHDL WHILE iteration scheme is translated to Verilog WHILE loop.
Example
VHDL |
Verilog |
process begin wait until a'event; i1 <= 0; wait for 0 ns;
while i1 < reg_dummy + 1 loop v2v_b(3 downto 0) <= a(3 downto 0); i1 <= i1 + 1; wait for 0 ns; end loop;
for cnt in 4 downto 1 loop v2v_b(i = "00000001") <= a(i); end loop;
len <= '8' wait for 0 ns;
loop v2v_b(i - "00000001") <= a; end loop;
end process; |
always @(a) begin i1 <= 0; #0
while (i1 < reg_dummy + 1) begin v2v_b[3:0] <= a[3:0]; i1 <= i1 + 1; #0; end
for (cnt = 4; cnt >= 1; cnt = cnt - 1) v2v_b[i - 'b00000001] <= a[i];
len <= 'b8 #0
forever v2v_b[i - 'b00000001] <= a;
end |
NULL Statements (Sequential Statements)
A NULL statement performs no action and is equivalent to the Verilog ``;'' statement.
Example
VHDL |
Verilog |
null; |
; |
Assert Statements (Sequential Statements)
The Assert statement shows a pre-defined message when the assertion fails. The severity is made part of the message. Furthermore, in the Verilog translation the time when the assertion was activated is shown.
Example
VHDL |
Verilog |
variable status : boolean;
assert status = false report "Some message" severity note; |
reg status
if (!(status==`false)) begin $write("note: "); $display("Some message"); $display("Time: ",$time); end |
Procedure Call Statements (Sequential Statements)
A VHDL Procedure call is translated into a Verilog task enable when the -Support Subprogram Calls switch has been selected.
Example
VHDL |
Verilog |
architecture cpu of cpu use work.mypackage.all; --defines ProcCall
begin p0 : process(s) begin ProcCall(s,s_out); end process;
end; |
module cpu; always @(s) begin : p0 ProcCall(s,s_out); end
//include file with called functions/tasks `include "cpu_cpu.v"
endmodule |
Concurrent Statements
VHDL concurrent statements occur in VHDL Architectures. These statements execute in concurrently, as there name suggests. VHDL2Verilog translates concurrent statements outlined in the following sections.
Block Statements (Concurrent Statement)
In VHDL it is possible to group statements together in a BLOCK. Declarations made in the Block have a local scope. In verilog there is no concepts of Blocks. VHDL2Verilog translates blocks by moving all its contents into the enclosing scope. Local declarations are renamed (the label of the block is prepended) and are also moved into the enclosing scope.
Example
VHDL |
Verilog |
architecture foo of aha is begin
b0: block constant a : boolean = true; begin s <= a and b and c; end block;
b1: block constant a : boolean = false; begin co <= (a and b) or (a and c) or (b and c); end block
end foo; |
module aha;
parameter B0_a = `true; parameter B1_a = `false;
// begin BLOCK B0 assign s = B0_a & b & c; // end BLOCK B0
// begin BLOCK B1 assign co = B1_a & b | B1_a & c | b & c; // end BLOCK B1
endmodule |
Process Statements (Concurrent Statement)
VHDL and Verilog have constructs that allow blocks of sequential statements to execute concurrently. In VHDL, these statements are PROCESS statements. PROCESS statements in VHDL are mapped to Verilog ALWAYS statements. If the VHDL process will execute only once during the simulation run (possible if the process sequential body has an infinite WAIT as its last item), then the process is mapped to the Verilog INITIAL statement.
VHDL2Verilog follows specific rules for mapping signal edges (RISING EDGE, FALLING EDGE) to Verilog. These rules apply only to processes with the following characteristics:
Process should have
1.Sensitivity signals or wait statement, and
2.Single IF (optional ELSIF) statement, and
3.IF (optional ELSIF) expression equivalent to Verilog POSEDGE or NEGEDGE. The IEEE Std_logic_1 164 package functions RISING_EDGE and FALLING_EDGE are identified by VHDL2Verilog as POSEDGE and NEGEDGE respectively.
In this case, the edge controls are moved to the ALWAYS sensitivity list, and the IF (ELSIF) expressions are modified to be equivalent to the VHDL description. Process PROCESS_DFF in the example below illustrates this concept.
Example
VHDL |
Verilog |
architecture diffeq of diffeq is begin
p0 : process begin Xoutport <= 0; Youtport <= 0; Uoutport <= 0; wait; end process p0;
p1 : process(Aport,DXport,Xinport, Yinport,Uinport) variable x_var, y_var, u_var : std_logic; begin Xoutport <= x_var after 2 ns; Youtport <= transport y_var; //will occur Xoutport <= u_var after 5ns; -- above will cancel previous assignment end process P1;
|
module diffeq;
initial begin : p0 Xoutport <= 0; Youtport <= 0; Uoutport <= 0; end
always @(Aport or DXport or Yinport or Uinport) begin : p1 reg x_var, y_var, u_var;
Xoutport <= #2 x_var; Youtport <= y_var; //fully non-blocking Xoutport <= #5 u_var; //above will not cancel prev assignment end |
Concurrent Signal Assignments (Concurrent Statement)
Concurrent Signal Assignments are used to drive signals continuously throughout the simulation run. Verilog CONTINUOUS ASSIGNMENTS provide the same capability. All VHDL concurrent signal assignments are translated to Verilog continuous assignments.
Example
VHDL |
Verilog |
architecture VeriArch of aha is signal s : std_logic; signal co : std_logic; begin s <= a and b and c after 2 ns; co <= (a and s) or (a and c); end VeriArch;
|
*********** DAN FIX THIS ********************* module aha(a,b,c,s,co);
wire V2V_s; wire V2V_co;
assign #2 V2V_s = a & b & c; assign V2V_co = a & V2v_s | a & c | b &c;
assign a = V2v_s; assign co = V2V_co;
endmodule |
Component Instantiations (Current Statement)
Both VHDL and Verilog are hierarchical languages and provide module instantiation capabilities. Additionally, values of generics can be changed during the process of module instantiation. Generic maps in VHDL component instantiations are translated to Verilog DEFPARAM statements.
Example
VHDL |
Verilog |
component inbuf generic (len : integer := 2) port(pad : in std_logic_vector(len downto 1); y : out std_logic_vector(len downto 1)); end component;
for all : inbuf use entity work.inbuf; begin
comp_1 :inbuf generic map(len=>2); port map (pad(1)=>a(1), y(1) => z(1), pad(2)=>a(2), y(2)>=>z(2) );
comp_2: inbuf generic map(len->2) port map( pad=>a, y=>z);
comp_3: inbuf generic map(len=>2) port map(a,z);
end rtl;
|
************ DLN FIX THIS module inbuf(pad,y); parameter len = 2;
input [len:1] pad; output [len:0] y;
assign y = pad; endmodule
defparam comp_1.len = 2; inbuf comp_1 ( .pad({a[2],a[1]}), .y({z[2],z[1]}) );
inbuf comp_2 (.pad(a), .y(z));
inbuf comp_3(a,z);
|
Generate Statements (Concurrent Statement)
VHDL GENERATE statements are useful when regular structures need to be modeled. In Verilog however, there is no comparable construct. VHDL2Verilog therefore elaborates the generate statement, and then translates the result into Verilog.
Example
VHDL |
Verilog |
Bit2: block constant ks : integer := BitW + BitW; constant kc : integer := BitW - 1; constant i : integer := 2; signal in1ANDin2 :std_ulogic_vector (0 to BitW-2); begin NextRow:for j in 0 TO BitW-2 generate in1ANDin2(j) <= ARR_MUL1in1(i) and ARR_MUL1in2(j);
NextRow1: IF j < (BitW-2) generate xx : fullxxx port map (in1ANDin2(j), carry(kc-BitW+1+j), carry(kc+j)); end generate NextRow1;
NextRow2: IF j = (BitW-2) generate pxx : partialfullxxx port map (in1ANDin2(j), carry(kc-BitW+1+j), carry(kc+j)); end generate NextRow2;
end generate; end block Bit2; |
// begin BLOCK Bit2 parameter Bit2_ks = BitW + BitW; parameter Bit2_kc = BitW - 1; parameter Bit2_i = 2;
wire [0:BitW - 2] Bit2_in1ANDin2;
assign Bit2_in1ANDin2[0] = ARR_MUL1in1[Bit2_i] & ARR_MUL1in2[0]; assign Bit2_in1ANDin2[1] = ARR_MUL1in1[Bit2_i] & ARR_MUL1in2[1]; assign Bit2_in1ANDin2[2] = ARR_MUL1in1[Bit2_i] & ARR_MUL1in2[2];
fullxxx xx_Bit2_NextRow1_0 ( Bit2_in1ANDin2[0], carry[Bit2_kc - BitW+1+0], carry[Bit2_kc + 0]);
fullxxx xx_Bit2_NextRow1_1 ( Bit2_in1ANDin2[1], carry[Bit2_kc - BitW+1+1], carry[Bit2_kc + 1]);
partialfullxxx pxx_Bit2_NextRow2_2 ( Bit2_in1ANDin2[2], carry[Bit2_kc - BitW+1+2], carry[Bit2_kc + 2]); // end BLOCK Bit2 |