Main Content

Verilog Dataflow Modeling with HDL Import

Use HDL import to import synthesizable HDL code into the Simulink® modeling environment. To import the HDL code, use the importhdl function. Make sure that the constructs used in the HDL code are supported by HDL import.

These tables list the supported Verilog® HDL dataflow patterns that you can use when importing the HDL code. If your code uses an unsupported dataflow model such as code that infers a latch, importhdl generates an error message with a link to the file name and line number. You can then update the code as illustrated in the preceding examples.

Supported Verilog Dataflow Patterns

Verilog Dataflow ModelExample Verilog Code

Blocking assignments in sequential always blocks and nonblocking assignments in combinational always blocks.

For example, this Verilog code uses a sequential assignment for the variable temp in a combinational always block.


module dataconv(clk,a,b,c);

input clk; integer i;
input wire [7:0] a, b;
output wire [7:0] c;
reg [1:0] temp [0:7];

always @(*) begin
    for (i=0;i<=7;i=i+1) begin
        temp[i] <= a[i] + b[i];
    end
 end

assign c = temp;

endmodule

Multiple assignments to the same signal. You can use partial and complete assignments to that signal.

This example shows the Verilog code that performs both partial assignment and complete assignment to the variable out1_reg.


module testPartialAndCompleteAssign
    (input [2:0] in1, in2,
     input cond, clk,
     output [2:0] out1);
  
  reg [2:0] out1_reg;
  
  always@(posedge clk) begin
    if(cond) begin
      out1_reg[0] = 1'b0;
      out1_reg[1] = 1'b0;
      out1_reg[2] = 1'b0;
    end
    else begin
      out_reg = in1 & in2;
    end
  end
  assign out1 = out1_reg;

endmodule    
    
  

Multiple assignments to the same variable in the true or false path of a Switch block that gets inferred.

For example, this Verilog code performs multiple assignments to the variable out1 inside both the if and else conditions of the always block.


module testSwitchMuxing
    (input [2:0] in1,
     input cond,
     output reg [2:0] out1);
  
  always@(*) begin
      if (cond) begin
          out1 = in1;
      end
      else begin
          out1 = 3'd2;
          out1 = 3'd1;
      end
   end
  
endmodule    
    
  
Bit select, part select, and array indexing operations with signals. A Multiport Switch is inferred when array indexing is performed at the RHS. An array indexing operation on the LHS is inferred as an Assign block.

For example, this Verilog code uses multiple assignments to the variable out1 in the false branch, which is not supported.


module ArrayIndexing 
    (In1, In2, In3, In4, 
    Sel1, Sel2, 
    Out1, Out2, Out3);

parameter w = 7;
input  [w:0] In1, In2, In3, In4;
input  [1:0] Sel1, Sel2;
output [w:0] Out1;
output [1:0] Out2;
output       Out3;

wire [w:0] v[3:0];

assign v[0] = In1;
assign v[1] = In2;
assign v[2] = In3;
assign v[3] = In4;

//Array indexing with signal Sel1
assign Out1 = v[Sel1];

//Part select on array index with signal Sel2
assign Out2 = v[Sel2][7:2];

//Bit select on array index with signal Sel
assign Out3 = v[Sel2][4];

endmodule

Unsupported Verilog Dataflow Patterns

These dataflow constructs are unsupported when you import the Verilog code. The Description and Example Scenarios column describes each scenario with an example and illustrates how you can avoid this scenario.

Verilog Dataflow ModelDescription and Example Scenarios

Latch detection from the Verilog code.

Presence of latches in the HDL code can result in algebraic loops in the generated Simulink model and result in model compilation failures. To avoid latch inference, specify all branches in if-else conditions and in case statements.

For example, when you import this Verilog code, the if-condition is inferred as a Switch block. The block has a true path that is specified in the code. The output of the Switch block is fed back directly as input to the false path which results Fin an algebraic loop.


module testAlgebraicLoop(input cond,
        input [2:0] in1,
        output reg [2:0] out1);

// causes latch inference - unsupported
always@(*) begin
    if (cond) begin
        out1 = in1;
    end
end

// Specify else branch to avoid latch inference
// always@(*) begin
//     if (cond) begin
//         out1 = in1;
//     end
//     else begin
//         out1 = in1 + 1;
//     end
// end

endmodule

Performing operations on clock, reset, or clock enable signals in the Verilog code.

When you define signals using names such as clk, rst, and enb, HDL import infers these signals to be the clock, global reset, and clock enable signals.

For example, this Verilog code uses an explicit assignment with the clock signal clk. This construct is not supported.


module testOperationOnClkBundle
    (input [2:0] in1,
     input clk,
     output reg [2:0] out1,
     output out2);
  
  reg [2:0] out1_reg;
  
  always@(posedge clk) begin
     out1_reg <= in1;
    end
 
  assign out2 = clk && 1'b1;

endmodule    
    
  

Make sure that your Verilog code does not perform operations on any of the signals in the clock bundle. In addition, for signals that you use for performing computations in your code, make sure that the signal names do not match any of the names that are inferred as clock, reset, or enable signals. See the clockBundle name-value pair of the importhdl function for possible signal names that are inferred as signals in the clock bundle.

Sensitivity of clock or reset signal to different clock edges or different reset edges inside the same module.

You cannot have one always block with the clock signal sensitive to the positive edge and the other always block with the clock signal sensitive to the negative edge inside the same module.

For example, this Verilog code uses the positive and negative edges of the same clock, which is not supported.


module testMultipleClockEdges
    (input [2:0] in1, in2,
     input clk,
     output [2:0] out1, out2);
  
  reg [2:0] out1_reg, out2_reg;
  
  /* clk sensitivity to posedge */
  always@(posedge clk) begin
     out1_reg <= in1 && in2;
    end
  
  /* clk sensitivity to neegedge */
  always@(negedge clk) begin
     out2_reg <= in1 || in2;
    end
  
  assign out1 = out1_reg;
  assign out2 = out2_reg;

endmodule    
    
  

Make sure that your Verilog code does not use both edges of the clock or reset signal in the same module. Use either posedge or negedge of the clock.

Realization of synchronous and asynchronous circuits inside the same module.

You cannot use Verilog code realizes both circuits in the same module as shown in the code below. Use different modules for realization of asynchronous and synchronous circuits.


module testSynchronousAsynchronous
    (input [2:0] in1, in2,
     input clk, reset,
     output [2:0] out1, out2);
  
  reg [2:0] out1_reg, out2_reg;
  
  /* synchronous always block */
  always@(posedge clk) begin
     out1_reg <= in1 && in2;
    end
  
  /* asynchronous always block */
  always@(posedge clk or posedge reset) 
  begin
     out2_reg <= in1 || in2;
    end
  
  assign out1 = out1_reg;
  assign out2 = out2_reg;

endmodule    
    
  

Initialization of multiple RAMs that are inferred in the same module.

For example, this Verilog code infers sample_store0 and sample_store1 as RAMs. This construct is not supported. Separate each RAM inference into a single module.


module testMultipleRAMs
    (input [2:0] in1, in2,
     input clk, reset,
     output reg [2:0] read_data0, read_data1);
  
  reg [2:0] out1_reg, out2_reg;
  
  /* Inference of RAM sample_store0 */
  always@(posedge clk) begin
    if (write_enable) begin
      sample_store0[write_address] <= write_data;
    end
    read_data0 = sample_store0[read_address0]
  end
  
  /* Inference of RAM sample_store1 */
  always@(posedge clk) begin
    if (write_enable) begin
      sample_store1[write_address] <= write_data;
    end
    read_data1 = sample_store0[read_address1]
  end
  
endmodule    
    
  

Usage of certain constructs when reading initial values from an initial block.

An initial block does not support constructs other than assignment statements or for loops with assignments. The RHS of the assignment statement must use only

For example, this Verilog code uses an if-else condition to assign a value to the variable dout_a and assigns a variable write_data to dout_c, which are not supported.

module testInitial 
        (input cond, 
        input [3:0] write_data
        output reg [3:0] dout_a, dout_b, doutc);
        
        parameter AddrWidth = 3;
        
        integer i;
        reg [3:0] ram [7:0]; 
        
        initial begin
          for (i=0; i<=2**AddrWidth - 1; i=i+1) begin
              ram[i] = 0;
          end
          dout_b = 0;

          // if-else condition - not supported
          if (cond) begin
               dout_a = 0;
          end
          else begin
               dout_a = 4;
          end
          end
          
          // Variable assignment to RHS - not supported
          dout_a = write_data;

          // Use assignment statements instead for 
          // dout_a and dout_c 
          // dout_a = 4;
          // dout_c = 32;
          // end
          // end
          
endmodule  


All dimensions of signals not referenced at time of usage.

Use all dimensions of a signal in the input Verilog code. If you specify an additional dimension, it creates an indexed bit select.

For example, this Verilog code creates an 8-bit variable temp. The assignment inside the always block generates an error because it does not use both dimensions of the variable.


module dataconv(clk,a,b,c);

input clk; 
input wire [1:0] a, b;
output wire [1:0] c;

reg [7:0] temp_reg [1:0][1:0];

// temp_reg is not indexed 
// with both dimensions - not supported
always @(posedge clk) begin
        temp_reg [0] <= a[0] + b[0];
        temp_reg [1] <= a[1] + b[1];
    end


// Use both dimensions when indexing a variable
// always @(posedge clk) begin
//        temp_reg [0][0] <= a[0] + b[0];
//        temp_reg [0][1] <= a[0] + b[1];
//        temp_reg [1][0] <= a[1] + b[0];
//        temp_reg [1][1] <= a[1] + b[1];

// You can also perform indexed bit select
//         temp_reg [1][0][1] = 1'b0;
//  end

assign c = temp_reg;

endmodule


See Also

Functions

Related Examples

More About