前言

Verilog中的二维数组很有用,可以使用for以及generate for配合二维数组进行使用,可以代替大量寄存器的场合,其实大量同类寄存器可以使用存储器进行代替,Verilog中可以使用二维数组对存储器进行建模。

存储器由FPGA的什么资源来构成,可以由综合属性来设定,或者由综合工具来自动设置。这不是本文的重点,具体可见:Vivado 随笔(1) 综合属性之 ram_style & rom_style?

下面一起来看Verilog中的数组以及如何使用数组对存储器进行建模。

存储器

存储器是数字存储元件,可帮助在数字电路中存储数据和信息。FPGA中的RAM以及ROM等存储器的模型大概都是如下这样,我们可以设计不同的位宽和深度:

在FPGA中,我们可以使用EDA工具提供的IP核对存储元件进行定制,当然也可以使用Verilog中的数组进行建模,下面介绍:

Verilog中的数组

我们还可以在verilog中创建和使用数组类型。这些在内存建模中特别有用。

为了在verilog中声明一个数组,我们只需要在变量名后添加一个额外的字段即可声明数组中有多少个元素。

下面的代码段显示了用于在Verilog中声明数组类型的常规语法。我们使用字段声明数组的大小。

// General syntax to declare an array type<type> <size> <variable_name> <elements>;

例如,假设我们要创建一个4位wire类型的数组。我们希望数组中总共有16个元素。下面的Verilog代码显示了如何创建此数组。

wire [3:0] example [15:0];

我们可以使用方括号访问数组类型中的各个元素。例如,下面的verilog代码显示了如何将Fh的值分配给示例数组中的第一个元素。

assign example[0] = 4'hF;

数组允许以Verilog为reg,wire,integer和real数据类型。

reg        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

必须指定每个维的索引才能访问数组的特定元素,并且可以是其他变量的表达式。可以为Verilog支持的任何不同数据类型形成一个数组。

y1 = 0;                         // Illegal - All elements can't be assigned in a single goy2[0] = 8'ha2;             // Assign 0xa2 to index=0
y2[2] = 8'h1c;            // Assign 0x1c to index=2

多维数组

在verilog 1995标准中,我们只能创建一维数组,例如上一节中使用的数组。

但是,当我们使用verilog 2001标准时,我们还可以创建具有多个维度的数组。

为此,我们只需添加另一个字段即可定义所需元素的数量。

下面的代码段显示了用于在verilog中创建2D数组的常规语法。

// General syntax to declare an array type<type> <size> <variable_name> <elements> <elements>;

举个例子,让我们考虑一下我们想从前面的例子中修改数组大小的情况。

现在,我们要创建一个变量,该变量可以存储2个元素,两个元素都有16个4位wire元素。

为此,我们只需在声明的末尾添加一个额外的字段即可。下面的代码段显示了我们将如何执行此操作。

wire [3:0] example [15:0][1:0];reg  [7:0] y3 [0:1][0:3];    // y is a 2D array rows=2,cols=4 each 8-bit wide

我们也使用与一维数组相同的方法来对多维数组赋值。但是,我们现在使用一对方括号在数组的两个维度上定义元素。

例如,假设我们要为两个维度中的最后一个元素分配Ah的值。下面的verilog代码显示了如何将数据分配给数组中的该元素。

和上面数组一样的原则:

必须指定每个维的索引才能访问数组的特定元素,并且可以是其他变量的表达式。可以为Verilog支持的任何不同数据类型形成一个数组。

y3[1][2] = 8'hdd;  // Assign 0xdd to rows=1 cols=2
y3[0][0] = 8'haa;     // Assign 0xaa to rows=0 cols=0example [15][1] = 4'ha;example [15][0] = 4'ha;

数组建模以及初始化示例

mem1是一个8位向量,mem2是一个深度为4(由范围[0:3]指定)的8位数组,mem3是一个具有4行2列的16位向量2D数组。这些变量被分配了不同的值并被打印。

module des ();reg [7:0]  mem1;                           // reg vector 8-bit widereg [7:0]  mem2 [0:3];              // 8-bit wide vector array with depth=4reg [15:0] mem3 [0:3][0:1];     // 16-bit wide vector 2D array with rows=4,cols=2initial beginint i;mem1 = 8'ha9;$display ("mem1 = 0x%0h", mem1);mem2[0] = 8'haa;mem2[1] = 8'hbb;mem2[2] = 8'hcc;mem2[3] = 8'hdd;for(i = 0; i < 4; i = i+1) begin$display("mem2[%0d] = 0x%0h", i, mem2[i]);endfor(int i = 0; i < 4; i += 1) beginfor(int j = 0; j < 2; j += 1) beginmem3[i][j] = i + j;$display("mem3[%0d][%0d] = 0x%0h", i, j, mem3[i][j]);endendend
endmodule

最终可以得到打印结果:

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

在给一个存储器逻辑设计的例子:

在此示例中,存储器是一个深度为4的数组,每个深度的宽度为16位。设计模块接受一个称为addr的附加输入信号,以访问存储器中的特定索引。

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) beginif (!rstn) beginfor (i = 0; i < 4; i = i+1) beginregister[i] <= 0;endend else beginif (sel & wr)register[addr] <= wdata;elseregister[addr] <= register[addr];end
endassign rdata = (sel & ~wr) ? register[addr] : 0;
endmodule

在硬件示意图中可以看到,存储器的每个索引都是一个16位触发器,并且输入地址用于访问一组特定的触发器。

FPGA的设计艺术(18)如何使用Verilog中的数组对存储器进行建模?相关推荐

  1. FPGA的设计艺术(17)如何搭建一个简易的逻辑测试平台?

    前言 提到FPGA逻辑的仿真,一般指的是行为仿真或者功能仿真,还有人会称为前仿,不包含时间延迟信息,只验证逻辑功能.对于小模块的仿真,需要写一个测试文件,英文是testbench,即测试平台.在tes ...

  2. FPGA的设计艺术(11)FPGA的构建过程

    前言 本文讨论FPGA的构建过程,由于FPGA的过程太多了,恐怕会有歧义,这个过程,不是开发过程,不是开发流程,而是实实在在的FPGA编译的过程,使用编译恐怕不是太合适,但是大家都叫习惯了,也知道FP ...

  3. FPGA的设计艺术(5)STA实战之时钟偏斜对建立保持时间的影响以及时序报告分析

    前言 本文首发:FPGA的设计艺术(5)STA实战之时钟偏斜对建立保持时间的影响以及时序报告分析. STA回顾 70年代的时序是通过Spice仿真执行的.80年代的时序包括在Verilog仿真中,以确 ...

  4. FPGA的设计艺术(9)FPGA开发技巧与工程管理

    文章目录 前言 设计技巧和常见错误 PCB设计 数字设计 同步设计计数器示例:纹波计数器 减少编码时的不确定性. Verilog/VHDL编码 仿真 为什么仿真? 工程管理 管理工程师 前言 阅读一段 ...

  5. FPGA的设计艺术(8)最佳的FPGA开发实践之严格遵循过程

    文章目录 前言 如何花费更少的时间去调试? 为什么使用过程? 需要多少过程? 最小的过程 明确需求 数字设计方案 逻辑设计 功能仿真 板上验证 版本控制 编码指南:简短的技术组合,可最大程度地减少错误 ...

  6. FPGA的设计艺术(6)STA实战之SmartTime时序约束及分析示例(I)

    前言 FPGA进行时序分析通常使用厂家的编译工具,进行时序分析,但是万变不离其宗,时序分析的知识通常都是通用的,原理都是一致的.下面根据SmartTime的资料来看下时序分析的实际操作是如何的,这在其 ...

  7. FPGA的设计艺术(4)STA实战之不同时序路径的建立保持时间计算

    前言 本文首发:FPGA的设计艺术(4)STA实战之不同时序路径的建立保持时间计算 STA定义 STA定义为:时序验证,可确保各种电路时序是否满足各种时序要求. ASIC / FPGA设计流程中最重要 ...

  8. FPGA的设计艺术(3)静态时序分析

    前言 本文首发:FPGA的设计艺术(3)静态时序分析,我的易百纳技术社区专栏. 同行邀请消息:FPGA/IC Technology Exchange 什么是静态时序分析(STA)? 静态时序分析介绍 ...

  9. FPGA的设计艺术(2)FPGA开发流程

    前言 注:本文首发易百纳技术社区,文章链接:FPGA的设计艺术(2)FPGA开发流程 本文介绍整个FPGA设计流程以及设计FPGA所需的各个步骤-从一开始到可以将设计下载到FPGA的阶段.但是在此之前 ...

最新文章

  1. 问题 C: 完美的数(思维)
  2. 应云而生,幽灵的威胁 - 云原生应用交付与运维
  3. 网络基本功系列:细说网络那些事儿
  4. Python3.1-标准库之Numpy
  5. python 两个df求相同的行_python – Pandas df操作:如果其他列行重复,则返回值列表的新列...
  6. Python学习之路-基础知识1
  7. 笔记本(宏基4741G)升级为固态硬盘
  8. matlab中的sprintf函数,Matlab中disp和sprintf函数使用方法和区别介绍
  9. 网络共享时 计算机名如何设置方法,win7怎么在局域网共享文件夹|win7局域网共享设置方法...
  10. 网络服务器是干什么用的
  11. 让电脑前后面板音频插孔同时输出声音方法
  12. 灵魂画师全都出来了,都怪昨天那个AI画猫的应用……
  13. 用计算机管理硬盘分区,硬盘分区diskgenius工具使用方法,教你如何进行硬盘管理...
  14. Icon图标 [Java]
  15. 2048java设计报告_2048设计报告.doc
  16. 安图实验室信息系统--用户许可协议(仅供学习使用)
  17. 微服务架构深度解析与最佳实践
  18. 强烈推荐一款开源项目! (OPC)微服务能力开放平台!
  19. 有限群元素的阶必然存在
  20. Matlab中滤波器的设计(FDAT)

热门文章

  1. VMware宣布Big Data Extensions 2.0 GA
  2. jBPM4.4 no jBPM DB schema:
  3. 20 Very Useful Java Code Snippets
  4. java 加密算法 base64
  5. C# 遍历 HTML元素 遍历html控件
  6. 给jqGrid数据行添加修改和删除操作链接
  7. tomcat乱码怎么解决_PDF转word乱码怎么办?解决方法如此简单!
  8. java 抽象工厂工厂_Java设计模式之简单工厂、工厂方法和抽象工厂
  9. linux mysql 1045 错误_Linux 下,mysql数据库报无法登陆错误:ERROR 1045 (28000): Access denied for use...
  10. 关于tomcat中文乱码的问题解决