1 |
2 |
tsahidanie |
//-----------------------------------------------------------------------------
|
2 |
|
|
// Title : {/A/,/A/} detection
|
3 |
|
|
// Project : SIP
|
4 |
|
|
//-----------------------------------------------------------------------------
|
5 |
|
|
// File : sip_rxaui_aa_detection.v
|
6 |
|
|
// Author : Lior Valency
|
7 |
|
|
// Created : 11/02/2008
|
8 |
|
|
// Last modified : 11/02/2008
|
9 |
|
|
//-----------------------------------------------------------------------------
|
10 |
|
|
// Description : The purpose of this block is to detect the {/A/,/A/} pattern
|
11 |
|
|
// and according to this pattern send the first /A/ to lane0 and the second /A/
|
12 |
|
|
// to lane1.
|
13 |
|
|
// It implement <ReceiveFlow> algorithm describe in chapter <2.2.2> in the SPEC.
|
14 |
|
|
//-----------------------------------------------------------------------------
|
15 |
|
|
// Copyright (c) 2007 Marvell International Ltd.
|
16 |
|
|
//
|
17 |
|
|
// THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL SEMICONDUCTOR, INC.
|
18 |
|
|
// NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT
|
19 |
|
|
// OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE
|
20 |
|
|
// DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.
|
21 |
|
|
// THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESS,
|
22 |
|
|
// IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.
|
23 |
|
|
//
|
24 |
|
|
//------------------------------------------------------------------------------
|
25 |
|
|
// Modification history :
|
26 |
|
|
// 12/12/2007 : created
|
27 |
|
|
//-----------------------------------------------------------------------------
|
28 |
|
|
`timescale 10ps / 10ps
|
29 |
|
|
|
30 |
|
|
module sip_rxaui_aa_detection(/*AUTOARG*/
|
31 |
|
|
// Outputs
|
32 |
|
|
lane0_rx, lane1_rx, rxaui_status,
|
33 |
|
|
// Inputs
|
34 |
|
|
clk, reset_, serdes_mode, rx_aligned_data, serdes_rx_data
|
35 |
|
|
);
|
36 |
|
|
|
37 |
|
|
`include "sip_rxaui_params.inc"
|
38 |
|
|
|
39 |
|
|
/*AUTO_CONSTANT(MSB_LANE0 or LSB_LANE0)*/
|
40 |
|
|
|
41 |
|
|
//////////////////////
|
42 |
|
|
// Local parameters //
|
43 |
|
|
//////////////////////
|
44 |
|
|
parameter DIS_POS_A = 10'b001100_0011; // 0xC3
|
45 |
|
|
parameter DIS_NEG_A = 10'b110011_1100; // 0x33C
|
46 |
|
|
parameter AA_ERR_CNT_W = 2;
|
47 |
|
|
parameter AA_ERR_CNT_INIT_VALUE = 2'd2;
|
48 |
|
|
parameter DATA_SHIFT_W = 2;
|
49 |
|
|
|
50 |
|
|
///////////////
|
51 |
|
|
// INTERFACE //
|
52 |
|
|
///////////////
|
53 |
|
|
|
54 |
|
|
// General
|
55 |
|
|
input clk;
|
56 |
|
|
input reset_;
|
57 |
|
|
|
58 |
|
|
// Configuration
|
59 |
|
|
input serdes_mode;
|
60 |
|
|
|
61 |
|
|
// Comma detect I/F
|
62 |
|
|
input [SERDES_DATA_W-1:0] rx_aligned_data;
|
63 |
|
|
|
64 |
|
|
// Fifo I/F
|
65 |
|
|
output [STD_DATA_W-1:0] lane0_rx;
|
66 |
|
|
output [STD_DATA_W-1:0] lane1_rx;
|
67 |
|
|
|
68 |
|
|
// Status
|
69 |
|
|
output [STATUS_REG_W-1:0] rxaui_status;
|
70 |
|
|
|
71 |
|
|
// Serdes Interface
|
72 |
|
|
input [SERDES_DATA_W-1:0] serdes_rx_data;
|
73 |
|
|
|
74 |
|
|
///////////////////////
|
75 |
|
|
// Registers & Wires //
|
76 |
|
|
///////////////////////
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
////////////////////////////////
|
80 |
|
|
// Internal Registers & Wires //
|
81 |
|
|
////////////////////////////////
|
82 |
|
|
reg [SERDES_DATA_W-1:0] rx_data_shift_reg[DATA_SHIFT_W-1:0];
|
83 |
|
|
reg [SERDES_DATA_W-1:0] rx_data_shift_reg_d[DATA_SHIFT_W-1:0];
|
84 |
|
|
wire [2:0] detect_aa;
|
85 |
|
|
wire any_aa_detect;
|
86 |
|
|
reg pre_aa_state;
|
87 |
|
|
wire aa_state_d;
|
88 |
|
|
reg aa_state;
|
89 |
|
|
wire [AA_ERR_CNT_W-1:0] aa_staet_err_counter_d;
|
90 |
|
|
reg [AA_ERR_CNT_W-1:0] aa_staet_err_counter;
|
91 |
|
|
wire aa_err_counter_eq_2;
|
92 |
|
|
wire [STATUS_REG_W-1:0] rxaui_status_d;
|
93 |
|
|
reg [STATUS_REG_W-1:0] rxaui_status;
|
94 |
|
|
|
95 |
|
|
integer i;
|
96 |
|
|
|
97 |
|
|
///////////
|
98 |
|
|
// Logic //
|
99 |
|
|
///////////
|
100 |
|
|
|
101 |
|
|
// Search for {/A/,/A/} pattern in one of the data.
|
102 |
|
|
// Option 1: (The pattern arrive in 1cc)
|
103 |
|
|
// rx_data_align : | AA | DD |
|
104 |
|
|
// rx_data_align_del1: | XX | AA |
|
105 |
|
|
// detect_aa: | 0 | 110|
|
106 |
|
|
// Option 2: (The pattern arrive in 2cc)
|
107 |
|
|
// rx_data_align : | AX | DA |
|
108 |
|
|
// rx_data_align_del1: | XX | AX |
|
109 |
|
|
// detect_aa: | 0 | 101|
|
110 |
|
|
assign detect_aa[2] = (rx_data_shift_reg[0][SERDES_DATA_W-1:SERDES_DATA_W/2] == DIS_POS_A) |
|
111 |
|
|
(rx_data_shift_reg[0][SERDES_DATA_W-1:SERDES_DATA_W/2] == DIS_NEG_A);
|
112 |
|
|
assign detect_aa[1] = (rx_data_shift_reg[0][SERDES_DATA_W/2-1:0] == DIS_POS_A) |
|
113 |
|
|
(rx_data_shift_reg[0][SERDES_DATA_W/2-1:0] == DIS_NEG_A);
|
114 |
|
|
assign detect_aa[0] = (rx_aligned_data[SERDES_DATA_W/2-1:0] == DIS_POS_A) |
|
115 |
|
|
(rx_aligned_data[SERDES_DATA_W/2-1:0] == DIS_NEG_A);
|
116 |
|
|
|
117 |
|
|
// Check if any {/A/,/A/} was detected
|
118 |
|
|
assign any_aa_detect = (detect_aa[0] & detect_aa[2]) | (detect_aa[2] & detect_aa[1]);
|
119 |
|
|
|
120 |
|
|
// Define the state of the transmission, LSB or MSB is to lane0.
|
121 |
|
|
always @(/*AUTOSENSE*/aa_state or detect_aa)
|
122 |
|
|
begin
|
123 |
|
|
pre_aa_state = aa_state;
|
124 |
|
|
case(detect_aa[2:0])
|
125 |
|
|
3'b110:
|
126 |
|
|
pre_aa_state = LSB_LANE0;
|
127 |
|
|
3'b101,3'b111:
|
128 |
|
|
pre_aa_state = MSB_LANE0;
|
129 |
|
|
default:
|
130 |
|
|
pre_aa_state = aa_state;
|
131 |
|
|
endcase // case(detect_aa)
|
132 |
|
|
end // always @ (...
|
133 |
|
|
|
134 |
|
|
// Check if the state of the {/A/,/A/) is change
|
135 |
|
|
assign aa_state_chg = (pre_aa_state != aa_state);
|
136 |
|
|
|
137 |
|
|
// Error Counter:
|
138 |
|
|
// Count the number of error from the current state
|
139 |
|
|
assign aa_staet_err_counter_d = (any_aa_detect == SET) ?
|
140 |
|
|
(((aa_state_chg == UNSET) ||
|
141 |
|
|
(aa_err_counter_eq_2 == SET)) ? {AA_ERR_CNT_W{1'b0}} :
|
142 |
|
|
(aa_staet_err_counter + 2'd1)) : aa_staet_err_counter;
|
143 |
|
|
|
144 |
|
|
// new aa state is latch only after 3 error are detect from the current state
|
145 |
|
|
assign aa_err_counter_eq_2 = (aa_staet_err_counter == 2'd2);
|
146 |
|
|
assign aa_state_d = ((aa_err_counter_eq_2 == SET) &&
|
147 |
|
|
(aa_state_chg == SET)) ? pre_aa_state : aa_state;
|
148 |
|
|
|
149 |
|
|
// Split the data to lane0 and lane1
|
150 |
|
|
// In case working in serdes mode (Data from Serdes = 10bits, Data from
|
151 |
|
|
// block 20bits), we need to use the fifo but not comma detect or AA
|
152 |
|
|
// detection
|
153 |
|
|
assign lane0_rx = (serdes_mode == SET) ? serdes_rx_data[SERDES_DATA_W/2-1:0] :
|
154 |
|
|
(aa_state == LSB_LANE0) ? rx_data_shift_reg[1][SERDES_DATA_W/2-1:0] :
|
155 |
|
|
rx_data_shift_reg[1][SERDES_DATA_W-1:SERDES_DATA_W/2];
|
156 |
|
|
assign lane1_rx = (serdes_mode == SET) ? serdes_rx_data[SERDES_DATA_W/2-1:0] :
|
157 |
|
|
(aa_state == MSB_LANE0) ? rx_data_shift_reg[1][SERDES_DATA_W/2-1:0] :
|
158 |
|
|
rx_data_shift_reg[1][SERDES_DATA_W-1:SERDES_DATA_W/2];
|
159 |
|
|
|
160 |
|
|
// Shift register implementation
|
161 |
|
|
always @(rx_data_shift_reg[0] or rx_data_shift_reg[1]/*AUTOSENSE*/
|
162 |
|
|
or rx_aligned_data) begin
|
163 |
|
|
for(i=0; i < DATA_SHIFT_W; i=i+1)
|
164 |
|
|
if (i==1'b0) begin
|
165 |
|
|
rx_data_shift_reg_d[i] = rx_aligned_data;
|
166 |
|
|
end
|
167 |
|
|
else begin
|
168 |
|
|
rx_data_shift_reg_d[i] = rx_data_shift_reg[i-1];
|
169 |
|
|
end
|
170 |
|
|
end
|
171 |
|
|
|
172 |
|
|
/////////////////////
|
173 |
|
|
// Status Register //
|
174 |
|
|
/////////////////////
|
175 |
|
|
|
176 |
|
|
assign rxaui_status_d = {
|
177 |
|
|
detect_aa[2:0], // 8:6
|
178 |
|
|
aa_state_chg, // 5
|
179 |
|
|
pre_aa_state, // 4
|
180 |
|
|
any_aa_detect, // 3
|
181 |
|
|
aa_state, // 2
|
182 |
|
|
aa_staet_err_counter[AA_ERR_CNT_W-1:0] // 1:0
|
183 |
|
|
};
|
184 |
|
|
|
185 |
|
|
|
186 |
|
|
////////////////
|
187 |
|
|
// FF SECTION //
|
188 |
|
|
////////////////
|
189 |
|
|
|
190 |
|
|
always @(posedge clk or negedge reset_)
|
191 |
|
|
begin
|
192 |
|
|
if(~reset_)
|
193 |
|
|
begin
|
194 |
|
|
for(i=0; i < DATA_SHIFT_W; i=i+1)
|
195 |
|
|
begin
|
196 |
|
|
rx_data_shift_reg[i] <= #1 {SERDES_DATA_W{1'b0}};
|
197 |
|
|
end
|
198 |
|
|
aa_state <= #1 LSB_LANE0;
|
199 |
|
|
rxaui_status <= #1 {STATUS_REG_W{1'b0}};
|
200 |
|
|
// The initial value of this is 3 after reset we are not
|
201 |
|
|
// sync with the correct lane0/lane1 and we want to sync
|
202 |
|
|
// after the first detection of {/A/,/A/}
|
203 |
|
|
aa_staet_err_counter <= #1 AA_ERR_CNT_INIT_VALUE;
|
204 |
|
|
end
|
205 |
|
|
else
|
206 |
|
|
begin
|
207 |
|
|
for(i=0; i < DATA_SHIFT_W; i=i+1)
|
208 |
|
|
begin
|
209 |
|
|
rx_data_shift_reg[i] <= #1 rx_data_shift_reg_d[i];
|
210 |
|
|
end
|
211 |
|
|
aa_state <= #1 aa_state_d;
|
212 |
|
|
aa_staet_err_counter <= #1 aa_staet_err_counter_d;
|
213 |
|
|
rxaui_status <= #1 rxaui_status_d;
|
214 |
|
|
end
|
215 |
|
|
end // always @ (posedge clk or negedge reset_)
|
216 |
|
|
|
217 |
|
|
endmodule // sip_rxaui_aa_detection
|