Verilog-2001 generateの高度な使用例:パラメトリックマルチプレクサの生成


verilog-2001 generate use case: multiplexer generator
  • clumsy level 1
  • clumsy level 2

  • clumsy level 1
    Verilogは文法の柔軟性が悪く,2001版ではgenerate機能が強化され,かえってその弊害が浮き彫りになった.generateの大きな用途はparameterに基づいて生成されたコード行数を自動的に判断することであり、assign、always、case文をサポートすることができるが、完全な文ブロックを含まなければならない.1つのN組のMビット制御信号のうち、指示信号に基づいて1組の制御信号が選択されるものとする.これらの制御信号には、いつでも1つのグループだけがユニホットコードであり、他のグループは全0であるという特徴がある.仮想コードの一部は次のとおりです.
    wire [param_m – 1 : 0] ctrl_in [param_n – 1 : 0];
    reg  [param_m – 1 : 0] ctrl_out;
    wire [31:0] sel;
    
    always@(*) begin
       case(sel)
          ‘h0:  ctrl_out = ctrl_in[0];
          ‘h1:  ctrl_out = ctrl_in[1];
          …  //wrong,         
          param_n-1: ctrl_out = ctrl_in[param_n-1] 
          default: ctrl_out = ‘h0;
       endcase
    

    param_だからnはparameterによって決まるので,以上のコードは書けない.直接generate文法に変えても、だめです.
    wire [param_m – 1 : 0] ctrl_in [param_n – 1 : 0];
    reg [param_m – 1 : 0] ctrl_out;
    wire [31:0] sel;
    genvar i;
    
    always@(*) begin
       case(sel)
       generate
          for (i=0;i

    これは私たちに書き方を変えさせます.
    wire [param_m – 1 : 0] ctrl_in  [param_n – 1 : 0];
    wire [param_m – 1 : 0] ctrl_tmp [param_n – 1 : 0];
    wire [param_m – 1 : 0] ctrl_out;
    wire [31:0] sel;
    
    assign ctrl_tmp[0] = ctrl_in[0];
    assign ctrl_tmp[1] = ctrl_in[1] | ctrl_tmp[1];
    … //               
    Assign ctrl_tmp[param_n-1:0] = ctrl_in[param_n-1:0] | ctrl_tmp[param_n-2];
    

    Note:入力制御信号の特殊性のため、ビット「または」を押した後、どのビットがハイレベルなのかを見つけるだけでmuxの目的に達します.
    書き換えたコードは不器用なようですが、今回はgenerateで生成できます.
    wire [param_m – 1 : 0] ctrl_in  [param_n – 1 : 0];
    wire [param_m – 1 : 0] ctrl_tmp [param_n – 1 : 0];
    wire [param_m – 1 : 0] ctrl_out;
    wire [31:0] sel;
    
    genvar i;
    generate 
    for (i=0;i

    clumsy level 2
    もっとバカならctrl_in特殊なpatternではなく、データのように、どのように生成しますか?もっと不器用にsel信号を利用してctrlを多く生成しますtmp2.
    ctrl_tmp2[0] = (sel==0) ? ctrl_in[0] : ‘h0;
    

    以下は、ctrlがdataに変換された完全な例です.
    wire [param_m – 1 : 0] data_in   [param_n – 1 : 0];
    wire [param_m – 1 : 0] data_tmp  [param_n – 1 : 0];
    wire [param_m – 1 : 0] data_tmp2 [param_n – 1 : 0];
    wire [param_m – 1 : 0] data_out;
    wire [31:0] sel;
    
    genvar i;
    generate 
    for (i=0;i

    注意:selはparamより大きい必要があります.nの可能な数は、1つも選択されていない場合を処理することができ、不満項目のcase defaultに似ています.