课 程 设 计 报 告
课程名称:
设计名称: FIR滤波器的FPGA实现
姓 名:
学 号:
班 级:
指导教师:
起止日期:
课 程 设 计 任 务 书
学生班级: 学生姓名: 学号:
设计名称:
起止日期: 指导教师:
"
设计要求:
利用MATLAB软件设计一数字频率10MHz的低通滤波器并用FPGA实现它,具体包括:
1)阐述FIR的基本原理和基本结构;
2)用MATLAB软件设计3dB带宽0.2,阻带抑制≥45dB的FIR滤波器;研究不同滤波器
设计方法滤波器抽头数和滤波器平坦度、带外抑制度、过渡带宽等性能关系;选出符合要求抽头数最少的一种设计;对所设计的FIR系数进行8bit量化,并生成FPGA滤波器系数.coe文件;
| 3)采用QuartusII 或ISE等FPGA集成开发软件,通过调用IPcore设计滤波器,采用10MHz工作时钟和50MHz工作时钟两种方式分别实现2)中的滤波器功能;编写FPGA封装程序和功能测试程序;综合并比较2种设计的资源占用情况。 参考书目:数字信号处理;ISE9.X使用手册;QuartusII7.X 使用手册;软件IPcore自带pdf文档;精通MATLAB7.0 |
| 时间 | 设计内容 |
| 11.17-11.22 | 查阅相关资料 |
| 11.23-11.25 | 设计系统整体方案,分析功能及指标要求 |
| 11.26-11.30 | 完成FIR滤波器系数的设计 |
| 12.1-12.4 | 调用Altera MegaCore实现FIR滤波器 |
| 12.5-12.7 | 调用Altera DSP Builder实现FIR滤波器 |
| 12.8-12.9 | Simulink下实现FIR滤波器的算法级仿真 |
| 12.10-12.14 | QuartusII下仿真FIR滤波器 |
| 12.15-12.17 | 撰写报告 |
| 12.21 | 答辩 |
| 周 | 星期一 | 星期二 | 星期三 | 星期四 | 星期五 | |||||
"
指导教师评语:
成绩: 指导教师:
| 年 月 日 |
一、设计目的和意义
FIR数字滤波器能够满足滤波器对幅度和相位特性的严格要求,避免模拟滤波器的温漂和噪声等问题,具有精确的线性相位、易于硬件实现和系统稳定等优点,可广泛应用于现代电子通信系统。实际信号处理应用往往要求系统兼具实时性和灵活性,而现有设计方案(如DSP)则难以同时达到这两方面要求。而使用具有并行处理特性的FPGA实现FIR滤波器,具有很强的实时性和灵活性,因此为数字信号处理提供一种很好的解决方案。
本设计使用MATLAB软件和Altera公司的FPGA开发软件QuartusⅡ进行FIR滤波器的设计仿真,该设计方案能够直观检验滤波器的设计效果,提高设计效率,缩短设计周期。
通过本次设计的主要目的在于:
1、掌握ENA设计的基本流程及方法
2、熟悉MATLAB工具箱及Simulink的使用
3、熟悉Quartus II开发环境及其使用
4、熟悉verilog HDL的使用
二、设计原理
有限长度滤波器(FIR)是线性滤波器的一种,它因原理及实现结构简单和很容易实现线性相位而在雷达、通信以及信号处理领域得到广泛应用。FPGA具有足够的硬件资源和足够的灵活性,可以几乎无限次修改验证设计和极大缩短研发周期,因而在现代电子系统设计和研发中具有无可替代的作用。
2.1 FIR滤波器的特点
有限长度滤波器(FIR)具有以下特点:
(1)系统的单位冲击响应h(n)在有限个n值处不为零;
(2)系统函数H(z)在|z|>0处只有零点,即有限z平面只有零点,而全部极点都在z=0处(因果系统);
(3)结构上主要是非递归结构,没有输出到输入的反馈;
FIR滤波器的系统函数为:
2.2 FIR滤波器的基本结构
FIR滤波器主要有:横截型(直接型,卷积型)、级联型、频率抽样型、快速卷积结构、线性相位结构;
2.2.1 横截型
FIR滤波器的差分方程即卷积和公式,也是x(n)的延时链的横向结构,所以称为卷积型或横截型结构。按H(z)或差分方程直接画出结构图,故也称为直接型结构。横截型结构是FIR滤波器设计中应用最为普遍的一种结构,如图1所示。
图 1 FIR滤波器的横截型结构
2.2.2 级联型
将H (z)分解成实系数二阶因子的乘积形式
图 2 FIR滤波器的级联型结构
其中[N/2]表示取N/2的整数部分。若N为偶数,则N—1为奇数,故系数B2K中有一个为零,这是因为,这时有奇数个根,其中复数根成共轭对必为偶数,必然有奇数个实根;N为奇数时,FIR滤波器的级联结构,其中每一个二阶因子用图1的横型结构。
这种结构的每一节控制一对零点,因而再需要控制传输零点时,可以采用它。但是这种结构所需要的系数(I = 0,1,2,k,= 1,2,...,[N/2])比卷积型的系数h (n)要多,因而所需的乘法次数也比卷积型的要多。
2.2.3 频率抽样型
N个频率抽样H(k)恢复H(z)的内插公式:
图 3 FIR滤波器的频率抽样型结构
在频率抽样型结构中,调整H(k)就可以有效地调整频响特性,若h(n)长度相同,则网络结构完全相同,除了各支路增益H(k),便于标准化、模块化。有限字长效应可能导致零极点不能完全对消,导致系统不稳定,系数多为复数,增加了复数乘法和存储量。
2.2.4 快速卷积结构
只要将两个有限长序列补上一定的零值点,就可以用圆周卷积来代替两序列的线性卷积。由于时域的圆周卷积,等效到频域则为离散傅立叶变换的乘积。因而,如果即将输入x (n)补上L-N1个零值点,将有限长单位冲激响应h (n)补上L-N2个零值点,只要满足L >= N1 + N2-1,则L点的圆周卷积就能代表线性卷积,即用DFT表示,则有Y(k) =X(k)H(k),其中
Y(k) = DFT[y (n)],L点
X(k) = DFT[x(n)],L点
H(k) = DFT[h (n)],L点
这样,我们就可得到快速卷积结构,当N1,N2足够长时,它比直接计算线性卷积要快得多。
2.2.5线性相位结构
FIR滤波器单位抽样响应h(n)为实数,,且满足偶对称或者奇对称,即对称中心在处,则这种FIR滤波器具有严格的线性相位。
N为奇数时,
令
(4)
N为偶数时,
(5)
三、详细设计步骤
3.1 整体设计思路
首先使用MATLAB进行FIR滤波器的系数设计,然后在simulink中进行算法级仿真,验证设计的正确性,在Quartus II中进行门级仿真,验证硬件的正确性。
3.2 系统算法级设计及指标要求
3.2.1 FIR滤波器设计分析
分析题目要求:设计数字频率10MHz,3dB带宽0.2,阻带抑制≥45dB的FIR滤波器;由3dB带宽0.2,则知需设计通带截止频率为2MHz;由奈奎斯特定律可知阻带起始频率应大于等于1/2被的数字频率,则阻带起始频率设置为3MHz可满足;阻带衰减≥45dB,阻带衰减为65dB的FIR滤波器即可满足要求。
3.2.2 利用“Filter Designer&Analysis”设计FIR滤波器系数并导出到MATLAB工作区间
打开MATLAB软件,打开start—>ToolBoxes—> Filter Designer&Analysis,在Units框内选择“KHz”;在Fs内填写10000,即数字采样频率为10000KHz(10MHz);在Fpass内填写2000,即通带截止频率为2000KHz(2MHz);在Fstop内填写3000,即阻带起始频率为3000KHz(3MHz),Astop填65,即为阻带衰减65dB。如图4:
图 4 FIR滤波器系数设计
在“Filter Designer&Analysis”下,打开File—>Export…出现下图
图 5 导出FIR滤波器系数到MATLAB工作空间
点击“Export” 将系数导出到MATLAB工作区间。在MATLAB命令窗口输入“Num”可显示刚刚设计的浮点数系数如下:
Columns 1 through 11
-0.0011 -0.0133 -0.0319 -0.0229 0.0248 0.0423 -0.0299 -0.0917 0.0339 0.3133 0.48
Columns 12 through 21
0.3133 0.0339 -0.0917 -0.0299 0.0423 0.0248 -0.0229 -0.0319 -0.0133 -0.0011
设计出的FIR滤波器的幅频及相频响应如图6:
图 6 FIR滤波器的幅频、相频响应
冲击响应如图7:
图 7 FIR滤波器的冲击响应
3.2.3 将滤波器系数进行8位量化圆整
在在MATLAB命令窗口输入“num=round(Num*(2^7))”对滤波器系数进行8位量化,量化后的系数如下:
>> num=round(Num*(2^7))
num =
Columns 1 through 18
0 -2 -4 -3 3 5 -4 -12 4 40 59 40 4 -12 -4 5 3 -3
Columns 19 through 21
-4 -2 0
经过8位量化圆整后的系数的幅频相频响应如图:
图 8 FIR滤波器量化圆整后的系数的幅频相频响应
3.2.4 将系数以.coe文件输出
在MATLAB命令窗口输入:
>> freqz(num)
>> fid=fopen('D:\\work\\firdata.coe','wt');
>> fprintf(fid,'%d\\n',num);
>> fclose(fid);
在D盘的“work”文件下生成系数文件。
图 9 利用MATLAB生成.coe文件
3.3 调用DSP Builder设计FIR滤波器
在调用Altera的MegaCore之前,首先要安装Altera公司的DSP Builder工具,同时DSP Builder的版本要和Quartus II的版本一致,并且已装好MATLAB R2007b以上版本。本次课程设计用的工具为Quartus II 9.0、DSP Builder 9.0、MATLAB R2008a。
3.3.1 调用DSP Builder中的MegaCore Functions生成FIR滤波器
装好DSP Builder 9.0后,打开Simulink,就会出现Altera DSP Builder Blockset文件夹。在Altera DSP Builder Blockset文件中找到MegaCore Functions,将“fir_compiler_v9_0”拖入已建好的模型文件中,如下图10:
图 10 Altera MegaCore Functions
双击“fir_compiler_v9_0”将FIR滤波器的系数导入,如图11:
图 11 MegaCore导入FIR滤波器系数
然后生成IP Core,生成后的FIR滤波器如图12:
图 12 利用MegaCore生成的FIR滤波器
其中,reset_n是复位信号输入端口,低电平有效,ast_sink_data(7:0)是8位正弦波数据输入端口,ast_soure_ready是信源准备好信号输入端口,ast_source_data(16:0)是经FIR滤波器后的数据输出端口。加入signle compiler和时钟并连接好电路后如图13:
图 13 MegaCore电路模型图
3.3.2 使用DSP Builder设计FIR滤波器
由FIR滤波器结构可知,FIR滤波器累由乘法器和加法器组成,因此刚刚设计的FIR滤波器可由乘法器和加法器来完成。由于DSP Builder提供的Multiply Add允许输入2、3、4个整形数据,因此,上述设计的21阶FIR滤波器可由7个3输入的Multiply Add来完成。
(1)设计乘加子系统
Multiply Add的设置按照下表进行,其中Constant Values就是滤波器系数。
Table 1 Multiply Add设置参数表
| 参数名称 | Multiply Add | Multiply Add1 | Multiply Add2 | Multiply Add3 | Multiply Add4 | Multiply Add5 | Multiply Add6 |
| Number of Multipliers | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
| Bus Type | Signed Integer | Signed Integer | Signed Integer | Signed Integer | Signed Integer | Signed Integer | Signed Integer |
| Input [number of bit].[] | 16 | 16 | 16 | 16 | 16 | 16 | 16 |
| Counstant Values | [0 -2 -4] | [-3 3 5] | [4 -12 4] | [40 59 40] | [4 -12 -4] | [5 3 -3] | [-4 -2 0] |
图 14 FIR滤波器的乘加子系统设计
配置完成后,创建乘加子系统如图15:
图 15 设计完成的乘加子系统
(2)加入正弦信号模块和Add模块
在simulink Library Browser下的Source中拖入两个Sine Wave模块,分别设置为10KHz和3.3MHz。
在simulink Library Browser下的Math Operations中找到Add模块并加入文件中。
(3)加入Input、Output、Shift Tap模块
在Altera DSP Builder Blockset中的IO&Bus找到Input、Output模块加入文件中,并设置为16位有符号整型数据。
在在Altera DSP Builder Blockset中的Storage中找到Shift Taps模块并加入文件,设置Number of Taps的参数为21。
(4)加入Bus Conversion模块
在Altera DSP Builder Blockset中的IO&Bus找到Bus Conversion模块,加入文件中。因为每个Multiply Add的输出为34位,每两个Multiply Add需要扩展一位,因此共输出为40位。因此,Bus Conversion中的Input填40;Output填16,;由于8位量化,输出须截掉8位,因此Input Bit Connected To Output LSB填8。
(5)加入Signl Compiler模块和时钟模块
在Altera DSP Builder Blockset中的AltLab中找到Signl Compiler模块和时钟模块,加入文件中,并将时钟模块设置为100ns。
(6)加入示波器Scope模块并连接各模块
在simulink Library Browser下的sinks中找到Scope并加入文件中,将Scope设置为4通道。连接各个模块,如图16:
图 16 采用DSP Builder设计的FIR滤波器模型
3.3 Simulink下进行算法级仿真
3.3.1 Simulink下进行算法级仿真
在simulation—>Configuration Parameters设置如下图17:
图 17 simulation仿真设置
按下Ctrl+T进行仿真。
3.3.2 建立可进行硬件仿真的FIR滤波器
上述中的FIR滤波器只能在simulink下进行,如果要在硬件中运行,需要采用查表的方法输入正弦波数据,因此需要加入Increment Decrement模块和LUT模块并将电路改为下图18:
图 18 应用于硬件的FIR滤波器模型
3.4 QuartusⅡ仿真
3.4.1 生成Quartus II工程
双击signle compiler,弹出如下图19界面:
图 19 Signl Compiler
点击“compile”生成.qpf工程。
3.4.2 在QuartusII下仿真
首先打开上述生成的QuartusII工程文件,编译、建立波形文件,并设置时钟为100ns,生成网表文件后仿真。
3.5 QuartusⅡ下Test Bench仿真
3.5.1 Test Bench仿真
在quartusII下新建verilog文件,输入Test Benchverilog代码,其中,
initial
begin
trigger = 0;
i = 0;
nummismatches = 0;
on_first_change = 1'b1;
fid=$fopen("D:/work/data.txt
end
always @(Output)
begin
End
代码中fid=$fopen("D:/work/data.txt用于在D盘work文件夹下建立data.txt文件。
$fwrite(fid, "%d\\n", Output);用于写入Output数据。
3.5.2 导出Output数据使用Matlab绘图显示
在MATLAB中输入:
fid=fopen('D:\\work\\data.txt','r');
a=fscanf(fid,['%d' a '\\n'])
fid=fopen('D:\\work\\data.txt','r');
a=fscanf(fid,'%d')
fid=fopen('D:\\work\\data.txt','r');
a=fscanf(fid,['%d' a '\\n'])
plot(a)
四、设计结果及分析
4.1 simulink下算法级仿真分析
滤除低频10KHz中的3.3MHz,时钟为10M,采样率为10M,如图20:
图 20 10KHz中叠加3.3MHz正弦信号及其仿真
第一行为10KHz的正弦波,第二行为3.3MHz正弦波信号,第三行为两种频率正弦波信号的叠加,第四行为经FIR滤波器滤波后的波形。由图可知,叠加在10KHz中的3.3MHz的高频信号被滤除。以下分别是在10KHz中叠加3.3MHz、1MHz中叠加3.3MHz的情形:
图 21 20KHz中叠加3.3MHz正弦信号及其仿真
图 22 11MHz中叠加3.3MHz正弦信号及其仿真
4.2 QuartusII下时域仿真分析
QuartusII下首先使用波形文件仿真,时钟设置为100ns(10MHz),如图23:
图 23 QuartusII下FIR滤波器的时域仿真
4.3 Test Bench仿真分析
Test Bench文件由波形文件修改而来,时钟依然是100ns(10MHz),MATLAB绘图如下:
图 24 Test Bench仿真FIR并用MATLAB绘图
五、体会
通过这次课程设计,我掌握了EDA设计的基本方法和流程,同时熟悉了常用EDA工具的使用,对EDA也有了一个系统的认识。
在整个课程设计过程中,首先学习了FIR滤波器的原理、结构及实现方式,其次查找资料,以迄设计出完美的FIR滤波器。再次,通过QuartusII等EDA软件和IPCore实现FIR滤波器。整个过程大概分为两个阶段:第一阶段,FIR滤波器系数的设计。通过查找资料,我利用MATLAB下ToolBoxes中的Filter Designer&Analysis来设计滤波器的系数。这个工具可以直接输出实现要求的最小阶数的FIR滤波器系数,其中可选波纹法、窗函数法等设计方法进行设计。设计中发现,通带平坦度越好、过渡带越窄、阻带衰减越大、带外抑制度越好滤波器的阶数就越高,因此FIR滤波器的性能是与所占用的硬件资源成正相关的,设计中谋求一种既符合要求由节省硬件资源的方案。第二个阶段,FIR滤波器的实现。这个过程,查的资料最多,关键问题在于仿真和IPCore的调用。通过查找资料,使用过Modelsim、QuartusII等仿真工具,使用过Altera DSP Builder、MegaCore及Xilinx的Core generator,最终使用Altera DSP Builder完成设计。
六、参考文献
[1] 程佩青.数字信号处理教程.清华大学出版社,2007.
[2] 马建国,孟宪元.FPGA现代数字系统设计.北京:清华大学出版社,2010.
[3] 王城,薛小刚,钟信潮.FPGA/CPLD设计工具-Xilinx使用详解.中国人民邮电出版社,2005.
[4] 张威.MATLAB基础与编程入门.西安电子科技大学出版社,2008.
[5] 徐明远,邵玉斌.MATLAB仿真在通信与电子工程中的应用.西安电子科技大学出版社,2010.
七、附件:Test Bench verilog源代码
`timescale 1 ps/ 1 ps
module LowPassPro_vlg_sample_tst(
Clock,
clr,
sampler_tx
);
input Clock;
input clr;
output sampler_tx;
reg sample;
time current_time;
always @(Clock or clr)
begin
if ($time > 0)
begin
if ($time == 0 || $time != current_time)
begin
if (sample === 1'bx)
sample = 0;
else
sample = ~sample;
end
current_time = $time;
end
end
assign sampler_tx = sample;
endmodule
module LowPassPro_vlg_check_tst (
Output,sampler_rx
);
input [15:0] Output;
input sampler_rx;
reg [15:0] Output_expected;
reg [15:0] Output_prev;
reg [15:0] Output_expected_prev;
reg [15:0] last_Output_exp;
reg trigger;
integer i,fid;
integer nummismatches;
reg [1:1] on_first_change ;
initial
begin
trigger = 0;
i = 0;
nummismatches = 0;
on_first_change = 1'b1;
fid=$fopen("D:/work/data.txt
end
always @(Output)
begin
//if(ct1>1000)begin ct2 = ct2+1;end
$fwrite(fid, "%d\\n", Output);
end
// update real /o prevs
always @(trigger)
begin
Output_prev = Output;
end
// update expected /o prevs
always @(trigger)
begin
Output_expected_prev = Output_expected;
end
// expected \\Output [ 15 ]
always
begin
Output_expected[15] = 1'b0;
Output_expected[15] = #50000 1'b1;
#50000;
end
// expected \\Output [ 14 ]
always
begin
Output_expected[14] = 1'b0;
Output_expected[14] = #50000 1'b1;
#50000;
end
// expected \\Output [ 13 ]
always
begin
Output_expected[13] = 1'b0;
Output_expected[13] = #50000 1'b1;
#50000;
end
// expected \\Output [ 12 ]
always
begin
Output_expected[12] = 1'b0;
Output_expected[12] = #50000 1'b1;
#50000;
end
// expected \\Output [ 11 ]
always
begin
Output_expected[11] = 1'b0;
Output_expected[11] = #50000 1'b1;
#50000;
end
// expected \\Output [ 10 ]
always
begin
Output_expected[10] = 1'b0;
Output_expected[10] = #50000 1'b1;
#50000;
end
// expected \\Output [ 9 ]
always
begin
Output_expected[9] = 1'b0;
Output_expected[9] = #50000 1'b1;
#50000;
end
// expected \\Output [ 8 ]
always
begin
Output_expected[8] = 1'b0;
Output_expected[8] = #50000 1'b1;
#50000;
end
// expected \\Output [ 7 ]
always
begin
Output_expected[7] = 1'b0;
Output_expected[7] = #50000 1'b1;
#50000;
end
// expected \\Output [ 6 ]
always
begin
Output_expected[6] = 1'b0;
Output_expected[6] = #50000 1'b1;
#50000;
end
// expected \\Output [ 5 ]
always
begin
Output_expected[5] = 1'b0;
Output_expected[5] = #50000 1'b1;
#50000;
end
// expected \\Output [ 4 ]
always
begin
Output_expected[4] = 1'b0;
Output_expected[4] = #50000 1'b1;
#50000;
end
// expected \\Output [ 3 ]
always
begin
Output_expected[3] = 1'b0;
Output_expected[3] = #50000 1'b1;
#50000;
end
// expected \\Output [ 2 ]
always
begin
Output_expected[2] = 1'b0;
Output_expected[2] = #50000 1'b1;
#50000;
end
// expected \\Output [ 1 ]
always
begin
Output_expected[1] = 1'b0;
Output_expected[1] = #50000 1'b1;
#50000;
end
// expected \\Output [ 0 ]
always
begin
Output_expected[0] = 1'b0;
Output_expected[0] = #50000 1'b1;
#50000;
end
// generate trigger
always @(Output_expected or Output)
begin
trigger <= ~trigger;
end
always @(posedge sampler_rx or negedge sampler_rx)
begin
`ifdef debug_tbench
$display("Scanning pattern %d @time = %t",i,$realtime );
i = i + 1;
$display("| expected Output = %b | ",Output_expected_prev);
$display("| real Output = %b | ",Output_prev);
`endif
if (
( Output_expected_prev[0] !== 1'bx ) && ( Output_prev[0] !== Output_expected_prev[0] )
&& ((Output_expected_prev[0] !== last_Output_exp[0]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[0] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[0] = Output_expected_prev[0];
end
if (
( Output_expected_prev[1] !== 1'bx ) && ( Output_prev[1] !== Output_expected_prev[1] )
&& ((Output_expected_prev[1] !== last_Output_exp[1]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[1] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[1] = Output_expected_prev[1];
end
if (
( Output_expected_prev[2] !== 1'bx ) && ( Output_prev[2] !== Output_expected_prev[2] )
&& ((Output_expected_prev[2] !== last_Output_exp[2]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[2] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[2] = Output_expected_prev[2];
end
if (
( Output_expected_prev[3] !== 1'bx ) && ( Output_prev[3] !== Output_expected_prev[3] )
&& ((Output_expected_prev[3] !== last_Output_exp[3]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[3] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[3] = Output_expected_prev[3];
end
if (
( Output_expected_prev[4] !== 1'bx ) && ( Output_prev[4] !== Output_expected_prev[4] )
&& ((Output_expected_prev[4] !== last_Output_exp[4]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[4] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[4] = Output_expected_prev[4];
end
if (
( Output_expected_prev[5] !== 1'bx ) && ( Output_prev[5] !== Output_expected_prev[5] )
&& ((Output_expected_prev[5] !== last_Output_exp[5]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[5] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[5] = Output_expected_prev[5];
end
if (
( Output_expected_prev[6] !== 1'bx ) && ( Output_prev[6] !== Output_expected_prev[6] )
&& ((Output_expected_prev[6] !== last_Output_exp[6]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[6] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[6] = Output_expected_prev[6];
end
if (
( Output_expected_prev[7] !== 1'bx ) && ( Output_prev[7] !== Output_expected_prev[7] )
&& ((Output_expected_prev[7] !== last_Output_exp[7]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[7] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[7] = Output_expected_prev[7];
end
if (
( Output_expected_prev[8] !== 1'bx ) && ( Output_prev[8] !== Output_expected_prev[8] )
&& ((Output_expected_prev[8] !== last_Output_exp[8]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[8] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[8] = Output_expected_prev[8];
end
if (
( Output_expected_prev[9] !== 1'bx ) && ( Output_prev[9] !== Output_expected_prev[9] )
&& ((Output_expected_prev[9] !== last_Output_exp[9]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[9] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[9] = Output_expected_prev[9];
end
if (
( Output_expected_prev[10] !== 1'bx ) && ( Output_prev[10] !== Output_expected_prev[10] )
&& ((Output_expected_prev[10] !== last_Output_exp[10]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[10] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[10] = Output_expected_prev[10];
end
if (
( Output_expected_prev[11] !== 1'bx ) && ( Output_prev[11] !== Output_expected_prev[11] )
&& ((Output_expected_prev[11] !== last_Output_exp[11]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[11] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[11] = Output_expected_prev[11];
end
if (
( Output_expected_prev[12] !== 1'bx ) && ( Output_prev[12] !== Output_expected_prev[12] )
&& ((Output_expected_prev[12] !== last_Output_exp[12]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[12] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[12] = Output_expected_prev[12];
end
if (
( Output_expected_prev[13] !== 1'bx ) && ( Output_prev[13] !== Output_expected_prev[13] )
&& ((Output_expected_prev[13] !== last_Output_exp[13]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[13] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[13] = Output_expected_prev[13];
end
if (
( Output_expected_prev[14] !== 1'bx ) && ( Output_prev[14] !== Output_expected_prev[14] )
&& ((Output_expected_prev[14] !== last_Output_exp[14]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[14] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[14] = Output_expected_prev[14];
end
if (
( Output_expected_prev[15] !== 1'bx ) && ( Output_prev[15] !== Output_expected_prev[15] )
&& ((Output_expected_prev[15] !== last_Output_exp[15]) ||
on_first_change[1])
)
begin
$display ("ERROR! Vector Mismatch for output port Output[15] :: @time = %t", $realtime);
$display (" Expected value = %b", Output_expected_prev);
$display (" Real value = %b", Output_prev);
nummismatches = nummismatches + 1;
on_first_change[1] = 1'b0;
last_Output_exp[15] = Output_expected_prev[15];
end
trigger <= ~trigger;
end
initial
begin
$timeformat(-12,3," ps",6);
#3000000;
if (nummismatches > 0)
$display ("%d mismatched vectors : Simulation failed !",nummismatches);
else
$display ("Simulation passed !");
$stop;
end
endmodule
module LowPassPro_vlg_vec_tst();
// constants
// general purpose registers
reg Clock;
reg clr;
// wires
wire [15:0] Output;
wire sampler;
// assign statements (if any)
LowPassPro i1 (
// port map - connection between master ports and signals/registers
.Clock(Clock),
.clr(clr),
.\\Output (Output)
);
// Clock
always
begin
Clock = 1'b0;
Clock = #50000 1'b1;
#50000;
end
// clr
initial
begin
clr = 1'b1;
end
LowPassPro_vlg_sample_tst tb_sample (
.Clock(Clock),
.clr(clr),
.sampler_tx(sampler)
);
LowPassPro_vlg_check_tst tb_out(
.Output(Output),
.sampler_rx(sampler)
);
endmodule下载本文