【FPGA开发】用 Verilog编程实现一个分秒计数器(实现按键暂停、消抖功能)

目录

一、实现一个分秒计数器

1. 任务说明

2. 消抖模块介绍

2.1 消抖模块的作用

2.2 模块接口定义 

2.3 核心实现原理

2.4 硬件行为测试

3. 项目实例 

3.1 新建项目 

3.2 创建Verilog文件添加至顶层实体 

3.3 引脚分配 

3.4 选择烧录器 

3.5 添加烧录文件&下载

​3.6 烧录结果 


一、实现一个分秒计数器

1. 任务说明

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

2. 消抖模块介绍

2.1 消抖模块的作用

按键在物理接触时会产生机械抖动(约10-20ms),导致FPGA误判多次触发。消抖模块通过延时检测消除抖动,确保每次按键动作只产生单次稳定信号

2.2 模块接口定义 
module debounce #(
    parameter DEBOUNCE_MS = 20,       // 消抖时间(默认20ms)
    parameter CLK_FREQ = 50_000_000   // 时钟频率(默认50MHz)
 )
(
    input clk,         // 时钟输入(50MHz)
    input button_in,    // 原始按键输入(需预同步)
    output reg button_out // 消抖后输出(稳定信号)
);
2.3 核心实现原理

(1) 同步器

reg button_sync;
always @(posedge clk) begin
    button_sync <= button_in;  // 用D触发器同步异步信号
end

 (2) 消抖状态机

localparam COUNTER_MAX = (CLK_FREQ / 1000) * DEBOUNCE_MS;
reg [COUNTER_BITS-1:0] counter;
always @(posedge clk) begin
    if (button_sync != button_out) begin  // 检测到输入变化
        if (counter == COUNTER_MAX-1) begin
            button_out <= button_sync;    // 稳定后更新输出
            counter <= 0;
        end else begin
            counter <= counter + 1;       // 计数等待稳定
        end
    end else begin
        counter <= 0;  // 状态未变化时复位计数器
    end
end

消抖逻辑:

  • 当检测到按键状态变化时,启动计数器。

  • 持续计数直到达到DEBOUNCE_MS时间(如20ms)。

  • 只有信号稳定超过设定时间,才更新输出。

2.4 硬件行为测试
时间按键物理状态button_inbutton_out说明
0ms松开(高)11初始状态
1ms按下(抖动)0→1→01抖动期,输出不变
21ms稳定按下00消抖完成,输出更新
22ms松开(抖动)1→0→10抖动期,输出不变
42ms稳定松开11消抖完成,输出更新

3. 项目实例 

3.1 新建项目 

建立项目工程名

 然后一直点击NEXT进入开发板选型界面

开发板信息如下,点击finish创建 

 

3.2 创建Verilog文件添加至顶层实体 

编译代码如下:

module Counter (
    input clk,            // 50MHz时钟(PIN_Y2)
    input raw_reset,      // 原始复位信号(KEY0,PIN_M23,低有效)
    input raw_start_pause,// 原始启动/暂停信号(KEY1,PIN_M21,低有效)
    output [6:0] hex3,    // 分钟十位(HEX3,无小数点)
    output [6:0] hex2,    // 分钟个位(HEX2,无小数点)
    output [6:0] hex1,    // 秒十位(HEX1,无小数点)
    output [6:0] hex0     // 秒个位(HEX0,无小数点)
);

// ================= 消抖模块 ==================
wire debounced_reset;      // 消抖后的复位(高有效)
wire debounced_start_pause;// 消抖后的启停(高有效)

debounce #(
    .DEBOUNCE_MS(20)      // 20ms消抖时间
) deb_reset_inst (
    .clk(clk),
    .button_in(~raw_reset), // 物理按键低有效,取反
    .button_out(debounced_reset)
);

debounce deb_start_inst (
    .clk(clk),
    .button_in(~raw_start_pause),
    .button_out(debounced_start_pause)
);

// ================= 核心计数 ==================
core_counter counter_core (
    .clk(clk),
    .reset(debounced_reset),
    .start_pause(debounced_start_pause),
    .hex3(hex3),
    .hex2(hex2),
    .hex1(hex1),
    .hex0(hex0)
);

endmodule

// ============== 消抖模块实现 ================
module debounce #(
    parameter DEBOUNCE_MS = 20,       // 消抖时间(毫秒)
    parameter CLK_FREQ = 50_000_000   // 时钟频率(Hz)
)(
    input clk,
    input button_in,     // 原始按键输入
    output reg button_out// 消抖后输出
);

localparam COUNTER_MAX = (CLK_FREQ / 1000) * DEBOUNCE_MS;
localparam COUNTER_BITS = $clog2(COUNTER_MAX);

reg [COUNTER_BITS-1:0] counter;
reg button_sync;

// 同步器防亚稳态
always @(posedge clk) begin
    button_sync <= button_in;
end

// 消抖核心逻辑
always @(posedge clk) begin
    if (button_sync != button_out) begin
        if (counter == COUNTER_MAX-1) begin
            button_out <= button_sync;
            counter <= 0;
        end else begin
            counter <= counter + 1;
        end
    end else begin
        counter <= 0;
    end
end

endmodule

// ============== 核心计数逻辑 ================
module core_counter (
    input clk,
    input reset,        // 高有效复位
    input start_pause,  // 高有效启停(1=暂停,0=运行)
    output [6:0] hex3,  // 改为7位输出
    output [6:0] hex2,
    output [6:0] hex1,
    output [6:0] hex0
);

// 分频器(50MHz→1Hz)
reg [25:0] counter;
wire one_sec_enable = (counter == 26'd49_999_999);

// BCD计数器
reg [3:0] min_tens; // 0-5
reg [3:0] min_ones; // 0-9
reg [3:0] sec_tens; // 0-5
reg [3:0] sec_ones; // 0-9

// 七段译码器(共阳极,g,f,e,d,c,b,a)
function [6:0] seg7;
    input [3:0] bcd;
    begin
        case (bcd)
            4'd0: seg7 = 7'b1000000; // 0
            4'd1: seg7 = 7'b1111001; // 1
            4'd2: seg7 = 7'b0100100; // 2
            4'd3: seg7 = 7'b0110000; // 3
            4'd4: seg7 = 7'b0011001; // 4
            4'd5: seg7 = 7'b0010010; // 5
            4'd6: seg7 = 7'b0000010; // 6
            4'd7: seg7 = 7'b1111000; // 7
            4'd8: seg7 = 7'b0000000; // 8
            4'd9: seg7 = 7'b0010000; // 9
            default: seg7 = 7'b1111111; // 灭
        endcase
    end
endfunction

// 分频逻辑
always @(posedge clk or posedge reset) begin
    if (reset) begin
        counter <= 0;
    end else begin
        if (one_sec_enable)
            counter <= 0;
        else
            counter <= counter + 1;
    end
end

// 计数逻辑(高电平暂停)
always @(posedge clk or posedge reset) begin
    if (reset) begin
        {sec_ones, sec_tens, min_ones, min_tens} <= 16'd0;
    end else if (!start_pause) begin // 低电平运行
        if (one_sec_enable) begin
            if (sec_ones == 9) begin
                sec_ones <= 0;
                if (sec_tens == 5) begin
                    sec_tens <= 0;
                    if (min_ones == 9) begin
                        min_ones <= 0;
                        min_tens <= (min_tens == 5) ? 0 : min_tens + 1;
                    end else begin
                        min_ones <= min_ones + 1;
                    end
                end else begin
                    sec_tens <= sec_tens + 1;
                end
            end else begin
                sec_ones <= sec_ones + 1;
            end
        end
    end
end

// 数码管输出(无小数点)
assign hex3 = seg7(min_tens);  // 分钟十位
assign hex2 = seg7(min_ones);  // 分钟个位
assign hex1 = seg7(sec_tens);  // 秒十位
assign hex0 = seg7(sec_ones);  // 秒个位

endmodule

另存为.v文件(名称与工程名一致)

 选择Files,显示Counter.v文件

右键点击文件,将其设置为顶层实体  

3.3 引脚分配 

进行引脚分配: 

3.4 选择烧录器 

点击选择烧录器 

 选择USB-Blaster [USB-0]

 PS:如果遇到无法识别USB接口的情况,即只显示No-Hardware,可参考一下博客进行解决:使用Altera综合工具Quartus II下载到FPGA时无法识别USB-Blaster问题_fpga usb blaster 禁止-优快云博客文章浏览阅读1.7w次,点赞25次,收藏48次。问题描述:当使用Quartus II综合好的文件下载到FPGA时发现,没有识别到下载接口USB_Blaster,如下图所示。图片中高亮的部分只有显示No Hardware,并没有显示我们需要的USB-Blaster[USB-0](上面截图显示出来USB-Blaster[USB-0]是因为这张图是我解决这个问题后截取的),那么遇到这种情况该如何解决呢?解决方法: 首先检查你得设备..._fpga usb blaster 禁止 https://blog.youkuaiyun.com/l2563898960/article/details/80309089

3.5 添加烧录文件&下载

 

进入output_files,选择.sof文件,点击open 

 

点击添加编程与配置,然后点击start开始下载

3.6 烧录结果 

点击KEY0,分秒计数器重置归零;长按KEY1可以暂停计数,松开可继续计时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值