Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / xpcs_pio.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: xpcs_pio.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
// ****************************************************************
//
// Sun Proprietary/Confidential: Internal Use Only
//
// ****************************************************************
// Design: Vega
// Block: XPCS
// Author: Carlos Castil
//
// Module: xpcs_pio
// File: xpcs_pio.v
//
// Description: This block contains all xpcs reg csrs.
//
// Revision History
// ------------------------------------------------------------
// Ver Date Comments
// ------------------------------------------------------------
// 1.0 10/17/02 Created
//
// ****************************************************************
module xpcs_pio (
core_clk,
// reset signals
reset,
sw_reset,
clr_sw_reset,
hw_reset,
// PIO Interface to HT
sel_xpcs,
pio_rd,
pio_addr,
pio_wdata,
rdata_xpcs,
ack_xpcs,
pio_err_xpcs,
xpcs_interrupt,
csr_xpcs_enable,
csr_link_status,
csr_ebuffer_state,
csr_receive_state,
csr_bypass_signal_detect,
csr_lane_sync_status,
csr_loopback,
csr_low_power,
csr_vendor_debug_sel,
csr_vendor_debug_io_test,
training_vector,
inc_tx_pkt_count,
inc_rx_pkt_count,
inc_deskew_error,
csr_tx_state,
csr_trigger_transmit_fault,
csr_trigger_receive_fault,
csr_tx_test_enable,
csr_test_pattern_sel,
csr_enable_tx_buffers,
csr_lane_sync_state0,
csr_lane_sync_state1,
csr_lane_sync_state2,
csr_lane_sync_state3,
trigger_symbol_err_cnt0,
trigger_symbol_err_cnt1,
trigger_symbol_err_cnt2,
trigger_symbol_err_cnt3
);
input core_clk;
input reset;
input clr_sw_reset;
input hw_reset;
output sw_reset;
input csr_link_status;
input [3:0] csr_lane_sync_status;
input inc_deskew_error;
input [3:0] csr_lane_sync_state0;
input [3:0] csr_lane_sync_state1;
input [3:0] csr_lane_sync_state2;
input [3:0] csr_lane_sync_state3;
input trigger_symbol_err_cnt0;
input trigger_symbol_err_cnt1;
input trigger_symbol_err_cnt2;
input trigger_symbol_err_cnt3;
input [3:0] csr_tx_state;
input [7:0] csr_ebuffer_state;
input csr_receive_state;
input inc_tx_pkt_count;
input inc_rx_pkt_count;
input csr_trigger_transmit_fault;
input csr_trigger_receive_fault;
output xpcs_interrupt;
output csr_xpcs_enable;
output csr_loopback;
output csr_low_power;
output csr_bypass_signal_detect;
output csr_enable_tx_buffers;
output csr_tx_test_enable;
output [1:0] csr_test_pattern_sel;
output [3:0] csr_vendor_debug_sel;
output csr_vendor_debug_io_test;
output [31:0] training_vector;
// PIO Interface With MAC/HT
input sel_xpcs;
input pio_rd;
input [8:0] pio_addr;
input [31:0] pio_wdata;
output [31:0] rdata_xpcs;
output ack_xpcs;
output pio_err_xpcs;
reg [8:0] pio_addr_reg;
reg [31:0] pio_wdata_reg;
reg pio_rd_reg;
reg sel_xpcs_reg;
reg sel_xpcs_d;
reg write_pulse;
reg read_pulse;
reg csr_bypass_signal_detect;
reg csr_xpcs_enable;
reg [3:0] csr_vendor_debug_sel;
reg csr_vendor_debug_io_test;
reg [31:0] training_vector;
reg [8:0] addr;
reg [31:0] wr_data;
reg ack_xpcs;
reg [31:0] rdata_xpcs;
reg [15:0] csr_tx_pkt_count;
reg [15:0] csr_rx_pkt_count;
reg [7:0] deskew_error_count;
reg [31:0] rd_data;
reg csr_link_status_mask;
reg csr_enable_tx_buffers;
reg sw_reset;
reg csr_loopback;
reg csr_low_power;
reg csr_tx_test_enable;
reg [1:0] csr_test_pattern_sel;
reg csr_fault_mask;
reg pio_err_xpcs;
reg csr_fault;
reg csr_fault_d;
wire control1_wr_en;
wire test_control_wr_en;
wire conf_wr_en;
wire ld_training_vector;
wire mask1_wr_en;
wire pkt_counter_wr_en;
wire deskew_err_wr_en;
wire sel_pls;
wire csr_trigger_transmit_fault;
wire csr_trigger_receive_fault;
wire set_xpcs_interrupt;
reg xpcs_interrupt;
reg csr_link_status_d;
reg set_link_status_low;
reg link_status_latch_low;
reg clear_status1;
reg clear_status2;
reg csr_trigger_transmit_fault_d;
reg set_transmit_fault_high;
reg transmit_fault_latch_high;
reg csr_trigger_receive_fault_d;
reg set_receive_fault_high;
reg receive_fault_latch_high;
reg inc_rx_pkt_count_d;
reg inc_tx_pkt_count_d;
reg inc_deskew_error_d;
reg [15:0] symbol_err_cnt0;
wire clear_symbol_err_cnt0;
reg [15:0] symbol_err_cnt1;
wire clear_symbol_err_cnt1;
reg [15:0] symbol_err_cnt2;
wire clear_symbol_err_cnt2;
reg [15:0] symbol_err_cnt3;
wire clear_symbol_err_cnt3;
// **********************************
// PIO Control Logic
// **********************************
always @ (posedge core_clk)
begin
sel_xpcs_reg <= sel_xpcs;
sel_xpcs_d <= sel_xpcs_reg;
pio_rd_reg <= pio_rd;
pio_addr_reg <= pio_addr;
pio_wdata_reg <= pio_wdata;
end
// sel_pls is the select pulse
assign sel_pls = (sel_xpcs_reg & ~sel_xpcs_d);
// Generate PIO registered ack and read data
always @ (posedge core_clk)
begin
ack_xpcs <= (read_pulse | write_pulse);
rdata_xpcs <= rd_data;
pio_err_xpcs <= (read_pulse | write_pulse ) & (rd_data == 32'hBADCAFEE);
end
// Register write PIO data on sel_pls
always @ (posedge core_clk)
begin
read_pulse <= sel_pls & pio_rd_reg ;
write_pulse <= sel_pls & ~pio_rd_reg ;
addr <= pio_addr_reg;
wr_data <= pio_wdata_reg;
end
assign control1_wr_en = write_pulse & addr[8:0]==9'h000;
assign test_control_wr_en = write_pulse & addr[8:0]==9'h009;
assign conf_wr_en = write_pulse & addr[8:0]==9'h00a;
assign ld_training_vector = write_pulse & addr[8:0]==9'h012;
assign mask1_wr_en = write_pulse & addr[8:0]==9'h00c;
assign pkt_counter_wr_en = write_pulse & addr[8:0]==9'h00d;
assign deskew_err_wr_en = write_pulse & addr[8:0]==9'h00f;
// Read Mux
always @ (/*AUTOSENSE*/addr or csr_bypass_signal_detect
or csr_ebuffer_state or csr_enable_tx_buffers or csr_fault
or csr_fault_mask or csr_lane_sync_state0
or csr_lane_sync_state1 or csr_lane_sync_state2
or csr_lane_sync_state3 or csr_lane_sync_status
or csr_link_status or csr_link_status_mask or csr_loopback
or csr_low_power or csr_receive_state or csr_rx_pkt_count
or csr_test_pattern_sel or csr_tx_pkt_count or csr_tx_state
or csr_tx_test_enable or csr_vendor_debug_io_test
or csr_vendor_debug_sel or csr_xpcs_enable
or deskew_error_count or link_status_latch_low
or receive_fault_latch_high or sw_reset
or transmit_fault_latch_high or symbol_err_cnt0
or symbol_err_cnt1 or symbol_err_cnt2 or symbol_err_cnt3
or training_vector)
begin
case (addr[7:0]) // synopsys parallel_case full_case
// Port Info
8'h00 : rd_data = {16'h0000,sw_reset,csr_loopback,2'b10,csr_low_power,11'b00001000000}; // control1
8'h01 : rd_data = {24'h000000,csr_fault,4'b0000,link_status_latch_low,2'b00}; // status1
8'h02 : rd_data = {32'h00000000}; // device id
8'h03 : rd_data = {31'h00000000,1'b1}; // speed ability
8'h04 : rd_data = {4'hC,20'h00000,8'h08}; // devices in package
8'h05 : rd_data = {30'h00000000,2'b01}; // control2
8'h06 : rd_data = {20'h00000,transmit_fault_latch_high,receive_fault_latch_high,8'h00,2'b10}; // status2
8'h07 : rd_data = {32'h00000000}; // package id
8'h08 : rd_data = {19'h00000, csr_link_status, 8'h80, csr_lane_sync_status};
8'h09 : rd_data = {29'h00000000,csr_tx_test_enable,csr_test_pattern_sel}; // test control
8'h0A : rd_data = {24'h000000,csr_vendor_debug_io_test,
csr_vendor_debug_sel,
csr_bypass_signal_detect,
csr_enable_tx_buffers,
csr_xpcs_enable}; // configuration
8'h0B : rd_data = {7'h00, csr_lane_sync_state3, // 4 bits
csr_lane_sync_state2, // 4 bits
csr_lane_sync_state1, // 4 bits
csr_lane_sync_state0, // 4 bits
csr_ebuffer_state, // 8 bits
csr_receive_state}; // 1 bits rx diagnostic
8'h0C : rd_data = {24'h000000,csr_fault_mask,4'h0,csr_link_status_mask,2'b00}; // mask1
8'h0D : rd_data = {csr_tx_pkt_count,csr_rx_pkt_count}; // packet counter
8'h0E : rd_data = {28'h0000000, csr_tx_state}; // 4 bits tx diagnostic
8'h0F : rd_data = {24'h000000, deskew_error_count};
8'h10 : rd_data = {symbol_err_cnt1,symbol_err_cnt0};
8'h11 : rd_data = {symbol_err_cnt3,symbol_err_cnt2};
8'h12 : rd_data = training_vector[31:0];
default : rd_data = {32'hBADCAFEE};
endcase
end // always @ (...
always @ (posedge core_clk)
if (reset)
begin
csr_loopback <= 1'b0;
csr_low_power <= 1'b0;
end
else
begin
csr_loopback <= (control1_wr_en) ? wr_data[14] : csr_loopback;
csr_low_power <= (control1_wr_en) ? wr_data[11] : csr_low_power;
end
always @ (posedge core_clk)
if (hw_reset)
sw_reset <= 1'b0;
else
sw_reset <= (control1_wr_en) ? wr_data[15] : (clr_sw_reset) ? 1'b0 : sw_reset;
always @ (posedge core_clk)
if (reset)
begin
csr_tx_test_enable <= 1'b0;
csr_test_pattern_sel <= 2'b00;
end
else
begin
csr_tx_test_enable <= (test_control_wr_en) ? wr_data[2] : csr_tx_test_enable;
csr_test_pattern_sel <= (test_control_wr_en) ? wr_data[1:0] : csr_test_pattern_sel;
end
always @ (posedge core_clk)
if (reset)
begin
csr_vendor_debug_io_test <= 1'b0;
csr_vendor_debug_sel <= 4'h0;
csr_bypass_signal_detect <= 1'b0;
csr_enable_tx_buffers <= 1'b1;
csr_xpcs_enable <= 1'b1;
end
else
begin
csr_vendor_debug_io_test <= (conf_wr_en) ? wr_data[7] : csr_vendor_debug_io_test;
csr_vendor_debug_sel <= (conf_wr_en) ? wr_data[6:3] : csr_vendor_debug_sel;
csr_bypass_signal_detect <= (conf_wr_en) ? wr_data[2] : csr_bypass_signal_detect;
csr_enable_tx_buffers <= (conf_wr_en) ? wr_data[1] : csr_enable_tx_buffers;
csr_xpcs_enable <= (conf_wr_en) ? wr_data[0] : csr_xpcs_enable;
end
always @ (posedge core_clk)
if (reset)
begin
csr_fault_mask <= 1'b1;
csr_link_status_mask <= 1'b1;
end
else
begin
csr_fault_mask <= (mask1_wr_en) ? wr_data[7] : csr_fault_mask;
csr_link_status_mask <= (mask1_wr_en) ? wr_data[2] : csr_link_status_mask;
end
/****************************************************************************/
// Logic for packet counts
/****************************************************************************/
always @ (posedge core_clk)
if (reset)
begin
inc_tx_pkt_count_d <= 1'b0;
inc_rx_pkt_count_d <= 1'b0;
end
else
begin
inc_tx_pkt_count_d <= inc_tx_pkt_count;
inc_rx_pkt_count_d <= inc_rx_pkt_count;
end
always @ (posedge core_clk)
if (reset)
begin
csr_tx_pkt_count <= 16'b0;
csr_rx_pkt_count <= 16'b0;
end
else
begin
csr_tx_pkt_count <= (pkt_counter_wr_en) ? wr_data[31:16] :
(csr_link_status & inc_tx_pkt_count & !inc_tx_pkt_count_d) ? csr_tx_pkt_count + 16'h0001 :
csr_tx_pkt_count;
csr_rx_pkt_count <= (pkt_counter_wr_en) ? wr_data[15:0] :
(csr_link_status & inc_rx_pkt_count & !inc_rx_pkt_count_d) ? csr_rx_pkt_count + 16'h0001 :
csr_rx_pkt_count;
end
/****************************************************************************/
// Logic for deskew error count
/****************************************************************************/
always @ (posedge core_clk)
inc_deskew_error_d <= inc_deskew_error;
always @ (posedge core_clk)
if (reset)
deskew_error_count <= 8'b0;
else if (deskew_err_wr_en)
deskew_error_count <= wr_data[7:0];
else if (inc_deskew_error & !inc_deskew_error_d & (deskew_error_count != 8'hFF))
deskew_error_count <= deskew_error_count + 8'h01;
else
deskew_error_count <= deskew_error_count;
/****************************************************************************/
// Logic for transmit/receive fault status
/****************************************************************************/
always @ (posedge core_clk)
if (reset | !csr_xpcs_enable)
begin
csr_fault <= 1'b0;
csr_fault_d <= 1'b0;
end
else
begin
csr_fault <= transmit_fault_latch_high | receive_fault_latch_high;
csr_fault_d <= csr_fault;
end
// transmit fault
always @ (posedge core_clk)
if (reset)
csr_trigger_transmit_fault_d <= 1'b0;
else
csr_trigger_transmit_fault_d <= csr_trigger_transmit_fault;
always @ (posedge core_clk)
if (reset)
set_transmit_fault_high <= 1'b0;
else if (csr_trigger_transmit_fault & !csr_trigger_transmit_fault_d)
set_transmit_fault_high <= 1'b1;
else if (clear_status2)
set_transmit_fault_high <= 1'b0;
else
set_transmit_fault_high <= set_transmit_fault_high;
always @ (posedge core_clk)
if (reset)
transmit_fault_latch_high <= 1'b0;
else
transmit_fault_latch_high <= set_transmit_fault_high ? 1'b1 : csr_trigger_transmit_fault;
// receive fault
always @ (posedge core_clk)
if (reset)
csr_trigger_receive_fault_d <= 1'b0;
else
csr_trigger_receive_fault_d <= csr_trigger_receive_fault;
always @ (posedge core_clk)
if (reset)
set_receive_fault_high <= 1'b0;
else if (csr_trigger_receive_fault & !csr_trigger_receive_fault_d)
set_receive_fault_high <= 1'b1;
else if (clear_status2)
set_receive_fault_high <= 1'b0;
else
set_receive_fault_high <= set_receive_fault_high;
always @ (posedge core_clk)
if (reset)
receive_fault_latch_high <= 1'b0;
else
receive_fault_latch_high <= set_receive_fault_high ? 1'b1 : csr_trigger_receive_fault;
/****************************************************************************/
// Logic for link up/down status
/****************************************************************************/
always @ (posedge core_clk)
if (reset)
csr_link_status_d <= 1'b0;
else
csr_link_status_d <= csr_link_status;
always @ (posedge core_clk)
if (reset)
set_link_status_low <= 1'b0;
else if (!csr_link_status & csr_link_status_d)
set_link_status_low <= 1'b1;
else if (clear_status2)
set_link_status_low <= 1'b0;
else
set_link_status_low <= set_link_status_low;
always @ (posedge core_clk)
if (reset)
link_status_latch_low <= 1'b0;
else
link_status_latch_low <= set_link_status_low ? 1'b0 : csr_link_status;
// ************************************
// Interrupt logic
// ************************************
// Register interrupt
assign set_xpcs_interrupt = ((csr_link_status_d ^ csr_link_status) & (!csr_link_status_mask)) |
( (csr_fault & !csr_fault_d) & (!csr_fault_mask));
always @ (posedge core_clk)
if (reset)
xpcs_interrupt <= 1'b0;
else if (set_xpcs_interrupt)
xpcs_interrupt <= 1'b1;
else if (clear_status1)
xpcs_interrupt <= 1'b0;
else
xpcs_interrupt <= xpcs_interrupt;
// Clear on read signals
always @ (posedge core_clk)
if (reset)
clear_status1 <= 1'b0;
else
clear_status1 <= (read_pulse & addr[7:0]==8'h01);
always @ (posedge core_clk)
if (reset)
clear_status2 <= 1'b0;
else
clear_status2 <= (read_pulse & addr[7:0]==8'h06);
// ************************************
// Symbol error counters
// ************************************
assign clear_symbol_err_cnt0 = read_pulse & (addr == 9'h010);
always @ (posedge core_clk)
if (reset | clear_symbol_err_cnt0 )
symbol_err_cnt0 <= 16'h0000;
else if (trigger_symbol_err_cnt0 & (symbol_err_cnt0 != 16'hFFFF) & csr_xpcs_enable)
symbol_err_cnt0 <= symbol_err_cnt0 + 16'h0001;
else // else maintain error cnt
symbol_err_cnt0 <= symbol_err_cnt0;
assign clear_symbol_err_cnt1 = read_pulse & (addr == 9'h010);
always @ (posedge core_clk)
if (reset | clear_symbol_err_cnt1 )
symbol_err_cnt1 <= 16'h0000;
else if (trigger_symbol_err_cnt1 & (symbol_err_cnt1 != 16'hFFFF) & csr_xpcs_enable)
symbol_err_cnt1 <= symbol_err_cnt1 + 16'h0001;
else // else maintain error cnt
symbol_err_cnt1 <= symbol_err_cnt1;
assign clear_symbol_err_cnt2 = read_pulse & (addr == 9'h011);
always @ (posedge core_clk)
if (reset | clear_symbol_err_cnt2 )
symbol_err_cnt2 <= 16'h0000;
else if (trigger_symbol_err_cnt2 & (symbol_err_cnt2 != 16'hFFFF) & csr_xpcs_enable)
symbol_err_cnt2 <= symbol_err_cnt2 + 16'h0001;
else // else maintain error cnt
symbol_err_cnt2 <= symbol_err_cnt2;
assign clear_symbol_err_cnt3 = read_pulse & (addr == 9'h011);
always @ (posedge core_clk)
if (reset | clear_symbol_err_cnt3 )
symbol_err_cnt3 <= 16'h0000;
else if (trigger_symbol_err_cnt3 & (symbol_err_cnt3 != 16'hFFFF) & csr_xpcs_enable)
symbol_err_cnt3 <= symbol_err_cnt3 + 16'h0001;
else // else maintain error cnt
symbol_err_cnt3 <= symbol_err_cnt3;
// ************************************
// training vector
// ************************************
always @ (posedge core_clk)
begin
if (reset)
training_vector <= 0;
else if (ld_training_vector)
training_vector <= wr_data[31:0];
else if (csr_vendor_debug_sel[3:0] == `SEL_xpcs_training_vector)
training_vector <= ~training_vector;
else training_vector <= training_vector;
end
endmodule // xpcs_pio