diff options
Diffstat (limited to 'manufacturer/altera/cyclone10_lp/src/betsy.v')
| -rw-r--r-- | manufacturer/altera/cyclone10_lp/src/betsy.v | 1916 |
1 files changed, 1916 insertions, 0 deletions
diff --git a/manufacturer/altera/cyclone10_lp/src/betsy.v b/manufacturer/altera/cyclone10_lp/src/betsy.v new file mode 100644 index 0000000..2116b34 --- /dev/null +++ b/manufacturer/altera/cyclone10_lp/src/betsy.v @@ -0,0 +1,1916 @@ +/* + * 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 |



