博文目录

  • 写在前面
  • 正文
    • 多维数组
    • 多维数组赋值
    • 内存
    • 寄存器变量应用实例
    • 寄存器阵列应用实例
  • 参考资料
  • 交个朋友

写在前面

上篇博客讲了单比特的变量称为标量,多比特的变量称为向量。其实向量就类似于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 widewire [0:7] y2 [3:0]          // y is an 8-bit vector net with a depth of 4reg  [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 widewire [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 begina[0] = 16'h0000;
a[1] = 16'h0101;
//.......or
a[0][0] = 1'b0;
a[0][1] = 1'b1;
//......orfor(integer i = 0; i <16; i = i + 1) begina[i] <= 0;
endend

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

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

举一个仿真的例子:


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

仿真结果:

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

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


参考资料

  • 参考资料1
  • 参考资料2

交个朋友

  • 个人微信公众号:FPGA LAB

  • 知乎:李锐博恩

  • FPGA/IC技术交流2020

Verilog初级教程(5)Verilog中的多维数组和存储器相关推荐

  1. Verilog初级教程(23)Verilog仿真中的显示任务

    文章目录 前言 正文 Display/Write Tasks Verilog Strobes Verilog Continuous Monitors Verilog Format Specifiers ...

  2. Verilog初级教程(21)Verilog中的延迟控制语句

    文章目录 前言 正文 延迟控制语句 事件控制语句 Named Events Event or operator 往期回顾 参考资料及推荐关注 前言 Verilog中的延迟控制有两种类型–延迟和事件表达 ...

  3. Verilog初级教程(20)Verilog中的`ifdef 条件编译语句

    文章目录 前言 正文 语法 示例 Testbench文件 往期回顾 参考资料及推荐关注 前言 `ifdef条件编译语句在逻辑设计中还是很常见的,但也常见一些滥用的情况,这应该避免. 应该在什么情况下使 ...

  4. Verilog初级教程(15)Verilog中的阻塞与非阻塞语句

    文章目录 前言 正文 阻塞赋值 非阻塞赋值 往期回顾 参考资料以及推荐关注 前言 本文通过仿真的方式,形象的说明阻塞赋值以及非阻塞赋值的区别,希望和其他教程相辅相成,共同辅助理解. 正文 阻塞赋值 阻 ...

  5. Verilog初级教程(14)Verilog中的赋值语句

    文章目录 前言 正文 合理的左值 过程性赋值(Procedural assignment) 连续赋值 过程连续性赋值 往期回顾 前言 何为赋值语句?即将值放到线网或者变量上,这种操作称为赋值,英文:a ...

  6. Verilog初级教程(12)Verilog中的generate块

    文章目录 前言 正文 generate for generate if generate case 参考资料 本系列博文 前言 verilog中的generate块可以称为生成块,所谓生成,可以理解为 ...

  7. Verilog初级教程(11)Verilog中的initial块

    文章目录 前言 正文 语法格式 initial块是用来干什么的? initial块何时开始又何时结束? 一个模块中允许有多少个initial块? 参考资料 写在最后 前言 仿真中通常会依次执行一组Ve ...

  8. Verilog初级教程(19)Verilog中的参数

    文章目录 前言 正文 模块参数 覆盖参数 例子说明 递增计数器 递减计数器 Specify参数 模块参数与Specify参数的区别 往期回顾 参考资料及推荐关注 前言 Verilog中的参数是使得设计 ...

  9. Verilog初级教程(16)Verilog中的控制块

    文章目录 前言 正文 条件语句if 语法 硬件实现 循环语句 forever repeat while for 往期回顾 参考资料及推荐关注 前言 硬件行为的实现离不开条件语句和其他控制逻辑流的方式. ...

最新文章

  1. Udacity机器人软件工程师课程笔记(八)-ROS Turtlesim 包的相关命令
  2. 腾讯斥资3.17亿美元增持B站 持股增至12%
  3. 生信多组学整合工具的比较研究
  4. 使用proc文件系统
  5. SpringCloud相关概念介绍
  6. WildFly 8.0.0.Alpha1的发布和一些历史
  7. QT| C/C++之win98扫雷外挂增强版
  8. python语法基础题你好_Python基础要打牢,先学会基本语法
  9. 在html中直接使用%3c php%3e,HTB-靶机-Calamity
  10. LINQ-查询表达式基础
  11. 物联网工程专业该怎么学?老学长吐血整理!!
  12. IMAGE_DOS_HEADER解析
  13. Hadoop与MPP
  14. 系统临时文件的写和读:createTempFile和tempFileContent
  15. Java 求最大公约数
  16. JAVA 输出 1 3 6 10 15 ....
  17. agd插值算法_多目标自适应和声搜索算法
  18. MBT测试思想在苏宁蛙测的运用实践分享
  19. ECSHOP模板文件功能说明
  20. 删除Mysql数据库的表空间,日志文件

热门文章

  1. 微信九宫图生成HTML源码
  2. BAPI_GOODSMVT_CREATE(调拨 收货 发货 入库 退货)BAPI
  3. 解决backtrack5连接不上ssh问题
  4. 算法设计与分析: 2-7 士兵站队问题
  5. C++ system()函数的常用用法 (史上最详细)
  6. MySQL 数据库管理之 --- 日志查询
  7. anaconda安装及配置
  8. 【源码阅读技巧一】查看类关系图,接口实现关系图(idea版本)Diagrams关系图
  9. Expert 诊断优化系列------------------内存不够用么?
  10. ROSNOTE : ros::spin() / ros::spinOnce() /rospy.spin()