我正在处理二进制解码器,并尝试参数化地址大小。这是一个项目要求,这是在门级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
答案 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