原创 VHDL中的文件I/O

2010-8-31 08:38 7220 6 6 分类: FPGA/CPLD

==============================================================================


==============================================================================

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

一、文件I/O

上节讲了,在testbench常将数据写入文件,或者从文件读入数据等,这都需要用到VHDL语言中与文件打交道的语言,即是常说的file I/O. 这里强调两点:文件I/O语言是不能被综合的,文件I/O与FPGA的I/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版本!

 

=============================================================================



library ieee;
    use std.textio.all;
    use ieee.std_logic_textio.all;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
   
entity testin is
     
end entity testin;
architecture rtl of testin is
    begin
        process is
            file file_out1,filein: text; --定义text类型的文件句柄;
            variable fstatus1,fstatus2:FILE_OPEN_STATUS;   --定义文件状态指示变量;
            variable count:integer:=5;           --定义integer型写入数据;
            variable stringdata:string(5 downto 1):="whwnh";--定义string型写入数据;
            variable vectordata:bit_vector(5 downto 0):="001000";--定义bit_vector型的写入数据;
            variable value:std_logic_vector(3 downto 0):="1111";--定义std_logic_vector型的写入数据;
            variable BUF,BUF1:LINE;
            begin
               
                    file_open(fstatus1,file_out1,"datain.txt",write_mode);  --打开文件“datain.txt"
                    write(file_out1,string'("the first parameter is="));    --通过write()函数直接向文件中写入对应类型数据。
                    readline(input,buf);                                    --从控制台输入字符串输入文件;
                    write(buf,count);
                    writeline(file_out1,buf);                                      --向文件中输入integer类型
                    wait for 20 ns;
                    write(buf,string'("the second parameter is="));
                    write(buf,value);
                    writeline(file_out1,buf);   
                    wait for 20 ns;                                     --向文件中输入std_logic_vector类型数据;
                    write(buf,string'("the third parameter is="));
                    write(buf,vectordata);
                    writeline(file_out1,buf); 
                    wait for 20 ns;                                  --向文件中输入bit_vector类型数据;
                    write(buf,string'("the forth parameter is="));
                    write(buf,stringdata);                                  --向文件中输入string类型数据。   
                    writeline(file_out1,buf);
                    write(file_out1,string'("end of file"));
                    file_close(file_out1); 
                    wait for 100 ns;                                --关闭文件
                    file_open(fstatus1,file_out1,"datain.txt",read_mode);  --以读取模式打开文件
                    readline(file_out1,buf);                               --读取文件数据并输出到控制台界面。
                    writeline(output,buf);               
                    file_close(file_out1);
                    wait for 100 ns;
                    file_open(fstatus1,filein,"STD_INPUT",read_mode);      --以控制台作为文件输入
                    file_open(fstatus2,file_out1,"STD_OUTPUT",write_mode);  --以控制台作为文件输出
                    readline(filein,BUF);
                    writeline(file_out1,BUF);
           
         wait;  
        end process;
    end rtl;


控制台文件



输出.txt文件


==============================================================================


一、next,exit

这两个关键词有点类似于C语言中的continue和break.

PROCESS(A, B)
CONSTANT max_limit : INTEGER := 255;
BEGIN
FOR i IN 0 TO max_limit LOOP
IF (done(i) = TRUE) THEN
NEXT;
ELSE
done(i) := TRUE;
END IF;
q(i) <= a(i) AND b(i);
END LOOP;
END PROCESS;

如程序中用到了next,如果i还没有到达max_limit那么将会退出本次循环,i=i+1,然后继续循环。

PROCESS(a)
variable int_a : integer;
BEGIN
int_a := a;
FOR i IN 0 TO max_limit LOOP
IF (int_a <= 0) THEN -- less than or
EXIT; -- equal to
ELSE
int_a := int_a -1;
q(i) <= 3.1416 / REAL(int_a * i); -- signal
END IF; -- assign
END LOOP;
y <= q;
END PROCESS;

本例中使用了EXIT,当int_a<0时,那么程序将跳出loop循环,转而执行loop后的下一句话y<=q;

另外需要注意的是 EXIT支持嵌套,即是如果在loop中嵌套了loop,那么EXIT只会跳出最里层的loop.

另外EXIT还有一种语法 EXIT which_loop when(a<0); 在a<0满足时,跳出EXIT,不同的是现在的EXIT可以跳出指定loop(在loop有标签的情况下),如果没有指出,那么还是跳出最内层loop.

二、assert

assert是一个非常有用的语法,他可以判断一个boolean变量,如果该变量为假就输出一个用户指定的信息到终端(控制台),用户可以附带输出信息的严格等级,从低到高依次是:note,warning,error,failure,可以让用户区分信息的类型。同样assert语句也是不能被综合的。

assert可以同步语句(在process外),此时assert后面的任何变量变化都会引起assert语句判断一次。

assert还可以是顺序语句,此时assert存在于process中。

三、wait

使用wait语句,使设计者可以方便的在顺序语句中控制执行时间。可以用于process,procedure,function等子程序当中。

  WAIT ON signal changes (signal)
  WAIT UNTIL an expression is true  (boolean_expression)
  WAIT FOR a specific amount of time (time_expression)

 

  PROCESS
  BEGIN
  WAIT UNTIL clock = ‘1’ AND clock’EVENT;
  q <= d;
  END PROCESS;

 

  WAIT ON a, b;  只有a或者b 某一个信号变化才执行下面的语句。

  WAIT UNTIL (( x * 10 ) < 100 ); 只有x<10才执行下面的句子,否则程序将会停在此处。

  WAIT FOR 10 ns;
  WAIT FOR ( a * ( b + c )); 程序在此处必须挂起这么多时间再执行下面的语句。

  但是wait for语句会引起程序等待超时(有点像死锁),所以得注意使用。

  可以使用语句 WAIT UNTIL (sendA = ‘0’) FOR 1 us;
              ASSERT (sendA = ‘0’)
              REPORT “sendA timed out at ‘0’”
              SEVERITY ERROR;                       这样可以消除等待超时。

 

  process(clk) 相当于一个wait on clk在process的末尾,但是在有wait的process中不能有敏感信号表!同时注意wait on 必须在process的结尾。

 

 
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条