分秒计数器设计(Verilog编程)

在DE2-115板子上用 Verilog编程实现一个 分秒计数器,并具备按键暂停、按键消抖功能。

设计思路:

HEX0和HEX1是秒的个位和十位,HEX2和HEX3是分的个位和十位。将计数器的数值转换成七段数码管的显示码。

然后按键暂停功能,按下一个按键来暂停或继续计数。同时为了防止机械抖动,设计消抖模块当检测到按键按下后,等待一段时间(比如20ms),再检测是否仍然是按下状态,如果是,则认为有效。

状态机的使用,可能需要几个状态,比如运行状态和暂停状态,通过按键切换。状态机的转换由按键事件触发。同时,计数器的递增也需要状态控制,每个1秒递增一次。

代码实现:

module MinuteSecondCounter(
    input clk,          // 50MHz时钟
    input key_pause,    // 暂停按键
    output [6:0] HEX0,  // 秒个位
    output [6:0] HEX1,  // 秒十位
    output [6:0] HEX2,  // 分个位
    output [6:0] HEX3   // 分十位
);

// 内部信号定义
wire pause_pressed;
reg  en_1hz;
reg [5:0] sec = 0;
reg [5:0] min = 0;
reg state = 0; // 0:运行, 1:暂停

// 按键消抖模块实例化
debounce debounce_inst(
    .clk(clk),
    .button(key_pause),
    .out(pause_pressed)
);
parameter CLK_FREQ = 50_000_000; 
localparam CNT_MAX = CLK_FREQ - 1; 
// 1Hz时钟生成
reg [25:0] cnt_div;
always @(posedge clk ) begin
    begin
        cnt_div <= 0;
        en_1hz  <= 0;
    end  begin
        if (cnt_div == CNT_MAX) begin
            cnt_div <= 0;
            en_1hz  <= 1;    
        end else begin
            cnt_div <= cnt_div + 1;
            en_1hz  <= 0;
        end
    end
end

// 边沿检测电路
reg pause_pressed_d;
wire pause_posedge;
always @(posedge clk) pause_pressed_d <= pause_pressed;
assign pause_posedge = ~pause_pressed_d & pause_pressed;

// 状态机控制
always @(posedge clk) begin
    if(pause_posedge) state <= ~state;
end

// 分秒计数器逻辑
always @(posedge clk) begin
    if(!state && en_1hz) begin // 运行状态
        if(sec == 6'd59) begin
            sec <= 0;
            min <= (min == 6'd59) ? 0 : min + 1;
        end else begin
            sec <= sec + 1;
        end
    end
end

// 数码管显示模块
seg7 seg0(.num(sec%10),  .seg(HEX0));
seg7 seg1(.num(sec/10),  .seg(HEX1));
seg7 seg2(.num(min%10),  .seg(HEX2));
seg7 seg3(.num(min/10),  .seg(HEX3));

endmodule

// 按键消抖模块
module debounce(
    input clk,
    input button,
    output reg out
);

reg [19:0] cnt;
reg button_sync;
reg [1:0] state;

parameter IDLE = 0, CHECK = 1;

always @(posedge clk) begin
    button_sync <= button; // 同步输入
    
    case(state)
        IDLE: begin
            if(button_sync != out) begin
                state <= CHECK;
                cnt <= 0;
            end
        end
        CHECK: begin
            if(cnt == 20'd999_999) begin
                out <= button_sync;
                state <= IDLE;
            end else begin
                cnt <= cnt + 1;
            end
        end
    endcase
end
endmodule

// 七段译码器模块个位
module seg7(
    input [3:0] num,
    output reg [6:0] seg
);

always @(*) begin
    case(num)
        4'd0: seg = 7'b1000000; // 0
        4'd1: seg = 7'b1111001; // 1
        4'd2: seg = 7'b0100100; // 2
        4'd3: seg = 7'b0110000; // 3
        4'd4: seg = 7'b0011001; // 4
        4'd5: seg = 7'b0010010; // 5
        4'd6: seg = 7'b0000010; // 6
        4'd7: seg = 7'b1111000; // 7
        4'd8: seg = 7'b0000000; // 8
        4'd9: seg = 7'b0010000; // 9
        default: seg = 7'b1111111; // 灭
    endcase
end
endmodule


实物效果:

总结:
多多益善

你可能感兴趣的:(fpga开发)