Verilog:$readmemb和$readmemh系统函数的使用与其中的初始化地址相关问题(详细细节)

news2024/12/27 13:06:48

相关阅读

Verilog基础icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482


        $readmemb和$readmemh两个系统函数用于将文件中的数据加载到存储器或者被称为数组的memory中。首先给出他们的语法的BNF范式,有关BNF范式的内容可以在之前的文章中找到:

        首先要注意的是,作为系统函数的一类,这些语句都是能在过程块initial和always中使用的。

        load_memory_tasks分为两类,一类是以二进制解析文件中的数据,而另一类是以十六进制解析。特别提醒,$readmemb和$readmemh中美元符$和后面的关键词之间必须连续,不能有空白。

        file_name指的是要读取数据的文本文件名,文件名可以使用绝对路径或相对路径,相对指的是相对当前仿真器的工作目录(一般为项目文件所在文件夹)。

        要读取数据的文件有以下三点要求:

  • 用于分隔数字的空白字符(空格、换行符、制表符、换页符)
  • 注释(两种形式的注释都可以,即//或/* */)
  • 二进制或十六进制数字(这里指的是纯数字,不含任何其他指示性的符号,即111,fff这种,且不能包含正负号+、-)

        memory_name指的是需要初始化的存储器名,数字的长度不能高于存储器的数据位宽,否则当读取到不符合要求的数据会报错,无法继续读取。未知值(x或X)、高阻抗值(z或Z)和下划线(_)可用于指定数字,应使用若干空白字符和/或注释来分隔数字,下面是一些例子。

test.v
module test();
    
    reg [7:0]data[7:0];//和reg [7:0]data[0:7];效果相同
    initial
        $readmemb("../data.txt", data);
endmodule


data.txt
//前5个数据正常读取,直到0b报错无法解析
11 01 11111 11 100 0b101 110 111 1000 001 100001 


//第一个数据太大了,报错无法解析
11111111111 11 01 11111 11


//可以在数字中插入_
11_00 1122 2344 


//可以用换行符分隔
11
22
33


//可以用注释分隔数字
11/*55555*/01 11111 11 100 

//可以在数字中使用x或z
z1 x1 11 12

        当指定的数字位宽小于存储器的位宽时,将会进行位宽拓展,这里的拓展规则只和数据有关而与存储器变量的类型无关,类似于Verilog基础:表达式中的整数常量(integer)一文中“无符号数字的位宽小于位宽常数指定的大小”一样,如果数字最高位是1或0,则补0至存储器的数据位宽,如果是z则补z,如果是x则补x。

        当文件数据被从上至下,从左至右读取时,每个数据被分配给索引从低到高的各个存储器变量,寻址可以通过在系统任务调用中指定开始和/或结束地址以及在数据文件中使用符号指定地址来控制。

        当地址出现在数据文件中时,格式为@字符,后跟十六进制数字,如下所示:

@hhh  
@HHH
@HhH
@ 1h1 //错误

        数字中允许同时使用大写和小写数字。@和数字之间不允许有空格,可以使用数据文件中所需的任意多的地址规范,当系统任务遇到地址规范时,它会从该内存地址开始加载后续数据,并将数据填入对应地址索引的寄存器变量中。

        文件中的所有数字都有默认的地址,分为几种情况:

  • 如果系统函数中没有规定起始地址和终止地址,数据文件中也没有显式的地址,则数据的默认地址为从寄存器变量的最小地址开始依次加1。读取将从寄存器变量的最小地址开始依次读取后面的数据,直到有一个数据的默认地址大于寄存器变量的最大地址(因为此时的数据地址范围要求为从寄存器变量的最小地址到最大地址之间),或者数据读完。举例说明如下所示。
test.v
module test();
    reg  [7:0]data[7:1];
    initial
        $readmemb("data.txt", data);//地址范围1到7
endmodule

data.txt //data[5], data[6], data[7]未初始化
00 //地址为1
01 //地址为2
10 //地址为3
11 //地址为4


data.txt //恰好全部初始化
00 //地址为1
01 //地址为2
10 //地址为3
11 //地址为4
00 //地址为5
01 //地址为6
10 //地址为7

data.txt //全部初始化
00 //地址为1
01 //地址为2
10 //地址为3
11 //地址为4
00 //地址为5
01 //地址为6
10 //地址为7
11 //地址为8,当试图读取这个数时会提示超出范围(Too many data words read on line 8 of file)        
   //并结束读取
  • 如果系统函数中只规定了起始地址(它必须在存储器的地址范围内),数据文件中也没有显式的地址,则数据的默认地址为从起始地址开始依次加1。读取将从起始地址开始依次读取后面的数据,直到有一个数据的默认地址大于寄存器变量的最大地址(因为此时的数据地址范围要求为从寄存器变量的最小地址到最大地址之间),或者数据读完。举例说明如下所示。
test.v
module test();
    reg  [7:0]data[7:1];
    initial
        $readmemb("data.txt", data, 2);//起始地址为2(必须在1到7之间),则地址范围是2到7
endmodule

data.txt //data[1]和data[6], data[7]未初始化
00 //地址为2
01 //地址为3
10 //地址为4
11 //地址为5


data.txt //data[1]未初始化
00 //地址为2
01 //地址为3
10 //地址为4
11 //地址为5
00 //地址为6
01 //地址为7,读取完这个数据遇到文件结束,结束读取


data.txt //data[1]未初始化
00 //地址为2
01 //地址为3
10 //地址为4
11 //地址为5
00 //地址为6
01 //地址为7
10 //地址为8,当试图读取这个数时会提示超出范围(Too many data words read on line 7 of file)
   //并结束读取 
  • 如果系统函数中规定了起始地址和结束地址(它们必须在存储器的地址范围内),数据文件中也没有显式的地址,则数据的默认地址为从起始地址(因此它必须在存储器的地址范围内)开始依次加1或减1,这取决于起始地址和结束地址的大小,如果结束地址大于起始地址,则为加1,否则为减1。读取将从起始地址开始依次读取后面的数据,直到有一个数据的默认地址大于寄存器变量的最大地址,或小于最小地址(因为此时的数据地址范围要求为从寄存器变量的最小地址到最大地址之间),或者数据读完。举例说明如下所示。
test.v
module test();
    reg  [7:0]data[7:1];
    initial
        $readmemb("data.txt", data, 2, 5);//起始地址为2,终止地址为5(必须在1到7之间),则地 
                                          //址的范围是2到5,默认地址递增
endmodule

data.txt //data[1], data[5], data[6], data[7]未初始化
00 //地址为2
01 //地址为3
10 //地址为4


data.txt //data[1]未初始化
00 //地址为2
01 //地址为3
10 //地址为4
11 //地址为5
00 //地址为6
01 //地址为7,读取完这个数据遇到文件结束,结束读取


data.txt //data[1]未初始化
00 //地址为2
01 //地址为3
10 //地址为4
11 //地址为5
00 //地址为6
01 //地址为7
10 //地址为8,当试图读取这个数时会提示超出范围(Too many data words read on line 7 of file)
   //并结束读取 
test.v
module test();
    reg  [7:0]data[7:1];
    initial
        $readmemb("data.txt", data, 5, 2);//起始地址为5,终止地址为2(必须在1到7之间),则地 
                                          //址的范围是2到5,默认地址递减
endmodule

data.txt //data[1], data[2], data[6], data[7]未初始化
00 //地址为5
01 //地址为4
10 //地址为3


data.txt //data[1], data[6], data[7]未初始化
00 //地址为5
01 //地址为4
10 //地址为3
11 //地址为2,读取完这个数据遇到文件结束,结束读取


data.txt //data[1], data[6], data[7]未初始化
00 //地址为5
01 //地址为4
10 //地址为3
11 //地址为2
00 //地址为1,当试图读取这个数时会提示超出范围(Too many data words read on line 5 of file)
   //并结束读取 
01 //地址为0
  • 现在我们来看数据文件中有显式的地址标识时的情况,第一个地址标号规定了其前后的地址,后面的地址标号规定了其后的地址,根据上面的规则,可以是递增也可以是递减。如下所示。
data.txt //系统函数中起始地址小于终止地址,或没有终止地址,或没有起始和终止地址,则递增
00 //地址为-2
01 //地址为-1
10 //地址为0
@1
00 //地址为1
01 //地址为2
10 //地址为3
@7
00 //地址为7
01 //地址为8
10 //地址为9


data.txt //系统函数中起始地址大于终止地址,则递减
00 //地址为9
01 //地址为8
10 //地址为7
11 //地址为6
@5
00 //地址为5
01 //地址为4
10 //地址为3
11 //地址为2
@6
00 //地址为6
01 //地址为5
10 //地址为4
11 //地址为3


        在读取有地址标号的文件时,首先会定位到地址和起始地址相同的那条数据(当没有起始地址时,是定位到存储器对应的最小地址,上面的第一种情况中为1),然后开始从左到右,从上到下,一条一条数据依次读取数据,直到文件结束(所以可能会出现初始化覆盖的情况,如下所示),或者有数据的地址超出了范围才结束读取。

test.v
module test();
    reg  [7:0]data[7:1];
    initial
        $readmemb("data.txt", data, 2);//起始地址为2(必须在1到7之间),则地址范围是2到7
endmodule


data.txt
00 //地址为-1
01 //地址为0
10 //地址为1
11 //地址为2, 从这里开始读取
@3
00 //地址为3
01 //地址为4
10 //地址为5
11 //地址为6
@0
00 //地址为1
00 //地址为2,覆盖了地址为2的原值11
11 //地址为3,覆盖了地址为3的原值00
00 //地址为4,覆盖了地址为4的原值01

data.txt
00 //地址为-1
01 //地址为0
10 //地址为1
11 //地址为2, 从这里开始读取
@3
00 //地址为3
01 //地址为4
10 //地址为5
11 //地址为6
11 //地址为7
11 //地址为8,当试图读取这个数时会提示超出范围(Too many data words read on line 11 of       
   //file并结束读取,因此后面不会覆盖
@0
00 //地址为1
00 //地址为2,
11 //地址为3,
00 //地址为4,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1031106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GaussDB技术解读系列:性能调优

近日,在第14届中国数据库技术大会(DTCC2023)的GaussDB“五高两易”核心技术,给世界一个更优选择专场,华为数据库技术专家李士福详细解读了GaussDB性能调优的相关技术和应用实践。 本篇为大家分享GaussDB性能调优的实践…

【MySQL 45讲笔记】

文章目录 第一讲:一条SQL查询语句是如何执行的?第二讲:一条SQL更新语句是如何执行的?第三讲:事务隔离,为什么你改了我还看不见第四讲:深入浅出索引(上)第五讲&#xff1a…

Python函数绘图与高等代数互溶实例(二): 闪点函数

Python函数绘图与高等代数互溶实例(一):正弦函数与余弦函数 Python函数绘图与高等代数互溶实例(二):闪点函数 Python函数绘图与高等代数互溶实例(二):设置X|Y轴|网格线 一: 函数plot(),展示变量的变化趋势 import numpy as np import matplotlib.pyplot as plt from pylab i…

商家收款一万手续费多少

目前微信和支付宝作为主流的支付平台,为商家提供了安全、便捷的支付解决方案。但是在正常情况下,商家需要向平台支付交易额0.6%至1%不等的手续费,这个费率看似很少,但长期积累下来的手续费支出也是一笔不小的开支。 什么是收款手…

复习Day01:数组part01:701. 二分查找、35. 搜索插入位置、367. 有效的完全平方数、69. x的平方根、74. 搜索二维矩阵

之前的blog链接:https://blog.csdn.net/weixin_43303286/article/details/131690654?spm1001.2014.3001.5501 我用的方法是在leetcode再过一遍例题,明显会的就复制粘贴,之前没写出来就重写,然后从拓展题目中找题目来写。辅以Lab…

UI设计和平面设计的区别是什么?看完这篇一次搞懂

很多想要从事视觉领域工作的新手设计师,搞不懂UI设计和平面设计的区别;也有很多平面设计师工作后想转UI,却不知道该如何进行,导致择业和职业发展受阻,其实核心问题还是因为没有弄清楚UI设计和平面设计的区别是什么。 …

电工-三极管主要参数(直流、交流、极限)

三极管主要参数(直流、交流、极限) 三极管的主要参数分为三种,即直流参数、交流参数和极限参数,下面分别介绍: 直流参数 共发射极直流放大倍数βIc/Ib 集电极—基极反向截止电流Icbo,Ic0时,…

浅谈终端安全接入

前言: 随着网络的发展,现代企业大多都会部署企业的有线网络与无线网络,在传统的企业网内,随着越来越多的终端设备接入到公司网络,管理人员控制和审计外部用户接入的企业办公网的难度和工作量也越来越大。而如果允许外…

代码随想录二刷Day 15

102. Binary Tree Level Order Traversal vector<int>() it is basically constructor of std::vector class and will create a new empty vector. You can also mention the size of required vector in brackets. 访问二维vector的元素: 如果指定外层和内层向量的大…

技术贴 | 深度解析 PostgreSQL Protocol v3.0(二)— 扩展查询

引言 PostgreSQL 使用基于消息的协议在前端&#xff08;客户端&#xff09;和后端&#xff08;服务器&#xff09;之间进行通信。该协议通过 TCP/IP 和 Unix 域套接字支持。 《深度解析 PostgreSQL Protocol v3.0》系列技术贴&#xff0c;将带大家深度了解 PostgreSQL Protoc…

Matter 是什么?

Matter&#xff08;物联网Matter&#xff09;旨在成为一个可互操作的标准&#xff0c;促进技术采用和创新&#xff0c;逐渐取代智能家居生态系统的专有协议。 Matter采用一个开源的软件开发工具包&#xff08;SDK&#xff09;&#xff0c;其中包含了协议规范的实现&#xff0c…

如何低成本、低门槛开发全屋智能系统?

近期&#xff0c;某个科技通讯巨头豪掷 15 亿重金&#xff0c;准备成立房地产公司以大力推动全屋智能的发展。从大部分科技公司频频押注全屋智能领域来看&#xff0c;全屋智能已然成为智能家居第一大发展趋势&#xff0c;是资本市场的重头戏。 但全屋智能并不好做&#xff0c;…

【Linux】详解线程第一篇——由单线程到多线程的转变

线程详解 前言正式开始啥是线程理解线程Windows和Linux下的线程Windows下的线程Linux下的线程对比 重新理解进程理解曾经写的代码 Linux的线程pthread库验证多线程在同一个进程中跑ps -aL线程资源线程切换成本低线程缺点线程异常线程等待pthread_create的第三个参数——回调函数…

MyBatis友人帐之ResultMap及分页

一、ResultMap 1.1查询为null问题 要解决的问题&#xff1a;属性名和字段名不一致 解决方案 方案一&#xff1a;为列名指定别名 , 别名和java实体类的属性名一致 . <select id"selectUserById" resultType"User">select id , name , pwd as passwor…

thinkphp8路由

thinkphp8已出来有好一段时间了。这些天闲来无事&#xff0c;研究了下tp8的路由。默认情况下&#xff0c;tp8的路由是在route\app.php的文件里。但在实际工作中&#xff0c;我们并不会这样子去写路由。因为这样不好管理。更多的&#xff0c;是通过应用级别去管理路由。假如项目…

【JDK 8-函数式编程】4.4 Supplier

一、Supplier 接口 二、实战 Stage 1: 创建 Student 类 Stage 2: 创建方法 Stage 3: 调用方法 Stage 4: 执行结果 一、Supplier 接口 供给型 接口: 无入参&#xff0c;有返回值&#xff08;T : 出参类型&#xff09; 调用方法: T get(); 用途: 如 无参的工厂方法&#x…

多频超声波清洗机有什么特点?使用需要注意什么?

多频超声波清洗机是指具备多个频率可调的超声波发生器的清洗机&#xff0c;是在一只清洗槽内&#xff0c;安装有两种或三种以上不同频率的超声波换能器&#xff0c;由多只发生器分别推动各自频率的超声波进行清洗。传统的超声波清洗机通常只能在固定的频率下工作&#xff0c;而…

口袋参谋:新品上架如何做市场调查?这个方法超实用

很多商家在新品上架之前&#xff0c;都会对宝贝的市场行情进行调查分析&#xff0c;只有了解指定关键词下的行业市场数据&#xff0c;了解消费者需求,才能针对性的进行卖货。 可是我们要是人工一点点去搜集&#xff0c;一点点去翻找&#xff0c;很多数据是没法进行人工去统计的…

JavaScript - canvas - 选择部分区域的图像数据

效果 示例 项目结构&#xff1a; 源码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>选择部分区域的图像数据</title><style type"text/css">div {width: 200px;height: 200px;di…

基于图的基础推荐方式

文章目录 1. 基于图的基础推荐方式1.1 链路预测&#xff08;Link Prediction&#xff09;1.2 什么是路径1.3 基于路径的基础链路预测1.4 图游走算法DeepWalk1.4.1 Word2Vec1.4.2 DeepWalk原理1.4.3 DeepWalk代码示例 1.5 图游走算法Node2Vec1.5.1 Node2Vec原理1.5.2 Node2Vec公…