276 lines
6.8 KiB
Verilog
276 lines
6.8 KiB
Verilog
//
|
|
// 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
|