在基于verilog的FPGA设计中,我们常常可以看到以下形式的进程:
1 reg [19:0] cnt; 2 always@(posedge Clk50M or negedge Rst_n) 3 begin 4 if(!Rst_n) 5 cnt<=20'd0; 6 else if(cnt_able) 7 cnt<=cnt+1'b1; 8 end
信号Rst_n用来对进程中所用变量的初始化,这个复位信号是十分重要的,如果没有复位,会导致一些寄存器的初始值变得未知,如果此时FPGA就开始工作的话,极易导致错误。
那么,这个复位信号来自何处?难道我们做好的系统,每次上电后都要手动按一下reset按钮么?
答案是否定的!这个复位信号其实是由特定的程序来产生的,系统每次上电,都会由该程序产生一个复位信号,从而避免了手动复位。
在网上找了多种方案,觉得只有这个程序比较简单实用,转来如下:
1 /************************************** 2 * 功能:同步复位产生模块 3 * 输入参数: 4 * 1. clk: 50M 时钟输入 5 * 2. 全局复位信号 6 * 输出参数: 7 * sys_rst_n:系统全局同步复位信号 8 ***************************************/ 9 module system_ctrl 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
说明:
1.第一个进程用来延时,当上电后,延时100ms,以保证FPGA内部达到稳定状态;此时sys_rst_n始终为0,也就是系统时钟处于复位状态中。
2.当100ms延时结束后,sys_rst_n与系统时钟同步释放,即sys_rst_n拉高,复位结束,系统开始正常工作;