10-阻塞赋值和非阻塞赋值-播报
时间:2023-05-25 02:03:55
来源:博客园
【资料图】
1.阻塞赋值和非阻塞赋值
阻塞赋值的赋值号用"="表示,对应的电路结构往往与触发边沿没有关系,只与输入电平的变化有关系,它的操作可以认为是只有一个步骤的操作,即计算赋值号右边的语句并更新赋值号左边的语句,此时不允许有来自任何其他verilog语句的干扰,直到现行的赋值完成,才允许下一条的赋值语句执行串行块(begin end)中,各条赋值语将以它们在顺序块中的排列次序依次执行
a = 1;b = 2;c = 3;begin a = b + 1; // a = 3 b = a + 2; // b = 5 c = a - 1; // c = 4end
非阻塞赋值的赋值号用"<="表示,对应的电路结构往往与触发沿有关系,只有在触发沿的时刻才能进行非阻塞赋值;非阻塞赋值操作可以看作是两个步骤的过程:在赋值开始时刻,计算赋值号右边的语句(所有赋值号右边的结果),在赋值结束时刻(end),更新赋值号左边的语句在计算非阻塞赋值号右边的语句和更新赋值号左边语句期间,允许其他的verilog语句同时进行操作非阻塞赋值只能用于寄存器类型变量进行赋值,因此只能用于initial语句和always语句,不允许用于连续赋值语句assign
a = 1;b = 2;c = 3;begin // 开始 结束 a <= b + 1; // 三条语句并行执行 3 3 b <= a + 2; // 3 3 c <= a - 1; // 0 0end
2.实践
2.1 阻塞赋值
module blocking( input wire sys_clk, input wire sys_rst_n, input wire [1:0] in, output reg [1:0] out); // 定义中间变量 reg [1:0] in_reg; always@(posedge sys_clk or negedge sys_rst_n) begin if(sys_rst_n == 1"b0) begin in_reg = 2"b0; out = 1"b0; end else begin in_reg = in; out = in_reg; end endendmodule
- 创建quartus工程,进行编译
`timescale 1ns/1nsmodule tb_blocking(); reg sys_clk; reg sys_rst_n; reg [1:0] in; wire [1:0] out; // 初始化时钟和复位信号,输入信号 intial begin sys_clk = 1"b1; sys_rst_n <= 1"b0; in <=2"b0; #20; sys_rst_in = 1"b1; end // 模拟时钟 initial begin #10; sys_clk = ~sys_clk; end always #10 in <= {$random} % 4; // 生成非负数0,1,2,3 blocking block_inst( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .in (in), .out (out) ); endmodule
2.2 非阻塞赋值
module nonblocking( input wire sys_clk, input wire sys_rst_n, input wire [1:0] in, output reg [1:0] out); // 定义中间变量 reg [1:0] in_reg; always@(posedge sys_clk or negedge sys_rst_n) begin if(sys_rst_n == 1"b0) begin in_reg <= 2"b0; out <= 1"b0; end else begin in_reg <= in; out <= in_reg; end endendmodule
- 当想要对想要的信号打两拍的时候,使用非阻塞赋值
- 时序逻辑电路使用非阻塞赋值,组合逻辑电路使用阻塞赋值
- always语句块实现组合逻辑,使用阻塞赋值,不能即使用阻塞赋值又使用非阻塞赋值
- 避免锁存器latch,使用锁存器的时候使用非阻塞赋值的方式
- 一个always语句块只对一个变量进行赋值
标签: