[英]Parameterizing an incomplete case statement in Verilog
I am trying to parameterize some code I have written.我正在尝试参数化我编写的一些代码。 The non parameterized version below is written for WIDTH = 4. I have a reg
digits
that cycles a zero.下面的非参数化版本是为 WIDTH = 4 编写的。我有一个循环零的 reg
digits
。 Based on where this zero is I want to output a particular vector to segments
from my array SS
(I assign values to it elsewhere).基于这个零的位置,我想输出一个特定的向量到我的数组
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
How can I parameterize this case statement for a different width of digits
?如何为不同宽度的
digits
参数化这个 case 语句? I've tried using a for
loop instead of a case statement like this:我试过使用
for
循环而不是这样的 case 语句:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits[i]) segments[6:0] <= ~SS[i];
end
But it won't synthesize because it says segments
has multiple drivers and if I do it in a different way like below it says digits
is not constant so it can't synthesize:但它不会合成,因为它说
segments
有多个驱动程序,如果我以不同的方式来做,如下所示,它说digits
不是恒定的,所以它不能合成:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits == (1 << i)) segments[6:0] <= ~SS[i];
end
How can I do this?我怎样才能做到这一点? I have thought of taking the log base 2 of
~digits
and checking if that is equal to i
within the loop but I'm not sure how to do that in hardware.我想过取
~digits
对数基数 2 并检查它是否等于循环中的i
但我不确定如何在硬件中做到这一点。 Is there a better way?有没有更好的办法?
You can do a loop and take advantage of the "last assignment wins".您可以进行循环并利用“最后一次分配获胜”。 See below.
见下文。 I used some SystemVerilog syntax here, but you could do it without it.
我在这里使用了一些 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
I would go further and replace the shift register with a binary counter:我会更进一步,用二进制计数器替换移位寄存器:
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];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.