Xilinx IOserdes 原语使用 ---- 回环实验
下面RTL 代码,仅供参考,参考手册 :xilinx UG471
首先需要调节 bitslip 对齐,可以自己自定义序列接收检测,方可传输数据。
注意:
bitslip 必须在clkdiv 的一个周期下作用,等待两个周期后采样的Q4到Q1数据才有效,serdes 的复位至少需要两个时钟周期
`timescale 1ns / 1psmodule serdes(input i_clk_p,input i_clk_n// output o_data,// input i_data);wire clk_50MHZx1;
wire clk_400MHZx8;reg [15:0] r_rst_cnt;
reg r_rst_d0;
reg r_rst_d1;(*mark_debug = "true"*) reg [7:0] r_tx_data;(*mark_debug = "true"*) wire [7:0] r_rx_data;(*mark_debug = "true"*) reg [7:0] r_send_data;(*mark_debug = "true"*) reg r_sync_done;(*mark_debug = "true"*) reg r_sync_done_d;(*mark_debug = "true"*) reg [15:0] r_sync_cnt;(*mark_debug = "true"*) reg [4:0] r_bitslip_gap;(*mark_debug = "true"*) reg BITSLIP;wire RST;
wire vio;
wire a_50M;
wire a_400M;clk_wiz_0 clk_wiz_0_inst0(// Clock out ports.clk_out1(clk_50MHZx1), // output clk_out1.clk_out2(clk_400MHZx8), // output clk_out2.clk_out3(a_50M), // output clk_out3.clk_out4(a_400M), // output clk_out4// Status and control signals.locked(locked), // output locked// Clock in ports.clk_in1_p(i_clk_p), // input clk_in1_p.clk_in1_n(i_clk_n)); // input clk_in1_n
// INST_TAG_END ------ End INSTANTIATION Template ---------vio_0 your_instance_name (.clk(clk_50MHZx1), // input wire clk.probe_out0(vio) // output wire [0 : 0] probe_out0
);assign RST = r_rst_d1 || vio;always @ (posedge clk_50MHZx1 or negedge locked)beginif (!locked) beginr_rst_cnt <= 0;r_rst_d0 <= 0;r_rst_d1 <= 0;end else beginr_rst_cnt <= (r_rst_cnt == 1024)?r_rst_cnt:r_rst_cnt + 1;r_rst_d0 <= (r_rst_cnt < 1024)?1:0;r_rst_d1 <= r_rst_d0;end
end /*------------------------------------------*\iodelay
\*------------------------------------------*/// (* IODELAY_GROUP = <iodelay_group_name> *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL// IDELAYCTRL IDELAYCTRL_inst (// .RDY(RDY), // 1-bit output: Ready output// .REFCLK(REFCLK), // 1-bit input: Reference clock input// .RST(RST) // 1-bit input: Active high reset input// );// (* IODELAY_GROUP = <iodelay_group_name> *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL// IDELAYE2 #(// .CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE)// .DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN)// .HIGH_PERFORMANCE_MODE("FALSE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")// .IDELAY_TYPE("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE// .IDELAY_VALUE(0), // Input delay tap setting (0-31)// .PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE// .REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).// .SIGNAL_PATTERN("DATA") // DATA, CLOCK input signal// )// IDELAYE2_inst (// .CNTVALUEOUT(CNTVALUEOUT), // 5-bit output: Counter value output// .DATAOUT(DATAOUT), // 1-bit output: Delayed data output// .C(C), // 1-bit input: Clock input// .CE(CE), // 1-bit input: Active high enable increment/decrement input// .CINVCTRL(CINVCTRL), // 1-bit input: Dynamic clock inversion input// .CNTVALUEIN(CNTVALUEIN), // 5-bit input: Counter value input// .DATAIN(DATAIN), // 1-bit input: Internal delay data input// .IDATAIN(IDATAIN), // 1-bit input: Data input from the I/O// .INC(INC), // 1-bit input: Increment / Decrement tap delay input// .LD(LD), // 1-bit input: Load IDELAY_VALUE input// .LDPIPEEN(LDPIPEEN), // 1-bit input: Enable PIPELINE register to load data input// .REGRST(REGRST) // 1-bit input: Active-high reset tap-delay input// );/*------------------------------------------*\serdes
\*------------------------------------------*/ISERDESE2 #(.DATA_RATE("SDR"), // DDR, SDR.DATA_WIDTH(8), // Parallel data width (2-8,10,14).DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE).DYN_CLK_INV_EN("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1).INIT_Q1(1'b0),.INIT_Q2(1'b0),.INIT_Q3(1'b0),.INIT_Q4(1'b0),.INTERFACE_TYPE("NETWORKING"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE.IOBDELAY("NONE"), // NONE, BOTH, IBUF, IFD.NUM_CE(2), // Number of clock enables (1,2).OFB_USED("TRUE"), // Select OFB path (FALSE, TRUE).SERDES_MODE("MASTER"), // MASTER, SLAVE// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1).SRVAL_Q1(1'b0),.SRVAL_Q2(1'b0),.SRVAL_Q3(1'b0),.SRVAL_Q4(1'b0))ISERDESE2_inst (.O(), // 1-bit output: Combinatorial output// Q1 - Q8: 1-bit (each) output: Registered data outputs.Q1(r_rx_data[7]),.Q2(r_rx_data[6]),.Q3(r_rx_data[5]),.Q4(r_rx_data[4]),.Q5(r_rx_data[3]),.Q6(r_rx_data[2]),.Q7(r_rx_data[1]),.Q8(r_rx_data[0]),// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports.SHIFTOUT1(),.SHIFTOUT2(),.BITSLIP(BITSLIP), //å³ç§»ï¼Œæ¡¶åž‹ç§»ä½? // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1// to Q8 output ports will shift, as in a barrel-shifter operation, one// position every time Bitslip is invoked (DDR operation is different from// SDR).// CE1, CE2: 1-bit (each) input: Data register clock enable inputs.CE1(1),.CE2(1),.CLKDIVP(0), // 1-bit input: TBD// Clocks: 1-bit (each) input: ISERDESE2 clock input ports.CLK(a_400M), // 1-bit input: High-speed clock.CLKB(~a_400M), // 1-bit input: High-speed secondary clock.CLKDIV(a_50M), // 1-bit input: Divided clock.OCLK(0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY" // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity.DYNCLKDIVSEL(0), // 1-bit input: Dynamic CLKDIV inversion.DYNCLKSEL(0), // 1-bit input: Dynamic CLK/CLKB inversion// Input Data: 1-bit (each) input: ISERDESE2 data input ports.D(), // 1-bit input: Data input.DDLY(), // 1-bit input: Serial data from IDELAYE2.OFB(OFB), // 1-bit input: Data feedback from OSERDESE2.OCLKB(), // 1-bit input: High speed negative edge output clock.RST(RST), // 1-bit input: Active high asynchronous reset// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports.SHIFTIN1(),.SHIFTIN2());OSERDESE2 #(.DATA_RATE_OQ("SDR"), // DDR, SDR.DATA_RATE_TQ("SDR"), // DDR, BUF, SDR.DATA_WIDTH(8), // Parallel data width (2-8,10,14).INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1).INIT_TQ(1'b0), // Initial value of TQ output (1'b0,1'b1).SERDES_MODE("MASTER"), // MASTER, SLAVE.SRVAL_OQ(1'b0), // OQ output value when SR is used (1'b0,1'b1).SRVAL_TQ(1'b0), // TQ output value when SR is used (1'b0,1'b1).TBYTE_CTL("FALSE"), // Enable tristate byte operation (FALSE, TRUE).TBYTE_SRC("FALSE"), // Tristate byte source (FALSE, TRUE).TRISTATE_WIDTH(1) // 3-state converter width (1,4))OSERDESE2_inst (.OFB(OFB), // 1-bit output: Feedback path for data.OQ(), // 1-bit output: Data path output// SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each).SHIFTOUT1(),.SHIFTOUT2(),.TBYTEOUT(), // 1-bit output: Byte group tristate.TFB(), // 1-bit output: 3-state control.TQ(), // 1-bit output: 3-state control.CLK(a_400M), // 1-bit input: High speed clock.CLKDIV(a_50M), // 1-bit input: Divided clock// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1(r_tx_data[0]),.D2(r_tx_data[1]),.D3(r_tx_data[2]),.D4(r_tx_data[3]),.D5(r_tx_data[4]),.D6(r_tx_data[5]),.D7(r_tx_data[6]),.D8(r_tx_data[7]),.OCE(1), // 1-bit input: Output data clock enable.RST(RST), // 1-bit input: Reset// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each).SHIFTIN1(),.SHIFTIN2(),// T1 - T4: 1-bit (each) input: Parallel 3-state inputs.T1(0),.T2(0),.T3(0),.T4(0),.TBYTEIN(0), // 1-bit input: Byte group tristate.TCE(0) // 1-bit input: 3-state clock enable);always @ (posedge clk_50MHZx1)beginif (RST) beginr_send_data <= 0;end else if (!r_sync_done) beginr_send_data <= 0;end else if (r_sync_done) beginr_send_data <= r_send_data + 1; end else r_send_data <= r_send_data ;
end always @ (posedge clk_50MHZx1 )beginif (RST) beginr_tx_data <= 0;end else if (!r_sync_done) beginr_tx_data <= 8'hBC;end else if (r_sync_done) beginr_tx_data <= r_send_data; end else r_tx_data <= 0;
end always @ (posedge clk_50MHZx1) beginif (RST) beginr_sync_done_d <= 0;r_bitslip_gap <= 0;end else if ( !r_sync_done_d && r_rx_data == 8'hBC) beginr_sync_done_d <= 1;end else if (r_sync_cnt == 100) beginr_bitslip_gap <= 0;end else beginr_sync_done_d <= 0; r_bitslip_gap <= r_bitslip_gap + 1;
end
endalways @ (posedge clk_50MHZx1) beginif (RST)r_sync_cnt <= 0;else if (r_sync_cnt == 100)r_sync_cnt <= r_sync_cnt;else if (r_sync_done_d)r_sync_cnt <= r_sync_cnt + 1;else r_sync_cnt <= r_sync_cnt;
end always @ (posedge clk_50MHZx1) beginif (RST)r_sync_done <= 0;else if (r_sync_cnt == 100)r_sync_done <= 1;else r_sync_done <= r_sync_done;
end always @ (posedge clk_50MHZx1) beginif (RST)BITSLIP <= 0;else if (!r_sync_done_d && r_bitslip_gap == 31 && r_rx_data!= 8'hBC)BITSLIP <= 1;else BITSLIP <= 0;
end endmodule