Verilog/SystemVerilog 在 case 语句中推断闩锁

Verilog/SystemVerilog inferred latch in case statement

我无法理解为什么我的代码有锁存器

logic [1:0] lru_list [0:3];

always_comb begin
    if(reset) begin
        lru_list[0] = 0;
        lru_list[1] = 0;
        lru_list[2] = 0;
        lru_list[3] = 0;
    end
    else begin
        case({access, update, access_index_i < 4})
            3'b101: begin
                lru_list[0] = lru_list[0] + 1;
                lru_list[1] = lru_list[1] + 1;
                lru_list[2] = lru_list[2] + 1;
                lru_list[3] = lru_list[3] + 1;
                lru_list[access_index_i] = 0;
            end
            3'b011: begin
                lru_list[0] = lru_list[0];
                lru_list[1] = lru_list[1];
                lru_list[2] = lru_list[2];
                lru_list[3] = lru_list[3];
                lru_list[access_index_i] = 0;
            end
            default: begin
                lru_list[0] = lru_list[0];
                lru_list[1] = lru_list[1];
                lru_list[2] = lru_list[2];
                lru_list[3] = lru_list[3];
            end
        endcase
    end

end // always_comb

在 case 语句中,我有一个默认 case,它将捕获所有不匹配的值。我还为数组中的每个索引设置了一个值。我不明白我在哪里隐式地将我的数组设置为隐式值。

我认为这可能与 lru_list[access_index_i] = 0; 有关,但注释掉这两行仍然会出现保存错误。

这是我要开始的。
首先在 always 语句中添加一个敏感列表。你有一个 "reset" if 在那里,所以听起来你想要 always @(posedge clk 或 posedge reset)。我知道您正在使用 always_comb,但我很想知道这是否确实解决了问题。它会告诉。

编辑:所以我刚刚意识到您正在使用 RHS 上的相同变量对 LHS 变量进行操作。你需要计时。否则当你组合进入计数状态时,它永远无法解决,因为它总是在无限循环中添加。总是@(posedge clk 或 posedge reset)我认为你会得到更好的结果。

其次,可能更重要的是,您似乎正在使用 access_index_i < 4 并试图从中提取一些位来构成串联向量的最低有效位 {access, update, access_index_i < 4}。如果你向右移动,我认为逻辑会在结果中插入 4'b0000,我猜它并不是真正的开始,所以我想知道在 3'b101 案例中实际使用了什么位作为它将由 {bit,bit,vector} 寻址。似乎您想说 {bit,bit,vector[4]} 或类似的东西。您实际上可能正在使用 access_index_i 的最低有效 3 位来处理您的组合语句。

编辑:回复您在下方的评论。你可以,(这就是我所做的)将问题分成两部分,组合和时钟。

reg [3:0] my_sig;
wire [3:0] my_sig_wire;

always @ (posedge clk)
begin
    my_sig <= my_sig_wire;
end

always (*)
   begin
     if(reset)
       begin 
        my_sig_wire = 4'b0000;  // This will also reset the clocked version
       end
     else
        begin
        my_sig_wire = my_sig;  // This is okay, because no matter
                               // how much I alter my_sig_wire, my_sig will
                               // only change on the clock pulse.  So
                               // we avoid the infinite loop problem
        my_sig_wire[index] = 1'b0;  //  Tweak one of the signals for fun.
                                    //  on the next clock, my_sig is updated!
        end
    end

组合块定义了纯粹基于输入的输出,没有状态。

时序元件(触发器)包含状态,因此输出可以基于输入和状态,或仅基于状态。

您的默认语句:

default: begin
            lru_list[0] = lru_list[0];

通过保存一个值来维持状态,因此不能组合。您尚未定义触发器 (@(posedge clk)),因此推断出一个锁存器来保持状态。