Files
b210-k7-fpga/lib/xge/rtl/verilog/fault_sm.v
T
Ben Hilburn fbbc991a7d Pushing the bulk of UHD-3.7.0 code.
Original-commit: ff1546f8137f7f92bb250f685561b0c34cc0e053
2014-02-14 12:05:07 -08:00

288 lines
8.6 KiB
Verilog

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