《基于XILINX FPGA嵌入式系统设计与开发》第二章
第二章 开发环境
2.1 Xilinx ISE介绍
2.1.1 ISE简介
2.1.2 ISE安装
2.1.3 ISE库编译
在编译ISE的仿真库时,Xilinx为我们提供了相当方便的界面,为了与Modelsim关联,我们需要通过Xilinx lib GUI进行库编译,最后在Xilinx目录中,得到最新的modelsim.ini导入到Modelsim安装目录下。
在开始菜单中,我们选择Xilinx ISE Design Suite 13.2->ISE Design Tools->Tools->Simulation Library Compilation Wizard,将出来如图界面。
我们选择Modelsim SE仿真器,仿真器执行路径为Modelsim安装路径,其他的默认。对于ISE的版本,Modelsim版本支持是有说明的。目前我们使用的是ISE 13.2版本,Modelsim最低版本为Modelsim SE 6.6D。
选择VHDL及其Verilog
选择器件,在此全部选择
库产生的路径,选择默认
设置好后,软件将进行自动运行。从0%至20%会比较慢,等待即可。
2.2 Mentor Modelsim介绍
Mentor公司的ModelSim是业界最优秀的HDL语言仿真软件,它能提供友好的仿真环境,是业界唯一的单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术、和单一内核仿真技术,编译仿真速度快,编译的代码与平台无关,便于保护IP核,个性化的图形界面和用户接口,为用户加快调错提供强有力的手段,是FPGA/ASIC设计的首选仿真软件。
ModelSim分几种不同的版本:SE、PE、LE和OEM,其中SE是最高级的版本,而集成在 Actel、Atmel、Altera、Xilinx以及Lattice等FPGA厂商设计工具中的均是其OEM版本。SE版和OEM版在功能和性能方面有较大差别,比如对于大家都关心的仿真速度问题,以Xilinx公司提供的OEM版本ModelSim XE为例,对于代码少于40000行的设计,ModelSim SE 比ModelSim XE要快10倍;对于代码超过40000行的设计,ModelSim SE要比ModelSim XE快近40倍。ModelSim SE支持PC、UNIX和LINUX混合平台;提供全面完善以及高性能的验证功能;全面支持业界广泛的标准;Mentor Graphics公司提供业界最好的技术支持与服务。
2.2.1 Modelsim安装
双击modelsim-win32-6.6d-se.exe,分别按照下述步骤进行。
解压Modelsim
安装Modelsim
创建modeltech_6.6d文件
单击YES
单击Agree
图1-6 Waiting~~~
单击YES
单击YES
单击No
LICENSE安装
双击桌面上的MODELSIM快捷键,如果没有报错说明,**成功,否则,返回上述步骤再次**。
2.2.2 Modelsim的使用
对于FPGA设计人员来说,调用脚本进行批出来,比直接使用GUI更方便,后续的例程我们都将采用脚本进行仿真,因此,在本书中,将Modelsim中常用的脚本进行详细介绍。
在使用之前,我们需要将Xilinx ISE库文件加载至Modelsim中,在库编译结束后,在C:\Xilinx\13.2\ISE_DS\ISE\bin\nt找到modelsim.ini文件,将库路径复制到Modelsim目录下modelsim.ini(去掉只读属性),保存即可。
modelsim.ini文件修改
修改前后的库文件
常用命令介绍
;编译本地库//注释符号;
vlib work
;编译verilog
vlog +acc"../src/rxa.v"
;编译IPCORE
vlog +acc"../core/abc.v"
;编译顶层文件
vlog +acc"../sim/tb_tb.v"
;编译本地库
;这部分是XILINX 调用方法,对于Altera需要更改
vlog +acc"C:/Xilinx/12.3/ISE_DS/ISE/verilog/src/glbl.v"
;加载激励以及仿真库
vsim -novopt -t 1ps -L xilinxcorelib_ver -L unisims_ver -L unimacro_ver -L secureio -lib work rxta_tb glbl
;加载波形, *符号表示所有的信号,类似于通配符
add wave /*
;运行加上时间与单位
run 100us
2.2.3 Modelsim实例
下面以加法器来进行说明,测试顶层文件为add.v,激励文件为tb_add.v。
add.v文件包含下述代码
`timescale 1ns / 1ps
module add(
clk,
rst,
din1,
din2,
dout
);
input clk ;
input rst ;
input [2:0] din1;
input [2:0] din2;
output [3:0] dout;
reg [3:0] dout;
always @(posedge clk)
begin
if(rst)
dout <= 4'd0;
else
dout <= din1 + din2;
end
endmodule
tb_add.v文件包含下述代码
`timescale 1ns / 1ps
module tb_add;
// Inputs
reg clk;
reg rst;
reg [2:0] din1;
reg [2:0] din2;
// Outputs
wire [3:0] dout;
// Instantiate the Unit Under Test (UUT)
add uut (
.clk(clk),
.rst(rst),
.din1(din1),
.din2(din2),
.dout(dout)
);
initial
begin
clk = 0;
rst = 1;
din1 = 0;
din2 = 0;
#100
rst = 0;
end
always #(20/2) clk = ~clk;
always @(posedge clk)
begin
din1 <= $random%7;
din2 <= $random%7;
end
endmodule
详细操作步骤如下。
步骤1:打开Modelsim,在命令窗口输入路径切换命令,cd {D:\Book_Examples\Lab2_1\sim},此路径为工程目录sim的路径。
步骤2:运行.do文件,即批处理脚本文件。在批处理中,如果HDL语言出现语法等错误,编译器会报错,如下图所示,根据提示修改后,再次运行。
在命令窗口中运行
add wave /*
调用run命令,run 10us即可看到结果,如下图所示。
2.3 Matlab
2.3.1 Matlab
MATLAB产品家族是美国Mathworks公司开发的用于概念设计,算法开发,建模仿真,实时实现的理想的集成环境。由于其完整的专业体系和先进的设计开发思想,使得MATLAB在多种领域有着广阔的应用空间,特别是在MATLAB的主要应用方向上,如科学计算、建模仿真以及信息工程系统的设计开发上已经成为行业内的首选设计工具,MATLAB已被广大科研工作者和工程技术人员作为广泛使用和开发型工具软件。
2.3.2 FPGA开发中常用命令
如果大家对Xilinx System Generator或者Altera DSPBuilder有所了解,就知道MATLAB在FPGA设计中应用极其广泛。对于逻辑开发人员而言,掌握最基本的即可。主要有信号处理部分、激励源的生成与输出、以及从Modelsim中读入数据。此部分详见实战训练。
2.4 设计规范
2.4.1 FPGA工程文件夹
在工程中,包括6个文件,说明如下:
图4-1 工程文件夹
imp文件夹:FPGA实现文件;
src文件夹:FPGA source文件,HDL所在文件;
core文件夹:调用IP所在文件夹;
sim文件夹:仿真所在文件夹;
mat文件夹:MATLAB脚本所在文件夹;
doc文件夹:项目设计所在文件夹;
2.4.2 HDL编写规范
变量命名,首位为字母,所有变量命名都为小写,有需要时加下划线或者字母,如clk_1x;
时钟信号,随着系统设计的复杂性,当时钟由外部晶振送至FPGA专用时钟管脚,系统时钟等高速时钟的产生必须通过PLL(Xilinx为DCM)生成,严禁通过计数的方式来分倍频,严格保证设计的稳定性,对于SPI、I2C等低速接口可以采用自定义计数分频;
时序逻辑用非阻塞;
组合逻辑用阻塞;
严禁使用不能综合的关键字
n initial;
n for;
n forever;
n while;
n repeat;
n wait;
n $display等系统任务函数;
使用case语句必须加上default;
if…else…必须成对出现;
跨时钟域处理
n 信号,采用打拍方式进行隔离;
n 数据,采用FIFO进行跨时钟域处理;
外部输入复位信号送至FPGA,内部复位信号由PLL供给;
always@块中,不能同时出现一个信号的上下升沿;
时钟信号以clk开头,如clk50,clk100;
复位信号,rst高;rst_n,为低;
信号定义先输入时钟、复位,再信号输入,次之为信号输出;
地址信号addr;
握手信号带_rdy;
信号打拍带_ff,如din,打一拍din_ff1,两拍din_ff2;
常用计数器名字cnt, 或者cont;
当设计需要一块很大的RAM时,将其进行拆分,如32K的可以分为16*2K,便于时序设计;
输入需寄存;
输出需寄存;
2.4.3 HDL测试文件的编写
HDL测试流程
对于TestBench的编写,主要包括module声明,信号定义,DUT的例化以及激励信号的产生。
常用语句
1)产生时钟信号
时钟是所有测试文件工作的关键,产生时钟的方法有下述两种,至于HDL语法,可参考相关HDL资料。
1 forever语句
initial
begin
forever clk = #(10/2) ~clk;
end
2 always语句
initial
begin
clk = 0;
end
always #(10/2) clk = ~clk;
2) Memory Initialization Files
在Verilog中初始化Memory的函数有$readmemb和$readmemh,其中$readmemh为读取二进制文件,$readmemh为读取十六进制文件。
在仿真文件中,初始化memory。
reg [15:0] mem [0:1023]
initial
begin
$readmemh(“din.txt”,mem);
end
将数据送至激励端口,例子如下
reg clk;
reg [15:0] datain;
reg [9:0] cnt;
reg [15:0] mem [0:1023];
initial
begin
cnt = 0;
$readmemh(“din.txt”,mem);
end
//例化DUT
…
always #(10/2) clk = ~clk ; //100MHz
always @(posedge clk)
begin
cnt <= cnt + 1’b1;
end
always @(posedge clk)
begin
datain <= mem[cnt];
end
3) inout信号
大多数设计中,尤其是外挂SRAM,都会设计到inout信号。
module bidir_infer (DATA, READ_WRITE);
input READ_WRITE ;
inout [1:0] DATA ;
reg [1:0] LATCH_OUT ;
always @ (READ_WRITE or DATA)
begin
if (READ_WRITE == 1)
LATCH_OUT <= DATA;
end
assign DATA = (READ_WRITE == 1) ? 2'bZ : LATCH_OUT;
endmodule
TestBench文件
module test_bidir_ver;
reg read_writet;
reg [1:0] data_in;
wire [1:0] datat, data_out;
bidir_infer uut (datat, read_writet);
assign datat = (read_writet == 1) ? data_in : 2'bZ;
assign data_out = (read_writet == 0) ? datat : 2'bZ;
initial begin
read_writet = 1;
data_in = 11;
#50 read_writet = 0;
end
endmodule
4) timescales
timescale直接决定了我们仿真时间单元及其精度。具体用法为
`timescale reference_time/precision
举例说明
`timescale 1 ns / 1 ps //时间单位为1ns,精度为1ps
module testbench;
..
..
initial begin
#5 reset = 1; // 5ns后reset值为1
#10 reset = 0; // 15ns后reset值为0
..
end
endmodule
5) 监视
Displaying Results
Displaying results is facilitated in Verilog by the $display and $monitor keywords. Although
VHDL does not have equivalent display-specific commands, it provides the std_textio package,
which allows file I/O redirection to the display terminal window (for an example of this
technique, see Self-Checking Testbenches, below).
initial begin
$timeformat(-9,1,"ns",12);
$display(" Time Clk Rst Ld SftRg Data Sel");
$monitor("%t %b %b %b %b %b %b", $realtime,
clock, reset, load, shiftreg, data, sel);
end
6) 生成文件
在Verilog中,类似于C语言。当我们涉及到大量数据分析时,如果需要看频谱效果,则需要将数据导入到MATLAB中,此时在TestBench中生成文件,
parameter FILE = "../mat/file1.txt";
input clk ;
input [WIDTH-1 : 0] data;
input rdy ;
integer fid;
initial
begin
fid = $fopen(FILE);
end
always @(posedge clk)
begin
if(rdy)
begin
$fdisplayh(fid, data);
end
else ;
end
7) 编写Testbench指导原则
Know the simulator before writing the testbench.
Although commonly-used simulation tools conform to HDL industry standards, these
standards do not address several important simulation-specific issues.
Avoid using infinite loops
When an event is added to an event-based simulator, CPU and memory usage increases,
and simulation processing slows.
Break up stimuli into logical blocks
Within a testbench, all initial (Verilog) and process (VHDL) blocks run concurrently.
Avoid displaying unimportant data
Displaying a large amount of simulation data slows simulation considerably.
2.5 实战训练—FIR滤波器设计
2.5.1 目的—ISE、Modelsim与Matlab联合开发
单击Targets,生成Xilinx .coe文件
2.5.2实战训练
顶层代码
`timescale 1ns / 10ps
module fir_top(
clk,
rst,
din,
rdy,
dout
);
input clk ;
input rst ;
input [15:0] din ;
output rdy ;
output [15:0]dout;
wire [33:0] fird;
fir_core U(
.sclr(rst ),
.rfd ( ),
.rdy (rdy ),
.clk (clk ),
.dout(fird),
.din (din )
);
reg [15:0] dout;
always @(posedge clk)
begin
if(rst)
dout <= 16'd0;
else
dout <= fird[32:17] + fird[16];
end
endmodule
激励文件
`timescale 1ns / 10ps
module tb_fir_core;
// Inputs
reg clk;
reg rst;
reg [15:0] din;
wire rdy;
// Outputs
wire [15:0] dout;
reg[15:0] driv_src[0:10240];
initial
begin
$readmemh("filter.txt",driv_src);
end
// Instantiate the Unit Under Test (UUT)
fir_top uut (
.clk(clk),
.rst(rst),
.din(din),
.rdy(rdy),
.dout(dout)
);
reg [1:0] div;
reg [13:0]cnt;
initial
begin
clk = 0;
rst = 1;
din = 0;
div = 0;
cnt = 0;
#100;
rst = 0;
end
always #(5/2) clk = ~clk;//200
always @(posedge clk)
begin
div <= div +1'b1;
end
always @(posedge clk)
begin
if (2'd0 == div)
cnt <= cnt + 1'b1;
else ;
end
always @(posedge clk)
begin
din <= driv_src [cnt];
end
data_output # (.WIDTH(16),
.FILE("../mat/cos.txt")
)U1_OUT_DATA(
.clk(clk),
.rdy(rdy),
.data(dout)
);
endmodule
MATLAB中的filter
2.5 总结
用户403664 2014-2-21 11:30