Xilinx oserdese原语使用求助
时间:10-02
整理:3721RD
点击:
最近做项目需要用FPGA驱动AD9122,要用到并串转换,所以使用了xilinx的oserdese2和MMCM_ADV原语,但是仿真结果和文档上的时序说明对不上,但是找不出原因,哪位大神能帮忙看看,感激不尽。代码如下:
//MMCM 产生时钟
`timescale 1ns/100ps
module ad_mmcm_drp (
// clocks
clk,
mmcm_rst,
mmcm_clk_0,
mmcm_clk_1
);
// parameters
parameterMMCM_CLKIN_PERIOD= 1.667;
parameterMMCM_CLKIN2_PERIOD= 1.667;
parameterMMCM_VCO_div= 6;
parameterMMCM_VCO_MUL = 12.000;
parameterMMCM_CLK0_div = 2.000;
parameterMMCM_CLK1_div = 6;
// clocks
inputclk;
inputmmcm_rst;
outputmmcm_clk_0;
outputmmcm_clk_1;
;
wirebufg_fb_clk_s;
wiremmcm_fb_clk_s;
wiremmcm_clk_0_s;
wiremmcm_clk_1_s;
wiremmcm_locked_s;
// instantiations
MMCME2_ADV #(
.BANDWIDTH ("OPTIMIZED"),
.CLKOUT4_CASCADE ("FALSE"),
.COMPENSATION ("ZHOLD"),
.STARTUP_WAIT ("FALSE"),
.divCLK_divIDE (MMCM_VCO_div),
.CLKFBOUT_MULT_F (MMCM_VCO_MUL),
.CLKFBOUT_PHASE (0.000),
.CLKFBOUT_USE_FINE_PS ("FALSE"),
.CLKOUT0_divIDE_F (MMCM_CLK0_div),
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT0_USE_FINE_PS ("FALSE"),
.CLKOUT1_divIDE (MMCM_CLK1_div),
.CLKOUT1_PHASE (0.000),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT1_USE_FINE_PS ("FALSE"),
.CLKIN1_PERIOD (MMCM_CLKIN_PERIOD),
.CLKIN2_PERIOD (MMCM_CLKIN2_PERIOD),
.REF_JITTER1 (0.010))
i_mmcm (
.CLKIN1 (clk),
.CLKFBIN (bufg_fb_clk_s),
.CLKFBOUT (mmcm_fb_clk_s),
.CLKOUT0 (mmcm_clk_0_s),
.CLKOUT1 (mmcm_clk_1_s),
.LOCKED (mmcm_locked_s),
.DCLK (),
.DEN (1'b0),
.DADDR (7'd0),
.DWE (1'b0),
.DI (16'd0),
.DO (),
.DRDY (),
.CLKFBOUTB (),
.CLKOUT0B (),
.CLKOUT1B (),
.CLKOUT2 (),
.CLKOUT2B (),
.CLKOUT3 (),
.CLKOUT3B (),
.CLKOUT4 (),
.CLKOUT5 (),
.CLKOUT6 (),
.CLKIN2 (),
.CLKINSEL (1'b1),
.PSCLK (1'b0),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSDONE (),
.CLKINSTOPPED (),
.CLKFBSTOPPED (),
.PWRDWN (1'b0),
.RST (mmcm_rst));
BUFG i_fb_clk_bufg(.I (mmcm_fb_clk_s),.O (bufg_fb_clk_s));
BUFG i_clk_0_bufg(.I (mmcm_clk_0_s),.O (mmcm_clk_0));
BUFG i_clk_1_bufg(.I (mmcm_clk_1_s),.O (mmcm_clk_1));
endmodule
//并串转换模块
`timescale 1ps/1ps
module ad_serdes_out (
// reset and clocks
rst,
clk,
div_clk,
// data interface
data_s0,
data_s1,
data_s2,
data_s3,
data_s4,
data_s5,
data_s6,
data_s7,
data_out_p,
data_out_n);
// parameters
parameterDEVICE_TYPE = 0;
parameterSERDES_OR_DDR_N = 1;
parameterDATA_WIDTH = 16;
localparamDEVICE_6SERIES = 1;
localparamDEVICE_7SERIES = 0;
localparamDW = DATA_WIDTH - 1;
// reset and clocks
inputrst;
inputclk;
inputdiv_clk;
// data interface
input[DW:0]data_s0;
input[DW:0]data_s1;
input[DW:0]data_s2;
input[DW:0]data_s3;
input[DW:0]data_s4;
input[DW:0]data_s5;
input[DW:0]data_s6;
input[DW:0]data_s7;
output[DW:0]data_out_p;
output[DW:0]data_out_n;
// internal signals
wire[DW:0]data_out_s;
wire[DW:0]serdes_shift1_s;
wire[DW:0]serdes_shift2_s;
// instantiations
genvar l_inst;
generate
for (l_inst = 0; l_inst <= DW; l_inst = l_inst + 1) begin: g_data
if (SERDES_OR_DDR_N == 0) begin
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC"))
i_oddr (
.S (1'b0),
.CE (1'b1),
.R (rst),
.C (clk),
.D1 (data_s0[l_inst]),
.D2 (data_s1[l_inst]),
.Q (data_out_s[l_inst]));
end
if ((SERDES_OR_DDR_N == 1) && (DEVICE_TYPE == DEVICE_7SERIES)) begin
OSERDESE2#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("MASTER"))
i_serdes (
.D1 (data_s0[l_inst]),
.D2 (data_s1[l_inst]),
.D3 (data_s2[l_inst]),
.D4 (data_s3[l_inst]),
.D5 (data_s4[l_inst]),
.D6 (data_s5[l_inst]),
.D7 (data_s6[l_inst]),
.D8 (data_s7[l_inst]),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (1'b1),
.CLK (clk),
.CLKdiv (div_clk),
.OQ (data_out_s[l_inst]),
.TQ (),
.OFB (),
.TFB (),
.TBYTEIN (1'b0),
.TBYTEOUT (),
.TCE (1'b0),
.RST (rst));
end
if ((SERDES_OR_DDR_N == 1) && (DEVICE_TYPE == DEVICE_6SERIES)) begin
OSERDESE1#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.INTERFACE_TYPE ("DEFAULT"),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("MASTER"))
i_serdes_m (
.D1 (data_s0[l_inst]),
.D2 (data_s1[l_inst]),
.D3 (data_s2[l_inst]),
.D4 (data_s3[l_inst]),
.D5 (data_s4[l_inst]),
.D6 (data_s5[l_inst]),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (serdes_shift1_s[l_inst]),
.SHIFTIN2 (serdes_shift2_s[l_inst]),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (1'b1),
.CLK (clk),
.CLKdiv (div_clk),
.CLKPERF (1'b0),
.CLKPERFDELAY (1'b0),
.WC (1'b0),
.ODV (1'b0),
.OQ (data_out_s[l_inst]),
.TQ (),
.OCBEXTEND (),
.OFB (),
.TFB (),
.TCE (1'b0),
.RST (rst));
OSERDESE1#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.INTERFACE_TYPE ("DEFAULT"),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("SLAVE"))
i_serdes_s (
.D1 (1'b0),
.D2 (1'b0),
.D3 (data_s6[l_inst]),
.D4 (data_s7[l_inst]),
.D5 (1'b0),
.D6 (1'b0),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (serdes_shift1_s[l_inst]),
.SHIFTOUT2 (serdes_shift2_s[l_inst]),
.OCE (1'b1),
.CLK (clk),
.CLKdiv (div_clk),
.CLKPERF (1'b0),
.CLKPERFDELAY (1'b0),
.WC (1'b0),
.ODV (1'b0),
.OQ (),
.TQ (),
.OCBEXTEND (),
.OFB (),
.TFB (),
.TCE (1'b0),
.RST (rst));
end
OBUFDS i_obuf (
.I (data_out_s[l_inst]),
.O (data_out_p[l_inst]),
.OB (data_out_n[l_inst]));
end
endgenerate
endmodule
//testbench
module ad_seriestest;
reg ose_rst;
reg mmcm_rst;
reg sys_clk;
wire div_clk;
wire clk;
reg [15:0] data_0;
reg [15:0] data_1;
reg [15:0] data_2;
reg [15:0] data_3;
reg [15:0] data_4;
reg [15:0] data_5;
reg [15:0] data_6;
reg [15:0] data_7;
wire [15:0] data_out_p;
wire [15:0] data_out_n;
ad_mmcm_drp i_mmcm(
// clocks
.clk(sys_clk),
.mmcm_rst(mmcm_rst),
.mmcm_clk_0(clk),
.mmcm_clk_1(div_clk)
);
ad_serdes_out i_serdes_1(
// reset and clocks
.rst(ose_rst),
.clk(clk),
.div_clk(div_clk),
// data interface
.data_s0(data_0),
.data_s1(data_1),
.data_s2(data_2),
.data_s3(data_3),
.data_s4(data_4),
.data_s5(data_5),
.data_s6(data_6),
.data_s7(data_7),
.data_out_p(data_out_p),
.data_out_n(data_out_n));
initial sys_clk=1'b1;
always #1 sys_clk=~sys_clk;
initial
begin
ose_rst=1'b1;
#200 ose_rst=1'b0;
end
initial
begin
mmcm_rst=1'b1;
#10 mmcm_rst=1'b0;
end
initial
begin
#220 data_0=16'd0;data_1=16'd1;data_2=16'd2;data_3=16'd3;data_4=16'd4;data_5=16'd5;data_6=16'd6;data_7=16'd7;
#6 data_0=16'd8;data_1=16'd9;data_2=16'd10;data_3=16'd11;data_4=16'd12;data_5=16'd13;data_6=16'd14;data_7=16'd15;
#6data_0=16'd16;data_1=16'd17;data_2=16'd18;data_3=16'd19;data_4=16'd20;data_5=16'd21;data_6=16'd22;data_7=16'd23;
#6 data_0=16'd0;data_1=16'd1;data_2=16'd2;data_3=16'd3;data_4=16'd4;data_5=16'd5;data_6=16'd6;data_7=16'd7;
#100 $finish;
end
endmodule
仿真结果
官方文档上的时序为当转换为8:1时,从CLK_div上升沿采样到第一个串行数据输出的latency为4个clk周期
找到问题的可以一起交流交流喔
//MMCM 产生时钟
`timescale 1ns/100ps
module ad_mmcm_drp (
// clocks
clk,
mmcm_rst,
mmcm_clk_0,
mmcm_clk_1
);
// parameters
parameterMMCM_CLKIN_PERIOD= 1.667;
parameterMMCM_CLKIN2_PERIOD= 1.667;
parameterMMCM_VCO_div= 6;
parameterMMCM_VCO_MUL = 12.000;
parameterMMCM_CLK0_div = 2.000;
parameterMMCM_CLK1_div = 6;
// clocks
inputclk;
inputmmcm_rst;
outputmmcm_clk_0;
outputmmcm_clk_1;
;
wirebufg_fb_clk_s;
wiremmcm_fb_clk_s;
wiremmcm_clk_0_s;
wiremmcm_clk_1_s;
wiremmcm_locked_s;
// instantiations
MMCME2_ADV #(
.BANDWIDTH ("OPTIMIZED"),
.CLKOUT4_CASCADE ("FALSE"),
.COMPENSATION ("ZHOLD"),
.STARTUP_WAIT ("FALSE"),
.divCLK_divIDE (MMCM_VCO_div),
.CLKFBOUT_MULT_F (MMCM_VCO_MUL),
.CLKFBOUT_PHASE (0.000),
.CLKFBOUT_USE_FINE_PS ("FALSE"),
.CLKOUT0_divIDE_F (MMCM_CLK0_div),
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT0_USE_FINE_PS ("FALSE"),
.CLKOUT1_divIDE (MMCM_CLK1_div),
.CLKOUT1_PHASE (0.000),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT1_USE_FINE_PS ("FALSE"),
.CLKIN1_PERIOD (MMCM_CLKIN_PERIOD),
.CLKIN2_PERIOD (MMCM_CLKIN2_PERIOD),
.REF_JITTER1 (0.010))
i_mmcm (
.CLKIN1 (clk),
.CLKFBIN (bufg_fb_clk_s),
.CLKFBOUT (mmcm_fb_clk_s),
.CLKOUT0 (mmcm_clk_0_s),
.CLKOUT1 (mmcm_clk_1_s),
.LOCKED (mmcm_locked_s),
.DCLK (),
.DEN (1'b0),
.DADDR (7'd0),
.DWE (1'b0),
.DI (16'd0),
.DO (),
.DRDY (),
.CLKFBOUTB (),
.CLKOUT0B (),
.CLKOUT1B (),
.CLKOUT2 (),
.CLKOUT2B (),
.CLKOUT3 (),
.CLKOUT3B (),
.CLKOUT4 (),
.CLKOUT5 (),
.CLKOUT6 (),
.CLKIN2 (),
.CLKINSEL (1'b1),
.PSCLK (1'b0),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSDONE (),
.CLKINSTOPPED (),
.CLKFBSTOPPED (),
.PWRDWN (1'b0),
.RST (mmcm_rst));
BUFG i_fb_clk_bufg(.I (mmcm_fb_clk_s),.O (bufg_fb_clk_s));
BUFG i_clk_0_bufg(.I (mmcm_clk_0_s),.O (mmcm_clk_0));
BUFG i_clk_1_bufg(.I (mmcm_clk_1_s),.O (mmcm_clk_1));
endmodule
//并串转换模块
`timescale 1ps/1ps
module ad_serdes_out (
// reset and clocks
rst,
clk,
div_clk,
// data interface
data_s0,
data_s1,
data_s2,
data_s3,
data_s4,
data_s5,
data_s6,
data_s7,
data_out_p,
data_out_n);
// parameters
parameterDEVICE_TYPE = 0;
parameterSERDES_OR_DDR_N = 1;
parameterDATA_WIDTH = 16;
localparamDEVICE_6SERIES = 1;
localparamDEVICE_7SERIES = 0;
localparamDW = DATA_WIDTH - 1;
// reset and clocks
inputrst;
inputclk;
inputdiv_clk;
// data interface
input[DW:0]data_s0;
input[DW:0]data_s1;
input[DW:0]data_s2;
input[DW:0]data_s3;
input[DW:0]data_s4;
input[DW:0]data_s5;
input[DW:0]data_s6;
input[DW:0]data_s7;
output[DW:0]data_out_p;
output[DW:0]data_out_n;
// internal signals
wire[DW:0]data_out_s;
wire[DW:0]serdes_shift1_s;
wire[DW:0]serdes_shift2_s;
// instantiations
genvar l_inst;
generate
for (l_inst = 0; l_inst <= DW; l_inst = l_inst + 1) begin: g_data
if (SERDES_OR_DDR_N == 0) begin
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC"))
i_oddr (
.S (1'b0),
.CE (1'b1),
.R (rst),
.C (clk),
.D1 (data_s0[l_inst]),
.D2 (data_s1[l_inst]),
.Q (data_out_s[l_inst]));
end
if ((SERDES_OR_DDR_N == 1) && (DEVICE_TYPE == DEVICE_7SERIES)) begin
OSERDESE2#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("MASTER"))
i_serdes (
.D1 (data_s0[l_inst]),
.D2 (data_s1[l_inst]),
.D3 (data_s2[l_inst]),
.D4 (data_s3[l_inst]),
.D5 (data_s4[l_inst]),
.D6 (data_s5[l_inst]),
.D7 (data_s6[l_inst]),
.D8 (data_s7[l_inst]),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (1'b1),
.CLK (clk),
.CLKdiv (div_clk),
.OQ (data_out_s[l_inst]),
.TQ (),
.OFB (),
.TFB (),
.TBYTEIN (1'b0),
.TBYTEOUT (),
.TCE (1'b0),
.RST (rst));
end
if ((SERDES_OR_DDR_N == 1) && (DEVICE_TYPE == DEVICE_6SERIES)) begin
OSERDESE1#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.INTERFACE_TYPE ("DEFAULT"),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("MASTER"))
i_serdes_m (
.D1 (data_s0[l_inst]),
.D2 (data_s1[l_inst]),
.D3 (data_s2[l_inst]),
.D4 (data_s3[l_inst]),
.D5 (data_s4[l_inst]),
.D6 (data_s5[l_inst]),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (serdes_shift1_s[l_inst]),
.SHIFTIN2 (serdes_shift2_s[l_inst]),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (1'b1),
.CLK (clk),
.CLKdiv (div_clk),
.CLKPERF (1'b0),
.CLKPERFDELAY (1'b0),
.WC (1'b0),
.ODV (1'b0),
.OQ (data_out_s[l_inst]),
.TQ (),
.OCBEXTEND (),
.OFB (),
.TFB (),
.TCE (1'b0),
.RST (rst));
OSERDESE1#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.INTERFACE_TYPE ("DEFAULT"),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("SLAVE"))
i_serdes_s (
.D1 (1'b0),
.D2 (1'b0),
.D3 (data_s6[l_inst]),
.D4 (data_s7[l_inst]),
.D5 (1'b0),
.D6 (1'b0),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (serdes_shift1_s[l_inst]),
.SHIFTOUT2 (serdes_shift2_s[l_inst]),
.OCE (1'b1),
.CLK (clk),
.CLKdiv (div_clk),
.CLKPERF (1'b0),
.CLKPERFDELAY (1'b0),
.WC (1'b0),
.ODV (1'b0),
.OQ (),
.TQ (),
.OCBEXTEND (),
.OFB (),
.TFB (),
.TCE (1'b0),
.RST (rst));
end
OBUFDS i_obuf (
.I (data_out_s[l_inst]),
.O (data_out_p[l_inst]),
.OB (data_out_n[l_inst]));
end
endgenerate
endmodule
//testbench
module ad_seriestest;
reg ose_rst;
reg mmcm_rst;
reg sys_clk;
wire div_clk;
wire clk;
reg [15:0] data_0;
reg [15:0] data_1;
reg [15:0] data_2;
reg [15:0] data_3;
reg [15:0] data_4;
reg [15:0] data_5;
reg [15:0] data_6;
reg [15:0] data_7;
wire [15:0] data_out_p;
wire [15:0] data_out_n;
ad_mmcm_drp i_mmcm(
// clocks
.clk(sys_clk),
.mmcm_rst(mmcm_rst),
.mmcm_clk_0(clk),
.mmcm_clk_1(div_clk)
);
ad_serdes_out i_serdes_1(
// reset and clocks
.rst(ose_rst),
.clk(clk),
.div_clk(div_clk),
// data interface
.data_s0(data_0),
.data_s1(data_1),
.data_s2(data_2),
.data_s3(data_3),
.data_s4(data_4),
.data_s5(data_5),
.data_s6(data_6),
.data_s7(data_7),
.data_out_p(data_out_p),
.data_out_n(data_out_n));
initial sys_clk=1'b1;
always #1 sys_clk=~sys_clk;
initial
begin
ose_rst=1'b1;
#200 ose_rst=1'b0;
end
initial
begin
mmcm_rst=1'b1;
#10 mmcm_rst=1'b0;
end
initial
begin
#220 data_0=16'd0;data_1=16'd1;data_2=16'd2;data_3=16'd3;data_4=16'd4;data_5=16'd5;data_6=16'd6;data_7=16'd7;
#6 data_0=16'd8;data_1=16'd9;data_2=16'd10;data_3=16'd11;data_4=16'd12;data_5=16'd13;data_6=16'd14;data_7=16'd15;
#6data_0=16'd16;data_1=16'd17;data_2=16'd18;data_3=16'd19;data_4=16'd20;data_5=16'd21;data_6=16'd22;data_7=16'd23;
#6 data_0=16'd0;data_1=16'd1;data_2=16'd2;data_3=16'd3;data_4=16'd4;data_5=16'd5;data_6=16'd6;data_7=16'd7;
#100 $finish;
end
endmodule
仿真结果
官方文档上的时序为当转换为8:1时,从CLK_div上升沿采样到第一个串行数据输出的latency为4个clk周期
找到问题的可以一起交流交流喔
你是说数据输出Latency和文档不符吗?
如果是这样,不符那就对了,以仿真为准。