我正在使用一个verilog模块(如下所示(,该模块有两个始终块。因为一个块设置寄存器,另一个块使用寄存器,所以不会有某种竞争条件吗。这会引起什么样的问题?
谢谢,Stephen
module XYZ
(
input wire CLK,
input wire Reset,
input wire nReset,
input wire [15:0] X,
input wire [15:0] A,
input wire T,
input wire B,
output reg M
);
assign C = X > A;
reg P;
reg N;
always @(posedge CLK, negedge nReset)
begin
if (~nReset)
begin
P <= 1;
N <= 1;
end else begin
if (Reset)
begin
P <= 1;
N <= 1;
end else begin
P <= T? 1: ((C & ~M)? 0: P);
N <= B? 1: ((M & ~C)? 0: N);
end
end
end
always @(posedge CLK, negedge nReset)
begin
if (~nReset)
begin
M <= 0;
end else begin
if (Reset)
begin
M <= 0;
end else begin
M <= M? ~(N & ~C): (P & C);
end
end
end
端模块
否,不存在竞赛条件。Verilog是一个事件驱动的模拟器。Posedge(除非时钟出现故障或重置(通常在每个模拟刻度执行一次。如果正确使用非阻塞分配(看起来确实如此(,则由边缘触发的每个始终块都将使用输入变量值的旧版本,即在时钟边缘之前存在的值。
下面是一个简化的例子:
always @(posedge clk)
r <= in;
always @(posedge clk)
out <= r;
在这种情况下会发生以下情况:
r
将在稍后的模拟时间点被分配in
的值,在对始终块进行评估之后(参见nba调度区域(。由于
r
还没有真正改变,所以out
将被调度为被分配具有边缘之前的值的r
的值。
如果r
在边缘之前为0,而in
为1,则在模拟结束时,r
将变为1,out
将变为0。
这模仿了硬件中实际失败的行为。
在您的情况下,它可能看起来是一个循环依赖项。事实上,它没有。出于与上述相同的原因,M
值将是来自posedge之前的值,并且不会引起任何竞争。由于Flops的性质-逻辑性质,它们不能被包含在组合循环中。
我完全同意上述答案,我会对上述答案提出更多建议,当我开始学习Verilog时,我也有同样的疑问,参考书中的这些行澄清了我的疑问。我在这里处理声明对于进一步的疑问,你可以在这里发表评论,或者你可以查看
- 参考。第135页
- 书名:Verilog HDL:数字设计与综合指南,第二版Samir Palnitkar 示例2中使用的
非阻塞语句消除了竞争条件。在时钟的正边缘,所有右侧的值变量为"read",右侧表达式为评估并存储在临时变量中。写入期间操作,存储在临时变量中的值将被赋值到左侧变量。分离读写操作确保寄存器a和b的值交换正确,无论写入操作的顺序如何执行。不利的一面是,非阻塞分配可能会导致模拟器性能的降低和存储器使用的增加。
//Example 2: Two concurrent always blocks with nonblocking
//statements
always @(posedge clock)
a <= b;
always @(posedge clock)
b <= a;
u可以使用这种类型的编码风格,这不是强制性的,但为了便于调试和加快模拟,u可以尽可能减少开始-结束块的使用
module XYZ
(
input wire CLK,
input wire Reset,
input wire nReset,
input wire [15:0] X,
input wire [15:0] A,
input wire T,
input wire B,
output reg M
);
reg P,N;
always @(posedge CLK, negedge nReset)
if (~nReset)begin
P <= #10 1;
N <= #10 1;
end else if (Reset) begin
P <= #10 1;
N <= #10 1;
end else begin
P <= #10 T ? 1 : ((C & ~M) ? 0: P);
N <= #10 B ? 1 : ((M & ~C) ? 0: N);
end
always @(posedge CLK, negedge nReset)
if (~nReset) M <= #10 0 ;
else if ( Reset) M <= #10 0 ;
else M <= #10 M ? ~(N & ~C): (P & C);
assign C = X > A;
endmodule