3

我知道闩锁在硬件和 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_done在 30 个班次后有数据random。如果我以这种方式实现它,我会收到闩锁的警告,并且它无法正常工作。

同样,在下面的代码中:

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 在按下停止位时变低。

我怎样才能避免这些闩锁?

4

3 回答 3

2

为什么不分配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 硬件描述语言。当强调描述

将每个寄存器的逻辑拆分到其自己的始终块中。

但是,首先绘制您要执行的操作的 RTL 示意图。如果你不能画出你想要设计的 RTL 原理图,你的设计很可能不是好的硬件。

于 2013-03-10T14:59:46.750 回答
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
于 2013-03-10T14:59:51.110 回答
1

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

于 2013-03-11T10:39:31.013 回答