always@(posedge clk)时序赋值延迟一个周期

前几天是问了我一个小问题,我总结关键点如下:
情形一:

always@(posedge clk) begin
	if(ce == 1'b1 && ready == 1'b1)
		w_en <= 1'b1;
	else
		w_en <= 1'b0;
end 

情形二:

always@(posedge clk) begin
	if(ce == 1'b1 && ready == 1'b1)
		if(data <= 8'b1111_1111)
			data <= data_in;
		else 
			data <= data; //data_in是上一个模块的时序输出
end 

他的问题是:为什么情形一中的w_en在条件满足的时候立马发生变化,也就是在本周期改变;而在情形二中当条件满足的时候,data的值不是立马发生变化,而是在下一周期发生变化?
可以用波形表示如下:
always@(posedge clk)时序赋值延迟一个周期_第1张图片
这个问题我当时也没注意过,写程序的时候我大多时候是看着时序图对了就行了,被这一问难倒了!!!

通过分析我明白了。
分析:

情形一:
首先,进入这个过程块的条件是在时序的上升沿,如果满足if条件就会执行 w_en <= 1'b1;
赋值过程是这样的,首先统一计算表达式右边的值,然后在统一的赋给左边的变量,改变是几乎
是立即发生的,也就是在本周期改变。w_en <= 1'b1 语句右边的值可以看做是一个组合逻辑
信号,所以改变是立即发生的。

情形二:
首先,进入这个过程块的条件也是在时序的上升沿,如果满足if条件就会进入到data<=
data_in,否则保持不变。赋值的过程也是先统一计算表达式右边的值,然后在一次性赋给表达
左边的变量data,改变也几乎是立即的,即也是在本周期进行更新。由于data_in是有外部的模
块传输进来的,所以需要看一下data_in是否经过时序驱动,如果经过时序驱动,那data_in就
相当于一个时序逻辑信号,所以data肯定会比data_in晚一个周期。如果data_in是一个组合逻辑信号,那么data和data_in的波形在条件满足之后就会完全对齐。
请看下面的这个式子:
always@(posedge clk)begin
	if(条件满足) begin
		b <= a;
	end
	else begin
	……
	end	
end

如果把 a换成data_in,把b换成data可能会更好理解一点。

附录:

顶层模块:

module non_block(
input					clk,
input					rst,
input					ce,
input					ready,
input	 [7:0]		data_in,
output  reg				w_en,
output  reg [7:0]		data
    );
    
    reg			[7:0]	data_reg = 8'b01010101;
    always@(posedge clk)begin
    	if(!rst)begin
    		w_en <= 1'b0;
    		data	  <= 8'b0;
    	end
    	else if(ce ==1'b1 && ready ==1'b1) begin
    		if(data<=8'b11111111)begin
    			w_en <= 1'b1;
    			data  <= data_in;
    		end
    	end
    end
    
endmodule

tb1:

module tb_non_block(

    );
    reg						clk;
    reg						rst;
    reg						ce;
    reg						ready;
    reg		[7:0]		    data_in;
    
    wire				    w_en;
    wire	 [7:0]			data;
    
    initial begin
    	clk = 1;
    	forever #10 begin
    		clk = ~clk;
    	end
    end
    
    
    initial begin
    	rst = 0;
    	ce =0;
    	ready = 0;
    	#60;
    	rst = 1;
    	#20;
    	ce = 1'b1;
    	ready = 1'b1;
    end
    //data_in是一个时序逻辑信号
    always@(posedge clk)begin
    	if(!rst)
    		data_in <=0;
    	else if(data_in<=8'b11111111)
    		data_in <= data_in +1;
    end
    
    non_block non_block0(
    .clk(clk),
    .rst(rst),
    .ce(ce),
    .ready(ready),
    .data_in(data_in),
    .w_en(w_en),
    .data(data)
        );
endmodule

对应的波形如下:

always@(posedge clk)时序赋值延迟一个周期_第2张图片

tb2:

module tb_non_block(

    );
    reg						clk;
    reg						rst;
    reg						ce;
    reg						ready;
    reg		[7:0]		    data_in;
    
    wire				    w_en;
    wire	 [7:0]			data;
    
    initial begin
    	clk = 1;
    	forever #10 begin
    		clk = ~clk;
    	end
    end
    
    
    initial begin
    	rst = 0;
    	ce =0;
    	ready = 0;
     	data_in = 8'b0;
    	#60;
    	rst = 1;
    	#20;
    	ce = 1'b1;
    	ready = 1'b1;
    	data_in = 8'b00010001; //data_in是一个组合逻辑信号
    end
    
    non_block non_block0(
    .clk(clk),
    .rst(rst),
    .ce(ce),
    .ready(ready),
    .data_in(data_in),
    .w_en(w_en),
    .data(data)
        );
endmodule

对应的波形:
always@(posedge clk)时序赋值延迟一个周期_第3张图片

你可能感兴趣的:(verilog)