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_15/bench
- from Rev 335 to Rev 338
- ↔ Reverse comparison
Rev 335 → Rev 338
/verilog/tb_ethernet.v
0,0 → 1,17112
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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.24 2002/11/22 17:29:42 mohor |
// Flow control test almost finished. |
// |
// Revision 1.23 2002/11/22 02:12:16 mohor |
// test_mac_full_duplex_flow_control tests pretty much finished. |
// TEST 0: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL |
// FRM. AT 4 TX BD ( 10Mbps ) finished. |
// TEST 2: RECEIVE CONTROL FRAMES WITH PASSALL OPTION |
// TURNED OFF AT ONE RX BD ( 10Mbps ) finished. |
// |
// Revision 1.22 2002/11/21 13:56:50 mohor |
// test_mac_full_duplex_flow test 0 finished. Sending the control (PAUSE) frame |
// finished. |
// |
// Revision 1.21 2002/11/19 20:27:45 mohor |
// Temp version. |
// |
// Revision 1.20 2002/11/19 17:41:19 tadejm |
// Just some updates. |
// |
// Revision 1.19 2002/11/14 13:12:47 tadejm |
// Late collision is not reported any more. |
// |
// 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_control(0, 2); // 0 - 2 |
|
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 |
// receive just preamble between some packets |
if ((num_of_frames == 0) || (num_of_frames == 4) || (num_of_frames == 9)) |
begin |
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h6, 8'h55, 0, 0, 1'b0); |
@(posedge mrx_clk); |
wait (MRxDV === 1'b0); // end receive |
repeat(10) @(posedge mrx_clk); |
repeat(15) @(posedge wb_clk); |
end |
// receiving frames and checking end of them |
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 |
// check RX buffer descriptor of a packet |
if (num_of_frames >= min_tmp) |
begin |
if ( (data[15:0] !== 16'h6080) && // wrap bit |
(data[15:0] !== 16'h4080) ) // 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 > 6) |
begin |
if ( (data[15:0] !== 16'h6084) && // wrap bit |
(data[15:0] !== 16'h4084) ) // 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) // MAC does not recognize Dest. ADDR. for lengths 5, 6 => no MISS |
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) // MAC does not recognize Dest. ADDR. for length 3, 4 => no MISS, CRC ERROR |
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(" 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;// 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 |
// receive just preamble between some packets |
if ((num_of_frames == 0) || (num_of_frames == 4) || (num_of_frames == 9)) |
begin |
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h6, 8'h55, 0, 0, 1'b0); |
@(posedge mrx_clk); |
wait (MRxDV === 1'b0); // end receive |
repeat(10) @(posedge mrx_clk); |
repeat(15) @(posedge wb_clk); |
end |
// receiving frames and checking end of them |
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)) && (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'h6080) && // wrap bit |
(data[15:0] !== 16'h4080) ) // 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 > 6) |
begin |
if ( (data[15:0] !== 16'h6084) && // wrap bit |
(data[15:0] !== 16'h4084) ) // 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) // MAC does not recognize Dest. ADDR. for lengths 5, 6 => no MISS |
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) // MAC does not recognize Dest. ADDR. for length 3, 4 => no MISS, CRC ERROR |
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(" 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_control; |
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; |
integer mac_hi_addr; |
integer mac_lo_addr; |
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; |
reg PassAll; |
reg RxFlow; |
reg enable_irq_in_rxbd; |
reg [15:0] pause_value; |
begin |
// MAC FULL DUPLEX FLOW CONTROL TEST |
test_heading("MAC FULL DUPLEX FLOW CONTROL TEST"); |
$display(" "); |
$display("MAC FULL DUPLEX FLOW CONTROL 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_control: //// |
//// //// |
//// 0: Test //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1) |
begin |
|
//////////////////////////////////////////////////////////////////// |
//// //// |
//// Test inserts control frames while transmitting normal //// |
//// frames. Using 4 TX buffer decriptors ( 10Mbps ). //// |
//// //// |
//////////////////////////////////////////////////////////////////// |
if (test_num == 0) // |
begin |
// TEST 0: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL FRM. AT 4 TX BD ( 10Mbps ) |
test_name = "TEST 0: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL FRM. AT 4 TX BD ( 10Mbps )"; |
`TIME; $display(" TEST 0: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL FRM. AT 4 TX BD ( 10Mbps )"); |
|
// reset MAC completely |
hard_reset; |
// set wb slave response |
wb_slave.cycle_response(`ACK_RESPONSE, wbs_waits, wbs_retries); |
|
max_tmp = 0; |
min_tmp = 0; |
// set 4 TX buffer descriptors - must be set before TX enable |
wbm_write(`ETH_TX_BD_NUM, 32'h4, 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); |
// enable TX flow control |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_TXFLOW, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
// Set MAC address |
mac_hi_addr = 32'h00000001; |
mac_lo_addr = 32'h02030405; |
wbm_write(`ETH_MAC_ADDR1, mac_hi_addr, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
wbm_write(`ETH_MAC_ADDR0, mac_lo_addr, 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'h34; |
set_tx_packet(`MEMORY_BASE, (max_tmp - 4), st_data); // length without CRC. Writing data to the memory |
st_data = 8'h56; |
set_tx_packet((`MEMORY_BASE + max_tmp), (max_tmp - 4), st_data); // length without CRC. Writing data to the memory |
// 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; |
|
|
// Initialize one part of memory with data of control packet |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h0), 32'h0180c200, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h4), {16'h0001, mac_hi_addr[15:0]}, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h8), mac_lo_addr, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'hc), 32'h88080001, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h10), 32'h11110000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h14), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h18), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h1c), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h20), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h24), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h28), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h2c), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h30), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h34), 32'h00000000, 4'hF); |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h38), 32'h00000000, 4'hF); |
// append_tx_crc(`MEMORY_BASE + 2 * max_tmp, 60, 0); // CRC is appended after the data |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////// |
// In the following section, control frame will be sent while no other transmission is in progress.// |
// TXC interrupt won't be unmasked. // |
///////////////////////////////////////////////////////////////////////////////////////////////////// |
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data) |
begin |
test_fail("IRQ already pending!"); |
fail = fail + 1; |
`TIME; $display("*E IRQ already pending!"); |
end |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set!"); |
end |
|
// first destination address on ethernet PHY |
eth_phy.set_tx_mem_addr(0); |
// Request sending the control frame with pause value = 0x1111 |
wbm_write(`ETH_TX_CTRL, `ETH_TX_CTRL_TXPAUSERQ | 32'h1111, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
wait (MTxEn === 1'b1); // start transmit |
wait (MTxEn === 1'b0); // end transmit |
repeat(10) @ (posedge wb_clk); // wait some time |
repeat(10) @ (posedge mtx_clk); // wait some time |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data !== `ETH_INT_TXC) |
begin |
test_fail("TXC IRQ should be set!"); |
fail = fail + 1; |
`TIME; $display("*E TXC IRQ should be set!"); |
end |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set because TXC irq is masked!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set because TXC irq is masked!"); |
end |
|
// Clear TXC interrupt |
wbm_write(`ETH_INT, `ETH_INT_TXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set!"); |
end |
|
check_tx_packet((`MEMORY_BASE + 2 * max_tmp), 0, 60, tmp); |
if (tmp > 0) |
begin |
$display("Wrong data of the transmitted packet"); |
test_fail("Wrong data of the transmitted packet"); |
fail = fail + 1; |
end |
// check transmited TX packet CRC |
#1 check_tx_crc(0, 60, 1'b0, tmp); // length without CRC |
if (tmp > 0) |
begin |
$display("Wrong CRC of the transmitted packet"); |
test_fail("Wrong CRC of the transmitted packet"); |
fail = fail + 1; |
end |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////// |
// In the following section, control frame will be sent while no other transmission is in progress.// |
// TXC interrupt is unmasked. // |
///////////////////////////////////////////////////////////////////////////////////////////////////// |
|
// unmask all 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); |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data) |
begin |
test_fail("IRQ already pending!"); |
fail = fail + 1; |
`TIME; $display("*E IRQ already pending!"); |
end |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set!"); |
end |
|
// unmask only TXC interrupts |
wbm_write(`ETH_INT_MASK, `ETH_INT_TXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
// first destination address on ethernet PHY |
eth_phy.set_tx_mem_addr(0); |
// Request sending the control frame with pause value = 0x2222 |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h10), 32'h22220000, 4'hF); // Just for data test |
wbm_write(`ETH_TX_CTRL, `ETH_TX_CTRL_TXPAUSERQ | 32'h2222, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
wait (MTxEn === 1'b1); // start transmit |
wait (MTxEn === 1'b0); // end transmit |
repeat(10) @ (posedge wb_clk); // wait some time |
repeat(10) @ (posedge mtx_clk); // wait some time |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data !== `ETH_INT_TXC) |
begin |
test_fail("TXC IRQ should be set!"); |
fail = fail + 1; |
`TIME; $display("*E TXC IRQ should be set!"); |
end |
|
if (!wb_int) |
begin |
test_fail("WB INT signal should be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should be set!"); |
end |
|
// Clear TXC interrupt |
wbm_write(`ETH_INT, `ETH_INT_TXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set!"); |
end |
|
|
check_tx_packet((`MEMORY_BASE + 2 * max_tmp), 0, 60, tmp); |
if (tmp > 0) |
begin |
$display("Wrong data of the transmitted packet"); |
test_fail("Wrong data of the transmitted packet"); |
fail = fail + 1; |
end |
// check transmited TX packet CRC |
#1 check_tx_crc(0, 60, 1'b0, tmp); // length without CRC |
if (tmp > 0) |
begin |
$display("Wrong CRC of the transmitted packet"); |
test_fail("Wrong CRC of the transmitted packet"); |
fail = fail + 1; |
end |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////// |
// In the following section, control frame sending is requested while no other transmission // |
// is in progress. TXC interrupt is unmasked. // |
///////////////////////////////////////////////////////////////////////////////////////////////////// |
|
// unmask all 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); |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data) |
begin |
test_fail("IRQ already pending!"); |
fail = fail + 1; |
`TIME; $display("*E IRQ already pending!"); |
end |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set!"); |
end |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////// |
// In the following section, control frame request and data send request are both set. At the // |
// beginning control frame request will be faster than data send request, later the opposite. // |
///////////////////////////////////////////////////////////////////////////////////////////////////// |
for (i=0; i<32; i=i+1) |
begin |
// Request sending the control frame with pause value = 0x5678 |
set_tx_bd(0, 0, 16'h100, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE)); // irq, pad, crc |
set_tx_bd_wrap(0); |
// first destination address on ethernet PHY |
eth_phy.set_tx_mem_addr(0); |
set_tx_bd_ready(0, 0); |
|
wait (MTxEn === 1'b1); // start transmit |
|
repeat(i) @ (posedge mtx_clk); // We need to wait some time until TX module starts using the data (preamble stage is over) |
|
// Send control frame request |
wb_slave.wr_mem((`MEMORY_BASE + 2 * max_tmp + 8'h10), {i[3:0], i[3:0], i[3:0], i[3:0], 16'h0}, 4'hF); // Just for data test |
wbm_write(`ETH_TX_CTRL, `ETH_TX_CTRL_TXPAUSERQ | {16'h0, i[3:0], i[3:0], i[3:0], i[3:0]}, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
wait (MTxEn === 1'b0); // Wait until data frame transmission is over |
repeat(10) @ (posedge mtx_clk); // wait some time so status is written |
tmp_len = eth_phy.tx_len; // the length of a packet which was sent out first!!! |
repeat(10) @ (posedge wb_clk); // wait some time so status is written |
|
// first destination address on ethernet PHY |
eth_phy.set_tx_mem_addr(0); |
|
if(tmp_len == 64) // Control frame |
begin |
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data !== `ETH_INT_TXC) |
begin |
test_fail("TXC IRQ should be set!"); |
fail = fail + 1; |
`TIME; $display("*E TXC IRQ should be set!"); |
`TIME; $display("ETH_INT = 0x%0x", data); |
end |
end |
else |
begin |
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data !== `ETH_INT_TXB) |
begin |
test_fail("TXB IRQ should be set!"); |
fail = fail + 1; |
`TIME; $display("*E TXB IRQ should be set!"); |
`TIME; $display("ETH_INT = 0x%0x", data); |
end |
end |
|
if(tmp_len == 64) // Control frame |
check_tx_packet((`MEMORY_BASE + 2 * max_tmp), 0, 60, tmp); |
else |
check_tx_packet((`MEMORY_BASE), 0, 32'h100, tmp); |
|
if (tmp > 0) |
begin |
$display("Wrong data of the transmitted packet"); |
test_fail("Wrong data of the transmitted packet"); |
fail = fail + 1; |
end |
|
// check transmited TX packet CRC |
if(tmp_len == 64) // Control frame |
#1 check_tx_crc(0, 60, 1'b0, tmp); // length without CRC |
else |
#1 check_tx_crc(0, 32'h100, 1'b0, tmp); // length without CRC |
|
if (tmp > 0) |
begin |
$display("Wrong CRC of the transmitted packet"); |
test_fail("Wrong CRC of the transmitted packet"); |
fail = fail + 1; |
end |
|
|
wait (MTxEn === 1'b1); // start transmit of the control frame |
wait (MTxEn === 1'b0); // end transmit of the control frame |
repeat(10) @ (posedge wb_clk); // wait some time |
repeat(10) @ (posedge mtx_clk); // wait some time so status is written |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data !== (`ETH_INT_TXC | `ETH_INT_TXB)) |
begin |
test_fail("TXC and TXB IRQ should be set!"); |
fail = fail + 1; |
`TIME; $display("*E TXC and TXB IRQ should be set! (ETH_INT=0x%0x)", data); |
end |
|
if (!wb_int) |
begin |
test_fail("WB INT signal should be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should be set!"); |
end |
|
// Clear TXC and TXB interrupt |
wbm_write(`ETH_INT, `ETH_INT_TXC | `ETH_INT_TXB, 4'hF, 1, 4'h0, 4'h0); |
|
if (wb_int) |
begin |
test_fail("WB INT signal should not be set!"); |
fail = fail + 1; |
`TIME; $display("*E WB INT signal should not be set!"); |
end |
|
if(tmp_len == 64) // Control frame |
check_tx_packet((`MEMORY_BASE), 0, 32'h100, tmp); |
else |
check_tx_packet((`MEMORY_BASE + 2 * max_tmp), 0, 60, tmp); |
|
if (tmp > 0) |
begin |
$display("Wrong data of the transmitted packet"); |
test_fail("Wrong data of the transmitted packet"); |
fail = fail + 1; |
end |
|
// check transmited TX packet CRC |
if(tmp_len == 64) // Control frame |
#1 check_tx_crc(0, 32'h100, 1'b0, tmp); // length without CRC |
else |
#1 check_tx_crc(0, 60, 1'b0, tmp); // length without CRC |
|
if (tmp > 0) |
begin |
$display("Wrong CRC of the transmitted packet"); |
test_fail("Wrong CRC of the transmitted packet"); |
fail = fail + 1; |
end |
end // for loop |
|
if(fail) |
begin |
test_name = "TEST 0: FINISHED WITH ERRORS"; |
`TIME; $display(" TEST 0: FINISHED WITH ERRORS"); |
end |
else |
begin |
test_name = "TEST 0: SUCCESSFULLY FINISHED"; |
`TIME; $display(" TEST 0: SUCCESSFULLY FINISHED"); |
end |
|
if(fail == 0) |
test_ok; |
else |
fail = 0; |
|
end |
|
|
if (test_num == 1) // |
begin |
#1; |
// TEST 1: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL FRM. AT 4 TX BD ( 100Mbps ) |
test_name = "TEST 1: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL FRM. AT 4 TX BD ( 100Mbps )"; |
`TIME; $display(" TEST 1: INSERT CONTROL FRM. WHILE TRANSMITTING NORMAL FRM. AT 4 TX BD ( 100Mbps )"); |
end |
|
//////////////////////////////////////////////////////////////////// |
//// //// |
//// Receive control frames with PASSALL option turned on and //// |
//// off. Using only one RX buffer decriptor ( 10Mbps ). //// |
//// //// |
//////////////////////////////////////////////////////////////////// |
if (test_num == 2) // |
begin |
// TEST 2: RECEIVE CONTROL FRAMES WITH PASSALL OPTION TURNED ON AND OFF AT ONE RX BD ( 10Mbps ) |
test_name = "TEST 2: RECEIVE CONTROL FRAMES WITH PASSALL OPTION TURNED ON AND OFF AT ONE RX BD ( 10Mbps )"; |
`TIME; $display(" TEST 2: RECEIVE CONTROL FRAMES WITH PASSALL OPTION TURNED ON AND OFF 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_TXEN | `ETH_MODER_FULLD | `ETH_MODER_IFG | |
`ETH_MODER_PRO | `ETH_MODER_BRO, |
4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
// enable RX_FLOW control |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_RXFLOW, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
// prepare one packet of 100 bytes long |
// st_data = 8'h1A; |
// set_rx_packet(64, 100, 1'b0, 48'h1234_5678_8765, 48'hA1B2_C3D4_E5F6, 16'hE77E, st_data); |
// append_rx_crc (64, 100, 1'b0, 1'b0); // CRC for data packet |
st_data = 8'h01; |
set_tx_packet(`MEMORY_BASE + 64, 100, 8'h01); // length without CRC |
set_tx_bd(0, 0, 100, 1'b1, 1'b1, 1'b1, (`MEMORY_BASE + 64)); |
set_tx_bd_wrap(0); |
|
// 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; |
|
// RXB and RXC interrupts masked |
wbm_write(`ETH_INT_MASK, `ETH_INT_TXB | `ETH_INT_TXE | `ETH_INT_RXE | `ETH_INT_BUSY | |
`ETH_INT_TXC, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
|
// Test irq logic while RXB and RXC interrupts are masked. IRQ in RxBD is cleared |
for (i=0; i<3; i=i+1) |
begin |
pause_value = i+1; |
set_rx_control_packet(0, pause_value); // CRC already appended |
// choose generating carrier sense and collision for first and last 64 lengths of frames |
case (i) |
0: // PASSALL = 0, RXFLOW = 1, IRQ in RxBD = 1 |
begin |
PassAll=0; RxFlow=1; enable_irq_in_rxbd=1; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b1, `MEMORY_BASE); |
// Set PASSALL = 0 and RXFLOW = 0 |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_RXFLOW, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
1: // PASSALL = 1, RXFLOW = 0, IRQ in RxBD = 1 |
begin |
PassAll=1; RxFlow=0; enable_irq_in_rxbd=1; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b1, `MEMORY_BASE); |
// Set PASSALL = 0 and RXFLOW = 0 |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_PASSALL, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
2: // PASSALL = 1, RXFLOW = 0, IRQ in RxBD = 0 |
begin |
PassAll=1; RxFlow=0; enable_irq_in_rxbd=0; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b0, `MEMORY_BASE); |
// Set PASSALL = 0 and RXFLOW = 0 |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_PASSALL, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
default: |
begin |
$display("*E We should never get here !!!"); |
test_fail("We should never get here !!!"); |
fail = fail + 1; |
end |
endcase |
|
// not detect carrier sense in FD and no collision |
eth_phy.no_carrier_sense_rx_fd_detect(0); |
eth_phy.collision(0); |
|
// set wrap bit and empty bit |
set_rx_bd_wrap(127); |
set_rx_bd_empty(127, 127); |
|
fork |
begin |
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, 64, 1'b0); |
repeat(10) @(posedge mrx_clk); |
end |
begin |
wait (MRxDV === 1'b1); // start transmit |
#1 check_rx_bd(127, data); |
if (data[15] !== 1) |
begin |
$display("*E Wrong buffer descriptor's ready bit read out from MAC"); |
test_fail("Wrong buffer descriptor's ready bit read out from MAC"); |
fail = fail + 1; |
end |
|
wait (MRxDV === 1'b0); // received pause frame |
repeat(5) @(posedge mrx_clk); // Wait some time so pause is activated. |
repeat(5) @(posedge mtx_clk); // Wait some time so pause is activated. |
|
set_tx_bd_ready(0, 0); // Request sending the data. Data should not be sent when pause frame was received |
// and RxFlow enabled. |
|
|
// When we exit the while loop, status frame is received |
repeat(`ETH_TX_FIFO_DEPTH) @(eth_ma_wb_ack_i); // Waiting until TX fifo is filled. |
repeat(10) @(posedge mtx_clk); // Wait some time for tx start. |
end |
|
join |
|
#1 check_rx_bd(127, data); |
// Checking buffer descriptor |
if(PassAll) |
begin |
if(enable_irq_in_rxbd) |
begin |
if(data !== 32'h406100) // Rx BD must not be marked as EMPTY (control frame is received) |
begin |
$display("*E Rx BD is not OK. Control frame should be received because PASSALL bit is 1"); |
$display("RxBD = 0x%0x", data); |
test_fail("Rx BD is not OK. Control frame should be received because PASSALL bit is 1"); |
fail = fail + 1; |
end |
end |
else |
begin |
if(data !== 32'h402100) // Rx BD must not be marked as EMPTY (control frame is received) |
begin |
$display("*E Rx BD is not OK. Control frame should be received because PASSALL bit is 1"); |
$display("RxBD = 0x%0x", data); |
test_fail("Rx BD is not OK. Control frame should be received because PASSALL bit is 1"); |
fail = fail + 1; |
end |
end |
end |
else |
begin |
if(data !== 32'he000) // Rx BD must be marked as EMPTY (no packet received) |
begin |
$display("*E Rx BD should be marked as EMPTY because a control frame was received while PASSALL bit is 0"); |
$display("RxBD = 0x%0x", data); |
test_fail("Rx BD should be marked as EMPTY because a control frame was received while PASSALL bit is 0"); |
fail = fail + 1; |
end |
end |
|
// Checking if interrupt was generated |
if (wb_int) |
begin |
`TIME; $display("*E WB INT signal should not be set because both RXB and RXC interrupts are masked"); |
test_fail("WB INT signal should not be set because both RXB and RXC interrupts are masked"); |
fail = fail + 1; |
end |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(RxFlow) |
begin |
if(data !== (`ETH_INT_RXC)) |
begin |
test_fail("RXC is not set or multiple IRQs active!"); |
fail = fail + 1; |
`TIME; $display("*E RXC is not set or multiple IRQs active! (ETH_INT=0x%0x)", data); |
end |
// Clear RXC interrupt |
wbm_write(`ETH_INT, `ETH_INT_RXC, 4'hF, 1, 4'h0, 4'h0); |
end |
else if(enable_irq_in_rxbd) |
begin |
if(data !== (`ETH_INT_RXB)) |
begin |
test_fail("RXB is not set or multiple IRQs active!"); |
fail = fail + 1; |
`TIME; $display("*E RXB is not set or multiple IRQs active! (ETH_INT=0x%0x)", data); |
end |
// Clear RXC interrupt |
wbm_write(`ETH_INT, `ETH_INT_RXB, 4'hF, 1, 4'h0, 4'h0); |
end |
else |
begin |
if(data !== 0) |
begin |
test_fail("Some IRQs is active!"); |
fail = fail + 1; |
`TIME; $display("*E Some IRQs is active! (ETH_INT=0x%0x)", data); |
end |
end |
|
|
if(RxFlow) |
begin |
if(MTxEn) // If pause frame was received OK, transmission of the data packet should not start |
begin |
`TIME; $display("*E Transmission should not be started because pause frame was received."); |
test_fail("Transmission should not be started because pause frame was received."); |
fail = fail + 1; |
end |
while(pause_value) |
begin |
pause_value=pause_value-1; |
repeat(2*64) @(posedge mtx_clk); // Wait for the time needed for the pause (1 slot). |
if((!pause_value) && (!MTxEn)) // Transmission should be enabled now. |
begin |
`TIME; $display("*E Transmission should be started because pause passed."); |
test_fail("Transmission should be started because pause passed."); |
fail = fail + 1; |
end |
else if((pause_value) && (MTxEn)) // Transmission should not be enabled now. |
begin |
`TIME; $display("*E Transmission should still be paused."); |
test_fail("Transmission should still be paused."); |
fail = fail + 1; |
end |
end |
end |
else |
begin |
if(!MTxEn) // Pause frame was not received because RxFlow is turned off. |
begin |
`TIME; $display("*E Transmission should be started because pause frame was not received (RxFlow=0)."); |
test_fail("Transmission should be started because pause frame was not received (RxFlow=0)."); |
fail = fail + 1; |
end |
end |
|
|
wait(wb_int); // Wait antil frame transmission is over and irq generated |
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(data !== (`ETH_INT_TXB)) |
begin |
test_fail("TXB is not set or multiple IRQs active!"); |
fail = fail + 1; |
`TIME; $display("*E TXB is not set or multiple IRQs active! (ETH_INT=0x%0x)", data); |
end |
// Clear TXB interrupt |
wbm_write(`ETH_INT, `ETH_INT_TXB, 4'hF, 1, 4'h0, 4'h0); |
end |
// End: Test is irq is set while RXB and RXC interrupts are masked. |
|
|
// Now all interrupts are unmasked. Performing tests again. |
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); |
|
for (i=0; i<4; i=i+1) |
begin |
pause_value = i+1; |
set_rx_control_packet(0, pause_value); // CRC already appended |
// choose generating carrier sense and collision for first and last 64 lengths of frames |
case (i) |
0: // PASSALL = 0, RXFLOW = 0 |
begin |
PassAll=0; RxFlow=0; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b1, `MEMORY_BASE); |
// Set PASSALL = 0 and RXFLOW = 0 |
wbm_write(`ETH_CTRLMODER, 0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
1: // PASSALL = 0, RXFLOW = 1 |
begin |
PassAll=0; RxFlow=1; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b1, `MEMORY_BASE); |
// Set PASSALL = 0 and RXFLOW = 0 |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_RXFLOW, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
2: // PASSALL = 1, RXFLOW = 0 |
begin |
PassAll=1; RxFlow=0; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b1, `MEMORY_BASE); |
// Set PASSALL = 0 and RXFLOW = 0 |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_PASSALL, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
default: // 3: PASSALL = 1, RXFLOW = 1 |
begin |
PassAll=1; RxFlow=1; |
// enable interrupt generation |
set_rx_bd(127, 127, 1'b1, `MEMORY_BASE); |
// Set PASSALL = 1 and RXFLOW = 1 |
wbm_write(`ETH_CTRLMODER, `ETH_CTRLMODER_PASSALL | `ETH_CTRLMODER_RXFLOW, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
end |
endcase |
|
// not detect carrier sense in FD and no collision |
eth_phy.no_carrier_sense_rx_fd_detect(0); |
eth_phy.collision(0); |
|
// set wrap bit and empty bit |
set_rx_bd_wrap(127); |
set_rx_bd_empty(127, 127); |
|
fork |
begin |
#1 eth_phy.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, 64, 1'b0); |
repeat(10) @(posedge mrx_clk); |
end |
begin |
#1 check_rx_bd(127, data); |
wait (MRxDV === 1'b1); // start transmit |
#1 check_rx_bd(127, data); |
if (data[15] !== 1) |
begin |
$display("*E Wrong buffer descriptor's ready bit read out from MAC"); |
test_fail("Wrong buffer descriptor's ready bit read out from MAC"); |
fail = fail + 1; |
end |
|
wait (MRxDV === 1'b0); // end transmit |
repeat(50) @(posedge mrx_clk); // Wait some time so frame is received and |
repeat (100) @(posedge wb_clk); // status/irq is written. |
|
if(RxFlow) // Waiting x slot times before continuing so pause is deactivated. |
repeat(64 * 2 * pause_value) @(posedge mrx_clk); |
end |
join |
|
#1 check_rx_bd(127, data); |
|
// Checking buffer descriptor |
if(PassAll) |
begin |
if(data !== 32'h406100) // Rx BD must not be marked as EMPTY (control frame is received) |
begin |
$display("*E Rx BD is not OK. Control frame should be received because PASSALL bit is 1"); |
$display("RxBD = 0x%0x", data); |
test_fail("Rx BD is not OK. Control frame should be received because PASSALL bit is 1"); |
fail = fail + 1; |
end |
end |
else |
begin |
if(data !== 32'he000) // Rx BD must be marked as EMPTY (no packet received) |
begin |
$display("*E Rx BD should be marked as EMPTY because a control frame was received while PASSALL bit is 0"); |
$display("RxBD = 0x%0x", data); |
test_fail("Rx BD should be marked as EMPTY because a control frame was received while PASSALL bit is 0"); |
fail = fail + 1; |
end |
end |
|
// Checking if interrupt was generated |
if(RxFlow || PassAll) |
begin |
if (!wb_int) |
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) |
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 |
|
wbm_read(`ETH_INT, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); |
if(RxFlow) |
begin |
if(data !== (`ETH_INT_RXC)) |
begin |
test_fail("RXC is not set or multiple IRQs active!"); |
fail = fail + 1; |
`TIME; $display("*E RXC is not set or multiple IRQs active! (ETH_INT=0x%0x)", data); |
end |
// Clear RXC interrupt |
wbm_write(`ETH_INT, `ETH_INT_RXC, 4'hF, 1, 4'h0, 4'h0); |
end |
else if(PassAll) |
begin |
if(data !== (`ETH_INT_RXB)) |
begin |
test_fail("RXB is not set or multiple IRQs active!"); |
fail = fail + 1; |
`TIME; $display("*E RXB is not set or multiple IRQs active! (ETH_INT=0x%0x)", data); |
end |
// Clear RXB interrupt |
wbm_write(`ETH_INT, `ETH_INT_RXB, 4'hF, 1, 4'h0, 4'h0); |
end |
else |
begin |
if(data !== 0) |
begin |
test_fail("No interrupt should be set!"); |
fail = fail + 1; |
`TIME; $display("*E No interrupt should be set! (ETH_INT=0x%0x)", data); |
end |
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 |
|
|
end // for (test_num=start_task; test_num <= end_task; test_num=test_num+1) |
|
|
end |
endtask // test_mac_full_duplex_flow_control |
|
|
////////////////////////////////////////////////////////////// |
// 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_control_packet; |
input [31:0] rxpnt; |
input [15:0] PauseTV; |
integer i; |
reg [47:0] dest_addr; |
reg [47:0] source_addr; |
reg [15:0] type_len; |
reg [21:0] buffer; |
reg delta_t; |
reg [15:0] PTV; |
reg [15:0] opcode; |
begin |
buffer = rxpnt[21:0]; |
dest_addr = 48'h0180_c200_0001; |
source_addr = 48'h0708_090A_0B0C; |
type_len = 16'h8808; |
opcode = 16'h0001; |
PTV = PauseTV; |
delta_t = 0; |
for(i = 0; i < 60; 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 if (i < 16) |
begin |
eth_phy.rx_mem[buffer] = opcode[15:8]; |
opcode = opcode << 8; |
end |
else if (i < 18) |
begin |
eth_phy.rx_mem[buffer] = PTV[15:8]; |
PTV = PTV << 8; |
end |
else |
begin |
eth_phy.rx_mem[buffer] = 0; |
end |
buffer = buffer + 1; |
end |
delta_t = !delta_t; |
append_rx_crc (rxpnt, 60, 1'b0, 1'b0); // CRC for control packet |
end |
endtask // set_rx_control_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_eth_defines.v
0,0 → 1,216
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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.9 2002/10/09 13:16:51 tadejm |
// Just back-up; not completed testbench and some testcases are not |
// wotking properly yet. |
// |
// 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 */ |
|
/* TX Control Register */ |
`define ETH_TX_CTRL_TXPAUSERQ 32'h10000 /* Send PAUSE request */ |
|
|
`define TIME $display(" Time: %0t", $time) |
/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/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 |