【FPGA/verilog -入门学习11】verilogTestbench中的文本文件写入,读出,打印等操作

本文参考:Verilog中的系统任务(显示/打印类)--$display, $write,$strobe,$monitor-CSDN博客

Verilog:parameter、localparam的区别和用法-CSDN博客

Verilog的系统任务----$fopen、$fclose和$fdisplay, $fwrite,$fstrobe,$fmonitor_verilog fopen-CSDN博客

Verilog的系统任务----$readmemh和$readmemb-CSDN博客

1,$display

$display可以直接打印一条文本信息,并在每一次$display执行后会自动换行,比如:

`timescale 1ns/1ns
module test_tb();
 
initial begin
    $display("China NO1!");
    $display("USA NO2!");
end

2,$write

$write的用法与$display一致,区别在于,一条$write语句执行完后,不会自动换行。比如下面的代码:

 
`timescale 1ns/1ns
module test_tb();
 
initial begin
    $write("China NO1!");
    $write("USA NO2!");
end

这两个系统函数除了直接打印文本外,也可以打印变量的值,其格式为(以$display为例):

$display("%b %b",a,b) ;

3,$strobe

$strobe 为选通显示任务。$strobe 使用方法与 $display 一致,但打印信息的时间和 $display 有所差异(也可以直接打印文本)。

当许多语句与 $display 任务在同一时间内执行时,这些语句和 $display 的执行顺序是不确定的,一般按照程序的顺序结构执行。

两者的区别在于:$strobe命令会在当前时间部结束时完成;

而$display是只要仿真器看到就会立即执行。

$strobe 是在其他语句执行完毕之后,才执行显示任务。例如:

 `timescale 1ns/1ns
module test_tb();
 
reg [3:0]  a ;
initial begin
    $strobe("begin!");
    a = 1 ;
    #1 ;
    a <= a + 1 ;
    //第一次显示
    $display("$display excuting result: %d.", a);
    $strobe("$strobe excuting result: %d.", a);
    #1 ;
    $display();
    //第二次显示
    $display("$display excuting result: %d.", a);
    $strobe("$strobe excuting result: %d.", a);
    $strobe("end!");
end
endmodule 

总结:$display() 和他前面一条语句同时执行,没有延时,

而 $strobe 会等待上一条指令执行完成后输出

可以看到,$strobe与$display的打印内容不是一致的。

这是因为该语句: a <= a + 1 ;也就是说a的第二次赋值是非阻塞赋值,而非阻塞赋值是需要时间的。

在第一次打印时,$display不会管你a是阻塞赋值还是非阻塞赋值,它就直接打印a当前的值1。而$strobe则会等到非阻塞赋值完成后再打印,所以其打印的值为2。

在第二次打印时,又延时了1ns,所以此时的非阻塞赋值完成,那么$strobe与$display的打印内容就均为2了。

所以$strobe这个系统任务通常是用来打印当前非阻塞赋值的变量值的。

4,$monitor

$monitor 为监测任务,用于变量的持续监测。只要变量发生了变化,$monitor 就会打印显示出对应的信息。 其使用方法与 $display一致。

下面的代码用$monitor 来实现监控a,b,c这3个变量,只要其中一个发生了变化,就会立马在终端打印。


`timescale 1ns/1ns
 
module test_tb();
 
reg [1:0]  a ;
reg [1:0]  b ;
reg [1:0]  c ;
 
initial begin
    a = 0 ;
    b = 0 ;
    c = 0 ;
 
    $monitor("a=%d b=%d c=%d",a,b,c);
    #50 $finish;    //50ns后停止
end
 
always #10 begin        //每10ns,随机生成a,b,c
    a = {$random}%4;
    b = {$random}%4;
    c = {$random}%4;
end
 

终端打印结果如下:

5,$fopen

  • $fopen:打开指定文件
  • $fclose:关闭指定文件
integer        handle1;                                 //定义句柄1
handle1 = $fopen("file_name",type)       //以指定类型(type)的方式来打开文件,并将其返回值赋给handle

integer        handle1;                                                           //定义句柄1
handle1 = $fopen("D:/file_test/file_test1.txt","w");          //以w类型(写)的方式来打开文件,并将其返回值赋给handle1

6,$fdisplay, $fwrite,$fstrobe,$fmonitor

这4个函数都可以对指定文件进行打印或写入操作,其用法与对应的$display, $write,$strobe,$monitor几乎一致。建议参考以上用法

区别在于$display等函数是直接在仿真中进行打印,而$fdisplay等函数是对指定文件进行打印,需要通过句柄来指定是对具体哪个文件进行操作。如:

        reg                data;

        integer        handle1;                                                         //定义句柄1

        handle1 = $fopen("D:/file_test/file_test1.txt","w");       //以w类型(写)的方式来打开文件,并将其返回值赋给handle1

//对指定文件写入数据

        $fdisplay(handle1,"%d\n",data);                                    //按照十进制格式写入数据到handle1对应的文件中,只能逐个写入

7,$fclose

$fclose系统任务用来关闭指定文件,关闭后即无法对该文件进行操作。其格式如下:

$fclose(handle1);        //关闭文件file_test1,至此文件操作结束

8,$readmemh和$readmemb

$readmemh(h,hexadecimal,十六进制)用来读取16进制的数据

$readmemb(b,binary,二进制)则用来读取2进制的数据。

$readmemb("<数据文件名>",<数组名>)

$readmemb ("<数据文件名>",<数组名>,<起始地址>)

$readmemb ("<数据文件名>",<存贮器名>,<起始地址>,<结束地址>)

$readmemh("<数据文件名>",<数组名>)

$readmemh ("<数据文件名>",<数组名>,<起始地址>)

$readmemh ("<数据文件名>",<数组名>,<起始地址>,<结束地址>)

使用方法1:不指定起始地址和结束对应地址

$readmemh("<数据文件名>",<数组名>)


`timescale 1ns / 1ns
 
module tb_read_test();
 
integer i;     
reg [7:0] mem_test [9:0];        //mem_test是位宽8bit,个数为10的数组
 
initial $readmemh("D:/read_test/read_test.srcs/sim_1/new/data.txt",mem_test);    //绝对路径
 
//显示数组的10个值
initial begin
    for(i=0; i<10; i=i+1)
        $display("%d: %h", i, mem_test[i]);
end

仿真结果如下:

  1. 去除部分数据文件中的数据,导致数组无法被填满(注释掉后面4个数据):

仿真结果如下:

数据文件仅有6个数据,而数组个数为10,所以数组的后4个数据仍没有被赋值。

使用方法2:指定起始地址,但不指定结束地址

即$readmemh ("<数据文件名>",<数组名>,<起始地址>),此时会将从数据文件中读到的第1个数据填入数组的起始地址,此后类推,直到数组被填满。而之前被起始地址跳过的数组的数据则不会被赋值。如果数据的个数大于数据文件中数据的个数,则数组无法被填满,未被填满的部分则依然是未知状态。

指定数据从数组的地址2开始赋值,则地址2应该被赋值0,地址3被赋值1,···等等。而地址0和地址1则仍保持未赋值状态:

`timescale 1ns / 1ns
 
module tb_read_test();
 
integer i; 
reg [7:0] mem_test [9:0];//mem_test是位宽8bit,个数为10的数组
 
initial $readmemh("D:/read_test/read_test.srcs/sim_1/new/data.txt",mem_test,2);//绝对路径,从地址2开始
 
//显示数组的10个值
initial begin
for(i=0; i<10; i=i+1)
$display("%d: %h", i, mem_test[i]);
end
 
endmodule

仿真结果如下:

从地址2开始依次被赋值00~07,而地址0和地址1则仍保持未赋值状态。

使用方法3:同时指定起始地址和结束地址

即$readmemh ("<数据文件名>",<数组名>,<起始地址>,<结束地址>),此时会将从数据文件中读到的第1个数据填入数组的起始地址,此后类推,直到指定的终结地址对应的数组也被赋值。处于起始地址和终结地址构成的区间范围外的地址对应的数组则不会被赋值。如果数据的个数大于数据文件中数据的个数,则数组无法被填满,未被填满的部分则依然是未知状态。

指定数据从数组的地址2开始赋值,直到地址8终结,则地址2应该被赋值0,地址3被赋值1,···等等,直到地址8也被赋值。而地址0、1、9则仍保持未赋值状态:

`timescale 1ns / 1ns
 
module tb_read_test();
 
integer i; 
reg [7:0] mem_test [9:0];//mem_test是位宽8bit,个数为10的数组
 
initial $readmemh("D:/read_test/read_test.srcs/sim_1/new/data.txt",mem_test,2,8);//绝对路径,从地址2开始
 
//显示数组的10个值
initial begin
for(i=0; i<10; i=i+1)
$display("%d: %h", i, mem_test[i]);
end
 
endmodule

仿真结果如下:

从地址2开始直到地址8依次被赋值00~06,而地址0、1、9则仍保持未赋值状态。

9,parameter、localparam的区别和用法

一、区别

parameter: 可以在实例化时修改参数值

localparam:只能在当前模块使用,不能进行实例化

二、用法

2.1 设计文件中parameter的用法

直接在模块名后面 #(parameter 参数名=参数值)

2.2 例化模块时parameter的用法

在模块名后面直接 #(.参数名 (参数值))

实列操作

需求1:

雷码转换设计的仿真测试结果写入txt文本

使用绝对路径(注意绝对路径下的文件夹命名都要遵循verilog变量命名规范)

需求分析:

1,创建文件夹,创建文件

2,将内容写入文件

3,关闭文件

`timescale 1ns/1ps
module testbench_top();


//参数定义
 `define CLK_PERIORD 20    

 
//接口申明
reg i_clk;
reg i_rst_n;
reg i_en;
reg[9:0] i_data;
wire o_vld;    //有效信号
wire[15:0] o_data;

vlg_design vlg_design_inst (
    .i_clk(i_clk),
    .i_rst_n(i_rst_n),
    .i_en(i_en),
    .i_data(i_data),
    .o_vld(o_vld),
    .o_data(o_data) 
    );        
    
integer i;

initial  begin
i_en <= 0;
i_clk <= 0;
i_rst_n <= 0;
i_data <= 0;
#2000;
i_rst_n <= 1;
end

always #(`CLK_PERIORD/2) i_clk = ~i_clk;

//产生激励
initial begin
    @(posedge i_clk);
    @(posedge i_rst_n);    
    i_en <= 1;
    @(posedge i_clk);    
    for (i = 1;i <= 1024;i = i+1) begin
        i_data <= i;
        @(posedge i_clk);
    end
    @(posedge i_clk);
    i_en <= 0;
    #50_000;
    $fclose(handle1);  //关闭文件
    $stop;
end

//实时显示,并写入文件
always@(posedge i_clk) begin
    if(o_vld) begin
        $display("%d",o_data);
        $fdisplay(handle1,"%d",o_data);  //往handle1 句柄的文件中写入文件
    end
    else ; 
end
//创建file_test1.txt 文件
integer   handle1; //定义句柄1
initial begin
  //以w类型(写)的方式来打开文件,并将其返回值赋给handle1  
  //使用绝对路径(注意绝对路径下的文件夹命名都要遵循verilog变量命名规范)
  //注意绝对路径的文件夹要存在,文件可以新生成,即先手动新建outputfile 文件夹
  handle1 = $fopen("./outputfile/file_test1.txt","w");   
end

endmodule

需求2:

txt文本文件中8位格雷码数据的读取与使用

/
//EDA工具平台:Vivado 2019.1 + ModelSim SE-64 10.5 
//开发套件型号: STAR 入门FPGA开发套件
//版   权  申   明: 本例程由《深入浅出玩转FPGA》作者“特权同学”原创,
//                仅供特权同学相关FPGA开发套件学习使用,谢谢支持
//官方淘宝店铺: http://myfpga.taobao.com/
//微 信 公 众 号:“FPGA快乐学习”
//                欢迎关注,获取更多更新的FPGA学习资料 
/
`timescale 1ns/1ps

module testbench_top();
    

//参数定义

`define CLK_PERIORD        10        //时钟周期设置为10ns(100MHz)    
parameter GRAY_MSB    = 7;



//接口申明
    
reg clk;
reg rst_n;
reg i_en;
reg[GRAY_MSB:0] i_data;
wire o_vld;
wire[GRAY_MSB:0] o_gray;

    
//对被测试的设计进行例化
    
vlg_design    #(
    .MSB(GRAY_MSB)
)    
uut_vlg_design(
    .i_clk(clk),
    .i_rst_n(rst_n),
    .i_en(i_en),
    .i_data(i_data),
    .o_vld(o_vld),
    .o_gray(o_gray)
    );    
    

//复位和时钟产生

    //时钟和复位初始化、复位产生
initial begin
    clk <= 0;
    rst_n <= 0;
    #1000;
    rst_n <= 1;
end
    
    //时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;


//文本文件的读取
reg[7:0] data_mem[255:0];

initial $readmemb("./input_file/8bit_grayencode.txt",data_mem);
    


//测试激励产生

initial begin
    i_en <= 'b0;
    i_data <= 'b0;
    $display("The value of GRAY_MSB is %0d",GRAY_MSB);
    @(posedge rst_n);    //等待复位完成
    
    @(posedge clk);
    i_en <= 'b1;
    i_data <= 'b0;    
    
    repeat(2**(GRAY_MSB+1)-1) begin
        @(posedge clk);
        i_en <= 'b1;
        i_data <= i_data+1;
    end
    @(posedge clk);
    i_en <= 'b0;
    #100;
    
    //$fclose(wfile);
    
    $stop;
end

/*integer wfile;

initial begin
    wfile = $fopen("./output_file/result_data.txt","w");
end*/

integer cnt;

always @(posedge clk) begin
    if(!rst_n) cnt <= 0;
    else if(o_vld) cnt <= cnt+1;
end

always @(posedge clk) begin
    if(o_vld) $display("%b\n%b\n\n",o_gray,data_mem[cnt]);
end
endmodule

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【计算机组成与体系结构Ⅱ】多处理器部分讨论题目

多处理机课堂讨论 1.并行计算体系结构有哪些? SIMD、MIMD 2.多处理机的存储结构有哪些? 对称式共享存储器结构、分布式共享存储结构 3.什么是多处理机的一致性? 如果对某个数据项的任何读操作均可得到其最新写入的值&#xff0c;则认为这个存储系统是一致的。 4.监听协议的工…

vivado 时间约束窗口

时间约束窗口 “时序约束”窗口仅适用于“合成”和“实施”设计。对于详细的设计约束&#xff0c;您必须直接使用和编辑XDC文件。欲了解更多信息&#xff0c;请参见创建合成约束。可以使用以下三个选项之一打开“计时约束”窗口&#xff0c;如图所示如下图所示&#xff1a; •…

ES-组合与聚合

ES组合查询 1 must 满足两个match才会被命中 GET /mergeindex/_search {"query": {"bool": {"must": [{"match": {"name": "liyong"}},{"match_phrase": {"desc": "liyong"}}]}}…

鼠标点击展开详情

网页部分&#xff1a; HTML部分&#xff1a; <body><br><div id"nav"><div id"dang"></div><ul id"aaa"><li class"a1"><img src"img/U011.jpg" width"195" heig…

鸿蒙南向开发环境的搭建

在嵌入式开发中&#xff0c;很多开发者习惯于使用Windows进行代码的编辑&#xff0c;比如使用Windows的Visual StudioCode进行OpenHarmony代码的开发。但当前阶段&#xff0c;大部分的开发板源码还不支持在Windows环境下进行编译&#xff0c;如Hi3861、Hi3516系列开发板。因此&…

论文阅读:Learning sRGB-to-Raw-RGB De-rendering with Content-Aware Metadata

论文阅读&#xff1a;Learning sRGB-to-Raw-RGB De-rendering with Content-Aware Metadata Abstract 大多数的 Camera ISP 会将 RAW 图经过一系列的处理&#xff0c;变成 sRGB 图像&#xff0c;ISP 的处理中很多模块是非线性的操作&#xff0c;这些操作会破坏环境光照的线性…

MySQL 常用数据类型总结

面试&#xff1a; 为什么建表时,加not null default ‘’ / default 0 答:不想让表中出现null值. 为什么不想要的null的值 答:&#xff08;1&#xff09;不好比较,null是一种类型,比较时,只能用专门的is null 和 is not null来比较. 碰到运算符,一律返回null &#xff08…

了解如何在linux使用podman管理容器

本章主要介绍使用 podman 管理容器。 了解什么是容器&#xff0c;容器和镜像的关系 安装和配置podman 拉取和删除镜像 给镜像打标签 导出和导入镜像 创建和删除镜像 数据卷的使用 管理容器的命令 使用普通用户管理容器 使用普通用户管理容器 对于初学者来说&#xff0c;不太容…

MySQL笔记-第09章_子查询

视频链接&#xff1a;【MySQL数据库入门到大牛&#xff0c;mysql安装到优化&#xff0c;百科全书级&#xff0c;全网天花板】 文章目录 第09章_子查询1. 需求分析与问题解决1.1 实际问题1.2 子查询的基本使用1.3 子查询的分类 2. 单行子查询2.1 单行比较操作符2.2 代码示例2.3 …

【51单片机系列】直流电机使用

本文是关于直流电机使用的相关介绍。 文章目录 一、直流电机介绍二、ULN2003芯片介绍三、在proteus中仿真实现对电机的驱动 51单片机的应用中&#xff0c;电机控制方面的应用也很多。在学习直流电机(PWM)之前&#xff0c;先使用GPIO控制电机的正反转和停止。但不能直接使用GPIO…

Android---Kotlin 学习006

数字类型 和 java 一样&#xff0c;Kotlin 中所有数字类型都是有符号的&#xff0c;也就是说既可以表示正数&#xff0c;也可以表示负数。 安全转换函数 与 java 不一样&#xff0c;kotlin 提供了 toDoubleOrNull 和 toIntOrNull 这样的安全转换函数&#xff0c;如果数值不能…

FL Studio终身永久2024中文版下载安装详细操作图文步骤教程

FL Studio2024版是一款在国内非常受欢迎的多功能音频处理软件&#xff0c;我们可以通过这款软件来对多种不同格式的音频文件来进行编辑处理。而且FL Studio 2024版还为用户们准备了超多的音乐乐器伴奏&#xff0c;我们可以直接一键调取自己需要的音调。 FL Studio 2024版不仅拥…

早上好,我的leetcode 【hash】(第二期)

写在前面&#xff1a;坚持才是最难的事情 C代码还是不方便写&#xff0c;改用python了&#xff0c;TAT 文章目录 1.两数之和49. 字母异位词分组128.最长连续序列 1.两数之和 你好&#xff0c;梦开始的地方~ https://leetcode.cn/problems/two-sum/description/?envTypestudy…

PMP项目管理 - 采购管理

系列文章目录 PMP项目管理 - 质量管理 PMP项目管理 - 采购管理 PMP项目管理 - 资源管理 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. PMP项目管理 -…

Next.js加载异步组件 骨架屏

Next.js 中有两种处理页面加载的方式&#xff0c;一种是 Loading UI 一种是 Streaming。接下来我将介绍这两种的区别&#xff0c;以及实际的业务场景。 当我们进入某个页面时&#xff0c;需要获取页面数据&#xff0c;可能是从数据库读取也有可能是 API 服务&#xff0c;总之这…

Linux---进程概念

目录 一、冯诺依曼体系结构 二、操作系统 1.关于下三层的理解 2.关于上三层的理解 三、进程 1.进程(也叫做任务)对应的标识符---pid 2.fork---用代码创建进程(系统接口) 1&#xff09;初步认识一下fork 2&#xff09;fork函数的返回值 3&#xff09;fork的原理 问题1…

残差网络中的BN (Batch Normalization 批标准化层)的作用是什么?

文章目录 什么是BN &#xff08;Batch Normalization 批标准化层&#xff09;一、BN层对输入信号进行以下操作:二、BN 层有什么作用&#xff1f; 什么是BN &#xff08;Batch Normalization 批标准化层&#xff09; BN层的全称是Batch Normalization层,中文可以翻译为批标准化…

[Big Bird]论文解读:Big Bird: Transformers for Longer Sequences

文章目录 1 介绍2 模型架构3 结果 论文&#xff1a;Big Bird: Transformers for Longer Sequences 作者&#xff1a;Manzil Zaheer, Guru Guruganesh, Avinava Dubey, Joshua Ainslie, Chris Alberti, Santiago Ontanon, Philip Pham, Anirudh Ravula, Qifan Wang, Li Yang, Am…

多维时序 | MATLAB实现RIME-LSSVM【23年新算法】基于霜冰优化算法(RIME)优化最小二乘向量机(LSSVM)多变量时间序列预测

多维时序 | MATLAB实现RIME-LSSVM【23年新算法】基于霜冰优化算法(RIME)优化最小二乘向量机(LSSVM)多变量时间序列预测 目录 多维时序 | MATLAB实现RIME-LSSVM【23年新算法】基于霜冰优化算法(RIME)优化最小二乘向量机(LSSVM)多变量时间序列预测预测效果基本介绍模型描述程序设…

【最新版】在WSL上运行 Linux GUI (图形用户界面)应用(Gnome 文本编辑器、GIMP、Nautilus、VLC、X11 应用)

文章目录 一、 安装WSL1. 全新安装2. 现有 WSL 安装 二、运行 Linux GUI 应用1. 更新发行版中的包2. 安装 Gnome 文本编辑器启动 3. 安装 GIMP启动 4. 安装 Nautilus启动 5. 安装 VLC启动 6. 安装 X11 应用 适用于 Linux 的 Windows 子系统 (WSL) 现在支持在 Windows 上运行 Li…