FPGA八位十进制数字频率计.docx
《FPGA八位十进制数字频率计.docx》由会员分享,可在线阅读,更多相关《FPGA八位十进制数字频率计.docx(19页珍藏版)》请在冰豆网上搜索。
FPGA八位十进制数字频率计
数字系统设计与VHDL课程设计任务书
一、题目:
基于FPGA的八位十进制数字频率计的设计与仿真
二、主要内容
本次设计是运用FPGA(现场可编程门阵列)芯片来实现一个八位十进制数字频率计,输入信号频率通过数码管来显示。
设计中采用VerilogHDL语言编程,运用QUARTUSⅡ软件实现。
三、基本要求
1.查阅相关原始资料,书写文献综述,英文资料翻译。
2.理解相关的资料,确定系统功能、性能指标,选择系统组成方案。
3.选择系统方案,运用VerilogHDL编程,采用QUARTUSⅡ集成开发环境进行编辑、综合测试,并进行引脚锁定。
4.采用MagicSOPC实验开发平台,以FPGA为核心器件,主控芯片为EP2C35F672C8器件并下载到试验箱中进行验证,最终实现所需的八位十进制数字频率计,并在数码管上显示。
5.撰写研究报告及结果分析,书写课程设计论文。
四、时间安排
时间
主要内容
6月2日-4日
收集资料,熟悉材料
6月5日-6日
程序编辑和仿真
6月9日-11日
修改程序和下载验证
6月12日
答辩和录制视频等
6月13日
书写报告
五、教材及参考书
[1]潘松,王国栋.VHDL实用教程[M].西安:
电子科技大学出版社,2007.
[2]黄智伟.FPGA系统设计与实践[M].北京:
电子工业出版社,2005.
[3]包明.赵明富.EDA技术与数字系统设计[M].北京:
北京航空航天大学出版社,2001.
[4]莫琳,基于FPGA的频率计的设计与实现[J].现代电子技术,2004
[5]EDA修改稿
基于FPGA的八位十进制数字频率计
学生姓名:
学院:
专业班级:
专业课程:
指导教师:
2014年6月15日
一、系统设计
1.系统设计要求
(1)频率测量范围:
1-99.MHZ。
(2)测量误差<5%。
2.方案设计
使用现场可编程逻辑器件(FPGA)制作,利用VerilogHDL硬件描述语言编程进行控制,然后下载烧写实现。
对于八位十进制数字频率计的设计,本方案采用的是现场可编程逻辑器件来实现,它的优点是所有电路集成在一块芯片上,此方案所需的外围电路简单,这样它的体积就减少了,同时还提高了系统的稳定度,还可以用软件QuartusⅡ软件进行仿真和调试等,可以充分利用verilogHDL硬件描述语言方便的编程,提高开发效率,缩短研发周期,降低研发成本;而且易于进行功能的扩展,实现方法灵活,调试方便,修改容易。
3.设计说明
八位十进制数字频率计的基本原理是,测频法和测周期法。
测频法是在确定的时间Tw内,记录被测信号的周期Nx,则测得的频率为Fx=Nx/Tw。
测周期法需要有标准信号频率fs,在待测信号的一个周期Tx内,记录标准频率的周期数,则测得的频率为fx=fs/Ns。
4.设计模块
本设计可有3个模块实现,如下图所示。
顶层模块(时基控制,分频以及对测频的控制);十进制计数器模块,对测量的脉冲进行计数;数码管显示模块,用于测量的结果,通过试验箱上的数码管显示,利用动态扫描显示。
二、软件设计
1.程序框图
程序框图如图1所示。
图1程序框图
2.VerilogHDL源程序(见附录)
三、调试和下载验证
1.实验调试
(1)软件调试
1)运行QuartusII软件。
双击桌面QuartusII9.0或者开始菜单\altera\QuartusII9.0进入程序主窗口。
2)新建源程序文件。
点击File\new\verilogHDLFile,点击ok。
输入程序代码。
3)新建工程。
保存程序代码时,软件会自动提示新建工程,也可以点击取消,创建新的源程序文件,全部模块的源程序创建完成再新建工程,最后把所有模块添加到工程。
两个方法过程都差不多。
点击File\NewProjectWizard点击next,第一行是工程目录,第二行是工程名称,第三行是顶层实体名,这必须与主程序模块名一致。
然后点击next,点击AddAll再点击next,器件选择EP2C35F672C8,再点击next,确定。
4)综合编译。
点击starcompilation进行编译。
编译过程中提示首先提示Decode_8S缺失,仔细检查后发现没有创建Decode_8S源程序文件。
创建好后再编译,提示好几个地方的符号错误,双击错误定位到出现错误的地方,修改好,点击编译,提示一处错误,双击定位到出错地点,发现是逻辑错误,查阅参考书后,把错误修正了。
再点击编译,没有错误。
5)创建波形文件。
点击File\new\vectorwaveformfile,然后添加clk、key、SM_duan节点,设置clk频率,并把key波形随机设置几个1,点击仿真。
(2)硬件调试
在软件调试调试成功的情况下,接下来我们要进行硬件调试,步骤如下:
1)运行QuartusII软件,打开工程。
2)再次编译源程序(见附录)。
3)分配管脚(见附录)。
4)将生成的.sof文件写入FPGA试验箱中。
(3)实物拍照
实物如图2所示。
图2实物照片
2.实验结论
所做的八位十进制数字频率计,当输入信号时就会在数码管上显示被测信号的频率,并且误差很小,只有当被测信号频率特大时会出现误差,其他都和标准频率一样。
四、感受
两周的实训已经过去,对于我来说这两周的实训赋予了我太多实用的东西了,不仅让我更深层次的对课本的理论知识深入了理解,而且还让我对分析事物的逻辑思维能力得到了锻炼,提高了实际动手能力,下面谈一下就这两周实训中我自己的一些心得体会。
我们在老师提供的实践平台上通过自己的实践学到了很多课本上学不到的宝贵东西,熟悉了对相关软件的一般项目的操作和学到了处理简单问题的基本方法,更重要的是掌握了verilogHDL语言的基本设计思路和方法,我想这些会对我今后的学习起到很大的助推作用。
此外,还要在今后的课本理论知识学习过程中要一步一个脚印的扎实学习,灵活的掌握和运用专业理论知识这样才能在以后出去工作的实践过程中有所成果。
其次,在连接各个模块的时候一定要注意各个输入、输出引脚的线宽,因为每个线宽是不一样的,只要让各个线宽互相匹配,才能得出正确的结果,否则,出现任何一点小的误差就会导致整个文件系统的编译出现错误提示,在器件的选择上也有一定的技巧,只有选择了合适当前电路所适合的器件,编译才能得到完满成功。
通过这次课程设计使我懂得了理论与实际相结合很重要,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。
最后还要感谢学校为我们提供这样专业的实践平台还有实训老师在两周实训以来的不断指导和同学的热情帮助。
总的来说,这次实训我收获很大。
参考文献
[1]夏宇闻.Verilog数字系统教程[M].北京:
北京航空航天出版社,2006.
[2]梁瑞宇.FPGA设计实验指导书(VerilogHDL)[M].北京:
北京航空航天出版社,2008.
[3]潘松著.EDA技术实用教程-Verilog_HDL版(第4版)[M].北京:
科学出版社,2010.
附录源程序
八位十进制数字频率计程序实现如下
modulefreqtest(clock,clock0,dig,seg);
inputclock;//系统时钟
inputclock0;//被测信号输入
output[7:
0]dig;//数码管选择输出引脚
output[7:
0]seg;//数码管段输出引脚
reg[25:
0]counter;//时钟分频计数器
reg[31:
0]freq_result;//频率测量结果寄存器
wire[31:
0]pre_freq;//脉冲计数寄存器
regrst;
wiredivide_clk;//1Hz闸门信号
wireclk_scan;//数码管扫描显示时钟
wirecout1,cout2,cout3,cout4,cout5,cout6,cout7;
assignclk_scan=counter[15];//动态扫描时钟
//时钟分频进程:
分出1Hz基准信号
always@(posedgeclock)
begin
if(divide_clk)
counter<=26'd0;
else
counter<=counter+1'b1;
end
assigndivide_clk=(counter>=26'd);
//锁存测量值进程
always@(posedgeclock)
begin
if(divide_clk)
freq_result<=pre_freq;
end
//产生计数器复位信号
always@(posedgeclock)
begin
if(divide_clk)
rst<=1'b1;
else
rst<=1'b0;
end
//8位十进制计数模块:
由8个十进制计数模块构成
cnt10u1(.clock(clock0),.rst(rst),.cin(1'b1),.cout(cout1),.dout(pre_freq[3:
0]));
cnt10u2(.clock(clock0),.rst(rst),.cin(cout1),.cout(cout2),.dout(pre_freq[7:
4]));
cnt10u3(.clock(clock0),.rst(rst),.cin(cout2),.cout(cout3),.dout(pre_freq[11:
8]));
cnt10u4(.clock(clock0),.rst(rst),.cin(cout3),.cout(cout4),.dout(pre_freq[15:
12]));
cnt10u5(.clock(clock0),.rst(rst),.cin(cout4),.cout(cout5),.dout(pre_freq[19:
16]));
cnt10u6(.clock(clock0),.rst(rst),.cin(cout5),.cout(cout6),.dout(pre_freq[23:
20]));
cnt10u7(.clock(clock0),.rst(rst),.cin(cout6),.cout(cout7),.dout(pre_freq[27:
24]));
cnt10u8(.clock(clock0),.rst(rst),.cin(cout7),.cout(),.dout(pre_freq[31:
28]));
//数码管显示模块
scan_ledu9(.clk_1k(clk_scan),.d(freq_result),.dig(dig),.seg(seg));
endmodule
modulecnt10(clock,rst,cin,cout,dout);//10进制计数器
inputclock;//计数时钟
inputcin;//进位输入
inputrst;//复位信号
outputcout;//进位输出
output[3:
0]dout;//计数输出
reg[3:
0]counter;//寄存器
assigndout=counter;
assigncout=cin&&(counter>=4'd9);//进位输出
always@(posedgeclockorposedgerst)
begin
if(rst)
counter<=4'd0;//计数器复位
elseif(cin)//进位输入
begin
if(cout)
counter<=4'd0;
else
counter<=counter+1'b1;
end
end
endmodule
modulescan_led(clk_1k,d,dig,seg);
inputclk_1k;
input[31:
0]d;//输入要显示的数据
output[7:
0]dig;//数码管选择输出引脚
output[7:
0]seg;//数码管段输出引脚
reg[7:
0]seg_r;//定义数码管输出寄存器
reg[7:
0]dig_r;//定义数码管选择输出寄存器
reg[3:
0]disp_dat;//定义显示数据寄存器
reg[2:
0]count;//定义计数寄存器
assigndig=dig_r;//输出数码管选择
assignseg=seg_r;//输出数码管译码结果
always@(posedgeclk_1k)//定义上升沿触发进程
begin
count<=count+1'b1;
end
always@(posedgeclk_1k)
begin
if(d<10)
begin
case(count)//选择扫描显示数据
3'd0:
disp_dat=d[31:
28];//第一个数码管
3'd1:
disp_dat=d[27:
24];//第二个数码管
3'd2:
disp_dat=d[23:
20];//第三个数码管
3'd3:
disp_dat=d[19:
16];//第四个数码管
3'd4:
disp_dat=d[15:
12];//第五个数码管
3'd5:
disp_dat=d[11:
8];//第六个数码管
3'd6:
disp_dat=d[7:
4];//第七个数码管
3'd7:
disp_dat=d[3:
0];//第八个数码管
endcase
case(count)//选择数码管显示位
3'd0:
dig_r=8'b;//选择第一个数码管显示
3'd1:
dig_r=8'b;//选择第二个数码管显示
3'd2:
dig_r=8'b;//选择第三个数码管显示
3'd3:
dig_r=8'b;//选择第四个数码管显示
3'd4:
dig_r=8'b;//选择第五个数码管显示
3'd5:
dig_r=8'b;//选择第六个数码管显示
3'd6:
dig_r=8'b;//选择第七个数码管显示
3'd7:
dig_r=8'b;//选择第八个数码管显示
endcase
end
if(d>10&d<100)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
if(d>100&d<1000)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
if(d>1000&d<10000)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
if(d>10000&d<)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
if(d>&d<)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
if(d>&d<)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
if(d>)
begin
case(count)
3'd0:
disp_dat=d[31:
28];
3'd1:
disp_dat=d[27:
24];
3'd2:
disp_dat=d[23:
20];
3'd3:
disp_dat=d[19:
16];
3'd4:
disp_dat=d[15:
12];
3'd5:
disp_dat=d[11:
8];
3'd6:
disp_dat=d[7:
4];
3'd7:
disp_dat=d[3:
0];
endcase
case(count)
3'd0:
dig_r=8'b;
3'd1:
dig_r=8'b;
3'd2:
dig_r=8'b;
3'd3:
dig_r=8'b;
3'd4:
dig_r=8'b;
3'd5:
dig_r=8'b;
3'd6:
dig_r=8'b;
3'd7:
dig_r=8'b;
endcase
end
end
always@(disp_dat)
begin
case(disp_dat)//七段译码
4'h0:
seg_r=8'hc0;//显示0
4'h1:
seg_r=8'hf9;//显示1
4'h2:
seg_r=8'ha4;//显示2
4'h3:
seg_r=8'hb0;//显示3
4'h4:
seg_r=8'h99;//显示4
4'h5:
seg_r=8'h92;//显示5
4'h6:
seg_r=8'h82;//显示6
4'h7:
seg_r=8'hf8;//显示7
4'h8:
seg_r=8'h80;//显示8
4'h9:
seg_r=8'h90;//显示9
4'ha