diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/results.xml b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/results.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a2ecbf904618f1047b7b45846eaf316d8fb4ea8 --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/results.xml @@ -0,0 +1,6 @@ +<testsuites name="results"> + <testsuite name="all" package="all"> + <property name="random_seed" value="1650927471" /> + <testcase name="run_test" classname="test_fpga_core" file="/home/haiyang3/verilog-ethernet/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py" lineno="156" time="1.3866784572601318" sim_time_ns="4377.601" ratio_time="3156.8969555130184" /> + </testsuite> +</testsuites> diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/sim_build/cmds.f b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/sim_build/cmds.f new file mode 100644 index 0000000000000000000000000000000000000000..3e26e00a8b447d0e10f7930665bf0084d368f051 --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/sim_build/cmds.f @@ -0,0 +1 @@ ++timescale+1ns/1ps diff --git a/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v b/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v index da8329b276082e279038c7664d901314808f4b52..0f56f27c946fe29fa648bf64bd0f15c532240383 100644 --- a/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v +++ b/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v @@ -812,7 +812,28 @@ core_inst ( .qsfp_1_rx_clk_3(qsfp_1_rx_clk_3_int), .qsfp_1_rx_rst_3(qsfp_1_rx_rst_3_int), .qsfp_1_rxd_3(qsfp_1_rxd_3_int), - .qsfp_1_rxc_3(qsfp_1_rxc_3_int) + .qsfp_1_rxc_3(qsfp_1_rxc_3_int), + + // + .rx_payload_axis_tdata(), + .rx_udp_payload_axis_tkeep(), + .rx_udp_payload_axis_tvalid(), + .rx_udp_payload_axis_tready(1), + .rx_udp_payload_axis_tlast(), + + .tx_payload_axis_tdata(0), + .tx_udp_payload_axis_tkeep(0), + .tx_udp_payload_axis_tvalid(1), + .tx_udp_payload_axis_tready(), + .tx_udp_payload_axis_tlast(0), + + //network config + .local_mac(48'h02_00_00_00_00_00), + .local_ip({8'd192, 8'd168, 8'd1, 8'd128}) , + .gateway_ip({8'd192, 8'd168, 8'd1, 8'd1}) , + .subnet_mask({8'd255, 8'd255, 8'd255, 8'd0}), + .dest_mac(48'h02_00_00_00_00_01), + .dest_ip({8'd192, 8'd168, 8'd1, 8'd129}) ); endmodule diff --git a/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v b/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v index 670416bba7ef978e319b685392043377e87006d1..e398618e200db095d3269da868227c45ab093ba7 100644 --- a/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v +++ b/example/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v @@ -117,9 +117,39 @@ module fpga_core # input wire qsfp_1_rx_clk_3, input wire qsfp_1_rx_rst_3, input wire [63:0] qsfp_1_rxd_3, - input wire [7:0] qsfp_1_rxc_3 + input wire [7:0] qsfp_1_rxc_3, + + //input and output payload + + output wire [63:0] rx_payload_axis_tdata, + output wire [7:0] rx_payload_axis_tkeep, + output wire rx_payload_axis_tvalid, + input wire rx_payload_axis_tready, + output wire rx_payload_axis_tlast, + + input wire [63:0] tx_payload_axis_tdata, + input wire [7:0] tx_payload_axis_tkeep, + input wire tx_payload_axis_tvalid, + output wire tx_payload_axis_tready, + input wire tx_payload_axis_tlast, + + //networking parameter + // Configuration + input wire [47:0] local_mac, + input wire [31:0] local_ip, + input wire [31:0] gateway_ip, + input wire [31:0] subnet_mask, + input wire [47:0] dest_mac, // is not used, discovered by arp instead + input wire [31:0] dest_ip + ); +initial begin + $dumpfile ("dump.vcd"); + $dumpvars (0, fpga_core); + #1; +end + // AXI between MAC and Ethernet modules wire [63:0] rx_axis_tdata; wire [7:0] rx_axis_tkeep; @@ -160,6 +190,13 @@ wire tx_eth_payload_axis_tready; wire tx_eth_payload_axis_tlast; wire tx_eth_payload_axis_tuser; +/* +assign tx_eth_dest_mac = dest_mac; +assign tx_eth_src_mac = local_mac; +assign tx_eth_type = 16'h800; //hardcoded to be ipv4 +*/ + + // IP frame connections wire rx_ip_hdr_valid; wire rx_ip_hdr_ready; @@ -264,11 +301,6 @@ wire tx_fifo_udp_payload_axis_tready; wire tx_fifo_udp_payload_axis_tlast; wire tx_fifo_udp_payload_axis_tuser; -// Configuration -wire [47:0] local_mac = 48'h02_00_00_00_00_00; -wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128}; -wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1}; -wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0}; // IP ports not used assign rx_ip_hdr_ready = 1; @@ -279,7 +311,7 @@ assign tx_ip_dscp = 0; assign tx_ip_ecn = 0; assign tx_ip_length = 0; assign tx_ip_ttl = 0; -assign tx_ip_protocol = 0; +assign tx_ip_protocol = 8'b11; assign tx_ip_source_ip = 0; assign tx_ip_dest_ip = 0; assign tx_ip_payload_axis_tdata = 0; @@ -289,7 +321,8 @@ assign tx_ip_payload_axis_tlast = 0; assign tx_ip_payload_axis_tuser = 0; // Loop back UDP -wire match_cond = rx_udp_dest_port == 1234; +//wire match_cond = rx_udp_dest_port == 1234; +wire match_cond = 1'b1; //ignore port wire no_match = !match_cond; reg match_cond_reg = 0; @@ -313,15 +346,16 @@ always @(posedge clk) begin end end -assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond; +//assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond; +assign tx_udp_hdr_valid = 1'b1; assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match; assign tx_udp_ip_dscp = 0; assign tx_udp_ip_ecn = 0; assign tx_udp_ip_ttl = 64; assign tx_udp_ip_source_ip = local_ip; -assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip; -assign tx_udp_source_port = rx_udp_dest_port; -assign tx_udp_dest_port = rx_udp_source_port; +assign tx_udp_ip_dest_ip = dest_ip; +assign tx_udp_source_port = rx_udp_dest_port; //ignore right now +assign tx_udp_dest_port = rx_udp_source_port; //ignore right now assign tx_udp_length = rx_udp_length; assign tx_udp_checksum = 0; @@ -626,11 +660,11 @@ axis_fifo #( .KEEP_WIDTH(8), .ID_ENABLE(0), .DEST_ENABLE(0), - .USER_ENABLE(1), + .USER_ENABLE(0), .USER_WIDTH(1), .FRAME_FIFO(0) ) -udp_payload_fifo ( +rx_payload_fifo ( .clk(clk), .rst(rst), @@ -640,10 +674,51 @@ udp_payload_fifo ( .s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid), .s_axis_tready(rx_fifo_udp_payload_axis_tready), .s_axis_tlast(rx_fifo_udp_payload_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), + .s_axis_tid(8'b0), + .s_axis_tdest(8'b0), .s_axis_tuser(rx_fifo_udp_payload_axis_tuser), + // AXI output + .m_axis_tdata(rx_payload_axis_tdata), + .m_axis_tkeep(rx_payload_axis_tkeep), + .m_axis_tvalid(rx_payload_axis_tvalid), + .m_axis_tready(rx_payload_axis_tready), + .m_axis_tlast(rx_payload_axis_tlast), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(), + + // Status + .status_overflow(), + .status_bad_frame(), + .status_good_frame() +); + +axis_fifo #( + .DEPTH(8192), + .DATA_WIDTH(64), + .KEEP_ENABLE(1), + .KEEP_WIDTH(8), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(0), + .USER_WIDTH(1), + .FRAME_FIFO(0) +) +tx_payload_fifo ( + .clk(clk), + .rst(rst), + + // AXI input + .s_axis_tdata(tx_payload_axis_tdata), + .s_axis_tkeep(tx_payload_axis_tkeep), + .s_axis_tvalid(tx_payload_axis_tvalid), + .s_axis_tready(tx_payload_axis_tready), + .s_axis_tlast(tx_payload_axis_tlast), + .s_axis_tid(8'b0), + .s_axis_tdest(8'b0), + .s_axis_tuser(1'b0), + // AXI output .m_axis_tdata(tx_fifo_udp_payload_axis_tdata), .m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep), diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile index 87e6cf660da5726410d391e3e4b57bb08a1136e6..7fd877bdc2ef247445e8577b05c18922438b13f9 100644 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile @@ -21,7 +21,7 @@ TOPLEVEL_LANG = verilog SIM ?= icarus -WAVES ?= 0 +WAVES ?= 1 COCOTB_HDL_TIMEUNIT = 1ns COCOTB_HDL_TIMEPRECISION = 1ps diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/dump.vcd b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/dump.vcd new file mode 100644 index 0000000000000000000000000000000000000000..e8bc30e62f00754ea1712c9d734fdf81717b275b Binary files /dev/null and b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/dump.vcd differ diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/iverilog_dump.v b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/iverilog_dump.v new file mode 100644 index 0000000000000000000000000000000000000000..078e5fe4223925f8678cfc6d2fc384c09ada2282 --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/iverilog_dump.v @@ -0,0 +1,6 @@ +module iverilog_dump(); +initial begin + $dumpfile("fpga_core.fst"); + $dumpvars(0, fpga_core); +end +endmodule diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/results.xml b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/results.xml new file mode 100644 index 0000000000000000000000000000000000000000..68b8e5fea1f97c331d71741280506d7de1dc1c7d --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/results.xml @@ -0,0 +1,6 @@ +<testsuites name="results"> + <testsuite name="all" package="all"> + <property name="random_seed" value="1651005841" /> + <testcase name="run_test" classname="test_fpga_core" file="/home/haiyang3/verilog-ethernet/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py" lineno="187" time="1.4983394145965576" sim_time_ns="1751.041" ratio_time="1168.6544336628058" /> + </testsuite> +</testsuites> diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/sim_build/cmds.f b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/sim_build/cmds.f new file mode 100644 index 0000000000000000000000000000000000000000..3e26e00a8b447d0e10f7930665bf0084d368f051 --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/sim_build/cmds.f @@ -0,0 +1 @@ ++timescale+1ns/1ps diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py index ec5c34f306ae67abf5ad000605b04d669f8afd4c..bafb7454c9f670f554a5450f36636723a768daff 100644 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -36,7 +36,9 @@ from cocotb.clock import Clock from cocotb.triggers import RisingEdge from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink +from cocotbext.axi import AxiStreamFrame, AxiStreamBus, AxiStreamSource, AxiStreamSink +from netaddr import * class TB: def __init__(self, dut): @@ -47,6 +49,9 @@ class TB: cocotb.start_soon(Clock(dut.clk, 2.56, units="ns").start()) + self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_payload_axis"), dut.clk, dut.rst) + self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_payload_axis"), dut.clk, dut.rst) + # Ethernet cocotb.start_soon(Clock(dut.qsfp_0_rx_clk_0, 2.56, units="ns").start()) self.qsfp_0_0_source = XgmiiSource(dut.qsfp_0_rxd_0, dut.qsfp_0_rxc_0, dut.qsfp_0_rx_clk_0, dut.qsfp_0_rx_rst_0) @@ -152,6 +157,32 @@ class TB: self.dut.qsfp_1_rx_rst_3 <= 0 self.dut.qsfp_1_tx_rst_3 <= 0 + def set_idle_generator(self, generator=None): + if generator: + self.source.set_pause_generator(generator()) + + def set_backpressure_generator(self, generator=None): + if generator: + self.sink.set_pause_generator(generator()) + + def set_config(self, local_mac, local_ip, gateway_ip, dest_mac, dest_ip, subnet_mask = '255.255.255.0'): + self.dut.local_mac = local_mac + self.dut.local_ip = local_ip + self.dut.gateway_ip = gateway_ip + self.dut.subnet_mask = subnet_mask + self.dut.dest_mac = dest_mac + self.dut.dest_ip = dest_ip + +def size_list(): + data_width = len(cocotb.top.axis_tdata) + byte_width = data_width // 8 + return list(range(1, byte_width*4+1)) + [512] + [1]*64 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + @cocotb.test() async def run_test(dut): @@ -160,6 +191,16 @@ async def run_test(dut): await tb.init() + #set inserter + #none + local_mac = int(EUI('02:00:00:00:00:00')) + local_ip = int(IPAddress('192.168.1.128')) + gateway_ip = int(IPAddress('192.168.1.1')) + subnet_mask = int(IPAddress('255.255.255.0')) + dest_mac = int(EUI('5a:51:52:53:54:55')) + dest_ip = int(IPAddress('192.168.1.100')) + tb.set_config(local_mac, local_ip, gateway_ip, dest_mac, dest_ip, subnet_mask) + tb.log.info("test UDP RX packet") payload = bytes([x % 256 for x in range(256)]) @@ -168,10 +209,26 @@ async def run_test(dut): udp = UDP(sport=5678, dport=1234) test_pkt = eth / ip / udp / payload + tb.log.info("TX packet: %s", repr(test_pkt)) + test_frame = XgmiiFrame.from_payload(test_pkt.build()) await tb.qsfp_0_0_source.send(test_frame) + tb.log.info("Receive payload in AXIS") + rx_frame = await tb.sink.recv() + + assert rx_frame.tdata == payload + + + + + + tb.log.info("Send payload in AXIS") + test_frame = AxiStreamFrame(payload) + await tb.source.send(test_frame) + + tb.log.info("receive ARP request") rx_frame = await tb.qsfp_0_0_sink.recv() @@ -204,6 +261,7 @@ async def run_test(dut): await tb.qsfp_0_0_source.send(resp_frame) + tb.log.info("receive UDP packet") rx_frame = await tb.qsfp_0_0_sink.recv() @@ -214,11 +272,15 @@ async def run_test(dut): assert rx_pkt.dst == test_pkt.src assert rx_pkt.src == test_pkt.dst + + ''' assert rx_pkt[IP].dst == test_pkt[IP].src assert rx_pkt[IP].src == test_pkt[IP].dst assert rx_pkt[UDP].dport == test_pkt[UDP].sport - assert rx_pkt[UDP].sport == test_pkt[UDP].dport - assert rx_pkt[UDP].payload == test_pkt[UDP].payload + assert rx_pkt[UDP].sport == test_pkt[UDP].dport + ''' + + assert bytes(rx_pkt[UDP].payload) == payload await RisingEdge(dut.clk) await RisingEdge(dut.clk)