本文原创,转载请联系原作者并注明出处
grin2-Verilog赋值问题
Verilog中的赋值包括连续赋值和过程赋值两种方式。
一、连续赋值
- 连续赋值是数据流级建模,使用assign进行赋值,并且使用assign a = b;的描述方式。
- 连续赋值是要求assign左值必须是标量或者线网类型wire,不能是reg,对右操作数无要求。
- assign语句的执行时并行执行,assign语句出现的先后并不会影响赋值顺序。
- assign是持续驱动,总是处于激活状态,有变化立刻进行更新。
- assign 可以进行赋值延迟,控制对线网赋予新值的时间。
二、过程赋值
过程赋值是行为级建模,需要等到语句执行到时才赋值。过程赋值可以对矢量、reg等类型进行赋值。在过程块中进行过程赋值,但是不能在同一个always语块中混用阻塞和非阻塞。过程赋值包括阻塞赋值和非阻塞赋值,一般在时序电路中使用非阻塞赋值(<=),组合逻辑中使用阻塞赋值(=)
阻塞赋值:=
串行块中阻塞赋值语句按顺序执行,执行时,前一句执行完了才会开始后一句的执行。对应寄存器的值,与前面语句的操作输出有关。阻塞赋值会阻塞当前串行块中下一个语句的执行,但是不会阻塞后面的并行块中的语句执行。
非阻塞赋值:<=
非阻塞赋值不会阻塞同一顺序快中后面语句的执行(包括串行块和并行块 )。非阻塞赋值允许赋值调度,执行时,所有表达式的初始值先计算出来,并临时保存,等调度到相应的时刻完成赋值。
也就是说,阻塞赋值按顺序执行,且延时是相对于上一条语句延迟,而非阻塞的延迟是绝对延迟,相对于整体系统的仿真0时刻而言。使用非阻塞赋值可以避免竞争或者赋值混乱。
举个栗子
//******************
// always中的阻塞赋值
always@(*)
begin
#10 reg1 = D1;
#20 reg2 = D2;
#5 reg3 = D3;
#5 reg1 = D4;
//表示 t=10,reg1=D1;t=30,reg2 =D2 ;t=35,reg3=D3;t=40, reg1=D4
end
//*****************
//-----------------
//always中的非阻塞赋值
always@(*)
begin
#10 rega <= D1;
#20 regb <= D2;
#5 regc <= D3;
#5 rega <= D4;
//表示 t=5,rega=D4, regc=D3;t=10,rega =D1 ;t=20,regb=D2;
end
//-----------------