首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Verilog顺序块,并行块,阻塞,非阻塞赋值,语句延迟

Verilog顺序块,并行块,阻塞,非阻塞赋值,语句延迟

这几个概念是不一样的
顺序块:顺序块中的语句是按顺序执行的,每条语句中的延迟值是与其前一条语句执行的仿真时间有关。
并行块:并行块语句是并行执行的,它里面的每条语句中指定的延迟值都是相对于语句块开始执行的时候。 所以顺序块和并行块的区别是,里面每条语句执行的仿真时间,而非具体的阻塞,非阻塞语句。
阻塞赋值:在一下条语句执行前,这条赋值语句必须已经完成。 非阻塞赋值:当非阻塞性过程赋值语句执行时,计算右侧的表达式,然后在预定时刻将右侧的值赋给的目标。最快的输出也要在当前时刻结束前的最后时刻。它计算出右侧的值后,并不阻塞,后面的语句正常运行,而真正的赋值发生在当前或者延迟结束的时刻。 不阻塞后面语句执行,在当前或者延迟结束时刻赋值是它的特点。而后面语句内部延迟,它只是说明赋值延迟时刻而已,而不关注赋值的时机。它们是不同的概念。 语句延迟分为语句间延迟和语句内部延迟。 出现在赋值语句右侧的延迟称为语句内部延迟,左侧的称为语句间延迟。 它们的区别主要是,语句内部延迟是先计算右式,然后进入延迟等待,最后把重新计算的值赋给的目标。 而语句间延迟,是等待到延迟时间后,马上计算右式并赋值给左式。 对于一个阻塞,非阻塞式赋值,它们可以使用语句间的延迟,或者使用内部延迟,然后这些语句可以在存在于顺序块或者并行块中,它们三个的概念是不一样的。
来看几个例子
1  begin     #100 a <= 1;                         执行在100ns时, 但真正赋值发生在100ns快要结束,所有其它在100ns的语句都执行完时     # 50 b <= 1;        赋值在150ns时  同上    # 50 c <= 1;        赋值在200ns时   同上   end 因为处于顺序块,所以语句间的延迟值都是相对于前一条的。第一条a <= 1的执行需要发生在100ns,而不管它是阻塞或非阻塞,因为它是语句间的延迟。而因为是顺序块,所以b <=1发生成150. 如果全换成阻塞赋值,结果一样,但它们失去了非阻塞语句的特性。 如果换成并行块,则a赋值发生在100ns,b发生在50ns, c发生在50ns。

2  begin #100 a<=1;   b<=1;  c<=#50 1;   enda赋值在100ns处,b赋值在100ns处,c当前的时刻是100,但赋值发生在150ns结束的时刻。
3 begin  a <= #50 1; b <= #100 1; c<= #150 1;  enda赋值发生在50ns, b发生在100ns, c发生在150ns。 第一条语句,发生在0ns时,而调度到50ns进行非阻塞赋值。因为是非阻塞,所以计算左式后,下一条马上进行。 所以第二条语句发生在0ns, 而调度到100ns进行非阻塞赋值........如果换成并行块,一样的。
4  begin  a = #50 1; b = #100 1; c= #150 1;  end  a发生在50ns, b发生在150ns, c发生在300ns 第一条语句发生在0ns,但由于是阻塞式赋值,第一条完全执行完了,才会执行第二条,所以一定要等到50ns结束后,才进行赋值。 所以b语句发生的时间为50ns.............. 如果为并行块,a发生在50ns, b发生在100ns, c发生在150ns。 .
5  begin  a <= #50 1; b <= #100 1; #100 c = 1;  end a发生在50ns, b发生在100ns, c发生在100ns
6  begin  a <= #50 1; b = #100 1; #100 c = 1;  a发生在50, b发生在100, c发生在200;
7  begin  a <= #50;  #100 b = 1; c = #100 1; a发生在50, b发生在100, c发生在200
所以记住这三个概念的特点1  顺序块是说每一条语句执行的时间都是上一条语句的相对时间,与并行块对应。 2  语句内赋值是先计算左边,赋值到一个临时变量,然后等到延时时间到了再赋值。而语句间赋值,是这条语句的执行必须等到这个延时时间到了,计算赋值一起完成。 3  阻塞赋值,是说这条语句必须完全执行完成,才会执行下一条语句,而非阻塞赋值,是说这条语句计算右式,存放临时值,然后马上执行下一条语句,真正的赋值会调度到延迟时间后执行。这个执行还包含它必须是延迟时间结束的前一刻进行赋值。 当然,我们这里展示的只是赋值,其实概念上说来,这个叫做时序控制,赋值只是其中一方面 时序控制有两种形式1  延迟控制2  事件控制[ time control] procedure_statement而procedure_statement也并不只是赋值语句,所以这个结构可以有很多种表示。下面是几个例子 1   #50;      //只是延迟50ns, 并不做什么2   @(poseeg clk)    //只是等待到clk的上升沿,并不做什么可见procedure_statement不是必须的。3   #50  if ()   else ()        整个if condition的执行会在延迟50执行。4   q = @(posedge clk) d;   语句内部延迟,也可以是事件控制。 repeat的用法注意以下三种方式sum = repeat(3) @(posedge clk) sum + 1;               1repeat(3) @(posedge clk) sum = sum + 1;                2repeat(3) @(posedge clk);                                        3 第一语句叫做重复事件控制,它表示需要等到clk的三个上升沿才会执行sum+1, 因此sum = 1 第二语句就是repeat重复,表示 @(posedge clk) sum = sum+1要重复三次,因次三次后,sum = 3 第三个语句就是等待clk的三个上升沿。 第一语句在使赋值语句和某些沿或者一定数量沿同步的时候非常有用。
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表