关于#Verilog#的简易数字钟问题,如何解决?

就是我在写数字钟的时候出现了代码下载到板子上有功能没有实现的问题,具体问题是我设计的按键开关使用时无法进行小时或分钟的循环计数问题,还有就是从别的地方抄的修改时间的代码,但是不知道该怎么设定闹钟的问题,所以想请教一下佬们,帮我看看代码哪里出了问题

module  top_clock
(
input           clk  ,//系统时钟50MHz
input           rst_n,//复位信号低电平有效
input           key_in0,//模式转换按键
input           key_in1,//加按键
input           key_in2,//选择按键
input                 Hour,  //sw2
input                 Min,   //sw1
output  [5:0]   sel,//输出位选
output  [7:0]   seg, //输出段选
output          Buzzer_Out  
);

wire      [23:0]  data;
wire      [2:0]   cnt_s;
wire              key0;//模式转换按键
wire              key1;//加按键
wire              key2;//选择按键
wire              mode_flag;
key_filter    u1
(
    .clk     (clk   ),   //系统时钟50Mhz
    .rst_n   (rst_n ),   //全局复位
    .key_in  (key_in0),   //按键输入信号
    .key_flag(key0)   //                                   
);
key_filter    u2
(
    .clk     (clk   ),   //系统时钟50Mhz
    .rst_n   (rst_n ),   //全局复位
    .key_in  (key_in1),   //按键输入信号
    .key_flag(key1)   //                                   
);
key_filter    u3
(
    .clk     (clk   ),   //系统时钟50Mhz
    .rst_n   (rst_n ),   //全局复位
    .key_in  (key_in2),   //按键输入信号
    .key_flag(key2)   //                                   
);

data_gen    u4
(
        .clk      (clk      ),   //系统时钟,频率50MHz
        .rst_n    (rst_n    ),   //复位信号,低电平有效
        .cnt_s    (cnt_s    ),
        .data     (data     ),   //数码管要显示的值
        .mode_flag(mode_flag),
        .key1     (key1)   //   
);

clock    u5
(
    .clk     (clk  ),//系统时钟50MHz
    .rst_n   (rst_n),//复位信号低电平有效
    .key0    (key0 ),//模式转换按键 
    .key2    (key2 ),//选择按键
    .point    (6'b010100),   //小数点显示,高电平有效
    .data    (data ),
    .mode_flag(mode_flag),//模式转换标志位,key0每按下一次,模式转换一次,0为正常计数模式,1为调时模式
    .cnt_s   (cnt_s),
    .sel     (sel),    //输出位选
    .seg     (seg)//输出段选
);

Buzzer_module u6
(
    .clk( clk ) ,     
    .rstn( rstn ) ,  
    .data0(data[3:0]), // 秒个位数
    .data1(data[7:4]), // 秒十位数
    .data2(data[11:8]), // 分个位数
    .data3(data[15:12]), // 分十位数
    .Buzzer_Out( Buzzer_Out )  // 输出到顶部的蜂鸣器信号
);

TimeKeeper_module u7
    (
        .clk( clk ),
        .rstn( rstn ),
        .Hour( Hour ),    // 从顶部输入
        .Min( Min ),      // 从顶部输入
        .enable( enable ),  // 添加enable信号
        .data2( data2 ),          // 从U1输入的分钟个位
        .data3( data3 ),          // 从U1输入的分钟十位
        .data4( data4 ),        // 从U1输入的小时个位
        .data5( data5 ),        // 从U1输入的小时十位
    );

    
endmodule

以上是我的主模块,分模块我就挑不会的拿出来

module TimeKeeper_module(
    input clk,
    input rstn,
    input Hour,
    input Min,
    input enable, //添加enable输入    
    output reg [3:0] data2,       // 分钟个位输出
    output reg [3:0] data3,       // 分钟十位输出
    output reg [3:0] data4,       // 小时个位输出
    output reg [3:0] data5        // 小时十位输出
);

     reg clk_1HZ=0;                // 1Hz时钟信号
     reg [24:0]Count;              // 计数器
     parameter T1HZ = 50'd50_000_000;    // 1Hz时钟频率,周期为1秒

    always @ ( posedge clk )        // 在时钟上升沿触发
        begin 
            if( Count == T1HZ - 50'b1 )     // 当计数器达到1Hz时钟周期减1时
                begin
                    Count <= 0;               // 计数器清零
                    clk_1HZ <= ~clk_1HZ;      // 切换1Hz时钟信号的状态
                end
            else
                Count <= Count + 1;         // 计数器递增
        end
     
    always @( posedge clk_1HZ or negedge rstn )  // 在1Hz时钟信号上升沿或复位信号下降沿触发
    begin
        if (rstn == 0) // 这里缺少复位处理
        begin
            data2 <= 0;
            data3 <= 0;
            data4 <= 0;
            data5 <= 0;
        end
        else if (enable)
        begin
            if( Hour == 1 ) // 当调整小时信号为高电平
            begin
                if( data4 == 'd9 ) // 如果小时个位为9
                begin
                    data4 <= 0; // 小时个位清零
                    data5 <= data5 + 1; // 小时十位加1
                end
                else
                begin
                    if( data5 == 'd2 && data4 == 'd3) // 如果小时十位为2且个位为3
                    begin
                        data4 <= 0; // 小时个位清零
                        data5 <= 0; // 小时十位清零
                    end
                    else
                        data4 <= data4 + 1; // 小时个位加1
                end
            end
            else if( Min == 1 ) // 当调整分钟信号为高电平
            begin
                if( data2 == 'd9 ) // 如果分钟个位为9
                begin
                    data2 <= 0; // 分钟个位清零
                    if(data3 == 'd5 ) // 如果分钟十位为5
                        data3 <= 0; // 分钟十位清零
                    else
                        data3 <= data3 + 1; // 分钟十位加1
                end
                else
                    data2 <= data2 + 1; // 分钟个位加1
            end
        end
    end

endmodule


就是这个时间循环的分模块,无法实现按下按钮sw1或sw2时进行小时或分钟的循环操作,但是我确信我的引脚绑定是正确的,我用的板子是EP4C6F17C8型号的板子,如图

img

数字时钟的设计快要交了,希望佬们能帮忙看一下,谢谢佬们

看了你提供的代码,其中的 TimeKeeper_module 是实现小时和分钟增加的模块。对于按键功能无法实现的问题,我有一些猜想可能的问题原因,以及提供相应的解决方法:

  1. 软件模拟问题:首先,你是否尝试使用仿真工具(例如ModelSim)来模拟你的设计,看看是否在仿真环境下能够正常工作。如果模拟环境下按键能够正常工作,那么可能是硬件或FPGA配置的问题。如果在模拟环境下也不能正常工作,那么问题可能在代码逻辑上。

  2. 钢蹦/按键消抖:你的代码中使用了key_filter模块,我猜这可能是用来进行按键消抖的。消抖是很关键的一步,因为物理按键在按下和松开的时候会有很多的噪声。请确认key_filter模块的功能是否正常。

  3. 使能信号问题:你的代码中,TimeKeeper_module使用了一个enable输入信号,当enable为高电平时,按键输入会被接受,进行小时或分钟的增加。请确认在你期望的时刻,这个enable信号是否为高电平。

  4. 复位信号问题:你的代码中,所有模块在复位信号为低电平时将进行复位操作,包括TimeKeeper_moduleBuzzer_moduleclockdata_genkey_filter模块。请确认复位信号在你期望的时刻是否为高电平,以确保模块不在复位状态。

  5. 时钟频率和按键响应时间:如果你的时钟频率过高,可能在你按下和松开按键的时间内,FPGA已经处理了好几个时钟周期。如果你的设计中没有适当的边沿检测,可能会错过按键事件。你可能需要在TimeKeeper_module模块中增加一个边沿检测,当按键从低电平变为高电平时才增加小时或分钟。

以上是一些可能的问题原因和相应的解决方案,希望能帮助你解决问题。