Verilog中的多维数组和存储器

转自:https://reborn.blog.csdn.net/article/details/106974813

博文目录


写在前面

上篇博客讲了单比特的变量称为标量,多比特的变量称为向量。其实向量就类似于C或者其他语言中的一维数组,如果是reg类型的变量,对应的硬件逻辑是寄存器。
本篇博文进一步延伸,Verilog中也存在多维数组,它对应的硬件逻辑可以是存储器,诸如RAM,ROM,以及FIFO等。
存储器

  • 个人微信公众号: FPGA LAB

正文

多维数组

还是简单一些说吧,多维数组在Verilog中对应的硬件元素可以是存储器,向量,也即一维数组,可以认为是深度为0的二维数组。
由于能对应于硬件的数组,例如RAM,通常有这么几个参数,深度,宽度,因此我们一般做到二维数组,当然更多维的不是不可以,不违背语法,但用途极为有限。

例如:

 
  reg        y1 [11:0];        // y is an scalar reg array of depth=12, each 1-bit wide
  wire [0:7] y2 [3:0]          // y is an 8-bit vector net with a depth of 4
  reg  [7:0] y3 [0:1][0:3];    // y is a 2D array rows=2,cols=4 each 8-bit wide

y1是一个reg类型的数组,其深度为12,宽度为1;
y2是一个wire类型的数组,其深度为4,宽度为8;
y3是一个多维(三维)数组,其意义不在多说。

上面的第二位定义,我们需要强调一下,还是统一规则为好,也就是宽度最好是高位在左,低位在右。
例如:

reg    [0:0]    y1 [11:0];        // y is an scalar reg array of depth=12, each 1-bit wide
  wire [7:0] y2 [3:0]          // y is an 8-bit vector net with a depth of 4

多维数组赋值

对于多维数组赋值,也就是对存储器赋值,我们不能像如下方式:

reg [7:0] a [15:0] = 0;

这种方式是错误的,我们需要选中对应的元素进行赋值,例如:

reg [7:0] a [15:0];

initial begin

a[0] = 16’h0000;
a[1] = 16’h0101;
//…or
a[0][0] = 1’b0;
a[0][1] = 1’b1;
//…or

for(integer i = 0; i <16; i = i + 1) begin
a[i] <= 0;
end

end

上面的例子是在仿真文件中,当然在FPGA内,如此赋初值也是可以的,但更常用的还是通过系统函数readmemh

$readmemh("file_name", mem_array, start_addr, stop_addr);

举一个仿真的例子:

 
module des ();
  reg [7:0]  mem1;               // reg vector 8-bit wide
  reg [7:0]  mem2 [0:3];         // 8-bit wide vector array with depth=4
  reg [15:0] mem3 [0:3][0:1];   // 16-bit wide vector 2D array with rows=4,cols=2

initial begin
int i;

mem1 <span class="token operator">&#61;</span> <span class="token number">8</span>&#39;ha9<span class="token punctuation">;</span>
$display <span class="token punctuation">(</span><span class="token string">&#34;mem1 &#61; 0x%0h&#34;</span><span class="token punctuation">,</span> mem1<span class="token punctuation">)</span><span class="token punctuation">;</span>

mem2<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">&#61;</span> <span class="token number">8</span>&#39;haa<span class="token punctuation">;</span>
mem2<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">&#61;</span> <span class="token number">8</span>&#39;hbb<span class="token punctuation">;</span>
mem2<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">&#61;</span> <span class="token number">8</span>&#39;hcc<span class="token punctuation">;</span>
mem2<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">&#61;</span> <span class="token number">8</span>&#39;hdd<span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">&#61;</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">4</span><span class="token punctuation">;</span> i <span class="token operator">&#61;</span> i<span class="token operator">&#43;</span><span class="token number">1</span><span class="token punctuation">)</span> begin
  $<span class="token function">display</span><span class="token punctuation">(</span><span class="token string">&#34;mem2[%0d] &#61; 0x%0h&#34;</span><span class="token punctuation">,</span> i<span class="token punctuation">,</span> mem2<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
end

<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">&#61;</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">4</span><span class="token punctuation">;</span> i <span class="token operator">&#43;</span><span class="token operator">&#61;</span> <span class="token number">1</span><span class="token punctuation">)</span> begin
  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">&#61;</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> <span class="token number">2</span><span class="token punctuation">;</span> j <span class="token operator">&#43;</span><span class="token operator">&#61;</span> <span class="token number">1</span><span class="token punctuation">)</span> begin
    mem3<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&#61;</span> i <span class="token operator">&#43;</span> j<span class="token punctuation">;</span>
    $<span class="token function">display</span><span class="token punctuation">(</span><span class="token string">&#34;mem3[%0d][%0d] &#61; 0x%0h&#34;</span><span class="token punctuation">,</span> i<span class="token punctuation">,</span> j<span class="token punctuation">,</span> mem3<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  end
end

end
endmodule

仿真结果:

ncsim> run
mem1 = 0xa9
mem2[0] = 0xaa
mem2[1] = 0xbb
mem2[2] = 0xcc
mem2[3] = 0xdd
mem3[0][0] = 0x0
mem3[0][1] = 0x1
mem3[1][0] = 0x1
mem3[1][1] = 0x2
mem3[2][0] = 0x2
mem3[2][1] = 0x3
mem3[3][0] = 0x3
mem3[3][1] = 0x4
ncsim: *W,RNQUIE: Simulation is complete.

内存

前言和前面的标题中都已经涉及到了内存,例如RAM等,它们可以使用二维数组进行建模。
例如:
存储器
mem就是一个深度为256,宽度为8bit的内存空间,而它在Verilog中就是通过一个二维数组建模的。

寄存器变量应用实例

寄存器变量,相当于一个一维数组,下面定义一个寄存器变量,并对其进行操作:复位有效时,对寄存器变量赋初值,当sel以及wr有效时,将输入赋值给寄存器,否则,寄存器的值保持。
例如:

module des (    input           clk,
                input           rstn,
                input           wr,
                input           sel,
                input [15:0]    wdata,
                output [15:0]   rdata);

reg [15:0] register;

always @ (posedge clk) begin
if (!rstn)
register <= 0;
else begin
if (sel & wr)
register <= wdata;
else
register <= register;
end
end

assign rdata = (sel & ~wr) ? register : 0;
endmodule

硬件原理图显示,当写的控制逻辑处于有效状态时,会更新一个16位的触发器,当读的控制逻辑使能时,会返回当前值。

寄存器变量

寄存器阵列应用实例

同理,举一个二位数组的例子:

 
module des (    input           clk,
                input           rstn,
                input  [1:0]    addr,
                input           wr,
                input           sel,
                input [15:0]    wdata,
                output [15:0]   rdata);

reg [15:0] register [0:3];
integer i;

always @ (posedge clk) begin
if (!rstn) begin
for (i = 0; i < 4; i = i+1) begin
register[i] <= 0;
end
end else begin
if (sel & wr)
register[addr] <= wdata;
else
register[addr] <= register[addr];
end
end

assign rdata = (sel & ~wr) ? register[addr] : 0;
endmodule

在硬件原理图中可以看到,数组的每个索引都是一个16位的触发器,输入地址用于访问特定的触发器。
触发器阵列


参考资料


  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值