news 2026/6/23 3:39:08

17.按键-LED灯联动-状态机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
17.按键-LED灯联动-状态机

1.引言

使用状态机的方式实现按键逻辑

2.代码

顶层逻辑:

module top# ( parameter RATE = 32'd49_999_999 //分频时钟计数,初始时钟过快,人眼观察会导致LED常亮 ) ( input RSTn_i, //System differential reference clock inputs input sysclk_p, input sysclk_n, //led output [1:0] led_o, //key input key_i ); wire clk_i; //对差分时钟采用 IBUFGDS 原语去转换 IBUFGDS CLK_U( .I(sysclk_p), .IB(sysclk_n), .O(clk_i) ); wire led_stu; key_fsm u_key_fsm( .clk(clk_i), // 时钟(比如50MHz) .rst_n(RSTn_i), // 低电平复位 .key_in(key_i), // 按键输入(低电平按下) .key_out(led_stu) // 消抖后输出 ); run_led #( .RATE(RATE) ) led0_inst ( .I_sysclk(clk_i), .I_rstn(RSTn_i), .mode(1'b0), //设置成控制模式 .switch(led_stu),//控制led灯亮灭 .led_out(led_o[0]) ); endmodule

按键逻辑:

// 例:按键消抖状态机(摩尔机) module key_fsm( input clk, // 时钟(比如50MHz) input rst_n, // 低电平复位 input key_in, // 按键输入(低电平按下) output reg key_out // 消抖后输出 ); // 步骤1:定义状态(4个状态) parameter IDLE = 2'b00; // 空闲(无按键) parameter KEY_DOWN = 2'b01; // 检测到按键按下 parameter KEY_STABLE= 2'b10; // 按键稳定按下 parameter KEY_UP = 2'b11; // 按键松开 reg [1:0] current_state; // 当前状态 reg [1:0] next_state; // 下一状态 reg [19:0] cnt; // 消抖计数器(50MHz时钟下,计数1ms需要50_000个时钟) // 步骤2:状态寄存器(时序逻辑,clk触发) always @(posedge clk or negedge rst_n) begin if(!rst_n) begin current_state <= IDLE; // 复位回到空闲状态 end else begin current_state <= next_state; // 时钟沿更新为下一状态 end end // 步骤3:状态切换逻辑(组合逻辑) always @(*) begin case(current_state) IDLE: begin if(key_in == 1'b0) // 检测到按键按下 next_state = KEY_DOWN; else next_state = IDLE; end KEY_DOWN: begin if(cnt == 20'd499_999) // 计数1ms(消抖) next_state = KEY_STABLE; else next_state = KEY_DOWN; end KEY_STABLE: begin if(key_in == 1'b1) // 检测到按键松开 next_state = KEY_UP; else next_state = KEY_STABLE; end KEY_UP: begin if(cnt == 20'd499_999) // 计数1ms(消抖) next_state = IDLE; else next_state = KEY_UP; end default: next_state = IDLE; // 防溢出 endcase end // 步骤4:输出逻辑(时序逻辑,摩尔机) always @(posedge clk or negedge rst_n) begin if(!rst_n) begin key_out <= 1'b0; cnt <= 20'd0; end else begin // 计数器逻辑 case(current_state) KEY_DOWN, KEY_UP: begin if(cnt < 20'd499_999) cnt <= cnt + 1'b1; else cnt <= 20'd0; end default: cnt <= 20'd0; endcase // 输出逻辑 case(current_state) KEY_STABLE: key_out <= 1'b1; // 只有稳定按下时输出高电平 default: key_out <= 1'b0; endcase end end endmodule

led逻辑:

//led模块 //状态机设计:有两种状态:1 开关状态 2 自动翻转状态 可配置led的翻转速率 `timescale 1ns / 1ns module run_led# ( parameter RATE = 32'd99_999_999 //分频时钟计数,初始时钟过快,人眼观察会导致LED常亮 ) ( input I_sysclk, //系统时钟信号 input I_rstn, //异步复位 input mode, //模式选择,1=自动翻转 0 =开关状态 input switch, //开关控制(mode=0时有效) output reg led_out //LED灯输出 ); //定义状态 localparam SWITCH_MODE = 1'b0; localparam AUTO_MODE = 1'b1; //状态寄存器 reg current_state,next_state; // 自动模式计数器 reg [31:0] counter; reg auto_toggle; // 状态转移逻辑(时序部分) always @(posedge I_sysclk or negedge I_rstn) begin if (!I_rstn) begin current_state <= SWITCH_MODE; end else begin current_state <= next_state; end end // 状态转移条件(组合部分) always @(*) begin case (current_state) SWITCH_MODE: next_state = mode ? AUTO_MODE : SWITCH_MODE; AUTO_MODE: next_state = mode ? AUTO_MODE : SWITCH_MODE; default: next_state = SWITCH_MODE; endcase end // 状态动作(时序逻辑) always @(posedge I_sysclk or negedge I_rstn) begin if (!I_rstn) begin counter <= 32'd0; auto_toggle <= 1'b0; led_out <= 1'b0; end else begin case (current_state) SWITCH_MODE: begin counter <= 32'd0; auto_toggle <= 1'b0; led_out <= switch; // 直接由switch控制 end AUTO_MODE: begin // 计数器逻辑 if (counter >= RATE) begin counter <= 32'd0; auto_toggle <= ~auto_toggle; end else begin counter <= counter + 1'b1; end led_out <= auto_toggle; // 由自动翻转信号控制 end endcase end end //ila例化 //抓计数信号和LED输出信号特征 //ila_led led_test ( // .clk(I_sysclk), // input wire clk // .probe0(I_rstn), // input wire [0:0] probe0 // .probe1(next_state), // input wire [0:0] probe1 // .probe2(led_out) // input wire [3:0] probe2 // ); endmodule

引脚约束文件:

# ---------------- LED灯约束 ---------------- # 引脚位置:根据你的配置保留E14/E13,IO标准建议与硬件匹配 set_property PACKAGE_PIN E14 [get_ports {led_o[1]}] set_property PACKAGE_PIN E13 [get_ports {led_o[0]}] set_property IOSTANDARD LVCMOS18 [get_ports {led_o[*]}] # ---------------- 复位信号约束 ---------------- set_property PACKAGE_PIN A13 [get_ports RSTn_i] set_property IOSTANDARD LVCMOS18 [get_ports RSTn_i] set_property PULLUP true [get_ports RSTn_i] ;# 复位引脚加上拉(硬件防误触发) # ---------------- 按键约束 ---------------- set_property PACKAGE_PIN B14 [get_ports key_i] set_property IOSTANDARD LVCMOS18 [get_ports key_i] set_property PULLUP true [get_ports key_i] ;# 按键引脚加默认上拉 set_property PACKAGE_PIN AE5 [get_ports sysclk_p] set_property PACKAGE_PIN AE6 [get_ports sysclk_n] # DIFF_SSTL12:1.2V差分;若为2.5V改DIFF_SSTL25;3.3V改DIFF_LVCMOS33 set_property IOSTANDARD DIFF_SSTL12 [get_ports {sysclk_p sysclk_n}] # 步骤1:创建虚拟差分时钟(绑定p/n端) create_diff_clock -name sys_clk -clk_p sysclk_p -clk_n sysclk_n # 步骤2:设置时钟周期(关键!根据你的硬件时钟频率改,比如50MHz则-period 20.0) create_clock -name sys_clk -period 10.0 [get_ports sysclk_p] ; # ---------------- 比特流压缩 ---------------- set_property BITSTREAM.GENERAL.COMPRESS true [current_design]

3.现象

按键按下,LED灯亮。按键松开,LED灯灭。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 7:39:32

PermissionX:彻底简化Android运行时权限管理的终极解决方案

PermissionX&#xff1a;彻底简化Android运行时权限管理的终极解决方案 【免费下载链接】PermissionX An open source Android library that makes handling runtime permissions extremely easy. 项目地址: https://gitcode.com/gh_mirrors/pe/PermissionX PermissionX…

作者头像 李华
网站建设 2026/6/23 7:39:48

Pearcleaner:智能macOS系统清理工具,彻底释放磁盘空间

Pearcleaner&#xff1a;智能macOS系统清理工具&#xff0c;彻底释放磁盘空间 【免费下载链接】Pearcleaner Open-source mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner 你是否曾经卸载应用后&#xff0c;发现磁盘空间并没有真正释放&#…

作者头像 李华
网站建设 2026/6/23 5:33:59

Spark MLlib 基础统计模块相关性、卡方检验与向量汇总

一、相关性分析&#xff08;Correlation&#xff09;&#xff1a;快速算出特征之间的“关系矩阵” 1. 场景&#xff1a;为什么要算相关系数&#xff1f; 在特征工程阶段&#xff0c;我们经常会问&#xff1a; 哪些特征之间高度相关&#xff0c;可能存在冗余&#xff1f;某个特征…

作者头像 李华
网站建设 2026/6/22 21:26:03

使用质谱进行De Novo测序

使用质谱进行De Novo测序使用质谱进行De Novo测序是用于确定蛋白质或肽段的氨基酸序列的技术。质谱技术通过测量离子化分子或分子片段的质荷比&#xff08;mass-to-charge ratio&#xff09;&#xff0c;可以高精度地推断出其组成与结构。在De Novo测序中&#xff0c;质谱仪通常…

作者头像 李华