一、前言
上一篇讲述了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_clksrio_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 clockinput log_clk, // LOG interface clockinput phy_clk, // PHY interface clockinput gt_pcs_clk, // GT Fabric interface clockinput sys_rst, // Global reset signalinput port_initialized, // Port is intializedinput phy_rcvd_link_reset, // Received 4 consecutive reset symbolsinput force_reinit, // Force reinitializationinput clk_lock, // Indicates the MMCM has achieved a stable clockoutput reg controlled_force_reinit, // Force reinitializationoutput cfg_rst, // CFG dedicated resetoutput log_rst, // LOG dedicated resetoutput buf_rst, // BUF dedicated resetoutput phy_rst, // PHY dedicated resetoutput gt_pcs_rst // GT dedicated reset);// {{{ Parameter declarations -----------// Reset State Machinelocalparam 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) beginif (reset_condition) begincfg_rst_srl <= 4'b1111;end else if (clk_lock) begincfg_rst_srl <= {cfg_rst_srl[2:0], 1'b0};endendassign log_rst = log_rst_srl[3];always @(posedge log_clk or posedge reset_condition) beginif (reset_condition) beginlog_rst_srl <= 4'b1111;end else if (clk_lock) beginlog_rst_srl <= {log_rst_srl[2:0], 1'b0};endend// 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) beginif (reset_condition) beginphy_rst_srl <= 4'b1111;end else if (clk_lock) beginphy_rst_srl <= {phy_rst_srl[2:0], 1'b0};endendassign gt_pcs_rst = gt_pcs_rst_srl[3];always @(posedge gt_pcs_clk or posedge reset_condition) beginif (reset_condition) begingt_pcs_rst_srl <= 4'b1111;end else if (clk_lock) begingt_pcs_rst_srl <= {gt_pcs_rst_srl[2:0], 1'b0};endend// This controller is used to properly send link reset requests that were// made by the user.always@(posedge log_clk) beginreset_state <= reset_next_state;endalways @* begincasex (reset_state)IDLE: begin// Current State Outputssys_rst_int = 1'b0;controlled_force_reinit = 1'b0;// Next State Outputsif (force_reinit)reset_next_state = LINKRESET;elsereset_next_state = IDLE;endLINKRESET: begin// Current State Outputssys_rst_int = 1'b0;controlled_force_reinit = 1'b1;// Next State Outputsif (~port_initialized)reset_next_state = PHY_RESET1;elsereset_next_state = LINKRESET;endPHY_RESET1: begin// Current State Outputssys_rst_int = 1'b1;controlled_force_reinit = 1'b0;// Next State Outputsreset_next_state = PHY_RESET2;endPHY_RESET2: begin// Current State Outputssys_rst_int = 1'b1;controlled_force_reinit = 1'b0;// Next State Outputsif (force_reinit)reset_next_state = PHY_RESET2;elsereset_next_state = IDLE;enddefault: begin// Current State Outputssys_rst_int = 1'b0;controlled_force_reinit = 1'b0;// Next State Outputsreset_next_state = IDLE;endendcaseend
endmodule