一个测试平台文件就是一个VHDL模型,可以用来验证所设计的硬件模型的正确性。测试平台文件为所测试的元件提供了激励信号,仿真结果可以以波形的方式显示或存储测试结果到文件中。激励信号可以直接集成在测试平台文件中,也可以从外部文件加载。可以直接使用VHDL语言来编写测试平台文件。
1. 仿真激励输入信息的产生
硬件系统通常是通过输入信号来驱动,在不同输入信号情况下其行为表现是产生不同的输出结果。因此仿真激励输入信息的产生是对系统进行仿真的重要前提和必不可少的步骤。仿真激励输入信息的产生通常有程序直接产生方法和读TEXIO的方法。
1)程序直接产生法
所谓程序直接产生法就是由设计者设计一段VHDL语言程序,由该程序直接产生仿真的输入信息。在测试平台文件中,有两种常用的激励信号,一种是周期性的激励信号,其波形是周期性变化的;另一种是时序变化的,比如复位信号以及其他输入信号。下面各实例来讲述激励信号的产生。
①时钟信号、复位信号、允许信号
例如对一个带使能端的十二进制计数器进行仿真,该计数器有3个输入端,仿真时要产生clr、en和clk 3个输入信号,如图1所示,3个输入信号之间有严格的定时关系。这些定时波形可以用进程来产生,如例1所描述。
图1带使能端得十二进制计数器的仿真输入信号
【例1】激励信号产生
…
CONSTANT clk_cycle : TIME :=20ns;
…
PROCESS
BEGIN
test_clk<='1';
WAIT FOR clk_cycle/2;
test_clk<='0';
WAIT FOR clk_cycle/2; --产生周期为20ns的时钟信号
END PROCESS;
PROCESS
BEGIN
test_clr<='0';
test_en<='0';
WAIT FOR clk_cycle/4;
test_clr<='1';
test_en<='1';
WAIT FOR clk_cycle;
test_clr<='0';
WAIT FOR clk_cycle*10;
test_en<='0';
WAIT FOR clk_cycle*3 --产生复位信号和允许信号
test_en<='1';
WAIT;
END PROCESS;
例子中第一个进程产生周期为20ns的时钟周期test_clk。test_clk刚开始是高电平,保持10ns后变为低电平,再保持10ns,得到一个时钟周期。该进程没有指定敏感信号,因此进程执行到最后一条语句后又返回到最前面,开始执行进程的第一条语句。如此循环就能产生周期为20ns的时钟脉冲。
例子中第二个进程用来产生初始的复位信号和计数允许信号。该进程可产生宽20ns的复位信号,复位以后260ns再让test_en有效(高电平),从而使计数器进入正常的计数状态。该进程的最后一条语句是WAIT语句,它表明该进程只执行一次,进程在WAIT语句上处于无限制的等待状态。
②一般的激励信号
可以定义普通的激励信号来用作模型的输入信号。定义一般的激励信号通常在进程中定义。一般都可以使用WAIT语句来定义一般的激励信号。如例2下面的激励信号的定义,其波形如图2所示。
【例2】激励信号
signal c : std_logic := '0';
……
stim_proc: process
begin
wait for 80 ns;
c <= '1';
wait for 60 ns;
c <= '0';
wait for 50 ns;
c <= '1';
wait for 100 ns;
c <= '0';
……
wait; --一直等待
end process;
图2一般激励信号的波形
2)读TEXTIO文件产生法
读TEXTIO文件产生法是一种用数据文件输入仿真的方法,即仿真输入数据按定时要求按行存于一个文件(TEXTIO)中。在仿真时,根据定时要求按行读出,并赋予相应的输入信号。例3就是根据图1的仿真输入信号要求所设计的TEXTIO文件test.in。
【例3】
clk clr en
0ns 1 0 0
5ns 1 1 1
10ns 0 1 1
15ns 0 1 1
20ns 1 1 1
25ns 1 0 1
30ns 0 0 1
35ns 0 0 1
40ns 1 0 1
…
220ns 1 0 1
225ns 1 0 0
230ns 0 0 0
235ns 0 0 0
240ns 1 0 0
…
280ns 1 0 0
285ns 1 0 1
290ns 0 0 1
295ns 0 0 1
300ns 1 0 1
在test.in文件中每行包含3位数据,第1位为clk,第2位为clr,第3位为en。每行数据之间的定时间隔为10ns。如果在程序中每隔10ns读入一行数据,并将读入值赋予对应的clk、clr和en,那么就产生了图1所示的仿真输入信号。这一点利用TEXTIO中的READLINE和READ语句就很容易实现了。如例3:
【例4】
…
FILE intest : TEXT IS IN "text.in";
SIGNAL test_clk,test_clr,test_en : STD_LOGIC;
CONSTANT clk_cycle : TIME :=20 ns;
…
PROCESS
VARIABLE li:LINE;
VARIABLE clk,en,clr :STD_LOGIC;
BEGIN
READLINE(intest,li);
READ(li,clk);
READ(li,clr);
READ(li,en);
test_clk<=clk;
test_clr<=clr;
test_en<=en;
WAIT FOR clk_cycle/2;
IF(ENDFILE(intest)) THEN
WAIT;
END IF;
END PROCESS;
…
在该例中就描述了每隔10ns从test.in文件中读入一行数据,并将其对应值赋予test_clk、test_clr和test_en的情况。该进程除非碰到test.in文件的末尾标志,否则该进程中的语句就将循环进行,这样也就产生了图1所示的仿真输入信号。
输入仿真信号产生时还应该注意的一点是,输入控制信号和时钟信号最好不要在同一仿真时刻发生变化。例如图1中的test_clr和test_en变化时间与时钟变化沿错开了四分之一的时钟周期。这样做的好处是防止仿真中因判别二者变化的先后不同而出现相反的结果,使仿真结果具有唯一性。