FPGA内部动态可重置PLL讲解(二)

  对于全局时钟的管理,涉及到关于亚稳态的知识,大家可以上网搜索相关资料,这里不再赘述。亚稳态最简单的理解形式是无法判断是处于高电平状态还是处于低电平状态,这样会导致整个系统不稳定,会出现逻辑上的错误。

  任何对时钟的管理形式,都是最大限度避免亚稳态情况的出现,从而提高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视图为:

wps283.tmp

 

  通过两级缓存,使得rst_n也是伴随clk时钟下的使能信号。

  实际应用电路

  那么在实际应用中,由于电源等芯片转换需要一定的时间,FPGA稳定启动需要一定的时间,外围电路启动也需要一定的时间,人为的添加50ms的延时电路,使整个系统稳定。

  有PLL参与的时钟电路

  RTL视图

wps9B30.tmp

  Verilog 代码

  延时模块:

/*********************************************************

//description : this module will complete function of system init delay when power on
//author      : raymon
//address       :  GDUT university  of technology 
//e-mail      : 770811496@qq.com
//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      : 770811496@qq.com
//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视图

wpsBDCF.tmp

  Verilog 代码

/*********************************************************

//description : this module will complete function of system init delay when power on
//author        : raymon
//address      : GDUT university  of technology 
//e-mail         : 770811496@qq.com
//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         : 770811496@qq.com
//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

//=======================================================================

原文地址:https://www.cnblogs.com/raymon-tec/p/5151573.html