// (C) 2001-2015 Altera Corporation. All rights reserved. // Your use of Altera Corporation's design tools, logic functions and other // software and tools, and its AMPP partner logic functions, and any output // files 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 Altera Program License Subscription // Agreement, Altera MegaCore Function License Agreement, or other applicable // license agreement, including, without limitation, that your use is for the // sole purpose of programming logic devices manufactured by Altera and sold by // Altera or its authorized distributors. Please refer to the applicable // agreement for further details. `timescale 1ps/1ps module av_xcvr_avmm_csr #( parameter pll_type = 0, // 0-None,1-CMU,2-LC/ATX,3-fPLL parameter rx_enable = 0, // Indicates whether this interface contains an rx channel. parameter tx_enable = 0, // Indicates whether this interface contains a tx channel // Service request parameters parameter request_dcd = 0, // Request Duty Cycle Distortion correction at startup parameter request_vrc = 0, // Request Voltage Regulator Calibration at startup parameter request_offset = 1 // Request RX Offset Cancellation at startup - defaults to enabled, only PCIE w/HIP should disable this request ) ( // Avalon interface input wire av_clk, input wire av_reset, input wire [15:0] av_writedata, input wire [ 3:0] av_address, input wire av_write, input wire av_read, output reg [15:0] av_readdata, // Offset Cancellation input wire hardoccaldone, output wire hardoccalen, // PRBS input wire pcs_8g_prbs_done, input wire pcs_8g_prbs_err, // DCD input wire dcd_ack, input wire [7:0] dcd_sum_a, input wire [7:0] dcd_sum_b, // SLPBK output wire seriallpbken, // Channel STATUS input wire stat_pll_locked, input wire stat_tx_digital_reset, input wire stat_rx_digital_reset, // Reset overrides output wire tx_rst_ovr, output wire tx_digital_rst_n_val, output wire rx_rst_ovr, output wire rx_digital_rst_n_val, output wire rx_analog_rst_n_val ); import av_xcvr_h::*; localparam [15:0] RD_UNUSED = 16'h0000; wire [3:0] loc_address; //******************* // Readback registers wire [15:0] rd_dummy; wire [15:0] rd_oc; wire [15:0] rd_prbs; wire [15:0] rd_slpbk; wire [15:0] rd_status; wire [15:0] rd_id; wire [15:0] rd_request; wire [15:0] rd_rstctl; //********************* // Avalon readback data assign loc_address = av_address[3:0]; always @(posedge av_clk) if(~av_read) av_readdata <= RD_UNUSED; else case(loc_address) AV_XR_ADDR_DUMMY: av_readdata <= rd_dummy; AV_XR_ADDR_OC: av_readdata <= rd_oc; AV_XR_ADDR_PRBS: av_readdata <= rd_prbs; AV_XR_ADDR_SLPBK: av_readdata <= rd_slpbk; AV_XR_ADDR_STATUS: av_readdata <= rd_status; AV_XR_ADDR_ID: av_readdata <= rd_id; AV_XR_ADDR_REQUEST: av_readdata <= rd_request; AV_XR_ADDR_RSTCTL: av_readdata <= rd_rstctl; default: av_readdata <= RD_UNUSED; endcase //*************** // DUMMY register reg r_dummy = 1'b0; // Readback data assign rd_dummy = {15'd0,r_dummy}; always @(posedge av_clk or posedge av_reset) if(av_reset) r_dummy <= 1'b0; else if(av_write & (loc_address == AV_XR_ADDR_DUMMY)) r_dummy <= av_writedata[AV_XR_DUMMY_DUMMY_OFST]; //************ // OC register generate if (rx_enable == 1) begin:gen_oc_reg reg r_hardoccalen = 1'b0; // Control outputs assign hardoccalen = r_hardoccalen; // Readback data assign rd_oc[AV_XR_OC_CALEN_OFST ] = r_hardoccalen; assign rd_oc[AV_XR_OC_CALDONE_OFST] = hardoccaldone; // TODO - meta assign rd_oc[AV_XR_OC_UNUSED_OFST +:AV_XR_OC_UNUSED_LEN] = {AV_XR_OC_UNUSED_LEN{1'b0}}; // Avalon registers always @(posedge av_clk or posedge av_reset) if(av_reset) begin r_hardoccalen <= 1'b0; end else if(av_write & (loc_address == AV_XR_ADDR_OC)) begin r_hardoccalen <= av_writedata[AV_XR_OC_CALEN_OFST]; end end else begin // Register unused assign hardoccalen = 1'b0; assign rd_oc = RD_UNUSED; end endgenerate //************** // PRBS register generate if (rx_enable == 1) begin:gen_prbs_reg reg r_prbs_err_clr = 1'b0; // Readback data assign rd_prbs[AV_XR_PRBS_CLR_OFST ] = r_prbs_err_clr; assign rd_prbs[AV_XR_PRBS_8G_ERR_OFST ] = pcs_8g_prbs_err; // TODO - meta assign rd_prbs[AV_XR_PRBS_8G_DONE_OFST ] = pcs_8g_prbs_done; // TODO - meta assign rd_prbs[AV_XR_PRBS_UNUSED_OFST +:AV_XR_PRBS_UNUSED_LEN ] = {AV_XR_PRBS_UNUSED_LEN{1'b0}}; // Avalon registers always @(posedge av_clk or posedge av_reset) if(av_reset) begin r_prbs_err_clr <= 1'b0; end else if(av_write & (loc_address == AV_XR_ADDR_PRBS)) begin r_prbs_err_clr <= av_writedata[AV_XR_PRBS_CLR_OFST]; end end else begin // Register unused assign rd_prbs = RD_UNUSED; end endgenerate //*************** // SLPBK register generate if (tx_enable == 1) begin:gen_slpbk_reg reg r_seriallpbken = 1'b0; // Control outputs assign seriallpbken = r_seriallpbken; // Readback data assign rd_slpbk[AV_XR_SLPBK_SLPBKEN_OFST] = r_seriallpbken; assign rd_slpbk[AV_XR_SLPBK_UNUSED_OFST +:AV_XR_SLPBK_UNUSED_LEN] = {AV_XR_SLPBK_UNUSED_LEN{1'b0}}; // Avalon registers always @(posedge av_clk or posedge av_reset) if(av_reset) begin r_seriallpbken <= 1'b0; end else if(av_write & (loc_address == AV_XR_ADDR_SLPBK)) begin r_seriallpbken <= av_writedata[AV_XR_SLPBK_SLPBKEN_OFST]; end end else begin // Register unused assign seriallpbken = 1'b0; assign rd_slpbk = RD_UNUSED; end endgenerate //**************** // STATUS register // Readback data // TX status generate if (tx_enable == 1) begin:gen_status_reg_tx wire stat_tx_digital_reset_r; // Resynchronize input signals alt_xcvr_resync #( .WIDTH(1) ) alt_xcvr_resync_inst ( .clk (av_clk), .reset (av_reset), .d (stat_tx_digital_reset), .q (stat_tx_digital_reset_r) ); assign rd_status[AV_XR_STATUS_TX_DIGITAL_RESET_OFST] = stat_tx_digital_reset_r; end else begin assign rd_status[AV_XR_STATUS_TX_DIGITAL_RESET_OFST] = 1'b0; end endgenerate // RX status generate if (rx_enable == 1) begin:gen_status_reg_rx wire stat_rx_digital_reset_r; // Resynchronize input signals alt_xcvr_resync #( .WIDTH(1) ) alt_xcvr_resync_inst ( .clk (av_clk), .reset (av_reset), .d (stat_rx_digital_reset), .q (stat_rx_digital_reset_r) ); assign rd_status[AV_XR_STATUS_RX_DIGITAL_RESET_OFST] = stat_rx_digital_reset_r; end else begin assign rd_status[AV_XR_STATUS_RX_DIGITAL_RESET_OFST] = 1'b0; end endgenerate // PLL status generate if (pll_type != AV_XR_ID_PLL_TYPE_NONE) begin:gen_status_reg_pll wire stat_pll_locked_r; reg r_pll_locked_flag; // Resynchronize input signals alt_xcvr_resync #( .WIDTH(1) ) alt_xcvr_resync_inst ( .clk (av_clk), .reset (av_reset), .d (stat_pll_locked), .q (stat_pll_locked_r) ); // pll_locked flag logic // Set by AVMM interface, cleared by pll_locked deassertion always @(posedge av_clk or posedge av_reset) begin if(av_reset) r_pll_locked_flag <= 1'b0; else if(av_write & (loc_address == AV_XR_ADDR_STATUS)) r_pll_locked_flag <= av_writedata[AV_XR_STATUS_PLL_LOCKED_FLAG_OFST]; else if(!stat_pll_locked_r) r_pll_locked_flag <= 1'b0; end assign rd_status[AV_XR_STATUS_PLL_LOCKED_OFST ] = stat_pll_locked_r; assign rd_status[AV_XR_STATUS_PLL_LOCKED_FLAG_OFST ] = r_pll_locked_flag; end else begin assign rd_status[AV_XR_STATUS_PLL_LOCKED_OFST ] = 1'b0; assign rd_status[AV_XR_STATUS_PLL_LOCKED_FLAG_OFST ] = 1'b0; end endgenerate assign rd_status[AV_XR_STATUS_UNUSED_OFST+:AV_XR_STATUS_UNUSED_LEN] = {AV_XR_STATUS_UNUSED_LEN{1'b0}}; //************ // ID register // Readback data assign rd_id[AV_XR_ID_TX_CHANNEL_OFST ] = (tx_enable == 1) ? 1'b1 : 1'b0; assign rd_id[AV_XR_ID_RX_CHANNEL_OFST ] = (rx_enable == 1) ? 1'b1 : 1'b0; assign rd_id[AV_XR_ID_PLL_TYPE_OFST+:AV_XR_ID_PLL_TYPE_LEN] = pll_type[1:0]; assign rd_id[AV_XR_ID_UNUSED_OFST+:AV_XR_ID_UNUSED_LEN] = {AV_XR_ID_UNUSED_LEN{1'b0}}; //************************** // REQUEST services register assign rd_request[AV_XR_REQUEST_DCD_OFST ] = (request_dcd == 0) ? 1'b0 : 1'b1; assign rd_request[AV_XR_REQUEST_VRC_OFST ] = (request_vrc == 0) ? 1'b0 : 1'b1; assign rd_request[AV_XR_REQUEST_OFFSET_OFST ] = (request_offset == 0) ? 1'b0 : 1'b1; assign rd_request[AV_XR_REQUEST_UNUSED_OFST+:AV_XR_REQUEST_UNUSED_LEN] = {AV_XR_REQUEST_UNUSED_LEN{1'b0}}; //************************ // RSTCTL register // User reset controls // Avalon registers for Tx digital reset generate if (tx_enable == 1) begin:gen_rstctl_reg_tx reg r_tx_rst_ovr = 1'b0; reg r_tx_digital_rst_n_val = 1'b0; always @(posedge av_clk or posedge av_reset) begin if(av_reset) begin r_tx_rst_ovr <= 1'b0; r_tx_digital_rst_n_val <= 1'b0; end else if(av_write & (loc_address == AV_XR_ADDR_RSTCTL)) begin r_tx_rst_ovr <= av_writedata[AV_XR_RSTCTL_TX_RST_OVR_OFST]; r_tx_digital_rst_n_val <= av_writedata[AV_XR_RSTCTL_TX_DIGITAL_RST_N_VAL_OFST]; end end assign tx_rst_ovr = r_tx_rst_ovr; assign tx_digital_rst_n_val = r_tx_digital_rst_n_val; end else begin assign tx_rst_ovr = 1'b0; assign tx_digital_rst_n_val = 1'b0; end endgenerate // Avalon registers for Rx digital and analog resets generate if (rx_enable == 1) begin:gen_rstctl_reg_rx reg r_rx_rst_ovr = 1'b0; reg r_rx_digital_rst_n_val = 1'b0; reg r_rx_analog_rst_n_val = 1'b0; always @(posedge av_clk or posedge av_reset) begin if(av_reset) begin r_rx_rst_ovr <= 1'b0; r_rx_digital_rst_n_val <= 1'b0; r_rx_analog_rst_n_val <= 1'b0; end else if(av_write & (loc_address == AV_XR_ADDR_RSTCTL)) begin r_rx_rst_ovr <= av_writedata[AV_XR_RSTCTL_RX_RST_OVR_OFST]; r_rx_digital_rst_n_val <= av_writedata[AV_XR_RSTCTL_RX_DIGITAL_RST_N_VAL_OFST]; r_rx_analog_rst_n_val <= av_writedata[AV_XR_RSTCTL_RX_ANALOG_RST_N_VAL_OFST]; end end assign rx_rst_ovr = r_rx_rst_ovr; assign rx_digital_rst_n_val = r_rx_digital_rst_n_val; assign rx_analog_rst_n_val = r_rx_analog_rst_n_val; end else begin assign rx_rst_ovr = 1'b0; assign rx_digital_rst_n_val = 1'b0; assign rx_analog_rst_n_val = 1'b0; end endgenerate assign rd_rstctl[AV_XR_RSTCTL_TX_RST_OVR_OFST ] = tx_rst_ovr; assign rd_rstctl[AV_XR_RSTCTL_TX_DIGITAL_RST_N_VAL_OFST] = tx_digital_rst_n_val; assign rd_rstctl[AV_XR_RSTCTL_RX_RST_OVR_OFST ] = rx_rst_ovr; assign rd_rstctl[AV_XR_RSTCTL_RX_DIGITAL_RST_N_VAL_OFST] = rx_digital_rst_n_val; assign rd_rstctl[AV_XR_RSTCTL_RX_ANALOG_RST_N_VAL_OFST ] = rx_analog_rst_n_val; assign rd_rstctl[AV_XR_RSTCTL_UNUSED_OFST+:AV_XR_RSTCTL_UNUSED_LEN] = {AV_XR_RSTCTL_UNUSED_LEN{1'b0}}; endmodule