对于全局时钟的管理,涉及到关于亚稳态的知识,大家可以上网搜索相关资料,这里不再赘述。亚稳态最简单的理解形式是无法判断是处于高电平状态还是处于低电平状态,这样会导致整个系统不稳定,会出现逻辑上的错误。
任何对时钟的管理形式,都是最大限度避免亚稳态情况的出现,从而提高MTBF(平均无故障时间)。
对于常用的异步复位形式(之前博客有提及到),如下:
always @(posedge clk or negedge rst_n) if(!rst_n) begin ...... ...... end else begin ........... ........... end
上述得异步复位结构,正常情况下,寄存器的更新会伴随clk的上升沿进行更新,但是rst_n何时结束就不一定了,若是在寄存器的 建立时间 + 保持时间之外,那么输出是稳定的,但是若是在这之内,那么会导致输出的数据不一定正确。
目前笔者搜索到的资料,较为合适的,能够最大限度降低亚稳态产生的逻辑电路,就是“异步复位,同步释放”。
module rstn_ (clk,rstn,rstn_out); input clk ; input rstn; output rstn_out; //所要输出的复位信号 reg rst_out1,rst_out2; always@(posedge clk or negedge rstn) begin if(!rstn) begin rst_out1 <= 1'b0; rst_out2 <= 1'b0; end else begin rst_out1 <= 1'b1; rst_out2 <= rst_out1; end assign rstn_out = rst_out2; endmodule
RTL视图为:
通过两级缓存,使得rst_n也是伴随clk时钟下的使能信号。
实际应用电路
那么在实际应用中,由于电源等芯片转换需要一定的时间,FPGA稳定启动需要一定的时间,外围电路启动也需要一定的时间,人为的添加50ms的延时电路,使整个系统稳定。
有PLL参与的时钟电路
RTL视图
Verilog 代码
延时模块:
/********************************************************* //description : this module will complete function of system init delay when power on //author : raymon //address : GDUT university of technology //e-mail : [email protected] //contact : 770811496 //time : 2015-1-31 **********************************************************/ `timescale 1ns/1ns module system_init_delay #( parameter SYS_DELAY_TOP = 24'd2500000 //50ms system init delay ) ( //------------------------------------------- //global clock input clk, //50MHz input rst_n, //system interface output delay_done ); //------------------------------------------ //Delay 50ms for steady state when power on reg [23:0] delay_cnt = 24'd0; always@(posedge clk or negedge rst_n) begin if(!rst_n) delay_cnt <= 0; else if(delay_cnt < SYS_DELAY_TOP - 1'b1) delay_cnt <= delay_cnt + 1'b1; else delay_cnt <= SYS_DELAY_TOP - 1'b1; end assign delay_done = (delay_cnt == SYS_DELAY_TOP - 1'b1)? 1'b1 : 1'b0; endmodule
PLL
此模块是正常的利用quartus II生成的IP核PLL,这里不再讲解。
顶层模块:
/********************************************************* //description : this module will complete function of system init delay when power on //author : raymon //address : GDUT university of technology //e-mail : [email protected] //contact : 770811496 //time : 2015-1-31 **********************************************************/ `timescale 1ns/1ns module sys_control(clk, rst_n, clk_ref, sys_rst_n); //---------------------------------------------- //globol clock input clk; //50MHz input rst_n; //reset //---------------------------------------------- //synced signal output clk_ref; //clock output output sys_rst_n; //system reset //---------------------------------- //component instantiation for system_delay wire delay_done; //system init delay has done system_init_delay #( .SYS_DELAY_TOP (24'd2500000) ) u_system_init_delay ( //global clock .clk (clk), .rst_n (1'b1), //It don't depend on rst_n when power up //system interface .delay_done (delay_done) ); //注意这里因为PLL的areset复位信号是高电平复位,和平常使用的rst_n信号正好相反
wire pll_reset = ~delay_done; //pll of ip needs high level to reset //---------------------------------- //using IP wire locked; sys_pll U1( .areset(pll_reset), .inclk0(clk), .c0(clk_ref), //output 100MHz .locked(locked) ); //---------------------------------------------- //rst_n sync, only controlled by the main clk reg rst_nr1, rst_nr2; always @(posedge clk_ref) begin if(!rst_n) begin rst_nr1 <= 1'b0; rst_nr2 <= 1'b0; end else begin rst_nr1 <= 1'b1; rst_nr2 <= rst_nr1; end end assign sys_rst_n = rst_nr2 & locked; //active low endmodule
无PLL参与的时钟电路
RTL视图
Verilog 代码
/********************************************************* //description : this module will complete function of system init delay when power on //author : raymon //address : GDUT university of technology //e-mail : [email protected] //contact : 770811496 //time : 2015-1-31 **********************************************************/ `timescale 1ns/1ns module system_init_delay #( parameter SYS_DELAY_TOP = 24'd2500000 //50ms system init delay ) ( //------------------------------------------- //global clock input clk, //50MHz input rst_n, //system interface output delay_done ); //------------------------------------------ //Delay 50ms for steady state when power on reg [23:0] delay_cnt = 24'd0; always@(posedge clk or negedge rst_n) begin if(!rst_n) delay_cnt <= 0; else if(delay_cnt < SYS_DELAY_TOP - 1'b1) delay_cnt <= delay_cnt + 1'b1; else delay_cnt <= SYS_DELAY_TOP - 1'b1; end assign delay_done = (delay_cnt == SYS_DELAY_TOP - 1'b1)? 1'b1 : 1'b0; endmodule
上述是延时部分的代码。
/********************************************************* //description :this module will complete function of system init delay when power on //author : raymon //address : GDUT university of technology //e-mail : [email protected] //contact : 770811496 //time : 2015-1-31 **********************************************************/ `timescale 1ns/1ns module system_ctrl(clk, rst_n, clk_ref, sys_rst_n); //---------------------------------------------- //globol clock input clk; input rst_n; //---------------------------------------------- //synced signal output clk_ref; //clock output output sys_rst_n; //system reset //---------------------------------------------- //rst_n sync, only controlled by the main clk reg rst_nr1, rst_nr2; always @(posedge clk) begin if(!rst_n) begin rst_nr1 <= 1'b0; rst_nr2 <= 1'b0; end else begin rst_nr1 <= 1'b1; rst_nr2 <= rst_nr1; end end //---------------------------------- //component instantiation for system_delay wire delay_done; //system init delay has done system_init_delay #( .SYS_DELAY_TOP (24'd2500000) ) u_system_init_delay ( //global clock .clk (clk), .rst_n (1'b1), //It don't depend on rst_n when power up //system interface .delay_done (delay_done) ); assign clk_ref = clk; assign sys_rst_n = rst_nr2 & delay_done; //active High endmodule
上述是实现整个模块,可以查看RTL视图。
上面提到的最大限度降低亚稳态复位电路,在应用时,直接可以调用。目前已在多个工程中使用。
//=======================================================================
更多详细的资料下载可以登录笔者百度网盘:
网址:http://pan.baidu.com/s/1bnwLaqF
密码:fgtb
//=======================================================================