我是verilog的新手,我发现执行verilog很棘手。如何在verilog程序中执行。假设我有2个模块和一个测试平台 -
module module1(clock,A,B,C);
input A,B,clock;
output C;
assign c=A+B;
endmodule
module module2(clock,A,B,C);
input A,B,clock;
output C;
assign C=A-B;
endmodule
module testbench;
reg A,B,clock;
wire C;
module1 m1(clock,A,B,C);
module2 m2(clock,A,B,C);
initial
clock=1'b0;
always
#4 clock=~clock;
endmodule
我理解所有初始块在时间0开始。但是这些初始块然后顺序执行,即如果初始块具有多于一行,则它们将顺序地或同时地执行。此外,模块执行是如何进行的?将module1
首先启动,因为它出现在testbench中的module2
之前并完全完成,然后module2
启动或同时运行。如果时钟在4秒后发生变化会发生什么情况,如果时钟发生变化,模块会在中间停止运行,还是会完成之前的执行,然后再次使用新时钟启动?
答案 0 :(得分:2)
在verilog中,模块的实例化意味着向您的主板添加物理硬件。
模块只不过是可以同时工作的小型硬件块。每个模块都可以有一些程序块,连续赋值语句或两者。
每个程序块执行并发,类似适用于连续赋值语句。
我这样说:
Procedural blocks: initial, always etc. blocks.
Continuous assignment: assign, force etc.
因此,无论您在实例化模块的序列中,都将以并行的方式工作。
这里有时间戳的概念。每个时间戳包含有效,无效和NBA地区。请参考图:
对于每个时间戳,所有将在每个区域中检查实例。如果要执行任何执行,请说module1
然后它会同时完成其他模块,我们也会检查module2
。如果模块之间存在某种依赖关系,则再次执行。
在您的示例中,c
是两个模块的单线和输出,这会产生一个种族条件模块之间的强大,当然不好。
从硬件角度进行思考。两个或多个不同的硬件模块可以具有相同的输入,但不能具有相同的输出。因此,输出线必须不同。
module testbench;
reg A,B,clock;
wire C1,C2; // different wires
module1 m1(clock,A,B,C1);
module2 m2(clock,A,B,C2);
initial clock=1'b0;
always #4 clock=~clock;
endmodule
此外,这里的模块有连续分配,因此时钟有无效果。模块也没有在时钟之间运行。只是在这些时间戳中没有安排任何活动。
正如我们现在所知,所有程序块都是并行执行的。但程序块中的内容按顺序执行 。要在并发中制作内容,请使用fork..join
构造。例如:
initial
begin
a<=0;
#5;
b<=1; // b is assigned at 5ns
end
initial
fork
a<=0;
#5;
b<=1; // b is assigned at 0ns
join
有关详细信息,请参阅Verilog Procedural Blocks,Concurrent and Sequential Statements网站。
答案 1 :(得分:0)
从模拟的角度考虑这个问题的另一种方法
设计中的所有初始,始终和连续分配语句从时间0开始并发执行。它没有&#39;无论它们是否在不同的模块中 - 它们都是同等的。精化步骤展平了所有模块实例。剩下的就是这些模块内部事物的分层名称。
现在,除非你在大规模并行CPU上运行仿真(基本上是在真正的合成硬件上运行),否则无法同时实际运行所有这些进程,软件模拟器必须首先选择一个进程。你不能依赖它选择的那个。
这就是Verilog算法的功能。它将计划在时间0运行的所有内容放入事件队列(活动队列),并开始逐个执行每个进程。它执行每个进程直到完成,或者它必须阻止等待一些延迟或信号改变。进程必须阻塞,它被挂起并放到另一个队列中。然后,当前队列中的下一个进程开始执行,并且这些步骤将一直重复,直到当前队列为空。
然后,调度算法选择另一个队列成为活动队列,如果调度该队列有一些延迟,则提前计时。