北京理工大学VHDL实验报告.docx
《北京理工大学VHDL实验报告.docx》由会员分享,可在线阅读,更多相关《北京理工大学VHDL实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
北京理工大学VHDL实验报告
课程名称:
VHDL硬件描述语言实验时间:
2013年10月
实验报告
姓名:
学号:
专业:
信息工程
班级:
05111003
实验一时钟分频电路
一、实验概述
按“Modulus”为模,将“ClkIn”时钟脉冲信号分频,在“ClkOut”上输出。
如果“Modulus”是偶数,它产生对称的输出波形,否则,其输出波形的高电平宽度大于低电平宽度。
(参考讲义4后实例)
二、实验目的
理解Generic语句参数传递的作用。
三、实验要求
1.编写源程序2.用VHDL建立测试平台(Test-Bench)
3.用ModelSim仿真4.“Modulus”设不同值观察波形结果
四、VHDL源代码
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
entitytopis
generic(Modulus:
integer:
=3);--用generic语句设置参数Modulus
port(
ClkIn:
instd_logic;
Reset:
instd_logic;
ClkOut:
outstd_logic);
endtop;
architectureBehavioraloftopis
begin
process(ClkIn,Reset)
variableCount:
integerrange0toModulus-1;--使用参数Modulus
begin
if(Reset='1')then--异步复位
Count:
=0;
ClkOut<='0';
elsif(rising_edge(ClkIn))then--同步释放
if(Count=Modulus-1)then
Count:
=0;
else
Count:
=Count+1;
endif;
if(Count>=Modulus/2)then--注意观察Modulus为奇偶数时的波形
ClkOut<='1';
else
ClkOut<='0';
endif;
endif;
endprocess;
endBehavioral
五、仿真结果
✓Modulus=3
✓Modulus=4
实验二序列检测器
一、实验概述
序列检测器可用于检测一组或多组由二进制码组成的脉冲序列信号,这在数字通信领域有广泛的应用。
如下图,RST为复位信号,低电平有效。
在时钟CLK作用下,串行二进制码数据从DIN输入。
D[7..0]为预先设置的码。
当序列检测器连续收到一组串行二进制码后,当这组码出现与检测器中预先设置的码相同码时,A输出1,否则输出0。
二、实验目的
掌握有限状态机的描述。
三、实验要求
1.画出状态转移图2.编写源程序
3.用VHDL建立测试平台TestBench4.采用ModelSim进行仿真
四、状态转移图
五、实验代码
VHDL源程序(部分代码)
✓次态逻辑进程
COM:
process(clk,rst,data_buf,seq_buf,current_state)
begin
casecurrent_stateis
whenidle=>--空闲状态
next_state<=compare;
Aout_buf<='0';
whencompare=>--比较状态(工作状态)
next_state<=compare;
if(data_buf=seq_buf)then
Aout_buf<='1';
else
Aout_buf<='0';
endif;
endcase;
endprocess;
✓状态寄存器进程
REG:
process(clk,rst)
begin
if(rst='0')then--异步复位
seq_buf<="00000000";
current_state<=idle;
elsif(rising_edge(clk))then
seq_buf<=seq_buf(6downto0)&din_buf;--输入din串转并
current_state<=next_state;
endif;
endprocess;
✓输出进程
LATCH:
process(clk,rst,Aout_buf)
begin
if(rst='0')then
Aout<='0';
elsif(rising_edge(clk))then
Aout<=Aout_buf;
endif;
endprocess;
Test-Bench(部分代码)
✓定义句柄
filedin_vec:
textopenread_modeis"din.vec";
filedata_pre:
textopenread_modeis"data_pre.vec";
fileresult:
textopenwrite_modeis"d_resuly.out";
✓激励进程
stim_proc:
process
variabledin_line:
line;--输入比特流(按行计)
variabledin_bit:
std_logic;--输入比特流(按比特计)
variabledata_line:
line;--预置序列(按行计)
variabledata_byte:
std_logic_vector(7downto0);--预置序列
variableout_line:
line;--输出结果(端口A的输出)
begin
whilenotendfile(din_vec)loop
clk<='0';
readline(din_vec,din_line);
read(din_line,din_bit);
readline(data_pre,data_line);
read(data_line,data_byte);
data<=data_byte;
din<=din_bit;
waitfor10ns;
clk<='1';
write(out_line,string'("Time="));--向.out文件中写入结果
write(out_line,now);
write(out_line,string'(":
Theresultis:
"));
write(out_line,Aout);
write(out_line,string'(".(1-->mathc;0-->notmatch)"));
writeline(result,out_line);
waitfor10ns;
endloop;
wait;
endprocess;
六、仿真结果
如下图所示(见下页),预置序列“10101010”从初始时刻开始就给到输入端“data”,之后端口“din”的数据利用TEXTIO模式从.vec文件中读取。
经过一段时间,到达
时刻后,A端口输出持续一个时钟周期高电平,反观此前8个时钟周期的输入数据din,发现恰好是“10101010”。
继续观察发现
、
时刻A端口也输出了持续1个时钟周期的高电平,经检验之前8个时钟周期的din也符合“10101010”。
另一方面,当某8个连续时钟周期的din不满足“10101010”的组合时,A端口的输出均为‘0’(尽管没有穷举非10101010的情况)。
因此可以认为该状态机的功能符合设计要求。
Figure1Modelsim仿真结果
七、实验感悟
在本次试验中,我学习了有限状态机(Mealy型)的编写方法。
1.画状态转移图
2.选择合适的描述风格(我选择的描述风格是三个进程,分别是次态逻辑进程、状态寄存器进程、输出逻辑进程)。
3.编写VHDL代码。
通过以上若干步骤,我基本掌握了有限状态机的描述。
实验三2FSK解调电路
一、自拟题目
设计并实现一个2FSK解调器。
外部一个2FSK调制的正弦信号,幅度为0~3V,f_1=500Hz,f_2=2KHz.使用ADC采集信号,在FPGA内做2FSK解调(相干或非相干),在示波器上观察输出信号,并且与信号源输入波形对比。
仿真平台:
Matlab和Modelsim。
二、题目分析
2FSK信号是用载波频率的变化表征被传递信息的状态的,被调制载波的频率随着二进制信号的0、1状态而变化,即载频为
代表传“0“,即载频为
代表传“1“。
我们的任务是解调上述2FSK信号,从中获取传输的二进制信息。
解调的方式有相干解调和非相干解调两种。
其中相干解调的系统框图如下所示,它是将信号先前值滤波得到两路载波分量,再用乘法器对信号进行非线性变换,混频得到有用的低频分量和多余的高频分量,接着经过低通滤波器后,根据提取到的位同步时钟抽样判决,最终获得解调输出。
图表2-1相干解调实现框图
另一种是非相干解调。
在模拟电路中实现非相干解调的方法常常是利用锁相环路的鉴频功能,但在数字电路中,数字鉴频的方法更为可取。
三、方案一的设计、仿真
1.系统级设计及simulink仿真
1.1设计
2FSK调制信号生成模块:
为了在模型中获得2FSK调制波形,我们设计了下面的模块,两个离散正弦源产生的信号分别与矩形波及其反相信号相乘然后相加。
再把它封装成一个Mask,Mask与外部的接口参数一共五项,如下图所示,使用时只须输入下列数据就可以得到想要的2FSK波形。
图表3-1调制信号源及其封装效果
2FSK信号解调模块:
该模块中,2FSK调制波形首先分别与两路不同频率的本振信号做乘积混频,得到的结果经过FIR低通滤波器(设计方法及参数见后)滤除高频分量后,进入门限判决模块(内部结构见后),最终从门限判决器的输出端口得到2FSK的解调信号。
图表3-2解调系统框图
FIR低通滤波器:
在MATLAB中调用DSPSystem工具箱中的FilterDesign&AnalyzeTool,在下图所示的界面中设计滤波器。
考虑到信号经过滤波器后要保持线性相位,以及硬件设备的资源问题,我们采用FIR滤波器;确定参数时,首先考虑调制信号中高频分量为2KHz,为了满足Nyquist采样定理以及考虑到工程实践中的实际效果,我们确定采样频率为10KHz,又由于有用的低频分量频率非常低,且需要滤除1KHz及更高的频率分量,所以我们把通带设为50Hz,阻带频率设为500Hz,最终设计结果如下图所示。
把滤波器的系数导出到Workspace中,再赋给simulink中的滤波器模型即可。
(此处滤波器为56阶,但在VHDL实现时考虑到复杂程度及资源问题把阶数降到了46阶)。
图表3-3FIR滤波器参数设计
1.2仿真
假设本振信号的频率非常准确,当2FSK输入信号理想时,得到如下结果:
图表3-4理想情况结果
我们只观察1~4图形。
图形一是2FSK调制波形,窗口2是与500Hz的本振信号混频后的波形,窗口3是经过FIR低通滤波器后的结果,窗口4是经过门限判决后最后得到的解调信号。
当码元频率为
时,混频、滤波后其对应的输出是高电平1;
与之相反,输出是低电平0。
这样的结果符合预期。
2.VHDL实现(子模块描述)
图表3-6RTL模型
输入输出端口定义:
输入端口:
clk——系统总时钟
bfsk_in——基带仿真信号输入
输出端口:
bfsk_out——FSK信号解调输出
sig_filter——滤波器输出
bfsk_in_com——基于仿真信号
sig_mul——混频器输出
sig_sin_osc——本振信号输出
2.110kHz时钟模块
此模块完成时钟分频,为后续模块提供统一的采样频率。
2.2NCO模块
相干解调方法中,如何产生准确本振信号非常重要。
下图是NCO的参数设置界面,在参考多方资料及仿真尝试后,我们确定了如下参数,并生成NCO核及其VHD文件。
图表3-7NCO参数设置
NCO的VHD实体与外部的接口有7个:
phi_inc_i:
INSTD_LOGIC_VECTOR(31DOWNTO0);
clk:
INSTD_LOGIC;
reset_n:
INSTD_LOGIC;
clken:
INSTD_LOGIC;
fsin_o:
OUTSTD_LOGIC_VECTOR(9DOWNTO0);
fcos_o:
OUTSTD_LOGIC_VECTOR(9DOWNTO0);
out_valid:
OUTSTD_LOGIC
其中输入端口需要的设置是:
(1)给“phi_inc_i”42950的相位步进值。
(2)给“clk“一个50MHz的时钟。
(3)“reset_n“、”clken“置高。
实际用到的输出端口是“fsin_o“,它输出的是500Hz的正弦信号。
2.3乘法器模块
将2FSK信号与NCO输出信号混频,得到的信号包含直有用的直流信号和无用的高频信号。
2.4FIR数字滤波器
我们按照前文中所述的方法设计出FIR低通滤波器后,按照其系数自己编写了FIR滤波器的VHDL程序。
为了提高运算效率、节省资源,我们采用了“行波流水“的存储方式来实现各级的延时器
。
即在每个时钟周期将delay_pipeline(0)到delay_pipeline(44)整体移位到delay_pipeline
(1)~(45),然后再把这一时刻的输入信号存放到delay_pipeline(0)当中。
这样,Quaturs综合出的电路是46个8位的并行移位寄存器,每个时钟周期进行一次整体移位。
另外,根据DSP所学,FIR数字滤波器具有线性相位的特性,其系统函数的系数是“前后对称“的,我们利用这一点可以将乘法器的个数减半,极大地节省了资源(原理如下图所示)。
图表3-8FIR滤波器框图
延时器的代码如下:
PROCESS(clk)
BEGIN
IF(clk'eventANDclk='1')THEN
IF(clk_enable='1')THEN
delay_pipeline(0)<=filter_in;
delay_pipeline(1TO45)<=delay_pipeline(0TO44);
ENDIF;
ENDIF;
ENDPROCESS;
2.5门限判决模块
该模块对滤波器的输出做0、1判决,得到最终的解调输出信号。
3.MATLAB与Modelsim联合仿真
3.1仿真过程描述
在仿真阶段,我们利用MATLAB生成bfsk调制信号的数据存放在.vec文本文档中,并用在testbench中书写相关代码,使Modelsim读入这些数据作为系统的输入信号;仿真过程中,由Modelsim实时地导出解调信号的数据,存放在相应.out文本文档中;仿真结束后,用MATLAB读取.out文档中的数据,绘制出解调后的波形。
这样就实现了MATLAB和Modelsim的联动仿真,极大提高了仿真、分析的效率。
3.2仿真结果
图表3-9modelsim仿真输出波形
图表3-10MATLAB的GUI绘图结果
四、结论与感受
观察图3-9发现,modelsim仿真结果和设计系统时simulink仿真的结果是完全一致的,这表明基于VHDL的程序编写是正确的。
对比图3-9和图3-10发现,modelsim输出的数据文件被matlab的gui仿真工具读入并且绘图后的结果和modelsim仿真结果是一致的,这表明基于VHDL的textIO仿真是正确的。
经过这次实验,我练习了层次化设计方法、用TEXTIO模式仿真,收获颇丰。
五、附录
1.VHDL源代码(部分)
1.1顶层文件
……
Entityfilter_testis
port(
clk:
instd_logic;
bfsk_in:
instd_logic_vector(7downto0);
bfsk_out:
outstd_logic;
bfsk_in_com:
outstd_logic_vector(7downto0);
sig_sin_osc:
outstd_logic_vector(7downto0);
sig_mul:
outstd_logic_vector(7downto0);
sig_filter:
outstd_logic_vector(7downto0)
);
endfilter_test;
architecturebehavioroffilter_testis
signalclk_enable:
std_logic;
signalrst_fir:
std_logic;
signalfs_10khz:
std_logic;
signalfilter_in:
std_logic_vector(7downto0);
signalfilter_out:
std_logic_vector(7downto0);
signalsin_2khz:
std_logic_vector(7downto0);
signalclk_50hz:
std_logic;
signalbfsk_in_com1:
std_logic_vector(7downto0):
="00000000";
begin
clk_enable<='1';
rst_fir<='0';
bfsk_in_com1<=bfsk_in-"10000000";
bfsk_in_com<=bfsk_in_com1;
u1:
sampling_freq_10khzportmap(clk,fs_10khz);
u2:
sin_oscportmap(clk,fs_10khz,sin_2khz);
sig_sin_osc<=sin_2khz;
u3:
multiplierportmap(fs_10khz,bfsk_in_com1,sin_2khz,filter_in);
sig_mul<=filter_in;
u4:
fir_newportmap(fs_10khz,clk_enable,rst_fir,filter_in,filter_out
);
sig_filter<=filter_out;
u5:
threshold_decisionportmap(fs_10khz,filter_out,bfsk_out);
endbehavior;
1.2时钟分频子模块(省略)
1.3乘法器子模块
……
entitymultiplieris
port(
fs_clk:
instd_logic;
signal1,signal2:
instd_logic_vector(7downto0);
signal3:
outstd_logic_vector(7downto0)
);
endmultiplier;
architecturebhofmultiplieris
signalbuf_sig:
std_logic_vector(15downto0):
="0000000000000000";
begin
process(fs_clk)
begin
if(rising_edge(fs_clk))then
buf_sig<=signal1*signal2;
endif;
endprocess;
signal3<=buf_sig(15downto8);
endbh;
1.4FIR滤波器子模块(省略)
1.5门限判决子模块
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_signed.all;
entitythreshold_decisionis
port(
fs_clk:
instd_logic;
signal_in:
instd_logic_vector(7downto0);
signal_out:
outstd_logic:
='0'
);
endthreshold_decision;
architecturebhofthreshold_decisionis
begin
process(fs_clk,signal_in)
begin
if(rising_edge(fs_clk))then
if(signal_in>"11101100")then
signal_out<='0';
else
signal_out<='1';
endif;
endif;
endprocess;
endbh;
1.6NCO子模块(IP核,省略)
2.仿真测试源程序
……
architecturebhvoffilter_test_tbis
signalclk:
std_logic:
='1';
signalbfsk_in:
std_logic_vector(7downto0);
signalbfsk_in_com:
std_logic_vector(7downto0);
signalbfsk_out:
std_logic;
signalsig_sin_osc:
std_logic_vector(7downto0);
signalsig_mul:
std_logic_vector(7downto0);
signalsig_filter:
std_logic_vector(7downto0);
componentfilter_testis
port(
clk:
instd_logic;
bfsk_in:
instd_logic_vector(7dow