【问题标题】:Verilog/SystemVerilog inferred latch in case statementVerilog/SystemVerilog 在 case 语句中推断闩锁
【发布时间】:2016-08-18 02:44:24
【问题描述】:

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

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 语句中,我有一个默认情况,它将捕获所有不匹配的值。我还为数组中的每个索引设置了一个值。我不明白我在哪里隐式地将我的数组设置为隐式值。

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

【问题讨论】:

    标签: arrays switch-statement verilog system-verilog hdl


    【解决方案1】:

    这是我要开始的。
    首先在 always 语句中添加一个敏感度列表。如果在那里你有一个“重置”,所以听起来你想要总是@(posedge clk或posedge重置)。我知道您正在使用 always_comb,但我很想知道这是否确实消除了问题。它会告诉你。

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

    其次,可能更重要的是,您似乎正在使用 access_index_i

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

    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
    

    【讨论】:

    • 但我有一个关于组合与顺序的问题。由于我的access_index_i 是一个变量,我想在一个时钟周期内将该特定索引设置为 0。如果我组合分配它,我可以做到这一点,但顺序需要 2 个时钟周期。首先,我需要将 lru_list[] + 1 更新为所有四个索引,然后将四个索引之一设置为零。你会推荐我做什么?我不能做access_index_i := 2lru_list[access_index_i] &lt;= &lt;some val not 0&gt;lru_list[2] &lt;= 0;,因为这会给同一个变量分配两个不同的值
    • 在原帖中查看我对您的评论的回答。
    【解决方案2】:

    组合块纯粹根据输入定义输出,没有状态。

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

    您的默认声明:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-19
      • 1970-01-01
      相关资源
      最近更新 更多