什么是循环?
循环是一段不断执行的代码。 条件语句通常包含在循环中,以便条件变为真时可以终止。 如果循环永远运行,则仿真将无限期挂起。
下表列出了SystemVerilog中不同类型的循环构造。
forever | 永远运行给定的语句集 |
---|---|
repeat | 将给定的语句集重复给定的次数 |
while | 只要给定条件为真,就重复给定的一组语句 |
– | – |
for | 与while循环类似,但更简洁,更流行 |
do while | 至少重复一次给定的语句集,然后在条件为true时循环 |
– | – |
foreach | 主要用于遍历数组中的所有元素 |
forever
就像while(1)一样,这是一个无限循环。请注意,除非您在永久块内添加时间延迟以延长仿真时间,否则仿真将挂起。
注意:
【1】while(1)其中1代表一个常量表达式,它永远不会等于0。循环会一直执行下去。
【2】线程是占用cpu资源的,但是如果挂起的话,操作系统就不给这个现成分配cpu资源,除非以后再恢复,所以线程挂起的作用就是节省cpu资源
module tb;
// 此初始块有一个永久循环,它将“永久运行”,仿真不会停止
initial begin
forever begin
#5 $display ("Hello World !");
end
end
// 因为另一个初始块将永远运行,所以我们的仿真将挂起!
//为了避免这种情况,我们将在50ns后使用$ finish明确终止仿真。
initial
#50 $finish;
endmodule
Simulation Log
ncsim> run
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Simulation complete via $finish(1) at time 50 NS + 0
repeat
用于在一个块中重复语句一定次数。下面显示的示例将显示该消息5次,并继续执行其余代码。
module tb;
// 此初始块将执行重复语句,该语句将运行5次并退出
initial begin
// 在开始结尾重复5次,然后退出“repeat”块
repeat(5) begin
$display ("Hello World !");
end
end
endmodule
Simulation Log
ncsim> run
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
ncsim: *W,RNQUIE: Simulation is complete.
while
如果您知道verilog / C,您已经知道这一点。只要条件为真,它将重复该块。计数器最初为零,并递增直到达到10。
module tb;
bit clk;
always #10 clk = ~clk;
initial begin
bit [3:0] counter;
$display ("Counter = %0d", counter); // Counter = 0
while (counter < 10) begin
@(posedge clk);
counter++;
$display ("Counter = %0d", counter); // 计数器增量
end
$display ("Counter = %0d", counter); // Counter = 10
$finish;
end
endmodule
Simulation Log
ncsim> run
Counter = 0
Counter = 1
Counter = 2
Counter = 3
Counter = 4
Counter = 5
Counter = 6
Counter = 7
Counter = 8
Counter = 9
Counter = 10
Counter = 10
Simulation complete via $finish(1) at time 190 NS + 0
for
与verilog / C类似,这使您可以在同一行上提及起始值,条件和增量表达式。
module tb;
bit clk;
always #10 clk = ~clk;
initial begin
bit [3:0] counter;
$display ("Counter = %0d", counter); // Counter = 0
for (counter = 2; counter < 14; counter = counter + 2) begin
@(posedge clk);
$display ("Counter = %0d", counter); // Counter increments
end
$display ("Counter = %0d", counter); // Counter = 14
$finish;
end
endmodule
Simulation Log
ncsim> run
Counter = 0
Counter = 2
Counter = 4
Counter = 6
Counter = 8
Counter = 10
Counter = 12
Counter = 14
Simulation complete via $finish(1) at time 110 NS + 0
do well
首先执行代码,然后检查条件以查看是否应再次执行该代码。
module tb;
bit clk;
always #10 clk = ~clk;
initial begin
bit [3:0] counter;
$display ("Counter = %0d", counter); // Counter = 0
do begin
@ (posedge clk);
counter ++;
$display ("Counter = %0d", counter); // Counter increments
end while (counter < 5);
$display ("Counter = %0d", counter); // Counter = 14
$finish;
end
endmodule
Simulation Log
ncsim> run
Counter = 0
Counter = 1
Counter = 2
Counter = 3
Counter = 4
Counter = 5
Counter = 5
Simulation complete via $finish(1) at time 90 NS + 0
foreach
这是最适合遍历数组变量的方法,因为您不必查找数组大小,而是将变量设置为从0开始直到array_size-1,并在每次迭代时递增。
module tb_top;
bit [7:0] array [8]; // 创建一个固定大小的数组
initial begin
// 为数组中的每个位置分配一个值
foreach (array [index]) begin
array[index] = index;
end
// 遍历每个位置并打印当前位置的值
foreach (array [index]) begin
$display ("array[%0d] = 0x%0d", index, array[index]);
end
end
endmodule
Simulation Log
ncsim> run
array[0] = 0x0
array[1] = 0x1
array[2] = 0x2
array[3] = 0x3
array[4] = 0x4
array[5] = 0x5
array[6] = 0x6
array[7] = 0x7
ncsim: *W,RNQUIE: Simulation is complete.
参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-control-flow-loops