门级Verilog:有条件的,生成门输入

时间:2016-04-28 04:19:13

标签: verilog

我正在处理二进制解码器,并尝试参数化地址大小。这是一个项目要求,这是在门级verilog。

有没有办法在第二个生成语句中根据ADDR_SIZE生成i [k]语句?

module Decoder #(
  parameter ADDR_SIZE = 5
)(
  out,
  in
);
  input wire [ADDR_SIZE-1:0] in;
  output wire [(2**ADDR_SIZE)-1:0] out;
  wire [ADDR_SIZE-1:0] code, codeNot;

  genvar j;
  generate
    for (j = 0; j < ADDR_SIZE; j = j + 1)
    begin : bufs
      buf (code[j], in[j]);
      not(codeNot[j], in[j]);
    end
  endgenerate

  genvar i;
  generate
    for (i = 0; i < (2**ADDR_SIZE); i = i + 1)
    begin : selects
      and (out[i],
        i[0] ? codeNot[0] : code[0],
        i[1] ? codeNot[1] : code[1],
        i[2] ? codeNot[2] : code[2],
        i[3] ? codeNot[3] : code[3],
        i[4] ? codeNot[4] : code[4],
      );
    end
  endgenerate
endmodule

因此,如果ADDR_SIZE = 4,那么唯一会改变的是:

 and (out[i],
        i[0] ? codeNot[0] : code[0],
        i[1] ? codeNot[1] : code[1],
        i[2] ? codeNot[2] : code[2],
        i[3] ? codeNot[3] : code[3]
      );

或者如果ADDR_SIZE = 6

 and (out[i],
        i[0] ? codeNot[0] : code[0],
        i[1] ? codeNot[1] : code[1],
        i[2] ? codeNot[2] : code[2],
        i[3] ? codeNot[3] : code[3],
        i[4] ? codeNot[4] : code[4],
        i[5] ? codeNot[5] : code[5]
      );

由于它是解码器,我接受二进制输入2 ^ ADDR_SIZE(默认为5)。取决于输入二进制值是什么,相应的输出线将被驱动为高,所以如果在= 5&#39; b00001,out = 32&#39; b ... 0000001(点都是零。只有最低有效位是高)。如果在= 5&#39; b00011,则= 32&#39; b ... 0000100。

该部分已完成,并在以下代码中使用5位地址。我现在正试图这样做,如果我设置ADDR_SIZE = 4,我的输入现在是4&b; b我的输出现在是16&b; b。其中大多数都有效,每个输出行只是一个AND或inNot取决于地点。

在取出所有生成的代码之后,我基本上会问我如何执行以下操作。同样,重要的是在结构Verilog中完成。

parameter ADDR_SIZE = 5

generate . . .
 and(out, a, b, c, d, e);
endgenerate

parameter ADDR_SIZE = 3

generate . . .
 and(out, a, b, c);
endgenerate

parameter ADDR_SIZE = 6

generate . . .
 and(out, a, b, c, d, e, f);
endgenerate

1 个答案:

答案 0 :(得分:0)

如果你只想使用门级,我的建议是使用一个递归调用自身较小版本的模块。例如:

module my_and #(parameter SIZE=4) (output out, input [SIZE-1:0] in);
generate
  if (SIZE<2) begin
    // Intentionally cause a compile error if ever selected

    // Verilog requires you to be a bit clever with your error messages 
    // Suggest using using non-existing modules instances
    non_existing_module my_and_SIZE_is_less_than_2 ();

    // SystemVerlog allows option for more meaningful message
    //$error("SIZE must be >= 2, was %0d @ %m", SIZE);
  end
  else begin
    case(SIZE)
      2 : and and2 (out, in[0], in[1]);
      3 : and and3 (out, in[0], in[1], in[2]);
      4 : and and4 (out, in[0], in[1], in[2], in[3]);
      default : begin : recursive
        wire half0, half1;
        my_and #(SIZE/2) half_0 (half0, in[SIZE/2-1:0]);
        my_and #(SIZE/2) half_1 (half1, in[SIZE-1-(SIZE%2):SIZE/2]);
        if (SIZE%2) begin : odd
          and and3 (out, half0, half1, in[SIZE-1]);
        end
        else begin : even
          and and2 (out, half0, half1);
        end
      end
    endcase
  end
endgenerate
endmodule

注意 my_and未经过优化。根据您的目标最大大小和and的输入,您可能需要考虑让递归方法有条件地分成三个或四个子切片的组。

然后为select:

创建一个局部向量
genvar i,k;
generate
  for (i = 0; i < (2**ADDR_SIZE); i = i + 1)
  begin : selects
    wire [ADDR_SIZE-1:0] local_select; // local to scope
    for(k = 0; k < ADDR_SIZE; k = k + 1)
    begin
      assign local_select[k] = i[k] ? code[k] : codeNot[k];
    end
    my_and #(ADDR_SIZE) dec(out[i], local_select);
  end
endgenerate

RTL显然更简单:

module Decoder #(
  parameter ADDR_SIZE = 5
)(
  output reg [(2**ADDR_SIZE)-1:0] out,
  input [ADDR_SIZE-1:0] in
);
always @* begin
  out = {(2**ADDR_SIZE){1'b0}};
  out[in] = 1'b1;
end
endmodule