Verilog的循环语句

时间:2021-01-01 00:58:00

这篇文章将讨论可以在 verilog 中使用的不同类型的循环语句----for循环、while循环、foever循环和repeat循环。

正如之前文章中描述的那样,有许多语句只能在过程块中使用,这些语句被用来控制在 verilog 设计中给数据赋值。类似的,在 verilog 中使用的四种不同类型的循环语句也是用来在设计中赋值的顺序语句。因此只能在过程块内编写循环,例always块或initial块。

Verilog 中的循环

设计者可以在 verilog 中使用循环语句来多次执行相同的代码。最常用的循环语句是for循环----使用此循环将一段代码执行固定次数

设计者还可以在 verilog 中使用repeat循环----它与 for 循环功能类似

在 verilog 中常用的另一种循环是while循环,只要给定条件为真,此循环就会执行特定代码。

Verilog Forever循环

verilog 中的forever循环会创建一个连续执行的代码块,就像其他编程语言中的无限循环一样。这与 verilog 中的其他类型的循环形成对比,例如 for 循环和 while 循环,它们就只会运行固定的次数

forever循环最常见的用法是在testbench生成时钟信号forever循环无法被综合,这意味着只能在testbench中使用它。

下面的代码片段展示了 forever语句的一般语法。

forever begin
    // 这里写要被循环执行的语句
end

示例

为了更好地演示如何在实践中使用forever循环,请看这个示例----生成一个频率为 10MHz 的时钟信号,以在testbench中使用它。

首先为信号赋初始值,使用 forever 语句定期翻转信号。下面的代码片段展示如何在实现这个时钟。

initial begin
   clk = 1'b0;
   forever begin
     #500 clk = ~clk;
   end
end

首先,请注意示例中使用了verilog中的initial块,这是过程语句的一个示例。在initial块中编写的任何代码都会在仿真开始时执行一次。在testbench代码中使用的几乎都是initial块而不是always块。这样做的原因是它们只执行一次,而仿真通常只需要运行一次。

要注意的另一件重要事情是使用 # 符号来实现时间延迟。为了让这个例子正常工作,需要在代码中包含timescale编译指令----来指定仿真的时间单位和精度

在此示例中时间单位被设置为 ns而精度被设置为 ps,如下面的代码片段所示。

`timescale 1ns / 1ps

Verilog Repeat循环

repeat循环将会给特定的 verilog 代码块执行指定的次数

虽然repeat循环在testbench中最为常见,但设计者也可以在可综合的代码中使用它。但是,在使用这种语句来构造可综合代码时必须小心,因为其只能被用来描述重复结构。

下面的代码片段展示了repeat循环的一般语法。

repeat (<number>) begin    //指定重复次数
    //需要重复执行的代码
end

<number> 用来确定重复循环的次数。repeat 循环与 for 循环非常相似,因为它们都将代码重复固定次数

这两种循环的主要区别在于 for 循环包含一个局部变量,设计者可以在循环内部引用该变量,该变量的值在循环的每次迭代中更新。

相反,repeat 循环则不包括这个局部变量。所以在不需要这个变量的情况下,repeat 循环实际上比 for 循环更简洁。

示例

接下来将用一个简单示例来演示其具体用法----假设设计中有一个信号,而设计中的另一个信号则在该信号出现上升沿时翻转,这个翻转总共只实现6次

下面的波形展示了在此示例中要实现的功能。

Verilog的循环语句

对应的代码如下所示。

repeat (6) begin      //重复6次
  @(posedge sig_a)    //上升沿
      sig_b = ~sig_b; //翻转
end

在这个例子中可以看到, <number> 参数被设置为 6。因此,repeat循环将在终止之前总共运行六次。

在 verilog 中,@ 符号被用实现wait event,这意味着代码将在此行暂停并等待括号中的条件评估为----一旦发生代码将继续运行。在此示例中,此运算符被用来阻止repeat循环的执行,直到在 sig_a 信号上检测到上升沿。

最后,只要检测到上升沿,就可以使用 not这个位运算符(~)来翻转信号。

下面的波形展示这段代码的仿真结果。

Verilog的循环语句

Verilog While 循环

在while循环的每次迭代之前都会判断指定的条件,只要给定条件为,while 循环就会执行条件内的verilog 代码;反之则不会执行

while 循环类似一个重复执行的if语句。由于 while 循环通常不可被综合,所以经常在testbench使用它来生成测试激励。

下面的代码片段展示了 verilog 中 while 循环的一般语法。

while <condition> begin    //判断条件
  // Code to execute       //要重复执行的语句
end

<condition> 用来来确定循环何时执行和何时停止

示例

为了更好地演示如何在 verilog 中使用 while 循环,接下来将用一个简单示例来演示其具体用法----创建一个从 0 到 3 的integer型变量,然后在循环的每次迭代中打印这个变量的值。

下面的代码片段展示了如何实现这个例子。

while (iter < 4) begin
  $display("iter = %0d", iter);
  iter = iter + 1;
end

这个例子假设 iter 变量已经被声明并赋了一个初始值 0。在循环的每次迭代中,循环体内代码的第二行都使 iter 变量+1。此示例中的 <condition> 参数被设置为仅当 iter 变量小于 4 时才执行循环。因此,此循环中 iter 变量将从 0 递增到 3。

$display 被用来在循环的每次迭代中打印 iter 变量的值,%0d 运算符指示变量应打印为十进制数。

Verilog For循环

for 循环会将一段代码执行固定次数,与 while 循环一样,只要给定条件为,for 循环就会执行。将此条件将被指定为 for 循环声明的一部分,用于控制循环执行的次数。

虽然它通常用于testbench,但也可以在可综合的 verilog 代码中使用 for 循环。在可综合的代码中使用 for 循环时,通常使用它来复制硬件,最常见的例子之一是移位寄存器。

正如之前提到的,for 循环与 repeat 循环非常相似。主要区别在于 for 循环使用了一个局部变量,它可以在循环代码中使用。

下面的代码片段展示了在 verilog中for 循环的一般语法。

for (<initial_condition>; <stop_condition>; <increment>) begin    //执行条件判断
  //要循环执行的代码
end

<initial_condition> 用来设置循环变量的初始值。在使用它之前,必须先声明将在循环中使用的局部变量。

<stop_condition> 用来确定循环运行次数的条件语句。for 循环将继续执行,直到该字段被判断为 false。

<increment> 用来确定在循环的每次迭代中如何更新循环变量。

示例

为了更好地演示如何在 verilog 中使用 for 循环,接下来将用一个简单示例来演示其具体用法----一个简单的4位串行移位寄存器。

实现移位寄存器实际上是 for 循环最常见的用例之一----可以使用一个简单的verilog数组来实现。首先将移位寄存器的输入赋值给数组的第一个元素,然后使用 for 循环将数组整体向左移动一位

下面的 verilog 代码片段展示了如何使用 for 循环实现此移位寄存器。

//将输入赋值给数组的第一个数
shift[0] <= circuit_in;

//使用for循环语句来将数组整体向左移动
for (i = 1; i < 4; i = i + 1) begin
  shift[i] <= shift[i-1];
end

在此代码中首先要注意的是,循环变量 (i) 被用来引用循环中的数组元素。在中使用它之前,必须先声明这个循环变量。由于移位数组有四位,因此设置了 <stop_condition>小于4,以便仅当循环变量 (i) 小于4时才执行循环。最后,设置了 <increment> 字段以使循环变量在每次迭代中都增加 1----这允许代码遍历数组中的每个元素。

在这个例子中使用了非阻塞赋值,这是因为移位寄存器是时序逻辑电路的一个典型例子。因此必须在时钟控制的verilog always块中编写此代码才能正确实现移位寄存器。


  • ????您有任何问题,都可以在评论区和我交流????

  • ????您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞????、评论????和收藏