我正在尝试在Python中实现一个基于简单事件的Verilog模拟器,但实际上我很难在规范中找到一些细节(IEEE 1364-2005的第11节)。
让我们说我刚刚在clk
上执行了更新事件,现在获得了新值1(之前为0)。根据规范,这要求我安排评估活动'敏感过程。
我是否必须将always @(posedge clk)
块的评估安排为活动或非活动事件?我猜测后者是正确的吗?
或实际上,说得更一般。基本上所有事件都被安排为非活动事件,但以下情况除外:
非常感谢!
答案 0 :(得分:3)
默认情况下,所有内容都在 Active 区域中运行。例外是:
我们可以通过在任何现有的模拟器中运行以下内容来证明@
在活动区域中发生:
int x;
initial begin
$monitor("From $monitor: x is %0d",x);
#0 x = 5; // inactive event
x = 3; // active event (after inactive event)
#1; // go to next time stamp
fork
#0 x = 7; // inactive event
x = 11; // active event
join
#0 fork // inactive region
#0 x = 2; // inactive event
x = 5; // active event
x <= 4; // NBA event
join
end
// active event region
always @* $display("From @* $display: x is %0d",x);
输出:
From @* $display: x is 3 From $monitor: x is 3 From @* $display: x is 11 From @* $display: x is 7 From @* $display: x is 5 From @* $display: x is 2 From @* $display: x is 4 From $monitor: x is 4
显示报告的次数,然后进行监控。这排除了监视器或未来区域中的@
累积。显示是报告每个事件区域。每个事件区域只能循环回活动区域。因此,必须在活动区域中处理@
,并且更新变量x
的每个区域都会触发新的活动区域事件。
这也可以通过了解Verilog的历史来证明。不幸的是,这没有很好的记录。我倾向于通过在80年代末90年代后期使用/开发verilog的人了解它。最重要的解释是:在IEEE Std 1364-1995之前,Inactive和NBA地区被添加到Verilog,@
早于这两个地区。添加区域以向非确定性模拟器添加确定性。
always @(posedge clk) pipe0 = in;
always @(posedge clk) pipe1 = pipe0; // unpredictable, non-deterministic order
always @(posedge clk) #0 pipe0 = in; // Inactive region added some determinism
always @(posedge clk) pipe1 = pipe0;
always @(posedge clk) #0 pipe0 = in; // But was fragile
always @(posedge clk) #0 pipe1 = pipe0; // unpredictable order again
always @(posedge clk) pipe2 = pipe1;
always @(posedge clk) pipe0 <= in;
always @(posedge clk) pipe1 <= pipe0;
always @(posedge clk) pipe2 <= pipe1; // NBA region fixed it
...
always @(posedge clk) pipeN <= pipeM; // and made it scalable
if (E is an update event)
的真实条件,修改对象并安排新的评估事件(下次输入活动区域时处理)。完成所有激活的事件后,计划将返回到while循环的顶部。 NBA 区域仅指定值,评估实际上是在较早的 Active 区域阶段完成的。
module TEST;
reg test = 0;
reg test2 = 0;
reg clk = 0;
initial begin
clk <= 1;
test <= 1;
end
always @(posedge clk) begin
test2 <= test;
end
endmodule
while循环的每次迭代都看起来像这样:
Iteration:0 Active: <----- This is region is executing clk$tmp = eval(1) test$tmp = eval(1) Inactive: NBA: clk = clk$tmp test = test$tmp Iteration:1 Active: Inactive: NBA: <----- This is region is executing clk = clk$tmp test = test$tmp Active.schedule( eval( "@(posedge clk)" ) Iteration:2 Active: <----- This is region is executing eval( "@(posedge clk)" ) Active.schedule( "test2$tmp = eval(test)" ) NBA.schedule( "test2 = test2$tmp" ) Inactive: NBA: Iteration:3 Active: <----- This is region is executing test2$tmp = eval(test) Inactive: NBA: test2 = test2$tmp Iteration:4 Active: Inactive: NBA: <----- This is region is executing test2 = test2$tmp Iteration:5 --> next simulation cycle