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