// (C) 2001-2020 Intel Corporation. All rights reserved. // Your use of Intel Corporation's design tools, logic functions and other // software and tools, and its AMPP partner logic functions, and any output // files from any of the foregoing (including device programming or simulation // files), and any associated documentation or information are expressly subject // to the terms and conditions of the Intel Program License Subscription // Agreement, Intel FPGA IP License Agreement, or other applicable // license agreement, including, without limitation, that your use is for the // sole purpose of programming logic devices manufactured by Intel and sold by // Intel or its authorized distributors. Please refer to the applicable // agreement for further details. // ********************************************************************* // Description // // Example Design RX Phy Top-level module // // ********************************************************************* module rx_phy_top # ( parameter BITEC_DP_CARD_REV = 0, parameter RX_SYMBOLS_PER_CLOCK = 2, parameter RX_PIXELS_PER_CLOCK = 4, parameter RX_MAX_LANE_COUNT = 4 ) ( // RX Reference Clock input wire rx_cdr_refclk, output wire dp_rx_clk_cal, // RX Reference Reset input wire rx_cdr_resetn, // RX Link Rate (8bits) input wire [7:0] dp_rx_link_rate_8bits, // RX Transceiver Reconfiguration Interface (To Arbiter or Reconfig module) input wire rx_rcfg_mgmt_reset, input wire rx_rcfg_mgmt_clk, output wire rx_rcfg_en, output wire rx_rcfg_write, output wire rx_rcfg_read, output wire [12:0] rx_rcfg_address, output wire [31:0] rx_rcfg_writedata, input wire [31:0] rx_rcfg_readdata, input wire rx_rcfg_waitrequest, input wire [(RX_MAX_LANE_COUNT-1):0] rx_rcfg_cal_busy, // RX Transceiver Interface output wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_clkout, input wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_serial_data, output wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_ready, // To Transceiver Reconfiguration Arbiter input wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_rcfg_write, input wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_rcfg_read, input wire [((RX_MAX_LANE_COUNT*11)-1):0] gxb_rx_rcfg_address, input wire [((RX_MAX_LANE_COUNT*32)-1):0] gxb_rx_rcfg_writedata, output wire [((RX_MAX_LANE_COUNT*32)-1):0] gxb_rx_rcfg_readdata, output wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_rcfg_waitrequest, output wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_rcfg_cal_busy, // To DP RX Core Sub-System input wire dp_rx_restart, input wire dp_rx_rcfg_req, output wire dp_rx_rcfg_ack, output wire dp_rx_rcfg_busy, input wire dp_rx_analog_rcfg_req, input wire [(RX_MAX_LANE_COUNT*2-1):0] dp_rx_analog_rcfg_vod, input wire [(RX_MAX_LANE_COUNT*2-1):0] dp_rx_analog_rcfg_emp, output wire [((RX_MAX_LANE_COUNT*RX_SYMBOLS_PER_CLOCK*10)-1):0] dp_rx_parallel_data, output wire [(RX_MAX_LANE_COUNT-1):0] dp_rx_is_lockedtoref, output wire [(RX_MAX_LANE_COUNT-1):0] dp_rx_is_lockedtodata, input wire [(RX_MAX_LANE_COUNT-1):0] dp_rx_bitslip, output wire dp_rx_cal_busy, input wire [(RX_MAX_LANE_COUNT-1):0] dp_rx_set_locktoref, input wire [(RX_MAX_LANE_COUNT-1):0] dp_rx_set_locktodata, output wire dp_xcvr_precal_en ); // ---------------------- // Local Parameter // ---------------------- // ---------------------- // Signal Declaration // ---------------------- reg clk_cal; // RX XCVR reset wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_analogreset; wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_analogreset_ack; wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_digitalreset; wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_digitalreset_ack; wire [(RX_MAX_LANE_COUNT-1):0] gxb_rx_polinv; // RX Word Aligner reg [(RX_MAX_LANE_COUNT-1):0] rx_std_wa_patternalign; wire [(RX_MAX_LANE_COUNT-1):0] rx_std_wa_patternalign_nxt; wire [(RX_MAX_LANE_COUNT*RX_SYMBOLS_PER_CLOCK-1):0] rx_syncstatus; wire [(RX_MAX_LANE_COUNT*RX_SYMBOLS_PER_CLOCK-1):0] rx_patterndetect; // -------------------------- // Internal Generated Reset // -------------------------- assign dp_rx_clk_cal = clk_cal; // ---------------------------------- // Cal Clock must be half of rx_rcfg_mgmt_clk // ---------------------------------- always @(posedge rx_rcfg_mgmt_reset or posedge rx_rcfg_mgmt_clk) if (rx_rcfg_mgmt_reset) clk_cal <= 1'b0; else clk_cal <= ~clk_cal; // ---------------------- // Transceiver System // ---------------------- reg [2:0] rx_restart_d; wire rx_restart_sync = rx_restart_d[2]; always @ (posedge rx_rcfg_mgmt_clk) rx_restart_d <= {rx_restart_d[1:0],dp_rx_restart}; wire dp_rx_xcvr_reset; wire [(RX_MAX_LANE_COUNT-1):0] out_dp_rx_is_lockedtodata; gxb_rx_reset gxb_rx_reset_i ( .clock (rx_rcfg_mgmt_clk), .reset ((~rx_cdr_resetn) | dp_rx_xcvr_reset | rx_restart_sync), .rx_analogreset (gxb_rx_analogreset), .rx_analogreset_stat (gxb_rx_analogreset_ack), .rx_cal_busy ({RX_MAX_LANE_COUNT{dp_rx_cal_busy}}), .rx_digitalreset (gxb_rx_digitalreset), .rx_digitalreset_stat (gxb_rx_digitalreset_ack), .rx_is_lockedtodata (out_dp_rx_is_lockedtodata), .rx_ready (gxb_rx_ready) ); assign dp_rx_cal_busy = |rx_rcfg_cal_busy; // Transceiver Reconfiguration intel_reconfig_alt_s10 intel_reconfig_alt_s10_i ( .clk (rx_rcfg_mgmt_clk), .reset (rx_rcfg_mgmt_reset), .rx_analogreset_ack (&gxb_rx_analogreset_ack), .rx_link_rate (dp_rx_link_rate_8bits), .rx_link_rate_strobe (dp_rx_rcfg_req), .rx_xcvr_busy (dp_rx_rcfg_busy), .rx_xcvr_reset (dp_rx_xcvr_reset), .rx_vodemp_strobe (1'b0), .rx_vod (dp_rx_analog_rcfg_vod), .rx_emp (dp_rx_analog_rcfg_emp), .dp_xcvr_precal_en (dp_xcvr_precal_en), // TX Reconfig (Not Used) .tx_analogreset_ack (1'b0), .tx_link_rate (8'd0), .tx_vod (2'd0), .tx_emp (2'd0), .tx_link_rate_strobe (1'b0), .tx_vodemp_strobe (1'b0), .tx_mgmt_readdata (32'd0), .tx_mgmt_waitrequest (1'b0), .txpll_mgmt_readdata (32'd0), .txpll_mgmt_waitrequest (1'b0), .tx_xcvr_cal_busy (1'b0), .tx_pll_cal_busy (1'b0), .rx_mgmt_chnum (rx_rcfg_address[12:11]), .rx_mgmt_address (rx_rcfg_address[10:0]), .rx_mgmt_writedata (rx_rcfg_writedata), .rx_mgmt_readdata (rx_rcfg_readdata), .rx_mgmt_write (rx_rcfg_write), .rx_mgmt_read (rx_rcfg_read), .rx_mgmt_waitrequest (rx_rcfg_waitrequest), .rx_xcvr_cal_busy (dp_rx_cal_busy) ); defparam intel_reconfig_alt_s10_i.RX_LANES = RX_MAX_LANE_COUNT; defparam intel_reconfig_alt_s10_i.RX_RATES_NUM = 4; // Number of data rate supported. assign dp_rx_rcfg_ack = 1'b1; assign rx_rcfg_en = dp_rx_rcfg_busy; wire [(RX_MAX_LANE_COUNT-1):0] out_gxb_rx_clkout; wire [(RX_MAX_LANE_COUNT-1):0] out_dp_rx_is_lockedtoref; wire [((RX_MAX_LANE_COUNT*RX_SYMBOLS_PER_CLOCK*10)-1):0] out_dp_rx_parallel_data; wire [(RX_MAX_LANE_COUNT-1):0] in_dp_rx_set_locktodata; wire [(RX_MAX_LANE_COUNT-1):0] in_dp_rx_set_locktoref; wire [(RX_MAX_LANE_COUNT-1):0] in_dp_rx_bitslip; // Transceiver RX gxb_rx gxb_rx_i ( .rx_cdr_refclk0 (rx_cdr_refclk), .reconfig_clk ({RX_MAX_LANE_COUNT{rx_rcfg_mgmt_clk}}), .reconfig_reset ({RX_MAX_LANE_COUNT{rx_rcfg_mgmt_reset}}), .reconfig_write (gxb_rx_rcfg_write), .reconfig_read (gxb_rx_rcfg_read), .reconfig_address (gxb_rx_rcfg_address), .reconfig_writedata (gxb_rx_rcfg_writedata), .reconfig_readdata (gxb_rx_rcfg_readdata), .reconfig_waitrequest (gxb_rx_rcfg_waitrequest), .rx_cal_busy (gxb_rx_rcfg_cal_busy), .rx_serial_data (gxb_rx_serial_data), .rx_clkout (out_gxb_rx_clkout), .rx_analogreset (gxb_rx_analogreset), .rx_analogreset_stat (gxb_rx_analogreset_ack), .rx_digitalreset (gxb_rx_digitalreset), .rx_digitalreset_stat (gxb_rx_digitalreset_ack), .rx_set_locktodata (in_dp_rx_set_locktodata), .rx_set_locktoref (in_dp_rx_set_locktoref), .rx_coreclkin (gxb_rx_clkout), .rx_polinv (gxb_rx_polinv), .rx_is_lockedtodata (out_dp_rx_is_lockedtodata), .rx_is_lockedtoref (out_dp_rx_is_lockedtoref), .rx_parallel_data (out_dp_rx_parallel_data), .unused_rx_parallel_data (), // RX Transceiver Word Aligner interface .rx_std_wa_patternalign (rx_std_wa_patternalign), .rx_patterndetect (rx_patterndetect), .rx_syncstatus (rx_syncstatus) ); // ----------------------------------------------------------------------- // Transceiver RX Word Aligner controller // - Stratix 10 required rx_bitslip pulse asserted for at least 200ns. // It took at least 20-60 PCS clock cycles to complete 1 bit slipping. // This Design Example provide alternate solution by making used of // Transceiver Word Aligner feature to perform the word alignment during // DisplayPort Link Training. // --------------------------------------------------------------------- generate begin genvar i; for (i=0; i < RX_MAX_LANE_COUNT; i = i+1) begin:rx_wa wire rx_rcfg_mgmt_reset_sync, dp_rx_bitslip_sync, dp_rx_rcfg_req_sync; bitec_dp_reset_sync #(.ASYNC_RESET(1)) mgmt_reset_sync (.reset_in (rx_rcfg_mgmt_reset), .clk (gxb_rx_clkout[i]), .reset (rx_rcfg_mgmt_reset_sync)); bitec_dp_cdc #(.W (1)) rx_bitslip_cc (.in(in_dp_rx_bitslip[i]), .out(dp_rx_bitslip_sync), .in_clk(gxb_rx_clkout[0]), .out_clk(gxb_rx_clkout[i]), .in_reset(rx_rcfg_mgmt_reset), .out_reset(rx_rcfg_mgmt_reset_sync)); bitec_dp_cdc #(.W (1)) rx_req_cc (.in(dp_rx_rcfg_req), .out(dp_rx_rcfg_req_sync), .in_clk(rx_rcfg_mgmt_clk), .out_clk(gxb_rx_clkout[i]), .in_reset(rx_rcfg_mgmt_reset), .out_reset(rx_rcfg_mgmt_reset_sync)); assign rx_std_wa_patternalign_nxt[i] = (dp_rx_rcfg_req_sync | dp_rx_bitslip_sync) ? 1'b1 : ((&rx_syncstatus[i*RX_SYMBOLS_PER_CLOCK +: RX_SYMBOLS_PER_CLOCK]) ? 1'b0 : rx_std_wa_patternalign[i]); always @ (posedge gxb_rx_clkout[i] or posedge rx_rcfg_mgmt_reset_sync) if(rx_rcfg_mgmt_reset_sync) rx_std_wa_patternalign[i] <= 1'b0; else rx_std_wa_patternalign[i] <= rx_std_wa_patternalign_nxt[i]; end end endgenerate generate if(BITEC_DP_CARD_REV == 2) begin // Rev 11 // RX lane polarity, inverted assign gxb_rx_polinv = {RX_MAX_LANE_COUNT{1'b1}}; // RX lane order, reversed assign gxb_rx_clkout = (RX_MAX_LANE_COUNT == 1) ? { out_gxb_rx_clkout }: ((RX_MAX_LANE_COUNT == 2) ? {2{out_gxb_rx_clkout[1]}} : {4{out_gxb_rx_clkout[3]}}); assign dp_rx_is_lockedtodata = (RX_MAX_LANE_COUNT == 1) ? { out_dp_rx_is_lockedtodata }: ((RX_MAX_LANE_COUNT == 2) ? { out_dp_rx_is_lockedtodata[0], out_dp_rx_is_lockedtodata[1] }: { out_dp_rx_is_lockedtodata[0], out_dp_rx_is_lockedtodata[1], out_dp_rx_is_lockedtodata[2], out_dp_rx_is_lockedtodata[3] }) ; assign dp_rx_is_lockedtoref = (RX_MAX_LANE_COUNT == 1) ? { out_dp_rx_is_lockedtoref }: ((RX_MAX_LANE_COUNT == 2) ? { out_dp_rx_is_lockedtoref[0], out_dp_rx_is_lockedtoref[1] }: { out_dp_rx_is_lockedtoref[0], out_dp_rx_is_lockedtoref[1], out_dp_rx_is_lockedtoref[2], out_dp_rx_is_lockedtoref[3] }) ; assign dp_rx_parallel_data = (RX_MAX_LANE_COUNT == 1) ? { out_dp_rx_parallel_data[0 +:(RX_SYMBOLS_PER_CLOCK*10)] } : ((RX_MAX_LANE_COUNT == 2) ? { out_dp_rx_parallel_data[0 +:(RX_SYMBOLS_PER_CLOCK*10)],out_dp_rx_parallel_data[(1*RX_SYMBOLS_PER_CLOCK*10) +:(RX_SYMBOLS_PER_CLOCK*10)] } : { out_dp_rx_parallel_data[0 +:(RX_SYMBOLS_PER_CLOCK*10)],out_dp_rx_parallel_data[(1*RX_SYMBOLS_PER_CLOCK*10) +:(RX_SYMBOLS_PER_CLOCK*10)],out_dp_rx_parallel_data[(2*RX_SYMBOLS_PER_CLOCK*10) +:(RX_SYMBOLS_PER_CLOCK*10)],out_dp_rx_parallel_data[(3*RX_SYMBOLS_PER_CLOCK*10) +:(RX_SYMBOLS_PER_CLOCK*10)] }); assign in_dp_rx_bitslip = (RX_MAX_LANE_COUNT == 1) ? { dp_rx_bitslip }: ((RX_MAX_LANE_COUNT == 2) ? { dp_rx_bitslip[0], dp_rx_bitslip[1] }: { dp_rx_bitslip[0], dp_rx_bitslip[1], dp_rx_bitslip[2], dp_rx_bitslip[3] }) ; assign in_dp_rx_set_locktodata = (RX_MAX_LANE_COUNT == 1) ? { dp_rx_set_locktodata }: ((RX_MAX_LANE_COUNT == 2) ? { dp_rx_set_locktodata[0], dp_rx_set_locktodata[1] }: { dp_rx_set_locktodata[0], dp_rx_set_locktodata[1], dp_rx_set_locktodata[2], dp_rx_set_locktodata[3] }) ; assign in_dp_rx_set_locktoref = (RX_MAX_LANE_COUNT == 1) ? { dp_rx_set_locktoref }: ((RX_MAX_LANE_COUNT == 2) ? { dp_rx_set_locktoref[0], dp_rx_set_locktoref[1] }: { dp_rx_set_locktoref[0], dp_rx_set_locktoref[1], dp_rx_set_locktoref[2], dp_rx_set_locktoref[3] }) ; end else begin if(BITEC_DP_CARD_REV == 1) begin // Rev 9 or later, RX lane polarity, inverted assign gxb_rx_polinv = {RX_MAX_LANE_COUNT{1'b1}}; end else begin // Rev 4 - 8, RX lane polarity, not inverted assign gxb_rx_polinv = {RX_MAX_LANE_COUNT{1'b0}}; end // RX lane order, not reversed assign gxb_rx_clkout = out_gxb_rx_clkout ; assign dp_rx_is_lockedtodata = out_dp_rx_is_lockedtodata ; assign dp_rx_is_lockedtoref = out_dp_rx_is_lockedtoref ; assign dp_rx_parallel_data = out_dp_rx_parallel_data ; assign in_dp_rx_bitslip = dp_rx_bitslip ; assign in_dp_rx_set_locktodata = dp_rx_set_locktodata ; assign in_dp_rx_set_locktoref = dp_rx_set_locktoref ; end endgenerate endmodule