fpga: lib: Add ZPU support to SV transport adapter
Original-commit: 105d8d1661d76bfe7264798a691b061366c94898
This commit is contained in:
@@ -10,10 +10,12 @@
|
|||||||
|
|
||||||
module eth_ifc_all_tb;
|
module eth_ifc_all_tb;
|
||||||
|
|
||||||
eth_ifc_tb #(.TEST_NAME("ORIGINAL"), .ENET_W(64), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(0)) ORIGINAL ();
|
eth_ifc_tb #(.TEST_NAME("ORIGINAL"), .ENET_W(64), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(0), .PREAMBLE_BYTES(6), .CPU_PREAMBLE(0)) ORIGINAL ();
|
||||||
eth_ifc_tb #(.TEST_NAME("64B"), .ENET_W(64), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(1)) ETH64 ();
|
eth_ifc_tb #(.TEST_NAME("64B_X4XX"), .ENET_W(64), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(1), .PREAMBLE_BYTES(0), .CPU_PREAMBLE(0)) ETH64_X4XX ();
|
||||||
eth_ifc_tb #(.TEST_NAME("512B"), .ENET_W(512), .CPU_W(64), .CHDR_W(512), .SV_ETH_IFC(1)) ETH512_CHDR512 ();
|
eth_ifc_tb #(.TEST_NAME("64B_N3XX"), .ENET_W(64), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(1), .PREAMBLE_BYTES(6), .CPU_PREAMBLE(0)) ETH64_N3XX ();
|
||||||
eth_ifc_tb #(.TEST_NAME("512_64B"), .ENET_W(512), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(1)) ETH512_CHDR64 ();
|
eth_ifc_tb #(.TEST_NAME("64B_X3XX"), .ENET_W(64), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(1), .PREAMBLE_BYTES(6), .CPU_PREAMBLE(1)) ETH64_X3XX ();
|
||||||
eth_ifc_tb #(.TEST_NAME("512_128B"), .ENET_W(512), .CPU_W(64), .CHDR_W(128), .SV_ETH_IFC(1)) ETH512_CHDR128 ();
|
eth_ifc_tb #(.TEST_NAME("512B"), .ENET_W(512), .CPU_W(64), .CHDR_W(512), .SV_ETH_IFC(1), .PREAMBLE_BYTES(0), .CPU_PREAMBLE(0)) ETH512_CHDR512 ();
|
||||||
|
eth_ifc_tb #(.TEST_NAME("512_64B"), .ENET_W(512), .CPU_W(64), .CHDR_W(64), .SV_ETH_IFC(1), .PREAMBLE_BYTES(0), .CPU_PREAMBLE(0)) ETH512_CHDR64 ();
|
||||||
|
eth_ifc_tb #(.TEST_NAME("512_128B"), .ENET_W(512), .CPU_W(64), .CHDR_W(128), .SV_ETH_IFC(1), .PREAMBLE_BYTES(0), .CPU_PREAMBLE(0)) ETH512_CHDR128 ();
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -5,16 +5,36 @@
|
|||||||
//
|
//
|
||||||
// Module: eth_ifc_tb
|
// Module: eth_ifc_tb
|
||||||
//
|
//
|
||||||
// Description: Testbench for eth_interface
|
// Description:
|
||||||
|
//
|
||||||
|
// Testbench for eth_ipv4_interface and eth_interface. Both DUTs should have
|
||||||
|
// the same behavior, but eth_interface only supports 64-bit and does not
|
||||||
|
// support having preamble bytes on the CPU interface.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// TEST_NAME : Name of this test (for the reporting outputs)
|
||||||
|
// SV_ETH_IFC : If true, use eth_ipv4_interface (SystemVerilog) as the
|
||||||
|
// DUT, otherwise use eth_interface (Verilog, 64-bit only).
|
||||||
|
// ENET_W : Width of the Ethernet interface to simulate
|
||||||
|
// CPU_W : Width of the CPU interface to simulate
|
||||||
|
// CHDR_W : Width of the CHDR interface to simulate
|
||||||
|
// PREAMBLE_BYTES : Number of preamble bytes expected by then Ethernet
|
||||||
|
// interface. Can be 0 or 6.
|
||||||
|
// CPU_PREAMBLE : If true, then the CPU interface will expect
|
||||||
|
// PREAMBLE_BYTES (for ZPU). Otherwise it will expect 0
|
||||||
|
// bytes of preamble (for ARM CPU).
|
||||||
//
|
//
|
||||||
|
|
||||||
module eth_ifc_tb #(
|
module eth_ifc_tb #(
|
||||||
parameter TEST_NAME = "eth_ifc_tb",
|
parameter TEST_NAME = "eth_ifc_tb",
|
||||||
parameter SV_ETH_IFC = 1,
|
parameter SV_ETH_IFC = 1,
|
||||||
parameter ENET_W = 64,
|
parameter ENET_W = 64,
|
||||||
parameter CPU_W = 64,
|
parameter CPU_W = 64,
|
||||||
parameter CHDR_W = 64
|
parameter CHDR_W = 64,
|
||||||
)(
|
parameter PREAMBLE_BYTES = 0,
|
||||||
|
parameter CPU_PREAMBLE = 0
|
||||||
|
) (
|
||||||
/* no IO */
|
/* no IO */
|
||||||
);
|
);
|
||||||
// Include macros and time declarations for use with PkgTestExec
|
// Include macros and time declarations for use with PkgTestExec
|
||||||
@@ -43,7 +63,6 @@ module eth_ifc_tb #(
|
|||||||
localparam ETH_PERIOD = (ENET_W==512) ? 3.1:5.0;
|
localparam ETH_PERIOD = (ENET_W==512) ? 3.1:5.0;
|
||||||
// can set PREAMBLE_BYTES to 0 or 6 if SV_ETH_IFC, but otherwise
|
// can set PREAMBLE_BYTES to 0 or 6 if SV_ETH_IFC, but otherwise
|
||||||
// it's hard-coded to 6. (0 is normal for 100G)(6 is normal for old Xge)
|
// it's hard-coded to 6. (0 is normal for 100G)(6 is normal for old Xge)
|
||||||
localparam PREAMBLE_BYTES = SV_ETH_IFC ? 0 : 6;
|
|
||||||
// Include for register offsets
|
// Include for register offsets
|
||||||
`include "../eth_regs.vh"
|
`include "../eth_regs.vh"
|
||||||
// allows the DUT to push full words and tb does not check tuser/tkeep of packets it's transmitting
|
// allows the DUT to push full words and tb does not check tuser/tkeep of packets it's transmitting
|
||||||
@@ -139,9 +158,9 @@ module eth_ifc_tb #(
|
|||||||
|
|
||||||
|
|
||||||
if (SV_ETH_IFC) begin : gen_new_dut
|
if (SV_ETH_IFC) begin : gen_new_dut
|
||||||
|
|
||||||
eth_ipv4_interface #(
|
eth_ipv4_interface #(
|
||||||
.PREAMBLE_BYTES(PREAMBLE_BYTES),
|
.PREAMBLE_BYTES(PREAMBLE_BYTES),
|
||||||
|
.CPU_PREAMBLE(CPU_PREAMBLE),
|
||||||
.CPU_FIFO_SIZE(MTU),
|
.CPU_FIFO_SIZE(MTU),
|
||||||
.CHDR_FIFO_SIZE(MTU),
|
.CHDR_FIFO_SIZE(MTU),
|
||||||
.PROTOVER(PROTOVER),
|
.PROTOVER(PROTOVER),
|
||||||
@@ -150,7 +169,7 @@ module eth_ifc_tb #(
|
|||||||
.RT_TBL_SIZE(RT_TBL_SIZE),
|
.RT_TBL_SIZE(RT_TBL_SIZE),
|
||||||
.BASE(BASE),.SYNC(SYNC),
|
.BASE(BASE),.SYNC(SYNC),
|
||||||
.ENET_W(ENET_W),.CPU_W(CPU_W),.CHDR_W(CHDR_W)
|
.ENET_W(ENET_W),.CPU_W(CPU_W),.CHDR_W(CHDR_W)
|
||||||
) eth_interface (
|
) eth_ipv4_interface_i (
|
||||||
.bus_clk(clk),.bus_rst(reset),.eth_pause_req(),.*
|
.bus_clk(clk),.bus_rst(reset),.eth_pause_req(),.*
|
||||||
);
|
);
|
||||||
end else begin : gen_old_dut
|
end else begin : gen_old_dut
|
||||||
@@ -229,7 +248,7 @@ module eth_ifc_tb #(
|
|||||||
.PROTOVER(PROTOVER), .NODE_INST(NODE_INST), .MTU(MTU),
|
.PROTOVER(PROTOVER), .NODE_INST(NODE_INST), .MTU(MTU),
|
||||||
.REG_AWIDTH(REG_AWIDTH), .RT_TBL_SIZE(RT_TBL_SIZE),
|
.REG_AWIDTH(REG_AWIDTH), .RT_TBL_SIZE(RT_TBL_SIZE),
|
||||||
.BASE(BASE)
|
.BASE(BASE)
|
||||||
) eth_interface (
|
) eth_interface_i (
|
||||||
.*,
|
.*,
|
||||||
.my_udp_port (my_udp_chdr_port)
|
.my_udp_port (my_udp_chdr_port)
|
||||||
);
|
);
|
||||||
@@ -281,6 +300,7 @@ module eth_ifc_tb #(
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
task test_reset();
|
task test_reset();
|
||||||
|
test.start_test({TEST_NAME,"::Wait for Reset"}, 10us);
|
||||||
wait(!reset);
|
wait(!reset);
|
||||||
repeat (10) @(posedge clk);
|
repeat (10) @(posedge clk);
|
||||||
test.end_test();
|
test.end_test();
|
||||||
@@ -355,12 +375,12 @@ module eth_ifc_tb #(
|
|||||||
typedef ChdrPacket #(CHDR_W,CHDR_USER_W) ChdrPacket_t;
|
typedef ChdrPacket #(CHDR_W,CHDR_USER_W) ChdrPacket_t;
|
||||||
|
|
||||||
task automatic test_ethcpu(int num_samples[$], int ERROR_PROB=2, int EXPECT_DROPS=0);
|
task automatic test_ethcpu(int num_samples[$], int ERROR_PROB=2, int EXPECT_DROPS=0);
|
||||||
TestExec test_e2c = new();
|
|
||||||
automatic EthXportPacket_t send[$];
|
automatic EthXportPacket_t send[$];
|
||||||
automatic CpuXportPacket_t expected[$];
|
automatic CpuXportPacket_t expected[$];
|
||||||
automatic int sample_sum = 0;
|
automatic int sample_sum = 0;
|
||||||
|
|
||||||
test_e2c.start_test({TEST_NAME,"::Ethernet to CPU"}, 60us);
|
$display("%s::Ethernet to CPU", TEST_NAME);
|
||||||
|
|
||||||
// This path is
|
// This path is
|
||||||
// eth_rx -> s_mac(eth_adapter) -> s_mac(eth_dispatch) ->
|
// eth_rx -> s_mac(eth_adapter) -> s_mac(eth_dispatch) ->
|
||||||
//// in_reg(AXI_FIFO)(SIZE=1)
|
//// in_reg(AXI_FIFO)(SIZE=1)
|
||||||
@@ -377,11 +397,21 @@ module eth_ifc_tb #(
|
|||||||
automatic ipv4_hdr_t ipv4_hdr = DEFAULT_IPV4_HDR;
|
automatic ipv4_hdr_t ipv4_hdr = DEFAULT_IPV4_HDR;
|
||||||
automatic udp_hdr_t udp_hdr;
|
automatic udp_hdr_t udp_hdr;
|
||||||
automatic raw_pkt_t pay,udp_raw;
|
automatic raw_pkt_t pay,udp_raw;
|
||||||
automatic int preamble;
|
automatic int eth_preamble;
|
||||||
|
automatic int cpu_preamble;
|
||||||
|
|
||||||
if (PREAMBLE_BYTES == 6) preamble = NORMAL_PREAMBLE;
|
// eth_preamble refers to the preamble to add or expect on the Ethernet
|
||||||
else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE;
|
// interface whereas cpu_preamble is the preamble to add or expect on the
|
||||||
else $fatal(1, "Invalid PREAMBLE_BYTES");
|
// CPU interface. The CHDR interface never has a preamble.
|
||||||
|
if (PREAMBLE_BYTES == 6) begin
|
||||||
|
eth_preamble = NORMAL_PREAMBLE;
|
||||||
|
cpu_preamble = CPU_PREAMBLE ? NORMAL_PREAMBLE : NO_PREAMBLE;
|
||||||
|
end else if (PREAMBLE_BYTES == 0) begin
|
||||||
|
eth_preamble = NO_PREAMBLE;
|
||||||
|
cpu_preamble = NO_PREAMBLE;
|
||||||
|
end else begin
|
||||||
|
$fatal(1, "Invalid PREAMBLE_BYTES");
|
||||||
|
end
|
||||||
|
|
||||||
expected[i] = new;
|
expected[i] = new;
|
||||||
send[i] = new;
|
send[i] = new;
|
||||||
@@ -391,13 +421,13 @@ module eth_ifc_tb #(
|
|||||||
.ramp_inc(1),.pkt(pay),.SWIDTH(8));
|
.ramp_inc(1),.pkt(pay),.SWIDTH(8));
|
||||||
sample_sum += num_samples[i];
|
sample_sum += num_samples[i];
|
||||||
udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay,
|
udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay,
|
||||||
.preamble(preamble));
|
.preamble(eth_preamble));
|
||||||
send[i].push_bytes(udp_raw);
|
send[i].push_bytes(udp_raw);
|
||||||
send[i].tkeep_to_tuser(.ERROR_PROB(ERROR_PROB));
|
send[i].tkeep_to_tuser(.ERROR_PROB(ERROR_PROB));
|
||||||
|
|
||||||
// rebuild the expected packet for comparison without the preamble
|
// rebuild the expected packet for comparison without the preamble
|
||||||
udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay,
|
udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay,
|
||||||
.preamble(NO_PREAMBLE));
|
.preamble(cpu_preamble));
|
||||||
expected[i].push_bytes(udp_raw);
|
expected[i].push_bytes(udp_raw);
|
||||||
expected[i].tkeep_to_tuser();
|
expected[i].tkeep_to_tuser();
|
||||||
|
|
||||||
@@ -439,17 +469,17 @@ module eth_ifc_tb #(
|
|||||||
void'(expected.pop_front());
|
void'(expected.pop_front());
|
||||||
++drop_count;
|
++drop_count;
|
||||||
++pkt_num;
|
++pkt_num;
|
||||||
$display("Droped packet %d",pkt_num);
|
$display("Dropped packet: %d",pkt_num);
|
||||||
`ASSERT_ERROR(drop_count < EXPECT_DROPS,"Exceeded anticipated number of dropped packets e2c");
|
`ASSERT_ERROR(drop_count < EXPECT_DROPS,"Exceeded anticipated number of dropped packets e2c");
|
||||||
end
|
end
|
||||||
if (expected.size() > 0) begin
|
if (expected.size() > 0) begin
|
||||||
++pkt_num;
|
++pkt_num;
|
||||||
$display("Rcvd packet %d",pkt_num);
|
$display("Received packet: %d",pkt_num);
|
||||||
void'(expected.pop_front());
|
void'(expected.pop_front());
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (SV_ETH_IFC) begin
|
if (SV_ETH_IFC) begin
|
||||||
$display("Verify drop count is %d",drop_count);
|
$display("Drop count: %d",drop_count);
|
||||||
reg_rd_check(REG_CPU_DROPPED,drop_count);
|
reg_rd_check(REG_CPU_DROPPED,drop_count);
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
@@ -464,8 +494,6 @@ module eth_ifc_tb #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
join
|
join
|
||||||
|
|
||||||
test_e2c.end_test();
|
|
||||||
endtask : test_ethcpu
|
endtask : test_ethcpu
|
||||||
|
|
||||||
task automatic wait_for_udp_packets(int udp_dest_port);
|
task automatic wait_for_udp_packets(int udp_dest_port);
|
||||||
@@ -491,12 +519,11 @@ module eth_ifc_tb #(
|
|||||||
|
|
||||||
|
|
||||||
task automatic test_cpueth(int num_samples[$]);
|
task automatic test_cpueth(int num_samples[$]);
|
||||||
TestExec test_c2e = new();
|
|
||||||
automatic CpuXportPacket_t send[$];
|
automatic CpuXportPacket_t send[$];
|
||||||
automatic EthXportPacket_t expected[$];
|
automatic EthXportPacket_t expected[$];
|
||||||
automatic int sample_sum = 0;
|
automatic int sample_sum = 0;
|
||||||
|
|
||||||
test_c2e.start_test({TEST_NAME,"::CPU to Ethernet"}, 60us);
|
$display("%s::CPU to Ethernet", TEST_NAME);
|
||||||
// This path is
|
// This path is
|
||||||
// c2e -> (eth_adapter) s_cpu ->
|
// c2e -> (eth_adapter) s_cpu ->
|
||||||
//// (ARM_DEFRAMER)(IF ARM)
|
//// (ARM_DEFRAMER)(IF ARM)
|
||||||
@@ -522,7 +549,7 @@ module eth_ifc_tb #(
|
|||||||
.ramp_inc(1),.pkt(pay),.SWIDTH(8));
|
.ramp_inc(1),.pkt(pay),.SWIDTH(8));
|
||||||
sample_sum += num_samples[i];
|
sample_sum += num_samples[i];
|
||||||
udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay,
|
udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay,
|
||||||
.preamble(NO_PREAMBLE));
|
.preamble(CPU_PREAMBLE ? preamble : NO_PREAMBLE));
|
||||||
send[i].push_bytes(udp_raw);
|
send[i].push_bytes(udp_raw);
|
||||||
send[i].tkeep_to_tuser();
|
send[i].tkeep_to_tuser();
|
||||||
|
|
||||||
@@ -564,9 +591,8 @@ module eth_ifc_tb #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
join
|
join
|
||||||
test_c2e.end_test();
|
|
||||||
|
|
||||||
endtask : test_cpueth
|
endtask : test_cpueth
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Ethernet to CHDR test
|
// Ethernet to CHDR test
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -604,12 +630,12 @@ module eth_ifc_tb #(
|
|||||||
endfunction : unflatten_chdr
|
endfunction : unflatten_chdr
|
||||||
|
|
||||||
task automatic test_ethchdr(int num_samples[$], int ERROR_PROB=2, int EXPECT_DROPS=0);
|
task automatic test_ethchdr(int num_samples[$], int ERROR_PROB=2, int EXPECT_DROPS=0);
|
||||||
TestExec test_e2v = new();
|
|
||||||
automatic EthXportPacket_t send[$];
|
automatic EthXportPacket_t send[$];
|
||||||
automatic ChdrXportPacket_t expected[$];
|
automatic ChdrXportPacket_t expected[$];
|
||||||
automatic int sample_sum = 0;
|
automatic int sample_sum = 0;
|
||||||
|
|
||||||
test_e2v.start_test({TEST_NAME,"::Ethernet to CHDR"}, 60us);
|
$display("%s::Ethernet to CHDR", TEST_NAME);
|
||||||
|
|
||||||
// This path is
|
// This path is
|
||||||
// eth_rx -> s_mac(eth_adapter) -> s_mac(eth_dispatch) ->
|
// eth_rx -> s_mac(eth_adapter) -> s_mac(eth_dispatch) ->
|
||||||
//// in_reg(AXI_FIFO)(SIZE=1)
|
//// in_reg(AXI_FIFO)(SIZE=1)
|
||||||
@@ -715,17 +741,17 @@ module eth_ifc_tb #(
|
|||||||
void'(expected.pop_front());
|
void'(expected.pop_front());
|
||||||
++drop_count;
|
++drop_count;
|
||||||
++pkt_num;
|
++pkt_num;
|
||||||
$display("Dropped packet %d",pkt_num);
|
$display("Dropped packet: %d",pkt_num);
|
||||||
`ASSERT_ERROR(drop_count < EXPECT_DROPS,"Exceeded anticipated number of dropped packets e2v");
|
`ASSERT_ERROR(drop_count < EXPECT_DROPS,"Exceeded anticipated number of dropped packets e2v");
|
||||||
end
|
end
|
||||||
if (expected.size() > 0) begin
|
if (expected.size() > 0) begin
|
||||||
++pkt_num;
|
++pkt_num;
|
||||||
$display("Rcvd packet %d",pkt_num);
|
$display("Received packet: %d",pkt_num);
|
||||||
void'(expected.pop_front());
|
void'(expected.pop_front());
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (SV_ETH_IFC) begin
|
if (SV_ETH_IFC) begin
|
||||||
$display("Verify drop count is %d",drop_count);
|
$display("Drop count: %d",drop_count);
|
||||||
reg_rd_check(REG_CHDR_DROPPED,drop_count);
|
reg_rd_check(REG_CHDR_DROPPED,drop_count);
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
@@ -740,17 +766,14 @@ module eth_ifc_tb #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
join
|
join
|
||||||
test_e2v.end_test();
|
|
||||||
|
|
||||||
endtask : test_ethchdr;
|
endtask : test_ethchdr;
|
||||||
|
|
||||||
task automatic test_chdreth(int num_samples[$]);
|
task automatic test_chdreth(int num_samples[$]);
|
||||||
TestExec test_v2e = new();
|
|
||||||
automatic ChdrXportPacket_t send[$];
|
automatic ChdrXportPacket_t send[$];
|
||||||
automatic EthXportPacket_t expected[$];
|
automatic EthXportPacket_t expected[$];
|
||||||
automatic int sample_sum = 0;
|
automatic int sample_sum = 0;
|
||||||
|
|
||||||
test_v2e.start_test({TEST_NAME,"::CHDR to Ethernet"}, 60us);
|
$display("%s::CHDR to Ethernet", TEST_NAME);
|
||||||
// This path is
|
// This path is
|
||||||
// v2e -> s_chdr(eth_adapter) -> s_axis_rfnoc (xport_adapter_gen) ->
|
// v2e -> s_chdr(eth_adapter) -> s_axis_rfnoc (xport_adapter_gen) ->
|
||||||
//// axi_demux_mgmt_filter (AXI_DEMUX) (IF ALLOW_DISC) (discards discovery packets)
|
//// axi_demux_mgmt_filter (AXI_DEMUX) (IF ALLOW_DISC) (discards discovery packets)
|
||||||
@@ -877,8 +900,6 @@ module eth_ifc_tb #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
join
|
join
|
||||||
test_v2e.end_test();
|
|
||||||
|
|
||||||
endtask : test_chdreth
|
endtask : test_chdreth
|
||||||
|
|
||||||
integer cached_mgmt_seqnum = 0;
|
integer cached_mgmt_seqnum = 0;
|
||||||
@@ -887,7 +908,6 @@ module eth_ifc_tb #(
|
|||||||
`include "../../core/rfnoc_chdr_internal_utils.vh"
|
`include "../../core/rfnoc_chdr_internal_utils.vh"
|
||||||
`include "../../xport/rfnoc_xport_types.vh"
|
`include "../../xport/rfnoc_xport_types.vh"
|
||||||
task automatic test_chdr_endpoint();
|
task automatic test_chdr_endpoint();
|
||||||
TestExec test_e2v = new();
|
|
||||||
automatic EthXportPacket_t send[$];
|
automatic EthXportPacket_t send[$];
|
||||||
automatic EthXportPacket_t expected[$];
|
automatic EthXportPacket_t expected[$];
|
||||||
automatic int sample_sum = 0;
|
automatic int sample_sum = 0;
|
||||||
@@ -909,8 +929,7 @@ module eth_ifc_tb #(
|
|||||||
automatic int preamble;
|
automatic int preamble;
|
||||||
localparam NODE_INST=0;
|
localparam NODE_INST=0;
|
||||||
|
|
||||||
test_e2v.start_test({TEST_NAME,"::ChdrEndpoint"}, 60us);
|
test.start_test({TEST_NAME,"::ChdrEndpoint"}, 60us);
|
||||||
|
|
||||||
|
|
||||||
expected[0] = new;
|
expected[0] = new;
|
||||||
send[0] = new;
|
send[0] = new;
|
||||||
@@ -1030,170 +1049,175 @@ module eth_ifc_tb #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
join
|
join
|
||||||
test_e2v.end_test();
|
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
endtask : test_chdr_endpoint
|
endtask : test_chdr_endpoint
|
||||||
|
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
// Main test loop
|
// Main test loop
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
initial begin : tb_main
|
initial begin : tb_main
|
||||||
automatic int num_samples[$];
|
automatic int num_samples[$];
|
||||||
automatic int cpu_num_samples[$];
|
automatic int cpu_num_samples[$];
|
||||||
automatic int expected_drops;
|
automatic int expected_drops;
|
||||||
localparam QUICK = 0;
|
localparam QUICK = 0;
|
||||||
|
|
||||||
test.start_tb(TEST_NAME);
|
test.start_tb(TEST_NAME);
|
||||||
|
|
||||||
test.start_test({TEST_NAME,"::Wait for Reset"}, 10us);
|
// Check some parameters
|
||||||
clk_gen.start();
|
if (!SV_ETH_IFC) begin
|
||||||
eth_clk_gen.start();
|
`ASSERT_FATAL(CHDR_W == 64, "Legacy transport adapter only supports 64-bit CHDR");
|
||||||
clk_gen.reset();
|
`ASSERT_FATAL(CPU_PREAMBLE == 0, "CPU preamble is not supported on legacy transport adapter");
|
||||||
eth_clk_gen.reset();
|
end
|
||||||
|
|
||||||
eth.run();
|
clk_gen.start();
|
||||||
cpu.run();
|
eth_clk_gen.start();
|
||||||
v.run();
|
clk_gen.reset();
|
||||||
|
eth_clk_gen.reset();
|
||||||
|
|
||||||
|
eth.run();
|
||||||
|
cpu.run();
|
||||||
|
v.run();
|
||||||
|
|
||||||
test_reset();
|
test_reset();
|
||||||
test_registers();
|
test_registers();
|
||||||
|
test_chdr_endpoint();
|
||||||
|
|
||||||
test_chdr_endpoint();
|
// Check what happens if the input bandwidth exceeds
|
||||||
|
// the devices ability to consume packets
|
||||||
|
// This can happen in matched bandwidth cases
|
||||||
|
// if there is hold off from upstream
|
||||||
|
// Dropped packets exceed the drop count cause an error
|
||||||
|
// The actual dropped count is compared versus the real count
|
||||||
|
test.start_test({TEST_NAME,"::Input overrun"}, 200us);
|
||||||
|
|
||||||
// Check what happens if the input bandwidth exceeds
|
eth.set_master_stall_prob(0);
|
||||||
// the devices ability to consume packets
|
eth.set_slave_stall_prob(0);
|
||||||
// This can happen in matched bandwidth cases
|
cpu.set_master_stall_prob(0);
|
||||||
// if there is hold off from upstream
|
cpu.set_slave_stall_prob(0);
|
||||||
// Dropped packets exceed the drop count cause an error
|
v.set_master_stall_prob(0);
|
||||||
// The actual dropped count is compared versus the real count
|
v.set_slave_stall_prob(0);
|
||||||
test.start_test({TEST_NAME,"::Input overrun"}, 200us);
|
|
||||||
|
|
||||||
eth.set_master_stall_prob(0);
|
num_samples = {7936,7936,7936,7936,7936,320,
|
||||||
eth.set_slave_stall_prob(0);
|
7936,7936,7936,7936,7936,320};
|
||||||
cpu.set_master_stall_prob(0);
|
|
||||||
cpu.set_slave_stall_prob(0);
|
|
||||||
v.set_master_stall_prob(0);
|
|
||||||
v.set_slave_stall_prob(0);
|
|
||||||
|
|
||||||
num_samples = {7936,7936,7936,7936,7936,320,
|
// The actual number of expected drops depends on the
|
||||||
7936,7936,7936,7936,7936,320};
|
// bus width difference between ENET_W and CHDR/CPU_W
|
||||||
|
|
||||||
// The actual number of expected drops depends on the
|
// in this SIM unlimited Ethernet bandwidth is coming in at over 300 MHZ
|
||||||
// bus width difference between ENET_W and CHDR/CPU_W
|
// and output runs at 200 MHZ. This causes excess BW on transmitter even when matched.
|
||||||
|
expected_drops = 9;
|
||||||
|
|
||||||
// in this SIM unlimited Ethernet bandwidth is coming in at over 300 MHZ
|
test_ethchdr(num_samples,.EXPECT_DROPS(expected_drops),.ERROR_PROB(0));
|
||||||
// and output runs at 200 MHZ. This causes excess BW on transmitter even when matched.
|
test_ethcpu(num_samples,.EXPECT_DROPS(expected_drops),.ERROR_PROB(0));
|
||||||
expected_drops = 9;
|
|
||||||
|
|
||||||
test_ethchdr(num_samples,.EXPECT_DROPS(expected_drops),.ERROR_PROB(0));
|
test.end_test();
|
||||||
test_ethcpu(num_samples,.EXPECT_DROPS(expected_drops),.ERROR_PROB(0));
|
|
||||||
test.end_test();
|
|
||||||
|
|
||||||
eth.set_master_stall_prob(38);
|
eth.set_master_stall_prob(38);
|
||||||
eth.set_slave_stall_prob(38);
|
eth.set_slave_stall_prob(38);
|
||||||
cpu.set_master_stall_prob(38);
|
cpu.set_master_stall_prob(38);
|
||||||
cpu.set_slave_stall_prob(38);
|
cpu.set_slave_stall_prob(38);
|
||||||
v.set_master_stall_prob(38);
|
v.set_master_stall_prob(38);
|
||||||
v.set_slave_stall_prob(38);
|
v.set_slave_stall_prob(38);
|
||||||
|
|
||||||
num_samples = {1,2,3,4,5,6,7,8,
|
num_samples = {1,2,3,4,5,6,7,8,
|
||||||
ENET_W/8-1,ENET_W/8,ENET_W/8+1,
|
ENET_W/8-1,ENET_W/8,ENET_W/8+1,
|
||||||
2*ENET_W/8-1,2*ENET_W/8,2*ENET_W/8+1,
|
2*ENET_W/8-1,2*ENET_W/8,2*ENET_W/8+1,
|
||||||
CPU_W/8-1,CPU_W/8,CPU_W/8+1,
|
CPU_W/8-1,CPU_W/8,CPU_W/8+1,
|
||||||
2*CPU_W/8-1,2*CPU_W/8,2*CPU_W/8+1,
|
2*CPU_W/8-1,2*CPU_W/8,2*CPU_W/8+1,
|
||||||
CHDR_W/8-1,CHDR_W/8,CHDR_W/8+1,
|
CHDR_W/8-1,CHDR_W/8,CHDR_W/8+1,
|
||||||
2*CHDR_W/8-1,2*CHDR_W/8,2*CHDR_W/8+1
|
2*CHDR_W/8-1,2*CHDR_W/8,2*CHDR_W/8+1
|
||||||
};
|
};
|
||||||
// add some extra samples for CPU packets to try to get above the min
|
// Add some extra samples for CPU packets to try to get above the min
|
||||||
//packet size of 64. (just the headers makes up 42 bytes)
|
// packet size of 64 (just the headers make up 42 bytes). This way we still
|
||||||
//this way we still have some short packets to drop, but not as many.
|
// have some short packets to drop, but not as many.
|
||||||
foreach (num_samples[i]) cpu_num_samples[i] = num_samples[i]+20;
|
foreach (num_samples[i]) cpu_num_samples[i] = num_samples[i]+20;
|
||||||
test.start_test({TEST_NAME,"::PacketW Combos NO Errors"}, 10us);
|
test.start_test({TEST_NAME,"::PacketW Combos NO Errors"}, 10us);
|
||||||
fork // run in parallel
|
fork // run in parallel
|
||||||
// ethrx
|
// ethrx
|
||||||
test_ethcpu(cpu_num_samples,.ERROR_PROB(0));
|
test_ethcpu(cpu_num_samples,.ERROR_PROB(0));
|
||||||
test_ethchdr(num_samples,.ERROR_PROB(0));
|
test_ethchdr(num_samples,.ERROR_PROB(0));
|
||||||
// ethtx
|
// ethtx
|
||||||
test_chdreth(num_samples);
|
test_chdreth(num_samples);
|
||||||
test_cpueth(num_samples);
|
test_cpueth(num_samples);
|
||||||
join
|
|
||||||
test.end_test();
|
|
||||||
|
|
||||||
if (!QUICK) begin
|
|
||||||
|
|
||||||
test.start_test({TEST_NAME,"::PacketW Combos Errors"}, 10us);
|
|
||||||
fork // run in parallel
|
|
||||||
// ethrx
|
|
||||||
test_ethcpu(cpu_num_samples,.ERROR_PROB(2));
|
|
||||||
test_ethchdr(num_samples,.ERROR_PROB(2));
|
|
||||||
// ethtx
|
|
||||||
test_chdreth(num_samples);
|
|
||||||
test_cpueth(num_samples);
|
|
||||||
join
|
|
||||||
test.end_test();
|
|
||||||
|
|
||||||
num_samples = {16,32,64,128,256,512,1024,1500,1522,9000};
|
|
||||||
test.start_test({TEST_NAME,"::Pwr2 NoErrors"}, 60us);
|
|
||||||
fork // run in parallel
|
|
||||||
// ethrx
|
|
||||||
test_ethcpu(cpu_num_samples,.ERROR_PROB(0));
|
|
||||||
test_ethchdr(num_samples,.ERROR_PROB(0));
|
|
||||||
// ethtx
|
|
||||||
test_chdreth(num_samples);
|
|
||||||
test_cpueth(num_samples);
|
|
||||||
join
|
join
|
||||||
test.end_test();
|
test.end_test();
|
||||||
end
|
|
||||||
|
|
||||||
eth.set_master_stall_prob(0);
|
if (!QUICK) begin
|
||||||
eth.set_slave_stall_prob(0);
|
|
||||||
cpu.set_master_stall_prob(0);
|
|
||||||
cpu.set_slave_stall_prob(0);
|
|
||||||
v.set_master_stall_prob(0);
|
|
||||||
v.set_slave_stall_prob(0);
|
|
||||||
|
|
||||||
num_samples = {1,2,3,4,5,6,7,8,
|
test.start_test({TEST_NAME,"::PacketW Combos Errors"}, 10us);
|
||||||
ENET_W/8-1,ENET_W/8,ENET_W/8+1,
|
fork // run in parallel
|
||||||
2*ENET_W/8-1,2*ENET_W/8,2*ENET_W/8+1,
|
// ethrx
|
||||||
CPU_W/8-1,CPU_W/8,CPU_W/8+1,
|
test_ethcpu(cpu_num_samples,.ERROR_PROB(2));
|
||||||
2*CPU_W/8-1,2*CPU_W/8,2*CPU_W/8+1,
|
test_ethchdr(num_samples,.ERROR_PROB(2));
|
||||||
CHDR_W/8-1,CHDR_W/8,CHDR_W/8+1,
|
// ethtx
|
||||||
2*CHDR_W/8-1,2*CHDR_W/8,2*CHDR_W/8+1
|
test_chdreth(num_samples);
|
||||||
};
|
test_cpueth(num_samples);
|
||||||
test.start_test({TEST_NAME,"::Pktw NoStall+Error"}, 10us);
|
join
|
||||||
fork // run in parallel
|
test.end_test();
|
||||||
// ethrx
|
|
||||||
test_ethcpu(cpu_num_samples,.ERROR_PROB(2));
|
|
||||||
test_ethchdr(num_samples,.ERROR_PROB(2));
|
|
||||||
// ethtx
|
|
||||||
test_chdreth(num_samples);
|
|
||||||
test_cpueth(num_samples);
|
|
||||||
join
|
|
||||||
test.end_test();
|
|
||||||
|
|
||||||
// repeat with back to back cpu/chdr packets
|
num_samples = {16,32,64,128,256,512,1024,1500,1522,9000};
|
||||||
test.start_test({TEST_NAME,"::Serial Pktw NoStall+Error"}, 10us);
|
test.start_test({TEST_NAME,"::Pwr2 NoErrors"}, 60us);
|
||||||
fork // run in parallel
|
fork // run in parallel
|
||||||
// ethrx
|
// ethrx
|
||||||
begin
|
test_ethcpu(cpu_num_samples,.ERROR_PROB(0));
|
||||||
test_ethcpu(cpu_num_samples,.ERROR_PROB(2));
|
test_ethchdr(num_samples,.ERROR_PROB(0));
|
||||||
test_ethchdr(num_samples,.ERROR_PROB(2));
|
// ethtx
|
||||||
end
|
test_chdreth(num_samples);
|
||||||
// ethtx
|
test_cpueth(num_samples);
|
||||||
begin
|
join
|
||||||
test_chdreth(num_samples);
|
test.end_test();
|
||||||
test_cpueth(num_samples);
|
end
|
||||||
end
|
|
||||||
join
|
|
||||||
test.end_test();
|
|
||||||
|
|
||||||
// End the TB, but don't $finish, since we don't want to kill other
|
eth.set_master_stall_prob(0);
|
||||||
// instances of this testbench that may be running.
|
eth.set_slave_stall_prob(0);
|
||||||
test.end_tb(0);
|
cpu.set_master_stall_prob(0);
|
||||||
|
cpu.set_slave_stall_prob(0);
|
||||||
|
v.set_master_stall_prob(0);
|
||||||
|
v.set_slave_stall_prob(0);
|
||||||
|
|
||||||
// Kill the clocks to end this instance of the testbench
|
num_samples = {1,2,3,4,5,6,7,8,
|
||||||
clk_gen.kill();
|
ENET_W/8-1,ENET_W/8,ENET_W/8+1,
|
||||||
eth_clk_gen.kill();
|
2*ENET_W/8-1,2*ENET_W/8,2*ENET_W/8+1,
|
||||||
|
CPU_W/8-1,CPU_W/8,CPU_W/8+1,
|
||||||
|
2*CPU_W/8-1,2*CPU_W/8,2*CPU_W/8+1,
|
||||||
|
CHDR_W/8-1,CHDR_W/8,CHDR_W/8+1,
|
||||||
|
2*CHDR_W/8-1,2*CHDR_W/8,2*CHDR_W/8+1
|
||||||
|
};
|
||||||
|
test.start_test({TEST_NAME,"::Pktw NoStall+Error"}, 10us);
|
||||||
|
fork // run in parallel
|
||||||
|
// ethrx
|
||||||
|
test_ethcpu(cpu_num_samples,.ERROR_PROB(2));
|
||||||
|
test_ethchdr(num_samples,.ERROR_PROB(2));
|
||||||
|
// ethtx
|
||||||
|
test_chdreth(num_samples);
|
||||||
|
test_cpueth(num_samples);
|
||||||
|
join
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
|
// repeat with back to back cpu/chdr packets
|
||||||
|
test.start_test({TEST_NAME,"::Serial Pktw NoStall+Error"}, 10us);
|
||||||
|
fork // run in parallel
|
||||||
|
// ethrx
|
||||||
|
begin
|
||||||
|
test_ethcpu(cpu_num_samples,.ERROR_PROB(2));
|
||||||
|
test_ethchdr(num_samples,.ERROR_PROB(2));
|
||||||
|
end
|
||||||
|
// ethtx
|
||||||
|
begin
|
||||||
|
test_chdreth(num_samples);
|
||||||
|
test_cpueth(num_samples);
|
||||||
|
end
|
||||||
|
join
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
|
// End the TB, but don't $finish, since we don't want to kill other
|
||||||
|
// instances of this testbench that may be running.
|
||||||
|
test.end_tb(0);
|
||||||
|
|
||||||
|
// Kill the clocks to end this instance of the testbench
|
||||||
|
clk_gen.kill();
|
||||||
|
eth_clk_gen.kill();
|
||||||
end // initial begin
|
end // initial begin
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -42,7 +42,10 @@
|
|||||||
// NODE_INST : The node type to return for a node-info discovery
|
// NODE_INST : The node type to return for a node-info discovery
|
||||||
// DROP_UNKNOWN_MAC : Drop packets not addressed to us?
|
// DROP_UNKNOWN_MAC : Drop packets not addressed to us?
|
||||||
// DROP_MIN_PACKET : Drop packets smaller than 64 bytes?
|
// DROP_MIN_PACKET : Drop packets smaller than 64 bytes?
|
||||||
// PREAMBLE_BYTES : Number of bytes of Preamble expected
|
// PREAMBLE_BYTES : Number of bytes of preamble on Ethernet interface
|
||||||
|
// CPU_PREAMBLE : Set to 1 to use PREAMBLE_BYTES on CPU interface
|
||||||
|
// (for ZPU) or set to 0 to remove preamble on CPU
|
||||||
|
// interface (for ARM CPU).
|
||||||
// ADD_SOF : Add a SOF indication into the tuser field of the e2c
|
// ADD_SOF : Add a SOF indication into the tuser field of the e2c
|
||||||
// path. If false use TKEEP instead of USER.
|
// path. If false use TKEEP instead of USER.
|
||||||
// SYNC : Set to 1 if the c2e/e2c, v2e/e2v, and eth_rx/eth_tx are
|
// SYNC : Set to 1 if the c2e/e2c, v2e/e2v, and eth_rx/eth_tx are
|
||||||
@@ -80,6 +83,7 @@ module eth_ipv4_chdr_adapter #(
|
|||||||
bit DROP_UNKNOWN_MAC = 0,
|
bit DROP_UNKNOWN_MAC = 0,
|
||||||
bit DROP_MIN_PACKET = 0,
|
bit DROP_MIN_PACKET = 0,
|
||||||
int PREAMBLE_BYTES = 6,
|
int PREAMBLE_BYTES = 6,
|
||||||
|
bit CPU_PREAMBLE = 0,
|
||||||
bit ADD_SOF = 1,
|
bit ADD_SOF = 1,
|
||||||
bit SYNC = 0,
|
bit SYNC = 0,
|
||||||
int ENET_W = 64,
|
int ENET_W = 64,
|
||||||
@@ -180,11 +184,12 @@ module eth_ipv4_chdr_adapter #(
|
|||||||
.CPU_FIFO_SIZE (CPU_FIFO_SIZE),
|
.CPU_FIFO_SIZE (CPU_FIFO_SIZE),
|
||||||
.CHDR_FIFO_SIZE (CHDR_FIFO_SIZE),
|
.CHDR_FIFO_SIZE (CHDR_FIFO_SIZE),
|
||||||
.PREAMBLE_BYTES (PREAMBLE_BYTES),
|
.PREAMBLE_BYTES (PREAMBLE_BYTES),
|
||||||
|
.CPU_PREAMBLE (CPU_PREAMBLE),
|
||||||
.MAX_PACKET_BYTES (MAX_PACKET_BYTES),
|
.MAX_PACKET_BYTES (MAX_PACKET_BYTES),
|
||||||
.DROP_UNKNOWN_MAC (DROP_UNKNOWN_MAC),
|
.DROP_UNKNOWN_MAC (DROP_UNKNOWN_MAC),
|
||||||
.DROP_MIN_PACKET (DROP_MIN_PACKET),
|
.DROP_MIN_PACKET (DROP_MIN_PACKET),
|
||||||
.ENET_W (ENET_W)
|
.ENET_W (ENET_W)
|
||||||
) eth_dispatch_i (
|
) eth_ipv4_chdr_dispatch_i (
|
||||||
.eth_pause_req (eth_pause_req),
|
.eth_pause_req (eth_pause_req),
|
||||||
.eth_rx (eth_rx1),
|
.eth_rx (eth_rx1),
|
||||||
.e2v (e2v1),
|
.e2v (e2v1),
|
||||||
@@ -379,17 +384,17 @@ module eth_ipv4_chdr_adapter #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (PREAMBLE_BYTES > 0) begin : gen_add_preamble
|
if (PREAMBLE_BYTES > 0 && !CPU_PREAMBLE) begin : gen_c2e_add_preamble
|
||||||
// Add pad of PREAMBLE_BYTES empty bytes to the ethernet packet going
|
// Add pad of PREAMBLE_BYTES empty bytes to the ethernet packet going
|
||||||
// from the CPU to the SFP. This padding added before MAC addresses
|
// from the CPU to the SFP. This padding added before MAC addresses
|
||||||
// aligns the source and destination IP addresses, UDP headers etc.
|
// aligns the source and destination IP addresses, UDP headers etc.
|
||||||
// Note that the xge_mac_wrapper strips this padding to recreate the
|
// Note that the xge_mac_wrapper strips this padding to recreate the
|
||||||
// ethernet packet.
|
// ethernet packet.
|
||||||
axi4s_add_bytes #(.ADD_START(0),.ADD_BYTES(PREAMBLE_BYTES)
|
axi4s_add_bytes #(.ADD_START(0),.ADD_BYTES(PREAMBLE_BYTES)
|
||||||
) add_header (
|
) axi4s_add_bytes_c2e (
|
||||||
.i(c2e1), .o(c2e2)
|
.i(c2e1), .o(c2e2)
|
||||||
);
|
);
|
||||||
end else begin : gen_no_preamble
|
end else begin : gen_c2e_no_preamble
|
||||||
always_comb begin : c2e2_assign
|
always_comb begin : c2e2_assign
|
||||||
`AXI4S_ASSIGN(c2e2,c2e1)
|
`AXI4S_ASSIGN(c2e2,c2e1)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,7 +19,10 @@
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// - CPU_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CPU egress path
|
// - CPU_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CPU egress path
|
||||||
// - CHDR_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CHDR egress path
|
// - CHDR_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CHDR egress path
|
||||||
// - PREAMBLE_BYTES: Number of bytes in the Preamble
|
// - PREAMBLE_BYTES: Number of bytes of preamble on Ethernet interface
|
||||||
|
// - CPU_PREAMBLE: Set to 1 to use PREAMBLE_BYTES on CPU interface (for ZPU)
|
||||||
|
// or set to 0 to remove preamble on CPU interface (for ARM
|
||||||
|
// CPU).
|
||||||
// - DROP_UNKNOWN_MAC: Drop packets not addressed to us?
|
// - DROP_UNKNOWN_MAC: Drop packets not addressed to us?
|
||||||
// - DROP_MIN_PACKET: Drop packets smaller than 64 bytes?
|
// - DROP_MIN_PACKET: Drop packets smaller than 64 bytes?
|
||||||
// - ENET_W: Width of AXI bus going to Ethernet Mac
|
// - ENET_W: Width of AXI bus going to Ethernet Mac
|
||||||
@@ -42,6 +45,7 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
int CPU_FIFO_SIZE = $clog2(8*1024),
|
int CPU_FIFO_SIZE = $clog2(8*1024),
|
||||||
int CHDR_FIFO_SIZE = $clog2(8*1024),
|
int CHDR_FIFO_SIZE = $clog2(8*1024),
|
||||||
int PREAMBLE_BYTES = 6,
|
int PREAMBLE_BYTES = 6,
|
||||||
|
int CPU_PREAMBLE = 0,
|
||||||
int MAX_PACKET_BYTES = 2**16-1,
|
int MAX_PACKET_BYTES = 2**16-1,
|
||||||
bit DROP_UNKNOWN_MAC = 0,
|
bit DROP_UNKNOWN_MAC = 0,
|
||||||
bit DROP_MIN_PACKET = 0,
|
bit DROP_MIN_PACKET = 0,
|
||||||
@@ -133,14 +137,17 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
// tUser = {not used};
|
// tUser = {not used};
|
||||||
AxiStreamIf #(.DATA_WIDTH(ENET_W),.TKEEP(0),.TUSER(0))
|
AxiStreamIf #(.DATA_WIDTH(ENET_W),.TKEEP(0),.TUSER(0))
|
||||||
chdr1(eth_rx.clk,eth_rx.rst);
|
chdr1(eth_rx.clk,eth_rx.rst);
|
||||||
|
// tUser = {not used};
|
||||||
|
AxiStreamIf #(.DATA_WIDTH(ENET_W),.TKEEP(0),.TUSER(0),.MAX_PACKET_BYTES(MAX_PACKET_BYTES))
|
||||||
|
chdr2(eth_rx.clk,eth_rx.rst);
|
||||||
// chdr_out_fifo
|
// chdr_out_fifo
|
||||||
// e2v(OUTPUT)
|
// e2v(OUTPUT)
|
||||||
|
|
||||||
//---------------------------------------
|
//---------------------------------------
|
||||||
// Strip Bytes
|
// Strip Preamble Bytes
|
||||||
//---------------------------------------
|
//---------------------------------------
|
||||||
if (PREAMBLE_BYTES > 0) begin : gen_strip_preamble
|
if (PREAMBLE_BYTES > 0 && !CPU_PREAMBLE) begin : gen_strip_preamble
|
||||||
// Strip the preamble
|
// Keep the preamble since the CPU expects it.
|
||||||
always_comb begin
|
always_comb begin
|
||||||
`AXI4S_ASSIGN(inp,eth_rx);
|
`AXI4S_ASSIGN(inp,eth_rx);
|
||||||
end
|
end
|
||||||
@@ -148,7 +155,8 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
) strip_preamble (
|
) strip_preamble (
|
||||||
.i(inp),.o(in0)
|
.i(inp),.o(in0)
|
||||||
);
|
);
|
||||||
end else begin : gen_no_preamble
|
end else begin : gen_no_strip_preamble
|
||||||
|
// Remove the preamble since CHDR and CPU don't expect it.
|
||||||
always_comb begin
|
always_comb begin
|
||||||
`AXI4S_ASSIGN(in0,eth_rx);
|
`AXI4S_ASSIGN(in0,eth_rx);
|
||||||
end
|
end
|
||||||
@@ -220,12 +228,12 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
reached_min_packet_old <= 1'b0;
|
reached_min_packet_old <= 1'b0;
|
||||||
|
|
||||||
// Statemachine Decisions
|
// Statemachine Decisions
|
||||||
eth_dst_is_broadcast <=1'b0;
|
eth_dst_is_broadcast <= 1'b0;
|
||||||
eth_dst_is_me <=1'b0;
|
eth_dst_is_me <= 1'b0;
|
||||||
udp_dst_is_me <=1'b0;
|
udp_dst_is_me <= 1'b0;
|
||||||
ipv4_dst_is_me <=1'b0;
|
ipv4_dst_is_me <= 1'b0;
|
||||||
ipv4_protocol_is_udp <=1'b0;
|
ipv4_protocol_is_udp <= 1'b0;
|
||||||
eth_type_is_ipv4 <=1'b0;
|
eth_type_is_ipv4 <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
eth_dst_addr_old <= eth_dst_addr_new;
|
eth_dst_addr_old <= eth_dst_addr_new;
|
||||||
eth_src_addr_old <= eth_src_addr_new;
|
eth_src_addr_old <= eth_src_addr_new;
|
||||||
@@ -248,22 +256,24 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// get the fields - don't use assign. assign will not activate with changes to in0.
|
// Get the fields - don't use assign. assign will not activate with changes
|
||||||
|
// to in0.
|
||||||
|
localparam int OFFSET = CPU_PREAMBLE ? PREAMBLE_BYTES : 0;
|
||||||
always_comb begin : get_fields
|
always_comb begin : get_fields
|
||||||
eth_dst_addr_new = in0.get_packet_field48(eth_dst_addr_old,DST_MAC_BYTE,.NETWORK_ORDER(1));
|
eth_dst_addr_new = in0.get_packet_field48(eth_dst_addr_old, OFFSET+DST_MAC_BYTE, .NETWORK_ORDER(1));
|
||||||
eth_src_addr_new = in0.get_packet_field48(eth_src_addr_old,SRC_MAC_BYTE,.NETWORK_ORDER(1));
|
eth_src_addr_new = in0.get_packet_field48(eth_src_addr_old, OFFSET+SRC_MAC_BYTE, .NETWORK_ORDER(1));
|
||||||
ip_version_new = in0.get_packet_byte(ip_version_old,IP_VERSION_BYTE);
|
ip_version_new = in0.get_packet_byte (ip_version_old, OFFSET+IP_VERSION_BYTE);
|
||||||
ip_protocol_new = in0.get_packet_byte(ip_protocol_old,PROTOCOL_BYTE);
|
ip_protocol_new = in0.get_packet_byte (ip_protocol_old, OFFSET+PROTOCOL_BYTE );
|
||||||
ipv4_src_addr_new = in0.get_packet_field32(ipv4_src_addr_old,SRC_IP_BYTE,.NETWORK_ORDER(1));
|
ipv4_src_addr_new = in0.get_packet_field32(ipv4_src_addr_old, OFFSET+SRC_IP_BYTE, .NETWORK_ORDER(1));
|
||||||
ipv4_dst_addr_new = in0.get_packet_field32(ipv4_dst_addr_old,DST_IP_BYTE,.NETWORK_ORDER(1));
|
ipv4_dst_addr_new = in0.get_packet_field32(ipv4_dst_addr_old, OFFSET+DST_IP_BYTE, .NETWORK_ORDER(1));
|
||||||
udp_src_port_new = in0.get_packet_field16(udp_src_port_old,SRC_PORT_BYTE,.NETWORK_ORDER(1));
|
udp_src_port_new = in0.get_packet_field16(udp_src_port_old, OFFSET+SRC_PORT_BYTE, .NETWORK_ORDER(1));
|
||||||
udp_dst_port_new = in0.get_packet_field16(udp_dst_port_old,DST_PORT_BYTE,.NETWORK_ORDER(1));
|
udp_dst_port_new = in0.get_packet_field16(udp_dst_port_old, OFFSET+DST_PORT_BYTE, .NETWORK_ORDER(1));
|
||||||
eth_type_new = in0.get_packet_field16(eth_type_old,ETH_TYPE_BYTE,.NETWORK_ORDER(1));
|
eth_type_new = in0.get_packet_field16(eth_type_old, OFFSET+ETH_TYPE_BYTE, .NETWORK_ORDER(1));
|
||||||
end
|
end
|
||||||
|
|
||||||
always_comb begin : reached_bytes
|
always_comb begin : reached_bytes
|
||||||
reached_min_packet_new = in1.reached_packet_byte(MIN_PACKET_SIZE_BYTE);
|
reached_min_packet_new = in1.reached_packet_byte(OFFSET+MIN_PACKET_SIZE_BYTE);
|
||||||
reached_end_of_udp = in1.reached_packet_byte(DST_PORT_BYTE+3);// we have enough to decide
|
reached_end_of_udp = in1.reached_packet_byte(OFFSET+DST_PORT_BYTE+3);// we have enough to decide
|
||||||
end
|
end
|
||||||
|
|
||||||
// calculate error conditions
|
// calculate error conditions
|
||||||
@@ -498,7 +508,7 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
.i(cpu0),.o(cpu1)
|
.i(cpu0),.o(cpu1)
|
||||||
);
|
);
|
||||||
|
|
||||||
// The CPU can be slow to respond (relative to packet wirespeed) so
|
// The CPU can be slow to respond (relative to packet wire speed) so
|
||||||
// extra buffer for packets destined there so it doesn't back up.
|
// extra buffer for packets destined there so it doesn't back up.
|
||||||
axi4s_fifo #(
|
axi4s_fifo #(
|
||||||
.SIZE(CPU_FIFO_SIZE-$clog2(ENET_W/8))
|
.SIZE(CPU_FIFO_SIZE-$clog2(ENET_W/8))
|
||||||
@@ -521,9 +531,9 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// The transport should hook up to a crossbar downstream, which
|
// The transport should hook up to a crossbar downstream, which
|
||||||
// may backpressure this module because it is in the middle of
|
// may back-pressure this module because it is in the middle of
|
||||||
// transferring a packet. To ensure that upstream logic is not
|
// transferring a packet. To ensure that upstream logic is not
|
||||||
// blocked, we instantiate at laeast one packet of buffering here.
|
// blocked, we instantiate at least one packet of buffering here.
|
||||||
// The actual size is set by CHDR_FIFO_SIZE.
|
// The actual size is set by CHDR_FIFO_SIZE.
|
||||||
logic [15:0] chdr_occupied;
|
logic [15:0] chdr_occupied;
|
||||||
logic [15:0] chdr_occupied_q;
|
logic [15:0] chdr_occupied_q;
|
||||||
@@ -532,11 +542,25 @@ module eth_ipv4_chdr_dispatch #(
|
|||||||
.SIZE(CHDR_FIFO_WORD_SIZE)
|
.SIZE(CHDR_FIFO_WORD_SIZE)
|
||||||
) chdr_fifo_i (
|
) chdr_fifo_i (
|
||||||
.clear(1'b0),.space(),.occupied(chdr_occupied),
|
.clear(1'b0),.space(),.occupied(chdr_occupied),
|
||||||
.i(chdr1),.o(e2v)
|
.i(chdr1),.o(chdr2)
|
||||||
);
|
);
|
||||||
|
|
||||||
// documentation requires pause requests to be set for a minimum of 16 clocks.
|
// Remove the preamble on the CHDR path if it was not already removed.
|
||||||
// I'm providing the same gauranteed min time in the set and clear direction
|
if (PREAMBLE_BYTES > 0 && CPU_PREAMBLE) begin : gen_strip_chdr_preamble
|
||||||
|
axi4s_remove_bytes #(
|
||||||
|
.REM_START(0), .REM_END(PREAMBLE_BYTES-1)
|
||||||
|
) strip_preamble (
|
||||||
|
.i(chdr2), .o(e2v)
|
||||||
|
);
|
||||||
|
end else begin : gen_no_strip_chdr_preamble
|
||||||
|
always_comb begin
|
||||||
|
`AXI4S_ASSIGN(e2v, chdr2);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Documentation requires pause requests to be set for a minimum of 16
|
||||||
|
// clocks. I'm providing the same guaranteed min time in the set and clear
|
||||||
|
// direction.
|
||||||
logic [3:0] pause_timer;
|
logic [3:0] pause_timer;
|
||||||
typedef enum logic [1:0] {
|
typedef enum logic [1:0] {
|
||||||
ST_IDLE = 2'd0,
|
ST_IDLE = 2'd0,
|
||||||
|
|||||||
@@ -20,7 +20,10 @@
|
|||||||
// NODE_INST : The node type to return for a node-info discovery
|
// NODE_INST : The node type to return for a node-info discovery
|
||||||
// DROP_UNKNOWN_MAC : Drop packets not addressed to us?
|
// DROP_UNKNOWN_MAC : Drop packets not addressed to us?
|
||||||
// DROP_MIN_PACKET : Drop packets smaller than 64 bytes?
|
// DROP_MIN_PACKET : Drop packets smaller than 64 bytes?
|
||||||
// PREAMBLE_BYTES : Number of bytes of Preamble expected
|
// PREAMBLE_BYTES : Number of bytes of preamble on Ethernet interface
|
||||||
|
// CPU_PREAMBLE : Set to 1 to use PREAMBLE_BYTES on CPU interface
|
||||||
|
// (for ZPU) or set to 0 to remove preamble on CPU
|
||||||
|
// interface (for ARM CPU).
|
||||||
// ADD_SOF : Add a SOF indication into the tuser field of e2c
|
// ADD_SOF : Add a SOF indication into the tuser field of e2c
|
||||||
// SYNC : Set to 1 if the c2e/e2c, v2e/e2v, and eth_rx/eth_tx are
|
// SYNC : Set to 1 if the c2e/e2c, v2e/e2v, and eth_rx/eth_tx are
|
||||||
// synchronous to each other. Set to 0 to insert clock
|
// synchronous to each other. Set to 0 to insert clock
|
||||||
@@ -47,6 +50,7 @@ module eth_ipv4_interface #(
|
|||||||
bit DROP_UNKNOWN_MAC = 0,
|
bit DROP_UNKNOWN_MAC = 0,
|
||||||
bit DROP_MIN_PACKET = 0,
|
bit DROP_MIN_PACKET = 0,
|
||||||
int PREAMBLE_BYTES = 6,
|
int PREAMBLE_BYTES = 6,
|
||||||
|
bit CPU_PREAMBLE = 0,
|
||||||
bit ADD_SOF = 1,
|
bit ADD_SOF = 1,
|
||||||
bit SYNC = 0,
|
bit SYNC = 0,
|
||||||
bit PAUSE_EN = 0,
|
bit PAUSE_EN = 0,
|
||||||
@@ -351,6 +355,7 @@ module eth_ipv4_interface #(
|
|||||||
.DROP_UNKNOWN_MAC(DROP_UNKNOWN_MAC),
|
.DROP_UNKNOWN_MAC(DROP_UNKNOWN_MAC),
|
||||||
.DROP_MIN_PACKET (DROP_MIN_PACKET ),
|
.DROP_MIN_PACKET (DROP_MIN_PACKET ),
|
||||||
.PREAMBLE_BYTES (PREAMBLE_BYTES ),
|
.PREAMBLE_BYTES (PREAMBLE_BYTES ),
|
||||||
|
.CPU_PREAMBLE (CPU_PREAMBLE ),
|
||||||
.ADD_SOF (ADD_SOF ),
|
.ADD_SOF (ADD_SOF ),
|
||||||
.SYNC (SYNC ),
|
.SYNC (SYNC ),
|
||||||
.ENET_W (ENET_W ),
|
.ENET_W (ENET_W ),
|
||||||
|
|||||||
Reference in New Issue
Block a user