实验报告课程名称:_____FPGA实验______指导老师:__竺红卫/陈宏__成绩:__________________实验名称:____拨动开关的消抖电路的设计___实验类型:_FPGA实验_同组学生姓名:__一、实验目的和要求(必填)1. 熟悉软件对于消抖的实现原理;2. 熟悉实验板拨动开关的工作方法。
二、实验内容和原理(必填)实验板具有4个滑动开关,当开关关上或上拉时,FPGA的管脚连接3.3V电源,即逻辑高电平。
断开或下拉时,FPGA管脚接地,逻辑低电平。
一般开关的机械闭合时间为2ms,这里没有使用活动的回弹线路,尽管这种线路可以很容易地加到FPGA上。
实验需要实现的功能是:当RESET为低电平,不论SW为低电平或高电平,LED保持全灭;当RESET 为高电平,LED全亮;当RESET保持高电平时,每次SW由高电平变为低电平,对应的LED状态改变,而当SW由低电平变为高电平,对应的LED状态保持不变。
对LED引脚输出高电平时,LED点亮,,反之LED灭。
三、主要仪器设备(必填)1. 电脑一台;2. 实验板一块,Xilinx Spartan-3E;3. 实验板电源一只;4. 实验板连接电脑的下载线一根。
四、操作方法和实验步骤对于程序的各个步骤,如新建项目、新建Verilog HDL、新建.ucf文件、Synthesize、Implement Design、Generate Programming File、Configure Target Device等等,在实验一中已经展示过,每一次实验的基本操作步骤都是差不多的,故这里不再重复阐述。
本次实验共有5个源代码需要编写、运行并解释:1)未加debounce电路的源代码;2)加了debounce电路的源代码;3)由未加debounce电路的源代码出发,只添加锁存器的源代码;4)由未加debounce电路的源代码出发,只添加滤波器的源代码;5)加了debounce电路,并且一个开关控制3个灯,向上拨动开关时灭,向下亮的源代码。
前四种情况的.ucf文件如下:NET "CLK" LOC="C9";NET "led_d3" LOC="C11";NET "led_d4" LOC="F11";NET "led_d5" LOC="E11";NET "RST_N" LOC="L13";NET "sw1" LOC="L14";NET "sw2" LOC="H18";NET "sw3" LOC="N17";最后一种情况的.ucf文件如下:NET "CLK" LOC="C9";NET "led_d3" LOC="C11";NET "led_d4" LOC="F11";NET "led_d5" LOC="E11";NET "RST_N" LOC="L13";NET "sw1" LOC="L14";对于最后一种情况,只使用sw1同时控制板上的LD2、LD3、LD4。
五、实验源代码、现象和解释1)未加debounce电路源代码:`timescale 1ns/1nsmodule sw_led(clk, rst_n, sw1, sw2, sw3, led_d3, led_d4, led_d5);input clk;input rst_n;input sw1,sw2,sw3; //低电平有效output led_d3;output led_d4;output led_d5;reg d1,d2,d3;always @ (posedge clk or negedge rst_n)if ( !rst_n )begin d1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelsebeginif ( !sw1 ) d1 <= ~d1;if ( !sw2 ) d2 <= ~d2;if ( !sw3 ) d3 <= ~d3;endassign led_d5 = d1 ? 1'b1 : 1'b0;assign led_d3 = d2 ? 1'b1 : 1'b0;assign led_d4 = d3 ? 1'b1 : 1'b0;endmodule实验现象:当RESET关闭,不论SW状态如何,LED始终保持灭。
当RESET打开,LED立即全亮,此时再拨动SW,当SW向下拨,LED半亮,当SW向上拨,LED为全亮或全灭,出现两种状态的概率大致相同。
解释:当SW为低电平时,LED在以50MHz的频率闪烁,故表现为半亮;当SW向上拨,LED跟随拨动动作立即停止翻转,故LED为全亮或全灭,且两种状态概率相等。
2)加了debounce电路源代码:`timescale 1ns/1nsmodule sw_debounce(clk, rst_n, sw1, sw2, sw3, led_d3, led_d4, led_d5);input clk;input rst_n;input sw1,sw2,sw3; //低电平有效output led_d3;output led_d4;output led_d5;// ---------------------------------------------------------------------------// 通过降采样对sw1~sw3的输入做低通滤波,将其高频分量滤除,得到low_sw值// ---------------------------------------------------------------------------reg [19:0] cnt;always @ (posedge clk or negedge rst_n)if (!rst_n)cnt <= 20'd0;elsecnt <= cnt + 1'b1;reg [2:0] low_sw;always @(posedge clk or negedge rst_n)if (!rst_n)low_sw <= 3'b111;else if (cnt == 20'hfffff)low_sw <= {sw3,sw2,sw1};// ---------------------------------------------------------------------------// 以下的语句描述的是锁存器部分,将按键输入锁存一个周期后再与原输入信号进//行组合逻辑运算得到新的输入信号// ---------------------------------------------------------------------------reg [2:0] low_sw_r;always @ ( posedge clk or negedge rst_n )if (!rst_n)low_sw_r <= 3'b111;elselow_sw_r <= low_sw;wire [2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]); //这里捕获的是下降沿!reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n)begind1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelsebeginif ( led_ctrl[0] ) d1 <= ~d1;if ( led_ctrl[1] ) d2 <= ~d2;if ( led_ctrl[2] ) d3 <= ~d3;endassign led_d5 = d1 ? 1'b1 : 1'b0;assign led_d3 = d2 ? 1'b1 : 1'b0;assign led_d4 = d3 ? 1'b1 : 1'b0;endmodule实验现象:能够完整实现要求的实验功能。
当RESET为低电平,不论SW为低电平或高电平,LED保持全灭;当RESET为高电平,LED全亮;当RESET保持高电平时,每次SW由高电平变为低电平,对应的LED 状态改变,而当SW由低电平变为高电平,对应的LED状态保持不变。
解释:加滤波器实现的功能是消除高频按键抖动对LED控制的影响;加锁存器实现的功能是使LED在SW 信号遇到下降沿时翻转。
3)由未加debounce电路的源代码出发,只添加锁存器源代码:`timescale 1ns/1nsmodule sw_debounce(clk, rst_n, sw1, sw2, sw3, led_d3, led_d4, led_d5);input clk;input rst_n;input sw1,sw2,sw3; //低电平有效output led_d3;output led_d4;output led_d5;reg [2:0] low_sw;always @(posedge clk or negedge rst_n)if (!rst_n)low_sw <= 3'b111;elselow_sw <= {sw3,sw2,sw1};// ---------------------------------------------------------------------------// 以下的语句描述的是锁存器部分,将按键输入锁存一个周期后再与原输入信号进//行组合逻辑运算得到新的输入信号// ---------------------------------------------------------------------------reg [2:0] low_sw_r;always @ ( posedge clk or negedge rst_n )if (!rst_n)low_sw_r <= 3'b111;elselow_sw_r <= low_sw;wire [2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]); //这里捕获的是下降沿!reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n)begind1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelsebeginif ( led_ctrl[0] ) d1 <= ~d1;if ( led_ctrl[1] ) d2 <= ~d2;if ( led_ctrl[2] ) d3 <= ~d3;endassign led_d5 = d1 ? 1'b1 : 1'b0;assign led_d3 = d2 ? 1'b1 : 1'b0;assign led_d4 = d3 ? 1'b1 : 1'b0;endmodule实验现象:当RESET关闭时,LED始终全灭。