mirror of
https://github.com/fpganinja/taxi.git
synced 2026-08-03 22:11:22 -07:00
eth: Support ordered sets in XGMII-BASE-R encode/decode logic
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -146,6 +146,13 @@ xgmii_baser_dec_inst (
|
||||
.xgmii_rxc(xgmii_rxc),
|
||||
.xgmii_rx_valid(xgmii_rx_valid),
|
||||
|
||||
/*
|
||||
* Ordered sets
|
||||
*/
|
||||
.rx_os(),
|
||||
.rx_os_sig(),
|
||||
.rx_os_valid(),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
|
||||
@@ -97,6 +97,14 @@ xgmii_baser_enc_inst (
|
||||
.encoded_tx_hdr_valid(encoded_tx_hdr_valid),
|
||||
.tx_gbx_sync_out(tx_gbx_sync_int),
|
||||
|
||||
/*
|
||||
* Ordered sets
|
||||
*/
|
||||
.tx_os('0),
|
||||
.tx_os_sig(1'b0),
|
||||
.tx_os_valid(1'b0),
|
||||
.tx_os_ready(),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,13 @@ module taxi_xgmii_baser_dec #
|
||||
output wire logic [CTRL_W-1:0] xgmii_rxc,
|
||||
output wire logic xgmii_rx_valid,
|
||||
|
||||
/*
|
||||
* Ordered sets
|
||||
*/
|
||||
output wire logic [23:0] rx_os = '0,
|
||||
output wire logic rx_os_sig = 1'b0,
|
||||
output wire logic rx_os_valid = 1'b0,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
@@ -130,6 +137,10 @@ logic [DATA_W_INT-1:0] xgmii_rxd_reg = '0, xgmii_rxd_next;
|
||||
logic [CTRL_W_INT-1:0] xgmii_rxc_reg = '0, xgmii_rxc_next;
|
||||
logic [SEG_CNT-1:0] xgmii_rx_valid_reg = '0, xgmii_rx_valid_next;
|
||||
|
||||
logic [23:0] rx_os_reg = '0, rx_os_next;
|
||||
logic rx_os_sig_reg = 1'b0, rx_os_sig_next;
|
||||
logic rx_os_valid_reg = 1'b0, rx_os_valid_next;
|
||||
|
||||
logic rx_bad_block_reg = 1'b0, rx_bad_block_next;
|
||||
logic rx_sequence_error_reg = 1'b0, rx_sequence_error_next;
|
||||
logic frame_reg = 1'b0, frame_next;
|
||||
@@ -138,6 +149,10 @@ assign xgmii_rxd = xgmii_rxd_reg[DATA_W-1:0];
|
||||
assign xgmii_rxc = xgmii_rxc_reg[CTRL_W-1:0];
|
||||
assign xgmii_rx_valid = GBX_IF_EN ? xgmii_rx_valid_reg[0] : 1'b1;
|
||||
|
||||
assign rx_os = rx_os_reg;
|
||||
assign rx_os_sig = rx_os_sig_reg;
|
||||
assign rx_os_valid = rx_os_valid_reg;
|
||||
|
||||
assign rx_bad_block = rx_bad_block_reg;
|
||||
assign rx_sequence_error = rx_sequence_error_reg;
|
||||
|
||||
@@ -177,6 +192,11 @@ always_comb begin
|
||||
xgmii_rxd_next = {CTRL_W_INT{XGMII_ERROR}};
|
||||
xgmii_rxc_next = '1;
|
||||
xgmii_rx_valid_next = '0;
|
||||
|
||||
rx_os_next = '0;
|
||||
rx_os_sig_next = 1'b0;
|
||||
rx_os_valid_next = 1'b0;
|
||||
|
||||
rx_bad_block_next = 1'b0;
|
||||
rx_sequence_error_next = 1'b0;
|
||||
frame_next = frame_reg;
|
||||
@@ -263,9 +283,19 @@ always_comb begin
|
||||
xgmii_rxc_next[3:0] = 4'hf;
|
||||
xgmii_rxd_next[63:40] = encoded_rx_data_int[63:40];
|
||||
xgmii_rxc_next[7:4] = 4'h1;
|
||||
rx_os_next[7:0] = encoded_rx_data_int[63:56];
|
||||
rx_os_next[15:8] = encoded_rx_data_int[55:48];
|
||||
rx_os_next[23:16] = encoded_rx_data_int[47:40];
|
||||
if (encoded_rx_data_int[39:36] == O_SEQ_OS) begin
|
||||
xgmii_rxd_next[39:32] = XGMII_SEQ_OS;
|
||||
rx_bad_block_next = decode_err[3:0] != 0;
|
||||
rx_os_sig_next = 1'b0;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else if (encoded_rx_data_int[39:36] == O_SIG_OS) begin
|
||||
xgmii_rxd_next[39:32] = XGMII_SIG_OS;
|
||||
rx_bad_block_next = decode_err[3:0] != 0;
|
||||
rx_os_sig_next = 1'b1;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else begin
|
||||
xgmii_rxd_next[39:32] = XGMII_ERROR;
|
||||
rx_bad_block_next = 1'b1;
|
||||
@@ -283,9 +313,19 @@ always_comb begin
|
||||
// D7 D6 D5 O0 D3 D2 D1 BT
|
||||
xgmii_rxd_next[31:8] = encoded_rx_data_int[31:8];
|
||||
xgmii_rxc_next[3:0] = 4'h1;
|
||||
rx_os_next[7:0] = encoded_rx_data_int[31:24];
|
||||
rx_os_next[15:8] = encoded_rx_data_int[23:16];
|
||||
rx_os_next[23:16] = encoded_rx_data_int[15:8];
|
||||
if (encoded_rx_data_int[35:32] == O_SEQ_OS) begin
|
||||
xgmii_rxd_next[7:0] = XGMII_SEQ_OS;
|
||||
rx_bad_block_next = 1'b0;
|
||||
rx_os_sig_next = 1'b0;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else if (encoded_rx_data_int[35:32] == O_SIG_OS) begin
|
||||
xgmii_rxd_next[7:0] = XGMII_SIG_OS;
|
||||
rx_bad_block_next = 1'b0;
|
||||
rx_os_sig_next = 1'b1;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else begin
|
||||
xgmii_rxd_next[7:0] = XGMII_ERROR;
|
||||
rx_bad_block_next = 1'b1;
|
||||
@@ -302,14 +342,25 @@ always_comb begin
|
||||
xgmii_rxc_next[3:0] = 4'h1;
|
||||
if (encoded_rx_data_int[35:32] == O_SEQ_OS) begin
|
||||
xgmii_rxd_next[7:0] = XGMII_SEQ_OS;
|
||||
end else if (encoded_rx_data_int[35:32] == O_SIG_OS) begin
|
||||
xgmii_rxd_next[7:0] = XGMII_SIG_OS;
|
||||
end else begin
|
||||
xgmii_rxd_next[7:0] = XGMII_ERROR;
|
||||
rx_bad_block_next = 1'b1;
|
||||
end
|
||||
xgmii_rxd_next[63:40] = encoded_rx_data_int[63:40];
|
||||
xgmii_rxc_next[7:4] = 4'h1;
|
||||
rx_os_next[7:0] = encoded_rx_data_int[63:56];
|
||||
rx_os_next[15:8] = encoded_rx_data_int[55:48];
|
||||
rx_os_next[23:16] = encoded_rx_data_int[47:40];
|
||||
if (encoded_rx_data_int[39:36] == O_SEQ_OS) begin
|
||||
xgmii_rxd_next[39:32] = XGMII_SEQ_OS;
|
||||
rx_os_sig_next = 1'b0;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else if (encoded_rx_data_int[39:36] == O_SIG_OS) begin
|
||||
xgmii_rxd_next[39:32] = XGMII_SIG_OS;
|
||||
rx_os_sig_next = 1'b1;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else begin
|
||||
xgmii_rxd_next[39:32] = XGMII_ERROR;
|
||||
rx_bad_block_next = 1'b1;
|
||||
@@ -327,9 +378,19 @@ always_comb begin
|
||||
// C7 C6 C5 C4 O0 D3 D2 D1 BT
|
||||
xgmii_rxd_next[31:8] = encoded_rx_data_int[31:8];
|
||||
xgmii_rxc_next[3:0] = 4'h1;
|
||||
rx_os_next[7:0] = encoded_rx_data_int[31:24];
|
||||
rx_os_next[15:8] = encoded_rx_data_int[23:16];
|
||||
rx_os_next[23:16] = encoded_rx_data_int[15:8];
|
||||
if (encoded_rx_data_int[35:32] == O_SEQ_OS) begin
|
||||
xgmii_rxd_next[7:0] = XGMII_SEQ_OS;
|
||||
rx_bad_block_next = decode_err[7:4] != 0;
|
||||
rx_os_sig_next = 1'b0;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else if (encoded_rx_data_int[35:32] == O_SIG_OS) begin
|
||||
xgmii_rxd_next[7:0] = XGMII_SIG_OS;
|
||||
rx_bad_block_next = decode_err[7:4] != 0;
|
||||
rx_os_sig_next = 1'b1;
|
||||
rx_os_valid_next = 1'b1;
|
||||
end else begin
|
||||
xgmii_rxd_next[7:0] = XGMII_ERROR;
|
||||
rx_bad_block_next = 1'b1;
|
||||
@@ -453,12 +514,17 @@ always_ff @(posedge clk) begin
|
||||
xgmii_rxc_reg <= xgmii_rxc_next;
|
||||
xgmii_rx_valid_reg <= xgmii_rx_valid_next;
|
||||
|
||||
rx_os_reg <= rx_os_next;
|
||||
rx_os_sig_reg <= rx_os_sig_next;
|
||||
rx_os_valid_reg <= rx_os_valid_next;
|
||||
|
||||
rx_bad_block_reg <= rx_bad_block_next;
|
||||
rx_sequence_error_reg <= rx_sequence_error_next;
|
||||
frame_reg <= frame_next;
|
||||
|
||||
if (rst) begin
|
||||
xgmii_rx_valid_reg <= '0;
|
||||
rx_os_valid_reg <= 1'b0;
|
||||
frame_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,6 +44,14 @@ module taxi_xgmii_baser_enc #
|
||||
output wire logic encoded_tx_hdr_valid,
|
||||
output wire logic [GBX_CNT-1:0] tx_gbx_sync_out,
|
||||
|
||||
/*
|
||||
* Ordered sets
|
||||
*/
|
||||
input wire logic [23:0] tx_os = '0,
|
||||
input wire logic tx_os_sig = 1'b0,
|
||||
input wire logic tx_os_valid = 1'b0,
|
||||
output wire logic tx_os_ready,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
@@ -136,6 +144,8 @@ logic [HDR_W-1:0] encoded_tx_hdr_reg = '0, encoded_tx_hdr_next;
|
||||
logic encoded_tx_hdr_valid_reg = 1'b0, encoded_tx_hdr_valid_next;
|
||||
logic [GBX_CNT-1:0] tx_gbx_sync_reg = '0, tx_gbx_sync_next;
|
||||
|
||||
logic tx_os_ready_reg = 1'b0, tx_os_ready_next;
|
||||
|
||||
logic tx_bad_block_reg = 1'b0, tx_bad_block_next;
|
||||
|
||||
assign encoded_tx_data = encoded_tx_data_reg[DATA_W-1:0];
|
||||
@@ -144,6 +154,8 @@ assign encoded_tx_hdr = encoded_tx_hdr_reg;
|
||||
assign encoded_tx_hdr_valid = USE_HDR_VLD ? encoded_tx_hdr_valid_reg : 1'b1;
|
||||
assign tx_gbx_sync_out = GBX_IF_EN ? tx_gbx_sync_reg : '0;
|
||||
|
||||
assign tx_os_ready = tx_os_ready_reg;
|
||||
|
||||
assign tx_bad_block = tx_bad_block_reg;
|
||||
|
||||
if (DATA_W == 64) begin : repack_in
|
||||
@@ -187,6 +199,8 @@ always_comb begin
|
||||
encoded_tx_hdr_valid_next = '0;
|
||||
tx_gbx_sync_next = '0;
|
||||
|
||||
tx_os_ready_next = 1'b0;
|
||||
|
||||
tx_bad_block_next = 1'b0;
|
||||
|
||||
for (integer i = 0; i < CTRL_W_INT; i = i + 1) begin
|
||||
@@ -321,7 +335,21 @@ always_comb begin
|
||||
tx_bad_block_next = 1'b0;
|
||||
end else if (xgmii_txc_int == 8'hff) begin
|
||||
// all control
|
||||
encoded_tx_data_next = {encoded_ctrl, BLOCK_TYPE_CTRL};
|
||||
if (tx_os_valid && xgmii_txd_int[7:0] == XGMII_IDLE) begin
|
||||
// assume all idles, replace with ordered sets
|
||||
encoded_tx_data_next[7:0] = BLOCK_TYPE_OS_04;
|
||||
encoded_tx_data_next[15:8] = tx_os[23:16];
|
||||
encoded_tx_data_next[23:16] = tx_os[15:8];
|
||||
encoded_tx_data_next[31:24] = tx_os[7:0];
|
||||
encoded_tx_data_next[35:32] = tx_os_sig ? O_SIG_OS : O_SEQ_OS;
|
||||
encoded_tx_data_next[39:36] = tx_os_sig ? O_SIG_OS : O_SEQ_OS;
|
||||
encoded_tx_data_next[47:40] = tx_os[23:16];
|
||||
encoded_tx_data_next[55:48] = tx_os[15:8];
|
||||
encoded_tx_data_next[63:56] = tx_os[7:0];
|
||||
tx_os_ready_next = 1'b1;
|
||||
end else begin
|
||||
encoded_tx_data_next = {encoded_ctrl, BLOCK_TYPE_CTRL};
|
||||
end
|
||||
tx_bad_block_next = encode_err != 0;
|
||||
end else begin
|
||||
// no corresponding block format
|
||||
@@ -347,6 +375,8 @@ always_ff @(posedge clk) begin
|
||||
encoded_tx_hdr_valid_reg <= encoded_tx_hdr_valid_next;
|
||||
tx_gbx_sync_reg <= tx_gbx_sync_next;
|
||||
|
||||
tx_os_ready_reg <= tx_os_ready_next;
|
||||
|
||||
tx_bad_block_reg <= tx_bad_block_next;
|
||||
end
|
||||
|
||||
|
||||
@@ -176,6 +176,33 @@ async def run_test_alignment(dut, payload_data=None, ifg=12, enable_dic=True,
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
async def run_test_os(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.reset()
|
||||
|
||||
for sig in [False, True]:
|
||||
for k in range(24):
|
||||
os = 1 << k
|
||||
|
||||
tb.source.set_os(os, sig)
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
assert int(dut.rx_os.value) == os
|
||||
assert int(dut.rx_os_sig.value) == sig
|
||||
|
||||
tb.source.set_os(None)
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10
|
||||
|
||||
@@ -205,6 +232,9 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("force_offset_start", [False, True])
|
||||
factory.generate_tests()
|
||||
|
||||
factory = TestFactory(run_test_os)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
|
||||
@@ -176,6 +176,34 @@ async def run_test_alignment(dut, payload_data=None, ifg=12, enable_dic=True,
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
async def run_test_os(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.reset()
|
||||
|
||||
for sig in [False, True]:
|
||||
for k in range(24):
|
||||
os = 1 << k
|
||||
|
||||
dut.tx_os.value = os
|
||||
dut.tx_os_sig.value = sig
|
||||
dut.tx_os_valid.value = 1
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
assert tb.sink.get_os() == (os, sig)
|
||||
|
||||
dut.tx_os_valid.value = 0
|
||||
|
||||
for k in range(20):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
def size_list():
|
||||
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10
|
||||
|
||||
@@ -206,6 +234,9 @@ if getattr(cocotb, 'top', None) is not None:
|
||||
factory.add_option("force_offset_start", [False, True])
|
||||
factory.generate_tests()
|
||||
|
||||
factory = TestFactory(run_test_os)
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
|
||||
Reference in New Issue
Block a user