// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: pcg_low_tx.vr
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
task send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
send_packet_xgmii with xgm0(ptype, buf, len, options);
send_packet_gmii with gm1(ptype, buf, len, options);
send_packet_gmii with gm2(ptype, buf, len, options);
send_packet_gmii with gm3(ptype, buf, len, options);
task assert_col_tx with mii_def(bit [63:0] options) {
while(rxdv_set == 0) @(posedge $rxclk);
//printf("DEBUG: pcg_low_rx: Got token %0d at time: %0d\n",om_token,{get_time(HI),get_time(LO)} );
if( check_option( options, O_RX_COL) & cfg_reg[CFG_COL_LEN]>0 & !tx_done ) {
itmp = cfg_reg[CFG_COL_DEL];
while(itmp>0 & !tx_done) {
itmp = cfg_reg[CFG_COL_LEN];
while(itmp>0 & !tx_done) {
task assert_mii_err with mii_def() {
if(tx_err_start==-1) return;
printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
while(cnt++ < tx_err_start & !tx_done)
while(cnt++ < tx_err_len & !tx_done)
printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
task send_packet_mii with mii_def(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
bit [63:0] min_gap, time_tmp;
printf("DEBUG: PG low tx started: current_time: %0d\n", {get_time(HI),get_time(LO)} );
current_time = {get_time(HI),get_time(LO)};
if(port_speed==1) min_gap = 800 * MII_IP_GAP; // 800ns * MII_IP_GAP inter packet cycles
else min_gap = 80 * MII_IP_GAP; // 80ns * MII_IP_GAP inter packet cycles
time_tmp = current_time - last_tx_time;
printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
last_tx_time,current_time,time_tmp);
if((time_tmp < min_gap) & !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) ) {
time_tmp = min_gap - time_tmp;
if(debug_mii_tx) printf("DEBUG: PG low tx: Min_gap: %0d, gap_diff: %0d\n",min_gap,time_tmp);
if(port_speed==1) time_tmp = time_tmp / 400;
else time_tmp = time_tmp / 40;
if(debug_mii_tx) printf("DEBUG: PG low tx: waiting additional %0d cycles\n",time_tmp);
repeat(time_tmp) @(posedge $rxclk);
if( check_option(options, O_CUSTOM_IP_GAP) ) {
repeat(cfg_reg[CFG_IP_GAP]) @(posedge $rxclk);
assert_mii_err with (get_bind())();
if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
if( check_option(options, O_SFD_ERR) ) tmp = cfg_reg[CFG_SFD_TOKEN];
if(debug_mii==1) printf("MII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
//if( check_option(options, O_CD_ERR) ) $rxcrs = 1;
if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) { // Force nibble error
/* -----------------------------------------------
SEND EXTEND NOT NEEDED FOR MII
-----------------------------------------------
------------------------------------------------ */
last_tx_time = {get_time(HI),get_time(LO)};
task assert_gmii_err with gmii_def() {
if(tx_err_start==-1) return;
printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
while(cnt++ < tx_err_start & !tx_done)
while(cnt++ < tx_err_len & !tx_done)
printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
task send_packet_gmii with gmii_def(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
bit [63:0] min_gap, time_tmp;
current_time = {get_time(HI),get_time(LO)};
min_gap = 8 * GMII_IP_GAP; // 8nS * GMII_IP_GAP inter packet cycles
//if(port_speed==1) min_gap = 400 * MII_IP_GAP; // 400ns * MII_IP_GAP inter packet cycles
//else min_gap = 40 * MII_IP_GAP; // 40ns * MII_IP_GAP inter packet cycles
time_tmp = current_time - last_tx_time;
printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
last_tx_time,current_time,time_tmp);
if((time_tmp < min_gap) & !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) ) {
time_tmp = min_gap - time_tmp;
if(debug_mii_tx) printf("DEBUG: PG low tx: Min_gap: %0d, gap_diff: %0d\n",min_gap,time_tmp);
//if(port_speed==1) time_tmp = time_tmp / 400;
//else time_tmp = time_tmp / 40;
if(debug_mii_tx) printf("DEBUG: PG low tx: waiting additional %0d cycles\n",time_tmp);
repeat(time_tmp) @(posedge $rxclk);
if( check_option(options, O_CUSTOM_IP_GAP) ) {
repeat(cfg_reg[CFG_IP_GAP]) @(posedge $rxclk);
assert_gmii_err with (get_bind())();
if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
if( check_option(options, O_SFD_ERR) ) $rxd = cfg_reg[CFG_SFD_TOKEN];
if(debug_gmii==1) printf("GMII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) { // Force nibble error
/* -----------------------------------------------
----------------------------------------------- */
last_tx_time = {get_time(HI),get_time(LO)};
task assert_xgmii_err with xgmii_def() {
if(tx_err_start==-1) return;
printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
while(cnt++ < tx_err_start & !tx_done)
while(cnt++ < tx_err_len & !tx_done)
printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
task send_packet_xgmii with xgmii_def(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
bit [63:0] min_gap, time_tmp;
current_time = {get_time(HI),get_time(LO)};
min_gap = 8 * XGMII_IP_GAP; // 8nS * GMII_IP_GAP inter packet cycles
time_tmp = current_time - last_tx_time;
printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
last_tx_time,current_time,time_tmp);
if((time_tmp < min_gap) & !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) ) {
time_tmp = min_gap - time_tmp;
if(debug_xgmii_tx) printf("DEBUG: PG low tx: Min_gap: %0d, gap_diff: %0d\n",min_gap,time_tmp);
//if(port_speed==1) time_tmp = time_tmp / 400;
//else time_tmp = time_tmp / 40;
if(debug_xgmii_tx) printf("DEBUG: PG low tx: waiting additional %0d cycles\n",time_tmp);
//repeat(time_tmp) @(posedge $rxclk);
repeat(time_tmp) @(posedge $rxclk_int);
if( check_option(options, O_CUSTOM_IP_GAP) ) {
//repeat(cfg_reg[CFG_IP_GAP]) @(posedge $rxclk);
repeat(cfg_reg[CFG_IP_GAP]) @(posedge $rxclk_int);
assert_xgmii_err with (get_bind())();
if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
if( check_option(options, O_SFD_ERR) ) $rxd = cfg_reg[CFG_SFD_TOKEN];
if(debug_xgmii==1) printf("XGMII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) { // Force nibble error
/* -----------------------------------------------
----------------------------------------------- */
last_tx_time = {get_time(HI),get_time(LO)};
task wait_clk(integer count) {
repeat(count) @(posedge CLOCK);
task wait_tx_clk(integer count) {
0: wait_tx_clk_if with m0(count);
1: wait_tx_clk_if with m1(count);
2: wait_tx_clk_if with m2(count);
3: wait_tx_clk_if with m3(count);
4: wait_tx_clk_if with m4(count);
5: wait_tx_clk_if with m5(count);
6: wait_tx_clk_if with m6(count);
7: wait_tx_clk_if with m7(count);
8: wait_tx_clk_if with m18(count);
19: wait_tx_clk_if with m19(count);
task wait_tx_clk_if with mii_def(integer count) {
repeat(count) @(posedge $txclk);
task wait_rx_clk(integer count) {
0: wait_rx_clk_if with m0(count);
1: wait_rx_clk_if with m1(count);
2: wait_rx_clk_if with m2(count);
3: wait_rx_clk_if with m3(count);
4: wait_rx_clk_if with m4(count);
5: wait_rx_clk_if with m5(count);
6: wait_rx_clk_if with m6(count);
7: wait_rx_clk_if with m7(count);
8: wait_rx_clk_if with m18(count);
19: wait_rx_clk_if with m19(count);
task wait_rx_clk_if with mii_def(integer count) {
repeat(count) @(posedge $rxclk);