OpenCores
URL https://opencores.org/ocsvn/ethmac/ethmac/trunk

Subversion Repositories ethmac

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /ethmac/tags/rel_11/bench
    from Rev 335 to Rev 338
    Reverse comparison

Rev 335 → Rev 338

/verilog/tb_ethernet.v
0,0 → 1,16163
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_ethernet.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// - Igor Mohor, igorM@opencores.org ////
//// ////
//// All additional information is available in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.18 2002/10/18 17:03:34 tadejm
// Changed BIST scan signals.
//
// Revision 1.17 2002/10/18 13:58:22 tadejm
// Some code changed due to bug fixes.
//
// Revision 1.16 2002/10/09 13:16:51 tadejm
// Just back-up; not completed testbench and some testcases are not
// wotking properly yet.
//
// Revision 1.15 2002/09/20 14:29:12 tadej
// Full duplex tests modified and testbench bug repaired.
//
// Revision 1.14 2002/09/18 17:56:38 tadej
// Some additional reports added
//
// Revision 1.13 2002/09/16 17:53:49 tadej
// Full duplex test improved.
//
// Revision 1.12 2002/09/16 15:10:42 mohor
// MIIM test look better.
//
// Revision 1.11 2002/09/13 19:18:04 mohor
// Bench outputs data to display every 128 bytes.
//
// Revision 1.10 2002/09/13 18:44:29 mohor
// Beautiful tests merget together
//
// Revision 1.9 2002/09/13 18:41:45 mohor
// Rearanged testcases
//
// Revision 1.8 2002/09/13 14:50:15 mohor
// Bug in MIIM fixed.
//
// Revision 1.7 2002/09/13 12:29:14 mohor
// Headers changed.
//
// Revision 1.6 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
// Revision 1.2 2002/07/19 14:02:47 mohor
// Clock mrx_clk set to 2.5 MHz.
//
// Revision 1.1 2002/07/19 13:57:53 mohor
// Testing environment also includes traffic cop, memory interface and host
// interface.
//
//
//
//
//
 
 
`include "eth_phy_defines.v"
`include "wb_model_defines.v"
`include "tb_eth_defines.v"
`include "eth_defines.v"
`include "timescale.v"
 
module tb_ethernet();
 
 
reg wb_clk;
reg wb_rst;
wire wb_int;
 
wire mtx_clk; // This goes to PHY
wire mrx_clk; // This goes to PHY
 
wire [3:0] MTxD;
wire MTxEn;
wire MTxErr;
 
wire [3:0] MRxD; // This goes to PHY
wire MRxDV; // This goes to PHY
wire MRxErr; // This goes to PHY
wire MColl; // This goes to PHY
wire MCrs; // This goes to PHY
 
wire Mdi_I;
wire Mdo_O;
wire Mdo_OE;
tri Mdio_IO;
wire Mdc_O;
 
 
parameter Tp = 1;
 
 
// Ethernet Slave Interface signals
wire [31:0] eth_sl_wb_adr;
wire [31:0] eth_sl_wb_adr_i, eth_sl_wb_dat_o, eth_sl_wb_dat_i;
wire [3:0] eth_sl_wb_sel_i;
wire eth_sl_wb_we_i, eth_sl_wb_cyc_i, eth_sl_wb_stb_i, eth_sl_wb_ack_o, eth_sl_wb_err_o;
 
// Ethernet Master Interface signals
wire [31:0] eth_ma_wb_adr_o, eth_ma_wb_dat_i, eth_ma_wb_dat_o;
wire [3:0] eth_ma_wb_sel_o;
wire eth_ma_wb_we_o, eth_ma_wb_cyc_o, eth_ma_wb_stb_o, eth_ma_wb_ack_i, eth_ma_wb_err_i;
 
 
 
 
// Connecting Ethernet top module
eth_top eth_top
(
// WISHBONE common
.wb_clk_i(wb_clk), .wb_rst_i(wb_rst),
 
// WISHBONE slave
.wb_adr_i(eth_sl_wb_adr_i[11:2]), .wb_sel_i(eth_sl_wb_sel_i), .wb_we_i(eth_sl_wb_we_i),
.wb_cyc_i(eth_sl_wb_cyc_i), .wb_stb_i(eth_sl_wb_stb_i), .wb_ack_o(eth_sl_wb_ack_o),
.wb_err_o(eth_sl_wb_err_o), .wb_dat_i(eth_sl_wb_dat_i), .wb_dat_o(eth_sl_wb_dat_o),
// WISHBONE master
.m_wb_adr_o(eth_ma_wb_adr_o), .m_wb_sel_o(eth_ma_wb_sel_o), .m_wb_we_o(eth_ma_wb_we_o),
.m_wb_dat_i(eth_ma_wb_dat_i), .m_wb_dat_o(eth_ma_wb_dat_o), .m_wb_cyc_o(eth_ma_wb_cyc_o),
.m_wb_stb_o(eth_ma_wb_stb_o), .m_wb_ack_i(eth_ma_wb_ack_i), .m_wb_err_i(eth_ma_wb_err_i),
 
//TX
.mtx_clk_pad_i(mtx_clk), .mtxd_pad_o(MTxD), .mtxen_pad_o(MTxEn), .mtxerr_pad_o(MTxErr),
 
//RX
.mrx_clk_pad_i(mrx_clk), .mrxd_pad_i(MRxD), .mrxdv_pad_i(MRxDV), .mrxerr_pad_i(MRxErr),
.mcoll_pad_i(MColl), .mcrs_pad_i(MCrs),
// MIIM
.mdc_pad_o(Mdc_O), .md_pad_i(Mdi_I), .md_pad_o(Mdo_O), .md_padoe_o(Mdo_OE),
.int_o(wb_int)
 
// Bist
`ifdef ETH_BIST
,
.scanb_rst (1'b0),
.scanb_clk (1'b0),
.scanb_si (1'b0),
.scanb_so (),
.scanb_en (1'b0)
`endif
);
 
 
 
// Connecting Ethernet PHY Module
assign Mdio_IO = Mdo_OE ? Mdo_O : 1'bz ;
assign Mdi_I = Mdio_IO;
integer phy_log_file_desc;
 
eth_phy eth_phy
(
// WISHBONE reset
.m_rst_n_i(!wb_rst),
 
// MAC TX
.mtx_clk_o(mtx_clk), .mtxd_i(MTxD), .mtxen_i(MTxEn), .mtxerr_i(MTxErr),
 
// MAC RX
.mrx_clk_o(mrx_clk), .mrxd_o(MRxD), .mrxdv_o(MRxDV), .mrxerr_o(MRxErr),
.mcoll_o(MColl), .mcrs_o(MCrs),
 
// MIIM
.mdc_i(Mdc_O), .md_io(Mdio_IO),
 
// SYSTEM
.phy_log(phy_log_file_desc)
);
 
 
 
// Connecting WB Master as Host Interface
integer host_log_file_desc;
 
WB_MASTER_BEHAVIORAL wb_master
(
.CLK_I(wb_clk),
.RST_I(wb_rst),
.TAG_I({`WB_TAG_WIDTH{1'b0}}),
.TAG_O(),
.ACK_I(eth_sl_wb_ack_o),
.ADR_O(eth_sl_wb_adr), // only eth_sl_wb_adr_i[11:2] used
.CYC_O(eth_sl_wb_cyc_i),
.DAT_I(eth_sl_wb_dat_o),
.DAT_O(eth_sl_wb_dat_i),
.ERR_I(eth_sl_wb_err_o),
.RTY_I(1'b0), // inactive (1'b0)
.SEL_O(eth_sl_wb_sel_i),
.STB_O(eth_sl_wb_stb_i),
.WE_O (eth_sl_wb_we_i),
.CAB_O() // NOT USED for now!
);
 
assign eth_sl_wb_adr_i = {20'h0, eth_sl_wb_adr[11:2], 2'h0};
 
 
 
// Connecting WB Slave as Memory Interface Module
integer memory_log_file_desc;
 
WB_SLAVE_BEHAVIORAL wb_slave
(
.CLK_I(wb_clk),
.RST_I(wb_rst),
.ACK_O(eth_ma_wb_ack_i),
.ADR_I(eth_ma_wb_adr_o),
.CYC_I(eth_ma_wb_cyc_o),
.DAT_O(eth_ma_wb_dat_i),
.DAT_I(eth_ma_wb_dat_o),
.ERR_O(eth_ma_wb_err_i),
.RTY_O(), // NOT USED for now!
.SEL_I(eth_ma_wb_sel_o),
.STB_I(eth_ma_wb_stb_o),
.WE_I (eth_ma_wb_we_o),
.CAB_I(1'b0) // inactive (1'b0)
);
 
 
 
// Connecting WISHBONE Bus Monitors to ethernet master and slave interfaces
integer wb_s_mon_log_file_desc ;
integer wb_m_mon_log_file_desc ;
 
WB_BUS_MON wb_eth_slave_bus_mon
(
// WISHBONE common
.CLK_I(wb_clk),
.RST_I(wb_rst),
 
// WISHBONE slave
.ACK_I(eth_sl_wb_ack_o),
.ADDR_O({20'h0, eth_sl_wb_adr_i[11:2], 2'b0}),
.CYC_O(eth_sl_wb_cyc_i),
.DAT_I(eth_sl_wb_dat_o),
.DAT_O(eth_sl_wb_dat_i),
.ERR_I(eth_sl_wb_err_o),
.RTY_I(1'b0),
.SEL_O(eth_sl_wb_sel_i),
.STB_O(eth_sl_wb_stb_i),
.WE_O (eth_sl_wb_we_i),
.TAG_I({`WB_TAG_WIDTH{1'b0}}),
.TAG_O(),
.CAB_O(1'b0),
.log_file_desc (wb_s_mon_log_file_desc)
);
 
WB_BUS_MON wb_eth_master_bus_mon
(
// WISHBONE common
.CLK_I(wb_clk),
.RST_I(wb_rst),
 
// WISHBONE master
.ACK_I(eth_ma_wb_ack_i),
.ADDR_O(eth_ma_wb_adr_o),
.CYC_O(eth_ma_wb_cyc_o),
.DAT_I(eth_ma_wb_dat_i),
.DAT_O(eth_ma_wb_dat_o),
.ERR_I(eth_ma_wb_err_i),
.RTY_I(1'b0),
.SEL_O(eth_ma_wb_sel_o),
.STB_O(eth_ma_wb_stb_o),
.WE_O (eth_ma_wb_we_o),
.TAG_I({`WB_TAG_WIDTH{1'b0}}),
.TAG_O(),
.CAB_O(1'b0),
.log_file_desc(wb_m_mon_log_file_desc)
);
 
 
 
reg StartTB;
integer tb_log_file;
 
initial
begin
tb_log_file = $fopen("../log/eth_tb.log");
if (tb_log_file < 2)
begin
$display("*E Could not open/create testbench log file in ../log/ directory!");
$finish;
end
$fdisplay(tb_log_file, "========================== ETHERNET IP Core Testbench results ===========================");
$fdisplay(tb_log_file, " ");
 
phy_log_file_desc = $fopen("../log/eth_tb_phy.log");
if (phy_log_file_desc < 2)
begin
$fdisplay(tb_log_file, "*E Could not open/create eth_tb_phy.log file in ../log/ directory!");
$finish;
end
$fdisplay(phy_log_file_desc, "================ PHY Module Testbench access log ================");
$fdisplay(phy_log_file_desc, " ");
 
memory_log_file_desc = $fopen("../log/eth_tb_memory.log");
if (memory_log_file_desc < 2)
begin
$fdisplay(tb_log_file, "*E Could not open/create eth_tb_memory.log file in ../log/ directory!");
$finish;
end
$fdisplay(memory_log_file_desc, "=============== MEMORY Module Testbench access log ===============");
$fdisplay(memory_log_file_desc, " ");
 
host_log_file_desc = $fopen("../log/eth_tb_host.log");
if (host_log_file_desc < 2)
begin
$fdisplay(tb_log_file, "*E Could not open/create eth_tb_host.log file in ../log/ directory!");
$finish;
end
$fdisplay(host_log_file_desc, "================ HOST Module Testbench access log ================");
$fdisplay(host_log_file_desc, " ");
 
wb_s_mon_log_file_desc = $fopen("../log/eth_tb_wb_s_mon.log");
if (wb_s_mon_log_file_desc < 2)
begin
$fdisplay(tb_log_file, "*E Could not open/create eth_tb_wb_s_mon.log file in ../log/ directory!");
$finish;
end
$fdisplay(wb_s_mon_log_file_desc, "============== WISHBONE Slave Bus Monitor error log ==============");
$fdisplay(wb_s_mon_log_file_desc, " ");
$fdisplay(wb_s_mon_log_file_desc, " Only ERRONEOUS conditions are logged !");
$fdisplay(wb_s_mon_log_file_desc, " ");
 
wb_m_mon_log_file_desc = $fopen("../log/eth_tb_wb_m_mon.log");
if (wb_m_mon_log_file_desc < 2)
begin
$fdisplay(tb_log_file, "*E Could not open/create eth_tb_wb_m_mon.log file in ../log/ directory!");
$finish;
end
$fdisplay(wb_m_mon_log_file_desc, "============= WISHBONE Master Bus Monitor error log =============");
$fdisplay(wb_m_mon_log_file_desc, " ");
$fdisplay(wb_m_mon_log_file_desc, " Only ERRONEOUS conditions are logged !");
$fdisplay(wb_m_mon_log_file_desc, " ");
 
// Reset pulse
wb_rst = 1'b1;
#423 wb_rst = 1'b0;
 
// Clear memories
clear_memories;
clear_buffer_descriptors;
 
#423 StartTB = 1'b1;
end
 
 
 
// Generating wb_clk clock
initial
begin
wb_clk=0;
// forever #2.5 wb_clk = ~wb_clk; // 2*2.5 ns -> 200.0 MHz
forever #5 wb_clk = ~wb_clk; // 2*5 ns -> 100.0 MHz
// forever #10 wb_clk = ~wb_clk; // 2*10 ns -> 50.0 MHz
// forever #12.5 wb_clk = ~wb_clk; // 2*12.5 ns -> 40 MHz
// forever #15 wb_clk = ~wb_clk; // 2*10 ns -> 33.3 MHz
// forever #20 wb_clk = ~wb_clk; // 2*20 ns -> 25 MHz
// forever #25 wb_clk = ~wb_clk; // 2*25 ns -> 20.0 MHz
// forever #31.25 wb_clk = ~wb_clk; // 2*31.25 ns -> 16.0 MHz
// forever #50 wb_clk = ~wb_clk; // 2*50 ns -> 10.0 MHz
// forever #55 wb_clk = ~wb_clk; // 2*55 ns -> 9.1 MHz
end
 
 
 
integer tests_successfull;
integer tests_failed;
reg [799:0] test_name; // used for tb_log_file
 
reg [3:0] wbm_init_waits; // initial wait cycles between CYC_O and STB_O of WB Master
reg [3:0] wbm_subseq_waits; // subsequent wait cycles between STB_Os of WB Master
reg [2:0] wbs_waits; // wait cycles befor WB Slave responds
reg [7:0] wbs_retries; // if RTY response, then this is the number of retries before ACK
 
initial
begin
wait(StartTB); // Start of testbench
 
// Initial global values
tests_successfull = 0;
tests_failed = 0;
 
wbm_init_waits = 4'h1;
wbm_subseq_waits = 4'h3;
wbs_waits = 4'h1;
wbs_retries = 8'h2;
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
 
// Call tests
// ----------
// test_access_to_mac_reg(0, 3); // 0 - 3
// test_mii(0, 17); // 0 - 17
test_note("PHY generates ideal Carrier sense and Collision signals for following tests");
eth_phy.carrier_sense_real_delay(0);
// test_mac_full_duplex_transmit(8, 9); // 0 - (21)
test_mac_full_duplex_receive(8, 9);
// test_mac_full_duplex_flow(0, 0);
 
test_note("PHY generates 'real delayed' Carrier sense and Collision signals for following tests");
eth_phy.carrier_sense_real_delay(1);
 
 
// Finish test's logs
test_summary;
$display("\n\n END of SIMULATION");
$fclose(tb_log_file | phy_log_file_desc | memory_log_file_desc | host_log_file_desc);
$fclose(wb_s_mon_log_file_desc | wb_m_mon_log_file_desc);
 
$stop;
end
 
 
//////////////////////////////////////////////////////////////
// Test tasks
//////////////////////////////////////////////////////////////
 
task test_access_to_mac_reg;
input [31:0] start_task;
input [31:0] end_task;
integer bit_start_1;
integer bit_end_1;
integer bit_start_2;
integer bit_end_2;
integer num_of_reg;
integer i_addr;
integer i_data;
integer i_length;
integer tmp_data;
reg [31:0] tx_bd_num;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_data;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_tmp_data;
integer i;
integer i1;
integer i2;
integer i3;
integer fail;
integer test_num;
reg [31:0] addr;
reg [31:0] data;
reg [31:0] data_max;
begin
// ACCESS TO MAC REGISTERS TEST
test_heading("ACCESS TO MAC REGISTERS TEST");
$display(" ");
$display("ACCESS TO MAC REGISTERS TEST");
fail = 0;
 
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
 
 
//////////////////////////////////////////////////////////////////////
//// ////
//// test_access_to_mac_reg: ////
//// ////
//// 0: Walking 1 with single cycles across MAC regs. ////
//// 1: Walking 1 with single cycles across MAC buffer descript. ////
//// 2: Test max reg. values and reg. values after writing ////
//// inverse reset values and hard reset of the MAC ////
//// 3: Test buffer desc. RAM preserving values after hard reset ////
//// of the MAC and resetting the logic ////
//// ////
//////////////////////////////////////////////////////////////////////
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1)
begin
 
////////////////////////////////////////////////////////////////////
//// ////
//// Walking 1 with single cycles across MAC regs. ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 0) // Walking 1 with single cycles across MAC regs.
begin
// TEST 0: 'WALKING ONE' WITH SINGLE CYCLES ACROSS MAC REGISTERS ( VARIOUS BUS DELAYS )
test_name = "TEST 0: 'WALKING ONE' WITH SINGLE CYCLES ACROSS MAC REGISTERS ( VARIOUS BUS DELAYS )";
`TIME; $display(" TEST 0: 'WALKING ONE' WITH SINGLE CYCLES ACROSS MAC REGISTERS ( VARIOUS BUS DELAYS )");
data = 0;
for (i = 0; i <= 4; i = i + 1) // for initial wait cycles on WB bus
begin
wbm_init_waits = i;
wbm_subseq_waits = {$random} % 5; // it is not important for single accesses
for (i_addr = 0; i_addr <= 32'h4C; i_addr = i_addr + 4) // register address
begin
addr = `ETH_BASE + i_addr;
// set ranges of R/W bits
case (addr)
`ETH_MODER:
begin
bit_start_1 = 0;
bit_end_1 = 16;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_INT: // READONLY - tested within INT test
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_INT_MASK:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_IPGT:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_IPGR1:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_IPGR2:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_PACKETLEN:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_COLLCONF:
begin
bit_start_1 = 0;
bit_end_1 = 5;
bit_start_2 = 16;
bit_end_2 = 19;
end
`ETH_TX_BD_NUM:
begin
bit_start_1 = 0;
bit_end_1 = 7;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_CTRLMODER:
begin
bit_start_1 = 0;
bit_end_1 = 2;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIIMODER:
begin
bit_start_1 = 0;
bit_end_1 = 9;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIICOMMAND: // "WRITEONLY" - tested within MIIM test - 3 LSBits are not written here!!!
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIIADDRESS:
begin
bit_start_1 = 0;
bit_end_1 = 4;
bit_start_2 = 8;
bit_end_2 = 12;
end
`ETH_MIITX_DATA:
begin
bit_start_1 = 0;
bit_end_1 = 15;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIIRX_DATA: // READONLY - tested within MIIM test
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIISTATUS: // READONLY - tested within MIIM test
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MAC_ADDR0:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MAC_ADDR1:
begin
bit_start_1 = 0;
bit_end_1 = 15;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_HASH_ADDR0:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
default: // `ETH_HASH_ADDR1:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
endcase
for (i_data = 0; i_data <= 31; i_data = i_data + 1) // the position of walking one
begin
data = 1'b1 << i_data;
if ( (addr == `ETH_MIICOMMAND) && (i_data <= 2) ) // DO NOT WRITE to 3 LSBits of MIICOMMAND !!!
;
else
begin
wbm_write(addr, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i_data >= bit_start_1) && (i_data <= bit_end_1)) ||
((i_data >= bit_start_2) && (i_data <= bit_end_2)) ) // data should be equal to tmp_data
begin
if (tmp_data !== data)
begin
fail = fail + 1;
test_fail("RW bit of the MAC register was not written or not read");
`TIME;
$display("wbm_init_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, addr, data, tmp_data);
end
end
else // data should not be equal to tmp_data
begin
if (tmp_data === data)
begin
fail = fail + 1;
test_fail("NON RW bit of the MAC register was written, but it shouldn't be");
`TIME;
$display("wbm_init_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, addr, data, tmp_data);
end
end
end
end
end
end
// INTERMEDIATE DISPLAYS (The only one)
$display(" ->buffer descriptors tested with 0, 1, 2, 3 and 4 bus delay cycles");
if(fail == 0)
test_ok;
else
fail = 0; // Errors were reported previously
end
////////////////////////////////////////////////////////////////////
//// ////
//// Walking 1 with single cycles across MAC buffer descript. ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 1) // Start Walking 1 with single cycles across MAC buffer descript.
begin
// TEST 1: 'WALKING ONE' WITH SINGLE CYCLES ACROSS MAC BUFFER DESC. ( VARIOUS BUS DELAYS )
test_name = "TEST 1: 'WALKING ONE' WITH SINGLE CYCLES ACROSS MAC BUFFER DESC. ( VARIOUS BUS DELAYS )";
`TIME; $display(" TEST 1: 'WALKING ONE' WITH SINGLE CYCLES ACROSS MAC BUFFER DESC. ( VARIOUS BUS DELAYS )");
data = 0;
// set TX and RX buffer descriptors
tx_bd_num = 32'h40;
wbm_write(`ETH_TX_BD_NUM, tx_bd_num, 4'hF, 1, 0, 0);
for (i = 0; i <= 4; i = i + 1) // for initial wait cycles on WB bus
begin
wbm_init_waits = i;
wbm_subseq_waits = {$random} % 5; // it is not important for single accesses
for (i_addr = 32'h400; i_addr <= 32'h7FC; i_addr = i_addr + 4) // buffer descriptor address
begin
addr = `ETH_BASE + i_addr;
if (i_addr < (32'h400 + (tx_bd_num << 3))) // TX buffer descriptors
begin
// set ranges of R/W bits
case (addr[3])
1'b0: // buffer control bits
begin
bit_start_1 = 0;
bit_end_1 = 31; // 8;
bit_start_2 = 11;
bit_end_2 = 31;
end
default: // 1'b1: // buffer pointer
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
endcase
end
else // RX buffer descriptors
begin
// set ranges of R/W bits
case (addr[3])
1'b0: // buffer control bits
begin
bit_start_1 = 0;
bit_end_1 = 31; // 7;
bit_start_2 = 13;
bit_end_2 = 31;
end
default: // 1'b1: // buffer pointer
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
endcase
end
for (i_data = 0; i_data <= 31; i_data = i_data + 1) // the position of walking one
begin
data = 1'b1 << i_data;
if ( (addr[3] == 0) && (i_data == 15) ) // DO NOT WRITE to this bit !!!
;
else
begin
wbm_write(addr, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i_data >= bit_start_1) && (i_data <= bit_end_1)) ||
((i_data >= bit_start_2) && (i_data <= bit_end_2)) ) // data should be equal to tmp_data
begin
if (tmp_data !== data)
begin
fail = fail + 1;
test_fail("RW bit of the MAC buffer descriptors was not written or not read");
`TIME;
$display("wbm_init_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, addr, data, tmp_data);
end
end
else // data should not be equal to tmp_data
begin
if (tmp_data === data)
begin
fail = fail + 1;
test_fail("NON RW bit of the MAC buffer descriptors was written, but it shouldn't be");
`TIME;
$display("wbm_init_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, addr, data, tmp_data);
end
end
end
end
end
// INTERMEDIATE DISPLAYS
case (i)
0: $display(" ->buffer descriptors tested with 0 bus delay");
1: $display(" ->buffer descriptors tested with 1 bus delay cycle");
2: $display(" ->buffer descriptors tested with 2 bus delay cycles");
3: $display(" ->buffer descriptors tested with 3 bus delay cycles");
default: $display(" ->buffer descriptors tested with 4 bus delay cycles");
endcase
end
if(fail == 0)
test_ok;
else
fail = 0;
end
////////////////////////////////////////////////////////////////////
//// ////
//// Test max reg. values and reg. values after writing ////
//// inverse reset values and hard reset of the MAC ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 2) // Start this task
begin
// TEST 2: MAX REG. VALUES AND REG. VALUES AFTER WRITING INVERSE RESET VALUES AND HARD RESET OF THE MAC
test_name =
"TEST 2: MAX REG. VALUES AND REG. VALUES AFTER WRITING INVERSE RESET VALUES AND HARD RESET OF THE MAC";
`TIME; $display(
" TEST 2: MAX REG. VALUES AND REG. VALUES AFTER WRITING INVERSE RESET VALUES AND HARD RESET OF THE MAC");
// reset MAC registers
hard_reset;
for (i = 0; i <= 4; i = i + 1) // 0, 2 - WRITE; 1, 3, 4 - READ
begin
for (i_addr = 0; i_addr <= 32'h4C; i_addr = i_addr + 4) // register address
begin
addr = `ETH_BASE + i_addr;
// set ranges of R/W bits
case (addr)
`ETH_MODER:
begin
data = 32'h0000_A800;
data_max = 32'h0001_FFFF;
end
`ETH_INT: // READONLY - tested within INT test
begin
data = 32'h0000_0000;
data_max = 32'h0000_0000;
end
`ETH_INT_MASK:
begin
data = 32'h0000_0000;
data_max = 32'h0000_007F;
end
`ETH_IPGT:
begin
data = 32'h0000_0012;
data_max = 32'h0000_007F;
end
`ETH_IPGR1:
begin
data = 32'h0000_000C;
data_max = 32'h0000_007F;
end
`ETH_IPGR2:
begin
data = 32'h0000_0012;
data_max = 32'h0000_007F;
end
`ETH_PACKETLEN:
begin
data = 32'h0040_0600;
data_max = 32'hFFFF_FFFF;
end
`ETH_COLLCONF:
begin
data = 32'h000F_003F;
data_max = 32'h000F_003F;
end
`ETH_TX_BD_NUM:
begin
data = 32'h0000_0040;
data_max = 32'h0000_0080;
end
`ETH_CTRLMODER:
begin
data = 32'h0000_0000;
data_max = 32'h0000_0007;
end
`ETH_MIIMODER:
begin
data = 32'h0000_0064;
data_max = 32'h0000_03FF;
end
`ETH_MIICOMMAND: // "WRITEONLY" - tested within MIIM test - 3 LSBits are not written here!!!
begin
data = 32'h0000_0000;
data_max = 32'h0000_0007;
end
`ETH_MIIADDRESS:
begin
data = 32'h0000_0000;
data_max = 32'h0000_1F1F;
end
`ETH_MIITX_DATA:
begin
data = 32'h0000_0000;
data_max = 32'h0000_FFFF;
end
`ETH_MIIRX_DATA: // READONLY - tested within MIIM test
begin
data = 32'h0000_0000;
data_max = 32'h0000_0000;
end
`ETH_MIISTATUS: // READONLY - tested within MIIM test
begin
data = 32'h0000_0000;
data_max = 32'h0000_0000;
end
`ETH_MAC_ADDR0:
begin
data = 32'h0000_0000;
data_max = 32'hFFFF_FFFF;
end
`ETH_MAC_ADDR1:
begin
data = 32'h0000_0000;
data_max = 32'h0000_FFFF;
end
`ETH_HASH_ADDR0:
begin
data = 32'h0000_0000;
data_max = 32'hFFFF_FFFF;
end
default: // `ETH_HASH_ADDR1:
begin
data = 32'h0000_0000;
data_max = 32'hFFFF_FFFF;
end
endcase
wbm_init_waits = {$random} % 3;
wbm_subseq_waits = {$random} % 5; // it is not important for single accesses
if (i == 0)
wbm_write(addr, ~data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
else if (i == 2)
wbm_write(addr, 32'hFFFFFFFF, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
else if ((i == 1) || (i == 4))
begin
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== data)
begin
fail = fail + 1;
test_fail("RESET value of the MAC register is not correct");
`TIME;
$display(" addr %h, data %h, tmp_data %h", addr, data, tmp_data);
end
end
else // check maximum values
begin
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (addr == `ETH_TX_BD_NUM) // previous data should remain in this register
begin
if (tmp_data !== data)
begin
fail = fail + 1;
test_fail("Previous value of the TX_BD_NUM register did not remain");
`TIME;
$display(" addr %h, data_max %h, tmp_data %h", addr, data_max, tmp_data);
end
// try maximum (80)
wbm_write(addr, data_max, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== data_max)
begin
fail = fail + 1;
test_fail("MAX value of the TX_BD_NUM register is not correct");
`TIME;
$display(" addr %h, data_max %h, tmp_data %h", addr, data_max, tmp_data);
end
// try one less than maximum (80)
wbm_write(addr, (data_max - 1), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== (data_max - 1))
begin
fail = fail + 1;
test_fail("ONE less than MAX value of the TX_BD_NUM register is not correct");
`TIME;
$display(" addr %h, data_max %h, tmp_data %h", addr, data_max, tmp_data);
end
// try one more than maximum (80)
wbm_write(addr, (data_max + 1), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== (data_max - 1)) // previous data should remain in this register
begin
fail = fail + 1;
test_fail("Previous value of the TX_BD_NUM register did not remain");
`TIME;
$display(" addr %h, data_max %h, tmp_data %h", addr, data_max, tmp_data);
end
end
else
begin
if (tmp_data !== data_max)
begin
fail = fail + 1;
test_fail("MAX value of the MAC register is not correct");
`TIME;
$display(" addr %h, data_max %h, tmp_data %h", addr, data_max, tmp_data);
end
end
end
end
// reset MAC registers
if ((i == 0) || (i == 3))
hard_reset;
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test buffer desc. ram preserving values after hard reset ////
//// of the mac and reseting the logic ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 3) // Start this task
begin
// TEST 3: BUFFER DESC. RAM PRESERVING VALUES AFTER HARD RESET OF THE MAC AND RESETING THE LOGIC
test_name = "TEST 3: BUFFER DESC. RAM PRESERVING VALUES AFTER HARD RESET OF THE MAC AND RESETING THE LOGIC";
`TIME;
$display(" TEST 3: BUFFER DESC. RAM PRESERVING VALUES AFTER HARD RESET OF THE MAC AND RESETING THE LOGIC");
// reset MAC registers
hard_reset;
// reset LOGIC with soft reset
reset_mac;
reset_mii;
for (i = 0; i <= 3; i = i + 1) // 0, 2 - WRITE; 1, 3 - READ
begin
for (i_addr = 32'h400; i_addr <= 32'h7FC; i_addr = i_addr + 4) // buffer descriptor address
begin
addr = `ETH_BASE + i_addr;
wbm_init_waits = {$random} % 3;
wbm_subseq_waits = {$random} % 5; // it is not important for single accesses
if (i == 0)
begin
data = 32'hFFFFFFFF;
wbm_write(addr, 32'hFFFFFFFF, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if (i == 2)
begin
data = 32'h00000000;
wbm_write(addr, 32'h00000000, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else
begin
wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== data)
begin
fail = fail + 1;
test_fail("PRESERVED value of the MAC buffer descriptors is not correct");
`TIME;
$display(" addr %h, data %h, tmp_data %h", addr, data, tmp_data);
end
end
end
if ((i == 0) || (i == 2))
begin
// reset MAC registers
hard_reset;
// reset LOGIC with soft reset
reset_mac;
reset_mii;
end
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
if (test_num == 4) // Start this task
begin
/* // TEST 4: 'WALKING ONE' WITH BURST CYCLES ACROSS MAC REGISTERS ( VARIOUS BUS DELAYS )
test_name = "TEST 4: 'WALKING ONE' WITH BURST CYCLES ACROSS MAC REGISTERS ( VARIOUS BUS DELAYS )";
`TIME; $display(" TEST 4: 'WALKING ONE' WITH BURST CYCLES ACROSS MAC REGISTERS ( VARIOUS BUS DELAYS )");
data = 0;
burst_data = 0;
burst_tmp_data = 0;
i_length = 10; // two bursts for length 20
for (i = 0; i <= 4; i = i + 1) // for initial wait cycles on WB bus
begin
for (i1 = 0; i1 <= 4; i1 = i1 + 1) // for initial wait cycles on WB bus
begin
wbm_init_waits = i;
wbm_subseq_waits = i1;
#1;
for (i_data = 0; i_data <= 31; i_data = i_data + 1) // the position of walking one
begin
data = 1'b1 << i_data;
#1;
for (i2 = 32'h4C; i2 >= 0; i2 = i2 - 4)
begin
burst_data = burst_data << 32;
// DO NOT WRITE to 3 LSBits of MIICOMMAND !!!
if ( ((`ETH_BASE + i2) == `ETH_MIICOMMAND) && (i_data <= 2) )
begin
#1 burst_data[31:0] = 0;
end
else
begin
#1 burst_data[31:0] = data;
end
end
#1;
// 2 burst writes
addr = `ETH_BASE; // address of a first burst
wbm_write(addr, burst_data[(32 * 10 - 1):0], 4'hF, i_length, wbm_init_waits, wbm_subseq_waits);
burst_tmp_data = burst_data >> (32 * i_length);
addr = addr + 32'h28; // address of a second burst
wbm_write(addr, burst_tmp_data[(32 * 10 - 1):0], 4'hF, i_length, wbm_init_waits, wbm_subseq_waits);
#1;
// 2 burst reads
addr = `ETH_BASE; // address of a first burst
wbm_read(addr, burst_tmp_data[(32 * 10 - 1):0], 4'hF, i_length,
wbm_init_waits, wbm_subseq_waits); // first burst
burst_tmp_data = burst_tmp_data << (32 * i_length);
addr = addr + 32'h28; // address of a second burst
wbm_read(addr, burst_tmp_data[(32 * 10 - 1):0], 4'hF, i_length,
wbm_init_waits, wbm_subseq_waits); // second burst
#1;
for (i2 = 0; i2 <= 32'h4C; i2 = i2 + 4)
begin
// set ranges of R/W bits
case (`ETH_BASE + i2)
`ETH_MODER:
begin
bit_start_1 = 0;
bit_end_1 = 16;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_INT: // READONLY - tested within INT test
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_INT_MASK:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_IPGT:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_IPGR1:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_IPGR2:
begin
bit_start_1 = 0;
bit_end_1 = 6;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_PACKETLEN:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_COLLCONF:
begin
bit_start_1 = 0;
bit_end_1 = 5;
bit_start_2 = 16;
bit_end_2 = 19;
end
`ETH_TX_BD_NUM:
begin
bit_start_1 = 0;
bit_end_1 = 7;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_CTRLMODER:
begin
bit_start_1 = 0;
bit_end_1 = 2;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIIMODER:
begin
bit_start_1 = 0;
bit_end_1 = 9;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIICOMMAND: // "WRITEONLY" - tested within MIIM test - 3 LSBits are not written here!!!
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIIADDRESS:
begin
bit_start_1 = 0;
bit_end_1 = 4;
bit_start_2 = 8;
bit_end_2 = 12;
end
`ETH_MIITX_DATA:
begin
bit_start_1 = 0;
bit_end_1 = 15;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIIRX_DATA: // READONLY - tested within MIIM test
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MIISTATUS: // READONLY - tested within MIIM test
begin
bit_start_1 = 32; // not used
bit_end_1 = 32; // not used
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MAC_ADDR0:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_MAC_ADDR1:
begin
bit_start_1 = 0;
bit_end_1 = 15;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
`ETH_HASH_ADDR0:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
default: // `ETH_HASH_ADDR1:
begin
bit_start_1 = 0;
bit_end_1 = 31;
bit_start_2 = 32; // not used
bit_end_2 = 32; // not used
end
endcase
#1;
// 3 LSBits of MIICOMMAND are NOT written !!!
if ( ((`ETH_BASE + i2) == `ETH_MIICOMMAND) && (i_data <= 2) )
begin
if (burst_tmp_data[31:0] !== burst_data[31:0])
begin
fail = fail + 1;
test_fail("NON WR bit of the MAC MIICOMMAND register was wrong written or read");
`TIME;
$display("wbm_init_waits %d, wbm_subseq_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, wbm_subseq_waits, i2, burst_data[31:0], burst_tmp_data[31:0]);
end
end
else
begin
if ( ((i_data >= bit_start_1) && (i_data <= bit_end_1)) ||
((i_data >= bit_start_2) && (i_data <= bit_end_2)) ) // data should be equal to tmp_data
begin
if (burst_tmp_data[31:0] !== burst_data[31:0])
begin
fail = fail + 1;
test_fail("RW bit of the MAC register was not written or not read");
`TIME;
$display("wbm_init_waits %d, wbm_subseq_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, wbm_subseq_waits, i2, burst_data[31:0], burst_tmp_data[31:0]);
end
end
else // data should not be equal to tmp_data
begin
if (burst_tmp_data[31:0] === burst_data[31:0])
begin
fail = fail + 1;
test_fail("NON RW bit of the MAC register was written, but it shouldn't be");
`TIME;
$display("wbm_init_waits %d, wbm_subseq_waits %d, addr %h, data %h, tmp_data %h",
wbm_init_waits, wbm_subseq_waits, i2, burst_data[31:0], burst_tmp_data[31:0]);
end
end
end
burst_tmp_data = burst_tmp_data >> 32;
burst_data = burst_data >> 32;
end
end
end
end
if(fail == 0)
test_ok;
else
fail = 0;*/
end
 
end
 
end
endtask // test_access_to_mac_reg
 
 
task test_mii;
input [31:0] start_task;
input [31:0] end_task;
integer i;
integer i1;
integer i2;
integer i3;
integer cnt;
integer fail;
integer test_num;
reg [8:0] clk_div; // only 8 bits are valid!
reg [4:0] phy_addr;
reg [4:0] reg_addr;
reg [15:0] phy_data;
reg [15:0] tmp_data;
begin
// MIIM MODULE TEST
test_heading("MIIM MODULE TEST");
$display(" ");
$display("MIIM MODULE TEST");
fail = 0;
 
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
 
 
//////////////////////////////////////////////////////////////////////
//// ////
//// test_mii: ////
//// ////
//// 0: Test clock divider of mii management module with all ////
//// possible frequences. ////
//// 1: Test various readings from 'real' phy registers. ////
//// 2: Test various writings to 'real' phy registers (control ////
//// and non writable registers) ////
//// 3: Test reset phy through mii management module ////
//// 4: Test 'walking one' across phy address (with and without ////
//// preamble) ////
//// 5: Test 'walking one' across phy's register address (with ////
//// and without preamble) ////
//// 6: Test 'walking one' across phy's data (with and without ////
//// preamble) ////
//// 7: Test reading from phy with wrong phy address (host ////
//// reading high 'z' data) ////
//// 8: Test writing to phy with wrong phy address and reading ////
//// from correct one ////
//// 9: Test sliding stop scan command immediately after read ////
//// request (with and without preamble) ////
//// 10: Test sliding stop scan command immediately after write ////
//// request (with and without preamble) ////
//// 11: Test busy and nvalid status durations during write ////
//// (with and without preamble) ////
//// 12: Test busy and nvalid status durations during write ////
//// (with and without preamble) ////
//// 13: Test busy and nvalid status durations during scan (with ////
//// and without preamble) ////
//// 14: Test scan status from phy with detecting link-fail bit ////
//// (with and without preamble) ////
//// 15: Test scan status from phy with sliding link-fail bit ////
//// (with and without preamble) ////
//// 16: Test sliding stop scan command immediately after scan ////
//// request (with and without preamble) ////
//// 17: Test sliding stop scan command after 2. scan (with and ////
//// without preamble) ////
//// ////
//////////////////////////////////////////////////////////////////////
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1)
begin
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test clock divider of mii management module with all ////
//// possible frequences. ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 0) // Test clock divider of mii management module with all possible frequences.
begin
// TEST 0: CLOCK DIVIDER OF MII MANAGEMENT MODULE WITH ALL POSSIBLE FREQUENCES
test_name = "TEST 0: CLOCK DIVIDER OF MII MANAGEMENT MODULE WITH ALL POSSIBLE FREQUENCES";
`TIME; $display(" TEST 0: CLOCK DIVIDER OF MII MANAGEMENT MODULE WITH ALL POSSIBLE FREQUENCES");
wait(Mdc_O); // wait for MII clock to be 1
for(clk_div = 0; clk_div <= 255; clk_div = clk_div + 1)
begin
i1 = 0;
i2 = 0;
#Tp mii_set_clk_div(clk_div[7:0]);
@(posedge Mdc_O);
#Tp;
fork
begin
@(posedge Mdc_O);
#Tp;
disable count_i1;
disable count_i2;
end
begin: count_i1
forever
begin
@(posedge wb_clk);
i1 = i1 + 1;
#Tp;
end
end
begin: count_i2
forever
begin
@(negedge wb_clk);
i2 = i2 + 1;
#Tp;
end
end
join
if((clk_div[7:0] == 0) || (clk_div[7:0] == 1) || (clk_div[7:0] == 2) || (clk_div[7:0] == 3))
begin
if((i1 == i2) && (i1 == 2))
begin
end
else
begin
fail = fail + 1;
test_fail("Clock divider of MII module did'nt divide frequency corectly (it should divide by 2)");
end
end
else
begin
if((i1 == i2) && (i1 == {clk_div[7:1], 1'b0}))
begin
end
else
begin
fail = fail + 1;
test_fail("Clock divider of MII module did'nt divide frequency corectly");
end
end
end
if(fail == 0)
test_ok;
else
fail = 0;
end
////////////////////////////////////////////////////////////////////
//// ////
//// Test various readings from 'real' phy registers. ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 1) // Test various readings from 'real' phy registers.
begin
// TEST 1: VARIOUS READINGS FROM 'REAL' PHY REGISTERS
test_name = "TEST 1: VARIOUS READINGS FROM 'REAL' PHY REGISTERS";
`TIME; $display(" TEST 1: VARIOUS READINGS FROM 'REAL' PHY REGISTERS");
// set the fastest possible MII
clk_div = 0;
mii_set_clk_div(clk_div[7:0]);
// set address
reg_addr = 5'h1F;
phy_addr = 5'h1;
while(reg_addr >= 5'h4)
begin
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== 16'hDEAD)
begin
test_fail("Wrong data was read from PHY from 'not used' address space");
fail = fail + 1;
end
if (reg_addr == 5'h4) // go out of for loop
reg_addr = 5'h3;
else
reg_addr = reg_addr - 5'h9;
end
// set address
reg_addr = 5'h3;
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM})
begin
test_fail("Wrong data was read from PHY from ID register 2");
fail = fail + 1;
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test various writings to 'real' phy registers (control ////
//// and non writable registers) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 2) //
begin
// TEST 2: VARIOUS WRITINGS TO 'REAL' PHY REGISTERS ( CONTROL AND NON WRITABLE REGISTERS )
test_name = "TEST 2: VARIOUS WRITINGS TO 'REAL' PHY REGISTERS ( CONTROL AND NON WRITABLE REGISTERS )";
`TIME; $display(" TEST 2: VARIOUS WRITINGS TO 'REAL' PHY REGISTERS ( CONTROL AND NON WRITABLE REGISTERS )");
// negate data and try to write into unwritable register
tmp_data = ~phy_data;
// write request
#Tp mii_write_req(phy_addr, reg_addr, tmp_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== phy_data)
begin
test_fail("Data was written into unwritable PHY register - ID register 2");
fail = fail + 1;
end
// set address
reg_addr = 5'h0; // control register
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// write request
phy_data = 16'h7DFF; // bit 15 (RESET bit) and bit 9 are self clearing bits
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== 16'h7DFF)
begin
test_fail("Data was not correctly written into OR read from writable PHY register - control register");
fail = fail + 1;
end
// write request
#Tp mii_write_req(phy_addr, reg_addr, tmp_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from writable PHY register - control register");
fail = fail + 1;
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test reset phy through mii management module ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 3) //
begin
// TEST 3: RESET PHY THROUGH MII MANAGEMENT MODULE
test_name = "TEST 3: RESET PHY THROUGH MII MANAGEMENT MODULE";
`TIME; $display(" TEST 3: RESET PHY THROUGH MII MANAGEMENT MODULE");
// set address
reg_addr = 5'h0; // control register
// write request
phy_data = 16'h7DFF; // bit 15 (RESET bit) and bit 9 are self clearing bits
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from writable PHY register - control register");
fail = fail + 1;
end
// set reset bit - selfclearing bit in PHY
phy_data = phy_data | 16'h8000;
// write request
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check self clearing of reset bit
if (tmp_data[15] !== 1'b0)
begin
test_fail("Reset bit should be self cleared - control register");
fail = fail + 1;
end
// check reset value of control register
if (tmp_data !== {2'h0, (`LED_CFG1 || `LED_CFG2), `LED_CFG1, 3'h0, `LED_CFG3, 8'h0})
begin
test_fail("PHY was not reset correctly AND/OR reset bit not self cleared");
fail = fail + 1;
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test 'walking one' across phy address (with and without ////
//// preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 4) //
begin
// TEST 4: 'WALKING ONE' ACROSS PHY ADDRESS ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 4: 'WALKING ONE' ACROSS PHY ADDRESS ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 4: 'WALKING ONE' ACROSS PHY ADDRESS ( WITH AND WITHOUT PREAMBLE )");
// set PHY to test mode
#Tp eth_phy.test_regs(1); // set test registers (wholy writable registers) and respond to all PHY addresses
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
#Tp eth_phy.clear_test_regs;
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
// walk one across phy address
for (phy_addr = 5'h1; phy_addr > 5'h0; phy_addr = phy_addr << 1)
begin
reg_addr = $random;
tmp_data = $random;
// write request
#Tp mii_write_req(phy_addr, reg_addr, tmp_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
#Tp;
if (phy_data !== tmp_data)
begin
if (i)
test_fail("Data was not correctly written into OR read from test registers (without preamble)");
else
test_fail("Data was not correctly written into OR read from test registers (with preamble)");
fail = fail + 1;
end
@(posedge wb_clk);
#Tp;
end
end
// set PHY to normal mode
#Tp eth_phy.test_regs(0);
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test 'walking one' across phy's register address (with ////
//// and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 5) //
begin
// TEST 5: 'WALKING ONE' ACROSS PHY'S REGISTER ADDRESS ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 5: 'WALKING ONE' ACROSS PHY'S REGISTER ADDRESS ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 5: 'WALKING ONE' ACROSS PHY'S REGISTER ADDRESS ( WITH AND WITHOUT PREAMBLE )");
// set PHY to test mode
#Tp eth_phy.test_regs(1); // set test registers (wholy writable registers) and respond to all PHY addresses
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
#Tp eth_phy.clear_test_regs;
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
// walk one across reg address
for (reg_addr = 5'h1; reg_addr > 5'h0; reg_addr = reg_addr << 1)
begin
phy_addr = $random;
tmp_data = $random;
// write request
#Tp mii_write_req(phy_addr, reg_addr, tmp_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
#Tp;
if (phy_data !== tmp_data)
begin
if (i)
test_fail("Data was not correctly written into OR read from test registers (without preamble)");
else
test_fail("Data was not correctly written into OR read from test registers (with preamble)");
fail = fail + 1;
end
@(posedge wb_clk);
#Tp;
end
end
// set PHY to normal mode
#Tp eth_phy.test_regs(0);
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test 'walking one' across phy's data (with and without ////
//// preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 6) //
begin
// TEST 6: 'WALKING ONE' ACROSS PHY'S DATA ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 6: 'WALKING ONE' ACROSS PHY'S DATA ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 6: 'WALKING ONE' ACROSS PHY'S DATA ( WITH AND WITHOUT PREAMBLE )");
// set PHY to test mode
#Tp eth_phy.test_regs(1); // set test registers (wholy writable registers) and respond to all PHY addresses
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
#Tp eth_phy.clear_test_regs;
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
// walk one across data
for (tmp_data = 16'h1; tmp_data > 16'h0; tmp_data = tmp_data << 1)
begin
phy_addr = $random;
reg_addr = $random;
// write request
#Tp mii_write_req(phy_addr, reg_addr, tmp_data);
check_mii_busy; // wait for write to finish
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
#Tp;
if (phy_data !== tmp_data)
begin
if (i)
test_fail("Data was not correctly written into OR read from test registers (without preamble)");
else
test_fail("Data was not correctly written into OR read from test registers (with preamble)");
fail = fail + 1;
end
@(posedge wb_clk);
#Tp;
end
end
// set PHY to normal mode
#Tp eth_phy.test_regs(0);
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test reading from phy with wrong phy address (host ////
//// reading high 'z' data) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 7) //
begin
// TEST 7: READING FROM PHY WITH WRONG PHY ADDRESS ( HOST READING HIGH 'Z' DATA )
test_name = "TEST 7: READING FROM PHY WITH WRONG PHY ADDRESS ( HOST READING HIGH 'Z' DATA )";
`TIME; $display(" TEST 7: READING FROM PHY WITH WRONG PHY ADDRESS ( HOST READING HIGH 'Z' DATA )");
phy_addr = 5'h2; // wrong PHY address
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
$display(" => Two errors will be displayed from WB Bus Monitor, because correct HIGH Z data was read");
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp_data !== 16'hzzzz)
begin
test_fail("Data was read from PHY register with wrong PHY address - control register");
fail = fail + 1;
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test writing to phy with wrong phy address and reading ////
//// from correct one ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 8) //
begin
// TEST 8: WRITING TO PHY WITH WRONG PHY ADDRESS AND READING FROM CORRECT ONE
test_name = "TEST 8: WRITING TO PHY WITH WRONG PHY ADDRESS AND READING FROM CORRECT ONE";
`TIME; $display(" TEST 8: WRITING TO PHY WITH WRONG PHY ADDRESS AND READING FROM CORRECT ONE");
// set address
reg_addr = 5'h0; // control register
phy_addr = 5'h2; // wrong PHY address
// write request
phy_data = 16'h7DFF; // bit 15 (RESET bit) and bit 9 are self clearing bits
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
check_mii_busy; // wait for write to finish
phy_addr = 5'h1; // correct PHY address
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data === tmp_data)
begin
test_fail("Data was written into PHY register with wrong PHY address - control register");
fail = fail + 1;
end
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test sliding stop scan command immediately after read ////
//// request (with and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 9) //
begin
// TEST 9: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER READ REQUEST ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 9: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER READ REQUEST ( WITH AND WITHOUT PREAMBLE )";
`TIME;
$display(" TEST 9: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER READ REQUEST ( WITH AND WITHOUT PREAMBLE )");
for (i2 = 0; i2 <= 1; i2 = i2 + 1) // choose preamble or not
begin
#Tp eth_phy.preamble_suppresed(i2);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i2, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
i = 0;
cnt = 0;
while (i < 80) // delay for sliding of writing a STOP SCAN command
begin
for (i3 = 0; i3 <= 1; i3 = i3 + 1) // choose read or write after read will be finished
begin
// set address
reg_addr = 5'h0; // control register
phy_addr = 5'h1; // correct PHY address
cnt = 0;
// read request
#Tp mii_read_req(phy_addr, reg_addr);
fork
begin
repeat(i) @(posedge Mdc_O);
// write command 0x0 into MII command register
// MII command written while read in progress
wbm_write(`ETH_MIICOMMAND, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
#Tp check_mii_busy; // wait for read to finish
end
begin
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
end
join
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Read request did not proceed correctly, while SCAN STOP command was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Read request did not proceed correctly, while SCAN STOP command was written");
fail = fail + 1;
end
end
// check the BUSY signal to see if the bus is still IDLE
for (i1 = 0; i1 < 8; i1 = i1 + 1)
check_mii_busy; // wait for bus to become idle
// try normal write or read after read was finished
#Tp phy_data = {8'h7D, (i[7:0] + 1)};
#Tp cnt = 0;
if (i3 == 0) // write after read
begin
// write request
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while(Mdio_IO !== 1'bz)
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
else // read after read
begin
// read request
#Tp mii_read_req(phy_addr, reg_addr);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
// check if transfer was a proper length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after read request");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after read request");
fail = fail + 1;
end
end
end
#Tp;
// set delay of writing the command
if (i2) // without preamble
begin
case(i)
0, 1: i = i + 1;
18, 19, 20, 21, 22,
23, 24, 25, 26, 27,
28, 29, 30, 31, 32,
33, 34, 35: i = i + 1;
36: i = 80;
default: i = 18;
endcase
end
else // with preamble
begin
case(i)
0, 1: i = i + 1;
50, 51, 52, 53, 54,
55, 56, 57, 58, 59,
60, 61, 62, 63, 64,
65, 66, 67: i = i + 1;
68: i = 80;
default: i = 50;
endcase
end
@(posedge wb_clk);
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test sliding stop scan command immediately after write ////
//// request (with and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 10) //
begin
// TEST 10: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER WRITE REQUEST ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 10: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER WRITE REQUEST ( WITH AND WITHOUT PREAMBLE )";
`TIME;
$display(" TEST 10: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER WRITE REQUEST ( WITH AND WITHOUT PREAMBLE )");
for (i2 = 0; i2 <= 1; i2 = i2 + 1) // choose preamble or not
begin
#Tp eth_phy.preamble_suppresed(i2);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i2, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
i = 0;
cnt = 0;
while (i < 80) // delay for sliding of writing a STOP SCAN command
begin
for (i3 = 0; i3 <= 1; i3 = i3 + 1) // choose read or write after write will be finished
begin
// set address
reg_addr = 5'h0; // control register
phy_addr = 5'h1; // correct PHY address
cnt = 0;
// write request
phy_data = {8'h75, (i[7:0] + 1)};
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
fork
begin
repeat(i) @(posedge Mdc_O);
// write command 0x0 into MII command register
// MII command written while read in progress
wbm_write(`ETH_MIICOMMAND, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
#Tp check_mii_busy; // wait for write to finish
end
begin
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while(Mdio_IO !== 1'bz)
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
end
join
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Write request did not proceed correctly, while SCAN STOP command was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Write request did not proceed correctly, while SCAN STOP command was written");
fail = fail + 1;
end
end
// check the BUSY signal to see if the bus is still IDLE
for (i1 = 0; i1 < 8; i1 = i1 + 1)
check_mii_busy; // wait for bus to become idle
// try normal write or read after write was finished
#Tp cnt = 0;
if (i3 == 0) // write after write
begin
phy_data = {8'h7A, (i[7:0] + 1)};
// write request
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while(Mdio_IO !== 1'bz)
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data , 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
else // read after write
begin
// read request
#Tp mii_read_req(phy_addr, reg_addr);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data , 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
// check if transfer was a proper length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after write request");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after write request");
fail = fail + 1;
end
end
end
#Tp;
// set delay of writing the command
if (i2) // without preamble
begin
case(i)
0, 1: i = i + 1;
18, 19, 20, 21, 22,
23, 24, 25, 26, 27,
28, 29, 30, 31, 32,
33, 34, 35: i = i + 1;
36: i = 80;
default: i = 18;
endcase
end
else // with preamble
begin
case(i)
0, 1: i = i + 1;
50, 51, 52, 53, 54,
55, 56, 57, 58, 59,
60, 61, 62, 63, 64,
65, 66, 67: i = i + 1;
68: i = 80;
default: i = 50;
endcase
end
@(posedge wb_clk);
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test busy and nvalid status durations during write (with ////
//// and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 11) //
begin
// TEST 11: BUSY AND NVALID STATUS DURATIONS DURING WRITE ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 11: BUSY AND NVALID STATUS DURATIONS DURING WRITE ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 11: BUSY AND NVALID STATUS DURATIONS DURING WRITE ( WITH AND WITHOUT PREAMBLE )");
reset_mii; // reset MII
// set link up, if it wasn't due to previous tests, since there weren't PHY registers
#Tp eth_phy.link_up_down(1);
// set the MII
clk_div = 64;
mii_set_clk_div(clk_div[7:0]);
// set address
reg_addr = 5'h1; // status register
phy_addr = 5'h1; // correct PHY address
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}) | (`ETH_MIIMODER_CLKDIV & clk_div),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge Mdc_O);
// write request
#Tp mii_write_req(phy_addr, reg_addr, 16'h5A5A);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z anymore - 1. read");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
else // Busy bit should already be set to '1', due to reads from MII status register
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set after write, due to reads from MII status register");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer bits
if (i)
begin
repeat(32) @(posedge Mdc_O);
end
else
begin
repeat(64) @(posedge Mdc_O);
end
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO === 1'bz) // Mdio_IO should not be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal is not active anymore");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
else // Busy bit should still be set to '1'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
// wait for next negative clock edge
@(negedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to early, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
else // Busy bit should still be set to '1'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set after MII IO signal become HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
// wait for Busy to become inactive
i1 = 0;
while (i1 <= 2)
begin
// wait for next positive clock edge
@(posedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to early, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during write");
fail = fail + 1;
end
end
else // wait for Busy bit to be set to '0'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
i1 = 3; // end of Busy checking
end
else
begin
if (i1 == 2)
begin
test_fail("Busy signal should be cleared after 2 periods after MII IO signal become HIGH Z");
fail = fail + 1;
end
#Tp i1 = i1 + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set after write");
fail = fail + 1;
end
end
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test busy and nvalid status durations during write (with ////
//// and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 12) //
begin
// TEST 12: BUSY AND NVALID STATUS DURATIONS DURING READ ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 12: BUSY AND NVALID STATUS DURATIONS DURING READ ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 12: BUSY AND NVALID STATUS DURATIONS DURING READ ( WITH AND WITHOUT PREAMBLE )");
reset_mii; // reset MII
// set link up, if it wasn't due to previous tests, since there weren't PHY registers
#Tp eth_phy.link_up_down(1);
// set the MII
clk_div = 64;
mii_set_clk_div(clk_div[7:0]);
// set address
reg_addr = 5'h1; // status register
phy_addr = 5'h1; // correct PHY address
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}) | (`ETH_MIIMODER_CLKDIV & clk_div),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge Mdc_O);
// read request
#Tp mii_read_req(phy_addr, reg_addr);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z anymore - 1. read");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
else // Busy bit should already be set to '1', due to reads from MII status register
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set after read, due to reads from MII status register");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer bits
if (i)
begin
repeat(31) @(posedge Mdc_O);
end
else
begin
repeat(63) @(posedge Mdc_O);
end
// wait for next negative clock edge
@(negedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO === 1'bz) // Mdio_IO should not be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal is not active anymore");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
else // Busy bit should still be set to '1'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
// wait for next positive clock edge
@(posedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to early, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
else // Busy bit should still be set to '1'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set after MII IO signal become HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
// wait for Busy to become inactive
i1 = 0;
while (i1 <= 2)
begin
// wait for next positive clock edge
@(posedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to early, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set during read");
fail = fail + 1;
end
end
else // wait for Busy bit to be set to '0'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
i1 = 3; // end of Busy checking
end
else
begin
if (i1 == 2)
begin
test_fail("Busy signal should be cleared after 2 periods after MII IO signal become HIGH Z");
fail = fail + 1;
end
#Tp i1 = i1 + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] !== 1'b0)
begin
test_fail("Nvalid signal was set after read");
fail = fail + 1;
end
end
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test busy and nvalid status durations during scan (with ////
//// and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 13) //
begin
// TEST 13: BUSY AND NVALID STATUS DURATIONS DURING SCAN ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 13: BUSY AND NVALID STATUS DURATIONS DURING SCAN ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 13: BUSY AND NVALID STATUS DURATIONS DURING SCAN ( WITH AND WITHOUT PREAMBLE )");
reset_mii; // reset MII
// set link up, if it wasn't due to previous tests, since there weren't PHY registers
#Tp eth_phy.link_up_down(1);
// set the MII
clk_div = 64;
mii_set_clk_div(clk_div[7:0]);
// set address
reg_addr = 5'h1; // status register
phy_addr = 5'h1; // correct PHY address
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}) | (`ETH_MIIMODER_CLKDIV & clk_div),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge Mdc_O);
// scan request
#Tp mii_scan_req(phy_addr, reg_addr);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z anymore - 1. read");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
test_fail("Nvalid signal was not set while MII IO signal is not HIGH Z anymore - 1. read");
fail = fail + 1;
end
end
else // Busy bit should already be set to '1', due to reads from MII status register
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set after scan, due to reads from MII status register");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
test_fail("Nvalid signal should be set after scan, due to reads from MII status register");
fail = fail + 1;
end
end
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer bits
if (i)
begin
repeat(21) @(posedge Mdc_O);
end
else
begin
repeat(53) @(posedge Mdc_O);
end
// stop scan
#Tp mii_scan_finish; // finish scan operation
// wait for next positive clock edge
repeat(10) @(posedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO === 1'bz) // Mdio_IO should not be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal is not active anymore");
fail = fail + 1;
end
// Nvalid signal can be cleared here - it is still Testbench error
end
else // Busy bit should still be set to '1', Nvalid bit should still be set to '1'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
test_fail("Nvalid signal should be set while MII IO signal not HIGH Z");
fail = fail + 1;
end
end
// wait for next negative clock edge
@(negedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO === 1'bz) // Mdio_IO should not be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to late, Mdio_IO is HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal is not active anymore");
fail = fail + 1;
end
// Nvalid signal can be cleared here - it is still Testbench error
end
else // Busy bit should still be set to '1', Nvalid bit should still be set to '1'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set while MII IO signal not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
test_fail("Nvalid signal should be set while MII IO signal not HIGH Z");
fail = fail + 1;
end
end
// wait for next negative clock edge
@(posedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to early, Mdio_IO is not HIGH Z - set higher clock divider");
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
test_fail("Nvalid signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
end
else // Busy bit should still be set to '1', Nvalid bit can be set to '0'
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal should be set after MII IO signal become HIGH Z");
fail = fail + 1;
end
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
i2 = 1; // check finished
end
else
begin
i2 = 0; // check must continue
end
end
// wait for Busy to become inactive
i1 = 0;
while ((i1 <= 2) || (i2 == 0))
begin
// wait for next positive clock edge
@(posedge Mdc_O);
// read data from MII status register - Busy and Nvalid bits
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check MII IO signal and Busy and Nvalid bits
if (Mdio_IO !== 1'bz) // Mdio_IO should be HIGH Z here - testbench selfcheck
begin
test_fail("Testbench error - read was to early, Mdio_IO is not HIGH Z - set higher clock divider");
if (i1 <= 2)
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
test_fail("Busy signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
end
if (i2 == 0)
begin
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
test_fail("Nvalid signal was not set while MII IO signal is not HIGH Z");
fail = fail + 1;
end
end
end
else // wait for Busy bit to be set to '0'
begin
if (i1 <= 2)
begin
if (phy_data[`ETH_MIISTATUS_BUSY] === 1'b0)
begin
i1 = 3; // end of Busy checking
end
else
begin
if (i1 == 2)
begin
test_fail("Busy signal should be cleared after 2 periods after MII IO signal become HIGH Z");
fail = fail + 1;
end
#Tp i1 = i1 + 1;
end
end
if (i2 == 0)
begin
if (phy_data[`ETH_MIISTATUS_NVALID] === 1'b0)
begin
i2 = 1;
end
else
begin
test_fail("Nvalid signal should be cleared after MII IO signal become HIGH Z");
fail = fail + 1;
end
end
end
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test scan status from phy with detecting link-fail bit ////
//// (with and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 14) //
begin
// TEST 14: SCAN STATUS FROM PHY WITH DETECTING LINK-FAIL BIT ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 14: SCAN STATUS FROM PHY WITH DETECTING LINK-FAIL BIT ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 14: SCAN STATUS FROM PHY WITH DETECTING LINK-FAIL BIT ( WITH AND WITHOUT PREAMBLE )");
reset_mii; // reset MII
// set link up, if it wasn't due to previous tests, since there weren't PHY registers
#Tp eth_phy.link_up_down(1);
// set MII speed
clk_div = 6;
mii_set_clk_div(clk_div[7:0]);
// set address
reg_addr = 5'h1; // status register
phy_addr = 5'h1; // correct PHY address
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data from PHY status register - remember LINK-UP status
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
for (i = 0; i <= 1; i = i + 1)
begin
#Tp eth_phy.preamble_suppresed(i);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i, 8'h0}) | (`ETH_MIIMODER_CLKDIV & clk_div),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (i)
begin
// change saved data when preamble is suppressed
#Tp tmp_data = tmp_data | 16'h0040; // put bit 6 to ONE
end
// scan request
#Tp mii_scan_req(phy_addr, reg_addr);
check_mii_scan_valid; // wait for scan to make first data valid
fork
begin
repeat(2) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
end
begin
// Completely check second scan
#Tp cnt = 0;
// wait for serial bus to become active - second scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i == 0)) || ((cnt == 15) && (i == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Second scan request did not proceed correctly");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Second scan request did not proceed correctly");
fail = fail + 1;
end
end
end
join
// check third to fifth scans
for (i3 = 0; i3 <= 2; i3 = i3 + 1)
begin
fork
begin
repeat(2) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
if (i3 == 2) // after fourth scan read
begin
@(posedge Mdc_O);
// change saved data
#Tp tmp_data = tmp_data & 16'hFFFB; // put bit 3 to ZERO
// set link down
#Tp eth_phy.link_up_down(0);
end
end
begin
// Completely check scans
#Tp cnt = 0;
// wait for serial bus to become active - second scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i == 0)) || ((cnt == 15) && (i == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Fifth scan request did not proceed correctly");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Fifth scan request did not proceed correctly");
fail = fail + 1;
end
end
end
join
end
fork
begin
repeat(2) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] === 1'b0)
begin
test_fail("Link FAIL bit was not set in the MII status register");
fail = fail + 1;
end
// wait to see if data stayed latched
repeat(4) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not latched correctly in status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] === 1'b0)
begin
test_fail("Link FAIL bit was not set in the MII status register");
fail = fail + 1;
end
// change saved data
#Tp tmp_data = tmp_data | 16'h0004; // put bit 2 to ONE
// set link up
#Tp eth_phy.link_up_down(1);
end
begin
// Wait for sixth scan
// wait for serial bus to become active - sixth scan
wait(Mdio_IO !== 1'bz);
// wait for serial bus to become inactive - turn-around cycle in sixth scan
wait(Mdio_IO === 1'bz);
// wait for serial bus to become active - end of turn-around cycle in sixth scan
wait(Mdio_IO !== 1'bz);
// wait for serial bus to become inactive - end of sixth scan
wait(Mdio_IO === 1'bz);
end
join
@(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
// wait to see if data stayed latched
repeat(4) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
// STOP SCAN
#Tp mii_scan_finish; // finish scan operation
#Tp check_mii_busy; // wait for scan to finish
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test scan status from phy with sliding link-fail bit ////
//// (with and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 15) //
begin
// TEST 15: SCAN STATUS FROM PHY WITH SLIDING LINK-FAIL BIT ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 15: SCAN STATUS FROM PHY WITH SLIDING LINK-FAIL BIT ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 15: SCAN STATUS FROM PHY WITH SLIDING LINK-FAIL BIT ( WITH AND WITHOUT PREAMBLE )");
// set address
reg_addr = 5'h1; // status register
phy_addr = 5'h1; // correct PHY address
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read data from PHY status register - remember LINK-UP status
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
for (i2 = 0; i2 <= 1; i2 = i2 + 1) // choose preamble or not
begin
#Tp eth_phy.preamble_suppresed(i2);
// MII mode register
#Tp wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i2, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
if (i2)
begin
// change saved data when preamble is suppressed
#Tp tmp_data = tmp_data | 16'h0040; // put bit 6 to ONE
end
i = 0;
while (i < 80) // delay for sliding of LinkFail bit
begin
// first there are two scans
#Tp cnt = 0;
// scan request
#Tp mii_scan_req(phy_addr, reg_addr);
#Tp check_mii_scan_valid; // wait for scan to make first data valid
// check second scan
fork
begin
repeat(4) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Second data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
end
begin
// Completely check scan
#Tp cnt = 0;
// wait for serial bus to become active - second scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Second scan request did not proceed correctly");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Second scan request did not proceed correctly");
fail = fail + 1;
end
end
end
join
// reset counter
#Tp cnt = 0;
// SLIDING LINK DOWN and CHECK
fork
begin
// set link down
repeat(i) @(posedge Mdc_O);
// set link down
#Tp eth_phy.link_up_down(0);
end
begin
// check data in MII registers after each scan in this fork statement
if (i2) // without preamble
wait (cnt == 32);
else // with preamble
wait (cnt == 64);
repeat(3) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i < 49) && !i2) || ((i < 17) && i2) )
begin
if (phy_data !== (tmp_data & 16'hFFFB)) // bit 3 is ZERO
begin
test_fail("Third data was not correctly scaned from status register");
fail = fail + 1;
end
end
else
begin
if (phy_data !== tmp_data)
begin
test_fail("Third data was not correctly scaned from status register");
fail = fail + 1;
end
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i < 49) && !i2) || ((i < 17) && i2) )
begin
if (phy_data[0] === 1'b0)
begin
test_fail("Link FAIL bit was not set in the MII status register");
fail = fail + 1;
end
end
else
begin
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
end
end
begin
// check length
for (i3 = 0; i3 <= 1; i3 = i3 + 1) // two scans
begin
#Tp cnt = 0;
// wait for serial bus to become active if there is more than one scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("3. or 4. scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("3. or 4. scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
end
end
join
// reset counter
#Tp cnt = 0;
// check fifth scan and data from fourth scan
fork
begin
repeat(2) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== (tmp_data & 16'hFFFB)) // bit 3 is ZERO
begin
test_fail("4. data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] === 1'b0)
begin
test_fail("Link FAIL bit was not set in the MII status register");
fail = fail + 1;
end
end
begin
// Completely check intermediate scan
#Tp cnt = 0;
// wait for serial bus to become active - second scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Fifth scan request did not proceed correctly");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Fifth scan request did not proceed correctly");
fail = fail + 1;
end
end
end
join
// reset counter
#Tp cnt = 0;
// SLIDING LINK UP and CHECK
fork
begin
// set link up
repeat(i) @(posedge Mdc_O);
// set link up
#Tp eth_phy.link_up_down(1);
end
begin
// check data in MII registers after each scan in this fork statement
repeat(2) @(posedge Mdc_O);
if (i2) // without preamble
wait (cnt == 32);
else // with preamble
wait (cnt == 64);
repeat(3) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i < 49) && !i2) || ((i < 17) && i2) )
begin
if (phy_data !== tmp_data)
begin
test_fail("6. data was not correctly scaned from status register");
fail = fail + 1;
end
end
else
begin
if (phy_data !== (tmp_data & 16'hFFFB)) // bit 3 is ZERO
begin
test_fail("6. data was not correctly scaned from status register");
fail = fail + 1;
end
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i < 49) && !i2) || ((i < 17) && i2) )
begin
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
end
else
begin
if (phy_data[0] === 1'b0)
begin
test_fail("Link FAIL bit was not set in the MII status register");
fail = fail + 1;
end
end
end
begin
// check length
for (i3 = 0; i3 <= 1; i3 = i3 + 1) // two scans
begin
#Tp cnt = 0;
// wait for serial bus to become active if there is more than one scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("Scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("Scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
end
end
join
// check last scan
repeat(4) @(posedge Mdc_O);
// read data from PHY status register
#Tp wbm_read(`ETH_MIIRX_DATA, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("7. data was not correctly scaned from status register");
fail = fail + 1;
end
// read data from MII status register
#Tp wbm_read(`ETH_MIISTATUS, phy_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data[0] !== 1'b0)
begin
test_fail("Link FAIL bit was set in the MII status register");
fail = fail + 1;
end
#Tp mii_scan_finish; // finish scan operation
#Tp check_mii_busy; // wait for scan to finish
#Tp;
// set delay of writing the command
if (i2) // without preamble
begin
case(i)
0, 1, 2, 3, 4: i = i + 1;
13, 14, 15, 16, 17,
18, 19, 20, 21, 22,
23, 24, 25, 26, 27,
28, 29, 30, 31, 32,
33, 34, 35: i = i + 1;
36: i = 80;
default: i = 13;
endcase
end
else // with preamble
begin
case(i)
0, 1, 2, 3, 4: i = i + 1;
45, 46, 47, 48, 49,
50, 51, 52, 53, 54,
55, 56, 57, 58, 59,
60, 61, 62, 63, 64,
65, 66, 67: i = i + 1;
68: i = 80;
default: i = 45;
endcase
end
@(posedge wb_clk);
#Tp;
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test sliding stop scan command immediately after scan ////
//// request (with and without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 16) //
begin
// TEST 16: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER SCAN REQUEST ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 16: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER SCAN REQUEST ( WITH AND WITHOUT PREAMBLE )";
`TIME;
$display(" TEST 16: SLIDING STOP SCAN COMMAND IMMEDIATELY AFTER SCAN REQUEST ( WITH AND WITHOUT PREAMBLE )");
for (i2 = 0; i2 <= 1; i2 = i2 + 1) // choose preamble or not
begin
#Tp eth_phy.preamble_suppresed(i2);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i2, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
i = 0;
cnt = 0;
while (i < 80) // delay for sliding of writing a STOP SCAN command
begin
for (i3 = 0; i3 <= 1; i3 = i3 + 1) // choose read or write after scan will be finished
begin
// set address
reg_addr = 5'h0; // control register
phy_addr = 5'h1; // correct PHY address
cnt = 0;
// scan request
#Tp mii_scan_req(phy_addr, reg_addr);
fork
begin
repeat(i) @(posedge Mdc_O);
// write command 0x0 into MII command register
// MII command written while scan in progress
wbm_write(`ETH_MIICOMMAND, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
#Tp check_mii_busy; // wait for scan to finish
@(posedge wb_clk);
disable check;
end
begin: check
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
cnt = 0;
// wait for serial bus to become active if there is more than one scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
end
join
// check the BUSY signal to see if the bus is still IDLE
for (i1 = 0; i1 < 8; i1 = i1 + 1)
check_mii_busy; // wait for bus to become idle
// try normal write or read after scan was finished
phy_data = {8'h7D, (i[7:0] + 1)};
cnt = 0;
if (i3 == 0) // write after scan
begin
// write request
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while(Mdio_IO !== 1'bz)
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
else // read after scan
begin
// read request
#Tp mii_read_req(phy_addr, reg_addr);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
// check if transfer was a proper length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after scan request");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after scan request");
fail = fail + 1;
end
end
end
#Tp;
// set delay of writing the command
if (i2) // without preamble
begin
case(i)
0, 1: i = i + 1;
18, 19, 20, 21, 22,
23, 24, 25, 26, 27,
28, 29, 30, 31, 32,
33, 34, 35: i = i + 1;
36: i = 80;
default: i = 18;
endcase
end
else // with preamble
begin
case(i)
0, 1: i = i + 1;
50, 51, 52, 53, 54,
55, 56, 57, 58, 59,
60, 61, 62, 63, 64,
65, 66, 67: i = i + 1;
68: i = 80;
default: i = 50;
endcase
end
@(posedge wb_clk);
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test sliding stop scan command after 2. scan (with and ////
//// without preamble) ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 17) //
begin
// TEST 17: SLIDING STOP SCAN COMMAND AFTER 2. SCAN ( WITH AND WITHOUT PREAMBLE )
test_name = "TEST 17: SLIDING STOP SCAN COMMAND AFTER 2. SCAN ( WITH AND WITHOUT PREAMBLE )";
`TIME; $display(" TEST 17: SLIDING STOP SCAN COMMAND AFTER 2. SCAN ( WITH AND WITHOUT PREAMBLE )");
for (i2 = 0; i2 <= 1; i2 = i2 + 1) // choose preamble or not
begin
#Tp eth_phy.preamble_suppresed(i2);
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_NOPRE & {23'h0, i2, 8'h0}), 4'hF, 1, wbm_init_waits,
wbm_subseq_waits);
i = 0;
cnt = 0;
while (i < 80) // delay for sliding of writing a STOP SCAN command
begin
for (i3 = 0; i3 <= 1; i3 = i3 + 1) // choose read or write after scan will be finished
begin
// first there are two scans
// set address
reg_addr = 5'h0; // control register
phy_addr = 5'h1; // correct PHY address
cnt = 0;
// scan request
#Tp mii_scan_req(phy_addr, reg_addr);
// wait and check first 2 scans
begin
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
cnt = 0;
// wait for serial bus to become active if there is more than one scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
end
// reset counter
cnt = 0;
fork
begin
repeat(i) @(posedge Mdc_O);
// write command 0x0 into MII command register
// MII command written while scan in progress
wbm_write(`ETH_MIICOMMAND, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
#Tp check_mii_busy; // wait for scan to finish
@(posedge wb_clk);
disable check_3;
end
begin: check_3
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
cnt = 0;
// wait for serial bus to become active if there is more than one scan
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
// check transfer length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("First scan request did not proceed correctly, while SCAN STOP was written");
fail = fail + 1;
end
end
end
join
// check the BUSY signal to see if the bus is still IDLE
for (i1 = 0; i1 < 8; i1 = i1 + 1)
check_mii_busy; // wait for bus to become idle
// try normal write or read after scan was finished
phy_data = {8'h7D, (i[7:0] + 1)};
cnt = 0;
if (i3 == 0) // write after scan
begin
// write request
#Tp mii_write_req(phy_addr, reg_addr, phy_data);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while(Mdio_IO !== 1'bz)
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
// read request
#Tp mii_read_req(phy_addr, reg_addr);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
else // read after scan
begin
// read request
#Tp mii_read_req(phy_addr, reg_addr);
// wait for serial bus to become active
wait(Mdio_IO !== 1'bz);
// count transfer length
while( (Mdio_IO !== 1'bz) || ((cnt == 47) && (i2 == 0)) || ((cnt == 15) && (i2 == 1)) )
begin
@(posedge Mdc_O);
#Tp cnt = cnt + 1;
end
@(posedge Mdc_O);
check_mii_busy; // wait for read to finish
// read and check data
#Tp wbm_read(`ETH_MIIRX_DATA, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (phy_data !== tmp_data)
begin
test_fail("Data was not correctly written into OR read from PHY register - control register");
fail = fail + 1;
end
end
// check if transfer was a proper length
if (i2) // without preamble
begin
if (cnt != 33) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after scan request");
fail = fail + 1;
end
end
else // with preamble
begin
if (cnt != 65) // at this value Mdio_IO is HIGH Z
begin
test_fail("New request did not proceed correctly, after scan request");
fail = fail + 1;
end
end
end
#Tp;
// set delay of writing the command
if (i2) // without preamble
begin
case(i)
0, 1: i = i + 1;
18, 19, 20, 21, 22,
23, 24, 25, 26, 27,
28, 29, 30, 31, 32,
33, 34, 35: i = i + 1;
36: i = 80;
default: i = 18;
endcase
end
else // with preamble
begin
case(i)
0, 1: i = i + 1;
50, 51, 52, 53, 54,
55, 56, 57, 58, 59,
60, 61, 62, 63, 64,
65, 66, 67: i = i + 1;
68: i = 80;
default: i = 50;
endcase
end
@(posedge wb_clk);
end
end
// set PHY to normal mode
#Tp eth_phy.preamble_suppresed(0);
// MII mode register
wbm_write(`ETH_MIIMODER, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
end // for (test_num=start_task; test_num <= end_task; test_num=test_num+1)
 
end
endtask // test_mii
 
 
task test_mac_full_duplex_transmit;
input [31:0] start_task;
input [31:0] end_task;
integer bit_start_1;
integer bit_end_1;
integer bit_start_2;
integer bit_end_2;
integer num_of_reg;
integer num_of_frames;
integer num_of_bd;
integer i_addr;
integer i_data;
integer i_length;
integer tmp_len;
integer tmp_bd;
integer tmp_bd_num;
integer tmp_data;
integer tmp_ipgt;
integer test_num;
reg [31:0] tx_bd_num;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_data;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_tmp_data;
integer i;
integer i1;
integer i2;
integer i3;
integer fail;
integer speed;
reg frame_started;
reg frame_ended;
reg wait_for_frame;
reg [31:0] addr;
reg [31:0] data;
reg [31:0] tmp;
reg [ 7:0] st_data;
reg [15:0] max_tmp;
reg [15:0] min_tmp;
begin
// MAC FULL DUPLEX TRANSMIT TEST
test_heading("MAC FULL DUPLEX TRANSMIT TEST");
$display(" ");
$display("MAC FULL DUPLEX TRANSMIT TEST");
fail = 0;
 
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
/*
TASKS for set and control TX buffer descriptors (also send packet - set_tx_bd_ready):
-------------------------------------------------------------------------------------
set_tx_bd
(tx_bd_num_start[6:0], tx_bd_num_end[6:0], len[15:0], irq, pad, crc, txpnt[31:0]);
set_tx_bd_wrap
(tx_bd_num_end[6:0]);
set_tx_bd_ready
(tx_bd_num_start[6:0], tx_bd_num_end[6:0]);
check_tx_bd
(tx_bd_num_start[6:0], tx_bd_status[31:0]);
clear_tx_bd
(tx_bd_num_start[6:0], tx_bd_num_end[6:0]);
 
TASKS for set and control RX buffer descriptors:
------------------------------------------------
set_rx_bd
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0], irq, rxpnt[31:0]);
set_rx_bd_wrap
(rx_bd_num_end[6:0]);
set_rx_bd_empty
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0]);
check_rx_bd
(rx_bd_num_end[6:0], rx_bd_status);
clear_rx_bd
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0]);
 
TASKS for set and check TX packets:
-----------------------------------
set_tx_packet
(txpnt[31:0], len[15:0], eth_start_data[7:0]);
check_tx_packet
(txpnt_wb[31:0], txpnt_phy[31:0], len[15:0], failure[31:0]);
 
TASKS for set and check RX packets:
-----------------------------------
set_rx_packet
(rxpnt[31:0], len[15:0], plus_nibble, d_addr[47:0], s_addr[47:0], type_len[15:0], start_data[7:0]);
check_rx_packet
(rxpnt_phy[31:0], rxpnt_wb[31:0], len[15:0], plus_nibble, successful_nibble, failure[31:0]);
 
TASKS for append and check CRC to/of TX packet:
-----------------------------------------------
append_tx_crc
(txpnt_wb[31:0], len[15:0], negated_crc);
check_tx_crc
(txpnt_phy[31:0], len[15:0], negated_crc, failure[31:0]);
 
TASK for append CRC to RX packet (CRC is checked together with check_rx_packet):
--------------------------------------------------------------------------------
append_rx_crc
(rxpnt_phy[31:0], len[15:0], plus_nibble, negated_crc);
*/
 
//////////////////////////////////////////////////////////////////////
//// ////
//// test_mac_full_duplex_transmit: ////
//// ////
//// 0: Test no transmit when all buffers are RX ( 10Mbps ). ////
//// 1: Test no transmit when all buffers are RX ( 100Mbps ). ////
//// 2: Test transmit packets form MINFL to MAXFL sizes at ////
//// one TX buffer decriptor ( 10Mbps ). ////
//// 3: Test transmit packets form MINFL to MAXFL sizes at ////
//// one TX buffer decriptor ( 100Mbps ). ////
//// ////
//////////////////////////////////////////////////////////////////////
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1)
begin
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test no transmit when all buffers are RX ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 0) // Test no transmit when all buffers are RX ( 10Mbps ).
begin
// TEST 0: NO TRANSMIT WHEN ALL BUFFERS ARE RX ( 10Mbps )
test_name = "TEST 0: NO TRANSMIT WHEN ALL BUFFERS ARE RX ( 10Mbps )";
`TIME; $display(" TEST 0: NO TRANSMIT WHEN ALL BUFFERS ARE RX ( 10Mbps )");
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set all buffer descriptors to RX - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i = 0;
while (i < 128)
begin
for (i1 = 0; i1 <= i; i1 = i1 + 1)
begin
set_tx_packet((`MEMORY_BASE + (i1 * 200)), 100, 0);
set_tx_bd(i1, i1, 100, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + (i1 * 200)));
end
set_tx_bd_wrap(i);
fork
begin
set_tx_bd_ready(0, i);
repeat(20) @(negedge mtx_clk);
#1 disable check_tx_en10;
end
begin: check_tx_en10
wait (MTxEn === 1'b1);
test_fail("Tramsmit should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of %d packets should not start at all - active MTxEn", i);
end
join
for (i2 = 0; i2 < 20; i2 = i2 + 1)
begin
check_tx_bd(0, tmp);
#1;
if (tmp[15] === 1'b0)
begin
test_fail("Tramsmit should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of %d packets should not start at all - ready is 0", i);
end
if (tmp[8:0] !== 0)
begin
test_fail("Tramsmit should not be finished since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of should not be finished since it should not start at all");
end
@(posedge wb_clk);
end
wbm_read(`ETH_INT, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp[6:0] !== 0)
begin
test_fail("Tramsmit should not get INT since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of should not get INT since it should not start at all");
end
clear_tx_bd(0, i);
if ((i < 5) || (i > 124))
i = i + 1;
else
i = i + 120;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test no transmit when all buffers are RX ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 1) // Test no transmit when all buffers are RX ( 100Mbps ).
begin
// TEST 1: NO TRANSMIT WHEN ALL BUFFERS ARE RX ( 100Mbps )
test_name = "TEST 1: NO TRANSMIT WHEN ALL BUFFERS ARE RX ( 100Mbps )";
`TIME; $display(" TEST 1: NO TRANSMIT WHEN ALL BUFFERS ARE RX ( 100Mbps )");
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set all buffer descriptors to RX - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i = 0;
while (i < 128)
begin
for (i1 = 0; i1 <= i; i1 = i1 + 1)
begin
set_tx_packet((`MEMORY_BASE + (i1 * 200)), 100, 0);
set_tx_bd(i1, i1, 100, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + (i1 * 200)));
end
set_tx_bd_wrap(i);
fork
begin
set_tx_bd_ready(0, i);
repeat(20) @(negedge mtx_clk);
#1 disable check_tx_en100;
end
begin: check_tx_en100
wait (MTxEn === 1'b1);
test_fail("Tramsmit should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of %d packets should not start at all - active MTxEn", i);
end
join
for (i2 = 0; i2 < 20; i2 = i2 + 1)
begin
check_tx_bd(0, tmp);
#1;
if (tmp[15] === 1'b0)
begin
test_fail("Tramsmit should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of %d packets should not start at all - ready is 0", i);
end
if (tmp[8:0] !== 0)
begin
test_fail("Tramsmit should not be finished since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of should not be finished since it should not start at all");
end
@(posedge wb_clk);
end
wbm_read(`ETH_INT, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp[6:0] !== 0)
begin
test_fail("Tramsmit should not get INT since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Transmit of should not get INT since it should not start at all");
end
clear_tx_bd(0, i);
if ((i < 5) || (i > 124))
i = i + 1;
else
i = i + 120;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets form MINFL to MAXFL sizes at ////
//// one TX buffer decriptor ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 2) // without and with padding
begin
// TEST 2: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT ONE TX BD ( 10Mbps )
test_name = "TEST 2: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT ONE TX BD ( 10Mbps )";
`TIME; $display(" TEST 2: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT ONE TX BD ( 10Mbps )");
max_tmp = 0;
min_tmp = 0;
// set one TX buffer descriptor - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h1, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h01;
set_tx_packet(`MEMORY_BASE, (max_tmp), st_data); // length without CRC
st_data = 8'h10;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// choose generating carrier sense and collision for first and last 64 lengths of frames
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
eth_phy.set_tx_mem_addr(max_tmp);
// set wrap bit
set_tx_bd_wrap(0);
set_tx_bd_ready(0, 0);
#1 check_tx_bd(0, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_tx_bd(0, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else if (i_length > (max_tmp - 8)) // just last four
begin
tmp = 0;
wait (MTxEn === 1'b1); // start transmit
while (tmp < (i_length - 20))
begin
#1 tmp = tmp + 1;
@(posedge wb_clk);
end
#1 check_tx_bd(0, data);
while (data[15] === 1)
begin
#1 check_tx_bd(0, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MTxEn === 1'b1); // start transmit
#1 check_tx_bd(0, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(0, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
// check length of a PACKET
if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking in the following if statement is performed only for first and last 64 lengths
if ( ((i_length + 4) <= (min_tmp + 64)) || ((i_length + 4) > (max_tmp - 64)) )
begin
// check transmitted TX packet data
if (i_length[0] == 0)
begin
check_tx_packet((`MEMORY_BASE + i_length[1:0]), max_tmp, i_length, tmp);
end
else
begin
check_tx_packet(((`MEMORY_BASE + i_length[1:0]) + max_tmp), max_tmp, i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(max_tmp, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(0, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if (data[15:0] !== 16'h7800)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if (data[15:0] !== 16'h3800)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear TX buffer descriptor
clear_tx_bd(0, 0);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 64))
begin
// starting length is min_tmp, ending length is (min_tmp + 64)
$display(" pads appending to packets is NOT selected");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 64));
// set padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" pads appending to packets is selected");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
// reset padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" pads appending to packets is NOT selected");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 64))
i_length = i_length + 1;
else if ( ((i_length + 4) >= (min_tmp + 64)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets form MINFL to MAXFL sizes at ////
//// one TX buffer decriptor ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 3) // with and without padding
begin
// TEST 3: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT ONE TX BD ( 100Mbps )
test_name = "TEST 3: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT ONE TX BD ( 100Mbps )";
`TIME; $display(" TEST 3: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT ONE TX BD ( 100Mbps )");
max_tmp = 0;
min_tmp = 0;
// set one TX buffer descriptor - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h1, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h5A;
set_tx_packet(`MEMORY_BASE, (max_tmp), st_data); // length without CRC
st_data = 8'h10;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
 
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
eth_phy.set_tx_mem_addr(max_tmp);
// set wrap bit
set_tx_bd_wrap(0);
set_tx_bd_ready(0, 0);
#1 check_tx_bd(0, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_tx_bd(0, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else if (i_length > (max_tmp - 8)) // just last four
begin
tmp = 0;
wait (MTxEn === 1'b1); // start transmit
while (tmp < (i_length - 20))
begin
#1 tmp = tmp + 1;
@(posedge wb_clk);
end
#1 check_tx_bd(0, data);
while (data[15] === 1)
begin
#1 check_tx_bd(0, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MTxEn === 1'b1); // start transmit
#1 check_tx_bd(0, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(0, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
// check length of a PACKET
if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// check transmitted TX packet data
if (i_length[0] == 0)
begin
check_tx_packet((`MEMORY_BASE + i_length[1:0]), max_tmp, i_length, tmp);
end
else
begin
check_tx_packet(((`MEMORY_BASE + i_length[1:0]) + max_tmp), max_tmp, i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(max_tmp, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(0, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if (data[15:0] !== 16'h7800)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if (data[15:0] !== 16'h3800)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear TX buffer descriptor
clear_tx_bd(0, 0);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h", data);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 64))
begin
// starting length is min_tmp, ending length is (min_tmp + 64)
$display(" pads appending to packets is NOT selected");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 64));
// set padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" pads appending to packets is selected");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
// reset padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" pads appending to packets is NOT selected");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 64))
i_length = i_length + 1;
else if ( ((i_length + 4) >= (min_tmp + 64)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets form MINFL to MAXFL sizes at ////
//// maximum TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 4) // without and with padding
begin
// TEST 4: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT MAX TX BDs ( 10Mbps )
test_name = "TEST 4: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT MAX TX BDs ( 10Mbps )";
`TIME; $display(" TEST 4: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT MAX TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set maximum TX buffer descriptors (128) - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h80, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hA3;
set_tx_packet(`MEMORY_BASE, (max_tmp), st_data); // length without CRC
st_data = 8'h81;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
// first destination address on ethernet PHY
if (i_length[0] == 0)
eth_phy.set_tx_mem_addr(0);
else
eth_phy.set_tx_mem_addr(max_tmp);
// first 8 frames are transmitted with TX BD 0 (wrap bit on TX BD 0)
// number of all frames is 154 (146 without first 8)
if (num_of_frames < 8)
begin
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
endcase
// set wrap bit
set_tx_bd_wrap(0);
end
// after first 8 number of frames, 128 frames form TX BD 0 to 127 will be transmitted
else if ((num_of_frames - 8) == 0)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 128) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(127);
end
// after 128 + first 8 number of frames, 19 frames form TX BD 0 to 18 will be transmitted
else if ((num_of_frames - 8) == 20) // 128
begin
tmp_len = tmp_len; // length of frame remaines from previous settings
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 19) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
end
// set ready bit
if (num_of_frames < 8)
set_tx_bd_ready(0, 0);
else if ((num_of_frames - 8) < 128)
set_tx_bd_ready((num_of_frames - 8), (num_of_frames - 8));
else if ((num_of_frames - 136) < 19)
set_tx_bd_ready((num_of_frames - 136), (num_of_frames - 136));
// CHECK END OF TRANSMITION
#1 check_tx_bd(num_of_bd, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else if (i_length > (max_tmp - 8)) // just last four
begin
tmp = 0;
wait (MTxEn === 1'b1); // start transmit
while (tmp < (i_length - 20))
begin
#1 tmp = tmp + 1;
@(posedge wb_clk);
end
#1 check_tx_bd(num_of_bd, data);
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MTxEn === 1'b1); // start transmit
#1 check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
// check length of a PACKET
if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// check transmitted TX packet data
if (i_length[0] == 0)
begin
check_tx_packet((`MEMORY_BASE + i_length[1:0]), 0, i_length, tmp);
end
else
begin
check_tx_packet(((`MEMORY_BASE + i_length[1:0]) + max_tmp), max_tmp, i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
if (i_length[0] == 0)
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
else
check_tx_crc(max_tmp, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( ((data[15:0] !== 16'h7800) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( ((data[15:0] !== 16'h3800) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h1800) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear first half of 8 frames from TX buffer descriptor 0
if (num_of_frames < 4)
clear_tx_bd(num_of_bd, num_of_bd);
// clear BD with wrap bit
if (num_of_frames == 140)
clear_tx_bd(127, 127);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 7))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" pads appending to packets is NOT selected");
$display(" using only TX BD 0 out of 128 BDs assigned to TX (wrap at first BD - TX BD 0)");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 7));
$display(" ->all packets were send from TX BD 0");
// set padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (min_tmp + 128))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" pads appending to packets is NOT selected");
$display(" using all 128 BDs assigned to TX (wrap at 128th BD - TX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
(min_tmp + 8), (min_tmp + 128));
$display(" ->packets were send from TX BD %0d to TX BD %0d respectively",
1'b0, num_of_bd);
tmp_bd = num_of_bd + 1;
// set padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" pads appending to packets is selected");
$display(" using all 128 BDs assigned to TX (wrap at 128th BD - TX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
if (tmp_bd > num_of_bd)
$display(" ->packets were send from TX BD %0d to TX BD 127 and from TX BD 0 to TX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were send from TX BD %0d to TX BD %0d respectively",
tmp_bd, num_of_bd);
tmp_bd = num_of_bd + 1;
// reset padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" pads appending to packets is NOT selected");
$display(" using all 128 BDs assigned to TX (wrap at 128th BD - TX BD 127)");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
if (tmp_bd > num_of_bd)
$display(" ->packets were send from TX BD %0d to TX BD 127 and from TX BD 0 to TX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were send from TX BD %0d to TX BD %0d respectively",
tmp_bd, num_of_bd);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 128))
i_length = i_length + 1;
else if ( ((i_length + 4) == (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
i_length = 256;
else if ( ((i_length + 4) > (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if ((num_of_frames <= 8) || ((num_of_frames - 8) == 128))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets form MINFL to MAXFL sizes at ////
//// maximum TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 5) // with and without padding
begin
// TEST 5: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT MAX TX BDs ( 100Mbps )
test_name = "TEST 5: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT MAX TX BDs ( 100Mbps )";
`TIME; $display(" TEST 5: TRANSMIT PACKETS FROM MINFL TO MAXFL SIZES AT MAX TX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set maximum TX buffer descriptors (128) - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h80, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hA5;
set_tx_packet(`MEMORY_BASE, (max_tmp), st_data); // length without CRC
st_data = 8'h71;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
 
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
// first destination address on ethernet PHY
if (i_length[0] == 0)
eth_phy.set_tx_mem_addr(0);
else
eth_phy.set_tx_mem_addr(max_tmp);
// first 8 frames are transmitted with TX BD 0 (wrap bit on TX BD 0)
// number of all frames is 154 (146 without first 8)
if (num_of_frames < 8)
begin
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_tx_bd(0, 0, i_length, 1'b0, 1'b1, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
endcase
// set wrap bit
set_tx_bd_wrap(0);
end
// after first 8 number of frames, 128 frames form TX BD 0 to 127 will be transmitted
else if ((num_of_frames - 8) == 0)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 128) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(127);
end
// after 128 + first 8 number of frames, 19 frames form TX BD 0 to 18 will be transmitted
else if ((num_of_frames - 8) == 20) // 128
begin
tmp_len = tmp_len; // length of frame remaines from previous settings
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 19) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
end
// set ready bit
if (num_of_frames < 8)
set_tx_bd_ready(0, 0);
else if ((num_of_frames - 8) < 128)
set_tx_bd_ready((num_of_frames - 8), (num_of_frames - 8));
else if ((num_of_frames - 136) < 19)
set_tx_bd_ready((num_of_frames - 136), (num_of_frames - 136));
// CHECK END OF TRANSMITION
#1 check_tx_bd(num_of_bd, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else if (i_length > (max_tmp - 8)) // just last four
begin
tmp = 0;
wait (MTxEn === 1'b1); // start transmit
while (tmp < (i_length - 20))
begin
#1 tmp = tmp + 1;
@(posedge wb_clk);
end
#1 check_tx_bd(num_of_bd, data);
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MTxEn === 1'b1); // start transmit
#1 check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
// check length of a PACKET
if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking in the following if statement is performed only for first and last 64 lengths
// check transmitted TX packet data
if (i_length[0] == 0)
begin
check_tx_packet((`MEMORY_BASE + i_length[1:0]), 0, i_length, tmp);
end
else
begin
check_tx_packet(((`MEMORY_BASE + i_length[1:0]) + max_tmp), max_tmp, i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
if (i_length[0] == 0)
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
else
check_tx_crc(max_tmp, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( ((data[15:0] !== 16'h7800) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( ((data[15:0] !== 16'h3800) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h1800) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear first half of 8 frames from TX buffer descriptor 0
if (num_of_frames < 4)
clear_tx_bd(num_of_bd, num_of_bd);
// clear BD with wrap bit
if (num_of_frames == 140)
clear_tx_bd(127, 127);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 7))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" pads appending to packets is NOT selected");
$display(" using only TX BD 0 out of 128 BDs assigned to TX (wrap at first BD - TX BD 0)");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 7));
$display(" ->all packets were send from TX BD 0");
// set padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (min_tmp + 128))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" pads appending to packets is NOT selected");
$display(" using all 128 BDs assigned to TX (wrap at 128th BD - TX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
(min_tmp + 8), (min_tmp + 128));
$display(" ->packets were send from TX BD %0d to TX BD %0d respectively",
1'b0, num_of_bd);
tmp_bd = num_of_bd + 1;
// set padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" pads appending to packets is selected");
$display(" using all 128 BDs assigned to TX (wrap at 128th BD - TX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
if (tmp_bd > num_of_bd)
$display(" ->packets were send from TX BD %0d to TX BD 127 and from TX BD 0 to TX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were send from TX BD %0d to TX BD %0d respectively",
tmp_bd, num_of_bd);
tmp_bd = num_of_bd + 1;
// reset padding, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" pads appending to packets is NOT selected");
$display(" using all 128 BDs assigned to TX (wrap at 128th BD - TX BD 127)");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
if (tmp_bd > num_of_bd)
$display(" ->packets were send from TX BD %0d to TX BD 127 and from TX BD 0 to TX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were send from TX BD %0d to TX BD %0d respectively",
tmp_bd, num_of_bd);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 128))
i_length = i_length + 1;
else if ( ((i_length + 4) == (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
i_length = 256;
else if ( ((i_length + 4) > (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if ((num_of_frames <= 8) || ((num_of_frames - 8) == 128))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets form 0 to (MINFL - 1) sizes at ////
//// 8 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 6) //
begin
// TEST 6: TRANSMIT PACKETS FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 10Mbps )
test_name = "TEST 6: TRANSMIT PACKETS FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 10Mbps )";
`TIME; $display(" TEST 6: TRANSMIT PACKETS FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 8 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h8, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_PAD | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h12;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
st_data = 8'h34;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp - 4), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
frame_started = 0;
num_of_frames = 0;
num_of_bd = 0;
i_length = 0; // 0;
while (i_length < 70) // (min_tmp - 4))
begin
#1;
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
#1;
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(num_of_frames * 16);
// SET packets and wrap bit
// num_of_frames <= 9 => wrap set to TX BD 0
if (num_of_frames <= 9)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
// set wrap bit
set_tx_bd_wrap(0);
end
// 10 <= num_of_frames < 18 => wrap set to TX BD 3
else if ((num_of_frames == 10) || (num_of_frames == 14))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 4) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(3);
end
// 18 <= num_of_frames < 28 => wrap set to TX BD 4
else if ((num_of_frames == 18) || (num_of_frames == 23))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 5) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(4);
end
// 28 <= num_of_frames < 40 => wrap set to TX BD 5
else if ((num_of_frames == 28) || (num_of_frames == 34))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 6) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(5);
end
// 40 <= num_of_frames < 54 => wrap set to TX BD 6
else if ((num_of_frames == 40) || (num_of_frames == 47))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 7) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(6);
end
// 54 <= num_of_frames < 70 => wrap set to TX BD 7
else if ((num_of_frames == 54) || (num_of_frames == 62))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 8) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(7);
end
#1;
// SET ready bit
if (num_of_frames < 10)
set_tx_bd_ready(0, 0);
else if (num_of_frames < 14)
set_tx_bd_ready((num_of_frames - 10), (num_of_frames - 10));
else if (num_of_frames < 18)
set_tx_bd_ready((num_of_frames - 14), (num_of_frames - 14));
else if (num_of_frames < 23)
set_tx_bd_ready((num_of_frames - 18), (num_of_frames - 18));
else if (num_of_frames < 28)
set_tx_bd_ready((num_of_frames - 23), (num_of_frames - 23));
else if (num_of_frames < 34)
set_tx_bd_ready((num_of_frames - 28), (num_of_frames - 28));
else if (num_of_frames < 40)
set_tx_bd_ready((num_of_frames - 34), (num_of_frames - 34));
else if (num_of_frames < 47)
set_tx_bd_ready((num_of_frames - 40), (num_of_frames - 40));
else if (num_of_frames < 54)
set_tx_bd_ready((num_of_frames - 47), (num_of_frames - 47));
else if (num_of_frames < 62)
set_tx_bd_ready((num_of_frames - 54), (num_of_frames - 54));
else if (num_of_frames < 70)
set_tx_bd_ready((num_of_frames - 62), (num_of_frames - 62));
// CHECK END OF TRANSMITION
frame_started = 0;
if (num_of_frames >= 5)
#1 check_tx_bd(num_of_bd, data);
fork
begin: fr_st
wait (MTxEn === 1'b1); // start transmit
frame_started = 1;
end
begin
repeat (30) @(posedge mtx_clk);
if (num_of_frames < 5)
begin
if (frame_started == 1)
begin
`TIME; $display("*E Frame should NOT start!");
end
disable fr_st;
end
else
begin
if (frame_started == 0)
begin
`TIME; $display("*W Frame should start!");
disable fr_st;
end
end
end
join
// check packets larger than 4 bytes
if (num_of_frames >= 5)
begin
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
if (i_length <= (min_tmp - 4))
begin
if (eth_phy.tx_len != min_tmp)
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
end
else
begin
if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
end
// check transmitted TX packet data
if (i_length[0] == 0)
begin
#1 check_tx_packet(`MEMORY_BASE, (num_of_frames * 16), i_length, tmp);
end
else
begin
#1 check_tx_packet((`MEMORY_BASE + max_tmp), (num_of_frames * 16), i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
if (num_of_frames < (min_tmp - 4))
#1 check_tx_crc((num_of_frames * 16), (min_tmp - 4), 1'b0, tmp); // length without CRC
else
#1 check_tx_crc((num_of_frames * 16), i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
end
// check WB INT signal
if ((i_length[1:0] == 2'h0) && (num_of_frames >= 5))
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if (num_of_frames >= 5)
begin
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( (data[15:0] !== 16'h7800) && // wrap bit
(data[15:0] !== 16'h5800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( (data[15:0] !== 16'h3800) && // wrap bit
(data[15:0] !== 16'h1800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
end
else
begin
if (data[15] !== 1'b1)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear TX BD with wrap bit
if (num_of_frames == 63)
clear_tx_bd(16, 16);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1)) && (num_of_frames >= 5) )
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (i_length == 3)
begin
$display(" pads appending to packets is selected");
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packets with lengths from %0d to %0d are not transmitted (length increasing by 1 byte)",
0, 3);
end
else if (i_length == 9)
begin
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packet with length 4 is not transmitted (length increasing by 1 byte)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
5, 9);
end
else if (i_length == 17)
begin
$display(" using 4 BDs out of 8 BDs assigned to TX (wrap at 4th BD - TX BD 3)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
10, 17);
end
else if (i_length == 27)
begin
$display(" using 5 BDs out of 8 BDs assigned to TX (wrap at 5th BD - TX BD 4)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
18, 27);
end
else if (i_length == 40)
begin
$display(" using 6 BDs out of 8 BDs assigned to TX (wrap at 6th BD - TX BD 5)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
28, 40);
end
else if (i_length == 54)
begin
$display(" using 7 BDs out of 8 BDs assigned to TX (wrap at 7th BD - TX BD 6)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
41, 54);
end
else if (i_length == 69)
begin
$display(" using 8 BDs out of 8 BDs assigned to TX (wrap at 8th BD - TX BD 7)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if (/*(num_of_frames == 2) || (num_of_frames == 4) || (num_of_frames == 7) ||*/ (num_of_frames <= 10) ||
(num_of_frames == 14) || (num_of_frames == 18) || (num_of_frames == 23) || (num_of_frames == 28) ||
(num_of_frames == 34) || (num_of_frames == 40) || (num_of_frames == 47) ||
(num_of_frames == 54) || (num_of_frames == 62))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets form 0 to (MINFL - 1) sizes at ////
//// 8 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 7) //
begin
// TEST 7: TRANSMIT PACKETS FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 100Mbps )
test_name = "TEST 7: TRANSMIT PACKETS FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 100Mbps )";
`TIME; $display(" TEST 7: TRANSMIT PACKETS FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 8 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h8, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_PAD | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h12;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
st_data = 8'h34;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp - 4), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
frame_started = 0;
num_of_frames = 0;
num_of_bd = 0;
i_length = 0; // 0;
while (i_length < 70) // (min_tmp - 4))
begin
#1;
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
#1;
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(num_of_frames * 16);
// SET packets and wrap bit
// num_of_frames <= 9 => wrap set to TX BD 0
if (num_of_frames <= 9)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
// set wrap bit
set_tx_bd_wrap(0);
end
// 10 <= num_of_frames < 18 => wrap set to TX BD 3
else if ((num_of_frames == 10) || (num_of_frames == 14))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 4) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(3);
end
// 18 <= num_of_frames < 28 => wrap set to TX BD 4
else if ((num_of_frames == 18) || (num_of_frames == 23))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 5) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(4);
end
// 28 <= num_of_frames < 40 => wrap set to TX BD 5
else if ((num_of_frames == 28) || (num_of_frames == 34))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 6) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(5);
end
// 40 <= num_of_frames < 54 => wrap set to TX BD 6
else if ((num_of_frames == 40) || (num_of_frames == 47))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 7) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(6);
end
// 54 <= num_of_frames < 70 => wrap set to TX BD 7
else if ((num_of_frames == 54) || (num_of_frames == 62))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 8) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(7);
end
#1;
// SET ready bit
if (num_of_frames < 10)
set_tx_bd_ready(0, 0);
else if (num_of_frames < 14)
set_tx_bd_ready((num_of_frames - 10), (num_of_frames - 10));
else if (num_of_frames < 18)
set_tx_bd_ready((num_of_frames - 14), (num_of_frames - 14));
else if (num_of_frames < 23)
set_tx_bd_ready((num_of_frames - 18), (num_of_frames - 18));
else if (num_of_frames < 28)
set_tx_bd_ready((num_of_frames - 23), (num_of_frames - 23));
else if (num_of_frames < 34)
set_tx_bd_ready((num_of_frames - 28), (num_of_frames - 28));
else if (num_of_frames < 40)
set_tx_bd_ready((num_of_frames - 34), (num_of_frames - 34));
else if (num_of_frames < 47)
set_tx_bd_ready((num_of_frames - 40), (num_of_frames - 40));
else if (num_of_frames < 54)
set_tx_bd_ready((num_of_frames - 47), (num_of_frames - 47));
else if (num_of_frames < 62)
set_tx_bd_ready((num_of_frames - 54), (num_of_frames - 54));
else if (num_of_frames < 70)
set_tx_bd_ready((num_of_frames - 62), (num_of_frames - 62));
// CHECK END OF TRANSMITION
frame_started = 0;
if (num_of_frames >= 5)
#1 check_tx_bd(num_of_bd, data);
fork
begin: fr_st1
wait (MTxEn === 1'b1); // start transmit
frame_started = 1;
end
begin
repeat (30) @(posedge mtx_clk);
if (num_of_frames < 5)
begin
if (frame_started == 1)
begin
`TIME; $display("*E Frame should NOT start!");
end
disable fr_st1;
end
else
begin
if (frame_started == 0)
begin
`TIME; $display("*W Frame should start!");
disable fr_st1;
end
end
end
join
// check packets larger than 4 bytes
if (num_of_frames >= 5)
begin
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
if (i_length <= (min_tmp - 4))
begin
if (eth_phy.tx_len != min_tmp)
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
end
else
begin
if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
end
// check transmitted TX packet data
if (i_length[0] == 0)
begin
#1 check_tx_packet(`MEMORY_BASE, (num_of_frames * 16), i_length, tmp);
end
else
begin
#1 check_tx_packet((`MEMORY_BASE + max_tmp), (num_of_frames * 16), i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
if (num_of_frames < (min_tmp - 4))
#1 check_tx_crc((num_of_frames * 16), (min_tmp - 4), 1'b0, tmp); // length without CRC
else
#1 check_tx_crc((num_of_frames * 16), i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
end
// check WB INT signal
if ((i_length[1:0] == 2'h0) && (num_of_frames >= 5))
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if (num_of_frames >= 5)
begin
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( (data[15:0] !== 16'h7800) && // wrap bit
(data[15:0] !== 16'h5800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( (data[15:0] !== 16'h3800) && // wrap bit
(data[15:0] !== 16'h1800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
end
else
begin
if (data[15] !== 1'b1)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear TX BD with wrap bit
if (num_of_frames == 63)
clear_tx_bd(16, 16);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1)) && (num_of_frames >= 5) )
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (i_length == 3)
begin
$display(" pads appending to packets is selected");
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packets with lengths from %0d to %0d are not transmitted (length increasing by 1 byte)",
0, 3);
end
else if (i_length == 9)
begin
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packet with length 4 is not transmitted (length increasing by 1 byte)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
5, 9);
end
else if (i_length == 17)
begin
$display(" using 4 BDs out of 8 BDs assigned to TX (wrap at 4th BD - TX BD 3)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
10, 17);
end
else if (i_length == 27)
begin
$display(" using 5 BDs out of 8 BDs assigned to TX (wrap at 5th BD - TX BD 4)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
18, 27);
end
else if (i_length == 40)
begin
$display(" using 6 BDs out of 8 BDs assigned to TX (wrap at 6th BD - TX BD 5)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
28, 40);
end
else if (i_length == 54)
begin
$display(" using 7 BDs out of 8 BDs assigned to TX (wrap at 7th BD - TX BD 6)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
41, 54);
end
else if (i_length == 69)
begin
$display(" using 8 BDs out of 8 BDs assigned to TX (wrap at 8th BD - TX BD 7)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if (/*(num_of_frames == 2) || (num_of_frames == 4) || (num_of_frames == 7) ||*/ (num_of_frames <= 10) ||
(num_of_frames == 14) || (num_of_frames == 18) || (num_of_frames == 23) || (num_of_frames == 28) ||
(num_of_frames == 34) || (num_of_frames == 40) || (num_of_frames == 47) ||
(num_of_frames == 54) || (num_of_frames == 62))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets (no pads) from 0 to (MINFL - 1) ////
//// sizes at 8 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 8) //
begin
// TEST 8: TRANSMIT PACKETS (NO PADs) FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 10Mbps )
test_name = "TEST 8: TRANSMIT PACKETS (NO PADs) FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 10Mbps )";
`TIME; $display(" TEST 8: TRANSMIT PACKETS (NO PADs) FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 8 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h8, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, padding and CRC appending
// wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_PAD | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h12;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
st_data = 8'h34;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp - 4), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
frame_started = 0;
num_of_frames = 0;
num_of_bd = 0;
i_length = 0; // 0;
while (i_length < 70) // (min_tmp - 4))
begin
#1;
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
// // append CRC
// if ((i_length[0] == 1'b0) && (num_of_frames >= 6))
// begin
// append_tx_crc(`MEMORY_BASE, i_length, 1'b0);
// end
#1;
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(num_of_frames * 16);
// SET packets and wrap bit
// num_of_frames <= 9 => wrap set to TX BD 0
if (num_of_frames <= 5)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0) // CRC appended by 'HARDWARE'
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, (`MEMORY_BASE + max_tmp));
// set wrap bit
set_tx_bd_wrap(0);
end
else if (num_of_frames <= 9)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0) // CRC appended by 'SOFTWARE'
set_tx_bd(tmp_bd_num, tmp_bd_num, (tmp_len + 0), !tmp_len[1], 1'b0, 1'b0, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, (`MEMORY_BASE + max_tmp));
// set wrap bit
set_tx_bd_wrap(0);
end
// 10 <= num_of_frames < 18 => wrap set to TX BD 3
else if ((num_of_frames == 10) || (num_of_frames == 14))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 4) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, (tmp_len + 0), !tmp_len[1], 1'b0, 1'b0, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(3);
end
// 18 <= num_of_frames < 28 => wrap set to TX BD 4
else if ((num_of_frames == 18) || (num_of_frames == 23))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 5) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, (tmp_len + 0), !tmp_len[1], 1'b0, 1'b0, `MEMORY_BASE);
else // when (num_of_frames == 23), (i_length == 23) and therefor i_length[0] == 1 !!!
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1],
((num_of_frames == 23) && (tmp_bd_num == 0)), 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(4);
end
// 28 <= num_of_frames < 40 => wrap set to TX BD 5
else if ((num_of_frames == 28) || (num_of_frames == 34))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 6) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, (tmp_len + 0), !tmp_len[1], 1'b0, 1'b0, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(5);
end
// 40 <= num_of_frames < 54 => wrap set to TX BD 6
else if ((num_of_frames == 40) || (num_of_frames == 47))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 7) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, (tmp_len + 0), !tmp_len[1], 1'b0, 1'b0, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(6);
end
// 54 <= num_of_frames < 70 => wrap set to TX BD 7
else if ((num_of_frames == 54) || (num_of_frames == 62))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 8) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, (tmp_len + 0), !tmp_len[1], 1'b0, 1'b0, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b0, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(7);
end
#1;
// SET ready bit
if (num_of_frames < 10)
set_tx_bd_ready(0, 0);
else if (num_of_frames < 14)
set_tx_bd_ready((num_of_frames - 10), (num_of_frames - 10));
else if (num_of_frames < 18)
set_tx_bd_ready((num_of_frames - 14), (num_of_frames - 14));
else if (num_of_frames < 23)
set_tx_bd_ready((num_of_frames - 18), (num_of_frames - 18));
else if (num_of_frames < 28)
set_tx_bd_ready((num_of_frames - 23), (num_of_frames - 23));
else if (num_of_frames < 34)
set_tx_bd_ready((num_of_frames - 28), (num_of_frames - 28));
else if (num_of_frames < 40)
set_tx_bd_ready((num_of_frames - 34), (num_of_frames - 34));
else if (num_of_frames < 47)
set_tx_bd_ready((num_of_frames - 40), (num_of_frames - 40));
else if (num_of_frames < 54)
set_tx_bd_ready((num_of_frames - 47), (num_of_frames - 47));
else if (num_of_frames < 62)
set_tx_bd_ready((num_of_frames - 54), (num_of_frames - 54));
else if (num_of_frames < 70)
set_tx_bd_ready((num_of_frames - 62), (num_of_frames - 62));
// CHECK END OF TRANSMITION
frame_started = 0;
if (num_of_frames >= 5)
#1 check_tx_bd(num_of_bd, data);
fork
begin: fr_st2
wait (MTxEn === 1'b1); // start transmit
frame_started = 1;
end
begin
repeat (30) @(posedge mtx_clk);
if (num_of_frames < 5)
begin
if (frame_started == 1)
begin
`TIME; $display("*E Frame should NOT start!");
end
disable fr_st2;
end
else
begin
if (frame_started == 0)
begin
`TIME; $display("*W Frame should start!");
disable fr_st2;
end
end
end
join
// check packets larger than 4 bytes
if (num_of_frames >= 5)
begin
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
if ((eth_phy.tx_len != i_length) && (i_length[0] == 1'b0) && (num_of_frames >= 6))
begin
`TIME; $display("*E Wrong length of the packet out from MAC");
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
else if ((eth_phy.tx_len != (i_length + 4)) && (num_of_frames != 23))
begin
`TIME; $display("*E Wrong length of the packet out from MAC");
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
else if ((eth_phy.tx_len != (min_tmp)) && (num_of_frames == 23))
begin
`TIME; $display("*E Wrong length of the packet out from MAC");
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// check transmitted TX packet data
if (i_length[0] == 0)
begin
#1 check_tx_packet(`MEMORY_BASE, (num_of_frames * 16), i_length, tmp);
end
else if (num_of_frames == 23) // i_length[0] == 1 here
begin
#1 check_tx_packet((`MEMORY_BASE + max_tmp), (num_of_frames * 16), (min_tmp - 4), tmp);
end
else
begin
#1 check_tx_packet((`MEMORY_BASE + max_tmp), (num_of_frames * 16), i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
#1;
if ((i_length[0] == 1'b0) && (num_of_frames >= 6))
begin
end
else
check_tx_crc((num_of_frames * 16), (eth_phy.tx_len - 4), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
end
// check WB INT signal
if ((i_length[1:0] == 2'h0) && (num_of_frames >= 5))
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if (num_of_frames >= 5)
begin
if ((i_length[1] == 1'b0) && (i_length[0] == 1'b0)) // interrupt enabled
begin
if ( (data[15:0] !== 16'h6000) && // wrap bit
(data[15:0] !== 16'h4000) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if ((i_length[1] == 1'b1) && (i_length[0] == 1'b0)) // interrupt not enabled
begin
if ( (data[15:0] !== 16'h2000) && // wrap bit
(data[15:0] !== 16'h0000) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if ((i_length[1] == 1'b0) && (i_length[0] == 1'b1)) // interrupt enabled
begin
if ( (data[15:0] !== 16'h6800) && // wrap bit
(data[15:0] !== 16'h4800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if (num_of_frames != 23) // ((i_length[1] == 1'b1) && (i_length[0] == 1'b1)) // interrupt not enabled
begin
if ( (data[15:0] !== 16'h2800) && // wrap bit
(data[15:0] !== 16'h0800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // ((num_of_frames != 23) && (i_length[1] == 1'b1) && (i_length[0] == 1'b1)) // interrupt not enabled
begin
if ( (data[15:0] !== 16'h3800) && // wrap bit
(data[15:0] !== 16'h1800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
end
else
begin
if (data[15] !== 1'b1)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear TX BD with wrap bit
if (num_of_frames == 63)
clear_tx_bd(16, 16);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1)) && (num_of_frames >= 5) )
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (i_length == 3)
begin
$display(" pads appending to packets is selected");
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packets with lengths from %0d to %0d are not transmitted (length increasing by 1 byte)",
0, 3);
end
else if (i_length == 9)
begin
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packet with length 4 is not transmitted (length increasing by 1 byte)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
5, 9);
end
else if (i_length == 17)
begin
$display(" using 4 BDs out of 8 BDs assigned to TX (wrap at 4th BD - TX BD 3)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
10, 17);
end
else if (i_length == 27)
begin
$display(" using 5 BDs out of 8 BDs assigned to TX (wrap at 5th BD - TX BD 4)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
18, 27);
end
else if (i_length == 40)
begin
$display(" using 6 BDs out of 8 BDs assigned to TX (wrap at 6th BD - TX BD 5)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
28, 40);
end
else if (i_length == 54)
begin
$display(" using 7 BDs out of 8 BDs assigned to TX (wrap at 7th BD - TX BD 6)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
41, 54);
end
else if (i_length == 69)
begin
$display(" using 8 BDs out of 8 BDs assigned to TX (wrap at 8th BD - TX BD 7)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if (/*(num_of_frames == 2) || (num_of_frames == 4) || (num_of_frames == 7) ||*/ (num_of_frames <= 10) ||
(num_of_frames == 14) || (num_of_frames == 18) || (num_of_frames == 23) || (num_of_frames == 28) ||
(num_of_frames == 34) || (num_of_frames == 40) || (num_of_frames == 47) ||
(num_of_frames == 54) || (num_of_frames == 62))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets (no pads) form 0 to (MINFL - 1) ////
//// sizes at 8 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 9) //
begin
// TEST 9: TRANSMIT PACKETS (NO PADs) FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 100Mbps )
test_name = "TEST 9: TRANSMIT PACKETS (NO PADs) FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 100Mbps )";
`TIME; $display(" TEST 9: TRANSMIT PACKETS (NO PADs) FROM 0 TO (MINFL - 1) SIZES AT 8 TX BD ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 8 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h8, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_PAD | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h12;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
st_data = 8'h34;
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp - 4), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
frame_started = 0;
num_of_frames = 0;
num_of_bd = 0;
i_length = 0; // 0;
while (i_length < 70) // (min_tmp - 4))
begin
#1;
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.carrier_sense_tx_fd_detect(1);
eth_phy.collision(1);
end
endcase
#1;
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(num_of_frames * 16);
// SET packets and wrap bit
// num_of_frames <= 9 => wrap set to TX BD 0
if (num_of_frames <= 9)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
// set wrap bit
set_tx_bd_wrap(0);
end
// 10 <= num_of_frames < 18 => wrap set to TX BD 3
else if ((num_of_frames == 10) || (num_of_frames == 14))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 4) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(3);
end
// 18 <= num_of_frames < 28 => wrap set to TX BD 4
else if ((num_of_frames == 18) || (num_of_frames == 23))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 5) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(4);
end
// 28 <= num_of_frames < 40 => wrap set to TX BD 5
else if ((num_of_frames == 28) || (num_of_frames == 34))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 6) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(5);
end
// 40 <= num_of_frames < 54 => wrap set to TX BD 6
else if ((num_of_frames == 40) || (num_of_frames == 47))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 7) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(6);
end
// 54 <= num_of_frames < 70 => wrap set to TX BD 7
else if ((num_of_frames == 54) || (num_of_frames == 62))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 8) //
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
else
set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + max_tmp));
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_tx_bd_wrap(7);
end
#1;
// SET ready bit
if (num_of_frames < 10)
set_tx_bd_ready(0, 0);
else if (num_of_frames < 14)
set_tx_bd_ready((num_of_frames - 10), (num_of_frames - 10));
else if (num_of_frames < 18)
set_tx_bd_ready((num_of_frames - 14), (num_of_frames - 14));
else if (num_of_frames < 23)
set_tx_bd_ready((num_of_frames - 18), (num_of_frames - 18));
else if (num_of_frames < 28)
set_tx_bd_ready((num_of_frames - 23), (num_of_frames - 23));
else if (num_of_frames < 34)
set_tx_bd_ready((num_of_frames - 28), (num_of_frames - 28));
else if (num_of_frames < 40)
set_tx_bd_ready((num_of_frames - 34), (num_of_frames - 34));
else if (num_of_frames < 47)
set_tx_bd_ready((num_of_frames - 40), (num_of_frames - 40));
else if (num_of_frames < 54)
set_tx_bd_ready((num_of_frames - 47), (num_of_frames - 47));
else if (num_of_frames < 62)
set_tx_bd_ready((num_of_frames - 54), (num_of_frames - 54));
else if (num_of_frames < 70)
set_tx_bd_ready((num_of_frames - 62), (num_of_frames - 62));
// CHECK END OF TRANSMITION
frame_started = 0;
if (num_of_frames >= 5)
#1 check_tx_bd(num_of_bd, data);
fork
begin: fr_st3
wait (MTxEn === 1'b1); // start transmit
frame_started = 1;
end
begin
repeat (30) @(posedge mtx_clk);
if (num_of_frames < 5)
begin
if (frame_started == 1)
begin
`TIME; $display("*E Frame should NOT start!");
end
disable fr_st3;
end
else
begin
if (frame_started == 0)
begin
`TIME; $display("*W Frame should start!");
disable fr_st3;
end
end
end
join
// check packets larger than 4 bytes
if (num_of_frames >= 5)
begin
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
if (eth_phy.tx_len != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from MAC");
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// check transmitted TX packet data
if (i_length[0] == 0)
begin
#1 check_tx_packet(`MEMORY_BASE, (num_of_frames * 16), i_length, tmp);
end
else
begin
#1 check_tx_packet((`MEMORY_BASE + max_tmp), (num_of_frames * 16), i_length, tmp);
end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
#1 check_tx_crc((num_of_frames * 16), (eth_phy.tx_len - 4), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
end
// check WB INT signal
if ((i_length[1:0] == 2'h0) && (num_of_frames >= 5))
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if (num_of_frames >= 5)
begin
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( (data[15:0] !== 16'h7800) && // wrap bit
(data[15:0] !== 16'h5800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( (data[15:0] !== 16'h3800) && // wrap bit
(data[15:0] !== 16'h1800) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
end
else
begin
if (data[15] !== 1'b1)
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear TX BD with wrap bit
if (num_of_frames == 63)
clear_tx_bd(16, 16);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ( ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1)) && (num_of_frames >= 5) )
begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Transmit Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (i_length == 3)
begin
$display(" pads appending to packets is selected");
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packets with lengths from %0d to %0d are not transmitted (length increasing by 1 byte)",
0, 3);
end
else if (i_length == 9)
begin
$display(" using 1 BD out of 8 BDs assigned to TX (wrap at 1st BD - TX BD 0)");
$display(" ->packet with length 4 is not transmitted (length increasing by 1 byte)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
5, 9);
end
else if (i_length == 17)
begin
$display(" using 4 BDs out of 8 BDs assigned to TX (wrap at 4th BD - TX BD 3)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
10, 17);
end
else if (i_length == 27)
begin
$display(" using 5 BDs out of 8 BDs assigned to TX (wrap at 5th BD - TX BD 4)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
18, 27);
end
else if (i_length == 40)
begin
$display(" using 6 BDs out of 8 BDs assigned to TX (wrap at 6th BD - TX BD 5)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
28, 40);
end
else if (i_length == 54)
begin
$display(" using 7 BDs out of 8 BDs assigned to TX (wrap at 7th BD - TX BD 6)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
41, 54);
end
else if (i_length == 69)
begin
$display(" using 8 BDs out of 8 BDs assigned to TX (wrap at 8th BD - TX BD 7)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if (/*(num_of_frames == 2) || (num_of_frames == 4) || (num_of_frames == 7) ||*/ (num_of_frames <= 10) ||
(num_of_frames == 14) || (num_of_frames == 18) || (num_of_frames == 23) || (num_of_frames == 28) ||
(num_of_frames == 34) || (num_of_frames == 40) || (num_of_frames == 47) ||
(num_of_frames == 54) || (num_of_frames == 62))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across MAXFL value at ////
//// 13 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 10) // without and with padding
begin
// TEST 10: TRANSMIT PACKETS ACROSS MAXFL VALUE AT 13 TX BDs ( 10Mbps )
test_name = "TEST 10: TRANSMIT PACKETS ACROSS MAXFL VALUE AT 13 TX BDs ( 10Mbps )";
`TIME; $display(" TEST 10: TRANSMIT PACKETS ACROSS MAXFL VALUE AT 13 TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 13 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'hD, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL + 10 length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hA3;
set_tx_packet(`MEMORY_BASE, (max_tmp + 10), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (max_tmp - 5);
while (i_length <= (max_tmp - 3)) // (max_tmp - 4) is the limit
begin
$display(" i_length = %0d", i_length);
// choose generating carrier sense and collision
// case (i_length[1:0])
// 2'h0: // Interrupt is generated
// begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// end
// 2'h1: // Interrupt is not generated
// begin
// set_tx_bd enable interrupt generation
// mask interrupts
// wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
// eth_phy.carrier_sense_tx_fd_detect(1);
// eth_phy.collision(0);
// end
// 2'h2: // Interrupt is not generated
// begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
// wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
// `ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
// eth_phy.carrier_sense_tx_fd_detect(0);
// eth_phy.collision(1);
// end
// default: // 2'h3: // Interrupt is not generated
// begin
// set_tx_bd disable the interrupt generation
// mask interrupts
// wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
// eth_phy.carrier_sense_tx_fd_detect(1);
// eth_phy.collision(1);
// end
// endcase
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
//
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(2);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
 
 
// tmp_len = i_length; // length of frame
// tmp_bd_num = 0; // TX BD number
// while (tmp_bd_num < 8) //
// begin
// // if i_length[1] == 0 then enable interrupt generation otherwise disable it
// // if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
// if (tmp_len[0] == 0)
// set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, `MEMORY_BASE);
// else
// set_tx_bd(tmp_bd_num, tmp_bd_num, tmp_len, !tmp_len[1], 1'b1, 1'b1, (`MEMORY_BASE + 2*max_tmp));
// // set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
// tmp_len = tmp_len + 1;
// // set TX BD number
// tmp_bd_num = tmp_bd_num + 1;
// end
// // set wrap bit
// set_tx_bd_wrap(7);
// // set ready bit
// set_tx_bd_ready((i_length - (max_tmp - 8)), (i_length - (max_tmp - 8)));
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
// #1 check_tx_bd((i_length - (max_tmp - 8)), data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
// #1 check_tx_bd((i_length - (max_tmp - 8)), data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
// #1 check_tx_bd((i_length - (max_tmp - 8)), data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
// if (eth_phy.tx_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking in the following if statement is performed only for first and last 64 lengths
// if ( ((i_length + 4) <= (min_tmp + 64)) || ((i_length + 4) > (max_tmp - 64)) )
// begin
// check transmitted TX packet data
// if (i_length[0] == 0)
// begin
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
// end
// else
// begin
// check_tx_packet((`MEMORY_BASE + 2*max_tmp), 0, i_length, tmp);
// end
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
// if (i_length[0] == 0)
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
// else
// check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// end
// check WB INT signal
// if (i_length[1:0] == 2'h0)
// begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// end
// else
// begin
// if (wb_int !== 1'b0)
// begin
// `TIME; $display("*E WB INT signal should not be set");
// test_fail("WB INT signal should not be set");
// fail = fail + 1;
// end
// end
// // check TX buffer descriptor of a packet
// check_tx_bd((i_length - (max_tmp - 8)), data);
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 2)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 2)) ) // without wrap bit
// if (i_length[1] == 1'b0) // interrupt enabled
// begin
// if ( ((data[15:0] !== 16'h7800) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
// ((data[15:0] !== 16'h5800) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// end
// else // interrupt not enabled
// begin
// if ( ((data[15:0] !== 16'h3800) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
// ((data[15:0] !== 16'h1800) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
// begin
// `TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
// test_fail("TX buffer descriptor status is not correct");
// fail = fail + 1;
// end
// end
// // clear first half of 8 frames from TX buffer descriptor 0
// if (num_of_frames < 4)
// clear_tx_bd((i_length - (max_tmp - 8)), (i_length - (max_tmp - 8)));
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
// begin
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// end
// else
// begin
// if (data !== 0)
// begin
// `TIME; $display("*E Any of interrupts (except Transmit Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
// test_fail("Any of interrupts (except Transmit Buffer) was set");
// fail = fail + 1;
// end
// end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_bd == 0)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 1)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 2)
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across MAXFL value at ////
//// 13 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 11) // without and with padding
begin
// TEST 11: TRANSMIT PACKETS ACROSS MAXFL VALUE AT 13 TX BDs ( 100Mbps )
test_name = "TEST 11: TRANSMIT PACKETS ACROSS MAXFL VALUE AT 13 TX BDs ( 100Mbps )";
`TIME; $display(" TEST 11: TRANSMIT PACKETS ACROSS MAXFL VALUE AT 13 TX BDs ( 100Mbps )");
 
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 13 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'hD, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL + 10 length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hA3;
set_tx_packet(`MEMORY_BASE, (max_tmp + 10), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
 
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i_length = (max_tmp - 5);
while (i_length <= (max_tmp - 3)) // (max_tmp - 4) is the limit
begin
$display(" i_length = %0d", i_length);
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(2);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 2)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 2)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_bd == 0)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 1)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 2)
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across changed MAXFL value at ////
//// 47 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 12) // without and with padding
begin
// TEST 12: TRANSMIT PACKETS ACROSS CHANGED MAXFL VALUE AT 13 TX BDs ( 10Mbps )
test_name = "TEST 12: TRANSMIT PACKETS ACROSS CHANGED MAXFL VALUE AT 13 TX BDs ( 10Mbps )";
`TIME; $display(" TEST 12: TRANSMIT PACKETS ACROSS CHANGED MAXFL VALUE AT 13 TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 47 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h2F, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL + 10 length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
// change MAXFL value
max_tmp = min_tmp + 53;
wbm_write(`ETH_PACKETLEN, {min_tmp, max_tmp}, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
st_data = 8'h62;
set_tx_packet(`MEMORY_BASE, max_tmp, st_data); // length with CRC
append_tx_crc(`MEMORY_BASE, (max_tmp - 5), 1'b0); // for first packet
// enable TX, set full-duplex mode, NO padding and NO CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (max_tmp - 5); // (max_tmp - 1); // not (max_tmp - 5) because NO automatic CRC appending
while (i_length <= (max_tmp - 3)) // (max_tmp + 1)) // (max_tmp) is the limit
begin
$display(" i_length = %0d", i_length);
// prepare packet's CRC
if (num_of_bd == 1)
append_tx_crc(`MEMORY_BASE, (max_tmp - 4), 1'b0); // for second and third packets
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(2);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 2)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 2)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_bd == 0)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 1)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 2)
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across changed MAXFL value at ////
//// 47 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 13) // without and with padding
begin
// TEST 13: TRANSMIT PACKETS ACROSS CHANGED MAXFL VALUE AT 13 TX BDs ( 100Mbps )
test_name = "TEST 13: TRANSMIT PACKETS ACROSS CHANGED MAXFL VALUE AT 13 TX BDs ( 100Mbps )";
`TIME; $display(" TEST 13: TRANSMIT PACKETS ACROSS CHANGED MAXFL VALUE AT 13 TX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 47 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h2F, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL + 10 length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
// change MAXFL value
max_tmp = min_tmp + 53;
wbm_write(`ETH_PACKETLEN, {min_tmp, max_tmp}, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
st_data = 8'h62;
set_tx_packet(`MEMORY_BASE, max_tmp, st_data); // length with CRC
append_tx_crc(`MEMORY_BASE, (max_tmp - 5), 1'b0); // for first packet
// enable TX, set full-duplex mode, NO padding and NO CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i_length = (max_tmp - 5); // (max_tmp - 1); // not (max_tmp - 5) because NO automatic CRC appending
while (i_length <= (max_tmp - 3)) // (max_tmp + 1)) // (max_tmp) is the limit
begin
$display(" i_length = %0d", i_length);
// prepare packet's CRC
if (num_of_bd == 1)
append_tx_crc(`MEMORY_BASE, (max_tmp - 4), 1'b0); // for second and third packets
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(2);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 2)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 2)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_bd == 0)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 1)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 2)
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across changed MINFL value at ////
//// 7 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 14) // without and with padding
begin
// TEST 14: TRANSMIT PACKETS ACROSS CHANGED MINFL VALUE AT 7 TX BDs ( 10Mbps )
test_name = "TEST 14: TRANSMIT PACKETS ACROSS CHANGED MINFL VALUE AT 7 TX BDs ( 10Mbps )";
`TIME; $display(" TEST 14: TRANSMIT PACKETS ACROSS CHANGED MINFL VALUE AT 7 TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 7 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h7, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL + 10 length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
// change MINFL value
min_tmp = max_tmp - 177;
wbm_write(`ETH_PACKETLEN, {min_tmp, max_tmp}, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
st_data = 8'h62;
set_tx_packet(`MEMORY_BASE, min_tmp, st_data); // length without CRC
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_PAD | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (min_tmp - 5);
while (i_length <= (min_tmp - 3)) // (min_tmp - 4) is the limit
begin
$display(" i_length = %0d", i_length);
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(2);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 2)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 2)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_bd == 0)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 1)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 2)
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across changed MINFL value at ////
//// 7 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 15) // without and with padding
begin
// TEST 15: TRANSMIT PACKETS ACROSS CHANGED MINFL VALUE AT 7 TX BDs ( 100Mbps )
test_name = "TEST 15: TRANSMIT PACKETS ACROSS CHANGED MINFL VALUE AT 7 TX BDs ( 100Mbps )";
`TIME; $display(" TEST 15: TRANSMIT PACKETS ACROSS CHANGED MINFL VALUE AT 7 TX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 7 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h7, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL + 10 length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
// change MINFL value
min_tmp = max_tmp - 177;
wbm_write(`ETH_PACKETLEN, {min_tmp, max_tmp}, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
st_data = 8'h62;
set_tx_packet(`MEMORY_BASE, min_tmp, st_data); // length without CRC
// enable TX, set full-duplex mode, padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_PAD | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i_length = (min_tmp - 5);
while (i_length <= (min_tmp - 3)) // (min_tmp - 4) is the limit
begin
$display(" i_length = %0d", i_length);
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(2);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 2)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 2)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_bd == 0)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 1)
$display(" ->packet with length %0d sent", (i_length + 4));
else if (num_of_bd == 2)
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across MAXFL with HUGEN at ////
//// 19 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 16) // without and with padding
begin
// TEST 16: TRANSMIT PACKETS ACROSS MAXFL WITH HUGEN AT 19 TX BDs ( 10Mbps )
test_name = "TEST 16: TRANSMIT PACKETS ACROSS MAXFL WITH HUGEN AT 19 TX BDs ( 10Mbps )";
`TIME; $display(" TEST 16: TRANSMIT PACKETS ACROSS MAXFL WITH HUGEN AT 19 TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 19 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h13, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of 64k - 1 length (16'hFFFF)
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h8D;
set_tx_packet(`MEMORY_BASE, 16'hFFFF, st_data); // length with CRC
// enable TX, set full-duplex mode, NO padding, CRC appending and huge enabled
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN | `ETH_MODER_HUGEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (max_tmp - 5); // (max_tmp - 4) is the MAXFL limit
while (i_length <= (16'hFFFF - 4)) // (16'hFFFF - 4) is the limit
begin
$display(" i_length = %0d", i_length);
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(3, 3, (16'hFFFF - 5), 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(4, 4, (16'hFFFF - 4), 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(4);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
else if (num_of_bd == 3)
set_tx_bd_ready(3, 3);
else if (num_of_bd == 4)
set_tx_bd_ready(4, 4);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 4)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 4)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
if ((num_of_bd < 2) || (num_of_bd >= 3))
i_length = i_length + 1;
else if (num_of_bd == 2)
i_length = (16'hFFFF - 5);
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets across MAXFL with HUGEN at ////
//// 19 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 17) // without and with padding
begin
// TEST 17: TRANSMIT PACKETS ACROSS MAXFL WITH HUGEN AT 19 TX BDs ( 100Mbps )
test_name = "TEST 17: TRANSMIT PACKETS ACROSS MAXFL WITH HUGEN AT 19 TX BDs ( 100Mbps )";
`TIME; $display(" TEST 17: TRANSMIT PACKETS ACROSS MAXFL WITH HUGEN AT 19 TX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set 19 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h13, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of 64k - 1 length (16'hFFFF)
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h8D;
set_tx_packet(`MEMORY_BASE, 16'hFFFF, st_data); // length with CRC
// enable TX, set full-duplex mode, NO padding, CRC appending and huge enabled
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN | `ETH_MODER_HUGEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i_length = (max_tmp - 5); // (max_tmp - 4) is the MAXFL limit
while (i_length <= (16'hFFFF - 4)) // (16'hFFFF - 4) is the limit
begin
$display(" i_length = %0d", i_length);
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(2, 2, i_length+2, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(3, 3, (16'hFFFF - 5), 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(4, 4, (16'hFFFF - 4), 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(4);
set_tx_bd_ready(0, 0);
end
else if (num_of_bd == 1)
set_tx_bd_ready(1, 1);
else if (num_of_bd == 2)
set_tx_bd_ready(2, 2);
else if (num_of_bd == 3)
set_tx_bd_ready(3, 3);
else if (num_of_bd == 4)
set_tx_bd_ready(4, 4);
// CHECK END OF TRANSMITION
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
check_tx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a PACKET
$display(" eth_phy length = %0d", eth_phy.tx_len);
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of the packet out from MAC");
fail = fail + 1;
end
// checking packet
check_tx_packet(`MEMORY_BASE, 0, i_length, tmp);
if (tmp > 0)
begin
test_fail("Wrong data of the transmitted packet");
fail = fail + 1;
end
// check transmited TX packet CRC
check_tx_crc(0, i_length, 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of the transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 4)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 4)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
$display(" ->packet with length %0d sent", (i_length + 4));
// set length (loop variable)
if ((num_of_bd < 2) || (num_of_bd >= 3))
i_length = i_length + 1;
else if (num_of_bd == 2)
i_length = (16'hFFFF - 5);
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test IPG during Back-to-Back transmit at ////
//// 88 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 18) // without and with padding
begin
// TEST 18: IPG DURING BACK-TO-BACK TRANSMIT AT 88 TX BDs ( 10Mbps )
test_name = "TEST 18: IPG DURING BACK-TO-BACK TRANSMIT AT 88 TX BDs ( 10Mbps )";
`TIME; $display(" TEST 18: IPG DURING BACK-TO-BACK TRANSMIT AT 88 TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
tmp_ipgt = 0;
// set 88 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h58, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h29;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i_length = (min_tmp - 4);
while (i_length < (max_tmp - 4))
begin
// disable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set IPGT register
wbm_write(`ETH_IPGT, tmp_ipgt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// Reset_tx_bd enable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(1);
set_tx_bd_ready(0, 0);
set_tx_bd_ready(1, 1);
end
// CHECK END OF TWO TRANSMITIONs
// wait for first transmit to end
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
#Tp;
// destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
i1 = 0;
i2 = 0;
// count IPG clock periods
fork
begin
wait (MTxEn === 1'b1); // start second transmit
#Tp;
disable count_rising;
disable count_falling;
end
begin: count_rising
forever
begin
@(posedge mtx_clk);
i1 = i1 + 1;
#Tp;
end
end
begin: count_falling
forever
begin
@(negedge mtx_clk);
i2 = i2 + 1;
#Tp;
end
end
join
// check IPG length - INTERMEDIATE DISPLAYS
if((i1 == i2) && (i1 >= (tmp_ipgt + 3)))
begin
$display(" ->IPG with %0d mtx_clk periods (min %0d) between packets with lengths %0d and %0d checked",
i1, (tmp_ipgt + 3), (i_length + 4), (i_length + 4 + 1));
end
else
begin
`TIME; $display("*E IPG is not correct: (%0d + %0d) / 2, requested: %d", i1, i2, (tmp_ipgt + 3));
fail = fail + 1;
test_fail("IPG is not correct");
end
// wait for second transmit to end
wait (MTxEn === 1'b0); // end second transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a second PACKET
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4 + 1))
begin
test_fail("Wrong length of second packet out from MAC");
fail = fail + 1;
end
// checking second packet
check_tx_packet(`MEMORY_BASE, 0, (i_length + 1), tmp);
if (tmp > 0)
begin
test_fail("Wrong data of second transmitted packet");
fail = fail + 1;
end
// check second transmited TX packet CRC
check_tx_crc(0, (i_length + 1), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of second transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 1)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 1)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// set length (LOOP variable)
if ((tmp_ipgt + 3) < 130) // tmp_ipgt < 124
i_length = i_length + 2;
else
i_length = (max_tmp - 4);
// set IPGT
if ((tmp_ipgt + 3) < 10)
tmp_ipgt = tmp_ipgt + 1;
else if ((tmp_ipgt + 3) < 24)
tmp_ipgt = tmp_ipgt + 7;
else if ((tmp_ipgt + 3) == 24)
tmp_ipgt = 38 - 3;
else if ((tmp_ipgt + 3) == 38)
tmp_ipgt = 72 - 3;
else if ((tmp_ipgt + 3) == 72)
tmp_ipgt = 130 - 3; // 124 - 3
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = 0;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test IPG during Back-to-Back transmit at ////
//// 88 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 19) // without and with padding
begin
// TEST 19: IPG DURING BACK-TO-BACK TRANSMIT AT 88 TX BDs ( 100Mbps )
test_name = "TEST 19: IPG DURING BACK-TO-BACK TRANSMIT AT 88 TX BDs ( 100Mbps )";
`TIME; $display(" TEST 19: IPG DURING BACK-TO-BACK TRANSMIT AT 88 TX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
tmp_ipgt = 0;
// set 88 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h58, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h29;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i_length = (min_tmp - 4);
while (i_length < (max_tmp - 4))
begin
// disable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set IPGT register
wbm_write(`ETH_IPGT, tmp_ipgt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN | `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// Reset_tx_bd enable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd(1, 1, i_length+1, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(1);
set_tx_bd_ready(0, 0);
set_tx_bd_ready(1, 1);
end
// CHECK END OF TWO TRANSMITIONs
// wait for first transmit to end
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start transmit
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end transmit
num_of_frames = num_of_frames + 1;
num_of_bd = num_of_bd + 1;
#Tp;
// destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
i1 = 0;
i2 = 0;
// count IPG clock periods
fork
begin
wait (MTxEn === 1'b1); // start second transmit
#Tp;
disable count_rising1;
disable count_falling1;
end
begin: count_rising1
forever
begin
@(posedge mtx_clk);
i1 = i1 + 1;
#Tp;
end
end
begin: count_falling1
forever
begin
@(negedge mtx_clk);
i2 = i2 + 1;
#Tp;
end
end
join
// check IPG length - INTERMEDIATE DISPLAYS
if((i1 == i2) && (i1 >= (tmp_ipgt + 3)))
begin
$display(" ->IPG with %0d mtx_clk periods (min %0d) between packets with lengths %0d and %0d checked",
i1, (tmp_ipgt + 3), (i_length + 4), (i_length + 4 + 1));
end
else
begin
`TIME; $display("*E IPG is not correct: (%0d + %0d) / 2, requested: %d", i1, i2, (tmp_ipgt + 3));
fail = fail + 1;
test_fail("IPG is not correct");
end
// wait for second transmit to end
wait (MTxEn === 1'b0); // end second transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// check length of a second PACKET
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4 + 1))
begin
test_fail("Wrong length of second packet out from MAC");
fail = fail + 1;
end
// checking second packet
check_tx_packet(`MEMORY_BASE, 0, (i_length + 1), tmp);
if (tmp > 0)
begin
test_fail("Wrong data of second transmitted packet");
fail = fail + 1;
end
// check second transmited TX packet CRC
check_tx_crc(0, (i_length + 1), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of second transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 1)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 1)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// set length (LOOP variable)
if ((tmp_ipgt + 3) < 130) // tmp_ipgt < 124
i_length = i_length + 2;
else
i_length = (max_tmp - 4);
// set IPGT
if ((tmp_ipgt + 3) < 10)
tmp_ipgt = tmp_ipgt + 1;
else if ((tmp_ipgt + 3) < 24)
tmp_ipgt = tmp_ipgt + 7;
else if ((tmp_ipgt + 3) == 24)
tmp_ipgt = 38 - 3;
else if ((tmp_ipgt + 3) == 38)
tmp_ipgt = 72 - 3;
else if ((tmp_ipgt + 3) == 72)
tmp_ipgt = 130 - 3; // 124 - 3
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = 0;
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets after TX under-run on each packet's ////
//// byte at 2 TX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 20) // without padding
begin
// TEST 20: TRANSMIT PACKETS AFTER TX UNDER-RUN ON EACH PACKET's BYTE AT 2 TX BDs ( 10Mbps )
test_name = "TEST 20: TRANSMIT PACKETS AFTER TX UNDER-RUN ON EACH PACKET's BYTE AT 2 TX BDs ( 10Mbps )";
`TIME;
$display(" TEST 20: TRANSMIT PACKETS AFTER TX UNDER-RUN ON EACH PACKET's BYTE AT 2 TX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 2 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h2, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN |/* `ETH_MODER_PAD |*/ `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h99;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
// read IPG value
wbm_read(`ETH_IPGT, tmp_ipgt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
num_of_frames = 40; // (0..3) => start under-run on first word
num_of_bd = 0;
i_data = 3; // (3) => one BYTE read in first word - FIRST byte
i_length = (min_tmp + 4);
while (i_length < (max_tmp - 4))
begin
// Reset_tx_bd enable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + i_data[1:0]));
set_tx_bd(1, 1, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(1);
// set wb slave response: ACK (response), wbs_waits[2:0] (waits before response),
// wbs_retries[7:0] (RTYs before ACK if RTY response selected)
#1 wb_slave.cycle_response(`ACK_RESPONSE, 3'h0, 8'h0);
set_tx_bd_ready(1, 1);
set_tx_bd_ready(0, 0);
end
// frame under-run checking
frame_started = 0;
frame_ended = 0;
wait_for_frame = 0;
fork
begin
// for every 4 frames bytes 1, 2, 3 and 4 respectively are read in first word => 1 ACK
// in other words 4 bytes are read, since length is MINFL => num_of_frames[31:2] ACKs
repeat ((num_of_frames[31:2] + 1'b1)) @(posedge eth_ma_wb_ack_i);
@(negedge eth_ma_wb_ack_i); // wait for last ACK to finish
// set wb slave response: ACK (response), wbs_waits[2:0] (waits before response),
// wbs_retries[7:0] (RTYs before ACK if RTY response selected)
#1 wb_slave.cycle_response(`NO_RESPONSE, 3'h0, 8'hFF);
// wait for synchronization and some additional clocks
wait_for_frame = 1;
// wait for frame
wait ((wait_for_frame == 0) || (frame_started == 1))
if ((wait_for_frame == 0) && (frame_started == 0)) // frame didn't start
begin
disable check_fr;
end
else if ((wait_for_frame == 1) && (frame_started == 1)) // frame started
begin
disable wait_fr;
wait (frame_ended == 1);
end
repeat (2) @(posedge wb_clk);
// set wb slave response: ACK (response), wbs_waits[2:0] (waits before response),
// wbs_retries[7:0] (RTYs before ACK if RTY response selected)
wb_slave.cycle_response(`ACK_RESPONSE, 3'h0, 8'h0);
end
begin: wait_fr
wait (wait_for_frame == 1)
begin
// wait for synchronization and some additional clocks
repeat (3) @(posedge wb_clk);
repeat (2 * tmp_ipgt) @(posedge mtx_clk);
repeat (2) @(posedge wb_clk);
repeat (2) @(posedge mtx_clk);
wait_for_frame = 0;
end
end
begin: check_fr
// wait for frame to start
@(posedge MTxEn);
frame_started = 1;
`TIME; $display(" Under-run (on %0d. byte) frame started", (num_of_frames + 1));
// wait for frame to end due to under-run
@(negedge MTxEn);
frame_ended = 1;
`TIME; $display(" Under-run frame ended");
end
join
// wait for first transmit to end, if under-run didn't happen
if (frame_ended == 0)
begin
// WAIT FOR FIRST TRANSMIT
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start first transmit
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end first transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// CHECK FIRST FRAME
// check length of a first PACKET
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
`TIME; $display("*E Wrong length of first packet out from MAC");
test_fail("Wrong length of first packet out from MAC");
fail = fail + 1;
end
// checking first packet
check_tx_packet((`MEMORY_BASE + i_data[1:0]), 0, (i_length), tmp);
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of first transmitted packet");
test_fail("Wrong data of first transmitted packet");
fail = fail + 1;
end
// check first transmited TX packet CRC
check_tx_crc(0, (i_length), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
`TIME; $display("*E Wrong CRC of first transmitted packet");
test_fail("Wrong CRC of first transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 1)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 1)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
else
begin
// CHECK FIRST FRAME
// check length of a first PACKET
tmp_len = eth_phy.tx_len_err;
#1;
if (tmp_len != (num_of_frames + (4 - i_data)))
begin
`TIME; $display("*E Wrong length of first packet out from MAC");
test_fail("Wrong length of first packet out from MAC");
fail = fail + 1;
end
// checking first packet
check_tx_packet((`MEMORY_BASE + i_data[1:0]), 0, (num_of_frames), tmp);
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of first transmitted packet");
test_fail("Wrong data of first transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7900) && (num_of_bd == 1)) || // under-run, wrap bit
((data[15:0] !== 16'h5900) && (num_of_bd < 1)) ) // under-run, without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXE) !== 2'b10)
begin
`TIME; $display("*E Interrupt Transmit Error was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXE)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Error) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
num_of_bd = num_of_bd + 1;
// destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// WAIT FOR SECOND TRANSMIT
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start first transmit
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end first transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// CHECK SECOND FRAME
// check length of a second PACKET
if (frame_ended == 1'b1)
begin
`TIME; $display(" Second frame after under-run ended");
end
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
`TIME; $display("*E Wrong length of second packet out from MAC");
test_fail("Wrong length of second packet out from MAC");
fail = fail + 1;
end
// checking second packet
check_tx_packet(`MEMORY_BASE, 0, (i_length), tmp);
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of second transmitted packet");
test_fail("Wrong data of second transmitted packet");
fail = fail + 1;
end
// check second transmited TX packet CRC
check_tx_crc(0, (i_length), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
`TIME; $display("*E Wrong CRC of second transmitted packet");
test_fail("Wrong CRC of second transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 1)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 1)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// set initial value
i_data = i_data - 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = 0;
// set length (LOOP variable)
if (num_of_frames == i_length + 4) // 64 => this was last Byte (1st .. 64th) when i_length = min_tmp - 4
i_length = (max_tmp - 4);
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test transmit packets after TX under-run on each packet's ////
//// byte at 2 TX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 21) // without padding
begin
// TEST 21: TRANSMIT PACKETS AFTER TX UNDER-RUN ON EACH PACKET's BYTE AT 2 TX BDs ( 100Mbps )
test_name = "TEST 21: TRANSMIT PACKETS AFTER TX UNDER-RUN ON EACH PACKET's BYTE AT 2 TX BDs ( 100Mbps )";
`TIME;
$display(" TEST 21: TRANSMIT PACKETS AFTER TX UNDER-RUN ON EACH PACKET's BYTE AT 2 TX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 2 TX buffer descriptors - must be set before TX enable
wbm_write(`ETH_TX_BD_NUM, 32'h2, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable TX, set full-duplex mode, NO padding and CRC appending
wbm_write(`ETH_MODER, `ETH_MODER_TXEN |/* `ETH_MODER_PAD |*/ `ETH_MODER_FULLD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare a packet of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h99;
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC
// read IPG value
wbm_read(`ETH_IPGT, tmp_ipgt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
num_of_frames = 0; // (0..3) => start under-run on first word
num_of_bd = 0;
i_data = 3; // (3) => one BYTE read in first word - FIRST byte
i_length = (min_tmp + 4);
while (i_length < (max_tmp - 4))
begin
// Reset_tx_bd enable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.carrier_sense_tx_fd_detect(0);
eth_phy.collision(0);
// first destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// prepare BDs
if (num_of_bd == 0)
begin
set_tx_bd(0, 0, i_length, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + i_data[1:0]));
set_tx_bd(1, 1, i_length, 1'b1, 1'b1, 1'b1, `MEMORY_BASE);
set_tx_bd_wrap(1);
// set wb slave response: ACK (response), wbs_waits[2:0] (waits before response),
// wbs_retries[7:0] (RTYs before ACK if RTY response selected)
#1 wb_slave.cycle_response(`ACK_RESPONSE, 3'h2, 8'h0);
set_tx_bd_ready(1, 1);
set_tx_bd_ready(0, 0);
end
// frame under-run checking
frame_started = 0;
frame_ended = 0;
wait_for_frame = 0;
fork
begin
// for every 4 frames bytes 1, 2, 3 and 4 respectively are read in first word => 1 ACK
// in other words 4 bytes are read, since length is MINFL => num_of_frames[31:2] ACKs
repeat ((num_of_frames[31:2] + 1'b1)) @(posedge eth_ma_wb_ack_i);
@(negedge eth_ma_wb_ack_i); // wait for last ACK to finish
// set wb slave response: ACK (response), wbs_waits[2:0] (waits before response),
// wbs_retries[7:0] (RTYs before ACK if RTY response selected)
#1 wb_slave.cycle_response(`NO_RESPONSE, 3'h7, 8'hFF);
// wait for synchronization and some additional clocks
wait_for_frame = 1;
// wait for frame
wait ((wait_for_frame == 0) || (frame_started == 1))
if ((wait_for_frame == 0) && (frame_started == 0)) // frame didn't start
begin
disable check_fr1;
end
else if ((wait_for_frame == 1) && (frame_started == 1)) // frame started
begin
disable wait_fr1;
wait (frame_ended == 1);
end
repeat (2) @(posedge wb_clk);
// set wb slave response: ACK (response), wbs_waits[2:0] (waits before response),
// wbs_retries[7:0] (RTYs before ACK if RTY response selected)
wb_slave.cycle_response(`ACK_RESPONSE, 3'h2, 8'h0);
end
begin: wait_fr1
wait (wait_for_frame == 1)
begin
// wait for synchronization and some additional clocks
repeat (3) @(posedge wb_clk);
repeat (2 * tmp_ipgt) @(posedge mtx_clk);
repeat (2) @(posedge wb_clk);
repeat (2) @(posedge mtx_clk);
wait_for_frame = 0;
end
end
begin: check_fr1
// wait for frame to start
@(posedge MTxEn);
frame_started = 1;
$display(" Under-run (on %0d. byte) frame started", (num_of_frames + 1));
// wait for frame to end due to under-run
@(negedge MTxEn);
frame_ended = 1;
$display(" Under-run frame ended");
end
join
// wait for first transmit to end, if under-run didn't happen
if (frame_ended == 0)
begin
// WAIT FOR FIRST TRANSMIT
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start first transmit
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end first transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// CHECK FIRST FRAME
// check length of a first PACKET
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of second packet out from MAC");
fail = fail + 1;
end
// checking first packet
check_tx_packet((`MEMORY_BASE + i_data[1:0]), 0, (i_length), tmp);
if (tmp > 0)
begin
test_fail("Wrong data of second transmitted packet");
fail = fail + 1;
end
// check first transmited TX packet CRC
check_tx_crc(0, (i_length), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of second transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 1)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 1)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
num_of_bd = num_of_bd + 1;
// destination address on ethernet PHY
eth_phy.set_tx_mem_addr(0);
// WAIT FOR FIRST TRANSMIT
check_tx_bd(num_of_bd, data);
wait (MTxEn === 1'b1); // start first transmit
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MTxEn === 1'b0); // end first transmit
while (data[15] === 1)
begin
check_tx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
// CHECK SECOND FRAME
// check length of a second PACKET
tmp_len = eth_phy.tx_len;
#1;
if (tmp_len != (i_length + 4))
begin
test_fail("Wrong length of second packet out from MAC");
fail = fail + 1;
end
// checking second packet
check_tx_packet(`MEMORY_BASE, 0, (i_length), tmp);
if (tmp > 0)
begin
test_fail("Wrong data of second transmitted packet");
fail = fail + 1;
end
// check second transmited TX packet CRC
check_tx_crc(0, (i_length), 1'b0, tmp); // length without CRC
if (tmp > 0)
begin
test_fail("Wrong CRC of second transmitted packet");
fail = fail + 1;
end
// check WB INT signal
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
// check TX buffer descriptor of a packet
check_tx_bd(num_of_bd, data);
if ( ((data[15:0] !== 16'h7800) && (num_of_bd == 1)) || // wrap bit
((data[15:0] !== 16'h5800) && (num_of_bd < 1)) ) // without wrap bit
begin
`TIME; $display("*E TX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("TX buffer descriptor status is not correct");
fail = fail + 1;
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((data & `ETH_INT_TXB) !== 1'b1)
begin
`TIME; $display("*E Interrupt Transmit Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Transmit Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_TXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Transmit Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Transmit Buffer) were set");
fail = fail + 1;
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// set initial value
i_data = i_data - 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = 0;
// set length (LOOP variable)
if (num_of_frames == i_length + 4) // 64 => this vas last Byte (1st .. 64th) when i_length = min_tmp - 4
i_length = (max_tmp - 4);
@(posedge wb_clk);
end
// disable TX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
end // for (test_num=start_task; test_num <= end_task; test_num=test_num+1)
 
end
endtask // test_mac_full_duplex_transmit
 
 
task test_mac_full_duplex_receive;
input [31:0] start_task;
input [31:0] end_task;
integer bit_start_1;
integer bit_end_1;
integer bit_start_2;
integer bit_end_2;
integer num_of_reg;
integer num_of_frames;
integer num_of_bd;
integer i_addr;
integer i_data;
integer i_length;
integer tmp_len;
integer tmp_bd;
integer tmp_bd_num;
integer tmp_data;
integer tmp_ipgt;
integer test_num;
reg [31:0] tx_bd_num;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_data;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_tmp_data;
integer i;
integer i1;
integer i2;
integer i3;
integer fail;
integer speed;
reg frame_started;
reg frame_ended;
reg wait_for_frame;
reg check_frame;
reg stop_checking_frame;
reg first_fr_received;
reg [31:0] addr;
reg [31:0] data;
reg [31:0] tmp;
reg [ 7:0] st_data;
reg [15:0] max_tmp;
reg [15:0] min_tmp;
begin
// MAC FULL DUPLEX RECEIVE TEST
test_heading("MAC FULL DUPLEX RECEIVE TEST");
$display(" ");
$display("MAC FULL DUPLEX RECEIVE TEST");
fail = 0;
 
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
/*
TASKS for set and control TX buffer descriptors (also send packet - set_tx_bd_ready):
-------------------------------------------------------------------------------------
set_tx_bd
(tx_bd_num_start[6:0], tx_bd_num_end[6:0], len[15:0], irq, pad, crc, txpnt[31:0]);
set_tx_bd_wrap
(tx_bd_num_end[6:0]);
set_tx_bd_ready
(tx_bd_num_start[6:0], tx_bd_num_end[6:0]);
check_tx_bd
(tx_bd_num_start[6:0], tx_bd_status[31:0]);
clear_tx_bd
(tx_bd_num_start[6:0], tx_bd_num_end[6:0]);
 
TASKS for set and control RX buffer descriptors:
------------------------------------------------
set_rx_bd
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0], irq, rxpnt[31:0]);
set_rx_bd_wrap
(rx_bd_num_end[6:0]);
set_rx_bd_empty
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0]);
check_rx_bd
(rx_bd_num_end[6:0], rx_bd_status);
clear_rx_bd
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0]);
 
TASKS for set and check TX packets:
-----------------------------------
set_tx_packet
(txpnt[31:0], len[15:0], eth_start_data[7:0]);
check_tx_packet
(txpnt_wb[31:0], txpnt_phy[31:0], len[15:0], failure[31:0]);
 
TASKS for set and check RX packets:
-----------------------------------
set_rx_packet
(rxpnt[31:0], len[15:0], plus_nibble, d_addr[47:0], s_addr[47:0], type_len[15:0], start_data[7:0]);
check_rx_packet
(rxpnt_phy[31:0], rxpnt_wb[31:0], len[15:0], plus_nibble, successful_nibble, failure[31:0]);
 
TASKS for append and check CRC to/of TX packet:
-----------------------------------------------
append_tx_crc
(txpnt_wb[31:0], len[15:0], negated_crc);
check_tx_crc
(txpnt_phy[31:0], len[15:0], negated_crc, failure[31:0]);
 
TASK for append CRC to RX packet (CRC is checked together with check_rx_packet):
--------------------------------------------------------------------------------
append_rx_crc
(rxpnt_phy[31:0], len[15:0], plus_nibble, negated_crc);
*/
 
//////////////////////////////////////////////////////////////////////
//// ////
//// test_mac_full_duplex_receive: ////
//// ////
//// 0: Test no receive when all buffers are TX ( 10Mbps ). ////
//// 1: Test no receive when all buffers are TX ( 100Mbps ). ////
//// 2: Test receive packet synchronization with receive ////
//// disable/enable ( 10Mbps ). ////
//// 3: Test receive packet synchronization with receive ////
//// disable/enable ( 100Mbps ). ////
//// 4: Test receive packets form MINFL to MAXFL sizes at ////
//// one RX buffer decriptor ( 10Mbps ). ////
//// 5: Test receive packets form MINFL to MAXFL sizes at ////
//// one RX buffer decriptor ( 100Mbps ). ////
//// ////
//////////////////////////////////////////////////////////////////////
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1)
begin
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test no receive when all buffers are TX ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 0) // Test no receive when all buffers are TX ( 10Mbps ).
begin
// TEST 0: NO RECEIVE WHEN ALL BUFFERS ARE TX ( 10Mbps )
test_name = "TEST 0: NO RECEIVE WHEN ALL BUFFERS ARE TX ( 10Mbps )";
`TIME; $display(" TEST 0: NO RECEIVE WHEN ALL BUFFERS ARE TX ( 10Mbps )");
 
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set all buffer descriptors to TX - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h80, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
i = 0;
while (i < 128)
begin
for (i1 = 0; i1 <= i; i1 = i1 + 1)
begin
set_rx_packet((i1 * 50), 10, 1'b0, 48'h1234_5678_8765, 48'h0011_2233_4455, 16'h0101, 8'h0);
append_rx_crc((i1 * 50), 10, 1'b0, 1'b0);
set_rx_bd(i1, i1, 1'b1, (`MEMORY_BASE + (i1 * 50)));
end
set_rx_bd_wrap(i);
set_rx_bd_empty(0, i);
for (i1 = 0; i1 <= i; i1 = i1 + 1)
begin
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, (i1 * 50), 14, 1'b0);
repeat(10) @(posedge mrx_clk);
end
@(posedge mrx_clk);
for (i2 = 0; i2 < 20; i2 = i2 + 1)
begin
check_rx_bd(0, tmp);
#1;
if (tmp[15] === 1'b0)
begin
test_fail("Receive should not start at all");
fail = fail + 1;
`TIME; $display("*E Receive of %d packets should not start at all - empty is 0", i);
end
if (tmp[7:0] !== 0)
begin
test_fail("Receive should not be finished since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Receive of should not be finished since it should not start at all");
end
@(posedge wb_clk);
end
wbm_read(`ETH_INT, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp[6:0] !== 0)
begin
test_fail("Receive should not get INT since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Receive of should not get INT since it should not start at all");
end
clear_rx_bd(0, i);
if ((i < 5) || (i > 124))
i = i + 1;
else
i = i + 120;
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test no receive when all buffers are TX ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 1) // Test no receive when all buffers are TX ( 100Mbps ).
begin
// TEST 1: NO RECEIVE WHEN ALL BUFFERS ARE TX ( 100Mbps )
test_name = "TEST 1: NO RECEIVE WHEN ALL BUFFERS ARE TX ( 100Mbps )";
`TIME; $display(" TEST 1: NO RECEIVE WHEN ALL BUFFERS ARE TX ( 100Mbps )");
 
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set all buffer descriptors to TX - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h80, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
i = 0;
while (i < 128)
begin
for (i1 = 0; i1 <= i; i1 = i1 + 1)
begin
set_rx_packet((i1 * 50), 10, 1'b0, 48'h1234_5678_8765, 48'h0011_2233_4455, 16'h0101, 8'h0);
append_rx_crc((i1 * 50), 10, 1'b0, 1'b0);
set_rx_bd(i1, i1, 1'b1, (`MEMORY_BASE + (i1 * 50)));
end
set_rx_bd_wrap(i);
set_rx_bd_empty(0, i);
for (i1 = 0; i1 <= i; i1 = i1 + 1)
begin
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, (i1 * 50), 14, 1'b0);
repeat(10) @(posedge mrx_clk);
end
@(posedge mrx_clk);
for (i2 = 0; i2 < 20; i2 = i2 + 1)
begin
check_rx_bd(0, tmp);
#1;
if (tmp[15] === 1'b0)
begin
test_fail("Receive should not start at all");
fail = fail + 1;
`TIME; $display("*E Receive of %d packets should not start at all - empty is 0", i);
end
if (tmp[7:0] !== 0)
begin
test_fail("Receive should not be finished since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Receive of should not be finished since it should not start at all");
end
@(posedge wb_clk);
end
wbm_read(`ETH_INT, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (tmp[6:0] !== 0)
begin
test_fail("Receive should not get INT since it should not start at all");
fail = fail + 1;
`TIME; $display("*E Receive of should not get INT since it should not start at all");
end
clear_rx_bd(0, i);
if ((i < 5) || (i > 124))
i = i + 1;
else
i = i + 120;
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packet synchronization with receive ////
//// disable/enable ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 2) // Test no receive when all buffers are TX ( 10Mbps ).
begin
// TEST 2: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )
test_name = "TEST 2: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )";
`TIME; $display(" TEST 2: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )");
 
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set 10 RX buffer descriptor (8'h80 - 8'hA) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h76, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// disable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h0F;
set_rx_packet(0, (min_tmp + 1), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
append_rx_crc(0, (min_tmp + 1), 1'b0, 1'b0);
st_data = 8'h1A;
set_rx_packet(max_tmp, (min_tmp + 1), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
append_rx_crc(max_tmp, (min_tmp + 1), 1'b0, 1'b0);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
 
frame_started = 0;
frame_ended = 0;
wait_for_frame = 0;
check_frame = 0;
stop_checking_frame = 0;
first_fr_received = 1; // at the beginning the first frame of each two will be received!
num_of_frames = 0; //
num_of_bd = 0;
i_length = (min_tmp + 1); // 5 bytes longer than MINFL
while (i_length < (max_tmp - 4))
begin
// choose generating carrier sense and collision
case (num_of_frames[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is generated
begin
// disable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is generated
begin
// disable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
// set wrap bit
set_rx_bd_wrap(118);
set_rx_bd_empty(118, 118);
check_frame = 0;
stop_checking_frame = 0;
tmp_data = 0;
fork
begin // enable RX MAC on first of each two packets - every second should be recived normaly
if (num_of_frames[0] == 1'b0)
begin
repeat(1) @(posedge wb_clk);
if (num_of_frames[1] == 1'b0)
begin
repeat (num_of_frames[31:2]) @(posedge mrx_clk); // for every (second) frame enable receiver one clock later
end
else
begin
@(posedge mrx_clk);
repeat (num_of_frames[31:2]) @(negedge mrx_clk); // for every (second) frame enable receiver one clock later
end
// enable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_init_waits = 4'h0;
wbm_subseq_waits = 4'h0;
#1 wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits); // write ASAP
end
end
begin // send a packet from PHY RX
repeat(1) @(posedge wb_clk); // wait for WB write when it is without delays
if (num_of_frames[1] == 1'b0)
begin
set_rx_addr_type(0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E);
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
end
else
begin
set_rx_addr_type((max_tmp), 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E);
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
end
end
begin: send_packet0
wait (MRxDV === 1'b1); // start transmit
wait (MRxDV === 1'b0); // end transmit
check_frame = 1;
repeat(10) @(posedge mrx_clk);
repeat(15) @(posedge wb_clk);
stop_checking_frame = 1;
end
begin // count WB clocks between ACK (negedge) and RX_DV (posedge) or vice-versa
@(posedge eth_sl_wb_ack_o or posedge MRxDV);
if ((eth_sl_wb_ack_o === 1'b1) && (MRxDV === 1'b1))
begin
tmp_data = 32'h8000_0001; // bit[31]==1 => 'posedge MRxDV' was before 'negedge eth_sl_wb_ack_o'
end
else if (MRxDV === 1'b1)
begin
while (eth_sl_wb_ack_o === 1'b0)
begin
@(posedge wb_clk);
tmp_data = tmp_data + 1;
end
tmp_data = tmp_data | 32'h8000_0000; // bit[31]==1 => 'posedge MRxDV' was before 'negedge eth_sl_wb_ack_o'
end
else if (eth_sl_wb_ack_o === 1'b1)
begin
@(posedge wb_clk); // wait for one clock => tmp_data 'becomes' 0
while (MRxDV === 1'b0)
begin
@(posedge wb_clk);
tmp_data = tmp_data + 1; // bit[31]==0 => 'negedge eth_sl_wb_ack_o' was equal or before 'posedge MRxDV'
end
end
end
begin // check packet
wait (check_frame == 1);
check_rx_bd(118, tmp_bd);
while ((tmp_bd[15] === 1) && (stop_checking_frame == 0))
begin
#1 check_rx_bd(118, tmp_bd);
@(posedge wb_clk);
end
if (num_of_frames[0] == 1'b0)
begin
if (tmp_bd[15] === 1)
begin
if (first_fr_received == 1)
begin
first_fr_received = 0;
$display(" %0d packets (without this one) are checked - packets are received by two in a set",
num_of_frames); // +1 due to start with 0 AND -1 because this packet is excluded
$display(" From this moment:");
$display(" first one of two packets (including this one) is not accepted due to late RX enable");
if (tmp_data[31])
$display(" ->RX enable set %0d WB clks after RX_DV", tmp_data[30:0]);
else
$display(" ->RX enable set %0d WB clks before RX_DV", tmp_data[30:0]);
end
end
end
if (stop_checking_frame == 0)
disable send_packet0;
end
join
// ONLY IF packet was received!
if (tmp_bd[15] === 0)
begin
// check length of a PACKET
if (tmp_bd[31:16] != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
tmp_bd[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// check received RX packet data and CRC
if (first_fr_received == 0) // if PREVIOUS RX buffer descriptor was not ready, pointer address is -1
begin
if (num_of_frames[1] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + num_of_frames[1:0] - 1'b1), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, (`MEMORY_BASE + num_of_frames[1:0] - 1'b1), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
end
else // if PREVIOUS RX buffer descriptor was ready
begin
if (num_of_frames[1] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + num_of_frames[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, (`MEMORY_BASE + num_of_frames[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
end
end
// check WB INT signal
if ((num_of_frames[0] == 1'b0) && (first_fr_received == 0)) // interrupt enabled but no receive
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
// check RX buffer descriptor of a packet - only 15 LSBits
check_rx_bd(118, data);
if ((num_of_frames[0] == 1'b0) && (first_fr_received == 0)) // interrupt enabled but no receive
begin
if (data[15:0] !== 16'hE000)
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt enabled
begin
if (data[15:0] !== 16'h6000)
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((num_of_frames[0] == 1'b0) && (first_fr_received == 0)) // interrupt enabled but no receive
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts was set, interrupt reg: %0h, len: %0h", data, num_of_frames[1:0]);
test_fail("Any of interrupts was set");
fail = fail + 1;
end
end
else
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// disable RX after two packets
if (num_of_frames[0] == 1'b1)
begin
// disable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, 4'h0, 4'h0); // write ASAP
end
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = 0;
// set length (LOOP variable)
if (num_of_frames[31:2] == (i_length * 2 + 16)) // 64 => this vas last Byte (1st .. 64th) when i_length = min_tmp - 4
i_length = (max_tmp - 4);
@(posedge wb_clk);
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packet synchronization with receive ////
//// disable/enable ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 3) // Test no receive when all buffers are TX ( 100Mbps ).
begin
// TEST 3: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 100Mbps )
test_name = "TEST 3: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 100Mbps )";
`TIME; $display(" TEST 3: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 100Mbps )");
 
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set 10 RX buffer descriptor (8'h80 - 8'hA) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h76, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// disable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h0F;
set_rx_packet(0, (min_tmp + 1), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
append_rx_crc(0, (min_tmp + 1), 1'b0, 1'b0);
st_data = 8'h1A;
set_rx_packet(max_tmp, (min_tmp + 1), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
append_rx_crc(max_tmp, (min_tmp + 1), 1'b0, 1'b0);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
 
frame_started = 0;
frame_ended = 0;
wait_for_frame = 0;
check_frame = 0;
stop_checking_frame = 0;
first_fr_received = 1; // at the beginning the first frame of each two will be received!
num_of_frames = 0; //
num_of_bd = 0;
i_length = (min_tmp + 1); // 5 bytes longer than MINFL
while (i_length < (max_tmp - 4))
begin
// choose generating carrier sense and collision
case (num_of_frames[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is generated
begin
// disable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is generated
begin
// disable interrupt generation
set_rx_bd(118, 118, 1'b1, (`MEMORY_BASE + num_of_frames[1:0]));
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
//if (first_fr_received == 0)
//begin
// check_rx_bd(118, data);
// wbm_read((`TX_BD_BASE + (118 * 8) + 4), tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// $display("RX BD set : %h, %h", data, tmp);
//end
// set wrap bit
set_rx_bd_wrap(118);
set_rx_bd_empty(118, 118);
check_frame = 0;
stop_checking_frame = 0;
tmp_data = 0;
$display("mama 1");
fork
begin // enable RX MAC on first of each two packets - every second should be recived normaly
if (num_of_frames[0] == 1'b0)
begin
repeat(1) @(posedge wb_clk);
if (num_of_frames[1] == 1'b0)
begin
repeat (num_of_frames[31:2]) @(posedge mrx_clk); // for every (second) frame enable receiver one clock later
end
else
begin
@(posedge mrx_clk);
repeat (num_of_frames[31:2]) @(negedge mrx_clk); // for every (second) frame enable receiver one clock later
end
// enable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_init_waits = 4'h0;
wbm_subseq_waits = 4'h0;
#1 wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits); // write ASAP
$display("mama 2, num_of_frames=%0h", num_of_frames);
end
end
begin // send a packet from PHY RX
repeat(1) @(posedge wb_clk); // wait for WB write when it is without delays
if (num_of_frames[1] == 1'b0)
begin
set_rx_addr_type(0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E);
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
end
else
begin
set_rx_addr_type((max_tmp), 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E);
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
end
end
begin: send_packet1
wait (MRxDV === 1'b1); // start transmit
wait (MRxDV === 1'b0); // end transmit
check_frame = 1;
$display("mama 3");
repeat(10) @(posedge mrx_clk);
repeat(15) @(posedge wb_clk);
stop_checking_frame = 1;
end
begin // count WB clocks between ACK (negedge) and RX_DV (posedge) or vice-versa
@(posedge eth_sl_wb_ack_o or posedge MRxDV);
$display("mama 4");
if ((eth_sl_wb_ack_o === 1'b1) && (MRxDV === 1'b1))
begin
tmp_data = 32'h8000_0001; // bit[31]==1 => 'posedge MRxDV' was before 'negedge eth_sl_wb_ack_o'
$display("mama 4_1");
end
else if (MRxDV === 1'b1)
begin
while (eth_sl_wb_ack_o === 1'b0)
begin
@(posedge wb_clk);
tmp_data = tmp_data + 1;
end
tmp_data = tmp_data | 32'h8000_0000; // bit[31]==1 => 'posedge MRxDV' was before 'negedge eth_sl_wb_ack_o'
$display("mama 4_2");
end
else if (eth_sl_wb_ack_o === 1'b1)
begin
@(posedge wb_clk); // wait for one clock => tmp_data 'becomes' 0
while (MRxDV === 1'b0)
begin
@(posedge wb_clk);
tmp_data = tmp_data + 1; // bit[31]==0 => 'negedge eth_sl_wb_ack_o' was equal or before 'posedge MRxDV'
end
$display("mama 4_3");
end
end
begin // check packet
wait (check_frame == 1);
check_rx_bd(118, tmp_bd);
while ((tmp_bd[15] === 1) && (stop_checking_frame == 0))
begin
#1 check_rx_bd(118, tmp_bd);
@(posedge wb_clk);
end
$display("mama 5, tmp_bd=%0h", tmp_bd);
if (num_of_frames[0] == 1'b0)
begin
if (tmp_bd[15] === 1)
begin
if (first_fr_received == 1)
begin
first_fr_received = 0;
$display(" %0d packets (without this one) are checked - packets are received by two in a set",
num_of_frames); // +1 due to start with 0 AND -1 because this packet is excluded
$display(" From this moment:");
$display(" first one of two packets (including this one) is not accepted due to late RX enable");
if (tmp_data[31])
$display(" ->RX enable set %0d WB clks after RX_DV", tmp_data[30:0]);
else
$display(" ->RX enable set %0d WB clks before RX_DV", tmp_data[30:0]);
end
// check FB, etc.
end
else // (tmp_bd[15] === 0)
begin // check FB, packet, etc.
end
$display("mama 5_1");
end
else // (num_of_frames[0] == 1'b1)
begin
if (tmp_bd[15] === 1) // ERROR, because second packet of each two frames should be received
begin // check NOTHING
end
else // (tmp_bd[15] === 0)
begin // check FB, packet, etc.
end
$display("mama 5_2");
end
if (stop_checking_frame == 0)
disable send_packet1;
end
join
// ONLY IF packet was received!
$display("mama 6");
if (tmp_bd[15] === 0)
begin
// check length of a PACKET
if (tmp_bd[31:16] != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
tmp_bd[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// check received RX packet data and CRC
if (first_fr_received == 0) // if PREVIOUS RX buffer descriptor was not ready, pointer address is -1
begin
if (num_of_frames[1] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + num_of_frames[1:0] - 1'b1), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, (`MEMORY_BASE + num_of_frames[1:0] - 1'b1), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
end
else // if PREVIOUS RX buffer descriptor was ready
begin
if (num_of_frames[1] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + num_of_frames[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, (`MEMORY_BASE + num_of_frames[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
end
end
// check WB INT signal
if ((num_of_frames[0] == 1'b0) && (first_fr_received == 0)) // interrupt enabled but no receive
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
// check RX buffer descriptor of a packet - only 15 LSBits
check_rx_bd(118, data);
if ((num_of_frames[0] == 1'b0) && (first_fr_received == 0)) // interrupt enabled but no receive
begin
if (data[15:0] !== 16'hE000)
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt enabled
begin
if (data[15:0] !== 16'h6000)
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((num_of_frames[0] == 1'b0) && (first_fr_received == 0)) // interrupt enabled but no receive
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts was set, interrupt reg: %0h, len: %0h", data, num_of_frames[1:0]);
test_fail("Any of interrupts was set");
fail = fail + 1;
end
end
else
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// disable RX after two packets
if (num_of_frames[0] == 1'b1)
begin
// disable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, 4'h0, 4'h0); // write ASAP
end
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
num_of_bd = 0;
// set length (LOOP variable)
if (num_of_frames[31:2] == (i_length * 2 + 16)) // 64 => this vas last Byte (1st .. 64th) when i_length = min_tmp - 4
i_length = (max_tmp - 4);
@(posedge wb_clk);
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packets form MINFL to MAXFL sizes at ////
//// one RX buffer decriptor ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 4) //
begin
// TEST 4: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT ONE RX BD ( 10Mbps )
test_name = "TEST 4: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT ONE RX BD ( 10Mbps )";
`TIME; $display(" TEST 4: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT ONE RX BD ( 10Mbps )");
 
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set 1 RX buffer descriptor (8'h80 - 1) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h7F, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h0F;
set_rx_packet(0, (max_tmp - 4), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
st_data = 8'h1A;
set_rx_packet((max_tmp), (max_tmp - 4), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
 
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// choose generating carrier sense and collision for first and last 64 lengths of frames
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(127, 127, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_rx_bd(127, 127, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(127, 127, 1'b0, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(127, 127, 1'b0, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
if (i_length[0] == 1'b0)
append_rx_crc (0, i_length, 1'b0, 1'b0);
else
append_rx_crc (max_tmp, i_length, 1'b0, 1'b0);
// set wrap bit
set_rx_bd_wrap(127);
set_rx_bd_empty(127, 127);
fork
begin
if (i_length[0] == 1'b0)
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
else
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
repeat(10) @(posedge mrx_clk);
end
begin
#1 check_rx_bd(127, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_rx_bd(127, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MRxDV === 1'b1); // start transmit
#1 check_rx_bd(127, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MRxDV === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_rx_bd(127, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
end
join
// check length of a PACKET
if (data[31:16] != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
data[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// checking in the following if statement is performed only for first and last 64 lengths
// check received RX packet data and CRC
if (i_length[0] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + i_length[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, ((`MEMORY_BASE + i_length[1:0]) + max_tmp), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check RX buffer descriptor of a packet
check_rx_bd(127, data);
if (i_length[1] == 1'b0) // interrupt enabled no_carrier_sense_rx_fd_detect
begin
if ( ((data[15:0] !== 16'h6000) && (i_length[0] == 1'b0)) ||
((data[15:0] !== 16'h6000) && (i_length[0] == 1'b1)) )
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( ((data[15:0] !== 16'h2000) && (i_length[0] == 1'b0)) ||
((data[15:0] !== 16'h2000) && (i_length[0] == 1'b1)) )
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear RX buffer descriptor for first 4 frames
if (i_length < min_tmp)
clear_rx_bd(127, 127);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Receive Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Receive Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 64))
begin
// starting length is min_tmp, ending length is (min_tmp + 64)
$display(" receive small packets is NOT selected");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 64));
// set receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" receive small packets is selected");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
// reset receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" receive small packets is NOT selected");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 64))
i_length = i_length + 1;
else if ( ((i_length + 4) >= (min_tmp + 64)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packets form MINFL to MAXFL sizes at ////
//// one RX buffer decriptor ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 5) // Test no receive when all buffers are TX ( 100Mbps ).
begin
// TEST 5: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT ONE RX BD ( 100Mbps )
test_name = "TEST 5: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT ONE RX BD ( 100Mbps )";
`TIME; $display(" TEST 5: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT ONE RX BD ( 100Mbps )");
 
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set 1 RX buffer descriptor (8'h80 - 1) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h7F, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'h0F;
set_rx_packet(0, (max_tmp - 4), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
st_data = 8'h1A;
set_rx_packet((max_tmp), (max_tmp - 4), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
 
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// choose generating carrier sense and collision for first and last 64 lengths of frames
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(127, 127, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_rx_bd(127, 127, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(127, 127, 1'b0, (`MEMORY_BASE + i_length[1:0]));
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(127, 127, 1'b0, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
if (i_length[0] == 1'b0)
append_rx_crc (0, i_length, 1'b0, 1'b0);
else
append_rx_crc (max_tmp, i_length, 1'b0, 1'b0);
// set wrap bit
set_rx_bd_wrap(127);
set_rx_bd_empty(127, 127);
fork
begin
if (i_length[0] == 1'b0)
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
else
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
repeat(10) @(posedge mrx_clk);
end
begin
#1 check_rx_bd(127, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_rx_bd(127, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MRxDV === 1'b1); // start transmit
#1 check_rx_bd(127, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MRxDV === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_rx_bd(127, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
end
join
// check length of a PACKET
if (data[31:16] != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
data[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// checking in the following if statement is performed only for first and last 64 lengths
// check received RX packet data and CRC
if (i_length[0] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + i_length[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, ((`MEMORY_BASE + i_length[1:0]) + max_tmp), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check RX buffer descriptor of a packet
check_rx_bd(127, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( ((data[15:0] !== 16'h6000) && (i_length[0] == 1'b0)) ||
((data[15:0] !== 16'h6000) && (i_length[0] == 1'b1)) )
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( ((data[15:0] !== 16'h2000) && (i_length[0] == 1'b0)) ||
((data[15:0] !== 16'h2000) && (i_length[0] == 1'b1)) )
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear RX buffer descriptor for first 4 frames
if (i_length < min_tmp)
clear_rx_bd(127, 127);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Receive Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Receive Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 64))
begin
// starting length is min_tmp, ending length is (min_tmp + 64)
$display(" receive small packets is NOT selected");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 64));
// set receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" receive small packets is selected");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
// reset receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" receive small packets is NOT selected");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 64))
i_length = i_length + 1;
else if ( ((i_length + 4) >= (min_tmp + 64)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packets form MINFL to MAXFL sizes at ////
//// maximum RX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 6) //
begin
// TEST 6: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT MAX RX BDs ( 10Mbps )
test_name = "TEST 6: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT MAX RX BDs ( 10Mbps )";
`TIME; $display(" TEST 6: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT MAX RX BDs ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set maximum RX buffer descriptors (128) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hAC;
set_rx_packet(0, (max_tmp - 4), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
st_data = 8'h35;
set_rx_packet((max_tmp), (max_tmp - 4), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
 
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// append CRC to packet
if (i_length[0] == 1'b0)
append_rx_crc (0, i_length, 1'b0, 1'b0);
else
append_rx_crc (max_tmp, i_length, 1'b0, 1'b0);
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
// first 8 frames are received with RX BD 0 (wrap bit on RX BD 0)
// number of all frames is 154 (146 without first 8)
if (num_of_frames < 8)
begin
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(0, 0, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_rx_bd(0, 0, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(0, 0, 1'b0, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(0, 0, 1'b0, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
endcase
// set wrap bit
set_rx_bd_wrap(0);
end
// after first 8 number of frames, 128 frames form RX BD 0 to 127 will be received
else if ((num_of_frames - 8) == 0)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // RX BD number
while (tmp_bd_num < 128) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(127);
end
// after 128 + first 8 number of frames, 19 frames form RX BD 0 to 18 will be received
else if ((num_of_frames - 8) == 20) // 128
begin
tmp_len = tmp_len; // length of frame remaines from previous settings
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 19) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
end
// set empty bit
if (num_of_frames < 8)
set_rx_bd_empty(0, 0);
else if ((num_of_frames - 8) < 128)
set_rx_bd_empty((num_of_frames - 8), (num_of_frames - 8));
else if ((num_of_frames - 136) < 19)
set_rx_bd_empty((num_of_frames - 136), (num_of_frames - 136));
// CHECK END OF RECEIVE
fork
begin
if (i_length[0] == 1'b0)
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
else
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
repeat(10) @(posedge mrx_clk);
end
begin
#1 check_rx_bd(num_of_bd, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_rx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MRxDV === 1'b1); // start transmit
#1 check_rx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MRxDV === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_rx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
end
join
// check length of a PACKET
if (data[31:16] != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
data[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// checking in the following if statement is performed only for first and last 64 lengths
// check received RX packet data and CRC
if (i_length[0] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + i_length[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, ((`MEMORY_BASE + i_length[1:0]) + max_tmp), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check RX buffer descriptor of a packet
check_rx_bd(num_of_bd, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( ((data[15:0] !== 16'h6000) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h4000) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( ((data[15:0] !== 16'h2000) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h0000) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear first half of 8 frames from RX buffer descriptor 0
if (num_of_frames < 4)
clear_rx_bd(num_of_bd, num_of_bd);
// clear BD with wrap bit
if (num_of_frames == 140)
clear_rx_bd(127, 127);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Receive Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Receive Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 7))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" receive small packets is NOT selected");
$display(" using only RX BD 0 out of 128 BDs assigned to RX (wrap at first BD - RX BD 0)");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 7));
$display(" ->all packets were received on RX BD 0");
// reset receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (min_tmp + 128))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" receive small packets is NOT selected");
$display(" using all 128 BDs assigned to RX (wrap at 128th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
(min_tmp + 8), (min_tmp + 128));
$display(" ->packets were received on RX BD %0d to RX BD %0d respectively",
1'b0, num_of_bd);
tmp_bd = num_of_bd + 1;
// set receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" receive small packets is selected");
$display(" using all 128 BDs assigned to RX (wrap at 128th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
if (tmp_bd > num_of_bd)
$display(" ->packets were received from RX BD %0d to RX BD 127 and from RX BD 0 to RX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were received from RX BD %0d to RX BD %0d respectively",
tmp_bd, num_of_bd);
tmp_bd = num_of_bd + 1;
// reset receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" receive small packets is NOT selected");
$display(" using all 128 BDs assigned to RX (wrap at 128th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
if (tmp_bd > num_of_bd)
$display(" ->packets were received from RX BD %0d to RX BD 127 and from RX BD 0 to RX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were received from RX BD %0d to RX BD %0d respectively",
tmp_bd, num_of_bd);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 128))
i_length = i_length + 1;
else if ( ((i_length + 4) == (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
i_length = 256;
else if ( ((i_length + 4) > (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if ((num_of_frames <= 8) || ((num_of_frames - 8) == 128))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packets form MINFL to MAXFL sizes at ////
//// maximum RX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 7) //
begin
// TEST 7: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT MAX RX BDs ( 100Mbps )
test_name = "TEST 7: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT MAX RX BDs ( 100Mbps )";
`TIME; $display(" TEST 7: RECEIVE PACKETS FROM MINFL TO MAXFL SIZES AT MAX RX BDs ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
num_of_frames = 0;
num_of_bd = 0;
// set maximum RX buffer descriptors (128) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, NO receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hAC;
set_rx_packet(0, (max_tmp - 4), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
st_data = 8'h35;
set_rx_packet((max_tmp), (max_tmp - 4), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
 
i_length = (min_tmp - 4);
while (i_length <= (max_tmp - 4))
begin
// append CRC to packet
if (i_length[0] == 1'b0)
append_rx_crc (0, i_length, 1'b0, 1'b0);
else
append_rx_crc (max_tmp, i_length, 1'b0, 1'b0);
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// Reset_tx_bd nable interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1: // Interrupt is not generated
begin
// set_tx_bd enable interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3: // Interrupt is not generated
begin
// set_tx_bd disable the interrupt generation
// mask interrupts
wbm_write(`ETH_INT_MASK, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
// first 8 frames are received with RX BD 0 (wrap bit on RX BD 0)
// number of all frames is 154 (146 without first 8)
if (num_of_frames < 8)
begin
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(0, 0, 1'b1, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
2'h1: // Interrupt is not generated
begin
// enable interrupt generation
set_rx_bd(0, 0, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
2'h2: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(0, 0, 1'b0, (`MEMORY_BASE + i_length[1:0]));
// interrupts are unmasked
end
default: // 2'h3: // Interrupt is not generated
begin
// disable interrupt generation
set_rx_bd(0, 0, 1'b0, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
// interrupts are masked
end
endcase
// set wrap bit
set_rx_bd_wrap(0);
end
// after first 8 number of frames, 128 frames form RX BD 0 to 127 will be received
else if ((num_of_frames - 8) == 0)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 0; // RX BD number
while (tmp_bd_num < 128) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(127);
end
// after 128 + first 8 number of frames, 19 frames form RX BD 0 to 18 will be received
else if ((num_of_frames - 8) == 20) // 128
begin
tmp_len = tmp_len; // length of frame remaines from previous settings
tmp_bd_num = 0; // TX BD number
while (tmp_bd_num < 19) // (tmp_len <= (max_tmp - 4)) - this is the last frame
begin
// if i_length[1] == 0 then enable interrupt generation otherwise disable it
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, !tmp_len[1], ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
if ((tmp_len + 4) < (min_tmp + 128))
tmp_len = tmp_len + 1;
else if ( ((tmp_len + 4) == (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = 256;
else if ( ((tmp_len + 4) > (min_tmp + 128)) && ((tmp_len + 4) <= (max_tmp - 256)) )
tmp_len = tmp_len + 128;
else if ( ((tmp_len + 4) > (max_tmp - 256)) && ((tmp_len + 4) < (max_tmp - 16)) )
tmp_len = max_tmp - (4 + 16);
else if ((tmp_len + 4) >= (max_tmp - 16))
tmp_len = tmp_len + 1;
// set TX BD number
tmp_bd_num = tmp_bd_num + 1;
end
end
// set empty bit
if (num_of_frames < 8)
set_rx_bd_empty(0, 0);
else if ((num_of_frames - 8) < 128)
set_rx_bd_empty((num_of_frames - 8), (num_of_frames - 8));
else if ((num_of_frames - 136) < 19)
set_rx_bd_empty((num_of_frames - 136), (num_of_frames - 136));
// CHECK END OF RECEIVE
fork
begin
if (i_length[0] == 1'b0)
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
else
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
repeat(10) @(posedge mrx_clk);
end
begin
#1 check_rx_bd(num_of_bd, data);
if (i_length < min_tmp) // just first four
begin
while (data[15] === 1)
begin
#1 check_rx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
else
begin
wait (MRxDV === 1'b1); // start transmit
#1 check_rx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's ready bit read out from MAC");
fail = fail + 1;
end
wait (MRxDV === 1'b0); // end transmit
while (data[15] === 1)
begin
#1 check_rx_bd(num_of_bd, data);
@(posedge wb_clk);
end
repeat (1) @(posedge wb_clk);
end
end
join
// check length of a PACKET
if (data[31:16] != (i_length + 4))
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
data[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// check received RX packet data and CRC
if (i_length[0] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + i_length[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, ((`MEMORY_BASE + i_length[1:0]) + max_tmp), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
// check WB INT signal
if (i_length[1:0] == 2'h0)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
// check RX buffer descriptor of a packet
check_rx_bd(num_of_bd, data);
if (i_length[1] == 1'b0) // interrupt enabled
begin
if ( ((data[15:0] !== 16'h6000) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h4000) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else // interrupt not enabled
begin
if ( ((data[15:0] !== 16'h2000) && ((num_of_frames < 8) || ((num_of_frames - 8) == 127))) || // wrap bit
((data[15:0] !== 16'h0000) && (num_of_frames >= 8) && ((num_of_frames - 8) != 127)) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h", data[15:0]);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// clear first half of 8 frames from RX buffer descriptor 0
if (num_of_frames < 4)
clear_rx_bd(num_of_bd, num_of_bd);
// clear BD with wrap bit
if (num_of_frames == 140)
clear_rx_bd(127, 127);
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if ((i_length[1:0] == 2'h0) || (i_length[1:0] == 2'h1))
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
else
begin
if (data !== 0)
begin
`TIME; $display("*E Any of interrupts (except Receive Buffer) was set, interrupt reg: %0h, len: %0h", data, i_length[1:0]);
test_fail("Any of interrupts (except Receive Buffer) was set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if ((i_length + 4) == (min_tmp + 7))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" receive small packets is NOT selected");
$display(" using only RX BD 0 out of 128 BDs assigned to RX (wrap at first BD - RX BD 0)");
$display(" ->packets with lengths from %0d (MINFL) to %0d are checked (length increasing by 1 byte)",
min_tmp, (min_tmp + 7));
$display(" ->all packets were received on RX BD 0");
// reset receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (min_tmp + 128))
begin
// starting length is min_tmp, ending length is (min_tmp + 128)
$display(" receive small packets is NOT selected");
$display(" using all 128 BDs assigned to RX (wrap at 128th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
(min_tmp + 8), (min_tmp + 128));
$display(" ->packets were received on RX BD %0d to RX BD %0d respectively",
1'b0, num_of_bd);
tmp_bd = num_of_bd + 1;
// set receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == (max_tmp - 16))
begin
// starting length is for +128 longer than previous ending length, while ending length is tmp_data
$display(" receive small packets is selected");
$display(" using all 128 BDs assigned to RX (wrap at 128th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 128 bytes)",
(min_tmp + 64 + 128), tmp_data);
if (tmp_bd > num_of_bd)
$display(" ->packets were received from RX BD %0d to RX BD 127 and from RX BD 0 to RX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were received from RX BD %0d to RX BD %0d respectively",
tmp_bd, num_of_bd);
tmp_bd = num_of_bd + 1;
// reset receive small, remain the rest
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
else if ((i_length + 4) == max_tmp)
begin
$display(" receive small packets is NOT selected");
$display(" using all 128 BDs assigned to RX (wrap at 128th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d (MAXFL) are checked (length increasing by 1 byte)",
(max_tmp - (4 + 16)), max_tmp);
if (tmp_bd > num_of_bd)
$display(" ->packets were received from RX BD %0d to RX BD 127 and from RX BD 0 to RX BD %0d respectively",
tmp_bd, num_of_bd);
else
$display(" ->packets were received from RX BD %0d to RX BD %0d respectively",
tmp_bd, num_of_bd);
end
// set length (loop variable)
if ((i_length + 4) < (min_tmp + 128))
i_length = i_length + 1;
else if ( ((i_length + 4) == (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
i_length = 256;
else if ( ((i_length + 4) > (min_tmp + 128)) && ((i_length + 4) <= (max_tmp - 256)) )
begin
i_length = i_length + 128;
tmp_data = i_length + 4; // last tmp_data is ending length
end
else if ( ((i_length + 4) > (max_tmp - 256)) && ((i_length + 4) < (max_tmp - 16)) )
i_length = max_tmp - (4 + 16);
else if ((i_length + 4) >= (max_tmp - 16))
i_length = i_length + 1;
else
begin
$display("*E TESTBENCH ERROR - WRONG PARAMETERS IN TESTBENCH");
#10 $stop;
end
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if ((num_of_frames <= 8) || ((num_of_frames - 8) == 128))
num_of_bd = 0;
else
num_of_bd = num_of_bd + 1;
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packets form 0 to (MINFL + 12) sizes at ////
//// 8 RX buffer decriptors ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 8) //
begin
// TEST 8: RECEIVE PACKETS FROM 0 TO (MINFL + 12) SIZES AT 8 TX BD ( 10Mbps )
test_name = "TEST 8: RECEIVE PACKETS FROM 0 TO (MINFL + 12) SIZES AT 8 TX BD ( 10Mbps )";
`TIME; $display(" TEST 8: RECEIVE PACKETS FROM 0 TO (MINFL + 12) SIZES AT 8 TX BD ( 10Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 8 RX buffer descriptors (120 - 127) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h78, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hAC;
set_rx_packet(0, (max_tmp - 4), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
st_data = 8'h35;
set_rx_packet((max_tmp), (max_tmp - 4), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
 
// write to phy's control register for 10Mbps
#Tp eth_phy.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 10;
frame_ended = 0;
num_of_frames = 0;// 0; // 10;
num_of_bd = 120;
i_length = 0 - 4;// (0 - 4); // 6; // 4 less due to CRC
while ((i_length + 4) < 78) // (min_tmp - 4))
begin
// append CRC to packet
if ((i_length[0] == 1'b0) && (num_of_frames > 4))
append_rx_crc (0, i_length, 1'b0, 1'b0);
else if (num_of_frames > 4)
append_rx_crc (max_tmp, i_length, 1'b0, 1'b0);
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0:
begin
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1:
begin
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2:
begin
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3:
begin
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
#1;
// first 10 frames are received with RX BD 120 (wrap bit on RX BD 120)
if (num_of_frames <= 9)
begin
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, (`MEMORY_BASE + i_length[1:0]));
end
2'h1: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
end
2'h2: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, (`MEMORY_BASE + i_length[1:0]));
end
default: // 2'h3: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
end
endcase
// set wrap bit
set_rx_bd_wrap(120);
end
// 10 <= num_of_frames < 18 => wrap set to TX BD 123
else if ((num_of_frames == 10) || (num_of_frames == 14))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 124) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(123);
end
// 18 <= num_of_frames < 28 => wrap set to RX BD 124
else if ((num_of_frames == 18) || (num_of_frames == 23))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 125) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(124);
end
// 28 <= num_of_frames < 40 => wrap set to RX BD 125
else if ((num_of_frames == 28) || (num_of_frames == 34))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 126) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(125);
end
// 40 <= num_of_frames < 54 => wrap set to RX BD 126
else if ((num_of_frames == 40) || (num_of_frames == 47))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 127) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(126);
end
// 54 <= num_of_frames < 70 => wrap set to RX BD 127
else if ((num_of_frames == 54) || (num_of_frames == 62))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 128) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(127);
end
// 70 <= num_of_frames < 78 => wrap set to RX BD 127
else if (num_of_frames == 70)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 128) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(127);
end
#1;
// SET empty bit
if (num_of_frames < 10)
set_rx_bd_empty(120, 120);
else if (num_of_frames < 14)
set_rx_bd_empty((120 + num_of_frames - 10), (120 + num_of_frames - 10));
else if (num_of_frames < 18)
set_rx_bd_empty((120 + num_of_frames - 14), (120 + num_of_frames - 14));
else if (num_of_frames < 23)
set_rx_bd_empty((120 + num_of_frames - 18), (120 + num_of_frames - 18));
else if (num_of_frames < 28)
set_rx_bd_empty((120 + num_of_frames - 23), (120 + num_of_frames - 23));
else if (num_of_frames < 34)
set_rx_bd_empty((120 + num_of_frames - 28), (120 + num_of_frames - 28));
else if (num_of_frames < 40)
set_rx_bd_empty((120 + num_of_frames - 34), (120 + num_of_frames - 34));
else if (num_of_frames < 47)
set_rx_bd_empty((120 + num_of_frames - 40), (120 + num_of_frames - 40));
else if (num_of_frames < 54)
set_rx_bd_empty((120 + num_of_frames - 47), (120 + num_of_frames - 47));
else if (num_of_frames < 62)
set_rx_bd_empty((120 + num_of_frames - 54), (120 + num_of_frames - 54));
else if (num_of_frames < 70)
set_rx_bd_empty((120 + num_of_frames - 62), (120 + num_of_frames - 62));
else if (num_of_frames < 78)
set_rx_bd_empty((120 + num_of_frames - 70), (120 + num_of_frames - 70));
// CHECK END OF RECEIVE
frame_ended = 0;
check_frame = 0;
fork
begin
if (i_length[0] == 1'b0)
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
else
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
repeat(10) @(posedge mrx_clk);
end
begin: fr_end1
wait (MRxDV === 1'b1); // start receive
#1 check_rx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's empty bit read out from MAC");
fail = fail + 1;
end
wait (MRxDV === 1'b0); // end receive
while ((data[15] === 1) && (check_frame == 0))
begin
#1 check_rx_bd(num_of_bd, data);
@(posedge wb_clk);
end
if (data[15] === 0)
frame_ended = 1;
repeat (1) @(posedge wb_clk);
end
begin
wait (MRxDV === 1'b1); // start receive
wait (MRxDV === 1'b0); // end receive
repeat(10) @(posedge mrx_clk);
repeat(15) @(posedge wb_clk);
check_frame = 1;
end
join
// check length of a PACKET
if ( ((data[31:16] != (i_length + 4)) && (num_of_frames >= 3)) ||
((data[31:16] != 0) && (num_of_frames < 3)) )
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
data[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// check received RX packet data and CRC
if ((frame_ended == 1) && (num_of_frames >= 5)) // 5 bytes is minimum size without CRC error, since
begin // CRC has 4 bytes for itself
if (i_length[0] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + i_length[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, ((`MEMORY_BASE + i_length[1:0]) + max_tmp), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
end
 
// check WB INT signal
if (num_of_frames >= 3) // Frames smaller than 3 are not received.
begin // Frames greater then 5 always cause an interrupt (Frame received)
if (wb_int !== 1'b1) // Frames with length 3 or 4 always cause an interrupt (CRC error)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
 
// check RX buffer descriptor of a packet
if (num_of_frames >= min_tmp)
begin
if ( (data[15:0] !== 16'h6000) && // wrap bit
(data[15:0] !== 16'h4000) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if (num_of_frames > 4)
begin
if ( (data[15:0] !== 16'h6004) && // wrap bit
(data[15:0] !== 16'h4004) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if (num_of_frames > 2)
begin
if ( (data[15:0] !== 16'h6006) && // wrap bit
(data[15:0] !== 16'h4006) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else
begin
if (data[15] !== 1'b1)
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (num_of_frames >= 5)
begin
if ((data & `ETH_INT_RXB) !== `ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
else if ((num_of_frames < 3)) // Frames smaller than 3 are not received.
begin
if (data) // Checking if any interrupt is pending)
begin
`TIME; $display("*E Interrupt(s) is(are) pending although frame was ignored, interrupt reg: %0h", data);
test_fail("Interrupts were set");
fail = fail + 1;
end
end
else
begin
if ((data & `ETH_INT_RXE) !== `ETH_INT_RXE)
begin
`TIME; $display("*E Interrupt Receive Buffer Error was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer Error was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXE)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer Error) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer Error) were set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_frames == 3)
begin
$display(" pads appending to packets is selected");
$display(" using 1 BD out of 8 BDs (120..127) assigned to RX (wrap at 1st BD - RX BD 120)");
$display(" ->packets with lengths from %0d to %0d are not received (length increasing by 1 byte)",
0, 3);
end
else if (num_of_frames == 9)
begin
$display(" using 1 BD out of 8 BDs (120..127) assigned to RX (wrap at 1st BD - RX BD 120)");
$display(" ->packet with length 4 is not received (length increasing by 1 byte)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
5, 9);
end
else if (num_of_frames == 17)
begin
$display(" using 4 BDs out of 8 BDs (120..127) assigned to RX (wrap at 4th BD - RX BD 123)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
10, 17);
end
else if (num_of_frames == 27)
begin
$display(" using 5 BDs out of 8 BDs (120..127) assigned to RX (wrap at 5th BD - RX BD 124)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
18, 27);
end
else if (num_of_frames == 40)
begin
$display(" using 6 BDs out of 8 BDs (120..127) assigned to RX (wrap at 6th BD - RX BD 125)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
28, 40);
end
else if (num_of_frames == 54)
begin
$display(" using 7 BDs out of 8 BDs (120..127) assigned to RX (wrap at 7th BD - RX BD 126)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
41, 54);
end
else if (num_of_frames == 69)
begin
$display(" using 8 BDs out of 8 BDs (120..127) assigned to RX (wrap at 8th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
else if (num_of_frames == 69)
begin
$display(" using 8 BDs out of 8 BDs (120..127) assigned to RX (wrap at 8th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
else if (num_of_frames == 77)
begin
$display(" using 8 BDs out of 8 BDs (120..127) assigned to RX (wrap at 8th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
70, 77);
end
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if (/*(num_of_frames == 2) || (num_of_frames == 4) || (num_of_frames == 7) ||*/ (num_of_frames <= 10) ||
(num_of_frames == 14) || (num_of_frames == 18) || (num_of_frames == 23) || (num_of_frames == 28) ||
(num_of_frames == 34) || (num_of_frames == 40) || (num_of_frames == 47) ||
(num_of_frames == 54) || (num_of_frames == 62) || (num_of_frames == 70))
num_of_bd = 120;
else
num_of_bd = num_of_bd + 1;
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packets form 0 to (MINFL + 12) sizes at ////
//// 8 RX buffer decriptors ( 100Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 9) //
begin
// TEST 9: RECEIVE PACKETS FROM 0 TO (MINFL + 12) SIZES AT 8 TX BD ( 100Mbps )
test_name = "TEST 9: RECEIVE PACKETS FROM 0 TO (MINFL + 12) SIZES AT 8 TX BD ( 100Mbps )";
`TIME; $display(" TEST 9: RECEIVE PACKETS FROM 0 TO (MINFL + 12) SIZES AT 8 TX BD ( 100Mbps )");
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
max_tmp = 0;
min_tmp = 0;
// set 8 RX buffer descriptors (120 - 127) - must be set before RX enable
wbm_write(`ETH_TX_BD_NUM, 32'h78, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// enable RX, set full-duplex mode, receive small, NO correct IFG
wbm_write(`ETH_MODER, `ETH_MODER_RXEN | `ETH_MODER_FULLD | `ETH_MODER_RECSMALL | `ETH_MODER_IFG |
`ETH_MODER_PRO | `ETH_MODER_BRO,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// prepare two packets of MAXFL length
wbm_read(`ETH_PACKETLEN, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
max_tmp = tmp[15:0]; // 18 bytes consists of 6B dest addr, 6B source addr, 2B type/len, 4B CRC
min_tmp = tmp[31:16];
st_data = 8'hAC;
set_rx_packet(0, (max_tmp - 4), 1'b0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
st_data = 8'h35;
set_rx_packet((max_tmp), (max_tmp - 4), 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// unmask interrupts
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXB | `ETH_INT_RXE | `ETH_INT_BUSY |
`ETH_INT_TXC | `ETH_INT_RXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
 
// write to phy's control register for 100Mbps
#Tp eth_phy.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
#Tp eth_phy.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
speed = 100;
frame_ended = 0;
num_of_frames = 0;
num_of_bd = 120;
i_length = 0 - 4;// (0 - 4); // 6; // 4 less due to CRC
while ((i_length + 4) < 78) // (min_tmp - 4))
begin
// append CRC to packet
if ((i_length[0] == 1'b0) && (i_length > 0))
append_rx_crc (0, i_length, 1'b0, 1'b0);
else if (i_length > 0)
append_rx_crc (max_tmp, i_length, 1'b0, 1'b0);
// choose generating carrier sense and collision
case (i_length[1:0])
2'h0:
begin
// not detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(0);
end
2'h1:
begin
// detect carrier sense in FD and no collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(0);
end
2'h2:
begin
// not detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(0);
eth_phy.collision(1);
end
default: // 2'h3:
begin
// detect carrier sense in FD and set collision
eth_phy.no_carrier_sense_rx_fd_detect(1);
eth_phy.collision(1);
end
endcase
#1;
// first 10 frames are received with RX BD 120 (wrap bit on RX BD 120)
if (num_of_frames <= 9)
begin
case (i_length[1:0])
2'h0: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, (`MEMORY_BASE + i_length[1:0]));
end
2'h1: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
end
2'h2: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, (`MEMORY_BASE + i_length[1:0]));
end
default: // 2'h3: // Interrupt is generated
begin
// enable interrupt generation
set_rx_bd(120, 120, 1'b1, ((`MEMORY_BASE + i_length[1:0]) + max_tmp));
end
endcase
// set wrap bit
set_rx_bd_wrap(120);
end
// 10 <= num_of_frames < 18 => wrap set to TX BD 123
else if ((num_of_frames == 10) || (num_of_frames == 14))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 124) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(123);
end
// 18 <= num_of_frames < 28 => wrap set to RX BD 124
else if ((num_of_frames == 18) || (num_of_frames == 23))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 125) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(124);
end
// 28 <= num_of_frames < 40 => wrap set to RX BD 125
else if ((num_of_frames == 28) || (num_of_frames == 34))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 126) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(125);
end
// 40 <= num_of_frames < 54 => wrap set to RX BD 126
else if ((num_of_frames == 40) || (num_of_frames == 47))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 127) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(126);
end
// 54 <= num_of_frames < 70 => wrap set to RX BD 127
else if ((num_of_frames == 54) || (num_of_frames == 62))
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 128) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(127);
end
// 70 <= num_of_frames < 78 => wrap set to RX BD 127
else if (num_of_frames == 70)
begin
tmp_len = i_length; // length of frame
tmp_bd_num = 120; // RX BD number
while (tmp_bd_num < 128) //
begin
// if i_length[0] == 0 then base address is `MEMORY_BASE otherwise it is `MEMORY_BASE + max_tmp
if (tmp_len[0] == 0)
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, (`MEMORY_BASE + tmp_len[1:0]));
else
set_rx_bd(tmp_bd_num, tmp_bd_num, 1'b1, ((`MEMORY_BASE + tmp_len[1:0]) + max_tmp));
// set length (loop variable) - THE SAME AS AT THE END OF THIS TASK !!!
tmp_len = tmp_len + 1;
// set RX BD number
tmp_bd_num = tmp_bd_num + 1;
end
// set wrap bit
set_rx_bd_wrap(127);
end
#1;
// SET empty bit
if (num_of_frames < 10)
set_rx_bd_empty(120, 120);
else if (num_of_frames < 14)
set_rx_bd_empty((120 + num_of_frames - 10), (120 + num_of_frames - 10));
else if (num_of_frames < 18)
set_rx_bd_empty((120 + num_of_frames - 14), (120 + num_of_frames - 14));
else if (num_of_frames < 23)
set_rx_bd_empty((120 + num_of_frames - 18), (120 + num_of_frames - 18));
else if (num_of_frames < 28)
set_rx_bd_empty((120 + num_of_frames - 23), (120 + num_of_frames - 23));
else if (num_of_frames < 34)
set_rx_bd_empty((120 + num_of_frames - 28), (120 + num_of_frames - 28));
else if (num_of_frames < 40)
set_rx_bd_empty((120 + num_of_frames - 34), (120 + num_of_frames - 34));
else if (num_of_frames < 47)
set_rx_bd_empty((120 + num_of_frames - 40), (120 + num_of_frames - 40));
else if (num_of_frames < 54)
set_rx_bd_empty((120 + num_of_frames - 47), (120 + num_of_frames - 47));
else if (num_of_frames < 62)
set_rx_bd_empty((120 + num_of_frames - 54), (120 + num_of_frames - 54));
else if (num_of_frames < 70)
set_rx_bd_empty((120 + num_of_frames - 62), (120 + num_of_frames - 62));
else if (num_of_frames < 78)
set_rx_bd_empty((120 + num_of_frames - 70), (120 + num_of_frames - 70));
// CHECK END OF RECEIVE
frame_ended = 0;
check_frame = 0;
fork
begin
if (i_length[0] == 1'b0)
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, (i_length + 4), 1'b0);
else
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, max_tmp, (i_length + 4), 1'b0);
repeat(10) @(posedge mrx_clk);
end
begin: fr_end2
wait (MRxDV === 1'b1); // start receive
#1 check_rx_bd(num_of_bd, data);
if (data[15] !== 1)
begin
test_fail("Wrong buffer descriptor's empty bit read out from MAC");
fail = fail + 1;
end
wait (MRxDV === 1'b0); // end receive
while ((data[15] === 1) && (check_frame == 0))
begin
#1 check_rx_bd(num_of_bd, data);
@(posedge wb_clk);
end
if (data[15] === 0)
frame_ended = 1;
repeat (1) @(posedge wb_clk);
end
begin
wait (MRxDV === 1'b1); // start receive
wait (MRxDV === 1'b0); // end receive
repeat(10) @(posedge mrx_clk);
repeat(15) @(posedge wb_clk);
check_frame = 1;
end
join
// check length of a PACKET
if ( (data[31:16] != (i_length + 4))/* && (frame_ended == 1)*/ )
begin
`TIME; $display("*E Wrong length of the packet out from PHY (%0d instead of %0d)",
data[31:16], (i_length + 4));
test_fail("Wrong length of the packet out from PHY");
fail = fail + 1;
end
// check received RX packet data and CRC
if ((frame_ended == 1) && (num_of_frames >= 5))
begin
if (i_length[0] == 1'b0)
begin
check_rx_packet(0, (`MEMORY_BASE + i_length[1:0]), (i_length + 4), 1'b0, 1'b0, tmp);
end
else
begin
check_rx_packet(max_tmp, ((`MEMORY_BASE + i_length[1:0]) + max_tmp), (i_length + 4), 1'b0, 1'b0, tmp);
end
if (tmp > 0)
begin
`TIME; $display("*E Wrong data of the received packet");
test_fail("Wrong data of the received packet");
fail = fail + 1;
end
end
 
// check WB INT signal
if (num_of_frames >= 5)
begin
if (wb_int !== 1'b1)
begin
`TIME; $display("*E WB INT signal should be set");
test_fail("WB INT signal should be set");
fail = fail + 1;
end
end
else
begin
if (wb_int !== 1'b0)
begin
`TIME; $display("*E WB INT signal should not be set");
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
end
 
// display RX buffer descriptor of a packet with length smaller than 7
check_rx_bd(num_of_bd, data);
if (num_of_frames <= 6)
begin
`TIME; $display("=> RX buffer descriptor is: %0h - len: %0d", data[15:0], num_of_frames);
end
// check RX buffer descriptor of a packet
if (num_of_frames >= min_tmp)
begin
if ( (data[15:0] !== 16'h6000) && // wrap bit
(data[15:0] !== 16'h4000) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if (num_of_frames > 4)
begin
if ( (data[15:0] !== 16'h6004) && // wrap bit
(data[15:0] !== 16'h4004) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else if (num_of_frames > 2)
begin
if ( (data[15:0] !== 16'h6006) && // wrap bit
(data[15:0] !== 16'h4006) ) // without wrap bit
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
else
begin
if (data[15] !== 1'b1)
begin
`TIME; $display("*E RX buffer descriptor status is not correct: %0h - len: %0d", data[15:0], num_of_frames);
test_fail("RX buffer descriptor status is not correct");
fail = fail + 1;
end
end
// check interrupts
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
if (num_of_frames >= 40)
begin
if ((data & `ETH_INT_RXB) !== 1'b1)//`ETH_INT_RXB)
begin
`TIME; $display("*E Interrupt Receive Buffer was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXB)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer) were set");
fail = fail + 1;
end
end
else
begin
if ((data & `ETH_INT_RXE) !== 1'b1)//`ETH_INT_RXE)
begin
`TIME; $display("*E Interrupt Receive Buffer Error was not set, interrupt reg: %0h", data);
test_fail("Interrupt Receive Buffer Error was not set");
fail = fail + 1;
end
if ((data & (~`ETH_INT_RXE)) !== 0)
begin
`TIME; $display("*E Other interrupts (except Receive Buffer Error) were set, interrupt reg: %0h", data);
test_fail("Other interrupts (except Receive Buffer Error) were set");
fail = fail + 1;
end
end
// clear interrupts
wbm_write(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// check WB INT signal
if (wb_int !== 1'b0)
begin
test_fail("WB INT signal should not be set");
fail = fail + 1;
end
// INTERMEDIATE DISPLAYS
if (num_of_frames == 3)
begin
$display(" pads appending to packets is selected");
$display(" using 1 BD out of 8 BDs (120..127) assigned to RX (wrap at 1st BD - RX BD 120)");
$display(" ->packets with lengths from %0d to %0d are not received (length increasing by 1 byte)",
0, 3);
end
else if (num_of_frames == 9)
begin
$display(" using 1 BD out of 8 BDs (120..127) assigned to RX (wrap at 1st BD - RX BD 120)");
$display(" ->packet with length 4 is not received (length increasing by 1 byte)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
5, 9);
end
else if (num_of_frames == 17)
begin
$display(" using 4 BDs out of 8 BDs (120..127) assigned to RX (wrap at 4th BD - RX BD 123)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
10, 17);
end
else if (num_of_frames == 27)
begin
$display(" using 5 BDs out of 8 BDs (120..127) assigned to RX (wrap at 5th BD - RX BD 124)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
18, 27);
end
else if (num_of_frames == 40)
begin
$display(" using 6 BDs out of 8 BDs (120..127) assigned to RX (wrap at 6th BD - RX BD 125)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
28, 40);
end
else if (num_of_frames == 54)
begin
$display(" using 7 BDs out of 8 BDs (120..127) assigned to RX (wrap at 7th BD - RX BD 126)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
41, 54);
end
else if (num_of_frames == 69)
begin
$display(" using 8 BDs out of 8 BDs (120..127) assigned to RX (wrap at 8th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
else if (num_of_frames == 69)
begin
$display(" using 8 BDs out of 8 BDs (120..127) assigned to RX (wrap at 8th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
55, 69);
end
else if (num_of_frames == 77)
begin
$display(" using 8 BDs out of 8 BDs (120..127) assigned to RX (wrap at 8th BD - RX BD 127)");
$display(" ->packets with lengths from %0d to %0d are checked (length increasing by 1 byte)",
70, 77);
end
// set length (loop variable)
i_length = i_length + 1;
// the number of frame transmitted
num_of_frames = num_of_frames + 1;
if (/*(num_of_frames == 2) || (num_of_frames == 4) || (num_of_frames == 7) ||*/ (num_of_frames <= 10) ||
(num_of_frames == 14) || (num_of_frames == 18) || (num_of_frames == 23) || (num_of_frames == 28) ||
(num_of_frames == 34) || (num_of_frames == 40) || (num_of_frames == 47) ||
(num_of_frames == 54) || (num_of_frames == 62) || (num_of_frames == 70))
num_of_bd = 120;
else
num_of_bd = num_of_bd + 1;
end
// disable RX
wbm_write(`ETH_MODER, `ETH_MODER_FULLD | `ETH_MODER_PAD | `ETH_MODER_CRCEN,
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
if(fail == 0)
test_ok;
else
fail = 0;
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packet synchronization with receive ////
//// disable/enable ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 10) // Test no receive when all buffers are TX ( 10Mbps ).
begin
// TEST 10: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )
test_name = "TEST 10: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )";
`TIME; $display(" TEST 10: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )");
 
 
 
 
 
 
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packet synchronization with receive ////
//// disable/enable ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 12) // Test no receive when all buffers are TX ( 10Mbps ).
begin
// TEST 12: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )
test_name = "TEST 12: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )";
`TIME; $display(" TEST 12: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )");
 
 
 
 
 
 
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packet synchronization with receive ////
//// disable/enable ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 14) // Test no receive when all buffers are TX ( 10Mbps ).
begin
// TEST 14: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )
test_name = "TEST 14: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )";
`TIME; $display(" TEST 14: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )");
 
 
 
 
 
 
end
 
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test receive packet synchronization with receive ////
//// disable/enable ( 10Mbps ). ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 16) // Test no receive when all buffers are TX ( 10Mbps ).
begin
// TEST 16: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )
test_name = "TEST 16: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )";
`TIME; $display(" TEST 16: RECEIVE PACKET SYNCHRONIZATION WITH RECEIVE DISABLE/ENABLE ( 10Mbps )");
 
 
 
 
 
 
end
 
 
 
end // for (test_num=start_task; test_num <= end_task; test_num=test_num+1)
 
end
endtask // test_mac_full_duplex_receive
 
 
task test_mac_full_duplex_flow;
input [31:0] start_task;
input [31:0] end_task;
integer bit_start_1;
integer bit_end_1;
integer bit_start_2;
integer bit_end_2;
integer num_of_reg;
integer num_of_frames;
integer num_of_bd;
integer i_addr;
integer i_data;
integer i_length;
integer tmp_len;
integer tmp_bd;
integer tmp_bd_num;
integer tmp_data;
integer tmp_ipgt;
integer test_num;
reg [31:0] tx_bd_num;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_data;
reg [((`MAX_BLK_SIZE * 32) - 1):0] burst_tmp_data;
integer i;
integer i1;
integer i2;
integer i3;
integer fail;
integer speed;
reg frame_started;
reg frame_ended;
reg wait_for_frame;
reg [31:0] addr;
reg [31:0] data;
reg [31:0] tmp;
reg [ 7:0] st_data;
reg [15:0] max_tmp;
reg [15:0] min_tmp;
begin
// MAC FULL DUPLEX FLOW TEST
test_heading("MAC FULL DUPLEX FLOW TEST");
$display(" ");
$display("MAC FULL DUPLEX FLOW TEST");
fail = 0;
 
// reset MAC registers
hard_reset;
// reset MAC and MII LOGIC with soft reset
reset_mac;
reset_mii;
// set wb slave response
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries);
 
/*
TASKS for set and control TX buffer descriptors (also send packet - set_tx_bd_ready):
-------------------------------------------------------------------------------------
set_tx_bd
(tx_bd_num_start[6:0], tx_bd_num_end[6:0], len[15:0], irq, pad, crc, txpnt[31:0]);
set_tx_bd_wrap
(tx_bd_num_end[6:0]);
set_tx_bd_ready
(tx_bd_num_start[6:0], tx_bd_num_end[6:0]);
check_tx_bd
(tx_bd_num_start[6:0], tx_bd_status[31:0]);
clear_tx_bd
(tx_bd_num_start[6:0], tx_bd_num_end[6:0]);
 
TASKS for set and control RX buffer descriptors:
------------------------------------------------
set_rx_bd
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0], irq, rxpnt[31:0]);
set_rx_bd_wrap
(rx_bd_num_end[6:0]);
set_rx_bd_empty
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0]);
check_rx_bd
(rx_bd_num_end[6:0], rx_bd_status);
clear_rx_bd
(rx_bd_num_strat[6:0], rx_bd_num_end[6:0]);
 
TASKS for set and check TX packets:
-----------------------------------
set_tx_packet
(txpnt[31:0], len[15:0], eth_start_data[7:0]);
check_tx_packet
(txpnt_wb[31:0], txpnt_phy[31:0], len[15:0], failure[31:0]);
 
TASKS for set and check RX packets:
-----------------------------------
set_rx_packet
(rxpnt[31:0], len[15:0], plus_nibble, d_addr[47:0], s_addr[47:0], type_len[15:0], start_data[7:0]);
check_rx_packet
(rxpnt_phy[31:0], rxpnt_wb[31:0], len[15:0], plus_nibble, successful_nibble, failure[31:0]);
 
TASKS for append and check CRC to/of TX packet:
-----------------------------------------------
append_tx_crc
(txpnt_wb[31:0], len[15:0], negated_crc);
check_tx_crc
(txpnt_phy[31:0], len[15:0], negated_crc, failure[31:0]);
 
TASK for append CRC to RX packet (CRC is checked together with check_rx_packet):
--------------------------------------------------------------------------------
append_rx_crc
(rxpnt_phy[31:0], len[15:0], plus_nibble, negated_crc);
*/
 
//////////////////////////////////////////////////////////////////////
//// ////
//// test_mac_full_duplex_flow: ////
//// ////
//// 0: Test ////
//// ////
//////////////////////////////////////////////////////////////////////
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1)
begin
 
////////////////////////////////////////////////////////////////////
//// ////
//// Test ////
//// ////
////////////////////////////////////////////////////////////////////
if (test_num == 0) // Test
begin
// TEST 0:
test_name = "TEST 0: ";
`TIME; $display(" TEST 0: ");
 
 
end
 
 
 
end // for (test_num=start_task; test_num <= end_task; test_num=test_num+1)
 
end
endtask // test_mac_full_duplex_flow
 
 
//////////////////////////////////////////////////////////////
// WB Behavioral Models Basic tasks
//////////////////////////////////////////////////////////////
 
task wbm_write;
input [31:0] address_i;
input [((`MAX_BLK_SIZE * 32) - 1):0] data_i;
input [3:0] sel_i;
input [31:0] size_i;
input [3:0] init_waits_i;
input [3:0] subseq_waits_i;
 
reg `WRITE_STIM_TYPE write_data;
reg `WB_TRANSFER_FLAGS flags;
reg `WRITE_RETURN_TYPE write_status;
integer i;
begin
write_status = 0;
 
flags = 0;
flags`WB_TRANSFER_SIZE = size_i;
flags`INIT_WAITS = init_waits_i;
flags`SUBSEQ_WAITS = subseq_waits_i;
 
write_data = 0;
write_data`WRITE_DATA = data_i[31:0];
write_data`WRITE_ADDRESS = address_i;
write_data`WRITE_SEL = sel_i;
 
for (i = 0; i < size_i; i = i + 1)
begin
wb_master.blk_write_data[i] = write_data;
data_i = data_i >> 32;
write_data`WRITE_DATA = data_i[31:0];
write_data`WRITE_ADDRESS = write_data`WRITE_ADDRESS + 4;
end
 
wb_master.wb_block_write(flags, write_status);
 
if (write_status`CYC_ACTUAL_TRANSFER !== size_i)
begin
`TIME;
$display("*E WISHBONE Master was unable to complete the requested write operation to MAC!");
end
end
endtask // wbm_write
 
task wbm_read;
input [31:0] address_i;
output [((`MAX_BLK_SIZE * 32) - 1):0] data_o;
input [3:0] sel_i;
input [31:0] size_i;
input [3:0] init_waits_i;
input [3:0] subseq_waits_i;
 
reg `READ_RETURN_TYPE read_data;
reg `WB_TRANSFER_FLAGS flags;
reg `READ_RETURN_TYPE read_status;
integer i;
begin
read_status = 0;
data_o = 0;
 
flags = 0;
flags`WB_TRANSFER_SIZE = size_i;
flags`INIT_WAITS = init_waits_i;
flags`SUBSEQ_WAITS = subseq_waits_i;
 
read_data = 0;
read_data`READ_ADDRESS = address_i;
read_data`READ_SEL = sel_i;
 
for (i = 0; i < size_i; i = i + 1)
begin
wb_master.blk_read_data_in[i] = read_data;
read_data`READ_ADDRESS = read_data`READ_ADDRESS + 4;
end
 
wb_master.wb_block_read(flags, read_status);
 
if (read_status`CYC_ACTUAL_TRANSFER !== size_i)
begin
`TIME;
$display("*E WISHBONE Master was unable to complete the requested read operation from MAC!");
end
 
for (i = 0; i < size_i; i = i + 1)
begin
data_o = data_o << 32;
read_data = wb_master.blk_read_data_out[(size_i - 1) - i]; // [31 - i];
data_o[31:0] = read_data`READ_DATA;
end
end
endtask // wbm_read
 
 
//////////////////////////////////////////////////////////////
// Ethernet Basic tasks
//////////////////////////////////////////////////////////////
 
task hard_reset; // MAC registers
begin
// reset MAC registers
@(posedge wb_clk);
#2 wb_rst = 1'b1;
repeat(2) @(posedge wb_clk);
#2 wb_rst = 1'b0;
end
endtask // hard_reset
 
task reset_mac; // MAC module
reg [31:0] tmp;
reg [31:0] tmp_no_rst;
begin
// read MODER register first
wbm_read(`ETH_MODER, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set reset bit - write back to MODER register with RESET bit
wbm_write(`ETH_MODER, (`ETH_MODER_RST | tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// clear reset bit - write back to MODER register without RESET bit
tmp_no_rst = `ETH_MODER_RST;
tmp_no_rst = ~tmp_no_rst;
wbm_write(`ETH_MODER, (tmp_no_rst & tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
endtask // reset_mac
 
task set_tx_bd;
input [6:0] tx_bd_num_start;
input [6:0] tx_bd_num_end;
input [15:0] len;
input irq;
input pad;
input crc;
input [31:0] txpnt;
 
integer i;
integer bd_status_addr, bd_ptr_addr;
// integer buf_addr;
begin
for(i = tx_bd_num_start; i <= tx_bd_num_end; i = i + 1)
begin
// buf_addr = `TX_BUF_BASE + i * 32'h600;
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// initialize BD - status
// wbm_write(bd_status_addr, 32'h00005800, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); // IRQ + PAD + CRC
wbm_write(bd_status_addr, {len, 1'b0, irq, 1'b0, pad, crc, 11'h0},
4'hF, 1, wbm_init_waits, wbm_subseq_waits); // IRQ + PAD + CRC
// initialize BD - pointer
// wbm_write(bd_ptr_addr, buf_addr, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); // Initializing BD-pointer
wbm_write(bd_ptr_addr, txpnt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); // Initializing BD-pointer
end
end
endtask // set_tx_bd
 
task set_tx_bd_wrap;
input [6:0] tx_bd_num_end;
integer bd_status_addr, tmp;
begin
bd_status_addr = `TX_BD_BASE + tx_bd_num_end * 8;
wbm_read(bd_status_addr, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set wrap bit to this BD - this BD should be last-one
wbm_write(bd_status_addr, (`ETH_TX_BD_WRAP | tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
endtask // set_tx_bd_wrap
 
task set_tx_bd_ready;
input [6:0] tx_nd_num_strat;
input [6:0] tx_bd_num_end;
integer i;
integer bd_status_addr, tmp;
begin
for(i = tx_nd_num_strat; i <= tx_bd_num_end; i = i + 1)
begin
bd_status_addr = `TX_BD_BASE + i * 8;
wbm_read(bd_status_addr, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set empty bit to this BD - this BD should be ready
wbm_write(bd_status_addr, (`ETH_TX_BD_READY | tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
end
endtask // set_tx_bd_ready
 
task check_tx_bd;
input [6:0] tx_bd_num_end;
output [31:0] tx_bd_status;
integer bd_status_addr, tmp;
begin
bd_status_addr = `TX_BD_BASE + tx_bd_num_end * 8;
wbm_read(bd_status_addr, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
#1 tx_bd_status = tmp;
#1;
end
endtask // check_tx_bd
 
task clear_tx_bd;
input [6:0] tx_nd_num_strat;
input [6:0] tx_bd_num_end;
integer i;
integer bd_status_addr, bd_ptr_addr;
begin
for(i = tx_nd_num_strat; i <= tx_bd_num_end; i = i + 1)
begin
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// clear BD - status
wbm_write(bd_status_addr, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// clear BD - pointer
wbm_write(bd_ptr_addr, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
end
endtask // clear_tx_bd
 
task set_rx_bd;
input [6:0] rx_bd_num_strat;
input [6:0] rx_bd_num_end;
input irq;
input [31:0] rxpnt;
// input [6:0] rxbd_num;
integer i;
integer bd_status_addr, bd_ptr_addr;
// integer buf_addr;
begin
for(i = rx_bd_num_strat; i <= rx_bd_num_end; i = i + 1)
begin
// buf_addr = `RX_BUF_BASE + i * 32'h600;
// bd_status_addr = `RX_BD_BASE + i * 8;
// bd_ptr_addr = bd_status_addr + 4;
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// initialize BD - status
// wbm_write(bd_status_addr, 32'h0000c000, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); // IRQ + PAD + CRC
wbm_write(bd_status_addr, {17'h0, irq, 14'h0},
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// initialize BD - pointer
// wbm_write(bd_ptr_addr, buf_addr, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); // Initializing BD-pointer
wbm_write(bd_ptr_addr, rxpnt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); // Initializing BD-pointer
end
end
endtask // set_rx_bd
 
task set_rx_bd_wrap;
input [6:0] rx_bd_num_end;
integer bd_status_addr, tmp;
begin
// bd_status_addr = `RX_BD_BASE + rx_bd_num_end * 8;
bd_status_addr = `TX_BD_BASE + rx_bd_num_end * 8;
wbm_read(bd_status_addr, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set wrap bit to this BD - this BD should be last-one
wbm_write(bd_status_addr, (`ETH_RX_BD_WRAP | tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
endtask // set_rx_bd_wrap
 
task set_rx_bd_empty;
input [6:0] rx_bd_num_strat;
input [6:0] rx_bd_num_end;
integer i;
integer bd_status_addr, tmp;
begin
for(i = rx_bd_num_strat; i <= rx_bd_num_end; i = i + 1)
begin
// bd_status_addr = `RX_BD_BASE + i * 8;
bd_status_addr = `TX_BD_BASE + i * 8;
wbm_read(bd_status_addr, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set empty bit to this BD - this BD should be ready
wbm_write(bd_status_addr, (`ETH_RX_BD_EMPTY | tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
end
endtask // set_rx_bd_empty
 
task check_rx_bd;
input [6:0] rx_bd_num_end;
output [31:0] rx_bd_status;
integer bd_status_addr, tmp;
begin
// bd_status_addr = `RX_BD_BASE + rx_bd_num_end * 8;
bd_status_addr = `TX_BD_BASE + rx_bd_num_end * 8;
wbm_read(bd_status_addr, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
#1 rx_bd_status = tmp;
#1;
end
endtask // check_rx_bd
 
task clear_rx_bd;
input [6:0] rx_bd_num_strat;
input [6:0] rx_bd_num_end;
integer i;
integer bd_status_addr, bd_ptr_addr;
begin
for(i = rx_bd_num_strat; i <= rx_bd_num_end; i = i + 1)
begin
// bd_status_addr = `RX_BD_BASE + i * 8;
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// clear BD - status
wbm_write(bd_status_addr, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// clear BD - pointer
wbm_write(bd_ptr_addr, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
end
endtask // clear_rx_bd
 
task set_tx_packet;
input [31:0] txpnt;
input [15:0] len;
input [7:0] eth_start_data;
integer i, sd;
integer buffer;
reg delta_t;
begin
buffer = txpnt;
sd = eth_start_data;
delta_t = 0;
 
// First write might not be word allign.
if(buffer[1:0] == 1)
begin
wb_slave.wr_mem(buffer - 1, {8'h0, sd[7:0], sd[7:0] + 3'h1, sd[7:0] + 3'h2}, 4'h7);
sd = sd + 3;
i = 3;
end
else if(buffer[1:0] == 2)
begin
wb_slave.wr_mem(buffer - 2, {16'h0, sd[7:0], sd[7:0] + 3'h1}, 4'h3);
sd = sd + 2;
i = 2;
end
else if(buffer[1:0] == 3)
begin
wb_slave.wr_mem(buffer - 3, {24'h0, sd[7:0]}, 4'h1);
sd = sd + 1;
i = 1;
end
else
i = 0;
delta_t = !delta_t;
 
for(i = i; i < (len - 4); i = i + 4) // Last 0-3 bytes are not written
begin
wb_slave.wr_mem(buffer + i, {sd[7:0], sd[7:0] + 3'h1, sd[7:0] + 3'h2, sd[7:0] + 3'h3}, 4'hF);
sd = sd + 4;
end
delta_t = !delta_t;
// Last word
if((len - i) == 3)
begin
wb_slave.wr_mem(buffer + i, {sd[7:0], sd[7:0] + 3'h1, sd[7:0] + 3'h2, 8'h0}, 4'hE);
end
else if((len - i) == 2)
begin
wb_slave.wr_mem(buffer + i, {sd[7:0], sd[7:0] + 3'h1, 16'h0}, 4'hC);
end
else if((len - i) == 1)
begin
wb_slave.wr_mem(buffer + i, {sd[7:0], 24'h0}, 4'h8);
end
else if((len - i) == 4)
begin
wb_slave.wr_mem(buffer + i, {sd[7:0], sd[7:0] + 3'h1, sd[7:0] + 3'h2, sd[7:0] + 3'h3}, 4'hF);
end
else
$display("(%0t)(%m) ERROR", $time);
delta_t = !delta_t;
end
endtask // set_tx_packet
 
task check_tx_packet;
input [31:0] txpnt_wb; // source
input [31:0] txpnt_phy; // destination
input [15:0] len;
output [31:0] failure;
integer i, data_wb, data_phy;
reg [31:0] addr_wb, addr_phy;
reg [31:0] failure;
reg delta_t;
begin
addr_wb = txpnt_wb;
addr_phy = txpnt_phy;
delta_t = 0;
failure = 0;
#1;
// First write might not be word allign.
if(addr_wb[1:0] == 1)
begin
wb_slave.rd_mem(addr_wb - 1, data_wb, 4'h7);
data_phy[31:24] = 0;
data_phy[23:16] = eth_phy.tx_mem[addr_phy[21:0]];
data_phy[15: 8] = eth_phy.tx_mem[addr_phy[21:0] + 1];
data_phy[ 7: 0] = eth_phy.tx_mem[addr_phy[21:0] + 2];
i = 3;
if (data_phy[23:0] !== data_wb[23:0])
begin
`TIME;
$display("*E Wrong 1. word (3 bytes) of TX packet! phy: %0h, wb: %0h", data_phy[23:0], data_wb[23:0]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = 1;
end
end
else if (addr_wb[1:0] == 2)
begin
wb_slave.rd_mem(addr_wb - 2, data_wb, 4'h3);
data_phy[31:16] = 0;
data_phy[15: 8] = eth_phy.tx_mem[addr_phy[21:0]];
data_phy[ 7: 0] = eth_phy.tx_mem[addr_phy[21:0] + 1];
i = 2;
if (data_phy[15:0] !== data_wb[15:0])
begin
`TIME;
$display("*E Wrong 1. word (2 bytes) of TX packet! phy: %0h, wb: %0h", data_phy[15:0], data_wb[15:0]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = 1;
end
end
else if (addr_wb[1:0] == 3)
begin
wb_slave.rd_mem(addr_wb - 3, data_wb, 4'h1);
data_phy[31: 8] = 0;
data_phy[ 7: 0] = eth_phy.tx_mem[addr_phy[21:0]];
i = 1;
if (data_phy[7:0] !== data_wb[7:0])
begin
`TIME;
$display("*E Wrong 1. word (1 byte) of TX packet! phy: %0h, wb: %0h", data_phy[7:0], data_wb[7:0]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = 1;
end
end
else
i = 0;
delta_t = !delta_t;
#1;
for(i = i; i < (len - 4); i = i + 4) // Last 0-3 bytes are not checked
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy.tx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.tx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy.tx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = eth_phy.tx_mem[addr_phy[21:0] + i + 3];
if (data_phy[31:0] !== data_wb[31:0])
begin
`TIME;
$display("*E Wrong %d. word (4 bytes) of TX packet! phy: %0h, wb: %0h", ((i/4)+1), data_phy[31:0], data_wb[31:0]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = failure + 1;
end
end
delta_t = !delta_t;
#1;
// Last word
if((len - i) == 3)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hE);
data_phy[31:24] = eth_phy.tx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.tx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy.tx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = 0;
if (data_phy[31:8] !== data_wb[31:8])
begin
`TIME;
$display("*E Wrong %d. word (3 bytes) of TX packet! phy: %0h, wb: %0h", ((i/4)+1), data_phy[31:8], data_wb[31:8]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = failure + 1;
end
end
else if((len - i) == 2)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hC);
data_phy[31:24] = eth_phy.tx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.tx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = 0;
data_phy[ 7: 0] = 0;
if (data_phy[31:16] !== data_wb[31:16])
begin
`TIME;
$display("*E Wrong %d. word (2 bytes) of TX packet! phy: %0h, wb: %0h", ((i/4)+1), data_phy[31:16], data_wb[31:16]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = failure + 1;
end
end
else if((len - i) == 1)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'h8);
data_phy[31:24] = eth_phy.tx_mem[addr_phy[21:0] + i];
data_phy[23:16] = 0;
data_phy[15: 8] = 0;
data_phy[ 7: 0] = 0;
if (data_phy[31:24] !== data_wb[31:24])
begin
`TIME;
$display("*E Wrong %d. word (1 byte) of TX packet! phy: %0h, wb: %0h", ((i/4)+1), data_phy[31:24], data_wb[31:24]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = failure + 1;
end
end
else if((len - i) == 4)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy.tx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.tx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy.tx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = eth_phy.tx_mem[addr_phy[21:0] + i + 3];
if (data_phy[31:0] !== data_wb[31:0])
begin
`TIME;
$display("*E Wrong %d. word (4 bytes) of TX packet! phy: %0h, wb: %0h", ((i/4)+1), data_phy[31:0], data_wb[31:0]);
$display(" address phy: %0h, address wb: %0h", addr_phy, addr_wb);
failure = failure + 1;
end
end
else
$display("(%0t)(%m) ERROR", $time);
delta_t = !delta_t;
end
endtask // check_tx_packet
 
task set_rx_packet;
input [31:0] rxpnt;
input [15:0] len;
input plus_dribble_nibble; // if length is longer for one nibble
input [47:0] eth_dest_addr;
input [47:0] eth_source_addr;
input [15:0] eth_type_len;
input [7:0] eth_start_data;
integer i, sd;
reg [47:0] dest_addr;
reg [47:0] source_addr;
reg [15:0] type_len;
reg [21:0] buffer;
reg delta_t;
begin
buffer = rxpnt[21:0];
dest_addr = eth_dest_addr;
source_addr = eth_source_addr;
type_len = eth_type_len;
sd = eth_start_data;
delta_t = 0;
for(i = 0; i < len; i = i + 1)
begin
if (i < 6)
begin
eth_phy.rx_mem[buffer] = dest_addr[47:40];
dest_addr = dest_addr << 8;
end
else if (i < 12)
begin
eth_phy.rx_mem[buffer] = source_addr[47:40];
source_addr = source_addr << 8;
end
else if (i < 14)
begin
eth_phy.rx_mem[buffer] = type_len[15:8];
type_len = type_len << 8;
end
else
begin
eth_phy.rx_mem[buffer] = sd[7:0];
sd = sd + 1;
end
buffer = buffer + 1;
end
delta_t = !delta_t;
if (plus_dribble_nibble)
eth_phy.rx_mem[buffer] = {4'h0, 4'hD /*sd[3:0]*/};
delta_t = !delta_t;
end
endtask // set_rx_packet
 
task set_rx_addr_type;
input [31:0] rxpnt;
input [47:0] eth_dest_addr;
input [47:0] eth_source_addr;
input [15:0] eth_type_len;
integer i;
reg [47:0] dest_addr;
reg [47:0] source_addr;
reg [15:0] type_len;
reg [21:0] buffer;
reg delta_t;
begin
buffer = rxpnt[21:0];
dest_addr = eth_dest_addr;
source_addr = eth_source_addr;
type_len = eth_type_len;
delta_t = 0;
for(i = 0; i < 14; i = i + 1)
begin
if (i < 6)
begin
eth_phy.rx_mem[buffer] = dest_addr[47:40];
dest_addr = dest_addr << 8;
end
else if (i < 12)
begin
eth_phy.rx_mem[buffer] = source_addr[47:40];
source_addr = source_addr << 8;
end
else // if (i < 14)
begin
eth_phy.rx_mem[buffer] = type_len[15:8];
type_len = type_len << 8;
end
buffer = buffer + 1;
end
delta_t = !delta_t;
end
endtask // set_rx_addr_type
 
task check_rx_packet;
input [31:0] rxpnt_phy; // source
input [31:0] rxpnt_wb; // destination
input [15:0] len;
input plus_dribble_nibble; // if length is longer for one nibble
input successful_dribble_nibble; // if additional nibble is stored into memory
output [31:0] failure;
integer i, data_wb, data_phy;
reg [31:0] addr_wb, addr_phy;
reg [31:0] failure;
reg [21:0] buffer;
reg delta_t;
begin
addr_phy = rxpnt_phy;
addr_wb = rxpnt_wb;
delta_t = 0;
failure = 0;
 
// First write might not be word allign.
if(addr_wb[1:0] == 1)
begin
wb_slave.rd_mem(addr_wb - 1, data_wb, 4'h7);
data_phy[31:24] = 0;
data_phy[23:16] = eth_phy.rx_mem[addr_phy[21:0]];
data_phy[15: 8] = eth_phy.rx_mem[addr_phy[21:0] + 1];
data_phy[ 7: 0] = eth_phy.rx_mem[addr_phy[21:0] + 2];
i = 3;
if (data_phy[23:0] !== data_wb[23:0])
begin
`TIME;
$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
$display("*E Wrong 1. word (3 bytes) of RX packet! phy = %h, wb = %h", data_phy[23:0], data_wb[23:0]);
failure = 1;
end
end
else if (addr_wb[1:0] == 2)
begin
wb_slave.rd_mem(addr_wb - 2, data_wb, 4'h3);
data_phy[31:16] = 0;
data_phy[15: 8] = eth_phy.rx_mem[addr_phy[21:0]];
data_phy[ 7: 0] = eth_phy.rx_mem[addr_phy[21:0] + 1];
i = 2;
if (data_phy[15:0] !== data_wb[15:0])
begin
`TIME;
$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
$display("*E Wrong 1. word (2 bytes) of RX packet! phy = %h, wb = %h", data_phy[15:0], data_wb[15:0]);
failure = 1;
end
end
else if (addr_wb[1:0] == 3)
begin
wb_slave.rd_mem(addr_wb - 3, data_wb, 4'h1);
data_phy[31: 8] = 0;
data_phy[ 7: 0] = eth_phy.rx_mem[addr_phy[21:0]];
i = 1;
if (data_phy[7:0] !== data_wb[7:0])
begin
`TIME;
$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
$display("*E Wrong 1. word (1 byte) of RX packet! phy = %h, wb = %h", data_phy[7:0], data_wb[7:0]);
failure = 1;
end
end
else
i = 0;
delta_t = !delta_t;
 
for(i = i; i < (len - 4); i = i + 4) // Last 0-3 bytes are not checked
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.rx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy.rx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = eth_phy.rx_mem[addr_phy[21:0] + i + 3];
if (data_phy[31:0] !== data_wb[31:0])
begin
`TIME;
if (i == 0)
$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
$display("*E Wrong %0d. word (4 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:0], data_wb[31:0]);
failure = failure + 1;
end
end
delta_t = !delta_t;
 
// Last word
if((len - i) == 3)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.rx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy.rx_mem[addr_phy[21:0] + i + 2];
if (plus_dribble_nibble)
data_phy[ 7: 0] = eth_phy.rx_mem[addr_phy[21:0] + i + 3];
else
data_phy[ 7: 0] = 0;
if (data_phy[31:8] !== data_wb[31:8])
begin
`TIME;
$display("*E Wrong %0d. word (3 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:8], data_wb[31:8]);
failure = failure + 1;
end
if (plus_dribble_nibble && successful_dribble_nibble)
begin
if (data_phy[3:0] !== data_wb[3:0])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (3 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
else if (plus_dribble_nibble && !successful_dribble_nibble)
begin
if (data_phy[3:0] === data_wb[3:0])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (3 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
end
else if((len - i) == 2)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hE);
data_phy[31:24] = eth_phy.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.rx_mem[addr_phy[21:0] + i + 1];
if (plus_dribble_nibble)
data_phy[15: 8] = eth_phy.rx_mem[addr_phy[21:0] + i + 2];
else
data_phy[15: 8] = 0;
data_phy[ 7: 0] = 0;
if (data_phy[31:16] !== data_wb[31:16])
begin
`TIME;
$display("*E Wrong %0d. word (2 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:16], data_wb[31:16]);
failure = failure + 1;
end
if (plus_dribble_nibble && successful_dribble_nibble)
begin
if (data_phy[11:8] !== data_wb[11:8])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (2 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
else if (plus_dribble_nibble && !successful_dribble_nibble)
begin
if (data_phy[11:8] === data_wb[11:8])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (2 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
end
else if((len - i) == 1)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hC);
data_phy[31:24] = eth_phy.rx_mem[addr_phy[21:0] + i];
if (plus_dribble_nibble)
data_phy[23:16] = eth_phy.rx_mem[addr_phy[21:0] + i + 1];
else
data_phy[23:16] = 0;
data_phy[15: 8] = 0;
data_phy[ 7: 0] = 0;
if (data_phy[31:24] !== data_wb[31:24])
begin
`TIME;
$display("*E Wrong %0d. word (1 byte) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:24], data_wb[31:24]);
failure = failure + 1;
end
if (plus_dribble_nibble && successful_dribble_nibble)
begin
if (data_phy[19:16] !== data_wb[19:16])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (1 byte) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
else if (plus_dribble_nibble && !successful_dribble_nibble)
begin
if (data_phy[19:16] === data_wb[19:16])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (1 byte) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
end
else if((len - i) == 4)
begin
wb_slave.rd_mem(addr_wb + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy.rx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy.rx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = eth_phy.rx_mem[addr_phy[21:0] + i + 3];
if (data_phy[31:0] !== data_wb[31:0])
begin
`TIME;
$display("*E Wrong %0d. word (4 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:0], data_wb[31:0]);
failure = failure + 1;
end
if (plus_dribble_nibble)
begin
wb_slave.rd_mem(addr_wb + i + 4, data_wb, 4'h8);
data_phy[31:24] = eth_phy.rx_mem[addr_phy[21:0] + i + 4];
if (successful_dribble_nibble)
begin
if (data_phy[27:24] !== data_wb[27:24])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (0 bytes) of RX packet!", ((i/4)+2));
failure = failure + 1;
end
end
else
begin
if (data_phy[27:24] === data_wb[27:24])
begin
`TIME;
$display("*E Wrong dribble nibble in %0d. word (0 bytes) of RX packet!", ((i/4)+2));
failure = failure + 1;
end
end
end
end
else
$display("(%0t)(%m) ERROR", $time);
delta_t = !delta_t;
end
endtask // check_rx_packet
 
//////////////////////////////////////////////////////////////
// Ethernet CRC Basic tasks
//////////////////////////////////////////////////////////////
 
task append_tx_crc;
input [31:0] txpnt_wb; // source
input [15:0] len; // length in bytes without CRC
input negated_crc; // if appended CRC is correct or not
reg [31:0] crc;
reg [31:0] addr_wb;
reg delta_t;
begin
addr_wb = txpnt_wb + {16'h0, len};
delta_t = 0;
// calculate CRC from prepared packet
paralel_crc_mac(txpnt_wb, {16'h0, len}, 1'b0, crc);
if (negated_crc)
crc = ~crc;
delta_t = !delta_t;
 
// Write might not be word allign.
if (addr_wb[1:0] == 1)
begin
wb_slave.wr_mem(addr_wb - 1, {8'h0, crc[7:0], crc[15:8], crc[23:16]}, 4'h7);
wb_slave.wr_mem(addr_wb + 3, {crc[31:24], 24'h0}, 4'h8);
end
else if (addr_wb[1:0] == 2)
begin
wb_slave.wr_mem(addr_wb - 2, {16'h0, crc[7:0], crc[15:8]}, 4'h3);
wb_slave.wr_mem(addr_wb + 2, {crc[23:16], crc[31:24], 16'h0}, 4'hC);
end
else if (addr_wb[1:0] == 3)
begin
wb_slave.wr_mem(addr_wb - 3, {24'h0, crc[7:0]}, 4'h1);
wb_slave.wr_mem(addr_wb + 1, {crc[15:8], crc[23:16], crc[31:24], 8'h0}, 4'hE);
end
else
begin
wb_slave.wr_mem(addr_wb, {crc[7:0], crc[15:8], crc[23:16], crc[31:24]}, 4'hF);
end
delta_t = !delta_t;
end
endtask // append_tx_crc
 
task check_tx_crc; // used to check crc added to TX packets by MAC
input [31:0] txpnt_phy; // destination
input [15:0] len; // length in bytes without CRC
input negated_crc; // if appended CRC is correct or not
output [31:0] failure;
reg [31:0] failure;
reg [31:0] crc_calc;
reg [31:0] crc;
reg [31:0] addr_phy;
reg delta_t;
begin
addr_phy = txpnt_phy;
failure = 0;
// calculate CRC from sent packet
// serial_crc_phy_tx(addr_phy, {16'h0, len}, 1'b0, crc_calc);
//#10;
paralel_crc_phy_tx(addr_phy, {16'h0, len}, 1'b0, crc_calc);
#1;
addr_phy = addr_phy + len;
// Read CRC - BIG endian
crc[31:24] = eth_phy.tx_mem[addr_phy[21:0]];
crc[23:16] = eth_phy.tx_mem[addr_phy[21:0] + 1];
crc[15: 8] = eth_phy.tx_mem[addr_phy[21:0] + 2];
crc[ 7: 0] = eth_phy.tx_mem[addr_phy[21:0] + 3];
 
delta_t = !delta_t;
if (negated_crc)
begin
if ((~crc_calc) !== crc)
begin
`TIME;
$display("*E Negated CRC was not successfuly transmitted!");
failure = failure + 1;
end
end
else
begin
if (crc_calc !== crc)
begin
`TIME;
$display("*E Transmitted CRC was not correct; crc_calc: %0h, crc_mem: %0h", crc_calc, crc);
failure = failure + 1;
end
end
delta_t = !delta_t;
end
endtask // check_tx_crc
 
task append_rx_crc;
input [31:0] rxpnt_phy; // source
input [15:0] len; // length in bytes without CRC
input plus_dribble_nibble; // if length is longer for one nibble
input negated_crc; // if appended CRC is correct or not
reg [31:0] crc;
reg [7:0] tmp;
reg [31:0] addr_phy;
reg delta_t;
begin
addr_phy = rxpnt_phy + len;
delta_t = 0;
// calculate CRC from prepared packet
paralel_crc_phy_rx(rxpnt_phy, {16'h0, len}, plus_dribble_nibble, crc);
if (negated_crc)
crc = ~crc;
delta_t = !delta_t;
 
if (plus_dribble_nibble)
begin
tmp = eth_phy.rx_mem[addr_phy];
eth_phy.rx_mem[addr_phy] = {crc[27:24], tmp[3:0]};
eth_phy.rx_mem[addr_phy + 1] = {crc[19:16], crc[31:28]};
eth_phy.rx_mem[addr_phy + 2] = {crc[11:8], crc[23:20]};
eth_phy.rx_mem[addr_phy + 3] = {crc[3:0], crc[15:12]};
eth_phy.rx_mem[addr_phy + 4] = {4'h0, crc[7:4]};
end
else
begin
eth_phy.rx_mem[addr_phy] = crc[31:24];
eth_phy.rx_mem[addr_phy + 1] = crc[23:16];
eth_phy.rx_mem[addr_phy + 2] = crc[15:8];
eth_phy.rx_mem[addr_phy + 3] = crc[7:0];
end
end
endtask // append_rx_crc
 
// paralel CRC checking for PHY TX
task paralel_crc_phy_tx;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc_out;
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer nibble_cnt;
reg [31:0] load_reg;
reg delta_t;
reg [31:0] crc_next;
reg [31:0] crc;
reg crc_error;
reg [3:0] data_in;
integer i;
begin
#1 addr_cnt = start_addr[21:0];
word_cnt = 24; // 27; // start of the frame - nibble granularity (MSbit first)
crc = 32'hFFFF_FFFF; // INITIAL value
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of nibbles from Byte length (2^1 = 2)
if (plus_dribble_nibble)
nibble_cnt = ((len + 4) << 1) + 1'b1; // one nibble longer
else
nibble_cnt = ((len + 4) << 1);
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
while (nibble_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// shift data in
 
if(nibble_cnt <= 8) // for additional 8 nibbles shift ZEROs in!
data_in[3:0] = 4'h0;
else
 
data_in[3:0] = {load_reg[word_cnt], load_reg[word_cnt+1], load_reg[word_cnt+2], load_reg[word_cnt+3]};
crc_next[0] = (data_in[0] ^ crc[28]);
crc_next[1] = (data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29]);
crc_next[2] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]);
crc_next[3] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]);
crc_next[4] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[0];
crc_next[5] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[1];
crc_next[6] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[ 2];
crc_next[7] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[3];
crc_next[8] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[4];
crc_next[9] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[5];
crc_next[10] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[6];
crc_next[11] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[7];
crc_next[12] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]) ^ crc[8];
crc_next[13] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]) ^ crc[9];
crc_next[14] = (data_in[3] ^ data_in[2] ^ crc[30] ^ crc[31]) ^ crc[10];
crc_next[15] = (data_in[3] ^ crc[31]) ^ crc[11];
crc_next[16] = (data_in[0] ^ crc[28]) ^ crc[12];
crc_next[17] = (data_in[1] ^ crc[29]) ^ crc[13];
crc_next[18] = (data_in[2] ^ crc[30]) ^ crc[14];
crc_next[19] = (data_in[3] ^ crc[31]) ^ crc[15];
crc_next[20] = crc[16];
crc_next[21] = crc[17];
crc_next[22] = (data_in[0] ^ crc[28]) ^ crc[18];
crc_next[23] = (data_in[1] ^ data_in[0] ^ crc[29] ^ crc[28]) ^ crc[19];
crc_next[24] = (data_in[2] ^ data_in[1] ^ crc[30] ^ crc[29]) ^ crc[20];
crc_next[25] = (data_in[3] ^ data_in[2] ^ crc[31] ^ crc[30]) ^ crc[21];
crc_next[26] = (data_in[3] ^ data_in[0] ^ crc[31] ^ crc[28]) ^ crc[22];
crc_next[27] = (data_in[1] ^ crc[29]) ^ crc[23];
crc_next[28] = (data_in[2] ^ crc[30]) ^ crc[24];
crc_next[29] = (data_in[3] ^ crc[31]) ^ crc[25];
crc_next[30] = crc[26];
crc_next[31] = crc[27];
 
crc = crc_next;
crc_error = crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number
case (nibble_cnt)
9: crc_out = {!crc[24], !crc[25], !crc[26], !crc[27], !crc[28], !crc[29], !crc[30], !crc[31],
!crc[16], !crc[17], !crc[18], !crc[19], !crc[20], !crc[21], !crc[22], !crc[23],
!crc[ 8], !crc[ 9], !crc[10], !crc[11], !crc[12], !crc[13], !crc[14], !crc[15],
!crc[ 0], !crc[ 1], !crc[ 2], !crc[ 3], !crc[ 4], !crc[ 5], !crc[ 6], !crc[ 7]};
default: crc_out = crc_out;
endcase
// wait for delta time
delta_t = !delta_t;
// increment address and load new data
if ((word_cnt+3) == 7)//4)
begin
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
end
// set new load bit position
if((word_cnt+3) == 31)
word_cnt = 16;
else if ((word_cnt+3) == 23)
word_cnt = 8;
else if ((word_cnt+3) == 15)
word_cnt = 0;
else if ((word_cnt+3) == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 4;// - 4;
// decrement nibble counter
nibble_cnt = nibble_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
#1;
end
endtask // paralel_crc_phy_tx
 
// paralel CRC calculating for PHY RX
task paralel_crc_phy_rx;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc_out;
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer nibble_cnt;
reg [31:0] load_reg;
reg delta_t;
reg [31:0] crc_next;
reg [31:0] crc;
reg crc_error;
reg [3:0] data_in;
integer i;
begin
#1 addr_cnt = start_addr[21:0];
word_cnt = 24; // 27; // start of the frame - nibble granularity (MSbit first)
crc = 32'hFFFF_FFFF; // INITIAL value
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of nibbles from Byte length (2^1 = 2)
if (plus_dribble_nibble)
nibble_cnt = ((len + 4) << 1) + 1'b1; // one nibble longer
else
nibble_cnt = ((len + 4) << 1);
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
while (nibble_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// shift data in
 
if(nibble_cnt <= 8) // for additional 8 nibbles shift ZEROs in!
data_in[3:0] = 4'h0;
else
 
data_in[3:0] = {load_reg[word_cnt], load_reg[word_cnt+1], load_reg[word_cnt+2], load_reg[word_cnt+3]};
crc_next[0] = (data_in[0] ^ crc[28]);
crc_next[1] = (data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29]);
crc_next[2] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]);
crc_next[3] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]);
crc_next[4] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[0];
crc_next[5] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[1];
crc_next[6] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[ 2];
crc_next[7] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[3];
crc_next[8] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[4];
crc_next[9] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[5];
crc_next[10] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[6];
crc_next[11] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[7];
crc_next[12] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]) ^ crc[8];
crc_next[13] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]) ^ crc[9];
crc_next[14] = (data_in[3] ^ data_in[2] ^ crc[30] ^ crc[31]) ^ crc[10];
crc_next[15] = (data_in[3] ^ crc[31]) ^ crc[11];
crc_next[16] = (data_in[0] ^ crc[28]) ^ crc[12];
crc_next[17] = (data_in[1] ^ crc[29]) ^ crc[13];
crc_next[18] = (data_in[2] ^ crc[30]) ^ crc[14];
crc_next[19] = (data_in[3] ^ crc[31]) ^ crc[15];
crc_next[20] = crc[16];
crc_next[21] = crc[17];
crc_next[22] = (data_in[0] ^ crc[28]) ^ crc[18];
crc_next[23] = (data_in[1] ^ data_in[0] ^ crc[29] ^ crc[28]) ^ crc[19];
crc_next[24] = (data_in[2] ^ data_in[1] ^ crc[30] ^ crc[29]) ^ crc[20];
crc_next[25] = (data_in[3] ^ data_in[2] ^ crc[31] ^ crc[30]) ^ crc[21];
crc_next[26] = (data_in[3] ^ data_in[0] ^ crc[31] ^ crc[28]) ^ crc[22];
crc_next[27] = (data_in[1] ^ crc[29]) ^ crc[23];
crc_next[28] = (data_in[2] ^ crc[30]) ^ crc[24];
crc_next[29] = (data_in[3] ^ crc[31]) ^ crc[25];
crc_next[30] = crc[26];
crc_next[31] = crc[27];
 
crc = crc_next;
crc_error = crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number
case (nibble_cnt)
9: crc_out = {!crc[24], !crc[25], !crc[26], !crc[27], !crc[28], !crc[29], !crc[30], !crc[31],
!crc[16], !crc[17], !crc[18], !crc[19], !crc[20], !crc[21], !crc[22], !crc[23],
!crc[ 8], !crc[ 9], !crc[10], !crc[11], !crc[12], !crc[13], !crc[14], !crc[15],
!crc[ 0], !crc[ 1], !crc[ 2], !crc[ 3], !crc[ 4], !crc[ 5], !crc[ 6], !crc[ 7]};
default: crc_out = crc_out;
endcase
// wait for delta time
delta_t = !delta_t;
// increment address and load new data
if ((word_cnt+3) == 7)//4)
begin
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
end
// set new load bit position
if((word_cnt+3) == 31)
word_cnt = 16;
else if ((word_cnt+3) == 23)
word_cnt = 8;
else if ((word_cnt+3) == 15)
word_cnt = 0;
else if ((word_cnt+3) == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 4;// - 4;
// decrement nibble counter
nibble_cnt = nibble_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
#1;
end
endtask // paralel_crc_phy_rx
 
// paralel CRC checking for MAC
task paralel_crc_mac;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc_out;
 
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer nibble_cnt;
reg [31:0] load_reg;
reg delta_t;
reg [31:0] crc_next;
reg [31:0] crc;
reg crc_error;
reg [3:0] data_in;
integer i;
begin
#1 addr_cnt = start_addr[19:0];
// set starting point depending with which byte frame starts (e.g. if addr_cnt[1:0] == 0, then
// MSB of the packet must be written to the LSB of Big ENDIAN Word [31:24])
if (addr_cnt[1:0] == 2'h1)
word_cnt = 16; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
else if (addr_cnt[1:0] == 2'h2)
word_cnt = 8; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
else if (addr_cnt[1:0] == 2'h3)
word_cnt = 0; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
else
word_cnt = 24; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
crc = 32'hFFFF_FFFF; // INITIAL value
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of nibbles from Byte length (2^1 = 2)
if (plus_dribble_nibble)
nibble_cnt = ((len + 4) << 1) + 1'b1; // one nibble longer
else
nibble_cnt = ((len + 4) << 1);
load_reg = wb_slave.wb_memory[{12'h0, addr_cnt}];
addr_cnt = addr_cnt + 4;
while (nibble_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// shift data in
 
if(nibble_cnt <= 8) // for additional 8 nibbles shift ZEROs in!
data_in[3:0] = 4'h0;
else
 
data_in[3:0] = {load_reg[word_cnt], load_reg[word_cnt+1], load_reg[word_cnt+2], load_reg[word_cnt+3]};
crc_next[0] = (data_in[0] ^ crc[28]);
crc_next[1] = (data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29]);
crc_next[2] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]);
crc_next[3] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]);
crc_next[4] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[0];
crc_next[5] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[1];
crc_next[6] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[ 2];
crc_next[7] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[3];
crc_next[8] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[4];
crc_next[9] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[5];
crc_next[10] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[6];
crc_next[11] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[7];
crc_next[12] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]) ^ crc[8];
crc_next[13] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]) ^ crc[9];
crc_next[14] = (data_in[3] ^ data_in[2] ^ crc[30] ^ crc[31]) ^ crc[10];
crc_next[15] = (data_in[3] ^ crc[31]) ^ crc[11];
crc_next[16] = (data_in[0] ^ crc[28]) ^ crc[12];
crc_next[17] = (data_in[1] ^ crc[29]) ^ crc[13];
crc_next[18] = (data_in[2] ^ crc[30]) ^ crc[14];
crc_next[19] = (data_in[3] ^ crc[31]) ^ crc[15];
crc_next[20] = crc[16];
crc_next[21] = crc[17];
crc_next[22] = (data_in[0] ^ crc[28]) ^ crc[18];
crc_next[23] = (data_in[1] ^ data_in[0] ^ crc[29] ^ crc[28]) ^ crc[19];
crc_next[24] = (data_in[2] ^ data_in[1] ^ crc[30] ^ crc[29]) ^ crc[20];
crc_next[25] = (data_in[3] ^ data_in[2] ^ crc[31] ^ crc[30]) ^ crc[21];
crc_next[26] = (data_in[3] ^ data_in[0] ^ crc[31] ^ crc[28]) ^ crc[22];
crc_next[27] = (data_in[1] ^ crc[29]) ^ crc[23];
crc_next[28] = (data_in[2] ^ crc[30]) ^ crc[24];
crc_next[29] = (data_in[3] ^ crc[31]) ^ crc[25];
crc_next[30] = crc[26];
crc_next[31] = crc[27];
 
crc = crc_next;
crc_error = crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number
case (nibble_cnt)
9: crc_out = {!crc[24], !crc[25], !crc[26], !crc[27], !crc[28], !crc[29], !crc[30], !crc[31],
!crc[16], !crc[17], !crc[18], !crc[19], !crc[20], !crc[21], !crc[22], !crc[23],
!crc[ 8], !crc[ 9], !crc[10], !crc[11], !crc[12], !crc[13], !crc[14], !crc[15],
!crc[ 0], !crc[ 1], !crc[ 2], !crc[ 3], !crc[ 4], !crc[ 5], !crc[ 6], !crc[ 7]};
default: crc_out = crc_out;
endcase
// wait for delta time
delta_t = !delta_t;
// increment address and load new data
if ((word_cnt+3) == 7)//4)
begin
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg = wb_slave.wb_memory[{12'h0, addr_cnt}];
addr_cnt = addr_cnt + 4;
end
// set new load bit position
if((word_cnt+3) == 31)
word_cnt = 16;
else if ((word_cnt+3) == 23)
word_cnt = 8;
else if ((word_cnt+3) == 15)
word_cnt = 0;
else if ((word_cnt+3) == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 4;// - 4;
// decrement nibble counter
nibble_cnt = nibble_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
#1;
end
endtask // paralel_crc_mac
 
// serial CRC checking for PHY TX
task serial_crc_phy_tx;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc;
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer bit_cnt;
reg [31:0] load_reg;
reg [31:0] crc_shift_reg;
reg [31:0] crc_store_reg;
reg delta_t;
begin
#1 addr_cnt = start_addr[21:0];
word_cnt = 24; // 27; // start of the frame - nibble granularity (MSbit first)
crc_store_reg = 32'hFFFF_FFFF; // INITIAL value
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of bits from Byte length (2^3 = 8)
if (plus_dribble_nibble)
bit_cnt = ((len + 4) << 3) + 3'h4; // one nibble longer
else
bit_cnt = ((len + 4) << 3);
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy.tx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
#1;
while (bit_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
#1;
// shift data in
 
if(bit_cnt <= 32) // for additional 32 bits shift ZEROs in!
crc_shift_reg[0] = 1'b0 ^ crc_store_reg[31];
else
 
crc_shift_reg[0] = load_reg[word_cnt] ^ crc_store_reg[31];
crc_shift_reg[1] = crc_store_reg[0] ^ crc_store_reg[31];
crc_shift_reg[2] = crc_store_reg[1] ^ crc_store_reg[31];
crc_shift_reg[3] = crc_store_reg[2];
crc_shift_reg[4] = crc_store_reg[3] ^ crc_store_reg[31];
crc_shift_reg[5] = crc_store_reg[4] ^ crc_store_reg[31];
crc_shift_reg[6] = crc_store_reg[5];
crc_shift_reg[7] = crc_store_reg[6] ^ crc_store_reg[31];
crc_shift_reg[8] = crc_store_reg[7] ^ crc_store_reg[31];
crc_shift_reg[9] = crc_store_reg[8];
crc_shift_reg[10] = crc_store_reg[9] ^ crc_store_reg[31];
crc_shift_reg[11] = crc_store_reg[10] ^ crc_store_reg[31];
crc_shift_reg[12] = crc_store_reg[11] ^ crc_store_reg[31];
crc_shift_reg[13] = crc_store_reg[12];
crc_shift_reg[14] = crc_store_reg[13];
crc_shift_reg[15] = crc_store_reg[14];
crc_shift_reg[16] = crc_store_reg[15] ^ crc_store_reg[31];
crc_shift_reg[17] = crc_store_reg[16];
crc_shift_reg[18] = crc_store_reg[17];
crc_shift_reg[19] = crc_store_reg[18];
crc_shift_reg[20] = crc_store_reg[19];
crc_shift_reg[21] = crc_store_reg[20];
crc_shift_reg[22] = crc_store_reg[21] ^ crc_store_reg[31];
crc_shift_reg[23] = crc_store_reg[22] ^ crc_store_reg[31];
crc_shift_reg[24] = crc_store_reg[23];
crc_shift_reg[25] = crc_store_reg[24];
crc_shift_reg[26] = crc_store_reg[25] ^ crc_store_reg[31];
crc_shift_reg[27] = crc_store_reg[26];
crc_shift_reg[28] = crc_store_reg[27];
crc_shift_reg[29] = crc_store_reg[28];
crc_shift_reg[30] = crc_store_reg[29];
crc_shift_reg[31] = crc_store_reg[30];
// wait for delta time
delta_t = !delta_t;
 
// store previous data
crc_store_reg = crc_shift_reg;
 
// put CRC out
case (bit_cnt)
33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 1:
begin
crc = crc_store_reg;
crc = {!crc[24], !crc[25], !crc[26], !crc[27], !crc[28], !crc[29], !crc[30], !crc[31],
!crc[16], !crc[17], !crc[18], !crc[19], !crc[20], !crc[21], !crc[22], !crc[23],
!crc[ 8], !crc[ 9], !crc[10], !crc[11], !crc[12], !crc[13], !crc[14], !crc[15],
!crc[ 0], !crc[ 1], !crc[ 2], !crc[ 3], !crc[ 4], !crc[ 5], !crc[ 6], !crc[ 7]};
end
default: crc = crc;
endcase
 
// increment address and load new data
#1;
if (word_cnt == 7)//4)
begin
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy.tx_mem[addr_cnt];
// load_reg[31:24] = {load_reg[28], load_reg[29], load_reg[30], load_reg[31],
// load_reg[24], load_reg[25], load_reg[26], load_reg[27]};
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.tx_mem[addr_cnt];
// load_reg[23:16] = {load_reg[20], load_reg[21], load_reg[22], load_reg[23],
// load_reg[16], load_reg[17], load_reg[18], load_reg[19]};
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy.tx_mem[addr_cnt];
// load_reg[15: 8] = {load_reg[12], load_reg[13], load_reg[14], load_reg[15],
// load_reg[ 8], load_reg[ 9], load_reg[10], load_reg[11]};
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy.tx_mem[addr_cnt];
// load_reg[ 7: 0] = {load_reg[ 4], load_reg[ 5], load_reg[ 6], load_reg[ 7],
// load_reg[ 0], load_reg[ 1], load_reg[ 2], load_reg[ 3]};
addr_cnt = addr_cnt + 1;
end
#1;
// set new load bit position
if(word_cnt == 31)
word_cnt = 16;
else if (word_cnt == 23)
word_cnt = 8;
else if (word_cnt == 15)
word_cnt = 0;
else if (word_cnt == 7)
word_cnt = 24;
 
// if(word_cnt == 24)
// word_cnt = 31;
// else if (word_cnt == 28)
// word_cnt = 19;
// else if (word_cnt == 16)
// word_cnt = 23;
// else if (word_cnt == 20)
// word_cnt = 11;
// else if(word_cnt == 8)
// word_cnt = 15;
// else if (word_cnt == 12)
// word_cnt = 3;
// else if (word_cnt == 0)
// word_cnt = 7;
// else if (word_cnt == 4)
// word_cnt = 27;
else
word_cnt = word_cnt + 1;// - 1;
#1;
// decrement bit counter
bit_cnt = bit_cnt - 1;
#1;
// wait for delta time
delta_t = !delta_t;
end // while
 
#1;
end
endtask // serial_crc_phy_tx
 
// serial CRC calculating for PHY RX
task serial_crc_phy_rx;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc;
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer bit_cnt;
reg [31:0] load_reg;
reg [31:0] crc_shift_reg;
reg [31:0] crc_store_reg;
reg delta_t;
begin
#1 addr_cnt = start_addr[21:0];
word_cnt = 24; // start of the frame
crc_shift_reg = 0;
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of bits from Byte length (2^3 = 8)
if (plus_dribble_nibble)
bit_cnt = ((len + 4) << 3) + 3'h4; // one nibble longer
else
bit_cnt = ((len + 4) << 3);
load_reg[31:24] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15:8] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[7:0] = eth_phy.rx_mem[addr_cnt];
 
while (bit_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// store previous data
crc_store_reg = crc_shift_reg;
// shift data in
if(bit_cnt <= 32) // for additional 32 bits shift ZEROs in!
crc_shift_reg[0] = 1'b0 ^ crc_store_reg[31];
else
crc_shift_reg[0] = load_reg[word_cnt] ^ crc_store_reg[31];
crc_shift_reg[1] = crc_store_reg[0] ^ crc_store_reg[31];
crc_shift_reg[2] = crc_store_reg[1] ^ crc_store_reg[31];
crc_shift_reg[3] = crc_store_reg[2];
crc_shift_reg[4] = crc_store_reg[3] ^ crc_store_reg[31];
crc_shift_reg[5] = crc_store_reg[4] ^ crc_store_reg[31];
crc_shift_reg[6] = crc_store_reg[5];
crc_shift_reg[7] = crc_store_reg[6] ^ crc_store_reg[31];
crc_shift_reg[8] = crc_store_reg[7] ^ crc_store_reg[31];
crc_shift_reg[9] = crc_store_reg[8];
crc_shift_reg[10] = crc_store_reg[9] ^ crc_store_reg[31];
crc_shift_reg[11] = crc_store_reg[10] ^ crc_store_reg[31];
crc_shift_reg[12] = crc_store_reg[11] ^ crc_store_reg[31];
crc_shift_reg[13] = crc_store_reg[12];
crc_shift_reg[14] = crc_store_reg[13];
crc_shift_reg[15] = crc_store_reg[14];
crc_shift_reg[16] = crc_store_reg[15] ^ crc_store_reg[31];
crc_shift_reg[17] = crc_store_reg[16];
crc_shift_reg[18] = crc_store_reg[17];
crc_shift_reg[19] = crc_store_reg[18];
crc_shift_reg[20] = crc_store_reg[19];
crc_shift_reg[21] = crc_store_reg[20];
crc_shift_reg[22] = crc_store_reg[21] ^ crc_store_reg[31];
crc_shift_reg[23] = crc_store_reg[22] ^ crc_store_reg[31];
crc_shift_reg[24] = crc_store_reg[23];
crc_shift_reg[25] = crc_store_reg[24];
crc_shift_reg[26] = crc_store_reg[25] ^ crc_store_reg[31];
crc_shift_reg[27] = crc_store_reg[26];
crc_shift_reg[28] = crc_store_reg[27];
crc_shift_reg[29] = crc_store_reg[28];
crc_shift_reg[30] = crc_store_reg[29];
crc_shift_reg[31] = crc_store_reg[30];
// wait for delta time
delta_t = !delta_t;
// increment address and load new data
if (word_cnt == 7)
begin
addr_cnt = addr_cnt + 1;
load_reg[31:24] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15:8] = eth_phy.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[7:0] = eth_phy.rx_mem[addr_cnt];
end
// set new load bit position
if(word_cnt == 31)
word_cnt = 16;
else if (word_cnt == 23)
word_cnt = 8;
else if (word_cnt == 15)
word_cnt = 0;
else if (word_cnt == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 1;
// decrement bit counter
bit_cnt = bit_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
 
// put CRC out
crc = crc_shift_reg;
#1;
end
endtask // serial_crc_phy_rx
 
// serial CRC checking for MAC
task serial_crc_mac;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc;
reg [19:0] addr_cnt; // only 20 address lines
integer word_cnt;
integer bit_cnt;
reg [31:0] load_reg;
reg [31:0] crc_shift_reg;
reg [31:0] crc_store_reg;
reg delta_t;
begin
#1 addr_cnt = start_addr[19:0];
// set starting point depending with which byte frame starts (e.g. if addr_cnt[1:0] == 0, then
// MSB of the packet must be written to the LSB of Big ENDIAN Word [31:24])
if (addr_cnt[1:0] == 2'h1)
word_cnt = 16; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
else if (addr_cnt[1:0] == 2'h2)
word_cnt = 8; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
else if (addr_cnt[1:0] == 2'h3)
word_cnt = 0; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
else
word_cnt = 24; // start of the frame for Big ENDIAN Bytes (Litle ENDIAN bits)
 
crc_shift_reg = 0;
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of bits from Byte length (2^3 = 8)
if (plus_dribble_nibble)
bit_cnt = ((len + 4) << 3) + 3'h4; // one nibble longer
else
bit_cnt = ((len + 4) << 3);
load_reg = wb_slave.wb_memory[{12'h0, addr_cnt}];
 
while (bit_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// store previous data
crc_store_reg = crc_shift_reg;
// shift data in
if(bit_cnt <= 32) // for additional 32 bits shift ZEROs in!
crc_shift_reg[0] = 1'b0 ^ crc_store_reg[31];
else
crc_shift_reg[0] = load_reg[word_cnt] ^ crc_store_reg[31];
crc_shift_reg[1] = crc_store_reg[0] ^ crc_store_reg[31];
crc_shift_reg[2] = crc_store_reg[1] ^ crc_store_reg[31];
crc_shift_reg[3] = crc_store_reg[2];
crc_shift_reg[4] = crc_store_reg[3] ^ crc_store_reg[31];
crc_shift_reg[5] = crc_store_reg[4] ^ crc_store_reg[31];
crc_shift_reg[6] = crc_store_reg[5];
crc_shift_reg[7] = crc_store_reg[6] ^ crc_store_reg[31];
crc_shift_reg[8] = crc_store_reg[7] ^ crc_store_reg[31];
crc_shift_reg[9] = crc_store_reg[8];
crc_shift_reg[10] = crc_store_reg[9] ^ crc_store_reg[31];
crc_shift_reg[11] = crc_store_reg[10] ^ crc_store_reg[31];
crc_shift_reg[12] = crc_store_reg[11] ^ crc_store_reg[31];
crc_shift_reg[13] = crc_store_reg[12];
crc_shift_reg[14] = crc_store_reg[13];
crc_shift_reg[15] = crc_store_reg[14];
crc_shift_reg[16] = crc_store_reg[15] ^ crc_store_reg[31];
crc_shift_reg[17] = crc_store_reg[16];
crc_shift_reg[18] = crc_store_reg[17];
crc_shift_reg[19] = crc_store_reg[18];
crc_shift_reg[20] = crc_store_reg[19];
crc_shift_reg[21] = crc_store_reg[20];
crc_shift_reg[22] = crc_store_reg[21] ^ crc_store_reg[31];
crc_shift_reg[23] = crc_store_reg[22] ^ crc_store_reg[31];
crc_shift_reg[24] = crc_store_reg[23];
crc_shift_reg[25] = crc_store_reg[24];
crc_shift_reg[26] = crc_store_reg[25] ^ crc_store_reg[31];
crc_shift_reg[27] = crc_store_reg[26];
crc_shift_reg[28] = crc_store_reg[27];
crc_shift_reg[29] = crc_store_reg[28];
crc_shift_reg[30] = crc_store_reg[29];
crc_shift_reg[31] = crc_store_reg[30];
// wait for delta time
delta_t = !delta_t;
// increment address and load new data for Big ENDIAN Bytes (Litle ENDIAN bits)
if (word_cnt == 7)
begin
addr_cnt = addr_cnt + 4;
load_reg = wb_slave.wb_memory[{12'h0, addr_cnt}];
end
// set new load bit position for Big ENDIAN Bytes (Litle ENDIAN bits)
if(word_cnt == 31)
word_cnt = 16;
else if (word_cnt == 23)
word_cnt = 8;
else if (word_cnt == 15)
word_cnt = 0;
else if (word_cnt == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 1;
// decrement bit counter
bit_cnt = bit_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
 
// put CRC out
crc = crc_shift_reg;
#1;
end
endtask // serial_crc_mac
 
//////////////////////////////////////////////////////////////
// MIIM Basic tasks
//////////////////////////////////////////////////////////////
 
task reset_mii; // MII module
reg [31:0] tmp;
reg [31:0] tmp_no_rst;
begin
// read MII mode register first
wbm_read(`ETH_MIIMODER, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// set reset bit - write back to MII mode register with RESET bit
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_RST | tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// clear reset bit - write back to MII mode register without RESET bit
tmp_no_rst = `ETH_MIIMODER_RST;
tmp_no_rst = ~tmp_no_rst;
wbm_write(`ETH_MIIMODER, (tmp_no_rst & tmp), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
endtask // reset_mii
 
task mii_set_clk_div; // set clock divider for MII clock
input [7:0] clk_div;
begin
// MII mode register
wbm_write(`ETH_MIIMODER, (`ETH_MIIMODER_CLKDIV & clk_div), 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
endtask // mii_set_clk_div
 
 
task check_mii_busy; // MII - check if BUSY
reg [31:0] tmp;
begin
@(posedge wb_clk);
// MII read status register
wbm_read(`ETH_MIISTATUS, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
while(tmp[`ETH_MIISTATUS_BUSY] !== 1'b0) //`ETH_MIISTATUS_BUSY
begin
@(posedge wb_clk);
wbm_read(`ETH_MIISTATUS, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
end
endtask // check_mii_busy
 
 
task check_mii_scan_valid; // MII - check if SCAN data are valid
reg [31:0] tmp;
begin
@(posedge wb_clk);
// MII read status register
wbm_read(`ETH_MIISTATUS, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
while(tmp[`ETH_MIISTATUS_NVALID] !== 1'b0) //`ETH_MIISTATUS_NVALID
begin
@(posedge wb_clk);
wbm_read(`ETH_MIISTATUS, tmp, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
end
end
endtask // check_mii_scan_valid
 
 
task mii_write_req; // requests write to MII
input [4:0] phy_addr;
input [4:0] reg_addr;
input [15:0] data_in;
begin
// MII address, PHY address = 1, command register address = 0
wbm_write(`ETH_MIIADDRESS, (`ETH_MIIADDRESS_FIAD & phy_addr) | (`ETH_MIIADDRESS_RGAD & (reg_addr << 8)),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// MII TX data
wbm_write(`ETH_MIITX_DATA, {16'h0000, data_in}, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// MII command
wbm_write(`ETH_MIICOMMAND, `ETH_MIICOMMAND_WCTRLDATA, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
end
endtask // mii_write_req
 
 
task mii_read_req; // requests read from MII
input [4:0] phy_addr;
input [4:0] reg_addr;
begin
// MII address, PHY address = 1, command register address = 0
wbm_write(`ETH_MIIADDRESS, (`ETH_MIIADDRESS_FIAD & phy_addr) | (`ETH_MIIADDRESS_RGAD & (reg_addr << 8)),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// MII command
wbm_write(`ETH_MIICOMMAND, `ETH_MIICOMMAND_RSTAT, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
end
endtask // mii_read_req
 
 
task mii_scan_req; // requests scan from MII
input [4:0] phy_addr;
input [4:0] reg_addr;
begin
// MII address, PHY address = 1, command register address = 0
wbm_write(`ETH_MIIADDRESS, (`ETH_MIIADDRESS_FIAD & phy_addr) | (`ETH_MIIADDRESS_RGAD & (reg_addr << 8)),
4'hF, 1, wbm_init_waits, wbm_subseq_waits);
// MII command
wbm_write(`ETH_MIICOMMAND, `ETH_MIICOMMAND_SCANSTAT, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
end
endtask // mii_scan_req
 
 
task mii_scan_finish; // finish scan from MII
begin
// MII command
wbm_write(`ETH_MIICOMMAND, 32'h0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits);
@(posedge wb_clk);
end
endtask // mii_scan_finish
 
//////////////////////////////////////////////////////////////
// Log files and memory tasks
//////////////////////////////////////////////////////////////
 
task clear_memories;
reg [22:0] adr_i;
reg delta_t;
begin
delta_t = 0;
for (adr_i = 0; adr_i < 4194304; adr_i = adr_i + 1)
begin
eth_phy.rx_mem[adr_i[21:0]] = 0;
eth_phy.tx_mem[adr_i[21:0]] = 0;
wb_slave.wb_memory[adr_i[21:2]] = 0;
delta_t = !delta_t;
end
end
endtask // clear_memories
 
task clear_buffer_descriptors;
reg [8:0] adr_i;
reg delta_t;
begin
delta_t = 0;
for (adr_i = 0; adr_i < 256; adr_i = adr_i + 1)
begin
wbm_write((`TX_BD_BASE + {adr_i[7:0], 2'b0}), 32'h0, 4'hF, 1, 4'h1, 4'h1);
delta_t = !delta_t;
end
end
endtask // clear_buffer_descriptors
 
task test_note;
input [799:0] test_note ;
reg [799:0] display_note ;
begin
display_note = test_note;
while ( display_note[799:792] == 0 )
display_note = display_note << 8 ;
$fdisplay( tb_log_file, " " ) ;
$fdisplay( tb_log_file, "NOTE: %s", display_note ) ;
$fdisplay( tb_log_file, " " ) ;
end
endtask // test_note
 
task test_heading;
input [799:0] test_heading ;
reg [799:0] display_test ;
begin
display_test = test_heading;
while ( display_test[799:792] == 0 )
display_test = display_test << 8 ;
$fdisplay( tb_log_file, " ***************************************************************************************" ) ;
$fdisplay( tb_log_file, " ***************************************************************************************" ) ;
$fdisplay( tb_log_file, " Heading: %s", display_test ) ;
$fdisplay( tb_log_file, " ***************************************************************************************" ) ;
$fdisplay( tb_log_file, " ***************************************************************************************" ) ;
$fdisplay( tb_log_file, " " ) ;
end
endtask // test_heading
 
 
task test_fail ;
input [7999:0] failure_reason ;
// reg [8007:0] display_failure ;
reg [7999:0] display_failure ;
reg [799:0] display_test ;
begin
tests_failed = tests_failed + 1 ;
 
display_failure = failure_reason; // {failure_reason, "!"} ;
while ( display_failure[7999:7992] == 0 )
display_failure = display_failure << 8 ;
 
display_test = test_name ;
while ( display_test[799:792] == 0 )
display_test = display_test << 8 ;
 
$fdisplay( tb_log_file, " *************************************************************************************" ) ;
$fdisplay( tb_log_file, " At time: %t ", $time ) ;
$fdisplay( tb_log_file, " Test: %s", display_test ) ;
$fdisplay( tb_log_file, " *FAILED* because") ;
$fdisplay( tb_log_file, " %s", display_failure ) ;
$fdisplay( tb_log_file, " *************************************************************************************" ) ;
$fdisplay( tb_log_file, " " ) ;
 
`ifdef STOP_ON_FAILURE
#20 $stop ;
`endif
end
endtask // test_fail
 
 
task test_ok ;
reg [799:0] display_test ;
begin
tests_successfull = tests_successfull + 1 ;
 
display_test = test_name ;
while ( display_test[799:792] == 0 )
display_test = display_test << 8 ;
 
$fdisplay( tb_log_file, " *************************************************************************************" ) ;
$fdisplay( tb_log_file, " At time: %t ", $time ) ;
$fdisplay( tb_log_file, " Test: %s", display_test ) ;
$fdisplay( tb_log_file, " reported *SUCCESSFULL*! ") ;
$fdisplay( tb_log_file, " *************************************************************************************" ) ;
$fdisplay( tb_log_file, " " ) ;
end
endtask // test_ok
 
 
task test_summary;
begin
$fdisplay(tb_log_file, "**************************** Ethernet MAC test summary **********************************") ;
$fdisplay(tb_log_file, "Tests performed: %d", tests_successfull + tests_failed) ;
$fdisplay(tb_log_file, "Failed tests : %d", tests_failed) ;
$fdisplay(tb_log_file, "Successfull tests: %d", tests_successfull) ;
$fdisplay(tb_log_file, "**************************** Ethernet MAC test summary **********************************") ;
$fclose(tb_log_file) ;
end
endtask // test_summary
 
 
endmodule
/verilog/tb_ethernet_with_cop.v
0,0 → 1,614
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_ethernet_with_cop.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/11 13:29:28 mohor
// Bist signals added.
//
// Revision 1.1 2002/09/18 16:40:40 mohor
// Simple testbench that includes eth_cop, eth_host and eth_memory modules.
// This testbench is used for testing the whole environment. Use tb_ethernet
// testbench for testing just the ethernet MAC core (many tests).
//
//
//
//
 
 
 
`include "tb_eth_defines.v"
`include "eth_defines.v"
`include "timescale.v"
 
module tb_ethernet_with_cop();
 
 
parameter Tp = 1;
 
 
reg wb_clk_o;
reg wb_rst_o;
 
reg mtx_clk;
reg mrx_clk;
 
wire [3:0] MTxD;
wire MTxEn;
wire MTxErr;
 
reg [3:0] MRxD; // This goes to PHY
reg MRxDV; // This goes to PHY
reg MRxErr; // This goes to PHY
reg MColl; // This goes to PHY
reg MCrs; // This goes to PHY
 
wire Mdi_I;
wire Mdo_O;
wire Mdo_OE;
wire Mdc_O;
 
integer tx_log;
integer rx_log;
 
reg StartTB;
 
`ifdef ETH_XILINX_RAMB4
reg gsr;
`endif
 
 
integer packet_ready_cnt, send_packet_cnt;
 
 
// Ethernet Slave Interface signals
wire [31:0] eth_sl_wb_adr_i, eth_sl_wb_dat_o, eth_sl_wb_dat_i;
wire [3:0] eth_sl_wb_sel_i;
wire eth_sl_wb_we_i, eth_sl_wb_cyc_i, eth_sl_wb_stb_i, eth_sl_wb_ack_o, eth_sl_wb_err_o;
 
// Memory Slave Interface signals
wire [31:0] mem_sl_wb_adr_i, mem_sl_wb_dat_o, mem_sl_wb_dat_i;
wire [3:0] mem_sl_wb_sel_i;
wire mem_sl_wb_we_i, mem_sl_wb_cyc_i, mem_sl_wb_stb_i, mem_sl_wb_ack_o, mem_sl_wb_err_o;
 
// Ethernet Master Interface signals
wire [31:0] eth_ma_wb_adr_o, eth_ma_wb_dat_i, eth_ma_wb_dat_o;
wire [3:0] eth_ma_wb_sel_o;
wire eth_ma_wb_we_o, eth_ma_wb_cyc_o, eth_ma_wb_stb_o, eth_ma_wb_ack_i, eth_ma_wb_err_i;
 
`ifdef ETH_WISHBONE_B3
wire [2:0] eth_ma_wb_cti_o;
wire [1:0] eth_ma_wb_bte_o;
`endif
 
 
// Host Master Interface signals
wire [31:0] host_ma_wb_adr_o, host_ma_wb_dat_i, host_ma_wb_dat_o;
wire [3:0] host_ma_wb_sel_o;
wire host_ma_wb_we_o, host_ma_wb_cyc_o, host_ma_wb_stb_o, host_ma_wb_ack_i, host_ma_wb_err_i;
 
 
 
eth_cop i_eth_cop
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE MASTER 1 Ethernet Master Interface is connected here
.m1_wb_adr_i(eth_ma_wb_adr_o), .m1_wb_sel_i(eth_ma_wb_sel_o), .m1_wb_we_i (eth_ma_wb_we_o),
.m1_wb_dat_o(eth_ma_wb_dat_i), .m1_wb_dat_i(eth_ma_wb_dat_o), .m1_wb_cyc_i(eth_ma_wb_cyc_o),
.m1_wb_stb_i(eth_ma_wb_stb_o), .m1_wb_ack_o(eth_ma_wb_ack_i), .m1_wb_err_o(eth_ma_wb_err_i),
 
// WISHBONE MASTER 2 Host Interface is connected here
.m2_wb_adr_i(host_ma_wb_adr_o), .m2_wb_sel_i(host_ma_wb_sel_o), .m2_wb_we_i (host_ma_wb_we_o),
.m2_wb_dat_o(host_ma_wb_dat_i), .m2_wb_dat_i(host_ma_wb_dat_o), .m2_wb_cyc_i(host_ma_wb_cyc_o),
.m2_wb_stb_i(host_ma_wb_stb_o), .m2_wb_ack_o(host_ma_wb_ack_i), .m2_wb_err_o(host_ma_wb_err_i),
 
// WISHBONE slave 1 Ethernet Slave Interface is connected here
.s1_wb_adr_o(eth_sl_wb_adr_i), .s1_wb_sel_o(eth_sl_wb_sel_i), .s1_wb_we_o (eth_sl_wb_we_i),
.s1_wb_cyc_o(eth_sl_wb_cyc_i), .s1_wb_stb_o(eth_sl_wb_stb_i), .s1_wb_ack_i(eth_sl_wb_ack_o),
.s1_wb_err_i(eth_sl_wb_err_o), .s1_wb_dat_i(eth_sl_wb_dat_o), .s1_wb_dat_o(eth_sl_wb_dat_i),
 
// WISHBONE slave 2 Memory Interface is connected here
.s2_wb_adr_o(mem_sl_wb_adr_i), .s2_wb_sel_o(mem_sl_wb_sel_i), .s2_wb_we_o (mem_sl_wb_we_i),
.s2_wb_cyc_o(mem_sl_wb_cyc_i), .s2_wb_stb_o(mem_sl_wb_stb_i), .s2_wb_ack_i(mem_sl_wb_ack_o),
.s2_wb_err_i(mem_sl_wb_err_o), .s2_wb_dat_i(mem_sl_wb_dat_o), .s2_wb_dat_o(mem_sl_wb_dat_i)
);
 
 
 
 
// Connecting Ethernet top module
eth_top ethtop
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE slave
.wb_adr_i(eth_sl_wb_adr_i[11:2]), .wb_sel_i(eth_sl_wb_sel_i), .wb_we_i(eth_sl_wb_we_i),
.wb_cyc_i(eth_sl_wb_cyc_i), .wb_stb_i(eth_sl_wb_stb_i), .wb_ack_o(eth_sl_wb_ack_o),
.wb_err_o(eth_sl_wb_err_o), .wb_dat_i(eth_sl_wb_dat_i), .wb_dat_o(eth_sl_wb_dat_o),
// WISHBONE master
.m_wb_adr_o(eth_ma_wb_adr_o), .m_wb_sel_o(eth_ma_wb_sel_o), .m_wb_we_o(eth_ma_wb_we_o),
.m_wb_dat_i(eth_ma_wb_dat_i), .m_wb_dat_o(eth_ma_wb_dat_o), .m_wb_cyc_o(eth_ma_wb_cyc_o),
.m_wb_stb_o(eth_ma_wb_stb_o), .m_wb_ack_i(eth_ma_wb_ack_i), .m_wb_err_i(eth_ma_wb_err_i),
 
`ifdef ETH_WISHBONE_B3
.m_wb_cti_o(eth_ma_wb_cti_o), .m_wb_bte_o(eth_ma_wb_bte_o),
`endif
 
//TX
.mtx_clk_pad_i(mtx_clk), .mtxd_pad_o(MTxD), .mtxen_pad_o(MTxEn), .mtxerr_pad_o(MTxErr),
 
//RX
.mrx_clk_pad_i(mrx_clk), .mrxd_pad_i(MRxD), .mrxdv_pad_i(MRxDV), .mrxerr_pad_i(MRxErr),
.mcoll_pad_i(MColl), .mcrs_pad_i(MCrs),
// MIIM
.mdc_pad_o(Mdc_O), .md_pad_i(Mdi_I), .md_pad_o(Mdo_O), .md_padoe_o(Mdo_OE),
.int_o()
 
// Bist
`ifdef ETH_BIST
,
.scanb_rst (1'b0),
.scanb_clk (1'b0),
.scanb_si (1'b0),
.scanb_so (),
.scanb_en (1'b0)
`endif
);
 
 
 
// Connecting Memory Interface Module
eth_memory i_eth_memory
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE slave: Memory Interface is connected here
.wb_adr_i(mem_sl_wb_adr_i), .wb_sel_i(mem_sl_wb_sel_i), .wb_we_i (mem_sl_wb_we_i),
.wb_cyc_i(mem_sl_wb_cyc_i), .wb_stb_i(mem_sl_wb_stb_i), .wb_ack_o(mem_sl_wb_ack_o),
.wb_err_o(mem_sl_wb_err_o), .wb_dat_o(mem_sl_wb_dat_o), .wb_dat_i(mem_sl_wb_dat_i)
);
 
 
// Connecting Host Interface
eth_host eth_host
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE master
.wb_adr_o(host_ma_wb_adr_o), .wb_sel_o(host_ma_wb_sel_o), .wb_we_o (host_ma_wb_we_o),
.wb_dat_i(host_ma_wb_dat_i), .wb_dat_o(host_ma_wb_dat_o), .wb_cyc_o(host_ma_wb_cyc_o),
.wb_stb_o(host_ma_wb_stb_o), .wb_ack_i(host_ma_wb_ack_i), .wb_err_i(host_ma_wb_err_i)
);
 
 
 
 
 
// Reset pulse
initial
begin
MCrs=0; // This should come from PHY
MColl=0; // This should come from PHY
MRxD=0; // This should come from PHY
MRxDV=0; // This should come from PHY
MRxErr=0; // This should come from PHY
packet_ready_cnt = 0;
send_packet_cnt = 0;
tx_log = $fopen("ethernet_tx.log");
rx_log = $fopen("ethernet_rx.log");
wb_rst_o = 1'b1;
`ifdef ETH_XILINX_RAMB4
gsr = 1'b0;
#100 gsr = 1'b1;
#100 gsr = 1'b0;
`endif
#100 wb_rst_o = 1'b0;
#100 StartTB = 1'b1;
end
 
`ifdef ETH_XILINX_RAMB4
assign glbl.GSR = gsr;
`endif
 
 
 
// Generating wb_clk_o clock
initial
begin
wb_clk_o=0;
// forever #20 wb_clk_o = ~wb_clk_o; // 2*20 ns -> 25 MHz
forever #12.5 wb_clk_o = ~wb_clk_o; // 2*12.5 ns -> 40 MHz
end
 
// Generating mtx_clk clock
initial
begin
mtx_clk=0;
#3 forever #20 mtx_clk = ~mtx_clk; // 2*20 ns -> 25 MHz
end
 
// Generating mrx_clk clock
initial
begin
mrx_clk=0;
#16 forever #20 mrx_clk = ~mrx_clk; // 2*20 ns -> 25 MHz
end
 
reg [31:0] tmp;
initial
begin
wait(StartTB); // Start of testbench
 
eth_host.wb_write(`ETH_MODER, 4'hf, 32'h0); // Reset OFF
eth_host.wb_read(`ETH_MODER, 4'hf, tmp);
eth_host.wb_write(`ETH_MAC_ADDR1, 4'hf, 32'h0002); // Set ETH_MAC_ADDR1 register
eth_host.wb_write(`ETH_MAC_ADDR0, 4'hf, 32'h03040506); // Set ETH_MAC_ADDR0 register
 
initialize_txbd(3);
initialize_rxbd(4);
 
// eth_host.wb_write(`ETH_MODER, 4'hf, `ETH_MODER_RXEN | `ETH_MODER_TXEN | `ETH_MODER_PRO |
// `ETH_MODER_CRCEN | `ETH_MODER_PAD); // Set MODER register
// eth_host.wb_write(`ETH_MODER, 4'hf, `ETH_MODER_RXEN | `ETH_MODER_TXEN |
// `ETH_MODER_CRCEN | `ETH_MODER_PAD); // Set MODER register
// eth_host.wb_write(`ETH_MODER, 4'hf, `ETH_MODER_RXEN | `ETH_MODER_TXEN | `ETH_MODER_BRO |
// `ETH_MODER_CRCEN | `ETH_MODER_PAD); // Set MODER register
// eth_host.wb_write(`ETH_MODER, 4'hf, `ETH_MODER_RXEN | `ETH_MODER_TXEN | `ETH_MODER_PRO |
// `ETH_MODER_CRCEN | `ETH_MODER_PAD | `ETH_MODER_LOOPBCK); // Set MODER register
eth_host.wb_write(`ETH_MODER, 4'hf, `ETH_MODER_RXEN | `ETH_MODER_TXEN | `ETH_MODER_PRO |
`ETH_MODER_CRCEN | `ETH_MODER_PAD | `ETH_MODER_LOOPBCK |
`ETH_MODER_FULLD); // Set MODER register
eth_host.wb_read(`ETH_MODER, 4'hf, tmp);
 
set_packet(16'h364, 8'h1);
set_packet(16'h234, 8'h11);
send_packet;
repeat (1000) @(posedge mrx_clk); // Waiting for TxEthMac to finish transmit
 
// repeat (10000) @(posedge wb_clk_o); // Waiting for TxEthMac to finish transmit
set_packet(16'h534, 8'h21);
// set_packet(16'h34, 8'h31);
 
/*
eth_host.wb_write(`ETH_CTRLMODER, 4'hf, 32'h4); // Enable Tx Flow control
eth_host.wb_write(`ETH_CTRLMODER, 4'hf, 32'h5); // Enable Tx Flow control
eth_host.wb_write(`ETH_TX_CTRL, 4'hf, 32'h10013); // Send Control frame with PAUSE_TV=0x0013
*/
 
send_packet;
repeat (1000) @(posedge mrx_clk); // Waiting for TxEthMac to finish transmit
send_packet;
repeat (1000) @(posedge mrx_clk); // Waiting for TxEthMac to finish transmit
 
/*
send_packet;
*/
 
 
repeat (10000) @(posedge wb_clk_o); // Waiting for TxEthMac to finish transmit
 
/*
GetDataOnMRxD(113, `UNICAST_XFR); // LengthRx bytes is comming on MRxD[3:0] signals
 
repeat (10000) @(posedge wb_clk_o); // Waiting for TxEthMac to finish transmit
 
GetDataOnMRxD(500, `BROADCAST_XFR); // LengthRx bytes is comming on MRxD[3:0] signals
 
repeat (1000) @(posedge mrx_clk); // Waiting for TxEthMac to finish transmit
 
 
GetDataOnMRxD(1200, `BROADCAST_XFR); // LengthRx bytes is comming on MRxD[3:0] signals
 
 
GetDataOnMRxD(1000, `UNICAST_XFR); // LengthRx bytes is comming on MRxD[3:0] signals
 
repeat (10000) @(posedge wb_clk_o); // Waiting for TxEthMac to finish transmit
*/
// Reading and printing interrupts
eth_host.wb_read(`ETH_INT, 4'hf, tmp);
$display("Print irq = 0x%0x", tmp);
//Clearing all interrupts
eth_host.wb_write(`ETH_INT, 4'hf, 32'h60);
 
// Reading and printing interrupts
eth_host.wb_read(`ETH_INT, 4'hf, tmp);
$display("Print irq = 0x%0x", tmp);
 
$display("\n\n End of simulation");
$stop;
 
 
 
end
 
`ifdef ETH_WISHBONE_B3
 
integer single_cnt_tx, burst_cnt_tx, burst_cnt;
integer single_cnt_rx, burst_cnt_rx;
 
initial
begin
single_cnt_tx=0; burst_cnt_tx=0; burst_cnt=0;
single_cnt_rx=0; burst_cnt_rx=0;
end
 
// Single and burst cycle watcher
always @ (posedge wb_clk_o)
begin
if(eth_ma_wb_ack_i) begin
if(eth_ma_wb_cyc_o & eth_ma_wb_we_o & eth_ma_wb_cti_o==3'b000) begin
if(burst_cnt!==0)
$display("(%0t)(%m) ERROR !!! burst_cnt should be 0 because this is a single access", $time);
else
single_cnt_rx=single_cnt_rx+1;
end
else if(eth_ma_wb_cyc_o & !eth_ma_wb_we_o & eth_ma_wb_cti_o==3'b000) begin
if(burst_cnt!==0)
$display("(%0t)(%m) ERROR !!! burst_cnt should be 0 because this is a single access", $time);
else
single_cnt_tx=single_cnt_tx+1;
end
else if(eth_ma_wb_cyc_o & eth_ma_wb_cti_o==3'b010) begin // burst in progress
burst_cnt=burst_cnt+1;
end
else if(eth_ma_wb_cyc_o & eth_ma_wb_we_o & eth_ma_wb_cti_o==3'b111 & burst_cnt==(`ETH_BURST_LENGTH-1)) begin
burst_cnt_rx=burst_cnt_rx+1;
burst_cnt=0;
end
else if(eth_ma_wb_cyc_o & !eth_ma_wb_we_o & eth_ma_wb_cti_o==3'b111 & burst_cnt==(`ETH_BURST_LENGTH-1)) begin
burst_cnt_tx=burst_cnt_tx+1;
burst_cnt=0;
end
else
$display("(%0t)(%m) ERROR !!! Unknown cycle type or sequence", $time);
end
end
`endif // ETH_WISHBONE_B3
 
 
 
task initialize_txbd;
input [6:0] txbd_num;
integer i;
integer bd_status_addr, buf_addr, bd_ptr_addr;
for(i=0; i<txbd_num; i=i+1) begin
buf_addr = `TX_BUF_BASE + i * 32'h600;
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// Initializing BD - status
if(i==txbd_num-1)
eth_host.wb_write(bd_status_addr, 4'hf, 32'h00007800); // last BD: + WRAP
else
eth_host.wb_write(bd_status_addr, 4'hf, 32'h00005800); // IRQ + PAD + CRC
 
eth_host.wb_write(bd_ptr_addr, 4'hf, buf_addr); // Initializing BD - pointer
end
endtask // initialize_txbd
 
 
task initialize_rxbd;
input [6:0] rxbd_num;
integer i;
integer bd_status_addr, buf_addr, bd_ptr_addr;
for(i=0; i<rxbd_num; i=i+1) begin
buf_addr = `RX_BUF_BASE + i * 32'h600;
bd_status_addr = `RX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// Initializing BD - status
if(i==rxbd_num-1)
eth_host.wb_write(bd_status_addr, 4'hf, 32'h0000e000); // last BD: + WRAP
else
eth_host.wb_write(bd_status_addr, 4'hf, 32'h0000c000); // IRQ + PAD + CRC
 
eth_host.wb_write(bd_ptr_addr, 4'hf, buf_addr); // Initializing BD - pointer
end
endtask // initialize_rxbd
 
 
task set_packet;
input [15:0] len;
input [7:0] start_data;
 
integer i, sd;
integer bd_status_addr, bd_ptr_addr, buffer, bd;
begin
sd = start_data;
bd_status_addr = `TX_BD_BASE + packet_ready_cnt * 8;
bd_ptr_addr = bd_status_addr + 4;
// Reading BD + buffer pointer
eth_host.wb_read(bd_status_addr, 4'hf, bd);
eth_host.wb_read(bd_ptr_addr, 4'hf, buffer);
 
while(bd & `ETH_TX_BD_READY) begin // Buffer is ready. Don't touch !!!
repeat(100) @(posedge wb_clk_o);
i=i+1;
eth_host.wb_read(bd_status_addr, 4'hf, bd);
if(i>1000) begin
$display("(%0t)(%m)Waiting for TxBD ready to clear timeout", $time);
$stop;
end
end
 
// First write might not be word allign.
if(buffer[1:0]==1) begin
eth_host.wb_write(buffer-1, 4'h7, {8'h0, sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2});
sd=sd+3;
i=3;
end
else if(buffer[1:0]==2) begin
eth_host.wb_write(buffer-2, 4'h3, {16'h0, sd[7:0], sd[7:0]+3'h1});
sd=sd+2;
i=2;
end
else if(buffer[1:0]==3) begin
eth_host.wb_write(buffer-3, 4'h1, {24'h0, sd[7:0]});
sd=sd+1;
i=1;
end
else
i=0;
 
 
for(i=i; i<len-4; i=i+4) begin // Last 0-3 bytes are not written
eth_host.wb_write(buffer+i, 4'hf, {sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2, sd[7:0]+3'h3});
sd=sd+4;
end
// Last word
if(len-i==3)
eth_host.wb_write(buffer+i, 4'he, {sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2, 8'h0});
else if(len-i==2)
eth_host.wb_write(buffer+i, 4'hc, {sd[7:0], sd[7:0]+3'h1, 16'h0});
else if(len-i==1)
eth_host.wb_write(buffer+i, 4'h8, {sd[7:0], 24'h0});
else if(len-i==4)
eth_host.wb_write(buffer+i, 4'hf, {sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2, sd[7:0]+3'h3});
else
$display("(%0t)(%m) ERROR", $time);
 
// Checking WRAP bit
if(bd & `ETH_TX_BD_WRAP)
packet_ready_cnt = 0;
else
packet_ready_cnt = packet_ready_cnt+1;
 
// Writing len to bd
bd = bd | (len<<16);
eth_host.wb_write(bd_status_addr, 4'hf, bd);
end
endtask // set_packet
 
 
task send_packet;
 
integer bd_status_addr, bd_ptr_addr, buffer, bd;
begin
bd_status_addr = `TX_BD_BASE + send_packet_cnt * 8;
bd_ptr_addr = bd_status_addr + 4;
// Reading BD + buffer pointer
eth_host.wb_read(bd_status_addr, 4'hf, bd);
eth_host.wb_read(bd_ptr_addr, 4'hf, buffer);
 
if(bd & `ETH_TX_BD_WRAP)
send_packet_cnt=0;
else
send_packet_cnt=send_packet_cnt+1;
 
// Setting ETH_TX_BD_READY bit
bd = bd | `ETH_TX_BD_READY;
eth_host.wb_write(bd_status_addr, 4'hf, bd);
end
 
 
endtask // send_packet
 
 
task GetDataOnMRxD;
input [15:0] Len;
input [31:0] TransferType;
integer tt;
 
begin
@ (posedge mrx_clk);
#1MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge mrx_clk);
#1;
end
 
MRxD=4'hd; // SFD
for(tt=1; tt<(Len+1); tt=tt+1)
begin
@ (posedge mrx_clk);
#1;
if(TransferType == `UNICAST_XFR && tt == 1)
MRxD= 4'h0; // Unicast transfer
else if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[3:0]; // Multicast transfer
 
@ (posedge mrx_clk);
#1;
if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[7:4];
end
 
@ (posedge mrx_clk);
#1;
MRxDV=1'b0;
end
endtask // GetDataOnMRxD
 
 
endmodule
/verilog/eth_phy.v
0,0 → 1,1415
//////////////////////////////////////////////////////////////////////
//// ////
//// File name: eth_phy.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// ////
//// All additional information is available in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.6 2002/10/09 13:16:51 tadejm
// Just back-up; not completed testbench and some testcases are not
// wotking properly yet.
//
// Revision 1.5 2002/09/18 17:55:08 tadej
// Bug repaired in eth_phy device
//
// Revision 1.3 2002/09/13 14:50:15 mohor
// Bug in MIIM fixed.
//
// Revision 1.2 2002/09/13 12:29:14 mohor
// Headers changed.
//
// Revision 1.1 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
//
//
 
`include "timescale.v"
`include "eth_phy_defines.v"
`include "tb_eth_defines.v"
module eth_phy // This PHY model simulate simplified Intel LXT971A PHY
(
// COMMON
m_rst_n_i,
 
// MAC TX
mtx_clk_o,
mtxd_i,
mtxen_i,
mtxerr_i,
 
// MAC RX
mrx_clk_o,
mrxd_o,
mrxdv_o,
mrxerr_o,
 
mcoll_o,
mcrs_o,
 
// MIIM
mdc_i,
md_io,
 
// SYSTEM
phy_log
);
 
//////////////////////////////////////////////////////////////////////
//
// Input/output signals
//
//////////////////////////////////////////////////////////////////////
 
// MAC miscellaneous signals
input m_rst_n_i;
// MAC TX signals
output mtx_clk_o;
input [3:0] mtxd_i;
input mtxen_i;
input mtxerr_i;
// MAC RX signals
output mrx_clk_o;
output [3:0] mrxd_o;
output mrxdv_o;
output mrxerr_o;
// MAC common signals
output mcoll_o;
output mcrs_o;
// MAC management signals
input mdc_i;
inout md_io;
// SYSTEM
input [31:0] phy_log;
 
 
//////////////////////////////////////////////////////////////////////
//
// PHY management (MIIM) REGISTER definitions
//
//////////////////////////////////////////////////////////////////////
//
// Supported registers:
//
// Addr | Register Name
//--------------------------------------------------------------------
// 0 | Control reg. |
// 1 | Status reg. #1 |--> normal operation
// 2 | PHY ID reg. 1 |
// 3 | PHY ID reg. 2 |
//----------------------
// Addr | Data MEMORY |--> for testing
//
//--------------------------------------------------------------------
//
// Control register
reg control_bit15; // self clearing bit
reg [14:10] control_bit14_10;
reg control_bit9; // self clearing bit
reg [8:0] control_bit8_0;
// Status register
wire [15:9] status_bit15_9 = `SUPPORTED_SPEED_AND_PORT;
wire status_bit8 = `EXTENDED_STATUS;
wire status_bit7 = 1'b0; // reserved
reg [6:0] status_bit6_0;
// PHY ID register 1
wire [15:0] phy_id1 = `PHY_ID1;
// PHY ID register 2
wire [15:0] phy_id2 = {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM};
//--------------------------------------------------------------------
//
// Data MEMORY
reg [15:0] data_mem [0:31]; // 32 locations of 16-bit data width
//
//////////////////////////////////////////////////////////////////////
 
 
//////////////////////////////////////////////////////////////////////
//
// PHY clocks - RX & TX
//
//////////////////////////////////////////////////////////////////////
 
reg mtx_clk_o;
reg mrx_clk_o;
 
// random generator for a RX period when link is down
real rx_link_down_halfperiod;
 
always@(status_bit6_0[2])
begin
if (!status_bit6_0[2]) // Link is down
begin
#1 rx_link_down_halfperiod = ({$random} % 243) + 13;
`ifdef VERBOSE
#1 $fdisplay(phy_log, " (%0t)(%m)MAC RX clock is %f MHz while ethernet link is down!",
$time, (1000/(rx_link_down_halfperiod*2)) );
`endif
end
end
 
`ifdef VERBOSE
always@(status_bit6_0[2])
begin
if (!status_bit6_0[2]) // Link is down
#1 $fdisplay(phy_log, " (%0t)(%m)Ethernet link is down!", $time);
else
#1 $fdisplay(phy_log, " (%0t)(%m)Ethernet link is up!", $time);
end
`endif
 
// speed selection signal eth_speed: 1'b1 - 100 Mbps, 1'b0 - 10 Mbps
wire eth_speed;
 
assign eth_speed = ( (control_bit14_10[13]) && !((`LED_CFG1) && (`LED_CFG2)) );
 
`ifdef VERBOSE
always@(eth_speed)
begin
if (eth_speed)
#1 $fdisplay(phy_log, " (%0t)(%m)PHY configured to 100 Mbps!", $time);
else
#1 $fdisplay(phy_log, " (%0t)(%m)PHY configured tp 10 Mbps!", $time);
end
`endif
 
// different clock calculation between RX and TX, so that there is alsways a litle difference
always
begin
mtx_clk_o = 0;
#7;
forever
begin
if (eth_speed) // 100 Mbps - 25 MHz, 40 ns
begin
#20 mtx_clk_o = ~mtx_clk_o;
end
else // 10 Mbps - 2.5 MHz, 400 ns
begin
#200 mtx_clk_o = ~mtx_clk_o;
end
end
end
 
always
begin
mrx_clk_o = 1;
#3;
forever
begin
if (status_bit6_0[2]) // Link is UP
begin
if (eth_speed) // 100 Mbps - 25 MHz, 40 ns
begin
//#(((1/0.025001)/2))
#19.99 mrx_clk_o = ~mrx_clk_o; // period is calculated from frequency in GHz
end
else // 10 Mbps - 2.5 MHz, 400 ns
begin
//#(((1/0.0024999)/2))
#200.01 mrx_clk_o = ~mrx_clk_o; // period is calculated from frequency in GHz
end
end
else // Link is down
begin
#(rx_link_down_halfperiod) mrx_clk_o = ~mrx_clk_o; // random frequency between 2 MHz and 40 MHz
end
end
end
 
//////////////////////////////////////////////////////////////////////
//
// PHY management (MIIM) interface
//
//////////////////////////////////////////////////////////////////////
reg respond_to_all_phy_addr; // PHY will respond to all phy addresses
reg no_preamble; // PHY responds to frames without preamble
 
integer md_transfer_cnt; // counter countes the value of whole data transfer
reg md_transfer_cnt_reset; // for reseting the counter
reg md_io_reg; // registered input
reg md_io_output; // registered output
reg md_io_rd_wr; // op-code latched (read or write)
reg md_io_enable; // output enable
reg [4:0] phy_address; // address of PHY device
reg [4:0] reg_address; // address of a register
reg md_get_phy_address; // for shifting PHY address in
reg md_get_reg_address; // for shifting register address in
reg [15:0] reg_data_in; // data to be written in a register
reg md_get_reg_data_in; // for shifting data in
reg md_put_reg_data_in; // for storing data into a selected register
reg [15:0] reg_data_out; // data to be read from a register
reg md_put_reg_data_out; // for registering data from a selected register
 
wire [15:0] register_bus_in; // data bus to a selected register
reg [15:0] register_bus_out; // data bus from a selected register
 
initial
begin
md_io_enable = 1'b0;
respond_to_all_phy_addr = 1'b0;
no_preamble = 1'b0;
end
 
// tristate output
assign #1 md_io = (m_rst_n_i && md_io_enable) ? md_io_output : 1'bz ;
 
// registering input
always@(posedge mdc_i or negedge m_rst_n_i)
begin
if (!m_rst_n_i)
md_io_reg <= #1 0;
else
md_io_reg <= #1 md_io;
end
 
// getting (shifting) PHY address, Register address and Data in
// putting Data out and shifting
always@(posedge mdc_i or negedge m_rst_n_i)
begin
if (!m_rst_n_i)
begin
phy_address <= 0;
reg_address <= 0;
reg_data_in <= 0;
reg_data_out <= 0;
md_io_output <= 0;
end
else
begin
if (md_get_phy_address)
begin
phy_address[4:1] <= phy_address[3:0]; // correct address is `ETH_PHY_ADDR
phy_address[0] <= md_io;
end
if (md_get_reg_address)
begin
reg_address[4:1] <= reg_address[3:0];
reg_address[0] <= md_io;
end
if (md_get_reg_data_in)
begin
reg_data_in[15:1] <= reg_data_in[14:0];
reg_data_in[0] <= md_io;
end
if (md_put_reg_data_out)
begin
reg_data_out <= register_bus_out;
end
if (md_io_enable)
begin
md_io_output <= reg_data_out[15];
reg_data_out[15:1] <= reg_data_out[14:0];
reg_data_out[0] <= 1'b0;
end
end
end
 
assign #1 register_bus_in = reg_data_in; // md_put_reg_data_in - allows writing to a selected register
 
// counter for transfer to and from MIIM
always@(posedge mdc_i or negedge m_rst_n_i)
begin
if (!m_rst_n_i)
begin
if (no_preamble)
md_transfer_cnt <= 33;
else
md_transfer_cnt <= 1;
end
else
begin
if (md_transfer_cnt_reset)
begin
if (no_preamble)
md_transfer_cnt <= 33;
else
md_transfer_cnt <= 1;
end
else if (md_transfer_cnt < 64)
begin
md_transfer_cnt <= md_transfer_cnt + 1'b1;
end
else
begin
if (no_preamble)
md_transfer_cnt <= 33;
else
md_transfer_cnt <= 1;
end
end
end
 
// MIIM transfer control
always@(m_rst_n_i or md_transfer_cnt or md_io_reg or md_io_rd_wr or
phy_address or respond_to_all_phy_addr or no_preamble)
begin
#1;
while ((m_rst_n_i) && (md_transfer_cnt <= 64))
begin
// reset the signal - put registered data in the register (when write)
// check preamble
if (md_transfer_cnt < 33)
begin
#4 md_put_reg_data_in = 1'b0;
if (md_io_reg !== 1'b1)
begin
#1 md_transfer_cnt_reset = 1'b1;
end
else
begin
#1 md_transfer_cnt_reset = 1'b0;
end
end
 
// check start bits
else if (md_transfer_cnt == 33)
begin
if (no_preamble)
begin
#4 md_put_reg_data_in = 1'b0;
if (md_io_reg === 1'b0)
begin
#1 md_transfer_cnt_reset = 1'b0;
end
else
begin
#1 md_transfer_cnt_reset = 1'b1;
//if ((md_io_reg !== 1'bz) && (md_io_reg !== 1'b1))
if (md_io_reg !== 1'bz)
begin
// ERROR - start !
`ifdef VERBOSE
$fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong first start bit (without preamble)", $time);
`endif
#10 $stop;
end
end
end
else // with preamble
begin
#4 ;
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m)MIIM - 32-bit preamble received", $time);
`endif
// check start bit only if md_transfer_cnt_reset is inactive, because if
// preamble suppression was changed start bit should not be checked
if ((md_io_reg !== 1'b0) && (md_transfer_cnt_reset == 1'b0))
begin
// ERROR - start !
`ifdef VERBOSE
$fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong first start bit", $time);
`endif
#10 $stop;
end
end
end
 
else if (md_transfer_cnt == 34)
begin
#4;
if (md_io_reg !== 1'b1)
begin
// ERROR - start !
#1;
`ifdef VERBOSE
if (no_preamble)
$fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong second start bit (without preamble)", $time);
else
$fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong second start bit", $time);
`endif
#10 $stop;
end
else
begin
`ifdef VERBOSE
if (no_preamble)
#1 $fdisplay(phy_log, " (%0t)(%m)MIIM - 2 start bits received (without preamble)", $time);
else
#1 $fdisplay(phy_log, " (%0t)(%m)MIIM - 2 start bits received", $time);
`endif
end
end
 
// register the op-code (rd / wr)
else if (md_transfer_cnt == 35)
begin
#4;
if (md_io_reg === 1'b1)
begin
#1 md_io_rd_wr = 1'b1;
end
else
begin
#1 md_io_rd_wr = 1'b0;
end
end
 
else if (md_transfer_cnt == 36)
begin
#4;
if ((md_io_reg === 1'b0) && (md_io_rd_wr == 1'b1))
begin
#1 md_io_rd_wr = 1'b1; // reading from PHY registers
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m)MIIM - op-code for READING from registers", $time);
`endif
end
else if ((md_io_reg === 1'b1) && (md_io_rd_wr == 1'b0))
begin
#1 md_io_rd_wr = 1'b0; // writing to PHY registers
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m)MIIM - op-code for WRITING to registers", $time);
`endif
end
else
begin
// ERROR - wrong opcode !
`ifdef VERBOSE
#1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong OP-CODE", $time);
`endif
#10 $stop;
end
// set the signal - get PHY address
begin
#1 md_get_phy_address = 1'b1;
end
end
 
// reset the signal - get PHY address
else if (md_transfer_cnt == 41)
begin
#4 md_get_phy_address = 1'b0;
// set the signal - get register address
#1 md_get_reg_address = 1'b1;
end
 
// reset the signal - get register address
// set the signal - put register data to output register
else if (md_transfer_cnt == 46)
begin
#4 md_get_reg_address = 1'b0;
#1 md_put_reg_data_out = 1'b1;
end
 
// reset the signal - put register data to output register
// set the signal - enable md_io as output when read
else if (md_transfer_cnt == 47)
begin
#4 md_put_reg_data_out = 1'b0;
if (md_io_rd_wr) //read
begin
if (md_io_reg !== 1'bz)
begin
// ERROR - turn around !
`ifdef VERBOSE
#1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong turn-around cycle before reading data out", $time);
`endif
#10 $stop;
end
if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
begin
#1 md_io_enable = 1'b1;
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address);
`endif
end
else
begin
`ifdef VERBOSE
#1 $fdisplay(phy_log, "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address);
`endif
end
end
else // write
begin
#1 md_io_enable = 1'b0;
// check turn around cycle when write on clock 47
if (md_io_reg !== 1'b1)
begin
// ERROR - turn around !
`ifdef VERBOSE
#1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong 1. turn-around cycle before writing data in",
$time);
`endif
#10 $stop;
end
end
end
 
// set the signal - get register data in when write
else if (md_transfer_cnt == 48)
begin
#4;
if (!md_io_rd_wr) // write
begin
#1 md_get_reg_data_in = 1'b1;
// check turn around cycle when write on clock 48
if (md_io_reg !== 1'b0)
begin
// ERROR - turn around !
`ifdef VERBOSE
#1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong 2. turn-around cycle before writing data in",
$time);
`endif
#10 $stop;
end
end
else // read
begin
#1 md_get_reg_data_in = 1'b0;
end
end
 
// reset the signal - enable md_io as output when read
// reset the signal - get register data in when write
// set the signal - put registered data in the register when write
else if (md_transfer_cnt == 64)
begin
#1 md_io_enable = 1'b0;
#4 md_get_reg_data_in = 1'b0;
if (!md_io_rd_wr) // write
begin
if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
begin
#1 md_put_reg_data_in = 1'b1;
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address);
$fdisplay(phy_log, " (%0t)(%m)MIIM - WRITING to register %x COMPLETED!", $time, reg_address);
`endif
end
else
begin
`ifdef VERBOSE
#1 $fdisplay(phy_log, "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address);
$fdisplay(phy_log, "*W (%0t)(%m)MIIM - NO WRITING to register %x !", $time, reg_address);
`endif
end
end
else // read
begin
`ifdef VERBOSE
if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
#1 $fdisplay(phy_log, " (%0t)(%m)MIIM - READING from register %x COMPLETED!",
$time, reg_address);
else
#1 $fdisplay(phy_log, "*W (%0t)(%m)MIIM - NO READING from register %x !", $time, reg_address);
`endif
end
end
 
// wait for one clock period
@(posedge mdc_i)
#1;
end
end
 
//====================================================================
//
// PHY management (MIIM) REGISTERS
//
//====================================================================
//
// Supported registers (normal operation):
//
// Addr | Register Name
//--------------------------------------------------------------------
// 0 | Control reg.
// 1 | Status reg. #1
// 2 | PHY ID reg. 1
// 3 | PHY ID reg. 2
//----------------------
// Addr | Data MEMORY |--> for testing
//
//--------------------------------------------------------------------
//
// Control register
// reg control_bit15; // self clearing bit
// reg [14:10] control_bit14_10;
// reg control_bit9; // self clearing bit
// reg [8:0] control_bit8_0;
// Status register
// wire [15:9] status_bit15_9 = `SUPPORTED_SPEED_AND_PORT;
// wire status_bit8 = `EXTENDED_STATUS;
// wire status_bit7 = 1'b0; // reserved
// reg [6:0] status_bit6_0 = `DEFAULT_STATUS;
// PHY ID register 1
// wire [15:0] phy_id1 = `PHY_ID1;
// PHY ID register 2
// wire [15:0] phy_id2 = {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM};
//--------------------------------------------------------------------
//
// Data MEMORY
// reg [15:0] data_mem [0:31]; // 32 locations of 16-bit data width
//
//====================================================================
 
//////////////////////////////////////////////////////////////////////
//
// PHY management (MIIM) REGISTER control
//
//////////////////////////////////////////////////////////////////////
 
// wholy writable registers for walking ONE's on data, phy and reg. addresses
reg registers_addr_data_test_operation;
 
// Non writable status registers
always
begin
#1 status_bit6_0[6] = no_preamble;
status_bit6_0[5] = 1'b0;
status_bit6_0[3] = 1'b1;
status_bit6_0[0] = 1'b1;
end
always@(posedge mrx_clk_o)
begin
status_bit6_0[4] <= #1 1'b0;
status_bit6_0[1] <= #1 1'b0;
end
initial
begin
status_bit6_0[2] = 1'b1;
registers_addr_data_test_operation = 0;
end
 
// Reading from a selected registers
always@(reg_address or registers_addr_data_test_operation or md_put_reg_data_out or
control_bit15 or control_bit14_10 or control_bit9 or control_bit8_0 or
status_bit15_9 or status_bit8 or status_bit7 or status_bit6_0 or
phy_id1 or phy_id2)
begin
if (registers_addr_data_test_operation) // test operation
begin
if (md_put_reg_data_out) // read enable
begin
register_bus_out = #1 data_mem[reg_address];
end
end
else // normal operation
begin
if (md_put_reg_data_out) // read enable
begin
case (reg_address)
5'h0: register_bus_out = #1 {control_bit15, control_bit14_10, control_bit9, control_bit8_0};
5'h1: register_bus_out = #1 {status_bit15_9, status_bit8, status_bit7, status_bit6_0};
5'h2: register_bus_out = #1 phy_id1;
5'h3: register_bus_out = #1 phy_id2;
default: register_bus_out = #1 16'hDEAD;
endcase
end
end
end
 
// Self clear control signals
reg self_clear_d0;
reg self_clear_d1;
reg self_clear_d2;
reg self_clear_d3;
// Self clearing control
always@(posedge mdc_i or negedge m_rst_n_i)
begin
if (!m_rst_n_i)
begin
self_clear_d0 <= #1 0;
self_clear_d1 <= #1 0;
self_clear_d2 <= #1 0;
self_clear_d3 <= #1 0;
end
else
begin
self_clear_d0 <= #1 md_put_reg_data_in;
self_clear_d1 <= #1 self_clear_d0;
self_clear_d2 <= #1 self_clear_d1;
self_clear_d3 <= #1 self_clear_d2;
end
end
 
// Writing to a selected register
always@(posedge mdc_i or negedge m_rst_n_i)
begin
if ((!m_rst_n_i) || (control_bit15))
begin
if (!registers_addr_data_test_operation) // normal operation
begin
control_bit15 <= #1 0;
control_bit14_10 <= #1 {1'b0, (`LED_CFG1 || `LED_CFG2), `LED_CFG1, 2'b0};
control_bit9 <= #1 0;
control_bit8_0 <= #1 {`LED_CFG3, 8'b0};
end
end
else
begin
if (registers_addr_data_test_operation) // test operation
begin
if (md_put_reg_data_in)
begin
data_mem[reg_address] <= #1 register_bus_in[15:0];
end
end
else // normal operation
begin
// bits that are normaly written
if (md_put_reg_data_in)
begin
case (reg_address)
5'h0:
begin
control_bit14_10 <= #1 register_bus_in[14:10];
control_bit8_0 <= #1 register_bus_in[8:0];
end
default:
begin
end
endcase
end
// self cleared bits written
if ((md_put_reg_data_in) && (reg_address == 5'h0))
begin
control_bit15 <= #1 register_bus_in[15];
control_bit9 <= #1 register_bus_in[9];
end
else if (self_clear_d3) // self cleared bits cleared
begin
control_bit15 <= #1 1'b0;
control_bit9 <= #1 1'b0;
end
end
end
end
 
//////////////////////////////////////////////////////////////////////
//
// PHY <-> MAC control (RX and TX clocks are at the begining)
//
//////////////////////////////////////////////////////////////////////
 
// CARRIER SENSE & COLLISION
 
// MAC common signals
reg mcoll_o;
reg mcrs_o;
// Internal signals controling Carrier sense & Collision
// MAC common signals generated when appropriate transfer
reg mcrs_rx;
reg mcrs_tx;
// delayed mtxen_i signal for generating delayed tx carrier sense
reg mtxen_d;
// collision signal set or rest within task for controling collision
reg task_mcoll;
// carrier sense signal set or rest within task for controling carrier sense
reg task_mcrs;
reg task_mcrs_lost;
// do not generate collision in half duplex - not normal operation
reg no_collision_in_half_duplex;
// generate collision in full-duplex mode also - not normal operation
reg collision_in_full_duplex;
// do not generate carrier sense in half duplex mode - not normal operation
reg no_carrier_sense_in_tx_half_duplex;
reg no_carrier_sense_in_rx_half_duplex;
// generate carrier sense during TX in full-duplex mode also - not normal operation
reg carrier_sense_in_tx_full_duplex;
// do not generate carrier sense during RX in full-duplex mode - not normal operation
reg no_carrier_sense_in_rx_full_duplex;
// on RX: delay after carrier sense signal; on TX: carrier sense delayed (delay is one clock period)
reg real_carrier_sense;
 
initial
begin
mcrs_rx = 0;
mcrs_tx = 0;
task_mcoll = 0;
task_mcrs = 0;
task_mcrs_lost = 0;
no_collision_in_half_duplex = 0;
collision_in_full_duplex = 0;
no_carrier_sense_in_tx_half_duplex = 0;
no_carrier_sense_in_rx_half_duplex = 0;
carrier_sense_in_tx_full_duplex = 0;
no_carrier_sense_in_rx_full_duplex = 0;
real_carrier_sense = 0;
end
 
// Collision
always@(m_rst_n_i or control_bit8_0 or collision_in_full_duplex or
mcrs_rx or mcrs_tx or task_mcoll or no_collision_in_half_duplex
)
begin
if (!m_rst_n_i)
mcoll_o = 0;
else
begin
if (control_bit8_0[8]) // full duplex
begin
if (collision_in_full_duplex) // collision is usually not asserted in full duplex
begin
mcoll_o = ((mcrs_rx && mcrs_tx) || task_mcoll);
`ifdef VERBOSE
if (mcrs_rx && mcrs_tx)
$fdisplay(phy_log, " (%0t)(%m) Collision set in FullDuplex!", $time);
if (task_mcoll)
$fdisplay(phy_log, " (%0t)(%m) Collision set in FullDuplex from TASK!", $time);
`endif
end
else
begin
mcoll_o = task_mcoll;
`ifdef VERBOSE
if (task_mcoll)
$fdisplay(phy_log, " (%0t)(%m) Collision set in FullDuplex from TASK!", $time);
`endif
end
end
else // half duplex
begin
mcoll_o = ((mcrs_rx && mcrs_tx && !no_collision_in_half_duplex) ||
task_mcoll);
`ifdef VERBOSE
if (mcrs_rx && mcrs_tx)
$fdisplay(phy_log, " (%0t)(%m) Collision set in HalfDuplex!", $time);
if (task_mcoll)
$fdisplay(phy_log, " (%0t)(%m) Collision set in HalfDuplex from TASK!", $time);
`endif
end
end
end
 
// Carrier sense
always@(m_rst_n_i or control_bit8_0 or carrier_sense_in_tx_full_duplex or
no_carrier_sense_in_rx_full_duplex or
no_carrier_sense_in_tx_half_duplex or
no_carrier_sense_in_rx_half_duplex or
mcrs_rx or mcrs_tx or task_mcrs or task_mcrs_lost
)
begin
if (!m_rst_n_i)
mcrs_o = 0;
else
begin
if (control_bit8_0[8]) // full duplex
begin
if (carrier_sense_in_tx_full_duplex) // carrier sense is usually not asserted during TX in full duplex
mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_full_duplex) ||
mcrs_tx || task_mcrs) && !task_mcrs_lost;
else
mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_full_duplex) ||
task_mcrs) && !task_mcrs_lost;
end
else // half duplex
begin
mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_half_duplex) ||
(mcrs_tx && !no_carrier_sense_in_tx_half_duplex) ||
task_mcrs) && !task_mcrs_lost;
end
end
end
 
// MAC TX CONTROL (RECEIVING AT PHY)
 
// storage memory for TX data received from MAC
reg [7:0] tx_mem [0:4194303]; // 4194304 locations (22 address lines) of 8-bit data width
reg [31:0] tx_mem_addr_in; // address for storing to TX memory
reg [7:0] tx_mem_data_in; // data for storing to TX memory
reg [31:0] tx_cnt; // counts nibbles
 
// control data of a TX packet for upper layer of testbench
reg tx_preamble_ok;
reg tx_sfd_ok;
// if there is a drible nibble, then tx packet is not byte aligned!
reg tx_byte_aligned_ok;
// complete length of TX packet (Bytes) received (without preamble and SFD)
reg [31:0] tx_len;
// complete length of TX packet (Bytes) received (without preamble and SFD) untill MTxErr signal was set first
reg [31:0] tx_len_err;
 
// TX control
always@(posedge mtx_clk_o)
begin
// storing data and basic checking of frame
if (!m_rst_n_i)
begin
tx_cnt <= 0;
tx_preamble_ok <= 0;
tx_sfd_ok <= 0;
tx_len <= 0;
tx_len_err <= 0;
end
else
begin
if (!mtxen_i)
begin
tx_cnt <= 0;
end
else
begin
// tx nibble counter
tx_cnt <= tx_cnt + 1;
// set initial values and check first preamble nibble
if (tx_cnt == 0)
begin
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m) TX frame started with tx_en set!", $time);
`endif
if (mtxd_i == 4'h5)
tx_preamble_ok <= 1;
else
tx_preamble_ok <= 0;
tx_sfd_ok <= 0;
tx_byte_aligned_ok <= 0;
tx_len <= 0;
tx_len_err <= 0;
// tx_mem_addr_in <= 0;
end
 
// check preamble
if ((tx_cnt > 0) && (tx_cnt <= 13))
begin
if ((tx_preamble_ok != 1) || (mtxd_i != 4'h5))
tx_preamble_ok <= 0;
end
// check SFD
if (tx_cnt == 14)
begin
`ifdef VERBOSE
if (tx_preamble_ok == 1)
$fdisplay(phy_log, " (%0t)(%m) TX frame preamble OK!", $time);
else
$fdisplay(phy_log, "*E (%0t)(%m) TX frame preamble NOT OK!", $time);
`endif
if (mtxd_i == 4'h5)
tx_sfd_ok <= 1;
else
tx_sfd_ok <= 0;
end
if (tx_cnt == 15)
begin
if ((tx_sfd_ok != 1) || (mtxd_i != 4'hD))
tx_sfd_ok <= 0;
end
 
// control for storing addresses, type/length, data and FCS to TX memory
if (tx_cnt > 15)
begin
if (tx_cnt == 16)
begin
`ifdef VERBOSE
if (tx_sfd_ok == 1)
$fdisplay(phy_log, " (%0t)(%m) TX frame SFD OK!", $time);
else
$fdisplay(phy_log, "*E (%0t)(%m) TX frame SFD NOT OK!", $time);
`endif
end
 
if (tx_cnt[0] == 0)
begin
tx_mem_data_in[3:0] <= mtxd_i; // storing LSB nibble
tx_byte_aligned_ok <= 0; // if transfer will stop after this, then there was drible nibble
end
else
begin
tx_mem[tx_mem_addr_in[21:0]] <= {mtxd_i, tx_mem_data_in[3:0]}; // storing data into tx memory
tx_len <= tx_len + 1; // enlarge byte length counter
tx_byte_aligned_ok <= 1; // if transfer will stop after this, then transfer is byte alligned
tx_mem_addr_in <= tx_mem_addr_in + 1'b1;
end
 
if (mtxerr_i)
tx_len_err <= tx_len;
end
end
end
 
// generating CARRIER SENSE for TX with or without delay
if (!m_rst_n_i)
begin
mcrs_tx <= 0;
mtxen_d <= 0;
end
else
begin
if (!real_carrier_sense)
begin
mtxen_d <= mtxen_i;
mcrs_tx <= mtxen_i;
end
else
begin
mtxen_d <= mtxen_i;
mcrs_tx <= mtxen_d;
end
end
end
 
`ifdef VERBOSE
reg frame_started;
 
initial
begin
frame_started = 0;
end
always@(posedge mtxen_i)
begin
frame_started <= 1;
end
always@(negedge mtxen_i)
begin
if (frame_started)
begin
$fdisplay(phy_log, " (%0t)(%m) TX frame ended with tx_en reset!", $time);
frame_started <= 0;
end
end
 
always@(posedge mrxerr_o)
begin
$fdisplay(phy_log, " (%0t)(%m) RX frame ERROR signal was set!", $time);
end
`endif
 
//////////////////////////////////////////////////////////////////////
//
// Tasks for PHY <-> MAC transactions
//
//////////////////////////////////////////////////////////////////////
 
initial
begin
tx_mem_addr_in = 0;
end
 
// setting the address of tx_mem, to set the starting point of tx packet
task set_tx_mem_addr;
input [31:0] tx_mem_address;
begin
#1 tx_mem_addr_in = tx_mem_address;
end
endtask // set_tx_mem_addr
 
// storage memory for RX data to be transmited to MAC
reg [7:0] rx_mem [0:4194303]; // 4194304 locations (22 address lines) of 8-bit data width
 
// MAC RX signals
reg [3:0] mrxd_o;
reg mrxdv_o;
reg mrxerr_o;
 
initial
begin
mrxd_o = 0;
mrxdv_o = 0;
mrxerr_o = 0;
mcrs_rx = 0;
end
 
task send_rx_packet;
input [(8*8)-1:0] preamble_data; // preamble data to be sent - correct is 64'h0055_5555_5555_5555
input [3:0] preamble_len; // length of preamble in bytes - max is 4'h8, correct is 4'h7
input [7:0] sfd_data; // SFD data to be sent - correct is 8'hD5
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes (without preamble and SFD)
input plus_drible_nibble; // if length is longer for one nibble
integer rx_cnt;
reg [31:0] rx_mem_addr_in; // address for reading from RX memory
reg [7:0] rx_mem_data_out; // data for reading from RX memory
begin
@(posedge mrx_clk_o);
// generating CARRIER SENSE for TX with or without delay
if (real_carrier_sense)
#1 mcrs_rx = 1;
else
#1 mcrs_rx = 0;
@(posedge mrx_clk_o);
#1 mcrs_rx = 1;
#1 mrxdv_o = 1;
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m) RX frame started with rx_dv set!", $time);
`endif
// set initial rx memory address
rx_mem_addr_in = start_addr;
// send preamble
for (rx_cnt = 0; (rx_cnt < (preamble_len << 1)) && (rx_cnt < 16); rx_cnt = rx_cnt + 1)
begin
#1 mrxd_o = preamble_data[3:0];
#1 preamble_data = preamble_data >> 4;
@(posedge mrx_clk_o);
end
// send SFD
for (rx_cnt = 0; rx_cnt < 2; rx_cnt = rx_cnt + 1)
begin
#1 mrxd_o = sfd_data[3:0];
#1 sfd_data = sfd_data >> 4;
@(posedge mrx_clk_o);
end
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m) RX frame preamble and SFD sent!", $time);
`endif
// send packet's addresses, type/length, data and FCS
for (rx_cnt = 0; rx_cnt < len; rx_cnt = rx_cnt + 1)
begin
#1;
rx_mem_data_out = rx_mem[rx_mem_addr_in[21:0]];
mrxd_o = rx_mem_data_out[3:0];
@(posedge mrx_clk_o);
#1;
mrxd_o = rx_mem_data_out[7:4];
rx_mem_addr_in = rx_mem_addr_in + 1;
@(posedge mrx_clk_o);
#1;
end
if (plus_drible_nibble)
begin
rx_mem_data_out = rx_mem[rx_mem_addr_in[21:0]];
mrxd_o = rx_mem_data_out[3:0];
@(posedge mrx_clk_o);
end
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m) RX frame addresses, type/length, data and FCS sent!", $time);
`endif
#1 mcrs_rx = 0;
#1 mrxdv_o = 0;
@(posedge mrx_clk_o);
`ifdef VERBOSE
$fdisplay(phy_log, " (%0t)(%m) RX frame ended with rx_dv reset!", $time);
`endif
end
endtask // send_rx_packet
 
 
 
task GetDataOnMRxD;
input [15:0] Len;
input [31:0] TransferType;
integer tt;
 
begin
@ (posedge mrx_clk_o);
#1 mrxdv_o=1'b1;
 
for(tt=0; tt<15; tt=tt+1)
begin
mrxd_o=4'h5; // preamble
@ (posedge mrx_clk_o);
#1;
end
 
mrxd_o=4'hd; // SFD
 
for(tt=1; tt<(Len+1); tt=tt+1)
begin
@ (posedge mrx_clk_o);
#1;
if(TransferType == `UNICAST_XFR && tt == 1)
mrxd_o = 4'h0; // Unicast transfer
else if(TransferType == `BROADCAST_XFR && tt < 7)
mrxd_o = 4'hf;
else
mrxd_o = tt[3:0]; // Multicast transfer
 
@ (posedge mrx_clk_o);
#1;
 
if(TransferType == `BROADCAST_XFR && tt == 6)
mrxd_o = 4'he;
else
 
if(TransferType == `BROADCAST_XFR && tt < 7)
mrxd_o = 4'hf;
else
mrxd_o = tt[7:4];
end
 
@ (posedge mrx_clk_o);
#1;
mrxdv_o = 1'b0;
end
endtask // GetDataOnMRxD
 
 
//////////////////////////////////////////////////////////////////////
//
// Tastks for controling PHY statuses and rx error
//
//////////////////////////////////////////////////////////////////////
 
// Link control tasks
task link_up_down;
input test_op;
begin
#1 status_bit6_0[2] = test_op; // 1 - link up; 0 - link down
end
endtask
 
// RX error
task rx_err;
input test_op;
begin
#1 mrxerr_o = test_op; // 1 - RX error set; 0 - RX error reset
end
endtask
 
//////////////////////////////////////////////////////////////////////
//
// Tastks for controling PHY carrier sense and collision
//
//////////////////////////////////////////////////////////////////////
 
// Collision
task collision;
input test_op;
begin
#1 task_mcoll = test_op;
end
endtask
 
// Carrier sense
task carrier_sense;
input test_op;
begin
#1 task_mcrs = test_op;
end
endtask
 
// Carrier sense lost - higher priority than Carrier sense task
task carrier_sense_lost;
input test_op;
begin
#1 task_mcrs_lost = test_op;
end
endtask
 
// No collision detection in half duplex
task no_collision_hd_detect;
input test_op;
begin
#1 no_collision_in_half_duplex = test_op;
end
endtask
 
// Collision detection in full duplex also
task collision_fd_detect;
input test_op;
begin
#1 collision_in_full_duplex = test_op;
end
endtask
 
// No carrier sense detection at TX in half duplex
task no_carrier_sense_tx_hd_detect;
input test_op;
begin
#1 no_carrier_sense_in_tx_half_duplex = test_op;
end
endtask
 
// No carrier sense detection at RX in half duplex
task no_carrier_sense_rx_hd_detect;
input test_op;
begin
#1 no_carrier_sense_in_rx_half_duplex = test_op;
end
endtask
 
// Carrier sense detection at TX in full duplex also
task carrier_sense_tx_fd_detect;
input test_op;
begin
#1 carrier_sense_in_tx_full_duplex = test_op;
end
endtask
 
// No carrier sense detection at RX in full duplex
task no_carrier_sense_rx_fd_detect;
input test_op;
begin
#1 no_carrier_sense_in_rx_full_duplex = test_op;
end
endtask
 
// Set real delay on carrier sense signal (and therefor collision signal)
task carrier_sense_real_delay;
input test_op;
begin
#1 real_carrier_sense = test_op;
end
endtask
 
//////////////////////////////////////////////////////////////////////
//
// Tastks for controling PHY management test operation
//
//////////////////////////////////////////////////////////////////////
 
// Set registers to test operation and respond to all phy addresses
task test_regs;
input test_op;
begin
#1 registers_addr_data_test_operation = test_op;
respond_to_all_phy_addr = test_op;
end
endtask
 
// Clears data memory for testing the MII
task clear_test_regs;
integer i;
begin
for (i = 0; i < 32; i = i + 1)
begin
#1 data_mem[i] = 16'h0;
end
end
endtask
 
// Accept frames with preamble suppresed
task preamble_suppresed;
input test_op;
begin
#1 no_preamble = test_op;
md_transfer_cnt_reset = 1'b1;
@(posedge mdc_i);
#1 md_transfer_cnt_reset = 1'b0;
end
endtask
 
 
 
 
 
endmodule
 
/verilog/tb_eth_defines.v
0,0 → 1,209
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is available in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.8 2002/09/13 18:41:45 mohor
// Rearanged testcases
//
// Revision 1.7 2002/09/13 12:29:14 mohor
// Headers changed.
//
// Revision 1.6 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
// Revision 1.3 2002/07/19 13:57:53 mohor
// Testing environment also includes traffic cop, memory interface and host
// interface.
//
// Revision 1.2 2002/05/03 10:22:17 mohor
// TX_BUF_BASE changed.
//
// Revision 1.1 2002/03/19 12:53:54 mohor
// Some defines that are used in testbench only were moved to tb_eth_defines.v
// file.
//
//
//
//
 
 
 
//`define VERBOSE // if log files of device modules are written
 
`define MULTICAST_XFR 0
`define UNICAST_XFR 1
`define BROADCAST_XFR 2
`define UNICAST_WRONG_XFR 3
 
`define ETH_BASE 32'hd0000000
`define ETH_WIDTH 32'h800
`define MEMORY_BASE 32'h2000
`define MEMORY_WIDTH 32'h10000
`define TX_BUF_BASE `MEMORY_BASE
`define RX_BUF_BASE `MEMORY_BASE + 32'h8000
`define TX_BD_BASE `ETH_BASE + 32'h00000400
`define RX_BD_BASE `ETH_BASE + 32'h00000600
 
`define M1_ADDRESSED_S1 ( (m1_wb_adr_i >= `ETH_BASE) & (m1_wb_adr_i < (`ETH_BASE + `ETH_WIDTH )) )
`define M1_ADDRESSED_S2 ( (m1_wb_adr_i >= `MEMORY_BASE) & (m1_wb_adr_i < (`MEMORY_BASE + `MEMORY_WIDTH)) )
`define M2_ADDRESSED_S1 ( (m2_wb_adr_i >= `ETH_BASE) & (m2_wb_adr_i < (`ETH_BASE + `ETH_WIDTH )) )
`define M2_ADDRESSED_S2 ( (m2_wb_adr_i >= `MEMORY_BASE) & (m2_wb_adr_i < (`MEMORY_BASE + `MEMORY_WIDTH)) )
 
 
 
/* Tx BD */
`define ETH_TX_BD_READY 32'h8000 /* Tx BD Ready */
`define ETH_TX_BD_IRQ 32'h4000 /* Tx BD IRQ Enable */
`define ETH_TX_BD_WRAP 32'h2000 /* Tx BD Wrap (last BD) */
`define ETH_TX_BD_PAD 32'h1000 /* Tx BD Pad Enable */
`define ETH_TX_BD_CRC 32'h0800 /* Tx BD CRC Enable */
 
`define ETH_TX_BD_UNDERRUN 32'h0100 /* Tx BD Underrun Status */
`define ETH_TX_BD_RETRY 32'h00F0 /* Tx BD Retry Status */
`define ETH_TX_BD_RETLIM 32'h0008 /* Tx BD Retransmission Limit Status */
`define ETH_TX_BD_LATECOL 32'h0004 /* Tx BD Late Collision Status */
`define ETH_TX_BD_DEFER 32'h0002 /* Tx BD Defer Status */
`define ETH_TX_BD_CARRIER 32'h0001 /* Tx BD Carrier Sense Lost Status */
 
/* Rx BD */
`define ETH_RX_BD_EMPTY 32'h8000 /* Rx BD Empty */
`define ETH_RX_BD_IRQ 32'h4000 /* Rx BD IRQ Enable */
`define ETH_RX_BD_WRAP 32'h2000 /* Rx BD Wrap (last BD) */
 
`define ETH_RX_BD_MISS 32'h0080 /* Rx BD Miss Status */
`define ETH_RX_BD_OVERRUN 32'h0040 /* Rx BD Overrun Status */
`define ETH_RX_BD_INVSIMB 32'h0020 /* Rx BD Invalid Symbol Status */
`define ETH_RX_BD_DRIBBLE 32'h0010 /* Rx BD Dribble Nibble Status */
`define ETH_RX_BD_TOOLONG 32'h0008 /* Rx BD Too Long Status */
`define ETH_RX_BD_SHORT 32'h0004 /* Rx BD Too Short Frame Status */
`define ETH_RX_BD_CRCERR 32'h0002 /* Rx BD CRC Error Status */
`define ETH_RX_BD_LATECOL 32'h0001 /* Rx BD Late Collision Status */
 
 
 
/* Register space */
`define ETH_MODER `ETH_BASE + 32'h00 /* Mode Register */
`define ETH_INT `ETH_BASE + 32'h04 /* Interrupt Source Register */
`define ETH_INT_MASK `ETH_BASE + 32'h08 /* Interrupt Mask Register */
`define ETH_IPGT `ETH_BASE + 32'h0C /* Back to Bak Inter Packet Gap Register */
`define ETH_IPGR1 `ETH_BASE + 32'h10 /* Non Back to Back Inter Packet Gap Register 1 */
`define ETH_IPGR2 `ETH_BASE + 32'h14 /* Non Back to Back Inter Packet Gap Register 2 */
`define ETH_PACKETLEN `ETH_BASE + 32'h18 /* Packet Length Register (min. and max.) */
`define ETH_COLLCONF `ETH_BASE + 32'h1C /* Collision and Retry Configuration Register */
`define ETH_TX_BD_NUM `ETH_BASE + 32'h20 /* Transmit Buffer Descriptor Number Register */
`define ETH_CTRLMODER `ETH_BASE + 32'h24 /* Control Module Mode Register */
`define ETH_MIIMODER `ETH_BASE + 32'h28 /* MII Mode Register */
`define ETH_MIICOMMAND `ETH_BASE + 32'h2C /* MII Command Register */
`define ETH_MIIADDRESS `ETH_BASE + 32'h30 /* MII Address Register */
`define ETH_MIITX_DATA `ETH_BASE + 32'h34 /* MII Transmit Data Register */
`define ETH_MIIRX_DATA `ETH_BASE + 32'h38 /* MII Receive Data Register */
`define ETH_MIISTATUS `ETH_BASE + 32'h3C /* MII Status Register */
`define ETH_MAC_ADDR0 `ETH_BASE + 32'h40 /* MAC Individual Address Register 0 */
`define ETH_MAC_ADDR1 `ETH_BASE + 32'h44 /* MAC Individual Address Register 1 */
`define ETH_HASH_ADDR0 `ETH_BASE + 32'h48 /* Hash Register 0 */
`define ETH_HASH_ADDR1 `ETH_BASE + 32'h4C /* Hash Register 1 */
`define ETH_TX_CTRL `ETH_BASE + 32'h50 /* Tx Control Register */
 
 
/* MODER Register */
`define ETH_MODER_RXEN 32'h00000001 /* Receive Enable */
`define ETH_MODER_TXEN 32'h00000002 /* Transmit Enable */
`define ETH_MODER_NOPRE 32'h00000004 /* No Preamble */
`define ETH_MODER_BRO 32'h00000008 /* Reject Broadcast */
`define ETH_MODER_IAM 32'h00000010 /* Use Individual Hash */
`define ETH_MODER_PRO 32'h00000020 /* Promiscuous (receive all) */
`define ETH_MODER_IFG 32'h00000040 /* Min. IFG not required */
`define ETH_MODER_LOOPBCK 32'h00000080 /* Loop Back */
`define ETH_MODER_NOBCKOF 32'h00000100 /* No Backoff */
`define ETH_MODER_EXDFREN 32'h00000200 /* Excess Defer */
`define ETH_MODER_FULLD 32'h00000400 /* Full Duplex */
`define ETH_MODER_RST 32'h00000800 /* Reset MAC */
`define ETH_MODER_DLYCRCEN 32'h00001000 /* Delayed CRC Enable */
`define ETH_MODER_CRCEN 32'h00002000 /* CRC Enable */
`define ETH_MODER_HUGEN 32'h00004000 /* Huge Enable */
`define ETH_MODER_PAD 32'h00008000 /* Pad Enable */
`define ETH_MODER_RECSMALL 32'h00010000 /* Receive Small */
 
/* Interrupt Source Register */
`define ETH_INT_TXB 32'h00000001 /* Transmit Buffer IRQ */
`define ETH_INT_TXE 32'h00000002 /* Transmit Error IRQ */
`define ETH_INT_RXB 32'h00000004 /* Receive Buffer IRQ */
`define ETH_INT_RXE 32'h00000008 /* Receive Error IRQ */
`define ETH_INT_BUSY 32'h00000010 /* Busy IRQ */
`define ETH_INT_TXC 32'h00000020 /* Transmit Control Frame IRQ */
`define ETH_INT_RXC 32'h00000040 /* Received Control Frame IRQ */
 
/* Interrupt Mask Register */
`define ETH_INT_MASK_TXB 32'h00000001 /* Transmit Buffer IRQ Mask */
`define ETH_INT_MASK_TXE 32'h00000002 /* Transmit Error IRQ Mask */
`define ETH_INT_MASK_RXF 32'h00000004 /* Receive Frame IRQ Mask */
`define ETH_INT_MASK_RXE 32'h00000008 /* Receive Error IRQ Mask */
`define ETH_INT_MASK_BUSY 32'h00000010 /* Busy IRQ Mask */
`define ETH_INT_MASK_TXC 32'h00000020 /* Transmit Control Frame IRQ Mask */
`define ETH_INT_MASK_RXC 32'h00000040 /* Received Control Frame IRQ Mask */
 
/* Control Module Mode Register */
`define ETH_CTRLMODER_PASSALL 32'h00000001 /* Pass Control Frames */
`define ETH_CTRLMODER_RXFLOW 32'h00000002 /* Receive Control Flow Enable */
`define ETH_CTRLMODER_TXFLOW 32'h00000004 /* Transmit Control Flow Enable */
 
/* MII Mode Register */
`define ETH_MIIMODER_CLKDIV 32'h000000FF /* Clock Divider */
`define ETH_MIIMODER_NOPRE 32'h00000100 /* No Preamble */
`define ETH_MIIMODER_RST 32'h00000200 /* MIIM Reset */
 
/* MII Command Register */
`define ETH_MIICOMMAND_SCANSTAT 32'h00000001 /* Scan Status */
`define ETH_MIICOMMAND_RSTAT 32'h00000002 /* Read Status */
`define ETH_MIICOMMAND_WCTRLDATA 32'h00000004 /* Write Control Data */
 
/* MII Address Register */
`define ETH_MIIADDRESS_FIAD 32'h0000001F /* PHY Address */
`define ETH_MIIADDRESS_RGAD 32'h00001F00 /* RGAD Address */
 
/* MII Status Register */
`define ETH_MIISTATUS_LINKFAIL 0 /* Link Fail bit */
`define ETH_MIISTATUS_BUSY 1 /* MII Busy bit */
`define ETH_MIISTATUS_NVALID 2 /* Data in MII Status Register is invalid bit */
 
 
`define TIME $display(" Time: %0t", $time)
/verilog/wb_bus_mon.v
0,0 → 1,401
//////////////////////////////////////////////////////////////////////
//// ////
//// File name "wb_bus_mon.v" ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Miha Dolenc (mihad@opencores.org) ////
//// ////
//// All additional information is available in the README.pdf ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/09/13 12:29:14 mohor
// Headers changed.
//
// Revision 1.1 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
// Revision 1.1 2002/02/01 13:39:43 mihad
// Initial testbench import. Still under development
//
// Revision 1.1 2001/08/06 18:12:58 mihad
// Pocasi delamo kompletno zadevo
//
//
 
`include "timescale.v"
`include "wb_model_defines.v"
// WISHBONE bus monitor module - it connects to WISHBONE master signals and
// monitors for any illegal combinations appearing on the bus.
module WB_BUS_MON(
CLK_I,
RST_I,
ACK_I,
ADDR_O,
CYC_O,
DAT_I,
DAT_O,
ERR_I,
RTY_I,
SEL_O,
STB_O,
WE_O,
TAG_I,
TAG_O,
CAB_O,
log_file_desc
) ;
 
input CLK_I ;
input RST_I ;
input ACK_I ;
input [(`WB_ADDR_WIDTH-1):0] ADDR_O ;
input CYC_O ;
input [(`WB_DATA_WIDTH-1):0] DAT_I ;
input [(`WB_DATA_WIDTH-1):0] DAT_O ;
input ERR_I ;
input RTY_I ;
input [(`WB_SEL_WIDTH-1):0] SEL_O ;
input STB_O ;
input WE_O ;
input [(`WB_TAG_WIDTH-1):0] TAG_I ;
input [(`WB_TAG_WIDTH-1):0] TAG_O ;
input CAB_O ;
input [31:0] log_file_desc ;
 
always@(posedge CLK_I or posedge RST_I)
begin
if (RST_I)
begin
// when reset is applied, all control signals must be low
if (CYC_O)
begin
$display("*E (%0t) CYC_O active under reset", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)CYC_O active under reset", $time) ;
end
if (STB_O)
begin
$display("*E (%0t) STB_O active under reset", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)STB_O active under reset", $time) ;
end
/*if (ACK_I)
$display("ACK_I active under reset") ;*/
if (ERR_I)
begin
$display("*E (%0t) ERR_I active under reset", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)ERR_I active under reset", $time) ;
end
if (RTY_I)
begin
$display("*E (%0t) RTY_I active under reset", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)RTY_I active under reset", $time) ;
end
if (CAB_O)
begin
$display("*E (%0t) CAB_O active under reset", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)CAB_O active under reset", $time) ;
end
end // reset
else
if (~CYC_O)
begin
// when cycle indicator is low, all control signals must be low
if (STB_O)
begin
$display("*E (%0t) STB_O active without CYC_O being active", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)STB_O active without CYC_O being active", $time) ;
end
if (ACK_I)
begin
$display("*E (%0t) ACK_I active without CYC_O being active", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)ACK_I active without CYC_O being active", $time) ;
end
if (ERR_I)
begin
$display("*E (%0t) ERR_I active without CYC_O being active", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)ERR_I active without CYC_O being active", $time) ;
end
if (RTY_I)
begin
$display("*E (%0t) RTY_I active without CYC_O being active", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)RTY_I active without CYC_O being active", $time) ;
end
if (CAB_O)
begin
$display("*E (%0t) CAB_O active without CYC_O being active", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)CAB_O active without CYC_O being active", $time) ;
end
end // ~CYC_O
end
 
reg [`WB_DATA_WIDTH-1:0] previous_data ;
reg [`WB_ADDR_WIDTH-1:0] previous_address ;
reg [`WB_SEL_WIDTH-1:0] previous_sel ;
reg previous_stb ;
reg previous_ack ;
reg previous_err ;
reg previous_rty ;
reg previous_cyc ;
reg can_change ;
 
always@(posedge CLK_I or posedge RST_I)
begin
if (RST_I)
begin
previous_stb <= 1'b0 ;
previous_ack <= 1'b0 ;
previous_err <= 1'b0 ;
previous_rty <= 1'b0 ;
previous_cyc <= 1'b0 ;
end
else
begin
previous_stb <= STB_O ;
previous_ack <= ACK_I ;
previous_err <= ERR_I ;
previous_rty <= RTY_I ;
previous_cyc <= CYC_O ;
end
end
 
// cycle monitor
always@(posedge CLK_I)
begin
if (CYC_O && ~RST_I) // cycle in progress
begin
if (STB_O)
begin
// check for two control signals active at same edge
if ( ACK_I && RTY_I )
begin
$display("*E (%0t) ACK_I and RTY_I asserted at the same time during cycle", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)ACK_I and RTY_I asserted at the same time during cycle", $time) ;
end
if ( ACK_I && ERR_I )
begin
$display("*E (%0t) ACK_I and ERR_I asserted at the same time during cycle", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)ACK_I and ERR_I asserted at the same time during cycle", $time) ;
end
if ( RTY_I && ERR_I )
begin
$display("*E (%0t) RTY_I and ERR_I asserted at the same time during cycle", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)RTY_I and ERR_I asserted at the same time during cycle", $time) ;
end
 
if ( can_change !== 1 )
begin
if ( ADDR_O !== previous_address )
begin
$display("*E (%0t) WB bus monitor detected address change in the middle of the cycle!", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)WB bus monitor detected address change in the middle of the cycle!", $time) ;
end
 
if ( SEL_O !== previous_sel )
begin
$display("*E (%0t) WB bus monitor detected select lines changed in the middle of the cycle!", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)WB bus monitor detected select lines changed in the middle of the cycle!", $time) ;
end
 
if ( (WE_O !== 0) && ( DAT_O !== previous_data ) )
begin
$display("*E (%0t) WB bus monitor detected data lines changed in the middle of the cycle!", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)WB bus monitor detected data lines changed in the middle of the cycle!", $time) ;
end
end
 
if ( ACK_I || RTY_I || ERR_I )
can_change = 1 ;
else
begin
previous_data = DAT_O ;
previous_address = ADDR_O ;
previous_sel = SEL_O ;
can_change = 0 ;
end
 
end // STB_O
else
begin //~STB_O
// while STB_O is inactive, only ACK_I is allowed to be active
if ( ERR_I )
begin
$display("*E (%0t) ERR_I asserted during cycle without STB_O", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)ERR_I asserted during cycle without STB_O", $time) ;
end
if ( RTY_I )
begin
$display("*E (%0t) RTY_I asserted during cycle without STB_O", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)RTY_I asserted during cycle without STB_O", $time) ;
end
 
if ((previous_ack !== 1) && (previous_err !== 1) && (previous_rty !== 1) && (previous_stb !== 0))
begin
$display("STB_O de-asserted without reception of slave response") ;
$fdisplay(log_file_desc, "STB_O de-asserted without reception of slave response") ;
end
 
can_change = 1 ;
end // ~STB_O
end // cycle in progress
else if (!RST_I)
begin
// cycle not in progress anymore
can_change = 1 ;
if ((previous_ack !== 1) && (previous_err !== 1) && (previous_rty !== 1) && (previous_stb !== 0))
begin
$display("STB_O de-asserted without reception of slave response") ;
$fdisplay(log_file_desc, "STB_O de-asserted without reception of slave response") ;
end
end
end // cycle monitor
 
// CAB_O monitor - CAB_O musn't change during one cycle
reg [1:0] first_cab_val ;
always@(posedge CLK_I or RST_I)
begin
if ((CYC_O === 0) || RST_I)
first_cab_val <= 2'b00 ;
else
begin
// cycle in progress - is this first clock edge in a cycle ?
if (first_cab_val[1] === 1'b0)
first_cab_val <= {1'b1, CAB_O} ;
else if ( first_cab_val[0] !== CAB_O )
begin
$display("*E (%0t) CAB_O value changed during cycle", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)CAB_O value changed during cycle", $time) ;
end
end
end // CAB_O monitor
 
// WE_O monitor for consecutive address bursts
reg [1:0] first_we_val ;
always@(posedge CLK_I or posedge RST_I)
begin
if (~CYC_O || ~CAB_O || RST_I)
first_we_val <= 2'b00 ;
else
if (STB_O)
begin
// cycle in progress - is this first clock edge in a cycle ?
if (first_we_val[1] == 1'b0)
first_we_val <= {1'b1, WE_O} ;
else if ( first_we_val[0] != WE_O )
begin
$display("*E (%0t) WE_O value changed during CAB cycle", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)WE_O value changed during CAB cycle", $time) ;
end
end
end // CAB_O monitor
 
// address monitor for consecutive address bursts
reg [`WB_ADDR_WIDTH:0] address ;
always@(posedge CLK_I or posedge RST_I)
begin
if (~CYC_O || ~CAB_O || RST_I)
address <= {(`WB_ADDR_WIDTH + 1){1'b0}} ;
else
begin
if (STB_O && ACK_I)
begin
if (address[`WB_ADDR_WIDTH] == 1'b0)
address <= {1'b1, (ADDR_O + `WB_SEL_WIDTH)} ;
else
begin
if ( address[(`WB_ADDR_WIDTH-1):0] != ADDR_O)
begin
$display("*E (%0t) Consecutive address burst address incrementing incorrect", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)Consecutive address burst address incrementing incorrect", $time) ;
end
else
address <= {1'b1, (ADDR_O + `WB_SEL_WIDTH)} ;
end
end
end
end // address monitor
 
// data monitor
always@(posedge CLK_I or posedge RST_I)
begin
if (CYC_O && STB_O && ~RST_I)
begin
if ( ((^ADDR_O) !== 1'b1) && ((^ADDR_O) !== 1'b0) )
begin
$display("*E (%0t) Master provided invalid address and qualified it with STB_O", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)Master provided invalid address and qualified it with STB_O", $time) ;
end
if ( WE_O )
begin
if (
(SEL_O[0] && (((^DAT_O[7:0]) !== 1'b0) && ((^DAT_O[7:0]) !== 1'b1))) ||
(SEL_O[1] && (((^DAT_O[15:8]) !== 1'b0) && ((^DAT_O[15:8]) !== 1'b1))) ||
(SEL_O[2] && (((^DAT_O[23:16]) !== 1'b0) && ((^DAT_O[23:16]) !== 1'b1))) ||
(SEL_O[3] && (((^DAT_O[31:24]) !== 1'b0) && ((^DAT_O[31:24]) !== 1'b1)))
)
begin
$display("*E (%0t) Master provided invalid data during write and qualified it with STB_O", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)Master provided invalid data during write and qualified it with STB_O", $time) ;
$display("*E (%0t) Byte select value: SEL_O = %b, Data bus value: DAT_O = %h ", $time, SEL_O, DAT_O) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)Byte select value: SEL_O = %b, Data bus value: DAT_O = %h ", $time, SEL_O, DAT_O) ;
end
 
end
else
if (~WE_O && ACK_I)
begin
if (
(SEL_O[0] && (((^DAT_I[7:0]) !== 1'b0) && ((^DAT_I[7:0]) !== 1'b1))) ||
(SEL_O[1] && (((^DAT_I[15:8]) !== 1'b0) && ((^DAT_I[15:8]) !== 1'b1))) ||
(SEL_O[2] && (((^DAT_I[23:16]) !== 1'b0) && ((^DAT_I[23:16]) !== 1'b1))) ||
(SEL_O[3] && (((^DAT_I[31:24]) !== 1'b0) && ((^DAT_I[31:24]) !== 1'b1)))
)
begin
$display("*E (%0t) Slave provided invalid data during read and qualified it with ACK_I", $time) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)Slave provided invalid data during read and qualified it with ACK_I", $time) ;
$display("*E (%0t) Byte select value: SEL_O = %b, Data bus value: DAT_I = %h ", $time, SEL_O, DAT_I) ;
$fdisplay(log_file_desc, "*E (%0t)(%m)Byte select value: SEL_O = %b, Data bus value: DAT_I = %h ", $time, SEL_O, DAT_I) ;
end
end
end
end
 
initial
begin
previous_data = 0 ;
previous_address = 0 ;
can_change = 1 ;
end
endmodule // BUS_MON
/verilog/eth_phy_defines.v
0,0 → 1,90
//////////////////////////////////////////////////////////////////////
//// ////
//// File name: eth_phy_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// ////
//// All additional information is available in the README.txt ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002, Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
//
//
 
// Address of PHY device (LXT971A)
`define ETH_PHY_ADDR 5'h01
 
// LED/Configuration pins on PHY device - see the specification, page 26, table 8
// Initial set of bits 13, 12 and 8 of Control Register
`define LED_CFG1 1'b0
`define LED_CFG2 1'b0
`define LED_CFG3 1'b1
 
// Supported speeds and physical ports - see the specification, page 67, table 41
// Set bits 15 to 9 of Status Register
`define SUPPORTED_SPEED_AND_PORT 7'h3F
 
// Extended status register (address 15)
// Set bit 8 of Status Register
`define EXTENDED_STATUS 1'b0
 
// Default status bits - see the specification, page 67, table 41
// Set bits 6 to 0 of Status Register
`define DEFAULT_STATUS 7'h09
 
// PHY ID 1 number - see the specification, page 68, table 42
// Set bits of Phy Id Register 1
`define PHY_ID1 16'h0013
 
// PHY ID 2 number - see the specification, page 68, table 43
// Set bits 15 to 10 of Phy Id Register 2
`define PHY_ID2 6'h1E
 
// Manufacturer MODEL number - see the specification, page 68, table 43
// Set bits 9 to 4 of Phy Id Register 2
`define MAN_MODEL_NUM 6'h0E
 
// Manufacturer REVISION number - see the specification, page 68, table 43
// Set bits 3 to 0 of Phy Id Register 2
`define MAN_REVISION_NUM 4'h2
 
 
 
 
/verilog/wb_slave_behavioral.v
0,0 → 1,410
//////////////////////////////////////////////////////////////////////
//// ////
//// File name: wb_slave_behavioral.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// ////
//// All additional information is available in the README.txt ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Tadej Markovic, tadej@opencores.org ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1 2002/09/13 11:57:21 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
// Revision 1.2 2002/03/06 09:10:56 mihad
// Added missing include statements
//
// Revision 1.1 2002/02/01 13:39:43 mihad
// Initial testbench import. Still under development
//
//
 
`include "timescale.v"
`include "wb_model_defines.v"
module WB_SLAVE_BEHAVIORAL
(
CLK_I,
RST_I,
ACK_O,
ADR_I,
CYC_I,
DAT_O,
DAT_I,
ERR_O,
RTY_O,
SEL_I,
STB_I,
WE_I,
CAB_I
);
 
/*------------------------------------------------------------------------------------------------------
WISHBONE signals
------------------------------------------------------------------------------------------------------*/
input CLK_I;
input RST_I;
output ACK_O;
input `WB_ADDR_TYPE ADR_I;
input CYC_I;
output `WB_DATA_TYPE DAT_O;
input `WB_DATA_TYPE DAT_I;
output ERR_O;
output RTY_O;
input `WB_SEL_TYPE SEL_I;
input STB_I;
input WE_I;
input CAB_I;
 
reg `WB_DATA_TYPE DAT_O;
 
/*------------------------------------------------------------------------------------------------------
Asynchronous dual-port RAM signals for storing and fetching the data
------------------------------------------------------------------------------------------------------*/
//reg `WB_DATA_TYPE wb_memory [0:16777215]; // WB memory - 24 addresses connected - 2 LSB not used
reg `WB_DATA_TYPE wb_memory [0:1048575]; // WB memory - 20 addresses connected - 2 LSB not used
reg `WB_DATA_TYPE mem_wr_data_out;
reg `WB_DATA_TYPE mem_rd_data_in;
 
/*------------------------------------------------------------------------------------------------------
Maximum values for WAIT and RETRY counters and which response !!!
------------------------------------------------------------------------------------------------------*/
reg [2:0] a_e_r_resp; // tells with which cycle_termination_signal must wb_slave respond !
reg [3:0] wait_cyc;
reg [7:0] max_retry;
 
// assign registers to default state while in reset
always@(RST_I)
begin
if (RST_I)
begin
a_e_r_resp <= 3'b000; // do not respond
wait_cyc <= 4'b0; // no wait cycles
max_retry <= 8'h0; // no retries
end
end //reset
 
task cycle_response;
input [2:0] ack_err_rty_resp; // acknowledge, error or retry response input flags
input [3:0] wait_cycles; // if wait cycles before each data termination cycle (ack, err or rty)
input [7:0] retry_cycles; // noumber of retry cycles before acknowledge cycle
begin
// assign values
a_e_r_resp <= #1 ack_err_rty_resp;
wait_cyc <= #1 wait_cycles;
max_retry <= #1 retry_cycles;
end
endtask // cycle_response
 
/*------------------------------------------------------------------------------------------------------
Tasks for writing and reading to and from memory !!!
------------------------------------------------------------------------------------------------------*/
reg `WB_ADDR_TYPE task_wr_adr_i;
reg `WB_ADDR_TYPE task_rd_adr_i;
reg `WB_DATA_TYPE task_dat_i;
reg `WB_DATA_TYPE task_dat_o;
reg `WB_SEL_TYPE task_sel_i;
reg task_wr_data;
reg task_data_written;
reg `WB_DATA_TYPE task_mem_wr_data;
 
// write to memory
task wr_mem;
input `WB_ADDR_TYPE adr_i;
input `WB_DATA_TYPE dat_i;
input `WB_SEL_TYPE sel_i;
begin
task_data_written = 0;
task_wr_adr_i = adr_i;
task_dat_i = dat_i;
task_sel_i = sel_i;
task_wr_data = 1;
wait(task_data_written);
task_wr_data = 0;
end
endtask
 
// read from memory
task rd_mem;
input `WB_ADDR_TYPE adr_i;
output `WB_DATA_TYPE dat_o;
input `WB_SEL_TYPE sel_i;
begin
task_rd_adr_i = adr_i;
task_sel_i = sel_i;
#1;
dat_o = task_dat_o;
end
endtask
 
/*------------------------------------------------------------------------------------------------------
Internal signals and logic
------------------------------------------------------------------------------------------------------*/
reg calc_ack;
reg calc_err;
reg calc_rty;
 
reg [7:0] retry_cnt;
reg [7:0] retry_num;
reg retry_expired;
 
// Retry counter
always@(posedge RST_I or posedge CLK_I)
begin
if (RST_I)
retry_cnt <= #1 8'h00;
else
begin
if (calc_ack || calc_err)
retry_cnt <= #1 8'h00;
else if (calc_rty)
retry_cnt <= #1 retry_num;
end
end
 
always@(retry_cnt or max_retry)
begin
if (retry_cnt < max_retry)
begin
retry_num = retry_cnt + 1'b1;
retry_expired = 1'b0;
end
else
begin
retry_num = retry_cnt;
retry_expired = 1'b1;
end
end
 
reg [3:0] wait_cnt;
reg [3:0] wait_num;
reg wait_expired;
 
// Wait counter
always@(posedge RST_I or posedge CLK_I)
begin
if (RST_I)
wait_cnt <= #1 4'h0;
else
begin
if (wait_expired || ~STB_I)
wait_cnt <= #1 4'h0;
else
wait_cnt <= #1 wait_num;
end
end
 
always@(wait_cnt or wait_cyc or STB_I or a_e_r_resp or retry_expired)
begin
if ((wait_cyc > 0) && (STB_I))
begin
if (wait_cnt < wait_cyc) // 4'h2)
begin
wait_num = wait_cnt + 1'b1;
wait_expired = 1'b0;
calc_ack = 1'b0;
calc_err = 1'b0;
calc_rty = 1'b0;
end
else
begin
wait_num = wait_cnt;
wait_expired = 1'b1;
if (a_e_r_resp == 3'b100)
begin
calc_ack = 1'b1;
calc_err = 1'b0;
calc_rty = 1'b0;
end
else
if (a_e_r_resp == 3'b010)
begin
calc_ack = 1'b0;
calc_err = 1'b1;
calc_rty = 1'b0;
end
else
if (a_e_r_resp == 3'b001)
begin
calc_err = 1'b0;
if (retry_expired)
begin
calc_ack = 1'b1;
calc_rty = 1'b0;
end
else
begin
calc_ack = 1'b0;
calc_rty = 1'b1;
end
end
else
begin
calc_ack = 1'b0;
calc_err = 1'b0;
calc_rty = 1'b0;
end
end
end
else
if ((wait_cyc == 0) && (STB_I))
begin
wait_num = 2'h0;
wait_expired = 1'b1;
if (a_e_r_resp == 3'b100)
begin
calc_ack = 1'b1;
calc_err = 1'b0;
calc_rty = 1'b0;
end
else if (a_e_r_resp == 3'b010)
begin
calc_ack = 1'b0;
calc_err = 1'b1;
calc_rty = 1'b0;
end
else if (a_e_r_resp == 3'b001)
begin
calc_err = 1'b0;
if (retry_expired)
begin
calc_ack = 1'b1;
calc_rty = 1'b0;
end
else
begin
calc_ack = 1'b0;
calc_rty = 1'b1;
end
end
else
begin
calc_ack = 1'b0;
calc_err = 1'b0;
calc_rty = 1'b0;
end
end
else
begin
wait_num = 2'h0;
wait_expired = 1'b0;
calc_ack = 1'b0;
calc_err = 1'b0;
calc_rty = 1'b0;
end
end
 
wire rd_sel = (CYC_I && STB_I && ~WE_I);
wire wr_sel = (CYC_I && STB_I && WE_I);
 
// Generate cycle termination signals
assign ACK_O = calc_ack && STB_I;
assign ERR_O = calc_err && STB_I;
assign RTY_O = calc_rty && STB_I;
 
// Assign address to asynchronous memory
always@(RST_I or ADR_I)
begin
if (RST_I) // this is added because at start of test bench we need address change in order to get data!
begin
#1 mem_rd_data_in = `WB_DATA_WIDTH'hxxxx_xxxx;
end
else
begin
// #1 mem_rd_data_in = wb_memory[ADR_I[25:2]];
#1 mem_rd_data_in = wb_memory[ADR_I[21:2]];
end
end
 
// Data input/output interface
always@(rd_sel or mem_rd_data_in or RST_I)
begin
if (RST_I)
DAT_O <=#1 `WB_DATA_WIDTH'hxxxx_xxxx; // assign outputs to unknown state while in reset
else if (rd_sel)
DAT_O <=#1 mem_rd_data_in;
else
DAT_O <=#1 `WB_DATA_WIDTH'hxxxx_xxxx;
end
 
 
always@(RST_I or task_rd_adr_i)
begin
if (RST_I)
task_dat_o = `WB_DATA_WIDTH'hxxxx_xxxx;
else
task_dat_o = wb_memory[task_rd_adr_i[21:2]];
end
always@(CLK_I or wr_sel or task_wr_data or ADR_I or task_wr_adr_i or
mem_wr_data_out or DAT_I or task_mem_wr_data or task_dat_i or
SEL_I or task_sel_i)
begin
if (task_wr_data)
begin
task_mem_wr_data = wb_memory[task_wr_adr_i[21:2]];
 
if (task_sel_i[3])
task_mem_wr_data[31:24] = task_dat_i[31:24];
if (task_sel_i[2])
task_mem_wr_data[23:16] = task_dat_i[23:16];
if (task_sel_i[1])
task_mem_wr_data[15: 8] = task_dat_i[15: 8];
if (task_sel_i[0])
task_mem_wr_data[ 7: 0] = task_dat_i[ 7: 0];
 
wb_memory[task_wr_adr_i[21:2]] = task_mem_wr_data; // write data
task_data_written = 1;
end
else if (wr_sel && CLK_I)
begin
// mem_wr_data_out = wb_memory[ADR_I[25:2]]; // if no SEL_I is active, old value will be written
mem_wr_data_out = wb_memory[ADR_I[21:2]]; // if no SEL_I is active, old value will be written
 
if (SEL_I[3])
mem_wr_data_out[31:24] = DAT_I[31:24];
if (SEL_I[2])
mem_wr_data_out[23:16] = DAT_I[23:16];
if (SEL_I[1])
mem_wr_data_out[15: 8] = DAT_I[15: 8];
if (SEL_I[0])
mem_wr_data_out[ 7: 0] = DAT_I[ 7: 0];
 
// wb_memory[ADR_I[25:2]] <= mem_wr_data_out; // write data
wb_memory[ADR_I[21:2]] = mem_wr_data_out; // write data
end
end
 
endmodule
/verilog/wb_master_behavioral.v
0,0 → 1,779
//////////////////////////////////////////////////////////////////////
//// ////
//// File name "wb_master_behavioral.v" ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Miha Dolenc (mihad@opencores.org) ////
//// ////
//// All additional information is available in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
// Revision 1.1 2002/07/29 11:25:20 mihad
// Adding test bench for memory interface
//
// Revision 1.1 2002/02/01 13:39:43 mihad
// Initial testbench import. Still under development
//
 
`include "wb_model_defines.v"
`include "timescale.v"
module WB_MASTER_BEHAVIORAL
(
CLK_I,
RST_I,
TAG_I,
TAG_O,
ACK_I,
ADR_O,
CYC_O,
DAT_I,
DAT_O,
ERR_I,
RTY_I,
SEL_O,
STB_O,
WE_O,
CAB_O
);
 
input CLK_I;
input RST_I;
input `WB_TAG_TYPE TAG_I;
output `WB_TAG_TYPE TAG_O;
input ACK_I;
output `WB_ADDR_TYPE ADR_O;
output CYC_O;
input `WB_DATA_TYPE DAT_I;
output `WB_DATA_TYPE DAT_O;
input ERR_I;
input RTY_I;
output `WB_SEL_TYPE SEL_O;
output STB_O;
output WE_O;
output CAB_O;
 
// instantiate low level master module
WB_MASTER32 wbm_low_level
(
.CLK_I(CLK_I),
.RST_I(RST_I),
.TAG_I(TAG_I),
.TAG_O(TAG_O),
.ACK_I(ACK_I),
.ADR_O(ADR_O),
.CYC_O(CYC_O),
.DAT_I(DAT_I),
.DAT_O(DAT_O),
.ERR_I(ERR_I),
.RTY_I(RTY_I),
.SEL_O(SEL_O),
.STB_O(STB_O),
.WE_O(WE_O),
.CAB_O(CAB_O)
) ;
 
// block read and write buffers definition
// single write buffer
reg `WRITE_STIM_TYPE blk_write_data [0:(`MAX_BLK_SIZE - 1)] ;
// read stimulus buffer - addresses, tags, selects etc.
reg `READ_STIM_TYPE blk_read_data_in [0:(`MAX_BLK_SIZE - 1)] ;
// read return buffer - data and tags received while performing block reads
reg `READ_RETURN_TYPE blk_read_data_out [0:(`MAX_BLK_SIZE - 1)] ;
 
// single write task
task wb_single_write ;
input `WRITE_STIM_TYPE write_data ;
input `WB_TRANSFER_FLAGS write_flags ;
inout `WRITE_RETURN_TYPE return ;
reg in_use ;
reg cab ;
reg ok ;
integer cyc_count ;
integer rty_count ;
reg retry ;
begin:main
 
return`TB_ERROR_BIT = 1'b0 ;
cab = 0 ;
return`CYC_ACTUAL_TRANSFER = 0 ;
rty_count = 0 ;
 
// check if task was called before previous call finished
if ( in_use === 1 )
begin
$display("*E, wb_single_write routine re-entered! Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
in_use = 1 ;
 
retry = 1 ;
 
while (retry === 1)
begin
// synchronize operation to clock
@(posedge CLK_I) ;
 
wbm_low_level.start_cycle(cab, 1'b1, ok) ;
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_single_write, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// first insert initial wait states
cyc_count = write_flags`INIT_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.wbm_write(write_data, return) ;
 
if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && write_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0)
begin
if ( rty_count === `WB_TB_MAX_RTY )
begin
$display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_single_write, Time %t ", $time) ;
retry = 0 ;
end
else
begin
retry = 1 ;
rty_count = rty_count + 1 ;
end
end
else
retry = 0 ;
 
// if test bench error bit is set, there is no meaning in introducing subsequent wait states
if ( return`TB_ERROR_BIT !== 0 )
begin
@(posedge CLK_I) ;
wbm_low_level.end_cycle ;
disable main ;
end
 
cyc_count = write_flags`SUBSEQ_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.end_cycle ;
end
 
in_use = 0 ;
 
end //main
endtask // wb_single_write
 
task wb_single_read ;
input `READ_STIM_TYPE read_data ;
input `WB_TRANSFER_FLAGS read_flags ;
inout `READ_RETURN_TYPE return ;
reg in_use ;
reg cab ;
reg ok ;
integer cyc_count ;
integer rty_count ;
reg retry ;
begin:main
 
return`TB_ERROR_BIT = 1'b0 ;
cab = 0 ;
rty_count = 0 ;
return`CYC_ACTUAL_TRANSFER = 0 ;
 
// check if task was called before previous call finished
if ( in_use === 1 )
begin
$display("*E, wb_single_read routine re-entered! Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
in_use = 1 ;
 
retry = 1 ;
 
while (retry === 1)
begin
// synchronize operation to clock
@(posedge CLK_I) ;
 
wbm_low_level.start_cycle(cab, 1'b0, ok) ;
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_single_read, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// first insert initial wait states
cyc_count = read_flags`INIT_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.wbm_read(read_data, return) ;
 
if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && read_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0)
begin
if ( rty_count === `WB_TB_MAX_RTY )
begin
$display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_single_read, Time %t ", $time) ;
retry = 0 ;
end
else
begin
retry = 1 ;
rty_count = rty_count + 1 ;
end
end
else
begin
retry = 0 ;
end
 
// if test bench error bit is set, there is no meaning in introducing subsequent wait states
if ( return`TB_ERROR_BIT !== 0 )
begin
@(posedge CLK_I) ;
wbm_low_level.end_cycle ;
disable main ;
end
 
cyc_count = read_flags`SUBSEQ_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.end_cycle ;
end
 
in_use = 0 ;
 
end //main
endtask // wb_single_read
 
task wb_RMW_read ;
input `READ_STIM_TYPE read_data ;
input `WB_TRANSFER_FLAGS read_flags ;
inout `READ_RETURN_TYPE return ;
reg in_use ;
reg cab ;
reg ok ;
integer cyc_count ;
integer rty_count ;
reg retry ;
begin:main
 
return`TB_ERROR_BIT = 1'b0 ;
cab = 0 ;
rty_count = 0 ;
return`CYC_ACTUAL_TRANSFER = 0 ;
 
// check if task was called before previous call finished
if ( in_use === 1 )
begin
$display("*E, wb_RMW_read routine re-entered! Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
in_use = 1 ;
 
retry = 1 ;
 
while (retry === 1)
begin
// synchronize operation to clock
@(posedge CLK_I) ;
 
wbm_low_level.start_cycle(cab, 1'b0, ok) ;
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_RMW_read, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// first insert initial wait states
cyc_count = read_flags`INIT_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.wbm_read(read_data, return) ;
 
if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && read_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0)
begin
if ( rty_count === `WB_TB_MAX_RTY )
begin
$display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_RMW_read, Time %t ", $time) ;
retry = 0 ;
end
else
begin
retry = 1 ;
rty_count = rty_count + 1 ;
end
end
else
begin
retry = 0 ;
end
 
// if test bench error bit is set, there is no meaning in introducing subsequent wait states
if ( return`TB_ERROR_BIT !== 0 )
begin
@(posedge CLK_I) ;
wbm_low_level.end_cycle ;
disable main ;
end
 
cyc_count = read_flags`SUBSEQ_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
if (retry === 1)
wbm_low_level.end_cycle ;
else
wbm_low_level.modify_cycle ;
end
 
in_use = 0 ;
 
end //main
endtask // wb_RMW_read
 
task wb_RMW_write ;
input `WRITE_STIM_TYPE write_data ;
input `WB_TRANSFER_FLAGS write_flags ;
inout `WRITE_RETURN_TYPE return ;
reg in_use ;
reg cab ;
reg ok ;
integer cyc_count ;
integer rty_count ;
reg retry ;
begin:main
 
return`TB_ERROR_BIT = 1'b0 ;
cab = 0 ;
return`CYC_ACTUAL_TRANSFER = 0 ;
rty_count = 0 ;
 
// check if task was called before previous call finished
if ( in_use === 1 )
begin
$display("*E, wb_RMW_write routine re-entered! Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
in_use = 1 ;
 
retry = 1 ;
 
while (retry === 1)
begin
// synchronize operation to clock
//@(posedge CLK_I) ;
ok = 1 ;
if (rty_count !== 0)
wbm_low_level.start_cycle(cab, 1'b1, ok) ;
 
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_single_write, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// first insert initial wait states
cyc_count = write_flags`INIT_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.wbm_write(write_data, return) ;
 
if ( return`CYC_ERR === 0 && return`CYC_ACK === 0 && return`CYC_RTY === 1 && write_flags`WB_TRANSFER_AUTO_RTY === 1 && return`TB_ERROR_BIT === 0)
begin
if ( rty_count === `WB_TB_MAX_RTY )
begin
$display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_single_write, Time %t ", $time) ;
retry = 0 ;
end
else
begin
retry = 1 ;
rty_count = rty_count + 1 ;
end
end
else
retry = 0 ;
 
// if test bench error bit is set, there is no meaning in introducing subsequent wait states
if ( return`TB_ERROR_BIT !== 0 )
begin
@(posedge CLK_I) ;
wbm_low_level.end_cycle ;
disable main ;
end
 
cyc_count = write_flags`SUBSEQ_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
wbm_low_level.end_cycle ;
end
 
in_use = 0 ;
 
end //main
endtask // wb_RMW_write
 
task wb_block_write ;
input `WB_TRANSFER_FLAGS write_flags ;
inout `WRITE_RETURN_TYPE return ;
 
reg in_use ;
reg `WRITE_STIM_TYPE current_write ;
reg cab ;
reg ok ;
integer cyc_count ;
integer rty_count ;
reg end_blk ;
begin:main
 
return`CYC_ACTUAL_TRANSFER = 0 ;
rty_count = 0 ;
 
// check if task was called before previous call finished
if ( in_use === 1 )
begin
$display("*E, wb_block_write routine re-entered! Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
if (write_flags`WB_TRANSFER_SIZE > `MAX_BLK_SIZE)
begin
$display("*E, number of transfers passed to wb_block_write routine exceeds defined maximum transaction length! Time %t", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
in_use = 1 ;
@(posedge CLK_I) ;
cab = write_flags`WB_TRANSFER_CAB ;
wbm_low_level.start_cycle(cab, 1'b1, ok) ;
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_block_write, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// insert initial wait states
cyc_count = write_flags`INIT_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
end_blk = 0 ;
while (end_blk === 0)
begin
// collect data for current data beat
current_write = blk_write_data[return`CYC_ACTUAL_TRANSFER] ;
wbm_low_level.wbm_write(current_write, return) ;
 
// check result of write operation
// check for severe test error
if (return`TB_ERROR_BIT !== 0)
begin
@(posedge CLK_I) ;
wbm_low_level.end_cycle ;
disable main ;
end
 
// slave returned error or error signal had invalid value
if (return`CYC_ERR !== 0)
end_blk = 1 ;
 
if (
(return`CYC_RTY !== 0) && (return`CYC_RTY !== 1) ||
(return`CYC_ACK !== 0) && (return`CYC_ACK !== 1) ||
(return`CYC_ERR !== 0) && (return`CYC_ERR !== 1)
)
begin
end_blk = 1 ;
$display("*E, at least one slave response signal was invalid when cycle finished! Routine wb_block_write, Time %t ", $time) ;
$display("ACK = %b \t RTY_O = %b \t ERR_O = %b \t", return`CYC_ACK, return`CYC_RTY, return`CYC_ERR) ;
end
 
if ((return`CYC_RTY === 1) && (write_flags`WB_TRANSFER_AUTO_RTY !== 1))
end_blk = 1 ;
 
if ((return`CYC_RTY === 1) && (write_flags`WB_TRANSFER_AUTO_RTY === 1))
begin
if ( rty_count === `WB_TB_MAX_RTY )
begin
$display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_block_write, Time %t ", $time) ;
end_blk = 1 ;
end
else
begin
rty_count = rty_count + 1 ;
end
end
else
rty_count = 0 ;
 
// check if slave responded at all
if (return`CYC_RESPONSE === 0)
end_blk = 1 ;
 
// check if all intended data was transfered
if (return`CYC_ACTUAL_TRANSFER === write_flags`WB_TRANSFER_SIZE)
end_blk = 1 ;
 
// insert subsequent wait cycles, if transfer is supposed to continue
if ( end_blk === 0 )
begin
cyc_count = write_flags`SUBSEQ_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
end
 
if ( (end_blk === 0) && (return`CYC_RTY === 1) )
begin
wbm_low_level.end_cycle ;
@(posedge CLK_I) ;
wbm_low_level.start_cycle(cab, 1'b1, ok) ;
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_block_write, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
end_blk = 1 ;
end
end
end //while
 
wbm_low_level.end_cycle ;
in_use = 0 ;
end //main
endtask //wb_block_write
 
task wb_block_read ;
input `WB_TRANSFER_FLAGS read_flags ;
inout `READ_RETURN_TYPE return ;
 
reg in_use ;
reg `READ_STIM_TYPE current_read ;
reg cab ;
reg ok ;
integer cyc_count ;
integer rty_count ;
reg end_blk ;
integer transfered ;
begin:main
 
return`CYC_ACTUAL_TRANSFER = 0 ;
transfered = 0 ;
rty_count = 0 ;
 
// check if task was called before previous call finished
if ( in_use === 1 )
begin
$display("*E, wb_block_read routine re-entered! Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
if (read_flags`WB_TRANSFER_SIZE > `MAX_BLK_SIZE)
begin
$display("*E, number of transfers passed to wb_block_read routine exceeds defined maximum transaction length! Time %t", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
in_use = 1 ;
@(posedge CLK_I) ;
cab = read_flags`WB_TRANSFER_CAB ;
 
wbm_low_level.start_cycle(cab, 1'b0, ok) ;
 
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_block_read, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// insert initial wait states
cyc_count = read_flags`INIT_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
 
end_blk = 0 ;
while (end_blk === 0)
begin
// collect data for current data beat
current_read = blk_read_data_in[return`CYC_ACTUAL_TRANSFER] ;
 
wbm_low_level.wbm_read(current_read, return) ;
 
if ( transfered !== return`CYC_ACTUAL_TRANSFER )
begin
blk_read_data_out[transfered] = return ;
transfered = return`CYC_ACTUAL_TRANSFER ;
end
 
// check result of read operation
// check for severe test error
if (return`TB_ERROR_BIT !== 0)
begin
@(posedge CLK_I) ;
wbm_low_level.end_cycle ;
disable main ;
end
 
// slave returned error or error signal had invalid value
if (return`CYC_ERR !== 0)
end_blk = 1 ;
 
if (
(return`CYC_RTY !== 0) && (return`CYC_RTY !== 1) ||
(return`CYC_ACK !== 0) && (return`CYC_ACK !== 1) ||
(return`CYC_ERR !== 0) && (return`CYC_ERR !== 1)
)
begin
end_blk = 1 ;
$display("*E, at least one slave response signal was invalid when cycle finished! Routine wb_block_read, Time %t ", $time) ;
$display("ACK = %b \t RTY_O = %b \t ERR_O = %b \t", return`CYC_ACK, return`CYC_RTY, return`CYC_ERR) ;
end
 
if ((return`CYC_RTY === 1) && (read_flags`WB_TRANSFER_AUTO_RTY !== 1))
end_blk = 1 ;
 
if ((return`CYC_RTY === 1) && (read_flags`WB_TRANSFER_AUTO_RTY === 1))
begin
if ( rty_count === `WB_TB_MAX_RTY )
begin
$display("*E, maximum number of retries received - access will not be repeated anymore! Routine wb_block_read, Time %t ", $time) ;
end_blk = 1 ;
end
else
begin
rty_count = rty_count + 1 ;
end
end
else
rty_count = 0 ;
 
// check if slave responded at all
if (return`CYC_RESPONSE === 0)
end_blk = 1 ;
 
// check if all intended data was transfered
if (return`CYC_ACTUAL_TRANSFER === read_flags`WB_TRANSFER_SIZE)
end_blk = 1 ;
 
// insert subsequent wait cycles, if transfer is supposed to continue
if ( end_blk === 0 )
begin
cyc_count = read_flags`SUBSEQ_WAITS ;
while ( cyc_count > 0 )
begin
@(posedge CLK_I) ;
cyc_count = cyc_count - 1 ;
end
end
 
if ( (end_blk === 0) && (return`CYC_RTY === 1) )
begin
wbm_low_level.end_cycle ;
@(posedge CLK_I) ;
wbm_low_level.start_cycle(cab, 1'b0, ok) ;
if ( ok !== 1 )
begin
$display("*E, Failed to initialize cycle! Routine wb_block_read, Time %t ", $time) ;
return`TB_ERROR_BIT = 1'b1 ;
end_blk = 1 ;
end
end
end //while
 
wbm_low_level.end_cycle ;
in_use = 0 ;
end //main
endtask //wb_block_read
 
endmodule
 
/verilog/wb_model_defines.v
0,0 → 1,148
//////////////////////////////////////////////////////////////////////
//// ////
//// File name "wb_model_defines.v" ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Miha Dolenc (mihad@opencores.org) ////
//// ////
//// All additional information is available in the README.pdf ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
 
// WISHBONE frequency in GHz
`define WB_FREQ 0.100
 
// memory frequency in GHz
`define MEM_FREQ 0.100
 
// setup and hold time definitions for WISHBONE - used in BFMs for signal generation
`define Tsetup 4
`define Thold 1
 
// how many clock cycles should model wait for design's response - integer 32 bit value
`define WAIT_FOR_RESPONSE 1023
 
// maximum number of transactions allowed in single call to block or cab transfer routines
`define MAX_BLK_SIZE 1024
 
// maximum retry terminations allowed for WISHBONE master to repeat an access
`define WB_TB_MAX_RTY 0
 
 
// some common types and defines
`define WB_ADDR_WIDTH 32
`define WB_DATA_WIDTH 32
`define WB_SEL_WIDTH `WB_DATA_WIDTH/8
`define WB_TAG_WIDTH 1
`define WB_ADDR_TYPE [(`WB_ADDR_WIDTH - 1):0]
`define WB_DATA_TYPE [(`WB_DATA_WIDTH - 1):0]
`define WB_SEL_TYPE [(`WB_SEL_WIDTH - 1):0]
`define WB_TAG_TYPE [(`WB_TAG_WIDTH - 1):0]
 
// read cycle stimulus - consists of:
// - address field - which address read will be performed from
// - sel field - what byte select value should be
// - tag field - what tag values should be put on the bus
`define READ_STIM_TYPE [(`WB_ADDR_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):0]
`define READ_STIM_LENGTH (`WB_ADDR_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH)
`define READ_ADDRESS [(`WB_ADDR_WIDTH - 1):0]
`define READ_SEL [(`WB_ADDR_WIDTH + `WB_SEL_WIDTH - 1):`WB_ADDR_WIDTH]
`define READ_TAG_STIM [(`WB_ADDR_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):(`WB_ADDR_WIDTH + `WB_SEL_WIDTH)]
 
// read cycle return type consists of:
// - read data field
// - tag field received from WISHBONE
// - wishbone slave response fields - ACK, ERR and RTY
// - test bench error indicator (when testcase has not used wb master model properly)
// - how much data was actually transfered
`define READ_RETURN_TYPE [(32 + 4 + `WB_DATA_WIDTH + `WB_TAG_WIDTH - 1):0]
`define READ_DATA [(32 + `WB_DATA_WIDTH + 4 - 1):32 + 4]
`define READ_TAG_RET [(32 + 4 + `WB_DATA_WIDTH + `WB_TAG_WIDTH - 1):(`WB_DATA_WIDTH + 32 + 4)]
`define READ_RETURN_LENGTH (32 + 4 + `WB_DATA_WIDTH + `WB_TAG_WIDTH - 1)
 
// write cycle stimulus type consists of
// - address field
// - data field
// - sel field
// - tag field
`define WRITE_STIM_TYPE [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):0]
`define WRITE_ADDRESS [(`WB_ADDR_WIDTH - 1):0]
`define WRITE_DATA [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH - 1):`WB_ADDR_WIDTH]
`define WRITE_SEL [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH - 1):(`WB_ADDR_WIDTH + `WB_DATA_WIDTH)]
`define WRITE_TAG_STIM [(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH - 1):(`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH)]
 
// length of WRITE_STIMULUS
`define WRITE_STIM_LENGTH (`WB_ADDR_WIDTH + `WB_DATA_WIDTH + `WB_SEL_WIDTH + `WB_TAG_WIDTH)
 
// write cycle return type consists of:
// - test bench error indicator (when testcase has not used wb master model properly)
// - wishbone slave response fields - ACK, ERR and RTY
// - tag field received from WISHBONE
// - how much data was actually transfered
`define WRITE_RETURN_TYPE [(32 + 4 + `WB_TAG_WIDTH - 1):0]
`define WRITE_TAG_RET [(32 + 4 + `WB_TAG_WIDTH - 1):32 + 4]
 
// this four fields are common to both read and write routines return values
`define TB_ERROR_BIT [0]
`define CYC_ACK [1]
`define CYC_RTY [2]
`define CYC_ERR [3]
`define CYC_RESPONSE [3:1]
`define CYC_ACTUAL_TRANSFER [35:4]
 
// block transfer flags
`define WB_TRANSFER_FLAGS [41:0]
// consists of:
// - number of transfer cycles to perform
// - flag that enables retry termination handling - if disabled, block transfer routines will return on any termination other than acknowledge
// - flag indicating CAB transfer is to be performed - ignored by all single transfer routines
// - number of initial wait states to insert
// - number of subsequent wait states to insert
`define WB_TRANSFER_SIZE [41:10]
`define WB_TRANSFER_AUTO_RTY [8]
`define WB_TRANSFER_CAB [9]
`define INIT_WAITS [3:0]
`define SUBSEQ_WAITS [7:4]
 
// wb slave response
`define ACK_RESPONSE 3'b100
`define ERR_RESPONSE 3'b010
`define RTY_RESPONSE 3'b001
`define NO_RESPONSE 3'b000
/verilog/wb_master32.v
0,0 → 1,374
//////////////////////////////////////////////////////////////////////
//// ////
//// File name "wb_master32.v" ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Miha Dolenc (mihad@opencores.org) ////
//// ////
//// All additional information is available in the README.pdf ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
// Revision 1.1 2002/07/29 11:25:20 mihad
// Adding test bench for memory interface
//
// Revision 1.1 2002/02/01 13:39:43 mihad
// Initial testbench import. Still under development
//
//
 
`include "wb_model_defines.v"
`include "timescale.v"
module WB_MASTER32
(
CLK_I,
RST_I,
TAG_I,
TAG_O,
ACK_I,
ADR_O,
CYC_O,
DAT_I,
DAT_O,
ERR_I,
RTY_I,
SEL_O,
STB_O,
WE_O,
CAB_O
);
 
input CLK_I;
input RST_I;
input `WB_TAG_TYPE TAG_I;
output `WB_TAG_TYPE TAG_O;
input ACK_I;
output `WB_ADDR_TYPE ADR_O;
output CYC_O;
input `WB_DATA_TYPE DAT_I;
output `WB_DATA_TYPE DAT_O;
input ERR_I;
input RTY_I;
output `WB_SEL_TYPE SEL_O;
output STB_O;
output WE_O;
output CAB_O ;
 
// period length
real Tp ;
 
reg `WB_ADDR_TYPE ADR_O;
reg `WB_SEL_TYPE SEL_O;
reg `WB_TAG_TYPE TAG_O;
reg CYC_O;
reg WE_O;
reg `WB_DATA_TYPE DAT_O;
reg CAB_O ;
reg STB_O ;
 
// variable used for indication on whether cycle was already started
reg in_use ;
 
// because of non-blocking assignments CYC_O is not sufficient indicator for cycle starting - this var is used in its place
reg cycle_in_progress ;
 
// same goes for CAB_O signal
reg cab ;
 
reg we ;
 
task start_cycle ;
input is_cab ;
input write ;
output ok ; // ok indicates to the caller that cycle was started succesfully - if not, caller must take appropriate action
begin:main
 
ok = 1 ;
 
// just check if valid value is provided for CAB_O signal (no x's or z's allowed)
if ( (is_cab !== 1'b0) && (is_cab !== 1'b1) )
begin
$display("*E, invalid CAB value for cycle! Requested CAB_O value = %b, Time %t ", is_cab, $time) ;
ok = 0 ;
disable main ;
end
 
if ( (cycle_in_progress === 1) || (CYC_O === 1))
begin
// cycle was previously started - allow cycle to continue if CAB and WE values match
$display("*W, cycle already in progress when start_cycle routine was called! Time %t ", $time) ;
if ((CAB_O !== is_cab) || (WE_O !== write) )
begin
ok = 0 ;
if ( is_cab === 1 )
$display("*E, cab cycle start attempted when non-cab cycle was in progress! Time %t", $time) ;
else
$display("*E, non-cab cycle start attempted when cab cycle was in progress! Time %t", $time) ;
 
if ( we === 1 )
$display("*E, write cycle start attempted when read cycle was in progress! Time %t", $time) ;
else
$display("*E, read cycle start attempted when write cycle was in progress! Time %t", $time) ;
 
disable main ;
end
end
 
CYC_O <= #(Tp - `Tsetup) 1'b1 ;
CAB_O <= #(Tp - `Tsetup) is_cab ;
WE_O <= #(Tp - `Tsetup) write ;
 
// this non-blocking assignments are made to internal variables, so read and write tasks can be called immediately after cycle start task
cycle_in_progress = 1'b1 ;
cab = is_cab ;
we = write ;
end
endtask //start_cycle
 
task end_cycle ;
begin
if ( CYC_O !== 1'b1 )
$display("*W, end_cycle routine called when CYC_O value was %b! Time %t ", CYC_O, $time) ;
 
CYC_O <= #`Thold 1'b0 ;
CAB_O <= #`Thold 1'b0 ;
cycle_in_progress = 1'b0 ;
end
endtask //end_cycle
 
task modify_cycle ;
begin
if ( CYC_O !== 1'b1 )
$display("*W, modify_cycle routine called when CYC_O value was %b! Time %t ", CYC_O, $time) ;
 
we = ~we ;
WE_O <= #(Tp - `Tsetup) we ;
end
endtask //modify_cycle
 
task wbm_read ;
input `READ_STIM_TYPE input_data ;
inout `READ_RETURN_TYPE output_data ;
reg `WB_ADDR_TYPE address ;
reg `WB_DATA_TYPE data ;
reg `WB_SEL_TYPE sel ;
reg `WB_TAG_TYPE tag ;
integer num_of_cyc ;
begin:main
output_data`TB_ERROR_BIT = 1'b0 ;
 
// check if task was called before previous call to read or write finished
if ( in_use === 1 )
begin
$display("*E, wbm_read routine re-entered or called concurently with write routine! Time %t ", $time) ;
output_data`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
if ( cycle_in_progress !== 1 )
begin
$display("*E, wbm_read routine called without start_cycle routine being called first! Time %t ", $time) ;
output_data`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
if ( we !== 0 )
begin
$display("*E, wbm_read routine called after write cycle was started! Time %t ", $time) ;
output_data`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// this branch contains timing controls - claim the use of WISHBONE
in_use = 1 ;
 
num_of_cyc = `WAIT_FOR_RESPONSE ;
 
// assign data outputs
ADR_O <= #(Tp - `Tsetup) input_data`READ_ADDRESS ;
SEL_O <= #(Tp - `Tsetup) input_data`READ_SEL ;
TAG_O <= #(Tp - `Tsetup) input_data`READ_TAG_STIM ;
 
// assign control output
STB_O <= #(Tp - `Tsetup) 1'b1 ;
 
output_data`CYC_ACK = 0 ;
output_data`CYC_RTY = 0 ;
output_data`CYC_ERR = 0 ;
 
@(posedge CLK_I) ;
output_data`CYC_ACK = ACK_I ;
output_data`CYC_RTY = RTY_I ;
output_data`CYC_ERR = ERR_I ;
 
while ( (num_of_cyc > 0) && (output_data`CYC_RESPONSE === 0) )
begin
@(posedge CLK_I) ;
output_data`CYC_ACK = ACK_I ;
output_data`CYC_RTY = RTY_I ;
output_data`CYC_ERR = ERR_I ;
num_of_cyc = num_of_cyc - 1 ;
end
 
output_data`READ_DATA = DAT_I ;
output_data`READ_TAG_RET = TAG_I ;
 
if ( output_data`CYC_RESPONSE === 0 )
begin
 
$display("*W, Terminating read cycle because no response was received in %d cycles! Time %t ", `WAIT_FOR_RESPONSE, $time) ;
end
 
if ( output_data`CYC_ACK === 1 && output_data`CYC_RTY === 0 && output_data`CYC_ERR === 0 )
output_data`CYC_ACTUAL_TRANSFER = output_data`CYC_ACTUAL_TRANSFER + 1 ;
 
STB_O <= #`Thold 1'b0 ;
ADR_O <= #`Thold {`WB_ADDR_WIDTH{1'bx}} ;
SEL_O <= #`Thold {`WB_SEL_WIDTH{1'bx}} ;
TAG_O <= #`Thold {`WB_TAG_WIDTH{1'bx}} ;
 
in_use = 0 ;
end
endtask // wbm_read
 
task wbm_write ;
input `WRITE_STIM_TYPE input_data ;
inout `WRITE_RETURN_TYPE output_data ;
reg `WB_ADDR_TYPE address ;
reg `WB_DATA_TYPE data ;
reg `WB_SEL_TYPE sel ;
reg `WB_TAG_TYPE tag ;
integer num_of_cyc ;
begin:main
output_data`TB_ERROR_BIT = 1'b0 ;
 
// check if task was called before previous call to read or write finished
if ( in_use === 1 )
begin
$display("*E, wbm_write routine re-entered or called concurently with read routine! Time %t ", $time) ;
output_data`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
if ( cycle_in_progress !== 1 )
begin
$display("*E, wbm_write routine called without start_cycle routine being called first! Time %t ", $time) ;
output_data`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
if ( we !== 1 )
begin
$display("*E, wbm_write routine after read cycle was started! Time %t ", $time) ;
output_data`TB_ERROR_BIT = 1'b1 ;
disable main ;
end
 
// this branch contains timing controls - claim the use of WISHBONE
in_use = 1 ;
 
num_of_cyc = `WAIT_FOR_RESPONSE ;
 
ADR_O <= #(Tp - `Tsetup) input_data`WRITE_ADDRESS ;
DAT_O <= #(Tp - `Tsetup) input_data`WRITE_DATA ;
SEL_O <= #(Tp - `Tsetup) input_data`WRITE_SEL ;
TAG_O <= #(Tp - `Tsetup) input_data`WRITE_TAG_STIM ;
 
STB_O <= #(Tp - `Tsetup) 1'b1 ;
 
output_data`CYC_ACK = 0 ;
output_data`CYC_RTY = 0 ;
output_data`CYC_ERR = 0 ;
 
@(posedge CLK_I) ;
output_data`CYC_ACK = ACK_I ;
output_data`CYC_RTY = RTY_I ;
output_data`CYC_ERR = ERR_I ;
 
while ( (num_of_cyc > 0) && (output_data`CYC_RESPONSE === 0) )
begin
@(posedge CLK_I) ;
output_data`CYC_ACK = ACK_I ;
output_data`CYC_RTY = RTY_I ;
output_data`CYC_ERR = ERR_I ;
num_of_cyc = num_of_cyc - 1 ;
end
 
output_data`WRITE_TAG_RET = TAG_I ;
if ( output_data`CYC_RESPONSE === 0 )
begin
$display("*W, Terminating write cycle because no response was received in %d cycles! Time %t ", `WAIT_FOR_RESPONSE, $time) ;
end
 
if ( output_data`CYC_ACK === 1 && output_data`CYC_RTY === 0 && output_data`CYC_ERR === 0 )
output_data`CYC_ACTUAL_TRANSFER = output_data`CYC_ACTUAL_TRANSFER + 1 ;
 
ADR_O <= #`Thold {`WB_ADDR_WIDTH{1'bx}} ;
DAT_O <= #`Thold {`WB_DATA_WIDTH{1'bx}} ;
SEL_O <= #`Thold {`WB_SEL_WIDTH{1'bx}} ;
TAG_O <= #`Thold {`WB_TAG_WIDTH{1'bx}} ;
 
STB_O <= #`Thold 1'b0 ;
 
in_use = 0 ;
end
endtask //wbm_write
 
initial
begin
Tp = 1 / `WB_FREQ ;
in_use = 0 ;
cycle_in_progress = 0 ;
cab = 0 ;
ADR_O <= {`WB_ADDR_WIDTH{1'bx}} ;
DAT_O <= {`WB_DATA_WIDTH{1'bx}} ;
SEL_O <= {`WB_SEL_WIDTH{1'bx}} ;
TAG_O <= {`WB_TAG_WIDTH{1'bx}} ;
CYC_O <= 1'b0 ;
STB_O <= 1'b0 ;
CAB_O <= 1'b0 ;
WE_O <= 1'b0 ;
if ( `Tsetup > Tp || `Thold >= Tp )
begin
$display("Either Tsetup or Thold values for WISHBONE BFMs are too large!") ;
$stop ;
end
end
 
endmodule
/verilog/tb_eth_top.v
0,0 → 1,1540
 
 
 
 
 
 
 
 
Please use tb_ethernet.v for testbench. Testbench will soon be
updated.
 
 
 
 
 
 
 
 
 
 
 
 
 
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_eth_top.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.13 2002/05/03 10:25:01 mohor
// Testbench supports unaligned accesses.
//
// Revision 1.12 2002/02/26 17:01:09 mohor
// Small fixes for external/internal DMA missmatches.
//
// Revision 1.11 2002/02/16 13:06:59 mohor
// EXTERNAL_DMA used instead of WISHBONE_DMA.
//
// Revision 1.10 2002/02/16 07:22:15 mohor
// Testbench fixed, code simplified, unused signals removed.
//
// Revision 1.9 2002/02/14 20:14:38 billditt
// Added separate tests for Multicast, Unicast, Broadcast
//
// Revision 1.8 2002/02/12 20:24:00 mohor
// HASH0 and HASH1 register read/write added.
//
// Revision 1.7 2002/02/06 14:11:35 mohor
// non-DMA host interface added. Select the right configutation in eth_defines.
//
// Revision 1.6 2001/12/08 12:36:00 mohor
// TX_BD_NUM register added instead of the RB_BD_ADDR.
//
// Revision 1.5 2001/10/19 11:24:04 mohor
// Number of addresses (wb_adr_i) minimized.
//
// Revision 1.4 2001/10/19 08:46:53 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.3 2001/09/24 14:55:49 mohor
// Defines changed (All precede with ETH_). Small changes because some
// tools generate warnings when two operands are together. Synchronization
// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC
// demands).
//
// Revision 1.2 2001/08/15 14:04:30 mohor
// Signal names changed on the top level for easier pad insertion (ASIC).
//
// Revision 1.1 2001/08/06 14:41:09 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:46:09 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
 
`include "tb_eth_defines.v"
`include "eth_defines.v"
`include "timescale.v"
 
module tb_eth_top();
 
 
parameter Tp = 1;
 
 
reg WB_CLK_I;
reg WB_RST_I;
reg [31:0] WB_DAT_I;
 
reg [31:0] WB_ADR_I;
reg [3:0] WB_SEL_I;
reg WB_WE_I;
reg WB_CYC_I;
reg WB_STB_I;
 
wire [31:0] WB_DAT_O;
wire WB_ACK_O;
wire WB_ERR_O;
reg [1:0] WB_ACK_I;
 
// WISHBONE master
wire [31:0] m_wb_adr_o;
wire [3:0] m_wb_sel_o;
wire m_wb_we_o;
reg [31:0] m_wb_dat_i;
wire [31:0] m_wb_dat_o;
wire m_wb_cyc_o;
wire m_wb_stb_o;
reg m_wb_ack_i;
reg m_wb_err_i;
 
reg MTxClk;
wire [3:0] MTxD;
wire MTxEn;
wire MTxErr;
 
reg MRxClk;
reg [3:0] MRxD;
reg MRxDV;
reg MRxErr;
reg MColl;
reg MCrs;
 
reg Mdi_I;
wire Mdo_O;
wire Mdo_OE;
wire Mdc_O;
 
 
reg [7:0] memory0 [0:65535];
reg [7:0] memory1 [0:65535];
reg [7:0] memory2 [0:65535];
reg [7:0] memory3 [0:65535];
 
reg WishboneBusy;
reg StartTB;
reg [9:0] TxBDIndex;
reg [9:0] RxBDIndex;
 
reg LogEnable;
 
integer mcd1;
integer mcd2;
 
reg [5:0] g_last_txbd;
 
// Connecting Ethernet top module
 
eth_top ethtop
(
// WISHBONE common
.wb_clk_i(WB_CLK_I), .wb_rst_i(WB_RST_I), .wb_dat_i(WB_DAT_I), .wb_dat_o(WB_DAT_O),
 
// WISHBONE slave
.wb_adr_i(WB_ADR_I[11:2]), .wb_sel_i(WB_SEL_I), .wb_we_i(WB_WE_I), .wb_cyc_i(WB_CYC_I),
.wb_stb_i(WB_STB_I), .wb_ack_o(WB_ACK_O), .wb_err_o(WB_ERR_O),
// WISHBONE master
.m_wb_adr_o(m_wb_adr_o), .m_wb_sel_o(m_wb_sel_o), .m_wb_we_o(m_wb_we_o), .m_wb_dat_i(m_wb_dat_i),
.m_wb_dat_o(m_wb_dat_o), .m_wb_cyc_o(m_wb_cyc_o), .m_wb_stb_o(m_wb_stb_o), .m_wb_ack_i(m_wb_ack_i),
.m_wb_err_i(m_wb_err_i),
 
//TX
.mtx_clk_pad_i(MTxClk), .mtxd_pad_o(MTxD), .mtxen_pad_o(MTxEn), .mtxerr_pad_o(MTxErr),
 
//RX
.mrx_clk_pad_i(MRxClk), .mrxd_pad_i(MRxD), .mrxdv_pad_i(MRxDV), .mrxerr_pad_i(MRxErr),
.mcoll_pad_i(MColl), .mcrs_pad_i(MCrs),
// MIIM
.mdc_pad_o(Mdc_O), .md_pad_i(Mdi_I), .md_pad_o(Mdo_O), .md_padoe_o(Mdo_OE),
.int_o()
);
 
 
bench_cop i_bench_cop
(
// WISHBONE common
.wb_clk_i(WB_CLK_I), .wb_rst_i(WB_RST_I), .wb_dat_i(WB_DAT_I), .wb_dat_o(WB_DAT_O),
 
// WISHBONE slave
.wb_adr_i(WB_ADR_I[11:2]), .wb_sel_i(WB_SEL_I), .wb_we_i(WB_WE_I), .wb_cyc_i(WB_CYC_I),
.wb_stb_i(WB_STB_I), .wb_ack_o(WB_ACK_O), .wb_err_o(WB_ERR_O),
// WISHBONE master
.m_wb_adr_o(m_wb_adr_o), .m_wb_sel_o(m_wb_sel_o), .m_wb_we_o(m_wb_we_o), .m_wb_dat_i(m_wb_dat_i),
.m_wb_dat_o(m_wb_dat_o), .m_wb_cyc_o(m_wb_cyc_o), .m_wb_stb_o(m_wb_stb_o), .m_wb_ack_i(m_wb_ack_i),
.m_wb_err_i(m_wb_err_i),
 
//TX
.mtx_clk_pad_i(MTxClk), .mtxd_pad_o(MTxD), .mtxen_pad_o(MTxEn), .mtxerr_pad_o(MTxErr),
 
//RX
.mrx_clk_pad_i(MRxClk), .mrxd_pad_i(MRxD), .mrxdv_pad_i(MRxDV), .mrxerr_pad_i(MRxErr),
.mcoll_pad_i(MColl), .mcrs_pad_i(MCrs),
// MIIM
.mdc_pad_o(Mdc_O), .md_pad_i(Mdi_I), .md_pad_o(Mdo_O), .md_padoe_o(Mdo_OE),
.int_o()
);
 
 
 
 
 
 
 
initial
begin
WB_CLK_I = 1'b0;
WB_DAT_I = 32'h0;
WB_ADR_I = 32'h0;
WB_SEL_I = 4'h0;
WB_WE_I = 1'b0;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
 
m_wb_ack_i = 0;
m_wb_err_i = 0;
MTxClk = 1'b0;
MRxClk = 1'b0;
MRxD = 4'h0;
MRxDV = 1'b0;
MRxErr = 1'b0;
MColl = 1'b0;
MCrs = 1'b0;
Mdi_I = 1'b0;
 
WishboneBusy = 1'b0;
TxBDIndex = 10'h0;
RxBDIndex = 10'h0;
LogEnable = 1'b1;
g_last_txbd = 6'h0;
end
 
 
// Reset pulse
initial
begin
mcd1 = $fopen("ethernet_tx.log");
mcd2 = $fopen("ethernet_rx.log");
WB_RST_I = 1'b1;
#100 WB_RST_I = 1'b0;
#100 StartTB = 1'b1;
end
 
 
 
// Generating WB_CLK_I clock
always
begin
// forever #2.5 WB_CLK_I = ~WB_CLK_I; // 2*2.5 ns -> 200.0 MHz
// forever #5 WB_CLK_I = ~WB_CLK_I; // 2*5 ns -> 100.0 MHz
// forever #10 WB_CLK_I = ~WB_CLK_I; // 2*10 ns -> 50.0 MHz
forever #12.5 WB_CLK_I = ~WB_CLK_I; // 2*12.5 ns -> 40 MHz
// forever #15 WB_CLK_I = ~WB_CLK_I; // 2*10 ns -> 33.3 MHz
// forever #20 WB_CLK_I = ~WB_CLK_I; // 2*20 ns -> 25 MHz
// forever #25 WB_CLK_I = ~WB_CLK_I; // 2*25 ns -> 20.0 MHz
// forever #31.25 WB_CLK_I = ~WB_CLK_I; // 2*31.25 ns -> 16.0 MHz
// forever #50 WB_CLK_I = ~WB_CLK_I; // 2*50 ns -> 10.0 MHz
// forever #55 WB_CLK_I = ~WB_CLK_I; // 2*55 ns -> 9.1 MHz
end
 
// Generating MTxClk clock
always
begin
// #3 forever #20 MTxClk = ~MTxClk; // 2*20 ns -> 25 MHz
#3 forever #200 MTxClk = ~MTxClk; // 2*200 ns -> 2.5 MHz
end
 
// Generating MRxClk clock
always
begin
// #16 forever #20 MRxClk = ~MRxClk; // 2*20 ns -> 25 MHz
#16 forever #200 MRxClk = ~MRxClk; // 2*200 ns -> 2.5 MHz
// #16 forever #62.5 MRxClk = ~MRxClk; // 2*62.5 ns -> 8 MHz // just for testing purposes
end
 
 
initial
begin
wait(StartTB); // Start of testbench
// Reset eth MAC core
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 0
 
InitializeMemory;
 
// Select which test you want to run:
// TestTxAndRx;
TestFullDuplex;
// TestUnicast;
// TestBroadcast;
// TestMulticast;
end
task TestTxAndRx;
 
integer ii, jj;
integer data_in, bd, pointer;
 
begin
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR<<2}); // r_RxBDAddress = 0x80
 
// WishboneWrite(32'h0000a06b, {26'h0, `ETH_MODER_ADR<<2}); // RxEn, Txen, CrcEn, Pad en, half duplex,
WishboneWrite(32'h0000a46b, {26'h0, `ETH_MODER_ADR<<2}); // RxEn, Txen, CrcEn, Pad en, full duplex,
// WishboneWrite(32'h0001a06b, {26'h0, `ETH_MODER_ADR<<2}); // r_RecSmall, RxEn, Txen, CrcEn, Pad en, half duplex,
// r_IPG, promisc On, reject broadcast
 
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR<<2}); //r_TxFlow = 1
 
WishboneWrite(32'h00000002, {26'h0, `ETH_MAC_ADDR1_ADR<<2}); // MAC = 000203040506
WishboneWrite(32'h03040506, {26'h0, `ETH_MAC_ADDR0_ADR<<2});
 
/*
// Just few reads
WishboneRead({26'h0, `ETH_MODER_ADR<<2}, data_in); // Read from ETH_MODER register
WishboneRead({26'h0, `ETH_TX_BD_NUM_ADR<<2}, data_in); // Read from ETH_TX_BD_NUM_ADR register
WishboneRead({26'h0, `ETH_MAC_ADDR1_ADR<<2}, data_in); // Read from ETH_MAC_ADDR1_ADR register
WishboneRead({26'h0, `ETH_MAC_ADDR0_ADR<<2}, data_in); // Read from ETH_MAC_ADDR0_ADR register
*/
 
 
 
 
for(jj=0; jj<8; jj=jj+4)
begin
WishboneWriteData(`TX_BUF_BASE + jj, 32'h11111111, 4'hf); // Initializing data to ff
end
 
for(jj=0; jj<8; jj=jj+4)
begin
WishboneWriteData(`RX_BUF_BASE + jj, 32'h11111111, 4'hf); // Initializing data to ff
end
 
// SendPacketX(16'h0064, 1'b0, 2'h3);
// SendPacketX(16'h0064, 1'b0, 2'h2);
// SendPacketX(16'h0064, 1'b0, 2'h1);
// SendPacketX(16'h0064, 1'b0, 2'h0);
// SendPacket(16'h0064, 1'b0);
// SendPacket(16'h0011, 1'b0);
// SendPacket(16'h0012, 1'b0);
 
fork
begin
/*
SendPacketX(16'h0064, 1'b0, 2'h1);
SendPacketX(16'h0064, 1'b0, 2'h2);
SendPacketX(16'h0064, 1'b0, 2'h3);
SendPacketX(16'h0064, 1'b0, 2'h0);
*/
// SendPacketX(16'h264, 1'b0, 2'h3);
// SendPacketX(16'h64, 1'b0, 2'h3);
// SendPacketX(16'h104, 1'b0, 2'h3);
end
begin
ReceivePacketX(16'h0040, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0041, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0042, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0043, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0044, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
end
 
// begin
// for(ii=0; ii<10000; ii=ii+1)
// begin
// WishboneRead({22'h01, 10'b0}, data_in); // read back
// #100;
// end
// end
//join
 
//fork
/*
begin
repeat(4)
begin
wait(tb_eth_top.ethtop.wishbone.TxStatusWrite); // wait until tx status is written
@ (posedge WB_CLK_I)
#1;
end
end
*/
begin
wait(tb_eth_top.ethtop.wishbone.RxStatusWrite); // wait until rx status is written
end
 
join
 
 
/*
SendPacket(16'h0013, 1'b0);
SendPacket(16'h0014, 1'b0);
 
SendPacket(16'h0030, 1'b0);
SendPacket(16'h0031, 1'b0);
SendPacket(16'h0032, 1'b0);
SendPacket(16'h0033, 1'b0);
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0045, 1'b0);
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0017, 1'b0);
*/
 
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h3); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h2); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h1); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
// ReceivePacket(16'h0050, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0051, 1'b0, `UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0052, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0053, 1'b0, `BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0054, 1'b0, `UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0055, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0056, 1'b0, `UNICAST_WRONG_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
 
repeat(1000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
// WishboneRead({24'h04, (8'h0<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h1<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h2<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h3<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h4<<2)}, RxBD); // Read from TxBD register
 
for(jj=0; jj<3; jj=jj+1) // How many TxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2)<<2)}, bd); // Read from TxBD
$display("\n(%0t)\t\tRead TxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Ready = 0?
begin
WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read TxBD pointer
$display("\t\t\tRead TxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0}+ii, data_in); // Read data from Tx Pointer
$write("\t0x%x", data_in);
end
end
end
 
 
for(jj=0; jj<3; jj=jj+1) // How many RxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2)<<2)}, bd); // Read from RxBD
$display("\n(%0t)\t\tRead RxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Empty = 0?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read RxBD pointer
$display("\t\t\tRead RxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]+4; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0} + ii, data_in); // Read data from Rx Pointer
$write("\t0x%x", data_in);
end
end
end
 
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
 
 
 
#100000 $stop;
end
endtask //TestTxAndRx
 
 
 
 
 
task TestFullDuplex;
 
integer ii, jj;
integer data_in, bd, pointer;
integer addr;
 
begin
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR<<2}); // r_RxBDAddress = 0x80
 
WishboneWrite(32'h0000a40b, {26'h0, `ETH_MODER_ADR<<2}); // CrcEn, Pad en, full duplex, reject broadcast, RxEn, TxEn
 
WishboneWrite(32'h00000002, {26'h0, `ETH_MAC_ADDR1_ADR<<2}); // MAC = 000203040506
WishboneWrite(32'h03040506, {26'h0, `ETH_MAC_ADDR0_ADR<<2});
 
initialize_txbd(5);
initialize_rxbd(6);
send_packet(48'h000123456789, 16'h0064);
 
/*
for(ii=0; ii<12; ii=ii+1) begin
addr = 32'h400 + ii*4;
WishboneRead(addr, data_in);
$display("\n(%0t)\t\tRead TxBD %0x = 0x%x", $time, ii, data_in);
end
 
for(ii=0; ii<14; ii=ii+1) begin
addr = 32'h600 + ii*4;
WishboneRead(addr, data_in);
$display("\n(%0t)\t\tRead RxBD %0x = 0x%x", $time, ii, data_in);
end
*/
 
// WishboneRead({22'h01, 10'b0}, data_in); // read back
// WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2)<<2)}, bd); // Read from TxBD
/*
for(jj=0; jj<8; jj=jj+4)
WishboneWriteData(`TX_BUF_BASE + jj, 32'h11111111, 4'hf); // Initializing data to ff
 
for(jj=0; jj<8; jj=jj+4)
WishboneWriteData(`RX_BUF_BASE + jj, 32'h11111111, 4'hf); // Initializing data to ff
 
 
fork
begin
SendPacketX(16'h0064, 1'b0, 2'h1);
SendPacketX(16'h0065, 1'b0, 2'h2);
SendPacketX(16'h0066, 1'b0, 2'h3);
SendPacketX(16'h0067, 1'b0, 2'h0);
end
begin
ReceivePacketX(16'h0040, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0041, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0042, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0043, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0044, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
end
*/
 
//fork
/*
begin
repeat(4)
begin
wait(tb_eth_top.ethtop.wishbone.TxStatusWrite); // wait until tx status is written
@ (posedge WB_CLK_I)
#1;
end
end
*/
 
/*
begin
wait(tb_eth_top.ethtop.wishbone.RxStatusWrite); // wait until rx status is written
end
 
join
*/
 
/*
SendPacket(16'h0013, 1'b0);
SendPacket(16'h0014, 1'b0);
 
SendPacket(16'h0030, 1'b0);
SendPacket(16'h0031, 1'b0);
SendPacket(16'h0032, 1'b0);
SendPacket(16'h0033, 1'b0);
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0045, 1'b0);
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0017, 1'b0);
*/
 
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h3); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h2); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h1); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
// ReceivePacket(16'h0050, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0051, 1'b0, `UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0052, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0053, 1'b0, `BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0054, 1'b0, `UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0055, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0056, 1'b0, `UNICAST_WRONG_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
 
repeat(1000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
// WishboneRead({24'h04, (8'h0<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h1<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h2<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h3<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h4<<2)}, RxBD); // Read from TxBD register
 
/*
for(jj=0; jj<3; jj=jj+1) // How many TxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2)<<2)}, bd); // Read from TxBD
$display("\n(%0t)\t\tRead TxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Ready = 0?
begin
WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read TxBD pointer
$display("\t\t\tRead TxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0}+ii, data_in); // Read data from Tx Pointer
$write("\t0x%x", data_in);
end
end
end
 
 
for(jj=0; jj<3; jj=jj+1) // How many RxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2)<<2)}, bd); // Read from RxBD
$display("\n(%0t)\t\tRead RxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Empty = 0?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read RxBD pointer
$display("\t\t\tRead RxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]+4; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0} + ii, data_in); // Read data from Rx Pointer
$write("\t0x%x", data_in);
end
end
end
 
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
*/
 
 
#100000 $stop;
end
endtask //TestFullDuplex
 
 
 
task initialize_txbd;
input [6:0] txbd_num;
integer i, j;
integer bd_status_addr, buf_addr, bd_ptr_addr;
for(i=0; i<txbd_num; i=i+1) begin
buf_addr = `TX_BUF_BASE + i * 32'h600;
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// Initializing BD - status
if(i==txbd_num-1)
WishboneWrite(32'h00007800, bd_status_addr); // last BD: + WRAP
else
WishboneWrite(32'h00005800, bd_status_addr); // IRQ + PAD + CRC
 
WishboneWrite(buf_addr, bd_ptr_addr); // Initializing BD - pointer
end
endtask // initialize_txbd
 
 
task initialize_rxbd;
input [6:0] rxbd_num;
integer i, j;
integer bd_status_addr, buf_addr, bd_ptr_addr;
for(i=0; i<rxbd_num; i=i+1) begin
buf_addr = `RX_BUF_BASE + i * 32'h600;
bd_status_addr = `RX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// Initializing BD - status
if(i==rxbd_num-1)
WishboneWrite(32'h0000e000, bd_status_addr); // last BD: + WRAP
else
WishboneWrite(32'h0000c000, bd_status_addr); // IRQ + PAD + CRC
 
WishboneWrite(buf_addr, bd_ptr_addr); // Initializing BD - pointer
end
endtask // initialize_rxbd
 
 
 
 
 
 
reg [7:0] LateCollisionCounter;
reg EnableCollisionCounter;
// Making a late collision
 
initial
EnableCollisionCounter =0; // Collision = OFF
 
always @ (posedge MTxClk)
begin
if(tb_eth_top.ethtop.wishbone.TxStartFrm)
begin
LateCollisionCounter = 0;
end
else
if(EnableCollisionCounter)
LateCollisionCounter = LateCollisionCounter + 1;
end
 
// Making a late collision
always @ (posedge MTxClk)
begin
if(LateCollisionCounter==0)
MColl = 0;
else
if(LateCollisionCounter==150)
MColl = 1;
else
if(LateCollisionCounter==155)
begin
MColl = 0;
MCrs = 0;
EnableCollisionCounter=0;
LateCollisionCounter=1;
end
end
 
 
// Switching Carrier Sense ON and OFF
always @ (posedge MTxClk)
begin
wait(tb_eth_top.ethtop.wishbone.TxStartFrm);
MCrs=1;
wait(tb_eth_top.ethtop.wishbone.TxEndFrm || !MCrs);
MCrs=0;
end
 
 
task TestUnicast;
 
integer ii, jj;
integer data_in, bd, pointer;
 
begin
$display("\nBegin TestUnicast \n");
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR, 2'h0}); // r_RxBDAddress = 0x80
WishboneWrite(32'h0000204b, {26'h0, `ETH_MODER_ADR, 2'h0}); // RxEn, Txen, CrcEn, no Pad, r_IFG, promisc off, broadcast off
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR, 2'h0}); // r_TxFlow = 1
 
$display("\n This Uniicast packet will be rejected, wrong address in MAC Address Regs\n");
ReceivePacket(16'h0014, 1'b0,`UNICAST_XFR);
WishboneWrite(32'h03040506, {26'h0,`ETH_MAC_ADDR0_ADR ,2'h0}); // Mac Address
WishboneWrite(32'h00000002, {26'h0,`ETH_MAC_ADDR1_ADR ,2'h0}); // Mac Address
$display("\n Set Proper Unicast Address in MAC_ADDRESS regs, resend packet\n");
ReceivePacket(16'h0015, 1'b0,`UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0016, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0,`UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0018, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0019, 1'b0,`UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
repeat(5000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
WishboneRead({26'h0, `ETH_MODER_ADR}, data_in); // Read from MODER register
 
WishboneRead({22'h01, (10'h80<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h88<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h89<<2)}, data_in); // Read from RxBD register
 
 
for(jj=0; jj<5; jj=jj+1) // How many RxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2)<<2)}, bd); // Read from RxBD
$display("\n(%0t)\t\tRead RxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Empty = 0?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read RxBD pointer
$display("\t\t\tRead RxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]+4; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0} + ii, data_in); // Read data from Rx Pointer
$write("\t0x%x", data_in);
end
end
end
 
 
#100000 $stop;
$display("\nEnd TestUnicast \n");
end
endtask //TestUnicast
 
task TestMulticast;
 
integer data_in;
begin
$display("\nBegin TestMulticast \n");
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR, 2'h0}); // r_RxBDAddress = 0x80
WishboneWrite(32'h00002043, {26'h0, `ETH_MODER_ADR, 2'h0}); // RxEn, Txen, CrcEn, No Pad, r_IFG, promiscuos off, broadcast enable
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR, 2'h0}); // r_TxFlow = 1
$display("\n This Multicast packet will be rejected by Hash Filter\n");
ReceivePacket(16'h0014, 1'b0,`MULTICAST_XFR);
WishboneWrite(32'h00400000, {26'h0, `ETH_HASH1_ADR,2'h0}); // set bit 16, multicast hash 36
WishboneRead({26'h0, `ETH_HASH1_ADR, 2'h0}, data_in); // read back
$display("\n Set Hash Filter to accept this Multicast packet, resend packet\n");
ReceivePacket(16'h0015, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0016, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0018, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
repeat(5000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
WishboneRead({26'h0, `ETH_MODER_ADR}, data_in); // Read from MODER register
 
WishboneRead({22'h01, (10'h80<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
$display("\nEnd TestMulticast \n");
#100000 $stop;
end
endtask //TestMulticast
 
 
task TestBroadcast;
 
integer data_in;
 
begin
$display("\n\n\nBegin TestBroadcast");
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR, 2'h0}); // r_RxBDAddress = 0x80
 
WishboneWrite(32'h0000A04b, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Reject Broadcast, TxEn, RxEn
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR, 2'h0}); // r_TxFlow = 1
 
$display("\nThis Broadcast packet will be rejected, r_BRO = 1");
ReceivePacket(16'h0014, 1'b0,`BROADCAST_XFR);
$display("\nSet r_Bro = 0, resend packet");
WishboneWrite(32'h0000A043, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Accept Broadcast, TxEn, RxEn
ReceivePacket(16'h0015, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
$display("\n This Broadcast packet will be rejected, r_BRO = 1");
WishboneWrite(32'h0000A04b, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Reject Broadcast, TxEn, RxEn
ReceivePacket(16'h0016, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
$display("\n Set r_Bro = 0, resend packet");
WishboneWrite(32'h0000A043, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Accept Broadcast, TxEn, RxEn
ReceivePacket(16'h0018, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
repeat(5000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
WishboneRead({26'h0, `ETH_MODER_ADR}, data_in); // Read from MODER register
 
WishboneRead({22'h01, (10'h80<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
 
#100000 $stop;
$display("\nEnd TestBroadcast \n");
end
endtask //TestBroadcast
 
 
always @ (posedge WB_CLK_I)
begin
if(m_wb_cyc_o & m_wb_stb_o) // Add valid address range
begin
repeat(2) @ (posedge WB_CLK_I);
begin
m_wb_ack_i <=#Tp 1'b1;
if(~m_wb_we_o)
begin
#Tp;
if(m_wb_adr_o[1:0] == 2'b00) // word access
begin
m_wb_dat_i[31:24] = memory3[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[23:16] = memory2[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[15:08] = memory1[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[07:00] = memory0[{m_wb_adr_o[31:2], 2'h0}];
end
else if(m_wb_adr_o[1:0] == 2'b10) // half access
begin
m_wb_dat_i[31:24] = 0;
m_wb_dat_i[23:16] = 0;
m_wb_dat_i[15:08] = memory1[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[07:00] = memory0[{m_wb_adr_o[31:2], 2'h0}];
end
else if(m_wb_adr_o[1:0] == 2'b01) // byte access
begin
m_wb_dat_i[31:24] = 0;
m_wb_dat_i[23:16] = memory2[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[15:08] = 0;
m_wb_dat_i[07:00] = 0;
end
else if(m_wb_adr_o[1:0] == 2'b11) // byte access
begin
m_wb_dat_i[31:24] = 0;
m_wb_dat_i[23:16] = 0;
m_wb_dat_i[15:08] = 0;
m_wb_dat_i[07:00] = memory0[{m_wb_adr_o[31:2], 2'h0}];
end
 
$fdisplay(mcd1, "(%0t) master read (0x%0x) = 0x%0x", $time, m_wb_adr_o, m_wb_dat_i);
end
else
begin
$fdisplay(mcd2, "(%0t) master write (0x%0x) = 0x%0x", $time, m_wb_adr_o, m_wb_dat_o);
if(m_wb_sel_o[0])
memory0[m_wb_adr_o] = m_wb_dat_o[7:0];
if(m_wb_sel_o[1])
memory1[m_wb_adr_o] = m_wb_dat_o[15:8];
if(m_wb_sel_o[2])
memory2[m_wb_adr_o] = m_wb_dat_o[23:16];
if(m_wb_sel_o[3])
memory3[m_wb_adr_o] = m_wb_dat_o[31:24];
end
end
@ (posedge WB_CLK_I);
m_wb_ack_i <=#Tp 1'b0;
end
end
 
 
 
// Detecting ram_oe and ram_we being active at the same time
always @ (posedge WB_CLK_I)
begin
if(tb_eth_top.ethtop.wishbone.ram_we & tb_eth_top.ethtop.wishbone.ram_oe)
begin
$display("\n\n(%0t)ERROR: ram_we and ram_oe both activated at the same time", $time);
#1000;
$stop;
end
end
 
 
 
 
always @ (posedge WB_CLK_I)
if(tb_eth_top.ethtop.wishbone.RxStatusWrite)
$fdisplay(mcd2, ""); // newline added
 
task WishboneWrite;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~WishboneBusy);
WishboneBusy = 1;
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = Address;
WB_DAT_I = Data;
WB_WE_I = 1'b1;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
 
 
wait(WB_ACK_O); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge WB_CLK_I);
if(LogEnable)
begin
if(~Address[11] & ~Address[10])
$write("\n(%0t) Write to register (Data: 0x%x, Reg. Addr: 0x%0x)", $time, Data, Address);
else
if(~Address[11] & Address[10])
if(Address[9:2] < tb_eth_top.ethtop.r_TxBDNum)
begin
$write("\n(%0t) Write to TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", $time, Data, Address);
if(Address[9:2] == tb_eth_top.ethtop.r_TxBDNum-2'h2)
$write("(%0t) Send Control packet\n", $time);
end
else
$write("\n(%0t) Write to RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", $time, Data, Address);
else
$write("\n(%0t) WB write ?????????????? Data: 0x%x Addr: 0x%0x", $time, Data, Address);
end
#1;
WB_ADR_I = 32'hx;
WB_DAT_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
#5 WishboneBusy = 0;
end
endtask
 
 
task WishboneRead;
input [31:0] Address;
output[31:0] data;
 
begin
wait (~WishboneBusy);
WishboneBusy = 1;
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = Address;
WB_WE_I = 1'b0;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
#3;
wait(WB_ACK_O); // waiting for acknowledge response
@ (posedge WB_CLK_I);
data = WB_DAT_O;
if(~Address[11] & ~Address[10])
// $write("\n(%0t) Read from register (Data: 0x%x, Reg. Addr: 0x%0x)", $time, WB_DAT_O, Address);
$write("\n(%0t) Read from register (Data: 0x%x, Reg. Addr: 0x%0x)", $time, data, Address);
else
if(~Address[11] & Address[10])
if(Address[9:2] < tb_eth_top.ethtop.r_TxBDNum)
// ; //$write("\n(%0t) Read from TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", $time, WB_DAT_O, Address);
; //$write("\n(%0t) Read from TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", $time, data, Address);
else
// ;//$write("\n(%0t) Read from RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", $time, WB_DAT_O, Address);
;//$write("\n(%0t) Read from RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", $time, data, Address);
else
// $write("\n(%0t) WB read ????????? Data: 0x%x Addr: 0x%0x", $time, WB_DAT_O, Address);
$write("\n(%0t) WB read ????????? Data: 0x%x Addr: 0x%0x", $time, data, Address);
#1;
WB_ADR_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
#5 WishboneBusy = 0;
end
endtask
 
 
 
task WishboneReadData;
input [31:0] Address;
output[31:0] data;
 
begin
@ (posedge WB_CLK_I);
data = {memory3[Address], memory2[Address], memory1[Address], memory0[Address]};
#5;
end
endtask
 
 
task WishboneWriteData;
input [31:0] Address;
input [31:0] data;
input [3:0] Select;
 
begin
@ (posedge WB_CLK_I);
if(Select[0])
memory0[Address] = data[7:0];
if(Select[1])
memory1[Address] = data[15:8];
if(Select[2])
memory2[Address] = data[23:16];
if(Select[3])
memory3[Address] = data[31:24];
// $display("\n(%0t) Write data to memory (Data: 0x%x, Addr: 0x%0x)", $time, data, Address);
#5;
end
endtask
 
 
 
 
task SendPacket;
input [15:0] Length;
input ControlFrame;
reg Wrap;
reg [31:0] TempAddr;
reg [31:0] TempData;
reg [31:0] kk;
begin
// if(TxBDIndex == 6) // Only 3 buffer descriptors are used
// Wrap = 1'b1;
// else
Wrap = 1'b0; // At the moment no wrap bit is set
 
 
// Writing data to buffer
for(kk=0; kk<Length; kk=kk+4)
begin
TempAddr = `TX_BUF_BASE + TxBDIndex * 32'h600 + kk;
TempData = {kk[7:0], kk[7:0]+2'h1, kk[7:0]+2'h2, kk[7:0]+2'h3};
WishboneWriteData(TempAddr, TempData, 4'hf); // Writing Data to buffer that is pointed by the BD
end
 
// Writing buffer pointer
TempAddr = {22'h01, ((TxBDIndex*2'h2 + 1'b1)<<2)};
TempData = `TX_BUF_BASE + TxBDIndex * 32'h600; // 1536 bytes is reserved for one frame
WishboneWrite(TempData, TempAddr); // Writing Tx pointer
 
TempAddr = {22'h01, ((TxBDIndex*2'h2)<<2)};
TempData = {Length[15:0], 1'b1, 1'b0, Wrap, 3'h0, ControlFrame, 1'b0, TxBDIndex[7:0]}; // Ready and Wrap = 1
 
#1;
// if(TxBDIndex == 6) // Only 4 buffer descriptors are used
// TxBDIndex = 0;
// else
TxBDIndex = TxBDIndex + 1;
 
WishboneWrite(TempData, TempAddr); // Writing status to TxBD
end
endtask
 
 
 
task SendPacketX;
input [15:0] Length;
input ControlFrame;
input [1:0] AddrOffset;
reg Wrap;
reg [31:0] TempAddr;
reg [31:0] TempData;
reg [31:0] kk;
reg [3:0] Select;
begin
Wrap = 1'b0;
 
case(AddrOffset)
2'h0 : Select = 4'hf;
2'h1 : Select = 4'h7;
2'h2 : Select = 4'h3;
2'h3 : Select = 4'h1;
endcase
 
// Writing data to buffer
for(kk=0; kk<Length+4; kk=kk+4) // Length+4 is because we might start up to 3 bytes later
begin
if(kk>0)
Select = 4'hf;
TempAddr = `TX_BUF_BASE + TxBDIndex * 32'h600 + kk;
TempData = {kk[7:0]+3'h1, kk[7:0]+3'h2, kk[7:0]+3'h3, kk[7:0]+3'h4};
WishboneWriteData(TempAddr, TempData, Select); // Writing Data to buffer that is pointed by the BD
end
 
// Writing buffer pointer
TempAddr = {22'h01, ((TxBDIndex*2'h2 + 1'b1)<<2)};
TempData = `TX_BUF_BASE + TxBDIndex * 32'h600 + AddrOffset; // 1536 bytes is reserved for one frame
WishboneWrite(TempData, TempAddr); // Writing Tx pointer
 
TempAddr = {22'h01, ((TxBDIndex*2'h2)<<2)};
TempData = {Length[15:0], 1'b1, 1'b1, Wrap, 3'h0, ControlFrame, 1'b0, TxBDIndex[7:0]}; // Ready, interrupt and Wrap = 1
 
#1;
if(Wrap)
TxBDIndex = 0;
else
TxBDIndex = TxBDIndex + 1;
 
WishboneWrite(TempData, TempAddr); // Writing status to TxBD
end
endtask
 
 
task send_packet;
input [47:0] dest_addr;
input [15:0] length;
 
reg [31:0] BD, ptr;
reg [31:0] i;
reg [2:0] increment;
 
reg [31:0] TempAddr;
reg [31:0] TempData;
reg [15:0] kk;
reg [3:0] Select;
begin
bd_status_addr = `TX_BD_BASE + g_last_txbd * 8;
 
mama
WishboneRead(bd_status_addr, BD); // Read BD
WishboneRead(bd_status_addr+4, ptr); // Read buffer pointer
 
case(ptr[1:0])
2'h0 : begin Select = 4'hf; increment = 3'h4 end
2'h1 : begin Select = 4'h7; increment = 3'h3 end
2'h2 : begin Select = 4'h3; increment = 3'h2 end
2'h3 : begin Select = 4'h1; increment = 3'h1 end
endcase
 
// Writing data to buffer
for(i=ptr; i<(length+ptr); i=i+increment) // (i=0; i<length; i=i+increment)
begin
if(i>ptr) // After first write all accesses are word accesses
begin Select = 4'hf; increment=3'h4; end
 
TempAddr = `TX_BUF_BASE + TxBDIndex * 32'h600 + kk;
TempData = {i[7:0]+3'h1, i[7:0]+3'h2, i[7:0]+3'h3, i[7:0]+3'h4};
mama
WishboneWriteData(TempAddr, TempData, Select); // Writing Data to buffer that is pointed by the BD
end
 
// Writing buffer pointer
TempAddr = {22'h01, ((TxBDIndex*2'h2 + 1'b1)<<2)};
TempData = `TX_BUF_BASE + TxBDIndex * 32'h600 + AddrOffset; // 1536 bytes is reserved for one frame
WishboneWrite(TempData, TempAddr); // Writing Tx pointer
 
TempAddr = {22'h01, ((TxBDIndex*2'h2)<<2)};
TempData = {length[15:0], 1'b1, 1'b1, Wrap, 3'h0, ControlFrame, 1'b0, TxBDIndex[7:0]}; // Ready, interrupt and Wrap = 1
 
#1;
if(Wrap)
TxBDIndex = 0;
else
TxBDIndex = TxBDIndex + 1;
 
WishboneWrite(TempData, TempAddr); // Writing status to TxBD
 
if(BD & 32'h2000) // Wrap bit set ?
g_last_txbd = 0;
else
g_last_txbd = g_last_txbd+1;
 
end
endtask // send_packet
 
 
task ReceivePacket; // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
input [15:0] LengthRx;
input RxControlFrame;
input [31:0] TransferType; //Broadcast,Unicast,Multicast
reg WrapRx;
reg [31:0] TempRxAddr;
// reg [31:0] TempRxData;
integer TempRxData;
reg abc;
begin
// if(RxBDIndex == 6) // Only 3 buffer descriptors are used
// WrapRx = 1'b1;
// else
WrapRx = 1'b0;
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2 + 1'b1)<<2)};
TempRxData = `RX_BUF_BASE + RxBDIndex * 32'h600; // 1536 bytes is reserved for one frame
WishboneWrite(TempRxData, TempRxAddr); // Writing Rx pointer
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2)<<2)};
TempRxData = {16'h0, 1'b1, 1'b0, WrapRx, 5'h0, RxBDIndex[7:0]}; // Ready and WrapRx = 1 or 0
 
#1;
// if(RxBDIndex == 6) // Only 4 buffer descriptors are used
// RxBDIndex = 0;
// else
RxBDIndex = RxBDIndex + 1;
 
abc=1;
WishboneWrite(TempRxData, TempRxAddr); // Writing status to RxBD
abc=0;
 
begin
#200;
if(RxControlFrame)
GetControlDataOnMRxD(LengthRx); // LengthRx = PAUSE timer value.
else
GetDataOnMRxD(LengthRx, TransferType); // LengthRx bytes is comming on MRxD[3:0] signals
end
 
end
endtask
 
 
task ReceivePacketX; // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
input [15:0] LengthRx;
input RxControlFrame;
input [31:0] TransferType; //Broadcast,Unicast,Multicast
input [1:0] AddrOffset;
reg WrapRx;
reg [31:0] TempRxAddr;
integer TempRxData;
reg abc;
begin
WrapRx = 1'b0;
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2 + 1'b1)<<2)};
TempRxData = `RX_BUF_BASE + RxBDIndex * 32'h600 + AddrOffset; // 1536 bytes is reserved for one frame
WishboneWrite(TempRxData, TempRxAddr); // Writing Rx pointer
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2)<<2)};
TempRxData = {16'h0, 1'b1, 1'b1, WrapRx, 5'h0, RxBDIndex[7:0]}; // Ready, interrupt and WrapRx = 1 or 0
 
#1;
RxBDIndex = RxBDIndex + 1;
 
abc=1;
WishboneWrite(TempRxData, TempRxAddr); // Writing status to RxBD
abc=0;
 
begin
#200;
if(RxControlFrame)
GetControlDataOnMRxD(LengthRx); // LengthRx = PAUSE timer value.
else
GetDataOnMRxD(LengthRx, TransferType); // LengthRx bytes is comming on MRxD[3:0] signals
end
 
end
endtask
 
 
task GetDataOnMRxD;
input [15:0] Len;
input [31:0] TransferType;
integer tt;
 
begin
@ (posedge MRxClk);
MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge MRxClk);
end
MRxD=4'hd; // SFD
for(tt=1; tt<(Len+1); tt=tt+1)
begin
@ (posedge MRxClk);
if(TransferType == `UNICAST_XFR && tt == 1)
MRxD= 4'h0; // Unicast transfer
else if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[3:0]; // Multicast transfer
 
@ (posedge MRxClk);
if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[7:4];
end
 
@ (posedge MRxClk);
MRxDV=1'b0;
end
endtask
 
 
task GetControlDataOnMRxD;
input [15:0] Timer;
reg [127:0] Packet;
reg [127:0] Data;
reg [31:0] Crc;
integer tt;
 
begin
Packet = 128'h10082C000010_deadbeef0013_8880_0010; // 0180c2000001 + 8808 + 0001
Crc = 32'h6014fe08; // not a correct value
@ (posedge MRxClk);
MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge MRxClk);
end
MRxD=4'hd; // SFD
for(tt=0; tt<32; tt=tt+1)
begin
Data = Packet << (tt*4);
@ (posedge MRxClk);
MRxD=Data[127:124];
end
for(tt=0; tt<2; tt=tt+1) // timer
begin
Data[15:0] = Timer << (tt*8);
@ (posedge MRxClk);
MRxD=Data[11:8];
@ (posedge MRxClk);
MRxD=Data[15:12];
end
for(tt=0; tt<42; tt=tt+1) // padding
begin
Data[7:0] = 8'h0;
@ (posedge MRxClk);
MRxD=Data[3:0];
@ (posedge MRxClk);
MRxD=Data[3:0];
end
for(tt=0; tt<4; tt=tt+1) // crc
begin
Data[31:0] = Crc << (tt*8);
@ (posedge MRxClk);
MRxD=Data[27:24];
@ (posedge MRxClk);
MRxD=Data[31:28];
end
@ (posedge MRxClk);
MRxDV=1'b0;
end
endtask
 
task InitializeMemory;
reg [9:0] mem_addr;
begin
LogEnable = 1'b0;
$display("\n\n(%0t) Initializing Memory...", $time);
for(mem_addr=0; mem_addr<=10'h0ff; mem_addr=mem_addr+1'b1)
WishboneWrite(32'h0, {22'h01, mem_addr<<2}); // Writing status to RxBD
LogEnable = 1'b1;
end
endtask
 
 
 
 
endmodule
/verilog/eth_host.v
0,0 → 1,145
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_host.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
//
 
`include "tb_eth_defines.v"
`include "timescale.v"
 
module eth_host
(
// WISHBONE common
wb_clk_i, wb_rst_i,
// WISHBONE master
wb_adr_o, wb_sel_o, wb_we_o, wb_dat_i, wb_dat_o, wb_cyc_o, wb_stb_o, wb_ack_i, wb_err_i
);
 
parameter Tp=1;
 
input wb_clk_i, wb_rst_i;
 
input [31:0] wb_dat_i;
input wb_ack_i, wb_err_i;
 
output [31:0] wb_adr_o, wb_dat_o;
output [3:0] wb_sel_o;
output wb_cyc_o, wb_stb_o, wb_we_o;
 
reg [31:0] wb_adr_o, wb_dat_o;
reg [3:0] wb_sel_o;
reg wb_cyc_o, wb_stb_o, wb_we_o;
 
integer host_log;
 
// Reset pulse
initial
begin
host_log = $fopen("eth_host.log");
end
 
 
task wb_write;
 
input [31:0] addr;
input [3:0] sel;
input [31:0] data;
 
begin
@ (posedge wb_clk_i); // Sync. with clock
#1;
wb_adr_o = addr;
wb_dat_o = data;
wb_sel_o = sel;
wb_cyc_o = 1;
wb_stb_o = 1;
wb_we_o = 1;
wait(wb_ack_i | wb_err_i);
$fdisplay(host_log, "(%0t)(%m)wb_write (0x%0x) = 0x%0x", $time, wb_adr_o, wb_dat_o);
@ (posedge wb_clk_i); // Sync. with clock
#1;
wb_adr_o = 'hx;
wb_dat_o = 'hx;
wb_sel_o = 'hx;
wb_cyc_o = 0;
wb_stb_o = 0;
wb_we_o = 'hx;
end
endtask
 
 
task wb_read;
 
input [31:0] addr;
input [3:0] sel;
output [31:0] data;
 
begin
@ (posedge wb_clk_i); // Sync. with clock
#1;
wb_adr_o = addr;
wb_sel_o = sel;
wb_cyc_o = 1;
wb_stb_o = 1;
wb_we_o = 0;
wait(wb_ack_i | wb_err_i);
@ (posedge wb_clk_i); // Sync. with clock
data = wb_dat_i;
$fdisplay(host_log, "(%0t)(%m)wb_read (0x%0x) = 0x%0x", $time, wb_adr_o, wb_dat_i);
#1;
wb_adr_o = 'hx;
wb_sel_o = 'hx;
wb_cyc_o = 0;
wb_stb_o = 0;
wb_we_o = 'hx;
end
endtask
 
 
 
endmodule
/verilog/tb_cop.v
0,0 → 1,506
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_cop.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/??????/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
 
 
 
`include "timescale.v"
 
module tb_cop();
 
 
parameter Tp = 1;
 
 
reg wb_clk_o;
reg wb_rst_o;
 
 
// WISHBONE master 1 (input)
reg [31:0] m1_wb_adr_o;
reg [3:0] m1_wb_sel_o;
reg m1_wb_we_o;
wire [31:0] m1_wb_dat_i;
reg [31:0] m1_wb_dat_o;
reg m1_wb_cyc_o;
reg m1_wb_stb_o;
wire m1_wb_ack_i;
wire m1_wb_err_i;
 
// WISHBONE master 2 (input)
reg [31:0] m2_wb_adr_o;
reg [3:0] m2_wb_sel_o;
reg m2_wb_we_o;
wire [31:0] m2_wb_dat_i;
reg [31:0] m2_wb_dat_o;
reg m2_wb_cyc_o;
reg m2_wb_stb_o;
wire m2_wb_ack_i;
wire m2_wb_err_i;
 
// WISHBONE slave 1 (output)
wire [31:0] s1_wb_adr_i;
wire [3:0] s1_wb_sel_i;
wire s1_wb_we_i;
reg [31:0] s1_wb_dat_o;
wire [31:0] s1_wb_dat_i;
wire s1_wb_cyc_i;
wire s1_wb_stb_i;
reg s1_wb_ack_o;
reg s1_wb_err_o;
 
// WISHBONE slave 2 (output)
wire [31:0] s2_wb_adr_i;
wire [3:0] s2_wb_sel_i;
wire s2_wb_we_i;
reg [31:0] s2_wb_dat_o;
wire [31:0] s2_wb_dat_i;
wire s2_wb_cyc_i;
wire s2_wb_stb_i;
reg s2_wb_ack_o;
reg s2_wb_err_o;
 
 
reg Wishbone1Busy;
reg Wishbone2Busy;
 
reg StartTB;
 
eth_cop i_eth_cop
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE MASTER 1
.m1_wb_adr_i(m1_wb_adr_o), .m1_wb_sel_i(m1_wb_sel_o), .m1_wb_we_i (m1_wb_we_o), .m1_wb_dat_o(m1_wb_dat_i),
.m1_wb_dat_i(m1_wb_dat_o), .m1_wb_cyc_i(m1_wb_cyc_o), .m1_wb_stb_i(m1_wb_stb_o), .m1_wb_ack_o(m1_wb_ack_i),
.m1_wb_err_o(m1_wb_err_i),
 
// WISHBONE MASTER 2
.m2_wb_adr_i(m2_wb_adr_o), .m2_wb_sel_i(m2_wb_sel_o), .m2_wb_we_i (m2_wb_we_o), .m2_wb_dat_o(m2_wb_dat_i),
.m2_wb_dat_i(m2_wb_dat_o), .m2_wb_cyc_i(m2_wb_cyc_o), .m2_wb_stb_i(m2_wb_stb_o), .m2_wb_ack_o(m2_wb_ack_i),
.m2_wb_err_o(m2_wb_err_i),
 
// WISHBONE slave 1
.s1_wb_adr_o(s1_wb_adr_i), .s1_wb_sel_o(s1_wb_sel_i), .s1_wb_we_o (s1_wb_we_i), .s1_wb_cyc_o(s1_wb_cyc_i),
.s1_wb_stb_o(s1_wb_stb_i), .s1_wb_ack_i(s1_wb_ack_o), .s1_wb_err_i(s1_wb_err_o), .s1_wb_dat_i(s1_wb_dat_o),
.s1_wb_dat_o(s1_wb_dat_i),
// WISHBONE slave 2
.s2_wb_adr_o(s2_wb_adr_i), .s2_wb_sel_o(s2_wb_sel_i), .s2_wb_we_o (s2_wb_we_i), .s2_wb_cyc_o(s2_wb_cyc_i),
.s2_wb_stb_o(s2_wb_stb_i), .s2_wb_ack_i(s2_wb_ack_o), .s2_wb_err_i(s2_wb_err_o), .s2_wb_dat_i(s2_wb_dat_o),
.s2_wb_dat_o(s2_wb_dat_i)
);
 
/*
s1_wb_adr_i m_wb_adr_i
s1_wb_sel_i m_wb_sel_i
s1_wb_we_i m_wb_we_i
s1_wb_dat_o m_wb_dat_o
s1_wb_dat_i m_wb_dat_i
s1_wb_cyc_i m_wb_cyc_i
s1_wb_stb_i m_wb_stb_i
s1_wb_ack_o m_wb_ack_o
s1_wb_err_o m_wb_err_o
*/
 
 
 
initial
begin
s1_wb_ack_o = 0;
s1_wb_err_o = 0;
s1_wb_dat_o = 0;
s2_wb_ack_o = 0;
s2_wb_err_o = 0;
s2_wb_dat_o = 0;
 
// WISHBONE master 1 (input)
m1_wb_adr_o = 0;
m1_wb_sel_o = 0;
m1_wb_we_o = 0;
m1_wb_dat_o = 0;
m1_wb_cyc_o = 0;
m1_wb_stb_o = 0;
 
// WISHBONE master 2 (input)
m2_wb_adr_o = 0;
m2_wb_sel_o = 0;
m2_wb_we_o = 0;
m2_wb_dat_o = 0;
m2_wb_cyc_o = 0;
m2_wb_stb_o = 0;
 
Wishbone1Busy = 1'b0;
Wishbone2Busy = 1'b0;
end
 
 
// Reset pulse
initial
begin
wb_rst_o = 1'b1;
#100 wb_rst_o = 1'b0;
#100 StartTB = 1'b1;
end
 
 
 
// Generating WB_CLK_I clock
always
begin
wb_clk_o = 0;
forever #15 wb_clk_o = ~wb_clk_o; // 2*15 ns -> 33.3 MHz
end
 
 
integer seed_wb1, seed_wb2;
integer jj, kk;
initial
begin
seed_wb1 = 0;
seed_wb2 = 5;
end
 
 
 
 
initial
begin
wait(StartTB); // Start of testbench
fork
begin
for(jj=0; jj<100; jj=jj+1)
begin
if(seed_wb1[3:0]<4)
begin
$display("(%0t) m1 write to eth start (Data = Addr = 0x%0x)", $time, {21'h1a0000, seed_wb1[10:0]}); //0xd0000xxx
Wishbone1Write({21'h1a0000, seed_wb1[10:0]}, {21'h1a0000, seed_wb1[10:0]});
end
else
if(seed_wb1[3:0]<=7 && seed_wb1[3:0]>=4)
begin
$display("(%0t) m1 read to eth start (Addr = 0x%0x)", $time, {21'h1a0000, seed_wb1[10:0]});
Wishbone1Read({21'h1a0000, seed_wb1[10:0]});
end
else
if(seed_wb1[3:0]<=11 && seed_wb1[3:0]>=8)
begin
$display("(%0t) m1 write to memory start (Data = Addr = 0x%0x)", $time, {21'h000040, seed_wb1[10:0]}); //0x00020xxx
Wishbone1Write({21'h1a0000, seed_wb1[10:0]}, {21'h000040, seed_wb1[10:0]});
end
else
if(seed_wb1[3:0]>=12)
begin
$display("(%0t) m1 read to memory start (Addr = 0x%0x)", $time, {21'h000040, seed_wb1[10:0]});
Wishbone1Read({21'h000040, seed_wb1[10:0]});
end
#1 seed_wb1 = $random(seed_wb1);
$display("seed_wb1[4:0] = 0x%0x", seed_wb1[4:0]);
repeat(seed_wb1[4:0]) @ (posedge wb_clk_o);
end
end
 
begin
for(kk=0; kk<100; kk=kk+1)
begin
if(seed_wb2[3:0]<4)
begin
$display("(%0t) m2 write to eth start (Data = Addr = 0x%0x)", $time, {21'h1a0000, seed_wb2[10:0]}); //0xd0000xxx
Wishbone2Write({21'h1a0000, seed_wb2[10:0]}, {21'h1a0000, seed_wb2[10:0]});
end
else
if(seed_wb2[3:0]<=7 && seed_wb2[3:0]>=4)
begin
$display("(%0t) m2 read to eth start (Addr = 0x%0x)", $time, {21'h1a0000, seed_wb2[10:0]});
Wishbone2Read({21'h1a0000, seed_wb2[10:0]});
end
else
if(seed_wb2[3:0]<=11 && seed_wb2[3:0]>=8)
begin
$display("(%0t) m2 write to memory start (Data = Addr = 0x%0x)", $time, {21'h000040, seed_wb2[10:0]}); //0x00020xxx
Wishbone2Write({21'h1a0000, seed_wb2[10:0]}, {21'h000040, seed_wb2[10:0]});
end
else
if(seed_wb2[3:0]>=12)
begin
$display("(%0t) m2 read to memory start (Addr = 0x%0x)", $time, {21'h000040, seed_wb2[10:0]});
Wishbone2Read({21'h000040, seed_wb2[10:0]});
end
#1 seed_wb2 = $random(seed_wb2);
$display("seed_wb2[4:0] = 0x%0x", seed_wb2[4:0]);
repeat(seed_wb2[4:0]) @ (posedge wb_clk_o);
end
end
 
 
 
join
 
#10000 $stop;
end
 
 
 
 
 
 
 
task Wishbone1Write;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~Wishbone1Busy);
Wishbone1Busy = 1;
@ (posedge wb_clk_o);
#1;
m1_wb_adr_o = Address;
m1_wb_dat_o = Data;
m1_wb_we_o = 1'b1;
m1_wb_cyc_o = 1'b1;
m1_wb_stb_o = 1'b1;
m1_wb_sel_o = 4'hf;
 
wait(m1_wb_ack_i | m1_wb_err_i); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m1_wb_ack_i)
$display("(%0t) Master1 write cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master1 write cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m1_wb_adr_o = 32'hx;
m1_wb_dat_o = 32'hx;
m1_wb_we_o = 1'bx;
m1_wb_cyc_o = 1'b0;
m1_wb_stb_o = 1'b0;
m1_wb_sel_o = 4'hx;
#5 Wishbone1Busy = 0;
end
endtask
 
 
task Wishbone1Read;
input [31:0] Address;
reg [31:0] Data;
integer ii;
 
begin
wait (~Wishbone1Busy);
Wishbone1Busy = 1;
@ (posedge wb_clk_o);
#1;
m1_wb_adr_o = Address;
m1_wb_we_o = 1'b0;
m1_wb_cyc_o = 1'b1;
m1_wb_stb_o = 1'b1;
m1_wb_sel_o = 4'hf;
 
wait(m1_wb_ack_i | m1_wb_err_i); // waiting for acknowledge response
Data = m1_wb_dat_i;
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m1_wb_ack_i)
$display("(%0t) Master1 read cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master1 read cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m1_wb_adr_o = 32'hx;
m1_wb_dat_o = 32'hx;
m1_wb_we_o = 1'bx;
m1_wb_cyc_o = 1'b0;
m1_wb_stb_o = 1'b0;
m1_wb_sel_o = 4'hx;
#5 Wishbone1Busy = 0;
end
endtask
 
 
 
task Wishbone2Write;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~Wishbone2Busy);
Wishbone2Busy = 1;
@ (posedge wb_clk_o);
#1;
m2_wb_adr_o = Address;
m2_wb_dat_o = Data;
m2_wb_we_o = 1'b1;
m2_wb_cyc_o = 1'b1;
m2_wb_stb_o = 1'b1;
m2_wb_sel_o = 4'hf;
 
wait(m2_wb_ack_i | m2_wb_err_i); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m2_wb_ack_i)
$display("(%0t) Master2 write cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master2 write cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m2_wb_adr_o = 32'hx;
m2_wb_dat_o = 32'hx;
m2_wb_we_o = 1'bx;
m2_wb_cyc_o = 1'b0;
m2_wb_stb_o = 1'b0;
m2_wb_sel_o = 4'hx;
#5 Wishbone2Busy = 0;
end
endtask
 
 
task Wishbone2Read;
input [31:0] Address;
reg [31:0] Data;
integer ii;
 
begin
wait (~Wishbone2Busy);
Wishbone2Busy = 1;
@ (posedge wb_clk_o);
#1;
m2_wb_adr_o = Address;
m2_wb_we_o = 1'b0;
m2_wb_cyc_o = 1'b1;
m2_wb_stb_o = 1'b1;
m2_wb_sel_o = 4'hf;
 
wait(m2_wb_ack_i | m2_wb_err_i); // waiting for acknowledge response
Data = m2_wb_dat_i;
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m2_wb_ack_i)
$display("(%0t) Master2 read cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master2 read cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m2_wb_adr_o = 32'hx;
m2_wb_dat_o = 32'hx;
m2_wb_we_o = 1'bx;
m2_wb_cyc_o = 1'b0;
m2_wb_stb_o = 1'b0;
m2_wb_sel_o = 4'hx;
#5 Wishbone2Busy = 0;
end
endtask
 
 
 
 
 
 
 
 
integer seed_ack_s1, seed_ack_s2;
integer cnt_s1, cnt_s2;
initial
begin
seed_ack_s1 = 1;
cnt_s1 = 1;
seed_ack_s2 = 2;
cnt_s2 = 32'h88888888;
end
 
// Response from slave 1
always @ (posedge wb_clk_o or posedge wb_rst_o)
begin
#1 seed_ack_s1 = $random(seed_ack_s1);
wait(s1_wb_cyc_i & s1_wb_stb_i);
s1_wb_dat_o = cnt_s1;
repeat(seed_ack_s1[3:0]) @ (posedge wb_clk_o);
#Tp s1_wb_ack_o = 1'b1;
 
if(~s1_wb_we_i)
cnt_s1=cnt_s1+1;
 
@ (posedge wb_clk_o);
#Tp s1_wb_ack_o = 1'b0;
end
 
// Response from slave 2
always @ (posedge wb_clk_o or posedge wb_rst_o)
begin
#1 seed_ack_s2 = $random(seed_ack_s2);
wait(s2_wb_cyc_i & s2_wb_stb_i);
s2_wb_dat_o = cnt_s2;
repeat(seed_ack_s2[3:0]) @ (posedge wb_clk_o);
#Tp s2_wb_ack_o = 1'b1;
 
if(~s1_wb_we_i)
cnt_s2=cnt_s2+1;
 
@ (posedge wb_clk_o);
#Tp s2_wb_ack_o = 1'b0;
end
 
endmodule
 
/verilog/eth_memory.v
0,0 → 1,148
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_memory.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
//
 
`include "tb_eth_defines.v"
`include "timescale.v"
 
module eth_memory
(
wb_clk_i, wb_rst_i, wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i,
wb_stb_i, wb_ack_o, wb_err_o, wb_dat_o, wb_dat_i
);
 
parameter Tp=1;
 
input wb_clk_i, wb_rst_i;
input [31:0] wb_adr_i, wb_dat_i;
input [3:0] wb_sel_i;
input wb_we_i, wb_cyc_i, wb_stb_i;
 
output wb_ack_o, wb_err_o;
output [31:0] wb_dat_o;
 
reg wb_ack_o, wb_err_o;
reg [31:0] wb_dat_o;
 
reg [7:0] memory0 [0:65535];
reg [7:0] memory1 [0:65535];
reg [7:0] memory2 [0:65535];
reg [7:0] memory3 [0:65535];
 
integer memory_log;
 
// Reset pulse
initial
begin
memory_log = $fopen("eth_memory.log");
wb_ack_o = 0;
wb_err_o = 0;
end
 
 
always @ (posedge wb_clk_i)
begin
if(wb_cyc_i & wb_stb_i)
begin
repeat(1) @ (posedge wb_clk_i); // Waiting 3 clock cycles before ack is set
begin // (you can add some random function here)
#1;
wb_ack_o = 1'b1;
if(~wb_we_i)
begin
if(wb_adr_i[1:0] == 2'b00) // word access
begin
wb_dat_o[31:24] = memory3[wb_adr_i[17:2]];
wb_dat_o[23:16] = memory2[wb_adr_i[17:2]];
wb_dat_o[15:08] = memory1[wb_adr_i[17:2]];
wb_dat_o[07:00] = memory0[wb_adr_i[17:2]];
end
else if(wb_adr_i[1:0] == 2'b10) // half access
begin
wb_dat_o[31:24] = 0;
wb_dat_o[23:16] = 0;
wb_dat_o[15:08] = memory1[wb_adr_i[17:2]];
wb_dat_o[07:00] = memory0[wb_adr_i[17:2]];
end
else if(wb_adr_i[1:0] == 2'b01) // byte access
begin
wb_dat_o[31:24] = 0;
wb_dat_o[23:16] = memory2[wb_adr_i[17:2]];
wb_dat_o[15:08] = 0;
wb_dat_o[07:00] = 0;
end
else if(wb_adr_i[1:0] == 2'b11) // byte access
begin
wb_dat_o[31:24] = 0;
wb_dat_o[23:16] = 0;
wb_dat_o[15:08] = 0;
wb_dat_o[07:00] = memory0[wb_adr_i[17:2]];
end
 
$fdisplay(memory_log, "(%0t)(%m)wb_read (0x%0x) = 0x%0x", $time, wb_adr_i, wb_dat_o);
end
else
begin
$fdisplay(memory_log, "(%0t)(%m)wb_write (0x%0x) = 0x%0x", $time, wb_adr_i, wb_dat_i);
if(wb_sel_i[0])
memory0[wb_adr_i[17:2]] = wb_dat_i[7:0];
if(wb_sel_i[1])
memory1[wb_adr_i[17:2]] = wb_dat_i[15:8];
if(wb_sel_i[2])
memory2[wb_adr_i[17:2]] = wb_dat_i[23:16];
if(wb_sel_i[3])
memory3[wb_adr_i[17:2]] = wb_dat_i[31:24];
end
end
@ (posedge wb_clk_i);
wb_ack_o <=#Tp 1'b0;
end
end
 
 
 
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.