前言
通过对时钟和复位的理解可以更好的了解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_clk和phy_clk域之间传输数据包。如果BUF用于统一时钟,则log_clk和phy_clk必须同步。否则,时钟必须匹配与接口子核心的速率。
每个子核心配置寄存器接口上的cfg_clk域是独立于该子核心时钟的。但是,为了使用提供的配置结构参考设计中的LOG维护控制器,所有这些接口的cfg_clk必须等同于log_clk。
1.2、典型时钟速率
下表是xilinx给出的典型时钟速率,我们以4x为例进行分析:
- 首先是gt_clk 和gt_pcs_clk,这个是根据线速率决定的,从下面的图3-14也可以看出,所谓的gt_clk就是我们之前熟悉的TXUSERCLK/RXUSERCLK,gt_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个时钟输入,简单总结如下:
- gt_clk:由链路速率决定
- gt_pcs_clk: gt_pcs_clk的频率是gt_clk的一半。
- phy_clk:phy_clk= (gt_clk * 链路Line宽度)/4
- log_clk :LOG(逻辑层)在log_clk域上运行。为了达到最佳吞吐量,log_clk应至少与phy_clk一样快。这是为了PHY层接收到的数据不会在BUF里一直停留。cfg_clk必须等同于log_clk
- drpclk :动态配置时钟,随意
- 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 <