简体   繁体   English

在 Verilog 中参数化不完整的 case 语句

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM