1// 2// Copyright 2016 Ettus Research LLC 3// 4 5 6`timescale 1ns/1ps 7`define NS_PER_TICK 1 8`define NUM_TEST_CASES 13 9 10`include "sim_clks_rsts.vh" 11`include "sim_exec_report.vh" 12`include "sim_cvita_lib.svh" 13`include "sim_axi4_lib.svh" 14`include "sim_set_rb_lib.svh" 15 16module one_gig_eth_loopback_tb(); 17 `TEST_BENCH_INIT("one_gig_eth_loopback_tb",`NUM_TEST_CASES,`NS_PER_TICK) 18 19 // Define all clocks and resets 20 `DEFINE_CLK(ETH_CLK_P, 1000/125, 50) //125MHz GT transceiver clock 21 `DEFINE_RESET(GSR, 0, 100) //100ns for GSR to deassert 22 23 wire ETH_CLK_N = ~ETH_CLK_P; 24 wire SFP_LN0_P, SFP_LN0_N, SFP_LN1_P, SFP_LN1_N; 25 26 //localparam PACKET_MODE = 0; 27 localparam PORTNUM = 8'd0; 28 29 // One_gigE Loopback Topology: 30 // 31 // TB Simulus ====> |------------| |----------------| 32 // | gigE MAC | <===> | gigE PCS/PMA | <====>|| 33 // TB Checker <==== |------------| |----------------| || Loopback through 34 // || 35 // ====> |------------| |----------------| || perfect serial channel 36 // Loopback | | gigE MAC | <===> | gigE PCS/PMA | <====>|| 37 // <==== |------------| |----------------| 38 39 // Initialize DUT 40 wire gige_refclk, gige_refclk_bufg; 41 wire m_user_clk, s_user_clk; 42 wire m_channel_up, s_channel_up; 43 wire [7:0] m_gmii_txd, m_gmii_rxd; 44 wire m_gmii_tx_en, m_gmii_tx_er, m_gmii_rx_dv, m_gmii_rx_er; 45 wire m_gmii_clk; 46 wire [7:0] s_gmii_txd, s_gmii_rxd; 47 wire s_gmii_tx_en, s_gmii_tx_er, s_gmii_rx_dv, s_gmii_rx_er; 48 wire s_gmii_clk; 49 wire [15:0] m_phy_status; 50 wire [15:0] s_phy_status; 51 wire [63:0] loop_tdata; 52 wire loop_tlast, loop_tvalid, loop_tready; 53 54 55 reg independent_clock; 56 assign m_channel_up = m_phy_status[0]; 57 assign s_channel_up = s_phy_status[0]; 58 //assign m_user_clk = gmii_clk; 59 //assign s_user_clk = gmii_clk; 60 assign m_user_clk = independent_clock; 61 assign s_user_clk = independent_clock; 62 wire gt0_qplloutclk, gt0_qplloutrefclk, pma_reset; 63 64 one_gige_phy_clk_gen gige_clk_gen_i ( 65 .areset(GSR), 66 .refclk_p(ETH_CLK_P), 67 .refclk_n(ETH_CLK_N), 68 .refclk(gige_refclk), 69 .refclk_bufg(gige_refclk_bufg) 70 ); 71 72 cvita_master m_tx_chdr (.clk(m_user_clk)); 73 cvita_slave s_rx_chdr (.clk(s_user_clk)); 74 initial 75 begin 76 independent_clock <= 1'b0; 77 forever 78 begin 79 independent_clock <= 1'b0; 80 #0.5; 81 independent_clock <= 1'b1; 82 #0.5; 83 end 84 end 85 86 //----------------------------------------------------------------- 87 // MDIO Master 88 //----------------------------------------------------------------- 89 wire mdc, mdio_m2s, mdio_s2m; 90 91 mdio_master #( 92 .MDC_DIVIDER (8'd200) 93 ) mdio_master_i ( 94 .clk (m_user_clk), 95 .rst (GSR), 96 .mdc (mdc), 97 .mdio_in (mdio_s2m), 98 .mdio_out (mdio_m2s), 99 .mdio_tri (), 100 .reg_wr_req (/*reg_wr_req*/), 101 .reg_wr_addr(/*reg_wr_addr*/), 102 .reg_wr_data(/*reg_wr_data*/), 103 .reg_rd_req (/*reg_rd_req*/), 104 .reg_rd_addr(/*reg_rd_addr*/), 105 .reg_rd_data(/*reg_rd_data*/), 106 .reg_rd_resp(/*reg_rd_resp*/) 107 ); 108 109 //GT COMMON 110 one_gig_eth_pcs_pma_gt_common core_gt_common_i 111 ( 112 .GTREFCLK0_IN (gige_refclk) , 113 .QPLLLOCK_OUT (), 114 .QPLLLOCKDETCLK_IN (independent_clock), 115 .QPLLOUTCLK_OUT (gt0_qplloutclk), 116 .QPLLOUTREFCLK_OUT (gt0_qplloutrefclk), 117 .QPLLREFCLKLOST_OUT (), 118 .QPLLRESET_IN (pma_reset) 119 ); 120 121 one_gige_phy one_gige_phy_master_i 122 ( 123 .reset(GSR), // Asynchronous reset for entire core. 124 .independent_clock(independent_clock), 125 .pma_reset_out(pma_reset), 126 .gt0_qplloutclk_in(gt0_qplloutclk), 127 .gt0_qplloutrefclk_in(gt0_qplloutrefclk), 128 // Tranceiver Interface 129 .gtrefclk(gige_refclk), // Reference clock for MGT: 125MHz, very high quality. 130 .gtrefclk_bufg(gige_refclk_bufg), // Reference clock routed through a BUFG 131 .txp(SFP_LN1_P), // Differential +ve of serial transmission from PMA to PMD. 132 .txn(SFP_LN1_N), // Differential -ve of serial transmission from PMA to PMD. 133 .rxp(SFP_LN0_P), // Differential +ve for serial reception from PMD to PMA. 134 .rxn(SFP_LN0_N), // Differential -ve for serial reception from PMD to PMA. 135 // GMII Interface (client MAC <=> PCS) 136 .gmii_clk(m_gmii_clk), // Clock to client MAC. 137 .gmii_txd(m_gmii_txd), // Transmit data from client MAC. 138 .gmii_tx_en(m_gmii_tx_en), // Transmit control signal from client MAC. 139 .gmii_tx_er(m_gmii_tx_er), // Transmit control signal from client MAC. 140 .gmii_rxd(m_gmii_rxd), // Received Data to client MAC. 141 .gmii_rx_dv(m_gmii_rx_dv), // Received control signal to client MAC. 142 .gmii_rx_er(m_gmii_rx_er), // Received control signal to client MAC. 143 // Management: MDIO Interface 144 .mdc(mdc), // Management Data Clock 145 .mdio_i(mdio_m2s), // Management Data In 146 .mdio_o(mdio_s2m), // Management Data Out 147 .mdio_t(), // Management Data Tristate 148 .configuration_vector(5'd0), // Alternative to MDIO interface. 149 .configuration_valid(1'b1), // Validation signal for Config vector (MUST be 1 for proper functionality...undocumented) 150 // General IO's 151 .status_vector(m_phy_status), // Core status. 152 .signal_detect(1'b1 /*Optical module not supported*/) // Input from PMD to indicate presence of optical input. 153 ); 154 155 simple_gemac_wrapper #(.RX_FLOW_CTRL(0), .PORTNUM(PORTNUM)) simple_gemac_wrapper_master_i 156 ( 157 .clk125(m_gmii_clk), 158 .reset(GSR), 159 160 .GMII_GTX_CLK(), 161 .GMII_TX_EN(m_gmii_tx_en), 162 .GMII_TX_ER(m_gmii_tx_er), 163 .GMII_TXD(m_gmii_txd), 164 .GMII_RX_CLK(m_gmii_clk), 165 .GMII_RX_DV(m_gmii_rx_dv), 166 .GMII_RX_ER(m_gmii_rx_er), 167 .GMII_RXD(m_gmii_rxd), 168 169 .sys_clk(m_user_clk), 170 .rx_tdata(s_rx_chdr.axis.tdata), 171 .rx_tuser(/*s_rx_chdr.axis.tuser*/), 172 .rx_tlast(s_rx_chdr.axis.tlast), 173 .rx_tvalid(s_rx_chdr.axis.tvalid), 174 .rx_tready(s_rx_chdr.axis.tready), 175 .tx_tdata(m_tx_chdr.axis.tdata), 176 .tx_tuser(/*m_tx_chdr.axis_tuser*/), 177 .tx_tlast(m_tx_chdr.axis.tlast), 178 .tx_tvalid(m_tx_chdr.axis.tvalid), 179 .tx_tready(m_tx_chdr.axis.tready), 180 // Debug 181 .debug_tx(), .debug_rx() 182 ); 183 184 one_gige_phy one_gige_phy_slave_i 185 ( 186 .reset(GSR), // Asynchronous reset for entire core. 187 .independent_clock(independent_clock), 188 .pma_reset_out(), 189 .gt0_qplloutclk_in(gt0_qplloutclk), 190 .gt0_qplloutrefclk_in(gt0_qplloutrefclk), 191 // Tranceiver Interface 192 .gtrefclk(gige_refclk), // Reference clock for MGT: 125MHz, very high quality. 193 .gtrefclk_bufg(gige_refclk_bufg), // Reference clock routed through a BUFG 194 .txp(SFP_LN0_P), // Differential +ve of serial transmission from PMA to PMD. 195 .txn(SFP_LN0_N), // Differential -ve of serial transmission from PMA to PMD. 196 .rxp(SFP_LN1_P), // Differential +ve for serial reception from PMD to PMA. 197 .rxn(SFP_LN1_N), // Differential -ve for serial reception from PMD to PMA. 198 // GMII Interface (client MAC <=> PCS) 199 .gmii_clk(s_gmii_clk), // Clock to client MAC. 200 .gmii_txd(s_gmii_txd), // Transmit data from client MAC. 201 .gmii_tx_en(s_gmii_tx_en), // Transmit control signal from client MAC. 202 .gmii_tx_er(s_gmii_tx_er), // Transmit control signal from client MAC. 203 .gmii_rxd(s_gmii_rxd), // Received Data to client MAC. 204 .gmii_rx_dv(s_gmii_rx_dv), // Received control signal to client MAC. 205 .gmii_rx_er(s_gmii_rx_er), // Received control signal to client MAC. 206 // Management: MDIO Interface 207 .mdc(mdc), // Management Data Clock 208 .mdio_i(mdio_m2s), // Management Data In 209 .mdio_o(mdio_s2m), // Management Data Out 210 .mdio_t(), // Management Data Tristate 211 .configuration_vector(5'd0), // Alternative to MDIO interface. 212 .configuration_valid(1'b1), // Validation signal for Config vector (MUST be 1 for proper functionality...undocumented) 213 // General IO's 214 .status_vector(s_phy_status), // Core status. 215 .signal_detect(1'b1 /*Optical module not supported*/) // Input from PMD to indicate presence of optical input. 216 ); 217 218 simple_gemac_wrapper #(.RX_FLOW_CTRL(0), .PORTNUM(PORTNUM)) simple_gemac_wrapper_slave_i 219 ( 220 .clk125(s_gmii_clk), 221 .reset(GSR), 222 223 .GMII_GTX_CLK(), 224 .GMII_TX_EN(s_gmii_tx_en), 225 .GMII_TX_ER(s_gmii_tx_er), 226 .GMII_TXD(s_gmii_txd), 227 .GMII_RX_CLK(s_gmii_clk), 228 .GMII_RX_DV(s_gmii_rx_dv), 229 .GMII_RX_ER(s_gmii_rx_er), 230 .GMII_RXD(s_gmii_rxd), 231 232 .sys_clk(s_user_clk), 233 .rx_tdata(loop_tdata), 234 .rx_tuser(), 235 .rx_tlast(loop_tlast), 236 .rx_tvalid(loop_tvalid), 237 .rx_tready(loop_tready), 238 .tx_tdata(loop_tdata), 239 .tx_tuser(), 240 .tx_tlast(loop_tlast), 241 .tx_tvalid(loop_tvalid), 242 .tx_tready(loop_tready), 243 // Debug 244 .debug_tx(), .debug_rx() 245 ); 246 247 //Testbench variables 248 cvita_hdr_t header, header_out; 249 cvita_stats_t stats; 250 logic [63:0] crc_cache; 251 252 //------------------------------------------ 253 //Main thread for testbench execution 254 //------------------------------------------ 255 initial begin : tb_main 256 `TEST_CASE_START("Wait for reset"); 257 while (GSR) @(posedge ETH_CLK_P); 258 `TEST_CASE_DONE((~GSR)); 259 260 m_tx_chdr.push_bubble(); 261 262 `TEST_CASE_START("Wait for master channel to come up"); 263 while (m_channel_up !== 1'b1) @(posedge m_user_clk); 264 `TEST_CASE_DONE(1'b1); 265 266 `TEST_CASE_START("Wait for slave channel to come up"); 267 while (s_channel_up !== 1'b1) @(posedge s_user_clk); 268 `TEST_CASE_DONE(1'b1); 269 270 // `TEST_CASE_START("Run PRBS15 BIST"); 271 // s_bist_loopback <= PACKET_MODE; 272 // @(posedge m_user_clk); 273 // m_bist_gen <= 1'b1; 274 // m_bist_check <= 1'b1; 275 // @(posedge m_user_clk); 276 // while (m_bist_locked !== 1'b1) @(posedge m_user_clk); 277 // repeat (512) @(posedge m_user_clk); 278 // `ASSERT_ERROR(m_bist_samps>256, "BIST: Num samples incorrect"); 279 // `ASSERT_ERROR(m_bist_errors===36'd0, "BIST: Errors!"); 280 // @(posedge m_user_clk); 281 // m_bist_gen <= 1'b0; 282 // repeat (256) @(posedge m_user_clk); 283 // m_bist_check <= 1'b0; 284 // `TEST_CASE_DONE(1'b1); 285 286 repeat(1000) @(posedge m_user_clk); 287 288 header = '{ 289 pkt_type:DATA, has_time:0, eob:0, seqnum:12'h666, 290 length:0, src_sid:$random, dst_sid:$random, timestamp:64'h0}; 291 292 `TEST_CASE_START("Fill up empty FIFO then drain (short packet)"); 293 s_rx_chdr.axis.tready = 0; 294 m_tx_chdr.push_ramp_pkt(16, 64'd0, 64'h100, header); 295 s_rx_chdr.axis.tready = 1; 296 s_rx_chdr.wait_for_pkt_get_info(header_out, stats); 297 `ASSERT_ERROR(stats.count==16, "Bad packet: Length mismatch"); 298 `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong SID"); 299 `TEST_CASE_DONE(1); 300 301 `TEST_CASE_START("Fill up empty FIFO then drain (long packet)"); 302 s_rx_chdr.axis.tready = 0; 303 m_tx_chdr.push_ramp_pkt(256, 64'd0, 64'h100, header); 304 s_rx_chdr.axis.tready = 1; 305 s_rx_chdr.wait_for_pkt_get_info(header_out, stats); 306 `ASSERT_ERROR(stats.count==256, "Bad packet: Length mismatch"); 307 `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong SID"); 308 `TEST_CASE_DONE(1); 309 310 header = '{ 311 pkt_type:DATA, has_time:1, eob:0, seqnum:12'h666, 312 length:0, src_sid:$random, dst_sid:$random, timestamp:64'h0}; 313 314 `TEST_CASE_START("Concurrent read and write (single packet)"); 315 s_rx_chdr.axis.tready = 1; 316 fork 317 begin 318 m_tx_chdr.push_ramp_pkt(1000, 64'd0, 64'h100, header); 319 end 320 begin 321 s_rx_chdr.wait_for_pkt_get_info(header_out, stats); 322 end 323 join 324 crc_cache = stats.crc; //Cache CRC for future test cases 325 `ASSERT_ERROR(stats.count==1000, "Bad packet: Length mismatch"); 326 `TEST_CASE_DONE(1); 327 328 `TEST_CASE_START("Concurrent read and write (multiple packets)"); 329 s_rx_chdr.axis.tready = 1; 330 fork 331 begin 332 repeat (20) begin 333 m_tx_chdr.push_ramp_pkt(20, 64'd0, 64'h100, header); 334 m_tx_chdr.push_bubble(); 335 end 336 end 337 begin 338 repeat (20) begin 339 s_rx_chdr.wait_for_pkt_get_info(header_out, stats); 340 `ASSERT_ERROR(stats.count==20, "Bad packet: Length mismatch"); 341 `ASSERT_ERROR(crc_cache==stats.crc, "Bad packet: Wrong CRC"); 342 end 343 end 344 join 345 `TEST_CASE_DONE(1); 346 347 //`TEST_CASE_START("Validate no drops (master)"); 348 //`TEST_CASE_DONE((m_overruns === 32'd0)); 349 350 //`TEST_CASE_START("Validate no drops (slave)"); 351 //`TEST_CASE_DONE((s_overruns === 32'd0)); 352 353 //s_bist_loopback <= 1'b1; 354 355 //`TEST_CASE_START("Run PRBS15 BIST (Loopback Mode)"); 356 //@(posedge m_user_clk); 357 //m_bist_gen <= 1'b1; 358 //m_bist_rate <= 5'd4; 359 //m_bist_check <= 1'b1; 360 //@(posedge m_user_clk); 361 //while (m_bist_locked !== 1'b1) @(posedge m_user_clk); 362 //repeat (512) @(posedge m_user_clk); 363 //`ASSERT_ERROR(m_bist_samps>256, "BIST: Num samples incorrect"); 364 //`ASSERT_ERROR(m_bist_errors===36'd0, "BIST: Errors!"); 365 //@(posedge m_user_clk); 366 //m_bist_gen <= 1'b0; 367 //repeat (256) @(posedge m_user_clk); 368 //m_bist_check <= 1'b0; 369 //`TEST_CASE_DONE(1'b1); 370 371 //s_bist_loopback <= 1'b0; 372 373 //`TEST_CASE_START("Validate no drops (master)"); 374 //`TEST_CASE_DONE((m_overruns === 32'd0)); 375 376 //`TEST_CASE_START("Validate no drops (slave)"); 377 //`TEST_CASE_DONE((s_overruns === 32'd0)); 378 379 end 380 381endmodule 382