SRIO学习(2)SRIO IP核时钟和复位

前言

通过对时钟和复位的理解可以更好的了解IP核的工作过程,不过不理解也不影响使用,example design帮我们都做好了。

一、时钟

可以直接看总结

1.1、整体说明

PHY在两个时钟域上运行:phy_clk是主要的核心时钟,gt_pcs_clk用于串行收发器接口。gt_clk不被PHY使用,而是被串行收发器接口使用。gt_pcs_clk的频率是gt_clk的一半。一般来说,phy_clk等于 (gt_clk * 操作链路宽度)/4 ,因此,对于配置为2x的核心,phy_clk的频率是gt_clk的一半。如果核心降到1x模式,phy_clk必须切换到gt_clk速率的四分之一。串行收发器还需要一个参考时钟(refclk),使用收发器的专用时钟引脚。参考时钟频率在生成核心时选择(可用选项取决于架构和线速率)。
在这里插入图片描述
LOG(逻辑层)在log_clk域上运行。为了达到最佳吞吐量,log_clk应至少与phy_clk一样快。这是为了PHY层接收到的数据不会在BUF里一直停留。

BUF(缓冲器)在log_clkphy_clk域之间传输数据包。如果BUF用于统一时钟,则log_clkphy_clk必须同步。否则,时钟必须匹配与接口子核心的速率。

每个子核心配置寄存器接口上的cfg_clk域是独立于该子核心时钟的。但是,为了使用提供的配置结构参考设计中的LOG维护控制器,所有这些接口的cfg_clk必须等同于log_clk

1.2、典型时钟速率

下表是xilinx给出的典型时钟速率,我们以4x为例进行分析:

  • 首先是gt_clkgt_pcs_clk,这个是根据线速率决定的,从下面的图3-14也可以看出,所谓的gt_clk就是我们之前熟悉的TXUSERCLK/RXUSERCLKgt_pcs_clk就是我们之前熟悉的TXUSERCLK2/RXUSERCLK2,这也就可以很好的理解为什么他俩之间是二倍的关系了。
  • 对于phy_clk,根据计算公式phy_clk= (gt_clk * 链路Line宽度)/4 ,所以phy_clk= gt_clk
  • log_clk则是不能小于phy_clk,所以大于等于最大phy_clk
    在这里插入图片描述

下图当中的示例设计采用单个差分输入时钟sys_clk,并实例化所需的时钟缓冲器和时钟模块来生成时钟。时钟方案在不同的FPGA系列之间略有不同,以适应每个设备的特定架构。sys_clk_p和sys_clk_n与DIFF_CLK接口相关联。

MMCM的乘法器和除法器值取决于参考时钟频率和线速率。在4x配置中,log_clk和gt_clk共享一个BUFG。在1x配置中,log_clk和phy_clk共享一个BUFG(并且不需要BUFGMUX,因为只有一个可能的phy_clk速率)。此外,如果在Vivado IDE中选择了统一时钟选项,则要求log_clk和phy_clk具有相同的速率。这意味着log_clk/cfg_clk的BUFG可以被移除,并且log_clk/cfg_clk与phy_clk绑定。
在这里插入图片描述

1.3、时钟总结

在这里插入图片描述
IP核当中有6个时钟输入,简单总结如下:

  1. gt_clk:由链路速率决定
  2. gt_pcs_clkgt_pcs_clk的频率是gt_clk的一半。
  3. phy_clkphy_clk= (gt_clk * 链路Line宽度)/4
  4. log_clkLOG(逻辑层)在log_clk域上运行。为了达到最佳吞吐量,log_clk应至少与phy_clk一样快。这是为了PHY层接收到的数据不会在BUF里一直停留。cfg_clk必须等同于log_clk
  5. drpclk :动态配置时钟,随意
  6. refclk :GT外部参考时钟

1.4、示例工程

这是示例工程当中的时钟模块,它将我们需要的时钟全部都已经产生好了,其中输入时钟信号sys_clkp就是GT外部参考时钟,mode_1x表示当前为1Line。

module srio_gen2_0_srio_clk
 (// Clock in ports
  input         sys_clkp,
  input         sys_clkn,
  // Status and control signals
  input         sys_rst,
  input         mode_1x,
  // Clock out ports
  output        log_clk,
  output        phy_clk,
  output        gt_pcs_clk,
  output        gt_clk,
  output        refclk,
  output        drpclk,
 
  // Status and control signals
  output        clk_lock
 );

  //------------------------------------
  // wire declarations
  //------------------------------------
  wire        refclk_bufg;
  wire        clkout0;
  wire        clkout1;
  wire        clkout2;
  wire        clkout3;
  wire [15:0] do_unused;
  wire        drdy_unused;
  wire        psdone_unused;
  wire        clkfbout;
  wire        to_feedback_in;
  wire        clkfboutb_unused;
  wire        clkout0b_unused;
  wire        clkout1b_unused;
  wire        clkout2b_unused;
  wire        clkout3_unused;
  wire        clkout3b_unused;
  wire        clkout4_unused;
  wire        clkout5_unused;
  wire        clkout6_unused;
  wire        clkfbstopped_unused;
  wire        clkinstopped_unused;
  // End wire declarations
  //------------------------------------


//  // input buffering

  //------------------------------------
  IBUFDS_GTE2 u_refclk_ibufds(
    .O      (refclk),
    .I      (sys_clkp),
    .IB     (sys_clkn),
    .CEB    (1'b0),
    .ODIV2  ()
  );

  BUFG refclk_bufg_inst
   (.O (refclk_bufg),
    .I (refclk));
  // End input buffering

  // MMCME2_ADV instantiation
  //------------------------------------
  MMCME2_ADV
  #(.BANDWIDTH            ("OPTIMIZED"),
    .CLKOUT4_CASCADE      ("FALSE"),
    .COMPENSATION         ("ZHOLD"),
    .STARTUP_WAIT         ("FALSE"),
    .DIVCLK_DIVIDE        (1),
    .CLKFBOUT_MULT_F      (6.000),
    .CLKFBOUT_PHASE       (0.000),
    .CLKFBOUT_USE_FINE_PS ("FALSE"),
    .CLKOUT0_DIVIDE_F     (3.000),
    .CLKOUT0_PHASE        (0.000),
    .CLKOUT0_DUTY_CYCLE   (0.500),
    .CLKOUT0_USE_FINE_PS  ("FALSE"),
    .CLKOUT1_DIVIDE       (12),
    .CLKOUT1_PHASE        (0.000),
    .CLKOUT1_DUTY_CYCLE   (0.500),
    .CLKOUT1_USE_FINE_PS  ("FALSE"),
    .CLKOUT2_DIVIDE       (6),
    .CLKOUT2_PHASE        (0.000),
    .CLKOUT2_DUTY_CYCLE   (0.500),
    .CLKOUT2_USE_FINE_PS  ("FALSE"),
    .CLKIN1_PERIOD        (6.400),
    .REF_JITTER1          (0.010))
  srio_mmcm_inst
    // Output clocks
   (.CLKFBOUT            (clkfbout),
    .CLKFBOUTB           (clkfboutb_unused),
    .CLKOUT0             (clkout0),
    .CLKOUT0B            (clkout0b_unused),
    .CLKOUT1             (clkout1),
    .CLKOUT1B            (clkout1b_unused),
    .CLKOUT2             (clkout2),
    .CLKOUT2B            (clkout2b_unused),
    .CLKOUT3             (clkout3_unused),
    .CLKOUT3B            (clkout3b_unused),
    .CLKOUT4             (clkout4_unused),
    .CLKOUT5             (clkout5_unused),
    .CLKOUT6             (clkout6_unused),
     // Input clock control
    .CLKFBIN             (clkfbout),
    .CLKIN1              (refclk_bufg),
    .CLKIN2              (1'b0),
     // Tied to always select the primary input clock
    .CLKINSEL            (1'b1),
    // Ports for dynamic reconfiguration
    .DADDR               (7'h0),
    .DCLK                (1'b0),
    .DEN                 (1'b0),
    .DI                  (16'h0),
    .DO                  (do_unused),
    .DRDY                (drdy_unused),
    .DWE                 (1'b0),
    // Ports for dynamic phase shift
    .PSCLK               (1'b0),
    .PSEN                (1'b0),
    .PSINCDEC            (1'b0),
    .PSDONE              (psdone_unused),
    // Other control and status signals
    .LOCKED              (clk_lock),
    .CLKINSTOPPED        (clkinstopped_unused),
    .CLKFBSTOPPED        (clkfbstopped_unused),
    .PWRDWN              (1'b0),
    .RST                 (1'b0)
  );
  // End 7 series MMCM instantiation

//______________________________________________________________________________

  // output buffering
  //-----------------------------------

  BUFG drpclk_bufr_inst
   (.O   (drpclk),
    .I   (clkout1));

  BUFG gt_clk_bufg_inst
   (.O (gt_clk),
    .I (clkout0));

  BUFG gt_pcs_clk_bufg_inst
   (.O (gt_pcs_clk),
    .I (clkout2));

  // Note that this bufg is a duplicate of the log_clk bufg, and is not necessary if BUFG resources are limited.
  BUFG phy_clk_bufg_inst
   (.O (phy_clk),
    .I (clkout1));

(* DONT_TOUCH = "true" *) BUFG log_clk_bufg_inst
   (.O (log_clk),
    .I (clkout1));
 
  // End output buffering
//______________________________________________________________________________

endmodule

二、复位

每个时钟域都有一个关联的复位信号。复位应该在各自的时钟域中被断言至少四个时钟周期,并且在同步的情况下去除(注意,如果核心被训练降频(比如:一端是4line,对端是1line,那么在建链的时候,速率会被降低到1line),phy_clk运行速度会比原始速率慢,复位仍然必须持续四个完整周期)。

包含的复位参考设计模块(srio_rst.v)有一个单一的复位输入,sys_rst。该信号是一个异步输入。此模块将复位同步到每个时钟域,并扩展脉冲以满足最小复位周期要求。

初始硬件复位应由用户设计生成。复位也可以使用RapidIO协议在带内进行通信。在重置SRIO Gen2 Endpoint 设备时必须特别小心。为了保证ackID对齐,应将所有的链路伙伴一起重置(也就是PHY、BUF、LOG这些模块都要复位)。建议在链路伙伴之间的复位重叠以减少丢失数据包和控制符号的发生。实现此操作的一种方法是进行核心复位的握手。从链路伙伴接收到的复位通过phy_rcvd_link_reset信号从核心传达给用户设计。在接收到链路复位时,应断言sys_rst信号。根据实现方式,可以根据phy_rcvd_link_reset的断言向用户应用程序发送复位信号。要向链路伙伴发送复位请求,请断言phy_link_reset信号,直到port_initialized输出变为低电平。在此时,应断言sys_rst到复位参考设计,完成握手。

个人总结:
上面都是翻译文档的。。。大概意思估计是要复位SRIO Gen2 Endpoint 的时候,先拉高phy_link_reset信号,然后IP核就会断言phy_rcvd_link_reset信号,那么此时用户就应该断言sys_rst有效,然后其他模块(PHY、BUF、LOG)就要跟着一起复位来保证ackID对齐,不过看示例工程里面的代码,不用管sys_rst,这个模块一旦收到phy_rcvd_link_reset信号有效,不需要你断言sys_rst就开始进行复位其他模块了。
以下是示例工程里面的代码:

module srio_gen2_0_srio_rst
   (
    input            cfg_clk,                 // CFG interface clock
    input            log_clk,                 // LOG interface clock
    input            phy_clk,                 // PHY interface clock
    input            gt_pcs_clk,              // GT Fabric interface clock

    input            sys_rst,                 // Global reset signal
    input            port_initialized,        // Port is intialized
    input            phy_rcvd_link_reset,     // Received 4 consecutive reset symbols
    input            force_reinit,            // Force reinitialization
    input            clk_lock,                // Indicates the MMCM has achieved a stable clock

    output reg       controlled_force_reinit, // Force reinitialization

    output           cfg_rst,                 // CFG dedicated reset
    output           log_rst,                 // LOG dedicated reset
    output           buf_rst,                 // BUF dedicated reset
    output           phy_rst,                 // PHY dedicated reset
    output           gt_pcs_rst               // GT dedicated reset
   );


  // {{{ Parameter declarations -----------
  // Reset State Machine
  localparam  IDLE       = 4'b0001;
  localparam  LINKRESET  = 4'b0010;
  localparam  PHY_RESET1 = 4'b0100;
  localparam  PHY_RESET2 = 4'b1000;

  // }}} End Parameter declarations -------
  
  wire sys_rst_buffered;


  // {{{ wire declarations ----------------
  reg   [0:3]   reset_state      = IDLE;
  reg   [0:3]   reset_next_state = IDLE;

 (* ASYNC_REG = "TRUE" *)
  reg  [3:0]        cfg_rst_srl;
 (* ASYNC_REG = "TRUE" *)
  reg  [3:0]        log_rst_srl;
 (* ASYNC_REG = "TRUE" *)
  reg  [3:0]        phy_rst_srl;
 (* ASYNC_REG = "TRUE" *)
  reg  [3:0]        gt_pcs_rst_srl;

  reg               sys_rst_int;
  wire              reset_condition = sys_rst || phy_rcvd_link_reset || sys_rst_int;

  // }}} End wire declarations ------------



  assign cfg_rst = cfg_rst_srl[3];
  always @(posedge cfg_clk or posedge reset_condition) begin
    if (reset_condition) begin
      cfg_rst_srl <= 4'b1111;
    end else if (clk_lock) begin
      cfg_rst_srl <= {cfg_rst_srl[2:0], 1'b0};
    end
  end


  assign log_rst = log_rst_srl[3];
  always @(posedge log_clk or posedge reset_condition) begin
    if (reset_condition) begin
      log_rst_srl <= 4'b1111;
    end else if (clk_lock) begin
      log_rst_srl <= {log_rst_srl[2:0], 1'b0};
    end
  end


  // The Buffer actively manages the reset due to the
  // nature of the domain crossing being done in the buffer.
  assign buf_rst = reset_condition;


  assign phy_rst = phy_rst_srl[3];
  always @(posedge phy_clk or posedge reset_condition) begin
    if (reset_condition) begin
      phy_rst_srl <= 4'b1111;
    end else if (clk_lock) begin
      phy_rst_srl <= {phy_rst_srl[2:0], 1'b0};
    end
  end


  assign gt_pcs_rst = gt_pcs_rst_srl[3];
  always @(posedge gt_pcs_clk or posedge reset_condition) begin
    if (reset_condition) begin
      gt_pcs_rst_srl <= 4'b1111;
    end else if (clk_lock) begin
      gt_pcs_rst_srl <= {gt_pcs_rst_srl[2:0], 1'b0};
    end
  end



  // This controller is used to properly send link reset requests that were
  // made by the user.
  always@(posedge log_clk) begin
    reset_state <= reset_next_state;
  end


  always @* begin
    casex (reset_state)

      IDLE: begin
        // Current State Outputs
        sys_rst_int             = 1'b0;
        controlled_force_reinit = 1'b0;
        // Next State Outputs
        if (force_reinit)
          reset_next_state = LINKRESET;
        else
          reset_next_state = IDLE;
      end

      LINKRESET: begin
        // Current State Outputs
        sys_rst_int             = 1'b0;
        controlled_force_reinit = 1'b1;
        // Next State Outputs
        if (~port_initialized)
          reset_next_state = PHY_RESET1;
        else
          reset_next_state = LINKRESET;
      end

      PHY_RESET1: begin
        // Current State Outputs
        sys_rst_int             = 1'b1;
        controlled_force_reinit = 1'b0;
        // Next State Outputs
        reset_next_state = PHY_RESET2;
      end

      PHY_RESET2: begin
        // Current State Outputs
        sys_rst_int             = 1'b1;
        controlled_force_reinit = 1'b0;
        // Next State Outputs
        if (force_reinit)
          reset_next_state = PHY_RESET2;
        else
          reset_next_state = IDLE;
      end

      default: begin
        // Current State Outputs
        sys_rst_int             = 1'b0;
        controlled_force_reinit = 1'b0;
        // Next State Outputs
        reset_next_state = IDLE;
      end

    endcase
  end



endmodule
  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顺子学不会FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值