diff --git a/src/eth/rtl/taxi_eth_phy_10g_rx.f b/src/eth/rtl/taxi_eth_phy_10g_rx.f index e097e4a..75ff13b 100644 --- a/src/eth/rtl/taxi_eth_phy_10g_rx.f +++ b/src/eth/rtl/taxi_eth_phy_10g_rx.f @@ -1,3 +1,3 @@ taxi_eth_phy_10g_rx.sv taxi_eth_phy_10g_rx_if.f -taxi_xgmii_baser_dec_64.sv +taxi_xgmii_baser_dec.sv diff --git a/src/eth/rtl/taxi_eth_phy_10g_rx.sv b/src/eth/rtl/taxi_eth_phy_10g_rx.sv index 5146c02..9ea7b02 100644 --- a/src/eth/rtl/taxi_eth_phy_10g_rx.sv +++ b/src/eth/rtl/taxi_eth_phy_10g_rx.sv @@ -66,16 +66,6 @@ module taxi_eth_phy_10g_rx # input wire logic cfg_rx_prbs31_enable ); -// check configuration -if (DATA_W != 64) - $fatal(0, "Error: Interface width must be 64"); - -if (CTRL_W * 8 != DATA_W) - $fatal(0, "Error: Interface requires byte (8-bit) granularity"); - -if (HDR_W != 2) - $fatal(0, "Error: HDR_W must be 2"); - wire [DATA_W-1:0] encoded_rx_data; wire encoded_rx_data_valid; wire [HDR_W-1:0] encoded_rx_hdr; @@ -131,7 +121,7 @@ eth_phy_10g_rx_if_inst ( .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable) ); -taxi_xgmii_baser_dec_64 #( +taxi_xgmii_baser_dec #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), .HDR_W(HDR_W), diff --git a/src/eth/rtl/taxi_eth_phy_10g_tx.f b/src/eth/rtl/taxi_eth_phy_10g_tx.f index 4938f32..32fcbfa 100644 --- a/src/eth/rtl/taxi_eth_phy_10g_tx.f +++ b/src/eth/rtl/taxi_eth_phy_10g_tx.f @@ -1,3 +1,3 @@ taxi_eth_phy_10g_tx.sv taxi_eth_phy_10g_tx_if.f -taxi_xgmii_baser_enc_64.sv +taxi_xgmii_baser_enc.sv diff --git a/src/eth/rtl/taxi_eth_phy_10g_tx.sv b/src/eth/rtl/taxi_eth_phy_10g_tx.sv index 010fa40..4f8c8f5 100644 --- a/src/eth/rtl/taxi_eth_phy_10g_tx.sv +++ b/src/eth/rtl/taxi_eth_phy_10g_tx.sv @@ -62,16 +62,6 @@ module taxi_eth_phy_10g_tx # input wire logic cfg_tx_prbs31_enable ); -// check configuration -if (DATA_W != 64) - $fatal(0, "Error: Interface width must be 64"); - -if (CTRL_W * 8 != DATA_W) - $fatal(0, "Error: Interface requires byte (8-bit) granularity"); - -if (HDR_W != 2) - $fatal(0, "Error: HDR_W must be 2"); - wire [DATA_W-1:0] encoded_tx_data; wire encoded_tx_data_valid; wire [HDR_W-1:0] encoded_tx_hdr; @@ -79,7 +69,7 @@ wire encoded_tx_hdr_valid; wire tx_gbx_sync_int; -taxi_xgmii_baser_enc_64 #( +taxi_xgmii_baser_enc #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), .HDR_W(HDR_W), diff --git a/src/eth/rtl/taxi_xgmii_baser_dec_64.sv b/src/eth/rtl/taxi_xgmii_baser_dec.sv similarity index 72% rename from src/eth/rtl/taxi_xgmii_baser_dec_64.sv rename to src/eth/rtl/taxi_xgmii_baser_dec.sv index 9ea173c..8fccb90 100644 --- a/src/eth/rtl/taxi_xgmii_baser_dec_64.sv +++ b/src/eth/rtl/taxi_xgmii_baser_dec.sv @@ -15,7 +15,7 @@ Authors: /* * XGMII 10GBASE-R decoder */ -module taxi_xgmii_baser_dec_64 # +module taxi_xgmii_baser_dec # ( parameter DATA_W = 64, parameter CTRL_W = (DATA_W/8), @@ -48,9 +48,14 @@ module taxi_xgmii_baser_dec_64 # output wire logic rx_sequence_error ); +localparam DATA_W_INT = 64; +localparam CTRL_W_INT = 8; + +localparam SEG_CNT = DATA_W_INT / DATA_W; + // check configuration -if (DATA_W != 64) - $fatal(0, "Error: Interface width must be 64"); +if (DATA_W != 32 && DATA_W != 64) + $fatal(0, "Error: Interface width must be 32 or 64"); if (CTRL_W * 8 != DATA_W) $fatal(0, "Error: Interface requires byte (8-bit) granularity"); @@ -109,34 +114,70 @@ localparam [7:0] BLOCK_TYPE_TERM_6 = 8'he1, // C7 D5 D4 D3 D2 D1 D0 BT BLOCK_TYPE_TERM_7 = 8'hff; // D6 D5 D4 D3 D2 D1 D0 BT -logic [DATA_W-1:0] decoded_ctrl; -logic [CTRL_W-1:0] decode_err; +wire [DATA_W_INT-1:0] encoded_rx_data_int; +wire encoded_rx_data_valid_int; +wire [HDR_W-1:0] encoded_rx_hdr_int; -logic [DATA_W-1:0] xgmii_rxd_reg = '0, xgmii_rxd_next; -logic [CTRL_W-1:0] xgmii_rxc_reg = '0, xgmii_rxc_next; -logic xgmii_rx_valid_reg = 1'b0, xgmii_rx_valid_next; +logic [DATA_W_INT-1:0] decoded_ctrl; +logic [CTRL_W_INT-1:0] decode_err; + +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 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; -assign xgmii_rxd = xgmii_rxd_reg; -assign xgmii_rxc = xgmii_rxc_reg; -assign xgmii_rx_valid = GBX_IF_EN ? xgmii_rx_valid_reg : 1'b1; +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_bad_block = rx_bad_block_reg; assign rx_sequence_error = rx_sequence_error_reg; +if (DATA_W == 64) begin : repack_in + + assign encoded_rx_data_int = encoded_rx_data; + assign encoded_rx_data_valid_int = GBX_IF_EN ? encoded_rx_data_valid : 1'b1; + assign encoded_rx_hdr_int = encoded_rx_hdr; + +end else begin : repack_in + + logic [DATA_W_INT-DATA_W-1:0] encoded_rx_data_reg = '0; + logic encoded_rx_data_valid_reg = '0; + logic [HDR_W-1:0] encoded_rx_hdr_reg = '0; + + assign encoded_rx_data_int = {encoded_rx_data, encoded_rx_data_reg}; + assign encoded_rx_data_valid_int = encoded_rx_data_valid_reg && (GBX_IF_EN ? encoded_rx_data_valid : 1'b1); + assign encoded_rx_hdr_int = encoded_rx_hdr_reg; + + always @(posedge clk) begin + if (!GBX_IF_EN || encoded_rx_data_valid) begin + encoded_rx_data_reg <= encoded_rx_data; + encoded_rx_data_valid_reg <= encoded_rx_hdr_valid; + if (encoded_rx_hdr_valid) begin + encoded_rx_hdr_reg <= encoded_rx_hdr; + end + end + + if (rst) begin + encoded_rx_data_valid_reg <= '0; + end + end + +end + always_comb begin - xgmii_rxd_next = {8{XGMII_ERROR}}; - xgmii_rxc_next = 8'hff; - xgmii_rx_valid_next = 1'b0; + xgmii_rxd_next = {CTRL_W_INT{XGMII_ERROR}}; + xgmii_rxc_next = '1; + xgmii_rx_valid_next = '0; rx_bad_block_next = 1'b0; rx_sequence_error_next = 1'b0; frame_next = frame_reg; - for (integer i = 0; i < CTRL_W; i = i + 1) begin - case (encoded_rx_data[7*i+8 +: 7]) + for (integer i = 0; i < CTRL_W_INT; i = i + 1) begin + case (encoded_rx_data_int[7*i+8 +: 7]) CTRL_IDLE: begin decoded_ctrl[8*i +: 8] = XGMII_IDLE; decode_err[i] = 1'b0; @@ -180,19 +221,31 @@ always_comb begin endcase end - if (GBX_IF_EN && !encoded_rx_data_valid) begin + if (SEG_CNT > 1) begin + // repack output + // disable broken verilator linter (unreachable code by parameter value) + // verilator lint_off WIDTH + // verilator lint_off SELRANGE + xgmii_rxd_next = {{CTRL_W{XGMII_ERROR}}, xgmii_rxd_reg[DATA_W_INT-1:DATA_W]}; + xgmii_rxc_next = {{CTRL_W{1'b1}}, xgmii_rxc_reg[CTRL_W_INT-1:CTRL_W]}; + xgmii_rx_valid_next = {1'b0, xgmii_rx_valid_reg[SEG_CNT-1:1]}; + // verilator lint_on WIDTH + // verilator lint_on SELRANGE + end + + if (!encoded_rx_data_valid_int) begin // wait for data - end else if (encoded_rx_hdr[0] == 0) begin + end else if (encoded_rx_hdr_int[0] == 0) begin // data block - xgmii_rxd_next = encoded_rx_data; + xgmii_rxd_next = encoded_rx_data_int; xgmii_rxc_next = 8'h00; - xgmii_rx_valid_next = 1'b1; + xgmii_rx_valid_next = '1; rx_bad_block_next = 1'b0; end else begin // control block // use only four bits of block type for reduced fanin - xgmii_rx_valid_next = 1'b1; - case (encoded_rx_data[7:4]) + xgmii_rx_valid_next = '1; + case (encoded_rx_data_int[7:4]) BLOCK_TYPE_CTRL[7:4]: begin // C7 C6 C5 C4 C3 C2 C1 C0 BT xgmii_rxd_next = decoded_ctrl; @@ -203,9 +256,9 @@ always_comb begin // D7 D6 D5 O4 C3 C2 C1 C0 BT xgmii_rxd_next[31:0] = decoded_ctrl[31:0]; xgmii_rxc_next[3:0] = 4'hf; - xgmii_rxd_next[63:40] = encoded_rx_data[63:40]; + xgmii_rxd_next[63:40] = encoded_rx_data_int[63:40]; xgmii_rxc_next[7:4] = 4'h1; - if (encoded_rx_data[39:36] == O_SEQ_OS) begin + 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; end else begin @@ -215,7 +268,7 @@ always_comb begin end BLOCK_TYPE_START_4[7:4]: begin // D7 D6 D5 C3 C2 C1 C0 BT - xgmii_rxd_next = {encoded_rx_data[63:40], XGMII_START, decoded_ctrl[31:0]}; + xgmii_rxd_next = {encoded_rx_data_int[63:40], XGMII_START, decoded_ctrl[31:0]}; xgmii_rxc_next = 8'h1f; rx_bad_block_next = decode_err[3:0] != 0; rx_sequence_error_next = frame_reg; @@ -223,16 +276,16 @@ always_comb begin end BLOCK_TYPE_OS_START[7:4]: begin // D7 D6 D5 O0 D3 D2 D1 BT - xgmii_rxd_next[31:8] = encoded_rx_data[31:8]; + xgmii_rxd_next[31:8] = encoded_rx_data_int[31:8]; xgmii_rxc_next[3:0] = 4'h1; - if (encoded_rx_data[35:32] == O_SEQ_OS) begin + 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; end else begin xgmii_rxd_next[7:0] = XGMII_ERROR; rx_bad_block_next = 1'b1; end - xgmii_rxd_next[63:32] = {encoded_rx_data[63:40], XGMII_START}; + xgmii_rxd_next[63:32] = {encoded_rx_data_int[63:40], XGMII_START}; xgmii_rxc_next[7:4] = 4'h1; rx_sequence_error_next = frame_reg; frame_next = 1'b1; @@ -240,17 +293,17 @@ always_comb begin BLOCK_TYPE_OS_04[7:4]: begin // D7 D6 D5 O4 O0 D3 D2 D1 BT rx_bad_block_next = 1'b0; - xgmii_rxd_next[31:8] = encoded_rx_data[31:8]; + xgmii_rxd_next[31:8] = encoded_rx_data_int[31:8]; xgmii_rxc_next[3:0] = 4'h1; - if (encoded_rx_data[35:32] == O_SEQ_OS) begin + if (encoded_rx_data_int[35:32] == O_SEQ_OS) begin xgmii_rxd_next[7:0] = XGMII_SEQ_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[63:40]; + xgmii_rxd_next[63:40] = encoded_rx_data_int[63:40]; xgmii_rxc_next[7:4] = 4'h1; - if (encoded_rx_data[39:36] == O_SEQ_OS) begin + if (encoded_rx_data_int[39:36] == O_SEQ_OS) begin xgmii_rxd_next[39:32] = XGMII_SEQ_OS; end else begin xgmii_rxd_next[39:32] = XGMII_ERROR; @@ -259,7 +312,7 @@ always_comb begin end BLOCK_TYPE_START_0[7:4]: begin // D7 D6 D5 D4 D3 D2 D1 BT - xgmii_rxd_next = {encoded_rx_data[63:8], XGMII_START}; + xgmii_rxd_next = {encoded_rx_data_int[63:8], XGMII_START}; xgmii_rxc_next = 8'h01; rx_bad_block_next = 1'b0; rx_sequence_error_next = frame_reg; @@ -267,9 +320,9 @@ always_comb begin end BLOCK_TYPE_OS_0[7:4]: begin // C7 C6 C5 C4 O0 D3 D2 D1 BT - xgmii_rxd_next[31:8] = encoded_rx_data[31:8]; + xgmii_rxd_next[31:8] = encoded_rx_data_int[31:8]; xgmii_rxc_next[3:0] = 4'h1; - if (encoded_rx_data[35:32] == O_SEQ_OS) begin + 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; end else begin @@ -289,7 +342,7 @@ always_comb begin end BLOCK_TYPE_TERM_1[7:4]: begin // C7 C6 C5 C4 C3 C2 D0 BT - xgmii_rxd_next = {decoded_ctrl[63:16], XGMII_TERM, encoded_rx_data[15:8]}; + xgmii_rxd_next = {decoded_ctrl[63:16], XGMII_TERM, encoded_rx_data_int[15:8]}; xgmii_rxc_next = 8'hfe; rx_bad_block_next = decode_err[7:2] != 0; rx_sequence_error_next = !frame_reg; @@ -297,7 +350,7 @@ always_comb begin end BLOCK_TYPE_TERM_2[7:4]: begin // C7 C6 C5 C4 C3 D1 D0 BT - xgmii_rxd_next = {decoded_ctrl[63:24], XGMII_TERM, encoded_rx_data[23:8]}; + xgmii_rxd_next = {decoded_ctrl[63:24], XGMII_TERM, encoded_rx_data_int[23:8]}; xgmii_rxc_next = 8'hfc; rx_bad_block_next = decode_err[7:3] != 0; rx_sequence_error_next = !frame_reg; @@ -305,7 +358,7 @@ always_comb begin end BLOCK_TYPE_TERM_3[7:4]: begin // C7 C6 C5 C4 D2 D1 D0 BT - xgmii_rxd_next = {decoded_ctrl[63:32], XGMII_TERM, encoded_rx_data[31:8]}; + xgmii_rxd_next = {decoded_ctrl[63:32], XGMII_TERM, encoded_rx_data_int[31:8]}; xgmii_rxc_next = 8'hf8; rx_bad_block_next = decode_err[7:4] != 0; rx_sequence_error_next = !frame_reg; @@ -313,7 +366,7 @@ always_comb begin end BLOCK_TYPE_TERM_4[7:4]: begin // C7 C6 C5 D3 D2 D1 D0 BT - xgmii_rxd_next = {decoded_ctrl[63:40], XGMII_TERM, encoded_rx_data[39:8]}; + xgmii_rxd_next = {decoded_ctrl[63:40], XGMII_TERM, encoded_rx_data_int[39:8]}; xgmii_rxc_next = 8'hf0; rx_bad_block_next = decode_err[7:5] != 0; rx_sequence_error_next = !frame_reg; @@ -321,7 +374,7 @@ always_comb begin end BLOCK_TYPE_TERM_5[7:4]: begin // C7 C6 D4 D3 D2 D1 D0 BT - xgmii_rxd_next = {decoded_ctrl[63:48], XGMII_TERM, encoded_rx_data[47:8]}; + xgmii_rxd_next = {decoded_ctrl[63:48], XGMII_TERM, encoded_rx_data_int[47:8]}; xgmii_rxc_next = 8'he0; rx_bad_block_next = decode_err[7:6] != 0; rx_sequence_error_next = !frame_reg; @@ -329,7 +382,7 @@ always_comb begin end BLOCK_TYPE_TERM_6[7:4]: begin // C7 D5 D4 D3 D2 D1 D0 BT - xgmii_rxd_next = {decoded_ctrl[63:56], XGMII_TERM, encoded_rx_data[55:8]}; + xgmii_rxd_next = {decoded_ctrl[63:56], XGMII_TERM, encoded_rx_data_int[55:8]}; xgmii_rxc_next = 8'hc0; rx_bad_block_next = decode_err[7] != 0; rx_sequence_error_next = !frame_reg; @@ -337,7 +390,7 @@ always_comb begin end BLOCK_TYPE_TERM_7[7:4]: begin // D6 D5 D4 D3 D2 D1 D0 BT - xgmii_rxd_next = {XGMII_TERM, encoded_rx_data[63:8]}; + xgmii_rxd_next = {XGMII_TERM, encoded_rx_data_int[63:8]}; xgmii_rxc_next = 8'h80; rx_bad_block_next = 1'b0; rx_sequence_error_next = !frame_reg; @@ -345,21 +398,21 @@ always_comb begin end default: begin // invalid block type - xgmii_rxd_next = {8{XGMII_ERROR}}; - xgmii_rxc_next = 8'hff; + xgmii_rxd_next = {CTRL_W_INT{XGMII_ERROR}}; + xgmii_rxc_next = '1; rx_bad_block_next = 1'b1; end endcase end // check all block type bits to detect bad encodings - if (GBX_IF_EN && !encoded_rx_hdr_valid) begin - // wait for header - end else if (encoded_rx_hdr == SYNC_DATA) begin + if (!encoded_rx_data_valid_int) begin + // wait for block + end else if (encoded_rx_hdr_int == SYNC_DATA) begin // data - nothing encoded - end else if (encoded_rx_hdr == SYNC_CTRL) begin + end else if (encoded_rx_hdr_int == SYNC_CTRL) begin // control - check for bad block types - case (encoded_rx_data[7:0]) + case (encoded_rx_data_int[7:0]) BLOCK_TYPE_CTRL: begin end BLOCK_TYPE_OS_4: begin end BLOCK_TYPE_START_4: begin end @@ -377,15 +430,15 @@ always_comb begin BLOCK_TYPE_TERM_7: begin end default: begin // invalid block type - xgmii_rxd_next = {8{XGMII_ERROR}}; - xgmii_rxc_next = 8'hff; + xgmii_rxd_next = {CTRL_W_INT{XGMII_ERROR}}; + xgmii_rxc_next = '1; rx_bad_block_next = 1'b1; end endcase end else begin // invalid header - xgmii_rxd_next = {8{XGMII_ERROR}}; - xgmii_rxc_next = 8'hff; + xgmii_rxd_next = {CTRL_W_INT{XGMII_ERROR}}; + xgmii_rxc_next = '1; rx_bad_block_next = 1'b1; end end @@ -400,7 +453,7 @@ always_ff @(posedge clk) begin frame_reg <= frame_next; if (rst) begin - xgmii_rx_valid_reg <= 1'b0; + xgmii_rx_valid_reg <= '0; frame_reg <= 1'b0; end end diff --git a/src/eth/rtl/taxi_xgmii_baser_enc_64.sv b/src/eth/rtl/taxi_xgmii_baser_enc.sv similarity index 59% rename from src/eth/rtl/taxi_xgmii_baser_enc_64.sv rename to src/eth/rtl/taxi_xgmii_baser_enc.sv index fbb43e5..6b82301 100644 --- a/src/eth/rtl/taxi_xgmii_baser_enc_64.sv +++ b/src/eth/rtl/taxi_xgmii_baser_enc.sv @@ -15,7 +15,7 @@ Authors: /* * XGMII 10GBASE-R encoder */ -module taxi_xgmii_baser_enc_64 # +module taxi_xgmii_baser_enc # ( parameter DATA_W = 64, parameter CTRL_W = (DATA_W/8), @@ -50,9 +50,16 @@ module taxi_xgmii_baser_enc_64 # output wire logic tx_bad_block ); +localparam DATA_W_INT = 64; +localparam CTRL_W_INT = 8; + +localparam USE_HDR_VLD = GBX_IF_EN || DATA_W != 64; + +localparam SEG_CNT = DATA_W_INT / DATA_W; + // check configuration -if (DATA_W != 64) - $fatal(0, "Error: Interface width must be 64"); +if (DATA_W != 32 && DATA_W != 64) + $fatal(0, "Error: Interface width must be 32 or 64"); if (CTRL_W * 8 != DATA_W) $fatal(0, "Error: Interface requires byte (8-bit) granularity"); @@ -111,32 +118,76 @@ localparam [7:0] BLOCK_TYPE_TERM_6 = 8'he1, // C7 D5 D4 D3 D2 D1 D0 BT BLOCK_TYPE_TERM_7 = 8'hff; // D6 D5 D4 D3 D2 D1 D0 BT -logic [DATA_W*7/8-1:0] encoded_ctrl; -logic [CTRL_W-1:0] encode_err; +wire [DATA_W_INT-1:0] xgmii_txd_int; +wire [CTRL_W_INT-1:0] xgmii_txc_int; +wire xgmii_tx_valid_int; -logic [DATA_W-1:0] encoded_tx_data_reg = '0, encoded_tx_data_next; -logic encoded_tx_data_valid_reg = 1'b0, encoded_tx_data_valid_next; +logic [DATA_W_INT*7/8-1:0] encoded_ctrl; +logic [CTRL_W_INT-1:0] encode_err; + +logic [DATA_W_INT-1:0] encoded_tx_data_reg = '0, encoded_tx_data_next; +logic [SEG_CNT-1:0] encoded_tx_data_valid_reg = '0, encoded_tx_data_valid_next; 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_bad_block_reg = 1'b0, tx_bad_block_next; -assign encoded_tx_data = encoded_tx_data_reg; -assign encoded_tx_data_valid = GBX_IF_EN ? encoded_tx_data_valid_reg : 1'b1; +assign encoded_tx_data = encoded_tx_data_reg[DATA_W-1:0]; +assign encoded_tx_data_valid = GBX_IF_EN ? encoded_tx_data_valid_reg[0] : 1'b1; assign encoded_tx_hdr = encoded_tx_hdr_reg; -assign encoded_tx_hdr_valid = GBX_IF_EN ? encoded_tx_hdr_valid_reg : 1'b1; +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_bad_block = tx_bad_block_reg; +if (DATA_W == 64) begin : repack_in + + assign xgmii_txd_int = xgmii_txd; + assign xgmii_txc_int = xgmii_txc; + assign xgmii_tx_valid_int = xgmii_tx_valid; + +end else begin : repack_in + + logic [DATA_W_INT-DATA_W-1:0] xgmii_txd_reg = '0; + logic [CTRL_W_INT-CTRL_W-1:0] xgmii_txc_reg = '0; + logic xgmii_tx_valid_reg = '0; + + assign xgmii_txd_int = {xgmii_txd, xgmii_txd_reg}; + assign xgmii_txc_int = {xgmii_txc, xgmii_txc_reg}; + assign xgmii_tx_valid_int = xgmii_tx_valid_reg && (GBX_IF_EN ? xgmii_tx_valid : 1'b1); + + always @(posedge clk) begin + if (!GBX_IF_EN || xgmii_tx_valid) begin + xgmii_txd_reg <= xgmii_txd; + xgmii_txc_reg <= xgmii_txc; + xgmii_tx_valid_reg <= !xgmii_tx_valid_reg; + if (GBX_IF_EN && tx_gbx_sync_in[0]) begin + // align header output with sync pulse + xgmii_tx_valid_reg <= 1'b0; + end + end + + if (rst) begin + xgmii_tx_valid_reg <= '0; + end + end + +end + always_comb begin + encoded_tx_data_next = {{CTRL_W_INT{CTRL_ERROR}}, BLOCK_TYPE_CTRL}; + encoded_tx_data_valid_next = '0; + encoded_tx_hdr_next = SYNC_CTRL; + encoded_tx_hdr_valid_next = '0; + tx_gbx_sync_next = '0; + tx_bad_block_next = 1'b0; - for (integer i = 0; i < CTRL_W; i = i + 1) begin - if (xgmii_txc[i]) begin + for (integer i = 0; i < CTRL_W_INT; i = i + 1) begin + if (xgmii_txc_int[i]) begin // control - case (xgmii_txd[8*i +: 8]) + case (xgmii_txd_int[8*i +: 8]) XGMII_IDLE: begin encoded_ctrl[7*i +: 7] = CTRL_IDLE; encode_err[i] = 1'b0; @@ -185,85 +236,102 @@ always_comb begin end end - if (xgmii_txc == 8'h00) begin - encoded_tx_data_next = xgmii_txd; + if (SEG_CNT > 1) begin + // repack output + // disable broken verilator linter (unreachable code by parameter value) + // verilator lint_off WIDTH + // verilator lint_off SELRANGE + encoded_tx_data_next = {{DATA_W{1'b0}}, encoded_tx_data_reg[DATA_W_INT-1:DATA_W]}; + encoded_tx_data_valid_next = {1'b0, encoded_tx_data_valid_reg[SEG_CNT-1:1]}; + encoded_tx_hdr_next = 2'b00; + encoded_tx_hdr_valid_next = 1'b0; + // verilator lint_on WIDTH + // verilator lint_on SELRANGE + end + + if (!xgmii_tx_valid_int) begin + // wait for block + end else if (xgmii_txc_int == 8'h00) begin + encoded_tx_data_next = xgmii_txd_int; + encoded_tx_data_valid_next = '1; encoded_tx_hdr_next = SYNC_DATA; + encoded_tx_hdr_valid_next = 1'b1; tx_bad_block_next = 1'b0; end else begin - if (xgmii_txc == 8'h1f && xgmii_txd[39:32] == XGMII_SEQ_OS) begin + if (xgmii_txc_int == 8'h1f && xgmii_txd_int[39:32] == XGMII_SEQ_OS) begin // ordered set in lane 4 - encoded_tx_data_next = {xgmii_txd[63:40], O_SEQ_OS, encoded_ctrl[27:0], BLOCK_TYPE_OS_4}; + encoded_tx_data_next = {xgmii_txd_int[63:40], O_SEQ_OS, encoded_ctrl[27:0], BLOCK_TYPE_OS_4}; tx_bad_block_next = encode_err[3:0] != 0; - end else if (xgmii_txc == 8'h1f && xgmii_txd[39:32] == XGMII_START) begin + end else if (xgmii_txc_int == 8'h1f && xgmii_txd_int[39:32] == XGMII_START) begin // start in lane 4 - encoded_tx_data_next = {xgmii_txd[63:40], 4'd0, encoded_ctrl[27:0], BLOCK_TYPE_START_4}; + encoded_tx_data_next = {xgmii_txd_int[63:40], 4'd0, encoded_ctrl[27:0], BLOCK_TYPE_START_4}; tx_bad_block_next = encode_err[3:0] != 0; - end else if (xgmii_txc == 8'h11 && xgmii_txd[7:0] == XGMII_SEQ_OS && xgmii_txd[39:32] == XGMII_START) begin + end else if (xgmii_txc_int == 8'h11 && xgmii_txd_int[7:0] == XGMII_SEQ_OS && xgmii_txd_int[39:32] == XGMII_START) begin // ordered set in lane 0, start in lane 4 - encoded_tx_data_next = {xgmii_txd[63:40], 4'd0, O_SEQ_OS, xgmii_txd[31:8], BLOCK_TYPE_OS_START}; + encoded_tx_data_next = {xgmii_txd_int[63:40], 4'd0, O_SEQ_OS, xgmii_txd_int[31:8], BLOCK_TYPE_OS_START}; tx_bad_block_next = 1'b0; - end else if (xgmii_txc == 8'h11 && xgmii_txd[7:0] == XGMII_SEQ_OS && xgmii_txd[39:32] == XGMII_SEQ_OS) begin + end else if (xgmii_txc_int == 8'h11 && xgmii_txd_int[7:0] == XGMII_SEQ_OS && xgmii_txd_int[39:32] == XGMII_SEQ_OS) begin // ordered set in lane 0 and lane 4 - encoded_tx_data_next = {xgmii_txd[63:40], O_SEQ_OS, O_SEQ_OS, xgmii_txd[31:8], BLOCK_TYPE_OS_04}; + encoded_tx_data_next = {xgmii_txd_int[63:40], O_SEQ_OS, O_SEQ_OS, xgmii_txd_int[31:8], BLOCK_TYPE_OS_04}; tx_bad_block_next = 1'b0; - end else if (xgmii_txc == 8'h01 && xgmii_txd[7:0] == XGMII_START) begin + end else if (xgmii_txc_int == 8'h01 && xgmii_txd_int[7:0] == XGMII_START) begin // start in lane 0 - encoded_tx_data_next = {xgmii_txd[63:8], BLOCK_TYPE_START_0}; + encoded_tx_data_next = {xgmii_txd_int[63:8], BLOCK_TYPE_START_0}; tx_bad_block_next = 1'b0; - end else if (xgmii_txc == 8'hf1 && xgmii_txd[7:0] == XGMII_SEQ_OS) begin + end else if (xgmii_txc_int == 8'hf1 && xgmii_txd_int[7:0] == XGMII_SEQ_OS) begin // ordered set in lane 0 - encoded_tx_data_next = {encoded_ctrl[55:28], O_SEQ_OS, xgmii_txd[31:8], BLOCK_TYPE_OS_0}; + encoded_tx_data_next = {encoded_ctrl[55:28], O_SEQ_OS, xgmii_txd_int[31:8], BLOCK_TYPE_OS_0}; tx_bad_block_next = encode_err[7:4] != 0; - end else if (xgmii_txc == 8'hff && xgmii_txd[7:0] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'hff && xgmii_txd_int[7:0] == XGMII_TERM) begin // terminate in lane 0 encoded_tx_data_next = {encoded_ctrl[55:7], 7'd0, BLOCK_TYPE_TERM_0}; tx_bad_block_next = encode_err[7:1] != 0; - end else if (xgmii_txc == 8'hfe && xgmii_txd[15:8] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'hfe && xgmii_txd_int[15:8] == XGMII_TERM) begin // terminate in lane 1 - encoded_tx_data_next = {encoded_ctrl[55:14], 6'd0, xgmii_txd[7:0], BLOCK_TYPE_TERM_1}; + encoded_tx_data_next = {encoded_ctrl[55:14], 6'd0, xgmii_txd_int[7:0], BLOCK_TYPE_TERM_1}; tx_bad_block_next = encode_err[7:2] != 0; - end else if (xgmii_txc == 8'hfc && xgmii_txd[23:16] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'hfc && xgmii_txd_int[23:16] == XGMII_TERM) begin // terminate in lane 2 - encoded_tx_data_next = {encoded_ctrl[55:21], 5'd0, xgmii_txd[15:0], BLOCK_TYPE_TERM_2}; + encoded_tx_data_next = {encoded_ctrl[55:21], 5'd0, xgmii_txd_int[15:0], BLOCK_TYPE_TERM_2}; tx_bad_block_next = encode_err[7:3] != 0; - end else if (xgmii_txc == 8'hf8 && xgmii_txd[31:24] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'hf8 && xgmii_txd_int[31:24] == XGMII_TERM) begin // terminate in lane 3 - encoded_tx_data_next = {encoded_ctrl[55:28], 4'd0, xgmii_txd[23:0], BLOCK_TYPE_TERM_3}; + encoded_tx_data_next = {encoded_ctrl[55:28], 4'd0, xgmii_txd_int[23:0], BLOCK_TYPE_TERM_3}; tx_bad_block_next = encode_err[7:4] != 0; - end else if (xgmii_txc == 8'hf0 && xgmii_txd[39:32] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'hf0 && xgmii_txd_int[39:32] == XGMII_TERM) begin // terminate in lane 4 - encoded_tx_data_next = {encoded_ctrl[55:35], 3'd0, xgmii_txd[31:0], BLOCK_TYPE_TERM_4}; + encoded_tx_data_next = {encoded_ctrl[55:35], 3'd0, xgmii_txd_int[31:0], BLOCK_TYPE_TERM_4}; tx_bad_block_next = encode_err[7:5] != 0; - end else if (xgmii_txc == 8'he0 && xgmii_txd[47:40] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'he0 && xgmii_txd_int[47:40] == XGMII_TERM) begin // terminate in lane 5 - encoded_tx_data_next = {encoded_ctrl[55:42], 2'd0, xgmii_txd[39:0], BLOCK_TYPE_TERM_5}; + encoded_tx_data_next = {encoded_ctrl[55:42], 2'd0, xgmii_txd_int[39:0], BLOCK_TYPE_TERM_5}; tx_bad_block_next = encode_err[7:6] != 0; - end else if (xgmii_txc == 8'hc0 && xgmii_txd[55:48] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'hc0 && xgmii_txd_int[55:48] == XGMII_TERM) begin // terminate in lane 6 - encoded_tx_data_next = {encoded_ctrl[55:49], 1'd0, xgmii_txd[47:0], BLOCK_TYPE_TERM_6}; + encoded_tx_data_next = {encoded_ctrl[55:49], 1'd0, xgmii_txd_int[47:0], BLOCK_TYPE_TERM_6}; tx_bad_block_next = encode_err[7] != 0; - end else if (xgmii_txc == 8'h80 && xgmii_txd[63:56] == XGMII_TERM) begin + end else if (xgmii_txc_int == 8'h80 && xgmii_txd_int[63:56] == XGMII_TERM) begin // terminate in lane 7 - encoded_tx_data_next = {xgmii_txd[55:0], BLOCK_TYPE_TERM_7}; + encoded_tx_data_next = {xgmii_txd_int[55:0], BLOCK_TYPE_TERM_7}; tx_bad_block_next = 1'b0; - end else if (xgmii_txc == 8'hff) begin + end else if (xgmii_txc_int == 8'hff) begin // all control encoded_tx_data_next = {encoded_ctrl, BLOCK_TYPE_CTRL}; tx_bad_block_next = encode_err != 0; end else begin // no corresponding block format - encoded_tx_data_next = {{8{CTRL_ERROR}}, BLOCK_TYPE_CTRL}; + encoded_tx_data_next = {{CTRL_W_INT{CTRL_ERROR}}, BLOCK_TYPE_CTRL}; tx_bad_block_next = 1'b1; end + encoded_tx_data_valid_next = '1; encoded_tx_hdr_next = SYNC_CTRL; + encoded_tx_hdr_valid_next = 1'b1; end - if (GBX_IF_EN && !xgmii_tx_valid) begin + if (GBX_IF_EN && !xgmii_tx_valid_int) begin tx_bad_block_next = 1'b0; end - encoded_tx_data_valid_next = xgmii_tx_valid; - encoded_tx_hdr_valid_next = xgmii_tx_valid; tx_gbx_sync_next = tx_gbx_sync_in; end diff --git a/src/eth/tb/taxi_eth_phy_10g/test_taxi_eth_phy_10g.py b/src/eth/tb/taxi_eth_phy_10g/test_taxi_eth_phy_10g.py index 4d99996..ffce0cf 100644 --- a/src/eth/tb/taxi_eth_phy_10g/test_taxi_eth_phy_10g.py +++ b/src/eth/tb/taxi_eth_phy_10g/test_taxi_eth_phy_10g.py @@ -16,6 +16,7 @@ import sys import cocotb_test.simulator +import pytest import cocotb from cocotb.clock import Clock from cocotb.triggers import RisingEdge @@ -41,8 +42,13 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - cocotb.start_soon(Clock(dut.tx_clk, 6.4, units="ns").start()) - cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start()) + if len(dut.xgmii_txd) == 64: + self.clk_period = 6.4 + else: + self.clk_period = 3.2 + + cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) self.xgmii_source = XgmiiSource(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst) self.xgmii_sink = XgmiiSink(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) @@ -232,7 +238,8 @@ def process_f_files(files): return list(lst.values()) -def test_taxi_eth_phy_10g(request): +@pytest.mark.parametrize("data_w", [32, 64]) +def test_taxi_eth_phy_10g(request, data_w): dut = "taxi_eth_phy_10g" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = dut @@ -246,7 +253,7 @@ def test_taxi_eth_phy_10g(request): parameters = {} - parameters['DATA_W'] = 64 + parameters['DATA_W'] = data_w parameters['CTRL_W'] = parameters['DATA_W'] // 8 parameters['HDR_W'] = 2 parameters['TX_GBX_IF_EN'] = 0 diff --git a/src/eth/tb/taxi_xgmii_baser_dec_64/Makefile b/src/eth/tb/taxi_xgmii_baser_dec/Makefile similarity index 97% rename from src/eth/tb/taxi_xgmii_baser_dec_64/Makefile rename to src/eth/tb/taxi_xgmii_baser_dec/Makefile index 6738333..be0f84d 100644 --- a/src/eth/tb/taxi_xgmii_baser_dec_64/Makefile +++ b/src/eth/tb/taxi_xgmii_baser_dec/Makefile @@ -17,7 +17,7 @@ RTL_DIR = ../../rtl LIB_DIR = ../../lib TAXI_SRC_DIR = $(LIB_DIR)/taxi/src -DUT = taxi_xgmii_baser_dec_64 +DUT = taxi_xgmii_baser_dec COCOTB_TEST_MODULES = test_$(DUT) COCOTB_TOPLEVEL = $(DUT) MODULE = $(COCOTB_TEST_MODULES) diff --git a/src/eth/tb/taxi_xgmii_baser_dec_64/baser.py b/src/eth/tb/taxi_xgmii_baser_dec/baser.py similarity index 100% rename from src/eth/tb/taxi_xgmii_baser_dec_64/baser.py rename to src/eth/tb/taxi_xgmii_baser_dec/baser.py diff --git a/src/eth/tb/taxi_xgmii_baser_dec_64/test_taxi_xgmii_baser_dec_64.py b/src/eth/tb/taxi_xgmii_baser_dec/test_taxi_xgmii_baser_dec.py similarity index 90% rename from src/eth/tb/taxi_xgmii_baser_dec_64/test_taxi_xgmii_baser_dec_64.py rename to src/eth/tb/taxi_xgmii_baser_dec/test_taxi_xgmii_baser_dec.py index 718fa6f..ba0d9c1 100644 --- a/src/eth/tb/taxi_xgmii_baser_dec_64/test_taxi_xgmii_baser_dec_64.py +++ b/src/eth/tb/taxi_xgmii_baser_dec/test_taxi_xgmii_baser_dec.py @@ -14,6 +14,7 @@ import logging import os import sys +import pytest import cocotb_test.simulator import cocotb @@ -41,9 +42,21 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start()) + if len(dut.xgmii_rxd) == 64: + self.clk_period = 6.4 + else: + self.clk_period = 3.2 - self.source = BaseRSerdesSource(dut.encoded_rx_data, dut.encoded_rx_hdr, dut.clk, scramble=False) + cocotb.start_soon(Clock(dut.clk, self.clk_period, units="ns").start()) + + self.source = BaseRSerdesSource( + data=dut.encoded_rx_data, + data_valid=dut.encoded_rx_data_valid, + hdr=dut.encoded_rx_hdr, + hdr_valid=dut.encoded_rx_hdr_valid, + clock=dut.clk, + scramble=False + ) self.sink = XgmiiSink(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst) dut.encoded_rx_data_valid.setimmediatevalue(1) @@ -214,8 +227,9 @@ def process_f_files(files): return list(lst.values()) -def test_taxi_xgmii_baser_dec_64(request): - dut = "taxi_xgmii_baser_dec_64" +@pytest.mark.parametrize("data_w", [32, 64]) +def test_taxi_xgmii_baser_dec(request, data_w): + dut = "taxi_xgmii_baser_dec" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = dut @@ -227,7 +241,7 @@ def test_taxi_xgmii_baser_dec_64(request): parameters = {} - parameters['DATA_W'] = 64 + parameters['DATA_W'] = data_w parameters['CTRL_W'] = parameters['DATA_W'] // 8 parameters['HDR_W'] = 2 parameters['GBX_IF_EN'] = 0 diff --git a/src/eth/tb/taxi_xgmii_baser_enc_64/Makefile b/src/eth/tb/taxi_xgmii_baser_enc/Makefile similarity index 97% rename from src/eth/tb/taxi_xgmii_baser_enc_64/Makefile rename to src/eth/tb/taxi_xgmii_baser_enc/Makefile index 0061ff1..231675b 100644 --- a/src/eth/tb/taxi_xgmii_baser_enc_64/Makefile +++ b/src/eth/tb/taxi_xgmii_baser_enc/Makefile @@ -17,7 +17,7 @@ RTL_DIR = ../../rtl LIB_DIR = ../../lib TAXI_SRC_DIR = $(LIB_DIR)/taxi/src -DUT = taxi_xgmii_baser_enc_64 +DUT = taxi_xgmii_baser_enc COCOTB_TEST_MODULES = test_$(DUT) COCOTB_TOPLEVEL = $(DUT) MODULE = $(COCOTB_TEST_MODULES) diff --git a/src/eth/tb/taxi_xgmii_baser_enc_64/baser.py b/src/eth/tb/taxi_xgmii_baser_enc/baser.py similarity index 100% rename from src/eth/tb/taxi_xgmii_baser_enc_64/baser.py rename to src/eth/tb/taxi_xgmii_baser_enc/baser.py diff --git a/src/eth/tb/taxi_xgmii_baser_enc_64/test_taxi_xgmii_baser_enc_64.py b/src/eth/tb/taxi_xgmii_baser_enc/test_taxi_xgmii_baser_enc.py similarity index 86% rename from src/eth/tb/taxi_xgmii_baser_enc_64/test_taxi_xgmii_baser_enc_64.py rename to src/eth/tb/taxi_xgmii_baser_enc/test_taxi_xgmii_baser_enc.py index 788e8ce..a96e025 100644 --- a/src/eth/tb/taxi_xgmii_baser_enc_64/test_taxi_xgmii_baser_enc_64.py +++ b/src/eth/tb/taxi_xgmii_baser_enc/test_taxi_xgmii_baser_enc.py @@ -14,6 +14,7 @@ import logging import os import sys +import pytest import cocotb_test.simulator import cocotb @@ -41,10 +42,22 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start()) + if len(dut.xgmii_txd) == 64: + self.clk_period = 6.4 + else: + self.clk_period = 3.2 + + cocotb.start_soon(Clock(dut.clk, self.clk_period, units="ns").start()) self.source = XgmiiSource(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst) - self.sink = BaseRSerdesSink(dut.encoded_tx_data, dut.encoded_tx_hdr, dut.clk, scramble=False) + self.sink = BaseRSerdesSink( + data=dut.encoded_tx_data, + data_valid=dut.encoded_tx_data_valid, + hdr=dut.encoded_tx_hdr, + hdr_valid=dut.encoded_tx_hdr_valid, + clock=dut.clk, + scramble=False + ) dut.xgmii_tx_valid.setimmediatevalue(1) dut.tx_gbx_sync_in.setimmediatevalue(0) @@ -185,12 +198,13 @@ if cocotb.SIM_NAME: factory.add_option("force_offset_start", [False, True]) factory.generate_tests() - factory = TestFactory(run_test_alignment) - factory.add_option("payload_data", [incrementing_payload]) - factory.add_option("ifg", [12]) - factory.add_option("enable_dic", [True, False]) - factory.add_option("force_offset_start", [False, True]) - factory.generate_tests() + if len(cocotb.top.xgmii_txd) == 64: + factory = TestFactory(run_test_alignment) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("enable_dic", [True, False]) + factory.add_option("force_offset_start", [False, True]) + factory.generate_tests() # cocotb-test @@ -214,8 +228,9 @@ def process_f_files(files): return list(lst.values()) -def test_taxi_xgmii_baser_enc_64(request): - dut = "taxi_xgmii_baser_enc_64" +@pytest.mark.parametrize("data_w", [32, 64]) +def test_taxi_xgmii_baser_enc(request, data_w): + dut = "taxi_xgmii_baser_enc" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = dut @@ -227,7 +242,7 @@ def test_taxi_xgmii_baser_enc_64(request): parameters = {} - parameters['DATA_W'] = 64 + parameters['DATA_W'] = data_w parameters['CTRL_W'] = parameters['DATA_W'] // 8 parameters['HDR_W'] = 2 parameters['GBX_IF_EN'] = 0