我知道锁存器在硬件和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
在random
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指示灯变低。
如何避免使用这些锁存器?
答案 0 :(得分: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原理图,那么您的设计很可能不是很好的硬件。
答案 1 :(得分: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
答案 2 :(得分:1)
如果您使所有代码同步(对posedge clk
敏感),则不会获得锁存。并且您将更容易编写时序约束(在最好的情况下,您只需要一个时钟周期的约束!)