mirror of
https://github.com/fpganinja/taxi.git
synced 2026-08-17 04:41:19 -07:00
eth: Add support for 1000BASE-X autonegotiation to 1000BASE-X MAC+PCS
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
taxi_eth_mac_phy_1g_basex.sv
|
||||
taxi_eth_mac_phy_1g_basex_rx.f
|
||||
taxi_eth_mac_phy_1g_basex_tx.f
|
||||
taxi_eth_phy_1g_basex_an.sv
|
||||
taxi_eth_mac_stats.f
|
||||
taxi_mac_ctrl_tx.sv
|
||||
taxi_mac_ctrl_rx.sv
|
||||
|
||||
@@ -21,6 +21,7 @@ module taxi_eth_mac_phy_1g_basex #
|
||||
parameter CTRL_W = (DATA_W/8),
|
||||
parameter logic TX_GBX_IF_EN = 1'b0,
|
||||
parameter logic RX_GBX_IF_EN = TX_GBX_IF_EN,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -76,6 +77,17 @@ module taxi_eth_mac_phy_1g_basex #
|
||||
input wire logic serdes_rx_data_valid = 1'b1,
|
||||
output wire logic serdes_rx_reset_req,
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
input wire logic an_en = 1'b1,
|
||||
input wire logic an_restart = 1'b0,
|
||||
input wire logic an_speedup = 1'b0,
|
||||
output wire logic an_intr,
|
||||
output wire logic an_complete,
|
||||
input wire logic [15:0] an_adv_ability = 16'h0020,
|
||||
output wire logic [15:0] an_lp_adv_ability,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
@@ -353,10 +365,97 @@ end else begin
|
||||
|
||||
end
|
||||
|
||||
// Autonegotiation
|
||||
wire logic [15:0] rx_an_cfg;
|
||||
wire logic rx_an_cfg_valid;
|
||||
wire logic rx_an_ability_match;
|
||||
wire logic rx_an_ack_match;
|
||||
wire logic rx_an_idle_match;
|
||||
|
||||
wire logic [15:0] tx_an_cfg;
|
||||
wire logic tx_an_cfg_valid;
|
||||
wire logic tx_an_cfg_ready;
|
||||
|
||||
if (AN_EN) begin : an
|
||||
|
||||
// synchronize RX signals to TX
|
||||
wire [15:0] sync_rx_an_cfg;
|
||||
wire sync_rx_an_cfg_valid;
|
||||
wire sync_rx_an_ability_match;
|
||||
wire sync_rx_an_ack_match;
|
||||
wire sync_rx_an_idle_match;
|
||||
|
||||
taxi_sync_signal #(
|
||||
.WIDTH(16+4),
|
||||
.N(2)
|
||||
)
|
||||
sync_inst (
|
||||
.clk(tx_clk),
|
||||
|
||||
.in({
|
||||
rx_an_cfg,
|
||||
rx_an_cfg_valid,
|
||||
rx_an_ability_match,
|
||||
rx_an_ack_match,
|
||||
rx_an_idle_match
|
||||
}),
|
||||
.out({
|
||||
sync_rx_an_cfg,
|
||||
sync_rx_an_cfg_valid,
|
||||
sync_rx_an_ability_match,
|
||||
sync_rx_an_ack_match,
|
||||
sync_rx_an_idle_match
|
||||
})
|
||||
);
|
||||
|
||||
taxi_eth_phy_1g_basex_an #(
|
||||
.DATA_W(DATA_W)
|
||||
)
|
||||
an_inst (
|
||||
.clk(tx_clk),
|
||||
.rst(tx_rst),
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.rx_an_cfg(sync_rx_an_cfg),
|
||||
.rx_an_cfg_valid(sync_rx_an_cfg_valid),
|
||||
.rx_an_ability_match(sync_rx_an_ability_match),
|
||||
.rx_an_ack_match(sync_rx_an_ack_match),
|
||||
.rx_an_idle_match(sync_rx_an_idle_match),
|
||||
|
||||
.tx_an_cfg(tx_an_cfg),
|
||||
.tx_an_cfg_valid(tx_an_cfg_valid),
|
||||
.tx_an_cfg_ready(tx_an_cfg_ready),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en),
|
||||
.an_restart(an_restart),
|
||||
.an_speedup(an_speedup),
|
||||
.an_intr(an_intr),
|
||||
.an_complete(an_complete),
|
||||
.an_adv_ability(an_adv_ability),
|
||||
.an_lp_adv_ability(an_lp_adv_ability)
|
||||
);
|
||||
|
||||
end else begin : an
|
||||
|
||||
assign tx_an_cfg = '0;
|
||||
assign tx_an_cfg_valid = 1'b0;
|
||||
|
||||
assign an_intr = 1'b0;
|
||||
assign an_complete = 1'b0;
|
||||
assign an_lp_adv_ability = '0;
|
||||
|
||||
end
|
||||
|
||||
taxi_eth_mac_phy_1g_basex_rx #(
|
||||
.DATA_W(DATA_W),
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(RX_GBX_IF_EN),
|
||||
.AN_EN(AN_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
|
||||
.PTP_TS_W(PTP_TS_W),
|
||||
@@ -382,6 +481,15 @@ rx_inst (
|
||||
.serdes_rx_data_valid(serdes_rx_data_valid),
|
||||
.serdes_rx_reset_req(serdes_rx_reset_req),
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.rx_an_cfg(rx_an_cfg),
|
||||
.rx_an_cfg_valid(rx_an_cfg_valid),
|
||||
.rx_an_ability_match(rx_an_ability_match),
|
||||
.rx_an_ack_match(rx_an_ack_match),
|
||||
.rx_an_idle_match(rx_an_idle_match),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
@@ -423,6 +531,7 @@ taxi_eth_mac_phy_1g_basex_tx #(
|
||||
.DATA_W(DATA_W),
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(TX_GBX_IF_EN),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
|
||||
@@ -455,6 +564,13 @@ tx_inst (
|
||||
.serdes_tx_gbx_req_stall(serdes_tx_gbx_req_stall),
|
||||
.serdes_tx_gbx_sync(serdes_tx_gbx_sync),
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.tx_an_cfg(tx_an_cfg),
|
||||
.tx_an_cfg_valid(tx_an_cfg_valid),
|
||||
.tx_an_cfg_ready(tx_an_cfg_ready),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@ module taxi_eth_mac_phy_1g_basex_fifo #
|
||||
parameter CTRL_W = (DATA_W/8),
|
||||
parameter logic TX_GBX_IF_EN = 1'b0,
|
||||
parameter logic RX_GBX_IF_EN = TX_GBX_IF_EN,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -89,6 +90,17 @@ module taxi_eth_mac_phy_1g_basex_fifo #
|
||||
input wire logic serdes_rx_data_valid = 1'b1,
|
||||
output wire logic serdes_rx_reset_req,
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
input wire logic an_en = 1'b1,
|
||||
input wire logic an_restart = 1'b0,
|
||||
input wire logic an_speedup = 1'b0,
|
||||
output wire logic an_intr,
|
||||
output wire logic an_complete,
|
||||
input wire logic [15:0] an_adv_ability = 16'h0020,
|
||||
output wire logic [15:0] an_lp_adv_ability,
|
||||
|
||||
/*
|
||||
* PTP clock
|
||||
*/
|
||||
@@ -297,6 +309,7 @@ taxi_eth_mac_phy_1g_basex #(
|
||||
.CTRL_W(CTRL_W),
|
||||
.TX_GBX_IF_EN(TX_GBX_IF_EN),
|
||||
.RX_GBX_IF_EN(RX_GBX_IF_EN),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TD_EN),
|
||||
@@ -350,6 +363,17 @@ mac_phy_inst (
|
||||
.serdes_rx_data_valid(serdes_rx_data_valid),
|
||||
.serdes_rx_reset_req(serdes_rx_reset_req),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en),
|
||||
.an_restart(an_restart),
|
||||
.an_speedup(an_speedup),
|
||||
.an_intr(an_intr),
|
||||
.an_complete(an_complete),
|
||||
.an_adv_ability(an_adv_ability),
|
||||
.an_lp_adv_ability(an_lp_adv_ability),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ module taxi_eth_mac_phy_1g_basex_rx #
|
||||
parameter DATA_W = 16,
|
||||
parameter CTRL_W = (DATA_W/8),
|
||||
parameter logic GBX_IF_EN = 1'b0,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b1,
|
||||
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
|
||||
@@ -45,6 +46,15 @@ module taxi_eth_mac_phy_1g_basex_rx #
|
||||
input wire logic serdes_rx_data_valid = 1'b1,
|
||||
output wire logic serdes_rx_reset_req,
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
output wire logic [15:0] rx_an_cfg,
|
||||
output wire logic rx_an_cfg_valid,
|
||||
output wire logic rx_an_ability_match,
|
||||
output wire logic rx_an_ack_match,
|
||||
output wire logic rx_an_idle_match,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
@@ -136,7 +146,7 @@ if (DATA_W == 16) begin
|
||||
.DATA_W(DATA_W),
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(GBX_IF_EN),
|
||||
.AN_EN(1'b0),
|
||||
.AN_EN(AN_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
|
||||
.PTP_TS_W(PTP_TS_W)
|
||||
@@ -160,11 +170,11 @@ if (DATA_W == 16) begin
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.rx_an_cfg(),
|
||||
.rx_an_cfg_valid(),
|
||||
.rx_an_ability_match(),
|
||||
.rx_an_ack_match(),
|
||||
.rx_an_idle_match(),
|
||||
.rx_an_cfg(rx_an_cfg),
|
||||
.rx_an_cfg_valid(rx_an_cfg_valid),
|
||||
.rx_an_ability_match(rx_an_ability_match),
|
||||
.rx_an_ack_match(rx_an_ack_match),
|
||||
.rx_an_idle_match(rx_an_idle_match),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
@@ -204,7 +214,7 @@ end else begin
|
||||
.DATA_W(DATA_W),
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(GBX_IF_EN),
|
||||
.AN_EN(1'b0),
|
||||
.AN_EN(AN_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_W(PTP_TS_W)
|
||||
)
|
||||
@@ -227,11 +237,11 @@ end else begin
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.rx_an_cfg(),
|
||||
.rx_an_cfg_valid(),
|
||||
.rx_an_ability_match(),
|
||||
.rx_an_ack_match(),
|
||||
.rx_an_idle_match(),
|
||||
.rx_an_cfg(rx_an_cfg),
|
||||
.rx_an_cfg_valid(rx_an_cfg_valid),
|
||||
.rx_an_ability_match(rx_an_ability_match),
|
||||
.rx_an_ack_match(rx_an_ack_match),
|
||||
.rx_an_idle_match(rx_an_idle_match),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
|
||||
@@ -20,6 +20,7 @@ module taxi_eth_mac_phy_1g_basex_tx #
|
||||
parameter DATA_W = 16,
|
||||
parameter CTRL_W = (DATA_W/8),
|
||||
parameter logic GBX_IF_EN = 1'b0,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TS_FMT_TOD = 1'b1,
|
||||
@@ -52,6 +53,13 @@ module taxi_eth_mac_phy_1g_basex_tx #
|
||||
input wire logic serdes_tx_gbx_req_stall = 1'b0,
|
||||
output wire logic serdes_tx_gbx_sync,
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
input wire logic [15:0] tx_an_cfg = '0,
|
||||
input wire logic tx_an_cfg_valid = 1'b0,
|
||||
output wire logic tx_an_cfg_ready,
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
@@ -142,7 +150,7 @@ if (DATA_W == 16) begin
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(GBX_IF_EN),
|
||||
.GBX_CNT(1),
|
||||
.AN_EN(1'b0),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_W(PTP_TS_W),
|
||||
@@ -173,9 +181,9 @@ if (DATA_W == 16) begin
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.tx_an_cfg('0),
|
||||
.tx_an_cfg_valid(1'b0),
|
||||
.tx_an_cfg_ready(),
|
||||
.tx_an_cfg(tx_an_cfg),
|
||||
.tx_an_cfg_valid(tx_an_cfg_valid),
|
||||
.tx_an_cfg_ready(tx_an_cfg_ready),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
@@ -213,7 +221,7 @@ end else begin
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(GBX_IF_EN),
|
||||
.GBX_CNT(1),
|
||||
.AN_EN(1'b0),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TS_W(PTP_TS_W),
|
||||
@@ -244,9 +252,9 @@ end else begin
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.tx_an_cfg('0),
|
||||
.tx_an_cfg_valid(1'b0),
|
||||
.tx_an_cfg_ready(),
|
||||
.tx_an_cfg(tx_an_cfg),
|
||||
.tx_an_cfg_valid(tx_an_cfg_valid),
|
||||
.tx_an_cfg_ready(tx_an_cfg_ready),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
|
||||
@@ -53,6 +53,7 @@ module taxi_eth_mac_1g_basex_us #
|
||||
|
||||
// MAC/PHY parameters
|
||||
parameter logic COMBINED_MAC_PCS = 1'b1,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -130,6 +131,17 @@ module taxi_eth_mac_1g_basex_us #
|
||||
*/
|
||||
taxi_axis_if.src m_axis_rx[CNT],
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
input wire logic an_en[CNT] = '{CNT{1'b1}},
|
||||
input wire logic an_restart[CNT] = '{CNT{1'b0}},
|
||||
input wire logic an_speedup[CNT] = '{CNT{1'b0}},
|
||||
output wire logic an_intr[CNT],
|
||||
output wire logic an_complete[CNT],
|
||||
input wire logic [15:0] an_adv_ability[CNT] = '{CNT{16'h0020}},
|
||||
output wire logic [15:0] an_lp_adv_ability[CNT],
|
||||
|
||||
/*
|
||||
* PTP clock
|
||||
*/
|
||||
@@ -422,6 +434,7 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch
|
||||
|
||||
// MAC/PHY parameters
|
||||
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TD_EN),
|
||||
@@ -513,6 +526,17 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch
|
||||
*/
|
||||
.m_axis_rx(m_axis_rx[n]),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en[n]),
|
||||
.an_restart(an_restart[n]),
|
||||
.an_speedup(an_speedup[n]),
|
||||
.an_intr(an_intr[n]),
|
||||
.an_complete(an_complete[n]),
|
||||
.an_adv_ability(an_adv_ability[n]),
|
||||
.an_lp_adv_ability(an_lp_adv_ability[n]),
|
||||
|
||||
/*
|
||||
* PTP clock
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,7 @@ module taxi_eth_mac_1g_basex_us_ch #
|
||||
|
||||
// MAC/PHY parameters
|
||||
parameter logic COMBINED_MAC_PCS = 1'b1,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -143,6 +144,17 @@ module taxi_eth_mac_1g_basex_us_ch #
|
||||
*/
|
||||
taxi_axis_if.src m_axis_rx,
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
input wire logic an_en = 1'b1,
|
||||
input wire logic an_restart = 1'b0,
|
||||
input wire logic an_speedup = 1'b0,
|
||||
output wire logic an_intr,
|
||||
output wire logic an_complete,
|
||||
input wire logic [15:0] an_adv_ability = 16'h0020,
|
||||
output wire logic [15:0] an_lp_adv_ability,
|
||||
|
||||
/*
|
||||
* PTP clock
|
||||
*/
|
||||
@@ -555,6 +567,7 @@ if (COMBINED_MAC_PCS) begin : mac
|
||||
.CTRL_W(CTRL_W),
|
||||
.TX_GBX_IF_EN(GBX_EN),
|
||||
.RX_GBX_IF_EN(GBX_EN),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TD_EN),
|
||||
@@ -608,6 +621,17 @@ if (COMBINED_MAC_PCS) begin : mac
|
||||
.serdes_rx_data_valid(serdes_rx_data_valid),
|
||||
.serdes_rx_reset_req(rx_reset_req),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en),
|
||||
.an_restart(an_restart),
|
||||
.an_speedup(an_speedup),
|
||||
.an_intr(an_intr),
|
||||
.an_complete(an_complete),
|
||||
.an_adv_ability(an_adv_ability),
|
||||
.an_lp_adv_ability(an_lp_adv_ability),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
|
||||
@@ -43,6 +43,7 @@ export PARAM_QPLL1_PD := 1
|
||||
export PARAM_QPLL0_EXT_CTRL := 0
|
||||
export PARAM_QPLL1_EXT_CTRL := 0
|
||||
export PARAM_COMBINED_MAC_PCS := 1
|
||||
export PARAM_AN_EN := 1
|
||||
export PARAM_DIC_EN := 1
|
||||
export PARAM_PTP_TS_EN := 1
|
||||
export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN)
|
||||
|
||||
@@ -127,6 +127,11 @@ class TB:
|
||||
dut.rx_rst_in.setimmediatevalue([0]*4)
|
||||
dut.tx_rst_in.setimmediatevalue([0]*4)
|
||||
|
||||
dut.an_en.setimmediatevalue([0]*4)
|
||||
dut.an_restart.setimmediatevalue([0]*4)
|
||||
dut.an_speedup.setimmediatevalue([1]*4)
|
||||
dut.an_adv_ability.setimmediatevalue([0x0020]*4)
|
||||
|
||||
dut.stat_rx_fifo_drop.setimmediatevalue([0]*4)
|
||||
|
||||
dut.cfg_tx_pad_en.setimmediatevalue([0]*4)
|
||||
@@ -774,6 +779,81 @@ async def run_test_pfc(dut, port=0, ifg=12):
|
||||
await RisingEdge(dut.xcvr_ctrl_clk)
|
||||
|
||||
|
||||
async def run_test_an(dut, port=0):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
tb.dut.an_en[port].value = 1
|
||||
tb.dut.an_restart[port].value = 0
|
||||
tb.dut.an_speedup[port].value = 1
|
||||
tb.dut.an_adv_ability[port].value = 0x0020
|
||||
|
||||
await tb.reset()
|
||||
|
||||
tb.log.info("Wait for reset")
|
||||
while int(dut.rx_rst_out[port].value):
|
||||
await RisingEdge(dut.xcvr_ctrl_clk)
|
||||
|
||||
tb.log.info("Wait for block lock")
|
||||
while not int(dut.rx_block_lock[port].value):
|
||||
await RisingEdge(dut.xcvr_ctrl_clk)
|
||||
|
||||
for k in range(100):
|
||||
await RisingEdge(dut.xcvr_ctrl_clk)
|
||||
|
||||
tb.log.info("AN_RESTART")
|
||||
tb.serdes_sources[port].set_an_cfg(0x0000)
|
||||
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
|
||||
tb.log.info("ABILITY_DETECT")
|
||||
tb.serdes_sources[port].set_an_cfg(0x002A)
|
||||
|
||||
lp_cfg = None
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
lp_cfg = tb.serdes_sinks[port].get_an_cfg()
|
||||
if tb.serdes_sinks[port].get_an_ability_match() and lp_cfg is not None and lp_cfg != 0:
|
||||
break
|
||||
|
||||
assert lp_cfg & 0xbfff == int(tb.dut.an_adv_ability[port].value) & 0xbfff
|
||||
|
||||
tb.log.info("ACKNOWLEDGE_DETECT")
|
||||
tb.serdes_sources[port].set_an_cfg(0x402A)
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
cfg = tb.serdes_sinks[port].get_an_cfg()
|
||||
if tb.serdes_sinks[port].get_an_ack_match():
|
||||
if lp_cfg | 0x4000 == cfg:
|
||||
break
|
||||
|
||||
tb.log.info("COMPLETE_ACKNOWLEDGE")
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
|
||||
assert lp_cfg & 0xbfff == int(tb.dut.an_adv_ability[port].value) & 0xbfff
|
||||
assert int(tb.dut.an_lp_adv_ability[port].value) & 0xbfff == 0x002A
|
||||
|
||||
tb.log.info("IDLE_DETECT")
|
||||
tb.serdes_sources[port].set_an_cfg(None)
|
||||
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
if tb.serdes_sinks[port].get_an_idle_match():
|
||||
break
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.tx_clk[port])
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10
|
||||
|
||||
@@ -811,6 +891,11 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("ifg", [12])
|
||||
factory.generate_tests()
|
||||
|
||||
if cocotb.top.AN_EN.value:
|
||||
for test in [run_test_an]:
|
||||
factory = TestFactory(test)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ module test_taxi_eth_mac_1g_basex_us #
|
||||
parameter logic [CNT-1:0] GT_RX_LPM_EN = '0,
|
||||
parameter logic [CNT-1:0] GT_RX_POLARITY = '0,
|
||||
parameter logic COMBINED_MAC_PCS = 1'b1,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -111,6 +112,14 @@ taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(TX_USER_W), .ID_EN(1), .ID_
|
||||
taxi_axis_if #(.DATA_W(PTP_TS_W), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) m_axis_tx_cpl[CNT]();
|
||||
taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(RX_USER_W)) m_axis_rx[CNT]();
|
||||
|
||||
logic an_en[CNT];
|
||||
logic an_restart[CNT];
|
||||
logic an_speedup[CNT];
|
||||
logic an_intr[CNT];
|
||||
logic an_complete[CNT];
|
||||
logic [15:0] an_adv_ability[CNT];
|
||||
logic [15:0] an_lp_adv_ability[CNT];
|
||||
|
||||
logic ptp_clk;
|
||||
logic ptp_rst;
|
||||
logic ptp_sample_clk;
|
||||
@@ -263,6 +272,7 @@ taxi_eth_mac_1g_basex_us #(
|
||||
.GT_RX_LPM_EN(GT_RX_LPM_EN),
|
||||
.GT_RX_POLARITY(GT_RX_POLARITY),
|
||||
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TD_EN),
|
||||
@@ -340,6 +350,17 @@ uut (
|
||||
*/
|
||||
.m_axis_rx(m_axis_rx),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en),
|
||||
.an_restart(an_restart),
|
||||
.an_speedup(an_speedup),
|
||||
.an_intr(an_intr),
|
||||
.an_complete(an_complete),
|
||||
.an_adv_ability(an_adv_ability),
|
||||
.an_lp_adv_ability(an_lp_adv_ability),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
||||
export PARAM_DATA_W := 16
|
||||
export PARAM_TX_GBX_IF_EN := 1
|
||||
export PARAM_RX_GBX_IF_EN := $(PARAM_TX_GBX_IF_EN)
|
||||
export PARAM_AN_EN := 1
|
||||
export PARAM_DIC_EN := 1
|
||||
export PARAM_PTP_TS_EN := 1
|
||||
export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN)
|
||||
|
||||
@@ -105,6 +105,11 @@ class TB:
|
||||
period_ns=self.ptp_clk_period
|
||||
)
|
||||
|
||||
dut.an_en.setimmediatevalue(0)
|
||||
dut.an_restart.setimmediatevalue(0)
|
||||
dut.an_speedup.setimmediatevalue(1)
|
||||
dut.an_adv_ability.setimmediatevalue(0x0020)
|
||||
|
||||
dut.stat_rx_fifo_drop.setimmediatevalue(0)
|
||||
|
||||
dut.cfg_tx_pad_en.setimmediatevalue(0)
|
||||
@@ -703,6 +708,73 @@ async def run_test_pfc(dut, gbx_cfg=None, ifg=12):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
|
||||
async def run_test_an(dut, gbx_cfg=None):
|
||||
|
||||
tb = TB(dut, gbx_cfg)
|
||||
|
||||
tb.dut.an_en.value = 1
|
||||
tb.dut.an_restart.value = 0
|
||||
tb.dut.an_speedup.value = 1
|
||||
tb.dut.an_adv_ability.value = 0x0020
|
||||
|
||||
await tb.reset()
|
||||
|
||||
for k in range(100):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
tb.log.info("AN_RESTART")
|
||||
tb.serdes_source.set_an_cfg(0x0000)
|
||||
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
tb.log.info("ABILITY_DETECT")
|
||||
tb.serdes_source.set_an_cfg(0x002A)
|
||||
|
||||
lp_cfg = None
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
lp_cfg = tb.serdes_sink.get_an_cfg()
|
||||
if tb.serdes_sink.get_an_ability_match() and lp_cfg is not None and lp_cfg != 0:
|
||||
break
|
||||
|
||||
assert lp_cfg & 0xbfff == int(tb.dut.an_adv_ability.value) & 0xbfff
|
||||
|
||||
tb.log.info("ACKNOWLEDGE_DETECT")
|
||||
tb.serdes_source.set_an_cfg(0x402A)
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
cfg = tb.serdes_sink.get_an_cfg()
|
||||
if tb.serdes_sink.get_an_ack_match():
|
||||
if lp_cfg | 0x4000 == cfg:
|
||||
break
|
||||
|
||||
tb.log.info("COMPLETE_ACKNOWLEDGE")
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
assert lp_cfg & 0xbfff == int(tb.dut.an_adv_ability.value) & 0xbfff
|
||||
assert int(tb.dut.an_lp_adv_ability.value) & 0xbfff == 0x002A
|
||||
|
||||
tb.log.info("IDLE_DETECT")
|
||||
tb.serdes_source.set_an_cfg(None)
|
||||
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
if tb.serdes_sink.get_an_idle_match():
|
||||
break
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10
|
||||
|
||||
@@ -745,6 +817,12 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("gbx_cfg", gbx_cfgs)
|
||||
factory.generate_tests()
|
||||
|
||||
if cocotb.top.AN_EN.value:
|
||||
for test in [run_test_an]:
|
||||
factory = TestFactory(test)
|
||||
factory.add_option("gbx_cfg", gbx_cfgs)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
@@ -788,6 +866,7 @@ def test_taxi_eth_mac_phy_1g_basex(request, data_w, ptp_td_en, gbx_en, dic_en, p
|
||||
parameters['DATA_W'] = data_w
|
||||
parameters['TX_GBX_IF_EN'] = gbx_en
|
||||
parameters['RX_GBX_IF_EN'] = parameters['TX_GBX_IF_EN']
|
||||
parameters['AN_EN'] = 1
|
||||
parameters['DIC_EN'] = dic_en
|
||||
parameters['PTP_TS_EN'] = 1
|
||||
parameters['PTP_TD_EN'] = ptp_td_en
|
||||
|
||||
@@ -22,6 +22,7 @@ module test_taxi_eth_mac_phy_1g_basex #
|
||||
parameter CTRL_W = DATA_W/8,
|
||||
parameter logic TX_GBX_IF_EN = 1'b0,
|
||||
parameter logic RX_GBX_IF_EN = TX_GBX_IF_EN,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -73,6 +74,14 @@ logic [CTRL_W-1:0] serdes_rx_data_k;
|
||||
logic serdes_rx_data_valid;
|
||||
logic serdes_rx_reset_req;
|
||||
|
||||
logic an_en;
|
||||
logic an_restart;
|
||||
logic an_speedup;
|
||||
logic an_intr;
|
||||
logic an_complete;
|
||||
logic [15:0] an_adv_ability;
|
||||
logic [15:0] an_lp_adv_ability;
|
||||
|
||||
logic ptp_clk;
|
||||
logic ptp_rst;
|
||||
logic ptp_sample_clk;
|
||||
@@ -205,6 +214,7 @@ taxi_eth_mac_phy_1g_basex #(
|
||||
.CTRL_W(CTRL_W),
|
||||
.TX_GBX_IF_EN(TX_GBX_IF_EN),
|
||||
.RX_GBX_IF_EN(RX_GBX_IF_EN),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TD_EN),
|
||||
@@ -260,6 +270,17 @@ uut (
|
||||
.serdes_rx_data_valid(serdes_rx_data_valid),
|
||||
.serdes_rx_reset_req(serdes_rx_reset_req),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en),
|
||||
.an_restart(an_restart),
|
||||
.an_speedup(an_speedup),
|
||||
.an_intr(an_intr),
|
||||
.an_complete(an_complete),
|
||||
.an_adv_ability(an_adv_ability),
|
||||
.an_lp_adv_ability(an_lp_adv_ability),
|
||||
|
||||
/*
|
||||
* PTP
|
||||
*/
|
||||
|
||||
@@ -36,6 +36,7 @@ export PARAM_DATA_W := 16
|
||||
export PARAM_TX_GBX_IF_EN := 1
|
||||
export PARAM_RX_GBX_IF_EN := $(PARAM_TX_GBX_IF_EN)
|
||||
export PARAM_AXIS_DATA_W := $(PARAM_DATA_W)
|
||||
export PARAM_AN_EN := 1
|
||||
export PARAM_DIC_EN := 1
|
||||
export PARAM_PTP_TS_EN := 1
|
||||
export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN)
|
||||
|
||||
@@ -103,6 +103,11 @@ class TB:
|
||||
period_ns=self.ptp_clk_period
|
||||
)
|
||||
|
||||
dut.an_en.setimmediatevalue(0)
|
||||
dut.an_restart.setimmediatevalue(0)
|
||||
dut.an_speedup.setimmediatevalue(1)
|
||||
dut.an_adv_ability.setimmediatevalue(0x0020)
|
||||
|
||||
dut.cfg_tx_pad_en.setimmediatevalue(0)
|
||||
dut.cfg_tx_min_pkt_len.setimmediatevalue(0)
|
||||
dut.cfg_tx_max_pkt_len.setimmediatevalue(0)
|
||||
@@ -262,6 +267,73 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
|
||||
await RisingEdge(dut.logic_clk)
|
||||
|
||||
|
||||
async def run_test_an(dut, gbx_cfg=None):
|
||||
|
||||
tb = TB(dut, gbx_cfg)
|
||||
|
||||
tb.dut.an_en.value = 1
|
||||
tb.dut.an_restart.value = 0
|
||||
tb.dut.an_speedup.value = 1
|
||||
tb.dut.an_adv_ability.value = 0x0020
|
||||
|
||||
await tb.reset()
|
||||
|
||||
for k in range(100):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
tb.log.info("AN_RESTART")
|
||||
tb.serdes_source.set_an_cfg(0x0000)
|
||||
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
tb.log.info("ABILITY_DETECT")
|
||||
tb.serdes_source.set_an_cfg(0x002A)
|
||||
|
||||
lp_cfg = None
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
lp_cfg = tb.serdes_sink.get_an_cfg()
|
||||
if tb.serdes_sink.get_an_ability_match() and lp_cfg is not None and lp_cfg != 0:
|
||||
break
|
||||
|
||||
assert lp_cfg & 0xbfff == int(tb.dut.an_adv_ability.value) & 0xbfff
|
||||
|
||||
tb.log.info("ACKNOWLEDGE_DETECT")
|
||||
tb.serdes_source.set_an_cfg(0x402A)
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
cfg = tb.serdes_sink.get_an_cfg()
|
||||
if tb.serdes_sink.get_an_ack_match():
|
||||
if lp_cfg | 0x4000 == cfg:
|
||||
break
|
||||
|
||||
tb.log.info("COMPLETE_ACKNOWLEDGE")
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
assert lp_cfg & 0xbfff == int(tb.dut.an_adv_ability.value) & 0xbfff
|
||||
assert int(tb.dut.an_lp_adv_ability.value) & 0xbfff == 0x002A
|
||||
|
||||
tb.log.info("IDLE_DETECT")
|
||||
tb.serdes_source.set_an_cfg(None)
|
||||
|
||||
# link timer
|
||||
for k in range(1250):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
if tb.serdes_sink.get_an_idle_match():
|
||||
break
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10
|
||||
|
||||
@@ -290,6 +362,12 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("gbx_cfg", gbx_cfgs)
|
||||
factory.generate_tests()
|
||||
|
||||
if cocotb.top.AN_EN.value:
|
||||
for test in [run_test_an]:
|
||||
factory = TestFactory(test)
|
||||
factory.add_option("gbx_cfg", gbx_cfgs)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
@@ -333,6 +411,7 @@ def test_taxi_eth_mac_phy_1g_basex_fifo(request, data_w, gbx_en, dic_en):
|
||||
parameters['TX_GBX_IF_EN'] = gbx_en
|
||||
parameters['RX_GBX_IF_EN'] = parameters['TX_GBX_IF_EN']
|
||||
parameters['AXIS_DATA_W'] = parameters['DATA_W']
|
||||
parameters['AN_EN'] = 1
|
||||
parameters['DIC_EN'] = dic_en
|
||||
parameters['PTP_TS_EN'] = 1
|
||||
parameters['PTP_TD_EN'] = parameters['PTP_TS_EN']
|
||||
|
||||
@@ -23,6 +23,7 @@ module test_taxi_eth_mac_phy_1g_basex_fifo #
|
||||
parameter logic TX_GBX_IF_EN = 1'b0,
|
||||
parameter logic RX_GBX_IF_EN = TX_GBX_IF_EN,
|
||||
parameter AXIS_DATA_W = 8,
|
||||
parameter logic AN_EN = 1'b1,
|
||||
parameter logic DIC_EN = 1'b1,
|
||||
parameter logic PTP_TS_EN = 1'b0,
|
||||
parameter logic PTP_TD_EN = PTP_TS_EN,
|
||||
@@ -87,6 +88,14 @@ logic [CTRL_W-1:0] serdes_rx_data_k;
|
||||
logic serdes_rx_data_valid;
|
||||
logic serdes_rx_reset_req;
|
||||
|
||||
logic an_en;
|
||||
logic an_restart;
|
||||
logic an_speedup;
|
||||
logic an_intr;
|
||||
logic an_complete;
|
||||
logic [15:0] an_adv_ability;
|
||||
logic [15:0] an_lp_adv_ability;
|
||||
|
||||
logic ptp_clk;
|
||||
logic ptp_rst;
|
||||
logic ptp_sample_clk;
|
||||
@@ -134,6 +143,7 @@ taxi_eth_mac_phy_1g_basex_fifo #(
|
||||
.CTRL_W(CTRL_W),
|
||||
.TX_GBX_IF_EN(TX_GBX_IF_EN),
|
||||
.RX_GBX_IF_EN(RX_GBX_IF_EN),
|
||||
.AN_EN(AN_EN),
|
||||
.DIC_EN(DIC_EN),
|
||||
.PTP_TS_EN(PTP_TS_EN),
|
||||
.PTP_TD_EN(PTP_TD_EN),
|
||||
@@ -202,6 +212,17 @@ uut (
|
||||
.serdes_rx_data_valid(serdes_rx_data_valid),
|
||||
.serdes_rx_reset_req(serdes_rx_reset_req),
|
||||
|
||||
/*
|
||||
* Autonegotiation
|
||||
*/
|
||||
.an_en(an_en),
|
||||
.an_restart(an_restart),
|
||||
.an_speedup(an_speedup),
|
||||
.an_intr(an_intr),
|
||||
.an_complete(an_complete),
|
||||
.an_adv_ability(an_adv_ability),
|
||||
.an_lp_adv_ability(an_lp_adv_ability),
|
||||
|
||||
/*
|
||||
* PTP clock
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user