Icarus Verilog

Icarus Verilog contains a code generator to emit VHDL from the Verilog netlist. This allows Icarus Verilog to function as a Verilog to VHDL translator.


To translate a Verilog program to VHDL, invoke "iverilog" with the -tvhdl flag.

% iverilog -t vhdl -o my_design.vhd my_design.v

The generated VHDL will be placed in a single file (a.out by default), even if the Verilog is spread over multiple files.


-pdebug=1Print progress messages as the code generator visits each part of the design.
-pdepth=NOnly output VHDL entities for modules found at depth < N in the hierarchy. N=0, the default, outputs all entities. For example, -pdepth=1 outputs only the top-level entity.

Supported Constructs[]

// Benchmark "top" written by ABC on Thu Jul 24 17:34:52 2014

☀`timescale 1ns / 1ps
// Company:

A Verilog module produces a VHDL entity/architecture pair with the same input and output ports. Any modules instantiated within the module produce both a VHDL component instantiation statement and a component declaration.

The code generator can identify most cases when a Verilog "out" port needs to be a "buffer" port in VHDL (i.e. when the signal needs to be read inside the entity).

reg [8:0] PaddlePosition;
reg [2:0] quadAr, quadBr;
always @(posedge clk) quadAr <= {quadAr[1:0], quadA};
always @(posedge clk) quadBr <= {quadBr[1:0], quadB};
always @(posedge clk)
if(quadAr[2] ^ quadAr[1] ^ quadBr[2] ^ quadBr[1])
  if(quadAr[2] ^ quadBr[1])
    if(~&PaddlePosition)        // make sure the value doesn't overflow
      PaddlePosition <= PaddlePosition + 1;
    if(|PaddlePosition)        // make sure the value doesn't underflow
      PaddlePosition <= PaddlePosition - 1;

`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 18:22:19 03/10/2021 // Design Name: // Module Name: A_NOR_B // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module A_NOR_B( input [3:0] A, input [3:0] B, output [3:0] NOR_AB


nor(NOR_AB[3],A[3],B[3]); nor(NOR_AB[2],A[2],B[2]); nor(NOR_AB[1],A[1],B[1]); nor(NOR_AB[0],A[0],B[0]);



Verilog functions are translated directly to VHDL functions. A special variable <function>_Result holds the return value of the function. For example:

assign DAC_data = cnt[10] ? ~cnt[9:0] : cnt[9:0];
function sum (
   a : unsigned(15 downto 0);
   b : unsigned(15 downto 0)
 return unsigned is
   variable sum_Result : unsigned(15 downto 0);
   sum_Result := (a + b);
   return sum_Result;
 end function;

Unlike Verilog functions, VHDL functions may not read global variables, and this restriction also applies to functions generated from Verilog. The Verilog-2001 "automatic" keyword is supported and generates recursive VHDL functions.


Signals and Types[]

Single-bit signals are converted to VHDL std_logic signals. Multi-bit vectors are converted to the signed/unsigned types from the ieee.numeric_std package. Conversion between these types is handled automatically, as is conversion from Boolean to std_logic values.

The mapping between Verilog signal values and std_logic values is as follows:

Verilog valueVHDL value

Drive strengths are not yet implemented.

Signal names which conflict with VHDL reserved words, differ only in case to another signal name, or are otherwise invalid as VHDL signal names are automatically renamed -- usually by prefixing "VL_".

Logic Gates[]

Primitive logic gates are translated to VHDL concurrent assignment statements. For example:

and(Z, X, Y);
Z <= X and Y;


Verilog blocking and non-blocking assignment are implemented using the the VHDL signal assignment operator.

Non-blocking assignment in Verilog has the same semantics as signal assignment in VHDL. For example, the following statement schedules the update of X at the next delay statement in Verilog, or wait statement in VHDL, or the end of the process:

X <= Y;

However, the Verilog blocking assignment operator schedules the update immediately. To emulate this in Verilog a zero-time wait is added after the assignment; this causes the VHDL simulator to schedule the update immediately after the statement has executed. For example, this Verilog statement:

X = Y;

Produces the following VHDL statements:

X <= Y;
wait for 0 ns;

The zero-delay wait is omitted if the statement is the last in the process, or the immediately following statement was a wait anyway.

Branching and Looping[]

Verilog if statements are translated directly to VHDL if statements which have identical semantics.

Verilog case statements can be translated to VHDL case statements provided the control and test expressions are "locally static" (basically, signal references or constants). If the control expression is not locally static, the VHDL code generator will assign it to a temporary variable immediately before the case statement and use that temporary as the control expression. For example, the following control expression would produce an invalid VHDL case statement:

case (cond&4'b1110)

So the code generator produces code to evaluate the expression separately and store it in a temporary:

  variable Verilog_Case_Ex : unsigned(3 downto 0);
  Verilog_Case_Ex := (cond and "1110");
  case Verilog_Case_Ex is

Test expression that are not locally static will currently produce invalid VHDL.

Time and Delays[]

User-defined Primitives[]


Signal Values and Resolution[]

There are several cases where the behaviour of the translated VHDL deviates from the source Verilog:

  • The result of division by zero is x in Verilog but raises an exception in VHDL.
  • Similarly, the result of reading past the end of an array in Verilog is x, whereas VHDL raises an exception.
  • Any signal that is driven by two or more processes will have the value 'U'. This is the result of the signal resolution function in the std_logic_1164 package.

Constructs not Supported[]

The following Verilog constructs cannot be translated to VHDL:

  • fork and join
  • force and release
  • disable
  • real-valued variables
  • switches
  • hierarchical dereferencing

Other Limitations[]

  • The test expressions in case statements must be constant.
  • Translation of a parameter to a corresponding VHDL generic declaration. Instead the default parameter value is used.