安富利GSM给您讲讲使用ModelSim 进行设计仿真

[复制链接]
楼主: GoldSunMonkey
手机看帖
扫描二维码
随时随地手机跟帖
GoldSunMonkey|  楼主 | 2011-12-25 17:14 | 显示全部楼层
80# davines 哈哈,因为我们真心无痕~

使用特权

评论回复
GoldSunMonkey|  楼主 | 2011-12-25 23:04 | 显示全部楼层
:)明天白天我们继续讲解。哈哈。欢迎前排占座

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:09 | 显示全部楼层
从仿真过程可以看出,TestBench为波形输入自动添加了驱动,因此,在仿真时候就不需要再为信号进行驱动
了。在我们这个例子中,并没有省很多事情,因为我们的设计输入只有一个时钟,但如果我们设计一个两个四
位数相加的加法器,如果考虑到所有可能的输入一个个地输入会很麻烦,这时候我们可以利用TestBench来进
行设置,我们在后面会举一个这样的例子。另外,我们要注意到TestBench文件中的实体与外界没有任何接口
相连,因此:
ENTITY divclk1_tb IS
END divclk1_tb;
定义的实体中没有端口,我们把所要仿真的对象当成一个部件在TestBench中来使用,以实现TestBench与仿
真对象之间的联系。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:10 | 显示全部楼层
TEXTIO介绍
TEXTIO是VHDL标准库STD中的一个程序包(Package)。在该包中定义了三个类型:LINE类型、TEXT类型以
及SIDE类型;一个子类型(subtype)WIDTH。此外,在该程序包中还定义了一些访问文件所必须的过程
(Procedure)。简单描述如下:

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:10 | 显示全部楼层
类型的定义如下:
type LINE is access string;
定义了LINE为存取类型的变量,它表示该变量是指向字符串的指针,它是TEXTIO中所有操作的基本单元,
读文件时,先按行(LINE)读出一行数据,再对LINE操作来读取各种数据类型的数据;写文件时,先将各
种的数据类型组合成LINE,再将LINE写入文件。在用户使用时,必须注意只有变量才可以是存取类型的,
而信号则不能是存取类型的。例如,我们可以定义
variable DLine : LINE;
但不能定义成:
signal DLine : LINE;

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:11 | 显示全部楼层
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在使用文件方面有较大的差异。在编译时注意选中对应的标准。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:11 | 显示全部楼层
type SIDE is (right, left);
定义了SIDE类型。表示定义了一个名为SIDE的数据类型,其中只能有两种状态,即right和left,right和left表示
将数据从左边还是右边写入行变量。该类型主要在TEXTIO程序包包含的过程(Procedure)中使用。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:12 | 显示全部楼层
过程(Procedure)的定义如下:
TEXTIO提供了基本的用于访问文本文件的过程。类似于C++,VHDL提供了重载功能。即完成相近功能的不同
的过程可以有相同的过程名,但其参数列表不同,或参数类型不同或参数个数不同。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:13 | 显示全部楼层
TEXTIO提供的基本过程有:
procedure READLINE(文件变量;行变量);
用于从指定文件读取一行数据到行变量中。
procedure WRITELINE(文件变量;行变量);
用于向指定文件写入行变量所包含的数据。
procedure READ(行变量; 数据类型);
用于从行变量中读取相应的数据类型的数据。
根据参数数据类型及参数个数的不同,有多种重载方式,TEXTIO提供了bit、bit_vector、BOOLEAN、
character、integer、real、string、time数据类型的重载。同时,提供了返回过程是否正确执行的
BOOLEAN数据类型的重载。例如,读取整数的过程为
procedure READ(L:inout LINE; VALUE: out integer; GOOD : out BOOLEAN);
其中,GOOD用于返回过程是否正确执行,若正确执行,则返回TRUE。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:14 | 显示全部楼层
procedure WRITE(行变量; 数据变量; 写入方式; 位宽);
该过程将数据写入行变量。其中写入方式表示写在行变量的左边还是右边,且其值只能为left或right,位宽表示
写入数据时占的位宽。例如:
write(OutLine,OutData,left,2);
表示将变量OutData写入LINE变量OutLine的左边占2个字节。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:14 | 显示全部楼层
TEXTIO在仿真中的应用
下面以一个简单的8位加法器来说明TEXTIO的使用。输入数据为两个8bit的有符号数,输出为9bit的有符号数,
以防止溢出。在编写加法器的描述文件时,首先要对两个数进行位的扩展,再进行加法运算。在编写测试文件
时,要注意读入数据与得到结果之间相差一个时钟周期,因此,需要在读出的结果与计算的结果之间需要插入一
个时钟周期的等待。仿真步骤如下:

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:15 | 显示全部楼层
生成输入及预定结果文件的C++程序
我们可以使用VC++、Matlab等高级软件工具编写生成输入和预定结果文件的程序,由于设定输入为8位有符合数,因此,其范围为[-127,127]。C++程序如下:
#include "iostream.h"
#include "fstream.h"
void main(void)
{
int i,j;
ofstream fsIn("d:\\yuproj\\modelsim\\TextioTest\\TestData.dat");
ofstream fsOut("d:\\yuproj\\modelsim\\TextioTest\\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();
}

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:16 | 显示全部楼层
在程序中,使用了C++类库iostream.h和fstream.h。主要使用了“<<”的输出功能。读者可以参考对应的
C++书籍。运行该程序可以在规定的目录下生成TestData.dat和Result.dat两个文本格式的文件。注意,一行输
入多个数据时,之间以空格隔开即可。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:16 | 显示全部楼层
2. 新建ModelSim工程
打开ModelSim,新建工程Textio,其存放目录为d:\yuproj\modelsim\TextioTest;
3. 添加设计源文件
新建设计文件NineBitsAdder,新建文件的方法是File->New->Source->VHDL,源代码如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.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 : in std_logic);
end Add2In;
architecture A_Add2In of Add2In is
begin
process(Clk)
begin
if Clk = '1' and Clk'event then
Q <= (D1(D1'left) & D1) + (D2(D2'left) & D2);
end if;
end process;
end A_Add2In;
在进行加法前,首先进行位的扩展,再进行加法运算。在时钟的上升沿完成加法运算。

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:17 | 显示全部楼层
添加测试文件
新建TestBench文件TestBench.vhd,新建文件的方法是File->New->Source->VHDL,代码如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;
use std.TEXTIO.all;
entity tb is
end tb;
architecture a_tb of tb is
component Add2In
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 : in std_logic);
end component;
signal D1 : std_logic_vector(7 downto 0):=(others=>'0');
signal D2 : std_logic_vector(7 downto 0):=(others=>'0');
signal Q : std_logic_vector(8 downto 0);
signal Clk : std_logic:='0';
signal Dlatch : boolean :=false;
signal SResult : integer;
begin
dut : Add2In
port map( D1=>D1,
D2=>D2,
Q => Q,
Clk => Clk);
Clk<=not Clk after 20 ns;
process
file InputD : text open read_mode is "TestData.dat";
variable DLine : LINE;
variable good : Boolean;
variable Data1 : integer;
variable Data2 : integer;
begin
wait until Clk='1' and Clk'event;
readline(InputD,DLine);
read(DLine,Data1,good);
read(DLine,Data2,good);
if ( good )then
D1 <= CONV_STD_LOGIC_VECTOR(Data1,8);
D2 <= CONV_STD_LOGIC_VECTOR(Data2,8);
else
assert false report "End of Reading Input File!"
severity error;
end if;
end process;
process
file InputR : text open read_mode is "Result.dat";
variable RLine : LINE;
variable Result : integer;
begin
wait until Clk='1' and Clk'event;
Dlatch<=true;
if Dlatch then
readline(InputR,RLine);
read(RLine,Result);
SResult<=Result ;
if SResult /=Q then
assert false report "Two values are different"
severity warning;
end if;
end if;
end process;
end a_tb;

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:18 | 显示全部楼层
5. 编译
下面开始仿真,先编译所有文件,方法是点击菜单Compile ->Compile All;
6. 装载设计
在命令窗口中输入vsim work.tb;
7. 打开波形窗口
在命令窗口中输入view wave,打开波形文件窗口;
8. 添加信号到波形窗口中
在命令窗口中输入add wave -dec *,将信号添加到波形文件中;

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:18 | 显示全部楼层
本帖最后由 GoldSunMonkey 于 2012-1-2 18:19 编辑

9. 运行仿真
在命令窗口中输入run –all该命令将使仿真一直运行下去;
10. 仿真结果
仿真结束后在主界面窗口中将会看到如下信息:
# ** Fatal: (vsim-3551) TEXTIO : Read past end of file "TestData.dat".
# Time: 2601020 ns Iteration: 0 Process: /tb/line__34 File: D:/yuProj/modelsim/TextioTest/TestBench.vhd
# Fatal error at D:/yuProj/modelsim/TextioTest/TestBench.vhd line 41
#
表示在读完TestData.dat后,因读空出现错误。其中没有出现我们程序中所设定的warning。表示加法器的仿
真结果与高级软件得到的预定结果相符合。我们可以改进程序,在其中加入ENDFILE()函数来判断是否读取
到文件的结尾,仿真结果如图示;
2012-01-02_181902.jpg

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:19 | 显示全部楼层
11. 结束仿真
输入命令quit –sim结束仿真。
12. 修改数据文件
将VC生成的文件Result.dat打开,将文件中的第100行的-155为100,保存该文件;
13. 仿真
同上,在ModelSim主窗口中输入如下命令:
vsim work.tb
view wave
add wave -dec *
run -all

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:20 | 显示全部楼层
14. 仿真结果运行完毕会在主窗口中显示如下警告信息,我们双击对应的警告信息,可以看到,仿真结果与
Result.dat中的预定结果不一致的地方。仿真图形如图所示。

2012-01-02_181902.jpg
# ** Warning: Two values are different
# Time: 4060 ns Iteration: 0 Instance: /tb
# ** Fatal: (vsim-3551) TEXTIO : Read past end of file "TestData.dat".
# Time: 2601020 ns Iteration: 0 Process: /tb/line__34 File: D:/yuProj/modelsim/TextioTest/TestBench.vhd
# Fatal error at D:/yuProj/modelsim/TextioTest/TestBench.vhd line 41
#

使用特权

评论回复
GoldSunMonkey|  楼主 | 2012-1-2 18:22 | 显示全部楼层
15. 退出仿真
输入命令quit –sim;
仿真分析:
在该程序中,首先读出输入文件的一行内容,再从该行中提取出两个值输入加法器。从预定结果文件中提取出
一个值,将加法器计算结果与该值比较,若两者不同则输出警告信息。我们也可以将输出写入一个文本文件,
再比较两个文本文件的异同以获知出错地方。这里要注意的是要使用TEXTIO程序包,另外,测试文件的实体
内的端口为空,相当于一块独立的电路板,使用Component在其中包含了上面定义的加法器,该独立的电路
板所完
成的功能是对设计的加法器进行测试。在该程序中使用了assert断言语句,要注意该语句后的表达式或变量为
真时不执行后续的输出,为假时执行后续的输出

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则