VHDL语言仿真激励文件testbench编写指南

本文档详细介绍了VHDL语言中testbench的编写,包括时钟和复位的模拟、文件读写操作以及随机数生成的方法。讲解了如何产生时钟和复位信号,文件的打开、读写操作以及使用line类型处理不同类型数据。同时提到了随机数生成,以及在仿真中的应用。
摘要由CSDN通过智能技术生成

前言

         最近小编接触了一些关于VHDL语言的项目,而之前一直使用Verilog语言,虽然之前也学习过VHDL,但是毕竟语言这东西,如果不经过实战练习很难掌握。所以在编写代码时感觉很别扭,在网上找相关资料感觉这方面的资料很杂乱,而且不是很全面。所以小编将自己最近使用到的知识整理了一下供大家参考。


一、时钟和复位的模拟

        一般的激励文件只要合理的模拟出时钟和复位,就可以开始使用进程语句开始编写其它信号了,所以理解怎么产生时钟、复位是编写激励文件的关键。如下代码显示了如何实现时钟和复位产生:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb_led is
--  Port ( );   --不用填
end tb_led;

architecture Behavioral of tb_led is

component key_led   --声明待测试模块
port(     
    --端口声明
      
    
    );
end component;

signal reset : std_logic := '0';
signal clk:std_logic:='1';
signal key:std_logic_vector(1 downto 0) :="11";
signal led:std_logic_vector(1 downto 0);

constant PERIOD : time := 2ps;  --时钟周期设置
begin

-----------------------------第一种:组合逻辑-------------------------------------
CLK <= not CLK after PERIOD/2;  --时钟
reset <= '1' after 5*PERIOD;   --复位

-----------------------------第二种:进程中编写-------------------------------------
clk_gen1 : PROCESS 
	CONSTANT period : TIME := 20 NS;
BEGIN
CLK <= '1';
	WAIT FOR period/2;
	CLK <= '0';
	WAIT FOR period/2;
END PROCESS;

--复位也可以使用process进程引入clk,使用if语句来实现
reset : process
   variable cnt : integer range 0 to 100
begin
   wait until rising_edge clk;
   cnt := cnt +1;
   if cnt>100 then
      reset <= '0';  
   else
      reset <= '1';  --复位
   end if;
end process ; -- identifier

--设着key在5个周期后为“10” 
process
begin
wait for 5*PERIOD;  --延迟5个周期
key <= "10";
wait;               --结束   --如果没有wait,会一直循环执行“延迟和赋值语句”。
                    --wait后面不带参数,表示一直等待,即结束。
end process;

--例化待测试模块
key_led1:key_led
port map
(
   --端口连接映射
);

end Behavioral;

关于wait语句的用法详解:

       wait 语句只能出现在进程中,能综合到 FPGA 线路中的形式只有一种: wait until …。这个语句是优先级很高的语句,如果要使用它,它必须是进程的第一条语句,而且它 的引脚必须是 FPGA 的 GCLK 引脚(全局时钟)。用 wait 语句时, wait 的时钟信号不能由进程的参数引入,时钟信号不能出现在 process 的括号中。最典型的应用: Wait until rising _ edge clk ;

        这是一条进程的时钟触发的语句。 Wait until rising _ edge 是保留字,整个语句的解读是:等待 clk 信号的上升沿到来。这一条语句的执行,是原地等待,直到 clk 上升沿到来后,才执行以下的语句。它和前述的含有上升沿的 if 语句是有区别的。在 if 语句里,上升沿没有到来时,条件框内的语句是不执行的,但是绕过条件框以外的语句是执行的。在 wait until rising _ edge 语句中,上升沿没有到来时,绕不过去的,后面的语句都不执行。 Wait until rising _ edge 构建的是典型的触发器电路。

        只要有了时钟和复位信号,其它模块需要用的信号就可以使用进程模块来编写了。

二、文件读写

1、文件类型有两种,一种是integer,文中的数据是以二进制存取的,不易查看(也可以通过ultraedit来查看)。另一种就是文本类型(text),数据以ASCii码存储,文本类型的数据容易查看。

2、文件打开有4中状态:

  • open_ok:打开成功
  • status_error:打开失败
  • name_error:名字错误
  • mode_error:打开模式失败

用file_open_status类型的数据来表示文件状态,声明方式如下:
        variable file_status:file_open_status

3、line类型,是以行的形式写入或读取数据的,还能借助于line来实现把integer,natural,bit_vector等类型的数据写入text类型的文件,下面有介绍。
声明形式:variable buf:line;

文件操作:
打开文件:file_open
写入文件:write,writeline
读取文件:read,readline
关闭文件:file_close
file_open(file_open_status,file_fid,file_name,mode);
file_open_status:文件打开的状态
file_fid:文件句柄(file声明)
file_name:文件名字(string类型,如:”data.txt”)
mode:打开的类型,write_mode和read_mode

write和writeline的区别
write只能写对应于文件类型的数据,如text类型只能写string,integer类型只能写integer类型数据
如果要写入integer,natural,std_logic,std_logic_vector类型的数据到text类型文件,就只能使用line来操作,首先write(buf,std_logic_vector),把要写入的std_logic_vector类型数据写入line类型的buf,
然后通过writeline(file,buf)来写入数据。read和readline的区别与write和writeline一样。

file_close(file_fid);

对控制台的操作:
writeline(output,buf); //output代表输出数据到控制台,是关键字,buf是line类型,可以理解为一行的意思
readline(input,buf); //input代表从控制台输入数据,是关键字

示例:
向控制台写入数据
signal cnt:natural:=0;
write(buf,cnt);
writeline(output,buf);

从控制台读取数据
readline(input,buf);
read(buf,cnt);

下面为我自己写的代码: 

-----------------------------------------------------------------------------------
--文件读
-----------------------------------------------------------------------------------
process ( clk _ in )
   variable buf : LINE ;
   variable file_status : file_open_status ;
   variable v : std _1ogic_ vector (11 downto 0);
   --需要根据文件存放目录,修改下面语句的文件路径 
   file file_in : text ;

begin 
   if ( clk'event and clk = '1') then 
      if ( rst = '1') then 
         nu11;
      elsif ( read_en = '1') then 
            file_open (
               file_status,--文件打开的状态
               file_in,--文件句柄
               "D:\work\PRJ\decoding_frame_1\sim\frame.txt", 
               read _ mode --打开类型
            ); --该语句不能放在复位时刻。
         f_status <= file_status ;  --在波形中显示文件打开状态
         if not ( ENDFILE ( file_in )) then 
            readline ( file_in , buf ); 
            read ( buf , v );
         --从V变量中获取值给信号
         else 
            file_close ( file_in ); 
         end if ;
      end if ;
   end if ; 
end process ;
-----------------------------------------------------------------------------------
--文件写
-----------------------------------------------------------------------------------
process ( clk _ in )
   variable buf : LINE ; --行类型变量
   variable file_status : file_open_status ;
   variable v : std _1ogic_ vector (11 downto 0);
   --需要根据文件存放目录,修改下面语句的文件路径 
   file file_out : text ;

begin 
   if ( clk'event and clk = '1') then 
      if ( rst = '1') then 
         nu11;
      elsif ( read_en = '1') then 
            file_open (
               file_status,--文件打开的状态
               file_out,--文件句柄
               "D:\work\PRJ\decoding_frame_1\sim\frame.txt", 
               write_mode --打开类型
            ); --该语句不能放在复位时刻。
         f_status <= file_status ;  --在波形中显示文件打开状态
         v := singnal_data;
         write ( buf , v );
         writeline ( file_out , buf ); 
      else 
         file_close ( file_out ); 
      end if ;
   end if ; 
end process ;

注意文件读写一定要包含下面这两个库:

  • use std.textio.all;
  • use ieee.std_logic_textio.all

三、随机数生成

如果想在仿真中产生随机数,vhdl可以使用math_real函数包中的uniform函数得到一个real类型的归一随机数。可以对这个数进行其它处理来满足具体要求。比如扩大倍数、截掉小数等。另外用于verilog产生随机数比较简单,也可以用vhdl调用一个verilog模块进行混合仿真。

library ieee;
use ieee.math_real.all;
use ieee.numeric_std.all;
...
PROCESS
VARIABLE seed1, seed2: positive; -- 缺省值为1
VARIABLE rand: real; -- 产生范围 0 到 1.0 的随机数
VARIABLE int_rand: integer;
BEGIN
UNIFORM(seed1, seed2, rand);
int_rand := INTEGER(TRUNC(rand*100.0)); --产生0-100的随机数


总结

以上的一些操作足以让一般的开发者进行激励文件的编写了。如果后续我在使用其它比较好的仿真方式时会持续更新该文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卯【金】刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值