0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在Testbench中如何读取和存储文本文件的数据呢?

冬至子 来源:Bug记录 作者:woodfan 2023-06-06 11:44 次阅读

对一些数据处理的模块进行调试仿真,模块需要特定的数据输入,比如单一频率的正弦波;为了解决这个问题,我们可以用matlabpython等工具生成文本数据,然后使用Verilog将数据读取进来;Testbench可以使用2种方法进行文本数据操作

  1. readmemb, readmemh, writememb, writememh操作
  2. fscanf, fwrite等操作

readmemb, readmemh, writememb, writememh操作

从字面意思理解,readmem是读取数据到memory,后缀的b, h代表了数据的进制;同理,writemem是将memory的数据写入到文件中;

所以,在使用这一类系统自带函数时,首先要有一个memory类型的变量。定义方法如下:

reg [M-1:0] mem [N:1];

mem”变量“(应该叫寄存器组)有N个”一维“变量,每个”一维“变量的bit宽度为M;你可以将mem理解为C语言中的二维数组,里面包含了N个一维数组,每个一维数组有M个元素,元素为bit。

事实上,我们称M为mem的数据宽度,N为mem的数据深度。

以readmemb为例,进行数据读取操作

initialbegin $readmemb("data.txt", mem);end

readmemb的第一个参数为文件名,第二个参数为memory变量名;至此,data.txt内部的N行数据存入了mem里。readmemh操作类似,不同的是data.txt的数据要求为16进制。

那么可能有人会有疑问了,假如有以下问题,mem存入的数据会是啥样:

  • data.txt每行的数据位宽小于M或者大于M

图片

图1 数据位宽小于M波形

图片

图2 数据位宽小于M存储

图片

图3 数据位宽大于M

图片

图4 数据位宽大于M,VCS警告

经过试验,M大于数据位宽,数据可以正常读取,高位补0;小于数据位宽,数据无法正常读取。

  • data.txt的数据不是二进制,或者不是纯数字

与M小于数据位宽的情况一致,无法正常读取数据。

  • 如果data.txt的行数小于N或大于N

图片

图5 行数小于N

图片

图6 行数大于N

经过试验,行数大于N,仿真器会出警告,但数据可以正常读取。小于N时,多余的部分memory的值为不定状态。

数据存入mem但还没有进入到模块的输入,接下来的操作可以参考下列代码:

reg [M-1:0] data_in;integer index = 1;
initialbegin forever begin @(posegde clk); data_in = mem[index]; index = (index >= N) ? 1 : index + 1; endend

代码里面,等待clk的上升沿,然后将mem的index元素赋值给data_in,然后index完成加1操作;整个过程不断循环;这里设置了index计数到N返回1的计数保护,防止出现无效数据。

再将data_in与被测模块的数据输入端口相连,数据就送入进去了。

图片

图7 送入的数据波形

writememb的操作与readmemb反过来,将mem的数据存储为文本操作如下:

initial
begin
    $writememb("new_data_b.txt", mem);
    $writememh("new_data_h.txt", mem);
end

存储之后的

图片

图8 writememh

图片

图9 writememb

fscanf, fwrite等操作

Verilog本身的语法与C类似,其自身也有文本操作的函数,也与C类似。使用Verilog对文本操作,首先需要进行如下操作:

integer fid;initialbegin fid = $fopen("data.txt", "r"); //fid = $fopen("data.txt", "w"); //write if (!fid) $display("file open error");end

如同C语言中的fopen一样,第一个参数为文件名,第二个参数为操作模式,包括读(r, rb),写(w, wb)等操作;根据返回值判断文件操作是否有错误。

然后,根据文本文件的数据格式,进行数据读取操作。

reg [M-1:0] data_in;
always @ (posedge clk) $fscanf(fid, "%d %d %d", data_in, mem[0], mem[1]);

fscanf用法与C语言类似,文件句柄为第一个参数,第二个参数为格式参数,第三个为数据保存变量,但不需要加&了。读取文件的时候第二个参数与第三个参数需要对应,否则数据读取可能会出错。(亲身经历)

数据存储操作如下,在前面fopen使用w模式下:

always @ (posegde clk) $fwrite(fid, "%d, %d, %d\\n", $signed(data_in), $signed(data_in)+1, $signed(data_in)+2);

数据可以按照第二个参数的格式存储进文本文件。还有一系列如fdisplay, 相对于fwrite, 它的文件写入数据之后会自动到下一行,所以第二个参数不需要加入“\\n”;ftell等函数。

注意,想要存储十进制的负数,除了第二个参数用%d,第三个参数的寄存器变量还要使用$signed转换为有符号数形式

图片

图10 正常情况文本操作读取后存储的数据

图片

图11 寄存器位宽小于数据位宽时,文本操作读取后存储的数据

注意,当存储的寄存器位宽小于数据位宽时,数据会被自动截去高位保留低位。

之前使用文件操作存储被测模块的输出时,每次文件的数据量(行数)都与理想中的数目对不上,找各种原因,最后才发现自己犯了一个低级错误,没有使用fclose关闭文件句柄。

initial begin #1000; $fclose(fid); $finish;end

停止仿真前,一定要用fclose关闭文件句柄,否则数据存取会出现不可预知的问题。

欢迎使用本文使用的Testbench做实验,注意,在windows下使用modelsim做实验时,文件名必须是绝对路径;tb中,使用"READMEM_ON"宏定义决定运行readmem或文件操作,可以尝试修改宏定义的值改变文件操作的函数类型;本文使用资源在公众号回复116获取;

两种方法差异对比

  1. readmem,writemem方法只能存取二进制或十六进制数据,数据格式固定,对多维其他格式数据读取不支持,没有文件操作灵活;文本操作方便其他的工具,如matlab,python处理数据
  2. readmem是可综合语句,所以可以用于对模块内的memory变量进行赋值,但其他语句是不可综合语句,只能用于仿真测试中
  3. 文件操作虽然支持各种格式的文本存取,但是操作上没有readmem, writemem简单;假如数据需要循环使用,readmem读取进memory之后,通过复位index就可以循环使用数据,而文本操作就麻烦一些。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • matlab
    +关注

    关注

    175

    文章

    2922

    浏览量

    228440
  • 寄存器
    +关注

    关注

    30

    文章

    5028

    浏览量

    117719
  • 正弦波
    +关注

    关注

    11

    文章

    562

    浏览量

    54321
  • 仿真器
    +关注

    关注

    14

    文章

    988

    浏览量

    82993
  • C语言
    +关注

    关注

    180

    文章

    7530

    浏览量

    128588
收藏 人收藏

    评论

    相关推荐

    如何在Go中操作文本文件

    作为一种编程语言,Go 具有广泛的内置功能,包括创建、读取和写入文本(.txt)文件文件的功能。 文件是现代世界我们日常生活的重要组成部分
    发表于 09-29 09:48 621次阅读

    求助,为什么CAN数据库(.dbc文本文件找不到报文?

    我有CAN数据库(dbc文件)。这是一个文本文件。此文件的扩展名为 dbc。Vector CANdb++编辑器
    发表于 01-23 06:28

    怎么用LABVIEW读取文本文件

    求助 怎么用LABVIEW读取文本文件 能不能给点提示或者框图谢谢啦
    发表于 04-15 10:40

    如何把文本文件里面的数据读取到波形图表

    本帖最后由 eehome 于 2013-1-5 09:50 编辑 如何把文本文件里面的数据读取到波形图表
    发表于 06-07 11:10

    matlab读取文本文件然后再计算

    matlab读取文本文件文本文件里有各时间点的电压瞬时值,需把它求和然后再求平均值。谢谢大侠了
    发表于 11-15 10:17

    问一个文本文件读取的问题

    `首先编写了一个文本读取的子VI,文本用的是相对路径现在在一个程序调用该子VI,且没有问题下面就是问题所在了我将程序打包exe可执行文件
    发表于 01-05 09:48

    labview怎么将文本文件数据按奇,偶行分别进读取

    labview怎么将文本文件数据按奇,偶行分别进读取。求程序框图,谢谢。
    发表于 03-27 09:22

    TCP通信时用到while循环,将读取的TCP数据写入文本文件,程序结束后打开那个文本文件里面怎么没有数据

    运行时不按停止按钮,它就一直读取TCP数据,因为我传输的TCP数据有限所以后面读取TCP数据VI会报错,这时候终止执行,打开
    发表于 12-12 21:23

    labview如何倒序读取文本文件

    一个文本文件,如何使用labview将其从末尾字符开始读取直到第一个并显示
    发表于 04-23 16:55

    CVI中文本文件的格式问题

    )coeffPath表示函数读取文本文件的路径,这个文本文件必须在四个连续行包含滤波器G0、G1、H0和H1的系数,请问它的格式是怎样的,最好给个案例,谢谢
    发表于 03-04 20:09

    labview如何读取6400个超声数据文本文件,并用波形图逐一显示出来

    /O打开读取文本文件函数后,具体操作思路是怎么样的。图片为部分6400个超声波文件文本
    发表于 04-17 22:27

    如何在 Python 读取文本文件

    读取文本文件。有三种方法可以 Python 读取文本文件 -read() - 此方法
    发表于 06-10 20:21

    C语言入门教程-文本文件

    文本文件 C中的文本文件很简单,不难掌握。所有的文本文件操作函数和相关类型都由stdio库提供。 当您的C程序需要文本输入输出(I/O)功能,且只有一个信息
    发表于 07-29 11:23 1227次阅读

    C语言入门教程-读取文本文件

    读取文本文件若要读取一个文件,请使用r模式打开。一般来说,读取文件时最好不要用fscanf,因为
    发表于 07-29 11:29 2824次阅读

    Arduino之如何逐行读取SD卡文本文件

    电子发烧友网站提供《Arduino之如何逐行读取SD卡文本文件.zip》资料免费下载
    发表于 07-12 10:17 1次下载
    Arduino之如何逐行<b class='flag-5'>读取</b>SD卡<b class='flag-5'>文本文件</b>