【复位】FGPA的复位 [部分转]
关于FGPA的复位
当初开始学FPGA的时候,总是疑惑:FPGA不是没有复位管教么,但总在always看到有复位信号。这个复位信号(我们暂且称为rst_n)从哪里来?
实际上是可以从两个方面获得的,这与我们的MCU一样。
- 上电自动复位
- 手动按键复位
考虑到系统的初始化可能需要一定的时间,需要写一段Verilog代码进行延时复位,这段代码综合后就是上电自动复位的过程,上电自动复位也要外部硬件提供一个低电平脉冲,第二种方法要求有按键复位的按键电路。作为一个正常的系统,上电自动复位和手动的按键复位都是必须的,且两者实际上是不可分割的。
上电自动复位
原理上很简单,写一个复位模块,等待一段稳定时间,将复位信号拉低一段足够长的时间,再将复位信号拉高。
如下Verilog源码,外部按键复位也将作为模块的一个引脚输入,用于异步的全局复位操作,正常的复位操作要进行,必须要求外部有一个短暂的脉冲作用在rst_n信号上,这可以通过按键电路中的RC电路实现。
1 /************************************** 2 * 功能:上电复位模块 3 * 输入参数: 4 * clk: 50M 时钟输入 5 * rst_n:外部按键全局复位信号 6 * 输出参数: 7 * sys_rst_n:系统全局同步复位信号 8 ***************************************/ 9 module reset 10 ( 11 input clk, 12 input rst_n, 13 output sys_rst_n 14 ); 15 16 //------------------------------------------ 17 // Delay 100ms for steady state 18 reg [22:0] cnt; 19 always@(posedge clk or negedge rst_n) 20 begin 21 if(!rst_n) 22 cnt <= 0; 23 else 24 begin 25 if(cnt < 23'd50_00000) //100ms 26 cnt <= cnt+1'b1; 27 else 28 cnt <= cnt; 29 end 30 end 31 32 //------------------------------------------ 33 //rst_n synchronism 34 reg rst_nr0; 35 reg rst_nr1; 36 always@(posedge clk or negedge rst_n) 37 begin 38 if(!rst_n) 39 begin 40 rst_nr0 <= 0; 41 rst_nr1 <= 0; 42 end 43 else if(cnt == 23'd50_00000) 44 begin 45 rst_nr0 <= 1; 46 rst_nr1 <= rst_nr0; 47 end 48 else 49 begin 50 rst_nr0 <= 0; 51 rst_nr1 <= 0; 52 end 53 end 54 55 assign sys_rst_n = rst_nr1; 56 57 endmodule
按键手动复位电路
不使用专用芯片的参考低电平复位电路如下:
电路中的复位管脚一端连接到FPGA的某个普通通用管脚,这样电路中的RC电路将产生上面Verilog代码中的rst_n上电低脉冲,这就是本文开头说自动上电复位和硬件按键复位相辅相成。
请注意两个电阻的值,R21要是R22的两个数量级以上,这样才能保证按键按下后被识别为低电平。
手动复位过程中为保证按键复位的稳定性,还可以修改上面的Verilog代码进行按键消抖检测。下面是抓到的按键在闭合的时候的波形:
按键在几个us之内就能达到低电平,该期间触点抖动比较严重。
1 module RMV_BJ ( 2 BJ_CLK, //采集时钟,40Hz 3 RESET, //系统复位信号 4 BUTTON_IN, //按键输入信号 5 BUTTON_OUT //消抖后的输出信号 6 ); 7 input B_CLK; 8 input RESET; 9 input BUTTON_IN; 10 output BUTTON_OUT; 11 reg BUTTON_IN_Q, BUTTON_IN_2Q, BUTTON_IN_3Q; 12 13 always @(posedge BJ_CLK or negedge RESET) 14 begin 15 if(~RESET) 16 begin 17 BUTTON_IN_Q <= 1'b1; 18 BUTTON_IN_2Q <= 1'b1; 19 BUTTON_IN_3Q <= 1'b1; 20 end 21 else 22 begin 23 BUTTON_IN_Q <= BUTTON_IN; 24 BUTTON_IN_2Q <= BUTTON_IN_Q; 25 BUTTON_IN_3Q <= BUTTON_IN_2Q; 26 end 27 end 28 29 wire BUTTON_OUT = BUTTON_IN_2Q | BUTTON_IN_3Q; 30 31 endmodule
上面的方法不能产生一个时钟脉冲的信号,如下的可以用10ms来采样,同时按键动作会产生一个时钟脉冲的信号,便于后续操作
1 /*-------------------------------------------------------------------------------------- 2 -- Filename ﹕ debounce_module.v 3 -- Author ﹕tony-ning 4 -- Description ﹕按键消抖 5 -- Called by ﹕Top module 6 -- Revision History ﹕15-10-16 7 -- Revision 1.0 8 -- Company ﹕ 9 -- Copyright(c) All right reserved 10 ---------------------------------------------------------------------------------------*/ 11 12 13 module debounce_module 14 ( 15 CLK, //采集时钟,40Hz 16 RSTn, //系统复位信号 17 BUTTON_IN, //按键输入信号 18 BUTTON_OUT //消抖后的输出信号 19 ); 20 input CLK; 21 input RSTn; 22 input BUTTON_IN; 23 output BUTTON_OUT; 24 25 reg key_reg1,key_reg2,key_out; 26 reg [24:0]count2; 27 28 always @( posedge CLK)//CLK 25M 29 begin 30 count2<=count2+1; 31 if(count2==250000) 32 begin 33 key_reg1<=BUTTON_IN; 34 count2<=0; 35 end 36 key_reg2<=key_reg1; 37 key_out<=key_reg2&(!key_reg1); 38 end 39 40 assign BUTTON_OUT = key_out; 41 42 endmodule
除了上面简单的复位电路,还可使用CAT811/TPS3823-33等专门的复位芯片,可以免去按键按键消抖的操作。