diff options
Diffstat (limited to 'fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v')
-rw-r--r-- | fpga/usrp3/lib/xge/rtl/verilog/fault_sm.v | 287 |
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 + |