[SV] 文件操作

转载https://blog.csdn.net/lbt_dvshare/article/details/132004995

Verilog 提供了很多对文件进行操作的系统任务。经常使用的系统任务主要包括:

  • 文件开、闭:​$fopen​, ​$fclose​, ​$ferror
  • 文件写入:​$fdisplay​, ​$fwrite​, ​$fstrobe​, ​$fmonitor
  • 字符串写入:​$sformat​, ​$swrite
  • 文件读取:​$fgetc​, ​$fgets​, ​$fscanf​, ​$fread
  • 文件定位:​$fseek​, ​$ftell​, ​$feof​, ​$frewind
  • 存储器加载:​$readmemh​, ​$readmemb

使用文件操作任务(尤其注意 ​$sforamt​, ​$gets​, ​$sscanf​ 等)对文件进行操作时,需要根据文件性质和变量内容确定使用哪一种系统任务,并保证参数及读写变量类型与文件内容的一致性,不要将字符串类型和多进制类型相混淆。

文件open/close
系统任务调用格式任务描述
文件打开fd = $fopen("fname", mode) ;fname 为打开文件的名字
fd 为返回的 32bit 文件描述符
--- 正确打开时,fd 为非零值
--- 打开出错时,fd为零值
mode 用于指定文件打开的方式
文件关闭$fclose(fd) ;关闭 fd 描述的对应文件
文件错误err = $ferror(fd, str) ;正常打开文件时:
--- err 与 str 均为零值,
打开文件出错时:
--- err 返回非零值表示错误
--- str 返回非零值存储错误类型
--- 官方建议 str 长度为 640bit 位宽


    
    
  1. integer fd1, fd2 ;
  2. integer err1, err2 ;
  3. reg [ 320: 0] str1, str2 ; //错误类型的变量也可以为可支持的 string 类型
  4. initial begin
  5. //existing file
  6. fd1 = $ fopen( "./DATA_RD.HEX", "r"); //打开存在的文件
  7. err1 = $ ferror(fd1, str1);
  8. $ display( "File1 descriptor is: %h.", fd1 ); //非零值
  9. $ display( "Error1 number is: %h.", err1 ); //0
  10. $ display( "Error2 info is: %s.", str1 ); //0
  11. $ fclose(fd1);
  12. //not existing file
  13. fd2 = $ fopen( "../../FILE_NOEXIST.HEX", "r"); //打开的文件不存在
  14. err2 = $ ferror(fd2, str2);
  15. $ display( "File2 descriptor is: %h.", fd2 ); //0
  16. $ display( "Error2 number is: %h.", err2 ); //非零值
  17. $ display( "Error2 info is: %s.", str2 ); //非零值
  18. $ fclose(fd2);
  19. end

运行结果:

 fd = $fopen("fname", mode) 中 mode 类型及其描述如下:

r只读打开一个文本文件,只允许读数据。
w只写打开一个文本文件,只允许写数据。如果文件存在,则原文件内容会被删除。如果文件不存在,则创建新文件。
a追加打开一个文本文件,并在文件末尾写数据。如果文件如果文件不存在,则创建新文件。
rb只读打开一个二进制文件,只允许读数据。
wb只写打开或建立一个二进制文件,只允许写数据。
ab追加打开一个二进制文件,并在文件末尾写数据。
r+读写打开一个文本文件,允许读和写
w+读写打开或建立一个文本文件,允许读写。如果文件存在,则原文件内容会被删除。如果文件不存在,则创建新文件。
a+读写打开一个文本文件,允许读和写。如果文件不存在,则创建新文件。读取文件会从文件起始地址的开始,写入只能是追加模式。
rb+读写打开一个二进制文本文件,功能与 "r+" 类似。
wb+读写打开或建立一个二进制文本文件,功能与 "w+" 类似。
ab+读写打开一个二进制文本文件,功能与 "a+" 类似。
文件写入
调用格式任务描述
$fdisplay(fd, arguments) ;按顺序或条件写文件,自动换行
$fwrite(fd, arguments) ;按顺序或条件写文件,不自动换行
$fstrobe(fd, arguments) ;语句执行完毕后选通写文件
$fmonitor(fd, arguments) ;只要数据有变化就写文件

    
    
  1. integer fd ;
  2. integer err, str ;
  3. initial begin
  4. fd = $ fopen( "./DATA_RD.HEX", "a+"); //末尾追加的方式打开
  5. err = $ ferror(fd, str);
  6. if (!err) begin
  7. $ fdisplay(fd, "New data1: %h", fd) ;
  8. $ fdisplay(fd, "New data2: %h", str) ;
  9. $ fdisplay(fd, "New data3: %h", err) ;
  10. //$write(fd, "New data3: %h", err) ; //最后一行不换行打印
  11. end
  12. $ fclose(fd);
  13. end
文件读取
系统任务 调用格式及说明
 按字符读文件 c = $fgetc( fd ) ;
 按字符格式将 fd 数据输出给变量 c,c 位宽最少为 8 读取错误时 c 值为 EOF(-1),可以用 $ferror 检查错误类型
 按字符写缓冲区 code = $ungetc(c, fd ) ;
 向文件 fd 缓冲区写字符 c c 值在下次调用 $fgetc 时返回,文件 fd 自身内容不会发生变化 正常写缓冲时返回值 code 为 0,发生错误时返回值 code 为 EOF
 按行读文件 code = $fgets(str, fd)
 按字符连续读,直至变量 str 被填满,或一行内容读取完毕,或文件结束 正常读取时返回值 code 为读取行数(次数),发生错误时 code 为 0
 按格式读文件 code = $fscanf(fd, format, args) ;
 按格式 format 将文件 fd 中的数据读取到变量 args 中 format 可参考 $display 指定格式说明 读取一次的停止条件为空格或换行 读取发生错误时返回值 code 为 0
 按格式读字符串 code = $sscanf(str, format, args) ;
 按格式 format 将字符串型变量 str 读取到变量 args 中 调用格式方法和 $fscanf 一致
 按二进制读文件 code = $fread(store, fd, start, count) ;
 按二进制数据流格式将数据从文件 fd 读取到数组或寄存器变量 store 中 start 为文件起始地址,count 为读取长度 若 start/count 未指定,数据会全部填充至变量 store 中 若 store 为寄存器类型,则 start/count 参数无效,store 变量填充满一次数据后便会停止读取
$fgetc 例子

    
    
  1. integer i ;
  2. reg [ 31: 0] char_buf ;
  3. initial begin
  4. # 30 ;
  5. fd = $ fopen( "DATA_RD.HEX", "r");
  6. $ write( "Read char: ");
  7. err = $ ferror(fd, str);
  8. if (!err) begin
  9. for (i=0; i<13; i++) begin
  10. char_buf[7:0] = $ fgetc(fd) ; //按单个字符读取
  11. $ write( "%c", char_buf[ 7: 0]) ; //不换行逐次打印单个字符
  12. end
  13. $ write( ".\n") ;
  14. end
  15. end
$fgets 例子

    
    
  1. integer fd ;
  2. integer code ;
  3. reg [ 99: 0] line_buf [ 9: 0] ;
  4. initial begin
  5. # 31 ;
  6. fd = $ fopen( "DATA_RD.HEX", "r");
  7. err = $ ferror(fd, str);
  8. if (!err) begin
  9. for (i=0; i<6; i++) begin //按字符串格式逐行读取
  10. code = $ fgets(line_buf[i], fd) ; //末尾含"\n",将打印2行
  11. $ display( "Get line data%d: %s", i, line_buf[i]) ;
  12. end
  13. end
  14. //十六进制显示,将显示对应的 ASCIII 码字
  15. $ display( "Show hex line data%d: %h", 2, line_buf[ 2]) ;
  16. $ display( "Show hex line data%d: %h", 4, line_buf[ 4]) ;
  17. $ fclose(fd) ;
  18. end
$fscanf

    
    
  1. reg [ 31: 0] data_buf [ 9: 0] ;
  2. reg [ 63: 0] string_buf [ 9: 0] ;
  3. reg [ 31: 0] data_get ;
  4. reg [ 63: 0] data_test ;
  5. initial begin
  6. fd = $ fopen( "DATA_RD.HEX", "r");
  7. err = $ ferror(fd, str);
  8. if (!err) begin
  9. for (i=0; i<4; i++) begin
  10. //前4行数据按照十六进制读取和显示
  11. code = $ fscanf(fd, "%h", data_buf[i]);
  12. $ display( "$fscanf read data%d: %h", i, data_buf[i]) ;
  13. end
  14. for (i=4; i<6; i++) begin
  15. //后2行数据按照字符串类型读取和显示
  16. code = $ fscanf(fd, "%s", string_buf[i]);
  17. $ display( "$fscanf read data%d: %s", i, string_buf[i]) ;
  18. end
  19. end
  20. end
文件定位
系统任务调用格式任务描述
获取文件位置pos = $ftell( fd ) ;返回文件当前位置距离文件首部的偏移量,初始地址为 0
偏移量按照字节为一单位(8bits)
配合 $fseek 使用
重定位code = $fseek(fd, offset, type) ;设置文件下一个输入或输出的位置
offset 为设置的偏移量
type 为偏移量的操作类型
--- 0: 设置位置到偏移地址
--- 1: 设置位置到当前位置加偏移量
--- 2: 设置位置到文件尾加偏移量,经常使用负数来表示文件尾向前的偏移量
无偏移重定位code = $rewind( fd ) ;等价于 $fseek( fd, 0, 0) ;
判断文件尾部code = $feof(fd) ;判读是否到文件尾部
检测到文件尾部时返回值为 1,否则为 0

    
    
  1. reg [ 31: 0] data4 ; //寄存器变量长度为 4bytes
  2. reg [ 199: 0] str_long ;
  3. integer pos ;
  4. initial begin
  5. # 40 ;
  6. fd = $ fopen( "DATA_RD.HEX", "r");
  7. err = $ ferror(fd, str);
  8. if (!err) begin
  9. //first read
  10. code = $ fscanf(fd, "%h", data4); //从0位置开始读
  11. pos = $ ftell(fd); //读8byte后位置为8,坐标为(0,8)
  12. $ display( "Position after read: %d", pos) ;
  13. $ display( "1st read data: %h", data4) ;
  14. //type = 0
  15. code = $ fseek(fd, 4, 0) ; //从位置4、坐标(0,4)开始读
  16. code = $ fscanf(fd, "%h", data4); //读到换行符停止
  17. pos = $ ftell(fd); //读4byte后位置为8,坐标为(0,8)
  18. $ display( "type 0: current position: %d", pos) ;
  19. $ display( "type 0: read data: %h", data4) ;
  20. //type = 1
  21. code = $ fseek(fd, 4, 1) ; //从位置4+9=12、坐标(1,3)据开始读
  22. code = $ fscanf(fd, "%h", data4); //读到换行符停止
  23. pos = $ ftell(fd); //读5byte后位置为17,坐标为(1,8)
  24. $ display( "type 1: current position: %d", pos) ;
  25. $ display( "type 1: read data: %h", data4) ;
  26. //type = 2
  27. code = $ fseek(fd, -( 96 -31), 2) ; //从位置31、坐标(3,4)开始读
  28. code = $ fscanf(fd, "%h", data4);
  29. pos = $ ftell(fd); //读4byte后位置为35,坐标为(3,8)
  30. $ display( "type 2: current position: %d", pos) ;
  31. $ display( "type 2: read data: %h", data4) ;
  32. //rewind read
  33. code = $ rewind(fd) ; //重新将文件指针的位置指向文件首部
  34. pos = $ ftell(fd); //此时位置为 0
  35. $ display( "Position after $rewind: %d", pos) ;
  36. //read all content of file
  37. while (!$ feof(fd)) begin
  38. code = $ fgets(str_long, fd);
  39. $ write( "Read : %s", str_long) ;
  40. end
  41. $ fclose(fd) ;
  42. end
  43. end
加载存储器
系统任务调用格式及说明
加载十六进制文件$readmemh("fname", mem, start_addr, finish_addr)
fname 为数据文件名字
mem 为数组型/存储器型变量
start_addr、finish_addr 分别为起始地址和终止地址
start_addr、finish_addr 可以省略,此时加载数据的停止条件为存储器变量 mem 被填充完毕,或文件读取完毕
文件内容只应该有空白符(或换行、空格符)、二进制或十六进制数据
注释用"//"进行标注,数据间建议用换行符区分
加载二进制文件$readmemb("fname", mem, start_addr, finish_addr)
用法格式同 $readmemb

ref : Verilog 文件操作-$fseek,$ftell,$feof - 芯片天地 (ica123.com)

</article>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Verilog是一种硬件描述语言,用于编写数字电路的模型和设计。.sv文件是Verilog文件的扩展名,用于存储Verilog代码。 Verilog是一种像C语言的文本语言,在工程师和设计者之间非常流行。它可用于描述数字逻辑、存储器、控制单元、以及其他电子系统的行为。通过使用Verilog,设计者可以创建高层次的设计,并将其转换为实现在FPGA、ASIC等硬件上的形式。 .sv文件是存储Verilog代码的文件。它通常包含模块定义、端口声明、内部信号定义和时序逻辑等内容。在.sv文件中,设计者可以定义模块的行为,并描述其在特定输入条件下的输出。.sv文件也包含了各种硬件原语和逻辑门的描述,供设计者使用。 在.sv文件中,设计者可以使用各种建模技术来模拟硬件电路的功能。这些技术包括行为建模、结构建模和数据流建模等。行为建模描述了模块的逻辑行为,它定义了在不同输入条件下模块的输出。结构建模描述了模块的组成结构,例如使用逻辑门和触发器等。数据流建模描述了数据的流动和操作,它定义了模块的数据传输和处理。 通过编写Verilog代码并保存为.sv文件,设计者可以使用EDA(Electronic Design Automation)工具将其合成为实际的硬件电路。设计者还可以使用仿真工具,如ModelSim和Xilinx Vivado等,对Verilog代码进行验证和调试。.sv文件是实现硬件设计的关键文件,它提供了一种有效的方式来编写和管理Verilog代码。 ### 回答2: Verilog .sv文件是指Verilog硬件描述语言(HDL)的源代码文件,其中包含了用于描述数字电路行为和结构的语句和模块定义。 Verilog是一种硬件描述语言,它以模块化的方式描述数字电路,可以用于设计各种不同的电子系统,例如处理器、ASIC、FPGA、芯片等。.sv文件是一种常见的Verilog代码文件格式,以.sv文件扩展名。 一个典型的.sv文件由以下几个部分组成: 1. 模块定义:.sv文件通常包含了一个或多个模块定义。模块是Verilog代码的基本单元,用于描述电路的行为或结构。每个模块都有一个唯一的名字和输入输出端口。 2. 输入输出定义:在模块定义中,会声明输入输出端口,它们定义了模块与其他模块或外部环境之间的接口。输入输出端口可以是信号线、寄存器或者其他符号。 3. 内部信号定义:在模块内部,可以定义内部信号来辅助实现电路功能。内部信号可以是寄存器、线网或者是其他变量。 4. 语句和逻辑:.sv文件中的语句用于描述电路的行为,可以包括逻辑操作、条件语句、循环语句、复位和时钟控制、以及其他硬件描述语言的特性。 5. 子模块实例化:在.sv文件中,可以实例化和连接其他模块以构建复杂的电路。这些子模块可以是已有的标准模块,也可以是自定义的模块。 6. 模块层次结构:.sv文件可以通过模块的层次结构来组织代码,使其更加清晰和易读。 总的来说,Verilog .sv文件为设计人员提供了一种描述数字电路的方式,通过定义模块、输入输出端口以及内部信号,并编写相应的逻辑和语句,可以实现各种电子系统的功能。 ### 回答3: Verilog是一种硬件描述语言,主要用于描述数字逻辑电路的结构和行为。.sv文件是Verilog源代码文件的一种常见扩展名。 在Verilog .sv文件中,我们可以使用模块的层次结构来描述数字逻辑电路。一个模块可以包含其他模块或基本的逻辑元件,如与门、或门、非门等。每个模块可以具有输入端口和输出端口,用于与外部环境或其他模块进行信号交互。 在.sv文件中,我们可以使用关键字“module”声明一个模块,并指定模块的输入和输出端口。我们可以给模块起一个名字,并在模块的内部定义逻辑结构。 在模块内部,我们可以使用关键字“input”和“output”定义输入和输出端口。同时,我们还可以使用“wire”或“reg”关键字定义内部信号或寄存器。我们可以使用逻辑门和其他模块来连接这些内部信号。 在.sv文件中,我们可以使用“assign”关键字来连接信号和端口。我们可以使用逻辑运算符(如与、或、非等)或位运算符(如位与、位或、位异或等)来定义各个信号之间的逻辑关系。 除了模块的层次结构和逻辑描述,.sv文件还可以包含一些其他的属性定义和约束条件。我们可以使用“parameter”关键字定义一些常量值,以便在整个设计中进行重用。我们还可以使用“always”关键字定义一个always块,用于描述时序逻辑和状态机的行为。 总之,Verilog .sv文件是用于描述数字逻辑电路的一种源代码文件。它可以帮助工程师们对电路进行建模、仿真和综合。通过Verilog .sv文件,我们可以清晰地描述电路的结构和行为,从而实现对电路的设计和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值