SRIO系列-时钟逻辑与复位逻辑

发布于:2024-04-24 ⋅ 阅读:(29) ⋅ 点赞:(0)

一、前言

上一篇讲述了SRIO协议的基本概念,传输的HELLO帧格式、事务类型等,本篇说一下SRIO IP核的时钟关系。

基本的IP设置可以参考此篇文章:【高速接口-RapidIO】Xilinx SRIO IP 核详解-CSDN博客

二、时钟关系

 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)。当生成核心时,参考时钟频率被选择(可用选项取决于体系结构和线路速率。

时钟 频率关系
phy_clk phy_clk = (gt_clk * link width)/4 主要的核时钟
gt_pcs_clk gt_pcs_clk = 1/2 * gt_clk 主要终于Serial Transceiver interface
refclk 见下表 用于Serial Transceiver interface
log_clk log_clk >=phy_clk
cfg_clk cfg_clk = log_clk 配置寄存器接口时钟

 不同lane下的时钟关系:

 对于7系列FPGAs,使用MMCM从串行收发器(GT)参考时钟生成时钟。时钟方案的方框图如下:

在SRIO的例子工程中,时钟主要有共享逻辑中的时钟模块提供,在这个模块中通过MMCM得到满足上述时钟关系的各时钟域时钟。

   srio_gen2_0_srio_clk
   srio_clk_inst (
      .sys_clkp                (sys_clkp        ),// input to the clock module
      .sys_clkn                (sys_clkn        ),// input to the clock module
      .sys_rst                 (sys_rst         ),// input to the clock module
      .mode_1x                 (mode_1x         ),// input to the clock module

      .log_clk                 (log_clk_out     ),// output from clock module
      .phy_clk                 (phy_clk_out     ),// output from clock module
      .gt_clk                  (gt_clk_out      ),// output from clock module
      .gt_pcs_clk              (gt_pcs_clk_out  ),// output from clock module
      .refclk                  (refclk_out      ),// output from clock module
      .drpclk                  (drpclk_out),      // output from clock module
      .clk_lock                (clk_lock_out_int) // output from clock module
     );

二、复位逻辑

SRIO每个时钟域都有一个指定的复位,复位应该声明各自时钟域的至少四个时钟周期,并同步取消复位。

在例子工程的复位模块中,会有一个异步的复位输入,在这个模块中,会将这个复位同步到各个时钟域,并且需要把复位的脉冲扩展到最小的复位时钟周期请求。

当重置SRIO端点设备时必须要将链路两端的设备一起复位,去保证AckID的对齐,从而减少数据包和控制字符的丢失。实现这一过程的方式是对核的复位进行握手。从接收端接收到的复位信号会通过phy_rcvd_link_reset给到用户设计。在接收到链路重置时应该置位sys_rst信号,还可以向用户应用程序响应phy_rcvd_link_reset的断言。

向对端发送重置请求,请求置位phy_rcvd_link-reset信号,直到端口初始化输出变低。

在例子工程中,srio_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


网站公告

今日签到

点亮在社区的每一天
去签到