diff options
author | mindchasers <privateisland@mindchasers.com> | 2021-03-02 12:28:04 -0500 |
---|---|---|
committer | mindchasers <privateisland@mindchasers.com> | 2021-03-02 12:28:04 -0500 |
commit | b49be0230de6f2e1a2a893b6eb5722429f78ec7f (patch) | |
tree | 8577312dbb0b38f37261c86c8e818a7c9fc6ffe7 /source | |
parent | 9a616927d7095d7afef9684c5569ab233c59fdcb (diff) |
an: encapsulate a simpliied version of SGMII auto negotiation
Diffstat (limited to 'source')
-rw-r--r-- | source/an.v | 122 |
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 |