显示页面 讨论 修订记录 反向链接 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 =====按键消抖===== ====硬件平台==== ------ - [[STEP-MXO2第一代]] ====设计要求==== ------ - 掌握FPGA边沿检测的设计 - 掌握按键消抖的原理 - 基于小脚丫[[STEP-MXO2第一代]]开发平台实现按键消抖的功能,实现脉冲和状态翻转输出。 ====工作原理==== ------ {{ :抖动原理.png |抖动原理}} 按键抖动的原理 - 抖动的产生 :通常的按键所用的开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。 - 消除抖动的措施:在按键按下的时刻,会出现波形的抖动,在之后的一段时间内,才会出现平稳的波形。我们舍弃了刚刚检测到按键按下的时刻,读取这一时刻之后20ms左右的按键信息,这样可以防止一次按键被误读多次。 根据上面的原理描述,我们可以对按键的输入管脚进行边沿检测,当检测到输入信号变化后计数开始,计数到20ms时进行采样,然后再对每次采样的值进行下降沿检测,检测的结果作为按键消抖的脉冲输出,然后每次检测到下降沿时让状态输出进行翻转并输出。 ====硬件连接==== ------ 为了方便我们在硬件平台上更直观的观察,我们使用25MHz时钟晶振分频产生1Hz的信号作为序列检测的时钟,按键信号作为按键消抖的信号输入,LED灯LD1和LD2分别作为按键消抖的脉冲和状态输出指示。 {{ :按键硬件图.jpg |按键硬件图}} {{ :led电路连接.jpg |LED电路连接}} ====代码设计==== ---- ===设计文件=== {{ :流水灯程序设计.jpg |流水灯程序设计}} 为了实现对8个LED的控制,我们设计了25位的计数器cnt进行1s周期的循环计数,同时我们定义了一个4位寄存器led_cnt作为状态机的状态控制流水灯的闪烁。状态机共有8个状态,每一个状态对应点亮一个LED灯。 首先是计数器的设计,计数器的计数范围为0~CNT_NUM-1,为了实现每个LED灯1秒的点亮时间,设计文件代码中我们定义参数CNT_NUM为25000000,但是在仿真文件调用设计文件时,为了方便仿真,我们会将参数CNT_NUM重新赋值为10. <code verilog> reg [24:0] cnt = 25'd0; always@(posedge clk_in or negedge rst_n_in) begin if(!rst_n_in) begin cnt <= 25'd0; end else if(cnt>=CNT_NUM-1) begin cnt <= 25'd0; end else begin cnt <= cnt + 25'd1; end end </code> 然后我们需要对状态机的状态进行控制,使得作为状态的寄存器led_cnt实现从0到7的循环加一操作。 <code verilog> reg [3:0] led_cnt = 4'd0; always@(posedge clk_in or negedge rst_n_in) begin if(!rst_n_in) begin led_cnt <= 4'd0; end else if(cnt==CNT_NUM-1) begin if(led_cnt==4'd7) led_cnt <= 4'd0; else led_cnt <= led_cnt + 4'd1; end end </code> 最后是组合逻辑,根据led_cnt的不同状态控制不同的LED点亮。 <code verilog> always@(led_cnt) begin case(led_cnt) 4'd0: led_out = 8'b1111_1110; 4'd1: led_out = 8'b1111_1101; 4'd2: led_out = 8'b1111_1011; 4'd3: led_out = 8'b1111_0111; 4'd4: led_out = 8'b1110_1111; 4'd5: led_out = 8'b1101_1111; 4'd6: led_out = 8'b1011_1111; 4'd7: led_out = 8'b0111_1111; default: led_out = 8'b1111_1111; endcase end </code> ===测试文件=== 测试文件中我们需要对设计文件中的参数CNT_NUM进行重新赋值 <code verilog> parameter CNT_NUM = 10; Water_led #(.CNT_NUM(CNT_NUM)) Water_led_uut ( .clk_in(sys_clk), .rst_n_in(sys_rst_n), .led_out(led_out) ); </code> 引脚分配如下: ^ 管脚名称 | clk_in| rst_n_in | led_out[0] |led_out[1] |led_out[2] |led_out[3] |led_out[4] |led_out[5] |led_out[6] |led_out[7] | ^ FPGA管脚 | C1 | A2 |B14 |C14 |E14 |F14 |G14 |J14 |K14 |L14 | ====仿真结果==== {{:流水灯仿真.jpg|流水灯仿真}} ====资源报告==== ^ 资源 | 数量 | 比例 | 说明 | ^ LUTs | 28 | 4% | | ^ 寄存器 | 33 | 2% | | ^ 存储器 | 0 | 0% | | ^ IO管脚 | 10 | | | ^ 时钟频率 | 25MHz | | | ====知识点==== * 分频设计 * 时序控制 * 简单状态机 ====参考文档==== * [[点亮led灯]] * {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}} ====相关文档==== ^ **文件名称** | **功能** | ^ **[[Water_led.v]]** | **流水灯** | ^ **[[Water_led_test.v]]** | **测试文件** |