<>一.数组的声明
wire [31 : 0] a_array [11 : 0]; // 12个32位wire型变量构成的数组 reg [31 : 0] b_array [11
: 0]; // 12个32位reg型变量构成的数组 wire [31 : 0] c_array [12 : 1]; // 12个32位wire型变量构成的数组
wire[31 : 0] d_array [18 : 7]; // 12个32位wire型变量构成的数组 wire [31 : 0] e_array [0 :
11]; // 12个32位wire型变量构成的数组 wire [31 : 0] e_array [3 : 14]; // 12个32位wire型变量构成的数组
声明语法:变量类型 数组名 [a : b]

其中,a,b的位置可以调换,(a-b)的绝对值 + 1等于数组元素的个数。

在C语言中,数组只需要指定类型和元素个数,语法如下:

变量类型 数组名 [元素个数]
int a_array [12]
但在Verilog中,并不能直接指定元素个数(SV中引入了这个功能,但Verilog中不行),而是采用区间表示,像 [0 : 11],[11 :
0],[18 : 7]都可以表示区间,它们都表示数组内的元素个数为12。

<>二. 数组的初始化
reg [31 : 0] addr_array [6 : 2]; always @(posedge clk) begin addr_array[2] <=
'h8; // 12 注意这里是从2开始,与数组的定义对应,不存在addr_array[0]和addr_array[1] addr_array[3] <=
'h14; // 20 addr_array[4] <= 'h18; // 24 addr_array[5] <= 'h20; // 32 addr_array
[6] <= 'h24; // 36 end
使用时序逻辑对数组进行初始化,这相当于定义了一个ROM。

这里其实就很可能掉入陷阱,一般我们可能认为,数组的区间仅用于表示元素个数,数组元素的索引一直都是从0开始,到元素个数-1结束。这对于以下两个数组来说是对的,
reg [31 : 0] a_array [4 : 0]; // 或者 reg [31 : 0] b_array [0 : 4];
但对于上面的reg [31 : 0] addr_array [6 : 2]不对。[6 : 2]这种写法不仅表示了数组的元素个数,还额外规定了数组的索引。

Verilog的这个语法是为了具体规定每个元素在寄存器中存储的位置,是有它的作用在的,但我们很可能参考C语言的规则去理解这个数组的语法,而错误的去访问
addr_array[0]和addr_array[1],其实这两个元素是未定义的,根本不存在与数组中。

更难受的是,赋值和使用addr_array[0]和addr_array[1]这两个原本不存在的元素,综合和实现都不报错!
这简直是灾难,可能导致很多令人费解的程序错误。

<>三. 推荐写法

为避免掉入陷阱和使用的方便,推荐仅使用以下的写法来声明数组。
reg [31 : 0] addr_array [0 : 4]; always @(posedge clk) begin addr_array[0] <=
'h8; addr_array[1] <= 'h14; addr_array[2] <= 'h18; addr_array[3] <= 'h20;
addr_array[4] <= 'h24; end
reg/wire [m-1 : 0] 数组名 [0 : n-1]

这样声明了一个:由n个位宽为m的reg/wire型变量组成的数组。这种写法也方便检查访问数组元素是否正确,0~4正好对应每个元素的索引值。

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信