//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// File name "sc_xgmii_if.cpp" ////
|
//// File name "sc_xgmii_if.cpp" ////
|
//// ////
|
//// ////
|
//// This file is part of the "10GE MAC" project ////
|
//// This file is part of the "10GE MAC" project ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <iostream>
|
#include <iostream>
|
#include <sys/times.h>
|
#include <sys/times.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
|
|
#include "systemc.h"
|
#include "systemc.h"
|
|
|
#include "sc_xgmii_if.h"
|
#include "sc_xgmii_if.h"
|
|
|
sc_fifo<packet_t*> * xgmii_if::get_tx_fifo_ptr() {
|
sc_fifo<packet_t*> * xgmii_if::get_tx_fifo_ptr() {
|
return &tx_fifo;
|
return &tx_fifo;
|
}
|
}
|
|
|
sc_fifo<packet_t*> * xgmii_if::get_rx_fifo_ptr() {
|
sc_fifo<packet_t*> * xgmii_if::get_rx_fifo_ptr() {
|
return &rx_fifo;
|
return &rx_fifo;
|
}
|
}
|
|
|
void xgmii_if::init(void) {
|
void xgmii_if::init(void) {
|
allow_idle_errors = false;
|
allow_idle_errors = false;
|
disable_padding = false;
|
disable_padding = false;
|
|
inject_noise = false;
|
}
|
}
|
|
|
void xgmii_if::connect_scoreboard(scoreboard *sbptr, scoreboard::sbSourceId sid) {
|
void xgmii_if::connect_scoreboard(scoreboard *sbptr, scoreboard::sbSourceId sid) {
|
sb = sbptr;
|
sb = sbptr;
|
sb_id = sid;
|
sb_id = sid;
|
}
|
}
|
|
|
void xgmii_if::transmit() {
|
void xgmii_if::transmit() {
|
|
|
packet_t* pkt;
|
packet_t* pkt;
|
|
|
sc_uint<64> txd = 0;
|
sc_uint<64> txd = 0;
|
sc_uint<8> txc = 0;
|
sc_uint<8> txc = 0;
|
|
|
|
int64_t noise [] = {0x1, 0xd5555555555555fb,
|
|
0x1, 0xd5555555555555fb,
|
|
0x1, 0xd5555555555555fc,
|
|
0x0, 0xd5555555555555fb,
|
|
0x1, 0xd5555555555555fb,
|
|
0x0, 0xd5555555555555fb,
|
|
0x1, 0x1111111111111111,
|
|
};
|
|
|
int lane = 0;
|
int lane = 0;
|
int bytecnt = 0;
|
int bytecnt = 0;
|
int length = 0;
|
int length = 0;
|
int preamblecnt = 0;
|
int preamblecnt = 0;
|
int ifg = 0;
|
int ifg = 0;
|
int fragment_size = 8;
|
int fragment_size = 8;
|
int coding_offset = 0;
|
int coding_offset = 0;
|
int fault_cnt = 0;
|
int fault_cnt = 0;
|
int fault_byte = 0;
|
int fault_byte = 0;
|
int fault_spacing;
|
int fault_spacing;
|
int fault_spacing_cnt = 0;
|
int fault_spacing_cnt = 0;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
while (true) {
|
while (true) {
|
|
|
if (length == 0 && tx_fifo.nb_read(pkt)) {
|
if (length == 0 && tx_fifo.nb_read(pkt)) {
|
|
|
if (!disable_padding) {
|
if (!disable_padding) {
|
pad(pkt, 60);
|
pad(pkt, 60);
|
}
|
}
|
pack(pkt);
|
pack(pkt);
|
|
|
calc_crc(pkt);
|
calc_crc(pkt);
|
|
|
//---
|
//---
|
// Inject errors
|
// Inject errors
|
|
|
if (pkt->err_flags & PKT_FLAG_ERR_CRC) {
|
if (pkt->err_flags & PKT_FLAG_ERR_CRC) {
|
pkt->crc++;
|
pkt->crc++;
|
}
|
}
|
|
|
if (pkt->err_flags & PKT_FLAG_ERR_FRG) {
|
if (pkt->err_flags & PKT_FLAG_ERR_FRG) {
|
pkt->length = fragment_size;
|
pkt->length = fragment_size;
|
fragment_size++;
|
fragment_size++;
|
if (fragment_size > 64) {
|
if (fragment_size > 64) {
|
fragment_size = 8;
|
fragment_size = 8;
|
}
|
}
|
}
|
}
|
|
|
if (pkt->err_flags & PKT_FLAG_ERR_CODING) {
|
if (pkt->err_flags & PKT_FLAG_ERR_CODING) {
|
if (coding_offset >= pkt->length) {
|
if (coding_offset >= pkt->length) {
|
pkt->err_info = pkt->length-1;
|
pkt->err_info = pkt->length-1;
|
}
|
}
|
else {
|
else {
|
pkt->err_info = coding_offset;
|
pkt->err_info = coding_offset;
|
}
|
}
|
coding_offset++;
|
coding_offset++;
|
if (coding_offset >= 70) {
|
if (coding_offset >= 70) {
|
coding_offset = 0;
|
coding_offset = 0;
|
}
|
}
|
}
|
}
|
|
|
//---
|
//---
|
// Inject local / remote faults
|
// Inject local / remote faults
|
|
|
if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT ||
|
if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT ||
|
pkt->err_flags & PKT_FLAG_REMOTE_FAULT) {
|
pkt->err_flags & PKT_FLAG_REMOTE_FAULT) {
|
fault_cnt = 4;
|
fault_cnt = 4;
|
fault_byte = 4;
|
fault_byte = 4;
|
fault_spacing_cnt = 0;
|
fault_spacing_cnt = 0;
|
|
|
fault_spacing = pkt->err_info;
|
fault_spacing = pkt->err_info;
|
cout << "INFO: Fault insert, spacing: " << fault_spacing << endl;
|
cout << "INFO: Fault insert, spacing: " << fault_spacing << endl;
|
}
|
}
|
|
|
//---
|
//---
|
// Pass packet to scoreboard
|
// Pass packet to scoreboard
|
|
|
sb->notify_packet_tx(sb_id, pkt);
|
sb->notify_packet_tx(sb_id, pkt);
|
|
|
add_crc(pkt);
|
add_crc(pkt);
|
strip_crc(pkt);
|
strip_crc(pkt);
|
length = pkt->length + 4;
|
length = pkt->length + 4;
|
|
|
//cout << "Transmit XGMII packet:\n" << * pkt << endl;
|
//cout << "Transmit XGMII packet:\n" << * pkt << endl;
|
|
|
}
|
}
|
|
|
|
|
if (ifg != 0) {
|
if (ifg != 0) {
|
txd |= ((sc_uint<64>)0x07) << (8 * lane);
|
txd |= ((sc_uint<64>)0x07) << (8 * lane);
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
ifg--;
|
ifg--;
|
|
|
}
|
}
|
else if (fault_spacing_cnt != 0) {
|
else if (fault_spacing_cnt != 0) {
|
|
|
txd |= ((sc_uint<64>)0x07) << (8 * lane);
|
txd |= ((sc_uint<64>)0x07) << (8 * lane);
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
|
|
fault_spacing_cnt--;
|
fault_spacing_cnt--;
|
|
|
}
|
}
|
else if ((lane == 0 || lane == 4) && fault_byte == 4) {
|
else if ((lane == 0 || lane == 4) && fault_byte == 4) {
|
|
|
txd |= ((sc_uint<64>)0x9c) << (8 * lane);
|
txd |= ((sc_uint<64>)0x9c) << (8 * lane);
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
|
|
fault_byte--;
|
fault_byte--;
|
|
|
}
|
}
|
else if (fault_byte == 3 || fault_byte == 2) {
|
else if (fault_byte == 3 || fault_byte == 2) {
|
|
|
fault_byte--;
|
fault_byte--;
|
|
|
}
|
}
|
else if (fault_byte == 1) {
|
else if (fault_byte == 1) {
|
|
|
if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT) {
|
if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT) {
|
txd |= ((sc_uint<64>)0x01) << (8 * lane);
|
txd |= ((sc_uint<64>)0x01) << (8 * lane);
|
}
|
}
|
else {
|
else {
|
txd |= ((sc_uint<64>)0x02) << (8 * lane);
|
txd |= ((sc_uint<64>)0x02) << (8 * lane);
|
}
|
}
|
fault_byte--;
|
fault_byte--;
|
|
|
fault_cnt--;
|
fault_cnt--;
|
if (fault_cnt > 0) {
|
if (fault_cnt > 0) {
|
fault_byte = 4;
|
fault_byte = 4;
|
}
|
}
|
|
|
if (fault_cnt == 1) {
|
if (fault_cnt == 1) {
|
fault_spacing_cnt = 4 * fault_spacing;
|
fault_spacing_cnt = 4 * fault_spacing;
|
}
|
}
|
}
|
}
|
else if ((lane == 0 || lane == 4) && bytecnt != length && preamblecnt == 0) {
|
else if ((lane == 0 || lane == 4) && bytecnt != length && preamblecnt == 0) {
|
|
|
txd |= ((sc_uint<64>)0xfb) << (8 * lane);
|
txd |= ((sc_uint<64>)0xfb) << (8 * lane);
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
|
|
preamblecnt++;
|
preamblecnt++;
|
|
|
}
|
}
|
else if (preamblecnt > 0 && preamblecnt < 7) {
|
else if (preamblecnt > 0 && preamblecnt < 7) {
|
|
|
txd |= ((sc_uint<64>)0x55) << (8 * lane);
|
txd |= ((sc_uint<64>)0x55) << (8 * lane);
|
|
|
preamblecnt++;
|
preamblecnt++;
|
|
|
}
|
}
|
else if (preamblecnt == 7) {
|
else if (preamblecnt == 7) {
|
|
|
txd |= ((sc_uint<64>)0xd5) << (8 * lane);
|
txd |= ((sc_uint<64>)0xd5) << (8 * lane);
|
|
|
preamblecnt++;
|
preamblecnt++;
|
|
|
}
|
}
|
else if (preamblecnt > 7 && (bytecnt == (length-4)) &&
|
else if (preamblecnt > 7 && (bytecnt == (length-4)) &&
|
(pkt->err_flags & PKT_FLAG_ERR_FRG)) {
|
(pkt->err_flags & PKT_FLAG_ERR_FRG)) {
|
|
|
//---
|
//---
|
// Fragment insertion
|
// Fragment insertion
|
|
|
bytecnt = 0;
|
bytecnt = 0;
|
length = 0;
|
length = 0;
|
preamblecnt = 0;
|
preamblecnt = 0;
|
ifg = 0;
|
ifg = 0;
|
|
|
}
|
}
|
else if (preamblecnt >7 && bytecnt == pkt->err_info &&
|
else if (preamblecnt >7 && bytecnt == pkt->err_info &&
|
(pkt->err_flags & PKT_FLAG_ERR_CODING)) {
|
(pkt->err_flags & PKT_FLAG_ERR_CODING)) {
|
|
|
//---
|
//---
|
// Coding error insertion
|
// Coding error insertion
|
|
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
|
txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
|
bytecnt++;
|
bytecnt++;
|
|
|
}
|
}
|
else if (preamblecnt > 7 && bytecnt < length) {
|
else if (preamblecnt > 7 && bytecnt < length) {
|
|
|
txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
|
txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
|
bytecnt++;
|
bytecnt++;
|
|
|
}
|
}
|
else if (preamblecnt > 7 && bytecnt == length) {
|
else if (preamblecnt > 7 && bytecnt == length) {
|
|
|
//---
|
//---
|
// End of frame TERMINATE
|
// End of frame TERMINATE
|
|
|
txd |= ((sc_uint<64>)0xfd) << (8 * lane);
|
txd |= ((sc_uint<64>)0xfd) << (8 * lane);
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
|
|
bytecnt = 0;
|
bytecnt = 0;
|
length = 0;
|
length = 0;
|
preamblecnt = 0;
|
preamblecnt = 0;
|
|
|
// Minimum IFG is 5 including TERMINATE
|
// Minimum IFG is 5 including TERMINATE
|
ifg = 4;
|
ifg = 4;
|
|
|
}
|
}
|
else {
|
else {
|
txd |= ((sc_uint<64>)0x07) << (8 * lane);
|
txd |= ((sc_uint<64>)0x07) << (8 * lane);
|
txc |= 0x01 << lane;
|
txc |= 0x01 << lane;
|
}
|
}
|
if (lane == 7) {
|
if (inject_noise) {
|
|
for (count = 0; count < 10000; count += 2) {
|
|
i = 2 * (random() % (sizeof(noise)/16));
|
|
cout << "NOISE: " << hex << noise[i] << " " << noise[i+1] << dec << endl;
|
|
xgmii_rxd = noise[i+1];
|
|
xgmii_rxc = noise[i];
|
|
txd = 0;
|
|
txc = 0;
|
|
wait();
|
|
}
|
|
inject_noise = false;
|
|
}
|
|
else if (lane == 7) {
|
xgmii_rxd = txd;
|
xgmii_rxd = txd;
|
xgmii_rxc = txc;
|
xgmii_rxc = txc;
|
txd = 0;
|
txd = 0;
|
txc = 0;
|
txc = 0;
|
wait();
|
wait();
|
}
|
}
|
lane = (lane + 1) % 8;
|
lane = (lane + 1) % 8;
|
|
|
}
|
}
|
};
|
};
|
|
|
|
|
void xgmii_if::receive() {
|
void xgmii_if::receive() {
|
|
|
packet_t* pkt;
|
packet_t* pkt;
|
|
|
sc_uint<64> rxd;
|
sc_uint<64> rxd;
|
sc_uint<8> rxc;
|
sc_uint<8> rxc;
|
|
|
int lane, bytecnt, ifgcnt;
|
int lane, bytecnt, ifgcnt;
|
|
|
lane = 0;
|
lane = 0;
|
|
|
wait();
|
wait();
|
|
|
while (true) {
|
while (true) {
|
|
|
ifgcnt = 1;
|
ifgcnt = 1;
|
|
|
rxd = xgmii_txd;
|
rxd = xgmii_txd;
|
rxc = xgmii_txc;
|
rxc = xgmii_txc;
|
|
|
|
|
//---
|
//---
|
// Wait for START code in lane0 or lane4
|
// Wait for START code in lane0 or lane4
|
|
|
while (true) {
|
while (true) {
|
|
|
// Check for START character
|
// Check for START character
|
if (((rxd >> (8*lane)) & 0xff) == 0xfb && ((rxc >> lane) & 0x1) == 1) {
|
if (((rxd >> (8*lane)) & 0xff) == 0xfb && ((rxc >> lane) & 0x1) == 1) {
|
if (disable_receive) {
|
if (disable_receive) {
|
cout << "INFO: XGMII Receive Disabled" << endl;
|
cout << "INFO: XGMII Receive Disabled" << endl;
|
}
|
}
|
else {
|
else {
|
break;
|
break;
|
}
|
}
|
};
|
};
|
|
|
// Check IDLE character and control lines
|
// Check IDLE character and control lines
|
if (((rxd >> (8*lane)) & 0xff) != 0x07 || ((rxc >> lane) & 0x1) != 1) {
|
if (((rxd >> (8*lane)) & 0xff) != 0x07 || ((rxc >> lane) & 0x1) != 1) {
|
if (allow_idle_errors) {
|
if (allow_idle_errors) {
|
cout << "INFO: IDLE check disabled" << endl;
|
cout << "INFO: IDLE check disabled" << endl;
|
}
|
}
|
else {
|
else {
|
cout << "ERROR: IDLE character " << hex << rxd << " " << rxc << dec << lane << endl;
|
cout << "ERROR: IDLE character " << hex << rxd << " " << rxc << dec << lane << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
};
|
};
|
|
|
ifgcnt++;
|
ifgcnt++;
|
|
|
lane = (lane + 1) % 8;
|
lane = (lane + 1) % 8;
|
if (lane == 0) {
|
if (lane == 0) {
|
wait();
|
wait();
|
rxd = xgmii_txd;
|
rxd = xgmii_txd;
|
rxc = xgmii_txc;
|
rxc = xgmii_txc;
|
}
|
}
|
}
|
}
|
|
|
//cout << "START in lane " << lane << " IFG " << ifgcnt << endl;
|
//cout << "START in lane " << lane << " IFG " << ifgcnt << endl;
|
|
|
// Check starting lane
|
// Check starting lane
|
if (lane != 0 && lane != 4) {
|
if (lane != 0 && lane != 4) {
|
cout << "ERROR: Lane aligment" << endl;
|
cout << "ERROR: Lane aligment" << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
|
|
// Check for minimum inter frame gap
|
// Check for minimum inter frame gap
|
if (ifgcnt < 9) {
|
if (ifgcnt < 9) {
|
cout << "ERROR: MINIMUM IFG " << ifgcnt << endl;
|
cout << "ERROR: MINIMUM IFG " << ifgcnt << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
|
|
//---
|
//---
|
// Capture data until end of frame is detected (TERMINATE)
|
// Capture data until end of frame is detected (TERMINATE)
|
|
|
pkt = new(packet_t);
|
pkt = new(packet_t);
|
pkt->ifg = ifgcnt;
|
pkt->ifg = ifgcnt;
|
pkt->start_lane = lane;
|
pkt->start_lane = lane;
|
pkt->length = 0;
|
pkt->length = 0;
|
|
|
bytecnt = 0;
|
bytecnt = 0;
|
while (true) {
|
while (true) {
|
|
|
// Look for end of frame delimiter in any lane
|
// Look for end of frame delimiter in any lane
|
if (((rxd >> (8*lane)) & 0xff) == 0xfd && ((rxc >> lane) & 0x1) == 1) {
|
if (((rxd >> (8*lane)) & 0xff) == 0xfd && ((rxc >> lane) & 0x1) == 1) {
|
break;
|
break;
|
};
|
};
|
|
|
// Stop if packet is too long
|
// Stop if packet is too long
|
if (bytecnt >= 10000) {
|
if (bytecnt >= 10000) {
|
break;
|
break;
|
}
|
}
|
|
|
// Validate preamble bytes
|
// Validate preamble bytes
|
if (bytecnt > 0 && bytecnt <= 6 && ((rxd >> (8*lane)) & 0xff) != 0x55) {
|
if (bytecnt > 0 && bytecnt <= 6 && ((rxd >> (8*lane)) & 0xff) != 0x55) {
|
cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
|
cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
|
|
// Validate SFD code in preamble
|
// Validate SFD code in preamble
|
if (bytecnt == 7 && ((rxd >> (8*lane)) & 0xff) != 0xd5) {
|
if (bytecnt == 7 && ((rxd >> (8*lane)) & 0xff) != 0xd5) {
|
cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
|
cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
|
|
// Store all bytes after preamble
|
// Store all bytes after preamble
|
if (bytecnt > 7) {
|
if (bytecnt > 7) {
|
if (((rxc >> lane) & 0x1) == 0) {
|
if (((rxc >> lane) & 0x1) == 0) {
|
pkt->data[pkt->length] = ((rxd >> (8*lane)) & 0xff);
|
pkt->data[pkt->length] = ((rxd >> (8*lane)) & 0xff);
|
pkt->length++;
|
pkt->length++;
|
}
|
}
|
else {
|
else {
|
cout << "ERROR: RXC high during data cycle" << endl;
|
cout << "ERROR: RXC high during data cycle" << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
}
|
}
|
else if (bytecnt > 0) {
|
else if (bytecnt > 0) {
|
if (((rxc >> lane) & 0x1) == 1) {
|
if (((rxc >> lane) & 0x1) == 1) {
|
cout << "ERROR: RXC high during preamble" << endl;
|
cout << "ERROR: RXC high during preamble" << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
}
|
}
|
|
|
bytecnt++;
|
bytecnt++;
|
lane = (lane + 1) % 8;
|
lane = (lane + 1) % 8;
|
if (lane == 0) {
|
if (lane == 0) {
|
wait();
|
wait();
|
rxd = xgmii_txd;
|
rxd = xgmii_txd;
|
rxc = xgmii_txc;
|
rxc = xgmii_txc;
|
}
|
}
|
}
|
}
|
|
|
|
|
lane = (lane + 1) % 8;
|
lane = (lane + 1) % 8;
|
if (lane == 0) {
|
if (lane == 0) {
|
wait();
|
wait();
|
rxd = xgmii_txd;
|
rxd = xgmii_txd;
|
rxc = xgmii_txc;
|
rxc = xgmii_txc;
|
}
|
}
|
|
|
//---
|
//---
|
// Store packet
|
// Store packet
|
|
|
strip_crc(pkt);
|
strip_crc(pkt);
|
|
|
unpack(pkt);
|
unpack(pkt);
|
//rx_fifo.write(pkt);
|
//rx_fifo.write(pkt);
|
//cout << "Received XGMII packet:" << * pkt << endl;
|
//cout << "Received XGMII packet:" << * pkt << endl;
|
|
|
//---
|
//---
|
// Pass packet to scoreboard
|
// Pass packet to scoreboard
|
|
|
sb->notify_packet_rx(sb_id, pkt);
|
sb->notify_packet_rx(sb_id, pkt);
|
|
|
}
|
}
|
};
|
};
|
|
|
|
|
void xgmii_if::monitor() {
|
void xgmii_if::monitor() {
|
|
|
sc_uint<64> rxd;
|
sc_uint<64> rxd;
|
sc_uint<8> rxc;
|
sc_uint<8> rxc;
|
|
|
wait();
|
wait();
|
|
|
while (true) {
|
while (true) {
|
|
|
rxd = xgmii_txd;
|
rxd = xgmii_txd;
|
rxc = xgmii_txc;
|
rxc = xgmii_txc;
|
|
|
//---
|
//---
|
// Check for local/remote fault
|
// Check for local/remote fault
|
|
|
if (((rxd & 0xffffffff) == 0x0100009c && (rxc & 0xf) == 0x1) &&
|
if (((rxd & 0xffffffff) == 0x0100009c && (rxc & 0xf) == 0x1) &&
|
(((rxd >> 32) & 0xffffffff) == 0x0100009c && ((rxc > 4) & 0xf) == 0x1)) {
|
(((rxd >> 32) & 0xffffffff) == 0x0100009c && ((rxc > 4) & 0xf) == 0x1)) {
|
|
|
//--
|
//--
|
// Local fault detection
|
// Local fault detection
|
|
|
if (!rx_local_fault) {
|
if (!rx_local_fault) {
|
cout << "XGMII Local Fault Asserted" << endl;
|
cout << "XGMII Local Fault Asserted" << endl;
|
|
|
// Notify Scoreboard
|
// Notify Scoreboard
|
sb->notify_status(sb_id, scoreboard::LOCAL_FAULT);
|
sb->notify_status(sb_id, scoreboard::LOCAL_FAULT);
|
}
|
}
|
rx_local_fault = true;
|
rx_local_fault = true;
|
|
|
}
|
}
|
else {
|
else {
|
|
|
if (rx_local_fault) {
|
if (rx_local_fault) {
|
cout << "XGMII Local Fault De-Asserted" << endl;
|
cout << "XGMII Local Fault De-Asserted" << endl;
|
}
|
}
|
rx_local_fault = false;
|
rx_local_fault = false;
|
|
|
}
|
}
|
|
|
if (((rxd & 0xffffffff) == 0x0200009c && (rxc & 0xf) == 0x1) &&
|
if (((rxd & 0xffffffff) == 0x0200009c && (rxc & 0xf) == 0x1) &&
|
(((rxd >> 32) & 0xffffffff) == 0x0200009c && ((rxc > 4) & 0xf) == 0x1)) {
|
(((rxd >> 32) & 0xffffffff) == 0x0200009c && ((rxc > 4) & 0xf) == 0x1)) {
|
|
|
//--
|
//--
|
// Remote fault detection
|
// Remote fault detection
|
|
|
if (!rx_remote_fault) {
|
if (!rx_remote_fault) {
|
cout << "XGMII Remote Fault Asserted" << endl;
|
cout << "XGMII Remote Fault Asserted" << endl;
|
|
|
// Notify Scoreboard
|
// Notify Scoreboard
|
sb->notify_status(sb_id, scoreboard::REMOTE_FAULT);
|
sb->notify_status(sb_id, scoreboard::REMOTE_FAULT);
|
}
|
}
|
rx_remote_fault = true;
|
rx_remote_fault = true;
|
|
|
}
|
}
|
else {
|
else {
|
|
|
if (rx_remote_fault) {
|
if (rx_remote_fault) {
|
cout << "XGMII Remote Fault De-Asserted" << endl;
|
cout << "XGMII Remote Fault De-Asserted" << endl;
|
}
|
}
|
rx_remote_fault = false;
|
rx_remote_fault = false;
|
|
|
}
|
}
|
|
|
wait();
|
wait();
|
}
|
}
|
};
|
};
|
|
|