EDA电子时钟设计
现代电子学实验报告
——第七次实验:多功能数字钟设计
----- 088202070 电子信息科学与技术
摘要:本文利用Verilog HDL语言自顶向下的设计方法设计多功能数字钟,突出了其作为硬件描述语言的良好可读性,可移植性和易理解等优越性,并且通过Altera QuartusⅡ8.0完成综合、仿真,并且程序下载到FPGA芯片后(目标机选用CycloneIII),运行结果稳定有效。
关键字:Verilog HDL;硬件描述语言; FPGA 实验目的
1、 学习和熟悉verilog语言的用法,了解其语言特点,从而熟练掌握verilog编程。 2、 练习运用模块化设计(或者是功能化)的思维设计电路。
3、 按照自己的思路设计出一个具有计时,校时,闹钟,跑表,等功能的时钟。 4、 总结实验感受。 一、 概要
1.1、VerilogHDL
硬件描述语言HDL(Hardware Des—cription Lan—guage)是一种用形式化方法来描述数字电路和系统的语言。目前.电子系统向集成化、大规模和高速度等方向发展,以硬件描述语言和逻辑综合为基础的自顶向下的电路设计方法在业界得到迅猛发展,HDL在这种形势下显示出了巨大的优势,展望将来HDL在硬件设计领域的地位将与c和c++在软件设计领域的地位一样,在大规模数字系统的设计中,它将逐步取代传统的逻辑状态表和逻辑电路图等硬件描述方法,而成为主要的硬件描述工具。 1.2、FPGA
FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(百度百科)
图1.1 实验使用的目标板
据图可见可使用资源:
输入:5个按键KEY0,KEY1,KEY2,KEY3,RESET。 输出:8位数码管,4个LED,一个蜂鸣器。 1.3设计任务 1、计时,时间以24h制显示。 2、校时。 3、闹钟:设定闹钟时间,蜂鸣器提示。 4、跑表:启动、停止。 二、实验原理
2.1、设计思想 根据上面的设计要求,本实验至少分为5个模块,有计时模块,校时模块,闹钟模块,跑表模块,显示模块;这5个模块是完成这个电路设计的最基本的要求,但是仅仅有这五个模块设计显然是不可取的,因为我们得为电路的控制作一些考虑,因为如果纯粹使用逻辑电路设计控制电路,这个过程会显得很繁琐,如果我们设计一个电路控制模块,那显然会大大降低我们的设计复杂度,也是电路看起来更直观一点;所以最终我们需要为这个电路设计6个大的模块;
1、 计时模块
作为一个时钟的最基本的功能——计时,我们很自然就想到用3个计数器来实现,一个24进制的计数器作为时钟的‘时’,其他两个60进制的计数器分别作为时钟的‘分’和‘秒’;
为了达到计时的功能,这个计数器还必须有一个频率为1Hz时钟信号,这样才能让整个时钟跑起来;
所以整个模块的设计图如下图所示:
图2.1.1 时钟模块
2、 校时模块
校时模块主要是对时间的一个校正,所以首先想到的是直接修改计时器的各个计数器,这个思路就是将按键与每个计数器的clk端相连,然后再通过逻辑电路控制计数器的cout端,这样就可以实时对时间进行修改;
还有一种思路就是利用计数器的可置位的特点,在这三个计数器的数据加载端连上一组寄存器或者是存储器RAM,这样我们就可以随时修改存储器,然后通过一个加载信号将数据加载到计数器里面,达到校时的效果,本实验采用的就是这种方法;(事实上计数器就是多个寄存器实现的) 模块设计图如下所示:
图2.1.2 校时寄存器组
3、 闹钟模块
闹钟模块比较复杂,我们可以分三个部分来看它,分别是闹钟时间设定寄存器(存储闹钟时间)、数据比较器、闹铃发生模块;
时间设定寄存器还可以用计数器搞定,比较器是用来比较时钟时间和闹钟时间,一旦时钟时间和闹钟所设定的时间一样就发出闹铃响信号,闹铃发生模块主要是由两个分频器和一个乐谱发生器构成,三个分频器分别是5MHz分频器用来产生乐曲发生分频器的基频,4Hz分频器用来产生乐曲节拍,还有一个减法器是根据乐曲的参数值改变其输出信号的频率;
将这些模块连接起来就组成一个闹钟模块,电路如下图:
图2.1.3 闹钟模块(比较器所连时钟计数器和闹钟设定寄存器未画出) 4、 跑表模块
跑表模块最简单的方法就是直接将时钟模块的分频频率调高100倍,具体不细说。(图略) 5、 电路控制模块
电路控制模块主要负责电路的模式选择,其他的还有按键防抖,和电路位选择器,锁存器以及若干门电路。关于按键防抖是采用的延时方法; 相关电路图如下:
图2.1.4 电路控制(部分电路)
6、 数据显示模块
数据显示模块主要功能是将合适的数据在合适的时间正确的显示出来,这其中除了单纯的显示模块,还需要一个数据选择器管理整个电路的数据。 电路图如下:
图2.1.5 数据显示模块
2.2、电路工作原理 2.2.1、电路顶层图
上图为多功能数字钟端口功能图。其具有的功能有:显示时一分一秒、闹钟、小时+分钟+秒可调和码表等基本功能 2.2.2、电路引脚图
图2.2.1 多功能数字钟端口功能图
2.2.3、主要引脚功能介绍
CLK:50MHZ的系统基准时钟输入。其150000分频作为七段码管扫描频率。将其5000000分频可得到1HZ的数字钟工作频率。将其1000000分频和4分频分别分时送入扬声器,使其产生5MHz基准频率、乐曲(2.5HZ)的节拍。
REST:系统复位信号,低电平有效。
KEY[3..0]:电路操作按键。
78LEDDATA[7..0]: 七段码管显示输出。
78LEDCOM:[7..8]: 七段码管扫描驱动。因为是八个七段码管,所以com为三位总线。扫描频率为10KHZ,由于人眼的视觉效果.呈现在眼前的便是整体的时一分一秒显。
SPK:输出到扬声器产生乐曲。
二、 实验小结
本实验采用了模块设计的思想,将划整个设计要求模块化,划分成几个各具不同功能的电路模块,分清各个模块的相互关系,确定模块的引脚功能和数量,最后再对每个模块进行逐一设计,最后将设计好的模块联系起来。这样统筹地设计电路,化整为零,各个击破的设计思想,大大地降低了设计电路的复杂度,使得思路更加清晰,也便于多人合作完成,和后续的维护。 四、结束语
在本文中采用Verilog HDL语言设计多功能数字钟,借助其功能强大的语言结构,简明的代码描述复杂控制逻辑设计。与工艺无关特性,在提高工作效率的同时达到求解目的,并可以通Verilog HDL语言的综合工具进行相应硬件电路的生成,具有传统逻辑设计方法所无法比拟的优越性。
附录Ⅰ:引脚配置
#Setup.tcl-----Setup pin setting for EP3C25-V5 main board
set_global_assignment -name RESERVE_ALL_UNUSED_PINS
set_location_assignment PIN_148 -to 78ledcom[0] set_location_assignment PIN_147 -to 78ledcom[1] set_location_assignment PIN_160 -to 78ledcom[2] set_location_assignment PIN_159 -to 78ledcom[3] set_location_assignment PIN_162 -to 78ledcom[4] set_location_assignment PIN_161 -to 78ledcom[5] set_location_assignment PIN_166 -to 78ledcom[6] set_location_assignment PIN_164 -to 78ledcom[7]
set_location_assignment PIN_145 -to 78leddata[0] set_location_assignment PIN_143 -to 78leddata[1] set_location_assignment PIN_137 -to 78leddata[2] set_location_assignment PIN_139 -to 78leddata[3] set_location_assignment PIN_144 -to 78leddata[4]
set_location_assignment PIN_146 -to 78leddata[5] set_location_assignment PIN_135 -to 78leddata[6] set_location_assignment PIN_142 -to 78leddata[7]
附录Ⅱ:模块细则(附代码)
一、计数器部分
1.1、可预置数、清零、复位24进制计数器
module
xtm_24cnt(qout,cout,data,load,cin,rst,clk); output[7:0] qout; output cout; input[7:0] data;
input load,cin,clk,rst; reg[7:0] qout;
always@(posedge clk or posedge rst) if(rst) qout
else if(load) qout=data; else if(~cin) begin
1.2、可预置数、清零、复位60进制计数器
module
xtm_cnt60(qout,cout,data,load,cin,rst,clk);
if(qout[3:0]==9) begin
qout[3:0]=0;
qout[7:4]=qout[7:4]+1'b1; end
else if(qout[7:0]==8'h23) qout[7:0]=0;
else qout[3:0]=qout[3:0]+1'b1; end
assign cout=((qout==8'h23)&~cin)?1:0; endmodule
output[7:0] qout;
output cout;
input[7:0] data;
input load,cin,clk,rst; reg[7:0] qout;
always@(posedge clk or posedge rst) if(rst) qout
else if(load) qout=data; else if(~cin) begin
begin
qout[3:0]=0;
if(qout[7:4]==5) qout[7:4]=0; else qout[7:4]=qout[7:4]+1'b1; end
else qout[3:0]=qout[3:0]+1'b1; end
assign cout=((qout==8'h59)&~cin)?0:1; if(qout[3:0]==9) endmodule
二、分频器部分 2.1、1Hz分频器
module xtm_div1Hz(clk,div_out,in); clk_div
else output reg div_out; begin
reg[31:0] clk_div;
clk_div
parameter CLK_FREQ='D50_000_000; div_out
end always@(posedge clk) end
begin
endmodule
if(clk_div
2.2、100Hz分频器
module xtm_div100Hz(clk,div_out,in); clk_div
else output reg div_out; begin
reg[31:0] clk_div;
clk_div
parameter CLK_FREQ='D50_000_000; div_out
end always@(posedge clk) end
begin
endmodule
if(clk_div
2.3、4Hz分频器
module xtm_4H_div(clk,div_out,in); clk_div
else output reg div_out; begin
reg[31:0] clk_div;
clk_div
parameter CLK_FREQ='D50_000_000; div_out
end always@(posedge clk) end
begin
endmodule
if(clk_div
2.4、5MHz分频器
module xtm_5M_div(clk,div_out); clk_div
else output reg div_out; begin
reg[31:0] clk_div;
clk_div
parameter CLK_FREQ='D50_000_000; div_out
begin
endmodule
if(clk_div
3.1、4按键输入电路状态控制器
module
xtm_colock_ctrSystem(rst,ctr0,ctr1,ctr2,ctr3,qout,out_ctr0,out_ctr1,out_ctr2,out_ctr3,out_ctr4,
out_ctr5,out_ctr6,out_ctr7,out_ctr8,out_ctr9,out_ctr10,out_ctr11); input rst;
input ctr0,ctr1,ctr2,ctr3; output[1:0] qout; output
out_ctr0,out_ctr1,out_ctr2,out_ctr3,out_ctr4,out_ctr5,out_ctr6,out_ctr7,out_ctr8,out_ctr9,out_ctr10,out_ctr11; reg[1:0] qout; reg[1:0] cnt0; reg[1:0] cnt1; reg[1:0] cnt2; reg[1:0] cnt3; reg out_ctr0; reg out_ctr1; reg out_ctr2; reg out_ctr3;
reg out_ctr4; reg out_ctr5; reg out_ctr6; reg out_ctr7; reg out_ctr8; reg out_ctr9; reg out_ctr10; reg out_ctr11;
always@(posedge rst or posedge ctr3) if(rst) begin qout=0; end else begin
qout=qout+1; end
always@(posedge ctr0 or posedge ctr1 or posedge ctr2) case(qout) 2'b00: begin
out_ctr0=ctr0; out_ctr1=0; out_ctr2=0; out_ctr3=0; out_ctr4=0; out_ctr5=0; out_ctr6=0; out_ctr7=0; out_ctr8=0; out_ctr9=0; out_ctr10=0; out_ctr11=0; end 2'b01: begin
out_ctr0=0; out_ctr1=0; out_ctr2=0; out_ctr3=ctr0; out_ctr4=0;
out_ctr5=ctr2;
out_ctr7=0; out_ctr8=0; out_ctr9=0; out_ctr10=0; out_ctr11=0; end 2'b10: begin
out_ctr0=0; out_ctr1=0; out_ctr2=0; out_ctr3=0; out_ctr4=0; out_ctr5=0; out_ctr6=ctr0; out_ctr7=ctr1; out_ctr8=ctr2; out_ctr9=0; out_ctr10=0;
3.2、按键输入防抖动器件
module xtm_antishack(clk,in,qout); input in,clk; output qout; 3.3数据锁存器
end 2'b11: begin
out_ctr0=0; out_ctr1=0; out_ctr2=0; out_ctr3=0; out_ctr4=0; out_ctr5=0; out_ctr6=0; out_ctr7=0; out_ctr8=0; out_ctr9=ctr0; out_ctr10=ctr1; out_ctr11=ctr2; end endcase endmodule
reg[15:0]counter;
always@(posedge in or posedge clk) if(in)
counter=60000; else if(counter>0) counter=counter-1;
assign qout=(counter==0)?1'b0:1'b1; endmodule
module xtm_lock(in,q,rst); input in,rst; output q; reg q;
always@(posedge in or posedge rst) if(rst) q
q
3.4电路位选择器
module
xtm_pos_sel(clk,rst,ctr0,ctr1,ctr2,out_ctr0,out_ctr1,out_ctr2); input rst,clk;
input ctr0,ctr1,ctr2;
output out_ctr0,out_ctr1,out_ctr2; reg[1:0] cnt;
reg out_ctr0; reg out_ctr1; reg out_ctr2;
always@(posedge rst or posedge ctr1) 3.5、3-3数据比较器
module
if(rst) cnt=0;
else if(cnt==2) cnt=0; else begin
cnt=cnt+1; end
always@(posedge clk or posedge ctr0) case(cnt) 2'b00: begin
out_ctr0=ctr0; end 2'b01: begin
out_ctr1=ctr0; end 2'b10: begin
out_ctr2=ctr0; end endcase endmodule
xtm_comp(hour,minute,second,M_hour,M_minute,M_second,out); `define MSB 8 input
[`MSB-1:0]hour,minute,second,M_hour,M_minute,M_second; output out; reg out;
always@(minute,M_minute,second) begin
if((minute==M_minute)&&(hour==M_hour)&&(second==M_second)) out=1; else out=0;
end
四、LED显示部分 4.1、LED显示控制器
module
bcd_led=datain0[7:4]; xtm_clockled(clk,reset_n,datain0,datain1,datseg_com=8'b11111101; ain2,seg_data,seg_com); end input clk; 3'b010: input reset_n;
begin
input [7:0] datain0; bcd_led=8'hf;
input [7:0] datain1; seg_com=8'b11111011; input [7:0] datain2; end output [7:0]seg_data; 3'b011: output [7:0]seg_com; begin
bcd_led=datain1[3:0]; reg[7:0]seg_com; seg_com=8'b11110111; reg[7:0]seg_data; end reg[3:0]bcd_led; 3'b100: reg[36:0]count;
begin
always@(posedge clk) bcd_led=datain1[7:4]; begin
seg_com=8'b11101111; if(reset_n) count
begin
always@(count[14:12] or datain0) bcd_led=8'hf;
begin
seg_com=8'b11011111; case(count[14:12]) end 3'b000: 3'b110: begin
begin
bcd_led=datain0[3:0]; bcd_led=datain2[3:0]; seg_com=8'b11111110; seg_com=8'b10111111; end end 3'b001: 3'b111:
begin
begin
bcd_led=datain2[7:4]; 4'h5:seg_data=8'h92;
seg_com=8'b01111111; 4'h6:seg_data=8'h82; end 4'h7:seg_data=8'hf8; endcase 4'h8:seg_data=8'h80; end 4'h9:seg_data=8'h90;
4'ha:seg_data=8'h88; always @(seg_com or bcd_led) 4'hb:seg_data=8'h83; 4'hc:seg_data=8'hc6;
4'hd:seg_data=8'ha1; begin
4'he:seg_data=8'h86; case(bcd_led)
//4'hf:seg_data=8'h8e; 4'h0:seg_data=8'hc0; 4'hf:seg_data=8'hf6; 4'h1:seg_data=8'hf9; default:seg_data=8'hc0; 4'h2:seg_data=8'ha4; endcase 4'h3:seg_data=8'hb0; end
4'h4:seg_data=8'h99; endmodule
五、数据发生器部分 5.1、《梁祝》乐谱发生器
module tonetable (clk4hz, predata); input clk4hz;
output [12:0] predata;
reg [12:0] predata; parameter low_3 = 13'd7583; parameter low_5 = 13'd6377; parameter low_6 = 13'd5681; parameter low_7 = 13'd5062; parameter mid_1 = 13'd4777; parameter mid_2 = 13'd4256; parameter mid_3 = 13'd3791; parameter mid_5 = 13'd3188; parameter mid_6 = 13'd2840; parameter high_1= 13'd2391; parameter stop= 13'd0;
reg [7:0] counter;
always @(posedge clk4hz) if (counter>=135) counter=8'b0; else counter=counter+1'b1;
always @(counter) case (counter) 8'd0: predata=low_3; 8'd1: predata=low_3; 8'd2: predata=low_3; 8'd3: predata=low_3; 8'd4: predata=low_5; 8'd5: predata=low_5; 8'd6: predata=low_5; 8'd7: predata=low_6; 8'd8: predata=mid_1; 8'd9: predata=mid_1; 8'd10: predata=mid_1; 8'd11: predata=mid_2; 8'd12: predata=low_6; 8'd13: predata=mid_1; 8'd14: predata=low_5; 8'd15: predata=low_5; //----------------------------------------------------------------- 8'd16: predata=mid_5; 8'd17: predata=mid_5; 8'd18: predata=mid_5; 8'd19: predata=high_1; 8'd20: predata=mid_6; 8'd21: predata=mid_5; 8'd22: predata=mid_3; 8'd23: predata=mid_5; 8'd24: predata=mid_2; 8'd25: predata=mid_2; 8'd26: predata=mid_2; 8'd27: predata=mid_2; 8'd28: predata=mid_2; 8'd29: predata=mid_2; 8'd30: predata=mid_2; 8'd31: predata=mid_2; //----------------------------------------------------------------- 8'd32: predata=mid_2; 8'd33: predata=mid_2; 8'd34: predata=mid_2; 8'd35: predata=mid_3; 8'd36: predata=low_7; 8'd37: predata=low_7; 8'd38: predata=low_6; 8'd39: predata=low_6; 8'd40: predata=low_5; 8'd41: predata=low_5;
8'd42: predata=low_5; 8'd43: predata=low_6; 8'd44: predata=mid_1; 8'd45: predata=mid_1; 8'd46: predata=mid_2; 8'd47: predata=mid_2; //------------------------------------------------------------------- 8'd48: predata=mid_3; 8'd49: predata=mid_3; 8'd50: predata=mid_1; 8'd51: predata=mid_1; 8'd52: predata=mid_6; 8'd53: predata=mid_5; 8'd54: predata=mid_6; 8'd55: predata=mid_1; 8'd56: predata=low_5; 8'd57: predata=low_5; 8'd58: predata=low_5; 8'd59: predata=low_5; //----------------------------------------------------------------- 8'd60: predata=mid_3; 8'd61: predata=mid_3; 8'd62: predata=mid_3; 8'd63: predata=mid_5; 8'd64: predata=low_7; 8'd65: predata=low_7; 8'd66: predata=low_7; 8'd67: predata=mid_2; 8'd68: predata=low_6; 8'd69: predata=mid_1; 8'd70: predata=low_5; 8'd71: predata=low_5; 8'd72: predata=low_5; 8'd73: predata=low_5; 8'd74: predata=low_5; 8'd75: predata=low_5; //----------------------------------------------------------------
8'd76: predata=low_3; 8'd77: predata=low_5; 8'd78: predata=low_3; 8'd79: predata=low_3; 8'd80: predata=low_5; 8'd81: predata=low_6; 8'd82: predata=low_7; 8'd83: predata=mid_2; 8'd84: predata=low_6; 8'd85: predata=low_6; 8'd86: predata=low_6; 8'd87: predata=low_6; 8'd88: predata=low_6; 8'd89: predata=low_6; 8'd90: predata=low_5; 8'd91: predata=low_6; //------------------------------------------------------------------ 8'd92: predata=mid_1; 8'd93: predata=mid_1; 8'd94: predata=mid_1; 8'd95: predata=mid_2; 8'd96: predata=mid_5; 8'd97: predata=mid_5; 8'd98: predata=mid_3; 8'd99: predata=mid_3; 8'd100: predata=mid_2; 8'd101: predata=mid_2; 8'd102: predata=mid_3; 8'd103: predata=mid_2; 8'd104: predata=mid_1; 8'd105: predata=mid_1; 8'd106: predata=low_6; 8'd107: predata=low_5; //------------------------------------------------------------------- 8'd108: predata=low_3; 8'd109: predata=low_3; 8'd110: predata=low_3; 8'd111: predata=low_3; 8'd112: predata=mid_1; 8'd113: predata=mid_1; 8'd114: predata=mid_1; 8'd115: predata=mid_1; 8'd116: predata=low_6; 8'd117: predata=mid_1; 8'd118: predata=low_6; 8'd119: predata=low_5;
8'd120: predata=low_3; 8'd121: predata=low_5; 8'd122: predata=low_6; 8'd123: predata=mid_1; 8'd124: predata=low_5; 8'd125: predata=low_5; 8'd126: predata=low_5; 8'd127: predata=low_5; 8'd128: predata=low_5; 8'd129: predata=low_5; 8'd130: predata=low_5; 8'd131: predata=low_5; 8'd132: predata=stop; 8'd133: predata=stop; 8'd134: predata=stop; 8'd135: predata=stop; default:predata=8'b0; endcase endmodule
六、多频分频频器部分 6.1、乐曲最终频率发生器
module xtm_divspk(clk,div_out,datain); clk_div
else input [12:0]datain; begin
output reg div_out; clk_div
reg[31:0] clk_div;
div_out
end
always@(posedge clk) endmodule begin
if(clk_div
七、数据选择器部分
7.1、可控制(4模式,4数据组)数据选通器
module
input [1:0]ctr3;
xtm_data_exc(clk,reset_n,ctr0,ctr1,ctr2,ctr3,iinput [7:0] input_data0; nput_data0,input_data1,input_data2,input_dinput [7:0] input_data1; ata3,input_data4,input_data5,input_data6,ininput [7:0] input_data2; put_data7,input_data8,input_data9,input_dainput [7:0] input_data3; ta10,input_data11,
input [7:0] input_data4; output_data0,output_data1,output_data2); input [7:0] input_data5; input clk; input [7:0] input_data6; input reset_n; input [7:0] input_data7; input [1:0]ctr0; input [7:0] input_data8; input [1:0]ctr1; input [7:0] input_data9;
input [1:0]ctr2;
input [7:0] input_data10;
input [7:0] input_data11; output_data1=input_data4;
output [7:0] output_data0; output [7:0] output_data1; output_data2=input_data5; output [7:0] output_data2; end reg[7:0]output_data0; 2'b210: reg[7:0]output_data1; begin reg[7:0]output_data2; output_data0=input_data6;
always@(clk, reset_n, ctr2) output_data1=input_data7; begin case(ctr2) output_data2=input_data8; 2'b00: end begin 2'b211: begin output_data0=input_data0; output_data0=input_data9; output_data1=input_data1; output_data1=input_data10; output_data2=input_data2; end output_data2=input_data11; 2'b01: end begin endcase end
output_data0=input_data3; endmodule
附录Ⅲ
参考文献:
现代电子技术实验《verilog HDL设计技术》………………李晨 南京大学金陵学院信工系 现代电子技术实验室 http://baike.baidu.com/view/31949.htm