Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / xpcs_rxio_ebuffer.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: xpcs_rxio_ebuffer.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: XPCS Physical Interface Core
// Block: 10G Ethernet Physical Interface Controller
// Author: Carlos Castil
//
// Module: xpcs_rxio_ebuffer
// File: xpcs_rxio_ebuffer.v
//
// Description:
// This block contains an elastic buffer and deskew controller
// for ieee 802.3ae xpcs clock tolerance compensation.
//
// Revision History
// ------------------------------------------------------------
// Ver Date Comments
// ------------------------------------------------------------
// 1.0 10/9/02 Created
//
// ****************************************************************
module xpcs_rxio_ebuffer (
rx_clk,
reset,
w_byte_0,
w_byte_1,
w_byte_2,
w_byte_3,
w_special_0,
w_special_1,
w_special_2,
w_special_3,
w_error_0,
w_error_1,
w_error_2,
w_error_3,
flush,
w_hold_0,
w_hold_1,
w_hold_2,
w_hold_3,
csr_link_status,
sync_status,
csr_pulse_deskew_error,
csr_ebuffer_state,
r_byte_0,
r_byte_1,
r_byte_2,
r_byte_3,
r_special_0,
r_special_1,
r_special_2,
r_special_3,
r_error_0,
r_error_1,
r_error_2,
r_error_3 );
input rx_clk;
input reset;
input sync_status;
input [7:0] w_byte_0;
input [7:0] w_byte_1;
input [7:0] w_byte_2;
input [7:0] w_byte_3;
input w_special_0;
input w_special_1;
input w_special_2;
input w_special_3;
input w_error_0;
input w_error_1;
input w_error_2;
input w_error_3;
output flush;
output w_hold_0;
output w_hold_1;
output w_hold_2;
output w_hold_3;
output csr_link_status;
output [7:0] csr_ebuffer_state;
output csr_pulse_deskew_error;
output [7:0] r_byte_0;
output [7:0] r_byte_1;
output [7:0] r_byte_2;
output [7:0] r_byte_3;
output r_special_0;
output r_special_1;
output r_special_2;
output r_special_3;
output r_error_0;
output r_error_1;
output r_error_2;
output r_error_3;
// Write Clock Domain Wires And Regs Which Are Not Flops
wire hold_en;
// State Machine control signals
reg [2:0] flush_cnt;
reg [2:0] deskew_cnt;
reg deskew_ack;
reg deskew_req;
wire deskew_done;
wire deskew_init;
wire dec_flush_cnt;
reg flush_int;
reg flush_reg;
reg deskew_ack_hold;
reg deskew_req_hold;
reg det_alg;
reg deskewing_reg;
wire deskewing;
wire deskew_on_pulse;
wire deskew_off_pulse;
wire det_alg_x4;
wire det_alg_lane0;
wire det_alg_lane1;
wire det_alg_lane2;
wire det_alg_lane3;
reg [9:0] w_s_in_0;
reg [9:0] w_s_in_1;
reg [9:0] w_s_in_2;
reg [9:0] w_s_in_3;
// ************************************************************************
// Align character detect logic
// ************************************************************************
// Register inputs from the deskew fifo
always @ (posedge rx_clk)
begin
w_s_in_0[9:0] <= {w_error_0, w_special_0, w_byte_0[7:0]};
w_s_in_1[9:0] <= {w_error_1, w_special_1, w_byte_1[7:0]};
w_s_in_2[9:0] <= {w_error_2, w_special_2, w_byte_2[7:0]};
w_s_in_3[9:0] <= {w_error_3, w_special_3, w_byte_3[7:0]};
end
assign det_alg_lane0 = ({w_error_0, w_special_0, w_byte_0[7:0]} == `XPCS_DEC_ALG) ;
assign det_alg_lane1 = ({w_error_1, w_special_1, w_byte_1[7:0]} == `XPCS_DEC_ALG) ;
assign det_alg_lane2 = ({w_error_2, w_special_2, w_byte_2[7:0]} == `XPCS_DEC_ALG) ;
assign det_alg_lane3 = ({w_error_3, w_special_3, w_byte_3[7:0]} == `XPCS_DEC_ALG) ;
// deskewing starts after detection of any align character in any lane
always @ (posedge rx_clk)
det_alg <= (det_alg_lane0 | det_alg_lane1 | det_alg_lane2 | det_alg_lane3);
always @ (posedge rx_clk)
if (reset)
deskewing_reg <= 1'b0;
else
deskewing_reg <= deskew_off_pulse ? 1'b0 : deskew_on_pulse ? 1'b1 : deskewing;
assign deskew_off_pulse = (deskew_cnt[2:0] == 3'b000);
assign deskew_on_pulse = (flush_cnt[2:0] == 3'b000) &
(det_alg_lane0 | det_alg_lane1 | det_alg_lane2 | det_alg_lane3) & !det_alg;
assign deskewing = deskew_on_pulse | deskewing_reg;
// assign hold_en = (deskew_cnt[2:0] != 3'b000) & deskewing & !det_alg_x4 ;
// deskew_cnt <= flush_reg ? 3'b100 : hold_en ? (deskew_cnt - 3'b001) : 3'b000;
// *********************************************************************
// Deskew Logic
// *********************************************************************
assign det_alg_x4 = det_alg_lane0 &
det_alg_lane1 &
det_alg_lane2 &
det_alg_lane3;
// *********************************************************************
// Deskew fifo control logic
// *********************************************************************
// Assert hold if deskewing and alignment detected on at least one lane
assign w_hold_0 = (hold_en & det_alg_lane0);
assign w_hold_1 = (hold_en & det_alg_lane1);
assign w_hold_2 = (hold_en & det_alg_lane2);
assign w_hold_3 = (hold_en & det_alg_lane3);
// ----------------------------
// Elastic Buffer output wires
// ----------------------------
assign {r_error_0,r_special_0,r_byte_0[7:0]} = w_s_in_0[9:0];
assign {r_error_1,r_special_1,r_byte_1[7:0]} = w_s_in_1[9:0];
assign {r_error_2,r_special_2,r_byte_2[7:0]} = w_s_in_2[9:0];
assign {r_error_3,r_special_3,r_byte_3[7:0]} = w_s_in_3[9:0];
// *********************************
// Deskew init and Deskew done logic
// *********************************
// Generate deskew request
always @ (posedge rx_clk)
if (reset)
deskew_req <= 1'b0;
else
deskew_req <= deskew_init ? !deskew_req : deskew_req;
// Generate pulse to flush deskew fifos and reset deskew_cnt
always @ (posedge rx_clk)
if (reset)
deskew_req_hold <= 1'b0;
else
deskew_req_hold <= deskew_req;
assign flush = (deskew_req ^ deskew_req_hold);
// Generate flush_int used to create deskew_ack
always @ (posedge rx_clk)
if (reset)
begin
flush_reg <= 1'b0;
flush_int <= 1'b0;
end
else
begin
flush_reg <= flush;
flush_int <= flush_reg ? 1'b1 : (deskew_cnt[2:0]==3'b000) ? 1'b0 : flush_int ;
end
// Count from 6, 5, 4, 3, 2, 1, to 0.... 5 clock count to account for deskew of
// 5 X 6.4 ns = 32 ns deskew window
always @ (posedge rx_clk)
if (reset)
begin
deskew_cnt <= 3'b000;
end
else
begin
deskew_cnt <= flush_reg ? 3'b100 : hold_en ? (deskew_cnt - 3'b001) : deskew_cnt;
end
// Wait for flush to complete to enable hold....fifo must flush
always @ (posedge rx_clk)
if (reset)
begin
flush_cnt <= 3'b000;
end
else
begin
flush_cnt <= flush_reg ? 3'b100 : (dec_flush_cnt) ? (flush_cnt - 3'b001) : 3'b000;
end
assign dec_flush_cnt = (flush_cnt != 3'b000);
// hold if counter is not expired and commas have not been detected across all lanes
// Deskewing starts immidiately on detection of an align character.
assign hold_en = (deskew_cnt[2:0] != 3'b000) & deskewing & !det_alg_x4 ;
// Generate acknowledge signal for deskew process
always @ (posedge rx_clk)
if (reset)
deskew_ack <= 1'b0;
else
deskew_ack <= (flush_int & (deskew_cnt[2:0]==3'b000)) ? deskew_req : deskew_ack ;
// Generate deskew done strobe from edge of deskew_ack
always @ (posedge rx_clk)
if (reset)
deskew_ack_hold <= 1'b0;
else
deskew_ack_hold <= deskew_ack;
assign deskew_done = (deskew_ack_hold ^ deskew_ack);
// ******************************************************************
// Elastic Buffer state machine
// ******************************************************************
xpcs_rxio_ebuffer_sm xpcs_rxio_ebuffer_sm (
.reset(reset),
.rx_clk(rx_clk),
.csr_link_status(csr_link_status),
.csr_pulse_deskew_error(csr_pulse_deskew_error),
.sync_status(sync_status),
.state(csr_ebuffer_state),
.deskew_init(deskew_init),
.deskew_done(deskew_done),
.r_byte_0(r_byte_0),
.r_byte_1(r_byte_1),
.r_byte_2(r_byte_2),
.r_byte_3(r_byte_3),
.r_special_0(r_special_0),
.r_special_1(r_special_1),
.r_special_2(r_special_2),
.r_special_3(r_special_3),
.r_error_0(r_error_0),
.r_error_1(r_error_1),
.r_error_2(r_error_2),
.r_error_3(r_error_3) );
endmodule