// (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. // File Name: altera_xcvr_reset_control.sv // // Description: // // A configurable reset controller intended to drive resets for HSSI transceiver PLLs and CHANNELS. // The reset controller makes use of individual reset counters to control reset timing for the various reset // outputs. // // Features: // - Optional TX,RX,PLL reset control. // - Optional synchronization of the reset input // - Optional hysteresis for the pll_locked status inputs // - Reset control per channel or shared. (E.g. separate rx_digitalreset control for each channel // or one control for all channels) // - Configurable reset timings // - Optional automatic or manual reset control mode // (For TX, tx_digitalreset can automatically be restarted on loss of pll_locked) // (For RX, rx_digitalreset can automatically be restarted on loss of rx_is_lockedtodata) `timescale 1ns / 1ns (* altera_attribute = "-name MERGE_TX_PLL_DRIVEN_BY_REGISTERS_WITH_SAME_CLEAR ON -to \"alt_xcvr_reset_counter:g_pll.counter_pll_powerdown|r_reset\" " *) //altera message_off 10036 module altera_xcvr_reset_control #( // General Options parameter CHANNELS = 1, // Number of CHANNELS parameter PLLS = 1, // Number of TX PLLs. For pll_powerdown and pll_locked parameter SYS_CLK_IN_MHZ = 250, // Clock frequency in MHz. Required for reset timers parameter SYNCHRONIZE_RESET = 1, // (0,1) Synchronize the reset input parameter REDUCED_SIM_TIME = 1, // (0,1) 1=Reduced reset timings for simulation // PLL options parameter TX_PLL_ENABLE = 0, // (0,1) Enable TX PLL reset parameter T_PLL_POWERDOWN = 1000, // pll_powerdown period in ns parameter SYNCHRONIZE_PLL_RESET = 0,// (0,1) Use synchronized reset input for PLL powerdown // !NOTE! Will prevent PLL merging across reset controllers // !NOTE! Requires SYNCHRONIZE_RESET == 1 // TX options parameter TX_ENABLE = 0, // (0,1) Enable TX resets parameter TX_PER_CHANNEL = 0, // (0,1) 1=separate TX reset per channel parameter T_TX_DIGITALRESET = 20, // tx_digitalreset period (after pll_powerdown) parameter T_PLL_LOCK_HYST = 0, // Amount of hysteresis to add to pll_locked status signal // RX options parameter RX_ENABLE = 0, // (0,1) Enable RX resets parameter RX_PER_CHANNEL = 0, // (0,1) 1=separate RX reset per channel parameter T_RX_ANALOGRESET = 40, // rx_analogreset period parameter T_RX_DIGITALRESET = 4000, // rx_digitalreset period (after rx_is_lockedtodata) // CAL BUSY option parameter EN_PLL_CAL_BUSY = 0 ) ( // User inputs and outputs input wire clock, // System clock input wire reset, // Asynchronous reset // Reset signals output wire [PLLS-1:0] pll_powerdown, // reset TX PLL (to PHY/PLL) output wire [CHANNELS-1:0] tx_analogreset, // reset TX PMA (to PHY) output wire [CHANNELS-1:0] tx_digitalreset, // reset TX PCS (to PHY) output wire [CHANNELS-1:0] rx_analogreset, // reset RX PMA (to PHY) output wire [CHANNELS-1:0] rx_digitalreset, // reset RX PCS (to PHY) // Status output output wire [CHANNELS-1:0] tx_ready, // TX is not in reset output wire [CHANNELS-1:0] rx_ready, // RX is not in reset // Digital reset override inputs (must by synchronous with clock) input wire [CHANNELS-1:0] tx_digitalreset_or, // reset request for tx_digitalreset input wire [CHANNELS-1:0] rx_digitalreset_or, // reset request for rx_digitalreset // TX control inputs input wire [PLLS-1:0] pll_locked, // TX PLL lock status (from PHY/PLL) input wire [pll_select_width(PLLS,TX_PER_CHANNEL,CHANNELS)-1:0] pll_select, // Select TX PLL locked signal input wire [CHANNELS-1:0] tx_cal_busy, // TX channel calibration status (from PHY/Reconfig) input wire [PLLS-1:0] pll_cal_busy, // TX PLL calibration status (from PLL) input wire [CHANNELS-1:0] tx_manual, // 0 = Automatically restart tx_digitalreset // when pll_locked deasserts. // 1 = Do nothing when pll_locked deasserts // RX control inputs input wire [CHANNELS-1:0] rx_is_lockedtodata, // RX CDR PLL locked-to-data status (from PHY) input wire [CHANNELS-1:0] rx_cal_busy, // RX channel calibration status (from PHY/Reconfig) input wire [CHANNELS-1:0] rx_manual // 0 = Automatically restart rx_digitalreset // when rx_is_lockedtodata deasserts // 1 = Do nothing when rx_is_lockedtodata deasserts ); // Faster reset time for simulation if indicated localparam SYNTH_CLK_IN_HZ = SYS_CLK_IN_MHZ * 1000000; localparam SIM_CLK_IN_HZ = (REDUCED_SIM_TIME == 1) ? 2 * 1000000 : SYNTH_CLK_IN_HZ; `ifdef ALTERA_RESERVED_QIS localparam SYS_CLK_IN_HZ = SYNTH_CLK_IN_HZ; `else localparam SYS_CLK_IN_HZ = SIM_CLK_IN_HZ; `endif // Calculate delays wire reset_sync; // Synchronized reset input wire stat_pll_powerdown; // PLL powerdown status genvar ig; //************************************************************************** //************************ Synchronize Reset Input ************************* generate if(SYNCHRONIZE_RESET == 1) begin: g_reset_sync // Synchronize reset input alt_xcvr_resync #( .SYNC_CHAIN_LENGTH(2), // Number of flip-flops for retiming .WIDTH (1), // Number of bits to resync .INIT_VALUE (1'b1) ) alt_xcvr_resync_reset ( .clk (clock ), .reset (reset ), .d (1'b0 ), .q (reset_sync ) ); end else begin: g_no_reset_sync assign reset_sync = reset; end endgenerate //************************ Synchronize Reset Input ************************* //************************************************************************** //*************************************************************************** //*************************** TX PLL Reset Logic **************************** generate if(TX_PLL_ENABLE) begin: g_pll wire lcl_pll_powerdown; wire reset_pll; assign pll_powerdown = {PLLS{lcl_pll_powerdown}}; if(SYNCHRONIZE_PLL_RESET == 1) begin : g_sync_pll_reset assign reset_pll = reset_sync; end else begin : g_no_sync_pll_reset assign reset_pll = reset; end // pll_powerdown alt_xcvr_reset_counter #( .CLKS_PER_SEC (SYS_CLK_IN_HZ ), // Clock frequency in Hz .RESET_PER_NS (T_PLL_POWERDOWN ), // Reset period in ns .ACTIVE_LEVEL (0 ) ) counter_pll_powerdown ( .clk (clock ), .async_req (reset_pll ), // asynchronous reset request .sync_req (1'b0 ), // synchronous reset request .reset_or (1'b0 ), .reset (lcl_pll_powerdown ), // synchronous reset out .reset_n (/*unused*/ ), .reset_stat (stat_pll_powerdown ) ); end else begin : g_no_pll assign pll_powerdown = {PLLS{1'b0}}; assign stat_pll_powerdown = 1'b0; end endgenerate //************************* End TX PLL Reset Logic ************************** //*************************************************************************** //*************************************************************************** //***************************** TX Reset Logic ****************************** generate if(TX_ENABLE) begin: g_tx localparam PLL_SEL_WIDTH = altera_xcvr_functions::clogb2(PLLS-1); for (ig=0;ig 1) ? pll_select : 1'b0; // Tie tx_analogreset to pll_powerdown if used, otherwise tie to reset input (which may be synchronized) assign tx_analogreset[ig] = TX_PLL_ENABLE ? pll_powerdown[0] : reset_sync; // Synchonize TX inputs alt_xcvr_resync #( .SYNC_CHAIN_LENGTH(2), // Number of flip-flops for retiming .WIDTH (3), .INIT_VALUE (0) ) resync_tx_cal_busy ( .clk (clock ), .reset (reset_sync ), .d ({lcl_tx_cal_busy|lcl_pll_cal_busy ,lcl_tx_manual ,lcl_pll_locked }), .q ({tx_cal_busy_sync,tx_manual_sync,pll_locked_sync}) ); // Add hysteresis to pll_locked if needed // Reset counter works fine for hysteresis if(T_PLL_LOCK_HYST != 0) begin : g_pll_locked_hyst alt_xcvr_reset_counter #( .CLKS_PER_SEC (SYS_CLK_IN_HZ ), // Clock frequency in Hz .RESET_PER_NS (T_PLL_LOCK_HYST) // Reset period in ns ) counter_pll_locked_hyst ( .clk (clock ), .async_req (reset_sync ), // asynchronous reset request .sync_req (~pll_locked_sync ), // synchronous reset request .reset_or (1'b0 ), .reset (/*unused*/ ), // synchronous reset out .reset_n (pll_locked_hyst ), .reset_stat (/*unused*/ ) ); end else begin : g_no_pll_locked_hyst // No hysteresis added; use synchronized pll_locked directly. assign pll_locked_hyst = pll_locked_sync; end // Add one-shot latch to pll_locked for initial reset sequence always @(posedge clock or posedge reset_sync) if(reset_sync) pll_locked_latch <= 1'b0; else if(pll_locked_hyst & ~tx_cal_busy_sync) pll_locked_latch <= 1'b1; // tx_digitalreset // Assert tx_digitalreset while any of the following // 1 - pll_powerdown is asserted. // 2 - TX calibration is in progress // 3 - PLL has not reached initial lock (pll_locked_latch) // 4 - PLL is not locked AND TX reset is NOT under manual control // 5 - Reset override alt_xcvr_reset_counter #( .CLKS_PER_SEC (SYS_CLK_IN_HZ ), // Clock frequency in Hz .RESET_PER_NS (T_TX_DIGITALRESET ) // Reset period in ns ) counter_tx_digitalreset ( .clk (clock ), .async_req (reset_sync ), // asynchronous reset request .sync_req (stat_pll_powerdown | tx_cal_busy_sync | ~pll_locked_latch | (~pll_locked_hyst&~tx_manual_sync)), // synchronous reset request .reset_or (lcl_tx_digitalreset_or ), // auxilliary reset override .reset (tx_digitalreset[ig] ), // synchronous reset out .reset_n (/*unused*/ ), .reset_stat (stat_tx_digitalreset ) ); // tx_ready alt_xcvr_reset_counter #( .RESET_COUNT(3) ) counter_tx_ready ( .clk (clock ), .async_req (reset_sync ), // asynchronous reset request .sync_req (stat_tx_digitalreset ), // synchronous reset request .reset_or (1'b0 ), // auxilliary reset override .reset (/*unused*/ ), // synchronous reset out .reset_n (tx_ready [ig] ), .reset_stat (/*unused*/ ) // reset status ); end else begin : g_fanout_tx assign tx_analogreset [ig] = tx_analogreset [0]; assign tx_digitalreset [ig] = tx_digitalreset [0]; assign tx_ready [ig] = tx_ready [0]; end end end else begin : g_no_tx assign tx_analogreset = {CHANNELS{1'b0}}; assign tx_digitalreset = {CHANNELS{1'b0}}; assign tx_ready = {CHANNELS{1'b0}}; end endgenerate //*************************** End TX Reset Logic **************************** //*************************************************************************** //*************************************************************************** //***************************** RX Reset Logic ****************************** generate if (RX_ENABLE) begin : g_rx for (ig=0;ig