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

时间:2016-05-27 21:11:39

标签: verilog

我正在尝试参数化我编写的一些代码。下面的非参数化版本是针对WIDTH = 4编写的。我有一个循环为零的reg digits。根据这个零的位置,我想从我的数组segmentsSS输出一个特定的向量(我在别处为它赋值)。

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循环而不是像这样的案例陈述:

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,但我不确定如何在硬件中执行此操作。还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

你可以做一个循环并利用&#34;最后一次分配获胜&#34;。见下文。我在这里使用了一些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];