/* * betsy.v * * Copyright (C) 2025 Private Island Networks Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * function: top module for three instantiated Ethernet PHYs + controllers * * */ // `define PASSTHROUGH `define PHY2_PRESENT module betsy ( input rstn, input clk_i, // 25Mhz input phy0_clk, output phy1_clk, `ifdef SIMULATION output pll_locked_o, output pclk_o, output [2:0] phy_up_o, `endif // PHY0 RGMII output phy0_rstn, input phy0_rx_clk, input phy0_rx_ctl, input [3:0] phy0_rx_d, output phy0_tx_clk, output phy0_tx_ctl, output [3:0] phy0_tx_d, output phy0_mdc, inout phy0_mdio, input phy0_intn, // TODO: resolve PWRDN input option inout [1:0] phy0_gpio, // PHY1 RGMII output phy1_rstn, input phy1_rx_clk, input phy1_rx_ctl, input [3:0] phy1_rx_d, output phy1_tx_clk, output phy1_tx_ctl, output [3:0] phy1_tx_d, output phy1_mdc, inout phy1_mdio, input phy1_intn, inout [1:0] phy1_gpio, // PHY2 RGMII output phy2_rstn, input phy2_rx_clk, input phy2_rx_ctl, input [3:0] phy2_rx_d, output phy2_tx_clk, output phy2_tx_ctl, output[3:0] phy2_tx_d, output phy2_mdc, inout phy2_mdio, input phy2_intn, inout [1:0] phy2_gpio, // FLASH output flash_clk, input flash_dqs, output flash_seln, inout [7:0] flash_d, // Debug output [2:0] fpga_led ); `define INCLUDED `include "../../../../src/ethernet_params.v" `undef INCLUDED /* PARAMS */ parameter NUM_PHYS = 3; parameter NUM_PLLS = 1; parameter MDIO_ROM_ADDR_SZ = 7; parameter NUM_ML_IF = 3; wire reset, pll_locked; reg sys_rstn; wire cont_clk, clk_25, clk_125; wire pclk; // main fabric clock for Ethernet pipeline reg [3:0] cnt_init; reg [25:0] heart_beat_cnt; wire [NUM_PHYS-1:0] phy_up; `ifdef SIMULATION assign pll_locked_o = pll_locked; assign pclk_o = pclk; assign phy_up_o = phy_up; `endif // misc resets wire [NUM_PHYS-1:0] phy_resetn; wire [NUM_PHYS-1:0] mac_reset; wire [NUM_PHYS-1:0] phy_int; wire [NUM_PHYS-1:0] rx_sample; // receive data + ctl input wire [1:0] rx0_ctl_i, rx1_ctl_i, rx2_ctl_i; wire [7:0] rx0_d_i, rx1_d_i, rx2_d_i; // transmit data + ctl output wire [1:0] tx0_ctl, tx1_ctl, tx2_ctl; wire [7:0] tx0_d, tx1_d, tx2_d; // Delayed RX input data reg [1:0] rx0_ctl_i_m1, rx0_ctl_i_m2, rx0_ctl_i_m3, rx0_ctl_i_m4; reg [7:0] rx0_d_i_m1, rx0_d_i_m2, rx0_d_i_m3, rx0_d_i_m4; reg [1:0] rx1_ctl_i_m1, rx1_ctl_i_m2, rx1_ctl_i_m3, rx1_ctl_i_m4; reg [7:0] rx1_d_i_m1, rx1_d_i_m2, rx1_d_i_m3, rx1_d_i_m4; reg [1:0] rx2_ctl_i_m1, rx2_ctl_i_m2, rx2_ctl_i_m3, rx2_ctl_i_m4; reg [7:0] rx2_d_i_m1, rx2_d_i_m2, rx2_d_i_m3, rx2_d_i_m4; // Delayed data shared between modules wire [1:0] rx0_ctl_m1, rx0_ctl_m2, rx0_ctl_m3, rx0_ctl_m4; wire [7:0] rx0_d_m1, rx0_d_m2, rx0_d_m3, rx0_d_m4; wire [1:0] rx1_ctl_m1, rx1_ctl_m2, rx1_ctl_m3, rx1_ctl_m4; wire [7:0] rx1_d_m1, rx1_d_m2, rx1_d_m3, rx1_d_m4; wire [1:0] rx2_ctl_m1, rx2_ctl_m2, rx2_ctl_m3, rx2_ctl_m4; wire [7:0] rx2_d_m1, rx2_d_m2, rx2_d_m3, rx2_d_m4; // MAC asserts when it determines RX data should be kept wire [NUM_PHYS-1:0] rx_mac_keep; wire [NUM_PHYS-1:0] rx_mac_wr_done; // drop filter outputs wire rx_df_fifo_we_01, rx_df_fifo_we_02, rx_df_fifo_we_0u; wire rx_df_fifo_we_10, rx_df_fifo_we_12; wire rx_df_fifo_we_20, rx_df_fifo_we_21; wire [8:0] rx_df_fifo_d_01, rx_df_fifo_d_02, rx_df_fifo_d_0u; wire [8:0] rx_df_fifo_d_10, rx_df_fifo_d_12; wire [8:0] rx_df_fifo_d_20, rx_df_fifo_d_21; wire [8:0] rx_df_fifo_d_u0; // pkt filter wire [NUM_PHYS-1:0] trigger; wire [NUM_PHYS-1:0] rx_enet_bcast; wire [NUM_PHYS-1:0] rx_ipv4_arp; wire rx_pf_keep_01, rx_pf_keep_02; wire rx_pf_keep_10, rx_pf_keep_12; wire rx_pf_keep_20, rx_pf_keep_21; wire rx_pf_keep_0u; wire rx_pf_keep_u0; // rx_fifos wire [NUM_PHYS-1:0] rx_mac_fifo_we; // Read Enable from Switch to FIFO for transmit data wire rx_sw_fifo_re_01, rx_sw_fifo_re_02, rx_sw_fifo_re_0u; wire rx_sw_fifo_re_10, rx_sw_fifo_re_12; wire rx_sw_fifo_re_20, rx_sw_fifo_re_21; wire rx_sw_fifo_re_u0; // FIFO empty flags from FIFO to switch wire rx_sf_fifo_empty_01, rx_sf_fifo_empty_02, rx_sf_fifo_empty_0u; wire rx_sf_fifo_empty_10, rx_sf_fifo_empty_12; wire rx_sf_fifo_empty_20, rx_sf_fifo_empty_21; wire rx_uc_fifo_empty_u0; wire rx_sf_almost_full_01; wire rx_sf_almost_full_10; wire rx_sf_almost_full_20; wire rx_sf_almost_full_0u; // data from FIFO to switch wire [8:0] rx_sf_fifo_d_01, rx_sf_fifo_d_02, rx_sf_fifo_d_0u; wire [8:0] rx_sf_fifo_d_10, rx_sf_fifo_d_12; wire [8:0] rx_sf_fifo_d_20, rx_sf_fifo_d_21; wire [8:0] rx_uc_fifo_d_u0; // data from MAC wire [8:0] rx_mac_fifo_d0, rx_mac_fifo_d1, rx_mac_fifo_d2; // RX byte cnt and mode from MAC wire [1:0] rx0_mode, rx1_mode, rx2_mode; wire [NUM_PHYS-1:0] rx_byte_cnt; wire [10:0] rx0_mac_byte_cnt; wire [10:0] rx1_mac_byte_cnt; wire [10:0] rx2_mac_byte_cnt; wire [10:0] rxu_byte_cnt, rx_mle_byte_cnt; // ml_engine wire mle_evt_start, mle_evt_active; wire [NUM_ML_IF-1:0] mle_enable, mle_empty, mle_we; wire mle_oe; wire [8:0] mle_d_0, mle_d_1, mle_d_2, mle_d_3; reg [8:0] mle_d_i; wire mle_fifo_empty, mle_fifo_re; wire [8:0] mle_fifo_d_o; // TX between switch and MAC wire [8:0] tx_sw_fifo_d0, tx_sw_fifo_d1, tx_sw_fifo_d2, tx_sw_fifo_du; wire [NUM_PHYS-1:0] tx_mac_fifo_re; wire tx_uc_fifo_re; wire [NUM_PHYS-1:0] tx_sw_fifo_empty; wire tx_sw_fifo_we; // for controller path wire [2:0] tx_sw_mode0, tx_sw_mode1, tx_sw_mode2; wire [2:0] tx_modeu; wire [NUM_PHYS-1:0] tx_mac_done; wire [10:0] tx0_byte_cnt, tx1_byte_cnt, tx2_byte_cnt; wire [2:0] tx_src_sel0, tx_src_sel1, tx_src_sel2; // TX between L3/L4 controller and MAC wire tx_uc_fifo_empty, tx_mle_fifo_empty; wire [8:0] tx_uc_fifo_d0, tx_mle_fifo_d0; // 100 Mbit wire [NUM_PHYS-1:0] mode_100Mbit; // Controller Peripheral Address Decode and Select wire mac_sel, pkt_filter_sel, mle_sel; wire [1:0] mac_addr; wire [15:0] pkt_filter_addr; // FCS RX wire [1:0] fcs_rx_addr0, fcs_rx_addr1, fcs_rx_addr2; wire [7:0] fcs_rx_din0, fcs_rx_din1, fcs_rx_din2; wire [7:0] fcs_rx_dout0, fcs_rx_dout1, fcs_rx_dout2; wire [NUM_PHYS-1:0] fcs_rx_init, fcs_rx_enable; // FCS TX wire [1:0] fcs_tx_addr0, fcs_tx_addr1, fcs_tx_addr2; wire [7:0] fcs_tx_din0, fcs_tx_din1, fcs_tx_din2; wire [7:0] fcs_tx_dout0, fcs_tx_dout1, fcs_tx_dout2; wire [NUM_PHYS-1:0] fcs_tx_init, fcs_tx_enable; // IPv4 wire [NUM_PHYS-1:0] ipv4_pkt_start; wire [NUM_PHYS-1:0] ipv4_pkt_complete; wire [NUM_PHYS-1:0] ipv4_rx_keep; wire [NUM_PHYS-1:0] ipv4_trigger_dst_addr; wire ipv4_pkt_complete_c, ipv4_addr_match_c; // UDP wire udp_port_match_c; // Network Debug & Metrics wire [NUM_PHYS-1:0] mac_int; wire [NUM_PHYS-1:0] mac_rx_active, mac_tx_active; wire [NUM_PHYS-1:0] drop_rx0_active, drop_rx1_active, drop_rx2_active; wire [NUM_PHYS-1:0] sync_rx0_active, sync_rx1_active, sync_rx2_active; wire drop_rx0_active_u, sync_rx0_active_u; wire [NUM_PHYS-1:0] rx_idle; wire [NUM_PHYS-1:0] rx_mac_error; wire [NUM_PHYS-1:0] rx_eop, rx_sop; wire [NUM_PHYS-1:0] tx_eop, tx_sop, tx_error; // Common Internal Memory Bus wire[15:0] mem_addr; reg [31:0] mem_d_i; // direction is from the point of view of the controller wire [31:0] mem_d_o; wire mem_we, mem_oe; wire mem_tgt_ready, mem_tgt_ready_mac_0, mem_tgt_ready_mac_1; wire [15:0] mac_0_d_o, mac_1_d_o, mac_2_d_o; wire [15:0] mle_d_o; wire [10:0] hfifo_d_o; // half FIFO / Interface for Controller wire hf_rx_fifo_int, hf_rx_fifo_int_acked; wire hf_ptrs_sel, hf_rx_sel, hf_tx_sel; // DPRAM PARAM data from controller wire [10:0] param_phy0_addr, param_phy1_addr, param_phy2_addr; wire [8:0] param_phy0_din, param_phy1_din, param_phy2_din; wire [8:0] param_phy0_dout, param_phy1_dout, param_phy2_dout; wire [8:0] param_ram_0_do, param_ram_1_do, param_ram_2_do; wire param_phy0_ce, param_phy1_ce, param_phy2_ce; wire param_phy0_we, param_phy1_we, param_phy2_we; wire [NUM_PHYS-1:0] param_sel; // MDIO controller and driver wire mdio_cont_work_start, mdio_cont_work_done, mdio_cont_work_run; wire [MDIO_ROM_ADDR_SZ-1:0] mdio_routine_addr; wire mdio_done, mdo_oe; wire mdo; reg mdi; wire [15:0] mdio_wd, mdio_rd; // write data, read data wire mdio_rd_we; wire mdio_ld, mdio_run; wire mdio_rwn; wire [4:0] mdio_reg_addr; // passed from mdio_cont -> mdio wire [4:0] mdio_phy_addr; wire [1:0] mdio_mux_sel; // MDIO Data block wire [MDIO_ROM_ADDR_SZ-1:0] mdio_rom_a; wire [7:0] mdio_rom_d; wire [4:0] mdio_reg_addr_set; wire [7:0] mdio_w_data_h_set, mdio_w_data_l_set; // Debug wire [7:0] gpio_controller, gpio_ipv4; reg evt_toggle; // Fabric PLL pll pll_0( .areset(reset), .inclk0(clk_i), .c0(clk_25), // 25 MHz .c1(clk_125), // 125 MHz .locked(pll_locked)); assign reset = ~rstn; assign cont_clk = clk_25; assign phy1_clk = clk_25; assign pclk = clk_125; always @(posedge cont_clk, negedge rstn) if (!rstn) cnt_init <= 4'd0; else if (cnt_init <= 4'd10) cnt_init <= cnt_init + 1'b1; // Place holder logic to remove reset properly per system requirements // TODO: Review this since it probably should negate after PLL_LOCK always @(posedge cont_clk, negedge rstn) if (!rstn) sys_rstn <= 1'b0; else if (cnt_init >= 10'd9) sys_rstn <= 1'b1; // TODO: Review sequence and move to Controller control assign phy0_rstn = sys_rstn; assign phy1_rstn = pll_locked; assign phy2_rstn = pll_locked; // TODO: Fix this assign phy_resetn = {pll_locked, pll_locked, pll_locked}; assign phy_int = {~phy2_intn, ~phy1_intn, ~phy0_intn}; // TODO: This will be replaced when the SPI master peripheral is ready assign flash_d = 8'hab; assign flash_seln = 1'b1; assign flash_clk = cont_clk; assign param_sel = 3'b000; // TODO: Gate these when not in use assign phy0_mdc = cont_clk; assign phy1_mdc = cont_clk; assign phy2_mdc = cont_clk; assign phy2_gpio[0] = gpio_ipv4[0]; assign phy2_gpio[1] = gpio_ipv4[1]; // Bits 3:0 on the positive edge of RX_CLK and bits 7:4 on the negative edge of RX_CLK. ddri rgmi_rx_0 ( .datain ({phy0_rx_ctl, phy0_rx_d}), .inclock (phy0_rx_clk), .dataout_h ({rx0_ctl_i[0],rx0_d_i[3:0]}), .dataout_l ({rx0_ctl_i[1],rx0_d_i[7:4]}) ); ddri rgmi_rx_1 ( .datain ({phy1_rx_ctl, phy1_rx_d}), .inclock (phy1_rx_clk), .dataout_h ({rx1_ctl_i[0],rx1_d_i[3:0]}), .dataout_l ({rx1_ctl_i[1],rx1_d_i[7:4]}) ); ddri rgmi_rx_2 ( .datain ({phy2_rx_ctl, phy2_rx_d}), .inclock (phy2_rx_clk), .dataout_h ({rx2_ctl_i[0],rx2_d_i[3:0]}), .dataout_l ({rx2_ctl_i[1],rx2_d_i[7:4]}) ); // Simple Pipeline to Make Timing always @(posedge phy0_rx_clk, negedge rstn) if (!rstn) begin rx0_d_i_m1 <= 8'h0; rx0_d_i_m2 <= 8'h0; rx0_d_i_m3 <= 8'h0; rx0_d_i_m4 <= 8'h0; end else begin rx0_d_i_m1 <= rx0_d_i; rx0_d_i_m2 <= {rx0_d_i[7:4], rx0_d_i_m1[3:0]} ; rx0_d_i_m3 <= rx0_d_i_m2; rx0_d_i_m4 <= rx0_d_i_m3; end always @(posedge phy0_rx_clk, negedge rstn) if (!rstn) begin rx0_ctl_i_m1 <= 2'h0; rx0_ctl_i_m2 <= 2'h0; rx0_ctl_i_m3 <= 2'h0; rx0_ctl_i_m4 <= 2'h0; end else begin rx0_ctl_i_m1 <= rx0_ctl_i; rx0_ctl_i_m2 <= {rx0_ctl_i[1],rx0_ctl_i_m1[0]}; rx0_ctl_i_m3 <= rx0_ctl_i_m2; rx0_ctl_i_m4 <= rx0_ctl_i_m3; end // pipeline regs for PHY1 always @(posedge phy1_rx_clk, negedge rstn) if (!rstn) begin rx1_d_i_m1 <= 8'h0; rx1_d_i_m2 <= 8'h0; rx1_d_i_m3 <= 8'h0; rx1_d_i_m4 <= 8'h0; end else begin rx1_d_i_m1 <= rx1_d_i; rx1_d_i_m2 <= {rx1_d_i[7:4], rx1_d_i_m1[3:0]} ; rx1_d_i_m3 <= rx1_d_i_m2; rx1_d_i_m4 <= rx1_d_i_m3; end always @(posedge phy1_rx_clk, negedge rstn) if (!rstn) begin rx1_ctl_i_m1 <= 2'h0; rx1_ctl_i_m2 <= 2'h0; rx1_ctl_i_m3 <= 2'h0; rx1_ctl_i_m4 <= 2'h0; end else begin rx1_ctl_i_m1 <= rx1_ctl_i; rx1_ctl_i_m2 <= {rx1_ctl_i[1], rx1_ctl_i_m1[0]}; rx1_ctl_i_m3 <= rx1_ctl_i_m2; rx1_ctl_i_m4 <= rx1_ctl_i_m3; end `ifdef PHY2_PRESENT // pipeline regs for PHY2 always @(posedge phy2_rx_clk, negedge rstn) if (!rstn) begin rx2_d_i_m1 <= 8'h0; rx2_d_i_m2 <= 8'h0; rx2_d_i_m3 <= 8'h0; rx2_d_i_m4 <= 8'h0; end else begin rx2_d_i_m1 <= rx2_d_i; rx2_d_i_m2 <= {rx2_d_i[7:4], rx2_d_i_m1[3:0]} ; rx2_d_i_m3 <= rx2_d_i_m2; rx2_d_i_m4 <= rx2_d_i_m3; end always @(posedge phy2_rx_clk, negedge rstn) if (!rstn) begin rx2_ctl_i_m1 <= 2'h0; rx2_ctl_i_m2 <= 2'h0; rx2_ctl_i_m3 <= 2'h0; rx2_ctl_i_m4 <= 2'h0; end else begin rx2_ctl_i_m1 <= rx2_ctl_i; rx2_ctl_i_m2 <= {rx2_ctl_i[1], rx2_ctl_i_m1[0]}; rx2_ctl_i_m3 <= rx2_ctl_i_m2; rx2_ctl_i_m4 <= rx2_ctl_i_m3; end `endif /* * main controller * */ controller #(.MDIO_ADDR_SZ(MDIO_ROM_ADDR_SZ), .NUM_PHYS(NUM_PHYS)) controller_0( .rstn(sys_rstn), .clk(cont_clk), // status & errors .phy_int(phy_int), .mac_int(rx_mac_error), // link status .phy_up(phy_up), // Memory Controller I/F .mem_we(mem_we), .mem_oe(mem_oe), .mem_addr(mem_addr), .mem_d_o(mem_d_o), .mem_d_i(mem_d_i), .mem_tgt_ready(mem_tgt_ready), // Internal Device Selects .mac_addr(mac_addr), .pkt_filter_addr(pkt_filter_addr), .pkt_filter_sel(pkt_filter_sel), .mac_sel(mac_sel), .mle_sel(mle_sel), .hf_ptrs_sel(hf_ptrs_sel), .hf_rx_sel(hf_rx_sel), .hf_tx_sel(hf_tx_sel), // half FIFO interface .rx_fifo_int(hf_rx_fifo_int), .rx_fifo_int_acked(hf_rx_fifo_int_acked), .tx_fifo_empty(rx_uc_fifo_empty_u0), // mdio_controller interface .mdio_cont_start(mdio_cont_work_start), .mdio_cont_done(mdio_cont_work_done), .mdio_routine_addr(mdio_routine_addr), .mdio_run(mdio_run), .mdio_we(mdio_rd_we), .mdio_d_i(mdio_rd), .mdio_mux_sel(mdio_mux_sel), // mdio_data params .mdio_phy_addr(mdio_phy_addr), .mdio_reg_addr(mdio_reg_addr_set), .mdio_w_data_h(mdio_w_data_h_set), .mdio_w_data_l(mdio_w_data_l_set), // Device Resets .phy_resetn(), .mac_reset(mac_reset), // Debug .gpio(gpio_controller) ); assign mem_tgt_ready = mem_tgt_ready_mac_0 && mem_tgt_ready_mac_1; // controller data mux always @(*) casex({ hf_tx_sel, hf_rx_sel, hf_ptrs_sel, mle_sel, mac_sel, mac_addr}) 7'b0000100: mem_d_i = {16'h0000, mac_0_d_o}; 7'b0000101: mem_d_i = {16'h0000, mac_1_d_o}; 7'b0000110: mem_d_i = {16'h0000, mac_2_d_o}; 7'b00010??: mem_d_i = {16'h0000, mle_d_o}; 7'b00100??: mem_d_i = {21'h0000, hfifo_d_o}; 7'b01000??: mem_d_i = {21'h0000, hfifo_d_o}; 7'b10000??: mem_d_i = {21'h0000, hfifo_d_o}; default: mem_d_i = 32'd0; endcase /* * controller I/F FIFO * FIFO side connects to network switch * Switch/system perspective: * RX: controller writes (data received into switch) * TX: controller reads (data transmitted from switch) */ half_fifo micro_fifo_0 ( .rstn( sys_rstn ), .fifo_clk(pclk), .uc_clk(cont_clk), // controller interrupt support .rx_fifo_int (hf_rx_fifo_int), .rx_fifo_int_acked (hf_rx_fifo_int_acked), // controller interface .dpram_addr(mem_addr[10:0]), .dpram_din(mem_d_o[10:0]), .dpram_dout(hfifo_d_o), .dpram_we(mem_we), .dpram_oe(mem_oe), .dpram_ptrs_sel(hf_ptrs_sel), .dpram_tx_sel(hf_tx_sel), .dpram_rx_sel(hf_rx_sel), // TX: switch -> hfifo -> controller .fifo_we(tx_sw_fifo_we), .fifo_d_in(tx_sw_fifo_du), // RX: controller -> hfifo -> switch .fifo_re(rx_sw_fifo_re_u0), .tx_byte_cnt(rxu_byte_cnt), .fifo_d_out(rx_uc_fifo_d_u0), .tx_empty(rx_uc_fifo_empty_u0) ); mdio_cont #(.ADDR_SZ(MDIO_ROM_ADDR_SZ)) mdio_cont_0( .rstn(sys_rstn), .clk(cont_clk), .work_start(mdio_cont_work_start), .work_run(mdio_cont_work_run), .work_done(mdio_cont_work_done), .routine_addr(mdio_routine_addr), .buffer_full(1'b0), .addr(mdio_rom_a), .di(mdio_rom_d), .reg_addr(mdio_reg_addr), .dout(mdio_wd), .ld(mdio_ld), .rwn(mdio_rwn), .done(mdio_done) ); mdio_data_ti mdio_data_ti_0( .ad(mdio_rom_a), .reg_addr(mdio_reg_addr_set), .data_in_h(mdio_w_data_h_set), .data_in_l(mdio_w_data_l_set), .d(mdio_rom_d), .oe(1'b1) ); mdio mdio_0( .rstn(sys_rstn), .mdc(cont_clk), // MDIO .mdi(mdi), .mdo(mdo), .mdo_oe(mdo_oe), // mdio controller interface .rwn(mdio_rwn), .phy_addr(mdio_phy_addr), .reg_addr(mdio_reg_addr), .di(mdio_wd), .ld(mdio_ld), .run(mdio_run), .done(mdio_done), // signal controller that mdio xfer is done // output port to converter .dout(mdio_rd), .we(mdio_rd_we) ); /* MDIO mux and output enables, infer open drain for each mdio I/O */ always @(*) begin case (mdio_mux_sel) 2'b00: mdi = phy0_mdio; 2'b01: mdi = phy1_mdio; 2'b10: mdi = phy2_mdio; endcase end // Support all PHYs assign phy0_mdio = (mdo_oe && mdio_mux_sel == 2'b00) ? mdo : 1'bz; assign phy1_mdio = (mdo_oe && mdio_mux_sel == 2'b01) ? mdo : 1'bz; assign phy2_mdio = (mdo_oe && mdio_mux_sel == 2'b10) ? mdo : 1'bz; always@(*) case(mle_enable) 3'b001: mle_d_i = mle_d_0; 3'b010: mle_d_i = mle_d_1; 3'b100: mle_d_i = mle_d_2; default: mle_d_i = 'd0; endcase ml_engine #(.NUM_IF(NUM_ML_IF)) ml_engine_0( .rstn(sys_rstn), .clk(pclk), // controller interface .cont_clk(cont_clk), .cont_sel(mle_sel), .cont_we(mem_we), .cont_addr(mem_addr), .cont_d_i(mem_d_o[15:0]), .cont_d_o(mle_d_o), .cont_tgt_ready(), // module interface .evt_start(mle_evt_start), .evt_active(mle_evt_active), .enable(mle_enable), .clk_e(1'b1), .we(|mle_we), .empty(mle_empty), .d_i(mle_d_i), // switch interface .fifo_empty_o(mle_fifo_empty), .fifo_re(mle_fifo_re), .fifo_d_o(mle_fifo_d_o), .byte_cnt(rx_mle_byte_cnt) ); /* * Controls the routing of data and transmit modes */ switch switch_0( .rstn(sys_rstn), .clk(pclk), // PHY status .phy_up(phy_up), .mode_100Mbit (mode_100Mbit), // FIFO input data from RX FIFOs .rx_d_01(rx_sf_fifo_d_01), .rx_d_02(rx_sf_fifo_d_02), .rx_d_0u(rx_sf_fifo_d_0u), .rx_d_10(rx_sf_fifo_d_10), .rx_d_12(rx_sf_fifo_d_12), .rx_d_20(rx_sf_fifo_d_20), .rx_d_21(rx_sf_fifo_d_21), .rx_d_u0(rx_uc_fifo_d_u0), .rx_mle_fifo_d(mle_fifo_d_o), // RX FIFO read enables .rx_fifo_re_01(rx_sw_fifo_re_01), .rx_fifo_re_02(rx_sw_fifo_re_02), .rx_fifo_re_0u(rx_sw_fifo_re_0u), .rx_fifo_re_10(rx_sw_fifo_re_10), .rx_fifo_re_12(rx_sw_fifo_re_12), .rx_fifo_re_20(rx_sw_fifo_re_20), .rx_fifo_re_21(rx_sw_fifo_re_21), .rx_fifo_re_u0(rx_sw_fifo_re_u0), .rx_fifo_re_mle(mle_fifo_re), // RX FIFO Empty flags .rx_fifo_empty_01(rx_sf_fifo_empty_01), .rx_fifo_empty_02(rx_sf_fifo_empty_02), .rx_fifo_empty_0u(rx_sf_fifo_empty_0u), .rx_fifo_empty_10(rx_sf_fifo_empty_10), .rx_fifo_empty_12(rx_sf_fifo_empty_12), .rx_fifo_empty_20(rx_sf_fifo_empty_20), .rx_fifo_empty_21(rx_sf_fifo_empty_21), .rx_fifo_empty_u0(rx_uc_fifo_empty_u0), .rx_fifo_empty_mle(mle_fifo_empty), // Write done event .rx_wr_done(rx_mac_wr_done), // RX Byte Count .rx0_byte_cnt(rx0_mac_byte_cnt), .rx1_byte_cnt(rx1_mac_byte_cnt), .rx2_byte_cnt(rx2_mac_byte_cnt), .rxu_byte_cnt(rxu_byte_cnt), .rx_mle_byte_cnt(rx_mle_byte_cnt), // TX FIFO data output .tx_d0(tx_sw_fifo_d0), .tx_d1(tx_sw_fifo_d1), .tx_d2(tx_sw_fifo_d2), .tx_du(tx_sw_fifo_du), // TX FIFO read enable .tx_fifo_re(tx_mac_fifo_re), .tx_fifo_we_u (tx_sw_fifo_we), // TX FIFO Empty Flags .tx_fifo_empty(tx_sw_fifo_empty), // TX modes for the PHYs and uc .tx_mode0(tx_sw_mode0), .tx_mode1(tx_sw_mode1), .tx_mode2(tx_sw_mode2), .tx_modeu(tx_modeu), // TX byte cnt .tx0_byte_cnt(tx0_byte_cnt), .tx1_byte_cnt(tx1_byte_cnt), .tx2_byte_cnt(tx2_byte_cnt), // TX Source Select .tx0_src_sel(tx_src_sel0), .tx1_src_sel(tx_src_sel1), .tx2_src_sel(tx_src_sel2), // TX state machine done flag .tx_f(tx_mac_done), .tx_custom(1'b0) ); /* * * PHY0 IEEE 802.3 ETHERNET for Interface to 1000BASE-T LAN * */ mac_rgmii mac_0( .rstn(sys_rstn), .phy_resetn (phy_resetn[0]), .rx_clk(phy0_rx_clk), .tx_clk(pclk), .tap_port (1'b0), // controller interface .cont_clk(cont_clk), .cont_sel(mac_sel & mac_addr == 2'b00), .cont_we(mem_we), .cont_addr(mem_addr[7:0]), .cont_d_i(mem_d_o[15:0]), .cont_d_o(mac_0_d_o), .cont_tgt_ready(mem_tgt_ready_mac_0), // ML engine interface .mle_active(mle_evt_active), .mle_if_enable(mle_enable[0]), .mle_if_oe(mle_oe), .mle_if_we(mle_we[0]), .mle_if_empty(mle_empty[0]), .mle_if_d_o(mle_d_0), // Line State .fixed_speed(1'b1), .mode_100Mbit(mode_100Mbit[0]), .phy_up(phy_up[0]), // Switch I/F .tx_mode(tx_sw_mode0), .tx_f(tx_mac_done[0]), // RGMII data I/F .rx_ctl({rx0_ctl_i[1],rx0_ctl_i_m1[0]}), .rx_d({rx0_d_i[7:4], rx0_d_i_m1[3:0]}), .tx_ctl(tx0_ctl), .tx_d(tx0_d), // RX FCS .fcs_rx_init(fcs_rx_init[0]), .fcs_rx_enable(fcs_rx_enable[0]), .fcs_rx_addr(fcs_rx_addr0), .fcs_rx_dout(fcs_rx_din0), .fcs_rx_din(fcs_rx_dout0), // TX FCS .fcs_tx_init(fcs_tx_init[0]), .fcs_tx_enable(fcs_tx_enable[0]), .fcs_tx_addr(fcs_tx_addr0), .fcs_tx_dout(fcs_tx_din0), .fcs_tx_din(fcs_tx_dout0), // MAC RX / FIFO Write .rx_fifo_we(rx_mac_fifo_we[0]), .rx_fifo_d(rx_mac_fifo_d0), .rx_keep(rx_mac_keep[0]), .rx_wr_done(rx_mac_wr_done[0]), .rx_byte_cnt(rx0_mac_byte_cnt), .rx_idle(rx_idle[0]), .rx_error(rx_mac_error[0]), // MAC TX / FIFO Read .tx_byte_cnt_i(tx0_byte_cnt), .tx_src_sel(tx_src_sel0), .tx_fifo_re(tx_mac_fifo_re[0]), .tx_fifo_d(tx_sw_fifo_d0), .tx_fifo_empty(tx_sw_fifo_empty[0]), // Alternate TX Port (uC) .tx_uc_fifo_empty(tx_uc_fifo_empty), .tx_uc_fifo_d(tx_uc_fifo_d0), // Alternate TX Port (MLE) .tx_mle_fifo_empty(tx_mle_fifo_empty), .tx_mle_fifo_d(tx_mle_fifo_d0), // Packet Filter .rx_sample(rx_sample[0]), .ipv4_pkt_start(ipv4_pkt_start[0]), .trigger(), .rx_ctl_m1(rx0_ctl_m1), .rx_ctl_m2(rx0_ctl_m2), .rx_ctl_m3(rx0_ctl_m3), .rx_ctl_m4(rx0_ctl_m4), .rx_d_m1(rx0_d_m1), .rx_d_m2(rx0_d_m2), .rx_d_m3(rx0_d_m3), .rx_d_m4(rx0_d_m4), // Param RAM .dpr_ad(param_phy0_addr), .dpr_we(param_phy0_we), .dpr_ce(param_phy0_ce), .dpr_di(param_phy0_din), .dpr_do(param_phy0_dout), // Metrics and Interrupts .rx_enet_bcast(rx_enet_bcast[0]), .rx_ipv4_arp(rx_ipv4_arp[0]), .rx_l3_proto(), .rx_pkt_length(), .mac_int(mac_int[0]), .rx_sop(rx_sop[0]), .rx_eop(rx_eop[0]), .tx_sop(tx_sop[0]), .tx_eop(tx_eop[0]), .rx_active(mac_rx_active[0]), .tx_active(mac_tx_active[0]) ); ipv4_rx ipv4_rx_0( .rstn(sys_rstn), .clk(phy0_rx_clk), // control .phy_resetn (phy_resetn[0]), .phy_up(phy_up[0]), // packet data .pkt_start(ipv4_pkt_start[0]), .rx_sample(rx_sample[0]), .rx_eop(rx_eop[0]), .rx_data_m1(rx0_d_m1), .rx_data_m2(rx0_d_m2), .rx_data_m3(rx0_d_m3), .rx_data_m4(rx0_d_m4), // flags .pkt_complete(ipv4_pkt_complete[0]), .trigger_src_addr(), .trigger_dst_addr(ipv4_trigger_dst_addr[0]), .keep(ipv4_rx_keep[0]) ); udp_rx udp_rx_0( .rstn(sys_rstn), .clk(phy0_rx_clk), // control .phy_resetn (phy_resetn[0]), .phy_up(phy_up[0]), // packet data .pkt_start(ipv4_trigger_dst_addr[0]), .rx_sample(rx_sample[0]), .rx_eop(rx_eop[0]), .rx_data_m1(rx0_d_m1), .rx_data_m2(rx0_d_m2), .rx_data_m3(rx0_d_m3), .rx_data_m4(rx0_d_m4), // flags .pkt_complete(), .trigger_src_port(), .trigger_dst_port(trigger[0]), .keep() ); // PHY0 MAC -> PHY1 pkt_filter pkt_filter_01( .rstn(sys_rstn), .clk(phy0_rx_clk), // input for programming .prgclk(cont_clk), .sel(pkt_filter_sel && pkt_filter_addr == 16'h0001), .we(mem_we), .addr(mem_addr[2:0]), .d_i(mem_d_o), .d_o(), // registered data .rx_d_m1(rx0_d_m1), .rx_d_m2(rx0_d_m2), .rx_d_m3(rx0_d_m3), .rx_d_m4(rx0_d_m4), // filter .new_frame (rx_sop[0]), .block(1'b0), .invert(1'b1), .trigger(rx_mac_keep[0]), .keep(rx_pf_keep_01) ); drop_fifo drop_fifo_01( .rstn(sys_rstn), .phy_up(phy_up[0]), .rx_clk(phy0_rx_clk), .tx_clk(pclk), .enable(1'b1), // ipv4_rx_keep[0] // control .keep (rx_pf_keep_01), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[0]), .wr_done(rx_mac_wr_done[0]), .rx_idle(rx_idle[0]), .rx_error(rx_mac_error[0]), .d_in(rx_mac_fifo_d0), // output .we_out(rx_df_fifo_we_01), .d_out(rx_df_fifo_d_01), // debug .active(drop_rx0_active[1]) ); sync_fifo sync_fifo_rx_01( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_01 & phy_up[1]), .d_in (rx_df_fifo_d_01), // output .re (rx_sw_fifo_re_01), .d_out(rx_sf_fifo_d_01), .empty(rx_sf_fifo_empty_01), .almost_full(), .reset_ptrs(1'b0), // debug .active(sync_rx0_active[1]) ); `ifdef PHY2_PRESENT // PHY0 MAC -> PHY1 pkt_filter pkt_filter_02( .rstn(sys_rstn), .clk(phy0_rx_clk), // input for programming .prgclk(cont_clk), .sel(pkt_filter_sel && pkt_filter_addr == 16'h0002), .we(mem_we), .addr(mem_addr[2:0]), .d_i(mem_d_o), .d_o(), // registered data .rx_d_m1(rx0_d_m1), .rx_d_m2(rx0_d_m2), .rx_d_m3(rx0_d_m3), .rx_d_m4(rx0_d_m4), // filter .new_frame (rx_sop[0]), .block(1'b0), .invert(1'b1), .trigger(rx_mac_keep[0]), .keep(rx_pf_keep_02) ); drop_fifo drop_fifo_02( .rstn(sys_rstn), .phy_up(phy_up[0]), .rx_clk(phy0_rx_clk), .tx_clk(pclk), .enable(1'b1), // ipv4_rx_keep[0] // control .keep (rx_pf_keep_02), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[0]), .wr_done(rx_mac_wr_done[0]), .rx_idle(rx_idle[0]), .rx_error(rx_mac_error[0]), .d_in(rx_mac_fifo_d0), // output .we_out(rx_df_fifo_we_02), .d_out(rx_df_fifo_d_02), // debug .active(drop_rx0_active[2]) ); sync_fifo sync_fifo_rx_02( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_02 & phy_up[2]), .d_in (rx_df_fifo_d_02), // output .re (rx_sw_fifo_re_02), .d_out(rx_sf_fifo_d_02), .empty(rx_sf_fifo_empty_02), .almost_full(), .reset_ptrs(1'b0), // debug .active(sync_rx0_active[2]) ); `endif ipv4_rx_c #(.IP_DST_MATCH_4(100)) ipv4_rx_c_0( .rstn(sys_rstn), .clk(phy0_rx_clk), // control .phy_up(phy_up[0]), // packet data .pkt_start(ipv4_pkt_start[0]), .rx_sample(rx_sample[0]), .rx_eop(rx_eop[0]), .rx_data_m1(rx0_d_m1), .rx_data_m2(rx0_d_m2), .rx_data_m3(rx0_d_m3), .rx_data_m4(rx0_d_m4), // flags .pkt_complete(ipv4_pkt_complete_c), .ip_addr_match(ipv4_addr_match_c) ); udp_rx_c udp_rx_c_0( .rstn(sys_rstn), .clk(phy0_rx_clk), // control .phy_up(phy_up[0]), // packet data .rx_sample(1'b1), .pkt_start(ipv4_trigger_dst_addr[0]), .rx_eop(rx_eop[0]), .rx_data_m1(rx0_d_m1), .rx_data_m2(rx0_d_m2), .rx_data_m3(rx0_d_m3), .rx_data_m4(rx0_d_m4), // flags .pkt_complete(), .udp_port_match(udp_port_match_c) ); drop_fifo drop_fifo_0u( .rstn(sys_rstn), .phy_up(phy_up[0]), .rx_clk(phy0_rx_clk), .tx_clk(pclk), .enable(ipv4_addr_match_c), // control .keep (udp_port_match_c), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[0]), .wr_done(rx_mac_wr_done[0]), .rx_idle(rx_idle[0]), .rx_error(rx_mac_error[0]), .d_in(rx_mac_fifo_d0), // output .we_out(rx_df_fifo_we_0u), .d_out(rx_df_fifo_d_0u), .active(drop_rx0_active_u) ); sync_fifo sync_fifo_rx_0u( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_0u), .d_in (rx_df_fifo_d_0u), // output .re (rx_sw_fifo_re_0u), .d_out(rx_sf_fifo_d_0u), .empty(rx_sf_fifo_empty_0u), .almost_full(rx_sf_almost_full_0u), .reset_ptrs(1'b0), // debug .active(sync_rx0_active_u ) ); dpram_inf #(.ADDR_WIDTH(10), .DPRAM_INIT("param_ram_0.txt")) param_ram_0( .rstn(sys_rstn), // Port A .a_clk(cont_clk), .a_clk_e(param_sel[0]), .a_we(1'b0), .a_oe(mem_oe), .a_addr(mem_addr[9:0]), .a_din(mem_d_o[8:0]), .a_dout(param_ram_0_do), // Port B .b_clk(pclk), .b_clk_e(param_phy0_ce), .b_we(param_phy0_we), .b_oe(1'b1), .b_addr(param_phy0_addr[9:0]), .b_din(param_phy0_dout), .b_dout(param_phy0_din) ); fcs fcs_rx_0( .rstn(sys_rstn), .clk(phy0_rx_clk), .init(fcs_rx_init[0]), .enable(fcs_rx_enable[0]), .addr(fcs_rx_addr0), .din(fcs_rx_din0), .dout(fcs_rx_dout0) ); fcs fcs_tx_0( .rstn(sys_rstn), .clk(pclk), .init(fcs_tx_init[0]), .enable(fcs_tx_enable[0]), .addr(fcs_tx_addr0), .din(fcs_tx_din0), .dout(fcs_tx_dout0) ); ipv4_tx_c ipv4_tx_c_0( .rstn(sys_rstn), .phy_resetn(phy_resetn[0]), .clk(pclk), // Control Interface .cont_clk(cont_clk), .cont_sel(ipv4_tx_c_sel), .cont_we(mem_we), .cont_addr(mem_addr[7:0]), .cont_d_i(mem_d_o[15:0]), .cont_d_o(), // Line State .mode_100Mbit(mode_100Mbit[0]), .phy_up(phy_up[0]), // Switch I/F .tx_mode(tx_sw_mode0), .tx_src_sel(tx_src_sel0), .byte_cnt_i(tx0_byte_cnt), // MAC Interface .fifo_re_i(tx_mac_fifo_re[0]), .fifo_empty_o(tx_uc_fifo_empty), .fifo_d_o(tx_uc_fifo_d0), // Debug .gpio(gpio_ipv4) ); ipv4_tx_mle ipv4_tx_mle_0( .rstn(sys_rstn), .phy_resetn(phy_resetn[0]), .clk(pclk), // Control Interface .cont_clk(cont_clk), .cont_sel(ipv4_tx_mle_sel), .cont_we(mem_we), .cont_addr(mem_addr[7:0]), .cont_d_i(mem_d_o[15:0]), .cont_d_o(), // Line State .mode_100Mbit(mode_100Mbit[0]), .phy_up(phy_up[0]), // Switch I/F .tx_mode(tx_sw_mode0), .tx_src_sel(tx_src_sel0), .byte_cnt_i(tx0_byte_cnt), // MAC Interface .fifo_re_i(tx_mac_fifo_re[0]), .fifo_empty_o(tx_mle_fifo_empty), .fifo_d_o(tx_mle_fifo_d0), // Debug .gpio() ); /* * * PHY1 IEEE 802.3 ETHERNET for Interface to 1000BASE-T LAN * */ mac_rgmii mac_1( .rstn(sys_rstn), .phy_resetn (phy_resetn[1]), .rx_clk(phy1_rx_clk), .tx_clk(pclk), .tap_port (1'b0), // Control Interface .cont_clk(cont_clk), .cont_sel(mac_sel & mac_addr == 2'b01), .cont_we(mem_we), .cont_addr(mem_addr[7:0]), .cont_d_i(mem_d_o[15:0]), .cont_d_o(mac_1_d_o), .cont_tgt_ready(mem_tgt_ready_mac_1), // ML engine interface .mle_active(mle_evt_active), .mle_if_enable(mle_enable[1]), .mle_if_oe(mle_oe), .mle_if_we(mle_we[1]), .mle_if_empty(mle_empty[1]), .mle_if_d_o(mle_d_1), // Line State .fixed_speed(1'b1), .mode_100Mbit(mode_100Mbit[1]), .phy_up(phy_up[1]), // Switch I/F .tx_mode(tx_sw_mode1), .tx_f(tx_mac_done[1]), // RGMII data I/F .rx_ctl({rx1_ctl_i[1],rx1_ctl_i_m1[0]}), .rx_d({rx1_d_i[7:4], rx1_d_i_m1[3:0]}), .tx_ctl(tx1_ctl), .tx_d(tx1_d), // RX FCS .fcs_rx_init(fcs_rx_init[1]), .fcs_rx_enable(fcs_rx_enable[1]), .fcs_rx_addr(fcs_rx_addr1), .fcs_rx_dout(fcs_rx_din1), .fcs_rx_din(fcs_rx_dout1), // TX FCS .fcs_tx_init(fcs_tx_init[1]), .fcs_tx_enable(fcs_tx_enable[1]), .fcs_tx_addr(fcs_tx_addr1), .fcs_tx_dout(fcs_tx_din1), .fcs_tx_din(fcs_tx_dout1), // MAC RX / FIFO Write .rx_fifo_we(rx_mac_fifo_we[1]), .rx_fifo_d(rx_mac_fifo_d1), .rx_keep(rx_mac_keep[1]), .rx_wr_done(rx_mac_wr_done[1]), .rx_byte_cnt(rx1_mac_byte_cnt), .rx_idle(rx_idle[1]), .rx_error(rx_mac_error[1]), // MAC TX / FIFO Read .tx_byte_cnt_i(tx1_byte_cnt), .tx_src_sel(tx_src_sel1), .tx_fifo_re(tx_mac_fifo_re[1]), .tx_fifo_d(tx_sw_fifo_d1), .tx_fifo_empty(tx_sw_fifo_empty[1]), // Alternate TX Port .tx_uc_fifo_empty(1'b1), // tie off to disable port .tx_uc_fifo_d(9'd0), .tx_mle_fifo_empty(1'b1), .tx_mle_fifo_d(9'd0), // Packet Filter .rx_sample(rx_sample[1]), .ipv4_pkt_start(ipv4_pkt_start[1]), .trigger(), .rx_ctl_m1(rx1_ctl_m1), .rx_ctl_m2(rx1_ctl_m2), .rx_ctl_m3(rx1_ctl_m3), .rx_ctl_m4(rx1_ctl_m4), .rx_d_m1(rx1_d_m1), .rx_d_m2(rx1_d_m2), .rx_d_m3(rx1_d_m3), .rx_d_m4(rx1_d_m4), // Param RAM .dpr_ad(param_phy1_addr), .dpr_we(param_phy1_we), .dpr_ce(param_phy1_ce), .dpr_di(param_phy1_din), .dpr_do(param_phy1_dout), // Metrics and Interrupts .rx_enet_bcast(rx_enet_bcast[1]), .rx_ipv4_arp(rx_ipv4_arp[1]), .rx_l3_proto(), .rx_pkt_length(), .mac_int(mac_int[1]), .rx_sop(rx_sop[1]), .rx_eop(rx_eop[1]), .tx_sop(tx_sop[1]), .tx_eop(tx_eop[1]), .rx_active(mac_rx_active[1]), .tx_active(mac_tx_active[1]) ); ipv4_rx ipv4_rx_1( .rstn(sys_rstn), .clk(phy1_rx_clk), // control .phy_resetn (phy_resetn[1]), .phy_up(phy_up[1]), // packet data .pkt_start(ipv4_pkt_start[1]), .rx_sample(rx_sample[1]), .rx_eop(rx_eop[1]), .rx_data_m1(rx1_d_m1), .rx_data_m2(rx1_d_m2), .rx_data_m3(rx1_d_m3), .rx_data_m4(rx1_d_m4), // flags .pkt_complete(ipv4_pkt_complete[1]), .trigger_src_addr(), .trigger_dst_addr(ipv4_trigger_dst_addr[1]), .keep(ipv4_rx_keep[1]) ); udp_rx udp_rx_1( .rstn(sys_rstn), .clk(phy1_rx_clk), // control .phy_resetn (phy_resetn[1]), .phy_up(phy_up[1]), // packet data .pkt_start(ipv4_trigger_dst_addr[1]), .rx_sample(rx_sample[1]), .rx_eop(rx_eop[1]), .rx_data_m1(rx1_d_m1), .rx_data_m2(rx1_d_m2), .rx_data_m3(rx1_d_m3), .rx_data_m4(rx1_d_m4), // flags .pkt_complete(), .trigger_src_port(), .trigger_dst_port(trigger[1]), .keep() ); // PHY1 MAC -> PHY 0 pkt_filter pkt_filter_10( .rstn(sys_rstn), .clk(phy1_rx_clk), // input for programming .prgclk(cont_clk), .sel(pkt_filter_sel && pkt_filter_addr == 16'h1000), .we(mem_we), .addr(mem_addr[2:0]), .d_i(mem_d_o), .d_o(), // registered data .rx_d_m1(rx1_d_m1), .rx_d_m2(rx1_d_m2), .rx_d_m3(rx1_d_m3), .rx_d_m4(rx1_d_m4), // filter .new_frame (rx_sop[1]), .block(1'b0), .invert(1'b1), .trigger(rx_mac_keep[1]), .keep(rx_pf_keep_10) ); drop_fifo drop_fifo_10( .rstn(sys_rstn), .phy_up(phy_up[1]), .rx_clk(phy1_rx_clk), .tx_clk(pclk), .enable(1'b1), // ipv4_rx_keep[1] // control .keep (rx_pf_keep_10), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[1]), .wr_done(rx_mac_wr_done[1]), .rx_idle(rx_idle[1]), .rx_error(rx_mac_error[1]), .d_in(rx_mac_fifo_d1), // output .we_out(rx_df_fifo_we_10), .d_out(rx_df_fifo_d_10), // debug .active(drop_rx1_active[0]) ); sync_fifo sync_fifo_rx_10( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_10 & phy_up[0]), .d_in (rx_df_fifo_d_10), // output .re (rx_sw_fifo_re_10), .d_out(rx_sf_fifo_d_10), .empty(rx_sf_fifo_empty_10), .almost_full(), .reset_ptrs(1'b0), // debug .active(sync_rx1_active[0]) ); `ifdef PHY2_PRESENT // PHY1 MAC -> PHY2 pkt_filter pkt_filter_12( .rstn(sys_rstn), .clk(phy1_rx_clk), // input for programming .prgclk(cont_clk), .sel(pkt_filter_sel && pkt_filter_addr == 16'h1002), .we(mem_we), .addr(mem_addr[2:0]), .d_i(mem_d_o), .d_o(), // registered data .rx_d_m1(rx1_d_m1), .rx_d_m2(rx1_d_m2), .rx_d_m3(rx1_d_m3), .rx_d_m4(rx1_d_m4), // filter .new_frame (rx_sop[1]), .block(1'b0), .invert(1'b1), .trigger(rx_mac_keep[1]), .keep(rx_pf_keep_12) ); drop_fifo drop_fifo_12( .rstn(sys_rstn), .phy_up(phy_up[1]), .rx_clk(phy1_rx_clk), .tx_clk(pclk), .enable(1'b1), // ipv4_rx_keep[1] // control .keep (rx_pf_keep_12), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[1]), .wr_done(rx_mac_wr_done[1]), .rx_idle(rx_idle[1]), .rx_error(rx_mac_error[1]), .d_in(rx_mac_fifo_d1), // output .we_out(rx_df_fifo_we_12), .d_out(rx_df_fifo_d_12), // debug .active(drop_rx1_active[2]) ); sync_fifo sync_fifo_rx_12( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_12 & phy_up[2]), .d_in (rx_df_fifo_d_12), // output .re (rx_sw_fifo_re_12), .d_out(rx_sf_fifo_d_12), .empty(rx_sf_fifo_empty_12), .almost_full(), .reset_ptrs(1'b0), // debug .active(sync_rx1_active[2]) ); `endif dpram_inf #(.ADDR_WIDTH(10), .DPRAM_INIT("param_ram_1.txt")) param_ram_1( .rstn(sys_rstn), // Port A .a_clk(cont_clk), .a_clk_e(param_sel[1]), .a_we(1'b0), .a_oe(mem_oe), .a_addr(mem_addr[9:0]), .a_din(mem_d_o[8:0]), .a_dout(param_ram_1_do), // Port B .b_clk(pclk), .b_clk_e(param_phy1_ce), .b_we(param_phy1_we), .b_oe(1'b1), .b_addr(param_phy1_addr[9:0]), .b_din(param_phy1_dout), .b_dout(param_phy1_din) ); fcs fcs_rx_1( .rstn(sys_rstn), .clk(phy1_rx_clk), .init(fcs_rx_init[1]), .enable(fcs_rx_enable[1]), .addr(fcs_rx_addr1), .din(fcs_rx_din1), .dout(fcs_rx_dout1) ); fcs fcs_tx_1( .rstn(sys_rstn), .clk(pclk), .init(fcs_tx_init[1]), .enable(fcs_tx_enable[1]), .addr(fcs_tx_addr1), .din(fcs_tx_din1), .dout(fcs_tx_dout1) ); `ifdef PHY2_PRESENT /* * * PHY2 IEEE 802.3 ETHERNET for Interface to 1000BASE-T LAN * */ mac_rgmii mac_2( .rstn(sys_rstn), .phy_resetn (phy_resetn[2]), .rx_clk(phy2_rx_clk), .tx_clk(pclk), .tap_port (1'b0), // Control Interface .cont_clk(cont_clk), .cont_sel(mac_sel & mac_addr == 2'b10), .cont_we(mem_we), .cont_addr(mem_addr[7:0]), .cont_d_i(mem_d_o[15:0]), .cont_d_o(mac_2_d_o), .cont_tgt_ready(mem_tgt_ready_mac_2), // ML engine interface .mle_active(mle_evt_active), .mle_if_enable(mle_enable[2]), .mle_if_oe(mle_oe), .mle_if_we(mle_we[2]), .mle_if_empty(mle_empty[2]), .mle_if_d_o(mle_d_2), // Line State .fixed_speed(1'b1), .mode_100Mbit(mode_100Mbit[2]), .phy_up(phy_up[2]), // Switch I/F .tx_mode(tx_sw_mode2), .tx_f(tx_mac_done[2]), // RGMII data I/F .rx_ctl({rx2_ctl_i[1],rx2_ctl_i_m1[0]}), .rx_d({rx2_d_i[7:4], rx2_d_i_m1[3:0]}), .tx_ctl(tx2_ctl), .tx_d(tx2_d), // RX FCS .fcs_rx_init(fcs_rx_init[2]), .fcs_rx_enable(fcs_rx_enable[2]), .fcs_rx_addr(fcs_rx_addr2), .fcs_rx_dout(fcs_rx_din2), .fcs_rx_din(fcs_rx_dout2), // TX FCS .fcs_tx_init(fcs_tx_init[2]), .fcs_tx_enable(fcs_tx_enable[2]), .fcs_tx_addr(fcs_tx_addr2), .fcs_tx_dout(fcs_tx_din2), .fcs_tx_din(fcs_tx_dout2), // MAC RX / FIFO Write .rx_fifo_we(rx_mac_fifo_we[2]), .rx_fifo_d(rx_mac_fifo_d2), .rx_keep(rx_mac_keep[2]), .rx_wr_done(rx_mac_wr_done[2]), .rx_byte_cnt(rx2_mac_byte_cnt), .rx_idle(rx_idle[2]), .rx_error(rx_mac_error[2]), // MAC TX / FIFO Read .tx_byte_cnt_i(tx2_byte_cnt), .tx_src_sel(tx_src_sel2), .tx_fifo_re(tx_mac_fifo_re[2]), .tx_fifo_d(tx_sw_fifo_d2), .tx_fifo_empty(tx_sw_fifo_empty[2]), // Alternate TX Port .tx_uc_fifo_empty(1'b1), // tie off to disable port .tx_uc_fifo_d(9'd0), .tx_mle_fifo_empty(1'b1), .tx_mle_fifo_d(9'd0), // Packet Filter .rx_sample(rx_sample[2]), .ipv4_pkt_start(ipv4_pkt_start[2]), .trigger(), .rx_ctl_m1(rx2_ctl_m1), .rx_ctl_m2(rx2_ctl_m2), .rx_ctl_m3(rx2_ctl_m3), .rx_ctl_m4(rx2_ctl_m4), .rx_d_m1(rx2_d_m1), .rx_d_m2(rx2_d_m2), .rx_d_m3(rx2_d_m3), .rx_d_m4(rx2_d_m4), // Param RAM .dpr_ad(param_phy2_addr), .dpr_we(param_phy2_we), .dpr_ce(param_phy2_ce), .dpr_di(param_phy2_din), .dpr_do(param_phy2_dout), // Metrics and Interrupts .rx_enet_bcast(rx_enet_bcast[2]), .rx_ipv4_arp(rx_ipv4_arp[2]), .rx_l3_proto(), .rx_pkt_length(), .mac_int(mac_int[2]), .rx_sop(rx_sop[2]), .rx_eop(rx_eop[2]), .tx_sop(tx_sop[2]), .tx_eop(tx_eop[2]), .rx_active(mac_rx_active[2]), .tx_active(mac_tx_active[2]) ); ipv4_rx ipv4_rx_2( .rstn(sys_rstn), .clk(phy2_rx_clk), // control .phy_resetn (phy_resetn[2]), .phy_up(phy_up[2]), // packet data .pkt_start(ipv4_pkt_start[2]), .rx_sample(rx_sample[2]), .rx_eop(rx_eop[2]), .rx_data_m1(rx2_d_m1), .rx_data_m2(rx2_d_m2), .rx_data_m3(rx2_d_m3), .rx_data_m4(rx2_d_m4), // flags .pkt_complete(ipv4_pkt_complete[2]), .trigger_src_addr(), .trigger_dst_addr(ipv4_trigger_dst_addr[2]), .keep(ipv4_rx_keep[2]) ); udp_rx udp_rx_2( .rstn(sys_rstn), .clk(phy2_rx_clk), // control .phy_resetn (phy_resetn[2]), .phy_up(phy_up[2]), // packet data .pkt_start(ipv4_trigger_dst_addr[2]), .rx_sample(rx_sample[2]), .rx_eop(rx_eop[2]), .rx_data_m1(rx2_d_m1), .rx_data_m2(rx2_d_m2), .rx_data_m3(rx2_d_m3), .rx_data_m4(rx2_d_m4), // flags .pkt_complete(), .trigger_src_port(), .trigger_dst_port(trigger[2]), .keep() ); // PHY2 MAC -> PHY 0 pkt_filter pkt_filter_20( .rstn(sys_rstn), .clk(phy2_rx_clk), // input for programming .prgclk(cont_clk), .sel(pkt_filter_sel && pkt_filter_addr == 16'h2000), .we(mem_we), .addr(mem_addr[2:0]), .d_i(mem_d_o), .d_o(), // registered data .rx_d_m1(rx2_d_m1), .rx_d_m2(rx2_d_m2), .rx_d_m3(rx2_d_m3), .rx_d_m4(rx2_d_m4), // filter .new_frame (rx_sop[2]), .block(1'b0), .invert(1'b1), .trigger(rx_mac_keep[2]), .keep(rx_pf_keep_20) ); drop_fifo drop_fifo_20( .rstn(sys_rstn), .phy_up(phy_up[2]), .rx_clk(phy2_rx_clk), .tx_clk(pclk), .enable(1'b1), // ipv4_rx_keep[2] // control .keep (rx_pf_keep_20), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[2]), .wr_done(rx_mac_wr_done[2]), .rx_idle(rx_idle[2]), .rx_error(rx_mac_error[2]), .d_in(rx_mac_fifo_d2), // output .we_out(rx_df_fifo_we_20), .d_out(rx_df_fifo_d_20), // debug .active(drop_rx2_active[0]) ); sync_fifo sync_fifo_rx_20( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_20 & phy_up[0]), .d_in (rx_df_fifo_d_20), // output .re (rx_sw_fifo_re_20), .d_out(rx_sf_fifo_d_20), .empty(rx_sf_fifo_empty_20), .almost_full(), .reset_ptrs(1'b0), // debug .active(sync_rx2_active[0]) ); // PHY1 MAC -> PHY2 pkt_filter pkt_filter_21( .rstn(sys_rstn), .clk(phy2_rx_clk), // input for programming .prgclk(cont_clk), .sel(pkt_filter_sel && pkt_filter_addr == 16'h2001), .we(mem_we), .addr(mem_addr[2:0]), .d_i(mem_d_o), .d_o(), // registered data .rx_d_m1(rx2_d_m1), .rx_d_m2(rx2_d_m2), .rx_d_m3(rx2_d_m3), .rx_d_m4(rx2_d_m4), // filter .new_frame (rx_sop[2]), .block(1'b0), .invert(1'b1), .trigger(rx_mac_keep[2]), .keep(rx_pf_keep_21) ); drop_fifo drop_fifo_21( .rstn(sys_rstn), .phy_up(phy_up[2]), .rx_clk(phy2_rx_clk), .tx_clk(pclk), .enable(1'b1), // ipv4_rx_keep[1] // control .keep (rx_pf_keep_21), .passthrough(1'b0), // input .we_in(rx_mac_fifo_we[2]), .wr_done(rx_mac_wr_done[2]), .rx_idle(rx_idle[2]), .rx_error(rx_mac_error[2]), .d_in(rx_mac_fifo_d2), // output .we_out(rx_df_fifo_we_21), .d_out(rx_df_fifo_d_21), // debug .active(drop_rx2_active[1]) ); sync_fifo sync_fifo_rx_21( .rstn(sys_rstn), .clk (pclk), // input .we (rx_df_fifo_we_21 & phy_up[1]), .d_in (rx_df_fifo_d_21), // output .re (rx_sw_fifo_re_21), .d_out(rx_sf_fifo_d_21), .empty(rx_sf_fifo_empty_21), .almost_full(), .reset_ptrs(1'b0), // debug .active(sync_rx2_active[2]) ); `endif dpram_inf #(.ADDR_WIDTH(10), .DPRAM_INIT("param_ram_2.txt")) param_ram_2( .rstn(sys_rstn), // Port A .a_clk(cont_clk), .a_clk_e(param_sel[2]), .a_we(1'b0), .a_oe(mem_oe), .a_addr(mem_addr[9:0]), .a_din(mem_d_o[8:0]), .a_dout(param_ram_2_do), // Port B .b_clk(pclk), .b_clk_e(param_phy2_ce), .b_we(param_phy2_we), .b_oe(1'b1), .b_addr(param_phy2_addr[9:0]), .b_din(param_phy2_dout), .b_dout(param_phy2_din) ); fcs fcs_rx_2( .rstn(sys_rstn), .clk(phy2_rx_clk), .init(fcs_rx_init[2]), .enable(fcs_rx_enable[2]), .addr(fcs_rx_addr2), .din(fcs_rx_din2), .dout(fcs_rx_dout2) ); fcs fcs_tx_2( .rstn(sys_rstn), .clk(pclk), .init(fcs_tx_init[2]), .enable(fcs_tx_enable[2]), .addr(fcs_tx_addr2), .din(fcs_tx_din2), .dout(fcs_tx_dout2) ); `ifdef PASSTHROUGH // phy0_tx_clk = phy1_rx_clk; // Bits 3:0 on the positive edge of TX_CLK and bits 7:4 on the negative edge of TX_CLK. // Note that PHY TX (output) clocks are routed through a DDR. ddro rgmii_tx_0( .aclr(1'b0), .datain_h({1'b1, rx1_ctl_i_m4[0],rx1_d_i_m4[3:0]}), .datain_l({1'b0, rx1_ctl_i_m4[1],rx1_d_i_m4[7:4]}), .oe(1'b1), .outclock(phy1_rx_clk), .dataout({phy0_tx_clk, phy0_tx_ctl, phy0_tx_d})); // phy1_tx_clk = phy0_rx_clk; ddro rgmii_tx_1( .aclr(1'b0), .datain_h({1'b1, rx0_ctl_i_m4[0],rx0_d_i_m4[3:0]}), .datain_l({1'b0, rx0_ctl_i_m4[1],rx0_d_i_m4[7:4]}), .oe(1'b1), .outclock(phy0_rx_clk), .dataout({phy1_tx_clk, phy1_tx_ctl, phy1_tx_d})); // phy2_tx_clk = phy0_rx_clk; ddro rgmii_tx_2( .aclr(1'b0), .datain_h({1'b1, rx0_ctl_i_m4[0],rx0_d_i_m4[3:0]}), .datain_l({1'b0, rx0_ctl_i_m4[1],rx0_d_i_m4[7:4]}), .oe(1'b1), .outclock(phy0_rx_clk), .dataout({phy2_tx_clk, phy2_tx_ctl, phy2_tx_d})); `else ddro rgmii_tx_0( .aclr(1'b0), .datain_h({1'b1, tx0_ctl[0], tx0_d[3:0]}), .datain_l({1'b0, tx0_ctl[1], tx0_d[7:4]}), .oe(1'b1), .outclock(pclk), .dataout({phy0_tx_clk, phy0_tx_ctl, phy0_tx_d})); ddro rgmii_tx_1( .aclr(1'b0), .datain_h({1'b1, tx1_ctl[0],tx1_d[3:0]}), .datain_l({1'b0, tx1_ctl[1],tx1_d[7:4]}), .oe(1'b1), .outclock(pclk), .dataout({phy1_tx_clk, phy1_tx_ctl, phy1_tx_d})); ddro rgmii_tx_2( .aclr(1'b0), .datain_h({1'b1, tx2_ctl[0],tx2_d[3:0]}), .datain_l({1'b0, tx2_ctl[1],tx2_d[7:4]}), .oe(1'b1), .outclock(pclk), .dataout({phy2_tx_clk, phy2_tx_ctl, phy2_tx_d})); `endif // Debug //Heart beat cnt for LEDs and general debug always @(posedge cont_clk, negedge sys_rstn) if (!sys_rstn) heart_beat_cnt <= 26'h0; else heart_beat_cnt <= heart_beat_cnt + 1'b1; always @(posedge pclk, negedge sys_rstn) if (!sys_rstn) evt_toggle <= 1'b0; else if (mle_evt_start) evt_toggle <= ~evt_toggle; assign fpga_led[0] = heart_beat_cnt[22]; assign fpga_led[1] = heart_beat_cnt[23]; assign fpga_led[2] = evt_toggle; endmodule