summaryrefslogtreecommitdiffhomepage
path: root/manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v
diff options
context:
space:
mode:
Diffstat (limited to 'manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v')
-rw-r--r--manufacturer/altera/cyclone10_lp/src/betsy_passthrough_regs.v375
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

Highly Recommended Verilog Books