summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormindchasers <privateisland@mindchasers.com>2021-03-02 12:28:04 -0500
committermindchasers <privateisland@mindchasers.com>2021-03-02 12:28:04 -0500
commitb49be0230de6f2e1a2a893b6eb5722429f78ec7f (patch)
tree8577312dbb0b38f37261c86c8e818a7c9fc6ffe7
parent9a616927d7095d7afef9684c5569ab233c59fdcb (diff)
an: encapsulate a simpliied version of SGMII auto negotiation
-rw-r--r--source/an.v122
1 files changed, 122 insertions, 0 deletions
diff --git a/source/an.v b/source/an.v
new file mode 100644
index 0000000..18b5d95
--- /dev/null
+++ b/source/an.v
@@ -0,0 +1,122 @@
+/*
+ * an.v
+ *
+ * Copyright 2021 Mind Chasers 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: Auto Negotiation
+ *
+ * Notes: a simplified version of AN suitable for SGMII only (not 1000BASE-SX)
+ */
+
+`timescale 1ns /10ps
+
+module an(
+ input rstn,
+ input phy_resetn, // The external PHY has its reset signal asserted
+ input clk,
+
+ // AN
+ input [1:0] phy_type, // SGMII==0, SX=1, SMA=3
+ input pulse_1_6ms, // SGMII
+ input pulse_10ms, // SX
+ input [1:0] fixed_speed,
+ input an_disable,
+ output reg an_duplex,
+ output reg [1:0] an_speed,
+ output reg an_link_up,
+ output reg [15:0] tx_config_reg,
+ output reg phy_up,
+
+ input rx_k_m1,
+ input rx_k_m2,
+ input rx_k_m3,
+ input rx_k_m4,
+
+ input [7:0] rx_data_m1,
+ input [7:0] rx_data_m2,
+ input [7:0] rx_data_m3,
+ input [7:0] rx_data_m4
+
+ // Debug
+);
+
+`include "sgmii_params.v"
+`include "ethernet_params.v"
+
+localparam PHY_TYPE_SGMII = 2'b00,
+ PHY_TYPE_SX = 2'b01,
+ PHY_TYPE_RSVD = 2'b10,
+ PHY_TYPE_SMA = 2'b11;
+
+
+localparam AN_TYPE_SX = 1'b0,
+ AN_TYPE_SGMII = 1'b1;
+
+localparam AN_ST_DISABLE=4'h0, AN_ST_ENABLE=4'h1, AN_ST_RESTART=4'h2,
+ AN_ST_ABILITY_DETECT=4'h3, AN_ST_ACK_DETECT=4'h4,
+ AN_ST_COMPLETE_ACK=4'h5, AN_ST_IDLE_DETECT=4'h6, AN_ST_LINK_OK=4'h7;
+
+// AN
+reg [2:0] an_state;
+wire an_ability_detect;
+wire an_link_timer_pulse;
+reg rx_config_detect;
+reg [15:0] rx_config_reg, tx_config_reg;
+reg [1:0] rx_config_cnt; // use to count consecutive rx config_regs
+
+/*
+ * SGMII Auto Negotiation State Machine
+ * Look for configuration /C/ ordered set
+ * /C/ is Alternating /C1/ and /C2/
+ * /C1/: /K28.5/D21.5(0xb5)/Config_Reg
+ * /C2/: /K28.5/D2.2(0x42)/Config_Reg
+ * Config Reg: Low High
+ */
+always @(posedge clk or negedge rstn)
+ if (!rstn)
+ begin
+ an_link_up <= 1'b0;
+ an_duplex <= 1'b0;
+ an_speed <= SGMII_SPEED_RSVD;
+ phy_up <= 1'b0;
+ end
+ else if ( !phy_resetn )
+ begin
+ an_link_up <= 1'b0;
+ an_duplex <= 1'b0;
+ an_speed <= SGMII_SPEED_RSVD;
+ phy_up <= 1'b0;
+ end
+ else if ( an_disable )
+ begin
+ phy_up <= 1'b1;
+ end
+ // D21.5 is part of config ( M2 has low, M1 has high )
+ else if (!rx_k_m1 && !rx_k_m2 && !rx_k_m3 && rx_data_m3 == D21_5 && rx_k_m4 && rx_data_m4 == K28_5 )
+ begin
+ an_link_up <= rx_data_m1[7];
+ an_duplex <= rx_data_m1[4];
+ an_speed <= rx_data_m1[3:2];
+ phy_up <= 1'b0;
+ end
+ // IDLE2 1:0xBC, 0:0x50
+ else if ( !rx_k_m1 && rx_data_m1 == D16_2 && rx_k_m2 == 1'b1 && rx_data_m2 == K28_5 )
+ phy_up <= 1'b1;
+
+
+assign an_ability_detect = (rx_config_cnt == 2'd3 && rx_config_reg != 16'h0000 );
+assign link_timer_pulse = (phy_type == PHY_TYPE_SGMII && pulse_1_6ms) || (phy_type == PHY_TYPE_SX && pulse_10ms);
+
+endmodule