在 Verilog 中参数化不完整的 case 语句
Parameterizing an incomplete case statement in Verilog
我正在尝试参数化我编写的一些代码。下面的非参数化版本是为 WIDTH = 4 编写的。我有一个循环零的 reg digits
。基于这个零的位置,我想从我的数组 SS
输出一个特定的向量到 segments
(我在别处给它赋值)。
reg [6:0] SS [3:0];
always @(posedge clk)
if (reset) digits <= 4'b1110;
else digits <= { digits[2:0], digits[3] };
always @(*)
if (reset) segments <= ~7'h0;
else case(~digits)
4'b1 : segments[6:0] <= ~SS[0];
4'b10 : segments[6:0] <= ~SS[1];
4'b100 : segments[6:0] <= ~SS[2];
4'b1000 : segments[6:0] <= ~SS[3];
default : segments[6:0] <= 7'h0;
endcase
如何为 digits
的不同宽度参数化此 case 语句?我试过使用 for
循环而不是像这样的 case 语句:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits[i]) segments[6:0] <= ~SS[i];
end
但它不会合成,因为它说 segments
有多个驱动程序,如果我像下面那样以不同的方式进行合成,它会说 digits
不是常数,所以它无法合成:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits == (1 << i)) segments[6:0] <= ~SS[i];
end
我该怎么做?我想过取 ~digits
的对数基数 2 并在循环中检查它是否等于 i
但我不确定如何在硬件中执行此操作。有没有更好的方法?
你可以做一个循环并利用 "last assignment wins"。见下文。我在这里使用了一些 SystemVerilog 语法,但没有它你也可以做到。
PARAMETER SS_SIZE = 4
logic [6:0] SS [SS_SIZE];
logic [SS_SIZE-1:0] digits;
always_ff @(posedge clk or posedge reset)
if (reset) digits <= {{(SS_SIZE-1){1'b1}},1'b0};
else digits <= { digits[SS_SIZEE-2:0], digits[SS_SIZE-1] };
always_comb begin
segments = '0;
for(int i=0; i<SS_SIZE; i++) begin
if(digits[i]==1'b0) begin
segments = ~SS[i];
end
end
end
我会更进一步,用二进制计数器替换移位寄存器:
PARAMETER SS_SIZE = 4
logic [6:0] SS [SS_SIZE];
logic [$clog2(SS_SIZE)-1:0] count;
always_ff @(posedge clk or posedge reset)
if (reset) count <= '0;
else if(count == (SS_SIZE-1)) count <= '0
else count <= count+1;
assign segments = ~SS[count];
我正在尝试参数化我编写的一些代码。下面的非参数化版本是为 WIDTH = 4 编写的。我有一个循环零的 reg digits
。基于这个零的位置,我想从我的数组 SS
输出一个特定的向量到 segments
(我在别处给它赋值)。
reg [6:0] SS [3:0];
always @(posedge clk)
if (reset) digits <= 4'b1110;
else digits <= { digits[2:0], digits[3] };
always @(*)
if (reset) segments <= ~7'h0;
else case(~digits)
4'b1 : segments[6:0] <= ~SS[0];
4'b10 : segments[6:0] <= ~SS[1];
4'b100 : segments[6:0] <= ~SS[2];
4'b1000 : segments[6:0] <= ~SS[3];
default : segments[6:0] <= 7'h0;
endcase
如何为 digits
的不同宽度参数化此 case 语句?我试过使用 for
循环而不是像这样的 case 语句:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits[i]) segments[6:0] <= ~SS[i];
end
但它不会合成,因为它说 segments
有多个驱动程序,如果我像下面那样以不同的方式进行合成,它会说 digits
不是常数,所以它无法合成:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits == (1 << i)) segments[6:0] <= ~SS[i];
end
我该怎么做?我想过取 ~digits
的对数基数 2 并在循环中检查它是否等于 i
但我不确定如何在硬件中执行此操作。有没有更好的方法?
你可以做一个循环并利用 "last assignment wins"。见下文。我在这里使用了一些 SystemVerilog 语法,但没有它你也可以做到。
PARAMETER SS_SIZE = 4
logic [6:0] SS [SS_SIZE];
logic [SS_SIZE-1:0] digits;
always_ff @(posedge clk or posedge reset)
if (reset) digits <= {{(SS_SIZE-1){1'b1}},1'b0};
else digits <= { digits[SS_SIZEE-2:0], digits[SS_SIZE-1] };
always_comb begin
segments = '0;
for(int i=0; i<SS_SIZE; i++) begin
if(digits[i]==1'b0) begin
segments = ~SS[i];
end
end
end
我会更进一步,用二进制计数器替换移位寄存器:
PARAMETER SS_SIZE = 4
logic [6:0] SS [SS_SIZE];
logic [$clog2(SS_SIZE)-1:0] count;
always_ff @(posedge clk or posedge reset)
if (reset) count <= '0;
else if(count == (SS_SIZE-1)) count <= '0
else count <= count+1;
assign segments = ~SS[count];