1///////////////////////////////////////////////////////////////////
2//
3// Copyright 2017 Ettus Research, A National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7// Module: n3xx_mgt_io_core
8// Description:
9//   Encapsulates the PSC/PMA, the MAC layer and the control interface
10//   for 1GbE, 10GbE and Aurora
11//
12//////////////////////////////////////////////////////////////////////
13
14module n3xx_mgt_io_core #(
15  parameter        PROTOCOL     = "10GbE",    // Must be {10GbE, 1GbE, Aurora, Disabled}
16  parameter        REG_BASE     = 0,
17  parameter        REG_DWIDTH   = 32,
18  parameter        REG_AWIDTH   = 14,
19  parameter        GT_COMMON    = 1,
20  parameter [7:0]  PORTNUM      = 8'd0,
21  parameter        MDIO_EN      = 0,
22  parameter [4:0]  MDIO_PHYADDR = 5'd0
23)(
24  // Resets
25  input                   areset,
26  input                   bus_rst,
27  // Clocks
28  input                   gt_refclk,
29  input                   gb_refclk,
30  input                   misc_clk,
31  input                   bus_clk,
32  input                   user_clk,
33  input                   sync_clk,
34  // SFP high-speed IO
35  output                  txp,
36  output                  txn,
37  input                   rxp,
38  input                   rxn,
39  // SFP low-speed IO
40  input                   sfpp_rxlos,
41  input                   sfpp_tx_fault,
42  output                  sfpp_tx_disable,
43  // Data port: Ethernet TX
44  input  [63:0]           s_axis_tdata,
45  input  [3:0]            s_axis_tuser,
46  input                   s_axis_tlast,
47  input                   s_axis_tvalid,
48  output                  s_axis_tready,
49  // Data port: Ethernet RX
50  output [63:0]           m_axis_tdata,
51  output [3:0]            m_axis_tuser,
52  output                  m_axis_tlast,
53  output                  m_axis_tvalid,
54  input                   m_axis_tready,
55  // Register port
56  input                   reg_wr_req,
57  input  [REG_AWIDTH-1:0] reg_wr_addr,
58  input  [REG_DWIDTH-1:0] reg_wr_data,
59  input                   reg_rd_req,
60  input  [REG_AWIDTH-1:0] reg_rd_addr,
61  output                  reg_rd_resp,
62  output [REG_DWIDTH-1:0] reg_rd_data,
63  // GT Common
64  input                   qpllrefclklost,
65  input                   qplllock,
66  input                   qplloutclk,
67  input                   qplloutrefclk,
68  input                   mmcm_locked,
69  output                  qpllreset,
70  output                  gt_pll_lock,
71  output                  gt_tx_out_clk_unbuf,
72
73  // Misc
74  output [31:0]           port_info,
75  output                  link_up,
76  output reg              activity
77);
78
79  //-----------------------------------------------------------------
80  // Registers
81  //-----------------------------------------------------------------
82  localparam [7:0] COMPAT_NUM         = 8'd2;
83
84  // Common registers
85  localparam [REG_AWIDTH-1:0] REG_PORT_INFO            = REG_BASE + 'h0;
86  localparam [REG_AWIDTH-1:0] REG_MAC_CTRL_STATUS      = REG_BASE + 'h4;
87  localparam [REG_AWIDTH-1:0] REG_PHY_CTRL_STATUS      = REG_BASE + 'h8;
88  localparam [REG_AWIDTH-1:0] REG_MAC_LED_CTL          = REG_BASE + 'hC;
89
90  // Ethernet specific
91  localparam [REG_AWIDTH-1:0] REG_ETH_MDIO_BASE        = REG_BASE + 'h10;
92  // Aurora specific
93  localparam [REG_AWIDTH-1:0] REG_AURORA_OVERRUNS      = REG_BASE + 'h20;
94  localparam [REG_AWIDTH-1:0] REG_CHECKSUM_ERRORS      = REG_BASE + 'h24;
95  localparam [REG_AWIDTH-1:0] REG_BIST_CHECKER_SAMPS   = REG_BASE + 'h28;
96  localparam [REG_AWIDTH-1:0] REG_BIST_CHECKER_ERRORS  = REG_BASE + 'h2C;
97
98  wire                  reg_rd_resp_mdio;
99  reg                   reg_rd_resp_glob = 1'b0;
100  wire [REG_DWIDTH-1:0] reg_rd_data_mdio;
101  reg  [REG_DWIDTH-1:0] reg_rd_data_glob = 32'h0;
102
103  // Protocol specific constants
104  wire [7:0]  mgt_protocol;
105  wire [31:0] mac_ctrl_rst_val, phy_ctrl_rst_val;
106  wire [1:0]  mac_led_ctl_rst_val = 2'h0;
107
108  // Flush logic: If the link is not up, we will flush all packets coming from
109  // the device. This avoids the MAC backpressuring when the PHY is down.
110  // The device will always send discovery packets to the transports during
111  // initialization, and they have no way of knowing if it's safe to travel
112  // down this route. c2mac == "CHDR to MAC"
113  wire  [63:0]     c2mac_tdata;
114  wire  [3:0]      c2mac_tuser;
115  wire             c2mac_tlast;
116  wire             c2mac_tvalid;
117  wire             c2mac_tready;
118
119  axis_packet_flush #(
120    .WIDTH(64+3), // tdata + tuser
121    .TIMEOUT_W(1), // Not using timeout
122    .FLUSH_PARTIAL_PKTS(0),
123    .PIPELINE("NONE")
124  ) linkup_flush (
125    .clk(bus_clk),
126    .reset(bus_rst),
127    .enable(~link_up), // enable flushing when link down
128    .timeout(1'b0),
129    .flushing(/* not required */),
130    .done(/* not required */),
131    // Input from device/crossbar
132    .s_axis_tdata  ({s_axis_tuser, s_axis_tdata}),
133    .s_axis_tlast  (s_axis_tlast),
134    .s_axis_tvalid (s_axis_tvalid),
135    .s_axis_tready (s_axis_tready),
136    // Output to MAC
137    .m_axis_tdata  ({c2mac_tuser, c2mac_tdata}),
138    .m_axis_tlast  (c2mac_tlast),
139    .m_axis_tvalid (c2mac_tvalid),
140    .m_axis_tready (c2mac_tready)
141  );
142
143  generate
144    if (PROTOCOL == "Aurora") begin
145      assign mgt_protocol     = 8'd3;
146      assign mac_ctrl_rst_val = 32'h0;
147      assign phy_ctrl_rst_val = 32'h0;
148    end else if (PROTOCOL == "10GbE") begin
149      assign mgt_protocol     = 8'd2;
150      assign mac_ctrl_rst_val = {31'h0, 1'b1}; // tx_enable on reset
151      assign phy_ctrl_rst_val = 32'h0;
152    end else if (PROTOCOL == "1GbE") begin
153      assign mgt_protocol     = 8'd1;
154      assign mac_ctrl_rst_val = {31'h0, 1'b1}; // tx_enable on reset
155      assign phy_ctrl_rst_val = 32'h0;
156    end else begin
157      assign mgt_protocol     = 8'd0;
158      assign mac_ctrl_rst_val = 32'h0;
159      assign phy_ctrl_rst_val = 32'h0;
160    end
161  endgenerate
162
163  // Writable registers
164  reg [31:0] mac_ctrl_reg = 32'h0;
165  reg [31:0] phy_ctrl_reg = 32'h0;
166  reg [1:0]  mac_led_ctl  =  2'h0;
167
168  always @(posedge bus_clk) begin
169    if (bus_rst) begin
170      mac_ctrl_reg <= mac_ctrl_rst_val;
171      phy_ctrl_reg <= phy_ctrl_rst_val;
172      mac_led_ctl  <= mac_led_ctl_rst_val;
173    end else if (reg_wr_req) begin
174      case(reg_wr_addr)
175        REG_MAC_CTRL_STATUS:
176          mac_ctrl_reg <= reg_wr_data;
177        REG_PHY_CTRL_STATUS:
178          phy_ctrl_reg <= reg_wr_data;
179        REG_MAC_LED_CTL:
180          mac_led_ctl <= reg_wr_data[1:0];
181      endcase
182    end
183  end
184
185  // Readable registers
186  wire [31:0] overruns;
187  wire [31:0] checksum_errors;
188  wire [47:0] bist_checker_samps;
189  wire [47:0] bist_checker_errors;
190  wire [31:0] mac_status, phy_status;
191  wire [31:0] mac_status_bclk, phy_status_bclk;
192
193  assign port_info = {COMPAT_NUM, 6'h0, activity, link_up, mgt_protocol, PORTNUM};
194
195  always @(posedge bus_clk) begin
196    // No reset handling needed for readback
197    if (reg_rd_req) begin
198      reg_rd_resp_glob <= 1'b1;
199      case(reg_rd_addr)
200        REG_PORT_INFO:
201          reg_rd_data_glob <= port_info;
202        REG_MAC_CTRL_STATUS:
203          reg_rd_data_glob <= mac_status_bclk;
204        REG_PHY_CTRL_STATUS:
205          reg_rd_data_glob <= phy_status_bclk;
206        REG_MAC_LED_CTL:
207          reg_rd_data_glob <= {30'd0, mac_led_ctl};
208        REG_AURORA_OVERRUNS:
209          reg_rd_data_glob <= overruns;
210        REG_CHECKSUM_ERRORS:
211          reg_rd_data_glob <= checksum_errors;
212        REG_BIST_CHECKER_SAMPS:
213          reg_rd_data_glob <= bist_checker_samps[47:16];  //Scale num samples by 2^16
214        REG_BIST_CHECKER_ERRORS:
215          reg_rd_data_glob <= bist_checker_errors[31:0];  //Don't scale errors
216        default:
217          reg_rd_resp_glob <= 1'b0;
218      endcase
219    end if (reg_rd_resp_glob) begin
220      reg_rd_resp_glob <= 1'b0;
221    end
222  end
223
224  synchronizer #( .STAGES(2), .WIDTH(32), .INITIAL_VAL(32'h0) ) mac_status_sync_i (
225     .clk(bus_clk), .rst(1'b0), .in(mac_status), .out(mac_status_bclk)
226  );
227
228  synchronizer #( .STAGES(2), .WIDTH(32), .INITIAL_VAL(32'h0) ) phy_status_sync_i (
229     .clk(bus_clk), .rst(1'b0), .in(phy_status), .out(phy_status_bclk)
230  );
231
232  // Regport Mux for response
233  regport_resp_mux #(
234    .WIDTH      (REG_DWIDTH),
235    .NUM_SLAVES (2)
236  ) reg_resp_mux_i (
237    .clk(bus_clk), .reset(bus_rst),
238    .sla_rd_resp({reg_rd_resp_mdio, reg_rd_resp_glob}),
239    .sla_rd_data({reg_rd_data_mdio, reg_rd_data_glob}),
240    .mst_rd_resp(reg_rd_resp), .mst_rd_data(reg_rd_data)
241  );
242
243  //-----------------------------------------------------------------
244  // Ethernet Specific: MDIO
245  //-----------------------------------------------------------------
246
247  wire mdc, mdio_m2s, mdio_s2m, mdio_s2m_sync;
248  generate
249    if ((PROTOCOL == "10GbE" || PROTOCOL == "1GbE") && (MDIO_EN == 1)) begin
250      mdio_master #(
251        .REG_BASE     (REG_ETH_MDIO_BASE),
252        .REG_AWIDTH   (REG_AWIDTH),
253        .MDC_DIVIDER  (8'd200)
254      ) mdio_master_i (
255        .clk          (bus_clk),
256        .rst          (bus_rst),
257        .mdc          (mdc),
258        .mdio_in      (mdio_s2m_sync),
259        .mdio_out     (mdio_m2s),
260        .mdio_tri     (),
261        .reg_wr_req   (reg_wr_req),
262        .reg_wr_addr  (reg_wr_addr),
263        .reg_wr_data  (reg_wr_data),
264        .reg_rd_req   (reg_rd_req),
265        .reg_rd_addr  (reg_rd_addr),
266        .reg_rd_data  (reg_rd_data_mdio),
267        .reg_rd_resp  (reg_rd_resp_mdio)
268      );
269
270      // We can cross mdio_s2m into the bus_clk domain. A synchronizer is safe
271      // here because the bit is inherently async
272      synchronizer #(.INITIAL_VAL(1'b0)) mdio_s2m_sync_i (
273        .clk(bus_clk), .rst(1'b0 /* no reset */), .in(mdio_s2m), .out(mdio_s2m_sync)
274      );
275    end else begin
276      assign mdc              = 1'b0;
277      assign mdio_m2s         = 1'b0;
278      assign reg_rd_resp_mdio = 1'b0;
279      assign reg_rd_data_mdio = 32'h0;
280    end
281  endgenerate
282
283  generate
284    if (PROTOCOL == "10GbE") begin
285      //-----------------------------------------------------------------
286      // 10 Gigabit Ethernet
287      //-----------------------------------------------------------------
288      wire [63:0] xgmii_txd;
289      wire [7:0]  xgmii_txc;
290      wire [63:0] xgmii_rxd;
291      wire [7:0]  xgmii_rxc;
292      wire        xge_phy_resetdone;
293
294      if (GT_COMMON == 1) begin
295        ten_gige_phy ten_gige_phy_i (
296          // Clocks and Reset
297          .areset(areset | phy_ctrl_reg[0]), // Asynchronous reset for entire core.
298          .refclk(gt_refclk),              // Transciever reference clock: 156.25MHz
299          .clk156(gb_refclk),              // Globally buffered core clock: 156.25MHz
300          .dclk(misc_clk),                 // Management/DRP clock: 78.125MHz
301          .sim_speedup_control(1'b0),
302          // GMII Interface (client MAC <=> PCS)
303          .xgmii_txd(xgmii_txd),          // Transmit data from client MAC.
304          .xgmii_txc(xgmii_txc),          // Transmit control signal from client MAC.
305          .xgmii_rxd(xgmii_rxd),          // Received Data to client MAC.
306          .xgmii_rxc(xgmii_rxc),          // Received control signal to client MAC.
307          // Tranceiver Interface
308          .txp(txp),                       // Differential +ve of serial transmission from PMA to PMD.
309          .txn(txn),                       // Differential -ve of serial transmission from PMA to PMD.
310          .rxp(rxp),                       // Differential +ve for serial reception from PMD to PMA.
311          .rxn(rxn),                       // Differential -ve for serial reception from PMD to PMA.
312          // Management: MDIO Interface
313          .mdc(mdc),                       // Management Data Clock
314          .mdio_in(mdio_m2s),              // Management Data In
315          .mdio_out(mdio_s2m),             // Management Data Out
316          .mdio_tri(),                     // Management Data Tristate
317          .prtad(MDIO_PHYADDR),            // MDIO address
318          // General IO's
319          .core_status(phy_status[7:0]),      // Core status
320          .resetdone(xge_phy_resetdone),
321          .signal_detect(~sfpp_rxlos),     // Input from PMD to indicate presence of optical input.   (Undocumented, but it seems Xilinx expect this to be inverted.)
322          .tx_fault(sfpp_tx_fault),
323          .tx_disable(sfpp_tx_disable),
324          .qpllreset(qpllreset),
325          .qplllock(qplllock),
326          .qplloutclk(qplloutclk),
327          .qplloutrefclk(qplloutrefclk),
328          .tx_out_clk(gt_tx_out_clk_unbuf)
329        );
330      end else begin
331        ten_gige_phy ten_gige_phy_i (
332          // Clocks and Reset
333          .areset(areset | phy_ctrl_reg[0]), // Asynchronous reset for entire core.
334          .refclk(gt_refclk),              // Transciever reference clock: 156.25MHz
335          .clk156(gb_refclk),              // Globally buffered core clock: 156.25MHz
336          .dclk(misc_clk),                 // Management/DRP clock: 78.125MHz
337          .sim_speedup_control(1'b0),
338          // GMII Interface (client MAC <=> PCS)
339          .xgmii_txd(xgmii_txd),          // Transmit data from client MAC.
340          .xgmii_txc(xgmii_txc),          // Transmit control signal from client MAC.
341          .xgmii_rxd(xgmii_rxd),          // Received Data to client MAC.
342          .xgmii_rxc(xgmii_rxc),          // Received control signal to client MAC.
343          // Tranceiver Interface
344          .txp(txp),                       // Differential +ve of serial transmission from PMA to PMD.
345          .txn(txn),                       // Differential -ve of serial transmission from PMA to PMD.
346          .rxp(rxp),                       // Differential +ve for serial reception from PMD to PMA.
347          .rxn(rxn),                       // Differential -ve for serial reception from PMD to PMA.
348          // Management: MDIO Interface
349          .mdc(mdc),                       // Management Data Clock
350          .mdio_in(mdio_m2s),              // Management Data In
351          .mdio_out(mdio_s2m),             // Management Data Out
352          .mdio_tri(),                     // Management Data Tristate
353          .prtad(MDIO_PHYADDR),            // MDIO address
354          // General IO's
355          .core_status(phy_status[7:0]),      // Core status
356          .resetdone(xge_phy_resetdone),
357          .signal_detect(~sfpp_rxlos),     // Input from PMD to indicate presence of optical input.   (Undocumented, but it seems Xilinx expect this to be inverted.)
358          .tx_fault(sfpp_tx_fault),
359          .tx_disable(sfpp_tx_disable)
360        );
361        assign qpllreset = 1'b0;
362        assign gt_pll_lock = 1'b0;
363        assign gt_tx_out_clk_unbuf = 1'b0;
364      end
365
366      xge_mac_wrapper #(
367        .PORTNUM(PORTNUM),
368        .WISHBONE(0)
369      ) xge_mac_wrapper_i (
370        // XGMII
371        .xgmii_clk(gb_refclk),
372        .xgmii_txd(xgmii_txd),
373        .xgmii_txc(xgmii_txc),
374        .xgmii_rxd(xgmii_rxd),
375        .xgmii_rxc(xgmii_rxc),
376        // Client FIFO Interfaces
377        .sys_clk(bus_clk),
378        .sys_rst(bus_rst),
379        .rx_tdata(m_axis_tdata),
380        .rx_tuser(m_axis_tuser),
381        .rx_tlast(m_axis_tlast),
382        .rx_tvalid(m_axis_tvalid),
383        .rx_tready(m_axis_tready),
384        .tx_tdata(c2mac_tdata),
385        .tx_tuser(c2mac_tuser),   // Bit[3] (error) is ignored for now.
386        .tx_tlast(c2mac_tlast),
387        .tx_tvalid(c2mac_tvalid),
388        .tx_tready(c2mac_tready),
389        // Other
390        .phy_ready(xge_phy_resetdone),
391        .ctrl_tx_enable(mac_ctrl_reg[0]),
392        .status_crc_error(mac_status[0]),
393        .status_fragment_error(mac_status[1]),
394        .status_txdfifo_ovflow(mac_status[2]),
395        .status_txdfifo_udflow(mac_status[3]),
396        .status_rxdfifo_ovflow(mac_status[4]),
397        .status_rxdfifo_udflow(mac_status[5]),
398        .status_pause_frame_rx(mac_status[6]),
399        .status_local_fault(mac_status[7]),
400        .status_remote_fault(mac_status[8]),
401        .wb_ack_o(),
402        .wb_dat_o(),
403        .wb_adr_i(1'b0),
404        .wb_clk_i(1'b0),
405        .wb_cyc_i(1'b0),
406        .wb_dat_i(1'b0),
407        .wb_rst_i(1'b0),
408        .wb_stb_i(1'b0),
409        .wb_we_i (1'b0),
410        .wb_int_o()
411      );
412
413      assign phy_status[31:8] = 24'h0;
414      assign mac_status[31:9] = 23'h0;
415      assign link_up = phy_status_bclk[0];
416
417    end else if (PROTOCOL == "1GbE") begin
418
419      //-----------------------------------------------------------------
420      // 1 Gigabit Ethernet
421      //-----------------------------------------------------------------
422      wire [7:0]  gmii_txd, gmii_rxd;
423      wire        gmii_tx_en, gmii_tx_er, gmii_rx_dv, gmii_rx_er;
424      wire        gmii_clk;
425      wire        gt0_qplloutclk, gt0_qplloutrefclk; //unused in 7-series Zynq
426
427      assign gt0_qplloutclk = 1'b0;
428      assign gt0_qplloutrefclk = 1'b0;
429      assign sfpp_tx_disable = 1'b0; // Always on.
430
431      if (GT_COMMON == 1) begin
432        one_gige_phy one_gige_phy_i (
433          .reset(areset | phy_ctrl_reg[0]),                  // Asynchronous reset for entire core.
434          .independent_clock(bus_clk),
435          .pma_reset_out(/*unused*/),
436          .gt0_qplloutclk_in(gt0_qplloutclk),
437          .gt0_qplloutrefclk_in(gt0_qplloutrefclk),
438          // Tranceiver Interface
439          .gtrefclk(gt_refclk),           // Reference clock for MGT: 125MHz, very high quality.
440          .gtrefclk_bufg(gb_refclk),      // Reference clock routed through a BUFG
441          .txp(txp),                      // Differential +ve of serial transmission from PMA to PMD.
442          .txn(txn),                      // Differential -ve of serial transmission from PMA to PMD.
443          .rxp(rxp),                      // Differential +ve for serial reception from PMD to PMA.
444          .rxn(rxn),                      // Differential -ve for serial reception from PMD to PMA.
445          // GMII Interface (client MAC <=> PCS)
446          .gmii_clk(gmii_clk),            // Clock to client MAC.
447          .gmii_txd(gmii_txd),            // Transmit data from client MAC.
448          .gmii_tx_en(gmii_tx_en),        // Transmit control signal from client MAC.
449          .gmii_tx_er(gmii_tx_er),        // Transmit control signal from client MAC.
450          .gmii_rxd(gmii_rxd),            // Received Data to client MAC.
451          .gmii_rx_dv(gmii_rx_dv),        // Received control signal to client MAC.
452          .gmii_rx_er(gmii_rx_er),        // Received control signal to client MAC.
453          // Management: MDIO Interface
454          .mdc(mdc),                      // Management Data Clock
455          .mdio_i(mdio_m2s),              // Management Data In
456          .mdio_o(mdio_s2m),              // Management Data Out
457          .mdio_t(),                      // Management Data Tristate
458          .phyaddr(MDIO_PHYADDR),         // MDIO address
459          .configuration_vector(5'd0),    // Alternative to MDIO interface.
460          .configuration_valid(1'b1),     // Validation signal for Config vector (MUST be 1 for proper functionality...undocumented)
461          // General IO's
462          .status_vector(phy_status[15:0]),    // Core status.
463          .signal_detect(1'b1 /*Optical module not supported*/) // Input from PMD to indicate presence of optical input.
464        );
465      end else begin
466        one_gige_phy one_gige_phy_i (
467          .reset(areset | phy_ctrl_reg[0]),                  // Asynchronous reset for entire core.
468          .independent_clock(bus_clk),
469          // Tranceiver Interface
470          .gtrefclk(gt_refclk),           // Reference clock for MGT: 125MHz, very high quality.
471          .gtrefclk_bufg(gb_refclk),      // Reference clock routed through a BUFG
472          .txp(txp),                      // Differential +ve of serial transmission from PMA to PMD.
473          .txn(txn),                      // Differential -ve of serial transmission from PMA to PMD.
474          .rxp(rxp),                      // Differential +ve for serial reception from PMD to PMA.
475          .rxn(rxn),                      // Differential -ve for serial reception from PMD to PMA.
476          // GMII Interface (client MAC <=> PCS)
477          .gmii_clk(gmii_clk),            // Clock to client MAC.
478          .gmii_txd(gmii_txd),            // Transmit data from client MAC.
479          .gmii_tx_en(gmii_tx_en),        // Transmit control signal from client MAC.
480          .gmii_tx_er(gmii_tx_er),        // Transmit control signal from client MAC.
481          .gmii_rxd(gmii_rxd),            // Received Data to client MAC.
482          .gmii_rx_dv(gmii_rx_dv),        // Received control signal to client MAC.
483          .gmii_rx_er(gmii_rx_er),        // Received control signal to client MAC.
484          // Management: MDIO Interface
485          .mdc(mdc),                      // Management Data Clock
486          .mdio_i(mdio_m2s),              // Management Data In
487          .mdio_o(mdio_s2m),              // Management Data Out
488          .mdio_t(),                      // Management Data Tristate
489          .phyaddr(MDIO_PHYADDR),         // MDIO address
490          .configuration_vector(5'd0),    // Alternative to MDIO interface.
491          .configuration_valid(1'b1),     // Validation signal for Config vector (MUST be 1 for proper functionality...undocumented)
492          // General IO's
493          .status_vector(phy_status[15:0]),    // Core status.
494          .signal_detect(1'b1 /*Optical module not supported*/) // Input from PMD to indicate presence of optical input.
495        );
496        assign qpllreset = 1'b0;
497        assign gt_pll_lock = 1'b0;
498        assign gt_tx_out_clk_unbuf = 1'b0;
499      end
500
501      simple_gemac_wrapper #(.RX_FLOW_CTRL(0), .PORTNUM(PORTNUM)) simple_gemac_wrapper_i
502      (
503        .clk125(gmii_clk),
504        .reset(areset),
505
506        .GMII_GTX_CLK(),
507        .GMII_TX_EN(gmii_tx_en),
508        .GMII_TX_ER(gmii_tx_er),
509        .GMII_TXD(gmii_txd),
510        .GMII_RX_CLK(gmii_clk),
511        .GMII_RX_DV(gmii_rx_dv),
512        .GMII_RX_ER(gmii_rx_er),
513        .GMII_RXD(gmii_rxd),
514
515        .sys_clk(bus_clk),
516        .rx_tdata(m_axis_tdata),
517        .rx_tuser(m_axis_tuser),
518        .rx_tlast(m_axis_tlast),
519        .rx_tvalid(m_axis_tvalid),
520        .rx_tready(m_axis_tready),
521        .tx_tdata(c2mac_tdata),
522        .tx_tuser(c2mac_tuser),
523        .tx_tlast(c2mac_tlast),
524        .tx_tvalid(c2mac_tvalid),
525        .tx_tready(c2mac_tready),
526
527        .wb_clk_i(1'b0),
528        .wb_rst_i(1'b0),
529        .wb_adr_i(8'h0),
530        .wb_dat_i(32'h0),
531        .wb_we_i(1'b0),
532        .wb_stb_i(1'b0),
533        .wb_cyc_i(1'b0),
534        .wb_dat_o(),
535        .wb_ack_o(),
536        .wb_int_o(),
537        .mdc(),
538        .mdio_out(1'b0),
539        .mdio_tri(),
540        .mdio_in(),
541        .debug_tx(),
542        .debug_rx()
543      );
544
545      assign phy_status[31:16] = 16'h0;
546      assign mac_status[31:0]  = 32'h0;
547      assign link_up = phy_status_bclk[0];
548
549      assign gt_tx_out_clk_unbuf = 1'b0;
550
551    end else if (PROTOCOL == "Aurora") begin
552
553      //-----------------------------------------------------------------
554      // Aurora
555      //-----------------------------------------------------------------
556      wire        user_rst;
557      wire [63:0] m2p_tdata, p2m_tdata;
558      wire        m2p_tvalid, m2p_tready, p2m_tvalid;
559      wire        channel_up, hard_err, soft_err, mac_crit_err;
560
561      wire        bist_checker_en  = mac_ctrl_reg[0];
562      wire        bist_gen_en      = mac_ctrl_reg[1];
563      wire        bist_loopback_en = mac_ctrl_reg[2];
564      wire [5:0]  bist_gen_rate    = mac_ctrl_reg[8:3];
565      wire        phy_areset       = mac_ctrl_reg[9];
566      wire        mac_clear        = mac_ctrl_reg[10];
567      wire        bist_checker_locked;
568
569      assign sfpp_tx_disable = 1'b0; // Always on.
570
571      if (GT_COMMON == 1) begin
572        aurora_phy_x1 aurora_phy_i (
573          // Resets
574          .areset(areset | phy_areset),
575          // Clocks
576          .refclk(gt_refclk),
577          .init_clk(misc_clk),
578          .user_clk(user_clk),
579          .user_rst(user_rst),
580          .sync_clk(sync_clk),
581          .qpllclk(qplloutclk),
582          .qpllrefclk(qplloutrefclk),
583          // GTX Serial I/O
584          .tx_p(txp),
585          .tx_n(txn),
586          .rx_p(rxp),
587          .rx_n(rxn),
588          // AXI4-Stream TX Interface
589          .s_axis_tdata(m2p_tdata),
590          .s_axis_tvalid(m2p_tvalid),
591          .s_axis_tready(m2p_tready),
592          // AXI4-Stream RX Interface
593          .m_axis_tdata(p2m_tdata),
594          .m_axis_tvalid(p2m_tvalid),
595          // AXI4-Lite Config Interface (unused)
596          .s_axi_awaddr(32'h0),
597          .s_axi_araddr(32'h0),
598          .s_axi_awvalid(1'b0),
599          .s_axi_awready(),
600          .s_axi_wdata(32'h0),
601          .s_axi_wvalid(1'b0),
602          .s_axi_wstrb(1'b0),
603          .s_axi_wready(),
604          .s_axi_bvalid(),
605          .s_axi_bresp(),
606          .s_axi_bready(1'b1),
607          .s_axi_arready(),
608          .s_axi_arvalid(1'b0),
609          .s_axi_rdata(),
610          .s_axi_rvalid(),
611          .s_axi_rresp(),
612          .s_axi_rready(1'b1),
613          // Status and Error Reporting Interface
614          .channel_up(channel_up),
615          .hard_err(hard_err),
616          .soft_err(soft_err),
617          .qplllock(qplllock),
618          .qpllreset(qpllreset),
619          .qpllrefclklost(qpllrefclklost),
620          .tx_out_clk(gt_tx_out_clk_unbuf),
621          .gt_pll_lock(gt_pll_lock),
622          .mmcm_locked(mmcm_locked)
623        );
624      end else begin
625        aurora_phy_x1 aurora_phy_i (
626          // Resets
627          .areset(areset | phy_areset),
628          // Clocks
629          .refclk(gt_refclk),
630          .init_clk(misc_clk),
631          .user_clk(user_clk),
632          .user_rst(user_rst),
633          // GTX Serial I/O
634          .tx_p(txp),
635          .tx_n(txn),
636          .rx_p(rxp),
637          .rx_n(rxn),
638          // AXI4-Stream TX Interface
639          .s_axis_tdata(m2p_tdata),
640          .s_axis_tvalid(m2p_tvalid),
641          .s_axis_tready(m2p_tready),
642          // AXI4-Stream RX Interface
643          .m_axis_tdata(p2m_tdata),
644          .m_axis_tvalid(p2m_tvalid),
645          // AXI4-Lite Config Interface (unused)
646          .s_axi_awaddr(32'h0),
647          .s_axi_araddr(32'h0),
648          .s_axi_awvalid(1'b0),
649          .s_axi_awready(),
650          .s_axi_wdata(32'h0),
651          .s_axi_wvalid(1'b0),
652          .s_axi_wstrb(1'b0),
653          .s_axi_wready(),
654          .s_axi_bvalid(),
655          .s_axi_bresp(),
656          .s_axi_bready(1'b1),
657          .s_axi_arready(),
658          .s_axi_arvalid(1'b0),
659          .s_axi_rdata(),
660          .s_axi_rvalid(),
661          .s_axi_rresp(),
662          .s_axi_rready(1'b1),
663          // Status and Error Reporting Interface
664          .channel_up(channel_up),
665          .hard_err(hard_err),
666          .soft_err(soft_err)
667        );
668        assign qpllreset = 1'b0;
669        assign gt_pll_lock = 1'b0;
670        assign gt_tx_out_clk_unbuf = 1'b0;
671      end
672
673      aurora_axis_mac #(
674        .PHY_ENDIANNESS ("LITTLE"),
675        .PACKET_MODE    (1),
676        .MAX_PACKET_SIZE(1024),
677        .BIST_ENABLED   (1)
678      ) aurora_mac_i (
679        // Clocks and resets
680        .phy_clk(user_clk), .phy_rst(user_rst),
681        .sys_clk(bus_clk), .sys_rst(bus_rst),
682        .clear(mac_clear),
683        // PHY Interface (Synchronous to phy_clk)
684        .phy_s_axis_tdata(p2m_tdata),
685        .phy_s_axis_tvalid(p2m_tvalid),
686        .phy_m_axis_tdata(m2p_tdata),
687        .phy_m_axis_tvalid(m2p_tvalid),
688        .phy_m_axis_tready(m2p_tready),
689        // User Interface (Synchronous to sys_clk)
690        .s_axis_tdata(c2mac_tdata),
691        .s_axis_tlast(c2mac_tlast),
692        .s_axis_tvalid(c2mac_tvalid),
693        .s_axis_tready(c2mac_tready),
694        .m_axis_tdata(m_axis_tdata),
695        .m_axis_tlast(m_axis_tlast),
696        .m_axis_tvalid(m_axis_tvalid),
697        .m_axis_tready(m_axis_tready),
698        // PHY Status Inputs (Synchronous to phy_clk)
699        .channel_up(channel_up),
700        .hard_err(hard_err),
701        .soft_err(soft_err),
702        // Status and Error Outputs (Synchronous to sys_clk)
703        .overruns(overruns),
704        .soft_errors(),
705        .checksum_errors(checksum_errors),
706        .critical_err(mac_crit_err),
707        // BIST Interface (Synchronous to sys_clk)
708        .bist_gen_en(bist_gen_en),
709        .bist_gen_rate(bist_gen_rate),
710        .bist_checker_en(bist_checker_en),
711        .bist_loopback_en(bist_loopback_en),
712        .bist_checker_locked(bist_checker_locked),
713        .bist_checker_samps(bist_checker_samps),
714        .bist_checker_errors(bist_checker_errors)
715      );
716
717      assign m_axis_tuser = 4'd0;
718
719      wire channel_up_bclk, hard_err_bclk, soft_err_bclk, mac_crit_err_bclk, gt_pll_lock_bclk;
720      synchronizer #(.INITIAL_VAL(1'b0)) channel_up_sync (
721        .clk(bus_clk), .rst(1'b0 /* no reset */), .in(channel_up), .out(channel_up_bclk));
722      synchronizer #(.INITIAL_VAL(1'b0)) hard_err_sync (
723        .clk(bus_clk), .rst(1'b0 /* no reset */), .in(hard_err), .out(hard_err_bclk));
724      synchronizer #(.INITIAL_VAL(1'b0)) soft_err_sync (
725        .clk(bus_clk), .rst(1'b0 /* no reset */), .in(soft_err), .out(soft_err_bclk));
726      synchronizer #(.INITIAL_VAL(1'b0)) mac_crit_err_sync (
727        .clk(bus_clk), .rst(1'b0 /* no reset */), .in(mac_crit_err), .out(mac_crit_err_bclk));
728
729      if (GT_COMMON == 1) begin
730        synchronizer #(.INITIAL_VAL(1'b0)) gt_pll_lock_sync (
731          .clk(bus_clk), .rst(1'b0 /* no reset */), .in(gt_pll_lock), .out(gt_pll_lock_bclk));
732      end else begin
733        assign gt_pll_lock_bclk = 1'b0;
734      end
735
736      reg [19:0]  bist_lock_latency;
737      always @(posedge bus_clk) begin
738        if (!bist_checker_en && !bist_checker_locked)
739          bist_lock_latency <= 20'd0;
740        else if (bist_checker_en && !bist_checker_locked)
741          bist_lock_latency <= bist_lock_latency + 20'd1;
742      end
743
744      reg mac_crit_err_latch;
745      always @(posedge bus_clk) begin
746        if (bus_rst | mac_clear) begin
747          mac_crit_err_latch <= 1'b0;
748        end else begin
749          if (mac_crit_err_bclk)
750            mac_crit_err_latch <= 1'b1;
751        end
752      end
753
754      assign phy_status = {30'd0, hard_err, channel_up};
755      assign mac_status = {
756        6'h0,                      //[31:26]
757        mac_crit_err_latch,        //[25]
758        1'b1,                      //[24]
759        gt_pll_lock_bclk,          //[23]
760        qpllrefclklost,            //[22]
761        qplllock,                  //[21]
762        qpllreset,                 //[20]
763        bist_lock_latency[19:4],   //[19:4]
764        bist_checker_locked,       //[3]
765        soft_err_bclk,             //[2]
766        hard_err_bclk,             //[1]
767        channel_up_bclk            //[0]
768      };
769
770      assign link_up = channel_up_bclk;
771
772    end else begin
773
774      //-----------------------------------------------------------------
775      // Disabled
776      //-----------------------------------------------------------------
777
778      assign phy_status = 'h0;
779      assign mac_status = 'h0;
780      assign link_up = 1'b0;
781
782      assign sfpp_tx_disable = 1'b0; // Always on.
783
784      assign c2mac_tready = 1'b1;
785      assign m_axis_tdata = 64'h0;
786      assign m_axis_tuser = 4'h0;
787      assign m_axis_tlast = 1'b0;
788      assign m_axis_tvalid = 1'b0;
789
790      assign qpllreset = 1'b0;
791      assign gt_pll_lock = 1'b0;
792      assign gt_tx_out_clk_unbuf = 1'b0;
793
794    end
795  endgenerate
796
797  wire identify_enable = mac_led_ctl[0];
798  wire identify_value  = mac_led_ctl[1];
799
800  //-----------------------------------------------------------------
801  // Activity detector
802  //-----------------------------------------------------------------
803
804  wire activity_int;
805
806  pulse_stretch act_pulse_str_i (
807    .clk(bus_clk),
808    .rst(bus_rst | ~link_up),
809    .pulse((s_axis_tvalid & s_axis_tready) | (m_axis_tvalid & m_axis_tready)),
810    .pulse_stretched(activity_int)
811  );
812
813  always @ (posedge bus_clk) activity <= identify_enable ? identify_value : activity_int;
814
815endmodule
816