赞
踩
1、Verilog代码
module flip_flop(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output reg led_out
);
// asynchronous reset D flip-flop
always @(posedge sys_clk) begin
if (sys_rst_n == 1'b0)
led_out <= 1'b0;
else
led_out <= key_in;
end
2、仿真现象
如图所示,led_out输出总比key_in输出延迟一个时钟周期
主要是非阻塞赋值与阻塞语句赋值的原因
解释如下:
①首先我们来看这一个代码段产生的效果
代码段:(主要是注意always块中的非阻塞赋值)
module blocking( input wire sys_clk , input wire sys_rst_n , input wire [1:0] in , output reg [1:0] out ); reg [1:0] in_reg; always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin in_reg <= 2'b00; out <= 2'b00; end else begin in_reg <= in; // 注意这一行 out <= in_reg; // 也要注意这一行,都是非阻塞赋值 end end endmodule
Testbench代码段:
module tb_blocking(); reg sys_clk; reg sys_rst_n; reg [1:0] in; // blocking Outputs wire [1:0] out; initial begin sys_clk = 1'b1; sys_rst_n <= 1'b0; in <= 2'b00; #20 sys_rst_n <= 1'b1; end always #10 sys_clk = ~sys_clk; always #20 in <= {$random} % 4; blocking blocking_inst( .sys_clk ( sys_clk ), .sys_rst_n ( sys_rst_n ), .in ( in ), .out ( out ) ); endmodule
产生的效果:
我们可以看到,in_reg总是滞后in一个时钟周期,out滞后in_reg一个时钟周期
②当我们把代码中always块的非阻塞赋值改为阻塞赋值时
代码段:
module blocking( input wire sys_clk , input wire sys_rst_n , input wire [1:0] in , output reg [1:0] out ); reg [1:0] in_reg; always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin in_reg <= 2'b00; out <= 2'b00; end else begin in_reg = in; // 注意这一行 out = in_reg; // 也注意这一行,阻塞赋值 end end endmodule
同上的Testbench,产生的仿真效果
我们可以看到,in_reg滞后in一个时钟周期,out居然不滞后in_reg了,这是为什么呢?
只能意会,不能言传,因为赋值语句,在赋值时候,相当于右边的信号有一个寄存器,需要寄存一拍。
1、时序逻辑:非阻塞赋值,组合逻辑:阻塞赋值(官方推荐)
2、always语句块中不要即使用阻塞赋值,又使用非阻塞赋值
3、锁存器不推荐使用,使用时要用非阻塞赋值
4、一个always语句块只对一个变量赋值
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。