mirror of
https://github.com/fpganinja/taxi.git
synced 2026-08-20 20:00:16 -07:00
eth: Suport AN config reg exchange in GMII-BASE-X encode/decode logic
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -114,7 +114,8 @@ rx_if_inst (
|
||||
taxi_gmii_basex_dec #(
|
||||
.DATA_W(DATA_W),
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(GBX_IF_EN)
|
||||
.GBX_IF_EN(GBX_IF_EN),
|
||||
.AN_EN(1'b0)
|
||||
)
|
||||
dec_inst (
|
||||
.clk(clk),
|
||||
@@ -135,6 +136,15 @@ dec_inst (
|
||||
.gmii_rx_er(gmii_rx_er),
|
||||
.gmii_rx_valid(gmii_rx_valid),
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.rx_an_cfg(),
|
||||
.rx_an_cfg_valid(),
|
||||
.rx_an_ability_match(),
|
||||
.rx_an_ack_match(),
|
||||
.rx_an_idle_match(),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
|
||||
@@ -70,7 +70,8 @@ taxi_gmii_basex_enc #(
|
||||
.DATA_W(DATA_W),
|
||||
.CTRL_W(CTRL_W),
|
||||
.GBX_IF_EN(GBX_IF_EN),
|
||||
.GBX_CNT(1)
|
||||
.GBX_CNT(1),
|
||||
.AN_EN(1'b0)
|
||||
)
|
||||
enc_inst (
|
||||
.clk(clk),
|
||||
@@ -93,7 +94,14 @@ enc_inst (
|
||||
.encoded_tx_data_dm(encoded_tx_data_dm),
|
||||
.encoded_tx_data_dv(encoded_tx_data_dv),
|
||||
.encoded_tx_data_valid(encoded_tx_data_valid),
|
||||
.tx_gbx_sync_out(tx_gbx_sync_int)
|
||||
.tx_gbx_sync_out(tx_gbx_sync_int),
|
||||
|
||||
/*
|
||||
* AN config register
|
||||
*/
|
||||
.tx_an_cfg('0),
|
||||
.tx_an_cfg_valid(1'b0),
|
||||
.tx_an_cfg_ready()
|
||||
);
|
||||
|
||||
taxi_eth_phy_1g_basex_tx_if #(
|
||||
|
||||
@@ -19,7 +19,8 @@ module taxi_gmii_basex_dec #
|
||||
(
|
||||
parameter DATA_W = 16,
|
||||
parameter CTRL_W = (DATA_W/8),
|
||||
parameter logic GBX_IF_EN = 1'b0
|
||||
parameter logic GBX_IF_EN = 1'b0,
|
||||
parameter logic AN_EN = 1'b1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
@@ -40,6 +41,15 @@ module taxi_gmii_basex_dec #
|
||||
output wire logic [CTRL_W-1:0] gmii_rx_er,
|
||||
output wire logic gmii_rx_valid,
|
||||
|
||||
/*
|
||||
* 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,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
@@ -82,12 +92,23 @@ logic frame_reg = 1'b0, frame_next;
|
||||
logic frame_cyc;
|
||||
logic odd_reg = 1'b0, odd_next;
|
||||
logic odd_cyc;
|
||||
logic k28p5_reg = 1'b0, k28p5_next;
|
||||
logic k28p5_cyc;
|
||||
logic c_reg = 1'b0, c_next;
|
||||
logic c_cyc;
|
||||
|
||||
logic [DATA_W-1:0] gmii_rxd_reg = '0, gmii_rxd_next;
|
||||
logic [CTRL_W-1:0] gmii_rx_dv_reg = '0, gmii_rx_dv_next;
|
||||
logic [CTRL_W-1:0] gmii_rx_er_reg = '0, gmii_rx_er_next;
|
||||
logic gmii_rx_valid_reg = '0, gmii_rx_valid_next;
|
||||
|
||||
logic [15:0] rx_an_cfg_reg = '0, rx_an_cfg_next;
|
||||
logic rx_an_cfg_valid_reg = 1'b0, rx_an_cfg_valid_next;
|
||||
logic an_cfg_match_reg = 1'b0, an_cfg_match_next;
|
||||
logic [1:0] an_ability_match_cnt_reg = '0, an_ability_match_cnt_next;
|
||||
logic [1:0] an_ack_match_cnt_reg = '0, an_ack_match_cnt_next;
|
||||
logic [1:0] an_idle_match_cnt_reg = '0, an_idle_match_cnt_next;
|
||||
|
||||
logic stat_rx_err_bad_block_reg = '0, stat_rx_err_bad_block_next;
|
||||
logic stat_rx_err_framing_reg = '0, stat_rx_err_framing_next;
|
||||
|
||||
@@ -96,23 +117,40 @@ assign gmii_rx_dv = gmii_rx_dv_reg;
|
||||
assign gmii_rx_er = gmii_rx_er_reg;
|
||||
assign gmii_rx_valid = gmii_rx_valid_reg;
|
||||
|
||||
assign rx_an_cfg = AN_EN ? rx_an_cfg_reg : '0;
|
||||
assign rx_an_cfg_valid = AN_EN ? rx_an_cfg_valid_reg : 1'b0;
|
||||
assign rx_an_ability_match = AN_EN ? &an_ability_match_cnt_reg : 1'b0;
|
||||
assign rx_an_ack_match = AN_EN ? &an_ack_match_cnt_reg : 1'b0;
|
||||
assign rx_an_idle_match = AN_EN ? &an_idle_match_cnt_reg : 1'b0;
|
||||
|
||||
assign stat_rx_err_bad_block = stat_rx_err_bad_block_reg;
|
||||
assign stat_rx_err_framing = stat_rx_err_framing_reg;
|
||||
|
||||
always_comb begin
|
||||
frame_next = frame_reg;
|
||||
odd_next = odd_reg;
|
||||
k28p5_next = k28p5_reg;
|
||||
c_next = c_reg;
|
||||
|
||||
gmii_rxd_next = '0;
|
||||
gmii_rx_dv_next = '0;
|
||||
gmii_rx_er_next = '0;
|
||||
gmii_rx_valid_next = 1'b0;
|
||||
|
||||
rx_an_cfg_next = rx_an_cfg_reg;
|
||||
rx_an_cfg_valid_next = 1'b0;
|
||||
an_cfg_match_next = an_cfg_match_reg;
|
||||
an_ability_match_cnt_next = an_ability_match_cnt_reg;
|
||||
an_ack_match_cnt_next = an_ack_match_cnt_reg;
|
||||
an_idle_match_cnt_next = an_idle_match_cnt_reg;
|
||||
|
||||
stat_rx_err_bad_block_next = 1'b0;
|
||||
stat_rx_err_framing_next = 1'b0;
|
||||
|
||||
frame_cyc = frame_reg;
|
||||
odd_cyc = odd_reg;
|
||||
k28p5_cyc = CTRL_W == 0 ? 1'b0 : k28p5_reg;
|
||||
c_cyc = c_reg;
|
||||
|
||||
if (encoded_rx_data_valid) begin
|
||||
// loop over bytes
|
||||
@@ -123,6 +161,7 @@ always_comb begin
|
||||
|
||||
if (encoded_rx_data_k[seg]) begin
|
||||
// Kx.y
|
||||
c_cyc = 1'b0;
|
||||
if (encoded_rx_data[seg*8 +: 8] == K(28,5)) begin
|
||||
// K28.5
|
||||
odd_cyc = 1'b0; // sync
|
||||
@@ -161,14 +200,58 @@ always_comb begin
|
||||
gmii_rxd_next[seg*8 +: 8] = encoded_rx_data[seg*8 +: 8];
|
||||
gmii_rx_dv_next[seg] = 1'b1;
|
||||
gmii_rx_er_next[seg] = 1'b0;
|
||||
end else if (AN_EN && k28p5_cyc && (encoded_rx_data[seg*8 +: 8] == D(5,6) || encoded_rx_data[seg*8 +: 8] == D(16,2))) begin
|
||||
// I1/I2
|
||||
an_ability_match_cnt_next = '0;
|
||||
an_ack_match_cnt_next = '0;
|
||||
if (!(&an_idle_match_cnt_next)) begin
|
||||
an_idle_match_cnt_next = an_idle_match_cnt_next + 1;
|
||||
end
|
||||
end else if (AN_EN && k28p5_cyc && (encoded_rx_data[seg*8 +: 8] == D(21,5) || encoded_rx_data[seg*8 +: 8] == D(2,2))) begin
|
||||
// C1/C2
|
||||
c_cyc = 1'b1;
|
||||
end else if (AN_EN && c_cyc) begin
|
||||
if (!odd_cyc) begin
|
||||
rx_an_cfg_next[7:0] = encoded_rx_data[seg*8 +: 8];
|
||||
an_cfg_match_next = rx_an_cfg_next[7:0] == encoded_rx_data[seg*8 +: 8];
|
||||
an_idle_match_cnt_next = '0;
|
||||
end else begin
|
||||
rx_an_cfg_next[15:8] = encoded_rx_data[seg*8 +: 8];
|
||||
rx_an_cfg_valid_next = 1'b1;
|
||||
if (an_cfg_match_next && ((rx_an_cfg_next[15:8] ^ encoded_rx_data[seg*8 +: 8]) & 8'h40) == 0) begin
|
||||
if (!(&an_ability_match_cnt_next)) begin
|
||||
an_ability_match_cnt_next = an_ability_match_cnt_next + 1;
|
||||
end
|
||||
end else begin
|
||||
an_ability_match_cnt_next = '0;
|
||||
end
|
||||
if (an_cfg_match_next && rx_an_cfg_next[14] && rx_an_cfg_next[15:8] == encoded_rx_data[seg*8 +: 8]) begin
|
||||
if (!(&an_ack_match_cnt_next)) begin
|
||||
an_ack_match_cnt_next = an_ack_match_cnt_next + 1;
|
||||
end
|
||||
end else begin
|
||||
an_ack_match_cnt_next = '0;
|
||||
end
|
||||
an_idle_match_cnt_next = '0;
|
||||
c_cyc = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// detect K28.5 symbols
|
||||
if (encoded_rx_data_k[seg] && encoded_rx_data[seg*8 +: 8] == K(28,5)) begin
|
||||
k28p5_cyc = 1'b1;
|
||||
end else begin
|
||||
k28p5_cyc = 1'b0;
|
||||
end
|
||||
|
||||
odd_cyc = !odd_cyc;
|
||||
end
|
||||
|
||||
frame_next = frame_cyc;
|
||||
odd_next = odd_cyc;
|
||||
k28p5_next = k28p5_cyc;
|
||||
c_next = c_cyc;
|
||||
|
||||
gmii_rx_valid_next = 1'b1;
|
||||
end
|
||||
@@ -177,24 +260,40 @@ end
|
||||
always_ff @(posedge clk) begin
|
||||
frame_reg <= frame_next;
|
||||
odd_reg <= odd_next;
|
||||
k28p5_reg <= k28p5_next;
|
||||
c_reg <= c_next;
|
||||
|
||||
gmii_rxd_reg <= gmii_rxd_next;
|
||||
gmii_rx_dv_reg <= gmii_rx_dv_next;
|
||||
gmii_rx_er_reg <= gmii_rx_er_next;
|
||||
gmii_rx_valid_reg <= gmii_rx_valid_next;
|
||||
|
||||
rx_an_cfg_reg <= rx_an_cfg_next;
|
||||
rx_an_cfg_valid_reg <= rx_an_cfg_valid_next;
|
||||
an_cfg_match_reg <= an_cfg_match_next;
|
||||
an_ability_match_cnt_reg <= an_ability_match_cnt_next;
|
||||
an_ack_match_cnt_reg <= an_ack_match_cnt_next;
|
||||
an_idle_match_cnt_reg <= an_idle_match_cnt_next;
|
||||
|
||||
stat_rx_err_bad_block_reg <= stat_rx_err_bad_block_next;
|
||||
stat_rx_err_framing_reg <= stat_rx_err_framing_next;
|
||||
|
||||
if (rst) begin
|
||||
frame_reg <= 1'b0;
|
||||
odd_reg <= 1'b0;
|
||||
k28p5_reg <= 1'b0;
|
||||
c_reg <= 1'b0;
|
||||
|
||||
gmii_rxd_reg <= '0;
|
||||
gmii_rx_dv_reg <= '0;
|
||||
gmii_rx_er_reg <= '0;
|
||||
gmii_rx_valid_reg <= 1'b0;
|
||||
|
||||
rx_an_cfg_valid_reg <= 1'b0;
|
||||
an_ability_match_cnt_reg <= '0;
|
||||
an_ack_match_cnt_reg <= '0;
|
||||
an_idle_match_cnt_reg <= '0;
|
||||
|
||||
stat_rx_err_bad_block_reg <= 1'b0;
|
||||
stat_rx_err_framing_reg <= 1'b0;
|
||||
end
|
||||
|
||||
@@ -20,7 +20,8 @@ module taxi_gmii_basex_enc #
|
||||
parameter DATA_W = 16,
|
||||
parameter CTRL_W = (DATA_W/8),
|
||||
parameter logic GBX_IF_EN = 1'b0,
|
||||
parameter GBX_CNT = 1
|
||||
parameter GBX_CNT = 1,
|
||||
parameter logic AN_EN = 1'b1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
@@ -43,7 +44,14 @@ module taxi_gmii_basex_enc #
|
||||
output wire logic [CTRL_W-1:0] encoded_tx_data_dm,
|
||||
output wire logic [CTRL_W-1:0] encoded_tx_data_dv,
|
||||
output wire logic encoded_tx_data_valid,
|
||||
output wire logic [GBX_CNT-1:0] tx_gbx_sync_out
|
||||
output wire logic [GBX_CNT-1:0] tx_gbx_sync_out,
|
||||
|
||||
/*
|
||||
* 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
|
||||
);
|
||||
|
||||
// check configuration
|
||||
@@ -137,6 +145,10 @@ logic odd_reg = 1'b0, odd_next;
|
||||
logic odd_cyc;
|
||||
logic cext_reg = 1'b0, cext_next;
|
||||
logic cext_cyc;
|
||||
logic an_cfg_reg = 1'b0, an_cfg_next;
|
||||
logic an_cfg_cyc;
|
||||
logic an_phase_reg = 1'b0, an_phase_next;
|
||||
logic an_phase_cyc;
|
||||
logic rd_reg = 1'b0, rd_next;
|
||||
logic rd_cyc;
|
||||
|
||||
@@ -147,6 +159,8 @@ logic [CTRL_W-1:0] encoded_tx_data_dv_reg = '0, encoded_tx_data_dv_next;
|
||||
logic encoded_tx_data_valid_reg = '0, encoded_tx_data_valid_next;
|
||||
logic [GBX_CNT-1:0] tx_gbx_sync_reg = '0, tx_gbx_sync_next;
|
||||
|
||||
logic tx_an_cfg_ready_reg = 1'b0, tx_an_cfg_ready_next;
|
||||
|
||||
assign encoded_tx_data = encoded_tx_data_reg;
|
||||
assign encoded_tx_data_k = encoded_tx_data_k_reg;
|
||||
assign encoded_tx_data_dm = encoded_tx_data_dm_reg;
|
||||
@@ -154,10 +168,14 @@ assign encoded_tx_data_dv = encoded_tx_data_dv_reg;
|
||||
assign encoded_tx_data_valid = encoded_tx_data_valid_reg;
|
||||
assign tx_gbx_sync_out = tx_gbx_sync_reg;
|
||||
|
||||
assign tx_an_cfg_ready = AN_EN ? tx_an_cfg_ready_reg : 1'b0;
|
||||
|
||||
always_comb begin
|
||||
frame_next = frame_reg;
|
||||
odd_next = odd_reg;
|
||||
cext_next = cext_reg;
|
||||
an_cfg_next = an_cfg_reg;
|
||||
an_phase_next = an_phase_reg;
|
||||
rd_next = rd_reg;
|
||||
|
||||
encoded_tx_data_next = '0;
|
||||
@@ -166,13 +184,17 @@ always_comb begin
|
||||
encoded_tx_data_dv_next = '0;
|
||||
encoded_tx_data_valid_next = '0;
|
||||
|
||||
tx_gbx_sync_next = tx_gbx_sync_in;
|
||||
|
||||
tx_an_cfg_ready_next = 1'b0;
|
||||
|
||||
frame_cyc = frame_reg;
|
||||
odd_cyc = odd_reg;
|
||||
cext_cyc = cext_reg;
|
||||
an_cfg_cyc = an_cfg_reg;
|
||||
an_phase_cyc = an_phase_reg;
|
||||
rd_cyc = rd_reg;
|
||||
|
||||
tx_gbx_sync_next = tx_gbx_sync_in;
|
||||
|
||||
if (gmii_tx_valid) begin
|
||||
// loop over bytes
|
||||
for (integer seg = 0; seg < CTRL_W; seg = seg + 1) begin
|
||||
@@ -198,12 +220,29 @@ always_comb begin
|
||||
encoded_tx_data_k_next[seg] = 1'b1;
|
||||
cext_cyc = 1'b1;
|
||||
end
|
||||
end else if (AN_EN && an_cfg_cyc) begin
|
||||
// config reg
|
||||
if (!odd_cyc) begin
|
||||
encoded_tx_data_next[seg*8 +: 8] = tx_an_cfg[7:0];
|
||||
encoded_tx_data_k_next[seg] = 1'b0;
|
||||
end else begin
|
||||
encoded_tx_data_next[seg*8 +: 8] = tx_an_cfg[15:8];
|
||||
encoded_tx_data_k_next[seg] = 1'b0;
|
||||
tx_an_cfg_ready_next = 1'b1;
|
||||
an_phase_cyc = !an_phase_cyc;
|
||||
an_cfg_cyc = 1'b0;
|
||||
end
|
||||
end else begin
|
||||
if (gmii_tx_en[seg] && odd_cyc == 0) begin
|
||||
// start of frame
|
||||
frame_cyc = 1'b1;
|
||||
encoded_tx_data_next[seg*8 +: 8] = CTRL_S;
|
||||
encoded_tx_data_k_next[seg] = 1'b1;
|
||||
end else if (AN_EN && tx_an_cfg_valid && odd_cyc == 1) begin
|
||||
// config reg
|
||||
an_cfg_cyc = 1'b1;
|
||||
encoded_tx_data_next[seg*8 +: 8] = an_phase_reg ? D(2,2) : D(21,5);
|
||||
encoded_tx_data_k_next[seg] = 1'b0;
|
||||
end else begin
|
||||
if (cext_cyc) begin
|
||||
// carrier extend
|
||||
@@ -235,6 +274,8 @@ always_comb begin
|
||||
frame_next = frame_cyc;
|
||||
odd_next = odd_cyc;
|
||||
cext_next = cext_cyc;
|
||||
an_cfg_next = an_cfg_cyc;
|
||||
an_phase_next = an_phase_cyc;
|
||||
rd_next = rd_cyc;
|
||||
|
||||
encoded_tx_data_valid_next = 1'b1;
|
||||
@@ -245,6 +286,8 @@ always_ff @(posedge clk) begin
|
||||
frame_reg <= frame_next;
|
||||
odd_reg <= odd_next;
|
||||
cext_reg <= cext_next;
|
||||
an_cfg_reg <= an_cfg_next;
|
||||
an_phase_reg <= an_phase_next;
|
||||
rd_reg <= rd_next;
|
||||
|
||||
encoded_tx_data_reg <= encoded_tx_data_next;
|
||||
@@ -254,10 +297,14 @@ always_ff @(posedge clk) begin
|
||||
encoded_tx_data_valid_reg <= encoded_tx_data_valid_next;
|
||||
tx_gbx_sync_reg <= tx_gbx_sync_next;
|
||||
|
||||
tx_an_cfg_ready_reg <= tx_an_cfg_ready_next;
|
||||
|
||||
if (rst) begin
|
||||
frame_reg <= 1'b0;
|
||||
odd_reg <= 1'b0;
|
||||
cext_reg <= 1'b0;
|
||||
an_cfg_reg <= 1'b0;
|
||||
an_phase_reg <= 1'b0;
|
||||
rd_reg <= 1'b0;
|
||||
|
||||
encoded_tx_data_reg <= '0;
|
||||
@@ -266,6 +313,8 @@ always_ff @(posedge clk) begin
|
||||
encoded_tx_data_dv_reg <= '0;
|
||||
encoded_tx_data_valid_reg <= 1'b0;
|
||||
tx_gbx_sync_reg <= '0;
|
||||
|
||||
tx_an_cfg_ready_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
||||
# module parameters
|
||||
export PARAM_DATA_W := 16
|
||||
export PARAM_GBX_IF_EN := 0
|
||||
export PARAM_AN_EN := "1'b1"
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
@@ -101,6 +101,38 @@ async def run_test(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, i
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
async def run_test_an(dut, gbx_cfg=None):
|
||||
|
||||
tb = TB(dut, gbx_cfg)
|
||||
|
||||
await tb.reset()
|
||||
|
||||
for k in range(16):
|
||||
an_cfg = 1 << k
|
||||
|
||||
tb.source.set_an_cfg(an_cfg)
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
assert int(dut.rx_an_cfg.value) == an_cfg
|
||||
assert int(dut.rx_an_ability_match.value)
|
||||
assert int(dut.rx_an_ack_match.value) == bool(an_cfg & 0x4000)
|
||||
assert not int(dut.rx_an_idle_match.value)
|
||||
|
||||
tb.source.set_an_cfg(None)
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
assert not int(dut.rx_an_ability_match.value)
|
||||
assert not int(dut.rx_an_ack_match.value)
|
||||
assert int(dut.rx_an_idle_match.value)
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)]
|
||||
|
||||
@@ -118,6 +150,9 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("pre_len", [8, 7])
|
||||
factory.generate_tests()
|
||||
|
||||
factory = TestFactory(run_test_an)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
@@ -156,6 +191,7 @@ def test_taxi_gmii_basex_dec(request, data_w):
|
||||
|
||||
parameters['DATA_W'] = data_w
|
||||
parameters['GBX_IF_EN'] = 0
|
||||
parameters['AN_EN'] = "1'b1"
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
||||
# module parameters
|
||||
export PARAM_DATA_W := 16
|
||||
export PARAM_GBX_IF_EN := 0
|
||||
export PARAM_AN_EN := "1'b1"
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
@@ -63,6 +63,9 @@ class TB:
|
||||
gbx_cfg=gbx_cfg
|
||||
)
|
||||
|
||||
dut.tx_an_cfg.setimmediatevalue(0)
|
||||
dut.tx_an_cfg_valid.setimmediatevalue(0)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
await RisingEdge(self.dut.clk)
|
||||
@@ -103,6 +106,39 @@ async def run_test(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, i
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
async def run_test_an(dut, gbx_cfg=None):
|
||||
|
||||
tb = TB(dut, gbx_cfg)
|
||||
|
||||
await tb.reset()
|
||||
|
||||
for k in range(16):
|
||||
an_cfg = 1 << k
|
||||
|
||||
dut.tx_an_cfg.value = an_cfg
|
||||
dut.tx_an_cfg_valid.value = 1
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
assert tb.sink.get_an_cfg() == an_cfg
|
||||
assert tb.sink.get_an_ability_match()
|
||||
assert tb.sink.get_an_ack_match() == bool(an_cfg & 0x4000)
|
||||
assert not tb.sink.get_an_idle_match()
|
||||
|
||||
dut.tx_an_cfg_valid.value = 0
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
assert not tb.sink.get_an_ability_match()
|
||||
assert not tb.sink.get_an_ack_match()
|
||||
assert tb.sink.get_an_idle_match()
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)]
|
||||
|
||||
@@ -120,6 +156,9 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("pre_len", [8, 7])
|
||||
factory.generate_tests()
|
||||
|
||||
factory = TestFactory(run_test_an)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
@@ -158,6 +197,7 @@ def test_taxi_gmii_basex_enc(request, data_w):
|
||||
|
||||
parameters['DATA_W'] = data_w
|
||||
parameters['GBX_IF_EN'] = 0
|
||||
parameters['AN_EN'] = "1'b1"
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user