阻塞赋值、非阻塞赋值和延迟

阻塞赋值(Blocking)

格式 b = a
特点:

  • 赋值语句执行完后,块才结束;
  • b的值在赋值语句执行完后立刻就改变;
  • 可能产生意想不到的结果。

举例:

如果a=1,b=2,c=3;
在一个always模块里面

always@(posedge i_clk)

begin

   b=a;

   c=b;

end

在这里插入图片描述
上例中的 "always"块用了阻塞赋值方式。clk信号的上升沿到来时,将发生如下的变化:b马上取a的值,c马上取b的值(即等于a),生成的电路图如下所示只用了一个触发器来寄存器a的值,又输出给b和c。

得到的答案是,a=1,b=1,c=1

非阻塞赋值(Non Blocking)

格式: b<=a
特点:

  • 块结束后才完成赋值操作;
  • b的值并不是立刻就改变;
  • 这是一种比较常用的赋值方法。(特别在编写可综合模块时)

举例:
如果a=1,b=2,c=3;

always@(posedge i_clk)

 begin

   b<=a;

   c<=b;

 end

上例中的"always"块中用了非阻塞赋值方式,定义了两个reg型信号b和c,clk信号的上升沿到来时,b就等于a,c就等于b,这里应该用到了两个触发器。请注意:赋值是在"always"块结束后执行的,c应为原来b的值,b为原来的a值。这个"always"块实际描述的电路功能如下图所示:
在这里插入图片描述
第二个块,得到的答案是,a=1,b=1,c=2

注意: 对于非阻塞赋值,c获得a的值,需要2个clk完成。第1个clk上升沿a的值赋给b,此时b的值还没有更新;第2个clk上升沿,b的值赋给c,此时c才能获得b更新后的值。

timescale

格式: `timescale time_unit / time_precision

`timescale 1ns / 1ps,

含义为:时延单位为1ns,时延精度为1ps。

假如我们延时x个时间单位,那延时的总时间time = x*time_unit,但最后真正延时的时间是根据time_precision对time进行四舍五入后的结果,如下面的代码所示。
举例:

`timescale 100ns / 10ns // 时间单位100ns,时间精度10ns
module tb;
reg [4:0] set;
parameter d1 = 20,
          d2 = 1.5,
          d3 = 1.54,
          d4 = 1.55;

initial begin
    #d1   set = 0;      // real_delay = round(20*100)   = 2000ns, 以10ns为精度做四舍五入
    #d2   set = 1;      // real_delay = round(1.5*100)  = 150ns 
    #d3   set = 2;      // real_delay = round(1.54*100) = 150ns 
    #d4   set = 3;      // real_delay = round(1.55*100) = 160ns 
end

endmodule

注意事项:

  • 时间单位和时间精度只能是1、10和100这三种整数,单位有s、ms、us、ns、ps和fs;
  • 时间精度必须小于等于时间单位
  • 时间精度会影响仿真时间,时间精度设置得更大,占用更多的内存,仿真时间更久

电路延迟

电路的延迟特性分为惯性延迟和传输延迟,
在这里插入图片描述

在这里插入图片描述

内定延迟和正规延迟

延迟的添加方法有两种:

  • 内定延迟或者正规延迟
    内定延迟:C = #2 A+B;(#号在里面)
    正规延迟:#2 C = A+B;(#号在外面)

内定延迟可以理解为排队取票
正规延迟理解为排队买票

赋值的方法有三种:
  • 连续赋值、阻塞赋值和非阻塞赋值

理论的组合方式就有6种,阻塞赋值和非阻塞赋值均为过程赋值。

1. 连续赋值+正规延迟

正规延迟(B):任何小于延迟值的输入变化都会被滤除而不会体现在输出上(和后面的不计算有区别)。

内定延迟+连续赋值因为存在记忆效应,所以是非法的。

**结论:**用来描述电路的惯性延迟。

2. 阻塞赋值 不建议加延迟

内定延迟(B):always触发-计算-延迟-输出-等待再次触发。

正规延迟(C):always触发-延迟-计算-输出-等待再次触发。

缺点:忽略延迟时间段内的数据变化。

结论:既不能模拟惯性延迟、也不能模拟传输延迟。不建议在阻塞赋值中插入延迟。

3. 非阻塞赋值+内定延迟

内定延迟(B):输入的变化延迟后会全部反应在输出上。

正规延迟(C):效果与阻塞赋值相同,会忽略延迟时间段内的数据变化。

**结论:**非阻塞赋值+内定延迟的方式可以描述传输延迟,这是过程赋值中唯一推荐的延迟描述。

赋值使用建议

阻塞赋值适用于组合逻辑

对于全加器

阻塞赋值能很好的反映了组合逻辑中的数据流动顺序。在这里插入图片描述
非阻塞赋值
非阻塞赋值对于左边赋值变量的更新操作的优先级要低于阻塞赋值,也要低于非阻塞赋值本身等号右边的表达式计算,需要等到当前仿真周期结束时才被执行。
X异或Y首先计算,但是所得的结果并不会立刻赋值给temp1,所以第二句中引用的是temp1的原值,不是第一句中X与上Y的结果。

不能反映组合逻辑中的数据流,除非将所有的中间变量都列入敏感事件表中。

结论: 在对组合逻辑建模时采用阻塞赋值。

非阻塞赋值适用于时序逻辑

当对变量的赋值与读取不在同一个always进程时,使用非阻塞赋值对变量赋值.
在这里插入图片描述

如果都使用阻塞赋值,则拥有相同的优先级,由于仿真器的执行顺序是随机的,有的仿真器会按照代码的先后顺序执行,有的则会按照随机顺序执行。

这种仿真语义的不确定性会带来综合结果的不确定性,

但是设计者撰写这段代码所希望得到的硬件结构确是一定的:希望以temp作为中间变量,用CLK时钟将X异或Y的结果同步后再打一拍赋值给XxorY,硬件电路相当于两个D触发器的串联,可以看作是一个2位的移位寄存器.

在这里插入图片描述
当CLK同步变化时,虽然两个D触发器被同时启动,但是由于输入到输出的信号建立需要一定的时间,所以触发器XxorY得到的是触发器temp输出的原值,从而使XxorY在两个周期后得到X异或Y的结果。

单个仿真语句之间的时延
initial 的时延
ref
https://blog.csdn.net/reborn_lee/article/details/82222665
https://blog.csdn.net/fzr_en/article/details/89552323
https://blog.csdn.net/kevindas/article/details/86777477

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值