企业网站源码利于优化,产品设计留学哪个国家好,石家庄网站建站,网站开发实战 王1.引言
使用状态机的方式实现按键逻辑 2.代码
顶层逻辑#xff1a;
module top#
(parameter RATE 32d49_999_999 //分频时钟计数#xff0c;初始时钟过快#xff0c;人眼观察会导致LED常亮
)
(
input RSTn_i,//System differential reference cloc…1.引言使用状态机的方式实现按键逻辑2.代码顶层逻辑module top# ( parameter RATE 32d49_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(1b0), //设置成控制模式 .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 2b00; // 空闲无按键 parameter KEY_DOWN 2b01; // 检测到按键按下 parameter KEY_STABLE 2b10; // 按键稳定按下 parameter KEY_UP 2b11; // 按键松开 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 1b0) // 检测到按键按下 next_state KEY_DOWN; else next_state IDLE; end KEY_DOWN: begin if(cnt 20d499_999) // 计数1ms消抖 next_state KEY_STABLE; else next_state KEY_DOWN; end KEY_STABLE: begin if(key_in 1b1) // 检测到按键松开 next_state KEY_UP; else next_state KEY_STABLE; end KEY_UP: begin if(cnt 20d499_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 1b0; cnt 20d0; end else begin // 计数器逻辑 case(current_state) KEY_DOWN, KEY_UP: begin if(cnt 20d499_999) cnt cnt 1b1; else cnt 20d0; end default: cnt 20d0; endcase // 输出逻辑 case(current_state) KEY_STABLE: key_out 1b1; // 只有稳定按下时输出高电平 default: key_out 1b0; endcase end end endmoduleled逻辑//led模块 //状态机设计有两种状态1 开关状态 2 自动翻转状态 可配置led的翻转速率 timescale 1ns / 1ns module run_led# ( parameter RATE 32d99_999_999 //分频时钟计数初始时钟过快人眼观察会导致LED常亮 ) ( input I_sysclk, //系统时钟信号 input I_rstn, //异步复位 input mode, //模式选择1自动翻转 0 开关状态 input switch, //开关控制mode0时有效 output reg led_out //LED灯输出 ); //定义状态 localparam SWITCH_MODE 1b0; localparam AUTO_MODE 1b1; //状态寄存器 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 32d0; auto_toggle 1b0; led_out 1b0; end else begin case (current_state) SWITCH_MODE: begin counter 32d0; auto_toggle 1b0; led_out switch; // 直接由switch控制 end AUTO_MODE: begin // 计数器逻辑 if (counter RATE) begin counter 32d0; auto_toggle ~auto_toggle; end else begin counter counter 1b1; 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/E13IO标准建议与硬件匹配 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_SSTL121.2V差分若为2.5V改DIFF_SSTL253.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灯灭。