锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

FPGA课程设计——数字电子时钟VERILOG(基于正点原子新起点开发板,支持8位或6位共阳极数码管显示时分秒...

时间:2023-06-07 21:37:00 集成电路00k326针db直插连接器贴led专用连接器

2019电子科学与技术专业FPGA课程设计

报 告

2022年 5月 20日

多功能数字电子钟的设计

摘要

自动化电子设计(EDA)是实现电子系统或电子产品自动化设计的技术EDA可以使用技术设计的结果FPGA / CPLD实施验证也可直接制成专用集成电路(ASIC)。

本文是用verilog用语言描述一个基础FPGA多功能数字电子时钟的设计,具有时间显示、精确计时、时间校准、 定时闹钟等功能。本文首先介绍了需要完成的工作,然后介绍了系统的整体设计和源代码开发过程。首先是源代码Quartus模拟和综合软件,下载到正点原子新启点开发板上FPGA设备上的试验结果表明,上述功能全部正确,工作稳定良好。

关键词EDA;数字闹钟;verilog

Abstract

Electronic design automation (EDA) is a technology to realize the automatic design of electronic system or electronic products. The design results using EDA technology can be verified by FPGA / CPLD or directly made into application specific integrated circuit (ASIC).

This paper uses Verilog language to describe the design of a multifunctional digital electronic clock based on FPGA. The design has the functions of time display, accurate timing, time calibration, timing alarm clock and so on. This paper first introduces the work to be completed, and then introduces the overall design of the system and the source code development process. The source code is first simulated and synthesized on quartus software, and then downloaded to the punctual atom xinqidian development board. The test results on FPGA devices show that all the above functions are correct and work stably.

Keywords: EDA; Digital alarm clock; verilog

目录

一、概述所作题目的意义,拟完成的工作 2

1.1选题意义 2

1.2 拟完成的工作 2

二、系统整体设计 3

2.1 系统方框图设计 3

2.2功能介绍 3

三、代码实现 3

3.1顶层模块 3

3.2 各底层模块 7

3.3 系统总原理框图 37

3.4 仿真波形 38

四、实物调试效果 40

4.1 硬件管脚分配说明 40

4.2 实物及现象 41

五、 课程设计经验 45

六、参考文献 46

一、概述主题的意义,拟完成的工作

1.1选题意义

数字钟是一种基于数字电路,结合模拟电路和电路基础知识设计的时间数字显示装置。它具有结构简单、设计方便、稳定性强等优点。它已广泛应用于各种公共场所,成为人们日常生活的必需品,给人们的生活、学习和工作带来极大的便利。由于数字集成电路的发展和石英振荡器的广泛应用,数字钟的精度远远超过了旧手表。手表的数字化给人们的生产和生活带来了极大的便利,大大扩大了手表的原始报时功能。随着科学技术和人们生活观念的变化,数字钟的设计呈现出新的发展趋势:体积更小、功能更强大,如增加定时控制、闹钟、仿广播等功能;设计外观更时尚、美观,适合人们审美观点的变化。因此,更先进的电子钟研究具有良好的发展前景和市场潜力。

数字钟不仅是一个数字电路,而且在其他领域也有相当大的发展空间,如定期自动报警、按时自动铃声、时间程序自动控制、定期广播、定期开关电路、定期开关烘箱、切断电源设备,甚至各种定期电气自动启动等,都是基于时钟数字化。因此,研究数字钟并扩展其应用具有非常现实的意义。

1.2 拟完成的工作

1.数字管或液晶屏显示时,分和秒(24小时进制);

2、具有按键校时功能,对小时和分单独校时,对分校时时,停止向小时进位;

3、具有闹钟功能,闹钟铃声为自主设计的用蜂鸣器发出的声音;

4、通过按键设置闹钟功能,且自动停闹和手动操作停闹; 

5、其它创意设计:增加闹钟模式开启指示灯和闹铃提示灯;可以作为秒表使用。

二、系统整体设计

2.1 系统方框图设计

2.2 功能介绍

本系统分为分频模块、计时模块、闹钟模块、秒表模块、控制模块、显示模块六个模块:分频模块给计时秒表闹钟模块提供时钟信号,控制模块控制计时秒表闹钟模块,通过显示模块的段选和位选进行显示。

三、代码实现

3.1 顶层模块

clock_top.v

module clock(

            //input

            clk,//时钟信号

            rst_n,//复位

            key,

mkey,

button,

            //output

            data, //a-g段

data_db,

            weixuan,//位选

beep,

LED,

nled,

bled,

           );

input clk;//时钟信号

input rst_n;//复位

input [2:0] key;

input mkey;

input button;

output [3:0] LED;

output nled;

output bled;

output [6:0] data;//段选

output data_db;

output [7:0] weixuan;//位选

output beep;

wire beep_1;



wire [1:0] H_data1;

wire [3:0] H_data2;

wire [2:0] H_data3;

wire [3:0] H_data4;

wire [2:0] H_data5;

wire [3:0] H_data6;

wire [3:0] H_data7;

wire [3:0] H_data8;



wire [1:0] N_data1;

wire [3:0] N_data2;

wire [2:0] N_data3;

wire [3:0] N_data4;



wire [1:0] C_data1;

wire [3:0] C_data2;

wire [2:0] C_data3;

wire [3:0] C_data4;

wire [2:0] C_data5;

wire [3:0] C_data6;

wire [3:0] C_data7;

wire [3:0] C_data8;



wire [3:0] pin_status_ctrl;



key    U1( .clk(clk),

  .rst_n(rst_n),

  .key(key),

  .pin_status_ctrl(pin_status_ctrl)

  );



model U2(.clk(clk),.rst_n(rst_n),.pin_status_ctrl(pin_status_ctrl),



               .H_data1(H_data1),

   .H_data2(H_data2),

   .H_data3(H_data3),

   .H_data4(H_data4),

   .H_data5(H_data5),

   .H_data6(H_data6),

   .H_data7(H_data7),

   .H_data8(H_data8),



.Display_Model(Display_Model),



.N_data1(N_data1),//闹钟

   .N_data2(N_data2),

   .N_data3(N_data3),

   .N_data4(N_data4),

.LED(LED),

               );

weixuan U3( .clk(clk),.rst_n(rst_n),.weixuan(weixuan));

duanxuan  U4(.clk(clk),.rst_n(rst_n),

.C_data1(C_data1),//实际显示

.C_data2(C_data2),

.C_data3(C_data3),

.C_data4(C_data4),

.C_data5(C_data5),

.C_data6(C_data6),

.C_data7(C_data7),

.C_data8(C_data8),



.data(data),

.data_db(data_db)

);

xianshi     U5(

                 .clk(clk),

        .rst_n(rst_n),

  .mkey(mkey),

        .H_data1(H_data1),//时钟

     .H_data2(H_data2),

     .H_data3(H_data3),

     .H_data4(H_data4),

     .H_data5(H_data5),

     .H_data6(H_data6),

     .H_data7(H_data7),

     .H_data8(H_data8),

  

     .Display_Model(Display_Model),//显示模式

  

     .N_data1(N_data1),//闹钟

     .N_data2(N_data2),

     .N_data3(N_data3),

     .N_data4(N_data4),

  

  .C_data1(C_data1),//实际显示

  .C_data2(C_data2),

  .C_data3(C_data3),

  .C_data4(C_data4),

  .C_data5(C_data5),

  .C_data6(C_data6),

  .C_data7(C_data7),

  .C_data8(C_data8),

                 );

  

beep U6( .clk(clk),.beep_1(beep_1),.beep(beep), .bled(bled),

 );

naozhong    U7( .clk(clk),

.rst_n(rst_n),

               .button(button),



     .H_data1(H_data1),//时钟

     .H_data2(H_data2),

     .H_data3(H_data3),

     .H_data4(H_data4),



    .N_data1(N_data1),//闹钟

     .N_data2(N_data2),

     .N_data3(N_data3),

     .N_data4(N_data4),

    

  .beep_1(beep_1),

.nled(nled),

               );



endmodule

模块仿真:

3.2 各底层模块

3.2.1 beep.v(蜂鸣器控制)

module beep(

              clk,

  beep_1,

  beep,

  bled); //模块名称beep

input clk; //系统时钟50MHz

input beep_1;

output beep; //蜂鸣器输出端

output bled;

reg bled;

reg beep_r; //寄存器

reg[27:0]count;

assign beep = beep_r; //脉冲输出

always@(posedge clk)

if(beep_1==1'b1)

  begin

count <= count + 1'b1;

  end

always @(count[20])

begin

if(beep_1==1'b0)

beep_r = 0;

else

beep_r = !(count[13]&count[24]&count[27]);

bled = (count[13]&count[24]&count[27]);

end

endmodule

模块仿真:

3.2.2 key.v (按键控制)

module key(

           clk,

  rst_n,

  key,

  

  pin_status_ctrl

  );

input clk;

input rst_n;

input [2:0] key;

output [2:0] pin_status_ctrl;

parameter T20MS = 25'd1_000_000;

reg[2:0] key_rst;  //

always @(posedge clk or negedge rst_n)//在时钟的上升沿或复位的下降沿会执行下面的操作

    if(!rst_n) key_rst <= 3'b111;//如果复位键按下则三位二进制数111赋值给key_rst

    else key_rst <= key;

reg[2:0] key_rst_r;

always @(posedge clk or negedge rst_n)

    if(!rst_n) key_rst_r <= 3'b111;

    else key_rst_r <= key_rst;//如果复位键没按下把key_rst的值赋值给key_rstr

  

wire[2:0] key_en;

assign key_en = key_rst_r & (~key_rst);//key_en等于key_rst_r与

/************************************************/

//按键消抖动

/************************************************/

reg[19:0] cnt;             //

always @(posedge clk or negedge rst_n)

    if(!rst_n) cnt <= 20'd0;

    else if(key_en) cnt <= 20'd0;//如果key_en等于1清零

    else cnt <= cnt + 1'b1;//cnt+1



//每隔20ms就取按键上的值   每20ms接收一次键值  (倒数第二个)

reg[2:0] pin_status;

always @(posedge clk or negedge rst_n)//clk信号上升沿到来时执行

    if(!rst_n) pin_status <= 3'b111;//如果复位键按下则将三位二进制数111赋值给pin_status

    else if(cnt == T20MS) pin_status <= key;//??

//

reg[2:0] pin_status_r;

always @(posedge clk or negedge rst_n)

    if(!rst_n) pin_status_r <= 3'b111;

    else pin_status_r <= pin_status;

//前20MS的值与后20MS的值  判断有没有按键按下 (最后一个)

wire[2:0]  pin_status_ctrl;//wier常用来表示以“assign”关键字指定的组合逻辑信号

assign pin_status_ctrl = pin_status_r & (~pin_status);//

endmodule

模块仿真:

3.2.3 duanxuan.v(段选控制)

module duanxuan( clk,

 rst_n,



 C_data1,//实际显示

 C_data2,

 C_data3,

 C_data4,

 C_data5,

 C_data6,

 C_data7,

 C_data8,

  

  data,

  data_db

 );

input clk;

input rst_n;

input [1:0] C_data1;

input [3:0] C_data2;

input [2:0] C_data3;

input [3:0] C_data4;

input [2:0] C_data5;

input [3:0] C_data6;

input [3:0] C_data7;

input [3:0] C_data8;



output [6:0] data;

output data_db;

/************************************************************/

reg[24:0] cnt; //声明cnt是一个18位的寄存器

reg[2:0] count;

parameter T5MS = 25'd100_000;//定义参数T5MS为



parameter   T_fenMiao     = 25'd500_000;//500_000

parameter   SEG_NUM0     = 8'hc0,//c0,

            SEG_NUM1     = 8'hf9,//f9,

            SEG_NUM2     = 8'ha4,//a4,

            SEG_NUM3     = 8'hb0,//b0,

            SEG_NUM4     = 8'h99,//99,

            SEG_NUM5     = 8'h92,//92,

            SEG_NUM6     = 8'h82,//82,

            SEG_NUM7     = 8'hf8,//F8,

            SEG_NUM8     = 8'h80,//80,

            SEG_NUM9     = 8'h90;//90,

/************************************************************/

//分秒计数器

reg [24:0] Cnt_FenMiao;

always @(posedge clk or negedge rst_n)

    if(!rst_n) Cnt_FenMiao <= 25'd0;

    else if(Cnt_FenMiao == T_fenMiao)

     Cnt_FenMiao <= 25'd0;

    else

        Cnt_FenMiao <= Cnt_FenMiao + 1'b1;    

/************************************************************/

always @(posedge clk or negedge rst_n)// 意思是在时钟的上升沿或复位的下降沿会执行下面的操作

    if(!rst_n) cnt <= 25'd0;//如果复位则

    else if(cnt == T5MS)

        cnt <= 25'd0;  

    else

        cnt <= cnt + 1'b1;

/************************************************************/

//数据编码

/************************************************************/

//数码管一要显示的列表数据(0~2)

reg [6:0] S_data1_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data1_temp <= 7'h3f;

    else

        case(C_data1)

            3'd0:    S_data1_temp <= SEG_NUM0;

            3'd1:    S_data1_temp <= SEG_NUM1;

            3'd2:    S_data1_temp <= SEG_NUM2;

            default: S_data1_temp <= SEG_NUM0;

        endcase

  

  

/***********************************/

//数码管二要显示的列表数据(0~9)

reg [6:0] S_data2_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data2_temp <= 7'h3f;

    else

        case(C_data2)

            4'd0:    S_data2_temp <= SEG_NUM0;

            4'd1:    S_data2_temp <= SEG_NUM1;

            4'd2:    S_data2_temp <= SEG_NUM2;

            4'd3:    S_data2_temp <= SEG_NUM3;

            4'd4:    S_data2_temp <= SEG_NUM4;

            4'd5:    S_data2_temp <= SEG_NUM5;

            4'd6:    S_data2_temp <= SEG_NUM6;

            4'd7:    S_data2_temp <= SEG_NUM7;

            4'd8:    S_data2_temp <= SEG_NUM8;

            4'd9:    S_data2_temp <= SEG_NUM9;

            default: S_data2_temp <= SEG_NUM0;

        endcase

//数码管三要显示的列表数据(0~5)

reg [6:0] S_data3_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data3_temp <= 7'h3f;

    else

        case(C_data3)

            3'd0:    S_data3_temp <= SEG_NUM0;

            3'd1:    S_data3_temp <= SEG_NUM1;

            3'd2:    S_data3_temp <= SEG_NUM2;

            3'd3:    S_data3_temp <= SEG_NUM3;

            3'd4:    S_data3_temp <= SEG_NUM4;

            3'd5:    S_data3_temp <= SEG_NUM5;

            default: S_data3_temp <= SEG_NUM0;

        endcase   

/***********************************/

//数码管四要显示的列表数据(0~9)

reg [6:0] S_data4_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data4_temp <= 7'h3f;

    else

        case(C_data4)

            4'd0:    S_data4_temp <= SEG_NUM0;

            4'd1:    S_data4_temp <= SEG_NUM1;

            4'd2:    S_data4_temp <= SEG_NUM2;

            4'd3:    S_data4_temp <= SEG_NUM3;

            4'd4:    S_data4_temp <= SEG_NUM4;

            4'd5:    S_data4_temp <= SEG_NUM5;

            4'd6:    S_data4_temp <= SEG_NUM6;

            4'd7:    S_data4_temp <= SEG_NUM7;

            4'd8:    S_data4_temp <= SEG_NUM8;

            4'd9:    S_data4_temp <= SEG_NUM9;

            default: S_data4_temp <= SEG_NUM0;

        endcase

//数码管五要显示的列表数据(0~5)

reg [6:0] S_data5_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data5_temp <= 7'h3f;

    else

        case(C_data5)

            3'd0:    S_data5_temp <= SEG_NUM0;

            3'd1:    S_data5_temp <= SEG_NUM1;

            3'd2:    S_data5_temp <= SEG_NUM2;

            3'd3:    S_data5_temp <= SEG_NUM3;

            3'd4:    S_data5_temp <= SEG_NUM4;

            3'd5:    S_data5_temp <= SEG_NUM5;

            default: S_data5_temp <= SEG_NUM0;

        endcase

  

  

/***********************************/

//数码管六要显示的列表数据(0~9)

reg [6:0] S_data6_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data6_temp <= 7'h3f;

    else

        case(C_data6)

            4'd0:    S_data6_temp <= SEG_NUM0;

            4'd1:    S_data6_temp <= SEG_NUM1;

            4'd2:    S_data6_temp <= SEG_NUM2;

            4'd3:    S_data6_temp <= SEG_NUM3;

            4'd4:    S_data6_temp <= SEG_NUM4;

            4'd5:    S_data6_temp <= SEG_NUM5;

            4'd6:    S_data6_temp <= SEG_NUM6;

            4'd7:    S_data6_temp <= SEG_NUM7;

            4'd8:    S_data6_temp <= SEG_NUM8;

            4'd9:    S_data6_temp <= SEG_NUM9;

            default: S_data6_temp <= SEG_NUM0;

        endcase

/*****************************************/

//数码管七要显示的列表数据(0~9)

reg [6:0] S_data7_temp;        

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data7_temp <= 7'h3f;

    else

        case(C_data7)

            4'd0:    S_data7_temp <= SEG_NUM0;

            4'd1:    S_data7_temp <= SEG_NUM1;

            4'd2:    S_data7_temp <= SEG_NUM2;

            4'd3:    S_data7_temp <= SEG_NUM3;

            4'd4:    S_data7_temp <= SEG_NUM4;

            4'd5:    S_data7_temp <= SEG_NUM5;

            4'd6:    S_data7_temp <= SEG_NUM6;

            4'd7:    S_data7_temp <= SEG_NUM7;

            4'd8:    S_data7_temp <= SEG_NUM8;

            4'd9:    S_data7_temp <= SEG_NUM9;

            default: S_data7_temp <= SEG_NUM0;

        endcase   

/***********************************/

//数码管八要显示的列表数据(0~9)

reg [6:0] S_data8_temp;

always @(posedge clk or negedge rst_n)

    if(!rst_n) S_data8_temp <= 7'h3f;

    else

        case(C_data8)

            4'd0:    S_data8_temp <= SEG_NUM0;

            4'd1:    S_data8_temp <= SEG_NUM1;

            4'd2:    S_data8_temp <= SEG_NUM2;

            4'd3:    S_data8_temp <= SEG_NUM3;

            4'd4:    S_data8_temp <= SEG_NUM4;

            4'd5:    S_data8_temp <= SEG_NUM5;

            4'd6:    S_data8_temp <= SEG_NUM6;

            4'd7:    S_data8_temp <= SEG_NUM7;

            4'd8:    S_data8_temp <= SEG_NUM8;

            4'd9:    S_data8_temp <= SEG_NUM9;

            default: S_data8_temp <= SEG_NUM0;

        endcase

assign data_db = data_dp;

assign data = data_temp;   

/**********************************************/    

reg[6:0] data_temp;

reg data_dp;

always @(posedge clk or negedge rst_n)//在时钟的上升沿或复位的下降沿会执行下面的操作

     if(!rst_n) begin

     data_temp <= 7'b1111111;



    end

    else if(cnt == T5MS)

 begin

       case(count) //选择数码管显示位

3'd0:begin

     //weixuan_r = 8'b01111111; //选择第一个数码管显示

 data_temp = S_data1_temp;

 data_dp = 1'b1;

     end

3'd1:begin

     //weixuan_r = 8'b10111111; //选择第二个数码管显示

 data_temp = S_data2_temp;

 data_dp = 1'b0;

     end

3'd2:begin

     //weixuan_r = 8'b11011111; //选择第三个数码管显示

  data_temp = S_data3_temp;

  data_dp = 1'b1;

     end

3'd3:begin

     //weixuan_r = 8'b11101111; //选择第四个数码管显示

  data_temp = S_data4_temp;

  data_dp = 1'b0;

     end

3'd4:begin

     //weixuan_r = 8'b11110111; //选择第五个数码管显示

  data_temp = S_data5_temp;

  data_dp = 1'b1;

     end

3'd5:begin

     //weixuan_r = 8'b11111011; //选择第六个数码管显示

  data_temp = S_data6_temp;

  data_dp = 1'b0;

     end

3'd6:begin

     //weixuan_r = 8'b11111101; //选择第七个数码管显示

  data_temp = S_data7_temp;

  data_dp = 1'b1;

     end

3'd7:begin

     //weixuan_r = 8'b11111110; //选择第八个数码管显示

  data_temp = S_data8_temp;

  data_dp = 1'b1;

     end

   endcase

     count <= count + 1'b1;

   end

endmodule

模块仿真:

3.2.4 weixuan.v(位选控制)

module weixuan(

               clk,

rst_n,





weixuan

);

input clk;

input rst_n;

output[7:0] weixuan;

parameter T5MS = 25'd100_000;//定义参数T5MS为

/**********************************************/

reg[7:0] weixuan_r;//声明select__wei是一个三位的寄存器

reg[24:0] cnt; //声明cnt是一个18位的寄存器

reg[2:0] count;

/*******************************************************/

assign weixuan = weixuan_r;

/**********************************************/    

//5ms计时

always @(posedge clk or negedge rst_n)// 意思是在时钟的上升沿或复位的下降沿会执行下面的操作

    if(!rst_n) cnt <= 25'd0;//如果复位则

    else if(cnt == T5MS)

        cnt <= 25'd0;  

    else

        cnt <= cnt + 1'b1;

always @(posedge clk or negedge rst_n)//在时钟的上升沿或复位的下降沿会执行下面的操作

     if(!rst_n) begin

      weixuan_r <= 8'b11111111;

    end

    else if(cnt == T5MS)

 begin

       case(count) //选择数码管显示位

3'd0:begin

     weixuan_r = 8'b01111111; //选择第一个数码管显示

     end

3'd1:begin

     weixuan_r = 8'b10111111; //选择第二个数码管显示

     end

3'd2:begin

     weixuan_r = 8'b11011111; //选择第三个数码管显示

       end

3'd3:begin

     weixuan_r = 8'b11101111; //选择第四个数码管显示

     end

3'd4:begin

     weixuan_r = 8'b11110111; //选择第五个数码管显示

       end

3'd5:begin

     weixuan_r = 8'b11111011; //选择第六个数码管显示

       end

3'd6:begin

     weixuan_r = 8'b11111101; //选择第七个数码管显示

     end

3'd7:begin

     weixuan_r = 8'b11111110; //选择第八个数码管显示

     end

   endcase

     count <= count + 1'b1;

   end

endmodule

模块仿真:

3.2.5 xiaoshi.v (时显示) 

 module xianshi(

                 clk,

        rst_n,

  mkey,

  

        H_data1,

     H_data2,

     H_data3,

     H_data4,

     H_data5,

     H_data6,

     H_data7,

     H_data8,

  

     Display_Model,//显示模式  0是时钟,1是闹钟设置

  

     N_data1,//闹钟

     N_data2,

     N_data3,

     N_data4,



  C_data1,//实际显示

  C_data2,

  C_data3,

  C_data4,

  C_data5,

  C_data6,

  C_data7,

  C_data8,

        );

input clk;

input rst_n;   

input mkey;

input [1:0] H_data1;

input [3:0] H_data2;

input [2:0] H_data3;

input [3:0] H_data4;

input [2:0] H_data5;

input [3:0] H_data6;

input [3:0] H_data7;

input [3:0] H_data8;



input Display_Model;



input [1:0] N_data1;

input [3:0] N_data2;

input [2:0] N_data3;

input [3:0] N_data4;



output[1:0] C_data1;//实际显示

output[3:0] C_data2;

output[2:0] C_data3;

output[3:0] C_data4;

output[2:0] C_data5;  

output[3:0] C_data6;

output[3:0] C_data7;

output[3:0] C_data8;



reg [1:0] b_data1;

reg [3:0] b_data2;

reg [2:0] b_data3;

reg [3:0] b_data4;

reg [2:0] b_data5;

reg [3:0] b_data6;

reg [3:0] b_data7;

reg [3:0] b_data8;



parameter T5MS = 25'd100_000;//定义参数T5MS 扫描周期





//定时发送数据

reg [24:0] cnt;    

reg [3:0] num;//每隔5MS,num加1

always @(posedge clk or negedge rst_n)

    if(!rst_n) begin

        cnt <= 25'd0;

        num <= 2'd0;

    end

    else if(cnt == T5MS) begin

        num <= num + 1'b1;

        cnt <= 25'd0;

    end

    else

        cnt <= cnt + 1'b1;

/******************************************/

//通过Display_Model来确定是要送秒表数据还是时钟数据

always @(posedge clk or negedge rst_n)

    if(!rst_n)

    begin

                 b_data1 <= 1'd0;

  b_data2 <= 3'd0;

  b_data3 <= 2'd0;

  b_data4 <= 3'd0;

  b_data5 <= 2'd0;

  b_data6 <= 3'd0;

  b_data7 <= 3'd0;

  b_data8 <= 3'd0;

end

    else

 begin

if(!mkey)//显示秒表 分秒10ms

begin

 case(num)

3'd0:    b_data1 <= Display_Model ? N_data2:H_data3;//每5ms给第一个数码管送数据 ,为闹钟模式时,显示闹钟值

3'd1:    b_data2 <= Display_Model ? N_data3:H_data4;//每5ms给第二个数码管送数据

3'd2:    b_data3 <= Display_Model ? N_data4:H_data5;//每5ms给第三个数码管送数据

3'd3:    b_data4 <= H_data6;

3'd4:    b_data5 <= H_data7;

3'd5:    b_data6 <= H_data8;

endcase

end

if(mkey)//显示时钟,时分秒

begin

  case(num)

3'd0:    b_data1 <= Display_Model ? N_data1:H_data1;//每5ms给第一个数码管送数据 ,为闹钟模式时,显示闹钟值

3'd1:    b_data2 <= Display_Model ? N_data2:H_data2;//每5ms给第二个数码管送数据

3'd2:    b_data3 <= Display_Model ? N_data3:H_data3;//每5ms给第三个数码管送数据

3'd3:    b_data4 <= Display_Model ? N_data4:H_data4;//每5ms给第四个数码管送数据

3'd4:    b_data5 <= H_data5;

3'd5:    b_data6 <= H_data6;

3'd6:    b_data7 <= H_data7;

3'd7:    b_data8 <= H_data8;

endcase

end

end

assign C_data1 = b_data1;

assign C_data2 = b_data2;

assign C_data3 = b_data3;

assign C_data4 = b_data4;

assign C_data5 = b_data5;

assign C_data6 = b_data6;

assign C_data7 = b_data7;

assign C_data8 = b_data8;

endmodule

模块仿真:

3.2.6naozhong.v(闹钟控制)

module naozhong(

              clk,

  rst_n,

  button,

  H_data1,

  H_data2,

  H_data3,

  H_data4,

  

  N_data1,

  N_data2,

  N_data3,

  N_data4,



  beep_1,

  nled,

  );

input clk;

input rst_n;   

input button;



output nled;

reg nled;

input [1:0] H_data1;

input [3:0] H_data2;

input [2:0] H_data3;

input [3:0] H_data4;



input [1:0] N_data1;

input [3:0] N_data2;

input [2:0] N_data3;

input [3:0] N_data4;



output beep_1;

reg beep;

assign beep_1 = beep;

reg  flag1;

reg  Y1,Y2,Y3,Y4;

reg [2:0] Yout;



always @(H_data1 or N_data1)

     begin

    if (H_data1 ==N_data1)

   Y1 <= 1'b1;

else

      Y1 <= 1'b0;

  end



always @(H_data2 or N_data2)

     begin

    if (H_data2 == N_data2)

   Y2 <= 1'b1;

else

      Y2 <= 1'b0;

  end

  

always @(H_data3 or N_data3)

     begin

    if (H_data3 == N_data3)

   Y3 <= 1'b1;

else

      Y3 <= 1'b0;

  end   

  

always @(H_data4 or N_data4)

     begin

    if (H_data4 == N_data4)

   Y4 <= 1'b1;

else

      Y4 <= 1'b0;

  end   

  

always @(posedge clk or negedge rst_n)

    if(!rst_n)

  begin

nled = 0;

flag1 = 1'b0;

beep = 1'b0;

  end

    else

 begin

 if(button==1)

  begin

     Yout =Y1+Y2+Y3+Y4;

    flag1 <= 1'b1;

 nled =1;

    if(Yout==3'd4 )

      beep = 1'b1;

else

beep = 1'b0;//一分钟响铃

     end

else

begin

nled =0;

beep = 1'b0;//一分钟响铃

end

 end

endmodule

模块仿真:

3.2.7 model.v(模式选择)

module model(

              clk,

  rst_n,

  pin_status_ctrl,



  H_data1,

  H_data2,

  H_data3,

  H_data4,

  H_data5,

  H_data6,

  H_data7,

  H_data8,

  

  Display_Model,

  Time_model,

  N_data1,

  N_data2,

  N_data3,

  N_data4,

  LED

  );

input clk;

input rst_n;   

input [2:0] pin_status_ctrl;//按键输入

output [3:0] LED;//模式指示灯

reg [3:0] LED;

output [1:0] H_data1;//计时器数据

output [3:0] H_data2;

output [2:0] H_data3;

output [3:0] H_data4;

output [2:0] H_data5;

output [3:0] H_data6;

output [3:0] H_data7;

output [3:0] H_data8;



output Display_Model;

output [1:0] N_data1;//闹钟数据

output [3:0] N_data2;

output [2:0] N_data3;

output [3:0] N_data4;



parameter   T_fenMiao     = 25'd500_000;//500_000 系统时钟50MHZ时钟分频 即50 000 000 /500 000 = 100hz  0.01s 记100次为1s

//分秒计数器

reg [24:0] Cnt_FenMiao;

always @(posedge clk or negedge rst_n)

    if(!rst_n) Cnt_FenMiao <= 25'd0;

    else if((Cnt_FenMiao == T_fenMiao)||(!isCount))

     Cnt_FenMiao <= 25'd0;

    else

        Cnt_FenMiao <= Cnt_FenMiao + 1'b1;    

/************************************************************/

  

//模式控制

//0计时模式,1,调分,2调时,3校0,4,闹钟分,5,闹钟时

reg[2:0] Time_model;

output[2:0] Time_model;

always @(posedge clk or negedge rst_n)

    if(!rst_n) Time_model <= 3'd0;

    else if(pin_status_ctrl[0])

        begin

            if(Time_model == 3'd5)

                Time_model <= 3'd0;

            else

            Time_model <= Time_model + 1'd1;

        end

  

reg Display_Model;

reg isCount;//控制时间计数器   为0,停止计数,默认给1



reg [1:0] flag;//用来标志reg1小时十位是否到了2,到了2,reg2个位只能加到4

reg [1:0] n_flag;

//时钟

reg [1:0] reg1;

reg [3:0] reg2;

reg [2:0] reg3;

reg [3:0] reg4;

reg [2:0] reg5;

reg [3:0] reg6;

reg [3:0] reg7;

reg [3:0] reg8;



//闹钟

reg [1:0] n_reg1;

reg [3:0] n_reg2;

reg [2:0] n_reg3;

reg [3:0] n_reg4;



always @(posedge clk or negedge rst_n)

    if(!rst_n) begin

        isCount <= 1'b0;

        LED = 4'B0000;

        reg1 <= 2'd0;

        reg2 <= 4'd0;

        reg3 <= 3'd0;

        reg4 <= 4'd0;

        reg5 <= 3'd0;

        reg6 <= 4'd0;

  reg7 <= 4'd0;

        reg8 <= 4'd0;



  n_reg1 <= 2'd0;

        n_reg2 <= 4'd0;

        n_reg3 <= 3'd0;

        n_reg4 <= 4'd0;

    end

    else

        case(Time_model)

        //时钟正常开始跑

            3'd0:

            begin

                 Display_Model <= 1'b0;//显示时钟

                 isCount <= 1'b1;//启动计数

  LED = 4'B0000;

                 if(Cnt_FenMiao == T_fenMiao)

                begin

                    reg8 <= reg8 + 1'b1;

  

                    if(reg8 == 4'd9)

                    begin

                        reg8 <= 4'd0;

                        reg7 <= reg7 + 1'b1;

                        if(reg7 == 4'd9)

                        begin

                            reg7 <= 4'd0;

                            reg6 <= reg6 +1'b1;

 if(reg6 == 4'd9)

 begin

     reg6 <=4'd0;

  reg5 <= reg5 +1'b1;

  if(reg5 == 3'd5)

  begin

      reg5 <= 3'd0;

      reg4 <= reg4 +1'b1;

if(reg4==4'd9)

begin

    reg4 <= 4'd0;

 reg3 <=reg3 +1'b1;

 if(reg3==3'd5)

 begin

   reg3 <= 3'd0;

                                          if(reg1 == 2'd2)

                                          begin

                                             reg2 <= reg2 + 1'b1;

                                             if(reg2 == 4'd3)

                                             begin

                                                 reg2 <= 4'd0;                

                                                 reg1 <= 2'd0;                            

                                             end

                                          end

                                          else

                                          begin

                                              reg2 <= reg2 + 1'b1;

                                              if(reg2 == 4'd9)

                                              begin

                                                reg2 <= 4'd0;

                                                reg1 <= reg1 + 1'b1;

                                              end

                                           end

 end



end

    

  end

  

 end



                        end

                        

                    end

                end

            end

            //调分模式               

            3'd1:

            begin

                isCount <= 1'b1;

  LED = 4'B0001;

                if(pin_status_ctrl[2])//加

                begin

                    reg4 <= reg4 + 1'b1;

                    if(reg4 == 4'd9)

                    begin

                        reg4 <= 4'd0;

                        reg3 <= reg3 + 1'b1;

                        if(reg3 > 3'd5)

                            reg3 <= 3'd0;

                    end

                end

                else if(pin_status_ctrl[1])//减

                    begin

                        reg4 <= reg4 - 1'b1;

                        if(reg4 == 4'd0)

                            begin

                                reg4 <= 4'd9;

                                reg3 <= reg3 - 1'b1;

                                if(reg3 == 3'd0)

                                    reg3 <= 3'd5;//这里写反了之前



                            end

                    end

            end



            //调时模式

            3'd2:

            begin

                isCount <= 1'b1;

  LED = 4'B0010;

                if(pin_status_ctrl[2])//加

                begin

                    if(flag == 2'd2)

                    begin

                        reg2 <= reg2 + 1'b1;

                        if(reg2 >= 4'd3)

                        begin

                            reg2 <= 4'd0;

                            reg1 <= 2'd0;

          

相关文章