Xilinx SELECTIO IP核调用配作可变延迟加输入解串工作模式时信号接口如下表所示:
接口名
方向
注释
DATA_IN_FROM_PINS
Input
来自外部IO数据输入引脚
DATA_IN_TO_DEVICE
Output
CLK_OUT同步后的输出数据
DELAY_BUSY
Output
IODELAY校准和相位变化正在进行忙信号
DELAY_CLK
Input
FPGA内部逻辑同步时钟,可接CLK_DIV_OUT
DELAY_DATA_CAL
Input
IODELAY相位校正信号
DELAY_DATA_CE
Input
相位增加(减少)使能信号
DELAY_DATA_INC
Input
相位增加(高)、减少(低)信号
BITSLIP
Input
帧信号对齐命令引脚
CLK_IN
Input
外部时钟输入引脚
CLK_DIV_OUT
Output
时钟输出,用于FPGA内部逻辑同步信号
IO_RESET
Input
IO模块复位信号,高电平有效
(在ISE中从Instantation template中例化会有一个CLK_RESET信号,但在实际IP核里并没有连接该信号)
ISERDES有三种模式:NETWORKING、NETWORKING_PIPELINED、RETIMED。其中NETWORKING模式无法启用BITSLIP功能。NETWORKING_PIPELINED模式数据输出并未同步到内部全局时钟,但相比于RETIMED模式其具有更少的延迟。RETIMED模式则数据输出同步至全局时钟模块,由CLK_DIV_OUT同步。
BITSLIP用于字对齐的调整,来自DATA_IN_FROM_PINS的数据为LSB first,在调节过程中BITSLIP拉高一个CLKDIVOUT时钟周期,随后拉低至少一个全局时钟周期,其伪代码为:
After reset
If input frame data not equal to required frame pattern then
BITSLIP<=1;
ELSE
BITSLIP<=0;
BITSLIP_COMPLETE<=1;
Wait at least one global clock cycle
Repeat
值得注意的是,在实验过程中发现,在RETIMED模式下,BITSLIP应当至少拉低三个全局时钟周期方能有效进行字对齐。
对于ISERDES的控制,其控制流程如下:
(1)
上电复位
(2)
拉高DELAY_DATA_CAL进行延迟调节
(3)
等待20个全局时钟周期
(4)
置位IO_RESET一个全局时钟周期
(5)
进行BITSLIP控制字调节,若超时返回(2),完成调节则进行下一步
(6)
周期性进行延迟调节(拉高DELAY_DATA_CAL但无需进行IO_RESET)
实验代码如下
//========================================================================================================================================================
// Company:
// Engineer:
// Create Date:
// Design Name:
// Module Name:
// Target Device:
// Tool versions:
// Description:
// Dependencies:
// Revision:
// Additional Comments:
//========================================================================================================================================================
module ISERDES_TEST#(
parameter
DATA_WIDTH=8
)(
input
IO_CLK_IN,
//IO输入时钟
input
IO_DATA_IN,
input
reset_n,
//复位信号,低电平有效
output
[DATA_WIDTH-1:0]
DATA_OUT,
output
BITSLIP_COMPLETE
//帧校准完成信号
);
//========================================================================================================================================================
//内部变量声明
//========================================================================================================================================================
wire
[DATA_WIDTH-1:0]
deserdes_data_w;
//解串数据
wire
sys_clk;
//系统时钟
wire
iserdes_delay_busy;
//ISErDES忙标志
wire
iserdes_cal;
//延迟校准信号
wire
iserdes_bitslip;
//帧校准信号
wire
iserdes_reset;
//iserdes复位信号,高电平有效
reg
[DATA_WIDTH-1:0]
deserdes_data_r;
//========================================================================================================================================================
//ISERDES模块例化
//========================================================================================================================================================
ISERDES_CORE ISERDES_mod
(
// From the system into the device
.DATA_IN_FROM_PINS(IO_DATA_IN),
//串行数据输入
.DATA_IN_TO_DEVICE(deserdes_data_w),
//并行数据输出
.DELAY_BUSY(iserdes_delay_busy),
//忙标志输出
.DELAY_CLK(sys_clk),
//同步时钟输入
.DELAY_DATA_CAL(iserdes_cal),
//延迟校准信号输入
.DELAY_DATA_CE(1'b0),
.DELAY_DATA_INC(1'b0),
.BITSLIP(iserdes_bitslip),
//帧校准信号
.CLK_IN(IO_CLK_IN),
// IO时钟输入
.CLK_DIV_OUT(sys_clk),
// 同步时钟输出
.IO_RESET(iserdes_reset)
//ISERDES模块复位信号
);
//========================================================================================================================================================
//ISERDES控制模块例化
//========================================================================================================================================================
ISERDES_CONTROL iserdes_con (
.sys_clk(sys_clk),
.sys_reset_n(reset_n),
.deserdes_data_in(deserdes_data_w),
.Idelay_reset_o(iserdes_reset),
.Idelay_cal_o(iserdes_cal),
.Iserdes_bitslip_o(iserdes_bitslip),
.Bitslip_complete(BITSLIP_COMPLETE)
);
//========================================================================================================================================================
//输出数据锁存
//========================================================================================================================================================
always @(posedge sys_clk)
begin
if(!reset_n)
deserdes_data_r<='d0;
else
deserdes_data_r<=deserdes_data_w;
end
assign
DATA_OUT=deserdes_data_r;
endmodule
//========================================================================================================================================================
// Company:
// Engineer:
// Create Date:
// Design Name:
// Module Name:
// Target Device:
// Tool versions:
// Description:
// Dependencies:
// Revision:
// Additional Comments:
//========================================================================================================================================================
module ISERDES_CONTROL#(
parameter
CAL_PERIOD=2**10,
parameter
SERIAL_RATe=8,
parameter
TRAIN_SEQ=8'b1010_1111,
parameter
DATA_WIDTH=8
)(
input
sys_clk,
input
sys_reset_n,
//复位信号,低电平有效
input [DATA_WIDTH-1:0]
deserdes_data_in,
//解串数据
output
Idelay_reset_o,
//IDELAY2复位信号
output
Idelay_cal_o,
//IDELAY2校准信号
output
Iserdes_bitslip_o,
//ISERDES帧对齐调节信号
output
Bitslip_complete
//帧对齐完成信号
);
//========================================================================================================================================================
//内部常亮声明
//========================================================================================================================================================
localparam
FSM_IDLE
=6'b000001,
FSM_Init_CAL
=6'b000010,
FSM_Init_WAIT
=6'b000100,
FSM_Init_RST
=6'b001000,
FSM_BITSLIP
=6'b010000,
FSM_Perod_CAL
=6'b100000;
//========================================================================================================================================================
//内部常亮声明
//========================================================================================================================================================
reg
[$clog2(CAL_PERIOD):0]
cal_time_cnt;
//校正周期计时器
reg
Idelay_cal_r ;
//校正信号寄存器及其下一状态
reg
Idelay_reset_r;
//IDELAY复位信号及下一状态
reg
[5:0]
Fsm_cs,Fsm_ns;
//有限状态机
reg
[4:0]
Cal_wait_cnt;
//cal校正等待信号
reg
Bitslip_r,Bitslip_r_n,Bitslip_r_nn;
//帧对齐调节信号及其缓存
reg
Bitslip_complete_r;
//帧对齐完成寄存器
reg
[$clog2(10**3):0]
Bitslip_cnt;
//帧对齐调节时间
//========================================================================================================================================================
//内部状态机
//========================================================================================================================================================
always@(posedge sys_clk )
begin
if(!sys_reset_n )
Fsm_cs<=FSM_IDLE;
else
Fsm_cs<=Fsm_ns;
end
always@(*)
begin
case(Fsm_cs)
FSM_IDLE:
Fsm_ns=FSM_Init_CAL;
FSM_Init_CAL:
Fsm_ns=FSM_Init_WAIT;
FSM_Init_WAIT:
begin
if( Cal_wait_cnt==5'd20 )
//等待20个时钟周期
Fsm_ns=FSM_Init_RST;
else
Fsm_ns=FSM_Init_WAIT;
end
FSM_Init_RST:
Fsm_ns=FSM_BITSLIP;
FSM_BITSLIP:
begin
if(Bitslip_cnt<=10**3-1)
begin
if(deserdes_data_in==TRAIN_SEQ)
Fsm_ns=FSM_Perod_CAL;
else
Fsm_ns=Fsm_cs;
end
else
Fsm_ns=FSM_IDLE;
end
FSM_Perod_CAL:
Fsm_ns=FSM_Perod_CAL;
default:Fsm_ns=FSM_IDLE;
endcase
end
//========================================================================================================================================================
//cal校正等待信号计时
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
Cal_wait_cnt<=5'd0;
else if(Fsm_cs==FSM_Init_WAIT)
Cal_wait_cnt<=Cal_wait_cnt+1'b1;
else
Cal_wait_cnt<=5'd0;
end
//========================================================================================================================================================
//校正周期计时
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
cal_time_cnt<='d0;
else if(Fsm_cs==FSM_Perod_CAL)
begin
if(cal_time_cnt==CAL_PERIOD-1)
cal_time_cnt<='d0;
else
cal_time_cnt<=cal_time_cnt+1'b1;
end
else
cal_time_cnt<='d0;
end
//========================================================================================================================================================
//Bitslip_cnt计时
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
Bitslip_cnt<='d0;
else if(Fsm_cs==FSM_BITSLIP)
Bitslip_cnt<=Bitslip_cnt+1'b1;
else
Bitslip_cnt<='d0;
end
//========================================================================================================================================================
//复位信号输出
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
Idelay_reset_r<=1'b0;
else if(Fsm_cs==FSM_Init_RST)
Idelay_reset_r<=1'b1;
else
Idelay_reset_r<=1'b0;
end
//========================================================================================================================================================
//校正信号输出
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
Idelay_cal_r<=1'b0;
else if(Fsm_cs==FSM_Init_CAL||((Fsm_cs==FSM_Perod_CAL)&&(cal_time_cnt==CAL_PERIOD-1)))
Idelay_cal_r<=1'b1;
else
Idelay_cal_r<=1'b0;
end
//========================================================================================================================================================
//帧调整信号
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
Bitslip_r<=1'b0;
else if((Fsm_cs==FSM_BITSLIP)&&(deserdes_data_in!=TRAIN_SEQ))
begin
if(Bitslip_r||Bitslip_r_n ||Bitslip_r_nn)
Bitslip_r<=1'b0;
else
Bitslip_r<=1'b1;
end
else
Bitslip_r<=1'b0;
end
always @(posedge sys_clk)
begin
if(!sys_reset_n)
Bitslip_r_n<=1'b0;
else
Bitslip_r_n<=Bitslip_r;
end
always @(posedge sys_clk)
begin
if(!sys_reset_n)
Bitslip_r_nn<=1'b0;
else
Bitslip_r_nn<=Bitslip_r_n;
end
//========================================================================================================================================================
//帧调整完成信号
//========================================================================================================================================================
always@(posedge sys_clk)
begin
if(!sys_reset_n)
Bitslip_complete_r<=1'b0;
else if((Fsm_cs==FSM_BITSLIP)&&(deserdes_data_in==TRAIN_SEQ))
Bitslip_complete_r<=1'b1;
else
Bitslip_complete_r<=Bitslip_complete_r;
end
//========================================================================================================================================================
//输出信号连接
//========================================================================================================================================================
assign
Idelay_reset_o
=Idelay_reset_r;
assign
Idelay_cal_o
=Idelay_cal_r;
assign
Iserdes_bitslip_o
=Bitslip_r;
assign
Bitslip_complete
=Bitslip_complete_r;
endmodule
testbench如下
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 19:41:07 10/22/2017
// Design Name: ISERDES_TEST
// Module Name: C:/Users/Administrator/Desktop/idelay_test/iserdes/IESRDES_TEST/ISERDES_TB.v
// Project Name: IESRDES_TEST
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: ISERDES_TEST
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module ISERDES_TB;
// Inputs
reg IO_CLK_IN;
reg IO_DATA_IN;
reg reset_n;
// Outputs
wire [7:0] DATA_OUT;
wire BITSLIP_COMPLETE;
// Instantiate the Unit Under Test (UUT)
ISERDES_TEST uut (
.IO_CLK_IN(IO_CLK_IN),
.IO_DATA_IN(IO_DATA_IN),
.reset_n(reset_n),
.DATA_OUT(DATA_OUT),
.BITSLIP_COMPLETE(BITSLIP_COMPLETE)
);
initial begin
// Initialize Inputs
IO_CLK_IN = 0;
IO_DATA_IN = 0;
reset_n = 0;
// Wait 100 ns for global reset to finish
@(posedge IO_CLK_IN);
#300;
reset_n=1;
@(posedge IO_CLK_IN)
@(posedge IO_CLK_IN)
IO_DATA_IN<=1;
send_data(8'hfd);
send_data(8'h1f);
send_data(8'hcc);
send_data(8'hcc);
send_data(8'hcc);
send_data(8'h4c);
send_data(8'hcc);
send_data(8'hc5);
send_data(8'hfd);
send_data(8'h1f);
send_data(8'hcc);
send_data(8'hcc);
send_data(8'hcc);
send_data(8'h4c);
send_data(8'hcc);
send_data(8'b1010_1111);
send_data(8'hc5);
send_data(8'hcc);
send_data(8'b1010_1111);
repeat(300)
begin
send_data(8'b1010_1111);
end
send_data(8'h36);
send_data(8'h73);
send_data(8'h98);
send_data(8'h56);
repeat(10000)
begin
send_data($random()%256);
end
$stop;
// Add stimulus here
end
always #8
IO_CLK_IN=~IO_CLK_IN;
task send_data(input [7:0] data);
integer i;
begin :data_send_seq
for(i=0;i<=7;i=i+1)
begin
@(posedge IO_CLK_IN)
IO_DATA_IN<=data[i];
end
end
endtask
endmodule