第6章 6-3赋值语句

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

reg x,y,z; reg [15:0] reg_a, reg_b; integer count; initial //所有行为语句必须放在initial或always 块内部 begin 在仿真0时刻执行 x= 0; y=1;z=1; //标量赋值 count=0; //整型变量赋值 reg_a=16’b0; reg_b=reg_a; //向量的初始化
注意:在对寄存器类型变量进行赋值时,如果赋值
符两侧宽度不相等,则采用以下原则: 1、如果右边表达式的位宽较宽,则将保留从最低 位开始的右侧值,把超过左侧位宽的高位丢弃; 2、如果左侧位宽大于右侧位宽,则不足的高位补0;
非阻塞赋值
module blocking(
非阻塞赋值使用“ 为变量赋值,在执行到赋值语 // 时钟输入信号 clk, <=” rst , 句时,仅仅对“ <=”右边的表达式的值进行评估,但并 //复位信号,用于给寄存器赋初值,低电平有效 不马上执行赋值,然后继续执行后面的操作。连续的 out1, 非阻塞赋值操作是同时完成的。
例:连续赋值语句举例
assign outl= i1& i2;
∥连续赋值语句,out是线网,i1和i2也是线网
assign addr[15:0]=addr1_bit[15:0]^addr2_bit[15:0];
∥向量线网的连续赋值语句。addr是16位的向量线网 ∥addr1_bits和addr2_bits是16位的向量寄存器
阻塞赋值 (Blocking Assignment)
非阻塞赋值 (Nonblocking Assignment)
Hale Waihona Puke Baidu
6.3.1 连续赋值
•连续赋值用于对线网 型的变量进行赋值;
线网型变量必须用连 续赋值的方法赋值
它只能为线网型变量赋值
•表达方式是以关键字assign开头,后面跟“=” 赋值 wire a , b;
例6-10 在不同的always块内为相同的变量赋值
module wrong_assign( clk, //时钟输入信号 sel , //选择信号,sel==1时输出din1的值,当sel=0时输出 din2的值 din1, din2, dout ); input clk; input sel; input din1; input din2; output dout; wire wire wire reg clk; sel; din1, din2; dout;
reg x,y,z; reg [15:0] reg_a, reg_b; integer count; //所有行为语句必须放在initial或always 块内部 initial begin 在仿真0时刻执行 x= 0; y=1;z=1; //标量赋值 count=0; //整型变量赋值 reg_a=16’b0; reg_b=reg_a; //向量的初始化 在仿真时刻15执行 #15 reg_a[2] =1’b1; //带延迟的位选赋值
1、连续赋值语句的左值必须是一个标量或向量线网,或者 是标量或向量线网的拼接,不能是标量或向量寄存器。 2、连续赋值语句总是处于激活状态,只要任意一个操作
数发生变化,表达式就会被立即重新计算,并且将结果赋给 等号左边的线网。
3、操作数(赋值符右端)可以是标量或向量的线网或寄存 器,也可以是函数调用。 4、赋值延迟用于控制对线网赋予新值的时间,根据仿真时 间单位进行说明。这对于描述实际电路中的时序非常有用。
过程赋值语句 的两种类型:
一、阻塞赋值语句
阻塞赋值使用“=”为变量赋值,在赋值结束以前不可以进 module blocking( din, //数据输入信号 行其他操作,在赋值结束后继续后面的操作。 dout //数据输出信号 ); input din; output dout; wire din; reg dout; reg [1:0] temp; //数据缓冲 always @ (din) begin temp[0] = din; temp[1] = temp[0]; dout = temp[1]; end endmodule
assign { c_out, sum[3:0]} = a[3:0] + b[3:0] + c_in;
∥拼接操作。赋值操作符左侧是标量线网和向量线网的拼接
隐式连续赋值:在线网声明的同时对其进行赋值
wire out;
assign out =in1 & in2;
∥普通的连续赋值语句
∥使用隐式连续赋值实现与上面两条语句同样的功能
§ 6.3 赋值语句
本节重点:
•掌握两种赋值语句:连续赋值和过程赋值语句 •掌握过程赋值的两种类型:阻塞赋值和非阻塞赋值
本节难点:
•阻塞赋值和非阻塞赋值的使用
§ 6.3 赋值语句
Verilog HDL有两种为变量赋值的方法: 连续赋值 (Continuous Assignment) 过程赋值 (Procedural Assignment)
例6-8连续的阻塞赋值
module blocking(
din, //数据输入信号 dout //数据输出信号 ); din; dout; din; dout; temp; //数据缓冲
input output wire reg reg [1:0] always @ (din) begin dout = temp[1]; temp[1] = temp[0]; temp[0] = din; end endmodule
endmodule
if(!rst)
else
begin out1 <= 1; out2 <= 0; end
begin
out1<= out2; out2<= out1; end
图6-3 例6-9的仿真波形
当rst异步复位信号 变低时,为outl和 out2赋初值1和0
当clk时钟信号的上升沿到来时执行 always块内的内容。由于使用了非阻 塞赋值,outl<=out2和out2<=outl这两 条语句是同时完成的
∥隐式连续赋值延迟 ∥连续赋值语句中的延迟
wire out ; //与左等效 assign #10 out=in1&in2
wire #10 out ; //线网延迟 assign out=in1&in2
wire out ; //与左等效
assign #10 out=in1&in2
6.3.2过程赋值语句
在仿真时刻15执行 reg_a[2] <= #15 1’b1; //带延迟的位选赋值 reg_b[15:13] <= #10 {x,y,z}; 在仿真时刻10执行 //把拼接操作的结果赋值给向量的部分位 count <= count+1; //给整型变量赋值(递增) 在仿真时刻0执行
end
多条阻塞语句与多条非阻塞语句的区别: 多条阻塞语句是顺序执行的,而多条非阻塞语句是 并行执行的 阻塞赋值和非阻塞赋值在使用上的一些注意事项: (1)在使用always块描述组合逻辑时,使用阻塞赋 值;在使用always块描述时序逻辑时,使用非阻塞 赋值 (2)不要在同一个always块内同时使用阻塞赋值和 非阻塞赋值 (3)无论是使用阻塞赋值或者非阻塞赋值,不要在 不同的always块内为同一个变量赋值 (4)在程序中不要使用0延时
assign out =i1 & i2;
∥注意,out并未声明为线网,但Verilog仿真器会推断出 ∥out是一个隐式声明的线网
连续赋值延迟:
•用于控制任一操作数发生变化后语句左值被赋予新值 之间的时间间隔。 assign #10 out =in1 & in2; wire #10 out =in1 & in2;
例6-11 不要在不同的always块内为同一个变量赋值
module correct_assign( clk, //时钟输入信号 sel , //选择信号,sel==1时输出din1的值,当sel=0时输出 din2的值 din1, din2, dout ); input clk; input sel; input din1; input din2; output dout; wire wire wire reg clk; sel; din1, din2; dout;
always @ (din) begin temp[0] = din; temp[1] = temp[0]; dout = temp[1]; end
由于阻塞赋值语句是一个接一个执行的,因此在din发生 变化以后首先执行temp[0]=din语句,执行完毕后temp[0] 的值立刻更新为din的值。之后temp[0]的值又被赋予了 temp[1],最终传递给了dout 。
∥定义两个1位的输人信号 ∥outl输出了a和b的与值 ∥out2输出了a和b的或值 //out3输出了a和b的异或值
wire
out1,out2,out3; ∥定义3个1位的输出信号
assign outl=a&b: assign out2=a|b: assign out3=a^b;
连续赋值语句的特点:
wire out =in1 & in2;
隐式线网声明:
•若一个信号被用在连续赋值语句左端,则Verilog编 译器认为该信号是一个隐式声明的线网。 •若线网被连接到模块的端口上,则Verilog编译器 认为隐式声明线网的宽度等于模块端口的宽度。 wire i1, i2;
∥连续赋值语句,out为线网类型
过程赋值语句左侧值的可选类型:
• reg、整型数、实型数、时间寄存器变量或存储
器单元。
• 上述个中类型的位选(例如,addr[0] )。 • 上述各种类型的域选(例如,addr[31:16] )。 • 上述三种类型的拼接。
阻塞赋值语句 (Blocking Assignment) 非阻塞赋值语句 (Nonblocking Assignment)
out2
input input output output wire wire reg reg ); clk; rst; out1; out2; clk; rst; out1; out2;
always @ (posedge clk or negedge rst) begin //异步复位 if(!rst) begin //为输出信号赋初值 out1 <= 1; out2 <= 0; end //时钟上升沿到来 else begin out1<= out2; //多条非阻塞赋值语句同时完成 out2<= out1; end end
• 过程赋值语句的更新对象是寄存器、整数、实数
或时间变量,位置在各种块结构中。
• 这些类型的变量在被赋值后,其值将保持不变, 直到被其他过程赋值语句赋予新值。
连续赋值语句
总是处于活动状态,任意一个 操作数的变化都会导致表达式 的重新计算以及重新赋值
过程赋值语句
只有在执行到的时候才 会起作用,且一旦赋值 将保持值不变
#10 reg_b[15:13] = {x,y,z} 在仿真时刻25执行 //把拼接操作的结果赋值给向量的部分位 count=count+1; end //给整型变量赋值(递增) 在仿真时刻25执行
结论1:由于阻塞赋值语句是按顺序执行的,因此 如果在一个begin_end块中使用阻塞式赋值语句,那 么这个块表现为串行行为。
//下面两个always块中都为dout赋值,但是似乎不会引起冲突。 always@(posedge clk)
if(sel == 1) dout <= din1; always@(posedge clk) if (sel==0)
dout<=din2;
endmodule Error (10028): Can't resolve multiple constant drivers for net "dout" at wrong_assign.v(20) Error (10029): Constant driver at wrong_assign.v(23)
always @ (din) begin dout = temp[1]; temp[1] = temp[0]; temp[0] = din; end
由于阻塞赋值语句是一个接一个执行的,因此首先执行 了dout=temp[1],将temp[1]的值赋予了dout,然后才执 行temp[1]=temp[0],此时temp[1]的值才被更新,也就是 说dout获得的是上次更新的temp[1]的值。
相关文档
最新文档