小梅哥Xilinx FPGA学习笔记17——模块化设计基础之加减法计数器

news2025/4/16 7:58:56

目录

一: 章节导读

1.1 任务要求

1.2 模块功能划分

二: 代码设计

2.1 灯控制逻辑(led_ctrl)

2.2 按键消抖模块(key_filter)

2.3 顶层模块(key_led)

2.4 引脚绑定

一: 章节导读

       在相对大一点的工程设计过程中,设计内容通常不会写在一个设计文件而是会针对不同的功能设计出不同的子文件,最后在顶层文件中再进行例化调用。

1.1 任务要求

       在上面设计并验证了独立按键的消抖,这里基于上一讲的按键消抖模块,利用 EDA 扩展板来实现一个加减法、移位计数器,实现每次按下按键 S0,8 个LED 显示状态以二进制加法格式加1,每次按下按键 S1,8 个 LED 显示状态以二进制加法格式减 1,每次按下按键 S2,8 个 LED 显示状态以二进制格式左移 1位,每次按下按键 S3,8 个 LED 显示状态以二进制格式右移 1 位,并以此学习模块化的设计方式。在后面章节中将利用第四章编写好的独立模块,组合起来设计一些应用性较强的项目,进一步理解模块化设计方式的优点。

1.2 模块功能划分

       为了实现四个按键控制 LED 灯按照二进制计数方式的加减、移位,可以将本讲模块划分为四个按键消抖模块以及一个 LED 控制模块,其模块间的连线如下图所示,这里的 key_in0~3 对应原理图上的 S0~S3 S4 作为复位信号使用。

二: 代码设计

2.1 灯控制逻辑(led_ctrl)

module led_ctrl(
    input       clk,
    input       reset_n,
    input       key_add,//自加按键(这是脉冲信号连接按键消抖模块中的按下脉冲标志Key_P_Flag)
    input       key_sub,//自减按键
    input       key_shift_l, //左移按键
    input       key_shift_r, //右移按键
    output reg  [7:0]led //led 显示 
);

always@(posedge clk or negedge reset_n)
    if(!reset_n)
        led <= 8'b0000_0000;
    else if(key_add)
        led <= led + 1'b1;       
    else if(key_sub)
        led <= led - 1'b1;
    else if(key_shift_l)
        led <= (led << 1);
    else if(key_shift_r)
        led <= (led >> 1);
    else
        led <= led;
endmodule

2.2 按键消抖模块(key_filter)

//基于状态机思维的按键消抖功能verilog实现思路
//1. 对异步输入信号打拍消除亚稳态
//2.寄存打拍后信号,对比得出上升沿与下降沿标志信号
//3.列出所有状态,编写状态机整体框架
//4.编写各状态间跳转方向以及对应跳转条件
//5.编写状态输出逻辑,在正确时刻输出信号赋值

module key_filter(
    input Key,
    input Clk,
    input Reset_n,
    output reg Key_P_Flag,
    output reg Key_R_Flag,
    output reg Key_State//向外输出过滤后的电平信号,使得输出电平比较干净。
    );
    
   
    reg [29:0]cnt_20ms;//定时20ms计数器
    reg [1:0]state;
    reg sync_d0_key,sync_d1_key;//定义两个同步D触发器的输出作为输入是为了消除未知信号Key的亚稳态,以及将异步信号Key变为同步信号  
    reg r_key;//定义下降沿
    wire nedge_key;//下降沿定义
    wire pedge_key;//下降沿定义
    
    
    always@(posedge Clk)
        sync_d0_key <= Key;
    always@(posedge Clk)
        sync_d1_key <= sync_d0_key;
        
    always@(posedge Clk)
        r_key <= sync_d1_key;    
     
    assign nedge_key = (sync_d1_key == 0)&&(r_key == 1);   
    assign pedge_key = (sync_d1_key == 1)&&(r_key == 0);   
       
    localparam IDLE = 0;//localparam是本地参数定义,用于定义一个标识符代表常量,无法进行参数传递,不可修改
    localparam P_FILTER = 1; //parameter可以进行参数传递,就是可修改的意思。
    localparam WAIT_R = 2;
    localparam R_FILTER = 3;
    parameter Dly_20ms_cnt = 1000_000-1;
    
     wire time_20ms_reached;
     assign time_20ms_reached = (cnt_20ms >= Dly_20ms_cnt);
    
     
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
        state <= IDLE;
        Key_R_Flag <= 0;
        Key_P_Flag <= 0;
        cnt_20ms <= 0;
        Key_State <= 1;
    end
    else begin
        case(state)
            IDLE:
                if(nedge_key)
                     state <= P_FILTER;
                else begin
                     state <= IDLE;
                     Key_R_Flag <= 0; //告知外界按键已经松开
                end                     
            P_FILTER:
                 if(time_20ms_reached)begin//顺利到达20ms说明按键已经顺利按下
                     state <= WAIT_R;  
                     Key_P_Flag <= 1; //告知外界按键已经按下
                     cnt_20ms <= 0;//计时到20ms后直接清零。
                     Key_State <= 0;//此时外界按键已经按下,所以输出低电平
                 end    
                 else if(pedge_key)begin
                     state <= IDLE; 
                     cnt_20ms <= 0;//回到IDLE后清零重新计数
                 end 
                 else begin
                     state <= state;  
                     cnt_20ms <= cnt_20ms+1;//其他状态开始计数
                 end           
            WAIT_R:
                 if(pedge_key)
                     state <= R_FILTER;
                 else begin
                     state <= WAIT_R;  
                     Key_P_Flag <= 0;
                 end           
            R_FILTER:
                 if(time_20ms_reached)begin
                     state <= IDLE;
                     Key_R_Flag <= 1; //告知外界按键已经松开
                     cnt_20ms <= 0;//计时到20ms后直接清零。
                     Key_State <= 1; //此时外界按键已经松开,所以Key_State为高电平,这样输出电平就比较干净
                 end    
                 else if(nedge_key)begin
                     state <= WAIT_R;
                     cnt_20ms <= 0;//回到WAIT_R后清零重新计数
                end
                else begin
                     state <= state; 
                     cnt_20ms <= cnt_20ms+1;//其他状态开始计数   
                end
        endcase    
    end   
endmodule

2.3 顶层模块(key_led

module key_led(
    input       clk,
    input       reset_n,
    input       key_in0,//自加按键
    input       key_in1,//自减按键
    input       key_in2, //左移按键
    input       key_in3, //右移按键
    output      [7:0]led //led 显示 
    );
    
    wire Key_P_Flag0;(不同的按键产生不同的脉冲信号)
    wire Key_P_Flag1;
    wire Key_P_Flag2;   
    wire Key_P_Flag3;
    
    key_filter key_filter_inst0(
        .Key(key_in0),
        .Clk(clk),
        .Reset_n(reset_n),
        .Key_P_Flag(Key_P_Flag0),
        .Key_R_Flag(),
        .Key_State()//向外输出过滤后的电平信号,使得输出电平比较干净。
    );
    
    key_filter key_filter_inst1(
        .Key(key_in1),
        .Clk(clk),
        .Reset_n(reset_n),
        .Key_P_Flag(Key_P_Flag1),
        .Key_R_Flag(),
        .Key_State()//向外输出过滤后的电平信号,使得输出电平比较干净。
    );
    
    key_filter key_filter_inst2(
        .Key(key_in2),
        .Clk(clk),
        .Reset_n(reset_n),
        .Key_P_Flag(Key_P_Flag2),
        .Key_R_Flag(),
        .Key_State()//向外输出过滤后的电平信号,使得输出电平比较干净。
    );
      
    key_filter key_filter_inst3(
        .Key(key_in3),
        .Clk(clk),
        .Reset_n(reset_n),
        .Key_P_Flag(Key_P_Flag3),
        .Key_R_Flag(),
        .Key_State()//向外输出过滤后的电平信号,使得输出电平比较干净。
    );
    
    led_ctrl led_ctrl(
        .clk(clk),
        .reset_n(reset_n),
        .key_add(Key_P_Flag0),//自加按键(脉冲信号)
        .key_sub(Key_P_Flag1),//自减按键
        .key_shift_l(Key_P_Flag2), //左移按键
        .key_shift_r(Key_P_Flag3), //右移按键
        .led(led) //led 显示 
);
    
    
endmodule

2.4 引脚绑定

set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports key_in0]
set_property IOSTANDARD LVCMOS33 [get_ports key_in1]
set_property IOSTANDARD LVCMOS33 [get_ports key_in2]
set_property IOSTANDARD LVCMOS33 [get_ports key_in3]
set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
set_property PACKAGE_PIN U18 [get_ports clk]
set_property PACKAGE_PIN H20 [get_ports key_in0]
set_property PACKAGE_PIN H16 [get_ports key_in1]
set_property PACKAGE_PIN J20 [get_ports key_in2]
set_property PACKAGE_PIN J19 [get_ports key_in3]
set_property PACKAGE_PIN F20 [get_ports reset_n]
set_property PACKAGE_PIN K18 [get_ports {led[7]}]
set_property PACKAGE_PIN H17 [get_ports {led[6]}]
set_property PACKAGE_PIN J18 [get_ports {led[5]}]
set_property PACKAGE_PIN K19 [get_ports {led[4]}]
set_property PACKAGE_PIN G18 [get_ports {led[3]}]
set_property PACKAGE_PIN G20 [get_ports {led[2]}]
set_property PACKAGE_PIN G19 [get_ports {led[1]}]
set_property PACKAGE_PIN G17 [get_ports {led[0]}]

上述代码全部经过上板验证,均正确且可正常使用。

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

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

相关文章

报表控件FastReport VCL 中的新 S3 传输 (Amazon)

在本文中&#xff0c;我们将探讨新的 S3 传输。从功能上来说&#xff0c;S3 与大多数人习惯使用的有很大不同&#xff0c;因此在本文的开头&#xff0c;我们将详细介绍它的主要功能。 FastReport .NET 是适用于.NET Core 3&#xff0c;ASP.NET&#xff0c;MVC和Windows窗体的全…

java maven项目添加oracle jdbc的依赖

一般添加依赖是直接在pom.xml中添加配置即可&#xff0c;Maven会自动获取对应的jar包&#xff0c;但是oracle驱动依赖添加后会显示红色&#xff0c;代表找不到依赖项&#xff0c;是因为Oracle授权问题&#xff0c;Maven3不提供Oracle JDBC driver&#xff0c;为了在Maven项目中…

LinkSLA管家式运维:为企业打造定制化 IT 支持体系

引言 在数字化转型的浪潮中&#xff0c;企业信息系统繁多&#xff0c;涉及人员复杂&#xff0c;且企业经营管理活动对IT系统的依赖程度越来越高。传统的运维模式已经不能满足企业对运维工作全面性、灵活性、稳定性和安全性的需求。管家式运维作为一种新型服务模式&#xff0c;…

CUDA安装与Tensorflow1-gpu环境搭建(windows版)

一、前提说明 1.1 Tensorflow-gpu环境搭建基本步骤 (1)明确环境搭建资源需求与下载 (2)安装CUDA与cuDNN (3)用Anaconda搭建tensorflow-gpu环境 (4)tensorflow-gpu环境测试 1.2 个人说明 由于科研需要复现机器学习、深度学习某些经典实验&#xff0c;这…

商品销售数据爬取分析可视化系统 爬虫+机器学习 淘宝销售数据 预测算法模型 大屏 大数据毕业设计(附源码)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

网络层解读

基本介绍 概述 当两台主机之间的距离较远(如相隔几十或几百公里&#xff0c;甚至几千公里)时&#xff0c;就需要另一种结构的网络&#xff0c;即广域网。广域网尚无严格的定义。通常是指覆盖范围很广(远超过一个城市的范围)的长距离的单个网络。它由一些结点交换机以及连接这些…

numpy数组04-数组的轴和读取数据

一、数组的轴 在numpy中数组的轴可以理解为方向&#xff0c;使用0&#xff0c;1&#xff0c;2...数字表示。 对于一个一维数组&#xff0c;只有一个0轴&#xff0c;对于2维数组&#xff08;如shape&#xff08;2&#xff0c;2&#xff09;&#xff09;&#xff0c;有0轴和1轴…

Windows搭建RTSP视频流服务(EasyDarWin服务器版)

文章目录 引言1、安装FFmpeg2、安装EasyDarWin3、实现本地\虚拟摄像头推流服务4、使用VLC或PotPlayer可视化播放器播放视频5、RTSP / RTMP系列文章 引言 RTSP和RTMP视频流的区别 RTSP &#xff08;Real-Time Streaming Protocol&#xff09;实时流媒体协议。 RTSP定义流格式&am…

idea利用JRebel插件,无需重启,实现Spring Boot项目热重载,节省开发时间和精力!

插件介绍 官方介绍 翻译过来的意思是&#xff1a; JRebel 是一款提高开发效率的工具&#xff0c;允许开发者立即重新加载代码更改。它跳过了在Java开发中常见的重新构建、重启和重新部署循环。JRebel 能够让开发者在相同的时间内完成更多工作&#xff0c;并且在编码时能够保持…

付费进群系统源码带定位完整独立版(12月30日)再次修复首发

搭建教程 nginx1.2 php5.6–7.2均可 最好是7.2 第一步上传文件程序到网站根目录解压 第二步导入数据库&#xff08;shujuku.sql&#xff09; 第三步修改/config/database.php里面的数据库地址 第四步修改/config/extra/ip.php里面的域名 第四步设置伪静态thinkphp 总后台账号&…

unity控制摄像机几种视角实现方式

目录 1、按下鼠标右键可以实现摄像机上下左右旋转 2、自由视角 3、摄像头跟随视角 4、跟随自由视角 5、第一人称跟随视角 python学习汇总连接&#xff1a; 1、按下鼠标右键可以实现摄像机上下左右旋转 这段代码定义了一个名为CameraRotate的脚本&#xff0c;用于控制摄像…

Unity坦克大战开发全流程——结束场景——通关界面

结束场景——通关界面 就照着这样来拼 写代码 hideme不要忘了 修改上一节课中的代码

Java项目:103SSM酒店管理系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 酒店管理系统基于SpringSpringMVCMybatis开发&#xff0c;功能简单&#xff0c;可用于毕设或者课程设计。 管理员功能如下&#xff1a; 房间管理住客入住…

图像去雾/图像去雨(matlab/python)

图像去雾和图像去雨是计算机视觉领域的两个重要问题&#xff0c;旨在改善被大气条件或降雨影响而模糊或噪声化的图像质量。这两个技术在很多实际应用中具有广泛的价值&#xff0c;包括无人驾驶、安防监控、航空航天等领域。下面将分点介绍图像去雾和图像去雨的相关内容。 1. 图…

微服务(10)

目录 46.k8s中镜像的下载策略是什么&#xff1f; 47.image的状态有哪些&#xff1f; 48.如何控制滚动更新过程&#xff1f; 49.DaemonSet资源对象的特性&#xff1f; 50.说说你对Job这种资源对象的了解&#xff1f; 46.k8s中镜像的下载策略是什么&#xff1f; 可通过命令k…

IIS服务器发布PHP网站

IIS服务器&#xff0c;相信开发者都不会陌生&#xff0c;它的英文全称是Internet Information Services&#xff0c;是由微软公司提供的基于运行Microsoft Windows的互联网基本服务&#xff0c;常用于Windows系统的Web项目部署&#xff0c;本篇以PHP项目为例&#xff0c;讲解如…

循环生成对抗网络(CycleGAN)

一、说明 循环生成对抗网络&#xff08;CycleGAN&#xff09;是一种训练深度卷积神经网络以执行图像到图像翻译任务的方法。网络使用不成对的数据集学习输入和输出图像之间的映射。 二、基本介绍 CycleGAN 是图像到图像的翻译模型&#xff0c;就像Pix2Pix一样。Pix2Pix模型面临…

kotlin快速入门1

在Google I/O 2017中&#xff0c;Google 宣布 Kotlin 成为 Android 官方开发语言。目前主流AndroidApp开发已经全部切换成此语言&#xff0c;因此对于Android开发而言&#xff0c;掌握Kotlin已经变成必要事情。 Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言&#xff…

超声波防碰撞电路原理图

如图所示为超声波防碰撞电路&#xff0c;电路采用LM1812并由时基电路Ⅱ来控制LM1812的发送与接收&#xff08;LM1812,即发送又接收&#xff09;。控制距离可用Skfl的电位器来调节&#xff0c;一般可控制2-3m。时基电路1组成单稳态电路&#xff0c;当达到报警距离时&#xff0c;…

python安装MongoDB与运算符优先级

python安装MongoDB MongoDB 是目前最流行的 NoSQL 数据库之一&#xff0c;使用的数据类型 BSON&#xff08;类似 JSON&#xff09;。 PyMongo Python 要连接 MongoDB 需要 MongoDB 驱动&#xff0c;这里我们使用 PyMongo 驱动来连接。 pip 安装 pip 是一个通用的 Python 包…