Main Content

HDL インポートを使用した Verilog データフロー モデリング

"HDL インポート" を使用して、合成可能な HDL コードを Simulink® モデリング環境にインポートします。HDL コードをインポートするには、関数 importhdl を使用します。HDL コードで使用されている構造が HDL インポートでサポートされていることを確認します。

以下の表に、HDL コードをインポートするときに使用可能な、サポートされる Verilog® HDL データフロー パターンを示します。コードで、ラッチを推定するコードなどのサポートされていないデータフロー モデルを使用している場合、importhdl はファイル名と行番号へのリンクを含むエラー メッセージを生成します。次に、前述の例に示すようにコードを更新できます。

サポートされる Verilog データフロー パターン

Verilog データフロー モデルVerilog コード例

連続的な always ブロックのブロッキング代入と組み合わせた always ブロックのノンブロッキング代入。

たとえば、次の Verilog コードでは組み合わせた always ブロックで変数 temp に順序代入を使用しています。


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

同じ信号への複数代入。その信号への部分的な代入および完全な代入を使用できます。

次の例は、変数 out1_reg への部分的な代入および完全な代入の両方を実行する Verilog コードを示しています。


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    
    
  

推定される Switch ブロックの true パスまたは false パスの同じ変数に対する複数回代入。

たとえば、この Verilog コードは always ブロックの if 条件と else 条件の両方の変数 out1 に対して複数回代入を実行します。


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    
    
  
信号でのビット選択、部分選択、および配列インデックス付け操作。RHS で配列インデックス演算が実行されると、Multiport Switch が推測されます。LHS での配列インデックス演算は Assign ブロックとして推測されます。

たとえば、この Verilog コードは false 分岐で変数 out1 への複数回代入を使用していますが、これはサポートされていません。


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

サポートされない Verilog データフロー パターン

Verilog コードをインポートする場合、これらのデータフロー構造はサポートされません。"説明とシナリオ例" 列に、各シナリオの説明と例、およびこのシナリオの回避方法を示します。

Verilog データフロー モデル説明とシナリオ例

Verilog コードからのラッチ検出。

HDL コード内にラッチが存在すると、生成された Simulink モデルで代数ループが発生したり、モデルのコンパイルに失敗する可能性があります。ラッチの干渉を防ぐには、if-else 条件および case ステートメントですべての分岐を指定します。

たとえば、次の Verilog コードをインポートするときに、if 条件は Switch ブロックとして推定されます。ブロックには、コード内で指定された true パスがあります。Switch ブロックの出力は false パスに入力として直接フィードバックされ、結果的に代数ループが発生します。


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

Verilog コード内のクロック、リセット、クロック イネーブル信号に対する演算の実行。

clkrst、および enb などの名前を使用して信号を定義する場合、HDL インポートはこれらの信号をクロック、グローバル リセット、クロック イネーブル信号であると推定します。

たとえば、次の Verilog コードは、クロック信号 clk による明示的な代入を使用しています。この構造はサポートされていません。


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    
    
  

Verilog コードのクロック バンドルでいずれの信号に対する演算も実行していないことを確認します。さらに、コードで計算の実行に使用する信号について、それらの信号名がクロック信号、リセット信号、またはイネーブル信号と推定されるいずれの名前とも一致しないことを確認してください。クロック バンドルで信号と推定される可能性がある信号名については、関数 importhdlclockBundle の名前と値のペアを参照してください。

同じモジュール内の異なるクロック エッジまたは異なるリセット エッジに対するクロック信号またはリセット信号の感度。

正のエッジの影響を受けるクロック信号をもつ always ブロックと負のエッジの影響を受けるクロック信号をもつ always ブロックを同じモジュール内に含めることはできません。

たとえば、次の Verilog コードでは同じクロックの正のエッジと負のエッジを使用していますが、これはサポートされていません。


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    
    
  

Verilog コードの同じモジュールでクロック信号またはリセット信号の両方のエッジを使用していないことを確認します。クロックの posedge または negedge のいずれかを使用します。

同じモジュール内での同期回路および非同期回路の実現。

以下のコードに示されているように、Verilog コードを使用して同じモジュールで両方の回路を実現することはできません。非同期回路と同期回路を実現するには異なるモジュールを使用します。


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    
    
  

同じモジュールで推定される複数の RAM の初期化。

たとえば、この Verilog コードは sample_store0sample_store1 を RAM として推定します。この構造はサポートされていません。RAM 推定ごとに単一のモジュールに分けます。


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    
    
  

initial ブロックからの初期値の読み取りでの特定の構造の使用。

initial ブロックは、代入ステートメントまたは代入のある for ループ以外の構造はサポートされません。代入ステートメントの RHS のみを使用しなければなりません。

たとえば、次の Verilog コードでは if-else 条件を使用して変数 dout_a に値を代入し、変数 write_data をサポートされていない dout_c に代入します。

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  


使用時にすべての次元が参照されていない信号。

入力 Verilog コードにおける信号のすべての次元を使用します。追加の次元を指定する場合は、インデックス付きのビット選択が作成されます。

たとえば、次の Verilog コードでは 8-bit の変数 temp を作成しています。この変数の両方の次元が使用されていないため、always ブロック内の代入でエラーが生成されます。


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


参考

関数

関連する例

詳細