verilog中的阻塞语句和非阻塞语句什么区别?

2024-12-16 01:45:52
推荐回答(3个)
回答1:

赋值的类型的选择取决于建模的逻辑类型
在时序块的 RTL 代码中使用非阻塞赋值。
非阻塞赋值在块结束后才完成赋值操作,此赋值方式可以避免在仿真出现冒险和竞争现象。
在组合的 RTL 代码中使用阻塞赋值。
使用阻塞方式对一个变量进行赋值时,此变量的值在在赋值语句执行完后就立即改变。
使用非阻塞赋值方式进行赋值时,各个赋值语句同步执行;因此,通常在一个时钟沿对临时变量进行赋值,而在另一个时钟沿对其进行采样。
下面的模块综合为触发器,
其中采用了阻塞赋值方式:
module bloc(clk,a,b);
input clk, a;
output b; reg b;
reg y;
always @(posedge clk)
begin
y=a;
b=y;
end
endmodule
下面的模块综合为两个触发器
,其中采用了非阻塞赋值方式:
module nonbloc(clk,a,b);
input clk, a;
output b; reg b;
reg y;
always @(posedge clk)
begin
y<=a;
b<=y;
end
endmodule
上面的两个例子的综合的结果不同,左边的例子使用了阻塞赋值方式,综合器将其综合为一个触发器。右边的例子使用了非阻塞赋值方式,综合器将其综合为两个触发器,y 将出现在综合列表中,作为第二个触发器的输入。

非阻塞过程赋值

module swap_vals;
reg a, b, clk;
initial begin 过程赋值有两类
a = 0; b = 1; clk = 0;
阻塞过程赋值
end
always #5 clk = ~clk; 非阻塞过程赋值
always @( posedge clk)
begin
a <= b; // 非阻塞过程赋值
b <= a; // 交换a和b值
end
endmodule

阻塞过程赋值执行完成后再执行在顺序块内下一条语句。
非阻塞赋值不阻塞过程流,仿真器读入一条赋值语句并对它进行调度之后,
就可以处理下一条赋值语句。
若过程块中的所有赋值都是非阻塞的,赋值按两步进行:
1. 仿真器计算所有RHS表达式的值,保存结果,并进行调度在时序控制指
定时间的赋值。
2. 在经过相应的延迟后,仿真器通过将保存的值赋给LHS表达式完成赋
值。
非阻塞过程赋值(续)

阻塞与非阻塞赋值语句行为差别举例1

module non_block1; 输出结果:
reg a, b, c, d, e, f;
initial begin // blocking assignments 0 a= x b= x c= x d= x e= x f = x
a = #10 1; // time 10
2 a= x b= x c= x d= x e= 0 f = x
b = #2 0; // time 12
c = #4 1; // time 16 4 a= x b= x c= x d= x e= 0 f = 1
end
initial begin // non- blocking assignments 10 a= 1 b= x c= x d= 1 e= 0 f = 1
d <= #10 1; // time 10
12 a= 1 b= 0 c= x d= 1 e= 0 f = 1
e <= #2 0; // time 2
f <= #4 1; // time 4 16 a= 1 b= 0 c= 1 d= 1 e= 0 f = 1
end
initial begin
$monitor($ time,," a= %b b= %b c= %b d= %b e= %b f= %b", a, b, c, d, e, f);
#100 $finish;
end
endmodule
非阻塞过程赋值(续)

阻塞与非阻塞赋值语句行为差别举例2

module pipeMult(product, mPlier, mCand, go, clock);
input go, clock;
input [7:0] mPlier, mCand;
output [15:0] product;
reg [15:0] product;
always @(posedge go)
product = repeat (4) @(posedge clock) mPlier * mCand;
endmodule

module pipeMult(product, mPlier, mCand, go, clock);
input go, clock;
input [7:0] mPlier, mCand;
output [15:0] product;
reg [15:0] product;
always @(posedge go)
product <= repeat (4) @(posedge clock) mPlier * mCand;
endmodule

回答2:

阻塞语句用“=”赋值,电路的输出时刻与输入相关,即输入变化时输出立刻变化,可用在assign和always
非阻塞语句用“<=”赋值,可以理解为在输入输出之间有个门,门开的时刻always @()括号中的条件,一般为电路时钟的上升沿或下降沿,输入对输出赋值。
阻塞语句一般用在组合逻辑电路中,非阻塞语句一般用在时序逻辑电路中;

回答3:

赋值的类型的选择取决于建模的逻辑类型
在时序块的 RTL 代码中使用非阻塞赋值。
非阻塞赋值在块结束后才完成赋值操作,此赋值方式可以避免在仿真出现冒险和竞争现象。
在组合的 RTL 代码中使用阻塞赋值。
使用阻塞方式对一个变量进行赋值时,此变量的值在在赋值语句执行完后就立即改变。
使用非阻塞赋值方式进行赋值时,各个赋值语句同步执行;因此,通常在一个时钟沿对临时变量进行赋值,而在另一个时钟沿对其进行采样。