VHDL课程设计函数信号发生器.docx
《VHDL课程设计函数信号发生器.docx》由会员分享,可在线阅读,更多相关《VHDL课程设计函数信号发生器.docx(15页珍藏版)》请在冰豆网上搜索。
VHDL课程设计函数信号发生器
学生某某:
学号:
专业:
年级班级:
课程名称:
可编程数字系统设计
实验项目:
VHDL设计一信号发生器
试验时间:
2014年5月24日
指导教师:
一、实验目的:
熟悉EDA工具,掌握用VHDL语言进展数字系统设计的根本方法和流程,提高工程实践能力
二、设计任务
设计信号发生器,用VHDL语言描述,用QuartusII工具编译和综合,并在实验板上调试并实现所要求功能和技术指标,撰写实验报告,最后提交验收并辩论。
题目一:
设计正弦波发生器
题目二:
设计锯齿波发生器
题目三:
设计三角波发生器
三、功能要求与技术指标
根本功能:
〔1〕模拟输出:
由于FPGA上无D/A转换模块,因此设计中必须包含PWM发生模块,PWM输出后经过RC低通波电路转换为电压幅值正比于占空比的模拟电压。
滤波电路需自行设计。
〔2〕可以通过按键设定波形的频率,频率可以显示在数码管上。
〔3〕按钮开关输入须消抖处理。
在完成以上功能的前提下,可增加其它一些实用的功能。
要求:
1、每个同学必须完成根本功能,在完成根本功能的前提下可自由发挥。
2、实验报告主要内容包含:
设计原理、系统分析、程序设计、仿真/实验结果〔例如波形图和实验板运行时的照片〕、结论或分析、使用说明等,在最后附上主要源程序。
3、程序代码结构清晰,可读性强,关键语句应注释。
四、设计原理:
原理图:
原理图〔PS:
RESTA按键已被删除〕
信号发生器的根本工作原理:
1、利用ROM、数组或使用CASE语句将计算的正弦波采样的占空比数据存储。
由分频器将FPGA上的晶振进展分频所得的时钟信号作为计数时钟。
最后进展利用比拟的方式得到占空比可调的脉冲波。
同时,分频器的分频系数可由键盘和数码管配合的显示数值进展运算反应回PWM模块,达到频率可调的目的。
此外,另设一输出接至LED2,无法测量波形的情况下,利用呼吸灯的效果可检测PWM模块的完成与频率可调的成功性。
2、键盘设移位复位键,数码管计数键与频率传送键。
同时设立消抖计数值,当按键按下以后进展计数,在按键退出后,停止计数,取最后一次计数作为按键信号完成按键消抖。
按下移位复位键,数码管位选下一位,同时示数复位清零,并且循环移位,当按完4次按键后,数码管全部清零。
按下数码管计数键,数码管计数,按一次计一次,采用十进制循环计数。
按下频率传送键,将数码管所显示的数值作为频率传送到PWM模块,设频率理论值X围10hz~99990hz。
3、用于按键显示的数码管计数的计数采用十进制。
设定的计数值由四位数码管动态显示,并且被设定的位选数码管‘.’点亮,明确该数码管被选中。
同时通电后,需利用移位复位功能将数码管清零。
五、系统分析:
1、根据原理图与原理框图:
系统电路可分成4个主干模块:
PWM模块、按键消抖模块、按键设定模块、数码管模块。
PWM:
通过对正弦波采样存储并利用时钟分频再进展比拟获得PWM波,同时分频系数由按键与数码管陪和共同反应运算结果进展分频。
按键消抖:
按键按下是会产生不稳定,设定何时的计数时间,再取按键拔起后获得的最后一次计数作为按键信号。
按键设定:
按键计数,按下后数码管进展计数。
移位复位,按下后数码管位选再移位与复位下一位数码管。
频率传送,将数码管示数作为频率传送到PWM模块。
数码管:
动态扫描,频率值显示在数码管上。
2、说明:
数码管显示不稳定,使用前先用移位复位键将示数清零。
测
六、程序设计:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
USEIEEE.NUMERIC_STD.ALL;
ENTITYzxb_maoIS
PORT(CLK:
INSTD_LOGIC;
RIGHTA:
INSTD_LOGIC;--右移输入键
TFILT:
INSTD_LOGIC;--频率选择键
RESTA:
INSTD_LOGIC;--复位输入键
NUMA:
INSTD_LOGIC;--按键计数输入键
PWM:
OUTSTD_LOGIC;
PWM_LED:
OUTSTD_LOGIC;--LED亮灯
SMG:
OUTSTD_LOGIC_VECTOR(7DOWNTO0);--数码管的段数据
DEN:
OUTSTD_LOGIC_VECTOR(3DOWNTO0));--数码管的选通信号
ENDzxb_mao;
ARCHITECTUREsynOFzxb_maoIS
signala,b,c,d:
integerrange0to9;--输入数
signalt:
integerrange0to50000000;--调频频信号
signalnum:
integerrange0to9;--数码管显示计数
signalnum_1:
integerrange0to3;--数码管位移数
signalcount:
integerrange0to50000000;--晶振分频计数
signalcount_key:
integerrange0to2499;--键盘扫描分频
signalclkt:
std_logic;--可调分频时钟
signalcout1:
integerrange0to255;
signal:
integerrange0to255;--采样数据
signaltmp:
std_logic_vector(5downto0);
signalkey1filt:
std_logic;--按键NUMA消抖后得到的信号
signalkey1t:
integerrange0to50000000;--用于对NUMA按键输入有效时间进展计数
signalkey2filt:
std_logic;--按键RIGHTA消抖后得到的信号
signalkey2t:
Integerrange0to50000000;--用于对RIGHT_按键输入有效时间进展计数
signalkey3filt:
std_logic;--按键TFILT消抖后得到的信号
signalkey3t:
integerrange0to50000000;--用于对LIFT_按键输入有效时间进展计数
signalcount1:
integerrange0to500000000;
signalcout2:
std_logic_vector(3downto0);
signalclk1hz:
std_logic;
signalclk100khz:
std_logic;
BEGIN
-----------------------------------PWM模块
PROCESS(CLK)
variabletmp:
integer;--时钟分频实现频率可调
BEGIN
tmp:
=tmp;
IFrISing_edge(CLK)THEN
IFcount=tthen
count<=0;
CLKT<='1';
ELSE
count<=count+1;
CLKT<='0';
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(CLKT)
BEGIN
IFrISing_edge(CLKT)THEN
IFcout1=255THEN
cout1<=0;
tmp<=tmp+1;
IFtmp="111111"then
tmp<="000000";
ENDIF;
ELSE
cout1<=cout1+1;
ENDIF;
ENDIF;
ENDPROCESS;
process(tmp)--正弦波数据采样存储
begin
caseconv_integer(tmp)is
when00=><=255;when01=><=254;when02=><=252;when03=><=249;
when04=><=245;when05=><=239;when06=><=233;when07=><=225;
when08=><=217;when09=><=207;when10=><=197;when11=><=186;
when12=><=174;when13=><=162;when14=><=150;when15=><=137;
when16=><=124;when17=><=112;when18=><=99;when19=><=87;
when20=><=75;when21=><=64;when22=><=53;when23=><=43;
when24=><=34;when25=><=26;when26=><=19;when27=><=13;
when28=><=8;when29=><=4;when30=><=1;when31=><=0;
when63=><=255;when62=><=254;when61=><=252;when60=><=249;
when59=><=245;when58=><=239;when57=><=233;when56=><=225;
when55=><=217;when54=><=207;when53=><=197;when52=><=186;
when51=><=174;when50=><=162;when49=><=150;when48=><=137;
when47=><=124;when46=><=112;when45=><=99;when44=><=87;
when43=><=75;when42=><=64;when41=><=53;when40=><=43;
when39=><=34;when38=><=26;when37=><=19;when36=><=13;
when35=><=8;when34=><=4;when33=><=1;when32=><=0;
whenothers=>null;
endcase;
ENDPROCESS;
PROCESS(CLK)
BEGIN
IFrISing_edge(CLK)THEN
IFcout1>THEN--比拟计数采样PWM
PWM<='0';
PWM_LED<='0';--LED实现PWM检测
ELSE
PWM<='1';
PWM_LED<='1';--LED实现PWM检测
ENDIF;
ENDIF;
ENDPROCESS;
------------------------------------按键消抖模块
PROCESS(NUMA)--NUMA按键消抖
BEGIN
IFCLK'eventandCLK='1'THEN
IFNUMA='0'THEN--当key1输入低电平,即按键按下
IFkey1t/=NTHEN--一直计数到N
key1t<=key1t+1;
ENDIF;
IFkey1t=N-1THEN--最后一个计数时输出key1filt脉冲
key1filt<='1';
ELSE
key1filt<='0';
ENDIF;
ELSE--假如key1输入高电平,明确按键被释放
key1t<=0;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(RIGHTA)--RIGHTA按键消抖
constantN:
integer:
=5000000;
BEGIN
IFCLK'eventandCLK='1'THEN
IFRIGHTA='0'THEN
IFkey2t/=NTHEN
key2t<=key2t+1;
ENDIF;
IFkey2t=N-1THEN
key2filt<='1';
ELSE
key2filt<='0';
ENDIF;
ELSE
key2t<=0;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(TFILT)--TFILT按键消抖
constantN:
integer:
=5000000;
BEGIN
IFCLK'eventandCLK='1'THEN
IFTFILT='0'THEN
IFkey3t/=NTHEN
key3t<=key3t+1;
ENDIF;
IFkey3t=N-1THEN
key3filt<='1';
ELSE
key3filt<='0';
ENDIF;
ELSE
key3t<=0;
ENDIF;
ENDIF;
ENDPROCESS;
------------------------------------四进制计数移动模块RIGHTA
PROCESS(key2filt)
BEGIN
IF(key2filt='1')THEN--按键RIGHTA经消抖处理后
IFnum_1=3THEN
num_1<=0;
ELSE
num_1<=num_1+1;
ENDIF;
ENDIF;
ENDPROCESS;
----------------------------------------十进制计数模块NUMA,RIGHT_,LIFT_
PROCESS(CLK)
BEGIN
IFrISing_edge(CLK)THEN
IFcount_key=249THEN
count_key<=0;
clk100khz<='1';
ELSE
count_key<=count_key+1;
clk100khz<='0';
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clk100khz,key1filt,key2filt)
BEGIN
IFCLK'eventandCLK='1'THEN
IFkey2filt='1'THEN--复位与移位复位
num<=0after50ns;
ELSE
IF(key1filt='1')THEN--按键NUMA经消抖处理后
IFnum=9THEN
num<=0;
ELSE
num<=num+1;
ENDIF;
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
---------------------------------------输入存放模块
PROCESS(num,num_1)
BEGIN
CASEnum_1IS
WHEN0=>a<=num;
WHEN1=>b<=num;
WHEN2=>c<=num;
WHEN3=>d<=num;
WHENothers=>NULL;
ENDCASE;
ENDPROCESS;
------------------------------------------------按键选定频率模块
PROCESS(key3filt)
BEGIN
IFkey3filt='1'THEN
t<=50000000/(((a*1000+1)+(b*100+1)+(c*10+1)+(d*1+1))*256*64);--实现频率可调
ENDIF;
ENDPROCESS;
------------------------------------------------数码管动态扫描频率与显示模块
PROCESS(CLK)
BEGIN
IFrISing_edge(CLK)THEN
IFcount1=24999THEN
count1<=0;
clk1hz<='1';
ELSE
count1<=count1+1;
clk1hz<='0';
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clk1hz)
BEGIN
IFrISing_edge(clk1hz)THEN
IFcout2="1000"THEN
cout2<="0000";
ELSE
cout2<=cout2+1;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(clk1hz)
BEGIN
IFcout2="0000"THEN
DEN<="0111";
CASEaIS
WHEN0=>SMG<="11000000";--0
WHEN1=>SMG<="11111001";--1
WHEN2=>SMG<="10100100";--2
WHEN3=>SMG<="10110000";--3
WHEN4=>SMG<="10011001";--4
WHEN5=>SMG<="10010010";--5
WHEN6=>SMG<="10000010";--6
WHEN7=>SMG<="11111000";--7
WHEN8=>SMG<="10000000";--8
WHEN9=>SMG<="10010000";--9
WHENothers=>NULL;
ENDCASE;
ENDIF;
IFnum_1=0andcout2="0001"THEN
SMG<="01111111";
DEN<="0111";
ENDIF;
IFcout2="0010"THEN
DEN<="1011";
CASEbIS
WHEN0=>SMG<="11000000";--0
WHEN1=>SMG<="11111001";--1
WHEN2=>SMG<="10100100";--2
WHEN3=>SMG<="10110000";--3
WHEN4=>SMG<="10011001";--4
WHEN5=>SMG<="10010010";--5
WHEN6=>SMG<="10000010";--6
WHEN7=>SMG<="11111000";--7
WHEN8=>SMG<="10000000";--8
WHEN9=>SMG<="10010000";--9
WHENothers=>NULL;
ENDCASE;
ENDIF;
IFnum_1=1andcout2="0011"THEN
SMG<="01111111";
DEN<="1011";
ENDIF;
IFcout2="0100"THEN
DEN<="1101";
CASEcIS
WHEN0=>SMG<="11000000";--0
WHEN1=>SMG<="11111001";--1
WHEN2=>SMG<="10100100";--2
WHEN3=>SMG<="10110000";--3
WHEN4=>SMG<="10011001";--4
WHEN5=>SMG<="10010010";--5
WHEN6=>SMG<="10000010";--6
WHEN7=>SMG<="11111000";--7
WHEN8=>SMG<="10000000";--8
WHEN9=>SMG<="10010000";--9
WHENothers=>NULL;
ENDCASE;
ENDIF;
IFnum_1=2andcout2="0101"THEN
SMG<="01111111";
DEN<="1101";
ENDIF;
IFcout2="0110"THEN
DEN<="1110";
CASEdIS
WHEN0=>SMG<="11000000";--0
WHEN1=>SMG<="11111001";--1
WHEN2=>SMG<="10100100";--2
WHEN3=>SMG<="10110000";--3
WHEN4=>SMG<="10011001";--4
WHEN5=>SMG<="10010010";--5
WHEN6=>SMG<="10000010";--6
WHEN7=>SMG<="11111000";--7
WHEN8=>SMG<="10000000";--8
WHEN9=>SMG<="10010000";--9
WHENothers=>NULL;
ENDCASE;
ENDIF;
IFnum_1=3andcout2="0111"THEN
DEN<="1110";
SMG<="01111111"