📜  Verilog数组

📅  最后修改于: 2021-01-11 14:40:04             🧑  作者: Mango

Verilog阵列

Verilog数组用于将元素分组为多维对象,以便于操作。 Verilog没有用户定义的类型,我们仅限于内置Verilog类型的数组,例如nets,regs和其他Verilog变量类型。

数组是相同类型变量的集合,并使用相同名称加上一个或多个索引进行访问。

通过在方括号内包含minmax索引来声明每个数组维。数组索引可以沿任一方向写入:

array_name[least_significant_index:most_significant_index]
array_name[most_significant_index:least_significant_index]

可以通过在数组声明之后具有多个维度来声明多维数组。

数组标识符之前的任何方括号都是在数组中复制的数据类型的一部分。

Verilog数组是可综合的,因此我们可以在可综合的RTL代码中使用它们。

在C语言中,数组从0开始以整数索引,或者转换为指针。但是可以初始化整个数组,并且每个元素都必须在过程语句中读取或单独写入。

在Verilog-2001中,数组从左边界索引到右边界。如果它们是向量,则可以将它们分配为单个单位,但是如果它们是数组则不能。 Verilog-2001支持多种尺寸。

在Verilog-2001中,所有数据类型都可以声明为数组。 wire,reg和所有其他网络类型也可以具有声明的矢量宽度。在对象名称之前声明的尺寸称为矢量宽度尺寸。

Verilog-2005规范还调用了带有reg类型的元素的一维数组作为内存。对于对诸如只读存储器(ROM)和随机存取存储器(RAM)之类的存储元件进行建模是有益的。

在对象名称之后声明的维称为数组维。数组包含固定数量的大小相等的数据元素。

使用连续范围的整数通过索引访问各个元素。一些数组允许使用任何数据类型的非连续值访问各个元素。

数组可以分类为固定大小的数组,也称为静态数组,其大小一旦声明即无法更改,或者可以调整动态数组的大小。

Verilog只有一种类型的阵列。 Verilog阵列可以打包解包。压缩数组是指在类型之后和数据标识符名称之前声明的维。解压缩数组是指在数据标识符名称之后声明的尺寸。

包装或固定阵列

在Verilog中,术语打包数组是指在对象名称之前声明的尺寸。

一维压缩数组也称为向量。压缩数组将向量划分为子字段,可以将其作为数组元素进行访问。在模拟和综合过程中,保证将打包数组表示为一组连续的位。

打包数组只能由bit,逻辑,reg ,枚举类型等单位数据类型以及其他打包数组和打包结构组成。这也意味着我们不能打包具有预定义宽度的整数类型的数组。

可以限制压缩数组的最大大小,但至少应为65536(216)位。

保证将打包数组表示为一组连续的位。

未包装的阵列

在Verilog中,术语“解压缩数组”用于指代在对象名称之后声明的尺寸。

解压缩的数组可以由任何数据类型组成。每个固定尺寸的尺寸都由地址范围表示,例如[0:1023]。

或使用单个正数来指定固定大小的未压缩数组的大小,例如[1024]。标记大小等于[0:size-1]。

未打包的数组可以或可以不表示为一组连续的位。

多维数组

可以使用打包和未打包维声明多维数组。创建多维压缩数组类似于将连续向量切成多个维。

当数组具有可以按逻辑分组的多个维度时,使用typedef分阶段定义多维数组以增强可读性很有用。

Verilog数组索引和切片

Verilog阵列一次只能访问一个元素。在Verilog数组中,我们还可以选择一个或多个数组的连续元素。这称为切片

数组切片只能应用于一个维度。其他维在表达式中必须具有单个索引值。

Verilog阵列操作

Verilog阵列比传统的Verilog阵列支持更多的操作。

  • +:和-:表示法

访问Verilog数组切片的范围时,我们可以使用[start +:递增宽度]和[start-:递减宽度]表示法来指定变量切片。

它们比选择可变切片时需要计算确切的开始索引和结束索引更简单。增量或减量宽度必须为常数。

bit signed [31:0] car A [7:0];                          // unpacked array of 8 32-bit vectors
int car B [1:0];                                                // unpacked array of 2 integers
car B = car A [7:6];                                        // select a 2-vector slice from car A
car B = car A [6+:2];                                     // equivalent to car A[7:6]
  • 分配和复制操作

Verilog阵列支持更多操作。可以在压缩和未压缩的阵列上执行以下操作。

A = B;                              // reading and writing the array
A[i:j]  = B[i:j];                 // reading and writing a slice of the array
A[x+:c] = B[y+:d];          // reading and writing a variable slice of the array
A[i] = B[i];                      // accessing an element of the array
A == B;                           // equality operations on the array
A[i:j]  != B[i:j];               // equality operations on slice of the array
  • 压缩数组分配

可以一次分配Verilog压缩数组,例如多位向量,单个元素或切片等。

logic [1:0][1:0][7:0] packed_3d_array;
 
always_ff @(posedge clk, negedge rst_n)
  if (!rst_n) begin
    packed_3d_array <= '0;                             // assign 0 to all elements of array
  end
  
  else begin
    packed_3d_array[0][0][0]   <= 1'b0;                    // assign one bit
    packed_3d_array[0][0]      <= A0a;                    // assign one element
    packed_3d_array[0][0][3:0] <= 4'ha;                   // assign part select
    packed_3d_array[0]         <= 16'habcd;                // assign slice
    packed_3d_array            <= 32'h01234567;         // assign entire array as vector
  end
  • 解压缩数组分配

可以将Verilog解压缩数组的所有或多个元素分配给值列表。

该列表可以包含单个数组元素的值,也可以包含整个数组的默认值。

logic [7:0] a, b, c;
logic [7:0] d_array[0:3];
logic [7:0] e_array[3:0];                // note index of unpacked dimension is reversed
                          
logic [7:0] mult_array_a[3:0][3:0];
logic [7:0] mult_array_b[3:0][3:0];
 
always_ff @(posedge clk, negedge rst_n)
  if (!rst_n) begin
    d_array <= '{default:0};                                  // assign 0 to all elements of array
  end
  
  else begin
    d_array        <= '{A00, c, b, a};                    // d_array[0]=A00, d_array[1]=c,    
                                                                             d_array[2]=b, d_array[3]=a

    e_array        <= '{A00, c, b, a};                    // e_array[3]=A00, e_array[2]=c,   
                                                                             e_array[1]=b, d_array[0]=a

    mult_array_a   <= '{'{A00, A01, A02, A03}, '{A04, A05, A06, A07},
                                    '{A08, A09, A0a, A0b},
                                    '{A0c, A0d, A0e, A0f}};               // assign to full array
    mult_array_b[3] <= '{A00, A01, A02, A03};        // assign to slice of array
  end