【问题标题】:What to do when a latch cannot be avoided?当无法避免闩锁时该怎么办?
【发布时间】:2013-03-10 14:03:18
【问题描述】:

我知道闩锁在硬件和 Verilog 编码中是不受欢迎的。但是,我有时会遇到无法避免闩锁的情况。比如这两种情况:

always @ (*)
begin
    random_next = random; //default state stays the same
    count_next_r = count_r;
        
        random_next = {random[28:0], feedback}; //**shift left the xor'd every posedge clock
        

    if (count_r == 30) //if all 30 bits are shifted into register
    begin
        count_next_r = 0;
        random_done = random; //assign the random number to output after 13 shifts
    end
    else
    
        count_next_r = count_r + 1;

这里的random_done 是一个闩锁。我看不到任何其他写这个的方式。我只希望random_donerandom 的 30 个班次后有数据。如果我以这种方式实现它,我会收到闩锁警告并且它无法正常工作。

同样,在下面的代码中:

always @ (*)
begin
    state_next = state_reg; //default state stays the same
    count_next = count_reg;
    sel_next = sel;
    case(state_reg)
        idle:
            begin
                //DISPLAY HI HERE
                sel_next = 2'b00;
                if(start)
                begin
                    count_next = random_done; //get the random number from LFSR module
                    state_next = starting;
                end
            end
        starting:
            begin
                if(count_next == 750000000) // **750M equals a delay of 15 seconds. 8191 for simulation
                begin                           //and starting from 'rand' ensures a random delay
                    outled = 1'b1; //turn on the led 
                    state_next = time_it; //go to next state
                end
                
                else
                begin
                    count_next = count_reg + 1; 
                    outled = 1'b0;
                end
            end     
        time_it:
            begin
                    sel_next = 2'b01; //start the timer
                    state_next = done;                  
            end
                
        done:
            begin
                if(stop)
                    begin
                        sel_next = 2'b10; //stop the timer
                        outled = 1'b0;
                    end
                
            end
            
        endcase
        

从上面的代码中,有问题的部分是这样的:

done:
    begin
        if(stop)
            begin
                sel_next = 2'b10; //stop the timer
                outled = 1'b0;
            end

这里outled 被检测为一个锁存器,在执行过程中我被警告了这一点。我只是想让 LED 在按下停止位时变低。

如何避免这些闩锁?

【问题讨论】:

    标签: hardware verilog fpga xilinx


    【解决方案1】:

    为什么不将random_done 分配给寄存器。

    创建一个计数器并让它从 30 开始倒数,然后如果它为零,则分配寄存器 random_done 新的随机值。

    reg [4:0] counter; 
    
    always@(posedge clk) begin
      if(rst) begin
        counter <= 5'd30;
      end
      else begin
        if(counter == 0) begin
          counter <= 5'd30;
        else begin
          counter <= counter - 1;
        end
    end
    
    wire count_done;
    
    assign count_done = (counter == 0);
    
    reg [size-1:0] random_done
    
    always@(posedge clk) begin
      ...
      if(count_done) random_done <= random;
      ...
    end
    

    对我来说,这段代码看起来有点混乱,看起来不像是在描述硬件。请记住,Verilog 是一种 HDL 硬件描述语言。当强调描述时。

    将每个寄存器的逻辑拆分到它自己的 always 块中。

    但是,首先要绘制一个 RTL 示意图,说明您正在尝试做什么。如果您无法绘制想要设计的 RTL 原理图,那么您的设计很可能不是好的硬件。

    【讨论】:

    • 感谢您的回答。您能否详细说明“每个寄存器在其自己的始终块中的逻辑”是什么意思?这不会让设计变得非常忙碌和混乱吗?
    • 忙吗?你是什​​么意思?从硬件的角度来看,这并不重要。它会是一样的。我的意思是,如果您有一个计数器,那么如果您有一个状态寄存器,则将其放在一个总是块中,它有自己的块,依此类推。如果您有要读取或写入的状态寄存器,则它始终处于阻塞状态。看看我在示例中的代码。一个总是阻塞计数器,然后另一个阻塞 random_done。
    【解决方案2】:

    您应该能够排除outled 逻辑。像这样。

    always @(posedge clk or negedge nreset) begin
        if (!nreset) begin
            outled <= 0;
        end else if (state_reg == starting) begin
            if (count_next == 750000000) begin
                outled <= 1'b1; //turn on the led 
            end else begin
                outled <= 1'b0;
            end
        end else if ((state_reg == done) && stop) begin
                outled <= 1'b0;
        end
    end
    

    【讨论】:

      【解决方案3】:

      如果您使所有代码同步(对posedge clk 敏感),您将不会获得闩锁。而且您将更轻松地编写时序约束(在最好的情况下,您只需要一个时钟周期约束!)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-17
        • 2011-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-24
        • 2014-03-23
        相关资源
        最近更新 更多