// // Synthesizable Rx checker for 10G Ethernet MAC. // Collects recevied packets and checks them against the deterministic expected result // to verify correct loopback functionality if used with the tx_checker. // `define IDLE 0 `define SEARCH 1 `define RECEIVE1 2 `define RECEIVE2 3 `define RECEIVE3 4 `define DONE 5 `define ERROR1 6 `define ERROR2 7 `define ERROR3 8 module rx_checker ( input clk156, input rst, input enable, output reg done, output reg correct, output reg [1:0] error, // input pkt_rx_avail, input pkt_rx_val, input pkt_rx_sop, input pkt_rx_eop, input [2:0] pkt_rx_mod, input [63:0] pkt_rx_data, input pkt_rx_err, output reg pkt_rx_ren ); reg [10:0] payload; reg [10:0] count; reg [7:0] state; always @(posedge clk156) if (rst) begin // Reset state <= `IDLE; done <= 0; correct <= 0; error <= 0; pkt_rx_ren <= 0; count <= 0; payload <= 45; // 1 less than ethernet minimum payload size.\ end else begin // Defaults state <= state; done <= 0; correct <= 0; error <= 0; pkt_rx_ren <= 0; count <= count; payload <= payload; case(state) // Wait in IDLE state until enabled. // incomming packets will not be detected in this state. `IDLE: begin if (enable) state <= `SEARCH; end // case: `IDLE // // Search for pkt_rx_avail going asserted to show that a packet is in the MAC's FIFO's. // Then assert pkt_rx_ren back to MAC to start transfer. pkt_rx_ren now remains asserted until // at least EOP, longer if pkt_rx_avail is still asserted at EOP as back-to-back Rx is possible. // We can come into this state with pkt_rx_ren already enabled for back-to-back Rx cases. // `SEARCH: begin if (pkt_rx_val) state <= `ERROR1; // Illegal signalling else if (payload == 1500) state <= `DONE; else if (pkt_rx_avail) begin // rx_avail has been asserted, now assert rx_ren to start transfer. payload <= payload + 1; pkt_rx_ren <= 1; state <= `RECEIVE1; end end // // Now wait for pkt_rx_val and pkt_rx_sop to assert in the same cycle with the first // 8 octects of a new packet. When asserted check all data bits against expected data. // Go to error states if something doesn't match or work correctly. // `RECEIVE1: begin pkt_rx_ren <= 1; if (pkt_rx_err) state <= `ERROR3; // CRC error from MAC else if (pkt_rx_val && pkt_rx_sop && ~pkt_rx_eop) begin if ((pkt_rx_data[63:16] == 48'h0001020304) && (pkt_rx_data[15:0] == 16'h0000) && (pkt_rx_mod == 3'h0)) state <= `RECEIVE2; else state <= `ERROR2; // Data missmatch error end else if (pkt_rx_val || pkt_rx_sop || pkt_rx_eop) // Error condition begin state <= `ERROR1; // Illegal signalling end end // case: `RECEIVE1 // // Check all data bits against expected data. // Go to error states if something doesn't match or work correctly. // `RECEIVE2: begin pkt_rx_ren <= 1; if (pkt_rx_err) state <= `ERROR3; // CRC error from MAC else if (pkt_rx_val && ~pkt_rx_sop && ~pkt_rx_eop) begin if ((pkt_rx_data[63:32] == 32'h05060708) && (pkt_rx_data[31:16] == 16'h88b5) && (pkt_rx_data[15:0] == 16'hBEEF) && (pkt_rx_mod == 3'h0)) begin count <= payload - 2; // Preload counter for this packet state <= `RECEIVE3; end else state <= `ERROR2; // Data missmatch error end else if (~pkt_rx_val || pkt_rx_sop || pkt_rx_eop) // Error condition begin state <= `ERROR1; // Illegal signalling end end // case: `RECEIVE2 // // Should now have received both MAC addresses, the ETHERTYPE and first 2 octects of payload. // Check remaining payload whilst looking for end of packet. // Currently don;pt support chained RX of packets, pkt_rx_en will go to 0. // (Remember packets are bigendian) // `RECEIVE3: begin count <= count - 8; if (pkt_rx_err) state <= `ERROR3; // CRC error from MAC else if (pkt_rx_val && ~pkt_rx_sop) begin case({pkt_rx_eop,pkt_rx_mod}) 4'b0000: begin if (pkt_rx_data[63:0] == {8{count[10:3]}}) begin pkt_rx_ren <= 1; state <= `RECEIVE3; end else state <= `ERROR2; // Data missmatch error end 4'b1000: begin if (pkt_rx_data[63:0] == {8{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1001: begin if (pkt_rx_data[63:56] == {1{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1010: begin if (pkt_rx_data[63:48] == {2{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1011: begin if (pkt_rx_data[63:40] == {3{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1100: begin if (pkt_rx_data[63:32] == {4{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1101: begin if (pkt_rx_data[63:24] == {5{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1110: begin if (pkt_rx_data[63:16] == {6{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end 4'b1111: begin if (pkt_rx_data[63:8] == {7{count[10:3]}}) begin pkt_rx_ren <= 0; state <= `SEARCH; end else state <= `ERROR2; // Data missmatch error end default: state <= `ERROR1; // Illegal signalling endcase // case({pkt_rx_eop,pkt_rx_mod}) end end // // Finished. Received and verified full sequence. Now assert corret signal and done. // Stay in this state until reset. // `DONE: begin done <= 1; correct <= 1; end // // Signal protocol error. // Stay in this state until reset. // `ERROR1: begin done <= 1; error <= 1; end // // Data payload of packet did not match reference // Stay in this state until reset. // `ERROR2: begin done <= 1; error <= 2; end // // CRC error reported by MAC // Stay in this state until reset. // `ERROR3: begin done <= 1; error <= 3; end endcase end endmodule // rx_checker