FPGA——分秒计数器设计(DE2-115开发板)

news2025/3/31 15:08:38

一、项目创建

1.创建工程

点击File->New Project Wizard...或者直接在页面处点击

 在第一行选择文件存放地点,第二行为项目名称,第三行为顶级设计实体名称

(下面的步骤可以暂时不做直接点Finish,因为是先写代码先把它跑出来暂时不用开发板) 

 一直Next直到下图,在框出的地方输入开发板芯片型号并选择

 这里选择 ModelSim-Altera 进行仿真(不需要仿真可以不选)

 然后继续点Next,直到完成

 2.创建文件

 选择File,点击New创建文件

选择框出的选项

然后关联了VSCode后会自动跳转到VSCode

二、功能实现

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

代码: 
module top(
    input CLOCK_50,     // 50MHz时钟(PIN_Y2)
    input KEY0,         // 复位按钮(PIN_M23)
    input KEY1,         // 暂停按钮(PIN_M21)
    output [6:0] HEX0,  // 秒个位(PIN_G18等)
    output [6:0] HEX1,  // 秒十位(PIN_M24等)
    output [6:0] HEX2,  // 分个位(PIN_K22等)
    output [6:0] HEX3   // 分十位(PIN_K21等)
);

// 内部信号声明
wire reset = ~KEY0;     // 低电平有效复位
wire clk_1hz;           // 1Hz时钟
wire carry_sec;         
wire key_stable;        // 消抖后的按键信号
reg pause_state = 0;    // 暂停状态寄存器
reg key_stable_d;       // 用于边沿检测的延迟寄存器

wire [3:0] sec_ones;    // 秒个位
wire [3:0] sec_tens;    // 秒十位
wire [3:0] min_ones;    // 分个位
wire [3:0] min_tens;    // 分十位

// 消抖后的暂停信号
debounce pause_debouncer(
    .clk(CLOCK_50),
    .button(~KEY1),     // KEY1低电平有效
    .out(key_stable)
);

// 边沿检测逻辑(上升沿)
always @(posedge CLOCK_50) begin
    key_stable_d <= key_stable;
end
wire key_rise = key_stable & ~key_stable_d;

// 状态翻转逻辑(每次按键翻转pause_state)
always @(posedge CLOCK_50 or posedge reset) begin
    if (reset) begin
        pause_state <= 0;
    end else if (key_rise) begin
        pause_state <= ~pause_state; // 按键按下时翻转状态
    end
end

// 时钟分频模块实例化
clk_divider clk_div(
    .clk(CLOCK_50),
    .reset(reset),
    .pause(pause_state),      // 暂停控制
    .clk_1hz(clk_1hz)
);

// 秒计数器模块实例化(添加enable端口)
second_counter sec_cnt(
    .clk(clk_1hz),
    .reset(reset),
    .enable(~pause),    // 暂停时停止计数
    .sec_ones(sec_ones),
    .sec_tens(sec_tens),
    .carry_sec(carry_sec)
);

// 分钟计数器模块实例化
minute_counter min_cnt(
    .clk(clk_1hz),
    .reset(reset),
    .inc(carry_sec),
    .min_ones(min_ones),
    .min_tens(min_tens)
);

// 七段译码器实例化
seg7_decoder seg_sec0(.bcd(sec_ones), .seg(HEX0));  // 秒个位
seg7_decoder seg_sec1(.bcd(sec_tens), .seg(HEX1));  // 秒十位
seg7_decoder seg_min0(.bcd(min_ones), .seg(HEX2));  // 分个位
seg7_decoder seg_min1(.bcd(min_tens), .seg(HEX3));  // 分十位

endmodule

// 时钟分频模块(带暂停控制)
module clk_divider(
    input clk,
    input reset,
    input pause, 
    output reg clk_1hz
);
reg [25:0] counter;

always @(posedge clk or posedge reset) begin
    if (reset) begin
        counter <= 0;
        clk_1hz <= 0;
    end
    else if (!pause) begin  // 暂停时停止分频
        if (counter == 26'd24_999_999) begin
            counter <= 0;
            clk_1hz <= ~clk_1hz;
        end
        else begin
            counter <= counter + 1;
        end
    end
end
endmodule

// 改进的按键消抖模块(20ms消抖)
module debounce(
    input clk,
    input button,
    output reg out
);
reg [19:0] counter;
reg [2:0] button_sync;  // 三级同步器

always @(posedge clk) begin
    // 同步器链
    button_sync <= {button_sync[1:0], button};
    
    // 消抖逻辑
    if (button_sync[2] != out) begin
        counter <= counter + 1;
        if (&counter) begin  // 计满20ms(50MHz时钟)
            out <= button_sync[2];
            counter <= 0;
        end
    end
    else begin
        counter <= 0;
    end
end
endmodule

// 带使能端的秒计数器
module second_counter(
    input clk,
    input reset,
    input enable,       // 使能信号
    output reg [3:0] sec_ones,
    output reg [3:0] sec_tens,
    output carry_sec    // 改为组合逻辑输出
);

// 组合逻辑判断是否到达59秒
assign carry_sec = (sec_ones == 9) && (sec_tens == 5);

always @(posedge clk or posedge reset) begin
    if (reset) begin
        sec_ones <= 0;
        sec_tens <= 0;
    end
    else if (enable) begin
        if (sec_ones == 9) begin
            sec_ones <= 0;
            if (sec_tens == 5)
                sec_tens <= 0;
            else
                sec_tens <= sec_tens + 1;
        end
        else begin
            sec_ones <= sec_ones + 1;
        end
    end
end
endmodule

// 分钟计数器(保持不变)
module minute_counter(
    input clk,
    input reset,
    input inc,
    output reg [3:0] min_ones,
    output reg [3:0] min_tens
);
always @(posedge clk or posedge reset) begin
    if (reset) begin
        min_ones <= 0;
        min_tens <= 0;
    end
    else if (inc) begin
        if (min_ones == 9) begin
            min_ones <= 0;
            if (min_tens == 5)
                min_tens <= 0;
            else
                min_tens <= min_tens + 1;
        end
        else begin
            min_ones <= min_ones + 1;
        end
    end
end
endmodule

// 七段译码器(保持不变)
module seg7_decoder(
    input [3:0] bcd,
    output reg [6:0] seg
);
always @(*) begin
    case (bcd)
        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

代码写好后一定要保存(每次更改也要保存不然运行的不是你更改后的代码),文件名默认为Verilog1,点击另存为,文件名为top(后缀.v,文件名和你的顶层实体名一样)

然后回到Quartus点击编译(此处单纯进行代码编译,检查代码是否错误,整体运行时间较久)点击1或者2处均可,编译成功无报错后点击3处或者在菜单栏点击Assignments->Pin Planner配置引脚

引脚配置如下图所示,配置好后退出就行

 然后对整个程序进行运行,点击框出的按钮或者点击Processing->Start Compilation

运行成功无报错后进行烧录(板子提前插好电源线和烧录程序的线),点击下图框选的两处均可进行烧录

第一次烧录可先点击Hardware Setup...,然后在Currently...处选择接入的USB线(第一次做的或许会找不到,可能是因为没有安装驱动,打开设备管理器,可以看到Altera USB-Blaster,图标下方有个黄色三角形警告,点击它选择下载驱动就行)

注意1,2处的选择,默认一般是这样,然后就可以点击Start,进度条为100%就成功了

最终效果:

计时器

2.状态机思想实现的分秒计数器

代码:

module top(
    input CLOCK_50,     // 50MHz时钟(PIN_Y2)
    input KEY0,         // 复位按钮(PIN_M23)
    input KEY1,         // 暂停按钮(PIN_M21)
    output [6:0] HEX0,  // 秒个位(PIN_G18等)
    output [6:0] HEX1,  // 秒十位(PIN_M24等)
    output [6:0] HEX2,  // 分个位(PIN_K22等)
    output [6:0] HEX3   // 分十位(PIN_K21等)
);

// 状态定义
localparam RUN    = 1'b0;
localparam PAUSE  = 1'b1;

// 内部信号声明
wire reset = ~KEY0;     // 低电平有效复位
wire clk_1hz;           // 1Hz时钟
wire carry_sec;         
wire key_stable;        // 消抖后的按键信号
reg key_stable_d;       // 用于边沿检测的延迟寄存器

// 计数器输出信号定义
wire [3:0] sec_ones; 
wire [3:0] sec_tens;
wire [3:0] min_ones;
wire [3:0] min_tens;

// 状态寄存器
reg current_state;
reg next_state;

// 消抖后的暂停信号
debounce pause_debouncer(
    .clk(CLOCK_50),
    .button(~KEY1),     // KEY1低电平有效
    .out(key_stable)
);

// 边沿检测逻辑(上升沿)
always @(posedge CLOCK_50) begin
    key_stable_d <= key_stable;
end
wire key_rise = key_stable & ~key_stable_d;

// 状态转移逻辑
always @(*) begin
    case (current_state)
        RUN:   next_state = key_rise ? PAUSE : RUN;
        PAUSE: next_state = key_rise ? RUN   : PAUSE;
        default: next_state = RUN;
    endcase
end

// 状态翻转逻辑(每次按键翻转pause_state)
always @(posedge CLOCK_50 or posedge reset) begin
    if (reset) current_state <= RUN;
    else current_state <= next_state;
end
// 输出控制信号
wire pause = (current_state == PAUSE);

// 时钟分频模块实例化
clk_divider clk_div(
    .clk(CLOCK_50),
    .reset(reset),
    .pause(pause),
    .clk_1hz(clk_1hz)
);

// 秒计数器模块实例化
second_counter sec_cnt(
    .clk(clk_1hz),
    .reset(reset),
    .enable(~pause),    // 暂停时停止计数
    .sec_ones(sec_ones),
    .sec_tens(sec_tens),
    .carry_sec(carry_sec)
);

// 分钟计数器模块实例化
minute_counter min_cnt(
    .clk(clk_1hz),
    .reset(reset),
    .inc(carry_sec),
    .min_ones(min_ones),
    .min_tens(min_tens)
);

// 七段译码器实例化
seg7_decoder seg_sec0(.bcd(sec_ones), .seg(HEX0));  // 秒个位
seg7_decoder seg_sec1(.bcd(sec_tens), .seg(HEX1));  // 秒十位
seg7_decoder seg_min0(.bcd(min_ones), .seg(HEX2));  // 分个位
seg7_decoder seg_min1(.bcd(min_tens), .seg(HEX3));  // 分十位

endmodule

// 时钟分频模块(带暂停控制)
module clk_divider(
    input clk,
    input reset,
    input pause, 
    output reg clk_1hz
);
reg [25:0] counter;

always @(posedge clk or posedge reset) begin
    if (reset) begin
        counter <= 0;
        clk_1hz <= 0;
    end
    else if (!pause) begin  // 暂停时停止分频
        if (counter == 26'd24_999_999) begin
            counter <= 0;
            clk_1hz <= ~clk_1hz;
        end
        else begin
            counter <= counter + 1;
        end
    end
end
endmodule

// 按键消抖模块(20ms消抖)
module debounce(
    input clk,
    input button,
    output reg out
);
reg [19:0] counter;
reg [2:0] button_sync;  // 三级同步器

always @(posedge clk) begin
    // 同步器链
    button_sync <= {button_sync[1:0], button};
    
    // 消抖逻辑
    if (button_sync[2] != out) begin
        counter <= counter + 1;
        if (&counter) begin  // 计满20ms(50MHz时钟)
            out <= button_sync[2];
            counter <= 0;
        end
    end
    else begin
        counter <= 0;
    end
end
endmodule

// 带使能端的秒计数器
module second_counter(
    input clk,
    input reset,
    input enable,       // 使能信号
    output reg [3:0] sec_ones,
    output reg [3:0] sec_tens,
    output carry_sec    // 改为组合逻辑输出
);

// 组合逻辑判断是否到达59秒
assign carry_sec = (sec_ones == 9) && (sec_tens == 5);

always @(posedge clk or posedge reset) begin
    if (reset) begin
        sec_ones <= 0;
        sec_tens <= 0;
    end
    else if (enable) begin
        if (sec_ones == 9) begin
            sec_ones <= 0;
            if (sec_tens == 5)
                sec_tens <= 0;
            else
                sec_tens <= sec_tens + 1;
        end
        else begin
            sec_ones <= sec_ones + 1;
        end
    end
end
endmodule

// 分钟计数器
module minute_counter(
    input clk,
    input reset,
    input inc,
    output reg [3:0] min_ones,
    output reg [3:0] min_tens
);
always @(posedge clk or posedge reset) begin
    if (reset) begin
        min_ones <= 0;
        min_tens <= 0;
    end
    else if (inc) begin
        if (min_ones == 9) begin
            min_ones <= 0;
            if (min_tens == 5)
                min_tens <= 0;
            else
                min_tens <= min_tens + 1;
        end
        else begin
            min_ones <= min_ones + 1;
        end
    end
end
endmodule

// 七段译码器
module seg7_decoder(
    input [3:0] bcd,
    output reg [6:0] seg
);
always @(*) begin
    case (bcd)
        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

其他步骤都是一样的,在开发板上的效果也同上。

三、总结

本次实验在DE2-115开发板上实现了一个分秒计数器,且有按键暂停、按键消抖的功能,还用状态机思想实现了一次,代码是用DeepSeek辅助写的,自己暂时还写不出来,先把功能实现后再逐步分析正确的代码更有助于我的学习,文章有什么问题与不足还请多多指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

雅思练习总结(九)

雅思练习总结&#xff08;九&#xff09; 本文章是雅思练习总结&#xff08;九&#xff09;&#xff0c;总结了文章《BAKELITE》&#xff0c;内容包括原文精翻&#xff0c;文章脉络总结&#xff0c;单词扩展学习3个部分 1 文章原文及翻译 BAKELITE 翻译&#xff1a;贝克莱特…

windows USB 了解

GUID GUID 是一个 128 位的数字&#xff0c;在全球范围内是独一无二的&#xff0c;常被用于标识软件组件、设备接口等&#xff0c;以保证在不同系统和环境中能唯一识别特定对象。 DEFINE_GUID(GUID_DEVINTERFACE_USCUSTOMKEYS, 0x12345678, 0x1234, 0x5678, 0x12, 0x12, 0x23…

光谱相机的光谱信息获取

光谱信息的获取方式主要依赖于不同分光技术和成像方法&#xff0c;将入射光分解为不同波长并记录其强度。以下是常见的光谱信息获取技术分类及原理&#xff1a; ‌1. 分光技术&#xff08;物理分解波长&#xff09;‌ ‌(1) 滤光片法‌ ‌原理‌&#xff1a;使用固定或可调滤…

免去繁琐的手动埋点,Gin 框架可观测性最佳实践

作者&#xff1a;牧思 背景 在云原生时代的今天&#xff0c;Golang 编程语言越来越成为开发者们的首选&#xff0c;而对于 Golang 开发者来说&#xff0c;最著名的 Golang Web 框架莫过于 Gin [ 1] 框架了&#xff0c;Gin 框架作为 Golang 编程语言官方的推荐框架 [ 2] &…

构建大语言模型应用:简介(第一部分)

本专栏聚焦大语言模型&#xff08;LLM&#xff09;相关内容的解析&#xff0c;通过检索增强生成&#xff08;RAG&#xff09;应用的视角来进行。 本系列文章 简介&#xff08;本文&#xff09;数据准备句子转换器向量数据库搜索与检索大语言模型开源检索增强生成评估大语言模…

PEmicro Multilink FX调试踩坑

文章目录 1.背景2 功能说明2.1 实时数据查看功能2.1 电压观测2.2 SWO功能 3 设置与支持 1.背景 既然使用了NXP的芯片&#xff0c;笔者就想使用一下它的专用调试器&#xff0c;这里先说一下&#xff0c;笔者是从朋友那里借了一个调试器&#xff0c;型号为PEmicro Multilink FX …

主流大模型采用的架构、注意力机制、位置编码等汇总表

记录下主流大模型的一些核心知识点&#xff0c;包括&#xff1a; 架构注意力机制位置编码归一化激活函数模型参数 表中的一些模型已经是很久之前的了&#xff0c;比如表中并未收入 DeepSeek V3 中使用的MLA的注意力机制。先占个位&#xff0c;后续如果有更新的汇总表再来更…

SpringBoot学习笔记3.27

目录 实战篇第二课 1.注册参数的校验&#xff1a; 学习过程中遇到的问题&#xff1a; 1.什么是正则表达式 2.怎么自定义异常&#xff1f; 1. 创建全局异常处理类 2. 定义响应对象 3. 使用 ExceptionHandler 4. 设置响应状态码 5. 返回统一响应 6. 测试全局异常处理 …

2025NCTF--Web

文章目录 Websqlmap-masterez_dashez_dash_revenge Web sqlmap-master 源码 from fastapi import FastAPI, Request from fastapi.responses import FileResponse, StreamingResponse import subprocessapp FastAPI()app.get("/") async def index():return File…

如何破解软件自动化测试框架的维护难题

破解软件自动化测试框架的维护难题应从优化测试用例设计、加强脚本的模块化与复用性、提高自动化测试工具的选择与使用效率等方面入手。其中&#xff0c;加强脚本的模块化与复用性尤为关键&#xff0c;通过提高脚本的模块化程度&#xff0c;可以显著降低后续维护成本&#xff0…

外星人入侵(python设计小游戏)

这个游戏简而言之就是操作一个飞机对前方的飞船进行射击&#xff0c;和一款很久之前的游戏很像&#xff0c;这里是超级低配版那个游戏&#xff0c;先来看看效果图&#xff1a; 由于设计的是全屏的&#xff0c;所以电脑不能截图。。。。 下面的就是你操控的飞船&#xff0c;上面…

iOS rootless无根越狱检测方案

不同于安卓的开源生态&#xff0c;iOS一直秉承着安全性更高的闭源生态&#xff0c;系统中的硬件、软件和服务会经过严格审核和测试&#xff0c;来保障安全性与稳定性。 据FairGurd观察&#xff0c;虽然iOS系统具备一定的安全性&#xff0c;但并非没有漏洞&#xff0c;如市面上…

LLM 优化技术(1)——Scaled-Dot-Product-Attention(SDPA)

在 Transformer 中抛弃了传统的 CNN 和 RNN&#xff0c;整个网络结构完全由Scaled Dot Product Attention 和Feed Forward Neural Network组成。一个基于 Transformer 的可训练的神经网络可以通过堆叠 Transformer 的形式进行搭建&#xff0c;Attention is All You Need论文中通…

基于音频驱动的CATIA动态曲面生成技术解析

一、技术背景与创新价值 在工业设计领域&#xff0c;参数化建模与动态仿真的结合一直是研究热点。本文提出的音频驱动建模技术突破了传统参数调整方式&#xff0c;实现了音乐节奏与三维曲面的实时动态交互。该技术可广泛应用于以下场景&#xff1a; ​艺术化产品设计&#xf…

5-管理员-维护权限

在“后台”-“人员管理”-“权限”下&#xff0c;通过不同的操作按钮&#xff0c;按照权限分组对权限进行设置。操作部分的按钮依次为 视野维护&#xff1a;设置该分组可以查看、访问的视图。权限维护&#xff1a;设置分组成员可以操作的具体动作等所有在禅道中涉及的权限。成…

全新升级 | Built For You Spring ‘25 发布,Fin 智能客服实现新突破!

图像识别、语音交互、任务自动化&#xff0c;立即体验智能客服蜕变&#xff01; 上周&#xff0c;Intercom 举办了 Built For You Spring 25 发布会&#xff0c;正式揭晓了 AI Agent Fin 的一系列令人振奋的更新。Fin 正在以前所未有的速度革新客户支持模式——它已经成功解决了…

LeeCode 434. 字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 请注意&#xff0c;你可以假定字符串里不包括任何不可打印的字符。 示例: 输入: "Hello, my name is John" 输出: 5 解释: 这里的单词是指连续的不是空格的字符&#xff0c;所以 "…

【AI编程学习之Python】第一天:Python的介绍

Python介绍 简介 Python是一种解释型、面向对象的语言。由吉多范罗苏姆(Guido van Rossum)于1989年发明,1991年正式公布。官网:www.python.org Python单词是"大蟒蛇”的意思。但是龟叔不是喜欢蟒蛇才起这个名字,而是正在追剧:英国电视喜剧片《蒙提派森的飞行马戏团》(Mo…

西域平台商品详情接口设计与实现‌

接口描述&#xff1a; 该接口用于获取西域平台中指定商品的详细信息&#xff0c;包括商品名称、价格、库存、描述、图片等。 点击获取key和secret 接口地址&#xff1a; GET /api/product/detail 请求参数&#xff1a; 参数名 类型 是否必填 描述 productId st…

如何让 history 记录命令执行时间?Linux/macOS 终端时间戳设置指南

引言:你真的会用 history 吗? 有没有遇到过这样的情况:你想回顾某个重要命令的执行记录,却发现 history 只列出了命令序号和内容,根本没有时间戳?这在运维排查、故障分析、甚至审计时都会带来极大的不便。 想象一下,你在服务器上误删了某个文件,但不知道具体是几点执…