实战项目——多功能电子时钟

一,项目要求

在这里插入图片描述

二,理论原理

通过按键来控制状态机的状态,在将状态值传送到各个模块进行驱动,在空闲状态下,数码管显示基础时钟,基础时钟是由7个计数器组合而成,当在ADJUST状态下可以调整时间,并且基础时间会随基础时钟的改变而改变,同过位置使能来确定更改的值在按下确定来更改基础时钟的时间,ALARM状态下可以设置闹钟的时间,设定方法和更改时钟方法一致,随后设置了一个beep_flag来驱动beep,当beep_flag为1且到达设定时间就响,若beep_flag不为1则停止响动,最后的秒表功能不多做赘述,之后通过状态机传出来的值,驱动数码管显示那个模块的输出值.

三,系统架构分析

本次系统架构分为:状态机模块,数码管驱动模块,基础时钟模块,调时模块,闹钟模块,秒表模块
在这里插入图片描述

三,状态转移图

在这里插入图片描述

四,源码展示

首先是状态机模块的实现,这里对应上边的状态转移图,通过传出的使能信号state来控制各个模块

/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 这是一个状态机模块用来控制不同状态的转换
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module state_change( 
    input 	wire				clk		,
    input 	wire				rst_n	,
    input   wire    [3:0]       key_in  ,//按键输入
    input   wire                beep    ,
    output  reg     [1:0]       led_on  ,//led灯显示用来判断当前在什么状态
    output  reg     [1:0]       state    //状态输出
);								 
//---------<参数定义>--------------------------------------------------------- 
parameter IDLE = 4'b0001,   //空闲状态表示显示基础时钟
          ADJUST = 4'b0010,//更改状态可以更改时钟的值
          ALARM  = 4'b0100,//闹钟状态,可以制定闹钟
          STOP   = 4'b1000;
//---------<内部信号定义>-----------------------------------------------------
reg     [3:0]   cstate;//现态
reg     [3:0]   nstate;//次态

//****************************************************************
//状态机
//****************************************************************
//三段式状态机第一段时序逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cstate <= IDLE;
    end
    else begin
        cstate <= nstate;
    end
end

//三段式状态机第二段组合逻辑
always @(*) begin
    case (cstate)
        IDLE    :begin
                    if (!key_in[0]) begin //当按键0按下时转到调时状态
                        nstate = ADJUST;
                    end
                    else if (!key_in[1]||!beep) begin
                        nstate = ALARM;
                    end
                    else if (!key_in[2]) begin
                        nstate = STOP ;
                    end
                    else begin
                        nstate = cstate; 
                    end
                end 
        ADJUST  :begin
                    if (!key_in[0]||!key_in[3]) begin//当按下按键0时转到基础时钟
                        nstate = IDLE;  
                    end
                    else if (!beep) begin//当蜂鸣器响立刻跳转到闹钟状态
                        nstate = ALARM;
                    end
                    else begin
                        nstate = cstate;
                    end
                end
        ALARM   :begin
                    if (!key_in[0]) begin//当按下按键0时转到基础时钟
                        nstate = IDLE;  
                    end
                    else begin
                        nstate = cstate;
                    end
                end
        STOP    :begin
                    if (!key_in[0]) begin
                        nstate = IDLE;
                    end
                    else if (!beep) begin//当蜂鸣器响立刻跳转到闹钟状态
                        nstate = ALARM;
                    end
                    else begin
                        nstate = cstate;
                    end
                end
        default: nstate = IDLE;
    endcase
end 

//三段式状态机第三段时序逻辑
always @(posedge clk or  negedge rst_n) begin
    if (!rst_n) begin
        state <= 2'b00;
    end
    else case (cstate)
        IDLE    : state <= 2'b00;
        ADJUST  : state <= 2'b01;
        ALARM   : state <= 2'b10;
        STOP    : state <= 2'b11;
        default: state <= 2'b00;
    endcase
end

//****************************************************************
//led显示状态,通过led的亮灭状态来看处在什么状态
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        led_on <= 2'b00;
    end
    else case (cstate)
        IDLE    : led_on <= 2'b00;
        ADJUST  : led_on <= 2'b01;
        ALARM   : led_on <= 2'b10;
        STOP    : led_on <= 2'b11;
        default: led_on <= 2'b00;
    endcase
end
endmodule

接下来是基础时钟模块,这个模块我为了后边的修改时钟模块方便所以我选择了使用七个计数器来实现。

/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 这是一个基础时钟通过用标准的五个计数器实现
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module counter( 
    input 	wire				clk		,
    input 	wire				rst_n	,
    input   wire    [3:0]       key_in  ,
    input   wire    [1:0]       state   ,//状态
    input   wire    [2:0]       flag    ,//位置信号
    input   wire    [23:0]      adjust_time,     //时间调整
    output  wire    [23:0]      times       //当前时间寄存区
);								 
//---------<参数定义>--------------------------------------------------------- 
parameter MAX1s = 26'd49_999_999;
reg			[25:0]	cnt_1s	;
wire				add_cnt	;
wire				end_cnt	;

//时钟内部参数
reg      [3:0]   sec_low    ;
reg      [3:0]   sec_high   ;
reg      [3:0]   mine_low   ;
reg      [3:0]   mine_high  ;
reg      [3:0]   hour_low   ;
reg      [3:0]   hour_high  ;
wire             add_sec_low;
wire             add_sec_high ;
wire             add_mine_low ;
wire             add_mine_high;
wire             add_hour_low ;
wire             add_hour_high;
wire             end_sec_low  ;
wire             end_sec_high ;
wire             end_mine_low ;
wire             end_mine_high;
wire             end_hour_low ;
wire             end_hour_high;
//---------<内部信号定义>-----------------------------------------------------
//****************************************************************
//1s计时器
//****************************************************************
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_1s <= 26'd0;
    end 
    else if(add_cnt&&(state != 4'b01))begin 
        if(end_cnt)begin 
            cnt_1s <= 26'd0;
        end
        else begin 
            cnt_1s <= cnt_1s + 1'b1;
        end 
    end
end 

assign add_cnt = 1;
assign end_cnt = add_cnt && cnt_1s == MAX1s;
    
//****************************************************************
//时钟计时
//****************************************************************

//****************************************************************
//秒钟计时,通过两个计数器来设定秒的个位和十位
//****************************************************************
always @(posedge clk or negedge rst_n ) begin
    if (!rst_n) begin
        sec_low <= 4'd0;
    end
    else if (add_sec_low) begin
        if (end_sec_low) begin
            sec_low <= 4'd0;
        end
        else begin
            sec_low <= sec_low + 1'd1;
        end
    end
    else if ((state == 2'b01)&&(!key_in[3])) begin
        sec_low <= adjust_time[3:0];
    end
    else begin
        sec_low <= sec_low;
    end   
end
assign add_sec_low = end_cnt&&((state != 2'b01)&&(flag != 3'd1));
assign end_sec_low = (sec_low == 4'd9)&&add_sec_low;

always @(posedge clk or negedge rst_n ) begin
    if (!rst_n) begin
        sec_high <= 4'd0;
    end
    else if (add_sec_high) begin
        if (end_sec_high) begin
            sec_high <= 4'd0;
        end
        else begin
            sec_high <= sec_high + 1'd1;
        end
    end
    else if ((state == 2'b01)&&(!key_in[3])) begin
        sec_high <= adjust_time[7:4];
    end
    else begin
        sec_high <= sec_high;
    end   
end
assign add_sec_high = end_sec_low&&(flag != 3'd2);
assign end_sec_high = (sec_high == 4'd5)&&add_sec_high;
//****************************************************************
//分钟计时器,通过两个计数器来控制分钟个位和十位
//****************************************************************
always @(posedge clk or negedge rst_n ) begin
    if (!rst_n) begin
        mine_low <= 4'd0;
    end
    else if (add_mine_low) begin
        if (end_mine_low) begin
            mine_low <= 4'd0;
        end
        else begin
            mine_low <= mine_low + 1'd1;
        end
    end
    else if ((state == 2'b01)&&(!key_in[3])) begin
        mine_low <= adjust_time[11:8];
    end
    else begin
        mine_low <= mine_low;
    end   
end
assign add_mine_low = end_sec_high&&(flag != 3'd3);
assign end_mine_low = (mine_low == 4'd9)&& add_mine_low;

always @(posedge clk or negedge rst_n ) begin
    if (!rst_n) begin
        mine_high <= 4'd0;
    end
    else if (add_mine_high) begin
        if (end_mine_high) begin
            mine_high <= 4'd0;
        end
        else begin
            mine_high <= mine_high + 1'd1;
        end
    end
    else if ((state == 2'b01)&&(!key_in[3])) begin
        mine_high <= adjust_time[15:12];
    end
    else begin
        mine_high <= mine_high;
    end   
end
assign add_mine_high = end_mine_low &&(flag != 3'd4);
assign end_mine_high = (mine_high == 4'd5)&& add_mine_high;
//****************************************************************
//小时计时器,通过两个计数器来控制小时的个位和十位
//****************************************************************
always @(posedge clk or negedge rst_n ) begin
    if (!rst_n) begin
        hour_low <= 4'd0;
    end
    else if (end_hour_high) begin
        hour_low <= 4'd0;
    end
    else if (add_hour_low) begin
        if (end_hour_low) begin
            hour_low <= 4'd0;
        end
        else begin
            hour_low <= hour_low + 1'd1;
        end
    end
    else if ((state == 2'b01)&&(!key_in[3])) begin
        hour_low <= adjust_time[19:16];
    end
    else begin
        hour_low <= hour_low;
    end   
end
assign add_hour_low = end_mine_high&&(flag != 3'd5) ;
assign end_hour_low = (hour_low == 4'd9)&& add_hour_low;

always @(posedge clk or negedge rst_n ) begin
    if (!rst_n) begin
        hour_high <= 4'd0;
    end
    else if (end_hour_high) begin
        hour_high <= 4'd0;
    end
    else if (add_hour_high) begin

        hour_high <= hour_high + 1'd1;
    end
    else if ((state == 2'b01)&&(!key_in[3])) begin
        hour_high <= adjust_time[23:20];
    end
    else begin
        hour_high <= hour_high;
    end   
end
assign add_hour_high = end_hour_low&&(flag != 3'd6);
assign end_hour_high = (hour_high == 4'd2)&&(hour_low >= 4'd4);
//拼接输出值
assign times = {hour_high , hour_low , mine_high , mine_low , sec_high , sec_low};
endmodule

接下来是修改时钟模块,这里通过定义了一个位置信号来达到选择到每一位,最后把修改的数值重新赋值给基础时钟

/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 这是一个调时模块,通过位置信号和按键信号来更改
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module adjust_state( 
    input 	wire				clk		,//全局时钟
    input 	wire				rst_n	,
    input   wire    [3:0]       key_in  ,//按键输入
    input   wire    [1:0]       state   ,//状态
    input   wire    [23:0]      times   ,//基本时钟时间
    output  wire    [2:0]       flag    ,//位置信号
    output  wire    [23:0]      adjust_time//调整后时间
);								 
//---------<参数定义>--------------------------------------------------------- 
//调时参数定义
reg [2:0]   flag_r;//位置信号
//时钟参数定义
reg      [3:0]   sec_low    ;
reg      [3:0]   sec_high   ;
reg      [3:0]   mine_low   ;
reg      [3:0]   mine_high  ;
reg      [3:0]   hour_low   ;
reg      [3:0]   hour_high  ;

//---------<内部信号定义>-----------------------------------------------------

//****************************************************************
//位置信号驱动
//****************************************************************
//控制位置信号
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag_r <= 3'd0;
    end
    else if ((state == 2'b01)) begin
        if (!key_in[1]) begin
           if (flag_r == 3'd6) begin
            flag_r <= 3'd1;
        end
        else begin
            flag_r <= flag_r + 1'b1;
        end
        end
        else begin
            flag_r <= flag_r;
        end 
    end
    else begin
        flag_r <= 3'd0;
    end
end
assign  flag = flag_r;
//****************************************************************
//调时主要模块,当不在调时状态时使得值一直和时钟保持相等,在调时状态时
//根据位置信号和按键信号来加减值
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        sec_low   <= times[3:0];
        sec_high  <= times[7:4];
        mine_low  <= times[11:8];
        mine_high <= times[15:12];
        hour_low  <= times[19:16];
        hour_high <= times[23:20];
    end
    else if (state != 2'b01) begin
        sec_low   <= times[3:0];
        sec_high  <= times[7:4];
        mine_low  <= times[11:8];
        mine_high <= times[15:12];
        hour_low  <= times[19:16];
        hour_high <= times[23:20];
    end
    else if (state == 2'b01) begin
        if (flag_r == 3'd1) begin
            if (!key_in[2]) begin     //当在调时状态并且位置信号为1时按下按键2使得分钟个位加1,下放同理
                sec_low <= sec_low + 1'b1;
            end
            else if (sec_low == 4'd10) begin
                sec_low <= 4'd0;
            end
        end
        else if (flag_r == 3'd2) begin
            if (!key_in[2]) begin
                sec_high <= sec_high + 1'b1;
            end
            else if (sec_high == 4'd6) begin
                sec_high <= 4'd0;
            end
        end
        else if (flag_r == 3'd3) begin
            if (!key_in[2]) begin
                mine_low <= mine_low + 1'b1;
            end
            else if (mine_low == 4'd10) begin
                mine_low <= 4'd0;
            end
        end
        else if (flag_r == 3'd4) begin
            if (!key_in[2]) begin
                mine_high <= mine_high + 1'b1;
            end
            else if (mine_high == 4'd6) begin
                mine_high <= 4'd0;
            end
        end
        else if (flag_r == 3'd5) begin
            if (!key_in[2]) begin
                hour_low <= hour_low + 1'b1;
            end
            else if ((hour_low == 4'd10)&&(hour_high <= 4'd1)) begin
                hour_low<= 4'd0;
            end
            else if ((hour_low == 4'd4)&&(hour_high == 4'd2)) begin
                hour_low <= 4'd0;
            end
        end
        else if (flag_r == 3'd6) begin
            if (!key_in[2]) begin
                hour_high <= hour_high + 1'b1;
            end
            else if ((hour_high == 4'd2)&&(hour_low >=4'd4)) begin
                hour_high <= 4'd0;
            end
            else if ((hour_high == 4'd3)&&(hour_low < 4'd4)) begin
                hour_high <= 4'd0;
            end
        end
        else begin
            sec_low   <= sec_low  ;
            sec_high  <= sec_high ;
            mine_low  <= mine_low ;
            mine_high <= mine_high;
            hour_low  <= hour_low ;
            hour_high <= hour_high;
        end
    end
end
//调值后的信号输出
assign adjust_time = {hour_high ,hour_low,mine_high , mine_low , sec_high , sec_low} ;
endmodule

下面是对于闹钟模块的介绍,闹钟模块中定时跟修改模块一致,只是会让修改后的值一直保持,只要基础时钟时间跟定时想同就使使能拉高,按下按键或者等待5s使能自动拉低,使能拉高切时间达到就使得蜂鸣器响达到闹钟的效果

/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 这是一个闹钟模块,在调时模块的基础上,增加了蜂鸣器驱动信号,;来控制定时
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module alarm_clock( 
    input 	wire				clk		,
    input 	wire				rst_n	,
    input   wire    [3:0]       key_in  ,
    input   wire    [1:0]       state   ,//状态
    input   wire    [23:0]      times   ,//基础时钟时间
    output  reg                 beep    ,//蜂鸣器
    output  wire    [2:0]       flag_alarm,//闹钟位置信号
    output  wire    [23:0]      adjust_alarm,//设定闹钟时间
    output  wire                led_alarm    //定时led

);								 
//---------<参数定义>--------------------------------------------------------- 
parameter MAX1S = 26'd49_999_999;//1s;


//闹钟参数定义
reg [2:0]   flag_alarm_r;//位置信号
reg         flag_beep_r   ;//蜂鸣器使能
reg      [3:0]   sec_low    ;
reg      [3:0]   sec_high   ;
reg      [3:0]   mine_low   ;
reg      [3:0]   mine_high  ;
reg      [3:0]   hour_low   ;
reg      [3:0]   hour_high  ;

//1s计时器参数定义
reg			[25:0]	cnt	   	;
wire				add_cnt	;
wire				end_cnt	;
//5s计数器参数定义
reg			[2:0]	cnt_5s	   	;
wire				add_cnt_5s	;
wire				end_cnt_5s	;

reg                 led_r       ;//led信号寄存器
reg                 flag        ;//计时驱动
//---------<内部信号定义>-----------------------------------------------------


//****************************************************************
//flag驱动控制计时
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag <= 0;
    end
    else if (end_cnt_5s) begin
        flag <= 1'b0;
    end
    else if (adjust_alarm === times&&times!= 0) begin
        flag <= 1'b1;
    end
    else begin
        flag <= flag ;
    end

end
//****************************************************************
//1s计时器
//****************************************************************


always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt <= 26'd0;
    end 
    else if(add_cnt)begin 
        if(end_cnt)begin 
            cnt <= 26'd0;
        end
        else begin 
            cnt <= cnt + 1'b1;
        end 
    end
    else if (state != 2'b10) begin
        cnt <= 26'd0;
    end
    else begin
        cnt <= cnt;
    end
end 

assign add_cnt = flag;
assign end_cnt = add_cnt && cnt == MAX1S;

//****************************************************************
//5s计时器
//****************************************************************


always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_5s <= 3'd0;
    end 
    else if(add_cnt_5s)begin 
        if(end_cnt_5s)begin 
            cnt_5s <= 3'd0;
        end
        else begin 
            cnt_5s <= cnt_5s + 1'b1;
        end 
    end
    else if (state != 2'b10) begin
        cnt_5s<= 3'd0;
    end
    else begin
        cnt_5s <= cnt_5s;
    end
end 

assign add_cnt_5s = end_cnt;
assign end_cnt_5s = add_cnt_5s && cnt_5s == 3'd5;


//****************************************************************
//位置信号驱动
//****************************************************************
//控制位置信号
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag_alarm_r <= 3'd0;
    end
    else if ((state == 2'b10)) begin
        if (!key_in[1]) begin
           if (flag_alarm_r == 3'd6) begin
            flag_alarm_r <= 3'd1;
        end
        else begin
            flag_alarm_r <= flag_alarm_r + 1'b1;
        end
        end
        else if (!key_in[3]) begin
            flag_alarm_r <= 3'd0;
        end
        else begin
            flag_alarm_r <= flag_alarm_r;
        end 
    end
    else begin
        flag_alarm_r <= 3'd0;
    end
end
assign  flag_alarm = flag_alarm_r;
//****************************************************************
//是定闹钟的主要模块,当不在闹钟状态时使得值一直设定的值一样,在闹钟
//时根据位置信号和按键信号来加减值
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        sec_low   <= 4'd0;
        sec_high  <= 4'd0;
        mine_low  <= 4'd0;
        mine_high <= 4'd0;
        hour_low  <= 4'd0;
        hour_high <= 4'd0;
    end
    else if (state == 2'b10) begin
        if (flag_alarm_r == 3'd1) begin
            if (!key_in[2]) begin
                sec_low <= sec_low + 1'b1;
            end
            else if (sec_low == 4'd10) begin
                sec_low <= 4'd0;
            end
        end
        else if (flag_alarm_r == 3'd2) begin
            if (!key_in[2]) begin
                sec_high <= sec_high + 1'b1;
            end
            else if (sec_high == 4'd6) begin
                sec_high <= 4'd0;
            end
        end
        else if (flag_alarm_r == 3'd3) begin
            if (!key_in[2]) begin
                mine_low <= mine_low + 1'b1;
            end
            else if (mine_low == 4'd10) begin
                mine_low <= 4'd0;
            end
        end
        else if (flag_alarm_r == 3'd4) begin
            if (!key_in[2]) begin
                mine_high <= mine_high + 1'b1;
            end
            else if (mine_high == 4'd6) begin
                mine_high <= 4'd0;
            end
        end
        else if (flag_alarm_r == 3'd5) begin
            if (!key_in[2]) begin
                hour_low <= hour_low + 1'b1;
            end
            else if ((hour_low == 4'd10)&&(hour_high <= 4'd1)) begin
                hour_low<= 4'd0;
            end
            else if ((hour_low == 4'd4)&&(hour_high == 4'd2)) begin
                hour_low <= 4'd0;
            end
        end
        else if (flag_alarm_r == 3'd6) begin
            if (!key_in[2]) begin
                hour_high <= hour_high + 1'b1;
            end
            else if ((hour_high == 4'd2)&&(hour_low >=4'd4)) begin
                hour_high <= 4'd0;
            end
            else if ((hour_high == 4'd3)&&(hour_low < 4'd4)) begin
                hour_high <= 4'd0;
            end
        end
        else begin
            sec_low   <= sec_low  ;
            sec_high  <= sec_high ;
            mine_low  <= mine_low ;
            mine_high <= mine_high;
            hour_low  <= hour_low ;
            hour_high <= hour_high;
        end
    end
end

assign adjust_alarm = {hour_high ,hour_low,mine_high , mine_low , sec_high , sec_low} ;

//****************************************************************
//闹钟判断和蜂鸣器模块
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        beep <= 1'b1;
    end
    else if ((adjust_alarm === times)&&flag_beep_r) begin//当时间达到并且使能为1时beep响
        beep <= 1'b0;
    end
    else if (!flag_beep_r) begin//当时能为0时
        beep <= 1'b1;
    end
    else begin
        beep <= beep;
    end
end
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag_beep_r <= 1'b0;
    end
    else if (end_cnt_5s) begin//当计时结束后使得使能自动归0停止闹钟
        flag_beep_r <= 1'b0;
    end
    else if (!key_in[3]&&(state == 2'b10)) begin//当按下第四个按键时翻转用来控制开始和结束
        flag_beep_r <= ~flag_beep_r;
    end
    else begin
       flag_beep_r <= flag_beep_r; 
    end
end
//****************************************************************
//led显示
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        led_r <= 1'b0;
    end
    else if (flag_beep_r == 1) begin//当使能为1即设定了闹钟led就亮否则不亮
        led_r <= 1'b1;
    end
    else begin
        led_r <= 1'b0;
    end
end
assign led_alarm = led_r;
endmodule    
    

下面是数码管驱动模块,这里我为了让选择到的哪一位频闪所以采用了一个巧妙的三位运算符的方法来控制,大家可以自己看一下

/**************************************功能介绍***********************************
Date	: 2023.8.2
Author	: WZY.
Version	: 
Description: 这是一个数码管显示模块,用来显示各个功能的值
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module seg_dirver( 
    input 	wire				clk		,
    input 	wire				rst_n	,
    input   wire    [1:0]       state   ,//状态
    input   wire    [23:0]      times ,     //基础时钟寄存器
    input   wire    [5:0]       point   ,//点控制寄存器
    input   wire    [2:0]       flag    ,//调时位选信号
    input   wire    [23:0]      adjust_time,//调时显示寄存器
    input   wire    [2:0]       flag_alarm,//闹钟位选信号
    input   wire    [23:0]      adjust_alarm,//闹钟显示寄存器
    input   wire    [23:0]      adjust_clock,//计时器寄存器
    output  reg     [5:0]       sel     ,//位选
    output  reg     [7:0]       seg     //段选
);								 
//---------<参数定义>--------------------------------------------------------- 
parameter MAX20US = 10'd999;
parameter MAX_500MS = 25'd24_999_999;//500ms
//数码管译码参数
parameter   ZERO            =   7'b100_0000    ,
            ONE             =   7'b111_1001    ,
            TWO             =   7'b010_0100    ,
            THREE           =   7'b011_0000    ,
            FOUR            =   7'b001_1001    ,
            FIVE            =   7'b001_0010    ,
            SIX             =   7'b000_0010    ,
            SEVEN           =   7'b111_1000    ,
            EIGHT           =   7'b000_0000    ,
            NINE            =   7'b001_0000    ,
            A               =   7'b000_1000    ,
            B               =   7'b000_0011    ,
            C               =   7'b100_0110    ,
            D               =   7'b010_0001    ,
            E               =   7'b000_0110    ,
            F               =   7'b000_1110    ,
            DARK             =  7'b111_1111     ;//全灭
//---------<内部信号定义>-----------------------------------------------------
//20us计数器
reg			[9:0]	cnt	   	;
wire				add_cnt	;
wire				end_cnt	;
//500ms计数器
reg			[24:0]	cnt_500ms	   	;
wire				add_cnt_500ms	;
wire				end_cnt_500ms	;
reg                 flash;//闪烁信号

reg         [23:0]   num     ;//位选赋值寄存器
reg         [4:0]      seg_temp;//seg单位值
reg                 point_r ;//点位控制
//****************************************************************
//20us计数器
//****************************************************************
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt <= 10'd0;
    end 
    else if(add_cnt)begin 
        if(end_cnt)begin 
            cnt <= 10'd0;
        end
        else begin 
            cnt <= cnt + 1'b1;
        end 
    end
end 

assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt == MAX20US;

//****************************************************************
//500ms计数器
//****************************************************************

always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_500ms <= 25'd0;
    end 
    else if(add_cnt_500ms)begin 
        if(end_cnt_500ms)begin 
            cnt_500ms <= 25'd0;
        end
        else begin 
            cnt_500ms <= cnt_500ms + 1'b1;
        end 
    end
    else begin
        cnt_500ms <= 25'd0;
    end
end 

assign add_cnt_500ms = (state == 2'b01)||(state == 2'b10);
assign end_cnt_500ms = add_cnt_500ms && cnt_500ms == MAX_500MS;
//****************************************************************
//驱动闪烁信号
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flash <= 1'b0;
    end
    else if (end_cnt_500ms) begin//每500ms翻转一次
        flash <= ~flash;
    end
    else if ((state != 2'b01)&&(state != 2'b10)) begin//当不在调时和闹钟状态归0
        flash <= 1'b0;
    end
    else begin
        flash <=flash;
    end
end
//****************************************************************
//seg显示选择.根据状态选择数码管显示的值
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        num <= 24'd0;
    end
    else if (state == 2'b00) begin
        num <=times;
    end
    else if (state == 2'b01) begin
        num <= adjust_time;
    end
    else if (state == 2'b10) begin
        num <= adjust_alarm;
    end
    else if (state == 2'b11) begin
        num <= adjust_clock;
    end
    else  begin
        num <= num;
    end
end
//****************************************************************
//驱动sel
//****************************************************************   
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        sel <= 6'b111_110;
    end 
    else if(end_cnt)begin 
        sel <= {sel[4:0],sel[5]};
    end 
    else begin 
       sel <= sel; 
    end 
end
//****************************************************************
//位选赋值,当选择到哪一位哪一位进行频闪
//****************************************************************
always @(*) begin
    case (sel)
        6'b011111:begin seg_temp = (flash&&((flag==3'd1||(flag_alarm == 3'd1))))?5'd15 : num[3:0]         ; point_r = point[0];end
        6'b101111:begin seg_temp = (flash&&((flag==3'd2||(flag_alarm == 3'd2))))?5'd15 : num[7:4]         ; point_r = point[1];end
        6'b110111:begin seg_temp = (flash&&((flag==3'd3||(flag_alarm == 3'd3))))?5'd15 : num[11:8]        ; point_r = point[2];end
        6'b111011:begin seg_temp = (flash&&((flag==3'd4||(flag_alarm == 3'd4))))?5'd15 : num[15:12]       ; point_r = point[3];end
        6'b111101:begin seg_temp = (flash&&((flag==3'd5||(flag_alarm == 3'd5))))?5'd15 : num[19:16]       ; point_r = point[4];end
        6'b111110:begin seg_temp = (flash&&((flag==3'd6||(flag_alarm == 3'd6))))?5'd15 : num[23:20]       ; point_r = point[5];end
        default: seg_temp = 4'd0;
    endcase
end
//****************************************************************
//译码
//****************************************************************
always @(*) begin
    case (seg_temp)
        4'd0: seg = {point_r,ZERO  };
        4'd1: seg = {point_r,ONE   };
        4'd2: seg = {point_r,TWO   };
        4'd3: seg = {point_r,THREE };
        4'd4: seg = {point_r,FOUR  };
        4'd5: seg = {point_r,FIVE  };
        4'd6: seg = {point_r,SIX   };
        4'd7: seg = {point_r,SEVEN };
        4'd8: seg = {point_r,EIGHT };
        4'd9: seg = {point_r,NINE  };
        4'd15:seg = {point_r,DARK};
        default: seg = 8'b1111_1111;
    endcase
end
endmodule

最后是消抖和秒表比较简单
消抖

module key_debounce (
    input   wire            clk     ,
    input   wire            rst_n   ,
    input   wire    [3:0]   key_in  ,
    output  wire    [3:0]   key_out 
);

parameter MAX20ms = 20'd999_999;

wire            add_cnt;//倒计时开始使能
wire            end_cnt;//倒计时结束使能
reg    [19:0]   cnt_20ms;//20ms计数寄存器
reg    [3:0]    key_r0;//同步
reg    [3:0]    key_r1;//打拍
reg             start;//下降沿检测寄存器
reg    [3:0]    flag;
reg    [3:0]    key_out_r;//输出按键信号寄存器
wire            nedge;



//下降沿检测
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        key_r0 <= 4'b1111;
        key_r1 <= 4'b1111;
    end
    else begin
        key_r0 <= key_in;
        key_r1 <= key_r0;
    end
end

assign nedge = (~key_r0[0]&key_r1[0])||(~key_r0[1]&key_r1[1])||(~key_r0[2]&key_r1[2])||(~key_r0[3]&key_r1[3]);

//20ms计时器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt_20ms <= 20'd0;
    end
    else if (nedge) begin
        cnt_20ms <= 20'd0;
    end
    else if (add_cnt) begin
        if (end_cnt) begin
            cnt_20ms <= 20'd0;
        end
        else begin
            cnt_20ms <= cnt_20ms + 1'b1;
        end
    end
    else begin
        cnt_20ms <= 20'd0;
    end
end

assign add_cnt = start;
assign end_cnt = add_cnt && (cnt_20ms == MAX20ms);

//约束start
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        start <= 1'b0;
    end
    else if (nedge) begin
        start <= 1'b1;
    end
    else if (end_cnt) begin
        start <= 1'b0;
    end
    else begin
        start <= start ;
    end
end

//约束flag
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag <= 4'b1111;
    end
    else if (nedge) begin
        flag <= 4'b1111;
    end
    else if (end_cnt) begin
        flag <= key_r0;
    end
    else begin
        flag <= 4'b1111 ;
    end
end
//脉冲信号
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        key_out_r <= 4'b1111;
    end
    else if (!flag[0]) begin
        key_out_r <= 4'b1110;
    end
    else if (!flag[1]) begin
        key_out_r <= 4'b1101;
    end
    else if (!flag[2]) begin
        key_out_r <= 4'b1011;
    end
    else if (!flag[3]) begin
        key_out_r <= 4'b0111;
    end
    else begin
        key_out_r <= 4'b1111;
    end
end

// //持续信号
// always @(posedge clk or negedge rst_n) begin
//     if (!rst_n) begin
//         key_out_r <= 4'b1111;
//     end
//     else if (!flag[0]) begin
//         key_out_r <= 4'b1110;
//     end
//     else if (!flag[1]) begin
//         key_out_r <= 4'b1101;
//     end
//     else if (!flag[2]) begin
//         key_out_r <= 4'b1011;
//     end
//     else if (!flag[3]) begin
//         key_out_r <= 4'b0111;
//     end
//     else begin
//         key_out_r <= key_out_r;
//     end
// end

assign key_out = key_out_r;
endmodule```
秒表

```cpp
/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 这是一个秒表
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module stop_watch( 
    input 	wire				clk		,
    input 	wire				rst_n	,
    input   wire    [3:0]       key_in  ,
    input   wire    [1:0]       state   ,
    output  wire    [23:0]      adjust_clock//秒表寄存器(分钟/秒/毫秒/)
);								 
//---------<参数定义>--------------------------------------------------------- 
parameter   max1ms = 19'd499_999;//100ms
reg  [3:0]  ms_low;
reg  [3:0]  ms_high;
reg  [3:0]  s_low;
reg  [3:0]  s_high;
reg  [3:0]  mine_low;
reg  [3:0]  mine_high;


reg			[18:0]	cnt	   	;
wire				add_cnt	;
wire				end_cnt	;

wire                add_cnt_ms_low;
wire                end_cnt_ms_low;
wire                add_cnt_ms_high;
wire                end_cnt_ms_high;
wire                add_cnt_s_low;
wire                end_cnt_s_low;
wire                add_cnt_s_high;
wire                end_cnt_s_high;
wire                add_cnt_mine_low;
wire                end_cnt_mine_low;
wire                add_cnt_mine_high;
wire                end_cnt_mine_high;

reg                 flag_clock;
//---------<内部信号定义>-----------------------------------------------------

//****************************************************************
//秒表使能
//****************************************************************
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag_clock <= 1'b0;
    end
    else if ((!key_in[1])&&(state == 2'b11)) begin
        flag_clock <= ~flag_clock;
    end
    else if ((state != 2'b11)||(!key_in[2])) begin
        flag_clock <= 1'b0;
    end
    else begin
        flag_clock <= flag_clock;
    end
end

//****************************************************************
//100ms计数器
//****************************************************************
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt <= 19'd0;
    end 
    else if(add_cnt)begin 
        if(end_cnt)begin 
            cnt <= 19'd0;
        end
        else begin 
            cnt <= cnt + 1'b1;
        end 
    end
    else if ((state != 2'b11)||(!key_in[2])) begin
        cnt <= 19'd0;
    end
    else begin
        cnt <= cnt;
    end
end 

assign add_cnt = (state == 2'b11)&&(flag_clock);
assign end_cnt = add_cnt && (cnt == max1ms);

    
//****************************************************************
//秒表模块
//**************************************************************** 

//ms
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        ms_low <= 4'd0;
    end
    else if (add_cnt_ms_low) begin
        if (end_cnt_ms_low) begin
            ms_low <= 4'd0;
        end
        else begin
            ms_low <= ms_low + 1'd1;
        end
    end
    else if ((state != 2'b11)||((state == 2'b11)&&(!key_in[2]))) begin
        ms_low <= 4'd0;
    end
    else begin
        ms_low <= ms_low;
    end
end

assign add_cnt_ms_low = end_cnt;
assign end_cnt_ms_low = add_cnt_ms_low&&(ms_low == 9);

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        ms_high <= 4'd0;
    end
    else if (add_cnt_ms_high) begin
        if (end_cnt_ms_high) begin
            ms_high <= 4'd0;
        end
        else begin
            ms_high <= ms_high + 1'd1;
        end
    end
    else if ((state != 2'b11)||((state == 2'b11)&&(!key_in[2]))) begin
        ms_high <= 4'd0;
    end
    else begin
        ms_high <= ms_high;
    end
end

assign add_cnt_ms_high = end_cnt_ms_low;
assign end_cnt_ms_high = add_cnt_ms_high&&(ms_high == 5);

//s
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        s_low <= 4'd0;
    end
    else if (add_cnt_s_low) begin
        if (end_cnt_s_low) begin
            s_low <= 4'd0;
        end
        else begin
            s_low <= s_low + 1'd1;
        end
    end
    else if ((state != 2'b11)||((state == 2'b11)&&(!key_in[2]))) begin
        s_low <= 4'd0;
    end
    else begin
        s_low <= s_low;
    end
end

assign add_cnt_s_low = end_cnt_ms_high;
assign end_cnt_s_low = add_cnt_s_low&&(s_low == 9);


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        s_high <= 4'd0;
    end
    else if (add_cnt_s_high) begin
        if (end_cnt_s_high) begin
            s_high <= 4'd0;
        end
        else begin
            s_high <= s_high + 1'd1;
        end
    end
    else if ((state != 2'b11)||((state == 2'b11)&&(!key_in[2]))) begin
        s_high <= 4'd0;
    end
    else begin
        s_high <= s_high;
    end
end

assign add_cnt_s_high = end_cnt_s_low;
assign end_cnt_s_high = add_cnt_s_high&&(s_high == 5);

//mine
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        mine_low <= 4'd0;
    end
    else if (add_cnt_mine_low) begin
        if (end_cnt_mine_low) begin
            mine_low <= 4'd0;
        end
        else begin
            mine_low <= mine_low + 1'd1;
        end
    end
    else if ((state != 2'b11)||((state == 2'b11)&&(!key_in[2]))) begin
        mine_low <= 4'd0;
    end
    else begin
        mine_low <= mine_low;
    end
end

assign add_cnt_mine_low = end_cnt_s_high;
assign end_cnt_mine_low = add_cnt_mine_low&&(mine_low == 9);

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        mine_high <= 4'd0;
    end
    else if (add_cnt_mine_high) begin
        if (end_cnt_mine_high) begin
            mine_high <= 4'd0;
        end
        else begin
            mine_high <= mine_high + 1'd1;
        end
    end
    else if ((state != 2'b11)||((state == 2'b11)&&(!key_in[2]))) begin
        mine_high <= 4'd0;
    end
    else begin
        mine_high <= mine_high;
    end
end

assign add_cnt_mine_high = end_cnt_mine_low;
assign end_cnt_mine_high = add_cnt_mine_high&&(mine_high == 5);


assign adjust_clock = {mine_high , mine_low ,s_high , s_low , ms_high,ms_low};


endmodule

顶层

/**************************************功能介绍***********************************
Date	: 2023.8.2
Author	: WZY.
Version	: 
Description: 这是一个顶层模块
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module top( 
    input   wire		clk     ,
    input   wire		rst_n	,
    input   wire    [3:0]       key_in  ,
    output  wire    [3:0]       led_on  ,
    output  wire                beep    ,
    output  wire    [5:0]       sel     ,
    output  wire    [7:0]       seg    
);								 
//---------<参数定义>--------------------------------------------------------- 
wire    [3:0]   key_debounce;
wire    [1:0]   state;
wire    [2:0]   flag;
wire    [23:0]  times;
wire    [23:0]  adjust_time;
wire    [2:0]   flag_alarm;
wire    [23:0]  adjust_alarm;
wire    [23:0]  adjust_clock;
//---------<内部信号定义>-----------------------------------------------------

// // ****************************************************************
// // 模块例化
// // ****************************************************************   
// //消抖模块例化
// key_debounce key_debounce_inst(
//                 .clk     (clk),
//                 .rst_n   (rst_n),
//                 .key_in  (key_in),
//                 .key_out (key_debounce)
// );

// //状态机例化
// state_change state_change_inst( 
//                 .clk		(clk),
//                 .rst_n	        (rst_n),
//                 .key_in         (key_debounce),//按键输入
//                 .beep           (beep)  ,
//                 .led_on         (led_on[1:0]),//led灯显示用来判断当前在什么状态
//                 .state          (state)  //状态输出
// );

// //基础时钟例化
// counter counter_inst( 
//                 .clk		(clk),
//                 .rst_n	        (rst_n),
//                 .key_in         (key_debounce),
//                 .state          (state),
//                 .flag           (flag),
//                 .times          (times),
//                 .adjust_time    (adjust_time)     //时间调整
// );	
// //调时模块例化
// adjust_state adjust_state_inst( 
//                 .clk	        (clk),
//                 .rst_n	        (rst_n),
//                 .key_in         (key_debounce),
//                 .state          (state),
//                 .times          (times),
//                 .flag           (flag),
//                 .adjust_time    (adjust_time)
// );	
// //闹钟模块例化
// alarm_clock alarm_clock_inst( 
//                 .clk		(clk),
//                 .rst_n	        (rst_n),
//                 .key_in         (key_debounce),
//                 .state          (state),
//                 .times          (times),
//                 .beep           (beep),
//                 .flag_alarm     (flag_alarm),
//                 .adjust_alarm   (adjust_alarm),
//                 .led_alarm      (led_on[3])

// );
// //秒表模块例化
// stop_watch stop_watch_inst( 
//                 .clk		    (clk),
//                 .rst_n	        (rst_n),
//                 .key_in         (key_debounce),
//                 .state          (state),
//                 .adjust_clock   (adjust_clock)//秒表寄存器(分钟/秒/毫秒/)
// );
// //数码管驱动例化
// seg_dirver seg_dirver_inst( 
//                 .clk		(clk),
//                 .rst_n	        (rst_n),
//                 .state          (state),
//                 .times          (times),
//                 .point          (6'b101011),
//                 .flag           (flag),//调时位选信号
//                 .adjust_time    (adjust_time),//调时显示寄存器
//                 .flag_alarm     (flag_alarm),//闹钟位选信号
//                 .adjust_alarm   (adjust_alarm),//闹钟显示寄存器
//                 .adjust_clock   (adjust_clock),//秒表显示寄存器
//                 .sel            (sel),
//                 .seg            (seg)
// );



// ****************************************************************
// 模块例化
// ****************************************************************   
//消抖模块例化
//状态机例化
state_change state_change_inst( 
                .clk		(clk),
                .rst_n	        (rst_n),
                .key_in         (key_in),//按键输入
                .beep           (beep)  ,
                .led_on         (led_on[1:0]),//led灯显示用来判断当前在什么状态
                .state          (state)  //状态输出
);

//基础时钟例化
counter counter_inst( 
                .clk		(clk),
                .rst_n	        (rst_n),
                .key_in         (key_in),
                .state          (state),
                .flag           (flag),
                .times          (times),
                .adjust_time    (adjust_time)     //时间调整
);	
//调时模块例化
adjust_state adjust_state_inst( 
                .clk	        (clk),
                .rst_n	        (rst_n),
                .key_in         (key_),
                .state          (state),
                .times          (times),
                .flag           (flag),
                .adjust_time    (adjust_time)
);	
//闹钟模块例化
alarm_clock alarm_clock_inst( 
                .clk		(clk),
                .rst_n	        (rst_n),
                .key_in         (key_in),
                .state          (state),
                .times          (times),
                .beep           (beep),
                .flag_alarm     (flag_alarm),
                .adjust_alarm   (adjust_alarm),
                .led_alarm      (led_on[3])

);
//秒表模块例化
stop_watch stop_watch_inst( 
                .clk		    (clk),
                .rst_n	        (rst_n),
                .key_in         (key_in),
                .state          (state),
                .adjust_clock   (adjust_clock)//秒表寄存器(分钟/秒/毫秒/)
);
//数码管驱动例化
seg_dirver seg_dirver_inst( 
                .clk		(clk),
                .rst_n	        (rst_n),
                .state          (state),
                .times          (times),
                .point          (6'b101011),
                .flag           (flag),//调时位选信号
                .adjust_time    (adjust_time),//调时显示寄存器
                .flag_alarm     (flag_alarm),//闹钟位选信号
                .adjust_alarm   (adjust_alarm),//闹钟显示寄存器
                .adjust_clock   (adjust_clock),//秒表显示寄存器
                .sel            (sel),
                .seg            (seg)
);
endmodule

四,测试文件

`timescale 1ns/1ns
    
module top_tb();

//激励信号定义 
reg		            clk     ;
reg		            rst_n	;
reg    [3:0]        key_in  ;
   
//输出信号定义	 
wire    [3:0]       led_on ;
wire                beep   ;
wire    [5:0]       sel    ;
wire    [7:0]       seg    ;
//时钟周期参数定义	
    parameter		CYCLE = 20; 
    defparam        top_inst.counter_inst.MAX1s = 10*CYCLE,
                    top_inst.seg_dirver_inst.MAX20US = CYCLE,
                    top_inst.seg_dirver_inst.MAX_500MS = 5*CYCLE,  
                    top_inst.alarm_clock_inst.MAX1S = 10*CYCLE;

//模块例化
    top top_inst( 
        .clk     (clk),
        .rst_n	 (rst_n),
        .key_in  (key_in),
        .led_on  (led_on),
        .beep    (beep),
        .sel     (sel),
        .seg     (seg)
);	

//产生时钟
    initial 		clk = 1'b0;
    always #(CYCLE/2) clk = ~clk;

//产生激励

// //调值模块仿真
//     initial  begin 
//         rst_n = 1'b1;
//         key_in = 4'b1111;
//         #(CYCLE*2);
//         rst_n = 1'b0;
//         #(CYCLE*20);
//        rst_n = 1'b1;
//        #(CYCLE*10000)  //延迟10000个周期来观察基础时钟
//        key_in = 4'b1110;//按下key0进入调时状态
//        #CYCLE
//        key_in = 4'b1111;
//        #(CYCLE*20)
//        key_in = 4'b1101;    //按下key1选择第一位
//        #CYCLE
//        key_in = 4'b1111;
//        #(CYCLE*20)
//        repeat(5)begin
//         key_in = 4'b1011;//连续按下key2使得秒的个位+1
//        #(CYCLE)
//        key_in = 4'b1111;
//        #(CYCLE*20);
//        end
//        #(CYCLE*100)
//        key_in = 4'b0111;//按下key3确定更改时间
//        #(CYCLE)
//        key_in = 4'b1111;
//        #(CYCLE*10000)
//         $stop;
//     end

//调值模块仿真
    initial  begin 
        rst_n = 1'b1;
        key_in = 4'b1111;
        #(CYCLE*2);
        rst_n = 1'b0;
        #(CYCLE*20);
       rst_n = 1'b1;
       key_in = 4'b1101;//按下key1进入闹钟状态
       #CYCLE
       key_in = 4'b1111;
       #(CYCLE*20)
       key_in = 4'b1101;    //按下key1选择第一位
       #CYCLE
       key_in = 4'b1111;
       #(CYCLE*20)
       key_in = 4'b1101;    //按下key1选择第二位
       #CYCLE
       key_in = 4'b1111;
       #(CYCLE*20)
       repeat(5)begin
        key_in = 4'b1011;//连续按下key2使得秒的个位+1使得计时50s
       #(CYCLE)
       key_in = 4'b1111;
       #(CYCLE*20);
       end
       key_in = 4'b0111;//按下key3确定设定闹钟
       #(CYCLE)
       key_in = 4'b1111;
       #(CYCLE*10000)  //延迟10000个周期等待闹钟触发
       #(CYCLE*10000)
        $stop;
    end

endmodule 

波形:
这是基础时钟的仿真波形,可以看到基础功能实现
在这里插入图片描述

这是修改时间模块的波形,可以看到当按键按下时状态改变并且当按下key1时位置信号变为001表示控制个位,之后按下key2个位数字+1并且按下key3时基础时钟的times变更为更改时间adjust_time的值说明更改成功基本功能实现
在这里插入图片描述

下面是闹钟模块的仿真波形,可以看到当设置闹钟后,等到基础时钟到达设定值,蜂鸣器拉低,开始5s计时,当计时结束蜂鸣器拉高停止响,这里我也同样做了按键停止,但是效果差不多,就只展示计时停止
在这里插入图片描述

六,结果展示

上板验证

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C51多功能电子时钟仿真是指通过模拟C51多功能电子时钟的运行过程和功能,进行模拟实验或者虚拟仿真,以实现实际场景中的功能测试和验证。 C51多功能电子时钟是一种基于C51单片机的时钟设备,具备多种功能,如时间显示、闹钟设置、日历显示等。为了验证其在实际使用中的稳定性和功能性,可以通过仿真来进行测试。 首先,仿真时钟的核心部分是C51单片机,可以通过软件模拟器来实现。在软件模拟器中,可以编写C语言程序,模拟时钟的运行流程和相应的功能实现。通过模拟输入按键、控制LED等方式,实现对时钟参数的设置和显示。 其次,仿真时钟可以通过模拟不同的时间段和日期,来验证时钟的准确性和可靠性。例如,可以设置特定的时间,并观察时钟在设定时间点是否准确显示,并能正常触发闹钟功能。同时,还可以模拟时钟经过长时间运行后,对时钟芯片的温度、电压等因素的影响,检测时钟在不同环境下的稳定性。 此外,还可以通过模拟时钟与其他设备的连接和通信,验证其与其他外部设备的兼容性和可扩展性。例如,模拟通过蓝牙或WiFi与手机等设备进行连接和数据传输,以实现远程控制和数据同步功能。 总之,C51多功能电子时钟仿真可以通过软件模拟器模拟时钟的运行和功能,验证其的准确性、稳定性和可靠性,进一步提高时钟设备的质量和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值