1、Clock IP设置
第一步,勾选“Dynamic phase shift”。
2、第二步,在需要相位调整的输出时钟后面勾选“Use Fine Ps”。
2、端口说明
上图是时钟IP核例化代码。
1)CLK_IN1为需要相位调整的输入时钟;
2)PSCLK为用于调整相位的系统时钟;
3)PSEN为相移使能;
4)PSINCDEC为相移加/减选择端,为“1”时,相位增加;为“0”时,相位减小;
5)PSDONE为相移完成标志;
6)RESET为复位;
7)CLK_OUT1为相移后的时钟;
8)LOCKED为IP核的锁时钟定标志,拉高时输出时钟稳定。
3、相移模块说明
PSEN每拉高一次,完成一个单位的相位移动,在11.01个周期后PSDONE拉高,标志一次相移的完成。在PSDONE拉高后,才能进行下一次PSEN拉高进行下一次相移,否则PSEN拉高无效。因此,可以通过控制PSEN使能的次数来控制相移的多少。
如下图所示,经过测试,一个单位相移值为0.018ns。
附录:时钟相移模块代码
//
// COPYRIGHT( c)2020, Beijing Institute of Technology Chongqing Innovation Center.
// ALL rights reserved
//
// Module Name : adc_clk_phase_shift.v
// File Name : adc_clk_phase_shift
// Target Devices : xc7k325t-2ffg1000
// Tool versions : ISE13.7
// Simulator : Modelsim10.5
// Description : adc clk phase shift
// Althor : mwj
//
//
// Revision Number : V1.1.0
// Data of Change : 2020-08-17
// Modifier : mwj( 1015729806@qq.com)
// Description : xxx
//
`timescale 1ns / 1ps
module adc_clk_phase_shift
#(
parameter TIME = 12 , /// Time Between Phase Modify , min = 12*clk
parameter TIMES_OF_SHIFT = 290 , /// Times of Phase Modify
parameter MAX_TIMES_OF_SHIFT = 555 /// Max of "Times of Phase Modify "
)
(
input I_rx_clk1 , /// ADC1 Clock
input I_rx_clk2 , /// ADC2 Clock
input I_psclk , ///
input I_rst , ///
output O_rx_clk1_shifted , /// ADC1 Clock(Shifted)
output O_rx_clk2_shifted /// ADC2 Clock(Shifted)
);
///-----------------------------------------------------------------------------
/// Signal Declarations
///-----------------------------------------------------------------------------
reg psen = 0 ;
reg psincdec = 1 ;
reg [26:0] time_cnt = 0 ;
(*KEEP = "TRUE"*)reg [9:0] phaseshift_cnt = 0 ;
wire psdone1 ;
wire psdone2 ;
wire locked ;
wire locked1 ;
wire locked2 ;
///-----------------------------------------------------------------------------
/// Main Codes
///-----------------------------------------------------------------------------
always @(posedge I_psclk)
begin
if((I_rst == 1'b1) || (locked == 1'b0))
begin
time_cnt <= 'd0;
end
else if (time_cnt == TIME )
begin
time_cnt <= 'd0;
end
else
begin
time_cnt <= time_cnt + 1'b1;
end
end
always @(posedge I_psclk)
begin
if((I_rst == 1'b1) || (locked == 1'b0))
begin
psen <= 1'b0;
end
else if ((time_cnt == TIME ) && (phaseshift_cnt != TIMES_OF_SHIFT))
// else if (time_cnt == TIME )
begin
psen <= 1'b1;
end
else
begin
psen <= 1'b0;
end
end
always @(posedge I_psclk)
begin
if((I_rst == 1'b1) || (locked == 1'b0))
begin
psincdec <= 1'b0;
end
else if ((time_cnt == TIME ) && (phaseshift_cnt != TIMES_OF_SHIFT))
// else if (time_cnt == TIME)
begin
psincdec <= 1'b1;
end
else
begin
psincdec <= 1'b0;
end
end
always @(posedge I_psclk)
begin
if((I_rst == 1'b1) || (locked == 1'b0))
begin
phaseshift_cnt <= 'd0;
end
else if ((time_cnt == TIME ) && (phaseshift_cnt != TIMES_OF_SHIFT))
// else if (time_cnt == TIME )
begin
if(phaseshift_cnt == MAX_TIMES_OF_SHIFT)
begin
phaseshift_cnt <= 'd0;
end
else
begin
phaseshift_cnt <= phaseshift_cnt + 1'b1;
end
end
end
assign locked = locked1 & locked2;
///----------------------------------------------
/// Module Instances
/// ---------------------------------------------
adcclk_phaseshift_pll_ip u1_adcclk_phaseshift_pll_ip
(
// input
.CLK_IN1 ( I_rx_clk1 ),
.PSCLK ( I_psclk ),
.PSEN ( psen ),
.PSINCDEC ( psincdec ),
.RESET ( I_rst ),
// output
.PSDONE ( psdone1 ),
.CLK_OUT1 ( O_rx_clk1_shifted ),
.LOCKED ( locked1 )
);
adcclk_phaseshift_pll_ip u2_adcclk_phaseshift_pll_ip
(
// input
.CLK_IN1 ( I_rx_clk2 ),
.PSCLK ( I_psclk ),
.PSEN ( psen ),
.PSINCDEC ( psincdec ),
.RESET ( I_rst ),
// output
.PSDONE ( psdone2 ),
.CLK_OUT1 ( O_rx_clk2_shifted ),
.LOCKED ( locked2 )
);
endmodule