//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// File name "fault_sm.v" ////
|
//// File name "fault_sm.v" ////
|
//// ////
|
//// ////
|
//// This file is part of the "10GE MAC" project ////
|
//// This file is part of the "10GE MAC" project ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
`include "defines.v"
|
`include "defines.v"
|
|
|
module fault_sm(/*AUTOARG*/
|
module fault_sm(/*AUTOARG*/
|
// Outputs
|
// Outputs
|
status_local_fault_crx, status_remote_fault_crx,
|
status_local_fault_crx, status_remote_fault_crx,
|
// Inputs
|
// Inputs
|
clk_xgmii_rx, reset_xgmii_rx_n, local_fault_msg_det,
|
clk_xgmii_rx, reset_xgmii_rx_n, local_fault_msg_det,
|
remote_fault_msg_det
|
remote_fault_msg_det
|
);
|
);
|
|
|
input clk_xgmii_rx;
|
input clk_xgmii_rx;
|
input reset_xgmii_rx_n;
|
input reset_xgmii_rx_n;
|
|
|
input [1:0] local_fault_msg_det;
|
input [1:0] local_fault_msg_det;
|
input [1:0] remote_fault_msg_det;
|
input [1:0] remote_fault_msg_det;
|
|
|
output status_local_fault_crx;
|
output status_local_fault_crx;
|
output status_remote_fault_crx;
|
output status_remote_fault_crx;
|
|
|
/*AUTOREG*/
|
/*AUTOREG*/
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
reg status_local_fault_crx;
|
reg status_local_fault_crx;
|
reg status_remote_fault_crx;
|
reg status_remote_fault_crx;
|
// End of automatics
|
// End of automatics
|
|
|
reg [1:0] curr_state;
|
reg [1:0] curr_state;
|
|
|
reg [7:0] col_cnt;
|
reg [7:0] col_cnt;
|
reg [1:0] fault_sequence;
|
reg [1:0] fault_sequence;
|
reg [1:0] last_seq_type;
|
reg [1:0] last_seq_type;
|
reg [1:0] link_fault;
|
reg [1:0] link_fault;
|
reg [2:0] seq_cnt;
|
reg [2:0] seq_cnt;
|
reg [1:0] seq_type;
|
reg [1:0] seq_type;
|
|
|
reg [1:0] seq_add;
|
reg [1:0] seq_add;
|
|
|
/*AUTOWIRE*/
|
/*AUTOWIRE*/
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
// End of automatics
|
|
|
|
|
|
parameter [1:0]
|
parameter [1:0]
|
SM_INIT = 2'd0,
|
SM_INIT = 2'd0,
|
SM_COUNT = 2'd1,
|
SM_COUNT = 2'd1,
|
SM_FAULT = 2'd2,
|
SM_FAULT = 2'd2,
|
SM_NEW_FAULT = 2'd3;
|
SM_NEW_FAULT = 2'd3;
|
|
|
|
|
always @(/*AS*/local_fault_msg_det or remote_fault_msg_det) begin
|
always @(/*AS*/local_fault_msg_det or remote_fault_msg_det) begin
|
|
|
//---
|
//---
|
// Fault indication. Indicate remote or local fault
|
// Fault indication. Indicate remote or local fault
|
|
|
fault_sequence = local_fault_msg_det | remote_fault_msg_det;
|
fault_sequence = local_fault_msg_det | remote_fault_msg_det;
|
|
|
|
|
//---
|
//---
|
// Sequence type, local, remote, or ok
|
// Sequence type, local, remote, or ok
|
|
|
if (|local_fault_msg_det) begin
|
if (|local_fault_msg_det) begin
|
seq_type = `LINK_FAULT_LOCAL;
|
seq_type = `LINK_FAULT_LOCAL;
|
end
|
end
|
else if (|remote_fault_msg_det) begin
|
else if (|remote_fault_msg_det) begin
|
seq_type = `LINK_FAULT_REMOTE;
|
seq_type = `LINK_FAULT_REMOTE;
|
end
|
end
|
else begin
|
else begin
|
seq_type = `LINK_FAULT_OK;
|
seq_type = `LINK_FAULT_OK;
|
end
|
end
|
|
|
|
|
//---
|
//---
|
// Adder for number of faults, if detected in lower 4 lanes and
|
// Adder for number of faults, if detected in lower 4 lanes and
|
// upper 4 lanes, add 2. That's because we process 64-bit at a time
|
// upper 4 lanes, add 2. That's because we process 64-bit at a time
|
// instead of typically 32-bit xgmii.
|
// instead of typically 32-bit xgmii.
|
|
|
if (|remote_fault_msg_det) begin
|
if (|remote_fault_msg_det) begin
|
seq_add = remote_fault_msg_det[1] + remote_fault_msg_det[0];
|
seq_add = remote_fault_msg_det[1] + remote_fault_msg_det[0];
|
end
|
end
|
else begin
|
else begin
|
seq_add = local_fault_msg_det[1] + local_fault_msg_det[0];
|
seq_add = local_fault_msg_det[1] + local_fault_msg_det[0];
|
end
|
end
|
|
|
end
|
end
|
|
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
|
|
if (reset_xgmii_rx_n == 1'b0) begin
|
if (reset_xgmii_rx_n == 1'b0) begin
|
|
|
|
|
status_local_fault_crx <= 1'b0;
|
status_local_fault_crx <= 1'b0;
|
status_remote_fault_crx <= 1'b0;
|
status_remote_fault_crx <= 1'b0;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
//---
|
//---
|
// Status signal to generate local/remote fault interrupts
|
// Status signal to generate local/remote fault interrupts
|
|
|
status_local_fault_crx <= curr_state == SM_FAULT &&
|
status_local_fault_crx <= curr_state == SM_FAULT &&
|
link_fault == `LINK_FAULT_LOCAL;
|
link_fault == `LINK_FAULT_LOCAL;
|
|
|
status_remote_fault_crx <= curr_state == SM_FAULT &&
|
status_remote_fault_crx <= curr_state == SM_FAULT &&
|
link_fault == `LINK_FAULT_REMOTE;
|
link_fault == `LINK_FAULT_REMOTE;
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
|
|
if (reset_xgmii_rx_n == 1'b0) begin
|
if (reset_xgmii_rx_n == 1'b0) begin
|
|
|
curr_state <= SM_INIT;
|
curr_state <= SM_INIT;
|
|
|
col_cnt <= 8'b0;
|
col_cnt <= 8'b0;
|
last_seq_type <= `LINK_FAULT_OK;
|
last_seq_type <= `LINK_FAULT_OK;
|
link_fault <= `LINK_FAULT_OK;
|
link_fault <= `LINK_FAULT_OK;
|
seq_cnt <= 3'b0;
|
seq_cnt <= 3'b0;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
case (curr_state)
|
case (curr_state)
|
|
|
SM_INIT:
|
SM_INIT:
|
begin
|
begin
|
|
|
last_seq_type <= seq_type;
|
last_seq_type <= seq_type;
|
|
|
if (|fault_sequence) begin
|
if (|fault_sequence) begin
|
|
|
// If a fault is detected, capture the type of
|
// If a fault is detected, capture the type of
|
// fault and start column counter. We need 4 fault
|
// fault and start column counter. We need 4 fault
|
// messages in 128 columns to accept the fault.
|
// messages in 128 columns to accept the fault.
|
|
|
if (fault_sequence[0]) begin
|
if (fault_sequence[0]) begin
|
col_cnt <= 8'd2;
|
col_cnt <= 8'd2;
|
end
|
end
|
else begin
|
else begin
|
col_cnt <= 8'd1;
|
col_cnt <= 8'd1;
|
end
|
end
|
seq_cnt <= {1'b0, seq_add};
|
seq_cnt <= {1'b0, seq_add};
|
curr_state <= SM_COUNT;
|
curr_state <= SM_COUNT;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
// If no faults, stay in INIT and clear counters
|
// If no faults, stay in INIT and clear counters
|
|
|
col_cnt <= 8'b0;
|
col_cnt <= 8'b0;
|
seq_cnt <= 3'b0;
|
seq_cnt <= 3'b0;
|
|
|
end
|
end
|
end
|
end
|
|
|
SM_COUNT:
|
SM_COUNT:
|
begin
|
begin
|
|
|
col_cnt <= col_cnt + 8'd2;
|
col_cnt <= col_cnt + 8'd2;
|
seq_cnt <= seq_cnt + {1'b0, seq_add};
|
seq_cnt <= seq_cnt + {1'b0, seq_add};
|
|
|
if (!fault_sequence[0] && col_cnt >= 8'd127) begin
|
if (!fault_sequence[0] && col_cnt >= 8'd127) begin
|
|
|
// No new fault in lower lanes and almost
|
// No new fault in lower lanes and almost
|
// reached the 128 columns count, abort fault.
|
// reached the 128 columns count, abort fault.
|
|
|
curr_state <= SM_INIT;
|
curr_state <= SM_INIT;
|
|
|
end
|
end
|
else if (col_cnt > 8'd127) begin
|
else if (col_cnt > 8'd127) begin
|
|
|
// Reached the 128 columns count, abort fault.
|
// Reached the 128 columns count, abort fault.
|
|
|
curr_state <= SM_INIT;
|
curr_state <= SM_INIT;
|
|
|
end
|
end
|
else if (|fault_sequence) begin
|
else if (|fault_sequence) begin
|
|
|
// If fault type has changed, move to NEW_FAULT.
|
// If fault type has changed, move to NEW_FAULT.
|
// If not, after detecting 4 fault messages move to
|
// If not, after detecting 4 fault messages move to
|
// FAULT state.
|
// FAULT state.
|
|
|
if (seq_type != last_seq_type) begin
|
if (seq_type != last_seq_type) begin
|
curr_state <= SM_NEW_FAULT;
|
curr_state <= SM_NEW_FAULT;
|
end
|
end
|
else begin
|
else begin
|
if ((seq_cnt + {1'b0, seq_add}) > 3'd3) begin
|
if ((seq_cnt + {1'b0, seq_add}) > 3'd3) begin
|
col_cnt <= 8'b0;
|
col_cnt <= 8'b0;
|
link_fault <= seq_type;
|
link_fault <= seq_type;
|
curr_state <= SM_FAULT;
|
curr_state <= SM_FAULT;
|
end
|
end
|
end
|
end
|
|
|
end
|
end
|
end
|
end
|
|
|
SM_FAULT:
|
SM_FAULT:
|
begin
|
begin
|
|
|
col_cnt <= col_cnt + 8'd2;
|
col_cnt <= col_cnt + 8'd2;
|
|
|
if (!fault_sequence[0] && col_cnt >= 8'd127) begin
|
if (!fault_sequence[0] && col_cnt >= 8'd127) begin
|
|
|
// No new fault in lower lanes and almost
|
// No new fault in lower lanes and almost
|
// reached the 128 columns count, abort fault.
|
// reached the 128 columns count, abort fault.
|
|
|
curr_state <= SM_INIT;
|
curr_state <= SM_INIT;
|
|
|
end
|
end
|
else if (col_cnt > 8'd127) begin
|
else if (col_cnt > 8'd127) begin
|
|
|
// Reached the 128 columns count, abort fault.
|
// Reached the 128 columns count, abort fault.
|
|
|
curr_state <= SM_INIT;
|
curr_state <= SM_INIT;
|
|
|
end
|
end
|
else if (|fault_sequence) begin
|
else if (|fault_sequence) begin
|
|
|
// Clear the column count each time we see a fault,
|
// Clear the column count each time we see a fault,
|
// if fault changes, go no next state.
|
// if fault changes, go no next state.
|
|
|
col_cnt <= 8'd0;
|
col_cnt <= 8'd0;
|
|
|
if (seq_type != last_seq_type) begin
|
if (seq_type != last_seq_type) begin
|
curr_state <= SM_NEW_FAULT;
|
curr_state <= SM_NEW_FAULT;
|
end
|
end
|
end
|
end
|
|
|
end
|
end
|
|
|
SM_NEW_FAULT:
|
SM_NEW_FAULT:
|
begin
|
begin
|
|
|
// Capture new fault type. Start counters.
|
// Capture new fault type. Start counters.
|
|
|
col_cnt <= 8'b0;
|
col_cnt <= 8'b0;
|
last_seq_type <= seq_type;
|
last_seq_type <= seq_type;
|
|
|
seq_cnt <= {1'b0, seq_add};
|
seq_cnt <= {1'b0, seq_add};
|
curr_state <= SM_COUNT;
|
curr_state <= SM_COUNT;
|
|
|
end
|
end
|
|
|
endcase
|
endcase
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
|
|