DE2-115分秒计数器

一、模块设计

如若不清楚怎么模块化,请看https://blog.csdn.net/szyugly/article/details/146379170?spm=1001.2014.3001.5501

1.1顶层模块

module top_counter(
    input  wire       CLOCK_50,    // 50MHz时钟
    input  wire       KEY0,        // 暂停/继续按键
    output wire [6:0] HEX3, HEX2, HEX1, HEX0,  // 4位七段数码管
    output wire [3:0] DIGIT_EN     // 数码管位选
);

wire clk_1hz;        // 1Hz时钟
wire clk_scan;       // 扫描时钟(1kHz)
wire pause_pulse;    // 消抖后的暂停信号

// 模块实例化
clk_div u_clk_div(
    .clk_50m(CLOCK_50),
    .clk_1hz(clk_1hz),
    .clk_1k(clk_scan)
);

debounce u_debounce(
    .clk(CLOCK_50),
    .key_in(KEY0),
    .key_out(pause_pulse)
);

time_counter u_time_counter(
    .clk(clk_1hz),
    .pause(pause_pulse),
    .min_ten(min_ten),
    .min_unit(min_unit),
    .sec_ten(sec_ten),
    .sec_unit(sec_unit)
);

display u_display(
    .clk(clk_scan),
    .min_ten(min_ten),
    .min_unit(min_unit),
    .sec_ten(sec_ten),
    .sec_unit(sec_unit),
    .seg_data({HEX3, HEX2, HEX1, HEX0}),
    .digit_en(DIGIT_EN)
);

endmodule

1.2计数器模块

module time_counter(
    input  wire clk,      // 1Hz时钟
    input  wire pause,    // 暂停信号
    output reg [3:0] min_ten,  // 分钟十位
    output reg [3:0] min_unit, // 分钟个位
    output reg [3:0] sec_ten,  // 秒钟十位
    output reg [3:0] sec_unit  // 秒钟个位
);

reg pause_state;  // 暂停状态寄存器

always @(posedge clk) begin
    if(pause) pause_state <= ~pause_state; // 切换暂停状态
end

always @(posedge clk) begin
    if(!pause_state) begin  // 非暂停状态
        // 秒个位计数
        if(sec_unit == 4'd9) begin
            sec_unit <= 0;
            // 秒十位计数
            if(sec_ten == 4'd5) begin
                sec_ten <= 0;
                // 分钟个位计数
                if(min_unit == 4'd9) begin
                    min_unit <= 0;
                    // 分钟十位计数
                    if(min_ten == 4'd5) begin
                        min_ten <= 0;
                    end else begin
                        min_ten <= min_ten + 1;
                    end
                end else begin
                    min_unit <= min_unit + 1;
                end
            end else begin
                sec_ten <= sec_ten + 1;
            end
        end else begin
            sec_unit <= sec_unit + 1;
        end
    end
end

endmodule

1.3按键消抖模块

module debounce(
    input  wire clk,      // 50MHz时钟
    input  wire key_in,   // 原始按键输入
    output reg  key_out   // 消抖后输出
);

reg [19:0] counter;      // 20ms计数器 (50MHz * 0.02s = 1,000,000)
reg key_reg;

always @(posedge clk) begin
    key_reg <= key_in;    // 同步输入
    
    if(key_reg != key_out) begin       // 状态变化
        counter <= 20'd0;
    end else if(counter < 20'd1_000_000) begin
        counter <= counter + 1;
    end else begin
        key_out <= key_reg;           // 稳定后更新输出
    end
end

endmodule

1.4显示驱动模块

module display(
    input  wire clk,          // 扫描时钟(1kHz)
    input  wire [3:0] min_ten,
    input  wire [3:0] min_unit,
    input  wire [3:0] sec_ten,
    input  wire [3:0] sec_unit,
    output reg  [6:0] seg_data,  // 段选信号
    output reg  [3:0] digit_en    // 位选使能
);

reg [1:0] scan_cnt;        // 扫描计数器
reg [3:0] data_temp;       // 当前显示数据

// 七段译码表(共阳极)
parameter [6:0] SEG_BCD [0:9] = {
    7'b1000000, // 0
    7'b1111001, // 1
    7'b0100100, // 2
    7'b0110000, // 3
    7'b0011001, // 4
    7'b0010010, // 5
    7'b0000010, // 6
    7'b1111000, // 7
    7'b0000000, // 8
    7'b0010000  // 9
};

always @(posedge clk) begin
    scan_cnt <= scan_cnt + 1;
    case(scan_cnt)
        2'b00: begin
            digit_en <= 4'b1110;  // 最低位
            data_temp <= sec_unit;
        end
        2'b01: begin
            digit_en <= 4'b1101;
            data_temp <= sec_ten;
        end
        2'b10: begin
            digit_en <= 4'b1011;
            data_temp <= min_unit;
        end
        2'b11: begin
            digit_en <= 4'b0111;  // 最高位
            data_temp <= min_ten;
        end
    endcase
    
    seg_data <= SEG_BCD[data_temp]; // 查表输出
end

endmodule

1.5分频模块

module clk_div(
    input  wire clk_50m,  // 50MHz输入
    output reg  clk_1hz,  // 1Hz输出
    output reg  clk_1k    // 1kHz扫描时钟
);

// 1Hz分频计数器 (50,000,000分频)
reg [25:0] cnt_1hz;
always @(posedge clk_50m) begin
    if(cnt_1hz == 26'd49_999_999) begin
        cnt_1hz <= 0;
        clk_1hz <= ~clk_1hz;
    end else begin
        cnt_1hz <= cnt_1hz + 1;
    end
end

// 1kHz分频计数器 (50,000分频)
reg [15:0] cnt_1k;
always @(posedge clk_50m) begin
    if(cnt_1k == 16'd49_999) begin
        cnt_1k <= 0;
        clk_1k <= ~clk_1k;
    end else begin
        cnt_1k <= cnt_1k + 1;
    end
end

endmodule

二、效果展示

计数器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值