|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
最近做项目需要用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
parameter MMCM_CLKIN_PERIOD = 1.667;
parameter MMCM_CLKIN2_PERIOD = 1.667;
parameter MMCM_VCO_DIV = 6;
parameter MMCM_VCO_MUL = 12.000;
parameter MMCM_CLK0_DIV = 2.000;
parameter MMCM_CLK1_DIV = 6;
// clocks
input clk;
input mmcm_rst;
output mmcm_clk_0;
output mmcm_clk_1;
;
wire bufg_fb_clk_s;
wire mmcm_fb_clk_s;
wire mmcm_clk_0_s;
wire mmcm_clk_1_s;
wire mmcm_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
parameter DEVICE_TYPE = 0;
parameter SERDES_OR_DDR_N = 1;
parameter DATA_WIDTH = 16;
localparam DEVICE_6SERIES = 1;
localparam DEVICE_7SERIES = 0;
localparam DW = DATA_WIDTH - 1;
// reset and clocks
input rst;
input clk;
input div_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;
#6 data_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周期
找到问题的可以一起交流交流喔 |
|