基于-verilog的数字时钟设计.doc
《基于-verilog的数字时钟设计.doc》由会员分享,可在线阅读,更多相关《基于-verilog的数字时钟设计.doc(18页珍藏版)》请在冰豆网上搜索。
课程设计
基于VerilogHDL的数字秒表设计
系别:
物理与电气工程学院
专业:
微电子学
班级:
<2>班
成员:
目录
一、前言…………………………………………………………………………………………………………………3
二、实验目的………………………………………………………………………………………………………….3
三、功能设计…………………………………………………………………………………………………………3
四、用Verilog描述电路……………………………………………………………………………………….4
4.1时钟调校及计时模块……………………………………………………………………………………4
4.2整数分频模块………………………………………………………………………………………………..8
4.3时钟信号选择模块………………………………………………………………………………………8
4.4七段显示设置………………………………………………………………………………………………11
4.4.1BCD码显示模块……………………………………………………………………………………11
4.4.2二位七段显示模块………………………………………………………………………………12
4.4.3一位七段显示模块………………………………………………………………………………12
4.5顶层模块实现…………………………………………………………………………………………14
五、模拟与仿真…………………………………………………………………………………………………..15
六、逻辑综合……………………………………………………………………………………………………….16
七、下载到硬件电路……………………………………………………………………………………………16
八、总结……………………………………………………………………………………………………………….18
九、心得体会……………………………………………………………………………………………………….18
十、参考文献……………………………………………………………………………………………………….19
一、前言
随着微电子技术的的飞速发展,大规模可编程器件的密度和性能不断提高,数字系统的设计方法、设计过程也发生了重大改变,传统的设计方法已经逐渐被电子设计自动化EDA(ElectronicDesignAutomation)工具所取代。
可编程器件可以通过硬件描述语言(如VerilogHDL)的形式根据实际设计的需要灵活地嵌入规模化的数字单元,大缩短了产品的设计周期。
以可编程逻辑器件为核心的设计在数字系统设计领域将占据越来越重要的作用,因此,作为硬件设计者掌握EDA设计方法和工具是必须的。
二、实验目的
(1)通过本次课程设计加深对Verilog语言课程的全面认识、复习和掌握。
(2) 掌握定时器、外部中断的设置和编程原理。
(3) 通过此次课程设计能够将软硬件结合起来,对程序进行编辑、调试。
使其能够通过电脑下载到芯片,正常工作。
(4)实际操作Quartus II软件,复习巩固以前所学知识。
三、功能设计
数字钟是一个常用的数字系统,其主要功能是计时和显示时间。
这里通过一个数字钟表的模块化设计方法,说明自顶向下的模块化设计方法和实现一个项目的设计步骤。
这里实现的电子表具有显示和调时的基本功能,可以显示时、分秒和毫秒,并通过按键进行工作模式选择,工作模式有4种,分别是正常计时模式、调时模式、调分模式、调秒模式。
构成电子表的基本基本模块有四个,分别是时钟调校及计时模块myclock、整数分频模块int_div、时钟信号选择模块clkgen和七段显示模块disp_dec。
四、用Verilog实现电路
4.1时钟调校及计时模块
时钟调校及计时模块myclock实现的功能是根据当前的工作状态进行时、分、秒的调整或正常的计时。
代码端口说明如下:
输入信号:
RSTn——复位信号
CLK——100Hz时钟信号
FLAG[1:
0]——工作模式控制信号,模式定义为:
00表示正常显示,01表示调时,10表示调分,11表示调秒;
UP——调校模式时以加1方式调节信号;
DN——调校模式时以减1方式调节信号。
输出信号:
H[7:
0]——“时”数据(十六进制);
M[7:
0]——“分”数据(十六进制);
S[7:
0]——“秒”数据(十六进制);
MS[7:
0]———“百分秒”数据(十六进制)。
该模块的设计思路是,当复位信号RSTn有效时,时、分、秒信号清零,否则工作模式控制信号FLAG的值决定当前的工作状态。
当FLAG=2’b00时,电子表工作在正常计时状态,对输入的100Hz的时钟信号clk进行计数,修改当前的百分秒(MS)、秒(S)、分(M)和时(H)的计数值;当FLAG信号=2’b01时,电子表工作在“时”校正状态,若此时UP信号有效则H加1,若此时DN信号有效则H减1,;当FLAG信号=1’b10时,电子表工作在“分”校正状态,若此时UP信号有效则M加1,若此时DN信号有效则M减1;当FLAG=2’b11时,电子表工作在“秒”校正状态,其UP和DN的控制过程与“时”、“分”类似
代码:
modulemyclock(RSTn,CLK,FLAG,UP,DN,H,M,S,MS);
inputRSTn,CLK,UP,DN;
output[7:
0]H,M,S;
output[7:
0]MS;
input[1:
0]FLAG;
reg[5:
0]m_H,m_M,m_S;
reg[6:
0]m_MS;
assignH=m_H;
assignM=m_M;
assignS=m_S;
assignMS=m_MS;
always(posedgeCLK)
if(~RSTn)//复位状态
begin
m_H<=8'd23;
m_M<=8'd52;
m_S<=8'b0;
m_MS<=8'b0;
end
elseif(FLAG==2'b01)//调时状态
begin
if(UP)
begin
if(m_H==8'd23)
m_H<=8'd0;
else
m_H=m_H+1'b1;
end
elseif(DN)
begin
if(m_H==8'h00)
m_H<=8'd23;
else
m_H<=m_H-1'b1;
end
end
elseif(FLAG==2'b10)//调分状态
begin
if(UP)
if(m_M==8'd59)
m_M<=8'd0;
else
m_M<=m_M+1'b1;
elseif(DN)
if(m_M==8'h00)
m_M<=8'd59;
else
m_M<=m_M-1'b1;
end
elseif(FLAG==2'b11)//调秒状态
begin
if(UP)
if(m_S==8'd59)
m_S<=8'b0;
else
m_S<=m_S+1'b1;
elseif(DN)
if(m_S==8'h00)
m_S<=8'd59;
else
m_S<=m_S<=m_S-1'b1;
end
else
begin//正常计时状态
if(m_MS==8'd99)
begin
m_MS<=8'd0;
if(m_S==8'd59)
begin
m_S<=8'd0;
if(m_M==8'd59)
begin
m_M<=8'd0;
if(m_H==8'd23)
m_H<=0;
else
m_H<=m_H+1'b1;
end
else
m_M<=m_M+8'd1;
end
else
m_S<=m_S+1'b1;
end
else
m_MS<=m_MS+1'b1;
end
endmodule
4.2整数分频模块
由于数字系统提供的基准时钟信号频率往往较高,因此需要分频模块产生所需频率的失踪信号,例如上面时钟校正及计时模块所需的100Hz的时钟信号。
整数分频模块int_div可以实现对输入时钟clock进行F_DIV分频后输出clk_out。
F_DIV分频系数围为1~2^n(n=F_DIV_WIDTH),若要改变分频系数,改变参数F_DIV或F_DIV_WIDTH到相应围即可。
若分频系数为偶数,则输出时钟占空比为50%;若分频系数为奇数,则输出的时钟占空比取决于输入的时钟占空比和分频系数(当输入为50%时,输出也是50%)。
代码:
moduleint_div(clock,clk_out);
parameterF_DIV=48000000;//分频系数
parameterF_DIV_WIDTH=32;//分频计数器宽度
inputclock;//输入时钟
outputclk_out;//输出时钟
regclk_p_r;
regclk_n_r;
reg[F_DIV_WIDTH-1:
0]count_p;
reg[F_DIV_WIDTH-1:
0]count_n;
wirefull_div_p;//上升沿计数满标志
wirehalf_div_p;//上升沿计数半满标志
wirefull_div_n;//下降沿计数满标志
wirehalf_div_n;//下降沿计数半满标志
//判断计数标志位置位与否
assignfull_div_p=(count_passignhalf_div_p=(count_p<(F_DIV>>1)-1);
assignfull_div_n=(count_nassignhalf_div_n=(count_n<(F_DIV>>1)-1);
//时钟输出
assignclk_out=(F_DIV==1)?
clock:
(F_DIV[0]?
(clk_p_r&clk_n_r):
clk_p_r);
always(posedgeclock)//上升沿脉冲计数
begin
if(full_div_p)
begin
count_p<=count_p+1'b1;
if(half_div_p)
clk_p_r<=1'b0;
else
clk_p_r<=1'b1;
end
else
begin
count_p<=0;
clk_p_r<=1'b0;
end
end
always(negedgeclock)//下降沿脉冲计数
begin
if(full_div_n)
begin
count_n<=count_n+1'b1;
if(half_div_n)
clk_n_r<=1'b0;
else
clk_n_r=1'b1;
end
else
begin
count_n<=0;