aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v')
-rw-r--r--fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v287
1 files changed, 287 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v b/fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v
new file mode 100644
index 000000000..525459ca3
--- /dev/null
+++ b/fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v
@@ -0,0 +1,287 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// 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
+