基于FPGA数字秒表的设计实现
一、测试要求
1 有源晶振频率:48MHZ
2 测试计时范围:00’00”00 ~ 59’59”99,显示的最长时间为59分59 秒
3 数字秒表的计时精度是10ms
4 显示工作方式:
a、用八位BCD七段数码管显示读数
b、采用记忆显示方法
c、用两个按钮开关(一个按钮使秒表复位,另一个按钮
控制秒表的启动/暂停)
二、设计要求
1 设计出符合设计要求的解决方案
2设计出单元电路
3 利用软件对各单元电路及整体电路进行仿真
4 在开发板上实现设计
5 撰写设计报告
三、秒表功能键
1、power:秒表电源键
2、Reset:秒表复位清零键
3、run/stop:秒表启动/停止键
四、实验原理
1 实验设计原理
(1)、秒表的逻辑结构较简单,它主要由十进制计数器、六进制计数器、分频器、数据选择器、和显示译码器等组成。在整个秒表中最关键的是如何获得一个精确的100HZ计时脉冲,除此之外,整个秒表还需有一个启动信号和一个清零信号,以便秒表能随意停止、启动以及清零复位。
(2)、秒表有共有8个输出显示,其中6个显示输出数据,分别为百分之一秒、十分之一秒、秒、十秒、分、十分,所以共有6个计数器与之相对应;另外两个为间隔符,显示‘-’。8个计数器的输出全都为BCD码输出,这样便与同显示译码器连接。
(3)、可定义一个24位二进制的寄存器hour用于存放8个计数器的输出,寄存器从高位到低位每连续4位为一组,分别存放百分之一秒、十分之一秒、间隔符、秒、十秒、间隔符、分、十分。由频率信号输出端输出频率为100HZ的时钟信号,输入到百分之一秒模块的时钟端clk,百分之一秒模块为100进制的计数器,当计数到“1001”时,百分之一秒模块清零,同时十分之一秒模块加1;十分之一秒模块也为100进制的计数器,当计数到“1001”时,十分之一秒模块清零,同时秒模块加1;以此类推。直到分模块计数到59进59。
(4)、为了消除按键消抖问题,定义寄存器key-inner来存储按键key的输入信号,key-flag作为启动/暂停的转换标志,key-inner[0]出现一个下降沿时,key-flag取反一次,当key-flag为0时计数器启动,1时计数器暂停,当key-flag为1同时key-inner[1]为9时,计数器清零。
(5)、定义18位寄存器count用于存放分频和扫描用的计数值。48MHZ的时钟信号480000分频,得到100HZ的时钟信号,而计数器已48MHZ的时钟信号218分频扫描8个七段译码器。
2 实验设计方案
利用一块芯片完成除时钟源,按键和显示器之外的所有数字电路功能。所有数字逻辑功能都在CPLD器件上用Verilog语言实现。这样设计具有体积小,设计周期短,调试方便,故障率地和修改升级容易等特点,本设计采用依次进行消抖、分频、数码管动态扫描、显示(译码)和计数流水线的设计方法。
3 实验原理框图
秒表原理框图
五、软件设计与波形仿真
1、秒表计数单位与对应输出信号
2、计数器总程序:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 20:10:58 04/19/2012
// Design Name:
// Module Name: mbiao1
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
/////////////////////////////////////////////////////////////////////////////////
module mbiao1(clk_48M,dig,seg,ena,key);
input[1:0] key;
input clk_48M; //输入频率为48MHZ的时钟
output[2:0] dig; //数码管位选
output[7:0] seg; //数码管段选
output ena; //3-8译码器使能
reg[2:0] dig,count3b;
reg[7:0] seg;
reg[3:0] disp_dat; //定义显示数据寄存器
reg[18:0]count; //定义计数寄存器
reg[23:0]hour; //定义现在时刻寄存器
reg clk100; //48MHZ的时钟信号480000分频,得到100HZ的时钟信号
reg key_flag; //启动/暂停的切换标志
reg [1:0]key_inner;
assign ena=0;
//按键输入缓存
always @(posedge count[16])
begin
key_inner<= key;
end
always @(negedge key_inner[0])
begin
key_flag=~key_flag;
end
//0.01秒信号产生部分,产生100HZ的时钟信号
always @ (posedge clk_48M)
begin
if(count==239999)
begin
clk100<=~clk100;
count<=0;
end
else
count<=count+1'b1;
end
//数码管动态扫描显示部分
always @(posedge count[10])
begin
count3b=count3b+1;
case(count3b)
3'd0:disp_dat=hour[3:0];
3'd1:disp_dat=hour[7:4];
3'd2:disp_dat=4'ha;
3'd3:disp_dat=hour[11:8];
3'd4:disp_dat=hour[15:12];
3'd5:disp_dat=4'ha;
3'd6:disp_dat=hour[19:16];
3'd7:disp_dat=hour[23:20];
default:disp_dat=4'bxxxx;
endcase
dig=count3b;
end
always @(disp_dat)
begin
case(disp_dat)
4'h0:seg=8'hc0;
4'h1:seg=8'hf9;
4'h2:seg=8'ha4;
4'h3:seg=8'hb0;
4'h4:seg=8'h99;
4'h5:seg=8'h92;
4'h6:seg=8'h82;
4'h7:seg=8'hf8;
4'h8:seg=8'h80;
4'h9:seg=8'h90;
4'ha:seg=8'hbf;
default:seg=8'bxxxxxxxx;
endcase
end
//计时处理部分
always @(posedge clk100)//计时处理
begin
if(!key_inner[1]&&key_flag==1) //判断是否复位键
begin
hour = 24'h0;
end
else if(!key_flag)
begin
hour[3:0] = hour[3:0] + 1;
if(hour[3:0] == 4'ha)
begin
hour[3:0] = 4'h0;
hour[7:4] = hour[7:4] + 1;
if(hour[7:4] == 4'ha)
begin
hour[7:4] = 4'h0;
hour[11:8] = hour[11:8] + 1;
if(hour[11:8] == 4'ha)
begin
hour[11:8] = 4'h0;
hour[15:12] = hour[15:12] + 1;
if(hour[15:12] == 4'h6)
begin
hour[15:12] = 4'h0;
hour[19:16] = hour[19:16] + 1;
if(hour[19:16] == 4'ha)
begin
hour[19:16] = 4'h0;
hour[23:20] = hour[23:20] + 1;
end
if(hour[23:20] == 4'h6)
hour[23:20] = 4'h0;
end
end
end
end
end
end
endmodule
2.1计数时的仿真波形
2.2清零时的仿真波形
2.3暂停时的仿真波形
六、硬件实现
1、用ISE软件对程序进行编译,并下载到硬件FPGA板子上进行硬件实现。板子上6个计数器与百分之一秒、十分之一秒、秒、十秒、分、十分相对应,并且开始00’00”00 ~ 59’59”99的计数,用两个数码管显示“-”用于分与十秒的间隔,十分之一秒与秒的间隔。
2、Run/stop和Reset功能键由FPGA板子上的开关栏的key[0]和key[1]代替。按一下key[0]键,数码管上的时间停止计时,然后按下key[1]键,数码管上时间清零复位为00’00”00;接着再按一下key[0]键,数码管从新开始计时。
七、心得体会
刚开始写程序时常因Verilog HDL语言的不熟悉,常出现综合错误的问题,但只要仔细检查、并经常使用该语言后,就会在很大程度上避免诸如语法错误等非逻辑问题。在定义寄存器用于计数功能时,最好先赋初值。对于复杂的逻辑功能的电路实现,可以采用分模块的方法,以便检查程序的正误,而对于功能较简单的电路设计,只需要一个模块,从而避免在模块间连接时出现错误。对于需要存放的比较大数据,最好直接采用整型,而不用定义寄存器,从而避免数据溢出。写程序时应该养成良好的书写习惯,如在关键处加备注;定义变量、工程名、文件名时应用能“望词生义”的效果;嵌套程序应对齐书写等。
数字秒表设计
系别:电子通信工程系
专业:电子信息工程
班级:
学号:
姓名:
数字秒表(基于verilong语言编程)课程设计
一、设计要求
用verilong语言编写程序,结合实际电路,设计一个4位LED数码显示“秒表”,显示时间为99.9~00.0秒,每秒自动减一,精度为0.1。另设计一个“开始”按键和一个“复位”按键。再增加一个“暂停”按键。
按键说明:按“开始”按键,开始计数,数码管显示从99.9开始每秒自动减一;按“复位”按键,系统复位,数码管显示99.9;按“暂停”按键,系统暂停计数,数码管显示当时的计数。
二、设计目的
1、 通过本次课程设计加深对verilong语言课程的全面认识、复习和掌握,对EPM7064芯片的应用达到进一步的了解。
2、 掌握定时器、外部中断的设置和编程原理。
3、 通过此次课程设计能够将软硬件结合起来,对程序进行编辑,调试。使其能够通过电脑下载到芯片,正常工作。
4、实际操作Quartus II软件,复习巩固以前所学知识。
三、总体设计
本秒表系统具有复位、暂停、秒表计时等功能。 clk为系统工作时钟,采用Altera DE2上的50M时钟信号,经过分频器产生秒表计时周期为0.01s的时钟,再经过计数器,分别对秒表的百分位、十分位、秒、秒十位、分、分十位进行计数。onoff为启动/暂停控制信号,当它为0时,启动计时,当它为1时,计时暂停。clr为复位信号,当该信号有效时,计数器和译码清零,此时数码管显示输出为00:00:00。在总体电路图中,根据设计要求,需要两个输入控制信号onoff和clr。由于开发板上除了拨动开关就是瞬时的按键开关,且按键开关平时都呈高电平,按一下为低电平。故在实际测试时采用了拨动开关SW0来控制秒表的启动/暂停,通过KEY0来控制秒表的清零。
四、设计思路描述
该实验要求进行计时并在数码管上显示时间,通过相关软件Quartus II编译,利用JTAG下载电路到核心芯片,驱动硬件工作。Altera_EPM7064(84PIN)有四个引脚GCLK1(83脚),GCLRn(1脚),OE1(84脚),OE2(2脚)。GCLK1是全局时钟,GCLRn(1脚是全局清零,OE1(84脚),OE2(2脚)是全局使能实现“开始”按键的功能;实现“清零(复位)”按键的功能;做为时钟信号CLK输入的入口地址。可将开关设计与此,其优势在在于到达延迟时间相等。其中“开始”按键当开关由1拨向0(由上向下拨)时开始计时;“清零(复位)”按键当开关由1拨向0(由上向下拨)时数码管清零(复位),此时若再拨“开始”按键则又可重新开始计时。
1) 电源部分需要并联四个电容,以达到滤波作用,获得实验所需的电压;
2) 利用三极管分别连接LED数码管和EPM7064,起到放大(电流)作用;
3) 本实验时钟信号的产生有晶振直接提供,同时由编写的子程序决定输出频率;
4) 芯片所需程序由计算机编译,采用Quartus II软件,编译调试无误后,进行下载;
5) IDI、TMS、TCK、TDO是JTAG的标准线。用来实现连接芯片,实现下载功能。
五、原理图
1
跟据数字秒表的原理图如图一所示,为设计项目选定CyclongII系列中的EP2C35F672C6器件,锁定顶层设计中各端口所对应的引脚号,并编译通过。然后对器件编程,使用USB-Blaste下载电缆把项目以在线配置的方式下载到Altera DE2实验板的EP2C35F672C6器件中。该数字式秒表具有清零功能,通过KEY0来控制,能够在计时过程中随时清零。用SW0键来控制锁存/计时,能在计时过程中通过按SW0键,SW0拨动开关打上时计时暂停,打下时仍继续。实验证明该秒表工作正常,基本上已达到了预期的设计要求。
图一、数字秒表原理图
2
六、PCB图
图二、数字秒表PCB图
七、系统软件设计
在设计电路时,要遵循从上到下的设计原则。首先从系统设计入手,在顶层进行功能划分和结构设计,顶层模块的每个层次模块均可完成一个较为独立的功能,次模块在调试成功后可生成一个默认符号,以供上一层模块调用。本系统由4个模块组成,分别是分频电路模块、模10计数模块和动态译码显示模块。本设计最小计时单位为0.1s,设计时需获得一个比较精确的10Hz(周期为0.1s)的计时脉冲。由于最终的设计结果要下载到可编程逻辑器件中测试,因此可利用Altera DE2开发板的12M晶振时钟。将12M时钟信号CLK送到分频器CLKGEN进行60万分频后,得到10Hz的频率由NEWCLK输出。采用Verilog语言编程,编译无误通过后创建默认文件符号CLKGEN以供上层电路调用。程序实现如下:
module clock(clk,key,dig,seg); //模块名clock
input clk; //输入时钟
input[1:0] key; //输入按键
output[7:0] dig; //数码管选择输出引脚
output[7:0] seg; //数码管段输出引脚
reg[7:0] seg_r; //定义数码管输出寄存器
reg[7:0] dig_r; //定义数码管选择输出寄存器 reg[3:0] disp_dat; //定义显示数据寄存器
reg[24:0]count; //定义计数寄存器
reg[15:0]hour; //定义现在时刻寄存器
3
reg sec,keyen; reg[1:0]dout1,dout2,dout3; wire[1:0]key_done;
assign dig = dig_r; assign seg = seg_r;
//秒信号产生部分
always @(posedge clk) begin
count = count + 1'b1;
if(count == 25'd6000000) begin
count = 25'd0; sec = ~sec; end
end
//按键消抖处理部分
assign key_done = (dout1 | dout2 | dout3);
always @(posedge count[17]) begin
dout1 <= key;
dout2 <= dout1;
dout3 <= dout2;
end
always @(negedge key_done[0]) begin
keyen = ~keyen; end
//数码管动态扫描显示部分
always @(posedge clk) begin
case(count[17:15]) 3'd0:disp_dat = hour[3:0]; 3'd1:disp_dat = hour[7:4]; 3'd2:disp_dat = hour[11:8]; 3'd3:disp_dat = hour[15:12];
endcase
case(count[17:15]) //定义标志位 //寄存器 //按键消抖输出 //输出数码管选择 //输出数码管译码结果 //定义clock上升沿触发 //0.5S到了吗? //计数器清零 //置位秒标志 //按键消抖输出 //将琴键开关转换为乒乓开关 //count[17:15]大约1ms改变一次 //选择扫描显示数据 //秒个位 //秒十位 //分个位 //分十位 //选择数码管显示位 4
3'd0:dig_r = 8'b11111110; //选择第一个数码管显示 3'd1:dig_r = 8'b11111101; //选择第二个数码管显示 3'd2:dig_r = 8'b11111011; //选择第三个数码管显示 3'd3:dig_r = 8'b11110111; //选择第四个数码管显示
endcase
end
always @(posedge clk)
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:seg_r = 8'hbf; //显示-
default:seg_r = 8'hff; //不显示
endcase
//if((count[17:15]== 3'd2)&sec)
//seg_r = 8'hff;
end
//计时处理部分
always @(negedge sec or negedge key_done[1])//计时处理
begin
if(!key_done[1]) //是清零键吗? begin
hour = 16'h0; //是,则清零 end
else if(!keyen)
begin
hour[3:0] = hour[3:0] + 1'b1; //秒加1
if(hour[3:0] == 4'ha)
begin
hour[3:0] = 4'h0;
hour[7:4] = hour[7:4] + 1'b1; //秒的十位加一
if(hour[7:4] == 4'h6)
begin
5
hour[7:4] = 4'h0;
hour[11:8] = hour[11:8] + 1'b1;//分个位加一
if(hour[11:8] == 4'ha)
begin
hour[11:8] = 4'h0;
hour[15:12] = hour[15:12] + 1'b1;//分十位加一
if(hour[15:12] == 4'h6)
hour[15:12] = 4'h0;
end
end
end
end
end
endmodule
在QuartusII环境下,打开一个新的原理图编辑窗口,然后调入秒表电路设计所需要的50万分频器CLKGEN、十进制计数器/分频器CNT10(4片),译码器DISP,以及电路需要的输入/输出元件。完成电路元件之间和输出/输入之间的连接,并通过QuartusII的编译
八、焊接调试
电路板组装心得:
收集资料,设计出电路原理图,选择元件型号,清点元器件的个数。测试元件,包括测电阻的阻值,根据电路图和电路板本身的实际连通情况开始整体布局连接电路。
电路板焊接心得:
在设计过程中,应该了解其难易,考虑一下焊接的难度。如果比较难就要追求速度(但是也要尽量焊好),如果简单一点,那么在焊接的同时要考虑到焊接工艺。一般情况下,工艺方面的要求就是焊点的光滑、亮度、毛刺这几个方面。一般不会要求电阻的方向之类的。焊接的方式:焊接前看一下元器件,了解一下它们的尺寸规格。然后从低到高开始焊接。
电路板调试心得:
首先,在上电源前先用万用表测试下电源和地之间是否有短路,这样可防止可能烧坏IC等元件。其次,测试电路板的各项功能,须从极端的角度去测试可能会出现的问题。再次,根据产品的性能要求,逐次测试其各个功能是否符合产品要求。最后,调试过程中会遇到各种问题,下面一一分析:第一,电源连接不上,就要查查电源连接电路。第二,电源连接上了,却不能工作,查其他电源是不是供电正常,然后查晶振是否工作。第三,还是工作不正常,目测下主要元件是否有焊反、焊错、短路等现象出现。包括元件用错了,型号不对,元件方向反了,元件的脚有损坏、虚焊、短路等,连接线有损坏或接触不良,电容的正负极焊反等。第四,加密IC焊错了,或没有加载相应的程序。
九、性能指标测试
首先,按照性能指标,测试每项功能是否达到,记录实际测试结果,分析误差、误差原因,以及解决办法。严格按照测试步骤:首先认真调查测试需求和仔细分析测试任务,然后 6
才有可能做好测试的准备工作,只有对测试任务非常清楚,测试目标极其明确的前提下,我们才可能制定出切实可行的测试计划。明确测试目标,详尽测试计划在对测试需求充分了解的基础上,制定尽可能详细的测试计划,对测试的实施是大有裨益的。
十、总结
在QuartusII开发环境下,采用自顶向下的设计方法有利于在早期发现结构设计中的错误,避免不必要的重复设计。再结合基于FPGA 的“在系统”可编程实验板,轻轻松松就能实现各种电子产品的设计,现场观察实验测试结果。大大缩短了产品的设计周期和调试周期,提高了设计的可靠性和成功率,充分体现了可编程逻辑器件在数字电路设计中的优越性。 十一、心得体会
两周时间的课程设计,终于达到了数字秒表系统的要求,尽管还不是十分完美,但从心底里说,还是很高兴的。
通过以上步骤就可以完成对数字秒表的过程设计。这次设计,我克服了很多关于设计问题方面的困难,使我对Protel DXP2004软件的使用有了更进一步的了解,并熟练掌握了一个单片机从编程开发到应用的电脑设计过程。
通过对数字秒表系统的理论设计,使我对已学知识有了更深入的理解,以及对更多模块及单片机芯片元件的功能和类型有了进一步的了解。它使我学到了更多理论知识。在设计制作过程中,我初步了解了电路的原理及设计制作方法,同时也积累了一些经验。在这次的课程设计中,我体会最深的就是,理论与实际的差别,往往理论上十分成熟的技术,在真正实现的过程中还是会出现很多问题,要考虑到诸多因素。通过此次设计,我真正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,只有通过实践,才能不断提高,不断进步。
7
时光流逝,转眼间我在略阳新华书店工作快一年了。回首走过的这段时间,很荣幸能与各位同事共同进步,我也在大家的身上学到不少的知识。我在…
石板小学20xx年卫生工作总结一年来,我校卫生工作在县教育局、莲城教管中心的领导下,完成了校园及学生个人卫生方面的各项工作,有力地…
发布时间:20xx-2-13阅读636次双击滚屏20xx年x月x日中午,公司张灯结彩、人头攒动,一派喜气洋洋,20xx年度工作总结…
东庄煤业安全科20xx年度工作总结20xx年x月日安全科20xx年度工作总结20xx年,安全科在各级领导的大力支持和帮助下,认真贯…
秘书个人工作总结站在岁末,回想过去一年在泰禾俱乐部的工作经历,点点滴滴浮于眼前,从前台接待工作到人事行政工作的转变,让我了解到不同…