VHDL 93TextIO

在编写testbench时,我们会用到一些VHDL语言,这些语言是我们不常用的,甚至以前没有见过的,但是在testbench中他们却是被经常用到,而且对我们的仿真编写非常有用。今天我们就来简单讲一下常用的几个VHDL句法。

一、文件I/O

上节讲了,在testbench常将数据写入文件,或者从文件读入数据等,这都需要用到VHDL语言中与文件打交道的语言,即是常说的file I/O. 这里强调两点:文件I/O语言是不能被综合的,文件I/OFPGAI/Opin是两回事。

根据存在文件中数据的不同,文件有多种类型,存入的数据可以是integer ,string,std_logic_vector 等等,但是定义时有区别,后面会说到。

对文件的操作有,定义文件,打开文件,从文件中读取数据,写入数据到文件等。

一、定义文件。

文件有两个大的类型,integer:文件中的数据是以二进制存取的,不能被人识别,只有integer型的数据能够存入这类文件。string:文件是以可以读取的ASCII码,可以被人识别,integer ,bit_vector(x downto x),string(x downto 1)std_logic_vector(x downto 0) ,bit等都可以被存入此类文件。

定义语法 file filein:text; type integerfile is file of integer; file filein:integerfile;

二、打开文件。

86版的VHDL在定义文件时即将文件隐式的打开了,这里我们讲93版的文件打开语句。

在上一步定义了文件句柄后就可以在程序中打开指定文件,同时指定打开模式。

file_open(fstatus,file file_handle:file_type, filename:string,openmode)

fstatus指示当前文件状态,但是在使用前首先得定义一名variable fstatus:FILE_OPEN_STATUS;,一般有OPEN_OK,STATUS_ERROR,NAME_ERROR,MODE_ERROR四种状态。

file_handle即是上一步定义的文件类型的句柄filein.

filename是以双隐号括起的文件名,如"datain.txt";

openmode是指打开该文件的模式,文件打开有read_mode,write_mode,append_mode三种。

三、读写文件。

在上一步以什么模式打开,该步就可以对文件进行操作了,当上一步打开文件后,就可以用read(file_handle,value:type) write(file_handle,value:type)向文件读写数据了,但是这里特别注意,如果直接使用这两个语句,你只能向文件中写入指定类型的数据,如integer类型的只能写入integer型数据,text型只能写入string的数据,而不是像第二步说的那么多类型,要想写入其他类型必须遵守以下操作步骤!

1)定义line型变量 variable buf:line,(2)将需要写入的数据写入line变量 write(buf,value)(这里的value就可以多种值),(3)line变量把数据写入文件 writeline(file_handle,buf)。一定要按前后顺序来操作。

四、文件关闭。

  在文件读写完毕后记得关闭文件file_close(file_handle),当然在文件操作中还有一个函数在反映是否读取到文件末尾ENDFILE(file_handle) 如果到达文件末尾将返回真(ture)否则返回假(false);

笔记:这里还要补充两种特殊的文件,input,output,也可以是“STD_INPUT","STD_OUTPUT"其实他们都是代表modelsim中的控制台,input和”STD_INPUT"就是从控制台输入数据,output "STD_OUTPUT"就是输出数据到控制台。后面两种格式要做为文件打开,前面一种可以直接作为文件句柄操作。如 file_open(fstatus,file_out,"STD_OUTPUT",write_mode); readline(output,buf);

同时有两个比较有用的写入语句 write(file_out,string'("hello")) write(file_out,bit_vector'(110"));

我们做了一个最完全的例子,将以上所有的操作包括进去,写了一个testbench,附录到下一节,同时将输出信息与被操作文件信息附录到图片,欢迎在下一节中获取源代码。

声明:以上操作均是基于VHDL1993版本!

 

 

 

TEXTIO VHDL 仿真与磁盘文件之间架起了桥梁,使用文本文件扩展VHDL 的仿真功能。本文介绍TEXTIO 程序包,以一个加法器实例说明TEXTIO 的使用方法,最后使用ModelSim 对设计进行仿真,并分析仿真结果。

  在对VHDL 源程序进行仿真时,由于有的输入输出关系仅仅靠输入波形或编写testbench 中的信号输入是难以验证结果正确性的,例如,设计8 位加法器,如果将所有的输入都验证一遍,是非常麻烦的,因为要全面判断输出是否正确需要一个个的验证。此外,若用VHDL 设计一个处理器,需要读入指令,这时候采用文本文件非常必要。   

  TEXTIO 提供了VHDL 仿真时与磁盘文件的交互。在验证加法器时候,可以将所有输入保存在一个文本文件中,将其它软件计算出的结果保存在另外的文件中。在VHDL 仿真时,可以直接读取输入文件作为设计的输入参数,并自动将结果与事先保存的文件相比较,给出一定的信息来确定结果的正确与否。在对VHDL 编写的处理器调试时,可以将包括指令类型、源地址、目标地址在内的指令保存成文本文件,利用TEXTIO 来读取这些指令。同时,将结果及中间变量保存成文本文件,以事后判断是否正确及便于查找原因。   

  由于TEXTIO 的文本输入输出功能非常有限,一些公司提供了扩展其功能的程序包,例如std_developerskit库中的std_iopak 程序包。在本文中,仅仅对TEXTIO 程序包做简单的介绍及其简单的使用。

  1 TEXTIO介绍   

  TEXTIO VHDL 标准库STD 中的一个程序包(Package)。在该包中定义了三个类型:LINE 类型、TEXT类型以及SIDE 类型。另外,还有一个子类型(subtypeWIDTH。此外,在该程序包中还定义了一些访问文件所必须的过程(Procedure)。

  1.1 类型定义

  (1)type LINE is access string   

  定义了LINE 为存取类型的变量,它表示该变量是指向字符串的指针,它是TEXTIO 中所有操作的基本单元。读文件时,先按行(LINE)读出一行数据,再对LINE 操作来读取各种数据类型的数据;写文件时,先将各种的数据类型组合成LINE,再将LINE 写入文件。在用户使用时,必须注意只有变量才可以是存取类型,而信号则不能是存取类型。例如,我们可以定义

  variable DLine : LINE;

  但不能定义成

  signal DLine : LINE;

  (2)type TEXT is file of string

  定义了TEXT ASCII 文件类型。定义成为TEXT 类型的文件是长度可变的ASCII 文件。例如在TEXTIO 中定义了两个标准的文本文件。

  file input : TEXT open read_mode is"STD_INPUT"

  file output : TEXT open write_mode is"STD_OUTPUT"

 

  定义好以后,就可以通过文件类型变量input output 来访问其对应的文件STD _ INPUT STD_OUTPUT

需要注意的是VHDL'87 VHDL'93 在使用文件方面有较大的差异,在编译时注意选中对应的标准。

  (3)type SIDE is (right,left)

  定义了SIDE 类型。表示定义了一个名为SIDE 的数据类型,其中只能有两种状态,即right left,分别表示将数据从左边还是右边写入行变量。该类型主要是在TEXTIO 程序包包含的过程中使用。

  (4)subtype WIDTH is natural

  定义WIDTH 为自然数的子类型。所谓子类型表示其取值范围是父类型范围的子集。

  1.2 过程定义

  TEXTIO 提供了基本的用于访问文本文件的过程。类似于C++,VHDL 提供了重载功能,即完成相近功能的不同过程可以有相同的过程名,但其参数列表不同,或参数类型不同或参数个数不同。

  TEXTIO 提供的基本过程有:

  procedure READLINE(文件变量;行变量);用于从指定文件读取一行数据到行变量中。

  procedure WRITELINE(文件变量;行变量);用于向指定文件写入行变量所包含的数据。

  procedure READ(行变量;数据类型);用于从行变量中读取相应数据类型的数据。

  根据参数数据类型及参数个数的不同,有多种重载方式,TEXTIO 提供了bitbit_vector BOOLEAN character、 integerrealstringtime数据类型的重载。同时,提供了返回过程是否正确执行的BOOLEAN 数据类型的重载。例如,读取整数的过程为

  procedure READ(L:inout LINE; VALUE: out integer; GOOD: out BOOLEAN);

  其中,GOOD 用于返回过程是否正确执行,若正确执行,则返回TRUE

  procedure WRITE(行变量; 数据变量; 写入方式; 位宽);

  该过程将数据写入行变量。其中写入方式表示写在行变量的左边还是右边,且其值只能为left right,位宽表示写入数据时占的位宽。例如:

  write(OutLine,OutData,left,2);

  表示将变量OutData 写入LINE 变量OutLine 的左边占2 个字节。

  2 TEXTIO应用实例   

  下面以一个简单的8 位加法器来说明TEXTIO 的使用。输入数据为两个8 位的有符号数,输出为9 位的有符号数,以防止溢出。在编写加法器的描述文件时,首先要对两个数进行位的扩展,再进行加法运算。在编写测试文件时,要注意读入数据与得到结果之间相差一个时钟周期。因此,需要在读出的结果与计算的结果之间插入一个时钟周期的等待。

  ①生成输入及预定结果文件的C++程序。

  我们可以使用VC++、Matlab 等高级软件工具编写生成输入和预定结果文件的程序。由于设定输入为8 位有符号数, 因此,其范围为[-127,127]C++程序如下:

  #include " iostream.h"

  #include " stream.h"

  void main(void){

  int i,j;

  ofstreamfsIn("d:\\yuproj\\modelsim\\NineBitAdder2\\TestData.dat");

  ofstreamfsOut("d:\\yuproj\\modelsim\\NineBitAdder2\\Result.dat");

  for(i=-127;i<128;i++) {

  for(j=-127;j<128;j++) {

  fsIn<<i<<""<j<<endl;

  fsOut<<i+j<<endl;

  }

  }

  fsIn.close();

  fsOut.close();

  }

  在程序中,使用了C++类库iostream.hfstream.h,主要使用了"<< " 的输出功能,读者可以参考相应的C++书 籍。运行该程序可以在规定的目录下生成TestData.dat Result.dat 两个文本格式的文件。注意,一行输入多个数据时,之间以空格隔开即可。

  ②编写的加法器描述如下。  

  libraryieee;

  useieee.std_logic_1164.all;

  useieee.std_logic_signed.all;

  entity Add2In is

  port( D1 : in std_logic_vector(7 downto 0);

  D2 : in std_logic_vector(7 downto 0);

  Q : out std_logic_vector(8 downto 0);

  Clk: instd_logic);

  end Add2In;  

  architecture A_Add2In of Add2In is

  begin

  process(Clk)

  begin

  if Clk = 1and Clkevent then

  Q <= (D1(D1left) & D1) + (D2(D2eft) & D2);

  endif;

  endprocess;

  end A_Add2In;

  在进行加法前,首先进行位的扩展,再进行加法运算,在时钟的上升沿完成加法运算。

  ③编写测试文件。

  在测试程序中,首先读出输入文件的一行内容,再从该行中提取出两个值输入加法器。从预定结果文件中提取出一个值,将加法器计算结果与该值比较,若两者不同则输出警告信息。也可以将输出写入一个文本文件,再比较两个文本文件的异同以获知出错的地方。这里要注意的是要使用TEXTIO 程序包,另外,测试文件实体内的端口为空,相当于一块独立的电路板。使用Component 在其中包含了上面定义的加法器,该独立的电路板所完成的功能是对设计的加法器进行测试。在程序中使用了assert 断言语句,要注意该语句后的表达式或变量为真时不执行后续的输出,为假时执行后续的输出。在程序中,还使用了类型转换函数CONV _ STD _LOGIC_VECTOR (),将整数转换为8 位的标准类型。另外,在程序中定义了变量Dlatch ,该变量的作用是将计算结果与预定结果的比较延迟一个时钟周期,周期地与预定结果比较。

  3 仿真结果   

  在ModelSim 中可以将它们编译仿真,注意在编译时选择语法标准为VHDL'93 标准。编译后,可以输入如下的仿真Macro 来执行仿真。

  vsim work.tb

  该命令将执行仿真work 库中的tb,其中tb 为测试文件的实体名。

add wave -dec *

该命令将所有的信号以十进制添加到波形文件中。

  run-all

  该命令将使仿真一直执行下去。

  输入以上各个命令,仿真结束后会在ModelSim 的提示符下出现如下信息:

  # ** Fatal: (vsim-3551) TEXTIO : Read past end of file" TestData.dat".

  # Time: 2601020ns Iteration: 0 Process:/tb/line__34File: D:/YuProj/ModelSim/NineBitAdder2/NineBitAdder2.vhd

  # FatalerroratD:/YuProj/ModelSim/NineBitAdder2/NineBitAdder2.vhd line 41

  表示在读完TestData.dat 后,因读空出现错误。其中没有出现程序中所设定的warning ,表示加法器的仿真结果与高级软件得到的预定结果相符合。我们可以改进程序,在其中加入ENDFILE()函数来判断是否读取到文件的结尾。仿真得到的波形如图1 所示。

 

 

 

  若人为地更改Result.dat文件中第9行的-246100,重新仿真,则出现如下信息:

  # ** Warning: Two values are different

  # Time: 420 ns Iteration: 0 Instance: /tb

  # ** Fatal: (vsim-3551) TEXTIO : Read past end of file" TestData.dat".

  # Time: 2601020ns Iteration: 0 Process:/tb/line__34File: D:/YuProj/ModelSim/NineBitAdder2/NineBitAdder2.vhd

  # FatalerroratD:/YuProj/ModelSim/NineBitAdder2/NineBitAdder2.vhd line 41

  #

  双击对应的警告信息,可以看到仿真结果与Result.dat 中预定结果不一致的地方。仿真图形如图2所示。

  结语   

  TEXTIO 使得VHDL 的仿真功能有了大的飞跃,在使用VHDL 描述处理器等模型及判断系统对不规则输入的响应时,起到了非常大的作用。本文通过简单的实例,说明了TEXTIO 库及其简单的应用流程。在当前嵌入式系统广泛应用的背景下,将更为需要TEXTIO 的应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值