Verilog中非阻塞赋值会使数据延时一个clock的疑惑?

 `timescale 1ns/1ps
module freq ();
reg             clk_250     =   1'b0        ;
reg             rst         =   1'b1        ;               
reg [6  :   0]  cnt         =   7'd0        ;
reg             valid       =   1'b0        ;
reg [2  :   0]  valid_cnt   =   3'd0        ;

parameter PERIOD_250 = 4 ;


//产生250MHZ时钟
initial
begin
    clk_250 = 0;
    forever #(PERIOD_250/2) clk_250 = ~clk_250; 
end

initial
begin
    #8  rst =   1'b0    ;
end

always  @   (   posedge clk_250 )
begin
    if( rst ==  1)
        cnt <=  8'b0000_0000    ;
    else
        begin
            if( cnt ==  8'd100  )
                cnt <=  8'd1    ;
            else
                cnt <=  cnt +   8'b1;
        end
end


always  @   (   posedge clk_250 )
begin
    if( rst ==  1'b1    )
        valid_cnt   <=  3'd0                ;
    else
        begin
            if( valid_cnt   ==  3'd6)
                valid_cnt   <=  3'd1;
            else
                valid_cnt   <=  valid_cnt   +   3'd1;
        end     
end


always  @   (   posedge clk_250 )
begin
    if( rst ==  1)
        valid   <=  1'b0    ;
    else
        begin
            if( valid_cnt   ==  1)
                valid   <=  1'd1;
            else
                valid   <=  1'd0;
        end
end
endmodule

上面代码想实现的是1到100的数据进行循环。并且有一个valid信号标志有效位,每6个数据有一个valid信号。下面是我用modelsim仿真得到的仿真图。图片说明
自己认为的仿真图应该是下面这样。图片说明
非阻塞赋值的结果要在下一个clock的上升沿才能得出。也就是需要延迟一个clock。仿真图里面感觉就有点自相矛盾。在生成cnt信号和valid-cnt 信号时直接在当前的clock就产生数据。然而产生valid信号时却是在下一个时钟产生的。
自己接触verilog时间不常工作需要,所以必须要把这个点弄会。总结上面的问题,其实就一个,非阻塞赋值会使得到的数据延时一个clock吗?如果是如何解释cnt和valid-cnt信号的生成。如果不延时一个clock那么valid信号为什么在下一clock才得出结果。希望能够得到专业的回答!!!毕竟我写了这么多又做了这么多的工作。

这个我觉得应该从时间片的概念上解答
图片说明

verilog的timeslot划分5个域:
Active region : 执行process语句,阻塞赋值,连续赋值,及非阻塞赋值的右侧求值事件,阻塞赋值和连续赋值会触发在该时刻的新事件。$display是在该region执行。
Inactive region : 执行 #0的阻塞赋值;
NBA region : 更新非阻塞赋值的LHS(左侧值);
Monitor region : 执行$monitor 和 $strobe等,不会触发任何其他事件的read-only region
process: 进程是Verilog中的独立执行单元,包括:原语(Primitives), 模块(Moules), initial过程块, always过程块, 连续赋值语句(assign), 异步任务(task)。在仿真时,所有的进程都是仿真器按Verilog的语义来顺序执行的,效果是各个进程并行执行的效果,在未执行完当前所有的进程时,仿真时间不会向前推进。
你这个例子就是先在active region执行了porcess 这个时候非阻塞运算的cnt值( 处在右侧求值阶段) ,cnt实际值=6,执行判断语句(cnt == 1)当然就不成立,active region执行然后才会跳转到NBA region ,更新非阻塞赋值的左侧值 即cnt在此刻才变成1

https://wenku.baidu.com/view/74f85228ed630b1c59eeb51c.html

非阻塞赋值,中每个<=都会占用一个时钟

cnt 、valid cnt和valid都是下一个时钟得出结果。
比如,代码中rst==1的时候,cnt保持为0,rst刚变化为0的第一个周期,语句是走的cnt <= cnt + 1,但是下一个周期,cnt才变成1。
valid也是同样的,在valid cnt为1的时候,走的是valid <=1这条语句,但是下一个周期valid才会赋值为1。

很簡單,
cnt和valid-cnt都是宣告為序向邏輯, 所以這兩個訊後都是要等clk敲完下一個cycle才會產生
簡單講, valid-cnt的部分改成組合邏輯的寫法, always(...or ...) begin xxx=ooo ... end, 就會是你要的答案

图中现象涉及到verilog仿真语义。
硬件来说
针对valid信号,因为在valid_cnt == 1时, 才会运行 valid <= 1'd1。
而valid_cnt =1 是在触发器hold之后,所以在第一个时钟上升沿时,条件valid_cnt == 1不成立,所以valid不会发生变化。
在第二个时钟上升沿到来时,valid_cnt == 1,这时才开始运行valid。此时valid_cnt刚刚由1变成2。

这个问题已经过去很久了,刚刚自己也碰到了这个问题,看了一些书和博客。不知道这样理解对不对。