diff options
Diffstat (limited to 'manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v')
| -rw-r--r-- | manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v b/manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v new file mode 100644 index 0000000..2ebf8a1 --- /dev/null +++ b/manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v @@ -0,0 +1,375 @@ +/* + * betsy.v + * + * Copyright (C) 2024 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 + * + * + */ + +module betsy ( + input rstn, + input clk, // 25Mhz + + input phy0_clk, + output phy1_clk, + + // 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, + 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 + ); + +localparam LINK_NORMAL_INTERFRAME = 2'b00, + LINK_PHY_STATUS = 2'b01, + LINK_ERROR_DATA_RX = 2'b10, + LINK_NORMAL_DATA_RX = 2'b11; + +localparam MDIO_ROM_ADDR_SZ = 7; + + +reg [25:0] heart_beat_cnt; +reg [7:0] datain_h_sig, datain_l_sig; +wire [7:0] dataout_h_sig, dataout_l_sig; + +wire [7:0] rx0_d, rx1_d; +wire [1:0] rx0_ctl, rx1_ctl; +reg [7:0] rx0_d_m1, rx0_d_m2, rx0_d_m3, rx0_d_m4; +reg [1:0] rx0_ctl_m1, rx0_ctl_m2, rx0_ctl_m3, rx0_ctl_m4; +reg rx0_sop, rx0_eop; +reg [7:0] rx1_d_m1, rx1_d_m2, rx1_d_m3, rx1_d_m4; +reg [1:0] rx1_ctl_m1, rx1_ctl_m2, rx1_ctl_m3, rx1_ctl_m4; +reg [15:0] rx_cnt; +reg [1:0] link_state; +reg link_up; + +reg [1:0] link_speed; // TODO: what's the right IEEE name? +reg link_duplex; + +// MDIO controller and driver +wire mdio_cont_work_start, mdio_cont_work_run; +wire mdio_cont_work_done; +wire [MDIO_ROM_ADDR_SZ-1:0] mdio_routine_addr; +wire [1:0] mdio_mux_sel; +wire mdio_done, mdo_oe; +wire mdo; +reg mdi; +wire [15:0] mdio_wd; +wire [15:0] mdio_rd; +wire [4:0] mdio_reg_addr; +wire mdio_ld, mdio_run; +wire mdio_rwn; +wire bin_to_ascii_run; + +// MDIO Data block +wire [MDIO_ROM_ADDR_SZ-1:0] rom_a; +wire [7:0] rom_d; +wire [4:0] mdio_reg_addr_set; +wire [7:0] mdio_w_data_h_set, mdio_w_data_l_set; +wire [4:0] mdio_page_set; +wire bin_to_ascii_we, mdio_rd_we, cont_rd_we; + +// Debug +wire pcs_pclk; // main fabric clock for Ethernet pipeline +wire pll_locked; + +pll pll_0( + .areset(~rstn), + .inclk0(clk), + .c0(phy1_clk), + .c1(pcs_pclk), + .locked(pll_locked)); + +// TODO: I have the h/l assignments backwards, SDC is wrong +ddri rgmi_rx_0 ( + .datain ( {phy0_rx_ctl, phy0_rx_d} ), + .inclock ( phy0_rx_clk ), + .dataout_h ( {rx0_ctl[1],rx0_d[7:4]} ), + .dataout_l ( {rx0_ctl[0],rx0_d[3:0]} ) + ); + + +ddri rgmi_rx_1 ( + .datain ( {phy1_rx_ctl, phy1_rx_d} ), + .inclock ( phy1_rx_clk ), + .dataout_h ( {rx1_ctl[1],rx1_d[7:4]} ), + .dataout_l ( {rx1_ctl[0],rx1_d[3:0]} ) + ); + +assign phy0_tx_clk = phy1_rx_clk; +ddro rgmii_tx_0( + .aclr(1'b0), + .datain_l({rx1_ctl_m4[1],rx1_d_m4[7:4]}), + .datain_h({rx1_ctl_m4[0],rx1_d_m4[3:0]}), + .oe(1'b1), + .outclock(phy1_rx_clk), + .dataout({phy0_tx_ctl, phy0_tx_d})); + +assign phy1_tx_clk = phy0_rx_clk; +ddro rgmii_tx_1( + .aclr(1'b0), + .datain_l({rx0_ctl_m4[1],rx0_d_m4[7:4]}), + .datain_h({rx0_ctl_m4[0],rx0_d_m4[3:0]}), + .oe(1'b1), + .outclock(phy0_rx_clk), + .dataout({phy1_tx_ctl, phy1_tx_d})); + +assign phy2_tx_clk = phy0_rx_clk; +ddro rgmii_tx_2( + .aclr(1'b0), + .datain_h({rx0_ctl_m4[1],rx0_d_m4[7:4]}), + .datain_l({rx0_ctl_m4[0],rx0_d_m4[3:0]}), + .oe(1'b1), + .outclock(phy0_rx_clk), + .dataout({phy2_tx_ctl, phy2_tx_d})); + +// pipeline regs +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) begin + rx0_d_m1 <= 8'h0; + rx0_d_m2 <= 8'h0; + rx0_d_m3 <= 8'h0; + rx0_d_m4 <= 8'h0; + end + else begin + rx0_d_m1 <= rx0_d; + rx0_d_m2 <= rx0_d_m1; + rx0_d_m3 <= rx0_d_m2; + rx0_d_m4 <= rx0_d_m3; + end + +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) begin + rx0_ctl_m1 <= 2'h0; + rx0_ctl_m2 <= 2'h0; + rx0_ctl_m3 <= 2'h0; + rx0_ctl_m4 <= 2'h0; + end + else begin + rx0_ctl_m1 <= rx0_ctl; + rx0_ctl_m2 <= rx0_ctl_m1; + rx0_ctl_m3 <= rx0_ctl_m2; + rx0_ctl_m4 <= rx0_ctl_m3; + end + +// TODO: take into account errors RXERR +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) + rx0_sop <= 1'b0; + else if (!rx0_ctl_m1[0] && rx0_ctl[0]) + rx0_sop <= 1'b1; + else + rx0_sop <= 1'b0; + +// TODO: take into account errors take into account errors +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) + rx0_eop <= 1'b0; + else if (rx0_ctl_m1[0] && !rx0_ctl[0]) + rx0_eop <= 1'b1; + else + rx0_eop <= 1'b0; + +// pipeline regs +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) begin + rx1_d_m1 <= 8'h0; + rx1_d_m2 <= 8'h0; + rx1_d_m3 <= 8'h0; + rx1_d_m4 <= 8'h0; + end + else begin + rx1_d_m1 <= rx1_d; + rx1_d_m2 <= rx1_d_m1; + rx1_d_m3 <= rx1_d_m2; + rx1_d_m4 <= rx1_d_m3; + end + +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) begin + rx1_ctl_m1 <= 2'h0; + rx1_ctl_m2 <= 2'h0; + rx1_ctl_m3 <= 2'h0; + rx1_ctl_m4 <= 2'h0; + end + else begin + rx1_ctl_m1 <= rx1_ctl; + rx1_ctl_m2 <= rx1_ctl_m1; + rx1_ctl_m3 <= rx1_ctl_m2; + rx1_ctl_m4 <= rx1_ctl_m3; + end + + +// capture link metrics during normal inter-frame +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) begin + link_up <= 1'b0; + link_speed <= 2'b11; // reserved + link_duplex <= 1'b0; + end + else if (rx0_ctl_m1 == 2'b00) begin + link_up <= rx0_d_m1[0]; + link_speed <= rx0_d_m1[2:1]; + link_duplex <= rx0_d_m1[3]; + end + +// capture link_state +always @(posedge phy0_rx_clk, negedge rstn) + if (!rstn) + link_state <= LINK_NORMAL_INTERFRAME; + else + link_state <= rx0_ctl_m1; + +assign phy0_rstn = 1'b1; +assign phy1_rstn = pll_locked; +assign phy2_rstn = pll_locked; + +assign flash_d = 8'hab; +assign flash_seln = 1'b1; +assign flash_clk = clk; + +//Heart beat by 50MHz clock +always @(posedge clk or negedge rstn) + if (!rstn) begin + heart_beat_cnt <= 26'h0; //0x3FFFFFF + end + else begin + heart_beat_cnt <= heart_beat_cnt + 1'b1; + end + + +assign phy0_mdc = clk; +assign phy1_mdc = clk; +assign phy2_mdc = clk; + +assign phy0_mdio = mdo_oe ? mdo : 1'bz; +assign phy1_mdio = 1'b0; +assign phy2_mdio = 1'b0; + +assign fpga_led[0] = heart_beat_cnt[22]; +assign fpga_led[1] = heart_beat_cnt[23]; +assign fpga_led[2] = heart_beat_cnt[24]; + +assign phy2_gpio[0] = rx0_sop; +assign phy2_gpio[1] = rx0_eop; + + + +mdio_controller #(.ADDR_SZ( MDIO_ROM_ADDR_SZ )) mdio_controller_0 + ( + .rstn(rstn), + .clk(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(rom_a), + .di(rom_d), + .reg_addr(mdio_reg_addr), + .dout(mdio_wd), + .ld(mdio_ld), + .rwn(mdio_rwn), + .done(mdio_done) + ); + +mdio_data_ti #(.ADDR_SZ( MDIO_ROM_ADDR_SZ )) mdio_data_ti_0( + .ad( rom_a ), + .page( mdio_page_set ), + .reg_addr( mdio_reg_addr_set ), + .data_in_h( mdio_w_data_h_set ), + .data_in_l( mdio_w_data_l_set ), + .d( rom_d ), + .oe( 1'b1 ) + ); + +mdio mdio_0( + .rstn(rstn), + .mdc(clk_10), + // MDIO + .mdi(mdi), + .mdo(mdo), + .mdo_oe(mdo_oe), + // mdio controller interface + .rwn(mdio_rwn), + .phy_addr(5'h00), + .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 ) + ); + + +endmodule |



