From d0a45d821378bff70aae1efd71dd257cef2eadb9 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 27 Sep 2020 01:45:56 -0700 Subject: [PATCH 01/37] Add fb2CG flash programming commands --- example/fb2CG/fpga_10g/fpga/Makefile | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/example/fb2CG/fpga_10g/fpga/Makefile b/example/fb2CG/fpga_10g/fpga/Makefile index bfce2fc9d..32e884d85 100644 --- a/example/fb2CG/fpga_10g/fpga/Makefile +++ b/example/fb2CG/fpga_10g/fpga/Makefile @@ -70,3 +70,40 @@ program: $(FPGA_TOP).bit echo "exit" >> program.tcl vivado -nojournal -nolog -mode batch -source program.tcl +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 64 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw" > flash.tcl + echo "connect_hw_server" >> flash.tcl + echo "open_hw_target" >> flash.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl + echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu512-spi-x1_x2_x4}] 0]" >> flash.tcl + echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl + echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl + From 2bc052e0d564fe4aa417e8673eaa85ff29474204 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Sep 2020 17:24:11 -0700 Subject: [PATCH 02/37] Update LED driver timing constraints --- example/fb2CG/fpga_10g/led.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/fb2CG/fpga_10g/led.tcl b/example/fb2CG/fpga_10g/led.tcl index e430903ef..1e1bd643d 100644 --- a/example/fb2CG/fpga_10g/led.tcl +++ b/example/fb2CG/fpga_10g/led.tcl @@ -7,6 +7,6 @@ foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == led_sreg_driver || REF_ if {[llength $select_ffs]} { set_property ASYNC_REG TRUE $select_ffs - set_false_path -from [all_registers] -to [get_cells "$inst/led_sync_reg_1_reg[*]"] + set_false_path -to [get_pins "$inst/led_sync_reg_1_reg[*]/D"] } } From 3f52ed675c95a0bdec002279e1ff5d236c536dcd Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Sep 2020 17:30:13 -0700 Subject: [PATCH 03/37] Fix flash settings --- example/AU200/fpga_10g/fpga.xdc | 1 - example/AU250/fpga_10g/fpga.xdc | 1 - 2 files changed, 2 deletions(-) diff --git a/example/AU200/fpga_10g/fpga.xdc b/example/AU200/fpga_10g/fpga.xdc index 33046e6df..aa61c277f 100644 --- a/example/AU200/fpga_10g/fpga.xdc +++ b/example/AU200/fpga_10g/fpga.xdc @@ -11,7 +11,6 @@ set_property BITSTREAM.CONFIG.CONFIGRATE 63.8 [current_design] set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] -set_property BITSTREAM.CONFIG.SPI_OPCODE 8'h6B [current_design] set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] # System clocks diff --git a/example/AU250/fpga_10g/fpga.xdc b/example/AU250/fpga_10g/fpga.xdc index 764edac1b..58a54e6ad 100644 --- a/example/AU250/fpga_10g/fpga.xdc +++ b/example/AU250/fpga_10g/fpga.xdc @@ -11,7 +11,6 @@ set_property BITSTREAM.CONFIG.CONFIGRATE 63.8 [current_design] set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] -set_property BITSTREAM.CONFIG.SPI_OPCODE 8'h6B [current_design] set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] # System clocks From bf9f1a621176ca7d3239b98519bdffe8919cba7b Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Sep 2020 18:29:27 -0700 Subject: [PATCH 04/37] Update flash programming commands --- example/AU200/fpga_10g/fpga/Makefile | 37 ++++++++++++++++++++++++++ example/AU250/fpga_10g/fpga/Makefile | 37 ++++++++++++++++++++++++++ example/AU280/fpga_10g/fpga/Makefile | 4 +-- example/AU50/fpga_10g/fpga/Makefile | 4 +-- example/VCU1525/fpga_10g/fpga/Makefile | 12 ++++----- 5 files changed, 84 insertions(+), 10 deletions(-) diff --git a/example/AU200/fpga_10g/fpga/Makefile b/example/AU200/fpga_10g/fpga/Makefile index 413e36bc4..149a24808 100644 --- a/example/AU200/fpga_10g/fpga/Makefile +++ b/example/AU200/fpga_10g/fpga/Makefile @@ -70,3 +70,40 @@ program: $(FPGA_TOP).bit echo "exit" >> program.tcl vivado -nojournal -nolog -mode batch -source program.tcl +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw" > flash.tcl + echo "connect_hw_server" >> flash.tcl + echo "open_hw_target" >> flash.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl + echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl + echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl + echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl + diff --git a/example/AU250/fpga_10g/fpga/Makefile b/example/AU250/fpga_10g/fpga/Makefile index 51f3d722c..56564740c 100644 --- a/example/AU250/fpga_10g/fpga/Makefile +++ b/example/AU250/fpga_10g/fpga/Makefile @@ -70,3 +70,40 @@ program: $(FPGA_TOP).bit echo "exit" >> program.tcl vivado -nojournal -nolog -mode batch -source program.tcl +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw" > flash.tcl + echo "connect_hw_server" >> flash.tcl + echo "open_hw_target" >> flash.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl + echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl + echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl + echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl + diff --git a/example/AU280/fpga_10g/fpga/Makefile b/example/AU280/fpga_10g/fpga/Makefile index d13e3cf67..78988829c 100644 --- a/example/AU280/fpga_10g/fpga/Makefile +++ b/example/AU280/fpga_10g/fpga/Makefile @@ -70,7 +70,7 @@ program: $(FPGA_TOP).bit vivado -nojournal -nolog -mode batch -source program.tcl %.mcs %.prm: %.bit - echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl echo "exit" >> generate_mcs.tcl vivado -nojournal -nolog -mode batch -source generate_mcs.tcl mkdir -p rev @@ -78,7 +78,7 @@ program: $(FPGA_TOP).bit while [ -e rev/$*_rev$$COUNT.bit ]; \ do COUNT=$$((COUNT+1)); done; \ COUNT=$$((COUNT-1)); \ - for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \ + for x in .mcs .prm; \ do cp $*$$x rev/$*_rev$$COUNT$$x; \ echo "Output: rev/$*_rev$$COUNT$$x"; done; diff --git a/example/AU50/fpga_10g/fpga/Makefile b/example/AU50/fpga_10g/fpga/Makefile index 49a028b5a..0cd5f9992 100644 --- a/example/AU50/fpga_10g/fpga/Makefile +++ b/example/AU50/fpga_10g/fpga/Makefile @@ -70,7 +70,7 @@ program: $(FPGA_TOP).bit vivado -nojournal -nolog -mode batch -source program.tcl %.mcs %.prm: %.bit - echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl echo "exit" >> generate_mcs.tcl vivado -nojournal -nolog -mode batch -source generate_mcs.tcl mkdir -p rev @@ -78,7 +78,7 @@ program: $(FPGA_TOP).bit while [ -e rev/$*_rev$$COUNT.bit ]; \ do COUNT=$$((COUNT+1)); done; \ COUNT=$$((COUNT-1)); \ - for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \ + for x in .mcs .prm; \ do cp $*$$x rev/$*_rev$$COUNT$$x; \ echo "Output: rev/$*_rev$$COUNT$$x"; done; diff --git a/example/VCU1525/fpga_10g/fpga/Makefile b/example/VCU1525/fpga_10g/fpga/Makefile index 8eea51831..3a8fc202a 100644 --- a/example/VCU1525/fpga_10g/fpga/Makefile +++ b/example/VCU1525/fpga_10g/fpga/Makefile @@ -70,8 +70,8 @@ program: $(FPGA_TOP).bit echo "exit" >> program.tcl vivado -nojournal -nolog -mode batch -source program.tcl -%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit - echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x04000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl echo "exit" >> generate_mcs.tcl vivado -nojournal -nolog -mode batch -source generate_mcs.tcl mkdir -p rev @@ -79,11 +79,11 @@ program: $(FPGA_TOP).bit while [ -e rev/$*_rev$$COUNT.bit ]; \ do COUNT=$$((COUNT+1)); done; \ COUNT=$$((COUNT-1)); \ - for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \ + for x in .mcs .prm; \ do cp $*$$x rev/$*_rev$$COUNT$$x; \ echo "Output: rev/$*_rev$$COUNT$$x"; done; -flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm echo "open_hw" > flash.tcl echo "connect_hw_server" >> flash.tcl echo "open_hw_target" >> flash.tcl @@ -91,8 +91,8 @@ flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl - echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl - echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl From 816e071a57285103824b542a9fbce518cdd42171 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 30 Sep 2020 23:50:31 -0700 Subject: [PATCH 05/37] Fix bitstream config for VCU1525 --- example/VCU1525/fpga_10g/fpga.xdc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/example/VCU1525/fpga_10g/fpga.xdc b/example/VCU1525/fpga_10g/fpga.xdc index 7e112e621..5b1dd8e2b 100644 --- a/example/VCU1525/fpga_10g/fpga.xdc +++ b/example/VCU1525/fpga_10g/fpga.xdc @@ -5,10 +5,13 @@ set_property CFGBVS GND [current_design] set_property CONFIG_VOLTAGE 1.8 [current_design] set_property BITSTREAM.GENERAL.COMPRESS true [current_design] -set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN {DIV-1} [current_design] +set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design] +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design] +set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design] set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] # System clocks # 300 MHz (DDR 0) From 9e4bd6e85415513d210dde3986e64ae4a433a006 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Thu, 1 Oct 2020 00:53:13 -0700 Subject: [PATCH 06/37] Fix flash programming commands for VCU108 --- example/VCU108/fpga_10g/fpga/Makefile | 2 +- example/VCU108/fpga_1g/fpga/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/VCU108/fpga_10g/fpga/Makefile b/example/VCU108/fpga_10g/fpga/Makefile index d400e5181..fbb18736d 100644 --- a/example/VCU108/fpga_10g/fpga/Makefile +++ b/example/VCU108/fpga_10g/fpga/Makefile @@ -106,7 +106,7 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl - echo "set_property PROGRAM.BPI_RS_PINS {none} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.BPI_RS_PINS {25:24} [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl echo "program_hw_devices [current_hw_device]" >> flash.tcl diff --git a/example/VCU108/fpga_1g/fpga/Makefile b/example/VCU108/fpga_1g/fpga/Makefile index b0da2b547..d4cab0088 100644 --- a/example/VCU108/fpga_1g/fpga/Makefile +++ b/example/VCU108/fpga_1g/fpga/Makefile @@ -89,7 +89,7 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl - echo "set_property PROGRAM.BPI_RS_PINS {none} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.BPI_RS_PINS {25:24} [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl echo "program_hw_devices [current_hw_device]" >> flash.tcl From 9261f26f649e7bedb9c2f9966c6cd58fa3bd0e21 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 2 Oct 2020 20:50:00 -0700 Subject: [PATCH 07/37] Update VCU108 XDC --- example/VCU108/fpga_10g/fpga.xdc | 44 ++++++++++++++++++++++++++++++++ example/VCU108/fpga_1g/fpga.xdc | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/example/VCU108/fpga_10g/fpga.xdc b/example/VCU108/fpga_10g/fpga.xdc index 13ef8e151..934fdab3f 100644 --- a/example/VCU108/fpga_10g/fpga.xdc +++ b/example/VCU108/fpga_10g/fpga.xdc @@ -151,4 +151,48 @@ set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] +# Flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[4]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[5]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[6]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[7]}] +#set_property -dict {LOC AN19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[8]}] +#set_property -dict {LOC AN18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[9]}] +#set_property -dict {LOC AR18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[10]}] +#set_property -dict {LOC AR17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[11]}] +#set_property -dict {LOC AT20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[12]}] +#set_property -dict {LOC AT19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[13]}] +#set_property -dict {LOC AT17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[14]}] +#set_property -dict {LOC AU17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[15]}] +#set_property -dict {LOC AR20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[0]}] +#set_property -dict {LOC AR19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[1]}] +#set_property -dict {LOC AV20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[2]}] +#set_property -dict {LOC AW20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[3]}] +#set_property -dict {LOC AU19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[4]}] +#set_property -dict {LOC AU18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[5]}] +#set_property -dict {LOC AV19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[6]}] +#set_property -dict {LOC AV18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[7]}] +#set_property -dict {LOC AW18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[8]}] +#set_property -dict {LOC AY18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[9]}] +#set_property -dict {LOC AY19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[10]}] +#set_property -dict {LOC BA19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[11]}] +#set_property -dict {LOC BA17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[12]}] +#set_property -dict {LOC BB17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[13]}] +#set_property -dict {LOC BB19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[14]}] +#set_property -dict {LOC BC19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[15]}] +#set_property -dict {LOC BB18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[16]}] +#set_property -dict {LOC BC18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[17]}] +#set_property -dict {LOC AY20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[18]}] +#set_property -dict {LOC BA20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[19]}] +#set_property -dict {LOC BD18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[20]}] +#set_property -dict {LOC BD17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[21]}] +#set_property -dict {LOC BC20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[22]}] +#set_property -dict {LOC BD20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[23]}] +#set_property -dict {LOC BE20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_region[0]}] +#set_property -dict {LOC BF20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_region[1]}] +#set_property -dict {LOC BF17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_oe_n}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_we_n}] +#set_property -dict {LOC AW17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] +#set_property -dict {LOC BC23 IOSTANDARD LVCMOS18} [get_ports {flash_wait}] + diff --git a/example/VCU108/fpga_1g/fpga.xdc b/example/VCU108/fpga_1g/fpga.xdc index da76f8135..163c9a1bd 100644 --- a/example/VCU108/fpga_1g/fpga.xdc +++ b/example/VCU108/fpga_1g/fpga.xdc @@ -151,3 +151,47 @@ create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] +# Flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[4]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[5]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[6]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[7]}] +#set_property -dict {LOC AN19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[8]}] +#set_property -dict {LOC AN18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[9]}] +#set_property -dict {LOC AR18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[10]}] +#set_property -dict {LOC AR17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[11]}] +#set_property -dict {LOC AT20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[12]}] +#set_property -dict {LOC AT19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[13]}] +#set_property -dict {LOC AT17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[14]}] +#set_property -dict {LOC AU17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[15]}] +#set_property -dict {LOC AR20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[0]}] +#set_property -dict {LOC AR19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[1]}] +#set_property -dict {LOC AV20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[2]}] +#set_property -dict {LOC AW20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[3]}] +#set_property -dict {LOC AU19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[4]}] +#set_property -dict {LOC AU18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[5]}] +#set_property -dict {LOC AV19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[6]}] +#set_property -dict {LOC AV18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[7]}] +#set_property -dict {LOC AW18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[8]}] +#set_property -dict {LOC AY18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[9]}] +#set_property -dict {LOC AY19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[10]}] +#set_property -dict {LOC BA19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[11]}] +#set_property -dict {LOC BA17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[12]}] +#set_property -dict {LOC BB17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[13]}] +#set_property -dict {LOC BB19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[14]}] +#set_property -dict {LOC BC19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[15]}] +#set_property -dict {LOC BB18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[16]}] +#set_property -dict {LOC BC18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[17]}] +#set_property -dict {LOC AY20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[18]}] +#set_property -dict {LOC BA20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[19]}] +#set_property -dict {LOC BD18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[20]}] +#set_property -dict {LOC BD17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[21]}] +#set_property -dict {LOC BC20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[22]}] +#set_property -dict {LOC BD20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[23]}] +#set_property -dict {LOC BE20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_region[0]}] +#set_property -dict {LOC BF20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_region[1]}] +#set_property -dict {LOC BF17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_oe_n}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_we_n}] +#set_property -dict {LOC AW17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] +#set_property -dict {LOC BC23 IOSTANDARD LVCMOS18} [get_ports {flash_wait}] + From ed7136a09504ca671fbc9cd318062f8471331528 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 3 Oct 2020 15:27:30 -0700 Subject: [PATCH 08/37] Update flash programming configuration for ExaNIC X10 and X25 --- example/ExaNIC_X10/fpga/fpga/Makefile | 4 ++-- example/ExaNIC_X25/fpga_10g/fpga.xdc | 1 - example/ExaNIC_X25/fpga_10g/fpga/Makefile | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/example/ExaNIC_X10/fpga/fpga/Makefile b/example/ExaNIC_X10/fpga/fpga/Makefile index 30c895374..7ca4147db 100644 --- a/example/ExaNIC_X10/fpga/fpga/Makefile +++ b/example/ExaNIC_X10/fpga/fpga/Makefile @@ -69,7 +69,7 @@ program: $(FPGA_TOP).bit vivado -nojournal -nolog -mode batch -source program.tcl %.mcs %.prm: %.bit - echo "write_cfgmem -force -format mcs -size 32 -interface BPIx16 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "write_cfgmem -force -format mcs -size 32 -interface BPIx16 -loadbit {up 0x00800000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl echo "exit" >> generate_mcs.tcl vivado -nojournal -nolog -mode batch -source generate_mcs.tcl mkdir -p rev @@ -96,7 +96,7 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl - echo "set_property PROGRAM.BPI_RS_PINS {none} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.BPI_RS_PINS {24:23} [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl echo "program_hw_devices [current_hw_device]" >> flash.tcl diff --git a/example/ExaNIC_X25/fpga_10g/fpga.xdc b/example/ExaNIC_X25/fpga_10g/fpga.xdc index cd3965aee..91567ddb5 100644 --- a/example/ExaNIC_X25/fpga_10g/fpga.xdc +++ b/example/ExaNIC_X25/fpga_10g/fpga.xdc @@ -9,7 +9,6 @@ set_property BITSTREAM.CONFIG.UNUSEDPIN Pullup [current_design] set_property BITSTREAM.CONFIG.CONFIGRATE 31.9 [current_design] set_property BITSTREAM.CONFIG.BPI_PAGE_SIZE 8 [current_design] set_property BITSTREAM.CONFIG.BPI_1ST_READ_CYCLE 4 [current_design] -set_property BITSTREAM.CONFIG.REVISIONSELECT_TRISTATE Enable [current_design] set_property CONFIG_MODE BPI16 [current_design] set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design] diff --git a/example/ExaNIC_X25/fpga_10g/fpga/Makefile b/example/ExaNIC_X25/fpga_10g/fpga/Makefile index 3facc2b92..c824d0eda 100644 --- a/example/ExaNIC_X25/fpga_10g/fpga/Makefile +++ b/example/ExaNIC_X25/fpga_10g/fpga/Makefile @@ -69,7 +69,7 @@ program: $(FPGA_TOP).bit vivado -nojournal -nolog -mode batch -source program.tcl %.mcs %.prm: %.bit - echo "write_cfgmem -force -format mcs -size 32 -interface BPIx16 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "write_cfgmem -force -format mcs -size 32 -interface BPIx16 -loadbit {up 0x00800000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl echo "exit" >> generate_mcs.tcl vivado -nojournal -nolog -mode batch -source generate_mcs.tcl mkdir -p rev @@ -87,7 +87,7 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm echo "open_hw_target" >> flash.tcl echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl - echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {28f256p30t-bpi-x16}] 0]" >> flash.tcl + echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {s29gl256p-bpi-x16}] 0]" >> flash.tcl echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl @@ -96,7 +96,7 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl - echo "set_property PROGRAM.BPI_RS_PINS {none} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.BPI_RS_PINS {24:23} [current_hw_cfgmem]" >> flash.tcl echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl echo "program_hw_devices [current_hw_device]" >> flash.tcl From 306aa4db0b122a278155bee048a783268bcfdbff Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 6 Oct 2020 00:39:32 -0700 Subject: [PATCH 09/37] Update VCU118 XDC --- example/VCU118/fpga_10g/fpga.xdc | 6 ++++++ example/VCU118/fpga_1g/fpga.xdc | 7 +++++++ example/VCU118/fpga_25g/fpga.xdc | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/example/VCU118/fpga_10g/fpga.xdc b/example/VCU118/fpga_10g/fpga.xdc index 6a64f1a3c..1773b7485 100644 --- a/example/VCU118/fpga_10g/fpga.xdc +++ b/example/VCU118/fpga_10g/fpga.xdc @@ -223,4 +223,10 @@ set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +# Flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] diff --git a/example/VCU118/fpga_1g/fpga.xdc b/example/VCU118/fpga_1g/fpga.xdc index c2b1fda60..0ef436d71 100644 --- a/example/VCU118/fpga_1g/fpga.xdc +++ b/example/VCU118/fpga_1g/fpga.xdc @@ -223,3 +223,10 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +# Flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] + diff --git a/example/VCU118/fpga_25g/fpga.xdc b/example/VCU118/fpga_25g/fpga.xdc index 6a64f1a3c..1773b7485 100644 --- a/example/VCU118/fpga_25g/fpga.xdc +++ b/example/VCU118/fpga_25g/fpga.xdc @@ -223,4 +223,10 @@ set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +# Flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] From 909ccae1518b49c65ef40f7ac5e35451d3d6179c Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 1 Dec 2020 14:01:15 -0800 Subject: [PATCH 10/37] Properly synchronize bad FCS status output --- rtl/eth_mac_10g_fifo.v | 2 +- rtl/eth_mac_1g_fifo.v | 2 +- rtl/eth_mac_1g_gmii_fifo.v | 2 +- rtl/eth_mac_1g_rgmii_fifo.v | 2 +- rtl/eth_mac_mii_fifo.v | 2 +- rtl/eth_mac_phy_10g_fifo.v | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rtl/eth_mac_10g_fifo.v b/rtl/eth_mac_10g_fifo.v index 45b0331ee..8d3c21564 100644 --- a/rtl/eth_mac_10g_fifo.v +++ b/rtl/eth_mac_10g_fifo.v @@ -227,7 +227,7 @@ always @(posedge rx_clk or posedge rx_rst) begin if (rx_rst) begin rx_sync_reg_1 <= 2'd0; end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_frame_int, rx_error_bad_frame_int}; + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; end end diff --git a/rtl/eth_mac_1g_fifo.v b/rtl/eth_mac_1g_fifo.v index ab20e7782..c825bbc3f 100644 --- a/rtl/eth_mac_1g_fifo.v +++ b/rtl/eth_mac_1g_fifo.v @@ -166,7 +166,7 @@ always @(posedge rx_clk or posedge rx_rst) begin if (rx_rst) begin rx_sync_reg_1 <= 2'd0; end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_frame_int, rx_error_bad_frame_int}; + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; end end diff --git a/rtl/eth_mac_1g_gmii_fifo.v b/rtl/eth_mac_1g_gmii_fifo.v index 75fb2b16e..60013aae9 100644 --- a/rtl/eth_mac_1g_gmii_fifo.v +++ b/rtl/eth_mac_1g_gmii_fifo.v @@ -178,7 +178,7 @@ always @(posedge rx_clk or posedge rx_rst) begin if (rx_rst) begin rx_sync_reg_1 <= 2'd0; end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_frame_int, rx_error_bad_frame_int}; + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; end end diff --git a/rtl/eth_mac_1g_rgmii_fifo.v b/rtl/eth_mac_1g_rgmii_fifo.v index be235fa44..8d8d1a64c 100644 --- a/rtl/eth_mac_1g_rgmii_fifo.v +++ b/rtl/eth_mac_1g_rgmii_fifo.v @@ -178,7 +178,7 @@ always @(posedge rx_clk or posedge rx_rst) begin if (rx_rst) begin rx_sync_reg_1 <= 2'd0; end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_frame_int, rx_error_bad_frame_int}; + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; end end diff --git a/rtl/eth_mac_mii_fifo.v b/rtl/eth_mac_mii_fifo.v index e6040db70..7f2e0508b 100644 --- a/rtl/eth_mac_mii_fifo.v +++ b/rtl/eth_mac_mii_fifo.v @@ -171,7 +171,7 @@ always @(posedge rx_clk or posedge rx_rst) begin if (rx_rst) begin rx_sync_reg_1 <= 2'd0; end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_frame_int, rx_error_bad_frame_int}; + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; end end diff --git a/rtl/eth_mac_phy_10g_fifo.v b/rtl/eth_mac_phy_10g_fifo.v index ab498d5af..dd6c96a6d 100644 --- a/rtl/eth_mac_phy_10g_fifo.v +++ b/rtl/eth_mac_phy_10g_fifo.v @@ -243,7 +243,7 @@ always @(posedge rx_clk or posedge rx_rst) begin if (rx_rst) begin rx_sync_reg_1 <= 5'd0; end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_high_ber_int, rx_block_lock_int, rx_bad_block_int, rx_error_bad_frame_int, rx_error_bad_frame_int}; + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_high_ber_int, rx_block_lock_int, rx_bad_block_int, rx_error_bad_fcs_int, rx_error_bad_frame_int}; end end From 2a2d8ac966d0c9ed3cff9ff99efb85a97551076d Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 20 Dec 2020 14:22:52 -0800 Subject: [PATCH 11/37] Fix reg type in VCU108 and VCU118 example designs --- example/VCU108/fpga_10g/rtl/fpga_core.v | 2 +- example/VCU118/fpga_10g/rtl/fpga_core.v | 2 +- example/VCU118/fpga_25g/rtl/fpga_core.v | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/VCU108/fpga_10g/rtl/fpga_core.v b/example/VCU108/fpga_10g/rtl/fpga_core.v index fdf63d8fb..740b86fc1 100644 --- a/example/VCU108/fpga_10g/rtl/fpga_core.v +++ b/example/VCU108/fpga_10g/rtl/fpga_core.v @@ -603,7 +603,7 @@ axis_switch #( .M_TOP({2'd2, 2'd1, 2'd0}), .M_CONNECT({3{3'b111}}), .S_REG_TYPE(0), - .M_REG_TYPE(1), + .M_REG_TYPE(2), .ARB_TYPE("PRIORITY"), .LSB_PRIORITY("HIGH") ) diff --git a/example/VCU118/fpga_10g/rtl/fpga_core.v b/example/VCU118/fpga_10g/rtl/fpga_core.v index efd80d687..827fc7fbf 100644 --- a/example/VCU118/fpga_10g/rtl/fpga_core.v +++ b/example/VCU118/fpga_10g/rtl/fpga_core.v @@ -644,7 +644,7 @@ axis_switch #( .M_TOP({2'd2, 2'd1, 2'd0}), .M_CONNECT({3{3'b111}}), .S_REG_TYPE(0), - .M_REG_TYPE(1), + .M_REG_TYPE(2), .ARB_TYPE("PRIORITY"), .LSB_PRIORITY("HIGH") ) diff --git a/example/VCU118/fpga_25g/rtl/fpga_core.v b/example/VCU118/fpga_25g/rtl/fpga_core.v index 3bed964df..f095b92ac 100644 --- a/example/VCU118/fpga_25g/rtl/fpga_core.v +++ b/example/VCU118/fpga_25g/rtl/fpga_core.v @@ -644,7 +644,7 @@ axis_switch #( .M_TOP({2'd2, 2'd1, 2'd0}), .M_CONNECT({3{3'b111}}), .S_REG_TYPE(0), - .M_REG_TYPE(1), + .M_REG_TYPE(2), .ARB_TYPE("PRIORITY"), .LSB_PRIORITY("HIGH") ) From 220e04d1a7e1124321cf3b6bb4e7477ea14568d4 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 25 Dec 2020 01:47:01 -0800 Subject: [PATCH 12/37] Update example design --- example/HXT100G/fpga_cxpt16/fpga/Makefile | 3 +-- example/HXT100G/fpga_cxpt16/rtl/fpga_core.v | 7 +++++-- example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py | 3 +-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/example/HXT100G/fpga_cxpt16/fpga/Makefile b/example/HXT100G/fpga_cxpt16/fpga/Makefile index 4ec2c1ece..1a1a5a1b3 100644 --- a/example/HXT100G/fpga_cxpt16/fpga/Makefile +++ b/example/HXT100G/fpga_cxpt16/fpga/Makefile @@ -21,8 +21,7 @@ SYN_FILES += lib/eth/rtl/eth_mac_10g.v SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v SYN_FILES += lib/eth/rtl/lfsr.v -SYN_FILES += lib/eth/rtl/eth_axis_rx_64.v -SYN_FILES += lib/eth/rtl/eth_axis_tx_64.v +SYN_FILES += lib/eth/rtl/eth_axis_rx.v SYN_FILES += lib/eth/lib/axis/rtl/axis_crosspoint.v SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v diff --git a/example/HXT100G/fpga_cxpt16/rtl/fpga_core.v b/example/HXT100G/fpga_cxpt16/rtl/fpga_core.v index afcc742c9..99cda3021 100644 --- a/example/HXT100G/fpga_cxpt16/rtl/fpga_core.v +++ b/example/HXT100G/fpga_cxpt16/rtl/fpga_core.v @@ -309,8 +309,11 @@ eth_mac_fifo_inst ( .ifg_delay(12) ); -eth_axis_rx_64 -eth_axis_rx_inst ( +eth_axis_rx #( + .DATA_WIDTH(64), + .KEEP_WIDTH(8) +) +eth_axis_rxinst ( .clk(clk), .rst(rst), // AXI input diff --git a/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py b/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py index ac672bd58..fdaa4dabf 100755 --- a/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py +++ b/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py @@ -40,8 +40,7 @@ srcs.append("../lib/eth/rtl/eth_mac_10g.v") srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx_64.v") -srcs.append("../lib/eth/rtl/eth_axis_tx_64.v") +srcs.append("../lib/eth/rtl/eth_axis_rx.v") srcs.append("../lib/eth/lib/axis/rtl/axis_crosspoint.v") srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") From a78627343d6da8c50c52f4a11aa624b5d84858de Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 25 Dec 2020 01:48:24 -0800 Subject: [PATCH 13/37] Change default target parameter --- example/ATLYS/fpga/rtl/fpga.v | 4 +++- example/ATLYS/fpga/rtl/fpga_core.v | 2 +- example/Arty/fpga/rtl/fpga.v | 4 +++- example/Arty/fpga/rtl/fpga_core.v | 2 +- example/C10LP/fpga/rtl/fpga.v | 4 +++- example/C10LP/fpga/rtl/fpga_core.v | 2 +- example/DE2-115/fpga/rtl/fpga.v | 4 +++- example/DE2-115/fpga/rtl/fpga_core.v | 2 +- example/KC705/fpga_gmii/rtl/fpga.v | 4 +++- example/KC705/fpga_gmii/rtl/fpga_core.v | 2 +- example/ML605/fpga_gmii/rtl/fpga.v | 4 +++- example/ML605/fpga_gmii/rtl/fpga_core.v | 2 +- example/ML605/fpga_rgmii/rtl/fpga.v | 4 +++- example/ML605/fpga_rgmii/rtl/fpga_core.v | 2 +- example/NexysVideo/fpga/rtl/fpga.v | 4 +++- example/NexysVideo/fpga/rtl/fpga_core.v | 2 +- 16 files changed, 32 insertions(+), 16 deletions(-) diff --git a/example/ATLYS/fpga/rtl/fpga.v b/example/ATLYS/fpga/rtl/fpga.v index a3f61bc34..9afe0712d 100644 --- a/example/ATLYS/fpga/rtl/fpga.v +++ b/example/ATLYS/fpga/rtl/fpga.v @@ -179,7 +179,9 @@ sync_signal_inst ( .out({uart_rxd_int}) ); -fpga_core +fpga_core #( + .TARGET("XILINX") +) core_inst ( /* * Clock: 125MHz diff --git a/example/ATLYS/fpga/rtl/fpga_core.v b/example/ATLYS/fpga/rtl/fpga_core.v index 43dfcee97..36a07e149 100644 --- a/example/ATLYS/fpga/rtl/fpga_core.v +++ b/example/ATLYS/fpga/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "XILINX" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/Arty/fpga/rtl/fpga.v b/example/Arty/fpga/rtl/fpga.v index 6b7d64121..9ed6cf374 100644 --- a/example/Arty/fpga/rtl/fpga.v +++ b/example/Arty/fpga/rtl/fpga.v @@ -214,7 +214,9 @@ sync_signal_inst ( assign phy_ref_clk = clk_25mhz_int; -fpga_core +fpga_core #( + .TARGET("XILINX") +) core_inst ( /* * Clock: 125MHz diff --git a/example/Arty/fpga/rtl/fpga_core.v b/example/Arty/fpga/rtl/fpga_core.v index c6256a986..68e7c0473 100644 --- a/example/Arty/fpga/rtl/fpga_core.v +++ b/example/Arty/fpga/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "XILINX" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/C10LP/fpga/rtl/fpga.v b/example/C10LP/fpga/rtl/fpga.v index bc1d33760..166d94c85 100644 --- a/example/C10LP/fpga/rtl/fpga.v +++ b/example/C10LP/fpga/rtl/fpga.v @@ -197,7 +197,9 @@ debounce_switch_inst ( assign user_led = ~led_int; -fpga_core +fpga_core #( + .TARGET("ALTERA") +) core_inst ( /* * Clock: 125MHz diff --git a/example/C10LP/fpga/rtl/fpga_core.v b/example/C10LP/fpga/rtl/fpga_core.v index b37fc3599..1a71c239c 100644 --- a/example/C10LP/fpga/rtl/fpga_core.v +++ b/example/C10LP/fpga/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "ALTERA" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/DE2-115/fpga/rtl/fpga.v b/example/DE2-115/fpga/rtl/fpga.v index ae51d7df2..e72e3497a 100644 --- a/example/DE2-115/fpga/rtl/fpga.v +++ b/example/DE2-115/fpga/rtl/fpga.v @@ -211,7 +211,9 @@ debounce_switch_inst ( sw_int}) ); -fpga_core +fpga_core #( + .TARGET("ALTERA") +) core_inst ( /* * Clock: 125MHz diff --git a/example/DE2-115/fpga/rtl/fpga_core.v b/example/DE2-115/fpga/rtl/fpga_core.v index 6e50e6b94..f570d9986 100644 --- a/example/DE2-115/fpga/rtl/fpga_core.v +++ b/example/DE2-115/fpga/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "ALTERA" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/KC705/fpga_gmii/rtl/fpga.v b/example/KC705/fpga_gmii/rtl/fpga.v index 7eec88e76..90402a7cf 100644 --- a/example/KC705/fpga_gmii/rtl/fpga.v +++ b/example/KC705/fpga_gmii/rtl/fpga.v @@ -209,7 +209,9 @@ sync_signal_inst ( .out({uart_rxd_int, uart_cts_int}) ); -fpga_core +fpga_core #( + .TARGET("XILINX") +) core_inst ( /* * Clock: 125MHz diff --git a/example/KC705/fpga_gmii/rtl/fpga_core.v b/example/KC705/fpga_gmii/rtl/fpga_core.v index 18973c19b..fbf0d7aff 100644 --- a/example/KC705/fpga_gmii/rtl/fpga_core.v +++ b/example/KC705/fpga_gmii/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "XILINX" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/ML605/fpga_gmii/rtl/fpga.v b/example/ML605/fpga_gmii/rtl/fpga.v index 64a2b2ab7..14f15c080 100644 --- a/example/ML605/fpga_gmii/rtl/fpga.v +++ b/example/ML605/fpga_gmii/rtl/fpga.v @@ -231,7 +231,9 @@ assign led = led_int; assign uart_rxd = uart_rxd_int; assign uart_cts = uart_cts_int; -fpga_core +fpga_core #( + .TARGET("XILINX") +) core_inst ( /* * Clock: 125MHz diff --git a/example/ML605/fpga_gmii/rtl/fpga_core.v b/example/ML605/fpga_gmii/rtl/fpga_core.v index cfd669e33..6a82bc638 100644 --- a/example/ML605/fpga_gmii/rtl/fpga_core.v +++ b/example/ML605/fpga_gmii/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "XILINX" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/ML605/fpga_rgmii/rtl/fpga.v b/example/ML605/fpga_rgmii/rtl/fpga.v index 82308bcf7..38640cccb 100644 --- a/example/ML605/fpga_rgmii/rtl/fpga.v +++ b/example/ML605/fpga_rgmii/rtl/fpga.v @@ -236,7 +236,9 @@ assign led = led_int; assign uart_rxd = uart_rxd_int; assign uart_cts = uart_cts_int; -fpga_core +fpga_core #( + .TARGET("XILINX") +) core_inst ( /* * Clock: 125MHz diff --git a/example/ML605/fpga_rgmii/rtl/fpga_core.v b/example/ML605/fpga_rgmii/rtl/fpga_core.v index 1f5fc6256..9aa010326 100644 --- a/example/ML605/fpga_rgmii/rtl/fpga_core.v +++ b/example/ML605/fpga_rgmii/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "XILINX" + parameter TARGET = "GENERIC" ) ( /* diff --git a/example/NexysVideo/fpga/rtl/fpga.v b/example/NexysVideo/fpga/rtl/fpga.v index 160b33784..e9cef2905 100644 --- a/example/NexysVideo/fpga/rtl/fpga.v +++ b/example/NexysVideo/fpga/rtl/fpga.v @@ -328,7 +328,9 @@ phy_rx_ctl_idelay .REGRST(1'b0) ); -fpga_core +fpga_core #( + .TARGET("XILINX") +) core_inst ( /* * Clock: 125MHz diff --git a/example/NexysVideo/fpga/rtl/fpga_core.v b/example/NexysVideo/fpga/rtl/fpga_core.v index 903ccc6ee..14275247f 100644 --- a/example/NexysVideo/fpga/rtl/fpga_core.v +++ b/example/NexysVideo/fpga/rtl/fpga_core.v @@ -31,7 +31,7 @@ THE SOFTWARE. */ module fpga_core # ( - parameter TARGET = "XILINX" + parameter TARGET = "GENERIC" ) ( /* From d1fc821c8bbdf435c74f2b84383c83c11eeef031 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 25 Dec 2020 02:03:57 -0800 Subject: [PATCH 14/37] Fix simulation startup issue in rgmii_phy_if --- rtl/rgmii_phy_if.v | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rtl/rgmii_phy_if.v b/rtl/rgmii_phy_if.v index 15f5943f5..17e3ffdeb 100644 --- a/rtl/rgmii_phy_if.v +++ b/rtl/rgmii_phy_if.v @@ -162,12 +162,12 @@ always @(posedge clk) begin end end -reg [3:0] rgmii_txd_1; -reg [3:0] rgmii_txd_2; -reg rgmii_tx_ctl_1; -reg rgmii_tx_ctl_2; +reg [3:0] rgmii_txd_1 = 0; +reg [3:0] rgmii_txd_2 = 0; +reg rgmii_tx_ctl_1 = 1'b0; +reg rgmii_tx_ctl_2 = 1'b0; -reg gmii_clk_en; +reg gmii_clk_en = 1'b1; always @* begin if (speed == 2'b00) begin From 4d31316fef5ea7e92be4019ebb79047c146724d2 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 25 Dec 2020 02:09:50 -0800 Subject: [PATCH 15/37] Remove travis-ci --- .travis.yml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 15f9a3c31..000000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: python -python: - - "3.6" -before_install: - - export d=`pwd` - - export PYTHON_EXE=`which python` - - sudo apt-get update -qq - - sudo apt-get install -y iverilog - - git clone https://github.com/jandecaluwe/myhdl.git - - cd $d/myhdl && sudo $PYTHON_EXE setup.py install - - cd $d/myhdl/cosimulation/icarus && make && sudo install -m 0755 -D ./myhdl.vpi /usr/lib/x86_64-linux-gnu/ivl/myhdl.vpi - - cd $d -script: - - cd tb && py.test - From 079d6329cb212d18f50b7cae30b264daf1efa097 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 01:11:03 -0800 Subject: [PATCH 16/37] Migrate example design testbenches to cocotb --- example/ADM_PCIE_9V3/fpga_10g/tb/arp_ep.py | 1 - example/ADM_PCIE_9V3/fpga_10g/tb/axis_ep.py | 1 - example/ADM_PCIE_9V3/fpga_10g/tb/eth_ep.py | 1 - .../fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 289 ++++++++ example/ADM_PCIE_9V3/fpga_10g/tb/ip_ep.py | 1 - .../fpga_10g/tb/test_fpga_core.py | 463 ------------ .../ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.v | 269 ------- example/ADM_PCIE_9V3/fpga_10g/tb/udp_ep.py | 1 - example/ADM_PCIE_9V3/fpga_10g/tb/xgmii_ep.py | 1 - example/ADM_PCIE_9V3/fpga_25g/tb/arp_ep.py | 1 - example/ADM_PCIE_9V3/fpga_25g/tb/axis_ep.py | 1 - example/ADM_PCIE_9V3/fpga_25g/tb/eth_ep.py | 1 - .../fpga_25g/tb/fpga_core/Makefile | 99 +++ .../fpga_25g/tb/fpga_core/test_fpga_core.py | 289 ++++++++ example/ADM_PCIE_9V3/fpga_25g/tb/ip_ep.py | 1 - .../fpga_25g/tb/test_fpga_core.py | 463 ------------ .../ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.v | 269 ------- example/ADM_PCIE_9V3/fpga_25g/tb/udp_ep.py | 1 - example/ADM_PCIE_9V3/fpga_25g/tb/xgmii_ep.py | 1 - example/ATLYS/fpga/tb/arp_ep.py | 1 - example/ATLYS/fpga/tb/axis_ep.py | 1 - example/ATLYS/fpga/tb/eth_ep.py | 1 - example/ATLYS/fpga/tb/fpga_core/Makefile | 105 +++ .../ATLYS/fpga/tb/fpga_core/test_fpga_core.py | 216 ++++++ example/ATLYS/fpga/tb/gmii_ep.py | 1 - example/ATLYS/fpga/tb/ip_ep.py | 1 - example/ATLYS/fpga/tb/test_fpga_core.py | 311 -------- example/ATLYS/fpga/tb/test_fpga_core.v | 125 ---- example/ATLYS/fpga/tb/udp_ep.py | 1 - example/AU200/fpga_10g/tb/arp_ep.py | 1 - example/AU200/fpga_10g/tb/axis_ep.py | 1 - example/AU200/fpga_10g/tb/eth_ep.py | 1 - example/AU200/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 289 ++++++++ example/AU200/fpga_10g/tb/ip_ep.py | 1 - example/AU200/fpga_10g/tb/test_fpga_core.py | 465 ------------ example/AU200/fpga_10g/tb/test_fpga_core.v | 269 ------- example/AU200/fpga_10g/tb/udp_ep.py | 1 - example/AU200/fpga_10g/tb/xgmii_ep.py | 1 - example/AU250/fpga_10g/tb/arp_ep.py | 1 - example/AU250/fpga_10g/tb/axis_ep.py | 1 - example/AU250/fpga_10g/tb/eth_ep.py | 1 - example/AU250/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 289 ++++++++ example/AU250/fpga_10g/tb/ip_ep.py | 1 - example/AU250/fpga_10g/tb/test_fpga_core.py | 465 ------------ example/AU250/fpga_10g/tb/test_fpga_core.v | 269 ------- example/AU250/fpga_10g/tb/udp_ep.py | 1 - example/AU250/fpga_10g/tb/xgmii_ep.py | 1 - example/AU280/fpga_10g/tb/arp_ep.py | 1 - example/AU280/fpga_10g/tb/axis_ep.py | 1 - example/AU280/fpga_10g/tb/eth_ep.py | 1 - example/AU280/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 287 ++++++++ example/AU280/fpga_10g/tb/ip_ep.py | 1 - example/AU280/fpga_10g/tb/test_fpga_core.py | 455 ------------ example/AU280/fpga_10g/tb/test_fpga_core.v | 257 ------- example/AU280/fpga_10g/tb/udp_ep.py | 1 - example/AU280/fpga_10g/tb/xgmii_ep.py | 1 - example/AU50/fpga_10g/tb/arp_ep.py | 1 - example/AU50/fpga_10g/tb/axis_ep.py | 1 - example/AU50/fpga_10g/tb/eth_ep.py | 1 - example/AU50/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 243 +++++++ example/AU50/fpga_10g/tb/ip_ep.py | 1 - example/AU50/fpga_10g/tb/test_fpga_core.py | 343 --------- example/AU50/fpga_10g/tb/test_fpga_core.v | 161 ---- example/AU50/fpga_10g/tb/udp_ep.py | 1 - example/AU50/fpga_10g/tb/xgmii_ep.py | 1 - example/Arty/fpga/tb/arp_ep.py | 1 - example/Arty/fpga/tb/axis_ep.py | 1 - example/Arty/fpga/tb/eth_ep.py | 1 - example/Arty/fpga/tb/fpga_core/Makefile | 102 +++ .../Arty/fpga/tb/fpga_core/test_fpga_core.py | 211 ++++++ example/Arty/fpga/tb/ip_ep.py | 1 - example/Arty/fpga/tb/mii_ep.py | 1 - example/Arty/fpga/tb/test_fpga_core.py | 326 --------- example/Arty/fpga/tb/test_fpga_core.v | 158 ---- example/Arty/fpga/tb/udp_ep.py | 1 - example/C10LP/fpga/tb/arp_ep.py | 1 - example/C10LP/fpga/tb/axis_ep.py | 1 - example/C10LP/fpga/tb/eth_ep.py | 1 - example/C10LP/fpga/tb/fpga_core/Makefile | 104 +++ .../C10LP/fpga/tb/fpga_core/test_fpga_core.py | 225 ++++++ example/C10LP/fpga/tb/gmii_ep.py | 1 - example/C10LP/fpga/tb/ip_ep.py | 1 - example/C10LP/fpga/tb/rgmii_ep.py | 1 - example/C10LP/fpga/tb/test_fpga_core.py | 302 -------- example/C10LP/fpga/tb/test_fpga_core.v | 104 --- example/C10LP/fpga/tb/udp_ep.py | 1 - example/DE2-115/fpga/tb/arp_ep.py | 1 - example/DE2-115/fpga/tb/axis_ep.py | 1 - example/DE2-115/fpga/tb/eth_ep.py | 1 - example/DE2-115/fpga/tb/fpga_core/Makefile | 105 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 230 ++++++ example/DE2-115/fpga/tb/gmii_ep.py | 1 - example/DE2-115/fpga/tb/ip_ep.py | 1 - example/DE2-115/fpga/tb/rgmii_ep.py | 1 - example/DE2-115/fpga/tb/test_fpga_core.py | 364 --------- example/DE2-115/fpga/tb/test_fpga_core.v | 158 ---- example/DE2-115/fpga/tb/udp_ep.py | 1 - example/DE5-Net/fpga/tb/arp_ep.py | 1 - example/DE5-Net/fpga/tb/axis_ep.py | 1 - example/DE5-Net/fpga/tb/eth_ep.py | 1 - example/DE5-Net/fpga/tb/fpga_core/Makefile | 99 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 214 ++++++ example/DE5-Net/fpga/tb/ip_ep.py | 1 - example/DE5-Net/fpga/tb/test_fpga_core.py | 303 -------- example/DE5-Net/fpga/tb/test_fpga_core.v | 137 ---- example/DE5-Net/fpga/tb/udp_ep.py | 1 - example/DE5-Net/fpga/tb/xgmii_ep.py | 1 - example/ExaNIC_X10/fpga/tb/arp_ep.py | 1 - example/ExaNIC_X10/fpga/tb/axis_ep.py | 1 - example/ExaNIC_X10/fpga/tb/eth_ep.py | 1 - example/ExaNIC_X10/fpga/tb/fpga_core/Makefile | 99 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 221 ++++++ example/ExaNIC_X10/fpga/tb/ip_ep.py | 1 - example/ExaNIC_X10/fpga/tb/test_fpga_core.py | 292 -------- example/ExaNIC_X10/fpga/tb/test_fpga_core.v | 122 ---- example/ExaNIC_X10/fpga/tb/udp_ep.py | 1 - example/ExaNIC_X10/fpga/tb/xgmii_ep.py | 1 - example/ExaNIC_X25/fpga_10g/tb/arp_ep.py | 1 - example/ExaNIC_X25/fpga_10g/tb/axis_ep.py | 1 - example/ExaNIC_X25/fpga_10g/tb/eth_ep.py | 1 - .../ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 221 ++++++ example/ExaNIC_X25/fpga_10g/tb/ip_ep.py | 1 - .../ExaNIC_X25/fpga_10g/tb/test_fpga_core.py | 292 -------- .../ExaNIC_X25/fpga_10g/tb/test_fpga_core.v | 122 ---- example/ExaNIC_X25/fpga_10g/tb/udp_ep.py | 1 - example/ExaNIC_X25/fpga_10g/tb/xgmii_ep.py | 1 - example/HXT100G/fpga/tb/arp_ep.py | 1 - example/HXT100G/fpga/tb/axis_ep.py | 1 - example/HXT100G/fpga/tb/eth_ep.py | 1 - example/HXT100G/fpga/tb/fpga_core/Makefile | 99 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 280 +++++++ example/HXT100G/fpga/tb/ip_ep.py | 1 - example/HXT100G/fpga/tb/test_fpga_core.py | 611 ---------------- example/HXT100G/fpga/tb/test_fpga_core.v | 416 ----------- example/HXT100G/fpga/tb/udp_ep.py | 1 - example/HXT100G/fpga/tb/xgmii_ep.py | 1 - example/HXT100G/fpga_cxpt16/tb/axis_ep.py | 1 - example/HXT100G/fpga_cxpt16/tb/eth_ep.py | 1 - .../HXT100G/fpga_cxpt16/tb/fpga_core/Makefile | 81 +++ .../tb/fpga_core/test_fpga_core.py | 249 +++++++ .../HXT100G/fpga_cxpt16/tb/test_fpga_core.py | 544 -------------- .../HXT100G/fpga_cxpt16/tb/test_fpga_core.v | 416 ----------- example/HXT100G/fpga_cxpt16/tb/xgmii_ep.py | 1 - example/KC705/fpga_gmii/tb/arp_ep.py | 1 - example/KC705/fpga_gmii/tb/axis_ep.py | 1 - example/KC705/fpga_gmii/tb/eth_ep.py | 1 - example/KC705/fpga_gmii/tb/fpga_core/Makefile | 105 +++ .../fpga_gmii/tb/fpga_core/test_fpga_core.py | 217 ++++++ example/KC705/fpga_gmii/tb/gmii_ep.py | 1 - example/KC705/fpga_gmii/tb/ip_ep.py | 1 - example/KC705/fpga_gmii/tb/test_fpga_core.py | 316 -------- example/KC705/fpga_gmii/tb/test_fpga_core.v | 134 ---- example/KC705/fpga_gmii/tb/udp_ep.py | 1 - example/ML605/fpga_gmii/tb/arp_ep.py | 1 - example/ML605/fpga_gmii/tb/axis_ep.py | 1 - example/ML605/fpga_gmii/tb/eth_ep.py | 1 - example/ML605/fpga_gmii/tb/fpga_core/Makefile | 105 +++ .../fpga_gmii/tb/fpga_core/test_fpga_core.py | 217 ++++++ example/ML605/fpga_gmii/tb/gmii_ep.py | 1 - example/ML605/fpga_gmii/tb/ip_ep.py | 1 - example/ML605/fpga_gmii/tb/test_fpga_core.py | 330 --------- example/ML605/fpga_gmii/tb/test_fpga_core.v | 146 ---- example/ML605/fpga_gmii/tb/udp_ep.py | 1 - example/ML605/fpga_rgmii/tb/arp_ep.py | 1 - example/ML605/fpga_rgmii/tb/axis_ep.py | 1 - example/ML605/fpga_rgmii/tb/eth_ep.py | 1 - .../ML605/fpga_rgmii/tb/fpga_core/Makefile | 104 +++ .../fpga_rgmii/tb/fpga_core/test_fpga_core.py | 229 ++++++ example/ML605/fpga_rgmii/tb/gmii_ep.py | 1 - example/ML605/fpga_rgmii/tb/ip_ep.py | 1 - example/ML605/fpga_rgmii/tb/rgmii_ep.py | 1 - example/ML605/fpga_rgmii/tb/test_fpga_core.py | 330 --------- example/ML605/fpga_rgmii/tb/test_fpga_core.v | 140 ---- example/ML605/fpga_rgmii/tb/udp_ep.py | 1 - example/ML605/fpga_sgmii/tb/arp_ep.py | 1 - example/ML605/fpga_sgmii/tb/axis_ep.py | 1 - example/ML605/fpga_sgmii/tb/eth_ep.py | 1 - .../ML605/fpga_sgmii/tb/fpga_core/Makefile | 99 +++ .../fpga_sgmii/tb/fpga_core/test_fpga_core.py | 218 ++++++ example/ML605/fpga_sgmii/tb/gmii_ep.py | 1 - example/ML605/fpga_sgmii/tb/ip_ep.py | 1 - example/ML605/fpga_sgmii/tb/test_fpga_core.py | 327 --------- example/ML605/fpga_sgmii/tb/test_fpga_core.v | 143 ---- example/ML605/fpga_sgmii/tb/udp_ep.py | 1 - example/NetFPGA_SUME/fpga/tb/arp_ep.py | 1 - example/NetFPGA_SUME/fpga/tb/axis_ep.py | 1 - example/NetFPGA_SUME/fpga/tb/eth_ep.py | 1 - .../NetFPGA_SUME/fpga/tb/fpga_core/Makefile | 99 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 245 +++++++ example/NetFPGA_SUME/fpga/tb/ip_ep.py | 1 - .../NetFPGA_SUME/fpga/tb/test_fpga_core.py | 350 --------- example/NetFPGA_SUME/fpga/tb/test_fpga_core.v | 179 ----- example/NetFPGA_SUME/fpga/tb/udp_ep.py | 1 - example/NetFPGA_SUME/fpga/tb/xgmii_ep.py | 1 - example/NexysVideo/fpga/tb/arp_ep.py | 1 - example/NexysVideo/fpga/tb/axis_ep.py | 1 - example/NexysVideo/fpga/tb/eth_ep.py | 1 - example/NexysVideo/fpga/tb/fpga_core/Makefile | 104 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 231 ++++++ example/NexysVideo/fpga/tb/gmii_ep.py | 1 - example/NexysVideo/fpga/tb/ip_ep.py | 1 - example/NexysVideo/fpga/tb/rgmii_ep.py | 1 - example/NexysVideo/fpga/tb/test_fpga_core.py | 315 -------- example/NexysVideo/fpga/tb/test_fpga_core.v | 125 ---- example/NexysVideo/fpga/tb/udp_ep.py | 1 - example/VCU108/fpga_10g/tb/arp_ep.py | 1 - example/VCU108/fpga_10g/tb/axis_ep.py | 1 - example/VCU108/fpga_10g/tb/eth_ep.py | 1 - example/VCU108/fpga_10g/tb/fpga_core/Makefile | 106 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 358 +++++++++ example/VCU108/fpga_10g/tb/gmii_ep.py | 1 - example/VCU108/fpga_10g/tb/ip_ep.py | 1 - example/VCU108/fpga_10g/tb/test_fpga_core.py | 576 --------------- example/VCU108/fpga_10g/tb/test_fpga_core.v | 228 ------ example/VCU108/fpga_10g/tb/udp_ep.py | 1 - example/VCU108/fpga_10g/tb/xgmii_ep.py | 1 - example/VCU108/fpga_1g/tb/arp_ep.py | 1 - example/VCU108/fpga_1g/tb/axis_ep.py | 1 - example/VCU108/fpga_1g/tb/eth_ep.py | 1 - example/VCU108/fpga_1g/tb/fpga_core/Makefile | 99 +++ .../fpga_1g/tb/fpga_core/test_fpga_core.py | 218 ++++++ example/VCU108/fpga_1g/tb/gmii_ep.py | 1 - example/VCU108/fpga_1g/tb/ip_ep.py | 1 - example/VCU108/fpga_1g/tb/test_fpga_core.py | 314 -------- example/VCU108/fpga_1g/tb/test_fpga_core.v | 131 ---- example/VCU108/fpga_1g/tb/udp_ep.py | 1 - example/VCU118/fpga_10g/tb/arp_ep.py | 1 - example/VCU118/fpga_10g/tb/axis_ep.py | 1 - example/VCU118/fpga_10g/tb/eth_ep.py | 1 - example/VCU118/fpga_10g/tb/fpga_core/Makefile | 106 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 402 ++++++++++ example/VCU118/fpga_10g/tb/gmii_ep.py | 1 - example/VCU118/fpga_10g/tb/ip_ep.py | 1 - example/VCU118/fpga_10g/tb/test_fpga_core.py | 688 ------------------ example/VCU118/fpga_10g/tb/test_fpga_core.v | 324 --------- example/VCU118/fpga_10g/tb/udp_ep.py | 1 - example/VCU118/fpga_10g/tb/xgmii_ep.py | 1 - example/VCU118/fpga_1g/tb/arp_ep.py | 1 - example/VCU118/fpga_1g/tb/axis_ep.py | 1 - example/VCU118/fpga_1g/tb/eth_ep.py | 1 - example/VCU118/fpga_1g/tb/fpga_core/Makefile | 99 +++ .../fpga_1g/tb/fpga_core/test_fpga_core.py | 218 ++++++ example/VCU118/fpga_1g/tb/gmii_ep.py | 1 - example/VCU118/fpga_1g/tb/ip_ep.py | 1 - example/VCU118/fpga_1g/tb/test_fpga_core.py | 314 -------- example/VCU118/fpga_1g/tb/test_fpga_core.v | 131 ---- example/VCU118/fpga_1g/tb/udp_ep.py | 1 - example/VCU118/fpga_25g/tb/arp_ep.py | 1 - example/VCU118/fpga_25g/tb/axis_ep.py | 1 - example/VCU118/fpga_25g/tb/eth_ep.py | 1 - example/VCU118/fpga_25g/tb/fpga_core/Makefile | 106 +++ .../fpga_25g/tb/fpga_core/test_fpga_core.py | 402 ++++++++++ example/VCU118/fpga_25g/tb/gmii_ep.py | 1 - example/VCU118/fpga_25g/tb/ip_ep.py | 1 - example/VCU118/fpga_25g/tb/test_fpga_core.py | 688 ------------------ example/VCU118/fpga_25g/tb/test_fpga_core.v | 324 --------- example/VCU118/fpga_25g/tb/udp_ep.py | 1 - example/VCU118/fpga_25g/tb/xgmii_ep.py | 1 - example/VCU1525/fpga_10g/tb/arp_ep.py | 1 - example/VCU1525/fpga_10g/tb/axis_ep.py | 1 - example/VCU1525/fpga_10g/tb/eth_ep.py | 1 - .../VCU1525/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 289 ++++++++ example/VCU1525/fpga_10g/tb/ip_ep.py | 1 - example/VCU1525/fpga_10g/tb/test_fpga_core.py | 465 ------------ example/VCU1525/fpga_10g/tb/test_fpga_core.v | 269 ------- example/VCU1525/fpga_10g/tb/udp_ep.py | 1 - example/VCU1525/fpga_10g/tb/xgmii_ep.py | 1 - example/ZCU102/fpga/tb/arp_ep.py | 1 - example/ZCU102/fpga/tb/axis_ep.py | 1 - example/ZCU102/fpga/tb/eth_ep.py | 1 - example/ZCU102/fpga/tb/fpga_core/Makefile | 99 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 252 +++++++ example/ZCU102/fpga/tb/gmii_ep.py | 1 - example/ZCU102/fpga/tb/ip_ep.py | 1 - example/ZCU102/fpga/tb/test_fpga_core.py | 374 ---------- example/ZCU102/fpga/tb/test_fpga_core.v | 194 ----- example/ZCU102/fpga/tb/udp_ep.py | 1 - example/ZCU102/fpga/tb/xgmii_ep.py | 1 - example/ZCU106/fpga/tb/arp_ep.py | 1 - example/ZCU106/fpga/tb/axis_ep.py | 1 - example/ZCU106/fpga/tb/eth_ep.py | 1 - example/ZCU106/fpga/tb/fpga_core/Makefile | 99 +++ .../fpga/tb/fpga_core/test_fpga_core.py | 230 ++++++ example/ZCU106/fpga/tb/gmii_ep.py | 1 - example/ZCU106/fpga/tb/ip_ep.py | 1 - example/ZCU106/fpga/tb/test_fpga_core.py | 318 -------- example/ZCU106/fpga/tb/test_fpga_core.v | 150 ---- example/ZCU106/fpga/tb/udp_ep.py | 1 - example/ZCU106/fpga/tb/xgmii_ep.py | 1 - example/fb2CG/fpga_10g/tb/arp_ep.py | 1 - example/fb2CG/fpga_10g/tb/axis_ep.py | 1 - example/fb2CG/fpga_10g/tb/eth_ep.py | 1 - example/fb2CG/fpga_10g/tb/fpga_core/Makefile | 99 +++ .../fpga_10g/tb/fpga_core/test_fpga_core.py | 287 ++++++++ example/fb2CG/fpga_10g/tb/ip_ep.py | 1 - example/fb2CG/fpga_10g/tb/test_fpga_core.py | 463 ------------ example/fb2CG/fpga_10g/tb/test_fpga_core.v | 269 ------- example/fb2CG/fpga_10g/tb/udp_ep.py | 1 - example/fb2CG/fpga_10g/tb/xgmii_ep.py | 1 - 306 files changed, 10781 insertions(+), 18492 deletions(-) delete mode 120000 example/ADM_PCIE_9V3/fpga_10g/tb/arp_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_10g/tb/axis_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_10g/tb/eth_ep.py create mode 100644 example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ADM_PCIE_9V3/fpga_10g/tb/ip_ep.py delete mode 100755 example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/ADM_PCIE_9V3/fpga_10g/tb/udp_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_25g/tb/arp_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_25g/tb/axis_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_25g/tb/eth_ep.py create mode 100644 example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile create mode 100644 example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ADM_PCIE_9V3/fpga_25g/tb/ip_ep.py delete mode 100755 example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.py delete mode 100644 example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.v delete mode 120000 example/ADM_PCIE_9V3/fpga_25g/tb/udp_ep.py delete mode 120000 example/ADM_PCIE_9V3/fpga_25g/tb/xgmii_ep.py delete mode 120000 example/ATLYS/fpga/tb/arp_ep.py delete mode 120000 example/ATLYS/fpga/tb/axis_ep.py delete mode 120000 example/ATLYS/fpga/tb/eth_ep.py create mode 100644 example/ATLYS/fpga/tb/fpga_core/Makefile create mode 100644 example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ATLYS/fpga/tb/gmii_ep.py delete mode 120000 example/ATLYS/fpga/tb/ip_ep.py delete mode 100755 example/ATLYS/fpga/tb/test_fpga_core.py delete mode 100644 example/ATLYS/fpga/tb/test_fpga_core.v delete mode 120000 example/ATLYS/fpga/tb/udp_ep.py delete mode 120000 example/AU200/fpga_10g/tb/arp_ep.py delete mode 120000 example/AU200/fpga_10g/tb/axis_ep.py delete mode 120000 example/AU200/fpga_10g/tb/eth_ep.py create mode 100644 example/AU200/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/AU200/fpga_10g/tb/ip_ep.py delete mode 100755 example/AU200/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/AU200/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/AU200/fpga_10g/tb/udp_ep.py delete mode 120000 example/AU200/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/AU250/fpga_10g/tb/arp_ep.py delete mode 120000 example/AU250/fpga_10g/tb/axis_ep.py delete mode 120000 example/AU250/fpga_10g/tb/eth_ep.py create mode 100644 example/AU250/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/AU250/fpga_10g/tb/ip_ep.py delete mode 100755 example/AU250/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/AU250/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/AU250/fpga_10g/tb/udp_ep.py delete mode 120000 example/AU250/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/AU280/fpga_10g/tb/arp_ep.py delete mode 120000 example/AU280/fpga_10g/tb/axis_ep.py delete mode 120000 example/AU280/fpga_10g/tb/eth_ep.py create mode 100644 example/AU280/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/AU280/fpga_10g/tb/ip_ep.py delete mode 100755 example/AU280/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/AU280/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/AU280/fpga_10g/tb/udp_ep.py delete mode 120000 example/AU280/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/AU50/fpga_10g/tb/arp_ep.py delete mode 120000 example/AU50/fpga_10g/tb/axis_ep.py delete mode 120000 example/AU50/fpga_10g/tb/eth_ep.py create mode 100644 example/AU50/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/AU50/fpga_10g/tb/ip_ep.py delete mode 100755 example/AU50/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/AU50/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/AU50/fpga_10g/tb/udp_ep.py delete mode 120000 example/AU50/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/Arty/fpga/tb/arp_ep.py delete mode 120000 example/Arty/fpga/tb/axis_ep.py delete mode 120000 example/Arty/fpga/tb/eth_ep.py create mode 100644 example/Arty/fpga/tb/fpga_core/Makefile create mode 100644 example/Arty/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/Arty/fpga/tb/ip_ep.py delete mode 120000 example/Arty/fpga/tb/mii_ep.py delete mode 100755 example/Arty/fpga/tb/test_fpga_core.py delete mode 100644 example/Arty/fpga/tb/test_fpga_core.v delete mode 120000 example/Arty/fpga/tb/udp_ep.py delete mode 120000 example/C10LP/fpga/tb/arp_ep.py delete mode 120000 example/C10LP/fpga/tb/axis_ep.py delete mode 120000 example/C10LP/fpga/tb/eth_ep.py create mode 100644 example/C10LP/fpga/tb/fpga_core/Makefile create mode 100644 example/C10LP/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/C10LP/fpga/tb/gmii_ep.py delete mode 120000 example/C10LP/fpga/tb/ip_ep.py delete mode 120000 example/C10LP/fpga/tb/rgmii_ep.py delete mode 100755 example/C10LP/fpga/tb/test_fpga_core.py delete mode 100644 example/C10LP/fpga/tb/test_fpga_core.v delete mode 120000 example/C10LP/fpga/tb/udp_ep.py delete mode 120000 example/DE2-115/fpga/tb/arp_ep.py delete mode 120000 example/DE2-115/fpga/tb/axis_ep.py delete mode 120000 example/DE2-115/fpga/tb/eth_ep.py create mode 100644 example/DE2-115/fpga/tb/fpga_core/Makefile create mode 100644 example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/DE2-115/fpga/tb/gmii_ep.py delete mode 120000 example/DE2-115/fpga/tb/ip_ep.py delete mode 120000 example/DE2-115/fpga/tb/rgmii_ep.py delete mode 100755 example/DE2-115/fpga/tb/test_fpga_core.py delete mode 100644 example/DE2-115/fpga/tb/test_fpga_core.v delete mode 120000 example/DE2-115/fpga/tb/udp_ep.py delete mode 120000 example/DE5-Net/fpga/tb/arp_ep.py delete mode 120000 example/DE5-Net/fpga/tb/axis_ep.py delete mode 120000 example/DE5-Net/fpga/tb/eth_ep.py create mode 100644 example/DE5-Net/fpga/tb/fpga_core/Makefile create mode 100644 example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/DE5-Net/fpga/tb/ip_ep.py delete mode 100755 example/DE5-Net/fpga/tb/test_fpga_core.py delete mode 100644 example/DE5-Net/fpga/tb/test_fpga_core.v delete mode 120000 example/DE5-Net/fpga/tb/udp_ep.py delete mode 120000 example/DE5-Net/fpga/tb/xgmii_ep.py delete mode 120000 example/ExaNIC_X10/fpga/tb/arp_ep.py delete mode 120000 example/ExaNIC_X10/fpga/tb/axis_ep.py delete mode 120000 example/ExaNIC_X10/fpga/tb/eth_ep.py create mode 100644 example/ExaNIC_X10/fpga/tb/fpga_core/Makefile create mode 100644 example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ExaNIC_X10/fpga/tb/ip_ep.py delete mode 100755 example/ExaNIC_X10/fpga/tb/test_fpga_core.py delete mode 100644 example/ExaNIC_X10/fpga/tb/test_fpga_core.v delete mode 120000 example/ExaNIC_X10/fpga/tb/udp_ep.py delete mode 120000 example/ExaNIC_X10/fpga/tb/xgmii_ep.py delete mode 120000 example/ExaNIC_X25/fpga_10g/tb/arp_ep.py delete mode 120000 example/ExaNIC_X25/fpga_10g/tb/axis_ep.py delete mode 120000 example/ExaNIC_X25/fpga_10g/tb/eth_ep.py create mode 100644 example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ExaNIC_X25/fpga_10g/tb/ip_ep.py delete mode 100755 example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/ExaNIC_X25/fpga_10g/tb/udp_ep.py delete mode 120000 example/ExaNIC_X25/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/HXT100G/fpga/tb/arp_ep.py delete mode 120000 example/HXT100G/fpga/tb/axis_ep.py delete mode 120000 example/HXT100G/fpga/tb/eth_ep.py create mode 100644 example/HXT100G/fpga/tb/fpga_core/Makefile create mode 100644 example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/HXT100G/fpga/tb/ip_ep.py delete mode 100755 example/HXT100G/fpga/tb/test_fpga_core.py delete mode 100644 example/HXT100G/fpga/tb/test_fpga_core.v delete mode 120000 example/HXT100G/fpga/tb/udp_ep.py delete mode 120000 example/HXT100G/fpga/tb/xgmii_ep.py delete mode 120000 example/HXT100G/fpga_cxpt16/tb/axis_ep.py delete mode 120000 example/HXT100G/fpga_cxpt16/tb/eth_ep.py create mode 100644 example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile create mode 100644 example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py delete mode 100755 example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py delete mode 100644 example/HXT100G/fpga_cxpt16/tb/test_fpga_core.v delete mode 120000 example/HXT100G/fpga_cxpt16/tb/xgmii_ep.py delete mode 120000 example/KC705/fpga_gmii/tb/arp_ep.py delete mode 120000 example/KC705/fpga_gmii/tb/axis_ep.py delete mode 120000 example/KC705/fpga_gmii/tb/eth_ep.py create mode 100644 example/KC705/fpga_gmii/tb/fpga_core/Makefile create mode 100644 example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py delete mode 120000 example/KC705/fpga_gmii/tb/gmii_ep.py delete mode 120000 example/KC705/fpga_gmii/tb/ip_ep.py delete mode 100755 example/KC705/fpga_gmii/tb/test_fpga_core.py delete mode 100644 example/KC705/fpga_gmii/tb/test_fpga_core.v delete mode 120000 example/KC705/fpga_gmii/tb/udp_ep.py delete mode 120000 example/ML605/fpga_gmii/tb/arp_ep.py delete mode 120000 example/ML605/fpga_gmii/tb/axis_ep.py delete mode 120000 example/ML605/fpga_gmii/tb/eth_ep.py create mode 100644 example/ML605/fpga_gmii/tb/fpga_core/Makefile create mode 100644 example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ML605/fpga_gmii/tb/gmii_ep.py delete mode 120000 example/ML605/fpga_gmii/tb/ip_ep.py delete mode 100755 example/ML605/fpga_gmii/tb/test_fpga_core.py delete mode 100644 example/ML605/fpga_gmii/tb/test_fpga_core.v delete mode 120000 example/ML605/fpga_gmii/tb/udp_ep.py delete mode 120000 example/ML605/fpga_rgmii/tb/arp_ep.py delete mode 120000 example/ML605/fpga_rgmii/tb/axis_ep.py delete mode 120000 example/ML605/fpga_rgmii/tb/eth_ep.py create mode 100644 example/ML605/fpga_rgmii/tb/fpga_core/Makefile create mode 100644 example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ML605/fpga_rgmii/tb/gmii_ep.py delete mode 120000 example/ML605/fpga_rgmii/tb/ip_ep.py delete mode 120000 example/ML605/fpga_rgmii/tb/rgmii_ep.py delete mode 100755 example/ML605/fpga_rgmii/tb/test_fpga_core.py delete mode 100644 example/ML605/fpga_rgmii/tb/test_fpga_core.v delete mode 120000 example/ML605/fpga_rgmii/tb/udp_ep.py delete mode 120000 example/ML605/fpga_sgmii/tb/arp_ep.py delete mode 120000 example/ML605/fpga_sgmii/tb/axis_ep.py delete mode 120000 example/ML605/fpga_sgmii/tb/eth_ep.py create mode 100644 example/ML605/fpga_sgmii/tb/fpga_core/Makefile create mode 100644 example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ML605/fpga_sgmii/tb/gmii_ep.py delete mode 120000 example/ML605/fpga_sgmii/tb/ip_ep.py delete mode 100755 example/ML605/fpga_sgmii/tb/test_fpga_core.py delete mode 100644 example/ML605/fpga_sgmii/tb/test_fpga_core.v delete mode 120000 example/ML605/fpga_sgmii/tb/udp_ep.py delete mode 120000 example/NetFPGA_SUME/fpga/tb/arp_ep.py delete mode 120000 example/NetFPGA_SUME/fpga/tb/axis_ep.py delete mode 120000 example/NetFPGA_SUME/fpga/tb/eth_ep.py create mode 100644 example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile create mode 100644 example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/NetFPGA_SUME/fpga/tb/ip_ep.py delete mode 100755 example/NetFPGA_SUME/fpga/tb/test_fpga_core.py delete mode 100644 example/NetFPGA_SUME/fpga/tb/test_fpga_core.v delete mode 120000 example/NetFPGA_SUME/fpga/tb/udp_ep.py delete mode 120000 example/NetFPGA_SUME/fpga/tb/xgmii_ep.py delete mode 120000 example/NexysVideo/fpga/tb/arp_ep.py delete mode 120000 example/NexysVideo/fpga/tb/axis_ep.py delete mode 120000 example/NexysVideo/fpga/tb/eth_ep.py create mode 100644 example/NexysVideo/fpga/tb/fpga_core/Makefile create mode 100644 example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/NexysVideo/fpga/tb/gmii_ep.py delete mode 120000 example/NexysVideo/fpga/tb/ip_ep.py delete mode 120000 example/NexysVideo/fpga/tb/rgmii_ep.py delete mode 100755 example/NexysVideo/fpga/tb/test_fpga_core.py delete mode 100644 example/NexysVideo/fpga/tb/test_fpga_core.v delete mode 120000 example/NexysVideo/fpga/tb/udp_ep.py delete mode 120000 example/VCU108/fpga_10g/tb/arp_ep.py delete mode 120000 example/VCU108/fpga_10g/tb/axis_ep.py delete mode 120000 example/VCU108/fpga_10g/tb/eth_ep.py create mode 100644 example/VCU108/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/VCU108/fpga_10g/tb/gmii_ep.py delete mode 120000 example/VCU108/fpga_10g/tb/ip_ep.py delete mode 100755 example/VCU108/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/VCU108/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/VCU108/fpga_10g/tb/udp_ep.py delete mode 120000 example/VCU108/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/VCU108/fpga_1g/tb/arp_ep.py delete mode 120000 example/VCU108/fpga_1g/tb/axis_ep.py delete mode 120000 example/VCU108/fpga_1g/tb/eth_ep.py create mode 100644 example/VCU108/fpga_1g/tb/fpga_core/Makefile create mode 100644 example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/VCU108/fpga_1g/tb/gmii_ep.py delete mode 120000 example/VCU108/fpga_1g/tb/ip_ep.py delete mode 100755 example/VCU108/fpga_1g/tb/test_fpga_core.py delete mode 100644 example/VCU108/fpga_1g/tb/test_fpga_core.v delete mode 120000 example/VCU108/fpga_1g/tb/udp_ep.py delete mode 120000 example/VCU118/fpga_10g/tb/arp_ep.py delete mode 120000 example/VCU118/fpga_10g/tb/axis_ep.py delete mode 120000 example/VCU118/fpga_10g/tb/eth_ep.py create mode 100644 example/VCU118/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/VCU118/fpga_10g/tb/gmii_ep.py delete mode 120000 example/VCU118/fpga_10g/tb/ip_ep.py delete mode 100755 example/VCU118/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/VCU118/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/VCU118/fpga_10g/tb/udp_ep.py delete mode 120000 example/VCU118/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/VCU118/fpga_1g/tb/arp_ep.py delete mode 120000 example/VCU118/fpga_1g/tb/axis_ep.py delete mode 120000 example/VCU118/fpga_1g/tb/eth_ep.py create mode 100644 example/VCU118/fpga_1g/tb/fpga_core/Makefile create mode 100644 example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/VCU118/fpga_1g/tb/gmii_ep.py delete mode 120000 example/VCU118/fpga_1g/tb/ip_ep.py delete mode 100755 example/VCU118/fpga_1g/tb/test_fpga_core.py delete mode 100644 example/VCU118/fpga_1g/tb/test_fpga_core.v delete mode 120000 example/VCU118/fpga_1g/tb/udp_ep.py delete mode 120000 example/VCU118/fpga_25g/tb/arp_ep.py delete mode 120000 example/VCU118/fpga_25g/tb/axis_ep.py delete mode 120000 example/VCU118/fpga_25g/tb/eth_ep.py create mode 100644 example/VCU118/fpga_25g/tb/fpga_core/Makefile create mode 100644 example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/VCU118/fpga_25g/tb/gmii_ep.py delete mode 120000 example/VCU118/fpga_25g/tb/ip_ep.py delete mode 100755 example/VCU118/fpga_25g/tb/test_fpga_core.py delete mode 100644 example/VCU118/fpga_25g/tb/test_fpga_core.v delete mode 120000 example/VCU118/fpga_25g/tb/udp_ep.py delete mode 120000 example/VCU118/fpga_25g/tb/xgmii_ep.py delete mode 120000 example/VCU1525/fpga_10g/tb/arp_ep.py delete mode 120000 example/VCU1525/fpga_10g/tb/axis_ep.py delete mode 120000 example/VCU1525/fpga_10g/tb/eth_ep.py create mode 100644 example/VCU1525/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/VCU1525/fpga_10g/tb/ip_ep.py delete mode 100755 example/VCU1525/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/VCU1525/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/VCU1525/fpga_10g/tb/udp_ep.py delete mode 120000 example/VCU1525/fpga_10g/tb/xgmii_ep.py delete mode 120000 example/ZCU102/fpga/tb/arp_ep.py delete mode 120000 example/ZCU102/fpga/tb/axis_ep.py delete mode 120000 example/ZCU102/fpga/tb/eth_ep.py create mode 100644 example/ZCU102/fpga/tb/fpga_core/Makefile create mode 100644 example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ZCU102/fpga/tb/gmii_ep.py delete mode 120000 example/ZCU102/fpga/tb/ip_ep.py delete mode 100755 example/ZCU102/fpga/tb/test_fpga_core.py delete mode 100644 example/ZCU102/fpga/tb/test_fpga_core.v delete mode 120000 example/ZCU102/fpga/tb/udp_ep.py delete mode 120000 example/ZCU102/fpga/tb/xgmii_ep.py delete mode 120000 example/ZCU106/fpga/tb/arp_ep.py delete mode 120000 example/ZCU106/fpga/tb/axis_ep.py delete mode 120000 example/ZCU106/fpga/tb/eth_ep.py create mode 100644 example/ZCU106/fpga/tb/fpga_core/Makefile create mode 100644 example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py delete mode 120000 example/ZCU106/fpga/tb/gmii_ep.py delete mode 120000 example/ZCU106/fpga/tb/ip_ep.py delete mode 100755 example/ZCU106/fpga/tb/test_fpga_core.py delete mode 100644 example/ZCU106/fpga/tb/test_fpga_core.v delete mode 120000 example/ZCU106/fpga/tb/udp_ep.py delete mode 120000 example/ZCU106/fpga/tb/xgmii_ep.py delete mode 120000 example/fb2CG/fpga_10g/tb/arp_ep.py delete mode 120000 example/fb2CG/fpga_10g/tb/axis_ep.py delete mode 120000 example/fb2CG/fpga_10g/tb/eth_ep.py create mode 100644 example/fb2CG/fpga_10g/tb/fpga_core/Makefile create mode 100644 example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py delete mode 120000 example/fb2CG/fpga_10g/tb/ip_ep.py delete mode 100755 example/fb2CG/fpga_10g/tb/test_fpga_core.py delete mode 100644 example/fb2CG/fpga_10g/tb/test_fpga_core.v delete mode 120000 example/fb2CG/fpga_10g/tb/udp_ep.py delete mode 120000 example/fb2CG/fpga_10g/tb/xgmii_ep.py diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/arp_ep.py b/example/ADM_PCIE_9V3/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/axis_ep.py b/example/ADM_PCIE_9V3/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/eth_ep.py b/example/ADM_PCIE_9V3/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..62f39e28a --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,289 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp_0_rx_clk_0, 6.4, 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) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_0, 6.4, units="ns").start()) + self.qsfp_0_0_sink = XgmiiSink(dut.qsfp_0_txd_0, dut.qsfp_0_txc_0, dut.qsfp_0_tx_clk_0, dut.qsfp_0_tx_rst_0) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_1, 6.4, units="ns").start()) + self.qsfp_0_1_source = XgmiiSource(dut.qsfp_0_rxd_1, dut.qsfp_0_rxc_1, dut.qsfp_0_rx_clk_1, dut.qsfp_0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_1, 6.4, units="ns").start()) + self.qsfp_0_1_sink = XgmiiSink(dut.qsfp_0_txd_1, dut.qsfp_0_txc_1, dut.qsfp_0_tx_clk_1, dut.qsfp_0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_2, 6.4, units="ns").start()) + self.qsfp_0_2_source = XgmiiSource(dut.qsfp_0_rxd_2, dut.qsfp_0_rxc_2, dut.qsfp_0_rx_clk_2, dut.qsfp_0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_2, 6.4, units="ns").start()) + self.qsfp_0_2_sink = XgmiiSink(dut.qsfp_0_txd_2, dut.qsfp_0_txc_2, dut.qsfp_0_tx_clk_2, dut.qsfp_0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_3, 6.4, units="ns").start()) + self.qsfp_0_3_source = XgmiiSource(dut.qsfp_0_rxd_3, dut.qsfp_0_rxc_3, dut.qsfp_0_rx_clk_3, dut.qsfp_0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_3, 6.4, units="ns").start()) + self.qsfp_0_3_sink = XgmiiSink(dut.qsfp_0_txd_3, dut.qsfp_0_txc_3, dut.qsfp_0_tx_clk_3, dut.qsfp_0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_0, 6.4, units="ns").start()) + self.qsfp_1_0_source = XgmiiSource(dut.qsfp_1_rxd_0, dut.qsfp_1_rxc_0, dut.qsfp_1_rx_clk_0, dut.qsfp_1_rx_rst_0) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_0, 6.4, units="ns").start()) + self.qsfp_1_0_sink = XgmiiSink(dut.qsfp_1_txd_0, dut.qsfp_1_txc_0, dut.qsfp_1_tx_clk_0, dut.qsfp_1_tx_rst_0) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_1_source = XgmiiSource(dut.qsfp_1_rxd_1, dut.qsfp_1_rxc_1, dut.qsfp_1_rx_clk_1, dut.qsfp_1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_1_sink = XgmiiSink(dut.qsfp_1_txd_1, dut.qsfp_1_txc_1, dut.qsfp_1_tx_clk_1, dut.qsfp_1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp_1_2_source = XgmiiSource(dut.qsfp_1_rxd_2, dut.qsfp_1_rxc_2, dut.qsfp_1_rx_clk_2, dut.qsfp_1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp_1_2_sink = XgmiiSink(dut.qsfp_1_txd_2, dut.qsfp_1_txc_2, dut.qsfp_1_tx_clk_2, dut.qsfp_1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp_1_3_source = XgmiiSource(dut.qsfp_1_rxd_3, dut.qsfp_1_rxc_3, dut.qsfp_1_rx_clk_3, dut.qsfp_1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp_1_3_sink = XgmiiSink(dut.qsfp_1_txd_3, dut.qsfp_1_txc_3, dut.qsfp_1_tx_clk_3, dut.qsfp_1_tx_rst_3) + + dut.user_sw.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_0.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_0.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_0.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_0.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_3.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp_0_rx_rst_0 <= 1 + self.dut.qsfp_0_tx_rst_0 <= 1 + self.dut.qsfp_0_rx_rst_1 <= 1 + self.dut.qsfp_0_tx_rst_1 <= 1 + self.dut.qsfp_0_rx_rst_2 <= 1 + self.dut.qsfp_0_tx_rst_2 <= 1 + self.dut.qsfp_0_rx_rst_3 <= 1 + self.dut.qsfp_0_tx_rst_3 <= 1 + self.dut.qsfp_1_rx_rst_0 <= 1 + self.dut.qsfp_1_tx_rst_0 <= 1 + self.dut.qsfp_1_rx_rst_1 <= 1 + self.dut.qsfp_1_tx_rst_1 <= 1 + self.dut.qsfp_1_rx_rst_2 <= 1 + self.dut.qsfp_1_tx_rst_2 <= 1 + self.dut.qsfp_1_rx_rst_3 <= 1 + self.dut.qsfp_1_tx_rst_3 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp_0_rx_rst_0 <= 0 + self.dut.qsfp_0_tx_rst_0 <= 0 + self.dut.qsfp_0_rx_rst_1 <= 0 + self.dut.qsfp_0_tx_rst_1 <= 0 + self.dut.qsfp_0_rx_rst_2 <= 0 + self.dut.qsfp_0_tx_rst_2 <= 0 + self.dut.qsfp_0_rx_rst_3 <= 0 + self.dut.qsfp_0_tx_rst_3 <= 0 + self.dut.qsfp_1_rx_rst_0 <= 0 + self.dut.qsfp_1_tx_rst_0 <= 0 + self.dut.qsfp_1_rx_rst_1 <= 0 + self.dut.qsfp_1_tx_rst_1 <= 0 + self.dut.qsfp_1_rx_rst_2 <= 0 + self.dut.qsfp_1_tx_rst_2 <= 0 + self.dut.qsfp_1_rx_rst_3 <= 0 + self.dut.qsfp_1_tx_rst_3 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp_0_0_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp_0_0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp_0_0_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp_0_0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/ip_ep.py b/example/ADM_PCIE_9V3/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.py b/example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index 7f0698a04..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,463 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - user_sw = Signal(intbv(0)[2:]) - qsfp_0_tx_clk_0 = Signal(bool(0)) - qsfp_0_tx_rst_0 = Signal(bool(0)) - qsfp_0_rx_clk_0 = Signal(bool(0)) - qsfp_0_rx_rst_0 = Signal(bool(0)) - qsfp_0_rxd_0 = Signal(intbv(0)[64:]) - qsfp_0_rxc_0 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_1 = Signal(bool(0)) - qsfp_0_tx_rst_1 = Signal(bool(0)) - qsfp_0_rx_clk_1 = Signal(bool(0)) - qsfp_0_rx_rst_1 = Signal(bool(0)) - qsfp_0_rxd_1 = Signal(intbv(0)[64:]) - qsfp_0_rxc_1 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_2 = Signal(bool(0)) - qsfp_0_tx_rst_2 = Signal(bool(0)) - qsfp_0_rx_clk_2 = Signal(bool(0)) - qsfp_0_rx_rst_2 = Signal(bool(0)) - qsfp_0_rxd_2 = Signal(intbv(0)[64:]) - qsfp_0_rxc_2 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_3 = Signal(bool(0)) - qsfp_0_tx_rst_3 = Signal(bool(0)) - qsfp_0_rx_clk_3 = Signal(bool(0)) - qsfp_0_rx_rst_3 = Signal(bool(0)) - qsfp_0_rxd_3 = Signal(intbv(0)[64:]) - qsfp_0_rxc_3 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_0 = Signal(bool(0)) - qsfp_1_tx_rst_0 = Signal(bool(0)) - qsfp_1_rx_clk_0 = Signal(bool(0)) - qsfp_1_rx_rst_0 = Signal(bool(0)) - qsfp_1_rxd_0 = Signal(intbv(0)[64:]) - qsfp_1_rxc_0 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_1 = Signal(bool(0)) - qsfp_1_tx_rst_1 = Signal(bool(0)) - qsfp_1_rx_clk_1 = Signal(bool(0)) - qsfp_1_rx_rst_1 = Signal(bool(0)) - qsfp_1_rxd_1 = Signal(intbv(0)[64:]) - qsfp_1_rxc_1 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_2 = Signal(bool(0)) - qsfp_1_tx_rst_2 = Signal(bool(0)) - qsfp_1_rx_clk_2 = Signal(bool(0)) - qsfp_1_rx_rst_2 = Signal(bool(0)) - qsfp_1_rxd_2 = Signal(intbv(0)[64:]) - qsfp_1_rxc_2 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_3 = Signal(bool(0)) - qsfp_1_tx_rst_3 = Signal(bool(0)) - qsfp_1_rx_clk_3 = Signal(bool(0)) - qsfp_1_rx_rst_3 = Signal(bool(0)) - qsfp_1_rxd_3 = Signal(intbv(0)[64:]) - qsfp_1_rxc_3 = Signal(intbv(0)[8:]) - - # Outputs - user_led_g = Signal(intbv(0)[2:]) - user_led_r = Signal(bool(0)) - front_led = Signal(intbv(0)[2:]) - qsfp_0_txd_0 = Signal(intbv(0)[64:]) - qsfp_0_txc_0 = Signal(intbv(0)[8:]) - qsfp_0_txd_1 = Signal(intbv(0)[64:]) - qsfp_0_txc_1 = Signal(intbv(0)[8:]) - qsfp_0_txd_2 = Signal(intbv(0)[64:]) - qsfp_0_txc_2 = Signal(intbv(0)[8:]) - qsfp_0_txd_3 = Signal(intbv(0)[64:]) - qsfp_0_txc_3 = Signal(intbv(0)[8:]) - qsfp_1_txd_0 = Signal(intbv(0)[64:]) - qsfp_1_txc_0 = Signal(intbv(0)[8:]) - qsfp_1_txd_1 = Signal(intbv(0)[64:]) - qsfp_1_txc_1 = Signal(intbv(0)[8:]) - qsfp_1_txd_2 = Signal(intbv(0)[64:]) - qsfp_1_txc_2 = Signal(intbv(0)[8:]) - qsfp_1_txd_3 = Signal(intbv(0)[64:]) - qsfp_1_txc_3 = Signal(intbv(0)[8:]) - - # sources and sinks - qsfp_0_0_source = xgmii_ep.XGMIISource() - qsfp_0_0_source_logic = qsfp_0_0_source.create_logic(qsfp_0_rx_clk_0, qsfp_0_rx_rst_0, txd=qsfp_0_rxd_0, txc=qsfp_0_rxc_0, name='qsfp_0_0_source') - - qsfp_0_0_sink = xgmii_ep.XGMIISink() - qsfp_0_0_sink_logic = qsfp_0_0_sink.create_logic(qsfp_0_tx_clk_0, qsfp_0_tx_rst_0, rxd=qsfp_0_txd_0, rxc=qsfp_0_txc_0, name='qsfp_0_0_sink') - - qsfp_0_1_source = xgmii_ep.XGMIISource() - qsfp_0_1_source_logic = qsfp_0_1_source.create_logic(qsfp_0_rx_clk_1, qsfp_0_rx_rst_1, txd=qsfp_0_rxd_1, txc=qsfp_0_rxc_1, name='qsfp_0_1_source') - - qsfp_0_1_sink = xgmii_ep.XGMIISink() - qsfp_0_1_sink_logic = qsfp_0_1_sink.create_logic(qsfp_0_tx_clk_1, qsfp_0_tx_rst_1, rxd=qsfp_0_txd_1, rxc=qsfp_0_txc_1, name='qsfp_0_1_sink') - - qsfp_0_2_source = xgmii_ep.XGMIISource() - qsfp_0_2_source_logic = qsfp_0_2_source.create_logic(qsfp_0_rx_clk_2, qsfp_0_rx_rst_2, txd=qsfp_0_rxd_2, txc=qsfp_0_rxc_2, name='qsfp_0_2_source') - - qsfp_0_2_sink = xgmii_ep.XGMIISink() - qsfp_0_2_sink_logic = qsfp_0_2_sink.create_logic(qsfp_0_tx_clk_2, qsfp_0_tx_rst_2, rxd=qsfp_0_txd_2, rxc=qsfp_0_txc_2, name='qsfp_0_2_sink') - - qsfp_0_3_source = xgmii_ep.XGMIISource() - qsfp_0_3_source_logic = qsfp_0_3_source.create_logic(qsfp_0_rx_clk_3, qsfp_0_rx_rst_3, txd=qsfp_0_rxd_3, txc=qsfp_0_rxc_3, name='qsfp_0_3_source') - - qsfp_0_3_sink = xgmii_ep.XGMIISink() - qsfp_0_3_sink_logic = qsfp_0_3_sink.create_logic(qsfp_0_tx_clk_3, qsfp_0_tx_rst_3, rxd=qsfp_0_txd_3, rxc=qsfp_0_txc_3, name='qsfp_0_3_sink') - - qsfp_1_0_source = xgmii_ep.XGMIISource() - qsfp_1_0_source_logic = qsfp_1_0_source.create_logic(qsfp_1_rx_clk_0, qsfp_1_rx_rst_0, txd=qsfp_1_rxd_0, txc=qsfp_1_rxc_0, name='qsfp_1_0_source') - - qsfp_1_0_sink = xgmii_ep.XGMIISink() - qsfp_1_0_sink_logic = qsfp_1_0_sink.create_logic(qsfp_1_tx_clk_0, qsfp_1_tx_rst_0, rxd=qsfp_1_txd_0, rxc=qsfp_1_txc_0, name='qsfp_1_0_sink') - - qsfp_1_1_source = xgmii_ep.XGMIISource() - qsfp_1_1_source_logic = qsfp_1_1_source.create_logic(qsfp_1_rx_clk_1, qsfp_1_rx_rst_1, txd=qsfp_1_rxd_1, txc=qsfp_1_rxc_1, name='qsfp_1_1_source') - - qsfp_1_1_sink = xgmii_ep.XGMIISink() - qsfp_1_1_sink_logic = qsfp_1_1_sink.create_logic(qsfp_1_tx_clk_1, qsfp_1_tx_rst_1, rxd=qsfp_1_txd_1, rxc=qsfp_1_txc_1, name='qsfp_1_1_sink') - - qsfp_1_2_source = xgmii_ep.XGMIISource() - qsfp_1_2_source_logic = qsfp_1_2_source.create_logic(qsfp_1_rx_clk_2, qsfp_1_rx_rst_2, txd=qsfp_1_rxd_2, txc=qsfp_1_rxc_2, name='qsfp_1_2_source') - - qsfp_1_2_sink = xgmii_ep.XGMIISink() - qsfp_1_2_sink_logic = qsfp_1_2_sink.create_logic(qsfp_1_tx_clk_2, qsfp_1_tx_rst_2, rxd=qsfp_1_txd_2, rxc=qsfp_1_txc_2, name='qsfp_1_2_sink') - - qsfp_1_3_source = xgmii_ep.XGMIISource() - qsfp_1_3_source_logic = qsfp_1_3_source.create_logic(qsfp_1_rx_clk_3, qsfp_1_rx_rst_3, txd=qsfp_1_rxd_3, txc=qsfp_1_rxc_3, name='qsfp_1_3_source') - - qsfp_1_3_sink = xgmii_ep.XGMIISink() - qsfp_1_3_sink_logic = qsfp_1_3_sink.create_logic(qsfp_1_tx_clk_3, qsfp_1_tx_rst_3, rxd=qsfp_1_txd_3, rxc=qsfp_1_txc_3, name='qsfp_1_3_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - user_led_g=user_led_g, - user_led_r=user_led_r, - front_led=front_led, - user_sw=user_sw, - - qsfp_0_tx_clk_0=qsfp_0_tx_clk_0, - qsfp_0_tx_rst_0=qsfp_0_tx_rst_0, - qsfp_0_txd_0=qsfp_0_txd_0, - qsfp_0_txc_0=qsfp_0_txc_0, - qsfp_0_rx_clk_0=qsfp_0_rx_clk_0, - qsfp_0_rx_rst_0=qsfp_0_rx_rst_0, - qsfp_0_rxd_0=qsfp_0_rxd_0, - qsfp_0_rxc_0=qsfp_0_rxc_0, - qsfp_0_tx_clk_1=qsfp_0_tx_clk_1, - qsfp_0_tx_rst_1=qsfp_0_tx_rst_1, - qsfp_0_txd_1=qsfp_0_txd_1, - qsfp_0_txc_1=qsfp_0_txc_1, - qsfp_0_rx_clk_1=qsfp_0_rx_clk_1, - qsfp_0_rx_rst_1=qsfp_0_rx_rst_1, - qsfp_0_rxd_1=qsfp_0_rxd_1, - qsfp_0_rxc_1=qsfp_0_rxc_1, - qsfp_0_tx_clk_2=qsfp_0_tx_clk_2, - qsfp_0_tx_rst_2=qsfp_0_tx_rst_2, - qsfp_0_txd_2=qsfp_0_txd_2, - qsfp_0_txc_2=qsfp_0_txc_2, - qsfp_0_rx_clk_2=qsfp_0_rx_clk_2, - qsfp_0_rx_rst_2=qsfp_0_rx_rst_2, - qsfp_0_rxd_2=qsfp_0_rxd_2, - qsfp_0_rxc_2=qsfp_0_rxc_2, - qsfp_0_tx_clk_3=qsfp_0_tx_clk_3, - qsfp_0_tx_rst_3=qsfp_0_tx_rst_3, - qsfp_0_txd_3=qsfp_0_txd_3, - qsfp_0_txc_3=qsfp_0_txc_3, - qsfp_0_rx_clk_3=qsfp_0_rx_clk_3, - qsfp_0_rx_rst_3=qsfp_0_rx_rst_3, - qsfp_0_rxd_3=qsfp_0_rxd_3, - qsfp_0_rxc_3=qsfp_0_rxc_3, - qsfp_1_tx_clk_0=qsfp_1_tx_clk_0, - qsfp_1_tx_rst_0=qsfp_1_tx_rst_0, - qsfp_1_txd_0=qsfp_1_txd_0, - qsfp_1_txc_0=qsfp_1_txc_0, - qsfp_1_rx_clk_0=qsfp_1_rx_clk_0, - qsfp_1_rx_rst_0=qsfp_1_rx_rst_0, - qsfp_1_rxd_0=qsfp_1_rxd_0, - qsfp_1_rxc_0=qsfp_1_rxc_0, - qsfp_1_tx_clk_1=qsfp_1_tx_clk_1, - qsfp_1_tx_rst_1=qsfp_1_tx_rst_1, - qsfp_1_txd_1=qsfp_1_txd_1, - qsfp_1_txc_1=qsfp_1_txc_1, - qsfp_1_rx_clk_1=qsfp_1_rx_clk_1, - qsfp_1_rx_rst_1=qsfp_1_rx_rst_1, - qsfp_1_rxd_1=qsfp_1_rxd_1, - qsfp_1_rxc_1=qsfp_1_rxc_1, - qsfp_1_tx_clk_2=qsfp_1_tx_clk_2, - qsfp_1_tx_rst_2=qsfp_1_tx_rst_2, - qsfp_1_txd_2=qsfp_1_txd_2, - qsfp_1_txc_2=qsfp_1_txc_2, - qsfp_1_rx_clk_2=qsfp_1_rx_clk_2, - qsfp_1_rx_rst_2=qsfp_1_rx_rst_2, - qsfp_1_rxd_2=qsfp_1_rxd_2, - qsfp_1_rxc_2=qsfp_1_rxc_2, - qsfp_1_tx_clk_3=qsfp_1_tx_clk_3, - qsfp_1_tx_rst_3=qsfp_1_tx_rst_3, - qsfp_1_txd_3=qsfp_1_txd_3, - qsfp_1_txc_3=qsfp_1_txc_3, - qsfp_1_rx_clk_3=qsfp_1_rx_clk_3, - qsfp_1_rx_rst_3=qsfp_1_rx_rst_3, - qsfp_1_rxd_3=qsfp_1_rxd_3, - qsfp_1_rxc_3=qsfp_1_rxc_3 - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp_0_tx_clk_0.next = not qsfp_0_tx_clk_0 - qsfp_0_rx_clk_0.next = not qsfp_0_rx_clk_0 - qsfp_0_tx_clk_1.next = not qsfp_0_tx_clk_1 - qsfp_0_rx_clk_1.next = not qsfp_0_rx_clk_1 - qsfp_0_tx_clk_2.next = not qsfp_0_tx_clk_2 - qsfp_0_rx_clk_2.next = not qsfp_0_rx_clk_2 - qsfp_0_tx_clk_3.next = not qsfp_0_tx_clk_3 - qsfp_0_rx_clk_3.next = not qsfp_0_rx_clk_3 - qsfp_1_tx_clk_0.next = not qsfp_1_tx_clk_0 - qsfp_1_rx_clk_0.next = not qsfp_1_rx_clk_0 - qsfp_1_tx_clk_1.next = not qsfp_1_tx_clk_1 - qsfp_1_rx_clk_1.next = not qsfp_1_rx_clk_1 - qsfp_1_tx_clk_2.next = not qsfp_1_tx_clk_2 - qsfp_1_rx_clk_2.next = not qsfp_1_rx_clk_2 - qsfp_1_tx_clk_3.next = not qsfp_1_tx_clk_3 - qsfp_1_rx_clk_3.next = not qsfp_1_rx_clk_3 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp_0_tx_rst_1.next = 1 - qsfp_0_rx_rst_1.next = 1 - qsfp_0_tx_rst_2.next = 1 - qsfp_0_rx_rst_2.next = 1 - qsfp_0_tx_rst_3.next = 1 - qsfp_0_rx_rst_3.next = 1 - qsfp_0_tx_rst_0.next = 1 - qsfp_0_rx_rst_0.next = 1 - qsfp_1_tx_rst_1.next = 1 - qsfp_1_rx_rst_1.next = 1 - qsfp_1_tx_rst_2.next = 1 - qsfp_1_rx_rst_2.next = 1 - qsfp_1_tx_rst_3.next = 1 - qsfp_1_rx_rst_3.next = 1 - qsfp_1_tx_rst_0.next = 1 - qsfp_1_rx_rst_0.next = 1 - yield clk.posedge - rst.next = 0 - qsfp_0_tx_rst_1.next = 0 - qsfp_0_rx_rst_1.next = 0 - qsfp_0_tx_rst_2.next = 0 - qsfp_0_rx_rst_2.next = 0 - qsfp_0_tx_rst_3.next = 0 - qsfp_0_rx_rst_3.next = 0 - qsfp_0_tx_rst_0.next = 0 - qsfp_0_rx_rst_0.next = 0 - qsfp_1_tx_rst_1.next = 0 - qsfp_1_rx_rst_1.next = 0 - qsfp_1_tx_rst_2.next = 0 - qsfp_1_rx_rst_2.next = 0 - qsfp_1_tx_rst_3.next = 0 - qsfp_1_rx_rst_3.next = 0 - qsfp_1_tx_rst_0.next = 0 - qsfp_1_rx_rst_0.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp_0_0_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_0_0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp_0_0_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_0_0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp_0_0_source.empty() - assert qsfp_0_0_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.v b/example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index 003072a91..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [1:0] user_sw = 0; -reg qsfp_0_tx_clk_0 = 0; -reg qsfp_0_tx_rst_0 = 0; -reg qsfp_0_rx_clk_0 = 0; -reg qsfp_0_rx_rst_0 = 0; -reg [63:0] qsfp_0_rxd_0 = 0; -reg [7:0] qsfp_0_rxc_0 = 0; -reg qsfp_0_tx_clk_1 = 0; -reg qsfp_0_tx_rst_1 = 0; -reg qsfp_0_rx_clk_1 = 0; -reg qsfp_0_rx_rst_1 = 0; -reg [63:0] qsfp_0_rxd_1 = 0; -reg [7:0] qsfp_0_rxc_1 = 0; -reg qsfp_0_tx_clk_2 = 0; -reg qsfp_0_tx_rst_2 = 0; -reg qsfp_0_rx_clk_2 = 0; -reg qsfp_0_rx_rst_2 = 0; -reg [63:0] qsfp_0_rxd_2 = 0; -reg [7:0] qsfp_0_rxc_2 = 0; -reg qsfp_0_tx_clk_3 = 0; -reg qsfp_0_tx_rst_3 = 0; -reg qsfp_0_rx_clk_3 = 0; -reg qsfp_0_rx_rst_3 = 0; -reg [63:0] qsfp_0_rxd_3 = 0; -reg [7:0] qsfp_0_rxc_3 = 0; -reg qsfp_1_tx_clk_0 = 0; -reg qsfp_1_tx_rst_0 = 0; -reg qsfp_1_rx_clk_0 = 0; -reg qsfp_1_rx_rst_0 = 0; -reg [63:0] qsfp_1_rxd_0 = 0; -reg [7:0] qsfp_1_rxc_0 = 0; -reg qsfp_1_tx_clk_1 = 0; -reg qsfp_1_tx_rst_1 = 0; -reg qsfp_1_rx_clk_1 = 0; -reg qsfp_1_rx_rst_1 = 0; -reg [63:0] qsfp_1_rxd_1 = 0; -reg [7:0] qsfp_1_rxc_1 = 0; -reg qsfp_1_tx_clk_2 = 0; -reg qsfp_1_tx_rst_2 = 0; -reg qsfp_1_rx_clk_2 = 0; -reg qsfp_1_rx_rst_2 = 0; -reg [63:0] qsfp_1_rxd_2 = 0; -reg [7:0] qsfp_1_rxc_2 = 0; -reg qsfp_1_tx_clk_3 = 0; -reg qsfp_1_tx_rst_3 = 0; -reg qsfp_1_rx_clk_3 = 0; -reg qsfp_1_rx_rst_3 = 0; -reg [63:0] qsfp_1_rxd_3 = 0; -reg [7:0] qsfp_1_rxc_3 = 0; - -// Outputs -wire [1:0] user_led_g; -wire user_led_r; -wire [1:0] front_led; -wire [63:0] qsfp_0_txd_0; -wire [7:0] qsfp_0_txc_0; -wire [63:0] qsfp_0_txd_1; -wire [7:0] qsfp_0_txc_1; -wire [63:0] qsfp_0_txd_2; -wire [7:0] qsfp_0_txc_2; -wire [63:0] qsfp_0_txd_3; -wire [7:0] qsfp_0_txc_3; -wire [63:0] qsfp_1_txd_0; -wire [7:0] qsfp_1_txc_0; -wire [63:0] qsfp_1_txd_1; -wire [7:0] qsfp_1_txc_1; -wire [63:0] qsfp_1_txd_2; -wire [7:0] qsfp_1_txc_2; -wire [63:0] qsfp_1_txd_3; -wire [7:0] qsfp_1_txc_3; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - user_sw, - qsfp_0_tx_clk_0, - qsfp_0_tx_rst_0, - qsfp_0_rx_clk_0, - qsfp_0_rx_rst_0, - qsfp_0_rxd_0, - qsfp_0_rxc_0, - qsfp_0_tx_clk_1, - qsfp_0_tx_rst_1, - qsfp_0_rx_clk_1, - qsfp_0_rx_rst_1, - qsfp_0_rxd_1, - qsfp_0_rxc_1, - qsfp_0_tx_clk_2, - qsfp_0_tx_rst_2, - qsfp_0_rx_clk_2, - qsfp_0_rx_rst_2, - qsfp_0_rxd_2, - qsfp_0_rxc_2, - qsfp_0_tx_clk_3, - qsfp_0_tx_rst_3, - qsfp_0_rx_clk_3, - qsfp_0_rx_rst_3, - qsfp_0_rxd_3, - qsfp_0_rxc_3, - qsfp_1_tx_clk_0, - qsfp_1_tx_rst_0, - qsfp_1_rx_clk_0, - qsfp_1_rx_rst_0, - qsfp_1_rxd_0, - qsfp_1_rxc_0, - qsfp_1_tx_clk_1, - qsfp_1_tx_rst_1, - qsfp_1_rx_clk_1, - qsfp_1_rx_rst_1, - qsfp_1_rxd_1, - qsfp_1_rxc_1, - qsfp_1_tx_clk_2, - qsfp_1_tx_rst_2, - qsfp_1_rx_clk_2, - qsfp_1_rx_rst_2, - qsfp_1_rxd_2, - qsfp_1_rxc_2, - qsfp_1_tx_clk_3, - qsfp_1_tx_rst_3, - qsfp_1_rx_clk_3, - qsfp_1_rx_rst_3, - qsfp_1_rxd_3, - qsfp_1_rxc_3 - ); - $to_myhdl( - user_led_g, - user_led_r, - front_led, - qsfp_0_txd_0, - qsfp_0_txc_0, - qsfp_0_txd_1, - qsfp_0_txc_1, - qsfp_0_txd_2, - qsfp_0_txc_2, - qsfp_0_txd_3, - qsfp_0_txc_3, - qsfp_1_txd_0, - qsfp_1_txc_0, - qsfp_1_txd_1, - qsfp_1_txc_1, - qsfp_1_txd_2, - qsfp_1_txc_2, - qsfp_1_txd_3, - qsfp_1_txc_3 - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .user_led_g(user_led_g), - .user_led_r(user_led_r), - .front_led(front_led), - .user_sw(user_sw), - .qsfp_0_tx_clk_0(qsfp_0_tx_clk_0), - .qsfp_0_tx_rst_0(qsfp_0_tx_rst_0), - .qsfp_0_txd_0(qsfp_0_txd_0), - .qsfp_0_txc_0(qsfp_0_txc_0), - .qsfp_0_rx_clk_0(qsfp_0_rx_clk_0), - .qsfp_0_rx_rst_0(qsfp_0_rx_rst_0), - .qsfp_0_rxd_0(qsfp_0_rxd_0), - .qsfp_0_rxc_0(qsfp_0_rxc_0), - .qsfp_0_tx_clk_1(qsfp_0_tx_clk_1), - .qsfp_0_tx_rst_1(qsfp_0_tx_rst_1), - .qsfp_0_txd_1(qsfp_0_txd_1), - .qsfp_0_txc_1(qsfp_0_txc_1), - .qsfp_0_rx_clk_1(qsfp_0_rx_clk_1), - .qsfp_0_rx_rst_1(qsfp_0_rx_rst_1), - .qsfp_0_rxd_1(qsfp_0_rxd_1), - .qsfp_0_rxc_1(qsfp_0_rxc_1), - .qsfp_0_tx_clk_2(qsfp_0_tx_clk_2), - .qsfp_0_tx_rst_2(qsfp_0_tx_rst_2), - .qsfp_0_txd_2(qsfp_0_txd_2), - .qsfp_0_txc_2(qsfp_0_txc_2), - .qsfp_0_rx_clk_2(qsfp_0_rx_clk_2), - .qsfp_0_rx_rst_2(qsfp_0_rx_rst_2), - .qsfp_0_rxd_2(qsfp_0_rxd_2), - .qsfp_0_rxc_2(qsfp_0_rxc_2), - .qsfp_0_tx_clk_3(qsfp_0_tx_clk_3), - .qsfp_0_tx_rst_3(qsfp_0_tx_rst_3), - .qsfp_0_txd_3(qsfp_0_txd_3), - .qsfp_0_txc_3(qsfp_0_txc_3), - .qsfp_0_rx_clk_3(qsfp_0_rx_clk_3), - .qsfp_0_rx_rst_3(qsfp_0_rx_rst_3), - .qsfp_0_rxd_3(qsfp_0_rxd_3), - .qsfp_0_rxc_3(qsfp_0_rxc_3), - .qsfp_1_tx_clk_0(qsfp_1_tx_clk_0), - .qsfp_1_tx_rst_0(qsfp_1_tx_rst_0), - .qsfp_1_txd_0(qsfp_1_txd_0), - .qsfp_1_txc_0(qsfp_1_txc_0), - .qsfp_1_rx_clk_0(qsfp_1_rx_clk_0), - .qsfp_1_rx_rst_0(qsfp_1_rx_rst_0), - .qsfp_1_rxd_0(qsfp_1_rxd_0), - .qsfp_1_rxc_0(qsfp_1_rxc_0), - .qsfp_1_tx_clk_1(qsfp_1_tx_clk_1), - .qsfp_1_tx_rst_1(qsfp_1_tx_rst_1), - .qsfp_1_txd_1(qsfp_1_txd_1), - .qsfp_1_txc_1(qsfp_1_txc_1), - .qsfp_1_rx_clk_1(qsfp_1_rx_clk_1), - .qsfp_1_rx_rst_1(qsfp_1_rx_rst_1), - .qsfp_1_rxd_1(qsfp_1_rxd_1), - .qsfp_1_rxc_1(qsfp_1_rxc_1), - .qsfp_1_tx_clk_2(qsfp_1_tx_clk_2), - .qsfp_1_tx_rst_2(qsfp_1_tx_rst_2), - .qsfp_1_txd_2(qsfp_1_txd_2), - .qsfp_1_txc_2(qsfp_1_txc_2), - .qsfp_1_rx_clk_2(qsfp_1_rx_clk_2), - .qsfp_1_rx_rst_2(qsfp_1_rx_rst_2), - .qsfp_1_rxd_2(qsfp_1_rxd_2), - .qsfp_1_rxc_2(qsfp_1_rxc_2), - .qsfp_1_tx_clk_3(qsfp_1_tx_clk_3), - .qsfp_1_tx_rst_3(qsfp_1_tx_rst_3), - .qsfp_1_txd_3(qsfp_1_txd_3), - .qsfp_1_txc_3(qsfp_1_txc_3), - .qsfp_1_rx_clk_3(qsfp_1_rx_clk_3), - .qsfp_1_rx_rst_3(qsfp_1_rx_rst_3), - .qsfp_1_rxd_3(qsfp_1_rxd_3), - .qsfp_1_rxc_3(qsfp_1_rxc_3) -); - -endmodule diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/udp_ep.py b/example/ADM_PCIE_9V3/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/xgmii_ep.py b/example/ADM_PCIE_9V3/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/arp_ep.py b/example/ADM_PCIE_9V3/fpga_25g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/axis_ep.py b/example/ADM_PCIE_9V3/fpga_25g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/eth_ep.py b/example/ADM_PCIE_9V3/fpga_25g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + 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 new file mode 100644 index 000000000..c7ef127ab --- /dev/null +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,289 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 2.56, units="ns").start()) + + # Ethernet + cocotb.fork(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) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_0, 2.56, units="ns").start()) + self.qsfp_0_0_sink = XgmiiSink(dut.qsfp_0_txd_0, dut.qsfp_0_txc_0, dut.qsfp_0_tx_clk_0, dut.qsfp_0_tx_rst_0) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_1, 2.56, units="ns").start()) + self.qsfp_0_1_source = XgmiiSource(dut.qsfp_0_rxd_1, dut.qsfp_0_rxc_1, dut.qsfp_0_rx_clk_1, dut.qsfp_0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_1, 2.56, units="ns").start()) + self.qsfp_0_1_sink = XgmiiSink(dut.qsfp_0_txd_1, dut.qsfp_0_txc_1, dut.qsfp_0_tx_clk_1, dut.qsfp_0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_2, 2.56, units="ns").start()) + self.qsfp_0_2_source = XgmiiSource(dut.qsfp_0_rxd_2, dut.qsfp_0_rxc_2, dut.qsfp_0_rx_clk_2, dut.qsfp_0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_2, 2.56, units="ns").start()) + self.qsfp_0_2_sink = XgmiiSink(dut.qsfp_0_txd_2, dut.qsfp_0_txc_2, dut.qsfp_0_tx_clk_2, dut.qsfp_0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_3, 2.56, units="ns").start()) + self.qsfp_0_3_source = XgmiiSource(dut.qsfp_0_rxd_3, dut.qsfp_0_rxc_3, dut.qsfp_0_rx_clk_3, dut.qsfp_0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_3, 2.56, units="ns").start()) + self.qsfp_0_3_sink = XgmiiSink(dut.qsfp_0_txd_3, dut.qsfp_0_txc_3, dut.qsfp_0_tx_clk_3, dut.qsfp_0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_0, 2.56, units="ns").start()) + self.qsfp_1_0_source = XgmiiSource(dut.qsfp_1_rxd_0, dut.qsfp_1_rxc_0, dut.qsfp_1_rx_clk_0, dut.qsfp_1_rx_rst_0) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_0, 2.56, units="ns").start()) + self.qsfp_1_0_sink = XgmiiSink(dut.qsfp_1_txd_0, dut.qsfp_1_txc_0, dut.qsfp_1_tx_clk_0, dut.qsfp_1_tx_rst_0) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_1, 2.56, units="ns").start()) + self.qsfp_1_1_source = XgmiiSource(dut.qsfp_1_rxd_1, dut.qsfp_1_rxc_1, dut.qsfp_1_rx_clk_1, dut.qsfp_1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_1, 2.56, units="ns").start()) + self.qsfp_1_1_sink = XgmiiSink(dut.qsfp_1_txd_1, dut.qsfp_1_txc_1, dut.qsfp_1_tx_clk_1, dut.qsfp_1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_2, 2.56, units="ns").start()) + self.qsfp_1_2_source = XgmiiSource(dut.qsfp_1_rxd_2, dut.qsfp_1_rxc_2, dut.qsfp_1_rx_clk_2, dut.qsfp_1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_2, 2.56, units="ns").start()) + self.qsfp_1_2_sink = XgmiiSink(dut.qsfp_1_txd_2, dut.qsfp_1_txc_2, dut.qsfp_1_tx_clk_2, dut.qsfp_1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_3, 2.56, units="ns").start()) + self.qsfp_1_3_source = XgmiiSource(dut.qsfp_1_rxd_3, dut.qsfp_1_rxc_3, dut.qsfp_1_rx_clk_3, dut.qsfp_1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_3, 2.56, units="ns").start()) + self.qsfp_1_3_sink = XgmiiSink(dut.qsfp_1_txd_3, dut.qsfp_1_txc_3, dut.qsfp_1_tx_clk_3, dut.qsfp_1_tx_rst_3) + + dut.user_sw.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_0.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_0.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_0.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_0.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_3.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp_0_rx_rst_0 <= 1 + self.dut.qsfp_0_tx_rst_0 <= 1 + self.dut.qsfp_0_rx_rst_1 <= 1 + self.dut.qsfp_0_tx_rst_1 <= 1 + self.dut.qsfp_0_rx_rst_2 <= 1 + self.dut.qsfp_0_tx_rst_2 <= 1 + self.dut.qsfp_0_rx_rst_3 <= 1 + self.dut.qsfp_0_tx_rst_3 <= 1 + self.dut.qsfp_1_rx_rst_0 <= 1 + self.dut.qsfp_1_tx_rst_0 <= 1 + self.dut.qsfp_1_rx_rst_1 <= 1 + self.dut.qsfp_1_tx_rst_1 <= 1 + self.dut.qsfp_1_rx_rst_2 <= 1 + self.dut.qsfp_1_tx_rst_2 <= 1 + self.dut.qsfp_1_rx_rst_3 <= 1 + self.dut.qsfp_1_tx_rst_3 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp_0_rx_rst_0 <= 0 + self.dut.qsfp_0_tx_rst_0 <= 0 + self.dut.qsfp_0_rx_rst_1 <= 0 + self.dut.qsfp_0_tx_rst_1 <= 0 + self.dut.qsfp_0_rx_rst_2 <= 0 + self.dut.qsfp_0_tx_rst_2 <= 0 + self.dut.qsfp_0_rx_rst_3 <= 0 + self.dut.qsfp_0_tx_rst_3 <= 0 + self.dut.qsfp_1_rx_rst_0 <= 0 + self.dut.qsfp_1_tx_rst_0 <= 0 + self.dut.qsfp_1_rx_rst_1 <= 0 + self.dut.qsfp_1_tx_rst_1 <= 0 + self.dut.qsfp_1_rx_rst_2 <= 0 + self.dut.qsfp_1_tx_rst_2 <= 0 + self.dut.qsfp_1_rx_rst_3 <= 0 + self.dut.qsfp_1_tx_rst_3 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp_0_0_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp_0_0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp_0_0_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp_0_0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/ip_ep.py b/example/ADM_PCIE_9V3/fpga_25g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.py b/example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.py deleted file mode 100755 index 7f0698a04..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.py +++ /dev/null @@ -1,463 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - user_sw = Signal(intbv(0)[2:]) - qsfp_0_tx_clk_0 = Signal(bool(0)) - qsfp_0_tx_rst_0 = Signal(bool(0)) - qsfp_0_rx_clk_0 = Signal(bool(0)) - qsfp_0_rx_rst_0 = Signal(bool(0)) - qsfp_0_rxd_0 = Signal(intbv(0)[64:]) - qsfp_0_rxc_0 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_1 = Signal(bool(0)) - qsfp_0_tx_rst_1 = Signal(bool(0)) - qsfp_0_rx_clk_1 = Signal(bool(0)) - qsfp_0_rx_rst_1 = Signal(bool(0)) - qsfp_0_rxd_1 = Signal(intbv(0)[64:]) - qsfp_0_rxc_1 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_2 = Signal(bool(0)) - qsfp_0_tx_rst_2 = Signal(bool(0)) - qsfp_0_rx_clk_2 = Signal(bool(0)) - qsfp_0_rx_rst_2 = Signal(bool(0)) - qsfp_0_rxd_2 = Signal(intbv(0)[64:]) - qsfp_0_rxc_2 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_3 = Signal(bool(0)) - qsfp_0_tx_rst_3 = Signal(bool(0)) - qsfp_0_rx_clk_3 = Signal(bool(0)) - qsfp_0_rx_rst_3 = Signal(bool(0)) - qsfp_0_rxd_3 = Signal(intbv(0)[64:]) - qsfp_0_rxc_3 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_0 = Signal(bool(0)) - qsfp_1_tx_rst_0 = Signal(bool(0)) - qsfp_1_rx_clk_0 = Signal(bool(0)) - qsfp_1_rx_rst_0 = Signal(bool(0)) - qsfp_1_rxd_0 = Signal(intbv(0)[64:]) - qsfp_1_rxc_0 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_1 = Signal(bool(0)) - qsfp_1_tx_rst_1 = Signal(bool(0)) - qsfp_1_rx_clk_1 = Signal(bool(0)) - qsfp_1_rx_rst_1 = Signal(bool(0)) - qsfp_1_rxd_1 = Signal(intbv(0)[64:]) - qsfp_1_rxc_1 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_2 = Signal(bool(0)) - qsfp_1_tx_rst_2 = Signal(bool(0)) - qsfp_1_rx_clk_2 = Signal(bool(0)) - qsfp_1_rx_rst_2 = Signal(bool(0)) - qsfp_1_rxd_2 = Signal(intbv(0)[64:]) - qsfp_1_rxc_2 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_3 = Signal(bool(0)) - qsfp_1_tx_rst_3 = Signal(bool(0)) - qsfp_1_rx_clk_3 = Signal(bool(0)) - qsfp_1_rx_rst_3 = Signal(bool(0)) - qsfp_1_rxd_3 = Signal(intbv(0)[64:]) - qsfp_1_rxc_3 = Signal(intbv(0)[8:]) - - # Outputs - user_led_g = Signal(intbv(0)[2:]) - user_led_r = Signal(bool(0)) - front_led = Signal(intbv(0)[2:]) - qsfp_0_txd_0 = Signal(intbv(0)[64:]) - qsfp_0_txc_0 = Signal(intbv(0)[8:]) - qsfp_0_txd_1 = Signal(intbv(0)[64:]) - qsfp_0_txc_1 = Signal(intbv(0)[8:]) - qsfp_0_txd_2 = Signal(intbv(0)[64:]) - qsfp_0_txc_2 = Signal(intbv(0)[8:]) - qsfp_0_txd_3 = Signal(intbv(0)[64:]) - qsfp_0_txc_3 = Signal(intbv(0)[8:]) - qsfp_1_txd_0 = Signal(intbv(0)[64:]) - qsfp_1_txc_0 = Signal(intbv(0)[8:]) - qsfp_1_txd_1 = Signal(intbv(0)[64:]) - qsfp_1_txc_1 = Signal(intbv(0)[8:]) - qsfp_1_txd_2 = Signal(intbv(0)[64:]) - qsfp_1_txc_2 = Signal(intbv(0)[8:]) - qsfp_1_txd_3 = Signal(intbv(0)[64:]) - qsfp_1_txc_3 = Signal(intbv(0)[8:]) - - # sources and sinks - qsfp_0_0_source = xgmii_ep.XGMIISource() - qsfp_0_0_source_logic = qsfp_0_0_source.create_logic(qsfp_0_rx_clk_0, qsfp_0_rx_rst_0, txd=qsfp_0_rxd_0, txc=qsfp_0_rxc_0, name='qsfp_0_0_source') - - qsfp_0_0_sink = xgmii_ep.XGMIISink() - qsfp_0_0_sink_logic = qsfp_0_0_sink.create_logic(qsfp_0_tx_clk_0, qsfp_0_tx_rst_0, rxd=qsfp_0_txd_0, rxc=qsfp_0_txc_0, name='qsfp_0_0_sink') - - qsfp_0_1_source = xgmii_ep.XGMIISource() - qsfp_0_1_source_logic = qsfp_0_1_source.create_logic(qsfp_0_rx_clk_1, qsfp_0_rx_rst_1, txd=qsfp_0_rxd_1, txc=qsfp_0_rxc_1, name='qsfp_0_1_source') - - qsfp_0_1_sink = xgmii_ep.XGMIISink() - qsfp_0_1_sink_logic = qsfp_0_1_sink.create_logic(qsfp_0_tx_clk_1, qsfp_0_tx_rst_1, rxd=qsfp_0_txd_1, rxc=qsfp_0_txc_1, name='qsfp_0_1_sink') - - qsfp_0_2_source = xgmii_ep.XGMIISource() - qsfp_0_2_source_logic = qsfp_0_2_source.create_logic(qsfp_0_rx_clk_2, qsfp_0_rx_rst_2, txd=qsfp_0_rxd_2, txc=qsfp_0_rxc_2, name='qsfp_0_2_source') - - qsfp_0_2_sink = xgmii_ep.XGMIISink() - qsfp_0_2_sink_logic = qsfp_0_2_sink.create_logic(qsfp_0_tx_clk_2, qsfp_0_tx_rst_2, rxd=qsfp_0_txd_2, rxc=qsfp_0_txc_2, name='qsfp_0_2_sink') - - qsfp_0_3_source = xgmii_ep.XGMIISource() - qsfp_0_3_source_logic = qsfp_0_3_source.create_logic(qsfp_0_rx_clk_3, qsfp_0_rx_rst_3, txd=qsfp_0_rxd_3, txc=qsfp_0_rxc_3, name='qsfp_0_3_source') - - qsfp_0_3_sink = xgmii_ep.XGMIISink() - qsfp_0_3_sink_logic = qsfp_0_3_sink.create_logic(qsfp_0_tx_clk_3, qsfp_0_tx_rst_3, rxd=qsfp_0_txd_3, rxc=qsfp_0_txc_3, name='qsfp_0_3_sink') - - qsfp_1_0_source = xgmii_ep.XGMIISource() - qsfp_1_0_source_logic = qsfp_1_0_source.create_logic(qsfp_1_rx_clk_0, qsfp_1_rx_rst_0, txd=qsfp_1_rxd_0, txc=qsfp_1_rxc_0, name='qsfp_1_0_source') - - qsfp_1_0_sink = xgmii_ep.XGMIISink() - qsfp_1_0_sink_logic = qsfp_1_0_sink.create_logic(qsfp_1_tx_clk_0, qsfp_1_tx_rst_0, rxd=qsfp_1_txd_0, rxc=qsfp_1_txc_0, name='qsfp_1_0_sink') - - qsfp_1_1_source = xgmii_ep.XGMIISource() - qsfp_1_1_source_logic = qsfp_1_1_source.create_logic(qsfp_1_rx_clk_1, qsfp_1_rx_rst_1, txd=qsfp_1_rxd_1, txc=qsfp_1_rxc_1, name='qsfp_1_1_source') - - qsfp_1_1_sink = xgmii_ep.XGMIISink() - qsfp_1_1_sink_logic = qsfp_1_1_sink.create_logic(qsfp_1_tx_clk_1, qsfp_1_tx_rst_1, rxd=qsfp_1_txd_1, rxc=qsfp_1_txc_1, name='qsfp_1_1_sink') - - qsfp_1_2_source = xgmii_ep.XGMIISource() - qsfp_1_2_source_logic = qsfp_1_2_source.create_logic(qsfp_1_rx_clk_2, qsfp_1_rx_rst_2, txd=qsfp_1_rxd_2, txc=qsfp_1_rxc_2, name='qsfp_1_2_source') - - qsfp_1_2_sink = xgmii_ep.XGMIISink() - qsfp_1_2_sink_logic = qsfp_1_2_sink.create_logic(qsfp_1_tx_clk_2, qsfp_1_tx_rst_2, rxd=qsfp_1_txd_2, rxc=qsfp_1_txc_2, name='qsfp_1_2_sink') - - qsfp_1_3_source = xgmii_ep.XGMIISource() - qsfp_1_3_source_logic = qsfp_1_3_source.create_logic(qsfp_1_rx_clk_3, qsfp_1_rx_rst_3, txd=qsfp_1_rxd_3, txc=qsfp_1_rxc_3, name='qsfp_1_3_source') - - qsfp_1_3_sink = xgmii_ep.XGMIISink() - qsfp_1_3_sink_logic = qsfp_1_3_sink.create_logic(qsfp_1_tx_clk_3, qsfp_1_tx_rst_3, rxd=qsfp_1_txd_3, rxc=qsfp_1_txc_3, name='qsfp_1_3_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - user_led_g=user_led_g, - user_led_r=user_led_r, - front_led=front_led, - user_sw=user_sw, - - qsfp_0_tx_clk_0=qsfp_0_tx_clk_0, - qsfp_0_tx_rst_0=qsfp_0_tx_rst_0, - qsfp_0_txd_0=qsfp_0_txd_0, - qsfp_0_txc_0=qsfp_0_txc_0, - qsfp_0_rx_clk_0=qsfp_0_rx_clk_0, - qsfp_0_rx_rst_0=qsfp_0_rx_rst_0, - qsfp_0_rxd_0=qsfp_0_rxd_0, - qsfp_0_rxc_0=qsfp_0_rxc_0, - qsfp_0_tx_clk_1=qsfp_0_tx_clk_1, - qsfp_0_tx_rst_1=qsfp_0_tx_rst_1, - qsfp_0_txd_1=qsfp_0_txd_1, - qsfp_0_txc_1=qsfp_0_txc_1, - qsfp_0_rx_clk_1=qsfp_0_rx_clk_1, - qsfp_0_rx_rst_1=qsfp_0_rx_rst_1, - qsfp_0_rxd_1=qsfp_0_rxd_1, - qsfp_0_rxc_1=qsfp_0_rxc_1, - qsfp_0_tx_clk_2=qsfp_0_tx_clk_2, - qsfp_0_tx_rst_2=qsfp_0_tx_rst_2, - qsfp_0_txd_2=qsfp_0_txd_2, - qsfp_0_txc_2=qsfp_0_txc_2, - qsfp_0_rx_clk_2=qsfp_0_rx_clk_2, - qsfp_0_rx_rst_2=qsfp_0_rx_rst_2, - qsfp_0_rxd_2=qsfp_0_rxd_2, - qsfp_0_rxc_2=qsfp_0_rxc_2, - qsfp_0_tx_clk_3=qsfp_0_tx_clk_3, - qsfp_0_tx_rst_3=qsfp_0_tx_rst_3, - qsfp_0_txd_3=qsfp_0_txd_3, - qsfp_0_txc_3=qsfp_0_txc_3, - qsfp_0_rx_clk_3=qsfp_0_rx_clk_3, - qsfp_0_rx_rst_3=qsfp_0_rx_rst_3, - qsfp_0_rxd_3=qsfp_0_rxd_3, - qsfp_0_rxc_3=qsfp_0_rxc_3, - qsfp_1_tx_clk_0=qsfp_1_tx_clk_0, - qsfp_1_tx_rst_0=qsfp_1_tx_rst_0, - qsfp_1_txd_0=qsfp_1_txd_0, - qsfp_1_txc_0=qsfp_1_txc_0, - qsfp_1_rx_clk_0=qsfp_1_rx_clk_0, - qsfp_1_rx_rst_0=qsfp_1_rx_rst_0, - qsfp_1_rxd_0=qsfp_1_rxd_0, - qsfp_1_rxc_0=qsfp_1_rxc_0, - qsfp_1_tx_clk_1=qsfp_1_tx_clk_1, - qsfp_1_tx_rst_1=qsfp_1_tx_rst_1, - qsfp_1_txd_1=qsfp_1_txd_1, - qsfp_1_txc_1=qsfp_1_txc_1, - qsfp_1_rx_clk_1=qsfp_1_rx_clk_1, - qsfp_1_rx_rst_1=qsfp_1_rx_rst_1, - qsfp_1_rxd_1=qsfp_1_rxd_1, - qsfp_1_rxc_1=qsfp_1_rxc_1, - qsfp_1_tx_clk_2=qsfp_1_tx_clk_2, - qsfp_1_tx_rst_2=qsfp_1_tx_rst_2, - qsfp_1_txd_2=qsfp_1_txd_2, - qsfp_1_txc_2=qsfp_1_txc_2, - qsfp_1_rx_clk_2=qsfp_1_rx_clk_2, - qsfp_1_rx_rst_2=qsfp_1_rx_rst_2, - qsfp_1_rxd_2=qsfp_1_rxd_2, - qsfp_1_rxc_2=qsfp_1_rxc_2, - qsfp_1_tx_clk_3=qsfp_1_tx_clk_3, - qsfp_1_tx_rst_3=qsfp_1_tx_rst_3, - qsfp_1_txd_3=qsfp_1_txd_3, - qsfp_1_txc_3=qsfp_1_txc_3, - qsfp_1_rx_clk_3=qsfp_1_rx_clk_3, - qsfp_1_rx_rst_3=qsfp_1_rx_rst_3, - qsfp_1_rxd_3=qsfp_1_rxd_3, - qsfp_1_rxc_3=qsfp_1_rxc_3 - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp_0_tx_clk_0.next = not qsfp_0_tx_clk_0 - qsfp_0_rx_clk_0.next = not qsfp_0_rx_clk_0 - qsfp_0_tx_clk_1.next = not qsfp_0_tx_clk_1 - qsfp_0_rx_clk_1.next = not qsfp_0_rx_clk_1 - qsfp_0_tx_clk_2.next = not qsfp_0_tx_clk_2 - qsfp_0_rx_clk_2.next = not qsfp_0_rx_clk_2 - qsfp_0_tx_clk_3.next = not qsfp_0_tx_clk_3 - qsfp_0_rx_clk_3.next = not qsfp_0_rx_clk_3 - qsfp_1_tx_clk_0.next = not qsfp_1_tx_clk_0 - qsfp_1_rx_clk_0.next = not qsfp_1_rx_clk_0 - qsfp_1_tx_clk_1.next = not qsfp_1_tx_clk_1 - qsfp_1_rx_clk_1.next = not qsfp_1_rx_clk_1 - qsfp_1_tx_clk_2.next = not qsfp_1_tx_clk_2 - qsfp_1_rx_clk_2.next = not qsfp_1_rx_clk_2 - qsfp_1_tx_clk_3.next = not qsfp_1_tx_clk_3 - qsfp_1_rx_clk_3.next = not qsfp_1_rx_clk_3 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp_0_tx_rst_1.next = 1 - qsfp_0_rx_rst_1.next = 1 - qsfp_0_tx_rst_2.next = 1 - qsfp_0_rx_rst_2.next = 1 - qsfp_0_tx_rst_3.next = 1 - qsfp_0_rx_rst_3.next = 1 - qsfp_0_tx_rst_0.next = 1 - qsfp_0_rx_rst_0.next = 1 - qsfp_1_tx_rst_1.next = 1 - qsfp_1_rx_rst_1.next = 1 - qsfp_1_tx_rst_2.next = 1 - qsfp_1_rx_rst_2.next = 1 - qsfp_1_tx_rst_3.next = 1 - qsfp_1_rx_rst_3.next = 1 - qsfp_1_tx_rst_0.next = 1 - qsfp_1_rx_rst_0.next = 1 - yield clk.posedge - rst.next = 0 - qsfp_0_tx_rst_1.next = 0 - qsfp_0_rx_rst_1.next = 0 - qsfp_0_tx_rst_2.next = 0 - qsfp_0_rx_rst_2.next = 0 - qsfp_0_tx_rst_3.next = 0 - qsfp_0_rx_rst_3.next = 0 - qsfp_0_tx_rst_0.next = 0 - qsfp_0_rx_rst_0.next = 0 - qsfp_1_tx_rst_1.next = 0 - qsfp_1_rx_rst_1.next = 0 - qsfp_1_tx_rst_2.next = 0 - qsfp_1_rx_rst_2.next = 0 - qsfp_1_tx_rst_3.next = 0 - qsfp_1_rx_rst_3.next = 0 - qsfp_1_tx_rst_0.next = 0 - qsfp_1_rx_rst_0.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp_0_0_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_0_0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp_0_0_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_0_0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp_0_0_source.empty() - assert qsfp_0_0_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.v b/example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.v deleted file mode 100644 index 003072a91..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/test_fpga_core.v +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [1:0] user_sw = 0; -reg qsfp_0_tx_clk_0 = 0; -reg qsfp_0_tx_rst_0 = 0; -reg qsfp_0_rx_clk_0 = 0; -reg qsfp_0_rx_rst_0 = 0; -reg [63:0] qsfp_0_rxd_0 = 0; -reg [7:0] qsfp_0_rxc_0 = 0; -reg qsfp_0_tx_clk_1 = 0; -reg qsfp_0_tx_rst_1 = 0; -reg qsfp_0_rx_clk_1 = 0; -reg qsfp_0_rx_rst_1 = 0; -reg [63:0] qsfp_0_rxd_1 = 0; -reg [7:0] qsfp_0_rxc_1 = 0; -reg qsfp_0_tx_clk_2 = 0; -reg qsfp_0_tx_rst_2 = 0; -reg qsfp_0_rx_clk_2 = 0; -reg qsfp_0_rx_rst_2 = 0; -reg [63:0] qsfp_0_rxd_2 = 0; -reg [7:0] qsfp_0_rxc_2 = 0; -reg qsfp_0_tx_clk_3 = 0; -reg qsfp_0_tx_rst_3 = 0; -reg qsfp_0_rx_clk_3 = 0; -reg qsfp_0_rx_rst_3 = 0; -reg [63:0] qsfp_0_rxd_3 = 0; -reg [7:0] qsfp_0_rxc_3 = 0; -reg qsfp_1_tx_clk_0 = 0; -reg qsfp_1_tx_rst_0 = 0; -reg qsfp_1_rx_clk_0 = 0; -reg qsfp_1_rx_rst_0 = 0; -reg [63:0] qsfp_1_rxd_0 = 0; -reg [7:0] qsfp_1_rxc_0 = 0; -reg qsfp_1_tx_clk_1 = 0; -reg qsfp_1_tx_rst_1 = 0; -reg qsfp_1_rx_clk_1 = 0; -reg qsfp_1_rx_rst_1 = 0; -reg [63:0] qsfp_1_rxd_1 = 0; -reg [7:0] qsfp_1_rxc_1 = 0; -reg qsfp_1_tx_clk_2 = 0; -reg qsfp_1_tx_rst_2 = 0; -reg qsfp_1_rx_clk_2 = 0; -reg qsfp_1_rx_rst_2 = 0; -reg [63:0] qsfp_1_rxd_2 = 0; -reg [7:0] qsfp_1_rxc_2 = 0; -reg qsfp_1_tx_clk_3 = 0; -reg qsfp_1_tx_rst_3 = 0; -reg qsfp_1_rx_clk_3 = 0; -reg qsfp_1_rx_rst_3 = 0; -reg [63:0] qsfp_1_rxd_3 = 0; -reg [7:0] qsfp_1_rxc_3 = 0; - -// Outputs -wire [1:0] user_led_g; -wire user_led_r; -wire [1:0] front_led; -wire [63:0] qsfp_0_txd_0; -wire [7:0] qsfp_0_txc_0; -wire [63:0] qsfp_0_txd_1; -wire [7:0] qsfp_0_txc_1; -wire [63:0] qsfp_0_txd_2; -wire [7:0] qsfp_0_txc_2; -wire [63:0] qsfp_0_txd_3; -wire [7:0] qsfp_0_txc_3; -wire [63:0] qsfp_1_txd_0; -wire [7:0] qsfp_1_txc_0; -wire [63:0] qsfp_1_txd_1; -wire [7:0] qsfp_1_txc_1; -wire [63:0] qsfp_1_txd_2; -wire [7:0] qsfp_1_txc_2; -wire [63:0] qsfp_1_txd_3; -wire [7:0] qsfp_1_txc_3; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - user_sw, - qsfp_0_tx_clk_0, - qsfp_0_tx_rst_0, - qsfp_0_rx_clk_0, - qsfp_0_rx_rst_0, - qsfp_0_rxd_0, - qsfp_0_rxc_0, - qsfp_0_tx_clk_1, - qsfp_0_tx_rst_1, - qsfp_0_rx_clk_1, - qsfp_0_rx_rst_1, - qsfp_0_rxd_1, - qsfp_0_rxc_1, - qsfp_0_tx_clk_2, - qsfp_0_tx_rst_2, - qsfp_0_rx_clk_2, - qsfp_0_rx_rst_2, - qsfp_0_rxd_2, - qsfp_0_rxc_2, - qsfp_0_tx_clk_3, - qsfp_0_tx_rst_3, - qsfp_0_rx_clk_3, - qsfp_0_rx_rst_3, - qsfp_0_rxd_3, - qsfp_0_rxc_3, - qsfp_1_tx_clk_0, - qsfp_1_tx_rst_0, - qsfp_1_rx_clk_0, - qsfp_1_rx_rst_0, - qsfp_1_rxd_0, - qsfp_1_rxc_0, - qsfp_1_tx_clk_1, - qsfp_1_tx_rst_1, - qsfp_1_rx_clk_1, - qsfp_1_rx_rst_1, - qsfp_1_rxd_1, - qsfp_1_rxc_1, - qsfp_1_tx_clk_2, - qsfp_1_tx_rst_2, - qsfp_1_rx_clk_2, - qsfp_1_rx_rst_2, - qsfp_1_rxd_2, - qsfp_1_rxc_2, - qsfp_1_tx_clk_3, - qsfp_1_tx_rst_3, - qsfp_1_rx_clk_3, - qsfp_1_rx_rst_3, - qsfp_1_rxd_3, - qsfp_1_rxc_3 - ); - $to_myhdl( - user_led_g, - user_led_r, - front_led, - qsfp_0_txd_0, - qsfp_0_txc_0, - qsfp_0_txd_1, - qsfp_0_txc_1, - qsfp_0_txd_2, - qsfp_0_txc_2, - qsfp_0_txd_3, - qsfp_0_txc_3, - qsfp_1_txd_0, - qsfp_1_txc_0, - qsfp_1_txd_1, - qsfp_1_txc_1, - qsfp_1_txd_2, - qsfp_1_txc_2, - qsfp_1_txd_3, - qsfp_1_txc_3 - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .user_led_g(user_led_g), - .user_led_r(user_led_r), - .front_led(front_led), - .user_sw(user_sw), - .qsfp_0_tx_clk_0(qsfp_0_tx_clk_0), - .qsfp_0_tx_rst_0(qsfp_0_tx_rst_0), - .qsfp_0_txd_0(qsfp_0_txd_0), - .qsfp_0_txc_0(qsfp_0_txc_0), - .qsfp_0_rx_clk_0(qsfp_0_rx_clk_0), - .qsfp_0_rx_rst_0(qsfp_0_rx_rst_0), - .qsfp_0_rxd_0(qsfp_0_rxd_0), - .qsfp_0_rxc_0(qsfp_0_rxc_0), - .qsfp_0_tx_clk_1(qsfp_0_tx_clk_1), - .qsfp_0_tx_rst_1(qsfp_0_tx_rst_1), - .qsfp_0_txd_1(qsfp_0_txd_1), - .qsfp_0_txc_1(qsfp_0_txc_1), - .qsfp_0_rx_clk_1(qsfp_0_rx_clk_1), - .qsfp_0_rx_rst_1(qsfp_0_rx_rst_1), - .qsfp_0_rxd_1(qsfp_0_rxd_1), - .qsfp_0_rxc_1(qsfp_0_rxc_1), - .qsfp_0_tx_clk_2(qsfp_0_tx_clk_2), - .qsfp_0_tx_rst_2(qsfp_0_tx_rst_2), - .qsfp_0_txd_2(qsfp_0_txd_2), - .qsfp_0_txc_2(qsfp_0_txc_2), - .qsfp_0_rx_clk_2(qsfp_0_rx_clk_2), - .qsfp_0_rx_rst_2(qsfp_0_rx_rst_2), - .qsfp_0_rxd_2(qsfp_0_rxd_2), - .qsfp_0_rxc_2(qsfp_0_rxc_2), - .qsfp_0_tx_clk_3(qsfp_0_tx_clk_3), - .qsfp_0_tx_rst_3(qsfp_0_tx_rst_3), - .qsfp_0_txd_3(qsfp_0_txd_3), - .qsfp_0_txc_3(qsfp_0_txc_3), - .qsfp_0_rx_clk_3(qsfp_0_rx_clk_3), - .qsfp_0_rx_rst_3(qsfp_0_rx_rst_3), - .qsfp_0_rxd_3(qsfp_0_rxd_3), - .qsfp_0_rxc_3(qsfp_0_rxc_3), - .qsfp_1_tx_clk_0(qsfp_1_tx_clk_0), - .qsfp_1_tx_rst_0(qsfp_1_tx_rst_0), - .qsfp_1_txd_0(qsfp_1_txd_0), - .qsfp_1_txc_0(qsfp_1_txc_0), - .qsfp_1_rx_clk_0(qsfp_1_rx_clk_0), - .qsfp_1_rx_rst_0(qsfp_1_rx_rst_0), - .qsfp_1_rxd_0(qsfp_1_rxd_0), - .qsfp_1_rxc_0(qsfp_1_rxc_0), - .qsfp_1_tx_clk_1(qsfp_1_tx_clk_1), - .qsfp_1_tx_rst_1(qsfp_1_tx_rst_1), - .qsfp_1_txd_1(qsfp_1_txd_1), - .qsfp_1_txc_1(qsfp_1_txc_1), - .qsfp_1_rx_clk_1(qsfp_1_rx_clk_1), - .qsfp_1_rx_rst_1(qsfp_1_rx_rst_1), - .qsfp_1_rxd_1(qsfp_1_rxd_1), - .qsfp_1_rxc_1(qsfp_1_rxc_1), - .qsfp_1_tx_clk_2(qsfp_1_tx_clk_2), - .qsfp_1_tx_rst_2(qsfp_1_tx_rst_2), - .qsfp_1_txd_2(qsfp_1_txd_2), - .qsfp_1_txc_2(qsfp_1_txc_2), - .qsfp_1_rx_clk_2(qsfp_1_rx_clk_2), - .qsfp_1_rx_rst_2(qsfp_1_rx_rst_2), - .qsfp_1_rxd_2(qsfp_1_rxd_2), - .qsfp_1_rxc_2(qsfp_1_rxc_2), - .qsfp_1_tx_clk_3(qsfp_1_tx_clk_3), - .qsfp_1_tx_rst_3(qsfp_1_tx_rst_3), - .qsfp_1_txd_3(qsfp_1_txd_3), - .qsfp_1_txc_3(qsfp_1_txc_3), - .qsfp_1_rx_clk_3(qsfp_1_rx_clk_3), - .qsfp_1_rx_rst_3(qsfp_1_rx_rst_3), - .qsfp_1_rxd_3(qsfp_1_rxd_3), - .qsfp_1_rxc_3(qsfp_1_rxc_3) -); - -endmodule diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/udp_ep.py b/example/ADM_PCIE_9V3/fpga_25g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ADM_PCIE_9V3/fpga_25g/tb/xgmii_ep.py b/example/ADM_PCIE_9V3/fpga_25g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/arp_ep.py b/example/ATLYS/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ATLYS/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/axis_ep.py b/example/ATLYS/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ATLYS/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/eth_ep.py b/example/ATLYS/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ATLYS/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/fpga_core/Makefile b/example/ATLYS/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..9cef21260 --- /dev/null +++ b/example/ATLYS/fpga/tb/fpga_core/Makefile @@ -0,0 +1,105 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_out.v +VERILOG_SOURCES += ../../lib/eth/rtl/gmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_gmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_gmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py b/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..6ed21ee44 --- /dev/null +++ b/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,216 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + # Ethernet + self.gmii_phy = GmiiPhy(dut.phy_txd, dut.phy_tx_er, dut.phy_tx_en, dut.phy_tx_clk, dut.phy_gtx_clk, + dut.phy_rxd, dut.phy_rx_er, dut.phy_rx_dv, dut.phy_rx_clk, speed=speed) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_in.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_out.v"), + os.path.join(eth_rtl_dir, "gmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_gmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_gmii.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ATLYS/fpga/tb/gmii_ep.py b/example/ATLYS/fpga/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/ATLYS/fpga/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/ip_ep.py b/example/ATLYS/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ATLYS/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/test_fpga_core.py b/example/ATLYS/fpga/tb/test_fpga_core.py deleted file mode 100755 index 37eca0441..000000000 --- a/example/ATLYS/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,311 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/iddr.v") -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_sdr_in.v") -srcs.append("../lib/eth/rtl/ssio_sdr_out.v") -srcs.append("../lib/eth/rtl/gmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_gmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_gmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[8:]) - phy_rx_dv = Signal(bool(0)) - phy_rx_er = Signal(bool(0)) - phy_tx_clk = Signal(bool(0)) - uart_rxd = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - phy_gtx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[8:]) - phy_tx_en = Signal(bool(0)) - phy_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - - # sources and sinks - mii_select = Signal(bool(0)) - - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_en=phy_rx_dv, - tx_er=phy_rx_er, - mii_select=mii_select, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_dv=phy_tx_en, - rx_er=phy_tx_er, - mii_select=mii_select, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_dv=phy_rx_dv, - phy_rx_er=phy_rx_er, - phy_gtx_clk=phy_gtx_clk, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_en=phy_tx_en, - phy_tx_er=phy_tx_er, - phy_reset_n=phy_reset_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - phy_tx_clk.next = not phy_tx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ATLYS/fpga/tb/test_fpga_core.v b/example/ATLYS/fpga/tb/test_fpga_core.v deleted file mode 100644 index bbd8df6a4..000000000 --- a/example/ATLYS/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,125 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg phy_rx_clk = 0; -reg [7:0] phy_rxd = 0; -reg phy_rx_dv = 0; -reg phy_rx_er = 0; -reg phy_tx_clk = 0; -reg uart_rxd = 0; - -// Outputs -wire [7:0] led; -wire phy_gtx_clk; -wire [7:0] phy_txd; -wire phy_tx_en; -wire phy_tx_er; -wire phy_reset_n; -wire uart_txd; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_dv, - phy_rx_er, - phy_tx_clk, - uart_rxd - ); - $to_myhdl( - led, - phy_gtx_clk, - phy_txd, - phy_tx_en, - phy_tx_er, - phy_reset_n, - uart_txd - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_dv(phy_rx_dv), - .phy_rx_er(phy_rx_er), - .phy_gtx_clk(phy_gtx_clk), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_en(phy_tx_en), - .phy_tx_er(phy_tx_er), - .phy_reset_n(phy_reset_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd) -); - -endmodule diff --git a/example/ATLYS/fpga/tb/udp_ep.py b/example/ATLYS/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ATLYS/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/AU200/fpga_10g/tb/arp_ep.py b/example/AU200/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/AU200/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/AU200/fpga_10g/tb/axis_ep.py b/example/AU200/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/AU200/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/AU200/fpga_10g/tb/eth_ep.py b/example/AU200/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/AU200/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/AU200/fpga_10g/tb/fpga_core/Makefile b/example/AU200/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/AU200/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..74a58792d --- /dev/null +++ b/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,289 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp0_rx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_source = XgmiiSource(dut.qsfp0_rxd_1, dut.qsfp0_rxc_1, dut.qsfp0_rx_clk_1, dut.qsfp0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp0_tx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_sink = XgmiiSink(dut.qsfp0_txd_1, dut.qsfp0_txc_1, dut.qsfp0_tx_clk_1, dut.qsfp0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_source = XgmiiSource(dut.qsfp0_rxd_2, dut.qsfp0_rxc_2, dut.qsfp0_rx_clk_2, dut.qsfp0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp0_tx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_sink = XgmiiSink(dut.qsfp0_txd_2, dut.qsfp0_txc_2, dut.qsfp0_tx_clk_2, dut.qsfp0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_source = XgmiiSource(dut.qsfp0_rxd_3, dut.qsfp0_rxc_3, dut.qsfp0_rx_clk_3, dut.qsfp0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp0_tx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_sink = XgmiiSink(dut.qsfp0_txd_3, dut.qsfp0_txc_3, dut.qsfp0_tx_clk_3, dut.qsfp0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_source = XgmiiSource(dut.qsfp0_rxd_4, dut.qsfp0_rxc_4, dut.qsfp0_rx_clk_4, dut.qsfp0_rx_rst_4) + cocotb.fork(Clock(dut.qsfp0_tx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_sink = XgmiiSink(dut.qsfp0_txd_4, dut.qsfp0_txc_4, dut.qsfp0_tx_clk_4, dut.qsfp0_tx_rst_4) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_source = XgmiiSource(dut.qsfp1_rxd_1, dut.qsfp1_rxc_1, dut.qsfp1_rx_clk_1, dut.qsfp1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_sink = XgmiiSink(dut.qsfp1_txd_1, dut.qsfp1_txc_1, dut.qsfp1_tx_clk_1, dut.qsfp1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_source = XgmiiSource(dut.qsfp1_rxd_2, dut.qsfp1_rxc_2, dut.qsfp1_rx_clk_2, dut.qsfp1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_sink = XgmiiSink(dut.qsfp1_txd_2, dut.qsfp1_txc_2, dut.qsfp1_tx_clk_2, dut.qsfp1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_source = XgmiiSource(dut.qsfp1_rxd_3, dut.qsfp1_rxc_3, dut.qsfp1_rx_clk_3, dut.qsfp1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_sink = XgmiiSink(dut.qsfp1_txd_3, dut.qsfp1_txc_3, dut.qsfp1_tx_clk_3, dut.qsfp1_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_source = XgmiiSource(dut.qsfp1_rxd_4, dut.qsfp1_rxc_4, dut.qsfp1_rx_clk_4, dut.qsfp1_rx_rst_4) + cocotb.fork(Clock(dut.qsfp1_tx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_sink = XgmiiSink(dut.qsfp1_txd_4, dut.qsfp1_txc_4, dut.qsfp1_tx_clk_4, dut.qsfp1_tx_rst_4) + + dut.sw.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp0_rx_rst_1 <= 1 + self.dut.qsfp0_tx_rst_1 <= 1 + self.dut.qsfp0_rx_rst_2 <= 1 + self.dut.qsfp0_tx_rst_2 <= 1 + self.dut.qsfp0_rx_rst_3 <= 1 + self.dut.qsfp0_tx_rst_3 <= 1 + self.dut.qsfp0_rx_rst_4 <= 1 + self.dut.qsfp0_tx_rst_4 <= 1 + self.dut.qsfp1_rx_rst_1 <= 1 + self.dut.qsfp1_tx_rst_1 <= 1 + self.dut.qsfp1_rx_rst_2 <= 1 + self.dut.qsfp1_tx_rst_2 <= 1 + self.dut.qsfp1_rx_rst_3 <= 1 + self.dut.qsfp1_tx_rst_3 <= 1 + self.dut.qsfp1_rx_rst_4 <= 1 + self.dut.qsfp1_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp0_rx_rst_1 <= 0 + self.dut.qsfp0_tx_rst_1 <= 0 + self.dut.qsfp0_rx_rst_2 <= 0 + self.dut.qsfp0_tx_rst_2 <= 0 + self.dut.qsfp0_rx_rst_3 <= 0 + self.dut.qsfp0_tx_rst_3 <= 0 + self.dut.qsfp0_rx_rst_4 <= 0 + self.dut.qsfp0_tx_rst_4 <= 0 + self.dut.qsfp1_rx_rst_1 <= 0 + self.dut.qsfp1_tx_rst_1 <= 0 + self.dut.qsfp1_rx_rst_2 <= 0 + self.dut.qsfp1_tx_rst_2 <= 0 + self.dut.qsfp1_rx_rst_3 <= 0 + self.dut.qsfp1_tx_rst_3 <= 0 + self.dut.qsfp1_rx_rst_4 <= 0 + self.dut.qsfp1_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp0_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp0_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/AU200/fpga_10g/tb/ip_ep.py b/example/AU200/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/AU200/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/AU200/fpga_10g/tb/test_fpga_core.py b/example/AU200/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index b2a0e316a..000000000 --- a/example/AU200/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,465 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sw = Signal(intbv(0)[4:]) - qsfp0_tx_clk_1 = Signal(bool(0)) - qsfp0_tx_rst_1 = Signal(bool(0)) - qsfp0_rx_clk_1 = Signal(bool(0)) - qsfp0_rx_rst_1 = Signal(bool(0)) - qsfp0_rxd_1 = Signal(intbv(0)[64:]) - qsfp0_rxc_1 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_2 = Signal(bool(0)) - qsfp0_tx_rst_2 = Signal(bool(0)) - qsfp0_rx_clk_2 = Signal(bool(0)) - qsfp0_rx_rst_2 = Signal(bool(0)) - qsfp0_rxd_2 = Signal(intbv(0)[64:]) - qsfp0_rxc_2 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_3 = Signal(bool(0)) - qsfp0_tx_rst_3 = Signal(bool(0)) - qsfp0_rx_clk_3 = Signal(bool(0)) - qsfp0_rx_rst_3 = Signal(bool(0)) - qsfp0_rxd_3 = Signal(intbv(0)[64:]) - qsfp0_rxc_3 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_4 = Signal(bool(0)) - qsfp0_tx_rst_4 = Signal(bool(0)) - qsfp0_rx_clk_4 = Signal(bool(0)) - qsfp0_rx_rst_4 = Signal(bool(0)) - qsfp0_rxd_4 = Signal(intbv(0)[64:]) - qsfp0_rxc_4 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_1 = Signal(bool(0)) - qsfp1_tx_rst_1 = Signal(bool(0)) - qsfp1_rx_clk_1 = Signal(bool(0)) - qsfp1_rx_rst_1 = Signal(bool(0)) - qsfp1_rxd_1 = Signal(intbv(0)[64:]) - qsfp1_rxc_1 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_2 = Signal(bool(0)) - qsfp1_tx_rst_2 = Signal(bool(0)) - qsfp1_rx_clk_2 = Signal(bool(0)) - qsfp1_rx_rst_2 = Signal(bool(0)) - qsfp1_rxd_2 = Signal(intbv(0)[64:]) - qsfp1_rxc_2 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_3 = Signal(bool(0)) - qsfp1_tx_rst_3 = Signal(bool(0)) - qsfp1_rx_clk_3 = Signal(bool(0)) - qsfp1_rx_rst_3 = Signal(bool(0)) - qsfp1_rxd_3 = Signal(intbv(0)[64:]) - qsfp1_rxc_3 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_4 = Signal(bool(0)) - qsfp1_tx_rst_4 = Signal(bool(0)) - qsfp1_rx_clk_4 = Signal(bool(0)) - qsfp1_rx_rst_4 = Signal(bool(0)) - qsfp1_rxd_4 = Signal(intbv(0)[64:]) - qsfp1_rxc_4 = Signal(intbv(0)[8:]) - uart_txd = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[3:]) - qsfp0_txd_1 = Signal(intbv(0)[64:]) - qsfp0_txc_1 = Signal(intbv(0)[8:]) - qsfp0_txd_2 = Signal(intbv(0)[64:]) - qsfp0_txc_2 = Signal(intbv(0)[8:]) - qsfp0_txd_3 = Signal(intbv(0)[64:]) - qsfp0_txc_3 = Signal(intbv(0)[8:]) - qsfp0_txd_4 = Signal(intbv(0)[64:]) - qsfp0_txc_4 = Signal(intbv(0)[8:]) - qsfp1_txd_1 = Signal(intbv(0)[64:]) - qsfp1_txc_1 = Signal(intbv(0)[8:]) - qsfp1_txd_2 = Signal(intbv(0)[64:]) - qsfp1_txc_2 = Signal(intbv(0)[8:]) - qsfp1_txd_3 = Signal(intbv(0)[64:]) - qsfp1_txc_3 = Signal(intbv(0)[8:]) - qsfp1_txd_4 = Signal(intbv(0)[64:]) - qsfp1_txc_4 = Signal(intbv(0)[8:]) - uart_rxd = Signal(bool(0)) - - # sources and sinks - qsfp0_1_source = xgmii_ep.XGMIISource() - qsfp0_1_source_logic = qsfp0_1_source.create_logic(qsfp0_rx_clk_1, qsfp0_rx_rst_1, txd=qsfp0_rxd_1, txc=qsfp0_rxc_1, name='qsfp0_1_source') - - qsfp0_1_sink = xgmii_ep.XGMIISink() - qsfp0_1_sink_logic = qsfp0_1_sink.create_logic(qsfp0_tx_clk_1, qsfp0_tx_rst_1, rxd=qsfp0_txd_1, rxc=qsfp0_txc_1, name='qsfp0_1_sink') - - qsfp0_2_source = xgmii_ep.XGMIISource() - qsfp0_2_source_logic = qsfp0_2_source.create_logic(qsfp0_rx_clk_2, qsfp0_rx_rst_2, txd=qsfp0_rxd_2, txc=qsfp0_rxc_2, name='qsfp0_2_source') - - qsfp0_2_sink = xgmii_ep.XGMIISink() - qsfp0_2_sink_logic = qsfp0_2_sink.create_logic(qsfp0_tx_clk_2, qsfp0_tx_rst_2, rxd=qsfp0_txd_2, rxc=qsfp0_txc_2, name='qsfp0_2_sink') - - qsfp0_3_source = xgmii_ep.XGMIISource() - qsfp0_3_source_logic = qsfp0_3_source.create_logic(qsfp0_rx_clk_3, qsfp0_rx_rst_3, txd=qsfp0_rxd_3, txc=qsfp0_rxc_3, name='qsfp0_3_source') - - qsfp0_3_sink = xgmii_ep.XGMIISink() - qsfp0_3_sink_logic = qsfp0_3_sink.create_logic(qsfp0_tx_clk_3, qsfp0_tx_rst_3, rxd=qsfp0_txd_3, rxc=qsfp0_txc_3, name='qsfp0_3_sink') - - qsfp0_4_source = xgmii_ep.XGMIISource() - qsfp0_4_source_logic = qsfp0_4_source.create_logic(qsfp0_rx_clk_4, qsfp0_rx_rst_4, txd=qsfp0_rxd_4, txc=qsfp0_rxc_4, name='qsfp0_4_source') - - qsfp0_4_sink = xgmii_ep.XGMIISink() - qsfp0_4_sink_logic = qsfp0_4_sink.create_logic(qsfp0_tx_clk_4, qsfp0_tx_rst_4, rxd=qsfp0_txd_4, rxc=qsfp0_txc_4, name='qsfp0_4_sink') - - qsfp1_1_source = xgmii_ep.XGMIISource() - qsfp1_1_source_logic = qsfp1_1_source.create_logic(qsfp1_rx_clk_1, qsfp1_rx_rst_1, txd=qsfp1_rxd_1, txc=qsfp1_rxc_1, name='qsfp1_1_source') - - qsfp1_1_sink = xgmii_ep.XGMIISink() - qsfp1_1_sink_logic = qsfp1_1_sink.create_logic(qsfp1_tx_clk_1, qsfp1_tx_rst_1, rxd=qsfp1_txd_1, rxc=qsfp1_txc_1, name='qsfp1_1_sink') - - qsfp1_2_source = xgmii_ep.XGMIISource() - qsfp1_2_source_logic = qsfp1_2_source.create_logic(qsfp1_rx_clk_2, qsfp1_rx_rst_2, txd=qsfp1_rxd_2, txc=qsfp1_rxc_2, name='qsfp1_2_source') - - qsfp1_2_sink = xgmii_ep.XGMIISink() - qsfp1_2_sink_logic = qsfp1_2_sink.create_logic(qsfp1_tx_clk_2, qsfp1_tx_rst_2, rxd=qsfp1_txd_2, rxc=qsfp1_txc_2, name='qsfp1_2_sink') - - qsfp1_3_source = xgmii_ep.XGMIISource() - qsfp1_3_source_logic = qsfp1_3_source.create_logic(qsfp1_rx_clk_3, qsfp1_rx_rst_3, txd=qsfp1_rxd_3, txc=qsfp1_rxc_3, name='qsfp1_3_source') - - qsfp1_3_sink = xgmii_ep.XGMIISink() - qsfp1_3_sink_logic = qsfp1_3_sink.create_logic(qsfp1_tx_clk_3, qsfp1_tx_rst_3, rxd=qsfp1_txd_3, rxc=qsfp1_txc_3, name='qsfp1_3_sink') - - qsfp1_4_source = xgmii_ep.XGMIISource() - qsfp1_4_source_logic = qsfp1_4_source.create_logic(qsfp1_rx_clk_4, qsfp1_rx_rst_4, txd=qsfp1_rxd_4, txc=qsfp1_rxc_4, name='qsfp1_4_source') - - qsfp1_4_sink = xgmii_ep.XGMIISink() - qsfp1_4_sink_logic = qsfp1_4_sink.create_logic(qsfp1_tx_clk_4, qsfp1_tx_rst_4, rxd=qsfp1_txd_4, rxc=qsfp1_txc_4, name='qsfp1_4_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sw=sw, - led=led, - - qsfp0_tx_clk_1=qsfp0_tx_clk_1, - qsfp0_tx_rst_1=qsfp0_tx_rst_1, - qsfp0_txd_1=qsfp0_txd_1, - qsfp0_txc_1=qsfp0_txc_1, - qsfp0_rx_clk_1=qsfp0_rx_clk_1, - qsfp0_rx_rst_1=qsfp0_rx_rst_1, - qsfp0_rxd_1=qsfp0_rxd_1, - qsfp0_rxc_1=qsfp0_rxc_1, - qsfp0_tx_clk_2=qsfp0_tx_clk_2, - qsfp0_tx_rst_2=qsfp0_tx_rst_2, - qsfp0_txd_2=qsfp0_txd_2, - qsfp0_txc_2=qsfp0_txc_2, - qsfp0_rx_clk_2=qsfp0_rx_clk_2, - qsfp0_rx_rst_2=qsfp0_rx_rst_2, - qsfp0_rxd_2=qsfp0_rxd_2, - qsfp0_rxc_2=qsfp0_rxc_2, - qsfp0_tx_clk_3=qsfp0_tx_clk_3, - qsfp0_tx_rst_3=qsfp0_tx_rst_3, - qsfp0_txd_3=qsfp0_txd_3, - qsfp0_txc_3=qsfp0_txc_3, - qsfp0_rx_clk_3=qsfp0_rx_clk_3, - qsfp0_rx_rst_3=qsfp0_rx_rst_3, - qsfp0_rxd_3=qsfp0_rxd_3, - qsfp0_rxc_3=qsfp0_rxc_3, - qsfp0_tx_clk_4=qsfp0_tx_clk_4, - qsfp0_tx_rst_4=qsfp0_tx_rst_4, - qsfp0_txd_4=qsfp0_txd_4, - qsfp0_txc_4=qsfp0_txc_4, - qsfp0_rx_clk_4=qsfp0_rx_clk_4, - qsfp0_rx_rst_4=qsfp0_rx_rst_4, - qsfp0_rxd_4=qsfp0_rxd_4, - qsfp0_rxc_4=qsfp0_rxc_4, - qsfp1_tx_clk_1=qsfp1_tx_clk_1, - qsfp1_tx_rst_1=qsfp1_tx_rst_1, - qsfp1_txd_1=qsfp1_txd_1, - qsfp1_txc_1=qsfp1_txc_1, - qsfp1_rx_clk_1=qsfp1_rx_clk_1, - qsfp1_rx_rst_1=qsfp1_rx_rst_1, - qsfp1_rxd_1=qsfp1_rxd_1, - qsfp1_rxc_1=qsfp1_rxc_1, - qsfp1_tx_clk_2=qsfp1_tx_clk_2, - qsfp1_tx_rst_2=qsfp1_tx_rst_2, - qsfp1_txd_2=qsfp1_txd_2, - qsfp1_txc_2=qsfp1_txc_2, - qsfp1_rx_clk_2=qsfp1_rx_clk_2, - qsfp1_rx_rst_2=qsfp1_rx_rst_2, - qsfp1_rxd_2=qsfp1_rxd_2, - qsfp1_rxc_2=qsfp1_rxc_2, - qsfp1_tx_clk_3=qsfp1_tx_clk_3, - qsfp1_tx_rst_3=qsfp1_tx_rst_3, - qsfp1_txd_3=qsfp1_txd_3, - qsfp1_txc_3=qsfp1_txc_3, - qsfp1_rx_clk_3=qsfp1_rx_clk_3, - qsfp1_rx_rst_3=qsfp1_rx_rst_3, - qsfp1_rxd_3=qsfp1_rxd_3, - qsfp1_rxc_3=qsfp1_rxc_3, - qsfp1_tx_clk_4=qsfp1_tx_clk_4, - qsfp1_tx_rst_4=qsfp1_tx_rst_4, - qsfp1_txd_4=qsfp1_txd_4, - qsfp1_txc_4=qsfp1_txc_4, - qsfp1_rx_clk_4=qsfp1_rx_clk_4, - qsfp1_rx_rst_4=qsfp1_rx_rst_4, - qsfp1_rxd_4=qsfp1_rxd_4, - qsfp1_rxc_4=qsfp1_rxc_4, - - uart_rxd=uart_rxd, - uart_txd=uart_txd - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp0_tx_clk_1.next = not qsfp0_tx_clk_1 - qsfp0_rx_clk_1.next = not qsfp0_rx_clk_1 - qsfp0_tx_clk_2.next = not qsfp0_tx_clk_2 - qsfp0_rx_clk_2.next = not qsfp0_rx_clk_2 - qsfp0_tx_clk_3.next = not qsfp0_tx_clk_3 - qsfp0_rx_clk_3.next = not qsfp0_rx_clk_3 - qsfp0_tx_clk_4.next = not qsfp0_tx_clk_4 - qsfp0_rx_clk_4.next = not qsfp0_rx_clk_4 - qsfp1_tx_clk_1.next = not qsfp1_tx_clk_1 - qsfp1_rx_clk_1.next = not qsfp1_rx_clk_1 - qsfp1_tx_clk_2.next = not qsfp1_tx_clk_2 - qsfp1_rx_clk_2.next = not qsfp1_rx_clk_2 - qsfp1_tx_clk_3.next = not qsfp1_tx_clk_3 - qsfp1_rx_clk_3.next = not qsfp1_rx_clk_3 - qsfp1_tx_clk_4.next = not qsfp1_tx_clk_4 - qsfp1_rx_clk_4.next = not qsfp1_rx_clk_4 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp0_tx_rst_1.next = 1 - qsfp0_rx_rst_1.next = 1 - qsfp0_tx_rst_2.next = 1 - qsfp0_rx_rst_2.next = 1 - qsfp0_tx_rst_3.next = 1 - qsfp0_rx_rst_3.next = 1 - qsfp0_tx_rst_4.next = 1 - qsfp0_rx_rst_4.next = 1 - qsfp1_tx_rst_1.next = 1 - qsfp1_rx_rst_1.next = 1 - qsfp1_tx_rst_2.next = 1 - qsfp1_rx_rst_2.next = 1 - qsfp1_tx_rst_3.next = 1 - qsfp1_rx_rst_3.next = 1 - qsfp1_tx_rst_4.next = 1 - qsfp1_rx_rst_4.next = 1 - yield clk.posedge - rst.next = 0 - qsfp0_tx_rst_1.next = 0 - qsfp0_rx_rst_1.next = 0 - qsfp0_tx_rst_2.next = 0 - qsfp0_rx_rst_2.next = 0 - qsfp0_tx_rst_3.next = 0 - qsfp0_rx_rst_3.next = 0 - qsfp0_tx_rst_4.next = 0 - qsfp0_rx_rst_4.next = 0 - qsfp1_tx_rst_1.next = 0 - qsfp1_rx_rst_1.next = 0 - qsfp1_tx_rst_2.next = 0 - qsfp1_rx_rst_2.next = 0 - qsfp1_tx_rst_3.next = 0 - qsfp1_rx_rst_3.next = 0 - qsfp1_tx_rst_4.next = 0 - qsfp1_rx_rst_4.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp0_1_source.empty() - assert qsfp0_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/AU200/fpga_10g/tb/test_fpga_core.v b/example/AU200/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index fddb81323..000000000 --- a/example/AU200/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] sw = 0; -reg qsfp0_tx_clk_1 = 0; -reg qsfp0_tx_rst_1 = 0; -reg qsfp0_rx_clk_1 = 0; -reg qsfp0_rx_rst_1 = 0; -reg [63:0] qsfp0_rxd_1 = 0; -reg [7:0] qsfp0_rxc_1 = 0; -reg qsfp0_tx_clk_2 = 0; -reg qsfp0_tx_rst_2 = 0; -reg qsfp0_rx_clk_2 = 0; -reg qsfp0_rx_rst_2 = 0; -reg [63:0] qsfp0_rxd_2 = 0; -reg [7:0] qsfp0_rxc_2 = 0; -reg qsfp0_tx_clk_3 = 0; -reg qsfp0_tx_rst_3 = 0; -reg qsfp0_rx_clk_3 = 0; -reg qsfp0_rx_rst_3 = 0; -reg [63:0] qsfp0_rxd_3 = 0; -reg [7:0] qsfp0_rxc_3 = 0; -reg qsfp0_tx_clk_4 = 0; -reg qsfp0_tx_rst_4 = 0; -reg qsfp0_rx_clk_4 = 0; -reg qsfp0_rx_rst_4 = 0; -reg [63:0] qsfp0_rxd_4 = 0; -reg [7:0] qsfp0_rxc_4 = 0; -reg qsfp1_tx_clk_1 = 0; -reg qsfp1_tx_rst_1 = 0; -reg qsfp1_rx_clk_1 = 0; -reg qsfp1_rx_rst_1 = 0; -reg [63:0] qsfp1_rxd_1 = 0; -reg [7:0] qsfp1_rxc_1 = 0; -reg qsfp1_tx_clk_2 = 0; -reg qsfp1_tx_rst_2 = 0; -reg qsfp1_rx_clk_2 = 0; -reg qsfp1_rx_rst_2 = 0; -reg [63:0] qsfp1_rxd_2 = 0; -reg [7:0] qsfp1_rxc_2 = 0; -reg qsfp1_tx_clk_3 = 0; -reg qsfp1_tx_rst_3 = 0; -reg qsfp1_rx_clk_3 = 0; -reg qsfp1_rx_rst_3 = 0; -reg [63:0] qsfp1_rxd_3 = 0; -reg [7:0] qsfp1_rxc_3 = 0; -reg qsfp1_tx_clk_4 = 0; -reg qsfp1_tx_rst_4 = 0; -reg qsfp1_rx_clk_4 = 0; -reg qsfp1_rx_rst_4 = 0; -reg [63:0] qsfp1_rxd_4 = 0; -reg [7:0] qsfp1_rxc_4 = 0; -reg uart_txd = 0; - -// Outputs -wire [2:0] led; -wire [63:0] qsfp0_txd_1; -wire [7:0] qsfp0_txc_1; -wire [63:0] qsfp0_txd_2; -wire [7:0] qsfp0_txc_2; -wire [63:0] qsfp0_txd_3; -wire [7:0] qsfp0_txc_3; -wire [63:0] qsfp0_txd_4; -wire [7:0] qsfp0_txc_4; -wire [63:0] qsfp1_txd_1; -wire [7:0] qsfp1_txc_1; -wire [63:0] qsfp1_txd_2; -wire [7:0] qsfp1_txc_2; -wire [63:0] qsfp1_txd_3; -wire [7:0] qsfp1_txc_3; -wire [63:0] qsfp1_txd_4; -wire [7:0] qsfp1_txc_4; -wire uart_rxd; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sw, - qsfp0_tx_clk_1, - qsfp0_tx_rst_1, - qsfp0_rx_clk_1, - qsfp0_rx_rst_1, - qsfp0_rxd_1, - qsfp0_rxc_1, - qsfp0_tx_clk_2, - qsfp0_tx_rst_2, - qsfp0_rx_clk_2, - qsfp0_rx_rst_2, - qsfp0_rxd_2, - qsfp0_rxc_2, - qsfp0_tx_clk_3, - qsfp0_tx_rst_3, - qsfp0_rx_clk_3, - qsfp0_rx_rst_3, - qsfp0_rxd_3, - qsfp0_rxc_3, - qsfp0_tx_clk_4, - qsfp0_tx_rst_4, - qsfp0_rx_clk_4, - qsfp0_rx_rst_4, - qsfp0_rxd_4, - qsfp0_rxc_4, - qsfp1_tx_clk_1, - qsfp1_tx_rst_1, - qsfp1_rx_clk_1, - qsfp1_rx_rst_1, - qsfp1_rxd_1, - qsfp1_rxc_1, - qsfp1_tx_clk_2, - qsfp1_tx_rst_2, - qsfp1_rx_clk_2, - qsfp1_rx_rst_2, - qsfp1_rxd_2, - qsfp1_rxc_2, - qsfp1_tx_clk_3, - qsfp1_tx_rst_3, - qsfp1_rx_clk_3, - qsfp1_rx_rst_3, - qsfp1_rxd_3, - qsfp1_rxc_3, - qsfp1_tx_clk_4, - qsfp1_tx_rst_4, - qsfp1_rx_clk_4, - qsfp1_rx_rst_4, - qsfp1_rxd_4, - qsfp1_rxc_4, - uart_txd - ); - $to_myhdl( - led, - qsfp0_txd_1, - qsfp0_txc_1, - qsfp0_txd_2, - qsfp0_txc_2, - qsfp0_txd_3, - qsfp0_txc_3, - qsfp0_txd_4, - qsfp0_txc_4, - qsfp1_txd_1, - qsfp1_txc_1, - qsfp1_txd_2, - qsfp1_txc_2, - qsfp1_txd_3, - qsfp1_txc_3, - qsfp1_txd_4, - qsfp1_txc_4, - uart_rxd - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sw(sw), - .led(led), - .qsfp0_tx_clk_1(qsfp0_tx_clk_1), - .qsfp0_tx_rst_1(qsfp0_tx_rst_1), - .qsfp0_txd_1(qsfp0_txd_1), - .qsfp0_txc_1(qsfp0_txc_1), - .qsfp0_rx_clk_1(qsfp0_rx_clk_1), - .qsfp0_rx_rst_1(qsfp0_rx_rst_1), - .qsfp0_rxd_1(qsfp0_rxd_1), - .qsfp0_rxc_1(qsfp0_rxc_1), - .qsfp0_tx_clk_2(qsfp0_tx_clk_2), - .qsfp0_tx_rst_2(qsfp0_tx_rst_2), - .qsfp0_txd_2(qsfp0_txd_2), - .qsfp0_txc_2(qsfp0_txc_2), - .qsfp0_rx_clk_2(qsfp0_rx_clk_2), - .qsfp0_rx_rst_2(qsfp0_rx_rst_2), - .qsfp0_rxd_2(qsfp0_rxd_2), - .qsfp0_rxc_2(qsfp0_rxc_2), - .qsfp0_tx_clk_3(qsfp0_tx_clk_3), - .qsfp0_tx_rst_3(qsfp0_tx_rst_3), - .qsfp0_txd_3(qsfp0_txd_3), - .qsfp0_txc_3(qsfp0_txc_3), - .qsfp0_rx_clk_3(qsfp0_rx_clk_3), - .qsfp0_rx_rst_3(qsfp0_rx_rst_3), - .qsfp0_rxd_3(qsfp0_rxd_3), - .qsfp0_rxc_3(qsfp0_rxc_3), - .qsfp0_tx_clk_4(qsfp0_tx_clk_4), - .qsfp0_tx_rst_4(qsfp0_tx_rst_4), - .qsfp0_txd_4(qsfp0_txd_4), - .qsfp0_txc_4(qsfp0_txc_4), - .qsfp0_rx_clk_4(qsfp0_rx_clk_4), - .qsfp0_rx_rst_4(qsfp0_rx_rst_4), - .qsfp0_rxd_4(qsfp0_rxd_4), - .qsfp0_rxc_4(qsfp0_rxc_4), - .qsfp1_tx_clk_1(qsfp1_tx_clk_1), - .qsfp1_tx_rst_1(qsfp1_tx_rst_1), - .qsfp1_txd_1(qsfp1_txd_1), - .qsfp1_txc_1(qsfp1_txc_1), - .qsfp1_rx_clk_1(qsfp1_rx_clk_1), - .qsfp1_rx_rst_1(qsfp1_rx_rst_1), - .qsfp1_rxd_1(qsfp1_rxd_1), - .qsfp1_rxc_1(qsfp1_rxc_1), - .qsfp1_tx_clk_2(qsfp1_tx_clk_2), - .qsfp1_tx_rst_2(qsfp1_tx_rst_2), - .qsfp1_txd_2(qsfp1_txd_2), - .qsfp1_txc_2(qsfp1_txc_2), - .qsfp1_rx_clk_2(qsfp1_rx_clk_2), - .qsfp1_rx_rst_2(qsfp1_rx_rst_2), - .qsfp1_rxd_2(qsfp1_rxd_2), - .qsfp1_rxc_2(qsfp1_rxc_2), - .qsfp1_tx_clk_3(qsfp1_tx_clk_3), - .qsfp1_tx_rst_3(qsfp1_tx_rst_3), - .qsfp1_txd_3(qsfp1_txd_3), - .qsfp1_txc_3(qsfp1_txc_3), - .qsfp1_rx_clk_3(qsfp1_rx_clk_3), - .qsfp1_rx_rst_3(qsfp1_rx_rst_3), - .qsfp1_rxd_3(qsfp1_rxd_3), - .qsfp1_rxc_3(qsfp1_rxc_3), - .qsfp1_tx_clk_4(qsfp1_tx_clk_4), - .qsfp1_tx_rst_4(qsfp1_tx_rst_4), - .qsfp1_txd_4(qsfp1_txd_4), - .qsfp1_txc_4(qsfp1_txc_4), - .qsfp1_rx_clk_4(qsfp1_rx_clk_4), - .qsfp1_rx_rst_4(qsfp1_rx_rst_4), - .qsfp1_rxd_4(qsfp1_rxd_4), - .qsfp1_rxc_4(qsfp1_rxc_4), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd) -); - -endmodule diff --git a/example/AU200/fpga_10g/tb/udp_ep.py b/example/AU200/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/AU200/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/AU200/fpga_10g/tb/xgmii_ep.py b/example/AU200/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/AU200/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/AU250/fpga_10g/tb/arp_ep.py b/example/AU250/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/AU250/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/AU250/fpga_10g/tb/axis_ep.py b/example/AU250/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/AU250/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/AU250/fpga_10g/tb/eth_ep.py b/example/AU250/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/AU250/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/AU250/fpga_10g/tb/fpga_core/Makefile b/example/AU250/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/AU250/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..74a58792d --- /dev/null +++ b/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,289 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp0_rx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_source = XgmiiSource(dut.qsfp0_rxd_1, dut.qsfp0_rxc_1, dut.qsfp0_rx_clk_1, dut.qsfp0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp0_tx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_sink = XgmiiSink(dut.qsfp0_txd_1, dut.qsfp0_txc_1, dut.qsfp0_tx_clk_1, dut.qsfp0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_source = XgmiiSource(dut.qsfp0_rxd_2, dut.qsfp0_rxc_2, dut.qsfp0_rx_clk_2, dut.qsfp0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp0_tx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_sink = XgmiiSink(dut.qsfp0_txd_2, dut.qsfp0_txc_2, dut.qsfp0_tx_clk_2, dut.qsfp0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_source = XgmiiSource(dut.qsfp0_rxd_3, dut.qsfp0_rxc_3, dut.qsfp0_rx_clk_3, dut.qsfp0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp0_tx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_sink = XgmiiSink(dut.qsfp0_txd_3, dut.qsfp0_txc_3, dut.qsfp0_tx_clk_3, dut.qsfp0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_source = XgmiiSource(dut.qsfp0_rxd_4, dut.qsfp0_rxc_4, dut.qsfp0_rx_clk_4, dut.qsfp0_rx_rst_4) + cocotb.fork(Clock(dut.qsfp0_tx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_sink = XgmiiSink(dut.qsfp0_txd_4, dut.qsfp0_txc_4, dut.qsfp0_tx_clk_4, dut.qsfp0_tx_rst_4) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_source = XgmiiSource(dut.qsfp1_rxd_1, dut.qsfp1_rxc_1, dut.qsfp1_rx_clk_1, dut.qsfp1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_sink = XgmiiSink(dut.qsfp1_txd_1, dut.qsfp1_txc_1, dut.qsfp1_tx_clk_1, dut.qsfp1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_source = XgmiiSource(dut.qsfp1_rxd_2, dut.qsfp1_rxc_2, dut.qsfp1_rx_clk_2, dut.qsfp1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_sink = XgmiiSink(dut.qsfp1_txd_2, dut.qsfp1_txc_2, dut.qsfp1_tx_clk_2, dut.qsfp1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_source = XgmiiSource(dut.qsfp1_rxd_3, dut.qsfp1_rxc_3, dut.qsfp1_rx_clk_3, dut.qsfp1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_sink = XgmiiSink(dut.qsfp1_txd_3, dut.qsfp1_txc_3, dut.qsfp1_tx_clk_3, dut.qsfp1_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_source = XgmiiSource(dut.qsfp1_rxd_4, dut.qsfp1_rxc_4, dut.qsfp1_rx_clk_4, dut.qsfp1_rx_rst_4) + cocotb.fork(Clock(dut.qsfp1_tx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_sink = XgmiiSink(dut.qsfp1_txd_4, dut.qsfp1_txc_4, dut.qsfp1_tx_clk_4, dut.qsfp1_tx_rst_4) + + dut.sw.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp0_rx_rst_1 <= 1 + self.dut.qsfp0_tx_rst_1 <= 1 + self.dut.qsfp0_rx_rst_2 <= 1 + self.dut.qsfp0_tx_rst_2 <= 1 + self.dut.qsfp0_rx_rst_3 <= 1 + self.dut.qsfp0_tx_rst_3 <= 1 + self.dut.qsfp0_rx_rst_4 <= 1 + self.dut.qsfp0_tx_rst_4 <= 1 + self.dut.qsfp1_rx_rst_1 <= 1 + self.dut.qsfp1_tx_rst_1 <= 1 + self.dut.qsfp1_rx_rst_2 <= 1 + self.dut.qsfp1_tx_rst_2 <= 1 + self.dut.qsfp1_rx_rst_3 <= 1 + self.dut.qsfp1_tx_rst_3 <= 1 + self.dut.qsfp1_rx_rst_4 <= 1 + self.dut.qsfp1_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp0_rx_rst_1 <= 0 + self.dut.qsfp0_tx_rst_1 <= 0 + self.dut.qsfp0_rx_rst_2 <= 0 + self.dut.qsfp0_tx_rst_2 <= 0 + self.dut.qsfp0_rx_rst_3 <= 0 + self.dut.qsfp0_tx_rst_3 <= 0 + self.dut.qsfp0_rx_rst_4 <= 0 + self.dut.qsfp0_tx_rst_4 <= 0 + self.dut.qsfp1_rx_rst_1 <= 0 + self.dut.qsfp1_tx_rst_1 <= 0 + self.dut.qsfp1_rx_rst_2 <= 0 + self.dut.qsfp1_tx_rst_2 <= 0 + self.dut.qsfp1_rx_rst_3 <= 0 + self.dut.qsfp1_tx_rst_3 <= 0 + self.dut.qsfp1_rx_rst_4 <= 0 + self.dut.qsfp1_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp0_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp0_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/AU250/fpga_10g/tb/ip_ep.py b/example/AU250/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/AU250/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/AU250/fpga_10g/tb/test_fpga_core.py b/example/AU250/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index b2a0e316a..000000000 --- a/example/AU250/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,465 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sw = Signal(intbv(0)[4:]) - qsfp0_tx_clk_1 = Signal(bool(0)) - qsfp0_tx_rst_1 = Signal(bool(0)) - qsfp0_rx_clk_1 = Signal(bool(0)) - qsfp0_rx_rst_1 = Signal(bool(0)) - qsfp0_rxd_1 = Signal(intbv(0)[64:]) - qsfp0_rxc_1 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_2 = Signal(bool(0)) - qsfp0_tx_rst_2 = Signal(bool(0)) - qsfp0_rx_clk_2 = Signal(bool(0)) - qsfp0_rx_rst_2 = Signal(bool(0)) - qsfp0_rxd_2 = Signal(intbv(0)[64:]) - qsfp0_rxc_2 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_3 = Signal(bool(0)) - qsfp0_tx_rst_3 = Signal(bool(0)) - qsfp0_rx_clk_3 = Signal(bool(0)) - qsfp0_rx_rst_3 = Signal(bool(0)) - qsfp0_rxd_3 = Signal(intbv(0)[64:]) - qsfp0_rxc_3 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_4 = Signal(bool(0)) - qsfp0_tx_rst_4 = Signal(bool(0)) - qsfp0_rx_clk_4 = Signal(bool(0)) - qsfp0_rx_rst_4 = Signal(bool(0)) - qsfp0_rxd_4 = Signal(intbv(0)[64:]) - qsfp0_rxc_4 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_1 = Signal(bool(0)) - qsfp1_tx_rst_1 = Signal(bool(0)) - qsfp1_rx_clk_1 = Signal(bool(0)) - qsfp1_rx_rst_1 = Signal(bool(0)) - qsfp1_rxd_1 = Signal(intbv(0)[64:]) - qsfp1_rxc_1 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_2 = Signal(bool(0)) - qsfp1_tx_rst_2 = Signal(bool(0)) - qsfp1_rx_clk_2 = Signal(bool(0)) - qsfp1_rx_rst_2 = Signal(bool(0)) - qsfp1_rxd_2 = Signal(intbv(0)[64:]) - qsfp1_rxc_2 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_3 = Signal(bool(0)) - qsfp1_tx_rst_3 = Signal(bool(0)) - qsfp1_rx_clk_3 = Signal(bool(0)) - qsfp1_rx_rst_3 = Signal(bool(0)) - qsfp1_rxd_3 = Signal(intbv(0)[64:]) - qsfp1_rxc_3 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_4 = Signal(bool(0)) - qsfp1_tx_rst_4 = Signal(bool(0)) - qsfp1_rx_clk_4 = Signal(bool(0)) - qsfp1_rx_rst_4 = Signal(bool(0)) - qsfp1_rxd_4 = Signal(intbv(0)[64:]) - qsfp1_rxc_4 = Signal(intbv(0)[8:]) - uart_txd = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[3:]) - qsfp0_txd_1 = Signal(intbv(0)[64:]) - qsfp0_txc_1 = Signal(intbv(0)[8:]) - qsfp0_txd_2 = Signal(intbv(0)[64:]) - qsfp0_txc_2 = Signal(intbv(0)[8:]) - qsfp0_txd_3 = Signal(intbv(0)[64:]) - qsfp0_txc_3 = Signal(intbv(0)[8:]) - qsfp0_txd_4 = Signal(intbv(0)[64:]) - qsfp0_txc_4 = Signal(intbv(0)[8:]) - qsfp1_txd_1 = Signal(intbv(0)[64:]) - qsfp1_txc_1 = Signal(intbv(0)[8:]) - qsfp1_txd_2 = Signal(intbv(0)[64:]) - qsfp1_txc_2 = Signal(intbv(0)[8:]) - qsfp1_txd_3 = Signal(intbv(0)[64:]) - qsfp1_txc_3 = Signal(intbv(0)[8:]) - qsfp1_txd_4 = Signal(intbv(0)[64:]) - qsfp1_txc_4 = Signal(intbv(0)[8:]) - uart_rxd = Signal(bool(0)) - - # sources and sinks - qsfp0_1_source = xgmii_ep.XGMIISource() - qsfp0_1_source_logic = qsfp0_1_source.create_logic(qsfp0_rx_clk_1, qsfp0_rx_rst_1, txd=qsfp0_rxd_1, txc=qsfp0_rxc_1, name='qsfp0_1_source') - - qsfp0_1_sink = xgmii_ep.XGMIISink() - qsfp0_1_sink_logic = qsfp0_1_sink.create_logic(qsfp0_tx_clk_1, qsfp0_tx_rst_1, rxd=qsfp0_txd_1, rxc=qsfp0_txc_1, name='qsfp0_1_sink') - - qsfp0_2_source = xgmii_ep.XGMIISource() - qsfp0_2_source_logic = qsfp0_2_source.create_logic(qsfp0_rx_clk_2, qsfp0_rx_rst_2, txd=qsfp0_rxd_2, txc=qsfp0_rxc_2, name='qsfp0_2_source') - - qsfp0_2_sink = xgmii_ep.XGMIISink() - qsfp0_2_sink_logic = qsfp0_2_sink.create_logic(qsfp0_tx_clk_2, qsfp0_tx_rst_2, rxd=qsfp0_txd_2, rxc=qsfp0_txc_2, name='qsfp0_2_sink') - - qsfp0_3_source = xgmii_ep.XGMIISource() - qsfp0_3_source_logic = qsfp0_3_source.create_logic(qsfp0_rx_clk_3, qsfp0_rx_rst_3, txd=qsfp0_rxd_3, txc=qsfp0_rxc_3, name='qsfp0_3_source') - - qsfp0_3_sink = xgmii_ep.XGMIISink() - qsfp0_3_sink_logic = qsfp0_3_sink.create_logic(qsfp0_tx_clk_3, qsfp0_tx_rst_3, rxd=qsfp0_txd_3, rxc=qsfp0_txc_3, name='qsfp0_3_sink') - - qsfp0_4_source = xgmii_ep.XGMIISource() - qsfp0_4_source_logic = qsfp0_4_source.create_logic(qsfp0_rx_clk_4, qsfp0_rx_rst_4, txd=qsfp0_rxd_4, txc=qsfp0_rxc_4, name='qsfp0_4_source') - - qsfp0_4_sink = xgmii_ep.XGMIISink() - qsfp0_4_sink_logic = qsfp0_4_sink.create_logic(qsfp0_tx_clk_4, qsfp0_tx_rst_4, rxd=qsfp0_txd_4, rxc=qsfp0_txc_4, name='qsfp0_4_sink') - - qsfp1_1_source = xgmii_ep.XGMIISource() - qsfp1_1_source_logic = qsfp1_1_source.create_logic(qsfp1_rx_clk_1, qsfp1_rx_rst_1, txd=qsfp1_rxd_1, txc=qsfp1_rxc_1, name='qsfp1_1_source') - - qsfp1_1_sink = xgmii_ep.XGMIISink() - qsfp1_1_sink_logic = qsfp1_1_sink.create_logic(qsfp1_tx_clk_1, qsfp1_tx_rst_1, rxd=qsfp1_txd_1, rxc=qsfp1_txc_1, name='qsfp1_1_sink') - - qsfp1_2_source = xgmii_ep.XGMIISource() - qsfp1_2_source_logic = qsfp1_2_source.create_logic(qsfp1_rx_clk_2, qsfp1_rx_rst_2, txd=qsfp1_rxd_2, txc=qsfp1_rxc_2, name='qsfp1_2_source') - - qsfp1_2_sink = xgmii_ep.XGMIISink() - qsfp1_2_sink_logic = qsfp1_2_sink.create_logic(qsfp1_tx_clk_2, qsfp1_tx_rst_2, rxd=qsfp1_txd_2, rxc=qsfp1_txc_2, name='qsfp1_2_sink') - - qsfp1_3_source = xgmii_ep.XGMIISource() - qsfp1_3_source_logic = qsfp1_3_source.create_logic(qsfp1_rx_clk_3, qsfp1_rx_rst_3, txd=qsfp1_rxd_3, txc=qsfp1_rxc_3, name='qsfp1_3_source') - - qsfp1_3_sink = xgmii_ep.XGMIISink() - qsfp1_3_sink_logic = qsfp1_3_sink.create_logic(qsfp1_tx_clk_3, qsfp1_tx_rst_3, rxd=qsfp1_txd_3, rxc=qsfp1_txc_3, name='qsfp1_3_sink') - - qsfp1_4_source = xgmii_ep.XGMIISource() - qsfp1_4_source_logic = qsfp1_4_source.create_logic(qsfp1_rx_clk_4, qsfp1_rx_rst_4, txd=qsfp1_rxd_4, txc=qsfp1_rxc_4, name='qsfp1_4_source') - - qsfp1_4_sink = xgmii_ep.XGMIISink() - qsfp1_4_sink_logic = qsfp1_4_sink.create_logic(qsfp1_tx_clk_4, qsfp1_tx_rst_4, rxd=qsfp1_txd_4, rxc=qsfp1_txc_4, name='qsfp1_4_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sw=sw, - led=led, - - qsfp0_tx_clk_1=qsfp0_tx_clk_1, - qsfp0_tx_rst_1=qsfp0_tx_rst_1, - qsfp0_txd_1=qsfp0_txd_1, - qsfp0_txc_1=qsfp0_txc_1, - qsfp0_rx_clk_1=qsfp0_rx_clk_1, - qsfp0_rx_rst_1=qsfp0_rx_rst_1, - qsfp0_rxd_1=qsfp0_rxd_1, - qsfp0_rxc_1=qsfp0_rxc_1, - qsfp0_tx_clk_2=qsfp0_tx_clk_2, - qsfp0_tx_rst_2=qsfp0_tx_rst_2, - qsfp0_txd_2=qsfp0_txd_2, - qsfp0_txc_2=qsfp0_txc_2, - qsfp0_rx_clk_2=qsfp0_rx_clk_2, - qsfp0_rx_rst_2=qsfp0_rx_rst_2, - qsfp0_rxd_2=qsfp0_rxd_2, - qsfp0_rxc_2=qsfp0_rxc_2, - qsfp0_tx_clk_3=qsfp0_tx_clk_3, - qsfp0_tx_rst_3=qsfp0_tx_rst_3, - qsfp0_txd_3=qsfp0_txd_3, - qsfp0_txc_3=qsfp0_txc_3, - qsfp0_rx_clk_3=qsfp0_rx_clk_3, - qsfp0_rx_rst_3=qsfp0_rx_rst_3, - qsfp0_rxd_3=qsfp0_rxd_3, - qsfp0_rxc_3=qsfp0_rxc_3, - qsfp0_tx_clk_4=qsfp0_tx_clk_4, - qsfp0_tx_rst_4=qsfp0_tx_rst_4, - qsfp0_txd_4=qsfp0_txd_4, - qsfp0_txc_4=qsfp0_txc_4, - qsfp0_rx_clk_4=qsfp0_rx_clk_4, - qsfp0_rx_rst_4=qsfp0_rx_rst_4, - qsfp0_rxd_4=qsfp0_rxd_4, - qsfp0_rxc_4=qsfp0_rxc_4, - qsfp1_tx_clk_1=qsfp1_tx_clk_1, - qsfp1_tx_rst_1=qsfp1_tx_rst_1, - qsfp1_txd_1=qsfp1_txd_1, - qsfp1_txc_1=qsfp1_txc_1, - qsfp1_rx_clk_1=qsfp1_rx_clk_1, - qsfp1_rx_rst_1=qsfp1_rx_rst_1, - qsfp1_rxd_1=qsfp1_rxd_1, - qsfp1_rxc_1=qsfp1_rxc_1, - qsfp1_tx_clk_2=qsfp1_tx_clk_2, - qsfp1_tx_rst_2=qsfp1_tx_rst_2, - qsfp1_txd_2=qsfp1_txd_2, - qsfp1_txc_2=qsfp1_txc_2, - qsfp1_rx_clk_2=qsfp1_rx_clk_2, - qsfp1_rx_rst_2=qsfp1_rx_rst_2, - qsfp1_rxd_2=qsfp1_rxd_2, - qsfp1_rxc_2=qsfp1_rxc_2, - qsfp1_tx_clk_3=qsfp1_tx_clk_3, - qsfp1_tx_rst_3=qsfp1_tx_rst_3, - qsfp1_txd_3=qsfp1_txd_3, - qsfp1_txc_3=qsfp1_txc_3, - qsfp1_rx_clk_3=qsfp1_rx_clk_3, - qsfp1_rx_rst_3=qsfp1_rx_rst_3, - qsfp1_rxd_3=qsfp1_rxd_3, - qsfp1_rxc_3=qsfp1_rxc_3, - qsfp1_tx_clk_4=qsfp1_tx_clk_4, - qsfp1_tx_rst_4=qsfp1_tx_rst_4, - qsfp1_txd_4=qsfp1_txd_4, - qsfp1_txc_4=qsfp1_txc_4, - qsfp1_rx_clk_4=qsfp1_rx_clk_4, - qsfp1_rx_rst_4=qsfp1_rx_rst_4, - qsfp1_rxd_4=qsfp1_rxd_4, - qsfp1_rxc_4=qsfp1_rxc_4, - - uart_rxd=uart_rxd, - uart_txd=uart_txd - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp0_tx_clk_1.next = not qsfp0_tx_clk_1 - qsfp0_rx_clk_1.next = not qsfp0_rx_clk_1 - qsfp0_tx_clk_2.next = not qsfp0_tx_clk_2 - qsfp0_rx_clk_2.next = not qsfp0_rx_clk_2 - qsfp0_tx_clk_3.next = not qsfp0_tx_clk_3 - qsfp0_rx_clk_3.next = not qsfp0_rx_clk_3 - qsfp0_tx_clk_4.next = not qsfp0_tx_clk_4 - qsfp0_rx_clk_4.next = not qsfp0_rx_clk_4 - qsfp1_tx_clk_1.next = not qsfp1_tx_clk_1 - qsfp1_rx_clk_1.next = not qsfp1_rx_clk_1 - qsfp1_tx_clk_2.next = not qsfp1_tx_clk_2 - qsfp1_rx_clk_2.next = not qsfp1_rx_clk_2 - qsfp1_tx_clk_3.next = not qsfp1_tx_clk_3 - qsfp1_rx_clk_3.next = not qsfp1_rx_clk_3 - qsfp1_tx_clk_4.next = not qsfp1_tx_clk_4 - qsfp1_rx_clk_4.next = not qsfp1_rx_clk_4 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp0_tx_rst_1.next = 1 - qsfp0_rx_rst_1.next = 1 - qsfp0_tx_rst_2.next = 1 - qsfp0_rx_rst_2.next = 1 - qsfp0_tx_rst_3.next = 1 - qsfp0_rx_rst_3.next = 1 - qsfp0_tx_rst_4.next = 1 - qsfp0_rx_rst_4.next = 1 - qsfp1_tx_rst_1.next = 1 - qsfp1_rx_rst_1.next = 1 - qsfp1_tx_rst_2.next = 1 - qsfp1_rx_rst_2.next = 1 - qsfp1_tx_rst_3.next = 1 - qsfp1_rx_rst_3.next = 1 - qsfp1_tx_rst_4.next = 1 - qsfp1_rx_rst_4.next = 1 - yield clk.posedge - rst.next = 0 - qsfp0_tx_rst_1.next = 0 - qsfp0_rx_rst_1.next = 0 - qsfp0_tx_rst_2.next = 0 - qsfp0_rx_rst_2.next = 0 - qsfp0_tx_rst_3.next = 0 - qsfp0_rx_rst_3.next = 0 - qsfp0_tx_rst_4.next = 0 - qsfp0_rx_rst_4.next = 0 - qsfp1_tx_rst_1.next = 0 - qsfp1_rx_rst_1.next = 0 - qsfp1_tx_rst_2.next = 0 - qsfp1_rx_rst_2.next = 0 - qsfp1_tx_rst_3.next = 0 - qsfp1_rx_rst_3.next = 0 - qsfp1_tx_rst_4.next = 0 - qsfp1_rx_rst_4.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp0_1_source.empty() - assert qsfp0_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/AU250/fpga_10g/tb/test_fpga_core.v b/example/AU250/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index fddb81323..000000000 --- a/example/AU250/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] sw = 0; -reg qsfp0_tx_clk_1 = 0; -reg qsfp0_tx_rst_1 = 0; -reg qsfp0_rx_clk_1 = 0; -reg qsfp0_rx_rst_1 = 0; -reg [63:0] qsfp0_rxd_1 = 0; -reg [7:0] qsfp0_rxc_1 = 0; -reg qsfp0_tx_clk_2 = 0; -reg qsfp0_tx_rst_2 = 0; -reg qsfp0_rx_clk_2 = 0; -reg qsfp0_rx_rst_2 = 0; -reg [63:0] qsfp0_rxd_2 = 0; -reg [7:0] qsfp0_rxc_2 = 0; -reg qsfp0_tx_clk_3 = 0; -reg qsfp0_tx_rst_3 = 0; -reg qsfp0_rx_clk_3 = 0; -reg qsfp0_rx_rst_3 = 0; -reg [63:0] qsfp0_rxd_3 = 0; -reg [7:0] qsfp0_rxc_3 = 0; -reg qsfp0_tx_clk_4 = 0; -reg qsfp0_tx_rst_4 = 0; -reg qsfp0_rx_clk_4 = 0; -reg qsfp0_rx_rst_4 = 0; -reg [63:0] qsfp0_rxd_4 = 0; -reg [7:0] qsfp0_rxc_4 = 0; -reg qsfp1_tx_clk_1 = 0; -reg qsfp1_tx_rst_1 = 0; -reg qsfp1_rx_clk_1 = 0; -reg qsfp1_rx_rst_1 = 0; -reg [63:0] qsfp1_rxd_1 = 0; -reg [7:0] qsfp1_rxc_1 = 0; -reg qsfp1_tx_clk_2 = 0; -reg qsfp1_tx_rst_2 = 0; -reg qsfp1_rx_clk_2 = 0; -reg qsfp1_rx_rst_2 = 0; -reg [63:0] qsfp1_rxd_2 = 0; -reg [7:0] qsfp1_rxc_2 = 0; -reg qsfp1_tx_clk_3 = 0; -reg qsfp1_tx_rst_3 = 0; -reg qsfp1_rx_clk_3 = 0; -reg qsfp1_rx_rst_3 = 0; -reg [63:0] qsfp1_rxd_3 = 0; -reg [7:0] qsfp1_rxc_3 = 0; -reg qsfp1_tx_clk_4 = 0; -reg qsfp1_tx_rst_4 = 0; -reg qsfp1_rx_clk_4 = 0; -reg qsfp1_rx_rst_4 = 0; -reg [63:0] qsfp1_rxd_4 = 0; -reg [7:0] qsfp1_rxc_4 = 0; -reg uart_txd = 0; - -// Outputs -wire [2:0] led; -wire [63:0] qsfp0_txd_1; -wire [7:0] qsfp0_txc_1; -wire [63:0] qsfp0_txd_2; -wire [7:0] qsfp0_txc_2; -wire [63:0] qsfp0_txd_3; -wire [7:0] qsfp0_txc_3; -wire [63:0] qsfp0_txd_4; -wire [7:0] qsfp0_txc_4; -wire [63:0] qsfp1_txd_1; -wire [7:0] qsfp1_txc_1; -wire [63:0] qsfp1_txd_2; -wire [7:0] qsfp1_txc_2; -wire [63:0] qsfp1_txd_3; -wire [7:0] qsfp1_txc_3; -wire [63:0] qsfp1_txd_4; -wire [7:0] qsfp1_txc_4; -wire uart_rxd; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sw, - qsfp0_tx_clk_1, - qsfp0_tx_rst_1, - qsfp0_rx_clk_1, - qsfp0_rx_rst_1, - qsfp0_rxd_1, - qsfp0_rxc_1, - qsfp0_tx_clk_2, - qsfp0_tx_rst_2, - qsfp0_rx_clk_2, - qsfp0_rx_rst_2, - qsfp0_rxd_2, - qsfp0_rxc_2, - qsfp0_tx_clk_3, - qsfp0_tx_rst_3, - qsfp0_rx_clk_3, - qsfp0_rx_rst_3, - qsfp0_rxd_3, - qsfp0_rxc_3, - qsfp0_tx_clk_4, - qsfp0_tx_rst_4, - qsfp0_rx_clk_4, - qsfp0_rx_rst_4, - qsfp0_rxd_4, - qsfp0_rxc_4, - qsfp1_tx_clk_1, - qsfp1_tx_rst_1, - qsfp1_rx_clk_1, - qsfp1_rx_rst_1, - qsfp1_rxd_1, - qsfp1_rxc_1, - qsfp1_tx_clk_2, - qsfp1_tx_rst_2, - qsfp1_rx_clk_2, - qsfp1_rx_rst_2, - qsfp1_rxd_2, - qsfp1_rxc_2, - qsfp1_tx_clk_3, - qsfp1_tx_rst_3, - qsfp1_rx_clk_3, - qsfp1_rx_rst_3, - qsfp1_rxd_3, - qsfp1_rxc_3, - qsfp1_tx_clk_4, - qsfp1_tx_rst_4, - qsfp1_rx_clk_4, - qsfp1_rx_rst_4, - qsfp1_rxd_4, - qsfp1_rxc_4, - uart_txd - ); - $to_myhdl( - led, - qsfp0_txd_1, - qsfp0_txc_1, - qsfp0_txd_2, - qsfp0_txc_2, - qsfp0_txd_3, - qsfp0_txc_3, - qsfp0_txd_4, - qsfp0_txc_4, - qsfp1_txd_1, - qsfp1_txc_1, - qsfp1_txd_2, - qsfp1_txc_2, - qsfp1_txd_3, - qsfp1_txc_3, - qsfp1_txd_4, - qsfp1_txc_4, - uart_rxd - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sw(sw), - .led(led), - .qsfp0_tx_clk_1(qsfp0_tx_clk_1), - .qsfp0_tx_rst_1(qsfp0_tx_rst_1), - .qsfp0_txd_1(qsfp0_txd_1), - .qsfp0_txc_1(qsfp0_txc_1), - .qsfp0_rx_clk_1(qsfp0_rx_clk_1), - .qsfp0_rx_rst_1(qsfp0_rx_rst_1), - .qsfp0_rxd_1(qsfp0_rxd_1), - .qsfp0_rxc_1(qsfp0_rxc_1), - .qsfp0_tx_clk_2(qsfp0_tx_clk_2), - .qsfp0_tx_rst_2(qsfp0_tx_rst_2), - .qsfp0_txd_2(qsfp0_txd_2), - .qsfp0_txc_2(qsfp0_txc_2), - .qsfp0_rx_clk_2(qsfp0_rx_clk_2), - .qsfp0_rx_rst_2(qsfp0_rx_rst_2), - .qsfp0_rxd_2(qsfp0_rxd_2), - .qsfp0_rxc_2(qsfp0_rxc_2), - .qsfp0_tx_clk_3(qsfp0_tx_clk_3), - .qsfp0_tx_rst_3(qsfp0_tx_rst_3), - .qsfp0_txd_3(qsfp0_txd_3), - .qsfp0_txc_3(qsfp0_txc_3), - .qsfp0_rx_clk_3(qsfp0_rx_clk_3), - .qsfp0_rx_rst_3(qsfp0_rx_rst_3), - .qsfp0_rxd_3(qsfp0_rxd_3), - .qsfp0_rxc_3(qsfp0_rxc_3), - .qsfp0_tx_clk_4(qsfp0_tx_clk_4), - .qsfp0_tx_rst_4(qsfp0_tx_rst_4), - .qsfp0_txd_4(qsfp0_txd_4), - .qsfp0_txc_4(qsfp0_txc_4), - .qsfp0_rx_clk_4(qsfp0_rx_clk_4), - .qsfp0_rx_rst_4(qsfp0_rx_rst_4), - .qsfp0_rxd_4(qsfp0_rxd_4), - .qsfp0_rxc_4(qsfp0_rxc_4), - .qsfp1_tx_clk_1(qsfp1_tx_clk_1), - .qsfp1_tx_rst_1(qsfp1_tx_rst_1), - .qsfp1_txd_1(qsfp1_txd_1), - .qsfp1_txc_1(qsfp1_txc_1), - .qsfp1_rx_clk_1(qsfp1_rx_clk_1), - .qsfp1_rx_rst_1(qsfp1_rx_rst_1), - .qsfp1_rxd_1(qsfp1_rxd_1), - .qsfp1_rxc_1(qsfp1_rxc_1), - .qsfp1_tx_clk_2(qsfp1_tx_clk_2), - .qsfp1_tx_rst_2(qsfp1_tx_rst_2), - .qsfp1_txd_2(qsfp1_txd_2), - .qsfp1_txc_2(qsfp1_txc_2), - .qsfp1_rx_clk_2(qsfp1_rx_clk_2), - .qsfp1_rx_rst_2(qsfp1_rx_rst_2), - .qsfp1_rxd_2(qsfp1_rxd_2), - .qsfp1_rxc_2(qsfp1_rxc_2), - .qsfp1_tx_clk_3(qsfp1_tx_clk_3), - .qsfp1_tx_rst_3(qsfp1_tx_rst_3), - .qsfp1_txd_3(qsfp1_txd_3), - .qsfp1_txc_3(qsfp1_txc_3), - .qsfp1_rx_clk_3(qsfp1_rx_clk_3), - .qsfp1_rx_rst_3(qsfp1_rx_rst_3), - .qsfp1_rxd_3(qsfp1_rxd_3), - .qsfp1_rxc_3(qsfp1_rxc_3), - .qsfp1_tx_clk_4(qsfp1_tx_clk_4), - .qsfp1_tx_rst_4(qsfp1_tx_rst_4), - .qsfp1_txd_4(qsfp1_txd_4), - .qsfp1_txc_4(qsfp1_txc_4), - .qsfp1_rx_clk_4(qsfp1_rx_clk_4), - .qsfp1_rx_rst_4(qsfp1_rx_rst_4), - .qsfp1_rxd_4(qsfp1_rxd_4), - .qsfp1_rxc_4(qsfp1_rxc_4), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd) -); - -endmodule diff --git a/example/AU250/fpga_10g/tb/udp_ep.py b/example/AU250/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/AU250/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/AU250/fpga_10g/tb/xgmii_ep.py b/example/AU250/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/AU250/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/AU280/fpga_10g/tb/arp_ep.py b/example/AU280/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/AU280/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/AU280/fpga_10g/tb/axis_ep.py b/example/AU280/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/AU280/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/AU280/fpga_10g/tb/eth_ep.py b/example/AU280/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/AU280/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/AU280/fpga_10g/tb/fpga_core/Makefile b/example/AU280/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/AU280/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..f2e5b20b6 --- /dev/null +++ b/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,287 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp0_rx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_source = XgmiiSource(dut.qsfp0_rxd_1, dut.qsfp0_rxc_1, dut.qsfp0_rx_clk_1, dut.qsfp0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp0_tx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_sink = XgmiiSink(dut.qsfp0_txd_1, dut.qsfp0_txc_1, dut.qsfp0_tx_clk_1, dut.qsfp0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_source = XgmiiSource(dut.qsfp0_rxd_2, dut.qsfp0_rxc_2, dut.qsfp0_rx_clk_2, dut.qsfp0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp0_tx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_sink = XgmiiSink(dut.qsfp0_txd_2, dut.qsfp0_txc_2, dut.qsfp0_tx_clk_2, dut.qsfp0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_source = XgmiiSource(dut.qsfp0_rxd_3, dut.qsfp0_rxc_3, dut.qsfp0_rx_clk_3, dut.qsfp0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp0_tx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_sink = XgmiiSink(dut.qsfp0_txd_3, dut.qsfp0_txc_3, dut.qsfp0_tx_clk_3, dut.qsfp0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_source = XgmiiSource(dut.qsfp0_rxd_4, dut.qsfp0_rxc_4, dut.qsfp0_rx_clk_4, dut.qsfp0_rx_rst_4) + cocotb.fork(Clock(dut.qsfp0_tx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_sink = XgmiiSink(dut.qsfp0_txd_4, dut.qsfp0_txc_4, dut.qsfp0_tx_clk_4, dut.qsfp0_tx_rst_4) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_source = XgmiiSource(dut.qsfp1_rxd_1, dut.qsfp1_rxc_1, dut.qsfp1_rx_clk_1, dut.qsfp1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_sink = XgmiiSink(dut.qsfp1_txd_1, dut.qsfp1_txc_1, dut.qsfp1_tx_clk_1, dut.qsfp1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_source = XgmiiSource(dut.qsfp1_rxd_2, dut.qsfp1_rxc_2, dut.qsfp1_rx_clk_2, dut.qsfp1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_sink = XgmiiSink(dut.qsfp1_txd_2, dut.qsfp1_txc_2, dut.qsfp1_tx_clk_2, dut.qsfp1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_source = XgmiiSource(dut.qsfp1_rxd_3, dut.qsfp1_rxc_3, dut.qsfp1_rx_clk_3, dut.qsfp1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_sink = XgmiiSink(dut.qsfp1_txd_3, dut.qsfp1_txc_3, dut.qsfp1_tx_clk_3, dut.qsfp1_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_source = XgmiiSource(dut.qsfp1_rxd_4, dut.qsfp1_rxc_4, dut.qsfp1_rx_clk_4, dut.qsfp1_rx_rst_4) + cocotb.fork(Clock(dut.qsfp1_tx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_sink = XgmiiSink(dut.qsfp1_txd_4, dut.qsfp1_txc_4, dut.qsfp1_tx_clk_4, dut.qsfp1_tx_rst_4) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp0_rx_rst_1 <= 1 + self.dut.qsfp0_tx_rst_1 <= 1 + self.dut.qsfp0_rx_rst_2 <= 1 + self.dut.qsfp0_tx_rst_2 <= 1 + self.dut.qsfp0_rx_rst_3 <= 1 + self.dut.qsfp0_tx_rst_3 <= 1 + self.dut.qsfp0_rx_rst_4 <= 1 + self.dut.qsfp0_tx_rst_4 <= 1 + self.dut.qsfp1_rx_rst_1 <= 1 + self.dut.qsfp1_tx_rst_1 <= 1 + self.dut.qsfp1_rx_rst_2 <= 1 + self.dut.qsfp1_tx_rst_2 <= 1 + self.dut.qsfp1_rx_rst_3 <= 1 + self.dut.qsfp1_tx_rst_3 <= 1 + self.dut.qsfp1_rx_rst_4 <= 1 + self.dut.qsfp1_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp0_rx_rst_1 <= 0 + self.dut.qsfp0_tx_rst_1 <= 0 + self.dut.qsfp0_rx_rst_2 <= 0 + self.dut.qsfp0_tx_rst_2 <= 0 + self.dut.qsfp0_rx_rst_3 <= 0 + self.dut.qsfp0_tx_rst_3 <= 0 + self.dut.qsfp0_rx_rst_4 <= 0 + self.dut.qsfp0_tx_rst_4 <= 0 + self.dut.qsfp1_rx_rst_1 <= 0 + self.dut.qsfp1_tx_rst_1 <= 0 + self.dut.qsfp1_rx_rst_2 <= 0 + self.dut.qsfp1_tx_rst_2 <= 0 + self.dut.qsfp1_rx_rst_3 <= 0 + self.dut.qsfp1_tx_rst_3 <= 0 + self.dut.qsfp1_rx_rst_4 <= 0 + self.dut.qsfp1_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp0_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp0_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/AU280/fpga_10g/tb/ip_ep.py b/example/AU280/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/AU280/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/AU280/fpga_10g/tb/test_fpga_core.py b/example/AU280/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index 5039f8528..000000000 --- a/example/AU280/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,455 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - qsfp0_tx_clk_1 = Signal(bool(0)) - qsfp0_tx_rst_1 = Signal(bool(0)) - qsfp0_rx_clk_1 = Signal(bool(0)) - qsfp0_rx_rst_1 = Signal(bool(0)) - qsfp0_rxd_1 = Signal(intbv(0)[64:]) - qsfp0_rxc_1 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_2 = Signal(bool(0)) - qsfp0_tx_rst_2 = Signal(bool(0)) - qsfp0_rx_clk_2 = Signal(bool(0)) - qsfp0_rx_rst_2 = Signal(bool(0)) - qsfp0_rxd_2 = Signal(intbv(0)[64:]) - qsfp0_rxc_2 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_3 = Signal(bool(0)) - qsfp0_tx_rst_3 = Signal(bool(0)) - qsfp0_rx_clk_3 = Signal(bool(0)) - qsfp0_rx_rst_3 = Signal(bool(0)) - qsfp0_rxd_3 = Signal(intbv(0)[64:]) - qsfp0_rxc_3 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_4 = Signal(bool(0)) - qsfp0_tx_rst_4 = Signal(bool(0)) - qsfp0_rx_clk_4 = Signal(bool(0)) - qsfp0_rx_rst_4 = Signal(bool(0)) - qsfp0_rxd_4 = Signal(intbv(0)[64:]) - qsfp0_rxc_4 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_1 = Signal(bool(0)) - qsfp1_tx_rst_1 = Signal(bool(0)) - qsfp1_rx_clk_1 = Signal(bool(0)) - qsfp1_rx_rst_1 = Signal(bool(0)) - qsfp1_rxd_1 = Signal(intbv(0)[64:]) - qsfp1_rxc_1 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_2 = Signal(bool(0)) - qsfp1_tx_rst_2 = Signal(bool(0)) - qsfp1_rx_clk_2 = Signal(bool(0)) - qsfp1_rx_rst_2 = Signal(bool(0)) - qsfp1_rxd_2 = Signal(intbv(0)[64:]) - qsfp1_rxc_2 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_3 = Signal(bool(0)) - qsfp1_tx_rst_3 = Signal(bool(0)) - qsfp1_rx_clk_3 = Signal(bool(0)) - qsfp1_rx_rst_3 = Signal(bool(0)) - qsfp1_rxd_3 = Signal(intbv(0)[64:]) - qsfp1_rxc_3 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_4 = Signal(bool(0)) - qsfp1_tx_rst_4 = Signal(bool(0)) - qsfp1_rx_clk_4 = Signal(bool(0)) - qsfp1_rx_rst_4 = Signal(bool(0)) - qsfp1_rxd_4 = Signal(intbv(0)[64:]) - qsfp1_rxc_4 = Signal(intbv(0)[8:]) - - # Outputs - qsfp0_txd_1 = Signal(intbv(0)[64:]) - qsfp0_txc_1 = Signal(intbv(0)[8:]) - qsfp0_txd_2 = Signal(intbv(0)[64:]) - qsfp0_txc_2 = Signal(intbv(0)[8:]) - qsfp0_txd_3 = Signal(intbv(0)[64:]) - qsfp0_txc_3 = Signal(intbv(0)[8:]) - qsfp0_txd_4 = Signal(intbv(0)[64:]) - qsfp0_txc_4 = Signal(intbv(0)[8:]) - qsfp1_txd_1 = Signal(intbv(0)[64:]) - qsfp1_txc_1 = Signal(intbv(0)[8:]) - qsfp1_txd_2 = Signal(intbv(0)[64:]) - qsfp1_txc_2 = Signal(intbv(0)[8:]) - qsfp1_txd_3 = Signal(intbv(0)[64:]) - qsfp1_txc_3 = Signal(intbv(0)[8:]) - qsfp1_txd_4 = Signal(intbv(0)[64:]) - qsfp1_txc_4 = Signal(intbv(0)[8:]) - - # sources and sinks - qsfp0_1_source = xgmii_ep.XGMIISource() - qsfp0_1_source_logic = qsfp0_1_source.create_logic(qsfp0_rx_clk_1, qsfp0_rx_rst_1, txd=qsfp0_rxd_1, txc=qsfp0_rxc_1, name='qsfp0_1_source') - - qsfp0_1_sink = xgmii_ep.XGMIISink() - qsfp0_1_sink_logic = qsfp0_1_sink.create_logic(qsfp0_tx_clk_1, qsfp0_tx_rst_1, rxd=qsfp0_txd_1, rxc=qsfp0_txc_1, name='qsfp0_1_sink') - - qsfp0_2_source = xgmii_ep.XGMIISource() - qsfp0_2_source_logic = qsfp0_2_source.create_logic(qsfp0_rx_clk_2, qsfp0_rx_rst_2, txd=qsfp0_rxd_2, txc=qsfp0_rxc_2, name='qsfp0_2_source') - - qsfp0_2_sink = xgmii_ep.XGMIISink() - qsfp0_2_sink_logic = qsfp0_2_sink.create_logic(qsfp0_tx_clk_2, qsfp0_tx_rst_2, rxd=qsfp0_txd_2, rxc=qsfp0_txc_2, name='qsfp0_2_sink') - - qsfp0_3_source = xgmii_ep.XGMIISource() - qsfp0_3_source_logic = qsfp0_3_source.create_logic(qsfp0_rx_clk_3, qsfp0_rx_rst_3, txd=qsfp0_rxd_3, txc=qsfp0_rxc_3, name='qsfp0_3_source') - - qsfp0_3_sink = xgmii_ep.XGMIISink() - qsfp0_3_sink_logic = qsfp0_3_sink.create_logic(qsfp0_tx_clk_3, qsfp0_tx_rst_3, rxd=qsfp0_txd_3, rxc=qsfp0_txc_3, name='qsfp0_3_sink') - - qsfp0_4_source = xgmii_ep.XGMIISource() - qsfp0_4_source_logic = qsfp0_4_source.create_logic(qsfp0_rx_clk_4, qsfp0_rx_rst_4, txd=qsfp0_rxd_4, txc=qsfp0_rxc_4, name='qsfp0_4_source') - - qsfp0_4_sink = xgmii_ep.XGMIISink() - qsfp0_4_sink_logic = qsfp0_4_sink.create_logic(qsfp0_tx_clk_4, qsfp0_tx_rst_4, rxd=qsfp0_txd_4, rxc=qsfp0_txc_4, name='qsfp0_4_sink') - - qsfp1_1_source = xgmii_ep.XGMIISource() - qsfp1_1_source_logic = qsfp1_1_source.create_logic(qsfp1_rx_clk_1, qsfp1_rx_rst_1, txd=qsfp1_rxd_1, txc=qsfp1_rxc_1, name='qsfp1_1_source') - - qsfp1_1_sink = xgmii_ep.XGMIISink() - qsfp1_1_sink_logic = qsfp1_1_sink.create_logic(qsfp1_tx_clk_1, qsfp1_tx_rst_1, rxd=qsfp1_txd_1, rxc=qsfp1_txc_1, name='qsfp1_1_sink') - - qsfp1_2_source = xgmii_ep.XGMIISource() - qsfp1_2_source_logic = qsfp1_2_source.create_logic(qsfp1_rx_clk_2, qsfp1_rx_rst_2, txd=qsfp1_rxd_2, txc=qsfp1_rxc_2, name='qsfp1_2_source') - - qsfp1_2_sink = xgmii_ep.XGMIISink() - qsfp1_2_sink_logic = qsfp1_2_sink.create_logic(qsfp1_tx_clk_2, qsfp1_tx_rst_2, rxd=qsfp1_txd_2, rxc=qsfp1_txc_2, name='qsfp1_2_sink') - - qsfp1_3_source = xgmii_ep.XGMIISource() - qsfp1_3_source_logic = qsfp1_3_source.create_logic(qsfp1_rx_clk_3, qsfp1_rx_rst_3, txd=qsfp1_rxd_3, txc=qsfp1_rxc_3, name='qsfp1_3_source') - - qsfp1_3_sink = xgmii_ep.XGMIISink() - qsfp1_3_sink_logic = qsfp1_3_sink.create_logic(qsfp1_tx_clk_3, qsfp1_tx_rst_3, rxd=qsfp1_txd_3, rxc=qsfp1_txc_3, name='qsfp1_3_sink') - - qsfp1_4_source = xgmii_ep.XGMIISource() - qsfp1_4_source_logic = qsfp1_4_source.create_logic(qsfp1_rx_clk_4, qsfp1_rx_rst_4, txd=qsfp1_rxd_4, txc=qsfp1_rxc_4, name='qsfp1_4_source') - - qsfp1_4_sink = xgmii_ep.XGMIISink() - qsfp1_4_sink_logic = qsfp1_4_sink.create_logic(qsfp1_tx_clk_4, qsfp1_tx_rst_4, rxd=qsfp1_txd_4, rxc=qsfp1_txc_4, name='qsfp1_4_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - qsfp0_tx_clk_1=qsfp0_tx_clk_1, - qsfp0_tx_rst_1=qsfp0_tx_rst_1, - qsfp0_txd_1=qsfp0_txd_1, - qsfp0_txc_1=qsfp0_txc_1, - qsfp0_rx_clk_1=qsfp0_rx_clk_1, - qsfp0_rx_rst_1=qsfp0_rx_rst_1, - qsfp0_rxd_1=qsfp0_rxd_1, - qsfp0_rxc_1=qsfp0_rxc_1, - qsfp0_tx_clk_2=qsfp0_tx_clk_2, - qsfp0_tx_rst_2=qsfp0_tx_rst_2, - qsfp0_txd_2=qsfp0_txd_2, - qsfp0_txc_2=qsfp0_txc_2, - qsfp0_rx_clk_2=qsfp0_rx_clk_2, - qsfp0_rx_rst_2=qsfp0_rx_rst_2, - qsfp0_rxd_2=qsfp0_rxd_2, - qsfp0_rxc_2=qsfp0_rxc_2, - qsfp0_tx_clk_3=qsfp0_tx_clk_3, - qsfp0_tx_rst_3=qsfp0_tx_rst_3, - qsfp0_txd_3=qsfp0_txd_3, - qsfp0_txc_3=qsfp0_txc_3, - qsfp0_rx_clk_3=qsfp0_rx_clk_3, - qsfp0_rx_rst_3=qsfp0_rx_rst_3, - qsfp0_rxd_3=qsfp0_rxd_3, - qsfp0_rxc_3=qsfp0_rxc_3, - qsfp0_tx_clk_4=qsfp0_tx_clk_4, - qsfp0_tx_rst_4=qsfp0_tx_rst_4, - qsfp0_txd_4=qsfp0_txd_4, - qsfp0_txc_4=qsfp0_txc_4, - qsfp0_rx_clk_4=qsfp0_rx_clk_4, - qsfp0_rx_rst_4=qsfp0_rx_rst_4, - qsfp0_rxd_4=qsfp0_rxd_4, - qsfp0_rxc_4=qsfp0_rxc_4, - qsfp1_tx_clk_1=qsfp1_tx_clk_1, - qsfp1_tx_rst_1=qsfp1_tx_rst_1, - qsfp1_txd_1=qsfp1_txd_1, - qsfp1_txc_1=qsfp1_txc_1, - qsfp1_rx_clk_1=qsfp1_rx_clk_1, - qsfp1_rx_rst_1=qsfp1_rx_rst_1, - qsfp1_rxd_1=qsfp1_rxd_1, - qsfp1_rxc_1=qsfp1_rxc_1, - qsfp1_tx_clk_2=qsfp1_tx_clk_2, - qsfp1_tx_rst_2=qsfp1_tx_rst_2, - qsfp1_txd_2=qsfp1_txd_2, - qsfp1_txc_2=qsfp1_txc_2, - qsfp1_rx_clk_2=qsfp1_rx_clk_2, - qsfp1_rx_rst_2=qsfp1_rx_rst_2, - qsfp1_rxd_2=qsfp1_rxd_2, - qsfp1_rxc_2=qsfp1_rxc_2, - qsfp1_tx_clk_3=qsfp1_tx_clk_3, - qsfp1_tx_rst_3=qsfp1_tx_rst_3, - qsfp1_txd_3=qsfp1_txd_3, - qsfp1_txc_3=qsfp1_txc_3, - qsfp1_rx_clk_3=qsfp1_rx_clk_3, - qsfp1_rx_rst_3=qsfp1_rx_rst_3, - qsfp1_rxd_3=qsfp1_rxd_3, - qsfp1_rxc_3=qsfp1_rxc_3, - qsfp1_tx_clk_4=qsfp1_tx_clk_4, - qsfp1_tx_rst_4=qsfp1_tx_rst_4, - qsfp1_txd_4=qsfp1_txd_4, - qsfp1_txc_4=qsfp1_txc_4, - qsfp1_rx_clk_4=qsfp1_rx_clk_4, - qsfp1_rx_rst_4=qsfp1_rx_rst_4, - qsfp1_rxd_4=qsfp1_rxd_4, - qsfp1_rxc_4=qsfp1_rxc_4 - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp0_tx_clk_1.next = not qsfp0_tx_clk_1 - qsfp0_rx_clk_1.next = not qsfp0_rx_clk_1 - qsfp0_tx_clk_2.next = not qsfp0_tx_clk_2 - qsfp0_rx_clk_2.next = not qsfp0_rx_clk_2 - qsfp0_tx_clk_3.next = not qsfp0_tx_clk_3 - qsfp0_rx_clk_3.next = not qsfp0_rx_clk_3 - qsfp0_tx_clk_4.next = not qsfp0_tx_clk_4 - qsfp0_rx_clk_4.next = not qsfp0_rx_clk_4 - qsfp1_tx_clk_1.next = not qsfp1_tx_clk_1 - qsfp1_rx_clk_1.next = not qsfp1_rx_clk_1 - qsfp1_tx_clk_2.next = not qsfp1_tx_clk_2 - qsfp1_rx_clk_2.next = not qsfp1_rx_clk_2 - qsfp1_tx_clk_3.next = not qsfp1_tx_clk_3 - qsfp1_rx_clk_3.next = not qsfp1_rx_clk_3 - qsfp1_tx_clk_4.next = not qsfp1_tx_clk_4 - qsfp1_rx_clk_4.next = not qsfp1_rx_clk_4 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp0_tx_rst_1.next = 1 - qsfp0_rx_rst_1.next = 1 - qsfp0_tx_rst_2.next = 1 - qsfp0_rx_rst_2.next = 1 - qsfp0_tx_rst_3.next = 1 - qsfp0_rx_rst_3.next = 1 - qsfp0_tx_rst_4.next = 1 - qsfp0_rx_rst_4.next = 1 - qsfp1_tx_rst_1.next = 1 - qsfp1_rx_rst_1.next = 1 - qsfp1_tx_rst_2.next = 1 - qsfp1_rx_rst_2.next = 1 - qsfp1_tx_rst_3.next = 1 - qsfp1_rx_rst_3.next = 1 - qsfp1_tx_rst_4.next = 1 - qsfp1_rx_rst_4.next = 1 - yield clk.posedge - rst.next = 0 - qsfp0_tx_rst_1.next = 0 - qsfp0_rx_rst_1.next = 0 - qsfp0_tx_rst_2.next = 0 - qsfp0_rx_rst_2.next = 0 - qsfp0_tx_rst_3.next = 0 - qsfp0_rx_rst_3.next = 0 - qsfp0_tx_rst_4.next = 0 - qsfp0_rx_rst_4.next = 0 - qsfp1_tx_rst_1.next = 0 - qsfp1_rx_rst_1.next = 0 - qsfp1_tx_rst_2.next = 0 - qsfp1_rx_rst_2.next = 0 - qsfp1_tx_rst_3.next = 0 - qsfp1_rx_rst_3.next = 0 - qsfp1_tx_rst_4.next = 0 - qsfp1_rx_rst_4.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp0_1_source.empty() - assert qsfp0_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/AU280/fpga_10g/tb/test_fpga_core.v b/example/AU280/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index 08ec99f09..000000000 --- a/example/AU280/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,257 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg qsfp0_tx_clk_1 = 0; -reg qsfp0_tx_rst_1 = 0; -reg qsfp0_rx_clk_1 = 0; -reg qsfp0_rx_rst_1 = 0; -reg [63:0] qsfp0_rxd_1 = 0; -reg [7:0] qsfp0_rxc_1 = 0; -reg qsfp0_tx_clk_2 = 0; -reg qsfp0_tx_rst_2 = 0; -reg qsfp0_rx_clk_2 = 0; -reg qsfp0_rx_rst_2 = 0; -reg [63:0] qsfp0_rxd_2 = 0; -reg [7:0] qsfp0_rxc_2 = 0; -reg qsfp0_tx_clk_3 = 0; -reg qsfp0_tx_rst_3 = 0; -reg qsfp0_rx_clk_3 = 0; -reg qsfp0_rx_rst_3 = 0; -reg [63:0] qsfp0_rxd_3 = 0; -reg [7:0] qsfp0_rxc_3 = 0; -reg qsfp0_tx_clk_4 = 0; -reg qsfp0_tx_rst_4 = 0; -reg qsfp0_rx_clk_4 = 0; -reg qsfp0_rx_rst_4 = 0; -reg [63:0] qsfp0_rxd_4 = 0; -reg [7:0] qsfp0_rxc_4 = 0; -reg qsfp1_tx_clk_1 = 0; -reg qsfp1_tx_rst_1 = 0; -reg qsfp1_rx_clk_1 = 0; -reg qsfp1_rx_rst_1 = 0; -reg [63:0] qsfp1_rxd_1 = 0; -reg [7:0] qsfp1_rxc_1 = 0; -reg qsfp1_tx_clk_2 = 0; -reg qsfp1_tx_rst_2 = 0; -reg qsfp1_rx_clk_2 = 0; -reg qsfp1_rx_rst_2 = 0; -reg [63:0] qsfp1_rxd_2 = 0; -reg [7:0] qsfp1_rxc_2 = 0; -reg qsfp1_tx_clk_3 = 0; -reg qsfp1_tx_rst_3 = 0; -reg qsfp1_rx_clk_3 = 0; -reg qsfp1_rx_rst_3 = 0; -reg [63:0] qsfp1_rxd_3 = 0; -reg [7:0] qsfp1_rxc_3 = 0; -reg qsfp1_tx_clk_4 = 0; -reg qsfp1_tx_rst_4 = 0; -reg qsfp1_rx_clk_4 = 0; -reg qsfp1_rx_rst_4 = 0; -reg [63:0] qsfp1_rxd_4 = 0; -reg [7:0] qsfp1_rxc_4 = 0; - -// Outputs -wire [63:0] qsfp0_txd_1; -wire [7:0] qsfp0_txc_1; -wire [63:0] qsfp0_txd_2; -wire [7:0] qsfp0_txc_2; -wire [63:0] qsfp0_txd_3; -wire [7:0] qsfp0_txc_3; -wire [63:0] qsfp0_txd_4; -wire [7:0] qsfp0_txc_4; -wire [63:0] qsfp1_txd_1; -wire [7:0] qsfp1_txc_1; -wire [63:0] qsfp1_txd_2; -wire [7:0] qsfp1_txc_2; -wire [63:0] qsfp1_txd_3; -wire [7:0] qsfp1_txc_3; -wire [63:0] qsfp1_txd_4; -wire [7:0] qsfp1_txc_4; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - qsfp0_tx_clk_1, - qsfp0_tx_rst_1, - qsfp0_rx_clk_1, - qsfp0_rx_rst_1, - qsfp0_rxd_1, - qsfp0_rxc_1, - qsfp0_tx_clk_2, - qsfp0_tx_rst_2, - qsfp0_rx_clk_2, - qsfp0_rx_rst_2, - qsfp0_rxd_2, - qsfp0_rxc_2, - qsfp0_tx_clk_3, - qsfp0_tx_rst_3, - qsfp0_rx_clk_3, - qsfp0_rx_rst_3, - qsfp0_rxd_3, - qsfp0_rxc_3, - qsfp0_tx_clk_4, - qsfp0_tx_rst_4, - qsfp0_rx_clk_4, - qsfp0_rx_rst_4, - qsfp0_rxd_4, - qsfp0_rxc_4, - qsfp1_tx_clk_1, - qsfp1_tx_rst_1, - qsfp1_rx_clk_1, - qsfp1_rx_rst_1, - qsfp1_rxd_1, - qsfp1_rxc_1, - qsfp1_tx_clk_2, - qsfp1_tx_rst_2, - qsfp1_rx_clk_2, - qsfp1_rx_rst_2, - qsfp1_rxd_2, - qsfp1_rxc_2, - qsfp1_tx_clk_3, - qsfp1_tx_rst_3, - qsfp1_rx_clk_3, - qsfp1_rx_rst_3, - qsfp1_rxd_3, - qsfp1_rxc_3, - qsfp1_tx_clk_4, - qsfp1_tx_rst_4, - qsfp1_rx_clk_4, - qsfp1_rx_rst_4, - qsfp1_rxd_4, - qsfp1_rxc_4 - ); - $to_myhdl( - qsfp0_txd_1, - qsfp0_txc_1, - qsfp0_txd_2, - qsfp0_txc_2, - qsfp0_txd_3, - qsfp0_txc_3, - qsfp0_txd_4, - qsfp0_txc_4, - qsfp1_txd_1, - qsfp1_txc_1, - qsfp1_txd_2, - qsfp1_txc_2, - qsfp1_txd_3, - qsfp1_txc_3, - qsfp1_txd_4, - qsfp1_txc_4 - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .qsfp0_tx_clk_1(qsfp0_tx_clk_1), - .qsfp0_tx_rst_1(qsfp0_tx_rst_1), - .qsfp0_txd_1(qsfp0_txd_1), - .qsfp0_txc_1(qsfp0_txc_1), - .qsfp0_rx_clk_1(qsfp0_rx_clk_1), - .qsfp0_rx_rst_1(qsfp0_rx_rst_1), - .qsfp0_rxd_1(qsfp0_rxd_1), - .qsfp0_rxc_1(qsfp0_rxc_1), - .qsfp0_tx_clk_2(qsfp0_tx_clk_2), - .qsfp0_tx_rst_2(qsfp0_tx_rst_2), - .qsfp0_txd_2(qsfp0_txd_2), - .qsfp0_txc_2(qsfp0_txc_2), - .qsfp0_rx_clk_2(qsfp0_rx_clk_2), - .qsfp0_rx_rst_2(qsfp0_rx_rst_2), - .qsfp0_rxd_2(qsfp0_rxd_2), - .qsfp0_rxc_2(qsfp0_rxc_2), - .qsfp0_tx_clk_3(qsfp0_tx_clk_3), - .qsfp0_tx_rst_3(qsfp0_tx_rst_3), - .qsfp0_txd_3(qsfp0_txd_3), - .qsfp0_txc_3(qsfp0_txc_3), - .qsfp0_rx_clk_3(qsfp0_rx_clk_3), - .qsfp0_rx_rst_3(qsfp0_rx_rst_3), - .qsfp0_rxd_3(qsfp0_rxd_3), - .qsfp0_rxc_3(qsfp0_rxc_3), - .qsfp0_tx_clk_4(qsfp0_tx_clk_4), - .qsfp0_tx_rst_4(qsfp0_tx_rst_4), - .qsfp0_txd_4(qsfp0_txd_4), - .qsfp0_txc_4(qsfp0_txc_4), - .qsfp0_rx_clk_4(qsfp0_rx_clk_4), - .qsfp0_rx_rst_4(qsfp0_rx_rst_4), - .qsfp0_rxd_4(qsfp0_rxd_4), - .qsfp0_rxc_4(qsfp0_rxc_4), - .qsfp1_tx_clk_1(qsfp1_tx_clk_1), - .qsfp1_tx_rst_1(qsfp1_tx_rst_1), - .qsfp1_txd_1(qsfp1_txd_1), - .qsfp1_txc_1(qsfp1_txc_1), - .qsfp1_rx_clk_1(qsfp1_rx_clk_1), - .qsfp1_rx_rst_1(qsfp1_rx_rst_1), - .qsfp1_rxd_1(qsfp1_rxd_1), - .qsfp1_rxc_1(qsfp1_rxc_1), - .qsfp1_tx_clk_2(qsfp1_tx_clk_2), - .qsfp1_tx_rst_2(qsfp1_tx_rst_2), - .qsfp1_txd_2(qsfp1_txd_2), - .qsfp1_txc_2(qsfp1_txc_2), - .qsfp1_rx_clk_2(qsfp1_rx_clk_2), - .qsfp1_rx_rst_2(qsfp1_rx_rst_2), - .qsfp1_rxd_2(qsfp1_rxd_2), - .qsfp1_rxc_2(qsfp1_rxc_2), - .qsfp1_tx_clk_3(qsfp1_tx_clk_3), - .qsfp1_tx_rst_3(qsfp1_tx_rst_3), - .qsfp1_txd_3(qsfp1_txd_3), - .qsfp1_txc_3(qsfp1_txc_3), - .qsfp1_rx_clk_3(qsfp1_rx_clk_3), - .qsfp1_rx_rst_3(qsfp1_rx_rst_3), - .qsfp1_rxd_3(qsfp1_rxd_3), - .qsfp1_rxc_3(qsfp1_rxc_3), - .qsfp1_tx_clk_4(qsfp1_tx_clk_4), - .qsfp1_tx_rst_4(qsfp1_tx_rst_4), - .qsfp1_txd_4(qsfp1_txd_4), - .qsfp1_txc_4(qsfp1_txc_4), - .qsfp1_rx_clk_4(qsfp1_rx_clk_4), - .qsfp1_rx_rst_4(qsfp1_rx_rst_4), - .qsfp1_rxd_4(qsfp1_rxd_4), - .qsfp1_rxc_4(qsfp1_rxc_4) -); - -endmodule diff --git a/example/AU280/fpga_10g/tb/udp_ep.py b/example/AU280/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/AU280/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/AU280/fpga_10g/tb/xgmii_ep.py b/example/AU280/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/AU280/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/AU50/fpga_10g/tb/arp_ep.py b/example/AU50/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/AU50/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/AU50/fpga_10g/tb/axis_ep.py b/example/AU50/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/AU50/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/AU50/fpga_10g/tb/eth_ep.py b/example/AU50/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/AU50/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/AU50/fpga_10g/tb/fpga_core/Makefile b/example/AU50/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/AU50/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..adcdea6f2 --- /dev/null +++ b/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,243 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp_rx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_source = XgmiiSource(dut.qsfp_rxd_1, dut.qsfp_rxc_1, dut.qsfp_rx_clk_1, dut.qsfp_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_tx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_sink = XgmiiSink(dut.qsfp_txd_1, dut.qsfp_txc_1, dut.qsfp_tx_clk_1, dut.qsfp_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_rx_clk_2, 6.4, units="ns").start()) + self.qsfp_2_source = XgmiiSource(dut.qsfp_rxd_2, dut.qsfp_rxc_2, dut.qsfp_rx_clk_2, dut.qsfp_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_tx_clk_2, 6.4, units="ns").start()) + self.qsfp_2_sink = XgmiiSink(dut.qsfp_txd_2, dut.qsfp_txc_2, dut.qsfp_tx_clk_2, dut.qsfp_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_rx_clk_3, 6.4, units="ns").start()) + self.qsfp_3_source = XgmiiSource(dut.qsfp_rxd_3, dut.qsfp_rxc_3, dut.qsfp_rx_clk_3, dut.qsfp_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_tx_clk_3, 6.4, units="ns").start()) + self.qsfp_3_sink = XgmiiSink(dut.qsfp_txd_3, dut.qsfp_txc_3, dut.qsfp_tx_clk_3, dut.qsfp_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp_rx_clk_4, 6.4, units="ns").start()) + self.qsfp_4_source = XgmiiSource(dut.qsfp_rxd_4, dut.qsfp_rxc_4, dut.qsfp_rx_clk_4, dut.qsfp_rx_rst_4) + cocotb.fork(Clock(dut.qsfp_tx_clk_4, 6.4, units="ns").start()) + self.qsfp_4_sink = XgmiiSink(dut.qsfp_txd_4, dut.qsfp_txc_4, dut.qsfp_tx_clk_4, dut.qsfp_tx_rst_4) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst.setimmediatevalue(1) + self.dut.qsfp_rx_rst_1 <= 1 + self.dut.qsfp_tx_rst_1 <= 1 + self.dut.qsfp_rx_rst_2 <= 1 + self.dut.qsfp_tx_rst_2 <= 1 + self.dut.qsfp_rx_rst_3 <= 1 + self.dut.qsfp_tx_rst_3 <= 1 + self.dut.qsfp_rx_rst_4 <= 1 + self.dut.qsfp_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp_rx_rst_1 <= 0 + self.dut.qsfp_tx_rst_1 <= 0 + self.dut.qsfp_rx_rst_2 <= 0 + self.dut.qsfp_tx_rst_2 <= 0 + self.dut.qsfp_rx_rst_3 <= 0 + self.dut.qsfp_tx_rst_3 <= 0 + self.dut.qsfp_rx_rst_4 <= 0 + self.dut.qsfp_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/AU50/fpga_10g/tb/ip_ep.py b/example/AU50/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/AU50/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/AU50/fpga_10g/tb/test_fpga_core.py b/example/AU50/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index ee1f1a230..000000000 --- a/example/AU50/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,343 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - qsfp_tx_clk_1 = Signal(bool(0)) - qsfp_tx_rst_1 = Signal(bool(0)) - qsfp_rx_clk_1 = Signal(bool(0)) - qsfp_rx_rst_1 = Signal(bool(0)) - qsfp_rxd_1 = Signal(intbv(0)[64:]) - qsfp_rxc_1 = Signal(intbv(0)[8:]) - qsfp_tx_clk_2 = Signal(bool(0)) - qsfp_tx_rst_2 = Signal(bool(0)) - qsfp_rx_clk_2 = Signal(bool(0)) - qsfp_rx_rst_2 = Signal(bool(0)) - qsfp_rxd_2 = Signal(intbv(0)[64:]) - qsfp_rxc_2 = Signal(intbv(0)[8:]) - qsfp_tx_clk_3 = Signal(bool(0)) - qsfp_tx_rst_3 = Signal(bool(0)) - qsfp_rx_clk_3 = Signal(bool(0)) - qsfp_rx_rst_3 = Signal(bool(0)) - qsfp_rxd_3 = Signal(intbv(0)[64:]) - qsfp_rxc_3 = Signal(intbv(0)[8:]) - qsfp_tx_clk_4 = Signal(bool(0)) - qsfp_tx_rst_4 = Signal(bool(0)) - qsfp_rx_clk_4 = Signal(bool(0)) - qsfp_rx_rst_4 = Signal(bool(0)) - qsfp_rxd_4 = Signal(intbv(0)[64:]) - qsfp_rxc_4 = Signal(intbv(0)[8:]) - - # Outputs - qsfp_txd_1 = Signal(intbv(0)[64:]) - qsfp_txc_1 = Signal(intbv(0)[8:]) - qsfp_txd_2 = Signal(intbv(0)[64:]) - qsfp_txc_2 = Signal(intbv(0)[8:]) - qsfp_txd_3 = Signal(intbv(0)[64:]) - qsfp_txc_3 = Signal(intbv(0)[8:]) - qsfp_txd_4 = Signal(intbv(0)[64:]) - qsfp_txc_4 = Signal(intbv(0)[8:]) - - # sources and sinks - qsfp_1_source = xgmii_ep.XGMIISource() - qsfp_1_source_logic = qsfp_1_source.create_logic(qsfp_rx_clk_1, qsfp_rx_rst_1, txd=qsfp_rxd_1, txc=qsfp_rxc_1, name='qsfp_1_source') - - qsfp_1_sink = xgmii_ep.XGMIISink() - qsfp_1_sink_logic = qsfp_1_sink.create_logic(qsfp_tx_clk_1, qsfp_tx_rst_1, rxd=qsfp_txd_1, rxc=qsfp_txc_1, name='qsfp_1_sink') - - qsfp_2_source = xgmii_ep.XGMIISource() - qsfp_2_source_logic = qsfp_2_source.create_logic(qsfp_rx_clk_2, qsfp_rx_rst_2, txd=qsfp_rxd_2, txc=qsfp_rxc_2, name='qsfp_2_source') - - qsfp_2_sink = xgmii_ep.XGMIISink() - qsfp_2_sink_logic = qsfp_2_sink.create_logic(qsfp_tx_clk_2, qsfp_tx_rst_2, rxd=qsfp_txd_2, rxc=qsfp_txc_2, name='qsfp_2_sink') - - qsfp_3_source = xgmii_ep.XGMIISource() - qsfp_3_source_logic = qsfp_3_source.create_logic(qsfp_rx_clk_3, qsfp_rx_rst_3, txd=qsfp_rxd_3, txc=qsfp_rxc_3, name='qsfp_3_source') - - qsfp_3_sink = xgmii_ep.XGMIISink() - qsfp_3_sink_logic = qsfp_3_sink.create_logic(qsfp_tx_clk_3, qsfp_tx_rst_3, rxd=qsfp_txd_3, rxc=qsfp_txc_3, name='qsfp_3_sink') - - qsfp_4_source = xgmii_ep.XGMIISource() - qsfp_4_source_logic = qsfp_4_source.create_logic(qsfp_rx_clk_4, qsfp_rx_rst_4, txd=qsfp_rxd_4, txc=qsfp_rxc_4, name='qsfp_4_source') - - qsfp_4_sink = xgmii_ep.XGMIISink() - qsfp_4_sink_logic = qsfp_4_sink.create_logic(qsfp_tx_clk_4, qsfp_tx_rst_4, rxd=qsfp_txd_4, rxc=qsfp_txc_4, name='qsfp_4_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - qsfp_tx_clk_1=qsfp_tx_clk_1, - qsfp_tx_rst_1=qsfp_tx_rst_1, - qsfp_txd_1=qsfp_txd_1, - qsfp_txc_1=qsfp_txc_1, - qsfp_rx_clk_1=qsfp_rx_clk_1, - qsfp_rx_rst_1=qsfp_rx_rst_1, - qsfp_rxd_1=qsfp_rxd_1, - qsfp_rxc_1=qsfp_rxc_1, - qsfp_tx_clk_2=qsfp_tx_clk_2, - qsfp_tx_rst_2=qsfp_tx_rst_2, - qsfp_txd_2=qsfp_txd_2, - qsfp_txc_2=qsfp_txc_2, - qsfp_rx_clk_2=qsfp_rx_clk_2, - qsfp_rx_rst_2=qsfp_rx_rst_2, - qsfp_rxd_2=qsfp_rxd_2, - qsfp_rxc_2=qsfp_rxc_2, - qsfp_tx_clk_3=qsfp_tx_clk_3, - qsfp_tx_rst_3=qsfp_tx_rst_3, - qsfp_txd_3=qsfp_txd_3, - qsfp_txc_3=qsfp_txc_3, - qsfp_rx_clk_3=qsfp_rx_clk_3, - qsfp_rx_rst_3=qsfp_rx_rst_3, - qsfp_rxd_3=qsfp_rxd_3, - qsfp_rxc_3=qsfp_rxc_3, - qsfp_tx_clk_4=qsfp_tx_clk_4, - qsfp_tx_rst_4=qsfp_tx_rst_4, - qsfp_txd_4=qsfp_txd_4, - qsfp_txc_4=qsfp_txc_4, - qsfp_rx_clk_4=qsfp_rx_clk_4, - qsfp_rx_rst_4=qsfp_rx_rst_4, - qsfp_rxd_4=qsfp_rxd_4, - qsfp_rxc_4=qsfp_rxc_4 - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp_tx_clk_1.next = not qsfp_tx_clk_1 - qsfp_rx_clk_1.next = not qsfp_rx_clk_1 - qsfp_tx_clk_2.next = not qsfp_tx_clk_2 - qsfp_rx_clk_2.next = not qsfp_rx_clk_2 - qsfp_tx_clk_3.next = not qsfp_tx_clk_3 - qsfp_rx_clk_3.next = not qsfp_rx_clk_3 - qsfp_tx_clk_4.next = not qsfp_tx_clk_4 - qsfp_rx_clk_4.next = not qsfp_rx_clk_4 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp_tx_rst_1.next = 1 - qsfp_rx_rst_1.next = 1 - qsfp_tx_rst_2.next = 1 - qsfp_rx_rst_2.next = 1 - qsfp_tx_rst_3.next = 1 - qsfp_rx_rst_3.next = 1 - qsfp_tx_rst_4.next = 1 - qsfp_rx_rst_4.next = 1 - yield clk.posedge - rst.next = 0 - qsfp_tx_rst_1.next = 0 - qsfp_rx_rst_1.next = 0 - qsfp_tx_rst_2.next = 0 - qsfp_rx_rst_2.next = 0 - qsfp_tx_rst_3.next = 0 - qsfp_rx_rst_3.next = 0 - qsfp_tx_rst_4.next = 0 - qsfp_rx_rst_4.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp_1_source.empty() - assert qsfp_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/AU50/fpga_10g/tb/test_fpga_core.v b/example/AU50/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index e151c66b8..000000000 --- a/example/AU50/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,161 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg qsfp_tx_clk_1 = 0; -reg qsfp_tx_rst_1 = 0; -reg qsfp_rx_clk_1 = 0; -reg qsfp_rx_rst_1 = 0; -reg [63:0] qsfp_rxd_1 = 0; -reg [7:0] qsfp_rxc_1 = 0; -reg qsfp_tx_clk_2 = 0; -reg qsfp_tx_rst_2 = 0; -reg qsfp_rx_clk_2 = 0; -reg qsfp_rx_rst_2 = 0; -reg [63:0] qsfp_rxd_2 = 0; -reg [7:0] qsfp_rxc_2 = 0; -reg qsfp_tx_clk_3 = 0; -reg qsfp_tx_rst_3 = 0; -reg qsfp_rx_clk_3 = 0; -reg qsfp_rx_rst_3 = 0; -reg [63:0] qsfp_rxd_3 = 0; -reg [7:0] qsfp_rxc_3 = 0; -reg qsfp_tx_clk_4 = 0; -reg qsfp_tx_rst_4 = 0; -reg qsfp_rx_clk_4 = 0; -reg qsfp_rx_rst_4 = 0; -reg [63:0] qsfp_rxd_4 = 0; -reg [7:0] qsfp_rxc_4 = 0; - -// Outputs -wire [63:0] qsfp_txd_1; -wire [7:0] qsfp_txc_1; -wire [63:0] qsfp_txd_2; -wire [7:0] qsfp_txc_2; -wire [63:0] qsfp_txd_3; -wire [7:0] qsfp_txc_3; -wire [63:0] qsfp_txd_4; -wire [7:0] qsfp_txc_4; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - qsfp_tx_clk_1, - qsfp_tx_rst_1, - qsfp_rx_clk_1, - qsfp_rx_rst_1, - qsfp_rxd_1, - qsfp_rxc_1, - qsfp_tx_clk_2, - qsfp_tx_rst_2, - qsfp_rx_clk_2, - qsfp_rx_rst_2, - qsfp_rxd_2, - qsfp_rxc_2, - qsfp_tx_clk_3, - qsfp_tx_rst_3, - qsfp_rx_clk_3, - qsfp_rx_rst_3, - qsfp_rxd_3, - qsfp_rxc_3, - qsfp_tx_clk_4, - qsfp_tx_rst_4, - qsfp_rx_clk_4, - qsfp_rx_rst_4, - qsfp_rxd_4, - qsfp_rxc_4 - ); - $to_myhdl( - qsfp_txd_1, - qsfp_txc_1, - qsfp_txd_2, - qsfp_txc_2, - qsfp_txd_3, - qsfp_txc_3, - qsfp_txd_4, - qsfp_txc_4 - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .qsfp_tx_clk_1(qsfp_tx_clk_1), - .qsfp_tx_rst_1(qsfp_tx_rst_1), - .qsfp_txd_1(qsfp_txd_1), - .qsfp_txc_1(qsfp_txc_1), - .qsfp_rx_clk_1(qsfp_rx_clk_1), - .qsfp_rx_rst_1(qsfp_rx_rst_1), - .qsfp_rxd_1(qsfp_rxd_1), - .qsfp_rxc_1(qsfp_rxc_1), - .qsfp_tx_clk_2(qsfp_tx_clk_2), - .qsfp_tx_rst_2(qsfp_tx_rst_2), - .qsfp_txd_2(qsfp_txd_2), - .qsfp_txc_2(qsfp_txc_2), - .qsfp_rx_clk_2(qsfp_rx_clk_2), - .qsfp_rx_rst_2(qsfp_rx_rst_2), - .qsfp_rxd_2(qsfp_rxd_2), - .qsfp_rxc_2(qsfp_rxc_2), - .qsfp_tx_clk_3(qsfp_tx_clk_3), - .qsfp_tx_rst_3(qsfp_tx_rst_3), - .qsfp_txd_3(qsfp_txd_3), - .qsfp_txc_3(qsfp_txc_3), - .qsfp_rx_clk_3(qsfp_rx_clk_3), - .qsfp_rx_rst_3(qsfp_rx_rst_3), - .qsfp_rxd_3(qsfp_rxd_3), - .qsfp_rxc_3(qsfp_rxc_3), - .qsfp_tx_clk_4(qsfp_tx_clk_4), - .qsfp_tx_rst_4(qsfp_tx_rst_4), - .qsfp_txd_4(qsfp_txd_4), - .qsfp_txc_4(qsfp_txc_4), - .qsfp_rx_clk_4(qsfp_rx_clk_4), - .qsfp_rx_rst_4(qsfp_rx_rst_4), - .qsfp_rxd_4(qsfp_rxd_4), - .qsfp_rxc_4(qsfp_rxc_4) -); - -endmodule diff --git a/example/AU50/fpga_10g/tb/udp_ep.py b/example/AU50/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/AU50/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/AU50/fpga_10g/tb/xgmii_ep.py b/example/AU50/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/AU50/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/Arty/fpga/tb/arp_ep.py b/example/Arty/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/Arty/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/Arty/fpga/tb/axis_ep.py b/example/Arty/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/Arty/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/Arty/fpga/tb/eth_ep.py b/example/Arty/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/Arty/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/Arty/fpga/tb/fpga_core/Makefile b/example/Arty/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..9eb26f795 --- /dev/null +++ b/example/Arty/fpga/tb/fpga_core/Makefile @@ -0,0 +1,102 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_mii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_mii.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/mii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/Arty/fpga/tb/fpga_core/test_fpga_core.py b/example/Arty/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..cce8223fd --- /dev/null +++ b/example/Arty/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,211 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, MiiPhy + + +class TB: + def __init__(self, dut, speed=100e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + self.mii_phy = MiiPhy(dut.phy_txd, None, dut.phy_tx_en, dut.phy_tx_clk, + dut.phy_rxd, dut.phy_rx_er, dut.phy_rx_dv, dut.phy_rx_clk, speed=speed) + + dut.phy_crs.setimmediatevalue(0) + dut.phy_col.setimmediatevalue(0) + + dut.btn.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.mii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.mii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.mii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.mii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_mii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_mii.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_in.v"), + os.path.join(eth_rtl_dir, "mii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/Arty/fpga/tb/ip_ep.py b/example/Arty/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/Arty/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/Arty/fpga/tb/mii_ep.py b/example/Arty/fpga/tb/mii_ep.py deleted file mode 120000 index e1b3a9129..000000000 --- a/example/Arty/fpga/tb/mii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/mii_ep.py \ No newline at end of file diff --git a/example/Arty/fpga/tb/test_fpga_core.py b/example/Arty/fpga/tb/test_fpga_core.py deleted file mode 100755 index 193eefc9f..000000000 --- a/example/Arty/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,326 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2019 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import mii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/ssio_sdr_in.v") -srcs.append("../lib/eth/rtl/mii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_mii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_mii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btn = Signal(intbv(0)[4:]) - sw = Signal(intbv(0)[4:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[4:]) - phy_rx_dv = Signal(bool(0)) - phy_rx_er = Signal(bool(0)) - phy_col = Signal(bool(0)) - phy_crs = Signal(bool(0)) - uart_rxd = Signal(bool(0)) - - # Outputs - led0_r = Signal(bool(0)) - led0_g = Signal(bool(0)) - led0_b = Signal(bool(0)) - led1_r = Signal(bool(0)) - led1_g = Signal(bool(0)) - led1_b = Signal(bool(0)) - led2_r = Signal(bool(0)) - led2_g = Signal(bool(0)) - led2_b = Signal(bool(0)) - led3_r = Signal(bool(0)) - led3_g = Signal(bool(0)) - led3_b = Signal(bool(0)) - led4 = Signal(bool(0)) - led5 = Signal(bool(0)) - led6 = Signal(bool(0)) - led7 = Signal(bool(0)) - phy_tx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[4:]) - phy_tx_en = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - - # sources and sinks - mii_source = mii_ep.MIISource() - - mii_source_logic = mii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_en=phy_rx_dv, - tx_er=phy_rx_er, - name='mii_source' - ) - - mii_sink = mii_ep.MIISink() - - mii_sink_logic = mii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_dv=phy_tx_en, - rx_er=False, - name='mii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btn=btn, - sw=sw, - led0_r=led0_r, - led0_g=led0_g, - led0_b=led0_b, - led1_r=led1_r, - led1_g=led1_g, - led1_b=led1_b, - led2_r=led2_r, - led2_g=led2_g, - led2_b=led2_b, - led3_r=led3_r, - led3_g=led3_g, - led3_b=led3_b, - led4=led4, - led5=led5, - led6=led6, - led7=led7, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_dv=phy_rx_dv, - phy_rx_er=phy_rx_er, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_en=phy_tx_en, - phy_col=phy_col, - phy_crs=phy_crs, - phy_reset_n=phy_reset_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - phy_clk_hp = Signal(int(20)) - - @instance - def phy_clk_gen(): - while True: - yield delay(int(phy_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - phy_tx_clk.next = not phy_tx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - mii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while mii_sink.empty(): - yield clk.posedge - - rx_frame = mii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - mii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while mii_sink.empty(): - yield clk.posedge - - rx_frame = mii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert mii_source.empty() - assert mii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/Arty/fpga/tb/test_fpga_core.v b/example/Arty/fpga/tb/test_fpga_core.v deleted file mode 100644 index 3ceea0953..000000000 --- a/example/Arty/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,158 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] btn = 0; -reg [3:0] sw = 0; -reg phy_rx_clk = 0; -reg [3:0] phy_rxd = 0; -reg phy_rx_dv = 0; -reg phy_rx_er = 0; -reg phy_col = 0; -reg phy_crs = 0; -reg phy_tx_clk = 0; -reg uart_rxd = 0; - -// Outputs -wire led0_r; -wire led0_g; -wire led0_b; -wire led1_r; -wire led1_g; -wire led1_b; -wire led2_r; -wire led2_g; -wire led2_b; -wire led3_r; -wire led3_g; -wire led3_b; -wire led4; -wire led5; -wire led6; -wire led7; -wire [3:0] phy_txd; -wire phy_tx_en; -wire phy_reset_n; -wire uart_txd; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btn, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_dv, - phy_rx_er, - phy_tx_clk, - phy_col, - phy_crs, - uart_rxd - ); - $to_myhdl( - led0_r, - led0_g, - led0_b, - led1_r, - led1_g, - led1_b, - led2_r, - led2_g, - led2_b, - led3_r, - led3_g, - led3_b, - led4, - led5, - led6, - led7, - phy_txd, - phy_tx_en, - phy_reset_n, - uart_txd - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk(clk), - .rst(rst), - .btn(btn), - .sw(sw), - .led0_r(led0_r), - .led0_g(led0_g), - .led0_b(led0_b), - .led1_r(led1_r), - .led1_g(led1_g), - .led1_b(led1_b), - .led2_r(led2_r), - .led2_g(led2_g), - .led2_b(led2_b), - .led3_r(led3_r), - .led3_g(led3_g), - .led3_b(led3_b), - .led4(led4), - .led5(led5), - .led6(led6), - .led7(led7), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_dv(phy_rx_dv), - .phy_rx_er(phy_rx_er), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_en(phy_tx_en), - .phy_col(phy_col), - .phy_crs(phy_crs), - .phy_reset_n(phy_reset_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd) -); - -endmodule diff --git a/example/Arty/fpga/tb/udp_ep.py b/example/Arty/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/Arty/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/arp_ep.py b/example/C10LP/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/C10LP/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/axis_ep.py b/example/C10LP/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/C10LP/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/eth_ep.py b/example/C10LP/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/C10LP/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/fpga_core/Makefile b/example/C10LP/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..cf1af8fc7 --- /dev/null +++ b/example/C10LP/fpga/tb/fpga_core/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py b/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..9d69b913f --- /dev/null +++ b/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,225 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import GmiiFrame, RgmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.rgmii_phy = RgmiiPhy(dut.phy_txd, dut.phy_tx_ctl, dut.phy_tx_clk, + dut.phy_rxd, dut.phy_rx_ctl, dut.phy_rx_clk, speed=speed) + + dut.phy_int_n.setimmediatevalue(1) + + dut.btn.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + + dut.clk.setimmediatevalue(0) + dut.clk90.setimmediatevalue(0) + + cocotb.fork(self._run_clk()) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + async def _run_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.clk <= 1 + await t + self.dut.clk90 <= 1 + await t + self.dut.clk <= 0 + await t + self.dut.clk90 <= 0 + await t + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.rgmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.rgmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_ddr_in.v"), + os.path.join(eth_rtl_dir, "rgmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/C10LP/fpga/tb/gmii_ep.py b/example/C10LP/fpga/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/C10LP/fpga/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/ip_ep.py b/example/C10LP/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/C10LP/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/rgmii_ep.py b/example/C10LP/fpga/tb/rgmii_ep.py deleted file mode 120000 index 986c56280..000000000 --- a/example/C10LP/fpga/tb/rgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/rgmii_ep.py \ No newline at end of file diff --git a/example/C10LP/fpga/tb/test_fpga_core.py b/example/C10LP/fpga/tb/test_fpga_core.py deleted file mode 100755 index b937f5392..000000000 --- a/example/C10LP/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,302 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import rgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/iddr.v") -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_ddr_in.v") -srcs.append("../lib/eth/rtl/ssio_ddr_out.v") -srcs.append("../lib/eth/rtl/rgmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/ip_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/rtl/eth_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - clk90 = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btn = Signal(intbv(0)[4:]) - sw = Signal(intbv(0)[3:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[4:]) - phy_rx_ctl = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - - # Outputs - led = Signal(intbv(0)[4:]) - phy_tx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[4:]) - phy_tx_ctl = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - - # sources and sinks - mii_select = Signal(bool(0)) - - rgmii_source = rgmii_ep.RGMIISource() - - rgmii_source_logic = rgmii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_ctl=phy_rx_ctl, - mii_select=mii_select, - name='rgmii_source' - ) - - rgmii_sink = rgmii_ep.RGMIISink() - - rgmii_sink_logic = rgmii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_ctl=phy_tx_ctl, - mii_select=mii_select, - name='rgmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - clk90=clk90, - rst=rst, - current_test=current_test, - - btn=btn, - sw=sw, - led=led, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_ctl=phy_rx_ctl, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_ctl=phy_tx_ctl, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @instance - def clkgen2(): - yield delay(4+2) - while True: - clk90.next = not clk90 - yield delay(4) - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - rgmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while rgmii_sink.empty(): - yield clk.posedge - - rx_frame = rgmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - rgmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while rgmii_sink.empty(): - yield clk.posedge - - rx_frame = rgmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert rgmii_source.empty() - assert rgmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/C10LP/fpga/tb/test_fpga_core.v b/example/C10LP/fpga/tb/test_fpga_core.v deleted file mode 100644 index bd4238578..000000000 --- a/example/C10LP/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,104 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk = 0; -reg clk90 = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] btn = 0; -reg [2:0] sw = 0; -reg phy_rx_clk = 0; -reg [3:0] phy_rxd = 0; -reg phy_rx_ctl = 0; -reg phy_int_n = 1; - -// Outputs -wire [3:0] led; -wire phy_tx_clk; -wire [3:0] phy_txd; -wire phy_tx_ctl; -wire phy_reset_n; - -initial begin - // myhdl integration - $from_myhdl( - clk, - clk90, - rst, - current_test, - btn, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_ctl, - phy_int_n - ); - $to_myhdl( - led, - phy_tx_clk, - phy_txd, - phy_tx_ctl, - phy_reset_n - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk(clk), - .clk90(clk90), - .rst(rst), - .btn(btn), - .sw(sw), - .led(led), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_ctl(phy_rx_ctl), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_ctl(phy_tx_ctl), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n) -); - -endmodule diff --git a/example/C10LP/fpga/tb/udp_ep.py b/example/C10LP/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/C10LP/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/arp_ep.py b/example/DE2-115/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/DE2-115/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/axis_ep.py b/example/DE2-115/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/DE2-115/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/eth_ep.py b/example/DE2-115/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/DE2-115/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/fpga_core/Makefile b/example/DE2-115/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..ca736cac6 --- /dev/null +++ b/example/DE2-115/fpga/tb/fpga_core/Makefile @@ -0,0 +1,105 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/hex_display.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py b/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..384499719 --- /dev/null +++ b/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,230 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import GmiiFrame, RgmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.rgmii_phy0 = RgmiiPhy(dut.phy0_txd, dut.phy0_tx_ctl, dut.phy0_tx_clk, + dut.phy0_rxd, dut.phy0_rx_ctl, dut.phy0_rx_clk, speed=speed) + + self.rgmii_phy1 = RgmiiPhy(dut.phy1_txd, dut.phy1_tx_ctl, dut.phy1_tx_clk, + dut.phy1_rxd, dut.phy1_rx_ctl, dut.phy1_rx_clk, speed=speed) + + dut.phy0_int_n.setimmediatevalue(1) + dut.phy1_int_n.setimmediatevalue(1) + + dut.btn.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + + dut.clk.setimmediatevalue(0) + dut.clk90.setimmediatevalue(0) + + cocotb.fork(self._run_clk()) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + async def _run_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.clk <= 1 + await t + self.dut.clk90 <= 1 + await t + self.dut.clk <= 0 + await t + self.dut.clk90 <= 0 + await t + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.rgmii_phy0.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.rgmii_phy0.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.rgmii_phy0.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.rgmii_phy0.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "hex_display.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_ddr_in.v"), + os.path.join(eth_rtl_dir, "rgmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/DE2-115/fpga/tb/gmii_ep.py b/example/DE2-115/fpga/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/DE2-115/fpga/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/ip_ep.py b/example/DE2-115/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/DE2-115/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/rgmii_ep.py b/example/DE2-115/fpga/tb/rgmii_ep.py deleted file mode 120000 index 986c56280..000000000 --- a/example/DE2-115/fpga/tb/rgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/rgmii_ep.py \ No newline at end of file diff --git a/example/DE2-115/fpga/tb/test_fpga_core.py b/example/DE2-115/fpga/tb/test_fpga_core.py deleted file mode 100755 index af67005d8..000000000 --- a/example/DE2-115/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,364 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import rgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../rtl/hex_display.v") -srcs.append("../lib/eth/rtl/iddr.v") -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_ddr_in.v") -srcs.append("../lib/eth/rtl/ssio_ddr_out.v") -srcs.append("../lib/eth/rtl/rgmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/ip_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/rtl/eth_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - clk90 = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btn = Signal(intbv(0)[4:]) - sw = Signal(intbv(0)[17:]) - phy0_rx_clk = Signal(bool(0)) - phy0_rxd = Signal(intbv(0)[4:]) - phy0_rx_ctl = Signal(bool(0)) - phy0_int_n = Signal(bool(1)) - phy1_rx_clk = Signal(bool(0)) - phy1_rxd = Signal(intbv(0)[4:]) - phy1_rx_ctl = Signal(bool(0)) - phy1_int_n = Signal(bool(1)) - - # Outputs - ledg = Signal(intbv(0)[8:]) - ledr = Signal(intbv(0)[18:]) - hex0 = Signal(intbv(0)[7:]) - hex1 = Signal(intbv(0)[7:]) - hex2 = Signal(intbv(0)[7:]) - hex3 = Signal(intbv(0)[7:]) - hex4 = Signal(intbv(0)[7:]) - hex5 = Signal(intbv(0)[7:]) - hex6 = Signal(intbv(0)[7:]) - hex7 = Signal(intbv(0)[7:]) - gpio = Signal(intbv(0)[36:]) - phy0_tx_clk = Signal(bool(0)) - phy0_txd = Signal(intbv(0)[4:]) - phy0_tx_ctl = Signal(bool(0)) - phy0_reset_n = Signal(bool(0)) - phy1_tx_clk = Signal(bool(0)) - phy1_txd = Signal(intbv(0)[4:]) - phy1_tx_ctl = Signal(bool(0)) - phy1_reset_n = Signal(bool(0)) - - # sources and sinks - mii_select_0 = Signal(bool(0)) - - rgmii_source_0 = rgmii_ep.RGMIISource() - - rgmii_source_0_logic = rgmii_source_0.create_logic( - phy0_rx_clk, - rst, - txd=phy0_rxd, - tx_ctl=phy0_rx_ctl, - mii_select=mii_select_0, - name='rgmii_source_0' - ) - - rgmii_sink_0 = rgmii_ep.RGMIISink() - - rgmii_sink_0_logic = rgmii_sink_0.create_logic( - phy0_tx_clk, - rst, - rxd=phy0_txd, - rx_ctl=phy0_tx_ctl, - mii_select=mii_select_0, - name='rgmii_sink_0' - ) - - mii_select_1 = Signal(bool(0)) - - rgmii_source_1 = rgmii_ep.RGMIISource() - - rgmii_source_1_logic = rgmii_source_1.create_logic( - phy1_rx_clk, - rst, - txd=phy1_rxd, - tx_ctl=phy1_rx_ctl, - mii_select=mii_select_1, - name='rgmii_source_1' - ) - - rgmii_sink_1 = rgmii_ep.RGMIISink() - - rgmii_sink_1_logic = rgmii_sink_1.create_logic( - phy1_tx_clk, - rst, - rxd=phy1_txd, - rx_ctl=phy1_tx_ctl, - mii_select=mii_select_1, - name='rgmii_sink_1' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - clk90=clk90, - rst=rst, - current_test=current_test, - - btn=btn, - sw=sw, - ledg=ledg, - ledr=ledr, - hex0=hex0, - hex1=hex1, - hex2=hex2, - hex3=hex3, - hex4=hex4, - hex5=hex5, - hex6=hex6, - hex7=hex7, - gpio=gpio, - - phy0_rx_clk=phy0_rx_clk, - phy0_rxd=phy0_rxd, - phy0_rx_ctl=phy0_rx_ctl, - phy0_tx_clk=phy0_tx_clk, - phy0_txd=phy0_txd, - phy0_tx_ctl=phy0_tx_ctl, - phy0_reset_n=phy0_reset_n, - phy0_int_n=phy0_int_n, - - phy1_rx_clk=phy1_rx_clk, - phy1_rxd=phy1_rxd, - phy1_rx_ctl=phy1_rx_ctl, - phy1_tx_clk=phy1_tx_clk, - phy1_txd=phy1_txd, - phy1_tx_ctl=phy1_tx_ctl, - phy1_reset_n=phy1_reset_n, - phy1_int_n=phy1_int_n - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @instance - def clkgen2(): - yield delay(4+2) - while True: - clk90.next = not clk90 - yield delay(4) - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy0_rx_clk.next = not phy0_rx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - rgmii_source_0.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while rgmii_sink_0.empty(): - yield clk.posedge - - rx_frame = rgmii_sink_0.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - rgmii_source_0.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while rgmii_sink_0.empty(): - yield clk.posedge - - rx_frame = rgmii_sink_0.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert rgmii_source_0.empty() - assert rgmii_sink_0.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/DE2-115/fpga/tb/test_fpga_core.v b/example/DE2-115/fpga/tb/test_fpga_core.v deleted file mode 100644 index 6010ac583..000000000 --- a/example/DE2-115/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,158 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk = 0; -reg clk90 = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] btn = 0; -reg [17:0] sw = 0; -reg phy0_rx_clk = 0; -reg [3:0] phy0_rxd = 0; -reg phy0_rx_ctl = 0; -reg phy0_int_n = 1; -reg phy1_rx_clk = 0; -reg [3:0] phy1_rxd = 0; -reg phy1_rx_ctl = 0; -reg phy1_int_n = 1; - -// Outputs -wire [17:0] ledr; -wire [8:0] ledg; -wire [6:0] hex0; -wire [6:0] hex1; -wire [6:0] hex2; -wire [6:0] hex3; -wire [6:0] hex4; -wire [6:0] hex5; -wire [6:0] hex6; -wire [6:0] hex7; -wire [35:0] gpio; -wire phy0_tx_clk; -wire [3:0] phy0_txd; -wire phy0_tx_ctl; -wire phy0_reset_n; -wire phy1_tx_clk; -wire [3:0] phy1_txd; -wire phy1_tx_ctl; -wire phy1_reset_n; - -initial begin - // myhdl integration - $from_myhdl( - clk, - clk90, - rst, - current_test, - btn, - sw, - phy0_rx_clk, - phy0_rxd, - phy0_rx_ctl, - phy0_int_n, - phy1_rx_clk, - phy1_rxd, - phy1_rx_ctl, - phy1_int_n - ); - $to_myhdl( - ledr, - ledg, - hex0, - hex1, - hex2, - hex3, - hex4, - hex5, - hex6, - hex7, - gpio, - phy0_tx_clk, - phy0_txd, - phy0_tx_ctl, - phy0_reset_n, - phy1_tx_clk, - phy1_txd, - phy1_tx_ctl, - phy1_reset_n - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk(clk), - .clk90(clk90), - .rst(rst), - .btn(btn), - .sw(sw), - .ledr(ledr), - .ledg(ledg), - .hex0(hex0), - .hex1(hex1), - .hex2(hex2), - .hex3(hex3), - .hex4(hex4), - .hex5(hex5), - .hex6(hex6), - .hex7(hex7), - .gpio(gpio), - .phy0_rx_clk(phy0_rx_clk), - .phy0_rxd(phy0_rxd), - .phy0_rx_ctl(phy0_rx_ctl), - .phy0_tx_clk(phy0_tx_clk), - .phy0_txd(phy0_txd), - .phy0_tx_ctl(phy0_tx_ctl), - .phy0_reset_n(phy0_reset_n), - .phy0_int_n(phy0_int_n), - .phy1_rx_clk(phy1_rx_clk), - .phy1_rxd(phy1_rxd), - .phy1_rx_ctl(phy1_rx_ctl), - .phy1_tx_clk(phy1_tx_clk), - .phy1_txd(phy1_txd), - .phy1_tx_ctl(phy1_tx_ctl), - .phy1_reset_n(phy1_reset_n), - .phy1_int_n(phy1_int_n) -); - -endmodule diff --git a/example/DE2-115/fpga/tb/udp_ep.py b/example/DE2-115/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/DE2-115/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/DE5-Net/fpga/tb/arp_ep.py b/example/DE5-Net/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/DE5-Net/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/DE5-Net/fpga/tb/axis_ep.py b/example/DE5-Net/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/DE5-Net/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/DE5-Net/fpga/tb/eth_ep.py b/example/DE5-Net/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/DE5-Net/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/DE5-Net/fpga/tb/fpga_core/Makefile b/example/DE5-Net/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/DE5-Net/fpga/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py b/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..1457503af --- /dev/null +++ b/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,214 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + self.sfp_a_source = XgmiiSource(dut.sfp_a_rxd, dut.sfp_a_rxc, dut.clk, dut.rst) + self.sfp_a_sink = XgmiiSink(dut.sfp_a_txd, dut.sfp_a_txc, dut.clk, dut.rst) + + self.sfp_b_source = XgmiiSource(dut.sfp_b_rxd, dut.sfp_b_rxc, dut.clk, dut.rst) + self.sfp_b_sink = XgmiiSink(dut.sfp_b_txd, dut.sfp_b_txc, dut.clk, dut.rst) + + self.sfp_c_source = XgmiiSource(dut.sfp_c_rxd, dut.sfp_c_rxc, dut.clk, dut.rst) + self.sfp_c_sink = XgmiiSink(dut.sfp_c_txd, dut.sfp_c_txc, dut.clk, dut.rst) + + self.sfp_d_source = XgmiiSource(dut.sfp_d_rxd, dut.sfp_d_rxc, dut.clk, dut.rst) + self.sfp_d_sink = XgmiiSink(dut.sfp_d_txd, dut.sfp_d_txc, dut.clk, dut.rst) + + dut.btn.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.sfp_a_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.sfp_a_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.sfp_a_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.sfp_a_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/DE5-Net/fpga/tb/ip_ep.py b/example/DE5-Net/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/DE5-Net/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/DE5-Net/fpga/tb/test_fpga_core.py b/example/DE5-Net/fpga/tb/test_fpga_core.py deleted file mode 100755 index dda16b28a..000000000 --- a/example/DE5-Net/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,303 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btn = Signal(intbv(0)[4:]) - sw = Signal(intbv(0)[4:]) - sfp_a_rxd = Signal(intbv(0)[64:]) - sfp_a_rxc = Signal(intbv(0)[8:]) - sfp_b_rxd = Signal(intbv(0)[64:]) - sfp_b_rxc = Signal(intbv(0)[8:]) - sfp_c_rxd = Signal(intbv(0)[64:]) - sfp_c_rxc = Signal(intbv(0)[8:]) - sfp_d_rxd = Signal(intbv(0)[64:]) - sfp_d_rxc = Signal(intbv(0)[8:]) - - # Outputs - led = Signal(intbv(0)[4:]) - led_bkt = Signal(intbv(0)[4:]) - led_hex0_d = Signal(intbv(0)[7:]) - led_hex0_dp = Signal(bool(0)) - led_hex1_d = Signal(intbv(0)[7:]) - led_hex1_dp = Signal(bool(0)) - sfp_a_txd = Signal(intbv(0)[64:]) - sfp_a_txc = Signal(intbv(0)[8:]) - sfp_b_txd = Signal(intbv(0)[64:]) - sfp_b_txc = Signal(intbv(0)[8:]) - sfp_c_txd = Signal(intbv(0)[64:]) - sfp_c_txc = Signal(intbv(0)[8:]) - sfp_d_txd = Signal(intbv(0)[64:]) - sfp_d_txc = Signal(intbv(0)[8:]) - - # sources and sinks - sfp_a_source = xgmii_ep.XGMIISource() - sfp_a_source_logic = sfp_a_source.create_logic(clk, rst, txd=sfp_a_rxd, txc=sfp_a_rxc, name='sfp_a_source') - - sfp_a_sink = xgmii_ep.XGMIISink() - sfp_a_sink_logic = sfp_a_sink.create_logic(clk, rst, rxd=sfp_a_txd, rxc=sfp_a_txc, name='sfp_a_sink') - - sfp_b_source = xgmii_ep.XGMIISource() - sfp_b_source_logic = sfp_b_source.create_logic(clk, rst, txd=sfp_b_rxd, txc=sfp_b_rxc, name='sfp_b_source') - - sfp_b_sink = xgmii_ep.XGMIISink() - sfp_b_sink_logic = sfp_b_sink.create_logic(clk, rst, rxd=sfp_b_txd, rxc=sfp_b_txc, name='sfp_b_sink') - - sfp_c_source = xgmii_ep.XGMIISource() - sfp_c_source_logic = sfp_c_source.create_logic(clk, rst, txd=sfp_c_rxd, txc=sfp_c_rxc, name='sfp_c_source') - - sfp_c_sink = xgmii_ep.XGMIISink() - sfp_c_sink_logic = sfp_c_sink.create_logic(clk, rst, rxd=sfp_c_txd, rxc=sfp_c_txc, name='sfp_c_sink') - - sfp_d_source = xgmii_ep.XGMIISource() - sfp_d_source_logic = sfp_d_source.create_logic(clk, rst, txd=sfp_d_rxd, txc=sfp_d_rxc, name='sfp_d_source') - - sfp_d_sink = xgmii_ep.XGMIISink() - sfp_d_sink_logic = sfp_d_sink.create_logic(clk, rst, rxd=sfp_d_txd, rxc=sfp_d_txc, name='sfp_d_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btn=btn, - sw=sw, - led=led, - led_bkt=led_bkt, - led_hex0_d=led_hex0_d, - led_hex0_dp=led_hex0_dp, - led_hex1_d=led_hex1_d, - led_hex1_dp=led_hex1_dp, - - sfp_a_txd=sfp_a_txd, - sfp_a_txc=sfp_a_txc, - sfp_a_rxd=sfp_a_rxd, - sfp_a_rxc=sfp_a_rxc, - sfp_b_txd=sfp_b_txd, - sfp_b_txc=sfp_b_txc, - sfp_b_rxd=sfp_b_rxd, - sfp_b_rxc=sfp_b_rxc, - sfp_c_txd=sfp_c_txd, - sfp_c_txc=sfp_c_txc, - sfp_c_rxd=sfp_c_rxd, - sfp_c_rxc=sfp_c_rxc, - sfp_d_txd=sfp_d_txd, - sfp_d_txc=sfp_d_txc, - sfp_d_rxd=sfp_d_rxd, - sfp_d_rxc=sfp_d_rxc - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - sfp_a_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while sfp_a_sink.empty(): - yield clk.posedge - - rx_frame = sfp_a_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - sfp_a_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while sfp_a_sink.empty(): - yield clk.posedge - - rx_frame = sfp_a_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert sfp_a_source.empty() - assert sfp_a_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/DE5-Net/fpga/tb/test_fpga_core.v b/example/DE5-Net/fpga/tb/test_fpga_core.v deleted file mode 100644 index d441f0cce..000000000 --- a/example/DE5-Net/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,137 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] btn = 0; -reg [3:0] sw = 0; -reg [63:0] sfp_a_rxd = 0; -reg [7:0] sfp_a_rxc = 0; -reg [63:0] sfp_b_rxd = 0; -reg [7:0] sfp_b_rxc = 0; -reg [63:0] sfp_c_rxd = 0; -reg [7:0] sfp_c_rxc = 0; -reg [63:0] sfp_d_rxd = 0; -reg [7:0] sfp_d_rxc = 0; - -// Outputs -wire [3:0] led; -wire [3:0] led_bkt; -wire [6:0] led_hex0_d; -wire led_hex0_dp; -wire [6:0] led_hex1_d; -wire led_hex1_dp; -wire [63:0] sfp_a_txd; -wire [7:0] sfp_a_txc; -wire [63:0] sfp_b_txd; -wire [7:0] sfp_b_txc; -wire [63:0] sfp_c_txd; -wire [7:0] sfp_c_txc; -wire [63:0] sfp_d_txd; -wire [7:0] sfp_d_txc; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btn, - sw, - sfp_a_rxd, - sfp_a_rxc, - sfp_b_rxd, - sfp_b_rxc, - sfp_c_rxd, - sfp_c_rxc, - sfp_d_rxd, - sfp_d_rxc - ); - $to_myhdl( - led, - led_bkt, - led_hex0_d, - led_hex0_dp, - led_hex1_d, - led_hex1_dp, - sfp_a_txd, - sfp_a_txc, - sfp_b_txd, - sfp_b_txc, - sfp_c_txd, - sfp_c_txc, - sfp_d_txd, - sfp_d_txc - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btn(btn), - .sw(sw), - .led(led), - .led_bkt(led_bkt), - .led_hex0_d(led_hex0_d), - .led_hex0_dp(led_hex0_dp), - .led_hex1_d(led_hex1_d), - .led_hex1_dp(led_hex1_dp), - .sfp_a_txd(sfp_a_txd), - .sfp_a_txc(sfp_a_txc), - .sfp_a_rxd(sfp_a_rxd), - .sfp_a_rxc(sfp_a_rxc), - .sfp_b_txd(sfp_b_txd), - .sfp_b_txc(sfp_b_txc), - .sfp_b_rxd(sfp_b_rxd), - .sfp_b_rxc(sfp_b_rxc), - .sfp_c_txd(sfp_c_txd), - .sfp_c_txc(sfp_c_txc), - .sfp_c_rxd(sfp_c_rxd), - .sfp_c_rxc(sfp_c_rxc), - .sfp_d_txd(sfp_d_txd), - .sfp_d_txc(sfp_d_txc), - .sfp_d_rxd(sfp_d_rxd), - .sfp_d_rxc(sfp_d_rxc) -); - -endmodule diff --git a/example/DE5-Net/fpga/tb/udp_ep.py b/example/DE5-Net/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/DE5-Net/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/DE5-Net/fpga/tb/xgmii_ep.py b/example/DE5-Net/fpga/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/DE5-Net/fpga/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X10/fpga/tb/arp_ep.py b/example/ExaNIC_X10/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ExaNIC_X10/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X10/fpga/tb/axis_ep.py b/example/ExaNIC_X10/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ExaNIC_X10/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X10/fpga/tb/eth_ep.py b/example/ExaNIC_X10/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ExaNIC_X10/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile b/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py b/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..512e286b0 --- /dev/null +++ b/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,221 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.sfp_1_rx_clk, 6.4, units="ns").start()) + self.sfp_1_source = XgmiiSource(dut.sfp_1_rxd, dut.sfp_1_rxc, dut.sfp_1_rx_clk, dut.sfp_1_rx_rst) + cocotb.fork(Clock(dut.sfp_1_tx_clk, 6.4, units="ns").start()) + self.sfp_1_sink = XgmiiSink(dut.sfp_1_txd, dut.sfp_1_txc, dut.sfp_1_tx_clk, dut.sfp_1_tx_rst) + + cocotb.fork(Clock(dut.sfp_2_rx_clk, 6.4, units="ns").start()) + self.sfp_2_source = XgmiiSource(dut.sfp_2_rxd, dut.sfp_2_rxc, dut.sfp_2_rx_clk, dut.sfp_2_rx_rst) + cocotb.fork(Clock(dut.sfp_2_tx_clk, 6.4, units="ns").start()) + self.sfp_2_sink = XgmiiSink(dut.sfp_2_txd, dut.sfp_2_txc, dut.sfp_2_tx_clk, dut.sfp_2_tx_rst) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.sfp_1_rx_rst.setimmediatevalue(0) + self.dut.sfp_1_tx_rst.setimmediatevalue(0) + self.dut.sfp_2_rx_rst.setimmediatevalue(0) + self.dut.sfp_2_tx_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.sfp_1_rx_rst <= 1 + self.dut.sfp_1_tx_rst <= 1 + self.dut.sfp_2_rx_rst <= 1 + self.dut.sfp_2_tx_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.sfp_1_rx_rst <= 0 + self.dut.sfp_1_tx_rst <= 0 + self.dut.sfp_2_rx_rst <= 0 + self.dut.sfp_2_tx_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.sfp_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.sfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.sfp_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.sfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ExaNIC_X10/fpga/tb/ip_ep.py b/example/ExaNIC_X10/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ExaNIC_X10/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X10/fpga/tb/test_fpga_core.py b/example/ExaNIC_X10/fpga/tb/test_fpga_core.py deleted file mode 100755 index e2214336c..000000000 --- a/example/ExaNIC_X10/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,292 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sfp_1_tx_clk = Signal(bool(0)) - sfp_1_tx_rst = Signal(bool(0)) - sfp_1_rx_clk = Signal(bool(0)) - sfp_1_rx_rst = Signal(bool(0)) - sfp_1_rxd = Signal(intbv(0)[64:]) - sfp_1_rxc = Signal(intbv(0)[8:]) - sfp_2_tx_clk = Signal(bool(0)) - sfp_2_tx_rst = Signal(bool(0)) - sfp_2_rx_clk = Signal(bool(0)) - sfp_2_rx_rst = Signal(bool(0)) - sfp_2_rxd = Signal(intbv(0)[64:]) - sfp_2_rxc = Signal(intbv(0)[8:]) - - # Outputs - sfp_1_led = Signal(intbv(0)[2:]) - sfp_2_led = Signal(intbv(0)[2:]) - sma_led = Signal(intbv(0)[2:]) - sfp_1_txd = Signal(intbv(0)[64:]) - sfp_1_txc = Signal(intbv(0)[8:]) - sfp_2_txd = Signal(intbv(0)[64:]) - sfp_2_txc = Signal(intbv(0)[8:]) - - # sources and sinks - sfp_1_source = xgmii_ep.XGMIISource() - sfp_1_source_logic = sfp_1_source.create_logic(sfp_1_rx_clk, sfp_1_rx_rst, txd=sfp_1_rxd, txc=sfp_1_rxc, name='sfp_1_source') - - sfp_1_sink = xgmii_ep.XGMIISink() - sfp_1_sink_logic = sfp_1_sink.create_logic(sfp_1_tx_clk, sfp_1_tx_rst, rxd=sfp_1_txd, rxc=sfp_1_txc, name='sfp_1_sink') - - sfp_2_source = xgmii_ep.XGMIISource() - sfp_2_source_logic = sfp_2_source.create_logic(sfp_2_rx_clk, sfp_2_rx_rst, txd=sfp_2_rxd, txc=sfp_2_rxc, name='sfp_2_source') - - sfp_2_sink = xgmii_ep.XGMIISink() - sfp_2_sink_logic = sfp_2_sink.create_logic(sfp_2_tx_clk, sfp_2_tx_rst, rxd=sfp_2_txd, rxc=sfp_2_txc, name='sfp_2_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sfp_1_led=sfp_1_led, - sfp_2_led=sfp_2_led, - sma_led=sma_led, - - sfp_1_tx_clk=sfp_1_tx_clk, - sfp_1_tx_rst=sfp_1_tx_rst, - sfp_1_txd=sfp_1_txd, - sfp_1_txc=sfp_1_txc, - sfp_1_rx_clk=sfp_1_rx_clk, - sfp_1_rx_rst=sfp_1_rx_rst, - sfp_1_rxd=sfp_1_rxd, - sfp_1_rxc=sfp_1_rxc, - sfp_2_tx_clk=sfp_2_tx_clk, - sfp_2_tx_rst=sfp_2_tx_rst, - sfp_2_txd=sfp_2_txd, - sfp_2_txc=sfp_2_txc, - sfp_2_rx_clk=sfp_2_rx_clk, - sfp_2_rx_rst=sfp_2_rx_rst, - sfp_2_rxd=sfp_2_rxd, - sfp_2_rxc=sfp_2_rxc - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @always_comb - def clk_logic(): - sfp_1_tx_clk.next = clk - sfp_1_tx_rst.next = rst - sfp_1_rx_clk.next = clk - sfp_1_rx_rst.next = rst - sfp_2_tx_clk.next = clk - sfp_2_tx_rst.next = rst - sfp_2_rx_clk.next = clk - sfp_2_rx_rst.next = rst - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - sfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while sfp_1_sink.empty(): - yield clk.posedge - - rx_frame = sfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - sfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while sfp_1_sink.empty(): - yield clk.posedge - - rx_frame = sfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert sfp_1_source.empty() - assert sfp_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ExaNIC_X10/fpga/tb/test_fpga_core.v b/example/ExaNIC_X10/fpga/tb/test_fpga_core.v deleted file mode 100644 index 790c5ced7..000000000 --- a/example/ExaNIC_X10/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,122 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg sfp_1_tx_clk = 0; -reg sfp_1_tx_rst = 0; -reg sfp_1_rx_clk = 0; -reg sfp_1_rx_rst = 0; -reg [63:0] sfp_1_rxd = 0; -reg [7:0] sfp_1_rxc = 0; -reg sfp_2_tx_clk = 0; -reg sfp_2_tx_rst = 0; -reg sfp_2_rx_clk = 0; -reg sfp_2_rx_rst = 0; -reg [63:0] sfp_2_rxd = 0; -reg [7:0] sfp_2_rxc = 0; - -// Outputs -wire [1:0] sfp_1_led; -wire [1:0] sfp_2_led; -wire [1:0] sma_led; -wire [63:0] sfp_1_txd; -wire [7:0] sfp_1_txc; -wire [63:0] sfp_2_txd; -wire [7:0] sfp_2_txc; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sfp_1_tx_clk, - sfp_1_tx_rst, - sfp_1_rx_clk, - sfp_1_rx_rst, - sfp_1_rxd, - sfp_1_rxc, - sfp_2_tx_clk, - sfp_2_tx_rst, - sfp_2_rx_clk, - sfp_2_rx_rst, - sfp_2_rxd, - sfp_2_rxc - ); - $to_myhdl( - sfp_1_led, - sfp_2_led, - sma_led, - sfp_1_txd, - sfp_1_txc, - sfp_2_txd, - sfp_2_txc - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sfp_1_led(sfp_1_led), - .sfp_2_led(sfp_2_led), - .sma_led(sma_led), - .sfp_1_tx_clk(sfp_1_tx_clk), - .sfp_1_tx_rst(sfp_1_tx_rst), - .sfp_1_txd(sfp_1_txd), - .sfp_1_txc(sfp_1_txc), - .sfp_1_rx_clk(sfp_1_rx_clk), - .sfp_1_rx_rst(sfp_1_rx_rst), - .sfp_1_rxd(sfp_1_rxd), - .sfp_1_rxc(sfp_1_rxc), - .sfp_2_tx_clk(sfp_2_tx_clk), - .sfp_2_tx_rst(sfp_2_tx_rst), - .sfp_2_txd(sfp_2_txd), - .sfp_2_txc(sfp_2_txc), - .sfp_2_rx_clk(sfp_2_rx_clk), - .sfp_2_rx_rst(sfp_2_rx_rst), - .sfp_2_rxd(sfp_2_rxd), - .sfp_2_rxc(sfp_2_rxc) -); - -endmodule diff --git a/example/ExaNIC_X10/fpga/tb/udp_ep.py b/example/ExaNIC_X10/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ExaNIC_X10/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X10/fpga/tb/xgmii_ep.py b/example/ExaNIC_X10/fpga/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/ExaNIC_X10/fpga/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X25/fpga_10g/tb/arp_ep.py b/example/ExaNIC_X25/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X25/fpga_10g/tb/axis_ep.py b/example/ExaNIC_X25/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X25/fpga_10g/tb/eth_ep.py b/example/ExaNIC_X25/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..512e286b0 --- /dev/null +++ b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,221 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.sfp_1_rx_clk, 6.4, units="ns").start()) + self.sfp_1_source = XgmiiSource(dut.sfp_1_rxd, dut.sfp_1_rxc, dut.sfp_1_rx_clk, dut.sfp_1_rx_rst) + cocotb.fork(Clock(dut.sfp_1_tx_clk, 6.4, units="ns").start()) + self.sfp_1_sink = XgmiiSink(dut.sfp_1_txd, dut.sfp_1_txc, dut.sfp_1_tx_clk, dut.sfp_1_tx_rst) + + cocotb.fork(Clock(dut.sfp_2_rx_clk, 6.4, units="ns").start()) + self.sfp_2_source = XgmiiSource(dut.sfp_2_rxd, dut.sfp_2_rxc, dut.sfp_2_rx_clk, dut.sfp_2_rx_rst) + cocotb.fork(Clock(dut.sfp_2_tx_clk, 6.4, units="ns").start()) + self.sfp_2_sink = XgmiiSink(dut.sfp_2_txd, dut.sfp_2_txc, dut.sfp_2_tx_clk, dut.sfp_2_tx_rst) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.sfp_1_rx_rst.setimmediatevalue(0) + self.dut.sfp_1_tx_rst.setimmediatevalue(0) + self.dut.sfp_2_rx_rst.setimmediatevalue(0) + self.dut.sfp_2_tx_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.sfp_1_rx_rst <= 1 + self.dut.sfp_1_tx_rst <= 1 + self.dut.sfp_2_rx_rst <= 1 + self.dut.sfp_2_tx_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.sfp_1_rx_rst <= 0 + self.dut.sfp_1_tx_rst <= 0 + self.dut.sfp_2_rx_rst <= 0 + self.dut.sfp_2_tx_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.sfp_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.sfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.sfp_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.sfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ExaNIC_X25/fpga_10g/tb/ip_ep.py b/example/ExaNIC_X25/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py b/example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index e2214336c..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,292 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sfp_1_tx_clk = Signal(bool(0)) - sfp_1_tx_rst = Signal(bool(0)) - sfp_1_rx_clk = Signal(bool(0)) - sfp_1_rx_rst = Signal(bool(0)) - sfp_1_rxd = Signal(intbv(0)[64:]) - sfp_1_rxc = Signal(intbv(0)[8:]) - sfp_2_tx_clk = Signal(bool(0)) - sfp_2_tx_rst = Signal(bool(0)) - sfp_2_rx_clk = Signal(bool(0)) - sfp_2_rx_rst = Signal(bool(0)) - sfp_2_rxd = Signal(intbv(0)[64:]) - sfp_2_rxc = Signal(intbv(0)[8:]) - - # Outputs - sfp_1_led = Signal(intbv(0)[2:]) - sfp_2_led = Signal(intbv(0)[2:]) - sma_led = Signal(intbv(0)[2:]) - sfp_1_txd = Signal(intbv(0)[64:]) - sfp_1_txc = Signal(intbv(0)[8:]) - sfp_2_txd = Signal(intbv(0)[64:]) - sfp_2_txc = Signal(intbv(0)[8:]) - - # sources and sinks - sfp_1_source = xgmii_ep.XGMIISource() - sfp_1_source_logic = sfp_1_source.create_logic(sfp_1_rx_clk, sfp_1_rx_rst, txd=sfp_1_rxd, txc=sfp_1_rxc, name='sfp_1_source') - - sfp_1_sink = xgmii_ep.XGMIISink() - sfp_1_sink_logic = sfp_1_sink.create_logic(sfp_1_tx_clk, sfp_1_tx_rst, rxd=sfp_1_txd, rxc=sfp_1_txc, name='sfp_1_sink') - - sfp_2_source = xgmii_ep.XGMIISource() - sfp_2_source_logic = sfp_2_source.create_logic(sfp_2_rx_clk, sfp_2_rx_rst, txd=sfp_2_rxd, txc=sfp_2_rxc, name='sfp_2_source') - - sfp_2_sink = xgmii_ep.XGMIISink() - sfp_2_sink_logic = sfp_2_sink.create_logic(sfp_2_tx_clk, sfp_2_tx_rst, rxd=sfp_2_txd, rxc=sfp_2_txc, name='sfp_2_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sfp_1_led=sfp_1_led, - sfp_2_led=sfp_2_led, - sma_led=sma_led, - - sfp_1_tx_clk=sfp_1_tx_clk, - sfp_1_tx_rst=sfp_1_tx_rst, - sfp_1_txd=sfp_1_txd, - sfp_1_txc=sfp_1_txc, - sfp_1_rx_clk=sfp_1_rx_clk, - sfp_1_rx_rst=sfp_1_rx_rst, - sfp_1_rxd=sfp_1_rxd, - sfp_1_rxc=sfp_1_rxc, - sfp_2_tx_clk=sfp_2_tx_clk, - sfp_2_tx_rst=sfp_2_tx_rst, - sfp_2_txd=sfp_2_txd, - sfp_2_txc=sfp_2_txc, - sfp_2_rx_clk=sfp_2_rx_clk, - sfp_2_rx_rst=sfp_2_rx_rst, - sfp_2_rxd=sfp_2_rxd, - sfp_2_rxc=sfp_2_rxc - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @always_comb - def clk_logic(): - sfp_1_tx_clk.next = clk - sfp_1_tx_rst.next = rst - sfp_1_rx_clk.next = clk - sfp_1_rx_rst.next = rst - sfp_2_tx_clk.next = clk - sfp_2_tx_rst.next = rst - sfp_2_rx_clk.next = clk - sfp_2_rx_rst.next = rst - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - sfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while sfp_1_sink.empty(): - yield clk.posedge - - rx_frame = sfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - sfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while sfp_1_sink.empty(): - yield clk.posedge - - rx_frame = sfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert sfp_1_source.empty() - assert sfp_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v b/example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index 790c5ced7..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,122 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg sfp_1_tx_clk = 0; -reg sfp_1_tx_rst = 0; -reg sfp_1_rx_clk = 0; -reg sfp_1_rx_rst = 0; -reg [63:0] sfp_1_rxd = 0; -reg [7:0] sfp_1_rxc = 0; -reg sfp_2_tx_clk = 0; -reg sfp_2_tx_rst = 0; -reg sfp_2_rx_clk = 0; -reg sfp_2_rx_rst = 0; -reg [63:0] sfp_2_rxd = 0; -reg [7:0] sfp_2_rxc = 0; - -// Outputs -wire [1:0] sfp_1_led; -wire [1:0] sfp_2_led; -wire [1:0] sma_led; -wire [63:0] sfp_1_txd; -wire [7:0] sfp_1_txc; -wire [63:0] sfp_2_txd; -wire [7:0] sfp_2_txc; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sfp_1_tx_clk, - sfp_1_tx_rst, - sfp_1_rx_clk, - sfp_1_rx_rst, - sfp_1_rxd, - sfp_1_rxc, - sfp_2_tx_clk, - sfp_2_tx_rst, - sfp_2_rx_clk, - sfp_2_rx_rst, - sfp_2_rxd, - sfp_2_rxc - ); - $to_myhdl( - sfp_1_led, - sfp_2_led, - sma_led, - sfp_1_txd, - sfp_1_txc, - sfp_2_txd, - sfp_2_txc - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sfp_1_led(sfp_1_led), - .sfp_2_led(sfp_2_led), - .sma_led(sma_led), - .sfp_1_tx_clk(sfp_1_tx_clk), - .sfp_1_tx_rst(sfp_1_tx_rst), - .sfp_1_txd(sfp_1_txd), - .sfp_1_txc(sfp_1_txc), - .sfp_1_rx_clk(sfp_1_rx_clk), - .sfp_1_rx_rst(sfp_1_rx_rst), - .sfp_1_rxd(sfp_1_rxd), - .sfp_1_rxc(sfp_1_rxc), - .sfp_2_tx_clk(sfp_2_tx_clk), - .sfp_2_tx_rst(sfp_2_tx_rst), - .sfp_2_txd(sfp_2_txd), - .sfp_2_txc(sfp_2_txc), - .sfp_2_rx_clk(sfp_2_rx_clk), - .sfp_2_rx_rst(sfp_2_rx_rst), - .sfp_2_rxd(sfp_2_rxd), - .sfp_2_rxc(sfp_2_rxc) -); - -endmodule diff --git a/example/ExaNIC_X25/fpga_10g/tb/udp_ep.py b/example/ExaNIC_X25/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ExaNIC_X25/fpga_10g/tb/xgmii_ep.py b/example/ExaNIC_X25/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/ExaNIC_X25/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga/tb/arp_ep.py b/example/HXT100G/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/HXT100G/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga/tb/axis_ep.py b/example/HXT100G/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/HXT100G/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga/tb/eth_ep.py b/example/HXT100G/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/HXT100G/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga/tb/fpga_core/Makefile b/example/HXT100G/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/HXT100G/fpga/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py b/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..cdbc9125c --- /dev/null +++ b/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,280 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + self.eth_r0_source = XgmiiSource(dut.eth_r0_rxd, dut.eth_r0_rxc, dut.clk, dut.rst) + self.eth_r0_sink = XgmiiSink(dut.eth_r0_txd, dut.eth_r0_txc, dut.clk, dut.rst) + + self.eth_r1_source = XgmiiSource(dut.eth_r1_rxd, dut.eth_r1_rxc, dut.clk, dut.rst) + self.eth_r1_sink = XgmiiSink(dut.eth_r1_txd, dut.eth_r1_txc, dut.clk, dut.rst) + + self.eth_r2_source = XgmiiSource(dut.eth_r2_rxd, dut.eth_r2_rxc, dut.clk, dut.rst) + self.eth_r2_sink = XgmiiSink(dut.eth_r2_txd, dut.eth_r2_txc, dut.clk, dut.rst) + + self.eth_r3_source = XgmiiSource(dut.eth_r3_rxd, dut.eth_r3_rxc, dut.clk, dut.rst) + self.eth_r3_sink = XgmiiSink(dut.eth_r3_txd, dut.eth_r3_txc, dut.clk, dut.rst) + + self.eth_r4_source = XgmiiSource(dut.eth_r4_rxd, dut.eth_r4_rxc, dut.clk, dut.rst) + self.eth_r4_sink = XgmiiSink(dut.eth_r4_txd, dut.eth_r4_txc, dut.clk, dut.rst) + + self.eth_r5_source = XgmiiSource(dut.eth_r5_rxd, dut.eth_r5_rxc, dut.clk, dut.rst) + self.eth_r5_sink = XgmiiSink(dut.eth_r5_txd, dut.eth_r5_txc, dut.clk, dut.rst) + + self.eth_r6_source = XgmiiSource(dut.eth_r6_rxd, dut.eth_r6_rxc, dut.clk, dut.rst) + self.eth_r6_sink = XgmiiSink(dut.eth_r6_txd, dut.eth_r6_txc, dut.clk, dut.rst) + + self.eth_r7_source = XgmiiSource(dut.eth_r7_rxd, dut.eth_r7_rxc, dut.clk, dut.rst) + self.eth_r7_sink = XgmiiSink(dut.eth_r7_txd, dut.eth_r7_txc, dut.clk, dut.rst) + + self.eth_r8_source = XgmiiSource(dut.eth_r8_rxd, dut.eth_r8_rxc, dut.clk, dut.rst) + self.eth_r8_sink = XgmiiSink(dut.eth_r8_txd, dut.eth_r8_txc, dut.clk, dut.rst) + + self.eth_r9_source = XgmiiSource(dut.eth_r9_rxd, dut.eth_r9_rxc, dut.clk, dut.rst) + self.eth_r9_sink = XgmiiSink(dut.eth_r9_txd, dut.eth_r9_txc, dut.clk, dut.rst) + + self.eth_r10_source = XgmiiSource(dut.eth_r10_rxd, dut.eth_r10_rxc, dut.clk, dut.rst) + self.eth_r10_sink = XgmiiSink(dut.eth_r10_txd, dut.eth_r10_txc, dut.clk, dut.rst) + + self.eth_r11_source = XgmiiSource(dut.eth_r11_rxd, dut.eth_r11_rxc, dut.clk, dut.rst) + self.eth_r11_sink = XgmiiSink(dut.eth_r11_txd, dut.eth_r11_txc, dut.clk, dut.rst) + + self.eth_l0_source = XgmiiSource(dut.eth_l0_rxd, dut.eth_l0_rxc, dut.clk, dut.rst) + self.eth_l0_sink = XgmiiSink(dut.eth_l0_txd, dut.eth_l0_txc, dut.clk, dut.rst) + + self.eth_l1_source = XgmiiSource(dut.eth_l1_rxd, dut.eth_l1_rxc, dut.clk, dut.rst) + self.eth_l1_sink = XgmiiSink(dut.eth_l1_txd, dut.eth_l1_txc, dut.clk, dut.rst) + + self.eth_l2_source = XgmiiSource(dut.eth_l2_rxd, dut.eth_l2_rxc, dut.clk, dut.rst) + self.eth_l2_sink = XgmiiSink(dut.eth_l2_txd, dut.eth_l2_txc, dut.clk, dut.rst) + + self.eth_l3_source = XgmiiSource(dut.eth_l3_rxd, dut.eth_l3_rxc, dut.clk, dut.rst) + self.eth_l3_sink = XgmiiSink(dut.eth_l3_txd, dut.eth_l3_txc, dut.clk, dut.rst) + + self.eth_l4_source = XgmiiSource(dut.eth_l4_rxd, dut.eth_l4_rxc, dut.clk, dut.rst) + self.eth_l4_sink = XgmiiSink(dut.eth_l4_txd, dut.eth_l4_txc, dut.clk, dut.rst) + + self.eth_l5_source = XgmiiSource(dut.eth_l5_rxd, dut.eth_l5_rxc, dut.clk, dut.rst) + self.eth_l5_sink = XgmiiSink(dut.eth_l5_txd, dut.eth_l5_txc, dut.clk, dut.rst) + + self.eth_l6_source = XgmiiSource(dut.eth_l6_rxd, dut.eth_l6_rxc, dut.clk, dut.rst) + self.eth_l6_sink = XgmiiSink(dut.eth_l6_txd, dut.eth_l6_txc, dut.clk, dut.rst) + + self.eth_l7_source = XgmiiSource(dut.eth_l7_rxd, dut.eth_l7_rxc, dut.clk, dut.rst) + self.eth_l7_sink = XgmiiSink(dut.eth_l7_txd, dut.eth_l7_txc, dut.clk, dut.rst) + + self.eth_l8_source = XgmiiSource(dut.eth_l8_rxd, dut.eth_l8_rxc, dut.clk, dut.rst) + self.eth_l8_sink = XgmiiSink(dut.eth_l8_txd, dut.eth_l8_txc, dut.clk, dut.rst) + + self.eth_l9_source = XgmiiSource(dut.eth_l9_rxd, dut.eth_l9_rxc, dut.clk, dut.rst) + self.eth_l9_sink = XgmiiSink(dut.eth_l9_txd, dut.eth_l9_txc, dut.clk, dut.rst) + + self.eth_l10_source = XgmiiSource(dut.eth_l10_rxd, dut.eth_l10_rxc, dut.clk, dut.rst) + self.eth_l10_sink = XgmiiSink(dut.eth_l10_txd, dut.eth_l10_txc, dut.clk, dut.rst) + + self.eth_l11_source = XgmiiSource(dut.eth_l11_rxd, dut.eth_l11_rxc, dut.clk, dut.rst) + self.eth_l11_sink = XgmiiSink(dut.eth_l11_txd, dut.eth_l11_txc, dut.clk, dut.rst) + + dut.sw.setimmediatevalue(0) + dut.jp.setimmediatevalue(0) + dut.uart_suspend.setimmediatevalue(0) + dut.uart_dtr.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(0) + dut.uart_rts.setimmediatevalue(0) + dut.amh_right_mdio_i.setimmediatevalue(0) + dut.amh_left_mdio_i.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.eth_l0_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.eth_l0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.eth_l0_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.eth_l0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/HXT100G/fpga/tb/ip_ep.py b/example/HXT100G/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/HXT100G/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga/tb/test_fpga_core.py b/example/HXT100G/fpga/tb/test_fpga_core.py deleted file mode 100755 index 3ca870e07..000000000 --- a/example/HXT100G/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,611 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sw = Signal(intbv(0)[2:]) - jp = Signal(intbv(0)[4:]) - uart_suspend = Signal(bool(0)) - uart_dtr = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - amh_right_mdio_i = Signal(bool(0)) - amh_left_mdio_i = Signal(bool(0)) - eth_r0_rxd = Signal(intbv(0)[64:]) - eth_r0_rxc = Signal(intbv(0)[8:]) - eth_r1_rxd = Signal(intbv(0)[64:]) - eth_r1_rxc = Signal(intbv(0)[8:]) - eth_r2_rxd = Signal(intbv(0)[64:]) - eth_r2_rxc = Signal(intbv(0)[8:]) - eth_r3_rxd = Signal(intbv(0)[64:]) - eth_r3_rxc = Signal(intbv(0)[8:]) - eth_r4_rxd = Signal(intbv(0)[64:]) - eth_r4_rxc = Signal(intbv(0)[8:]) - eth_r5_rxd = Signal(intbv(0)[64:]) - eth_r5_rxc = Signal(intbv(0)[8:]) - eth_r6_rxd = Signal(intbv(0)[64:]) - eth_r6_rxc = Signal(intbv(0)[8:]) - eth_r7_rxd = Signal(intbv(0)[64:]) - eth_r7_rxc = Signal(intbv(0)[8:]) - eth_r8_rxd = Signal(intbv(0)[64:]) - eth_r8_rxc = Signal(intbv(0)[8:]) - eth_r9_rxd = Signal(intbv(0)[64:]) - eth_r9_rxc = Signal(intbv(0)[8:]) - eth_r10_rxd = Signal(intbv(0)[64:]) - eth_r10_rxc = Signal(intbv(0)[8:]) - eth_r11_rxd = Signal(intbv(0)[64:]) - eth_r11_rxc = Signal(intbv(0)[8:]) - eth_l0_rxd = Signal(intbv(0)[64:]) - eth_l0_rxc = Signal(intbv(0)[8:]) - eth_l1_rxd = Signal(intbv(0)[64:]) - eth_l1_rxc = Signal(intbv(0)[8:]) - eth_l2_rxd = Signal(intbv(0)[64:]) - eth_l2_rxc = Signal(intbv(0)[8:]) - eth_l3_rxd = Signal(intbv(0)[64:]) - eth_l3_rxc = Signal(intbv(0)[8:]) - eth_l4_rxd = Signal(intbv(0)[64:]) - eth_l4_rxc = Signal(intbv(0)[8:]) - eth_l5_rxd = Signal(intbv(0)[64:]) - eth_l5_rxc = Signal(intbv(0)[8:]) - eth_l6_rxd = Signal(intbv(0)[64:]) - eth_l6_rxc = Signal(intbv(0)[8:]) - eth_l7_rxd = Signal(intbv(0)[64:]) - eth_l7_rxc = Signal(intbv(0)[8:]) - eth_l8_rxd = Signal(intbv(0)[64:]) - eth_l8_rxc = Signal(intbv(0)[8:]) - eth_l9_rxd = Signal(intbv(0)[64:]) - eth_l9_rxc = Signal(intbv(0)[8:]) - eth_l10_rxd = Signal(intbv(0)[64:]) - eth_l10_rxc = Signal(intbv(0)[8:]) - eth_l11_rxd = Signal(intbv(0)[64:]) - eth_l11_rxc = Signal(intbv(0)[8:]) - - # Outputs - led = Signal(intbv(0)[4:]) - uart_rst = Signal(bool(0)) - uart_ri = Signal(bool(0)) - uart_dcd = Signal(bool(0)) - uart_dsr = Signal(bool(0)) - uart_rxd = Signal(bool(1)) - uart_cts = Signal(bool(0)) - amh_right_mdc = Signal(bool(1)) - amh_right_mdio_o = Signal(bool(1)) - amh_right_mdio_t = Signal(bool(1)) - amh_left_mdc = Signal(bool(1)) - amh_left_mdio_o = Signal(bool(1)) - amh_left_mdio_t = Signal(bool(1)) - eth_r0_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r0_txc = Signal(intbv(0xff)[8:]) - eth_r1_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r1_txc = Signal(intbv(0xff)[8:]) - eth_r2_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r2_txc = Signal(intbv(0xff)[8:]) - eth_r3_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r3_txc = Signal(intbv(0xff)[8:]) - eth_r4_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r4_txc = Signal(intbv(0xff)[8:]) - eth_r5_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r5_txc = Signal(intbv(0xff)[8:]) - eth_r6_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r6_txc = Signal(intbv(0xff)[8:]) - eth_r7_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r7_txc = Signal(intbv(0xff)[8:]) - eth_r8_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r8_txc = Signal(intbv(0xff)[8:]) - eth_r9_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r9_txc = Signal(intbv(0xff)[8:]) - eth_r10_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r10_txc = Signal(intbv(0xff)[8:]) - eth_r11_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r11_txc = Signal(intbv(0xff)[8:]) - eth_l0_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l0_txc = Signal(intbv(0xff)[8:]) - eth_l1_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l1_txc = Signal(intbv(0xff)[8:]) - eth_l2_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l2_txc = Signal(intbv(0xff)[8:]) - eth_l3_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l3_txc = Signal(intbv(0xff)[8:]) - eth_l4_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l4_txc = Signal(intbv(0xff)[8:]) - eth_l5_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l5_txc = Signal(intbv(0xff)[8:]) - eth_l6_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l6_txc = Signal(intbv(0xff)[8:]) - eth_l7_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l7_txc = Signal(intbv(0xff)[8:]) - eth_l8_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l8_txc = Signal(intbv(0xff)[8:]) - eth_l9_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l9_txc = Signal(intbv(0xff)[8:]) - eth_l10_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l10_txc = Signal(intbv(0xff)[8:]) - eth_l11_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l11_txc = Signal(intbv(0xff)[8:]) - - # sources and sinks - eth_r0_source = xgmii_ep.XGMIISource() - eth_r0_source_logic = eth_r0_source.create_logic(clk, rst, txd=eth_r0_rxd, txc=eth_r0_rxc, name='eth_r0_source') - - eth_r0_sink = xgmii_ep.XGMIISink() - eth_r0_sink_logic = eth_r0_sink.create_logic(clk, rst, rxd=eth_r0_txd, rxc=eth_r0_txc, name='eth_r0_sink') - - eth_r1_source = xgmii_ep.XGMIISource() - eth_r1_source_logic = eth_r1_source.create_logic(clk, rst, txd=eth_r1_rxd, txc=eth_r1_rxc, name='eth_r1_source') - - eth_r1_sink = xgmii_ep.XGMIISink() - eth_r1_sink_logic = eth_r1_sink.create_logic(clk, rst, rxd=eth_r1_txd, rxc=eth_r1_txc, name='eth_r1_sink') - - eth_r2_source = xgmii_ep.XGMIISource() - eth_r2_source_logic = eth_r2_source.create_logic(clk, rst, txd=eth_r2_rxd, txc=eth_r2_rxc, name='eth_r2_source') - - eth_r2_sink = xgmii_ep.XGMIISink() - eth_r2_sink_logic = eth_r2_sink.create_logic(clk, rst, rxd=eth_r2_txd, rxc=eth_r2_txc, name='eth_r2_sink') - - eth_r3_source = xgmii_ep.XGMIISource() - eth_r3_source_logic = eth_r3_source.create_logic(clk, rst, txd=eth_r3_rxd, txc=eth_r3_rxc, name='eth_r3_source') - - eth_r3_sink = xgmii_ep.XGMIISink() - eth_r3_sink_logic = eth_r3_sink.create_logic(clk, rst, rxd=eth_r3_txd, rxc=eth_r3_txc, name='eth_r3_sink') - - eth_r4_source = xgmii_ep.XGMIISource() - eth_r4_source_logic = eth_r4_source.create_logic(clk, rst, txd=eth_r4_rxd, txc=eth_r4_rxc, name='eth_r4_source') - - eth_r4_sink = xgmii_ep.XGMIISink() - eth_r4_sink_logic = eth_r4_sink.create_logic(clk, rst, rxd=eth_r4_txd, rxc=eth_r4_txc, name='eth_r4_sink') - - eth_r5_source = xgmii_ep.XGMIISource() - eth_r5_source_logic = eth_r5_source.create_logic(clk, rst, txd=eth_r5_rxd, txc=eth_r5_rxc, name='eth_r5_source') - - eth_r5_sink = xgmii_ep.XGMIISink() - eth_r5_sink_logic = eth_r5_sink.create_logic(clk, rst, rxd=eth_r5_txd, rxc=eth_r5_txc, name='eth_r5_sink') - - eth_r6_source = xgmii_ep.XGMIISource() - eth_r6_source_logic = eth_r6_source.create_logic(clk, rst, txd=eth_r6_rxd, txc=eth_r6_rxc, name='eth_r6_source') - - eth_r6_sink = xgmii_ep.XGMIISink() - eth_r6_sink_logic = eth_r6_sink.create_logic(clk, rst, rxd=eth_r6_txd, rxc=eth_r6_txc, name='eth_r6_sink') - - eth_r7_source = xgmii_ep.XGMIISource() - eth_r7_source_logic = eth_r7_source.create_logic(clk, rst, txd=eth_r7_rxd, txc=eth_r7_rxc, name='eth_r7_source') - - eth_r7_sink = xgmii_ep.XGMIISink() - eth_r7_sink_logic = eth_r7_sink.create_logic(clk, rst, rxd=eth_r7_txd, rxc=eth_r7_txc, name='eth_r7_sink') - - eth_r8_source = xgmii_ep.XGMIISource() - eth_r8_source_logic = eth_r8_source.create_logic(clk, rst, txd=eth_r8_rxd, txc=eth_r8_rxc, name='eth_r8_source') - - eth_r8_sink = xgmii_ep.XGMIISink() - eth_r8_sink_logic = eth_r8_sink.create_logic(clk, rst, rxd=eth_r8_txd, rxc=eth_r8_txc, name='eth_r8_sink') - - eth_r9_source = xgmii_ep.XGMIISource() - eth_r9_source_logic = eth_r9_source.create_logic(clk, rst, txd=eth_r9_rxd, txc=eth_r9_rxc, name='eth_r9_source') - - eth_r9_sink = xgmii_ep.XGMIISink() - eth_r9_sink_logic = eth_r9_sink.create_logic(clk, rst, rxd=eth_r9_txd, rxc=eth_r9_txc, name='eth_r9_sink') - - eth_r10_source = xgmii_ep.XGMIISource() - eth_r10_source_logic = eth_r10_source.create_logic(clk, rst, txd=eth_r10_rxd, txc=eth_r10_rxc, name='eth_r10_source') - - eth_r10_sink = xgmii_ep.XGMIISink() - eth_r10_sink_logic = eth_r10_sink.create_logic(clk, rst, rxd=eth_r10_txd, rxc=eth_r10_txc, name='eth_r10_sink') - - eth_r11_source = xgmii_ep.XGMIISource() - eth_r11_source_logic = eth_r11_source.create_logic(clk, rst, txd=eth_r11_rxd, txc=eth_r11_rxc, name='eth_r11_source') - - eth_r11_sink = xgmii_ep.XGMIISink() - eth_r11_sink_logic = eth_r11_sink.create_logic(clk, rst, rxd=eth_r11_txd, rxc=eth_r11_txc, name='eth_r11_sink') - - eth_l0_source = xgmii_ep.XGMIISource() - eth_l0_source_logic = eth_l0_source.create_logic(clk, rst, txd=eth_l0_rxd, txc=eth_l0_rxc, name='eth_l0_source') - - eth_l0_sink = xgmii_ep.XGMIISink() - eth_l0_sink_logic = eth_l0_sink.create_logic(clk, rst, rxd=eth_l0_txd, rxc=eth_l0_txc, name='eth_l0_sink') - - eth_l1_source = xgmii_ep.XGMIISource() - eth_l1_source_logic = eth_l1_source.create_logic(clk, rst, txd=eth_l1_rxd, txc=eth_l1_rxc, name='eth_l1_source') - - eth_l1_sink = xgmii_ep.XGMIISink() - eth_l1_sink_logic = eth_l1_sink.create_logic(clk, rst, rxd=eth_l1_txd, rxc=eth_l1_txc, name='eth_l1_sink') - - eth_l2_source = xgmii_ep.XGMIISource() - eth_l2_source_logic = eth_l2_source.create_logic(clk, rst, txd=eth_l2_rxd, txc=eth_l2_rxc, name='eth_l2_source') - - eth_l2_sink = xgmii_ep.XGMIISink() - eth_l2_sink_logic = eth_l2_sink.create_logic(clk, rst, rxd=eth_l2_txd, rxc=eth_l2_txc, name='eth_l2_sink') - - eth_l3_source = xgmii_ep.XGMIISource() - eth_l3_source_logic = eth_l3_source.create_logic(clk, rst, txd=eth_l3_rxd, txc=eth_l3_rxc, name='eth_l3_source') - - eth_l3_sink = xgmii_ep.XGMIISink() - eth_l3_sink_logic = eth_l3_sink.create_logic(clk, rst, rxd=eth_l3_txd, rxc=eth_l3_txc, name='eth_l3_sink') - - eth_l4_source = xgmii_ep.XGMIISource() - eth_l4_source_logic = eth_l4_source.create_logic(clk, rst, txd=eth_l4_rxd, txc=eth_l4_rxc, name='eth_l4_source') - - eth_l4_sink = xgmii_ep.XGMIISink() - eth_l4_sink_logic = eth_l4_sink.create_logic(clk, rst, rxd=eth_l4_txd, rxc=eth_l4_txc, name='eth_l4_sink') - - eth_l5_source = xgmii_ep.XGMIISource() - eth_l5_source_logic = eth_l5_source.create_logic(clk, rst, txd=eth_l5_rxd, txc=eth_l5_rxc, name='eth_l5_source') - - eth_l5_sink = xgmii_ep.XGMIISink() - eth_l5_sink_logic = eth_l5_sink.create_logic(clk, rst, rxd=eth_l5_txd, rxc=eth_l5_txc, name='eth_l5_sink') - - eth_l6_source = xgmii_ep.XGMIISource() - eth_l6_source_logic = eth_l6_source.create_logic(clk, rst, txd=eth_l6_rxd, txc=eth_l6_rxc, name='eth_l6_source') - - eth_l6_sink = xgmii_ep.XGMIISink() - eth_l6_sink_logic = eth_l6_sink.create_logic(clk, rst, rxd=eth_l6_txd, rxc=eth_l6_txc, name='eth_l6_sink') - - eth_l7_source = xgmii_ep.XGMIISource() - eth_l7_source_logic = eth_l7_source.create_logic(clk, rst, txd=eth_l7_rxd, txc=eth_l7_rxc, name='eth_l7_source') - - eth_l7_sink = xgmii_ep.XGMIISink() - eth_l7_sink_logic = eth_l7_sink.create_logic(clk, rst, rxd=eth_l7_txd, rxc=eth_l7_txc, name='eth_l7_sink') - - eth_l8_source = xgmii_ep.XGMIISource() - eth_l8_source_logic = eth_l8_source.create_logic(clk, rst, txd=eth_l8_rxd, txc=eth_l8_rxc, name='eth_l8_source') - - eth_l8_sink = xgmii_ep.XGMIISink() - eth_l8_sink_logic = eth_l8_sink.create_logic(clk, rst, rxd=eth_l8_txd, rxc=eth_l8_txc, name='eth_l8_sink') - - eth_l9_source = xgmii_ep.XGMIISource() - eth_l9_source_logic = eth_l9_source.create_logic(clk, rst, txd=eth_l9_rxd, txc=eth_l9_rxc, name='eth_l9_source') - - eth_l9_sink = xgmii_ep.XGMIISink() - eth_l9_sink_logic = eth_l9_sink.create_logic(clk, rst, rxd=eth_l9_txd, rxc=eth_l9_txc, name='eth_l9_sink') - - eth_l10_source = xgmii_ep.XGMIISource() - eth_l10_source_logic = eth_l10_source.create_logic(clk, rst, txd=eth_l10_rxd, txc=eth_l10_rxc, name='eth_l10_source') - - eth_l10_sink = xgmii_ep.XGMIISink() - eth_l10_sink_logic = eth_l10_sink.create_logic(clk, rst, rxd=eth_l10_txd, rxc=eth_l10_txc, name='eth_l10_sink') - - eth_l11_source = xgmii_ep.XGMIISource() - eth_l11_source_logic = eth_l11_source.create_logic(clk, rst, txd=eth_l11_rxd, txc=eth_l11_rxc, name='eth_l11_source') - - eth_l11_sink = xgmii_ep.XGMIISink() - eth_l11_sink_logic = eth_l11_sink.create_logic(clk, rst, rxd=eth_l11_txd, rxc=eth_l11_txc, name='eth_l11_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sw=sw, - jp=jp, - led=led, - - uart_rst=uart_rst, - uart_suspend=uart_suspend, - uart_ri=uart_ri, - uart_dcd=uart_dcd, - uart_dtr=uart_dtr, - uart_dsr=uart_dsr, - uart_txd=uart_txd, - uart_rxd=uart_rxd, - uart_rts=uart_rts, - uart_cts=uart_cts, - - amh_right_mdc=amh_right_mdc, - amh_right_mdio_i=amh_right_mdio_i, - amh_right_mdio_o=amh_right_mdio_o, - amh_right_mdio_t=amh_right_mdio_t, - amh_left_mdc=amh_left_mdc, - amh_left_mdio_i=amh_left_mdio_i, - amh_left_mdio_o=amh_left_mdio_o, - amh_left_mdio_t=amh_left_mdio_t, - - eth_r0_txd=eth_r0_txd, - eth_r0_txc=eth_r0_txc, - eth_r0_rxd=eth_r0_rxd, - eth_r0_rxc=eth_r0_rxc, - eth_r1_txd=eth_r1_txd, - eth_r1_txc=eth_r1_txc, - eth_r1_rxd=eth_r1_rxd, - eth_r1_rxc=eth_r1_rxc, - eth_r2_txd=eth_r2_txd, - eth_r2_txc=eth_r2_txc, - eth_r2_rxd=eth_r2_rxd, - eth_r2_rxc=eth_r2_rxc, - eth_r3_txd=eth_r3_txd, - eth_r3_txc=eth_r3_txc, - eth_r3_rxd=eth_r3_rxd, - eth_r3_rxc=eth_r3_rxc, - eth_r4_txd=eth_r4_txd, - eth_r4_txc=eth_r4_txc, - eth_r4_rxd=eth_r4_rxd, - eth_r4_rxc=eth_r4_rxc, - eth_r5_txd=eth_r5_txd, - eth_r5_txc=eth_r5_txc, - eth_r5_rxd=eth_r5_rxd, - eth_r5_rxc=eth_r5_rxc, - eth_r6_txd=eth_r6_txd, - eth_r6_txc=eth_r6_txc, - eth_r6_rxd=eth_r6_rxd, - eth_r6_rxc=eth_r6_rxc, - eth_r7_txd=eth_r7_txd, - eth_r7_txc=eth_r7_txc, - eth_r7_rxd=eth_r7_rxd, - eth_r7_rxc=eth_r7_rxc, - eth_r8_txd=eth_r8_txd, - eth_r8_txc=eth_r8_txc, - eth_r8_rxd=eth_r8_rxd, - eth_r8_rxc=eth_r8_rxc, - eth_r9_txd=eth_r9_txd, - eth_r9_txc=eth_r9_txc, - eth_r9_rxd=eth_r9_rxd, - eth_r9_rxc=eth_r9_rxc, - eth_r10_txd=eth_r10_txd, - eth_r10_txc=eth_r10_txc, - eth_r10_rxd=eth_r10_rxd, - eth_r10_rxc=eth_r10_rxc, - eth_r11_txd=eth_r11_txd, - eth_r11_txc=eth_r11_txc, - eth_r11_rxd=eth_r11_rxd, - eth_r11_rxc=eth_r11_rxc, - eth_l0_txd=eth_l0_txd, - eth_l0_txc=eth_l0_txc, - eth_l0_rxd=eth_l0_rxd, - eth_l0_rxc=eth_l0_rxc, - eth_l1_txd=eth_l1_txd, - eth_l1_txc=eth_l1_txc, - eth_l1_rxd=eth_l1_rxd, - eth_l1_rxc=eth_l1_rxc, - eth_l2_txd=eth_l2_txd, - eth_l2_txc=eth_l2_txc, - eth_l2_rxd=eth_l2_rxd, - eth_l2_rxc=eth_l2_rxc, - eth_l3_txd=eth_l3_txd, - eth_l3_txc=eth_l3_txc, - eth_l3_rxd=eth_l3_rxd, - eth_l3_rxc=eth_l3_rxc, - eth_l4_txd=eth_l4_txd, - eth_l4_txc=eth_l4_txc, - eth_l4_rxd=eth_l4_rxd, - eth_l4_rxc=eth_l4_rxc, - eth_l5_txd=eth_l5_txd, - eth_l5_txc=eth_l5_txc, - eth_l5_rxd=eth_l5_rxd, - eth_l5_rxc=eth_l5_rxc, - eth_l6_txd=eth_l6_txd, - eth_l6_txc=eth_l6_txc, - eth_l6_rxd=eth_l6_rxd, - eth_l6_rxc=eth_l6_rxc, - eth_l7_txd=eth_l7_txd, - eth_l7_txc=eth_l7_txc, - eth_l7_rxd=eth_l7_rxd, - eth_l7_rxc=eth_l7_rxc, - eth_l8_txd=eth_l8_txd, - eth_l8_txc=eth_l8_txc, - eth_l8_rxd=eth_l8_rxd, - eth_l8_rxc=eth_l8_rxc, - eth_l9_txd=eth_l9_txd, - eth_l9_txc=eth_l9_txc, - eth_l9_rxd=eth_l9_rxd, - eth_l9_rxc=eth_l9_rxc, - eth_l10_txd=eth_l10_txd, - eth_l10_txc=eth_l10_txc, - eth_l10_rxd=eth_l10_rxd, - eth_l10_rxc=eth_l10_rxc, - eth_l11_txd=eth_l11_txd, - eth_l11_txc=eth_l11_txc, - eth_l11_rxd=eth_l11_rxd, - eth_l11_rxc=eth_l11_rxc - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - eth_l0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while eth_l0_sink.empty(): - yield clk.posedge - - rx_frame = eth_l0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - eth_l0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while eth_l0_sink.empty(): - yield clk.posedge - - rx_frame = eth_l0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert eth_l0_source.empty() - assert eth_l0_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/HXT100G/fpga/tb/test_fpga_core.v b/example/HXT100G/fpga/tb/test_fpga_core.v deleted file mode 100644 index 370c25e29..000000000 --- a/example/HXT100G/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,416 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [1:0] sw = 0; -reg [3:0] jp = 0; -reg uart_suspend = 0; -reg uart_dtr = 0; -reg uart_txd = 0; -reg uart_rts = 0; -reg amh_right_mdio_i = 0; -reg amh_left_mdio_i = 0; -reg [63:0] eth_r0_rxd = 0; -reg [7:0] eth_r0_rxc = 0; -reg [63:0] eth_r1_rxd = 0; -reg [7:0] eth_r1_rxc = 0; -reg [63:0] eth_r2_rxd = 0; -reg [7:0] eth_r2_rxc = 0; -reg [63:0] eth_r3_rxd = 0; -reg [7:0] eth_r3_rxc = 0; -reg [63:0] eth_r4_rxd = 0; -reg [7:0] eth_r4_rxc = 0; -reg [63:0] eth_r5_rxd = 0; -reg [7:0] eth_r5_rxc = 0; -reg [63:0] eth_r6_rxd = 0; -reg [7:0] eth_r6_rxc = 0; -reg [63:0] eth_r7_rxd = 0; -reg [7:0] eth_r7_rxc = 0; -reg [63:0] eth_r8_rxd = 0; -reg [7:0] eth_r8_rxc = 0; -reg [63:0] eth_r9_rxd = 0; -reg [7:0] eth_r9_rxc = 0; -reg [63:0] eth_r10_rxd = 0; -reg [7:0] eth_r10_rxc = 0; -reg [63:0] eth_r11_rxd = 0; -reg [7:0] eth_r11_rxc = 0; -reg [63:0] eth_l0_rxd = 0; -reg [7:0] eth_l0_rxc = 0; -reg [63:0] eth_l1_rxd = 0; -reg [7:0] eth_l1_rxc = 0; -reg [63:0] eth_l2_rxd = 0; -reg [7:0] eth_l2_rxc = 0; -reg [63:0] eth_l3_rxd = 0; -reg [7:0] eth_l3_rxc = 0; -reg [63:0] eth_l4_rxd = 0; -reg [7:0] eth_l4_rxc = 0; -reg [63:0] eth_l5_rxd = 0; -reg [7:0] eth_l5_rxc = 0; -reg [63:0] eth_l6_rxd = 0; -reg [7:0] eth_l6_rxc = 0; -reg [63:0] eth_l7_rxd = 0; -reg [7:0] eth_l7_rxc = 0; -reg [63:0] eth_l8_rxd = 0; -reg [7:0] eth_l8_rxc = 0; -reg [63:0] eth_l9_rxd = 0; -reg [7:0] eth_l9_rxc = 0; -reg [63:0] eth_l10_rxd = 0; -reg [7:0] eth_l10_rxc = 0; -reg [63:0] eth_l11_rxd = 0; -reg [7:0] eth_l11_rxc = 0; - -// Outputs -wire [3:0] led; -wire uart_rst; -wire uart_ri; -wire uart_dcd; -wire uart_dsr; -wire uart_rxd; -wire uart_cts; -wire amh_right_mdc; -wire amh_right_mdio_o; -wire amh_right_mdio_t; -wire amh_left_mdc; -wire amh_left_mdio_o; -wire amh_left_mdio_t; -wire [63:0] eth_r0_txd; -wire [7:0] eth_r0_txc; -wire [63:0] eth_r1_txd; -wire [7:0] eth_r1_txc; -wire [63:0] eth_r2_txd; -wire [7:0] eth_r2_txc; -wire [63:0] eth_r3_txd; -wire [7:0] eth_r3_txc; -wire [63:0] eth_r4_txd; -wire [7:0] eth_r4_txc; -wire [63:0] eth_r5_txd; -wire [7:0] eth_r5_txc; -wire [63:0] eth_r6_txd; -wire [7:0] eth_r6_txc; -wire [63:0] eth_r7_txd; -wire [7:0] eth_r7_txc; -wire [63:0] eth_r8_txd; -wire [7:0] eth_r8_txc; -wire [63:0] eth_r9_txd; -wire [7:0] eth_r9_txc; -wire [63:0] eth_r10_txd; -wire [7:0] eth_r10_txc; -wire [63:0] eth_r11_txd; -wire [7:0] eth_r11_txc; -wire [63:0] eth_l0_txd; -wire [7:0] eth_l0_txc; -wire [63:0] eth_l1_txd; -wire [7:0] eth_l1_txc; -wire [63:0] eth_l2_txd; -wire [7:0] eth_l2_txc; -wire [63:0] eth_l3_txd; -wire [7:0] eth_l3_txc; -wire [63:0] eth_l4_txd; -wire [7:0] eth_l4_txc; -wire [63:0] eth_l5_txd; -wire [7:0] eth_l5_txc; -wire [63:0] eth_l6_txd; -wire [7:0] eth_l6_txc; -wire [63:0] eth_l7_txd; -wire [7:0] eth_l7_txc; -wire [63:0] eth_l8_txd; -wire [7:0] eth_l8_txc; -wire [63:0] eth_l9_txd; -wire [7:0] eth_l9_txc; -wire [63:0] eth_l10_txd; -wire [7:0] eth_l10_txc; -wire [63:0] eth_l11_txd; -wire [7:0] eth_l11_txc; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sw, - jp, - uart_suspend, - uart_dtr, - uart_txd, - uart_rts, - amh_right_mdio_i, - amh_left_mdio_i, - eth_r0_rxd, - eth_r0_rxc, - eth_r1_rxd, - eth_r1_rxc, - eth_r2_rxd, - eth_r2_rxc, - eth_r3_rxd, - eth_r3_rxc, - eth_r4_rxd, - eth_r4_rxc, - eth_r5_rxd, - eth_r5_rxc, - eth_r6_rxd, - eth_r6_rxc, - eth_r7_rxd, - eth_r7_rxc, - eth_r8_rxd, - eth_r8_rxc, - eth_r9_rxd, - eth_r9_rxc, - eth_r10_rxd, - eth_r10_rxc, - eth_r11_rxd, - eth_r11_rxc, - eth_l0_rxd, - eth_l0_rxc, - eth_l1_rxd, - eth_l1_rxc, - eth_l2_rxd, - eth_l2_rxc, - eth_l3_rxd, - eth_l3_rxc, - eth_l4_rxd, - eth_l4_rxc, - eth_l5_rxd, - eth_l5_rxc, - eth_l6_rxd, - eth_l6_rxc, - eth_l7_rxd, - eth_l7_rxc, - eth_l8_rxd, - eth_l8_rxc, - eth_l9_rxd, - eth_l9_rxc, - eth_l10_rxd, - eth_l10_rxc, - eth_l11_rxd, - eth_l11_rxc - ); - $to_myhdl( - led, - uart_rst, - uart_ri, - uart_dcd, - uart_dsr, - uart_rxd, - uart_cts, - amh_right_mdc, - amh_right_mdio_o, - amh_right_mdio_t, - amh_left_mdc, - amh_left_mdio_o, - amh_left_mdio_t, - eth_r0_txd, - eth_r0_txc, - eth_r1_txd, - eth_r1_txc, - eth_r2_txd, - eth_r2_txc, - eth_r3_txd, - eth_r3_txc, - eth_r4_txd, - eth_r4_txc, - eth_r5_txd, - eth_r5_txc, - eth_r6_txd, - eth_r6_txc, - eth_r7_txd, - eth_r7_txc, - eth_r8_txd, - eth_r8_txc, - eth_r9_txd, - eth_r9_txc, - eth_r10_txd, - eth_r10_txc, - eth_r11_txd, - eth_r11_txc, - eth_l0_txd, - eth_l0_txc, - eth_l1_txd, - eth_l1_txc, - eth_l2_txd, - eth_l2_txc, - eth_l3_txd, - eth_l3_txc, - eth_l4_txd, - eth_l4_txc, - eth_l5_txd, - eth_l5_txc, - eth_l6_txd, - eth_l6_txc, - eth_l7_txd, - eth_l7_txc, - eth_l8_txd, - eth_l8_txc, - eth_l9_txd, - eth_l9_txc, - eth_l10_txd, - eth_l10_txc, - eth_l11_txd, - eth_l11_txc - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sw(sw), - .jp(jp), - .led(led), - .uart_rst(uart_rst), - .uart_suspend(uart_suspend), - .uart_ri(uart_ri), - .uart_dcd(uart_dcd), - .uart_dtr(uart_dtr), - .uart_dsr(uart_dsr), - .uart_txd(uart_txd), - .uart_rxd(uart_rxd), - .uart_rts(uart_rts), - .uart_cts(uart_cts), - .amh_right_mdc(amh_right_mdc), - .amh_right_mdio_i(amh_right_mdio_i), - .amh_right_mdio_o(amh_right_mdio_o), - .amh_right_mdio_t(amh_right_mdio_t), - .amh_left_mdc(amh_left_mdc), - .amh_left_mdio_i(amh_left_mdio_i), - .amh_left_mdio_o(amh_left_mdio_o), - .amh_left_mdio_t(amh_left_mdio_t), - .eth_r0_txd(eth_r0_txd), - .eth_r0_txc(eth_r0_txc), - .eth_r0_rxd(eth_r0_rxd), - .eth_r0_rxc(eth_r0_rxc), - .eth_r1_txd(eth_r1_txd), - .eth_r1_txc(eth_r1_txc), - .eth_r1_rxd(eth_r1_rxd), - .eth_r1_rxc(eth_r1_rxc), - .eth_r2_txd(eth_r2_txd), - .eth_r2_txc(eth_r2_txc), - .eth_r2_rxd(eth_r2_rxd), - .eth_r2_rxc(eth_r2_rxc), - .eth_r3_txd(eth_r3_txd), - .eth_r3_txc(eth_r3_txc), - .eth_r3_rxd(eth_r3_rxd), - .eth_r3_rxc(eth_r3_rxc), - .eth_r4_txd(eth_r4_txd), - .eth_r4_txc(eth_r4_txc), - .eth_r4_rxd(eth_r4_rxd), - .eth_r4_rxc(eth_r4_rxc), - .eth_r5_txd(eth_r5_txd), - .eth_r5_txc(eth_r5_txc), - .eth_r5_rxd(eth_r5_rxd), - .eth_r5_rxc(eth_r5_rxc), - .eth_r6_txd(eth_r6_txd), - .eth_r6_txc(eth_r6_txc), - .eth_r6_rxd(eth_r6_rxd), - .eth_r6_rxc(eth_r6_rxc), - .eth_r7_txd(eth_r7_txd), - .eth_r7_txc(eth_r7_txc), - .eth_r7_rxd(eth_r7_rxd), - .eth_r7_rxc(eth_r7_rxc), - .eth_r8_txd(eth_r8_txd), - .eth_r8_txc(eth_r8_txc), - .eth_r8_rxd(eth_r8_rxd), - .eth_r8_rxc(eth_r8_rxc), - .eth_r9_txd(eth_r9_txd), - .eth_r9_txc(eth_r9_txc), - .eth_r9_rxd(eth_r9_rxd), - .eth_r9_rxc(eth_r9_rxc), - .eth_r10_txd(eth_r10_txd), - .eth_r10_txc(eth_r10_txc), - .eth_r10_rxd(eth_r10_rxd), - .eth_r10_rxc(eth_r10_rxc), - .eth_r11_txd(eth_r11_txd), - .eth_r11_txc(eth_r11_txc), - .eth_r11_rxd(eth_r11_rxd), - .eth_r11_rxc(eth_r11_rxc), - .eth_l0_txd(eth_l0_txd), - .eth_l0_txc(eth_l0_txc), - .eth_l0_rxd(eth_l0_rxd), - .eth_l0_rxc(eth_l0_rxc), - .eth_l1_txd(eth_l1_txd), - .eth_l1_txc(eth_l1_txc), - .eth_l1_rxd(eth_l1_rxd), - .eth_l1_rxc(eth_l1_rxc), - .eth_l2_txd(eth_l2_txd), - .eth_l2_txc(eth_l2_txc), - .eth_l2_rxd(eth_l2_rxd), - .eth_l2_rxc(eth_l2_rxc), - .eth_l3_txd(eth_l3_txd), - .eth_l3_txc(eth_l3_txc), - .eth_l3_rxd(eth_l3_rxd), - .eth_l3_rxc(eth_l3_rxc), - .eth_l4_txd(eth_l4_txd), - .eth_l4_txc(eth_l4_txc), - .eth_l4_rxd(eth_l4_rxd), - .eth_l4_rxc(eth_l4_rxc), - .eth_l5_txd(eth_l5_txd), - .eth_l5_txc(eth_l5_txc), - .eth_l5_rxd(eth_l5_rxd), - .eth_l5_rxc(eth_l5_rxc), - .eth_l6_txd(eth_l6_txd), - .eth_l6_txc(eth_l6_txc), - .eth_l6_rxd(eth_l6_rxd), - .eth_l6_rxc(eth_l6_rxc), - .eth_l7_txd(eth_l7_txd), - .eth_l7_txc(eth_l7_txc), - .eth_l7_rxd(eth_l7_rxd), - .eth_l7_rxc(eth_l7_rxc), - .eth_l8_txd(eth_l8_txd), - .eth_l8_txc(eth_l8_txc), - .eth_l8_rxd(eth_l8_rxd), - .eth_l8_rxc(eth_l8_rxc), - .eth_l9_txd(eth_l9_txd), - .eth_l9_txc(eth_l9_txc), - .eth_l9_rxd(eth_l9_rxd), - .eth_l9_rxc(eth_l9_rxc), - .eth_l10_txd(eth_l10_txd), - .eth_l10_txc(eth_l10_txc), - .eth_l10_rxd(eth_l10_rxd), - .eth_l10_rxc(eth_l10_rxc), - .eth_l11_txd(eth_l11_txd), - .eth_l11_txc(eth_l11_txc), - .eth_l11_rxd(eth_l11_rxd), - .eth_l11_rxc(eth_l11_rxc) -); - -endmodule diff --git a/example/HXT100G/fpga/tb/udp_ep.py b/example/HXT100G/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/HXT100G/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga/tb/xgmii_ep.py b/example/HXT100G/fpga/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/HXT100G/fpga/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga_cxpt16/tb/axis_ep.py b/example/HXT100G/fpga_cxpt16/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/HXT100G/fpga_cxpt16/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga_cxpt16/tb/eth_ep.py b/example/HXT100G/fpga_cxpt16/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/HXT100G/fpga_cxpt16/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile b/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile new file mode 100644 index 000000000..20ada1fbd --- /dev/null +++ b/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile @@ -0,0 +1,81 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_crosspoint.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py b/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..b0649b146 --- /dev/null +++ b/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,249 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + self.eth_r0_source = XgmiiSource(dut.eth_r0_rxd, dut.eth_r0_rxc, dut.clk, dut.rst) + self.eth_r0_sink = XgmiiSink(dut.eth_r0_txd, dut.eth_r0_txc, dut.clk, dut.rst) + + self.eth_r1_source = XgmiiSource(dut.eth_r1_rxd, dut.eth_r1_rxc, dut.clk, dut.rst) + self.eth_r1_sink = XgmiiSink(dut.eth_r1_txd, dut.eth_r1_txc, dut.clk, dut.rst) + + self.eth_r2_source = XgmiiSource(dut.eth_r2_rxd, dut.eth_r2_rxc, dut.clk, dut.rst) + self.eth_r2_sink = XgmiiSink(dut.eth_r2_txd, dut.eth_r2_txc, dut.clk, dut.rst) + + self.eth_r3_source = XgmiiSource(dut.eth_r3_rxd, dut.eth_r3_rxc, dut.clk, dut.rst) + self.eth_r3_sink = XgmiiSink(dut.eth_r3_txd, dut.eth_r3_txc, dut.clk, dut.rst) + + self.eth_r4_source = XgmiiSource(dut.eth_r4_rxd, dut.eth_r4_rxc, dut.clk, dut.rst) + self.eth_r4_sink = XgmiiSink(dut.eth_r4_txd, dut.eth_r4_txc, dut.clk, dut.rst) + + self.eth_r5_source = XgmiiSource(dut.eth_r5_rxd, dut.eth_r5_rxc, dut.clk, dut.rst) + self.eth_r5_sink = XgmiiSink(dut.eth_r5_txd, dut.eth_r5_txc, dut.clk, dut.rst) + + self.eth_r6_source = XgmiiSource(dut.eth_r6_rxd, dut.eth_r6_rxc, dut.clk, dut.rst) + self.eth_r6_sink = XgmiiSink(dut.eth_r6_txd, dut.eth_r6_txc, dut.clk, dut.rst) + + self.eth_r7_source = XgmiiSource(dut.eth_r7_rxd, dut.eth_r7_rxc, dut.clk, dut.rst) + self.eth_r7_sink = XgmiiSink(dut.eth_r7_txd, dut.eth_r7_txc, dut.clk, dut.rst) + + self.eth_r8_source = XgmiiSource(dut.eth_r8_rxd, dut.eth_r8_rxc, dut.clk, dut.rst) + self.eth_r8_sink = XgmiiSink(dut.eth_r8_txd, dut.eth_r8_txc, dut.clk, dut.rst) + + self.eth_r9_source = XgmiiSource(dut.eth_r9_rxd, dut.eth_r9_rxc, dut.clk, dut.rst) + self.eth_r9_sink = XgmiiSink(dut.eth_r9_txd, dut.eth_r9_txc, dut.clk, dut.rst) + + self.eth_r10_source = XgmiiSource(dut.eth_r10_rxd, dut.eth_r10_rxc, dut.clk, dut.rst) + self.eth_r10_sink = XgmiiSink(dut.eth_r10_txd, dut.eth_r10_txc, dut.clk, dut.rst) + + self.eth_r11_source = XgmiiSource(dut.eth_r11_rxd, dut.eth_r11_rxc, dut.clk, dut.rst) + self.eth_r11_sink = XgmiiSink(dut.eth_r11_txd, dut.eth_r11_txc, dut.clk, dut.rst) + + self.eth_l0_source = XgmiiSource(dut.eth_l0_rxd, dut.eth_l0_rxc, dut.clk, dut.rst) + self.eth_l0_sink = XgmiiSink(dut.eth_l0_txd, dut.eth_l0_txc, dut.clk, dut.rst) + + self.eth_l1_source = XgmiiSource(dut.eth_l1_rxd, dut.eth_l1_rxc, dut.clk, dut.rst) + self.eth_l1_sink = XgmiiSink(dut.eth_l1_txd, dut.eth_l1_txc, dut.clk, dut.rst) + + self.eth_l2_source = XgmiiSource(dut.eth_l2_rxd, dut.eth_l2_rxc, dut.clk, dut.rst) + self.eth_l2_sink = XgmiiSink(dut.eth_l2_txd, dut.eth_l2_txc, dut.clk, dut.rst) + + self.eth_l3_source = XgmiiSource(dut.eth_l3_rxd, dut.eth_l3_rxc, dut.clk, dut.rst) + self.eth_l3_sink = XgmiiSink(dut.eth_l3_txd, dut.eth_l3_txc, dut.clk, dut.rst) + + self.eth_l4_source = XgmiiSource(dut.eth_l4_rxd, dut.eth_l4_rxc, dut.clk, dut.rst) + self.eth_l4_sink = XgmiiSink(dut.eth_l4_txd, dut.eth_l4_txc, dut.clk, dut.rst) + + self.eth_l5_source = XgmiiSource(dut.eth_l5_rxd, dut.eth_l5_rxc, dut.clk, dut.rst) + self.eth_l5_sink = XgmiiSink(dut.eth_l5_txd, dut.eth_l5_txc, dut.clk, dut.rst) + + self.eth_l6_source = XgmiiSource(dut.eth_l6_rxd, dut.eth_l6_rxc, dut.clk, dut.rst) + self.eth_l6_sink = XgmiiSink(dut.eth_l6_txd, dut.eth_l6_txc, dut.clk, dut.rst) + + self.eth_l7_source = XgmiiSource(dut.eth_l7_rxd, dut.eth_l7_rxc, dut.clk, dut.rst) + self.eth_l7_sink = XgmiiSink(dut.eth_l7_txd, dut.eth_l7_txc, dut.clk, dut.rst) + + self.eth_l8_source = XgmiiSource(dut.eth_l8_rxd, dut.eth_l8_rxc, dut.clk, dut.rst) + self.eth_l8_sink = XgmiiSink(dut.eth_l8_txd, dut.eth_l8_txc, dut.clk, dut.rst) + + self.eth_l9_source = XgmiiSource(dut.eth_l9_rxd, dut.eth_l9_rxc, dut.clk, dut.rst) + self.eth_l9_sink = XgmiiSink(dut.eth_l9_txd, dut.eth_l9_txc, dut.clk, dut.rst) + + self.eth_l10_source = XgmiiSource(dut.eth_l10_rxd, dut.eth_l10_rxc, dut.clk, dut.rst) + self.eth_l10_sink = XgmiiSink(dut.eth_l10_txd, dut.eth_l10_txc, dut.clk, dut.rst) + + self.eth_l11_source = XgmiiSource(dut.eth_l11_rxd, dut.eth_l11_rxc, dut.clk, dut.rst) + self.eth_l11_sink = XgmiiSink(dut.eth_l11_txd, dut.eth_l11_txc, dut.clk, dut.rst) + + dut.sw.setimmediatevalue(0) + dut.jp.setimmediatevalue(0) + dut.uart_suspend.setimmediatevalue(0) + dut.uart_dtr.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(0) + dut.uart_rts.setimmediatevalue(0) + dut.amh_right_mdio_i.setimmediatevalue(0) + dut.amh_left_mdio_i.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("send test packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00', type=0x8000) + test_pkt = eth / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.eth_l0_source.send(test_frame) + + rx_frame = await tb.eth_l0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt == test_pkt + + tb.log.info("update configuration") + + payload = bytes(range(15, -1, -1)) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00', type=0x8099) + test_pkt = eth / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.eth_l11_source.send(test_frame) + + await Timer(400, 'ns') + + tb.log.info("send test packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00', type=0x8000) + test_pkt = eth / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.eth_l0_source.send(test_frame) + + rx_frame = await tb.eth_r7_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt == test_pkt + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + os.path.join(axis_rtl_dir, "axis_crosspoint.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py b/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py deleted file mode 100755 index fdaa4dabf..000000000 --- a/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.py +++ /dev/null @@ -1,544 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_crosspoint.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sw = Signal(intbv(0)[2:]) - jp = Signal(intbv(0)[4:]) - uart_suspend = Signal(bool(0)) - uart_dtr = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - amh_right_mdio_i = Signal(bool(0)) - amh_left_mdio_i = Signal(bool(0)) - eth_r0_rxd = Signal(intbv(0)[64:]) - eth_r0_rxc = Signal(intbv(0)[8:]) - eth_r1_rxd = Signal(intbv(0)[64:]) - eth_r1_rxc = Signal(intbv(0)[8:]) - eth_r2_rxd = Signal(intbv(0)[64:]) - eth_r2_rxc = Signal(intbv(0)[8:]) - eth_r3_rxd = Signal(intbv(0)[64:]) - eth_r3_rxc = Signal(intbv(0)[8:]) - eth_r4_rxd = Signal(intbv(0)[64:]) - eth_r4_rxc = Signal(intbv(0)[8:]) - eth_r5_rxd = Signal(intbv(0)[64:]) - eth_r5_rxc = Signal(intbv(0)[8:]) - eth_r6_rxd = Signal(intbv(0)[64:]) - eth_r6_rxc = Signal(intbv(0)[8:]) - eth_r7_rxd = Signal(intbv(0)[64:]) - eth_r7_rxc = Signal(intbv(0)[8:]) - eth_r8_rxd = Signal(intbv(0)[64:]) - eth_r8_rxc = Signal(intbv(0)[8:]) - eth_r9_rxd = Signal(intbv(0)[64:]) - eth_r9_rxc = Signal(intbv(0)[8:]) - eth_r10_rxd = Signal(intbv(0)[64:]) - eth_r10_rxc = Signal(intbv(0)[8:]) - eth_r11_rxd = Signal(intbv(0)[64:]) - eth_r11_rxc = Signal(intbv(0)[8:]) - eth_l0_rxd = Signal(intbv(0)[64:]) - eth_l0_rxc = Signal(intbv(0)[8:]) - eth_l1_rxd = Signal(intbv(0)[64:]) - eth_l1_rxc = Signal(intbv(0)[8:]) - eth_l2_rxd = Signal(intbv(0)[64:]) - eth_l2_rxc = Signal(intbv(0)[8:]) - eth_l3_rxd = Signal(intbv(0)[64:]) - eth_l3_rxc = Signal(intbv(0)[8:]) - eth_l4_rxd = Signal(intbv(0)[64:]) - eth_l4_rxc = Signal(intbv(0)[8:]) - eth_l5_rxd = Signal(intbv(0)[64:]) - eth_l5_rxc = Signal(intbv(0)[8:]) - eth_l6_rxd = Signal(intbv(0)[64:]) - eth_l6_rxc = Signal(intbv(0)[8:]) - eth_l7_rxd = Signal(intbv(0)[64:]) - eth_l7_rxc = Signal(intbv(0)[8:]) - eth_l8_rxd = Signal(intbv(0)[64:]) - eth_l8_rxc = Signal(intbv(0)[8:]) - eth_l9_rxd = Signal(intbv(0)[64:]) - eth_l9_rxc = Signal(intbv(0)[8:]) - eth_l10_rxd = Signal(intbv(0)[64:]) - eth_l10_rxc = Signal(intbv(0)[8:]) - eth_l11_rxd = Signal(intbv(0)[64:]) - eth_l11_rxc = Signal(intbv(0)[8:]) - - # Outputs - led = Signal(intbv(0)[4:]) - uart_rst = Signal(bool(0)) - uart_ri = Signal(bool(0)) - uart_dcd = Signal(bool(0)) - uart_dsr = Signal(bool(0)) - uart_rxd = Signal(bool(1)) - uart_cts = Signal(bool(0)) - amh_right_mdc = Signal(bool(1)) - amh_right_mdio_o = Signal(bool(1)) - amh_right_mdio_t = Signal(bool(1)) - amh_left_mdc = Signal(bool(1)) - amh_left_mdio_o = Signal(bool(1)) - amh_left_mdio_t = Signal(bool(1)) - eth_r0_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r0_txc = Signal(intbv(0xff)[8:]) - eth_r1_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r1_txc = Signal(intbv(0xff)[8:]) - eth_r2_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r2_txc = Signal(intbv(0xff)[8:]) - eth_r3_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r3_txc = Signal(intbv(0xff)[8:]) - eth_r4_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r4_txc = Signal(intbv(0xff)[8:]) - eth_r5_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r5_txc = Signal(intbv(0xff)[8:]) - eth_r6_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r6_txc = Signal(intbv(0xff)[8:]) - eth_r7_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r7_txc = Signal(intbv(0xff)[8:]) - eth_r8_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r8_txc = Signal(intbv(0xff)[8:]) - eth_r9_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r9_txc = Signal(intbv(0xff)[8:]) - eth_r10_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r10_txc = Signal(intbv(0xff)[8:]) - eth_r11_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_r11_txc = Signal(intbv(0xff)[8:]) - eth_l0_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l0_txc = Signal(intbv(0xff)[8:]) - eth_l1_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l1_txc = Signal(intbv(0xff)[8:]) - eth_l2_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l2_txc = Signal(intbv(0xff)[8:]) - eth_l3_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l3_txc = Signal(intbv(0xff)[8:]) - eth_l4_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l4_txc = Signal(intbv(0xff)[8:]) - eth_l5_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l5_txc = Signal(intbv(0xff)[8:]) - eth_l6_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l6_txc = Signal(intbv(0xff)[8:]) - eth_l7_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l7_txc = Signal(intbv(0xff)[8:]) - eth_l8_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l8_txc = Signal(intbv(0xff)[8:]) - eth_l9_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l9_txc = Signal(intbv(0xff)[8:]) - eth_l10_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l10_txc = Signal(intbv(0xff)[8:]) - eth_l11_txd = Signal(intbv(0x0707070707070707)[64:]) - eth_l11_txc = Signal(intbv(0xff)[8:]) - - # sources and sinks - eth_r0_source = xgmii_ep.XGMIISource() - eth_r0_source_logic = eth_r0_source.create_logic(clk, rst, txd=eth_r0_rxd, txc=eth_r0_rxc, name='eth_r0_source') - - eth_r0_sink = xgmii_ep.XGMIISink() - eth_r0_sink_logic = eth_r0_sink.create_logic(clk, rst, rxd=eth_r0_txd, rxc=eth_r0_txc, name='eth_r0_sink') - - eth_r1_source = xgmii_ep.XGMIISource() - eth_r1_source_logic = eth_r1_source.create_logic(clk, rst, txd=eth_r1_rxd, txc=eth_r1_rxc, name='eth_r1_source') - - eth_r1_sink = xgmii_ep.XGMIISink() - eth_r1_sink_logic = eth_r1_sink.create_logic(clk, rst, rxd=eth_r1_txd, rxc=eth_r1_txc, name='eth_r1_sink') - - eth_r2_source = xgmii_ep.XGMIISource() - eth_r2_source_logic = eth_r2_source.create_logic(clk, rst, txd=eth_r2_rxd, txc=eth_r2_rxc, name='eth_r2_source') - - eth_r2_sink = xgmii_ep.XGMIISink() - eth_r2_sink_logic = eth_r2_sink.create_logic(clk, rst, rxd=eth_r2_txd, rxc=eth_r2_txc, name='eth_r2_sink') - - eth_r3_source = xgmii_ep.XGMIISource() - eth_r3_source_logic = eth_r3_source.create_logic(clk, rst, txd=eth_r3_rxd, txc=eth_r3_rxc, name='eth_r3_source') - - eth_r3_sink = xgmii_ep.XGMIISink() - eth_r3_sink_logic = eth_r3_sink.create_logic(clk, rst, rxd=eth_r3_txd, rxc=eth_r3_txc, name='eth_r3_sink') - - eth_r4_source = xgmii_ep.XGMIISource() - eth_r4_source_logic = eth_r4_source.create_logic(clk, rst, txd=eth_r4_rxd, txc=eth_r4_rxc, name='eth_r4_source') - - eth_r4_sink = xgmii_ep.XGMIISink() - eth_r4_sink_logic = eth_r4_sink.create_logic(clk, rst, rxd=eth_r4_txd, rxc=eth_r4_txc, name='eth_r4_sink') - - eth_r5_source = xgmii_ep.XGMIISource() - eth_r5_source_logic = eth_r5_source.create_logic(clk, rst, txd=eth_r5_rxd, txc=eth_r5_rxc, name='eth_r5_source') - - eth_r5_sink = xgmii_ep.XGMIISink() - eth_r5_sink_logic = eth_r5_sink.create_logic(clk, rst, rxd=eth_r5_txd, rxc=eth_r5_txc, name='eth_r5_sink') - - eth_r6_source = xgmii_ep.XGMIISource() - eth_r6_source_logic = eth_r6_source.create_logic(clk, rst, txd=eth_r6_rxd, txc=eth_r6_rxc, name='eth_r6_source') - - eth_r6_sink = xgmii_ep.XGMIISink() - eth_r6_sink_logic = eth_r6_sink.create_logic(clk, rst, rxd=eth_r6_txd, rxc=eth_r6_txc, name='eth_r6_sink') - - eth_r7_source = xgmii_ep.XGMIISource() - eth_r7_source_logic = eth_r7_source.create_logic(clk, rst, txd=eth_r7_rxd, txc=eth_r7_rxc, name='eth_r7_source') - - eth_r7_sink = xgmii_ep.XGMIISink() - eth_r7_sink_logic = eth_r7_sink.create_logic(clk, rst, rxd=eth_r7_txd, rxc=eth_r7_txc, name='eth_r7_sink') - - eth_r8_source = xgmii_ep.XGMIISource() - eth_r8_source_logic = eth_r8_source.create_logic(clk, rst, txd=eth_r8_rxd, txc=eth_r8_rxc, name='eth_r8_source') - - eth_r8_sink = xgmii_ep.XGMIISink() - eth_r8_sink_logic = eth_r8_sink.create_logic(clk, rst, rxd=eth_r8_txd, rxc=eth_r8_txc, name='eth_r8_sink') - - eth_r9_source = xgmii_ep.XGMIISource() - eth_r9_source_logic = eth_r9_source.create_logic(clk, rst, txd=eth_r9_rxd, txc=eth_r9_rxc, name='eth_r9_source') - - eth_r9_sink = xgmii_ep.XGMIISink() - eth_r9_sink_logic = eth_r9_sink.create_logic(clk, rst, rxd=eth_r9_txd, rxc=eth_r9_txc, name='eth_r9_sink') - - eth_r10_source = xgmii_ep.XGMIISource() - eth_r10_source_logic = eth_r10_source.create_logic(clk, rst, txd=eth_r10_rxd, txc=eth_r10_rxc, name='eth_r10_source') - - eth_r10_sink = xgmii_ep.XGMIISink() - eth_r10_sink_logic = eth_r10_sink.create_logic(clk, rst, rxd=eth_r10_txd, rxc=eth_r10_txc, name='eth_r10_sink') - - eth_r11_source = xgmii_ep.XGMIISource() - eth_r11_source_logic = eth_r11_source.create_logic(clk, rst, txd=eth_r11_rxd, txc=eth_r11_rxc, name='eth_r11_source') - - eth_r11_sink = xgmii_ep.XGMIISink() - eth_r11_sink_logic = eth_r11_sink.create_logic(clk, rst, rxd=eth_r11_txd, rxc=eth_r11_txc, name='eth_r11_sink') - - eth_l0_source = xgmii_ep.XGMIISource() - eth_l0_source_logic = eth_l0_source.create_logic(clk, rst, txd=eth_l0_rxd, txc=eth_l0_rxc, name='eth_l0_source') - - eth_l0_sink = xgmii_ep.XGMIISink() - eth_l0_sink_logic = eth_l0_sink.create_logic(clk, rst, rxd=eth_l0_txd, rxc=eth_l0_txc, name='eth_l0_sink') - - eth_l1_source = xgmii_ep.XGMIISource() - eth_l1_source_logic = eth_l1_source.create_logic(clk, rst, txd=eth_l1_rxd, txc=eth_l1_rxc, name='eth_l1_source') - - eth_l1_sink = xgmii_ep.XGMIISink() - eth_l1_sink_logic = eth_l1_sink.create_logic(clk, rst, rxd=eth_l1_txd, rxc=eth_l1_txc, name='eth_l1_sink') - - eth_l2_source = xgmii_ep.XGMIISource() - eth_l2_source_logic = eth_l2_source.create_logic(clk, rst, txd=eth_l2_rxd, txc=eth_l2_rxc, name='eth_l2_source') - - eth_l2_sink = xgmii_ep.XGMIISink() - eth_l2_sink_logic = eth_l2_sink.create_logic(clk, rst, rxd=eth_l2_txd, rxc=eth_l2_txc, name='eth_l2_sink') - - eth_l3_source = xgmii_ep.XGMIISource() - eth_l3_source_logic = eth_l3_source.create_logic(clk, rst, txd=eth_l3_rxd, txc=eth_l3_rxc, name='eth_l3_source') - - eth_l3_sink = xgmii_ep.XGMIISink() - eth_l3_sink_logic = eth_l3_sink.create_logic(clk, rst, rxd=eth_l3_txd, rxc=eth_l3_txc, name='eth_l3_sink') - - eth_l4_source = xgmii_ep.XGMIISource() - eth_l4_source_logic = eth_l4_source.create_logic(clk, rst, txd=eth_l4_rxd, txc=eth_l4_rxc, name='eth_l4_source') - - eth_l4_sink = xgmii_ep.XGMIISink() - eth_l4_sink_logic = eth_l4_sink.create_logic(clk, rst, rxd=eth_l4_txd, rxc=eth_l4_txc, name='eth_l4_sink') - - eth_l5_source = xgmii_ep.XGMIISource() - eth_l5_source_logic = eth_l5_source.create_logic(clk, rst, txd=eth_l5_rxd, txc=eth_l5_rxc, name='eth_l5_source') - - eth_l5_sink = xgmii_ep.XGMIISink() - eth_l5_sink_logic = eth_l5_sink.create_logic(clk, rst, rxd=eth_l5_txd, rxc=eth_l5_txc, name='eth_l5_sink') - - eth_l6_source = xgmii_ep.XGMIISource() - eth_l6_source_logic = eth_l6_source.create_logic(clk, rst, txd=eth_l6_rxd, txc=eth_l6_rxc, name='eth_l6_source') - - eth_l6_sink = xgmii_ep.XGMIISink() - eth_l6_sink_logic = eth_l6_sink.create_logic(clk, rst, rxd=eth_l6_txd, rxc=eth_l6_txc, name='eth_l6_sink') - - eth_l7_source = xgmii_ep.XGMIISource() - eth_l7_source_logic = eth_l7_source.create_logic(clk, rst, txd=eth_l7_rxd, txc=eth_l7_rxc, name='eth_l7_source') - - eth_l7_sink = xgmii_ep.XGMIISink() - eth_l7_sink_logic = eth_l7_sink.create_logic(clk, rst, rxd=eth_l7_txd, rxc=eth_l7_txc, name='eth_l7_sink') - - eth_l8_source = xgmii_ep.XGMIISource() - eth_l8_source_logic = eth_l8_source.create_logic(clk, rst, txd=eth_l8_rxd, txc=eth_l8_rxc, name='eth_l8_source') - - eth_l8_sink = xgmii_ep.XGMIISink() - eth_l8_sink_logic = eth_l8_sink.create_logic(clk, rst, rxd=eth_l8_txd, rxc=eth_l8_txc, name='eth_l8_sink') - - eth_l9_source = xgmii_ep.XGMIISource() - eth_l9_source_logic = eth_l9_source.create_logic(clk, rst, txd=eth_l9_rxd, txc=eth_l9_rxc, name='eth_l9_source') - - eth_l9_sink = xgmii_ep.XGMIISink() - eth_l9_sink_logic = eth_l9_sink.create_logic(clk, rst, rxd=eth_l9_txd, rxc=eth_l9_txc, name='eth_l9_sink') - - eth_l10_source = xgmii_ep.XGMIISource() - eth_l10_source_logic = eth_l10_source.create_logic(clk, rst, txd=eth_l10_rxd, txc=eth_l10_rxc, name='eth_l10_source') - - eth_l10_sink = xgmii_ep.XGMIISink() - eth_l10_sink_logic = eth_l10_sink.create_logic(clk, rst, rxd=eth_l10_txd, rxc=eth_l10_txc, name='eth_l10_sink') - - eth_l11_source = xgmii_ep.XGMIISource() - eth_l11_source_logic = eth_l11_source.create_logic(clk, rst, txd=eth_l11_rxd, txc=eth_l11_rxc, name='eth_l11_source') - - eth_l11_sink = xgmii_ep.XGMIISink() - eth_l11_sink_logic = eth_l11_sink.create_logic(clk, rst, rxd=eth_l11_txd, rxc=eth_l11_txc, name='eth_l11_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sw=sw, - jp=jp, - led=led, - - uart_rst=uart_rst, - uart_suspend=uart_suspend, - uart_ri=uart_ri, - uart_dcd=uart_dcd, - uart_dtr=uart_dtr, - uart_dsr=uart_dsr, - uart_txd=uart_txd, - uart_rxd=uart_rxd, - uart_rts=uart_rts, - uart_cts=uart_cts, - - amh_right_mdc=amh_right_mdc, - amh_right_mdio_i=amh_right_mdio_i, - amh_right_mdio_o=amh_right_mdio_o, - amh_right_mdio_t=amh_right_mdio_t, - amh_left_mdc=amh_left_mdc, - amh_left_mdio_i=amh_left_mdio_i, - amh_left_mdio_o=amh_left_mdio_o, - amh_left_mdio_t=amh_left_mdio_t, - - eth_r0_txd=eth_r0_txd, - eth_r0_txc=eth_r0_txc, - eth_r0_rxd=eth_r0_rxd, - eth_r0_rxc=eth_r0_rxc, - eth_r1_txd=eth_r1_txd, - eth_r1_txc=eth_r1_txc, - eth_r1_rxd=eth_r1_rxd, - eth_r1_rxc=eth_r1_rxc, - eth_r2_txd=eth_r2_txd, - eth_r2_txc=eth_r2_txc, - eth_r2_rxd=eth_r2_rxd, - eth_r2_rxc=eth_r2_rxc, - eth_r3_txd=eth_r3_txd, - eth_r3_txc=eth_r3_txc, - eth_r3_rxd=eth_r3_rxd, - eth_r3_rxc=eth_r3_rxc, - eth_r4_txd=eth_r4_txd, - eth_r4_txc=eth_r4_txc, - eth_r4_rxd=eth_r4_rxd, - eth_r4_rxc=eth_r4_rxc, - eth_r5_txd=eth_r5_txd, - eth_r5_txc=eth_r5_txc, - eth_r5_rxd=eth_r5_rxd, - eth_r5_rxc=eth_r5_rxc, - eth_r6_txd=eth_r6_txd, - eth_r6_txc=eth_r6_txc, - eth_r6_rxd=eth_r6_rxd, - eth_r6_rxc=eth_r6_rxc, - eth_r7_txd=eth_r7_txd, - eth_r7_txc=eth_r7_txc, - eth_r7_rxd=eth_r7_rxd, - eth_r7_rxc=eth_r7_rxc, - eth_r8_txd=eth_r8_txd, - eth_r8_txc=eth_r8_txc, - eth_r8_rxd=eth_r8_rxd, - eth_r8_rxc=eth_r8_rxc, - eth_r9_txd=eth_r9_txd, - eth_r9_txc=eth_r9_txc, - eth_r9_rxd=eth_r9_rxd, - eth_r9_rxc=eth_r9_rxc, - eth_r10_txd=eth_r10_txd, - eth_r10_txc=eth_r10_txc, - eth_r10_rxd=eth_r10_rxd, - eth_r10_rxc=eth_r10_rxc, - eth_r11_txd=eth_r11_txd, - eth_r11_txc=eth_r11_txc, - eth_r11_rxd=eth_r11_rxd, - eth_r11_rxc=eth_r11_rxc, - eth_l0_txd=eth_l0_txd, - eth_l0_txc=eth_l0_txc, - eth_l0_rxd=eth_l0_rxd, - eth_l0_rxc=eth_l0_rxc, - eth_l1_txd=eth_l1_txd, - eth_l1_txc=eth_l1_txc, - eth_l1_rxd=eth_l1_rxd, - eth_l1_rxc=eth_l1_rxc, - eth_l2_txd=eth_l2_txd, - eth_l2_txc=eth_l2_txc, - eth_l2_rxd=eth_l2_rxd, - eth_l2_rxc=eth_l2_rxc, - eth_l3_txd=eth_l3_txd, - eth_l3_txc=eth_l3_txc, - eth_l3_rxd=eth_l3_rxd, - eth_l3_rxc=eth_l3_rxc, - eth_l4_txd=eth_l4_txd, - eth_l4_txc=eth_l4_txc, - eth_l4_rxd=eth_l4_rxd, - eth_l4_rxc=eth_l4_rxc, - eth_l5_txd=eth_l5_txd, - eth_l5_txc=eth_l5_txc, - eth_l5_rxd=eth_l5_rxd, - eth_l5_rxc=eth_l5_rxc, - eth_l6_txd=eth_l6_txd, - eth_l6_txc=eth_l6_txc, - eth_l6_rxd=eth_l6_rxd, - eth_l6_rxc=eth_l6_rxc, - eth_l7_txd=eth_l7_txd, - eth_l7_txc=eth_l7_txc, - eth_l7_rxd=eth_l7_rxd, - eth_l7_rxc=eth_l7_rxc, - eth_l8_txd=eth_l8_txd, - eth_l8_txc=eth_l8_txc, - eth_l8_rxd=eth_l8_rxd, - eth_l8_rxc=eth_l8_rxc, - eth_l9_txd=eth_l9_txd, - eth_l9_txc=eth_l9_txc, - eth_l9_rxd=eth_l9_rxd, - eth_l9_rxc=eth_l9_rxc, - eth_l10_txd=eth_l10_txd, - eth_l10_txc=eth_l10_txc, - eth_l10_rxd=eth_l10_rxd, - eth_l10_rxc=eth_l10_rxc, - eth_l11_txd=eth_l11_txd, - eth_l11_txc=eth_l11_txc, - eth_l11_rxd=eth_l11_rxd, - eth_l11_rxc=eth_l11_rxc - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - test_frame = eth_ep.EthFrame() - test_frame.eth_dest_mac = 0xDAD1D2D3D4D5 - test_frame.eth_src_mac = 0x5A5152535455 - test_frame.eth_type = 0x8000 - test_frame.payload = bytearray(range(46)) - test_frame.update_fcs() - - axis_frame = test_frame.build_axis_fcs() - - xgmii_frame = xgmii_ep.XGMIIFrame(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+bytearray(axis_frame)) - - eth_l0_source.send(xgmii_frame) - - while eth_l0_sink.empty(): - yield clk.posedge - - check_frame = eth_l0_sink.recv() - - assert check_frame == xgmii_frame - - test_frame = eth_ep.EthFrame() - test_frame.eth_dest_mac = 0xDAD1D2D3D4D5 - test_frame.eth_src_mac = 0x5A5152535455 - test_frame.eth_type = 0x8099 - test_frame.payload = bytearray(range(15,-1,-1)) + bytearray([0]*(46-16)) - test_frame.update_fcs() - - axis_frame = test_frame.build_axis_fcs() - - xgmii_frame = xgmii_ep.XGMIIFrame(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+bytearray(axis_frame)) - - eth_l11_source.send(xgmii_frame) - - yield delay(400) - - test_frame = eth_ep.EthFrame() - test_frame.eth_dest_mac = 0xDAD1D2D3D4D5 - test_frame.eth_src_mac = 0x5A5152535455 - test_frame.eth_type = 0x8000 - test_frame.payload = bytearray(range(46)) - test_frame.update_fcs() - - axis_frame = test_frame.build_axis_fcs() - - xgmii_frame = xgmii_ep.XGMIIFrame(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+bytearray(axis_frame)) - - eth_l0_source.send(xgmii_frame) - - while eth_r7_sink.empty(): - yield clk.posedge - - check_frame = eth_r7_sink.recv() - - assert check_frame == xgmii_frame - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.v b/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.v deleted file mode 100644 index 370c25e29..000000000 --- a/example/HXT100G/fpga_cxpt16/tb/test_fpga_core.v +++ /dev/null @@ -1,416 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [1:0] sw = 0; -reg [3:0] jp = 0; -reg uart_suspend = 0; -reg uart_dtr = 0; -reg uart_txd = 0; -reg uart_rts = 0; -reg amh_right_mdio_i = 0; -reg amh_left_mdio_i = 0; -reg [63:0] eth_r0_rxd = 0; -reg [7:0] eth_r0_rxc = 0; -reg [63:0] eth_r1_rxd = 0; -reg [7:0] eth_r1_rxc = 0; -reg [63:0] eth_r2_rxd = 0; -reg [7:0] eth_r2_rxc = 0; -reg [63:0] eth_r3_rxd = 0; -reg [7:0] eth_r3_rxc = 0; -reg [63:0] eth_r4_rxd = 0; -reg [7:0] eth_r4_rxc = 0; -reg [63:0] eth_r5_rxd = 0; -reg [7:0] eth_r5_rxc = 0; -reg [63:0] eth_r6_rxd = 0; -reg [7:0] eth_r6_rxc = 0; -reg [63:0] eth_r7_rxd = 0; -reg [7:0] eth_r7_rxc = 0; -reg [63:0] eth_r8_rxd = 0; -reg [7:0] eth_r8_rxc = 0; -reg [63:0] eth_r9_rxd = 0; -reg [7:0] eth_r9_rxc = 0; -reg [63:0] eth_r10_rxd = 0; -reg [7:0] eth_r10_rxc = 0; -reg [63:0] eth_r11_rxd = 0; -reg [7:0] eth_r11_rxc = 0; -reg [63:0] eth_l0_rxd = 0; -reg [7:0] eth_l0_rxc = 0; -reg [63:0] eth_l1_rxd = 0; -reg [7:0] eth_l1_rxc = 0; -reg [63:0] eth_l2_rxd = 0; -reg [7:0] eth_l2_rxc = 0; -reg [63:0] eth_l3_rxd = 0; -reg [7:0] eth_l3_rxc = 0; -reg [63:0] eth_l4_rxd = 0; -reg [7:0] eth_l4_rxc = 0; -reg [63:0] eth_l5_rxd = 0; -reg [7:0] eth_l5_rxc = 0; -reg [63:0] eth_l6_rxd = 0; -reg [7:0] eth_l6_rxc = 0; -reg [63:0] eth_l7_rxd = 0; -reg [7:0] eth_l7_rxc = 0; -reg [63:0] eth_l8_rxd = 0; -reg [7:0] eth_l8_rxc = 0; -reg [63:0] eth_l9_rxd = 0; -reg [7:0] eth_l9_rxc = 0; -reg [63:0] eth_l10_rxd = 0; -reg [7:0] eth_l10_rxc = 0; -reg [63:0] eth_l11_rxd = 0; -reg [7:0] eth_l11_rxc = 0; - -// Outputs -wire [3:0] led; -wire uart_rst; -wire uart_ri; -wire uart_dcd; -wire uart_dsr; -wire uart_rxd; -wire uart_cts; -wire amh_right_mdc; -wire amh_right_mdio_o; -wire amh_right_mdio_t; -wire amh_left_mdc; -wire amh_left_mdio_o; -wire amh_left_mdio_t; -wire [63:0] eth_r0_txd; -wire [7:0] eth_r0_txc; -wire [63:0] eth_r1_txd; -wire [7:0] eth_r1_txc; -wire [63:0] eth_r2_txd; -wire [7:0] eth_r2_txc; -wire [63:0] eth_r3_txd; -wire [7:0] eth_r3_txc; -wire [63:0] eth_r4_txd; -wire [7:0] eth_r4_txc; -wire [63:0] eth_r5_txd; -wire [7:0] eth_r5_txc; -wire [63:0] eth_r6_txd; -wire [7:0] eth_r6_txc; -wire [63:0] eth_r7_txd; -wire [7:0] eth_r7_txc; -wire [63:0] eth_r8_txd; -wire [7:0] eth_r8_txc; -wire [63:0] eth_r9_txd; -wire [7:0] eth_r9_txc; -wire [63:0] eth_r10_txd; -wire [7:0] eth_r10_txc; -wire [63:0] eth_r11_txd; -wire [7:0] eth_r11_txc; -wire [63:0] eth_l0_txd; -wire [7:0] eth_l0_txc; -wire [63:0] eth_l1_txd; -wire [7:0] eth_l1_txc; -wire [63:0] eth_l2_txd; -wire [7:0] eth_l2_txc; -wire [63:0] eth_l3_txd; -wire [7:0] eth_l3_txc; -wire [63:0] eth_l4_txd; -wire [7:0] eth_l4_txc; -wire [63:0] eth_l5_txd; -wire [7:0] eth_l5_txc; -wire [63:0] eth_l6_txd; -wire [7:0] eth_l6_txc; -wire [63:0] eth_l7_txd; -wire [7:0] eth_l7_txc; -wire [63:0] eth_l8_txd; -wire [7:0] eth_l8_txc; -wire [63:0] eth_l9_txd; -wire [7:0] eth_l9_txc; -wire [63:0] eth_l10_txd; -wire [7:0] eth_l10_txc; -wire [63:0] eth_l11_txd; -wire [7:0] eth_l11_txc; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sw, - jp, - uart_suspend, - uart_dtr, - uart_txd, - uart_rts, - amh_right_mdio_i, - amh_left_mdio_i, - eth_r0_rxd, - eth_r0_rxc, - eth_r1_rxd, - eth_r1_rxc, - eth_r2_rxd, - eth_r2_rxc, - eth_r3_rxd, - eth_r3_rxc, - eth_r4_rxd, - eth_r4_rxc, - eth_r5_rxd, - eth_r5_rxc, - eth_r6_rxd, - eth_r6_rxc, - eth_r7_rxd, - eth_r7_rxc, - eth_r8_rxd, - eth_r8_rxc, - eth_r9_rxd, - eth_r9_rxc, - eth_r10_rxd, - eth_r10_rxc, - eth_r11_rxd, - eth_r11_rxc, - eth_l0_rxd, - eth_l0_rxc, - eth_l1_rxd, - eth_l1_rxc, - eth_l2_rxd, - eth_l2_rxc, - eth_l3_rxd, - eth_l3_rxc, - eth_l4_rxd, - eth_l4_rxc, - eth_l5_rxd, - eth_l5_rxc, - eth_l6_rxd, - eth_l6_rxc, - eth_l7_rxd, - eth_l7_rxc, - eth_l8_rxd, - eth_l8_rxc, - eth_l9_rxd, - eth_l9_rxc, - eth_l10_rxd, - eth_l10_rxc, - eth_l11_rxd, - eth_l11_rxc - ); - $to_myhdl( - led, - uart_rst, - uart_ri, - uart_dcd, - uart_dsr, - uart_rxd, - uart_cts, - amh_right_mdc, - amh_right_mdio_o, - amh_right_mdio_t, - amh_left_mdc, - amh_left_mdio_o, - amh_left_mdio_t, - eth_r0_txd, - eth_r0_txc, - eth_r1_txd, - eth_r1_txc, - eth_r2_txd, - eth_r2_txc, - eth_r3_txd, - eth_r3_txc, - eth_r4_txd, - eth_r4_txc, - eth_r5_txd, - eth_r5_txc, - eth_r6_txd, - eth_r6_txc, - eth_r7_txd, - eth_r7_txc, - eth_r8_txd, - eth_r8_txc, - eth_r9_txd, - eth_r9_txc, - eth_r10_txd, - eth_r10_txc, - eth_r11_txd, - eth_r11_txc, - eth_l0_txd, - eth_l0_txc, - eth_l1_txd, - eth_l1_txc, - eth_l2_txd, - eth_l2_txc, - eth_l3_txd, - eth_l3_txc, - eth_l4_txd, - eth_l4_txc, - eth_l5_txd, - eth_l5_txc, - eth_l6_txd, - eth_l6_txc, - eth_l7_txd, - eth_l7_txc, - eth_l8_txd, - eth_l8_txc, - eth_l9_txd, - eth_l9_txc, - eth_l10_txd, - eth_l10_txc, - eth_l11_txd, - eth_l11_txc - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sw(sw), - .jp(jp), - .led(led), - .uart_rst(uart_rst), - .uart_suspend(uart_suspend), - .uart_ri(uart_ri), - .uart_dcd(uart_dcd), - .uart_dtr(uart_dtr), - .uart_dsr(uart_dsr), - .uart_txd(uart_txd), - .uart_rxd(uart_rxd), - .uart_rts(uart_rts), - .uart_cts(uart_cts), - .amh_right_mdc(amh_right_mdc), - .amh_right_mdio_i(amh_right_mdio_i), - .amh_right_mdio_o(amh_right_mdio_o), - .amh_right_mdio_t(amh_right_mdio_t), - .amh_left_mdc(amh_left_mdc), - .amh_left_mdio_i(amh_left_mdio_i), - .amh_left_mdio_o(amh_left_mdio_o), - .amh_left_mdio_t(amh_left_mdio_t), - .eth_r0_txd(eth_r0_txd), - .eth_r0_txc(eth_r0_txc), - .eth_r0_rxd(eth_r0_rxd), - .eth_r0_rxc(eth_r0_rxc), - .eth_r1_txd(eth_r1_txd), - .eth_r1_txc(eth_r1_txc), - .eth_r1_rxd(eth_r1_rxd), - .eth_r1_rxc(eth_r1_rxc), - .eth_r2_txd(eth_r2_txd), - .eth_r2_txc(eth_r2_txc), - .eth_r2_rxd(eth_r2_rxd), - .eth_r2_rxc(eth_r2_rxc), - .eth_r3_txd(eth_r3_txd), - .eth_r3_txc(eth_r3_txc), - .eth_r3_rxd(eth_r3_rxd), - .eth_r3_rxc(eth_r3_rxc), - .eth_r4_txd(eth_r4_txd), - .eth_r4_txc(eth_r4_txc), - .eth_r4_rxd(eth_r4_rxd), - .eth_r4_rxc(eth_r4_rxc), - .eth_r5_txd(eth_r5_txd), - .eth_r5_txc(eth_r5_txc), - .eth_r5_rxd(eth_r5_rxd), - .eth_r5_rxc(eth_r5_rxc), - .eth_r6_txd(eth_r6_txd), - .eth_r6_txc(eth_r6_txc), - .eth_r6_rxd(eth_r6_rxd), - .eth_r6_rxc(eth_r6_rxc), - .eth_r7_txd(eth_r7_txd), - .eth_r7_txc(eth_r7_txc), - .eth_r7_rxd(eth_r7_rxd), - .eth_r7_rxc(eth_r7_rxc), - .eth_r8_txd(eth_r8_txd), - .eth_r8_txc(eth_r8_txc), - .eth_r8_rxd(eth_r8_rxd), - .eth_r8_rxc(eth_r8_rxc), - .eth_r9_txd(eth_r9_txd), - .eth_r9_txc(eth_r9_txc), - .eth_r9_rxd(eth_r9_rxd), - .eth_r9_rxc(eth_r9_rxc), - .eth_r10_txd(eth_r10_txd), - .eth_r10_txc(eth_r10_txc), - .eth_r10_rxd(eth_r10_rxd), - .eth_r10_rxc(eth_r10_rxc), - .eth_r11_txd(eth_r11_txd), - .eth_r11_txc(eth_r11_txc), - .eth_r11_rxd(eth_r11_rxd), - .eth_r11_rxc(eth_r11_rxc), - .eth_l0_txd(eth_l0_txd), - .eth_l0_txc(eth_l0_txc), - .eth_l0_rxd(eth_l0_rxd), - .eth_l0_rxc(eth_l0_rxc), - .eth_l1_txd(eth_l1_txd), - .eth_l1_txc(eth_l1_txc), - .eth_l1_rxd(eth_l1_rxd), - .eth_l1_rxc(eth_l1_rxc), - .eth_l2_txd(eth_l2_txd), - .eth_l2_txc(eth_l2_txc), - .eth_l2_rxd(eth_l2_rxd), - .eth_l2_rxc(eth_l2_rxc), - .eth_l3_txd(eth_l3_txd), - .eth_l3_txc(eth_l3_txc), - .eth_l3_rxd(eth_l3_rxd), - .eth_l3_rxc(eth_l3_rxc), - .eth_l4_txd(eth_l4_txd), - .eth_l4_txc(eth_l4_txc), - .eth_l4_rxd(eth_l4_rxd), - .eth_l4_rxc(eth_l4_rxc), - .eth_l5_txd(eth_l5_txd), - .eth_l5_txc(eth_l5_txc), - .eth_l5_rxd(eth_l5_rxd), - .eth_l5_rxc(eth_l5_rxc), - .eth_l6_txd(eth_l6_txd), - .eth_l6_txc(eth_l6_txc), - .eth_l6_rxd(eth_l6_rxd), - .eth_l6_rxc(eth_l6_rxc), - .eth_l7_txd(eth_l7_txd), - .eth_l7_txc(eth_l7_txc), - .eth_l7_rxd(eth_l7_rxd), - .eth_l7_rxc(eth_l7_rxc), - .eth_l8_txd(eth_l8_txd), - .eth_l8_txc(eth_l8_txc), - .eth_l8_rxd(eth_l8_rxd), - .eth_l8_rxc(eth_l8_rxc), - .eth_l9_txd(eth_l9_txd), - .eth_l9_txc(eth_l9_txc), - .eth_l9_rxd(eth_l9_rxd), - .eth_l9_rxc(eth_l9_rxc), - .eth_l10_txd(eth_l10_txd), - .eth_l10_txc(eth_l10_txc), - .eth_l10_rxd(eth_l10_rxd), - .eth_l10_rxc(eth_l10_rxc), - .eth_l11_txd(eth_l11_txd), - .eth_l11_txc(eth_l11_txc), - .eth_l11_rxd(eth_l11_rxd), - .eth_l11_rxc(eth_l11_rxc) -); - -endmodule diff --git a/example/HXT100G/fpga_cxpt16/tb/xgmii_ep.py b/example/HXT100G/fpga_cxpt16/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/HXT100G/fpga_cxpt16/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/KC705/fpga_gmii/tb/arp_ep.py b/example/KC705/fpga_gmii/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/KC705/fpga_gmii/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/KC705/fpga_gmii/tb/axis_ep.py b/example/KC705/fpga_gmii/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/KC705/fpga_gmii/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/KC705/fpga_gmii/tb/eth_ep.py b/example/KC705/fpga_gmii/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/KC705/fpga_gmii/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/KC705/fpga_gmii/tb/fpga_core/Makefile b/example/KC705/fpga_gmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..9cef21260 --- /dev/null +++ b/example/KC705/fpga_gmii/tb/fpga_core/Makefile @@ -0,0 +1,105 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_out.v +VERILOG_SOURCES += ../../lib/eth/rtl/gmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_gmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_gmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py b/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..c34cd29c3 --- /dev/null +++ b/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,217 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + # Ethernet + self.gmii_phy = GmiiPhy(dut.phy_txd, dut.phy_tx_er, dut.phy_tx_en, dut.phy_tx_clk, dut.phy_gtx_clk, + dut.phy_rxd, dut.phy_rx_er, dut.phy_rx_dv, dut.phy_rx_clk, speed=speed) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(1) + dut.uart_cts.setimmediatevalue(1) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_in.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_out.v"), + os.path.join(eth_rtl_dir, "gmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_gmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_gmii.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/KC705/fpga_gmii/tb/gmii_ep.py b/example/KC705/fpga_gmii/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/KC705/fpga_gmii/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/KC705/fpga_gmii/tb/ip_ep.py b/example/KC705/fpga_gmii/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/KC705/fpga_gmii/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/KC705/fpga_gmii/tb/test_fpga_core.py b/example/KC705/fpga_gmii/tb/test_fpga_core.py deleted file mode 100755 index 2eb05f154..000000000 --- a/example/KC705/fpga_gmii/tb/test_fpga_core.py +++ /dev/null @@ -1,316 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_sdr_in.v") -srcs.append("../lib/eth/rtl/ssio_sdr_out.v") -srcs.append("../lib/eth/rtl/gmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_gmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_gmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[4:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[8:]) - phy_rx_dv = Signal(bool(0)) - phy_rx_er = Signal(bool(0)) - phy_tx_clk = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - phy_gtx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[8:]) - phy_tx_en = Signal(bool(0)) - phy_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # sources and sinks - mii_select = Signal(bool(0)) - - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_en=phy_rx_dv, - tx_er=phy_rx_er, - mii_select=mii_select, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_dv=phy_tx_en, - rx_er=phy_tx_er, - mii_select=mii_select, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_dv=phy_rx_dv, - phy_rx_er=phy_rx_er, - phy_gtx_clk=phy_gtx_clk, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_en=phy_tx_en, - phy_tx_er=phy_tx_er, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - phy_tx_clk.next = not phy_tx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/KC705/fpga_gmii/tb/test_fpga_core.v b/example/KC705/fpga_gmii/tb/test_fpga_core.v deleted file mode 100644 index bbe377cba..000000000 --- a/example/KC705/fpga_gmii/tb/test_fpga_core.v +++ /dev/null @@ -1,134 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [3:0] sw = 0; -reg phy_rx_clk = 0; -reg [7:0] phy_rxd = 0; -reg phy_rx_dv = 0; -reg phy_rx_er = 0; -reg phy_tx_clk = 0; -reg phy_int_n = 1; -reg uart_rxd = 0; -reg uart_cts = 0; - -// Outputs -wire [7:0] led; -wire phy_gtx_clk; -wire [7:0] phy_txd; -wire phy_tx_en; -wire phy_tx_er; -wire phy_reset_n; -wire uart_txd; -wire uart_rts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_dv, - phy_rx_er, - phy_tx_clk, - phy_int_n, - uart_rxd, - uart_cts - ); - $to_myhdl( - led, - phy_gtx_clk, - phy_txd, - phy_tx_en, - phy_tx_er, - phy_reset_n, - uart_txd, - uart_rts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_dv(phy_rx_dv), - .phy_rx_er(phy_rx_er), - .phy_gtx_clk(phy_gtx_clk), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_en(phy_tx_en), - .phy_tx_er(phy_tx_er), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/KC705/fpga_gmii/tb/udp_ep.py b/example/KC705/fpga_gmii/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/KC705/fpga_gmii/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_gmii/tb/arp_ep.py b/example/ML605/fpga_gmii/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ML605/fpga_gmii/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_gmii/tb/axis_ep.py b/example/ML605/fpga_gmii/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ML605/fpga_gmii/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_gmii/tb/eth_ep.py b/example/ML605/fpga_gmii/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ML605/fpga_gmii/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_gmii/tb/fpga_core/Makefile b/example/ML605/fpga_gmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..9cef21260 --- /dev/null +++ b/example/ML605/fpga_gmii/tb/fpga_core/Makefile @@ -0,0 +1,105 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_sdr_out.v +VERILOG_SOURCES += ../../lib/eth/rtl/gmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_gmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_gmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..0ab4ab030 --- /dev/null +++ b/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,217 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk_125mhz, 8, units="ns").start()) + + # Ethernet + self.gmii_phy = GmiiPhy(dut.phy_txd, dut.phy_tx_er, dut.phy_tx_en, dut.phy_tx_clk, dut.phy_gtx_clk, + dut.phy_rxd, dut.phy_rx_er, dut.phy_rx_dv, dut.phy_rx_clk, speed=speed) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(1) + dut.uart_rts.setimmediatevalue(1) + + async def init(self): + + self.dut.rst_125mhz.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk_125mhz) + + self.dut.rst_125mhz <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk_125mhz) + + self.dut.rst_125mhz <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk_125mhz) + await RisingEdge(dut.clk_125mhz) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_in.v"), + os.path.join(eth_rtl_dir, "ssio_sdr_out.v"), + os.path.join(eth_rtl_dir, "gmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_gmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_gmii.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ML605/fpga_gmii/tb/gmii_ep.py b/example/ML605/fpga_gmii/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/ML605/fpga_gmii/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_gmii/tb/ip_ep.py b/example/ML605/fpga_gmii/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ML605/fpga_gmii/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_gmii/tb/test_fpga_core.py b/example/ML605/fpga_gmii/tb/test_fpga_core.py deleted file mode 100755 index bffc91271..000000000 --- a/example/ML605/fpga_gmii/tb/test_fpga_core.py +++ /dev/null @@ -1,330 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/iddr.v") -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_sdr_in.v") -srcs.append("../lib/eth/rtl/ssio_sdr_out.v") -srcs.append("../lib/eth/rtl/gmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_gmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_gmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - clk_125mhz = Signal(bool(0)) - rst_125mhz = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[8:]) - phy_rx_dv = Signal(bool(0)) - phy_rx_er = Signal(bool(0)) - phy_tx_clk = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # Outputs - ledu = Signal(bool(0)) - ledl = Signal(bool(0)) - ledd = Signal(bool(0)) - ledr = Signal(bool(0)) - ledc = Signal(bool(0)) - led = Signal(intbv(0)[8:]) - phy_gtx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[8:]) - phy_tx_en = Signal(bool(0)) - phy_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # sources and sinks - mii_select = Signal(bool(0)) - - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_en=phy_rx_dv, - tx_er=phy_rx_er, - mii_select=mii_select, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_dv=phy_tx_en, - rx_er=phy_tx_er, - mii_select=mii_select, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk_125mhz=clk_125mhz, - rst_125mhz=rst_125mhz, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - ledu=ledu, - ledl=ledl, - ledd=ledd, - ledr=ledr, - ledc=ledc, - led=led, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_dv=phy_rx_dv, - phy_rx_er=phy_rx_er, - phy_gtx_clk=phy_gtx_clk, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_en=phy_tx_en, - phy_tx_er=phy_tx_er, - phy_reset_n=phy_reset_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - clk_125mhz.next = not clk_125mhz - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - phy_tx_clk.next = not phy_tx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - rst_125mhz.next = 1 - yield clk.posedge - rst.next = 0 - rst_125mhz.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ML605/fpga_gmii/tb/test_fpga_core.v b/example/ML605/fpga_gmii/tb/test_fpga_core.v deleted file mode 100644 index b237ed924..000000000 --- a/example/ML605/fpga_gmii/tb/test_fpga_core.v +++ /dev/null @@ -1,146 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk_125mhz = 0; -reg rst_125mhz = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg phy_rx_clk = 0; -reg [7:0] phy_rxd = 0; -reg phy_rx_dv = 0; -reg phy_rx_er = 0; -reg phy_tx_clk = 0; -reg uart_txd = 0; -reg uart_rts = 0; - -// Outputs -wire ledu; -wire ledl; -wire ledd; -wire ledr; -wire ledc; -wire [7:0] led; -wire phy_gtx_clk; -wire [7:0] phy_txd; -wire phy_tx_en; -wire phy_tx_er; -wire phy_reset_n; -wire uart_rxd; -wire uart_cts; - -initial begin - // myhdl integration - $from_myhdl( - clk_125mhz, - rst_125mhz, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_dv, - phy_rx_er, - phy_tx_clk, - uart_txd, - uart_rts - ); - $to_myhdl( - ledu, - ledl, - ledd, - ledr, - ledc, - led, - phy_gtx_clk, - phy_txd, - phy_tx_en, - phy_tx_er, - phy_reset_n, - uart_rxd, - uart_cts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk_125mhz(clk_125mhz), - .rst_125mhz(rst_125mhz), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .ledu(ledu), - .ledl(ledl), - .ledd(ledd), - .ledr(ledr), - .ledc(ledc), - .led(led), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_dv(phy_rx_dv), - .phy_rx_er(phy_rx_er), - .phy_gtx_clk(phy_gtx_clk), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_en(phy_tx_en), - .phy_tx_er(phy_tx_er), - .phy_reset_n(phy_reset_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/ML605/fpga_gmii/tb/udp_ep.py b/example/ML605/fpga_gmii/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ML605/fpga_gmii/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/arp_ep.py b/example/ML605/fpga_rgmii/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ML605/fpga_rgmii/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/axis_ep.py b/example/ML605/fpga_rgmii/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ML605/fpga_rgmii/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/eth_ep.py b/example/ML605/fpga_rgmii/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ML605/fpga_rgmii/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/fpga_core/Makefile b/example/ML605/fpga_rgmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..cf1af8fc7 --- /dev/null +++ b/example/ML605/fpga_rgmii/tb/fpga_core/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..bbd7de706 --- /dev/null +++ b/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,229 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import GmiiFrame, RgmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.rgmii_phy = RgmiiPhy(dut.phy_txd, dut.phy_tx_ctl, dut.phy_tx_clk, + dut.phy_rxd, dut.phy_rx_ctl, dut.phy_rx_clk, speed=speed) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(1) + dut.uart_rts.setimmediatevalue(1) + + dut.clk_125mhz.setimmediatevalue(0) + dut.clk90_125mhz.setimmediatevalue(0) + + cocotb.fork(self._run_clk_125mhz()) + + async def init(self): + + self.dut.rst_125mhz.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk_125mhz) + + self.dut.rst_125mhz <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk_125mhz) + + self.dut.rst_125mhz <= 0 + + async def _run_clk_125mhz(self): + t = Timer(2, 'ns') + while True: + self.dut.clk_125mhz <= 1 + await t + self.dut.clk90_125mhz <= 1 + await t + self.dut.clk_125mhz <= 0 + await t + self.dut.clk90_125mhz <= 0 + await t + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.rgmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.rgmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk_125mhz) + await RisingEdge(dut.clk_125mhz) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_ddr_in.v"), + os.path.join(eth_rtl_dir, "rgmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ML605/fpga_rgmii/tb/gmii_ep.py b/example/ML605/fpga_rgmii/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/ML605/fpga_rgmii/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/ip_ep.py b/example/ML605/fpga_rgmii/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ML605/fpga_rgmii/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/rgmii_ep.py b/example/ML605/fpga_rgmii/tb/rgmii_ep.py deleted file mode 120000 index 986c56280..000000000 --- a/example/ML605/fpga_rgmii/tb/rgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/rgmii_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_rgmii/tb/test_fpga_core.py b/example/ML605/fpga_rgmii/tb/test_fpga_core.py deleted file mode 100755 index c0eaf984c..000000000 --- a/example/ML605/fpga_rgmii/tb/test_fpga_core.py +++ /dev/null @@ -1,330 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import rgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/iddr.v") -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_ddr_in.v") -srcs.append("../lib/eth/rtl/ssio_ddr_out.v") -srcs.append("../lib/eth/rtl/rgmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - clk_125mhz = Signal(bool(0)) - clk90_125mhz = Signal(bool(0)) - rst_125mhz = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[4:]) - phy_rx_ctl = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # Outputs - ledu = Signal(bool(0)) - ledl = Signal(bool(0)) - ledd = Signal(bool(0)) - ledr = Signal(bool(0)) - ledc = Signal(bool(0)) - led = Signal(intbv(0)[8:]) - phy_tx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[4:]) - phy_tx_ctl = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # sources and sinks - mii_select = Signal(bool(0)) - - rgmii_source = rgmii_ep.RGMIISource() - - rgmii_source_logic = rgmii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_ctl=phy_rx_ctl, - mii_select=mii_select, - name='rgmii_source' - ) - - rgmii_sink = rgmii_ep.RGMIISink() - - rgmii_sink_logic = rgmii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_ctl=phy_tx_ctl, - mii_select=mii_select, - name='rgmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk_125mhz=clk_125mhz, - clk90_125mhz=clk90_125mhz, - rst_125mhz=rst_125mhz, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - ledu=ledu, - ledl=ledl, - ledd=ledd, - ledr=ledr, - ledc=ledc, - led=led, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_ctl=phy_rx_ctl, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_ctl=phy_tx_ctl, - phy_reset_n=phy_reset_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - clk_125mhz.next = not clk_125mhz - - @instance - def clkgen2(): - yield delay(4+2) - while True: - clk90_125mhz.next = not clk90_125mhz - yield delay(4) - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - rst_125mhz.next = 1 - yield clk.posedge - rst.next = 0 - rst_125mhz.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - rgmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while rgmii_sink.empty(): - yield clk.posedge - - rx_frame = rgmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - rgmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while rgmii_sink.empty(): - yield clk.posedge - - rx_frame = rgmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert rgmii_source.empty() - assert rgmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ML605/fpga_rgmii/tb/test_fpga_core.v b/example/ML605/fpga_rgmii/tb/test_fpga_core.v deleted file mode 100644 index a2c412486..000000000 --- a/example/ML605/fpga_rgmii/tb/test_fpga_core.v +++ /dev/null @@ -1,140 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk_125mhz = 0; -reg clk90_125mhz = 0; -reg rst_125mhz = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg phy_rx_clk = 0; -reg [3:0] phy_rxd = 0; -reg phy_rx_ctl = 0; -reg uart_txd = 0; -reg uart_rts = 0; - -// Outputs -wire ledu; -wire ledl; -wire ledd; -wire ledr; -wire ledc; -wire [7:0] led; -wire phy_tx_clk; -wire [3:0] phy_txd; -wire phy_tx_ctl; -wire phy_reset_n; -wire uart_rxd; -wire uart_cts; - -initial begin - // myhdl integration - $from_myhdl( - clk_125mhz, - clk90_125mhz, - rst_125mhz, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_ctl, - uart_txd, - uart_rts - ); - $to_myhdl( - ledu, - ledl, - ledd, - ledr, - ledc, - led, - phy_tx_clk, - phy_txd, - phy_tx_ctl, - phy_reset_n, - uart_rxd, - uart_cts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk_125mhz(clk_125mhz), - .clk90_125mhz(clk90_125mhz), - .rst_125mhz(rst_125mhz), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .ledu(ledu), - .ledl(ledl), - .ledd(ledd), - .ledr(ledr), - .ledc(ledc), - .led(led), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_ctl(phy_rx_ctl), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_ctl(phy_tx_ctl), - .phy_reset_n(phy_reset_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/ML605/fpga_rgmii/tb/udp_ep.py b/example/ML605/fpga_rgmii/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ML605/fpga_rgmii/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_sgmii/tb/arp_ep.py b/example/ML605/fpga_sgmii/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ML605/fpga_sgmii/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_sgmii/tb/axis_ep.py b/example/ML605/fpga_sgmii/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ML605/fpga_sgmii/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_sgmii/tb/eth_ep.py b/example/ML605/fpga_sgmii/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ML605/fpga_sgmii/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_sgmii/tb/fpga_core/Makefile b/example/ML605/fpga_sgmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aafe627c --- /dev/null +++ b/example/ML605/fpga_sgmii/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..1c6bc2301 --- /dev/null +++ b/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,218 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink + + +class TB: + def __init__(self, dut, speed=1000): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk_125mhz, 6.4, units="ns").start()) + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(0) + dut.uart_rts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst_125mhz.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk_125mhz) + + self.dut.rst_125mhz <= 1 + self.dut.phy_gmii_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk_125mhz) + + self.dut.rst_125mhz <= 0 + self.dut.phy_gmii_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk_125mhz) + await RisingEdge(dut.clk_125mhz) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ML605/fpga_sgmii/tb/gmii_ep.py b/example/ML605/fpga_sgmii/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/ML605/fpga_sgmii/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_sgmii/tb/ip_ep.py b/example/ML605/fpga_sgmii/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ML605/fpga_sgmii/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ML605/fpga_sgmii/tb/test_fpga_core.py b/example/ML605/fpga_sgmii/tb/test_fpga_core.py deleted file mode 100755 index 202243041..000000000 --- a/example/ML605/fpga_sgmii/tb/test_fpga_core.py +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - clk_125mhz = Signal(bool(0)) - rst_125mhz = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - phy_gmii_clk = Signal(bool(0)) - phy_gmii_rst = Signal(bool(0)) - phy_gmii_clk_en = Signal(bool(0)) - phy_gmii_rxd = Signal(intbv(0)[8:]) - phy_gmii_rx_dv = Signal(bool(0)) - phy_gmii_rx_er = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # Outputs - ledu = Signal(bool(0)) - ledl = Signal(bool(0)) - ledd = Signal(bool(0)) - ledr = Signal(bool(0)) - ledc = Signal(bool(0)) - led = Signal(intbv(0)[8:]) - phy_gmii_txd = Signal(intbv(0)[8:]) - phy_gmii_tx_en = Signal(bool(0)) - phy_gmii_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # sources and sinks - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_gmii_clk, - phy_gmii_rst, - txd=phy_gmii_rxd, - tx_en=phy_gmii_rx_dv, - tx_er=phy_gmii_rx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_gmii_clk, - phy_gmii_rst, - rxd=phy_gmii_txd, - rx_dv=phy_gmii_tx_en, - rx_er=phy_gmii_tx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk_125mhz=clk_125mhz, - rst_125mhz=rst_125mhz, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - ledu=ledu, - ledl=ledl, - ledd=ledd, - ledr=ledr, - ledc=ledc, - led=led, - - phy_gmii_clk=phy_gmii_clk, - phy_gmii_rst=phy_gmii_rst, - phy_gmii_clk_en=phy_gmii_clk_en, - phy_gmii_rxd=phy_gmii_rxd, - phy_gmii_rx_dv=phy_gmii_rx_dv, - phy_gmii_rx_er=phy_gmii_rx_er, - phy_gmii_txd=phy_gmii_txd, - phy_gmii_tx_en=phy_gmii_tx_en, - phy_gmii_tx_er=phy_gmii_tx_er, - phy_reset_n=phy_reset_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - clk_125mhz.next = not clk_125mhz - phy_gmii_clk.next = not phy_gmii_clk - - clk_enable_rate = Signal(int(0)) - clk_enable_div = Signal(int(0)) - - @always(clk.posedge) - def clk_enable_gen(): - if clk_enable_div.next > 0: - phy_gmii_clk_en.next = 0 - clk_enable_div.next = clk_enable_div - 1 - else: - phy_gmii_clk_en.next = 1 - clk_enable_div.next = clk_enable_rate - 1 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - rst_125mhz.next = 1 - phy_gmii_rst.next = 1 - yield clk.posedge - rst.next = 0 - rst_125mhz.next = 0 - phy_gmii_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ML605/fpga_sgmii/tb/test_fpga_core.v b/example/ML605/fpga_sgmii/tb/test_fpga_core.v deleted file mode 100644 index 5b0f8d538..000000000 --- a/example/ML605/fpga_sgmii/tb/test_fpga_core.v +++ /dev/null @@ -1,143 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk_125mhz = 0; -reg rst_125mhz = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg phy_gmii_clk = 0; -reg phy_gmii_rst = 0; -reg phy_gmii_clk_en = 0; -reg [7:0] phy_gmii_rxd = 0; -reg phy_gmii_rx_dv = 0; -reg phy_gmii_rx_er = 0; -reg uart_txd = 0; -reg uart_rts = 0; - -// Outputs -wire ledu; -wire ledl; -wire ledd; -wire ledr; -wire ledc; -wire [7:0] led; -wire [7:0] phy_gmii_txd; -wire phy_gmii_tx_en; -wire phy_gmii_tx_er; -wire phy_reset_n; -wire uart_rxd; -wire uart_cts; - -initial begin - // myhdl integration - $from_myhdl( - clk_125mhz, - rst_125mhz, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_gmii_clk, - phy_gmii_rst, - phy_gmii_clk_en, - phy_gmii_rxd, - phy_gmii_rx_dv, - phy_gmii_rx_er, - uart_txd, - uart_rts - ); - $to_myhdl( - ledu, - ledl, - ledd, - ledr, - ledc, - led, - phy_gmii_txd, - phy_gmii_tx_en, - phy_gmii_tx_er, - phy_reset_n, - uart_rxd, - uart_cts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk_125mhz(clk_125mhz), - .rst_125mhz(rst_125mhz), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .ledu(ledu), - .ledl(ledl), - .ledd(ledd), - .ledr(ledr), - .ledc(ledc), - .led(led), - .phy_gmii_clk(phy_gmii_clk), - .phy_gmii_rst(phy_gmii_rst), - .phy_gmii_clk_en(phy_gmii_clk_en), - .phy_gmii_rxd(phy_gmii_rxd), - .phy_gmii_rx_dv(phy_gmii_rx_dv), - .phy_gmii_rx_er(phy_gmii_rx_er), - .phy_gmii_txd(phy_gmii_txd), - .phy_gmii_tx_en(phy_gmii_tx_en), - .phy_gmii_tx_er(phy_gmii_tx_er), - .phy_reset_n(phy_reset_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/ML605/fpga_sgmii/tb/udp_ep.py b/example/ML605/fpga_sgmii/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ML605/fpga_sgmii/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/NetFPGA_SUME/fpga/tb/arp_ep.py b/example/NetFPGA_SUME/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/NetFPGA_SUME/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/NetFPGA_SUME/fpga/tb/axis_ep.py b/example/NetFPGA_SUME/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/NetFPGA_SUME/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/NetFPGA_SUME/fpga/tb/eth_ep.py b/example/NetFPGA_SUME/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/NetFPGA_SUME/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile b/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py b/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..4c494afd0 --- /dev/null +++ b/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,245 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.sfp_1_rx_clk, 6.4, units="ns").start()) + self.sfp_1_source = XgmiiSource(dut.sfp_1_rxd, dut.sfp_1_rxc, dut.sfp_1_rx_clk, dut.sfp_1_rx_rst) + cocotb.fork(Clock(dut.sfp_1_tx_clk, 6.4, units="ns").start()) + self.sfp_1_sink = XgmiiSink(dut.sfp_1_txd, dut.sfp_1_txc, dut.sfp_1_tx_clk, dut.sfp_1_tx_rst) + + cocotb.fork(Clock(dut.sfp_2_rx_clk, 6.4, units="ns").start()) + self.sfp_2_source = XgmiiSource(dut.sfp_2_rxd, dut.sfp_2_rxc, dut.sfp_2_rx_clk, dut.sfp_2_rx_rst) + cocotb.fork(Clock(dut.sfp_2_tx_clk, 6.4, units="ns").start()) + self.sfp_2_sink = XgmiiSink(dut.sfp_2_txd, dut.sfp_2_txc, dut.sfp_2_tx_clk, dut.sfp_2_tx_rst) + + cocotb.fork(Clock(dut.sfp_3_rx_clk, 6.4, units="ns").start()) + self.sfp_3_source = XgmiiSource(dut.sfp_3_rxd, dut.sfp_3_rxc, dut.sfp_3_rx_clk, dut.sfp_3_rx_rst) + cocotb.fork(Clock(dut.sfp_3_tx_clk, 6.4, units="ns").start()) + self.sfp_3_sink = XgmiiSink(dut.sfp_3_txd, dut.sfp_3_txc, dut.sfp_3_tx_clk, dut.sfp_3_tx_rst) + + cocotb.fork(Clock(dut.sfp_4_rx_clk, 6.4, units="ns").start()) + self.sfp_4_source = XgmiiSource(dut.sfp_4_rxd, dut.sfp_4_rxc, dut.sfp_4_rx_clk, dut.sfp_4_rx_rst) + cocotb.fork(Clock(dut.sfp_4_tx_clk, 6.4, units="ns").start()) + self.sfp_4_sink = XgmiiSink(dut.sfp_4_txd, dut.sfp_4_txc, dut.sfp_4_tx_clk, dut.sfp_4_tx_rst) + + dut.btn.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.sfp_1_rx_rst.setimmediatevalue(0) + self.dut.sfp_1_tx_rst.setimmediatevalue(0) + self.dut.sfp_2_rx_rst.setimmediatevalue(0) + self.dut.sfp_2_tx_rst.setimmediatevalue(0) + self.dut.sfp_3_rx_rst.setimmediatevalue(0) + self.dut.sfp_3_tx_rst.setimmediatevalue(0) + self.dut.sfp_4_rx_rst.setimmediatevalue(0) + self.dut.sfp_4_tx_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.sfp_1_rx_rst <= 1 + self.dut.sfp_1_tx_rst <= 1 + self.dut.sfp_2_rx_rst <= 1 + self.dut.sfp_2_tx_rst <= 1 + self.dut.sfp_3_rx_rst <= 1 + self.dut.sfp_3_tx_rst <= 1 + self.dut.sfp_4_rx_rst <= 1 + self.dut.sfp_4_tx_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.sfp_1_rx_rst <= 0 + self.dut.sfp_1_tx_rst <= 0 + self.dut.sfp_2_rx_rst <= 0 + self.dut.sfp_2_tx_rst <= 0 + self.dut.sfp_3_rx_rst <= 0 + self.dut.sfp_3_tx_rst <= 0 + self.dut.sfp_4_rx_rst <= 0 + self.dut.sfp_4_tx_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.sfp_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.sfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.sfp_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.sfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/NetFPGA_SUME/fpga/tb/ip_ep.py b/example/NetFPGA_SUME/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/NetFPGA_SUME/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/NetFPGA_SUME/fpga/tb/test_fpga_core.py b/example/NetFPGA_SUME/fpga/tb/test_fpga_core.py deleted file mode 100755 index 0654346a2..000000000 --- a/example/NetFPGA_SUME/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,350 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btn = Signal(intbv(0)[2:]) - sfp_1_tx_clk = Signal(bool(0)) - sfp_1_tx_rst = Signal(bool(0)) - sfp_1_rx_clk = Signal(bool(0)) - sfp_1_rx_rst = Signal(bool(0)) - sfp_1_rxd = Signal(intbv(0)[64:]) - sfp_1_rxc = Signal(intbv(0)[8:]) - sfp_2_tx_clk = Signal(bool(0)) - sfp_2_tx_rst = Signal(bool(0)) - sfp_2_rx_clk = Signal(bool(0)) - sfp_2_rx_rst = Signal(bool(0)) - sfp_2_rxd = Signal(intbv(0)[64:]) - sfp_2_rxc = Signal(intbv(0)[8:]) - sfp_3_tx_clk = Signal(bool(0)) - sfp_3_tx_rst = Signal(bool(0)) - sfp_3_rx_clk = Signal(bool(0)) - sfp_3_rx_rst = Signal(bool(0)) - sfp_3_rxd = Signal(intbv(0)[64:]) - sfp_3_rxc = Signal(intbv(0)[8:]) - sfp_4_tx_clk = Signal(bool(0)) - sfp_4_tx_rst = Signal(bool(0)) - sfp_4_rx_clk = Signal(bool(0)) - sfp_4_rx_rst = Signal(bool(0)) - sfp_4_rxd = Signal(intbv(0)[64:]) - sfp_4_rxc = Signal(intbv(0)[8:]) - - # Outputs - sfp_1_led = Signal(intbv(0)[2:]) - sfp_2_led = Signal(intbv(0)[2:]) - sfp_3_led = Signal(intbv(0)[2:]) - sfp_4_led = Signal(intbv(0)[2:]) - led = Signal(intbv(0)[2:]) - sfp_1_txd = Signal(intbv(0)[64:]) - sfp_1_txc = Signal(intbv(0)[8:]) - sfp_2_txd = Signal(intbv(0)[64:]) - sfp_2_txc = Signal(intbv(0)[8:]) - sfp_3_txd = Signal(intbv(0)[64:]) - sfp_3_txc = Signal(intbv(0)[8:]) - sfp_4_txd = Signal(intbv(0)[64:]) - sfp_4_txc = Signal(intbv(0)[8:]) - - # sources and sinks - sfp_1_source = xgmii_ep.XGMIISource() - sfp_1_source_logic = sfp_1_source.create_logic(sfp_1_rx_clk, sfp_1_rx_rst, txd=sfp_1_rxd, txc=sfp_1_rxc, name='sfp_1_source') - - sfp_1_sink = xgmii_ep.XGMIISink() - sfp_1_sink_logic = sfp_1_sink.create_logic(sfp_1_tx_clk, sfp_1_tx_rst, rxd=sfp_1_txd, rxc=sfp_1_txc, name='sfp_1_sink') - - sfp_2_source = xgmii_ep.XGMIISource() - sfp_2_source_logic = sfp_2_source.create_logic(sfp_2_rx_clk, sfp_2_rx_rst, txd=sfp_2_rxd, txc=sfp_2_rxc, name='sfp_2_source') - - sfp_2_sink = xgmii_ep.XGMIISink() - sfp_2_sink_logic = sfp_2_sink.create_logic(sfp_2_tx_clk, sfp_2_tx_rst, rxd=sfp_2_txd, rxc=sfp_2_txc, name='sfp_2_sink') - - sfp_3_source = xgmii_ep.XGMIISource() - sfp_3_source_logic = sfp_3_source.create_logic(sfp_3_rx_clk, sfp_3_rx_rst, txd=sfp_3_rxd, txc=sfp_3_rxc, name='sfp_3_source') - - sfp_3_sink = xgmii_ep.XGMIISink() - sfp_3_sink_logic = sfp_3_sink.create_logic(sfp_3_tx_clk, sfp_3_tx_rst, rxd=sfp_3_txd, rxc=sfp_3_txc, name='sfp_3_sink') - - sfp_4_source = xgmii_ep.XGMIISource() - sfp_4_source_logic = sfp_4_source.create_logic(sfp_4_rx_clk, sfp_4_rx_rst, txd=sfp_4_rxd, txc=sfp_4_rxc, name='sfp_4_source') - - sfp_4_sink = xgmii_ep.XGMIISink() - sfp_4_sink_logic = sfp_4_sink.create_logic(sfp_4_tx_clk, sfp_4_tx_rst, rxd=sfp_4_txd, rxc=sfp_4_txc, name='sfp_4_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btn=btn, - sfp_1_led=sfp_1_led, - sfp_2_led=sfp_2_led, - sfp_3_led=sfp_3_led, - sfp_4_led=sfp_4_led, - led=led, - - sfp_1_tx_clk=sfp_1_tx_clk, - sfp_1_tx_rst=sfp_1_tx_rst, - sfp_1_txd=sfp_1_txd, - sfp_1_txc=sfp_1_txc, - sfp_1_rx_clk=sfp_1_rx_clk, - sfp_1_rx_rst=sfp_1_rx_rst, - sfp_1_rxd=sfp_1_rxd, - sfp_1_rxc=sfp_1_rxc, - sfp_2_tx_clk=sfp_2_tx_clk, - sfp_2_tx_rst=sfp_2_tx_rst, - sfp_2_txd=sfp_2_txd, - sfp_2_txc=sfp_2_txc, - sfp_2_rx_clk=sfp_2_rx_clk, - sfp_2_rx_rst=sfp_2_rx_rst, - sfp_2_rxd=sfp_2_rxd, - sfp_2_rxc=sfp_2_rxc, - sfp_3_tx_clk=sfp_3_tx_clk, - sfp_3_tx_rst=sfp_3_tx_rst, - sfp_3_txd=sfp_3_txd, - sfp_3_txc=sfp_3_txc, - sfp_3_rx_clk=sfp_3_rx_clk, - sfp_3_rx_rst=sfp_3_rx_rst, - sfp_3_rxd=sfp_3_rxd, - sfp_3_rxc=sfp_3_rxc, - sfp_4_tx_clk=sfp_4_tx_clk, - sfp_4_tx_rst=sfp_4_tx_rst, - sfp_4_txd=sfp_4_txd, - sfp_4_txc=sfp_4_txc, - sfp_4_rx_clk=sfp_4_rx_clk, - sfp_4_rx_rst=sfp_4_rx_rst, - sfp_4_rxd=sfp_4_rxd, - sfp_4_rxc=sfp_4_rxc - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @always_comb - def clk_logic(): - sfp_1_tx_clk.next = clk - sfp_1_tx_rst.next = rst - sfp_1_rx_clk.next = clk - sfp_1_rx_rst.next = rst - sfp_2_tx_clk.next = clk - sfp_2_tx_rst.next = rst - sfp_2_rx_clk.next = clk - sfp_2_rx_rst.next = rst - sfp_3_tx_clk.next = clk - sfp_3_tx_rst.next = rst - sfp_3_rx_clk.next = clk - sfp_3_rx_rst.next = rst - sfp_4_tx_clk.next = clk - sfp_4_tx_rst.next = rst - sfp_4_rx_clk.next = clk - sfp_4_rx_rst.next = rst - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - sfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while sfp_1_sink.empty(): - yield clk.posedge - - rx_frame = sfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - sfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while sfp_1_sink.empty(): - yield clk.posedge - - rx_frame = sfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert sfp_1_source.empty() - assert sfp_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/NetFPGA_SUME/fpga/tb/test_fpga_core.v b/example/NetFPGA_SUME/fpga/tb/test_fpga_core.v deleted file mode 100644 index be4ea203a..000000000 --- a/example/NetFPGA_SUME/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,179 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [1:0] btn = 0; -reg sfp_1_tx_clk = 0; -reg sfp_1_tx_rst = 0; -reg sfp_1_rx_clk = 0; -reg sfp_1_rx_rst = 0; -reg [63:0] sfp_1_rxd = 0; -reg [7:0] sfp_1_rxc = 0; -reg sfp_2_tx_clk = 0; -reg sfp_2_tx_rst = 0; -reg sfp_2_rx_clk = 0; -reg sfp_2_rx_rst = 0; -reg [63:0] sfp_2_rxd = 0; -reg [7:0] sfp_2_rxc = 0; -reg sfp_3_tx_clk = 0; -reg sfp_3_tx_rst = 0; -reg sfp_3_rx_clk = 0; -reg sfp_3_rx_rst = 0; -reg [63:0] sfp_3_rxd = 0; -reg [7:0] sfp_3_rxc = 0; -reg sfp_4_tx_clk = 0; -reg sfp_4_tx_rst = 0; -reg sfp_4_rx_clk = 0; -reg sfp_4_rx_rst = 0; -reg [63:0] sfp_4_rxd = 0; -reg [7:0] sfp_4_rxc = 0; - -// Outputs -wire [1:0] sfp_1_led; -wire [1:0] sfp_2_led; -wire [1:0] sfp_3_led; -wire [1:0] sfp_4_led; -wire [1:0] led; -wire [63:0] sfp_1_txd; -wire [7:0] sfp_1_txc; -wire [63:0] sfp_2_txd; -wire [7:0] sfp_2_txc; -wire [63:0] sfp_3_txd; -wire [7:0] sfp_3_txc; -wire [63:0] sfp_4_txd; -wire [7:0] sfp_4_txc; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btn, - sfp_1_tx_clk, - sfp_1_tx_rst, - sfp_1_rx_clk, - sfp_1_rx_rst, - sfp_1_rxd, - sfp_1_rxc, - sfp_2_tx_clk, - sfp_2_tx_rst, - sfp_2_rx_clk, - sfp_2_rx_rst, - sfp_2_rxd, - sfp_2_rxc, - sfp_3_tx_clk, - sfp_3_tx_rst, - sfp_3_rx_clk, - sfp_3_rx_rst, - sfp_3_rxd, - sfp_3_rxc, - sfp_4_tx_clk, - sfp_4_tx_rst, - sfp_4_rx_clk, - sfp_4_rx_rst, - sfp_4_rxd, - sfp_4_rxc - ); - $to_myhdl( - sfp_1_led, - sfp_2_led, - sfp_3_led, - sfp_4_led, - led, - sfp_1_txd, - sfp_1_txc, - sfp_2_txd, - sfp_2_txc, - sfp_3_txd, - sfp_3_txc, - sfp_4_txd, - sfp_4_txc - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btn(btn), - .sfp_1_led(sfp_1_led), - .sfp_2_led(sfp_2_led), - .sfp_3_led(sfp_3_led), - .sfp_4_led(sfp_4_led), - .led(led), - .sfp_1_tx_clk(sfp_1_tx_clk), - .sfp_1_tx_rst(sfp_1_tx_rst), - .sfp_1_txd(sfp_1_txd), - .sfp_1_txc(sfp_1_txc), - .sfp_1_rx_clk(sfp_1_rx_clk), - .sfp_1_rx_rst(sfp_1_rx_rst), - .sfp_1_rxd(sfp_1_rxd), - .sfp_1_rxc(sfp_1_rxc), - .sfp_2_tx_clk(sfp_2_tx_clk), - .sfp_2_tx_rst(sfp_2_tx_rst), - .sfp_2_txd(sfp_2_txd), - .sfp_2_txc(sfp_2_txc), - .sfp_2_rx_clk(sfp_2_rx_clk), - .sfp_2_rx_rst(sfp_2_rx_rst), - .sfp_2_rxd(sfp_2_rxd), - .sfp_2_rxc(sfp_2_rxc), - .sfp_3_tx_clk(sfp_3_tx_clk), - .sfp_3_tx_rst(sfp_3_tx_rst), - .sfp_3_txd(sfp_3_txd), - .sfp_3_txc(sfp_3_txc), - .sfp_3_rx_clk(sfp_3_rx_clk), - .sfp_3_rx_rst(sfp_3_rx_rst), - .sfp_3_rxd(sfp_3_rxd), - .sfp_3_rxc(sfp_3_rxc), - .sfp_4_tx_clk(sfp_4_tx_clk), - .sfp_4_tx_rst(sfp_4_tx_rst), - .sfp_4_txd(sfp_4_txd), - .sfp_4_txc(sfp_4_txc), - .sfp_4_rx_clk(sfp_4_rx_clk), - .sfp_4_rx_rst(sfp_4_rx_rst), - .sfp_4_rxd(sfp_4_rxd), - .sfp_4_rxc(sfp_4_rxc) -); - -endmodule diff --git a/example/NetFPGA_SUME/fpga/tb/udp_ep.py b/example/NetFPGA_SUME/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/NetFPGA_SUME/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/NetFPGA_SUME/fpga/tb/xgmii_ep.py b/example/NetFPGA_SUME/fpga/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/NetFPGA_SUME/fpga/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/arp_ep.py b/example/NexysVideo/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/NexysVideo/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/axis_ep.py b/example/NexysVideo/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/NexysVideo/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/eth_ep.py b/example/NexysVideo/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/NexysVideo/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/fpga_core/Makefile b/example/NexysVideo/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..cf1af8fc7 --- /dev/null +++ b/example/NexysVideo/fpga/tb/fpga_core/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py b/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..15cd8a67c --- /dev/null +++ b/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,231 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import GmiiFrame, RgmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.rgmii_phy = RgmiiPhy(dut.phy_txd, dut.phy_tx_ctl, dut.phy_tx_clk, + dut.phy_rxd, dut.phy_rx_ctl, dut.phy_rx_clk, speed=speed) + + dut.phy_int_n.setimmediatevalue(1) + dut.phy_pme_n.setimmediatevalue(1) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(1) + + dut.clk.setimmediatevalue(0) + dut.clk90.setimmediatevalue(0) + + cocotb.fork(self._run_clk()) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + async def _run_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.clk <= 1 + await t + self.dut.clk90 <= 1 + await t + self.dut.clk <= 0 + await t + self.dut.clk90 <= 0 + await t + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.rgmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.rgmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_ddr_in.v"), + os.path.join(eth_rtl_dir, "rgmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/NexysVideo/fpga/tb/gmii_ep.py b/example/NexysVideo/fpga/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/NexysVideo/fpga/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/ip_ep.py b/example/NexysVideo/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/NexysVideo/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/rgmii_ep.py b/example/NexysVideo/fpga/tb/rgmii_ep.py deleted file mode 120000 index 986c56280..000000000 --- a/example/NexysVideo/fpga/tb/rgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/rgmii_ep.py \ No newline at end of file diff --git a/example/NexysVideo/fpga/tb/test_fpga_core.py b/example/NexysVideo/fpga/tb/test_fpga_core.py deleted file mode 100755 index a11687904..000000000 --- a/example/NexysVideo/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,315 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import rgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/iddr.v") -srcs.append("../lib/eth/rtl/oddr.v") -srcs.append("../lib/eth/rtl/ssio_ddr_in.v") -srcs.append("../lib/eth/rtl/ssio_ddr_out.v") -srcs.append("../lib/eth/rtl/rgmii_phy_if.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g_rgmii.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - TARGET = "SIM" - - # Inputs - clk = Signal(bool(0)) - clk90 = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - phy_rx_clk = Signal(bool(0)) - phy_rxd = Signal(intbv(0)[4:]) - phy_rx_ctl = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - phy_pme_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - phy_tx_clk = Signal(bool(0)) - phy_txd = Signal(intbv(0)[4:]) - phy_tx_ctl = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - - # sources and sinks - mii_select = Signal(bool(0)) - - rgmii_source = rgmii_ep.RGMIISource() - - rgmii_source_logic = rgmii_source.create_logic( - phy_rx_clk, - rst, - txd=phy_rxd, - tx_ctl=phy_rx_ctl, - mii_select=mii_select, - name='rgmii_source' - ) - - rgmii_sink = rgmii_ep.RGMIISink() - - rgmii_sink_logic = rgmii_sink.create_logic( - phy_tx_clk, - rst, - rxd=phy_txd, - rx_ctl=phy_tx_ctl, - mii_select=mii_select, - name='rgmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - clk90=clk90, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - phy_rx_clk=phy_rx_clk, - phy_rxd=phy_rxd, - phy_rx_ctl=phy_rx_ctl, - phy_tx_clk=phy_tx_clk, - phy_txd=phy_txd, - phy_tx_ctl=phy_tx_ctl, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - phy_pme_n=phy_pme_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - - @instance - def clkgen2(): - yield delay(4+2) - while True: - clk90.next = not clk90 - yield delay(4) - - rx_clk_hp = Signal(int(4)) - - @instance - def rx_clk_gen(): - while True: - yield delay(int(rx_clk_hp)) - phy_rx_clk.next = not phy_rx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - yield clk.posedge - rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - rgmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while rgmii_sink.empty(): - yield clk.posedge - - rx_frame = rgmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - rgmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while rgmii_sink.empty(): - yield clk.posedge - - rx_frame = rgmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert rgmii_source.empty() - assert rgmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/NexysVideo/fpga/tb/test_fpga_core.v b/example/NexysVideo/fpga/tb/test_fpga_core.v deleted file mode 100644 index 088a94d2c..000000000 --- a/example/NexysVideo/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,125 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters -parameter TARGET = "SIM"; - -// Inputs -reg clk = 0; -reg clk90 = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg phy_rx_clk = 0; -reg [3:0] phy_rxd = 0; -reg phy_rx_ctl = 0; -reg phy_int_n = 1; -reg phy_pme_n = 1; -reg uart_rxd = 0; - -// Outputs -wire [7:0] led; -wire phy_tx_clk; -wire [3:0] phy_txd; -wire phy_tx_ctl; -wire phy_reset_n; -wire uart_txd; - -initial begin - // myhdl integration - $from_myhdl( - clk, - clk90, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_rx_clk, - phy_rxd, - phy_rx_ctl, - phy_int_n, - phy_pme_n, - uart_rxd - ); - $to_myhdl( - led, - phy_tx_clk, - phy_txd, - phy_tx_ctl, - phy_reset_n, - uart_txd - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core #( - .TARGET(TARGET) -) -UUT ( - .clk(clk), - .clk90(clk90), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .phy_rx_clk(phy_rx_clk), - .phy_rxd(phy_rxd), - .phy_rx_ctl(phy_rx_ctl), - .phy_tx_clk(phy_tx_clk), - .phy_txd(phy_txd), - .phy_tx_ctl(phy_tx_ctl), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .phy_pme_n(phy_pme_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd) -); - -endmodule diff --git a/example/NexysVideo/fpga/tb/udp_ep.py b/example/NexysVideo/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/NexysVideo/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/arp_ep.py b/example/VCU108/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/VCU108/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/axis_ep.py b/example/VCU108/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/VCU108/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/eth_ep.py b/example/VCU108/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/VCU108/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/fpga_core/Makefile b/example/VCU108/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..14b7969eb --- /dev/null +++ b/example/VCU108/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,106 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_switch.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_register.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..7418e7b2f --- /dev/null +++ b/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,358 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + cocotb.fork(Clock(dut.qsfp_rx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_source = XgmiiSource(dut.qsfp_rxd_1, dut.qsfp_rxc_1, dut.qsfp_rx_clk_1, dut.qsfp_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_tx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_sink = XgmiiSink(dut.qsfp_txd_1, dut.qsfp_txc_1, dut.qsfp_tx_clk_1, dut.qsfp_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_rx_clk_2, 6.4, units="ns").start()) + self.qsfp_2_source = XgmiiSource(dut.qsfp_rxd_2, dut.qsfp_rxc_2, dut.qsfp_rx_clk_2, dut.qsfp_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_tx_clk_2, 6.4, units="ns").start()) + self.qsfp_2_sink = XgmiiSink(dut.qsfp_txd_2, dut.qsfp_txc_2, dut.qsfp_tx_clk_2, dut.qsfp_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_rx_clk_3, 6.4, units="ns").start()) + self.qsfp_3_source = XgmiiSource(dut.qsfp_rxd_3, dut.qsfp_rxc_3, dut.qsfp_rx_clk_3, dut.qsfp_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_tx_clk_3, 6.4, units="ns").start()) + self.qsfp_3_sink = XgmiiSink(dut.qsfp_txd_3, dut.qsfp_txc_3, dut.qsfp_tx_clk_3, dut.qsfp_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp_rx_clk_4, 6.4, units="ns").start()) + self.qsfp_4_source = XgmiiSource(dut.qsfp_rxd_4, dut.qsfp_rxc_4, dut.qsfp_rx_clk_4, dut.qsfp_rx_rst_4) + cocotb.fork(Clock(dut.qsfp_tx_clk_4, 6.4, units="ns").start()) + self.qsfp_4_sink = XgmiiSink(dut.qsfp_txd_4, dut.qsfp_txc_4, dut.qsfp_tx_clk_4, dut.qsfp_tx_rst_4) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_cts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + self.dut.qsfp_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.phy_gmii_rst <= 1 + self.dut.qsfp_rx_rst_1 <= 1 + self.dut.qsfp_tx_rst_1 <= 1 + self.dut.qsfp_rx_rst_2 <= 1 + self.dut.qsfp_tx_rst_2 <= 1 + self.dut.qsfp_rx_rst_3 <= 1 + self.dut.qsfp_tx_rst_3 <= 1 + self.dut.qsfp_rx_rst_4 <= 1 + self.dut.qsfp_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.phy_gmii_rst <= 0 + self.dut.qsfp_rx_rst_1 <= 0 + self.dut.qsfp_tx_rst_1 <= 0 + self.dut.qsfp_rx_rst_2 <= 0 + self.dut.qsfp_tx_rst_2 <= 0 + self.dut.qsfp_rx_rst_3 <= 0 + self.dut.qsfp_tx_rst_3 <= 0 + self.dut.qsfp_rx_rst_4 <= 0 + self.dut.qsfp_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + tb.log.info("test gigabit tap, RX side") + + # insert tap + await RisingEdge(dut.clk) + dut.sw <= 0x8 + await RisingEdge(dut.clk) + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("loop back packet on XGMII interface") + + rx_frame = await tb.qsfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + await tb.qsfp_1_source.send(rx_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + tb.log.info("test gigabit tap, TX side") + + # insert tap + await RisingEdge(dut.clk) + dut.sw <= 0xC + await RisingEdge(dut.clk) + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("loop back packet on XGMII interface") + + rx_frame = await tb.qsfp_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + await tb.qsfp_1_source.send(rx_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_switch.v"), + os.path.join(axis_rtl_dir, "axis_register.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/VCU108/fpga_10g/tb/gmii_ep.py b/example/VCU108/fpga_10g/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/VCU108/fpga_10g/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/ip_ep.py b/example/VCU108/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/VCU108/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/test_fpga_core.py b/example/VCU108/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index 1224a08fe..000000000 --- a/example/VCU108/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,576 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_adapter.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_switch.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[4:]) - qsfp_tx_clk_1 = Signal(bool(0)) - qsfp_tx_rst_1 = Signal(bool(0)) - qsfp_rx_clk_1 = Signal(bool(0)) - qsfp_rx_rst_1 = Signal(bool(0)) - qsfp_rxd_1 = Signal(intbv(0)[64:]) - qsfp_rxc_1 = Signal(intbv(0)[8:]) - qsfp_tx_clk_2 = Signal(bool(0)) - qsfp_tx_rst_2 = Signal(bool(0)) - qsfp_rx_clk_2 = Signal(bool(0)) - qsfp_rx_rst_2 = Signal(bool(0)) - qsfp_rxd_2 = Signal(intbv(0)[64:]) - qsfp_rxc_2 = Signal(intbv(0)[8:]) - qsfp_tx_clk_3 = Signal(bool(0)) - qsfp_tx_rst_3 = Signal(bool(0)) - qsfp_rx_clk_3 = Signal(bool(0)) - qsfp_rx_rst_3 = Signal(bool(0)) - qsfp_rxd_3 = Signal(intbv(0)[64:]) - qsfp_rxc_3 = Signal(intbv(0)[8:]) - qsfp_tx_clk_4 = Signal(bool(0)) - qsfp_tx_rst_4 = Signal(bool(0)) - qsfp_rx_clk_4 = Signal(bool(0)) - qsfp_rx_rst_4 = Signal(bool(0)) - qsfp_rxd_4 = Signal(intbv(0)[64:]) - qsfp_rxc_4 = Signal(intbv(0)[8:]) - phy_gmii_clk = Signal(bool(0)) - phy_gmii_rst = Signal(bool(0)) - phy_gmii_clk_en = Signal(bool(0)) - phy_gmii_rxd = Signal(intbv(0)[8:]) - phy_gmii_rx_dv = Signal(bool(0)) - phy_gmii_rx_er = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - qsfp_txd_1 = Signal(intbv(0)[64:]) - qsfp_txc_1 = Signal(intbv(0)[8:]) - qsfp_txd_2 = Signal(intbv(0)[64:]) - qsfp_txc_2 = Signal(intbv(0)[8:]) - qsfp_txd_3 = Signal(intbv(0)[64:]) - qsfp_txc_3 = Signal(intbv(0)[8:]) - qsfp_txd_4 = Signal(intbv(0)[64:]) - qsfp_txc_4 = Signal(intbv(0)[8:]) - phy_gmii_txd = Signal(intbv(0)[8:]) - phy_gmii_tx_en = Signal(bool(0)) - phy_gmii_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # sources and sinks - qsfp_1_source = xgmii_ep.XGMIISource() - qsfp_1_source_logic = qsfp_1_source.create_logic(qsfp_rx_clk_1, qsfp_rx_rst_1, txd=qsfp_rxd_1, txc=qsfp_rxc_1, name='qsfp_1_source') - - qsfp_1_sink = xgmii_ep.XGMIISink() - qsfp_1_sink_logic = qsfp_1_sink.create_logic(qsfp_tx_clk_1, qsfp_tx_rst_1, rxd=qsfp_txd_1, rxc=qsfp_txc_1, name='qsfp_1_sink') - - qsfp_2_source = xgmii_ep.XGMIISource() - qsfp_2_source_logic = qsfp_2_source.create_logic(qsfp_rx_clk_2, qsfp_rx_rst_2, txd=qsfp_rxd_2, txc=qsfp_rxc_2, name='qsfp_2_source') - - qsfp_2_sink = xgmii_ep.XGMIISink() - qsfp_2_sink_logic = qsfp_2_sink.create_logic(qsfp_tx_clk_2, qsfp_tx_rst_2, rxd=qsfp_txd_2, rxc=qsfp_txc_2, name='qsfp_2_sink') - - qsfp_3_source = xgmii_ep.XGMIISource() - qsfp_3_source_logic = qsfp_3_source.create_logic(qsfp_rx_clk_3, qsfp_rx_rst_3, txd=qsfp_rxd_3, txc=qsfp_rxc_3, name='qsfp_3_source') - - qsfp_3_sink = xgmii_ep.XGMIISink() - qsfp_3_sink_logic = qsfp_3_sink.create_logic(qsfp_tx_clk_3, qsfp_tx_rst_3, rxd=qsfp_txd_3, rxc=qsfp_txc_3, name='qsfp_3_sink') - - qsfp_4_source = xgmii_ep.XGMIISource() - qsfp_4_source_logic = qsfp_4_source.create_logic(qsfp_rx_clk_4, qsfp_rx_rst_4, txd=qsfp_rxd_4, txc=qsfp_rxc_4, name='qsfp_4_source') - - qsfp_4_sink = xgmii_ep.XGMIISink() - qsfp_4_sink_logic = qsfp_4_sink.create_logic(qsfp_tx_clk_4, qsfp_tx_rst_4, rxd=qsfp_txd_4, rxc=qsfp_txc_4, name='qsfp_4_sink') - - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_gmii_clk, - phy_gmii_rst, - txd=phy_gmii_rxd, - tx_en=phy_gmii_rx_dv, - tx_er=phy_gmii_rx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_gmii_clk, - phy_gmii_rst, - rxd=phy_gmii_txd, - rx_dv=phy_gmii_tx_en, - rx_er=phy_gmii_tx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - qsfp_tx_clk_1=qsfp_tx_clk_1, - qsfp_tx_rst_1=qsfp_tx_rst_1, - qsfp_txd_1=qsfp_txd_1, - qsfp_txc_1=qsfp_txc_1, - qsfp_rx_clk_1=qsfp_rx_clk_1, - qsfp_rx_rst_1=qsfp_rx_rst_1, - qsfp_rxd_1=qsfp_rxd_1, - qsfp_rxc_1=qsfp_rxc_1, - qsfp_tx_clk_2=qsfp_tx_clk_2, - qsfp_tx_rst_2=qsfp_tx_rst_2, - qsfp_txd_2=qsfp_txd_2, - qsfp_txc_2=qsfp_txc_2, - qsfp_rx_clk_2=qsfp_rx_clk_2, - qsfp_rx_rst_2=qsfp_rx_rst_2, - qsfp_rxd_2=qsfp_rxd_2, - qsfp_rxc_2=qsfp_rxc_2, - qsfp_tx_clk_3=qsfp_tx_clk_3, - qsfp_tx_rst_3=qsfp_tx_rst_3, - qsfp_txd_3=qsfp_txd_3, - qsfp_txc_3=qsfp_txc_3, - qsfp_rx_clk_3=qsfp_rx_clk_3, - qsfp_rx_rst_3=qsfp_rx_rst_3, - qsfp_rxd_3=qsfp_rxd_3, - qsfp_rxc_3=qsfp_rxc_3, - qsfp_tx_clk_4=qsfp_tx_clk_4, - qsfp_tx_rst_4=qsfp_tx_rst_4, - qsfp_txd_4=qsfp_txd_4, - qsfp_txc_4=qsfp_txc_4, - qsfp_rx_clk_4=qsfp_rx_clk_4, - qsfp_rx_rst_4=qsfp_rx_rst_4, - qsfp_rxd_4=qsfp_rxd_4, - qsfp_rxc_4=qsfp_rxc_4, - - phy_gmii_clk=phy_gmii_clk, - phy_gmii_rst=phy_gmii_rst, - phy_gmii_clk_en=phy_gmii_clk_en, - phy_gmii_rxd=phy_gmii_rxd, - phy_gmii_rx_dv=phy_gmii_rx_dv, - phy_gmii_rx_er=phy_gmii_rx_er, - phy_gmii_txd=phy_gmii_txd, - phy_gmii_tx_en=phy_gmii_tx_en, - phy_gmii_tx_er=phy_gmii_tx_er, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp_tx_clk_1.next = not qsfp_tx_clk_1 - qsfp_rx_clk_1.next = not qsfp_rx_clk_1 - qsfp_tx_clk_2.next = not qsfp_tx_clk_2 - qsfp_rx_clk_2.next = not qsfp_rx_clk_2 - qsfp_tx_clk_3.next = not qsfp_tx_clk_3 - qsfp_rx_clk_3.next = not qsfp_rx_clk_3 - qsfp_tx_clk_4.next = not qsfp_tx_clk_4 - qsfp_rx_clk_4.next = not qsfp_rx_clk_4 - phy_gmii_clk.next = not phy_gmii_clk - - clk_enable_rate = Signal(int(0)) - clk_enable_div = Signal(int(0)) - - @always(clk.posedge) - def clk_enable_gen(): - if clk_enable_div.next > 0: - phy_gmii_clk_en.next = 0 - clk_enable_div.next = clk_enable_div - 1 - else: - phy_gmii_clk_en.next = 1 - clk_enable_div.next = clk_enable_rate - 1 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp_tx_rst_1.next = 1 - qsfp_rx_rst_1.next = 1 - qsfp_tx_rst_2.next = 1 - qsfp_rx_rst_2.next = 1 - qsfp_tx_rst_3.next = 1 - qsfp_rx_rst_3.next = 1 - qsfp_tx_rst_4.next = 1 - qsfp_rx_rst_4.next = 1 - phy_gmii_rst.next = 1 - yield clk.posedge - rst.next = 0 - qsfp_tx_rst_1.next = 0 - qsfp_rx_rst_1.next = 0 - qsfp_tx_rst_2.next = 0 - qsfp_rx_rst_2.next = 0 - qsfp_tx_rst_3.next = 0 - qsfp_rx_rst_3.next = 0 - qsfp_tx_rst_4.next = 0 - qsfp_rx_rst_4.next = 0 - phy_gmii_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp_1_source.empty() - assert qsfp_1_sink.empty() - - yield delay(100) - - yield clk.posedge - print("test 2: test gigabit tap") - current_test.next = 2 - - sw.next = 0x8 # enable tap on RX - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # loop packet back through on XGMII interface - while qsfp_1_sink.empty(): - yield clk.posedge - - qsfp_1_source.send(qsfp_1_sink.recv()) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - assert qsfp_1_source.empty() - assert qsfp_1_sink.empty() - - yield delay(100) - - sw.next = 0xc # enable tap on TX - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # loop packet back through on XGMII interface - while qsfp_1_sink.empty(): - yield clk.posedge - - qsfp_1_source.send(qsfp_1_sink.recv()) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - assert qsfp_1_source.empty() - assert qsfp_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/VCU108/fpga_10g/tb/test_fpga_core.v b/example/VCU108/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index 04b913f58..000000000 --- a/example/VCU108/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,228 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [3:0] sw = 0; -reg qsfp_tx_clk_1 = 0; -reg qsfp_tx_rst_1 = 0; -reg qsfp_rx_clk_1 = 0; -reg qsfp_rx_rst_1 = 0; -reg [63:0] qsfp_rxd_1 = 0; -reg [7:0] qsfp_rxc_1 = 0; -reg qsfp_tx_clk_2 = 0; -reg qsfp_tx_rst_2 = 0; -reg qsfp_rx_clk_2 = 0; -reg qsfp_rx_rst_2 = 0; -reg [63:0] qsfp_rxd_2 = 0; -reg [7:0] qsfp_rxc_2 = 0; -reg qsfp_tx_clk_3 = 0; -reg qsfp_tx_rst_3 = 0; -reg qsfp_rx_clk_3 = 0; -reg qsfp_rx_rst_3 = 0; -reg [63:0] qsfp_rxd_3 = 0; -reg [7:0] qsfp_rxc_3 = 0; -reg qsfp_tx_clk_4 = 0; -reg qsfp_tx_rst_4 = 0; -reg qsfp_rx_clk_4 = 0; -reg qsfp_rx_rst_4 = 0; -reg [63:0] qsfp_rxd_4 = 0; -reg [7:0] qsfp_rxc_4 = 0; -reg phy_gmii_clk = 0; -reg phy_gmii_rst = 0; -reg phy_gmii_clk_en = 0; -reg [7:0] phy_gmii_rxd = 0; -reg phy_gmii_rx_dv = 0; -reg phy_gmii_rx_er = 0; -reg phy_int_n = 1; -reg uart_rxd = 0; -reg uart_cts = 0; - -// Outputs -wire [7:0] led; -wire [63:0] qsfp_txd_1; -wire [7:0] qsfp_txc_1; -wire [63:0] qsfp_txd_2; -wire [7:0] qsfp_txc_2; -wire [63:0] qsfp_txd_3; -wire [7:0] qsfp_txc_3; -wire [63:0] qsfp_txd_4; -wire [7:0] qsfp_txc_4; -wire phy_tx_clk; -wire [7:0] phy_gmii_txd; -wire phy_gmii_tx_en; -wire phy_gmii_tx_er; -wire phy_reset_n; -wire uart_txd; -wire uart_rts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - qsfp_tx_clk_1, - qsfp_tx_rst_1, - qsfp_rx_clk_1, - qsfp_rx_rst_1, - qsfp_rxd_1, - qsfp_rxc_1, - qsfp_tx_clk_2, - qsfp_tx_rst_2, - qsfp_rx_clk_2, - qsfp_rx_rst_2, - qsfp_rxd_2, - qsfp_rxc_2, - qsfp_tx_clk_3, - qsfp_tx_rst_3, - qsfp_rx_clk_3, - qsfp_rx_rst_3, - qsfp_rxd_3, - qsfp_rxc_3, - qsfp_tx_clk_4, - qsfp_tx_rst_4, - qsfp_rx_clk_4, - qsfp_rx_rst_4, - qsfp_rxd_4, - qsfp_rxc_4, - phy_gmii_clk, - phy_gmii_rst, - phy_gmii_clk_en, - phy_gmii_rxd, - phy_gmii_rx_dv, - phy_gmii_rx_er, - phy_int_n, - uart_rxd, - uart_cts - ); - $to_myhdl( - led, - qsfp_txd_1, - qsfp_txc_1, - qsfp_txd_2, - qsfp_txc_2, - qsfp_txd_3, - qsfp_txc_3, - qsfp_txd_4, - qsfp_txc_4, - phy_gmii_txd, - phy_gmii_tx_en, - phy_gmii_tx_er, - phy_reset_n, - uart_txd, - uart_rts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .qsfp_tx_clk_1(qsfp_tx_clk_1), - .qsfp_tx_rst_1(qsfp_tx_rst_1), - .qsfp_txd_1(qsfp_txd_1), - .qsfp_txc_1(qsfp_txc_1), - .qsfp_rx_clk_1(qsfp_rx_clk_1), - .qsfp_rx_rst_1(qsfp_rx_rst_1), - .qsfp_rxd_1(qsfp_rxd_1), - .qsfp_rxc_1(qsfp_rxc_1), - .qsfp_tx_clk_2(qsfp_tx_clk_2), - .qsfp_tx_rst_2(qsfp_tx_rst_2), - .qsfp_txd_2(qsfp_txd_2), - .qsfp_txc_2(qsfp_txc_2), - .qsfp_rx_clk_2(qsfp_rx_clk_2), - .qsfp_rx_rst_2(qsfp_rx_rst_2), - .qsfp_rxd_2(qsfp_rxd_2), - .qsfp_rxc_2(qsfp_rxc_2), - .qsfp_tx_clk_3(qsfp_tx_clk_3), - .qsfp_tx_rst_3(qsfp_tx_rst_3), - .qsfp_txd_3(qsfp_txd_3), - .qsfp_txc_3(qsfp_txc_3), - .qsfp_rx_clk_3(qsfp_rx_clk_3), - .qsfp_rx_rst_3(qsfp_rx_rst_3), - .qsfp_rxd_3(qsfp_rxd_3), - .qsfp_rxc_3(qsfp_rxc_3), - .qsfp_tx_clk_4(qsfp_tx_clk_4), - .qsfp_tx_rst_4(qsfp_tx_rst_4), - .qsfp_txd_4(qsfp_txd_4), - .qsfp_txc_4(qsfp_txc_4), - .qsfp_rx_clk_4(qsfp_rx_clk_4), - .qsfp_rx_rst_4(qsfp_rx_rst_4), - .qsfp_rxd_4(qsfp_rxd_4), - .qsfp_rxc_4(qsfp_rxc_4), - .phy_gmii_clk(phy_gmii_clk), - .phy_gmii_rst(phy_gmii_rst), - .phy_gmii_clk_en(phy_gmii_clk_en), - .phy_gmii_rxd(phy_gmii_rxd), - .phy_gmii_rx_dv(phy_gmii_rx_dv), - .phy_gmii_rx_er(phy_gmii_rx_er), - .phy_gmii_txd(phy_gmii_txd), - .phy_gmii_tx_en(phy_gmii_tx_en), - .phy_gmii_tx_er(phy_gmii_tx_er), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/VCU108/fpga_10g/tb/udp_ep.py b/example/VCU108/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/VCU108/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_10g/tb/xgmii_ep.py b/example/VCU108/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/VCU108/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_1g/tb/arp_ep.py b/example/VCU108/fpga_1g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/VCU108/fpga_1g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_1g/tb/axis_ep.py b/example/VCU108/fpga_1g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/VCU108/fpga_1g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_1g/tb/eth_ep.py b/example/VCU108/fpga_1g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/VCU108/fpga_1g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_1g/tb/fpga_core/Makefile b/example/VCU108/fpga_1g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aafe627c --- /dev/null +++ b/example/VCU108/fpga_1g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py b/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..04e3ff69f --- /dev/null +++ b/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,218 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink + + +class TB: + def __init__(self, dut, speed=1000): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_cts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.phy_gmii_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.phy_gmii_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/VCU108/fpga_1g/tb/gmii_ep.py b/example/VCU108/fpga_1g/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/VCU108/fpga_1g/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_1g/tb/ip_ep.py b/example/VCU108/fpga_1g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/VCU108/fpga_1g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/VCU108/fpga_1g/tb/test_fpga_core.py b/example/VCU108/fpga_1g/tb/test_fpga_core.py deleted file mode 100755 index 5e2d1bee9..000000000 --- a/example/VCU108/fpga_1g/tb/test_fpga_core.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[4:]) - phy_gmii_clk = Signal(bool(0)) - phy_gmii_rst = Signal(bool(0)) - phy_gmii_clk_en = Signal(bool(0)) - phy_gmii_rxd = Signal(intbv(0)[8:]) - phy_gmii_rx_dv = Signal(bool(0)) - phy_gmii_rx_er = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - phy_gmii_txd = Signal(intbv(0)[8:]) - phy_gmii_tx_en = Signal(bool(0)) - phy_gmii_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # sources and sinks - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_gmii_clk, - phy_gmii_rst, - txd=phy_gmii_rxd, - tx_en=phy_gmii_rx_dv, - tx_er=phy_gmii_rx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_gmii_clk, - phy_gmii_rst, - rxd=phy_gmii_txd, - rx_dv=phy_gmii_tx_en, - rx_er=phy_gmii_tx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - phy_gmii_clk=phy_gmii_clk, - phy_gmii_rst=phy_gmii_rst, - phy_gmii_clk_en=phy_gmii_clk_en, - phy_gmii_rxd=phy_gmii_rxd, - phy_gmii_rx_dv=phy_gmii_rx_dv, - phy_gmii_rx_er=phy_gmii_rx_er, - phy_gmii_txd=phy_gmii_txd, - phy_gmii_tx_en=phy_gmii_tx_en, - phy_gmii_tx_er=phy_gmii_tx_er, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - phy_gmii_clk.next = not phy_gmii_clk - - clk_enable_rate = Signal(int(0)) - clk_enable_div = Signal(int(0)) - - @always(clk.posedge) - def clk_enable_gen(): - if clk_enable_div.next > 0: - phy_gmii_clk_en.next = 0 - clk_enable_div.next = clk_enable_div - 1 - else: - phy_gmii_clk_en.next = 1 - clk_enable_div.next = clk_enable_rate - 1 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - phy_gmii_rst.next = 1 - yield clk.posedge - rst.next = 0 - phy_gmii_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/VCU108/fpga_1g/tb/test_fpga_core.v b/example/VCU108/fpga_1g/tb/test_fpga_core.v deleted file mode 100644 index e3de43465..000000000 --- a/example/VCU108/fpga_1g/tb/test_fpga_core.v +++ /dev/null @@ -1,131 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [3:0] sw = 0; -reg phy_gmii_clk = 0; -reg phy_gmii_rst = 0; -reg phy_gmii_clk_en = 0; -reg [7:0] phy_gmii_rxd = 0; -reg phy_gmii_rx_dv = 0; -reg phy_gmii_rx_er = 0; -reg phy_int_n = 1; -reg uart_rxd = 0; -reg uart_cts = 0; - -// Outputs -wire [7:0] led; -wire [7:0] phy_gmii_txd; -wire phy_gmii_tx_en; -wire phy_gmii_tx_er; -wire phy_reset_n; -wire uart_txd; -wire uart_rts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_gmii_clk, - phy_gmii_rst, - phy_gmii_clk_en, - phy_gmii_rxd, - phy_gmii_rx_dv, - phy_gmii_rx_er, - phy_int_n, - uart_rxd, - uart_cts - ); - $to_myhdl( - led, - phy_gmii_txd, - phy_gmii_tx_en, - phy_gmii_tx_er, - phy_reset_n, - uart_txd, - uart_rts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .phy_gmii_clk(phy_gmii_clk), - .phy_gmii_rst(phy_gmii_rst), - .phy_gmii_clk_en(phy_gmii_clk_en), - .phy_gmii_rxd(phy_gmii_rxd), - .phy_gmii_rx_dv(phy_gmii_rx_dv), - .phy_gmii_rx_er(phy_gmii_rx_er), - .phy_gmii_txd(phy_gmii_txd), - .phy_gmii_tx_en(phy_gmii_tx_en), - .phy_gmii_tx_er(phy_gmii_tx_er), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/VCU108/fpga_1g/tb/udp_ep.py b/example/VCU108/fpga_1g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/VCU108/fpga_1g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/arp_ep.py b/example/VCU118/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/VCU118/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/axis_ep.py b/example/VCU118/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/VCU118/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/eth_ep.py b/example/VCU118/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/VCU118/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/fpga_core/Makefile b/example/VCU118/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..14b7969eb --- /dev/null +++ b/example/VCU118/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,106 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_switch.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_register.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..0a088c921 --- /dev/null +++ b/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,402 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_source = XgmiiSource(dut.qsfp1_rxd_1, dut.qsfp1_rxc_1, dut.qsfp1_rx_clk_1, dut.qsfp1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_sink = XgmiiSink(dut.qsfp1_txd_1, dut.qsfp1_txc_1, dut.qsfp1_tx_clk_1, dut.qsfp1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_source = XgmiiSource(dut.qsfp1_rxd_2, dut.qsfp1_rxc_2, dut.qsfp1_rx_clk_2, dut.qsfp1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_sink = XgmiiSink(dut.qsfp1_txd_2, dut.qsfp1_txc_2, dut.qsfp1_tx_clk_2, dut.qsfp1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_source = XgmiiSource(dut.qsfp1_rxd_3, dut.qsfp1_rxc_3, dut.qsfp1_rx_clk_3, dut.qsfp1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_sink = XgmiiSink(dut.qsfp1_txd_3, dut.qsfp1_txc_3, dut.qsfp1_tx_clk_3, dut.qsfp1_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_source = XgmiiSource(dut.qsfp1_rxd_4, dut.qsfp1_rxc_4, dut.qsfp1_rx_clk_4, dut.qsfp1_rx_rst_4) + cocotb.fork(Clock(dut.qsfp1_tx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_sink = XgmiiSink(dut.qsfp1_txd_4, dut.qsfp1_txc_4, dut.qsfp1_tx_clk_4, dut.qsfp1_tx_rst_4) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_1, 6.4, units="ns").start()) + self.qsfp2_1_source = XgmiiSource(dut.qsfp2_rxd_1, dut.qsfp2_rxc_1, dut.qsfp2_rx_clk_1, dut.qsfp2_rx_rst_1) + cocotb.fork(Clock(dut.qsfp2_tx_clk_1, 6.4, units="ns").start()) + self.qsfp2_1_sink = XgmiiSink(dut.qsfp2_txd_1, dut.qsfp2_txc_1, dut.qsfp2_tx_clk_1, dut.qsfp2_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_2, 6.4, units="ns").start()) + self.qsfp2_2_source = XgmiiSource(dut.qsfp2_rxd_2, dut.qsfp2_rxc_2, dut.qsfp2_rx_clk_2, dut.qsfp2_rx_rst_2) + cocotb.fork(Clock(dut.qsfp2_tx_clk_2, 6.4, units="ns").start()) + self.qsfp2_2_sink = XgmiiSink(dut.qsfp2_txd_2, dut.qsfp2_txc_2, dut.qsfp2_tx_clk_2, dut.qsfp2_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_3, 6.4, units="ns").start()) + self.qsfp2_3_source = XgmiiSource(dut.qsfp2_rxd_3, dut.qsfp2_rxc_3, dut.qsfp2_rx_clk_3, dut.qsfp2_rx_rst_3) + cocotb.fork(Clock(dut.qsfp2_tx_clk_3, 6.4, units="ns").start()) + self.qsfp2_3_sink = XgmiiSink(dut.qsfp2_txd_3, dut.qsfp2_txc_3, dut.qsfp2_tx_clk_3, dut.qsfp2_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_4, 6.4, units="ns").start()) + self.qsfp2_4_source = XgmiiSource(dut.qsfp2_rxd_4, dut.qsfp2_rxc_4, dut.qsfp2_rx_clk_4, dut.qsfp2_rx_rst_4) + cocotb.fork(Clock(dut.qsfp2_tx_clk_4, 6.4, units="ns").start()) + self.qsfp2_4_sink = XgmiiSink(dut.qsfp2_txd_4, dut.qsfp2_txc_4, dut.qsfp2_tx_clk_4, dut.qsfp2_tx_rst_4) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_cts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_4.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.phy_gmii_rst <= 1 + self.dut.qsfp1_rx_rst_1 <= 1 + self.dut.qsfp1_tx_rst_1 <= 1 + self.dut.qsfp1_rx_rst_2 <= 1 + self.dut.qsfp1_tx_rst_2 <= 1 + self.dut.qsfp1_rx_rst_3 <= 1 + self.dut.qsfp1_tx_rst_3 <= 1 + self.dut.qsfp1_rx_rst_4 <= 1 + self.dut.qsfp1_tx_rst_4 <= 1 + self.dut.qsfp2_rx_rst_1 <= 1 + self.dut.qsfp2_tx_rst_1 <= 1 + self.dut.qsfp2_rx_rst_2 <= 1 + self.dut.qsfp2_tx_rst_2 <= 1 + self.dut.qsfp2_rx_rst_3 <= 1 + self.dut.qsfp2_tx_rst_3 <= 1 + self.dut.qsfp2_rx_rst_4 <= 1 + self.dut.qsfp2_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.phy_gmii_rst <= 0 + self.dut.qsfp1_rx_rst_1 <= 0 + self.dut.qsfp1_tx_rst_1 <= 0 + self.dut.qsfp1_rx_rst_2 <= 0 + self.dut.qsfp1_tx_rst_2 <= 0 + self.dut.qsfp1_rx_rst_3 <= 0 + self.dut.qsfp1_tx_rst_3 <= 0 + self.dut.qsfp1_rx_rst_4 <= 0 + self.dut.qsfp1_tx_rst_4 <= 0 + self.dut.qsfp2_rx_rst_1 <= 0 + self.dut.qsfp2_tx_rst_1 <= 0 + self.dut.qsfp2_rx_rst_2 <= 0 + self.dut.qsfp2_tx_rst_2 <= 0 + self.dut.qsfp2_rx_rst_3 <= 0 + self.dut.qsfp2_tx_rst_3 <= 0 + self.dut.qsfp2_rx_rst_4 <= 0 + self.dut.qsfp2_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp1_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp1_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + tb.log.info("test gigabit tap, RX side") + + # insert tap + await RisingEdge(dut.clk) + dut.sw <= 0x8 + await RisingEdge(dut.clk) + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("loop back packet on XGMII interface") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + await tb.qsfp1_1_source.send(rx_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + tb.log.info("test gigabit tap, TX side") + + # insert tap + await RisingEdge(dut.clk) + dut.sw <= 0xC + await RisingEdge(dut.clk) + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("loop back packet on XGMII interface") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + await tb.qsfp1_1_source.send(rx_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_switch.v"), + os.path.join(axis_rtl_dir, "axis_register.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/VCU118/fpga_10g/tb/gmii_ep.py b/example/VCU118/fpga_10g/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/VCU118/fpga_10g/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/ip_ep.py b/example/VCU118/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/VCU118/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/test_fpga_core.py b/example/VCU118/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index 725c2d6df..000000000 --- a/example/VCU118/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,688 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_adapter.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_switch.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[4:]) - qsfp1_tx_clk_1 = Signal(bool(0)) - qsfp1_tx_rst_1 = Signal(bool(0)) - qsfp1_rx_clk_1 = Signal(bool(0)) - qsfp1_rx_rst_1 = Signal(bool(0)) - qsfp1_rxd_1 = Signal(intbv(0)[64:]) - qsfp1_rxc_1 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_2 = Signal(bool(0)) - qsfp1_tx_rst_2 = Signal(bool(0)) - qsfp1_rx_clk_2 = Signal(bool(0)) - qsfp1_rx_rst_2 = Signal(bool(0)) - qsfp1_rxd_2 = Signal(intbv(0)[64:]) - qsfp1_rxc_2 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_3 = Signal(bool(0)) - qsfp1_tx_rst_3 = Signal(bool(0)) - qsfp1_rx_clk_3 = Signal(bool(0)) - qsfp1_rx_rst_3 = Signal(bool(0)) - qsfp1_rxd_3 = Signal(intbv(0)[64:]) - qsfp1_rxc_3 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_4 = Signal(bool(0)) - qsfp1_tx_rst_4 = Signal(bool(0)) - qsfp1_rx_clk_4 = Signal(bool(0)) - qsfp1_rx_rst_4 = Signal(bool(0)) - qsfp1_rxd_4 = Signal(intbv(0)[64:]) - qsfp1_rxc_4 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_1 = Signal(bool(0)) - qsfp2_tx_rst_1 = Signal(bool(0)) - qsfp2_rx_clk_1 = Signal(bool(0)) - qsfp2_rx_rst_1 = Signal(bool(0)) - qsfp2_rxd_1 = Signal(intbv(0)[64:]) - qsfp2_rxc_1 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_2 = Signal(bool(0)) - qsfp2_tx_rst_2 = Signal(bool(0)) - qsfp2_rx_clk_2 = Signal(bool(0)) - qsfp2_rx_rst_2 = Signal(bool(0)) - qsfp2_rxd_2 = Signal(intbv(0)[64:]) - qsfp2_rxc_2 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_3 = Signal(bool(0)) - qsfp2_tx_rst_3 = Signal(bool(0)) - qsfp2_rx_clk_3 = Signal(bool(0)) - qsfp2_rx_rst_3 = Signal(bool(0)) - qsfp2_rxd_3 = Signal(intbv(0)[64:]) - qsfp2_rxc_3 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_4 = Signal(bool(0)) - qsfp2_tx_rst_4 = Signal(bool(0)) - qsfp2_rx_clk_4 = Signal(bool(0)) - qsfp2_rx_rst_4 = Signal(bool(0)) - qsfp2_rxd_4 = Signal(intbv(0)[64:]) - qsfp2_rxc_4 = Signal(intbv(0)[8:]) - phy_gmii_clk = Signal(bool(0)) - phy_gmii_rst = Signal(bool(0)) - phy_gmii_clk_en = Signal(bool(0)) - phy_gmii_rxd = Signal(intbv(0)[8:]) - phy_gmii_rx_dv = Signal(bool(0)) - phy_gmii_rx_er = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - qsfp1_txd_1 = Signal(intbv(0)[64:]) - qsfp1_txc_1 = Signal(intbv(0)[8:]) - qsfp1_txd_2 = Signal(intbv(0)[64:]) - qsfp1_txc_2 = Signal(intbv(0)[8:]) - qsfp1_txd_3 = Signal(intbv(0)[64:]) - qsfp1_txc_3 = Signal(intbv(0)[8:]) - qsfp1_txd_4 = Signal(intbv(0)[64:]) - qsfp1_txc_4 = Signal(intbv(0)[8:]) - qsfp2_txd_1 = Signal(intbv(0)[64:]) - qsfp2_txc_1 = Signal(intbv(0)[8:]) - qsfp2_txd_2 = Signal(intbv(0)[64:]) - qsfp2_txc_2 = Signal(intbv(0)[8:]) - qsfp2_txd_3 = Signal(intbv(0)[64:]) - qsfp2_txc_3 = Signal(intbv(0)[8:]) - qsfp2_txd_4 = Signal(intbv(0)[64:]) - qsfp2_txc_4 = Signal(intbv(0)[8:]) - phy_gmii_txd = Signal(intbv(0)[8:]) - phy_gmii_tx_en = Signal(bool(0)) - phy_gmii_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # sources and sinks - qsfp1_1_source = xgmii_ep.XGMIISource() - qsfp1_1_source_logic = qsfp1_1_source.create_logic(qsfp1_rx_clk_1, qsfp1_rx_rst_1, txd=qsfp1_rxd_1, txc=qsfp1_rxc_1, name='qsfp1_1_source') - - qsfp1_1_sink = xgmii_ep.XGMIISink() - qsfp1_1_sink_logic = qsfp1_1_sink.create_logic(qsfp1_tx_clk_1, qsfp1_tx_rst_1, rxd=qsfp1_txd_1, rxc=qsfp1_txc_1, name='qsfp1_1_sink') - - qsfp1_2_source = xgmii_ep.XGMIISource() - qsfp1_2_source_logic = qsfp1_2_source.create_logic(qsfp1_rx_clk_2, qsfp1_rx_rst_2, txd=qsfp1_rxd_2, txc=qsfp1_rxc_2, name='qsfp1_2_source') - - qsfp1_2_sink = xgmii_ep.XGMIISink() - qsfp1_2_sink_logic = qsfp1_2_sink.create_logic(qsfp1_tx_clk_2, qsfp1_tx_rst_2, rxd=qsfp1_txd_2, rxc=qsfp1_txc_2, name='qsfp1_2_sink') - - qsfp1_3_source = xgmii_ep.XGMIISource() - qsfp1_3_source_logic = qsfp1_3_source.create_logic(qsfp1_rx_clk_3, qsfp1_rx_rst_3, txd=qsfp1_rxd_3, txc=qsfp1_rxc_3, name='qsfp1_3_source') - - qsfp1_3_sink = xgmii_ep.XGMIISink() - qsfp1_3_sink_logic = qsfp1_3_sink.create_logic(qsfp1_tx_clk_3, qsfp1_tx_rst_3, rxd=qsfp1_txd_3, rxc=qsfp1_txc_3, name='qsfp1_3_sink') - - qsfp1_4_source = xgmii_ep.XGMIISource() - qsfp1_4_source_logic = qsfp1_4_source.create_logic(qsfp1_rx_clk_4, qsfp1_rx_rst_4, txd=qsfp1_rxd_4, txc=qsfp1_rxc_4, name='qsfp1_4_source') - - qsfp1_4_sink = xgmii_ep.XGMIISink() - qsfp1_4_sink_logic = qsfp1_4_sink.create_logic(qsfp1_tx_clk_4, qsfp1_tx_rst_4, rxd=qsfp1_txd_4, rxc=qsfp1_txc_4, name='qsfp1_4_sink') - - qsfp2_1_source = xgmii_ep.XGMIISource() - qsfp2_1_source_logic = qsfp2_1_source.create_logic(qsfp2_rx_clk_1, qsfp2_rx_rst_1, txd=qsfp2_rxd_1, txc=qsfp2_rxc_1, name='qsfp2_1_source') - - qsfp2_1_sink = xgmii_ep.XGMIISink() - qsfp2_1_sink_logic = qsfp2_1_sink.create_logic(qsfp2_tx_clk_1, qsfp2_tx_rst_1, rxd=qsfp2_txd_1, rxc=qsfp2_txc_1, name='qsfp2_1_sink') - - qsfp2_2_source = xgmii_ep.XGMIISource() - qsfp2_2_source_logic = qsfp2_2_source.create_logic(qsfp2_rx_clk_2, qsfp2_rx_rst_2, txd=qsfp2_rxd_2, txc=qsfp2_rxc_2, name='qsfp2_2_source') - - qsfp2_2_sink = xgmii_ep.XGMIISink() - qsfp2_2_sink_logic = qsfp2_2_sink.create_logic(qsfp2_tx_clk_2, qsfp2_tx_rst_2, rxd=qsfp2_txd_2, rxc=qsfp2_txc_2, name='qsfp2_2_sink') - - qsfp2_3_source = xgmii_ep.XGMIISource() - qsfp2_3_source_logic = qsfp2_3_source.create_logic(qsfp2_rx_clk_3, qsfp2_rx_rst_3, txd=qsfp2_rxd_3, txc=qsfp2_rxc_3, name='qsfp2_3_source') - - qsfp2_3_sink = xgmii_ep.XGMIISink() - qsfp2_3_sink_logic = qsfp2_3_sink.create_logic(qsfp2_tx_clk_3, qsfp2_tx_rst_3, rxd=qsfp2_txd_3, rxc=qsfp2_txc_3, name='qsfp2_3_sink') - - qsfp2_4_source = xgmii_ep.XGMIISource() - qsfp2_4_source_logic = qsfp2_4_source.create_logic(qsfp2_rx_clk_4, qsfp2_rx_rst_4, txd=qsfp2_rxd_4, txc=qsfp2_rxc_4, name='qsfp2_4_source') - - qsfp2_4_sink = xgmii_ep.XGMIISink() - qsfp2_4_sink_logic = qsfp2_4_sink.create_logic(qsfp2_tx_clk_4, qsfp2_tx_rst_4, rxd=qsfp2_txd_4, rxc=qsfp2_txc_4, name='qsfp2_4_sink') - - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_gmii_clk, - phy_gmii_rst, - txd=phy_gmii_rxd, - tx_en=phy_gmii_rx_dv, - tx_er=phy_gmii_rx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_gmii_clk, - phy_gmii_rst, - rxd=phy_gmii_txd, - rx_dv=phy_gmii_tx_en, - rx_er=phy_gmii_tx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - qsfp1_tx_clk_1=qsfp1_tx_clk_1, - qsfp1_tx_rst_1=qsfp1_tx_rst_1, - qsfp1_txd_1=qsfp1_txd_1, - qsfp1_txc_1=qsfp1_txc_1, - qsfp1_rx_clk_1=qsfp1_rx_clk_1, - qsfp1_rx_rst_1=qsfp1_rx_rst_1, - qsfp1_rxd_1=qsfp1_rxd_1, - qsfp1_rxc_1=qsfp1_rxc_1, - qsfp1_tx_clk_2=qsfp1_tx_clk_2, - qsfp1_tx_rst_2=qsfp1_tx_rst_2, - qsfp1_txd_2=qsfp1_txd_2, - qsfp1_txc_2=qsfp1_txc_2, - qsfp1_rx_clk_2=qsfp1_rx_clk_2, - qsfp1_rx_rst_2=qsfp1_rx_rst_2, - qsfp1_rxd_2=qsfp1_rxd_2, - qsfp1_rxc_2=qsfp1_rxc_2, - qsfp1_tx_clk_3=qsfp1_tx_clk_3, - qsfp1_tx_rst_3=qsfp1_tx_rst_3, - qsfp1_txd_3=qsfp1_txd_3, - qsfp1_txc_3=qsfp1_txc_3, - qsfp1_rx_clk_3=qsfp1_rx_clk_3, - qsfp1_rx_rst_3=qsfp1_rx_rst_3, - qsfp1_rxd_3=qsfp1_rxd_3, - qsfp1_rxc_3=qsfp1_rxc_3, - qsfp1_tx_clk_4=qsfp1_tx_clk_4, - qsfp1_tx_rst_4=qsfp1_tx_rst_4, - qsfp1_txd_4=qsfp1_txd_4, - qsfp1_txc_4=qsfp1_txc_4, - qsfp1_rx_clk_4=qsfp1_rx_clk_4, - qsfp1_rx_rst_4=qsfp1_rx_rst_4, - qsfp1_rxd_4=qsfp1_rxd_4, - qsfp1_rxc_4=qsfp1_rxc_4, - qsfp2_tx_clk_1=qsfp2_tx_clk_1, - qsfp2_tx_rst_1=qsfp2_tx_rst_1, - qsfp2_txd_1=qsfp2_txd_1, - qsfp2_txc_1=qsfp2_txc_1, - qsfp2_rx_clk_1=qsfp2_rx_clk_1, - qsfp2_rx_rst_1=qsfp2_rx_rst_1, - qsfp2_rxd_1=qsfp2_rxd_1, - qsfp2_rxc_1=qsfp2_rxc_1, - qsfp2_tx_clk_2=qsfp2_tx_clk_2, - qsfp2_tx_rst_2=qsfp2_tx_rst_2, - qsfp2_txd_2=qsfp2_txd_2, - qsfp2_txc_2=qsfp2_txc_2, - qsfp2_rx_clk_2=qsfp2_rx_clk_2, - qsfp2_rx_rst_2=qsfp2_rx_rst_2, - qsfp2_rxd_2=qsfp2_rxd_2, - qsfp2_rxc_2=qsfp2_rxc_2, - qsfp2_tx_clk_3=qsfp2_tx_clk_3, - qsfp2_tx_rst_3=qsfp2_tx_rst_3, - qsfp2_txd_3=qsfp2_txd_3, - qsfp2_txc_3=qsfp2_txc_3, - qsfp2_rx_clk_3=qsfp2_rx_clk_3, - qsfp2_rx_rst_3=qsfp2_rx_rst_3, - qsfp2_rxd_3=qsfp2_rxd_3, - qsfp2_rxc_3=qsfp2_rxc_3, - qsfp2_tx_clk_4=qsfp2_tx_clk_4, - qsfp2_tx_rst_4=qsfp2_tx_rst_4, - qsfp2_txd_4=qsfp2_txd_4, - qsfp2_txc_4=qsfp2_txc_4, - qsfp2_rx_clk_4=qsfp2_rx_clk_4, - qsfp2_rx_rst_4=qsfp2_rx_rst_4, - qsfp2_rxd_4=qsfp2_rxd_4, - qsfp2_rxc_4=qsfp2_rxc_4, - - phy_gmii_clk=phy_gmii_clk, - phy_gmii_rst=phy_gmii_rst, - phy_gmii_clk_en=phy_gmii_clk_en, - phy_gmii_rxd=phy_gmii_rxd, - phy_gmii_rx_dv=phy_gmii_rx_dv, - phy_gmii_rx_er=phy_gmii_rx_er, - phy_gmii_txd=phy_gmii_txd, - phy_gmii_tx_en=phy_gmii_tx_en, - phy_gmii_tx_er=phy_gmii_tx_er, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp1_tx_clk_1.next = not qsfp1_tx_clk_1 - qsfp1_rx_clk_1.next = not qsfp1_rx_clk_1 - qsfp1_tx_clk_2.next = not qsfp1_tx_clk_2 - qsfp1_rx_clk_2.next = not qsfp1_rx_clk_2 - qsfp1_tx_clk_3.next = not qsfp1_tx_clk_3 - qsfp1_rx_clk_3.next = not qsfp1_rx_clk_3 - qsfp1_tx_clk_4.next = not qsfp1_tx_clk_4 - qsfp1_rx_clk_4.next = not qsfp1_rx_clk_4 - qsfp2_tx_clk_1.next = not qsfp2_tx_clk_1 - qsfp2_rx_clk_1.next = not qsfp2_rx_clk_1 - qsfp2_tx_clk_2.next = not qsfp2_tx_clk_2 - qsfp2_rx_clk_2.next = not qsfp2_rx_clk_2 - qsfp2_tx_clk_3.next = not qsfp2_tx_clk_3 - qsfp2_rx_clk_3.next = not qsfp2_rx_clk_3 - qsfp2_tx_clk_4.next = not qsfp2_tx_clk_4 - qsfp2_rx_clk_4.next = not qsfp2_rx_clk_4 - phy_gmii_clk.next = not phy_gmii_clk - - clk_enable_rate = Signal(int(0)) - clk_enable_div = Signal(int(0)) - - @always(clk.posedge) - def clk_enable_gen(): - if clk_enable_div.next > 0: - phy_gmii_clk_en.next = 0 - clk_enable_div.next = clk_enable_div - 1 - else: - phy_gmii_clk_en.next = 1 - clk_enable_div.next = clk_enable_rate - 1 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp1_tx_rst_1.next = 1 - qsfp1_rx_rst_1.next = 1 - qsfp1_tx_rst_2.next = 1 - qsfp1_rx_rst_2.next = 1 - qsfp1_tx_rst_3.next = 1 - qsfp1_rx_rst_3.next = 1 - qsfp1_tx_rst_4.next = 1 - qsfp1_rx_rst_4.next = 1 - qsfp2_tx_rst_1.next = 1 - qsfp2_rx_rst_1.next = 1 - qsfp2_tx_rst_2.next = 1 - qsfp2_rx_rst_2.next = 1 - qsfp2_tx_rst_3.next = 1 - qsfp2_rx_rst_3.next = 1 - qsfp2_tx_rst_4.next = 1 - qsfp2_rx_rst_4.next = 1 - phy_gmii_rst.next = 1 - yield clk.posedge - rst.next = 0 - qsfp1_tx_rst_1.next = 0 - qsfp1_rx_rst_1.next = 0 - qsfp1_tx_rst_2.next = 0 - qsfp1_rx_rst_2.next = 0 - qsfp1_tx_rst_3.next = 0 - qsfp1_rx_rst_3.next = 0 - qsfp1_tx_rst_4.next = 0 - qsfp1_rx_rst_4.next = 0 - qsfp2_tx_rst_1.next = 0 - qsfp2_rx_rst_1.next = 0 - qsfp2_tx_rst_2.next = 0 - qsfp2_rx_rst_2.next = 0 - qsfp2_tx_rst_3.next = 0 - qsfp2_rx_rst_3.next = 0 - qsfp2_tx_rst_4.next = 0 - qsfp2_rx_rst_4.next = 0 - phy_gmii_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp1_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp1_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp1_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp1_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp1_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp1_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp1_1_source.empty() - assert qsfp1_1_sink.empty() - - yield delay(100) - - yield clk.posedge - print("test 2: test gigabit tap") - current_test.next = 2 - - sw.next = 0x8 # enable tap on RX - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # loop packet back through on XGMII interface - while qsfp1_1_sink.empty(): - yield clk.posedge - - qsfp1_1_source.send(qsfp1_1_sink.recv()) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - assert qsfp1_1_source.empty() - assert qsfp1_1_sink.empty() - - yield delay(100) - - sw.next = 0xc # enable tap on TX - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # loop packet back through on XGMII interface - while qsfp1_1_sink.empty(): - yield clk.posedge - - qsfp1_1_source.send(qsfp1_1_sink.recv()) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - assert qsfp1_1_source.empty() - assert qsfp1_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/VCU118/fpga_10g/tb/test_fpga_core.v b/example/VCU118/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index 24db5dc0c..000000000 --- a/example/VCU118/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,324 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [3:0] sw = 0; -reg qsfp1_tx_clk_1 = 0; -reg qsfp1_tx_rst_1 = 0; -reg qsfp1_rx_clk_1 = 0; -reg qsfp1_rx_rst_1 = 0; -reg [63:0] qsfp1_rxd_1 = 0; -reg [7:0] qsfp1_rxc_1 = 0; -reg qsfp1_tx_clk_2 = 0; -reg qsfp1_tx_rst_2 = 0; -reg qsfp1_rx_clk_2 = 0; -reg qsfp1_rx_rst_2 = 0; -reg [63:0] qsfp1_rxd_2 = 0; -reg [7:0] qsfp1_rxc_2 = 0; -reg qsfp1_tx_clk_3 = 0; -reg qsfp1_tx_rst_3 = 0; -reg qsfp1_rx_clk_3 = 0; -reg qsfp1_rx_rst_3 = 0; -reg [63:0] qsfp1_rxd_3 = 0; -reg [7:0] qsfp1_rxc_3 = 0; -reg qsfp1_tx_clk_4 = 0; -reg qsfp1_tx_rst_4 = 0; -reg qsfp1_rx_clk_4 = 0; -reg qsfp1_rx_rst_4 = 0; -reg [63:0] qsfp1_rxd_4 = 0; -reg [7:0] qsfp1_rxc_4 = 0; -reg qsfp2_tx_clk_1 = 0; -reg qsfp2_tx_rst_1 = 0; -reg qsfp2_rx_clk_1 = 0; -reg qsfp2_rx_rst_1 = 0; -reg [63:0] qsfp2_rxd_1 = 0; -reg [7:0] qsfp2_rxc_1 = 0; -reg qsfp2_tx_clk_2 = 0; -reg qsfp2_tx_rst_2 = 0; -reg qsfp2_rx_clk_2 = 0; -reg qsfp2_rx_rst_2 = 0; -reg [63:0] qsfp2_rxd_2 = 0; -reg [7:0] qsfp2_rxc_2 = 0; -reg qsfp2_tx_clk_3 = 0; -reg qsfp2_tx_rst_3 = 0; -reg qsfp2_rx_clk_3 = 0; -reg qsfp2_rx_rst_3 = 0; -reg [63:0] qsfp2_rxd_3 = 0; -reg [7:0] qsfp2_rxc_3 = 0; -reg qsfp2_tx_clk_4 = 0; -reg qsfp2_tx_rst_4 = 0; -reg qsfp2_rx_clk_4 = 0; -reg qsfp2_rx_rst_4 = 0; -reg [63:0] qsfp2_rxd_4 = 0; -reg [7:0] qsfp2_rxc_4 = 0; -reg phy_gmii_clk = 0; -reg phy_gmii_rst = 0; -reg phy_gmii_clk_en = 0; -reg [7:0] phy_gmii_rxd = 0; -reg phy_gmii_rx_dv = 0; -reg phy_gmii_rx_er = 0; -reg phy_int_n = 1; -reg uart_rxd = 0; -reg uart_cts = 0; - -// Outputs -wire [7:0] led; -wire [63:0] qsfp1_txd_1; -wire [7:0] qsfp1_txc_1; -wire [63:0] qsfp1_txd_2; -wire [7:0] qsfp1_txc_2; -wire [63:0] qsfp1_txd_3; -wire [7:0] qsfp1_txc_3; -wire [63:0] qsfp1_txd_4; -wire [7:0] qsfp1_txc_4; -wire [63:0] qsfp2_txd_1; -wire [7:0] qsfp2_txc_1; -wire [63:0] qsfp2_txd_2; -wire [7:0] qsfp2_txc_2; -wire [63:0] qsfp2_txd_3; -wire [7:0] qsfp2_txc_3; -wire [63:0] qsfp2_txd_4; -wire [7:0] qsfp2_txc_4; -wire phy_tx_clk; -wire [7:0] phy_gmii_txd; -wire phy_gmii_tx_en; -wire phy_gmii_tx_er; -wire phy_reset_n; -wire uart_txd; -wire uart_rts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - qsfp1_tx_clk_1, - qsfp1_tx_rst_1, - qsfp1_rx_clk_1, - qsfp1_rx_rst_1, - qsfp1_rxd_1, - qsfp1_rxc_1, - qsfp1_tx_clk_2, - qsfp1_tx_rst_2, - qsfp1_rx_clk_2, - qsfp1_rx_rst_2, - qsfp1_rxd_2, - qsfp1_rxc_2, - qsfp1_tx_clk_3, - qsfp1_tx_rst_3, - qsfp1_rx_clk_3, - qsfp1_rx_rst_3, - qsfp1_rxd_3, - qsfp1_rxc_3, - qsfp1_tx_clk_4, - qsfp1_tx_rst_4, - qsfp1_rx_clk_4, - qsfp1_rx_rst_4, - qsfp1_rxd_4, - qsfp1_rxc_4, - qsfp2_tx_clk_1, - qsfp2_tx_rst_1, - qsfp2_rx_clk_1, - qsfp2_rx_rst_1, - qsfp2_rxd_1, - qsfp2_rxc_1, - qsfp2_tx_clk_2, - qsfp2_tx_rst_2, - qsfp2_rx_clk_2, - qsfp2_rx_rst_2, - qsfp2_rxd_2, - qsfp2_rxc_2, - qsfp2_tx_clk_3, - qsfp2_tx_rst_3, - qsfp2_rx_clk_3, - qsfp2_rx_rst_3, - qsfp2_rxd_3, - qsfp2_rxc_3, - qsfp2_tx_clk_4, - qsfp2_tx_rst_4, - qsfp2_rx_clk_4, - qsfp2_rx_rst_4, - qsfp2_rxd_4, - qsfp2_rxc_4, - phy_gmii_clk, - phy_gmii_rst, - phy_gmii_clk_en, - phy_gmii_rxd, - phy_gmii_rx_dv, - phy_gmii_rx_er, - phy_int_n, - uart_rxd, - uart_cts - ); - $to_myhdl( - led, - qsfp1_txd_1, - qsfp1_txc_1, - qsfp1_txd_2, - qsfp1_txc_2, - qsfp1_txd_3, - qsfp1_txc_3, - qsfp1_txd_4, - qsfp1_txc_4, - qsfp2_txd_1, - qsfp2_txc_1, - qsfp2_txd_2, - qsfp2_txc_2, - qsfp2_txd_3, - qsfp2_txc_3, - qsfp2_txd_4, - qsfp2_txc_4, - phy_gmii_txd, - phy_gmii_tx_en, - phy_gmii_tx_er, - phy_reset_n, - uart_txd, - uart_rts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .qsfp1_tx_clk_1(qsfp1_tx_clk_1), - .qsfp1_tx_rst_1(qsfp1_tx_rst_1), - .qsfp1_txd_1(qsfp1_txd_1), - .qsfp1_txc_1(qsfp1_txc_1), - .qsfp1_rx_clk_1(qsfp1_rx_clk_1), - .qsfp1_rx_rst_1(qsfp1_rx_rst_1), - .qsfp1_rxd_1(qsfp1_rxd_1), - .qsfp1_rxc_1(qsfp1_rxc_1), - .qsfp1_tx_clk_2(qsfp1_tx_clk_2), - .qsfp1_tx_rst_2(qsfp1_tx_rst_2), - .qsfp1_txd_2(qsfp1_txd_2), - .qsfp1_txc_2(qsfp1_txc_2), - .qsfp1_rx_clk_2(qsfp1_rx_clk_2), - .qsfp1_rx_rst_2(qsfp1_rx_rst_2), - .qsfp1_rxd_2(qsfp1_rxd_2), - .qsfp1_rxc_2(qsfp1_rxc_2), - .qsfp1_tx_clk_3(qsfp1_tx_clk_3), - .qsfp1_tx_rst_3(qsfp1_tx_rst_3), - .qsfp1_txd_3(qsfp1_txd_3), - .qsfp1_txc_3(qsfp1_txc_3), - .qsfp1_rx_clk_3(qsfp1_rx_clk_3), - .qsfp1_rx_rst_3(qsfp1_rx_rst_3), - .qsfp1_rxd_3(qsfp1_rxd_3), - .qsfp1_rxc_3(qsfp1_rxc_3), - .qsfp1_tx_clk_4(qsfp1_tx_clk_4), - .qsfp1_tx_rst_4(qsfp1_tx_rst_4), - .qsfp1_txd_4(qsfp1_txd_4), - .qsfp1_txc_4(qsfp1_txc_4), - .qsfp1_rx_clk_4(qsfp1_rx_clk_4), - .qsfp1_rx_rst_4(qsfp1_rx_rst_4), - .qsfp1_rxd_4(qsfp1_rxd_4), - .qsfp1_rxc_4(qsfp1_rxc_4), - .qsfp2_tx_clk_1(qsfp2_tx_clk_1), - .qsfp2_tx_rst_1(qsfp2_tx_rst_1), - .qsfp2_txd_1(qsfp2_txd_1), - .qsfp2_txc_1(qsfp2_txc_1), - .qsfp2_rx_clk_1(qsfp2_rx_clk_1), - .qsfp2_rx_rst_1(qsfp2_rx_rst_1), - .qsfp2_rxd_1(qsfp2_rxd_1), - .qsfp2_rxc_1(qsfp2_rxc_1), - .qsfp2_tx_clk_2(qsfp2_tx_clk_2), - .qsfp2_tx_rst_2(qsfp2_tx_rst_2), - .qsfp2_txd_2(qsfp2_txd_2), - .qsfp2_txc_2(qsfp2_txc_2), - .qsfp2_rx_clk_2(qsfp2_rx_clk_2), - .qsfp2_rx_rst_2(qsfp2_rx_rst_2), - .qsfp2_rxd_2(qsfp2_rxd_2), - .qsfp2_rxc_2(qsfp2_rxc_2), - .qsfp2_tx_clk_3(qsfp2_tx_clk_3), - .qsfp2_tx_rst_3(qsfp2_tx_rst_3), - .qsfp2_txd_3(qsfp2_txd_3), - .qsfp2_txc_3(qsfp2_txc_3), - .qsfp2_rx_clk_3(qsfp2_rx_clk_3), - .qsfp2_rx_rst_3(qsfp2_rx_rst_3), - .qsfp2_rxd_3(qsfp2_rxd_3), - .qsfp2_rxc_3(qsfp2_rxc_3), - .qsfp2_tx_clk_4(qsfp2_tx_clk_4), - .qsfp2_tx_rst_4(qsfp2_tx_rst_4), - .qsfp2_txd_4(qsfp2_txd_4), - .qsfp2_txc_4(qsfp2_txc_4), - .qsfp2_rx_clk_4(qsfp2_rx_clk_4), - .qsfp2_rx_rst_4(qsfp2_rx_rst_4), - .qsfp2_rxd_4(qsfp2_rxd_4), - .qsfp2_rxc_4(qsfp2_rxc_4), - .phy_gmii_clk(phy_gmii_clk), - .phy_gmii_rst(phy_gmii_rst), - .phy_gmii_clk_en(phy_gmii_clk_en), - .phy_gmii_rxd(phy_gmii_rxd), - .phy_gmii_rx_dv(phy_gmii_rx_dv), - .phy_gmii_rx_er(phy_gmii_rx_er), - .phy_gmii_txd(phy_gmii_txd), - .phy_gmii_tx_en(phy_gmii_tx_en), - .phy_gmii_tx_er(phy_gmii_tx_er), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/VCU118/fpga_10g/tb/udp_ep.py b/example/VCU118/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/VCU118/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_10g/tb/xgmii_ep.py b/example/VCU118/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/VCU118/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_1g/tb/arp_ep.py b/example/VCU118/fpga_1g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/VCU118/fpga_1g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_1g/tb/axis_ep.py b/example/VCU118/fpga_1g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/VCU118/fpga_1g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_1g/tb/eth_ep.py b/example/VCU118/fpga_1g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/VCU118/fpga_1g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_1g/tb/fpga_core/Makefile b/example/VCU118/fpga_1g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aafe627c --- /dev/null +++ b/example/VCU118/fpga_1g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..04e3ff69f --- /dev/null +++ b/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,218 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink + + +class TB: + def __init__(self, dut, speed=1000): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_cts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.phy_gmii_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.phy_gmii_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/VCU118/fpga_1g/tb/gmii_ep.py b/example/VCU118/fpga_1g/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/VCU118/fpga_1g/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_1g/tb/ip_ep.py b/example/VCU118/fpga_1g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/VCU118/fpga_1g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_1g/tb/test_fpga_core.py b/example/VCU118/fpga_1g/tb/test_fpga_core.py deleted file mode 100755 index 5e2d1bee9..000000000 --- a/example/VCU118/fpga_1g/tb/test_fpga_core.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen.v") -srcs.append("../lib/eth/rtl/udp.v") -srcs.append("../lib/eth/rtl/udp_ip_rx.v") -srcs.append("../lib/eth/rtl/udp_ip_tx.v") -srcs.append("../lib/eth/rtl/ip_complete.v") -srcs.append("../lib/eth/rtl/ip.v") -srcs.append("../lib/eth/rtl/ip_eth_rx.v") -srcs.append("../lib/eth/rtl/ip_eth_tx.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[4:]) - phy_gmii_clk = Signal(bool(0)) - phy_gmii_rst = Signal(bool(0)) - phy_gmii_clk_en = Signal(bool(0)) - phy_gmii_rxd = Signal(intbv(0)[8:]) - phy_gmii_rx_dv = Signal(bool(0)) - phy_gmii_rx_er = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - phy_gmii_txd = Signal(intbv(0)[8:]) - phy_gmii_tx_en = Signal(bool(0)) - phy_gmii_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # sources and sinks - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_gmii_clk, - phy_gmii_rst, - txd=phy_gmii_rxd, - tx_en=phy_gmii_rx_dv, - tx_er=phy_gmii_rx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_gmii_clk, - phy_gmii_rst, - rxd=phy_gmii_txd, - rx_dv=phy_gmii_tx_en, - rx_er=phy_gmii_tx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - phy_gmii_clk=phy_gmii_clk, - phy_gmii_rst=phy_gmii_rst, - phy_gmii_clk_en=phy_gmii_clk_en, - phy_gmii_rxd=phy_gmii_rxd, - phy_gmii_rx_dv=phy_gmii_rx_dv, - phy_gmii_rx_er=phy_gmii_rx_er, - phy_gmii_txd=phy_gmii_txd, - phy_gmii_tx_en=phy_gmii_tx_en, - phy_gmii_tx_er=phy_gmii_tx_er, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - phy_gmii_clk.next = not phy_gmii_clk - - clk_enable_rate = Signal(int(0)) - clk_enable_div = Signal(int(0)) - - @always(clk.posedge) - def clk_enable_gen(): - if clk_enable_div.next > 0: - phy_gmii_clk_en.next = 0 - clk_enable_div.next = clk_enable_div - 1 - else: - phy_gmii_clk_en.next = 1 - clk_enable_div.next = clk_enable_rate - 1 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - phy_gmii_rst.next = 1 - yield clk.posedge - rst.next = 0 - phy_gmii_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/VCU118/fpga_1g/tb/test_fpga_core.v b/example/VCU118/fpga_1g/tb/test_fpga_core.v deleted file mode 100644 index e3de43465..000000000 --- a/example/VCU118/fpga_1g/tb/test_fpga_core.v +++ /dev/null @@ -1,131 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [3:0] sw = 0; -reg phy_gmii_clk = 0; -reg phy_gmii_rst = 0; -reg phy_gmii_clk_en = 0; -reg [7:0] phy_gmii_rxd = 0; -reg phy_gmii_rx_dv = 0; -reg phy_gmii_rx_er = 0; -reg phy_int_n = 1; -reg uart_rxd = 0; -reg uart_cts = 0; - -// Outputs -wire [7:0] led; -wire [7:0] phy_gmii_txd; -wire phy_gmii_tx_en; -wire phy_gmii_tx_er; -wire phy_reset_n; -wire uart_txd; -wire uart_rts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - phy_gmii_clk, - phy_gmii_rst, - phy_gmii_clk_en, - phy_gmii_rxd, - phy_gmii_rx_dv, - phy_gmii_rx_er, - phy_int_n, - uart_rxd, - uart_cts - ); - $to_myhdl( - led, - phy_gmii_txd, - phy_gmii_tx_en, - phy_gmii_tx_er, - phy_reset_n, - uart_txd, - uart_rts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .phy_gmii_clk(phy_gmii_clk), - .phy_gmii_rst(phy_gmii_rst), - .phy_gmii_clk_en(phy_gmii_clk_en), - .phy_gmii_rxd(phy_gmii_rxd), - .phy_gmii_rx_dv(phy_gmii_rx_dv), - .phy_gmii_rx_er(phy_gmii_rx_er), - .phy_gmii_txd(phy_gmii_txd), - .phy_gmii_tx_en(phy_gmii_tx_en), - .phy_gmii_tx_er(phy_gmii_tx_er), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/VCU118/fpga_1g/tb/udp_ep.py b/example/VCU118/fpga_1g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/VCU118/fpga_1g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/arp_ep.py b/example/VCU118/fpga_25g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/VCU118/fpga_25g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/axis_ep.py b/example/VCU118/fpga_25g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/VCU118/fpga_25g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/eth_ep.py b/example/VCU118/fpga_25g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/VCU118/fpga_25g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/fpga_core/Makefile b/example/VCU118/fpga_25g/tb/fpga_core/Makefile new file mode 100644 index 000000000..14b7969eb --- /dev/null +++ b/example/VCU118/fpga_25g/tb/fpga_core/Makefile @@ -0,0 +1,106 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_switch.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_register.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..a0e26ae8b --- /dev/null +++ b/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,402 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 2.56, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_1, 2.56, units="ns").start()) + self.qsfp1_1_source = XgmiiSource(dut.qsfp1_rxd_1, dut.qsfp1_rxc_1, dut.qsfp1_rx_clk_1, dut.qsfp1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp1_tx_clk_1, 2.56, units="ns").start()) + self.qsfp1_1_sink = XgmiiSink(dut.qsfp1_txd_1, dut.qsfp1_txc_1, dut.qsfp1_tx_clk_1, dut.qsfp1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_2, 2.56, units="ns").start()) + self.qsfp1_2_source = XgmiiSource(dut.qsfp1_rxd_2, dut.qsfp1_rxc_2, dut.qsfp1_rx_clk_2, dut.qsfp1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp1_tx_clk_2, 2.56, units="ns").start()) + self.qsfp1_2_sink = XgmiiSink(dut.qsfp1_txd_2, dut.qsfp1_txc_2, dut.qsfp1_tx_clk_2, dut.qsfp1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_3, 2.56, units="ns").start()) + self.qsfp1_3_source = XgmiiSource(dut.qsfp1_rxd_3, dut.qsfp1_rxc_3, dut.qsfp1_rx_clk_3, dut.qsfp1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp1_tx_clk_3, 2.56, units="ns").start()) + self.qsfp1_3_sink = XgmiiSink(dut.qsfp1_txd_3, dut.qsfp1_txc_3, dut.qsfp1_tx_clk_3, dut.qsfp1_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_4, 2.56, units="ns").start()) + self.qsfp1_4_source = XgmiiSource(dut.qsfp1_rxd_4, dut.qsfp1_rxc_4, dut.qsfp1_rx_clk_4, dut.qsfp1_rx_rst_4) + cocotb.fork(Clock(dut.qsfp1_tx_clk_4, 2.56, units="ns").start()) + self.qsfp1_4_sink = XgmiiSink(dut.qsfp1_txd_4, dut.qsfp1_txc_4, dut.qsfp1_tx_clk_4, dut.qsfp1_tx_rst_4) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_1, 2.56, units="ns").start()) + self.qsfp2_1_source = XgmiiSource(dut.qsfp2_rxd_1, dut.qsfp2_rxc_1, dut.qsfp2_rx_clk_1, dut.qsfp2_rx_rst_1) + cocotb.fork(Clock(dut.qsfp2_tx_clk_1, 2.56, units="ns").start()) + self.qsfp2_1_sink = XgmiiSink(dut.qsfp2_txd_1, dut.qsfp2_txc_1, dut.qsfp2_tx_clk_1, dut.qsfp2_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_2, 2.56, units="ns").start()) + self.qsfp2_2_source = XgmiiSource(dut.qsfp2_rxd_2, dut.qsfp2_rxc_2, dut.qsfp2_rx_clk_2, dut.qsfp2_rx_rst_2) + cocotb.fork(Clock(dut.qsfp2_tx_clk_2, 2.56, units="ns").start()) + self.qsfp2_2_sink = XgmiiSink(dut.qsfp2_txd_2, dut.qsfp2_txc_2, dut.qsfp2_tx_clk_2, dut.qsfp2_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_3, 2.56, units="ns").start()) + self.qsfp2_3_source = XgmiiSource(dut.qsfp2_rxd_3, dut.qsfp2_rxc_3, dut.qsfp2_rx_clk_3, dut.qsfp2_rx_rst_3) + cocotb.fork(Clock(dut.qsfp2_tx_clk_3, 2.56, units="ns").start()) + self.qsfp2_3_sink = XgmiiSink(dut.qsfp2_txd_3, dut.qsfp2_txc_3, dut.qsfp2_tx_clk_3, dut.qsfp2_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp2_rx_clk_4, 2.56, units="ns").start()) + self.qsfp2_4_source = XgmiiSource(dut.qsfp2_rxd_4, dut.qsfp2_rxc_4, dut.qsfp2_rx_clk_4, dut.qsfp2_rx_rst_4) + cocotb.fork(Clock(dut.qsfp2_tx_clk_4, 2.56, units="ns").start()) + self.qsfp2_4_sink = XgmiiSink(dut.qsfp2_txd_4, dut.qsfp2_txc_4, dut.qsfp2_tx_clk_4, dut.qsfp2_tx_rst_4) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_cts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_4.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp2_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp2_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.phy_gmii_rst <= 1 + self.dut.qsfp1_rx_rst_1 <= 1 + self.dut.qsfp1_tx_rst_1 <= 1 + self.dut.qsfp1_rx_rst_2 <= 1 + self.dut.qsfp1_tx_rst_2 <= 1 + self.dut.qsfp1_rx_rst_3 <= 1 + self.dut.qsfp1_tx_rst_3 <= 1 + self.dut.qsfp1_rx_rst_4 <= 1 + self.dut.qsfp1_tx_rst_4 <= 1 + self.dut.qsfp2_rx_rst_1 <= 1 + self.dut.qsfp2_tx_rst_1 <= 1 + self.dut.qsfp2_rx_rst_2 <= 1 + self.dut.qsfp2_tx_rst_2 <= 1 + self.dut.qsfp2_rx_rst_3 <= 1 + self.dut.qsfp2_tx_rst_3 <= 1 + self.dut.qsfp2_rx_rst_4 <= 1 + self.dut.qsfp2_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.phy_gmii_rst <= 0 + self.dut.qsfp1_rx_rst_1 <= 0 + self.dut.qsfp1_tx_rst_1 <= 0 + self.dut.qsfp1_rx_rst_2 <= 0 + self.dut.qsfp1_tx_rst_2 <= 0 + self.dut.qsfp1_rx_rst_3 <= 0 + self.dut.qsfp1_tx_rst_3 <= 0 + self.dut.qsfp1_rx_rst_4 <= 0 + self.dut.qsfp1_tx_rst_4 <= 0 + self.dut.qsfp2_rx_rst_1 <= 0 + self.dut.qsfp2_tx_rst_1 <= 0 + self.dut.qsfp2_rx_rst_2 <= 0 + self.dut.qsfp2_tx_rst_2 <= 0 + self.dut.qsfp2_rx_rst_3 <= 0 + self.dut.qsfp2_tx_rst_3 <= 0 + self.dut.qsfp2_rx_rst_4 <= 0 + self.dut.qsfp2_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp1_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp1_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + tb.log.info("test gigabit tap, RX side") + + # insert tap + await RisingEdge(dut.clk) + dut.sw <= 0x8 + await RisingEdge(dut.clk) + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("loop back packet on XGMII interface") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + await tb.qsfp1_1_source.send(rx_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + tb.log.info("test gigabit tap, TX side") + + # insert tap + await RisingEdge(dut.clk) + dut.sw <= 0xC + await RisingEdge(dut.clk) + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("loop back packet on XGMII interface") + + rx_frame = await tb.qsfp1_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + await tb.qsfp1_1_source.send(rx_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_switch.v"), + os.path.join(axis_rtl_dir, "axis_register.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/VCU118/fpga_25g/tb/gmii_ep.py b/example/VCU118/fpga_25g/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/VCU118/fpga_25g/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/ip_ep.py b/example/VCU118/fpga_25g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/VCU118/fpga_25g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/test_fpga_core.py b/example/VCU118/fpga_25g/tb/test_fpga_core.py deleted file mode 100755 index 725c2d6df..000000000 --- a/example/VCU118/fpga_25g/tb/test_fpga_core.py +++ /dev/null @@ -1,688 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_adapter.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_switch.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[4:]) - qsfp1_tx_clk_1 = Signal(bool(0)) - qsfp1_tx_rst_1 = Signal(bool(0)) - qsfp1_rx_clk_1 = Signal(bool(0)) - qsfp1_rx_rst_1 = Signal(bool(0)) - qsfp1_rxd_1 = Signal(intbv(0)[64:]) - qsfp1_rxc_1 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_2 = Signal(bool(0)) - qsfp1_tx_rst_2 = Signal(bool(0)) - qsfp1_rx_clk_2 = Signal(bool(0)) - qsfp1_rx_rst_2 = Signal(bool(0)) - qsfp1_rxd_2 = Signal(intbv(0)[64:]) - qsfp1_rxc_2 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_3 = Signal(bool(0)) - qsfp1_tx_rst_3 = Signal(bool(0)) - qsfp1_rx_clk_3 = Signal(bool(0)) - qsfp1_rx_rst_3 = Signal(bool(0)) - qsfp1_rxd_3 = Signal(intbv(0)[64:]) - qsfp1_rxc_3 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_4 = Signal(bool(0)) - qsfp1_tx_rst_4 = Signal(bool(0)) - qsfp1_rx_clk_4 = Signal(bool(0)) - qsfp1_rx_rst_4 = Signal(bool(0)) - qsfp1_rxd_4 = Signal(intbv(0)[64:]) - qsfp1_rxc_4 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_1 = Signal(bool(0)) - qsfp2_tx_rst_1 = Signal(bool(0)) - qsfp2_rx_clk_1 = Signal(bool(0)) - qsfp2_rx_rst_1 = Signal(bool(0)) - qsfp2_rxd_1 = Signal(intbv(0)[64:]) - qsfp2_rxc_1 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_2 = Signal(bool(0)) - qsfp2_tx_rst_2 = Signal(bool(0)) - qsfp2_rx_clk_2 = Signal(bool(0)) - qsfp2_rx_rst_2 = Signal(bool(0)) - qsfp2_rxd_2 = Signal(intbv(0)[64:]) - qsfp2_rxc_2 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_3 = Signal(bool(0)) - qsfp2_tx_rst_3 = Signal(bool(0)) - qsfp2_rx_clk_3 = Signal(bool(0)) - qsfp2_rx_rst_3 = Signal(bool(0)) - qsfp2_rxd_3 = Signal(intbv(0)[64:]) - qsfp2_rxc_3 = Signal(intbv(0)[8:]) - qsfp2_tx_clk_4 = Signal(bool(0)) - qsfp2_tx_rst_4 = Signal(bool(0)) - qsfp2_rx_clk_4 = Signal(bool(0)) - qsfp2_rx_rst_4 = Signal(bool(0)) - qsfp2_rxd_4 = Signal(intbv(0)[64:]) - qsfp2_rxc_4 = Signal(intbv(0)[8:]) - phy_gmii_clk = Signal(bool(0)) - phy_gmii_rst = Signal(bool(0)) - phy_gmii_clk_en = Signal(bool(0)) - phy_gmii_rxd = Signal(intbv(0)[8:]) - phy_gmii_rx_dv = Signal(bool(0)) - phy_gmii_rx_er = Signal(bool(0)) - phy_int_n = Signal(bool(1)) - uart_rxd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - qsfp1_txd_1 = Signal(intbv(0)[64:]) - qsfp1_txc_1 = Signal(intbv(0)[8:]) - qsfp1_txd_2 = Signal(intbv(0)[64:]) - qsfp1_txc_2 = Signal(intbv(0)[8:]) - qsfp1_txd_3 = Signal(intbv(0)[64:]) - qsfp1_txc_3 = Signal(intbv(0)[8:]) - qsfp1_txd_4 = Signal(intbv(0)[64:]) - qsfp1_txc_4 = Signal(intbv(0)[8:]) - qsfp2_txd_1 = Signal(intbv(0)[64:]) - qsfp2_txc_1 = Signal(intbv(0)[8:]) - qsfp2_txd_2 = Signal(intbv(0)[64:]) - qsfp2_txc_2 = Signal(intbv(0)[8:]) - qsfp2_txd_3 = Signal(intbv(0)[64:]) - qsfp2_txc_3 = Signal(intbv(0)[8:]) - qsfp2_txd_4 = Signal(intbv(0)[64:]) - qsfp2_txc_4 = Signal(intbv(0)[8:]) - phy_gmii_txd = Signal(intbv(0)[8:]) - phy_gmii_tx_en = Signal(bool(0)) - phy_gmii_tx_er = Signal(bool(0)) - phy_reset_n = Signal(bool(0)) - uart_txd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # sources and sinks - qsfp1_1_source = xgmii_ep.XGMIISource() - qsfp1_1_source_logic = qsfp1_1_source.create_logic(qsfp1_rx_clk_1, qsfp1_rx_rst_1, txd=qsfp1_rxd_1, txc=qsfp1_rxc_1, name='qsfp1_1_source') - - qsfp1_1_sink = xgmii_ep.XGMIISink() - qsfp1_1_sink_logic = qsfp1_1_sink.create_logic(qsfp1_tx_clk_1, qsfp1_tx_rst_1, rxd=qsfp1_txd_1, rxc=qsfp1_txc_1, name='qsfp1_1_sink') - - qsfp1_2_source = xgmii_ep.XGMIISource() - qsfp1_2_source_logic = qsfp1_2_source.create_logic(qsfp1_rx_clk_2, qsfp1_rx_rst_2, txd=qsfp1_rxd_2, txc=qsfp1_rxc_2, name='qsfp1_2_source') - - qsfp1_2_sink = xgmii_ep.XGMIISink() - qsfp1_2_sink_logic = qsfp1_2_sink.create_logic(qsfp1_tx_clk_2, qsfp1_tx_rst_2, rxd=qsfp1_txd_2, rxc=qsfp1_txc_2, name='qsfp1_2_sink') - - qsfp1_3_source = xgmii_ep.XGMIISource() - qsfp1_3_source_logic = qsfp1_3_source.create_logic(qsfp1_rx_clk_3, qsfp1_rx_rst_3, txd=qsfp1_rxd_3, txc=qsfp1_rxc_3, name='qsfp1_3_source') - - qsfp1_3_sink = xgmii_ep.XGMIISink() - qsfp1_3_sink_logic = qsfp1_3_sink.create_logic(qsfp1_tx_clk_3, qsfp1_tx_rst_3, rxd=qsfp1_txd_3, rxc=qsfp1_txc_3, name='qsfp1_3_sink') - - qsfp1_4_source = xgmii_ep.XGMIISource() - qsfp1_4_source_logic = qsfp1_4_source.create_logic(qsfp1_rx_clk_4, qsfp1_rx_rst_4, txd=qsfp1_rxd_4, txc=qsfp1_rxc_4, name='qsfp1_4_source') - - qsfp1_4_sink = xgmii_ep.XGMIISink() - qsfp1_4_sink_logic = qsfp1_4_sink.create_logic(qsfp1_tx_clk_4, qsfp1_tx_rst_4, rxd=qsfp1_txd_4, rxc=qsfp1_txc_4, name='qsfp1_4_sink') - - qsfp2_1_source = xgmii_ep.XGMIISource() - qsfp2_1_source_logic = qsfp2_1_source.create_logic(qsfp2_rx_clk_1, qsfp2_rx_rst_1, txd=qsfp2_rxd_1, txc=qsfp2_rxc_1, name='qsfp2_1_source') - - qsfp2_1_sink = xgmii_ep.XGMIISink() - qsfp2_1_sink_logic = qsfp2_1_sink.create_logic(qsfp2_tx_clk_1, qsfp2_tx_rst_1, rxd=qsfp2_txd_1, rxc=qsfp2_txc_1, name='qsfp2_1_sink') - - qsfp2_2_source = xgmii_ep.XGMIISource() - qsfp2_2_source_logic = qsfp2_2_source.create_logic(qsfp2_rx_clk_2, qsfp2_rx_rst_2, txd=qsfp2_rxd_2, txc=qsfp2_rxc_2, name='qsfp2_2_source') - - qsfp2_2_sink = xgmii_ep.XGMIISink() - qsfp2_2_sink_logic = qsfp2_2_sink.create_logic(qsfp2_tx_clk_2, qsfp2_tx_rst_2, rxd=qsfp2_txd_2, rxc=qsfp2_txc_2, name='qsfp2_2_sink') - - qsfp2_3_source = xgmii_ep.XGMIISource() - qsfp2_3_source_logic = qsfp2_3_source.create_logic(qsfp2_rx_clk_3, qsfp2_rx_rst_3, txd=qsfp2_rxd_3, txc=qsfp2_rxc_3, name='qsfp2_3_source') - - qsfp2_3_sink = xgmii_ep.XGMIISink() - qsfp2_3_sink_logic = qsfp2_3_sink.create_logic(qsfp2_tx_clk_3, qsfp2_tx_rst_3, rxd=qsfp2_txd_3, rxc=qsfp2_txc_3, name='qsfp2_3_sink') - - qsfp2_4_source = xgmii_ep.XGMIISource() - qsfp2_4_source_logic = qsfp2_4_source.create_logic(qsfp2_rx_clk_4, qsfp2_rx_rst_4, txd=qsfp2_rxd_4, txc=qsfp2_rxc_4, name='qsfp2_4_source') - - qsfp2_4_sink = xgmii_ep.XGMIISink() - qsfp2_4_sink_logic = qsfp2_4_sink.create_logic(qsfp2_tx_clk_4, qsfp2_tx_rst_4, rxd=qsfp2_txd_4, rxc=qsfp2_txc_4, name='qsfp2_4_sink') - - gmii_source = gmii_ep.GMIISource() - - gmii_source_logic = gmii_source.create_logic( - phy_gmii_clk, - phy_gmii_rst, - txd=phy_gmii_rxd, - tx_en=phy_gmii_rx_dv, - tx_er=phy_gmii_rx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_source' - ) - - gmii_sink = gmii_ep.GMIISink() - - gmii_sink_logic = gmii_sink.create_logic( - phy_gmii_clk, - phy_gmii_rst, - rxd=phy_gmii_txd, - rx_dv=phy_gmii_tx_en, - rx_er=phy_gmii_tx_er, - clk_enable=phy_gmii_clk_en, - name='gmii_sink' - ) - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - qsfp1_tx_clk_1=qsfp1_tx_clk_1, - qsfp1_tx_rst_1=qsfp1_tx_rst_1, - qsfp1_txd_1=qsfp1_txd_1, - qsfp1_txc_1=qsfp1_txc_1, - qsfp1_rx_clk_1=qsfp1_rx_clk_1, - qsfp1_rx_rst_1=qsfp1_rx_rst_1, - qsfp1_rxd_1=qsfp1_rxd_1, - qsfp1_rxc_1=qsfp1_rxc_1, - qsfp1_tx_clk_2=qsfp1_tx_clk_2, - qsfp1_tx_rst_2=qsfp1_tx_rst_2, - qsfp1_txd_2=qsfp1_txd_2, - qsfp1_txc_2=qsfp1_txc_2, - qsfp1_rx_clk_2=qsfp1_rx_clk_2, - qsfp1_rx_rst_2=qsfp1_rx_rst_2, - qsfp1_rxd_2=qsfp1_rxd_2, - qsfp1_rxc_2=qsfp1_rxc_2, - qsfp1_tx_clk_3=qsfp1_tx_clk_3, - qsfp1_tx_rst_3=qsfp1_tx_rst_3, - qsfp1_txd_3=qsfp1_txd_3, - qsfp1_txc_3=qsfp1_txc_3, - qsfp1_rx_clk_3=qsfp1_rx_clk_3, - qsfp1_rx_rst_3=qsfp1_rx_rst_3, - qsfp1_rxd_3=qsfp1_rxd_3, - qsfp1_rxc_3=qsfp1_rxc_3, - qsfp1_tx_clk_4=qsfp1_tx_clk_4, - qsfp1_tx_rst_4=qsfp1_tx_rst_4, - qsfp1_txd_4=qsfp1_txd_4, - qsfp1_txc_4=qsfp1_txc_4, - qsfp1_rx_clk_4=qsfp1_rx_clk_4, - qsfp1_rx_rst_4=qsfp1_rx_rst_4, - qsfp1_rxd_4=qsfp1_rxd_4, - qsfp1_rxc_4=qsfp1_rxc_4, - qsfp2_tx_clk_1=qsfp2_tx_clk_1, - qsfp2_tx_rst_1=qsfp2_tx_rst_1, - qsfp2_txd_1=qsfp2_txd_1, - qsfp2_txc_1=qsfp2_txc_1, - qsfp2_rx_clk_1=qsfp2_rx_clk_1, - qsfp2_rx_rst_1=qsfp2_rx_rst_1, - qsfp2_rxd_1=qsfp2_rxd_1, - qsfp2_rxc_1=qsfp2_rxc_1, - qsfp2_tx_clk_2=qsfp2_tx_clk_2, - qsfp2_tx_rst_2=qsfp2_tx_rst_2, - qsfp2_txd_2=qsfp2_txd_2, - qsfp2_txc_2=qsfp2_txc_2, - qsfp2_rx_clk_2=qsfp2_rx_clk_2, - qsfp2_rx_rst_2=qsfp2_rx_rst_2, - qsfp2_rxd_2=qsfp2_rxd_2, - qsfp2_rxc_2=qsfp2_rxc_2, - qsfp2_tx_clk_3=qsfp2_tx_clk_3, - qsfp2_tx_rst_3=qsfp2_tx_rst_3, - qsfp2_txd_3=qsfp2_txd_3, - qsfp2_txc_3=qsfp2_txc_3, - qsfp2_rx_clk_3=qsfp2_rx_clk_3, - qsfp2_rx_rst_3=qsfp2_rx_rst_3, - qsfp2_rxd_3=qsfp2_rxd_3, - qsfp2_rxc_3=qsfp2_rxc_3, - qsfp2_tx_clk_4=qsfp2_tx_clk_4, - qsfp2_tx_rst_4=qsfp2_tx_rst_4, - qsfp2_txd_4=qsfp2_txd_4, - qsfp2_txc_4=qsfp2_txc_4, - qsfp2_rx_clk_4=qsfp2_rx_clk_4, - qsfp2_rx_rst_4=qsfp2_rx_rst_4, - qsfp2_rxd_4=qsfp2_rxd_4, - qsfp2_rxc_4=qsfp2_rxc_4, - - phy_gmii_clk=phy_gmii_clk, - phy_gmii_rst=phy_gmii_rst, - phy_gmii_clk_en=phy_gmii_clk_en, - phy_gmii_rxd=phy_gmii_rxd, - phy_gmii_rx_dv=phy_gmii_rx_dv, - phy_gmii_rx_er=phy_gmii_rx_er, - phy_gmii_txd=phy_gmii_txd, - phy_gmii_tx_en=phy_gmii_tx_en, - phy_gmii_tx_er=phy_gmii_tx_er, - phy_reset_n=phy_reset_n, - phy_int_n=phy_int_n, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp1_tx_clk_1.next = not qsfp1_tx_clk_1 - qsfp1_rx_clk_1.next = not qsfp1_rx_clk_1 - qsfp1_tx_clk_2.next = not qsfp1_tx_clk_2 - qsfp1_rx_clk_2.next = not qsfp1_rx_clk_2 - qsfp1_tx_clk_3.next = not qsfp1_tx_clk_3 - qsfp1_rx_clk_3.next = not qsfp1_rx_clk_3 - qsfp1_tx_clk_4.next = not qsfp1_tx_clk_4 - qsfp1_rx_clk_4.next = not qsfp1_rx_clk_4 - qsfp2_tx_clk_1.next = not qsfp2_tx_clk_1 - qsfp2_rx_clk_1.next = not qsfp2_rx_clk_1 - qsfp2_tx_clk_2.next = not qsfp2_tx_clk_2 - qsfp2_rx_clk_2.next = not qsfp2_rx_clk_2 - qsfp2_tx_clk_3.next = not qsfp2_tx_clk_3 - qsfp2_rx_clk_3.next = not qsfp2_rx_clk_3 - qsfp2_tx_clk_4.next = not qsfp2_tx_clk_4 - qsfp2_rx_clk_4.next = not qsfp2_rx_clk_4 - phy_gmii_clk.next = not phy_gmii_clk - - clk_enable_rate = Signal(int(0)) - clk_enable_div = Signal(int(0)) - - @always(clk.posedge) - def clk_enable_gen(): - if clk_enable_div.next > 0: - phy_gmii_clk_en.next = 0 - clk_enable_div.next = clk_enable_div - 1 - else: - phy_gmii_clk_en.next = 1 - clk_enable_div.next = clk_enable_rate - 1 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp1_tx_rst_1.next = 1 - qsfp1_rx_rst_1.next = 1 - qsfp1_tx_rst_2.next = 1 - qsfp1_rx_rst_2.next = 1 - qsfp1_tx_rst_3.next = 1 - qsfp1_rx_rst_3.next = 1 - qsfp1_tx_rst_4.next = 1 - qsfp1_rx_rst_4.next = 1 - qsfp2_tx_rst_1.next = 1 - qsfp2_rx_rst_1.next = 1 - qsfp2_tx_rst_2.next = 1 - qsfp2_rx_rst_2.next = 1 - qsfp2_tx_rst_3.next = 1 - qsfp2_rx_rst_3.next = 1 - qsfp2_tx_rst_4.next = 1 - qsfp2_rx_rst_4.next = 1 - phy_gmii_rst.next = 1 - yield clk.posedge - rst.next = 0 - qsfp1_tx_rst_1.next = 0 - qsfp1_rx_rst_1.next = 0 - qsfp1_tx_rst_2.next = 0 - qsfp1_rx_rst_2.next = 0 - qsfp1_tx_rst_3.next = 0 - qsfp1_rx_rst_3.next = 0 - qsfp1_tx_rst_4.next = 0 - qsfp1_rx_rst_4.next = 0 - qsfp2_tx_rst_1.next = 0 - qsfp2_rx_rst_1.next = 0 - qsfp2_tx_rst_2.next = 0 - qsfp2_rx_rst_2.next = 0 - qsfp2_tx_rst_3.next = 0 - qsfp2_rx_rst_3.next = 0 - qsfp2_tx_rst_4.next = 0 - qsfp2_rx_rst_4.next = 0 - phy_gmii_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp1_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp1_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp1_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp1_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp1_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp1_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp1_1_source.empty() - assert qsfp1_1_sink.empty() - - yield delay(100) - - yield clk.posedge - print("test 2: test gigabit tap") - current_test.next = 2 - - sw.next = 0x8 # enable tap on RX - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # loop packet back through on XGMII interface - while qsfp1_1_sink.empty(): - yield clk.posedge - - qsfp1_1_source.send(qsfp1_1_sink.recv()) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - assert qsfp1_1_source.empty() - assert qsfp1_1_sink.empty() - - yield delay(100) - - sw.next = 0xc # enable tap on TX - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # loop packet back through on XGMII interface - while qsfp1_1_sink.empty(): - yield clk.posedge - - qsfp1_1_source.send(qsfp1_1_sink.recv()) - - while gmii_sink.empty(): - yield clk.posedge - - rx_frame = gmii_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert gmii_source.empty() - assert gmii_sink.empty() - assert qsfp1_1_source.empty() - assert qsfp1_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/VCU118/fpga_25g/tb/test_fpga_core.v b/example/VCU118/fpga_25g/tb/test_fpga_core.v deleted file mode 100644 index 24db5dc0c..000000000 --- a/example/VCU118/fpga_25g/tb/test_fpga_core.v +++ /dev/null @@ -1,324 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [3:0] sw = 0; -reg qsfp1_tx_clk_1 = 0; -reg qsfp1_tx_rst_1 = 0; -reg qsfp1_rx_clk_1 = 0; -reg qsfp1_rx_rst_1 = 0; -reg [63:0] qsfp1_rxd_1 = 0; -reg [7:0] qsfp1_rxc_1 = 0; -reg qsfp1_tx_clk_2 = 0; -reg qsfp1_tx_rst_2 = 0; -reg qsfp1_rx_clk_2 = 0; -reg qsfp1_rx_rst_2 = 0; -reg [63:0] qsfp1_rxd_2 = 0; -reg [7:0] qsfp1_rxc_2 = 0; -reg qsfp1_tx_clk_3 = 0; -reg qsfp1_tx_rst_3 = 0; -reg qsfp1_rx_clk_3 = 0; -reg qsfp1_rx_rst_3 = 0; -reg [63:0] qsfp1_rxd_3 = 0; -reg [7:0] qsfp1_rxc_3 = 0; -reg qsfp1_tx_clk_4 = 0; -reg qsfp1_tx_rst_4 = 0; -reg qsfp1_rx_clk_4 = 0; -reg qsfp1_rx_rst_4 = 0; -reg [63:0] qsfp1_rxd_4 = 0; -reg [7:0] qsfp1_rxc_4 = 0; -reg qsfp2_tx_clk_1 = 0; -reg qsfp2_tx_rst_1 = 0; -reg qsfp2_rx_clk_1 = 0; -reg qsfp2_rx_rst_1 = 0; -reg [63:0] qsfp2_rxd_1 = 0; -reg [7:0] qsfp2_rxc_1 = 0; -reg qsfp2_tx_clk_2 = 0; -reg qsfp2_tx_rst_2 = 0; -reg qsfp2_rx_clk_2 = 0; -reg qsfp2_rx_rst_2 = 0; -reg [63:0] qsfp2_rxd_2 = 0; -reg [7:0] qsfp2_rxc_2 = 0; -reg qsfp2_tx_clk_3 = 0; -reg qsfp2_tx_rst_3 = 0; -reg qsfp2_rx_clk_3 = 0; -reg qsfp2_rx_rst_3 = 0; -reg [63:0] qsfp2_rxd_3 = 0; -reg [7:0] qsfp2_rxc_3 = 0; -reg qsfp2_tx_clk_4 = 0; -reg qsfp2_tx_rst_4 = 0; -reg qsfp2_rx_clk_4 = 0; -reg qsfp2_rx_rst_4 = 0; -reg [63:0] qsfp2_rxd_4 = 0; -reg [7:0] qsfp2_rxc_4 = 0; -reg phy_gmii_clk = 0; -reg phy_gmii_rst = 0; -reg phy_gmii_clk_en = 0; -reg [7:0] phy_gmii_rxd = 0; -reg phy_gmii_rx_dv = 0; -reg phy_gmii_rx_er = 0; -reg phy_int_n = 1; -reg uart_rxd = 0; -reg uart_cts = 0; - -// Outputs -wire [7:0] led; -wire [63:0] qsfp1_txd_1; -wire [7:0] qsfp1_txc_1; -wire [63:0] qsfp1_txd_2; -wire [7:0] qsfp1_txc_2; -wire [63:0] qsfp1_txd_3; -wire [7:0] qsfp1_txc_3; -wire [63:0] qsfp1_txd_4; -wire [7:0] qsfp1_txc_4; -wire [63:0] qsfp2_txd_1; -wire [7:0] qsfp2_txc_1; -wire [63:0] qsfp2_txd_2; -wire [7:0] qsfp2_txc_2; -wire [63:0] qsfp2_txd_3; -wire [7:0] qsfp2_txc_3; -wire [63:0] qsfp2_txd_4; -wire [7:0] qsfp2_txc_4; -wire phy_tx_clk; -wire [7:0] phy_gmii_txd; -wire phy_gmii_tx_en; -wire phy_gmii_tx_er; -wire phy_reset_n; -wire uart_txd; -wire uart_rts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - qsfp1_tx_clk_1, - qsfp1_tx_rst_1, - qsfp1_rx_clk_1, - qsfp1_rx_rst_1, - qsfp1_rxd_1, - qsfp1_rxc_1, - qsfp1_tx_clk_2, - qsfp1_tx_rst_2, - qsfp1_rx_clk_2, - qsfp1_rx_rst_2, - qsfp1_rxd_2, - qsfp1_rxc_2, - qsfp1_tx_clk_3, - qsfp1_tx_rst_3, - qsfp1_rx_clk_3, - qsfp1_rx_rst_3, - qsfp1_rxd_3, - qsfp1_rxc_3, - qsfp1_tx_clk_4, - qsfp1_tx_rst_4, - qsfp1_rx_clk_4, - qsfp1_rx_rst_4, - qsfp1_rxd_4, - qsfp1_rxc_4, - qsfp2_tx_clk_1, - qsfp2_tx_rst_1, - qsfp2_rx_clk_1, - qsfp2_rx_rst_1, - qsfp2_rxd_1, - qsfp2_rxc_1, - qsfp2_tx_clk_2, - qsfp2_tx_rst_2, - qsfp2_rx_clk_2, - qsfp2_rx_rst_2, - qsfp2_rxd_2, - qsfp2_rxc_2, - qsfp2_tx_clk_3, - qsfp2_tx_rst_3, - qsfp2_rx_clk_3, - qsfp2_rx_rst_3, - qsfp2_rxd_3, - qsfp2_rxc_3, - qsfp2_tx_clk_4, - qsfp2_tx_rst_4, - qsfp2_rx_clk_4, - qsfp2_rx_rst_4, - qsfp2_rxd_4, - qsfp2_rxc_4, - phy_gmii_clk, - phy_gmii_rst, - phy_gmii_clk_en, - phy_gmii_rxd, - phy_gmii_rx_dv, - phy_gmii_rx_er, - phy_int_n, - uart_rxd, - uart_cts - ); - $to_myhdl( - led, - qsfp1_txd_1, - qsfp1_txc_1, - qsfp1_txd_2, - qsfp1_txc_2, - qsfp1_txd_3, - qsfp1_txc_3, - qsfp1_txd_4, - qsfp1_txc_4, - qsfp2_txd_1, - qsfp2_txc_1, - qsfp2_txd_2, - qsfp2_txc_2, - qsfp2_txd_3, - qsfp2_txc_3, - qsfp2_txd_4, - qsfp2_txc_4, - phy_gmii_txd, - phy_gmii_tx_en, - phy_gmii_tx_er, - phy_reset_n, - uart_txd, - uart_rts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .qsfp1_tx_clk_1(qsfp1_tx_clk_1), - .qsfp1_tx_rst_1(qsfp1_tx_rst_1), - .qsfp1_txd_1(qsfp1_txd_1), - .qsfp1_txc_1(qsfp1_txc_1), - .qsfp1_rx_clk_1(qsfp1_rx_clk_1), - .qsfp1_rx_rst_1(qsfp1_rx_rst_1), - .qsfp1_rxd_1(qsfp1_rxd_1), - .qsfp1_rxc_1(qsfp1_rxc_1), - .qsfp1_tx_clk_2(qsfp1_tx_clk_2), - .qsfp1_tx_rst_2(qsfp1_tx_rst_2), - .qsfp1_txd_2(qsfp1_txd_2), - .qsfp1_txc_2(qsfp1_txc_2), - .qsfp1_rx_clk_2(qsfp1_rx_clk_2), - .qsfp1_rx_rst_2(qsfp1_rx_rst_2), - .qsfp1_rxd_2(qsfp1_rxd_2), - .qsfp1_rxc_2(qsfp1_rxc_2), - .qsfp1_tx_clk_3(qsfp1_tx_clk_3), - .qsfp1_tx_rst_3(qsfp1_tx_rst_3), - .qsfp1_txd_3(qsfp1_txd_3), - .qsfp1_txc_3(qsfp1_txc_3), - .qsfp1_rx_clk_3(qsfp1_rx_clk_3), - .qsfp1_rx_rst_3(qsfp1_rx_rst_3), - .qsfp1_rxd_3(qsfp1_rxd_3), - .qsfp1_rxc_3(qsfp1_rxc_3), - .qsfp1_tx_clk_4(qsfp1_tx_clk_4), - .qsfp1_tx_rst_4(qsfp1_tx_rst_4), - .qsfp1_txd_4(qsfp1_txd_4), - .qsfp1_txc_4(qsfp1_txc_4), - .qsfp1_rx_clk_4(qsfp1_rx_clk_4), - .qsfp1_rx_rst_4(qsfp1_rx_rst_4), - .qsfp1_rxd_4(qsfp1_rxd_4), - .qsfp1_rxc_4(qsfp1_rxc_4), - .qsfp2_tx_clk_1(qsfp2_tx_clk_1), - .qsfp2_tx_rst_1(qsfp2_tx_rst_1), - .qsfp2_txd_1(qsfp2_txd_1), - .qsfp2_txc_1(qsfp2_txc_1), - .qsfp2_rx_clk_1(qsfp2_rx_clk_1), - .qsfp2_rx_rst_1(qsfp2_rx_rst_1), - .qsfp2_rxd_1(qsfp2_rxd_1), - .qsfp2_rxc_1(qsfp2_rxc_1), - .qsfp2_tx_clk_2(qsfp2_tx_clk_2), - .qsfp2_tx_rst_2(qsfp2_tx_rst_2), - .qsfp2_txd_2(qsfp2_txd_2), - .qsfp2_txc_2(qsfp2_txc_2), - .qsfp2_rx_clk_2(qsfp2_rx_clk_2), - .qsfp2_rx_rst_2(qsfp2_rx_rst_2), - .qsfp2_rxd_2(qsfp2_rxd_2), - .qsfp2_rxc_2(qsfp2_rxc_2), - .qsfp2_tx_clk_3(qsfp2_tx_clk_3), - .qsfp2_tx_rst_3(qsfp2_tx_rst_3), - .qsfp2_txd_3(qsfp2_txd_3), - .qsfp2_txc_3(qsfp2_txc_3), - .qsfp2_rx_clk_3(qsfp2_rx_clk_3), - .qsfp2_rx_rst_3(qsfp2_rx_rst_3), - .qsfp2_rxd_3(qsfp2_rxd_3), - .qsfp2_rxc_3(qsfp2_rxc_3), - .qsfp2_tx_clk_4(qsfp2_tx_clk_4), - .qsfp2_tx_rst_4(qsfp2_tx_rst_4), - .qsfp2_txd_4(qsfp2_txd_4), - .qsfp2_txc_4(qsfp2_txc_4), - .qsfp2_rx_clk_4(qsfp2_rx_clk_4), - .qsfp2_rx_rst_4(qsfp2_rx_rst_4), - .qsfp2_rxd_4(qsfp2_rxd_4), - .qsfp2_rxc_4(qsfp2_rxc_4), - .phy_gmii_clk(phy_gmii_clk), - .phy_gmii_rst(phy_gmii_rst), - .phy_gmii_clk_en(phy_gmii_clk_en), - .phy_gmii_rxd(phy_gmii_rxd), - .phy_gmii_rx_dv(phy_gmii_rx_dv), - .phy_gmii_rx_er(phy_gmii_rx_er), - .phy_gmii_txd(phy_gmii_txd), - .phy_gmii_tx_en(phy_gmii_tx_en), - .phy_gmii_tx_er(phy_gmii_tx_er), - .phy_reset_n(phy_reset_n), - .phy_int_n(phy_int_n), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/VCU118/fpga_25g/tb/udp_ep.py b/example/VCU118/fpga_25g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/VCU118/fpga_25g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU118/fpga_25g/tb/xgmii_ep.py b/example/VCU118/fpga_25g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/VCU118/fpga_25g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/VCU1525/fpga_10g/tb/arp_ep.py b/example/VCU1525/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/VCU1525/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/VCU1525/fpga_10g/tb/axis_ep.py b/example/VCU1525/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/VCU1525/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/VCU1525/fpga_10g/tb/eth_ep.py b/example/VCU1525/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/VCU1525/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/VCU1525/fpga_10g/tb/fpga_core/Makefile b/example/VCU1525/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/VCU1525/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..74a58792d --- /dev/null +++ b/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,289 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp0_rx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_source = XgmiiSource(dut.qsfp0_rxd_1, dut.qsfp0_rxc_1, dut.qsfp0_rx_clk_1, dut.qsfp0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp0_tx_clk_1, 6.4, units="ns").start()) + self.qsfp0_1_sink = XgmiiSink(dut.qsfp0_txd_1, dut.qsfp0_txc_1, dut.qsfp0_tx_clk_1, dut.qsfp0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_source = XgmiiSource(dut.qsfp0_rxd_2, dut.qsfp0_rxc_2, dut.qsfp0_rx_clk_2, dut.qsfp0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp0_tx_clk_2, 6.4, units="ns").start()) + self.qsfp0_2_sink = XgmiiSink(dut.qsfp0_txd_2, dut.qsfp0_txc_2, dut.qsfp0_tx_clk_2, dut.qsfp0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_source = XgmiiSource(dut.qsfp0_rxd_3, dut.qsfp0_rxc_3, dut.qsfp0_rx_clk_3, dut.qsfp0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp0_tx_clk_3, 6.4, units="ns").start()) + self.qsfp0_3_sink = XgmiiSink(dut.qsfp0_txd_3, dut.qsfp0_txc_3, dut.qsfp0_tx_clk_3, dut.qsfp0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp0_rx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_source = XgmiiSource(dut.qsfp0_rxd_4, dut.qsfp0_rxc_4, dut.qsfp0_rx_clk_4, dut.qsfp0_rx_rst_4) + cocotb.fork(Clock(dut.qsfp0_tx_clk_4, 6.4, units="ns").start()) + self.qsfp0_4_sink = XgmiiSink(dut.qsfp0_txd_4, dut.qsfp0_txc_4, dut.qsfp0_tx_clk_4, dut.qsfp0_tx_rst_4) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_source = XgmiiSource(dut.qsfp1_rxd_1, dut.qsfp1_rxc_1, dut.qsfp1_rx_clk_1, dut.qsfp1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp1_1_sink = XgmiiSink(dut.qsfp1_txd_1, dut.qsfp1_txc_1, dut.qsfp1_tx_clk_1, dut.qsfp1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_source = XgmiiSource(dut.qsfp1_rxd_2, dut.qsfp1_rxc_2, dut.qsfp1_rx_clk_2, dut.qsfp1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp1_2_sink = XgmiiSink(dut.qsfp1_txd_2, dut.qsfp1_txc_2, dut.qsfp1_tx_clk_2, dut.qsfp1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_source = XgmiiSource(dut.qsfp1_rxd_3, dut.qsfp1_rxc_3, dut.qsfp1_rx_clk_3, dut.qsfp1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp1_3_sink = XgmiiSink(dut.qsfp1_txd_3, dut.qsfp1_txc_3, dut.qsfp1_tx_clk_3, dut.qsfp1_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp1_rx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_source = XgmiiSource(dut.qsfp1_rxd_4, dut.qsfp1_rxc_4, dut.qsfp1_rx_clk_4, dut.qsfp1_rx_rst_4) + cocotb.fork(Clock(dut.qsfp1_tx_clk_4, 6.4, units="ns").start()) + self.qsfp1_4_sink = XgmiiSink(dut.qsfp1_txd_4, dut.qsfp1_txc_4, dut.qsfp1_tx_clk_4, dut.qsfp1_tx_rst_4) + + dut.sw.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp0_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp0_tx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp1_rx_rst_4.setimmediatevalue(0) + self.dut.qsfp1_tx_rst_4.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp0_rx_rst_1 <= 1 + self.dut.qsfp0_tx_rst_1 <= 1 + self.dut.qsfp0_rx_rst_2 <= 1 + self.dut.qsfp0_tx_rst_2 <= 1 + self.dut.qsfp0_rx_rst_3 <= 1 + self.dut.qsfp0_tx_rst_3 <= 1 + self.dut.qsfp0_rx_rst_4 <= 1 + self.dut.qsfp0_tx_rst_4 <= 1 + self.dut.qsfp1_rx_rst_1 <= 1 + self.dut.qsfp1_tx_rst_1 <= 1 + self.dut.qsfp1_rx_rst_2 <= 1 + self.dut.qsfp1_tx_rst_2 <= 1 + self.dut.qsfp1_rx_rst_3 <= 1 + self.dut.qsfp1_tx_rst_3 <= 1 + self.dut.qsfp1_rx_rst_4 <= 1 + self.dut.qsfp1_tx_rst_4 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp0_rx_rst_1 <= 0 + self.dut.qsfp0_tx_rst_1 <= 0 + self.dut.qsfp0_rx_rst_2 <= 0 + self.dut.qsfp0_tx_rst_2 <= 0 + self.dut.qsfp0_rx_rst_3 <= 0 + self.dut.qsfp0_tx_rst_3 <= 0 + self.dut.qsfp0_rx_rst_4 <= 0 + self.dut.qsfp0_tx_rst_4 <= 0 + self.dut.qsfp1_rx_rst_1 <= 0 + self.dut.qsfp1_tx_rst_1 <= 0 + self.dut.qsfp1_rx_rst_2 <= 0 + self.dut.qsfp1_tx_rst_2 <= 0 + self.dut.qsfp1_rx_rst_3 <= 0 + self.dut.qsfp1_tx_rst_3 <= 0 + self.dut.qsfp1_rx_rst_4 <= 0 + self.dut.qsfp1_tx_rst_4 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp0_1_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp0_1_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp0_1_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/VCU1525/fpga_10g/tb/ip_ep.py b/example/VCU1525/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/VCU1525/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/VCU1525/fpga_10g/tb/test_fpga_core.py b/example/VCU1525/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index b2a0e316a..000000000 --- a/example/VCU1525/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,465 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - sw = Signal(intbv(0)[4:]) - qsfp0_tx_clk_1 = Signal(bool(0)) - qsfp0_tx_rst_1 = Signal(bool(0)) - qsfp0_rx_clk_1 = Signal(bool(0)) - qsfp0_rx_rst_1 = Signal(bool(0)) - qsfp0_rxd_1 = Signal(intbv(0)[64:]) - qsfp0_rxc_1 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_2 = Signal(bool(0)) - qsfp0_tx_rst_2 = Signal(bool(0)) - qsfp0_rx_clk_2 = Signal(bool(0)) - qsfp0_rx_rst_2 = Signal(bool(0)) - qsfp0_rxd_2 = Signal(intbv(0)[64:]) - qsfp0_rxc_2 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_3 = Signal(bool(0)) - qsfp0_tx_rst_3 = Signal(bool(0)) - qsfp0_rx_clk_3 = Signal(bool(0)) - qsfp0_rx_rst_3 = Signal(bool(0)) - qsfp0_rxd_3 = Signal(intbv(0)[64:]) - qsfp0_rxc_3 = Signal(intbv(0)[8:]) - qsfp0_tx_clk_4 = Signal(bool(0)) - qsfp0_tx_rst_4 = Signal(bool(0)) - qsfp0_rx_clk_4 = Signal(bool(0)) - qsfp0_rx_rst_4 = Signal(bool(0)) - qsfp0_rxd_4 = Signal(intbv(0)[64:]) - qsfp0_rxc_4 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_1 = Signal(bool(0)) - qsfp1_tx_rst_1 = Signal(bool(0)) - qsfp1_rx_clk_1 = Signal(bool(0)) - qsfp1_rx_rst_1 = Signal(bool(0)) - qsfp1_rxd_1 = Signal(intbv(0)[64:]) - qsfp1_rxc_1 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_2 = Signal(bool(0)) - qsfp1_tx_rst_2 = Signal(bool(0)) - qsfp1_rx_clk_2 = Signal(bool(0)) - qsfp1_rx_rst_2 = Signal(bool(0)) - qsfp1_rxd_2 = Signal(intbv(0)[64:]) - qsfp1_rxc_2 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_3 = Signal(bool(0)) - qsfp1_tx_rst_3 = Signal(bool(0)) - qsfp1_rx_clk_3 = Signal(bool(0)) - qsfp1_rx_rst_3 = Signal(bool(0)) - qsfp1_rxd_3 = Signal(intbv(0)[64:]) - qsfp1_rxc_3 = Signal(intbv(0)[8:]) - qsfp1_tx_clk_4 = Signal(bool(0)) - qsfp1_tx_rst_4 = Signal(bool(0)) - qsfp1_rx_clk_4 = Signal(bool(0)) - qsfp1_rx_rst_4 = Signal(bool(0)) - qsfp1_rxd_4 = Signal(intbv(0)[64:]) - qsfp1_rxc_4 = Signal(intbv(0)[8:]) - uart_txd = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[3:]) - qsfp0_txd_1 = Signal(intbv(0)[64:]) - qsfp0_txc_1 = Signal(intbv(0)[8:]) - qsfp0_txd_2 = Signal(intbv(0)[64:]) - qsfp0_txc_2 = Signal(intbv(0)[8:]) - qsfp0_txd_3 = Signal(intbv(0)[64:]) - qsfp0_txc_3 = Signal(intbv(0)[8:]) - qsfp0_txd_4 = Signal(intbv(0)[64:]) - qsfp0_txc_4 = Signal(intbv(0)[8:]) - qsfp1_txd_1 = Signal(intbv(0)[64:]) - qsfp1_txc_1 = Signal(intbv(0)[8:]) - qsfp1_txd_2 = Signal(intbv(0)[64:]) - qsfp1_txc_2 = Signal(intbv(0)[8:]) - qsfp1_txd_3 = Signal(intbv(0)[64:]) - qsfp1_txc_3 = Signal(intbv(0)[8:]) - qsfp1_txd_4 = Signal(intbv(0)[64:]) - qsfp1_txc_4 = Signal(intbv(0)[8:]) - uart_rxd = Signal(bool(0)) - - # sources and sinks - qsfp0_1_source = xgmii_ep.XGMIISource() - qsfp0_1_source_logic = qsfp0_1_source.create_logic(qsfp0_rx_clk_1, qsfp0_rx_rst_1, txd=qsfp0_rxd_1, txc=qsfp0_rxc_1, name='qsfp0_1_source') - - qsfp0_1_sink = xgmii_ep.XGMIISink() - qsfp0_1_sink_logic = qsfp0_1_sink.create_logic(qsfp0_tx_clk_1, qsfp0_tx_rst_1, rxd=qsfp0_txd_1, rxc=qsfp0_txc_1, name='qsfp0_1_sink') - - qsfp0_2_source = xgmii_ep.XGMIISource() - qsfp0_2_source_logic = qsfp0_2_source.create_logic(qsfp0_rx_clk_2, qsfp0_rx_rst_2, txd=qsfp0_rxd_2, txc=qsfp0_rxc_2, name='qsfp0_2_source') - - qsfp0_2_sink = xgmii_ep.XGMIISink() - qsfp0_2_sink_logic = qsfp0_2_sink.create_logic(qsfp0_tx_clk_2, qsfp0_tx_rst_2, rxd=qsfp0_txd_2, rxc=qsfp0_txc_2, name='qsfp0_2_sink') - - qsfp0_3_source = xgmii_ep.XGMIISource() - qsfp0_3_source_logic = qsfp0_3_source.create_logic(qsfp0_rx_clk_3, qsfp0_rx_rst_3, txd=qsfp0_rxd_3, txc=qsfp0_rxc_3, name='qsfp0_3_source') - - qsfp0_3_sink = xgmii_ep.XGMIISink() - qsfp0_3_sink_logic = qsfp0_3_sink.create_logic(qsfp0_tx_clk_3, qsfp0_tx_rst_3, rxd=qsfp0_txd_3, rxc=qsfp0_txc_3, name='qsfp0_3_sink') - - qsfp0_4_source = xgmii_ep.XGMIISource() - qsfp0_4_source_logic = qsfp0_4_source.create_logic(qsfp0_rx_clk_4, qsfp0_rx_rst_4, txd=qsfp0_rxd_4, txc=qsfp0_rxc_4, name='qsfp0_4_source') - - qsfp0_4_sink = xgmii_ep.XGMIISink() - qsfp0_4_sink_logic = qsfp0_4_sink.create_logic(qsfp0_tx_clk_4, qsfp0_tx_rst_4, rxd=qsfp0_txd_4, rxc=qsfp0_txc_4, name='qsfp0_4_sink') - - qsfp1_1_source = xgmii_ep.XGMIISource() - qsfp1_1_source_logic = qsfp1_1_source.create_logic(qsfp1_rx_clk_1, qsfp1_rx_rst_1, txd=qsfp1_rxd_1, txc=qsfp1_rxc_1, name='qsfp1_1_source') - - qsfp1_1_sink = xgmii_ep.XGMIISink() - qsfp1_1_sink_logic = qsfp1_1_sink.create_logic(qsfp1_tx_clk_1, qsfp1_tx_rst_1, rxd=qsfp1_txd_1, rxc=qsfp1_txc_1, name='qsfp1_1_sink') - - qsfp1_2_source = xgmii_ep.XGMIISource() - qsfp1_2_source_logic = qsfp1_2_source.create_logic(qsfp1_rx_clk_2, qsfp1_rx_rst_2, txd=qsfp1_rxd_2, txc=qsfp1_rxc_2, name='qsfp1_2_source') - - qsfp1_2_sink = xgmii_ep.XGMIISink() - qsfp1_2_sink_logic = qsfp1_2_sink.create_logic(qsfp1_tx_clk_2, qsfp1_tx_rst_2, rxd=qsfp1_txd_2, rxc=qsfp1_txc_2, name='qsfp1_2_sink') - - qsfp1_3_source = xgmii_ep.XGMIISource() - qsfp1_3_source_logic = qsfp1_3_source.create_logic(qsfp1_rx_clk_3, qsfp1_rx_rst_3, txd=qsfp1_rxd_3, txc=qsfp1_rxc_3, name='qsfp1_3_source') - - qsfp1_3_sink = xgmii_ep.XGMIISink() - qsfp1_3_sink_logic = qsfp1_3_sink.create_logic(qsfp1_tx_clk_3, qsfp1_tx_rst_3, rxd=qsfp1_txd_3, rxc=qsfp1_txc_3, name='qsfp1_3_sink') - - qsfp1_4_source = xgmii_ep.XGMIISource() - qsfp1_4_source_logic = qsfp1_4_source.create_logic(qsfp1_rx_clk_4, qsfp1_rx_rst_4, txd=qsfp1_rxd_4, txc=qsfp1_rxc_4, name='qsfp1_4_source') - - qsfp1_4_sink = xgmii_ep.XGMIISink() - qsfp1_4_sink_logic = qsfp1_4_sink.create_logic(qsfp1_tx_clk_4, qsfp1_tx_rst_4, rxd=qsfp1_txd_4, rxc=qsfp1_txc_4, name='qsfp1_4_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - sw=sw, - led=led, - - qsfp0_tx_clk_1=qsfp0_tx_clk_1, - qsfp0_tx_rst_1=qsfp0_tx_rst_1, - qsfp0_txd_1=qsfp0_txd_1, - qsfp0_txc_1=qsfp0_txc_1, - qsfp0_rx_clk_1=qsfp0_rx_clk_1, - qsfp0_rx_rst_1=qsfp0_rx_rst_1, - qsfp0_rxd_1=qsfp0_rxd_1, - qsfp0_rxc_1=qsfp0_rxc_1, - qsfp0_tx_clk_2=qsfp0_tx_clk_2, - qsfp0_tx_rst_2=qsfp0_tx_rst_2, - qsfp0_txd_2=qsfp0_txd_2, - qsfp0_txc_2=qsfp0_txc_2, - qsfp0_rx_clk_2=qsfp0_rx_clk_2, - qsfp0_rx_rst_2=qsfp0_rx_rst_2, - qsfp0_rxd_2=qsfp0_rxd_2, - qsfp0_rxc_2=qsfp0_rxc_2, - qsfp0_tx_clk_3=qsfp0_tx_clk_3, - qsfp0_tx_rst_3=qsfp0_tx_rst_3, - qsfp0_txd_3=qsfp0_txd_3, - qsfp0_txc_3=qsfp0_txc_3, - qsfp0_rx_clk_3=qsfp0_rx_clk_3, - qsfp0_rx_rst_3=qsfp0_rx_rst_3, - qsfp0_rxd_3=qsfp0_rxd_3, - qsfp0_rxc_3=qsfp0_rxc_3, - qsfp0_tx_clk_4=qsfp0_tx_clk_4, - qsfp0_tx_rst_4=qsfp0_tx_rst_4, - qsfp0_txd_4=qsfp0_txd_4, - qsfp0_txc_4=qsfp0_txc_4, - qsfp0_rx_clk_4=qsfp0_rx_clk_4, - qsfp0_rx_rst_4=qsfp0_rx_rst_4, - qsfp0_rxd_4=qsfp0_rxd_4, - qsfp0_rxc_4=qsfp0_rxc_4, - qsfp1_tx_clk_1=qsfp1_tx_clk_1, - qsfp1_tx_rst_1=qsfp1_tx_rst_1, - qsfp1_txd_1=qsfp1_txd_1, - qsfp1_txc_1=qsfp1_txc_1, - qsfp1_rx_clk_1=qsfp1_rx_clk_1, - qsfp1_rx_rst_1=qsfp1_rx_rst_1, - qsfp1_rxd_1=qsfp1_rxd_1, - qsfp1_rxc_1=qsfp1_rxc_1, - qsfp1_tx_clk_2=qsfp1_tx_clk_2, - qsfp1_tx_rst_2=qsfp1_tx_rst_2, - qsfp1_txd_2=qsfp1_txd_2, - qsfp1_txc_2=qsfp1_txc_2, - qsfp1_rx_clk_2=qsfp1_rx_clk_2, - qsfp1_rx_rst_2=qsfp1_rx_rst_2, - qsfp1_rxd_2=qsfp1_rxd_2, - qsfp1_rxc_2=qsfp1_rxc_2, - qsfp1_tx_clk_3=qsfp1_tx_clk_3, - qsfp1_tx_rst_3=qsfp1_tx_rst_3, - qsfp1_txd_3=qsfp1_txd_3, - qsfp1_txc_3=qsfp1_txc_3, - qsfp1_rx_clk_3=qsfp1_rx_clk_3, - qsfp1_rx_rst_3=qsfp1_rx_rst_3, - qsfp1_rxd_3=qsfp1_rxd_3, - qsfp1_rxc_3=qsfp1_rxc_3, - qsfp1_tx_clk_4=qsfp1_tx_clk_4, - qsfp1_tx_rst_4=qsfp1_tx_rst_4, - qsfp1_txd_4=qsfp1_txd_4, - qsfp1_txc_4=qsfp1_txc_4, - qsfp1_rx_clk_4=qsfp1_rx_clk_4, - qsfp1_rx_rst_4=qsfp1_rx_rst_4, - qsfp1_rxd_4=qsfp1_rxd_4, - qsfp1_rxc_4=qsfp1_rxc_4, - - uart_rxd=uart_rxd, - uart_txd=uart_txd - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp0_tx_clk_1.next = not qsfp0_tx_clk_1 - qsfp0_rx_clk_1.next = not qsfp0_rx_clk_1 - qsfp0_tx_clk_2.next = not qsfp0_tx_clk_2 - qsfp0_rx_clk_2.next = not qsfp0_rx_clk_2 - qsfp0_tx_clk_3.next = not qsfp0_tx_clk_3 - qsfp0_rx_clk_3.next = not qsfp0_rx_clk_3 - qsfp0_tx_clk_4.next = not qsfp0_tx_clk_4 - qsfp0_rx_clk_4.next = not qsfp0_rx_clk_4 - qsfp1_tx_clk_1.next = not qsfp1_tx_clk_1 - qsfp1_rx_clk_1.next = not qsfp1_rx_clk_1 - qsfp1_tx_clk_2.next = not qsfp1_tx_clk_2 - qsfp1_rx_clk_2.next = not qsfp1_rx_clk_2 - qsfp1_tx_clk_3.next = not qsfp1_tx_clk_3 - qsfp1_rx_clk_3.next = not qsfp1_rx_clk_3 - qsfp1_tx_clk_4.next = not qsfp1_tx_clk_4 - qsfp1_rx_clk_4.next = not qsfp1_rx_clk_4 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp0_tx_rst_1.next = 1 - qsfp0_rx_rst_1.next = 1 - qsfp0_tx_rst_2.next = 1 - qsfp0_rx_rst_2.next = 1 - qsfp0_tx_rst_3.next = 1 - qsfp0_rx_rst_3.next = 1 - qsfp0_tx_rst_4.next = 1 - qsfp0_rx_rst_4.next = 1 - qsfp1_tx_rst_1.next = 1 - qsfp1_rx_rst_1.next = 1 - qsfp1_tx_rst_2.next = 1 - qsfp1_rx_rst_2.next = 1 - qsfp1_tx_rst_3.next = 1 - qsfp1_rx_rst_3.next = 1 - qsfp1_tx_rst_4.next = 1 - qsfp1_rx_rst_4.next = 1 - yield clk.posedge - rst.next = 0 - qsfp0_tx_rst_1.next = 0 - qsfp0_rx_rst_1.next = 0 - qsfp0_tx_rst_2.next = 0 - qsfp0_rx_rst_2.next = 0 - qsfp0_tx_rst_3.next = 0 - qsfp0_rx_rst_3.next = 0 - qsfp0_tx_rst_4.next = 0 - qsfp0_rx_rst_4.next = 0 - qsfp1_tx_rst_1.next = 0 - qsfp1_rx_rst_1.next = 0 - qsfp1_tx_rst_2.next = 0 - qsfp1_rx_rst_2.next = 0 - qsfp1_tx_rst_3.next = 0 - qsfp1_rx_rst_3.next = 0 - qsfp1_tx_rst_4.next = 0 - qsfp1_rx_rst_4.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp0_1_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp0_1_sink.empty(): - yield clk.posedge - - rx_frame = qsfp0_1_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp0_1_source.empty() - assert qsfp0_1_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/VCU1525/fpga_10g/tb/test_fpga_core.v b/example/VCU1525/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index fddb81323..000000000 --- a/example/VCU1525/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg [3:0] sw = 0; -reg qsfp0_tx_clk_1 = 0; -reg qsfp0_tx_rst_1 = 0; -reg qsfp0_rx_clk_1 = 0; -reg qsfp0_rx_rst_1 = 0; -reg [63:0] qsfp0_rxd_1 = 0; -reg [7:0] qsfp0_rxc_1 = 0; -reg qsfp0_tx_clk_2 = 0; -reg qsfp0_tx_rst_2 = 0; -reg qsfp0_rx_clk_2 = 0; -reg qsfp0_rx_rst_2 = 0; -reg [63:0] qsfp0_rxd_2 = 0; -reg [7:0] qsfp0_rxc_2 = 0; -reg qsfp0_tx_clk_3 = 0; -reg qsfp0_tx_rst_3 = 0; -reg qsfp0_rx_clk_3 = 0; -reg qsfp0_rx_rst_3 = 0; -reg [63:0] qsfp0_rxd_3 = 0; -reg [7:0] qsfp0_rxc_3 = 0; -reg qsfp0_tx_clk_4 = 0; -reg qsfp0_tx_rst_4 = 0; -reg qsfp0_rx_clk_4 = 0; -reg qsfp0_rx_rst_4 = 0; -reg [63:0] qsfp0_rxd_4 = 0; -reg [7:0] qsfp0_rxc_4 = 0; -reg qsfp1_tx_clk_1 = 0; -reg qsfp1_tx_rst_1 = 0; -reg qsfp1_rx_clk_1 = 0; -reg qsfp1_rx_rst_1 = 0; -reg [63:0] qsfp1_rxd_1 = 0; -reg [7:0] qsfp1_rxc_1 = 0; -reg qsfp1_tx_clk_2 = 0; -reg qsfp1_tx_rst_2 = 0; -reg qsfp1_rx_clk_2 = 0; -reg qsfp1_rx_rst_2 = 0; -reg [63:0] qsfp1_rxd_2 = 0; -reg [7:0] qsfp1_rxc_2 = 0; -reg qsfp1_tx_clk_3 = 0; -reg qsfp1_tx_rst_3 = 0; -reg qsfp1_rx_clk_3 = 0; -reg qsfp1_rx_rst_3 = 0; -reg [63:0] qsfp1_rxd_3 = 0; -reg [7:0] qsfp1_rxc_3 = 0; -reg qsfp1_tx_clk_4 = 0; -reg qsfp1_tx_rst_4 = 0; -reg qsfp1_rx_clk_4 = 0; -reg qsfp1_rx_rst_4 = 0; -reg [63:0] qsfp1_rxd_4 = 0; -reg [7:0] qsfp1_rxc_4 = 0; -reg uart_txd = 0; - -// Outputs -wire [2:0] led; -wire [63:0] qsfp0_txd_1; -wire [7:0] qsfp0_txc_1; -wire [63:0] qsfp0_txd_2; -wire [7:0] qsfp0_txc_2; -wire [63:0] qsfp0_txd_3; -wire [7:0] qsfp0_txc_3; -wire [63:0] qsfp0_txd_4; -wire [7:0] qsfp0_txc_4; -wire [63:0] qsfp1_txd_1; -wire [7:0] qsfp1_txc_1; -wire [63:0] qsfp1_txd_2; -wire [7:0] qsfp1_txc_2; -wire [63:0] qsfp1_txd_3; -wire [7:0] qsfp1_txc_3; -wire [63:0] qsfp1_txd_4; -wire [7:0] qsfp1_txc_4; -wire uart_rxd; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - sw, - qsfp0_tx_clk_1, - qsfp0_tx_rst_1, - qsfp0_rx_clk_1, - qsfp0_rx_rst_1, - qsfp0_rxd_1, - qsfp0_rxc_1, - qsfp0_tx_clk_2, - qsfp0_tx_rst_2, - qsfp0_rx_clk_2, - qsfp0_rx_rst_2, - qsfp0_rxd_2, - qsfp0_rxc_2, - qsfp0_tx_clk_3, - qsfp0_tx_rst_3, - qsfp0_rx_clk_3, - qsfp0_rx_rst_3, - qsfp0_rxd_3, - qsfp0_rxc_3, - qsfp0_tx_clk_4, - qsfp0_tx_rst_4, - qsfp0_rx_clk_4, - qsfp0_rx_rst_4, - qsfp0_rxd_4, - qsfp0_rxc_4, - qsfp1_tx_clk_1, - qsfp1_tx_rst_1, - qsfp1_rx_clk_1, - qsfp1_rx_rst_1, - qsfp1_rxd_1, - qsfp1_rxc_1, - qsfp1_tx_clk_2, - qsfp1_tx_rst_2, - qsfp1_rx_clk_2, - qsfp1_rx_rst_2, - qsfp1_rxd_2, - qsfp1_rxc_2, - qsfp1_tx_clk_3, - qsfp1_tx_rst_3, - qsfp1_rx_clk_3, - qsfp1_rx_rst_3, - qsfp1_rxd_3, - qsfp1_rxc_3, - qsfp1_tx_clk_4, - qsfp1_tx_rst_4, - qsfp1_rx_clk_4, - qsfp1_rx_rst_4, - qsfp1_rxd_4, - qsfp1_rxc_4, - uart_txd - ); - $to_myhdl( - led, - qsfp0_txd_1, - qsfp0_txc_1, - qsfp0_txd_2, - qsfp0_txc_2, - qsfp0_txd_3, - qsfp0_txc_3, - qsfp0_txd_4, - qsfp0_txc_4, - qsfp1_txd_1, - qsfp1_txc_1, - qsfp1_txd_2, - qsfp1_txc_2, - qsfp1_txd_3, - qsfp1_txc_3, - qsfp1_txd_4, - qsfp1_txc_4, - uart_rxd - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .sw(sw), - .led(led), - .qsfp0_tx_clk_1(qsfp0_tx_clk_1), - .qsfp0_tx_rst_1(qsfp0_tx_rst_1), - .qsfp0_txd_1(qsfp0_txd_1), - .qsfp0_txc_1(qsfp0_txc_1), - .qsfp0_rx_clk_1(qsfp0_rx_clk_1), - .qsfp0_rx_rst_1(qsfp0_rx_rst_1), - .qsfp0_rxd_1(qsfp0_rxd_1), - .qsfp0_rxc_1(qsfp0_rxc_1), - .qsfp0_tx_clk_2(qsfp0_tx_clk_2), - .qsfp0_tx_rst_2(qsfp0_tx_rst_2), - .qsfp0_txd_2(qsfp0_txd_2), - .qsfp0_txc_2(qsfp0_txc_2), - .qsfp0_rx_clk_2(qsfp0_rx_clk_2), - .qsfp0_rx_rst_2(qsfp0_rx_rst_2), - .qsfp0_rxd_2(qsfp0_rxd_2), - .qsfp0_rxc_2(qsfp0_rxc_2), - .qsfp0_tx_clk_3(qsfp0_tx_clk_3), - .qsfp0_tx_rst_3(qsfp0_tx_rst_3), - .qsfp0_txd_3(qsfp0_txd_3), - .qsfp0_txc_3(qsfp0_txc_3), - .qsfp0_rx_clk_3(qsfp0_rx_clk_3), - .qsfp0_rx_rst_3(qsfp0_rx_rst_3), - .qsfp0_rxd_3(qsfp0_rxd_3), - .qsfp0_rxc_3(qsfp0_rxc_3), - .qsfp0_tx_clk_4(qsfp0_tx_clk_4), - .qsfp0_tx_rst_4(qsfp0_tx_rst_4), - .qsfp0_txd_4(qsfp0_txd_4), - .qsfp0_txc_4(qsfp0_txc_4), - .qsfp0_rx_clk_4(qsfp0_rx_clk_4), - .qsfp0_rx_rst_4(qsfp0_rx_rst_4), - .qsfp0_rxd_4(qsfp0_rxd_4), - .qsfp0_rxc_4(qsfp0_rxc_4), - .qsfp1_tx_clk_1(qsfp1_tx_clk_1), - .qsfp1_tx_rst_1(qsfp1_tx_rst_1), - .qsfp1_txd_1(qsfp1_txd_1), - .qsfp1_txc_1(qsfp1_txc_1), - .qsfp1_rx_clk_1(qsfp1_rx_clk_1), - .qsfp1_rx_rst_1(qsfp1_rx_rst_1), - .qsfp1_rxd_1(qsfp1_rxd_1), - .qsfp1_rxc_1(qsfp1_rxc_1), - .qsfp1_tx_clk_2(qsfp1_tx_clk_2), - .qsfp1_tx_rst_2(qsfp1_tx_rst_2), - .qsfp1_txd_2(qsfp1_txd_2), - .qsfp1_txc_2(qsfp1_txc_2), - .qsfp1_rx_clk_2(qsfp1_rx_clk_2), - .qsfp1_rx_rst_2(qsfp1_rx_rst_2), - .qsfp1_rxd_2(qsfp1_rxd_2), - .qsfp1_rxc_2(qsfp1_rxc_2), - .qsfp1_tx_clk_3(qsfp1_tx_clk_3), - .qsfp1_tx_rst_3(qsfp1_tx_rst_3), - .qsfp1_txd_3(qsfp1_txd_3), - .qsfp1_txc_3(qsfp1_txc_3), - .qsfp1_rx_clk_3(qsfp1_rx_clk_3), - .qsfp1_rx_rst_3(qsfp1_rx_rst_3), - .qsfp1_rxd_3(qsfp1_rxd_3), - .qsfp1_rxc_3(qsfp1_rxc_3), - .qsfp1_tx_clk_4(qsfp1_tx_clk_4), - .qsfp1_tx_rst_4(qsfp1_tx_rst_4), - .qsfp1_txd_4(qsfp1_txd_4), - .qsfp1_txc_4(qsfp1_txc_4), - .qsfp1_rx_clk_4(qsfp1_rx_clk_4), - .qsfp1_rx_rst_4(qsfp1_rx_rst_4), - .qsfp1_rxd_4(qsfp1_rxd_4), - .qsfp1_rxc_4(qsfp1_rxc_4), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd) -); - -endmodule diff --git a/example/VCU1525/fpga_10g/tb/udp_ep.py b/example/VCU1525/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/VCU1525/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/VCU1525/fpga_10g/tb/xgmii_ep.py b/example/VCU1525/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/VCU1525/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/arp_ep.py b/example/ZCU102/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ZCU102/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/axis_ep.py b/example/ZCU102/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ZCU102/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/eth_ep.py b/example/ZCU102/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ZCU102/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/fpga_core/Makefile b/example/ZCU102/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/ZCU102/fpga/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py b/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..f8d3abd92 --- /dev/null +++ b/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,252 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.sfp0_rx_clk, 6.4, units="ns").start()) + self.sfp0_source = XgmiiSource(dut.sfp0_rxd, dut.sfp0_rxc, dut.sfp0_rx_clk, dut.sfp0_rx_rst) + cocotb.fork(Clock(dut.sfp0_tx_clk, 6.4, units="ns").start()) + self.sfp0_sink = XgmiiSink(dut.sfp0_txd, dut.sfp0_txc, dut.sfp0_tx_clk, dut.sfp0_tx_rst) + + cocotb.fork(Clock(dut.sfp1_rx_clk, 6.4, units="ns").start()) + self.sfp1_source = XgmiiSource(dut.sfp1_rxd, dut.sfp1_rxc, dut.sfp1_rx_clk, dut.sfp1_rx_rst) + cocotb.fork(Clock(dut.sfp1_tx_clk, 6.4, units="ns").start()) + self.sfp1_sink = XgmiiSink(dut.sfp1_txd, dut.sfp1_txc, dut.sfp1_tx_clk, dut.sfp1_tx_rst) + + cocotb.fork(Clock(dut.sfp2_rx_clk, 6.4, units="ns").start()) + self.sfp2_source = XgmiiSource(dut.sfp2_rxd, dut.sfp2_rxc, dut.sfp2_rx_clk, dut.sfp2_rx_rst) + cocotb.fork(Clock(dut.sfp2_tx_clk, 6.4, units="ns").start()) + self.sfp2_sink = XgmiiSink(dut.sfp2_txd, dut.sfp2_txc, dut.sfp2_tx_clk, dut.sfp2_tx_rst) + + cocotb.fork(Clock(dut.sfp3_rx_clk, 6.4, units="ns").start()) + self.sfp3_source = XgmiiSource(dut.sfp3_rxd, dut.sfp3_rxc, dut.sfp3_rx_clk, dut.sfp3_rx_rst) + cocotb.fork(Clock(dut.sfp3_tx_clk, 6.4, units="ns").start()) + self.sfp3_sink = XgmiiSink(dut.sfp3_txd, dut.sfp3_txc, dut.sfp3_tx_clk, dut.sfp3_tx_rst) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_rts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.sfp0_rx_rst.setimmediatevalue(0) + self.dut.sfp0_tx_rst.setimmediatevalue(0) + self.dut.sfp1_rx_rst.setimmediatevalue(0) + self.dut.sfp1_tx_rst.setimmediatevalue(0) + self.dut.sfp2_rx_rst.setimmediatevalue(0) + self.dut.sfp2_tx_rst.setimmediatevalue(0) + self.dut.sfp3_rx_rst.setimmediatevalue(0) + self.dut.sfp3_tx_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.sfp0_rx_rst <= 1 + self.dut.sfp0_tx_rst <= 1 + self.dut.sfp1_rx_rst <= 1 + self.dut.sfp1_tx_rst <= 1 + self.dut.sfp2_rx_rst <= 1 + self.dut.sfp2_tx_rst <= 1 + self.dut.sfp3_rx_rst <= 1 + self.dut.sfp3_tx_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.sfp0_rx_rst <= 0 + self.dut.sfp0_tx_rst <= 0 + self.dut.sfp1_rx_rst <= 0 + self.dut.sfp1_tx_rst <= 0 + self.dut.sfp2_rx_rst <= 0 + self.dut.sfp2_tx_rst <= 0 + self.dut.sfp3_rx_rst <= 0 + self.dut.sfp3_tx_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.sfp0_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.sfp0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.sfp0_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.sfp0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ZCU102/fpga/tb/gmii_ep.py b/example/ZCU102/fpga/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/ZCU102/fpga/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/ip_ep.py b/example/ZCU102/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ZCU102/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/test_fpga_core.py b/example/ZCU102/fpga/tb/test_fpga_core.py deleted file mode 100755 index 76cbc0c0e..000000000 --- a/example/ZCU102/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,374 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2020 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_adapter.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_switch.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - sfp0_tx_clk = Signal(bool(0)) - sfp0_tx_rst = Signal(bool(0)) - sfp0_rx_clk = Signal(bool(0)) - sfp0_rx_rst = Signal(bool(0)) - sfp0_rxd = Signal(intbv(0)[64:]) - sfp0_rxc = Signal(intbv(0)[8:]) - sfp1_tx_clk = Signal(bool(0)) - sfp1_tx_rst = Signal(bool(0)) - sfp1_rx_clk = Signal(bool(0)) - sfp1_rx_rst = Signal(bool(0)) - sfp1_rxd = Signal(intbv(0)[64:]) - sfp1_rxc = Signal(intbv(0)[8:]) - sfp2_tx_clk = Signal(bool(0)) - sfp2_tx_rst = Signal(bool(0)) - sfp2_rx_clk = Signal(bool(0)) - sfp2_rx_rst = Signal(bool(0)) - sfp2_rxd = Signal(intbv(0)[64:]) - sfp2_rxc = Signal(intbv(0)[8:]) - sfp3_tx_clk = Signal(bool(0)) - sfp3_tx_rst = Signal(bool(0)) - sfp3_rx_clk = Signal(bool(0)) - sfp3_rx_rst = Signal(bool(0)) - sfp3_rxd = Signal(intbv(0)[64:]) - sfp3_rxc = Signal(intbv(0)[8:]) - uart_rxd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - sfp0_txd = Signal(intbv(0)[64:]) - sfp0_txc = Signal(intbv(0)[8:]) - sfp1_txd = Signal(intbv(0)[64:]) - sfp1_txc = Signal(intbv(0)[8:]) - sfp2_txd = Signal(intbv(0)[64:]) - sfp2_txc = Signal(intbv(0)[8:]) - sfp3_txd = Signal(intbv(0)[64:]) - sfp3_txc = Signal(intbv(0)[8:]) - uart_txd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # sources and sinks - sfp0_source = xgmii_ep.XGMIISource() - sfp0_source_logic = sfp0_source.create_logic(sfp0_rx_clk, sfp0_rx_rst, txd=sfp0_rxd, txc=sfp0_rxc, name='sfp0_source') - - sfp0_sink = xgmii_ep.XGMIISink() - sfp0_sink_logic = sfp0_sink.create_logic(sfp0_tx_clk, sfp0_tx_rst, rxd=sfp0_txd, rxc=sfp0_txc, name='sfp0_sink') - - sfp1_source = xgmii_ep.XGMIISource() - sfp1_source_logic = sfp1_source.create_logic(sfp1_rx_clk, sfp1_rx_rst, txd=sfp1_rxd, txc=sfp1_rxc, name='sfp1_source') - - sfp1_sink = xgmii_ep.XGMIISink() - sfp1_sink_logic = sfp1_sink.create_logic(sfp1_tx_clk, sfp1_tx_rst, rxd=sfp1_txd, rxc=sfp1_txc, name='sfp1_sink') - - sfp2_source = xgmii_ep.XGMIISource() - sfp2_source_logic = sfp2_source.create_logic(sfp2_rx_clk, sfp2_rx_rst, txd=sfp2_rxd, txc=sfp2_rxc, name='sfp2_source') - - sfp2_sink = xgmii_ep.XGMIISink() - sfp2_sink_logic = sfp2_sink.create_logic(sfp2_tx_clk, sfp2_tx_rst, rxd=sfp2_txd, rxc=sfp2_txc, name='sfp2_sink') - - sfp3_source = xgmii_ep.XGMIISource() - sfp3_source_logic = sfp3_source.create_logic(sfp3_rx_clk, sfp3_rx_rst, txd=sfp3_rxd, txc=sfp3_rxc, name='sfp3_source') - - sfp3_sink = xgmii_ep.XGMIISink() - sfp3_sink_logic = sfp3_sink.create_logic(sfp3_tx_clk, sfp3_tx_rst, rxd=sfp3_txd, rxc=sfp3_txc, name='sfp3_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - sfp0_tx_clk=sfp0_tx_clk, - sfp0_tx_rst=sfp0_tx_rst, - sfp0_txd=sfp0_txd, - sfp0_txc=sfp0_txc, - sfp0_rx_clk=sfp0_rx_clk, - sfp0_rx_rst=sfp0_rx_rst, - sfp0_rxd=sfp0_rxd, - sfp0_rxc=sfp0_rxc, - sfp1_tx_clk=sfp1_tx_clk, - sfp1_tx_rst=sfp1_tx_rst, - sfp1_txd=sfp1_txd, - sfp1_txc=sfp1_txc, - sfp1_rx_clk=sfp1_rx_clk, - sfp1_rx_rst=sfp1_rx_rst, - sfp1_rxd=sfp1_rxd, - sfp1_rxc=sfp1_rxc, - sfp2_tx_clk=sfp2_tx_clk, - sfp2_tx_rst=sfp2_tx_rst, - sfp2_txd=sfp2_txd, - sfp2_txc=sfp2_txc, - sfp2_rx_clk=sfp2_rx_clk, - sfp2_rx_rst=sfp2_rx_rst, - sfp2_rxd=sfp2_rxd, - sfp2_rxc=sfp2_rxc, - sfp3_tx_clk=sfp3_tx_clk, - sfp3_tx_rst=sfp3_tx_rst, - sfp3_txd=sfp3_txd, - sfp3_txc=sfp3_txc, - sfp3_rx_clk=sfp3_rx_clk, - sfp3_rx_rst=sfp3_rx_rst, - sfp3_rxd=sfp3_rxd, - sfp3_rxc=sfp3_rxc, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - sfp0_tx_clk.next = not sfp0_tx_clk - sfp0_rx_clk.next = not sfp0_rx_clk - sfp1_tx_clk.next = not sfp1_tx_clk - sfp1_rx_clk.next = not sfp1_rx_clk - sfp2_tx_clk.next = not sfp2_tx_clk - sfp2_rx_clk.next = not sfp2_rx_clk - sfp3_tx_clk.next = not sfp3_tx_clk - sfp3_rx_clk.next = not sfp3_rx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - sfp0_tx_rst.next = 1 - sfp0_rx_rst.next = 1 - sfp1_tx_rst.next = 1 - sfp1_rx_rst.next = 1 - sfp2_tx_rst.next = 1 - sfp2_rx_rst.next = 1 - sfp3_tx_rst.next = 1 - sfp3_rx_rst.next = 1 - yield clk.posedge - rst.next = 0 - sfp0_tx_rst.next = 0 - sfp0_rx_rst.next = 0 - sfp1_tx_rst.next = 0 - sfp1_rx_rst.next = 0 - sfp2_tx_rst.next = 0 - sfp2_rx_rst.next = 0 - sfp3_tx_rst.next = 0 - sfp3_rx_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - sfp0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while sfp0_sink.empty(): - yield clk.posedge - - rx_frame = sfp0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - sfp0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while sfp0_sink.empty(): - yield clk.posedge - - rx_frame = sfp0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert sfp0_source.empty() - assert sfp0_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ZCU102/fpga/tb/test_fpga_core.v b/example/ZCU102/fpga/tb/test_fpga_core.v deleted file mode 100644 index 257d80c32..000000000 --- a/example/ZCU102/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,194 +0,0 @@ -/* - -Copyright (c) 2020 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg sfp0_tx_clk = 0; -reg sfp0_tx_rst = 0; -reg sfp0_rx_clk = 0; -reg sfp0_rx_rst = 0; -reg [63:0] sfp0_rxd = 0; -reg [7:0] sfp0_rxc = 0; -reg sfp1_tx_clk = 0; -reg sfp1_tx_rst = 0; -reg sfp1_rx_clk = 0; -reg sfp1_rx_rst = 0; -reg [63:0] sfp1_rxd = 0; -reg [7:0] sfp1_rxc = 0; -reg sfp2_tx_clk = 0; -reg sfp2_tx_rst = 0; -reg sfp2_rx_clk = 0; -reg sfp2_rx_rst = 0; -reg [63:0] sfp2_rxd = 0; -reg [7:0] sfp2_rxc = 0; -reg sfp3_tx_clk = 0; -reg sfp3_tx_rst = 0; -reg sfp3_rx_clk = 0; -reg sfp3_rx_rst = 0; -reg [63:0] sfp3_rxd = 0; -reg [7:0] sfp3_rxc = 0; -reg uart_rxd = 0; -reg uart_rts = 0; - -// Outputs -wire [7:0] led; -wire [63:0] sfp0_txd; -wire [7:0] sfp0_txc; -wire [63:0] sfp1_txd; -wire [7:0] sfp1_txc; -wire [63:0] sfp_2_txd; -wire [7:0] sfp_2_txc; -wire [63:0] sfp_3_txd; -wire [7:0] sfp_3_txc; -wire uart_txd; -wire uart_cts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - sfp0_tx_clk, - sfp0_tx_rst, - sfp0_rx_clk, - sfp0_rx_rst, - sfp0_rxd, - sfp0_rxc, - sfp1_tx_clk, - sfp1_tx_rst, - sfp1_rx_clk, - sfp1_rx_rst, - sfp1_rxd, - sfp1_rxc, - sfp2_tx_clk, - sfp2_tx_rst, - sfp2_rx_clk, - sfp2_rx_rst, - sfp2_rxd, - sfp2_rxc, - sfp3_tx_clk, - sfp3_tx_rst, - sfp3_rx_clk, - sfp3_rx_rst, - sfp3_rxd, - sfp3_rxc, - uart_rxd, - uart_rts - ); - $to_myhdl( - led, - sfp0_txd, - sfp0_txc, - sfp1_txd, - sfp1_txc, - sfp2_txd, - sfp2_txc, - sfp3_txd, - sfp3_txc, - uart_txd, - uart_cts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .sfp0_tx_clk(sfp0_tx_clk), - .sfp0_tx_rst(sfp0_tx_rst), - .sfp0_txd(sfp0_txd), - .sfp0_txc(sfp0_txc), - .sfp0_rx_clk(sfp0_rx_clk), - .sfp0_rx_rst(sfp0_rx_rst), - .sfp0_rxd(sfp0_rxd), - .sfp0_rxc(sfp0_rxc), - .sfp1_tx_clk(sfp1_tx_clk), - .sfp1_tx_rst(sfp1_tx_rst), - .sfp1_txd(sfp1_txd), - .sfp1_txc(sfp1_txc), - .sfp1_rx_clk(sfp1_rx_clk), - .sfp1_rx_rst(sfp1_rx_rst), - .sfp1_rxd(sfp1_rxd), - .sfp1_rxc(sfp1_rxc), - .sfp2_tx_clk(sfp2_tx_clk), - .sfp2_tx_rst(sfp2_tx_rst), - .sfp2_txd(sfp2_txd), - .sfp2_txc(sfp2_txc), - .sfp2_rx_clk(sfp2_rx_clk), - .sfp2_rx_rst(sfp2_rx_rst), - .sfp2_rxd(sfp2_rxd), - .sfp2_rxc(sfp2_rxc), - .sfp3_tx_clk(sfp3_tx_clk), - .sfp3_tx_rst(sfp3_tx_rst), - .sfp3_txd(sfp3_txd), - .sfp3_txc(sfp3_txc), - .sfp3_rx_clk(sfp3_rx_clk), - .sfp3_rx_rst(sfp3_rx_rst), - .sfp3_rxd(sfp3_rxd), - .sfp3_rxc(sfp3_rxc), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/ZCU102/fpga/tb/udp_ep.py b/example/ZCU102/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ZCU102/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ZCU102/fpga/tb/xgmii_ep.py b/example/ZCU102/fpga/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/ZCU102/fpga/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/arp_ep.py b/example/ZCU106/fpga/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/ZCU106/fpga/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/axis_ep.py b/example/ZCU106/fpga/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/ZCU106/fpga/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/eth_ep.py b/example/ZCU106/fpga/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/ZCU106/fpga/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/fpga_core/Makefile b/example/ZCU106/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/ZCU106/fpga/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py b/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..897809eaa --- /dev/null +++ b/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,230 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.sfp0_rx_clk, 6.4, units="ns").start()) + self.sfp0_source = XgmiiSource(dut.sfp0_rxd, dut.sfp0_rxc, dut.sfp0_rx_clk, dut.sfp0_rx_rst) + cocotb.fork(Clock(dut.sfp0_tx_clk, 6.4, units="ns").start()) + self.sfp0_sink = XgmiiSink(dut.sfp0_txd, dut.sfp0_txc, dut.sfp0_tx_clk, dut.sfp0_tx_rst) + + cocotb.fork(Clock(dut.sfp1_rx_clk, 6.4, units="ns").start()) + self.sfp1_source = XgmiiSource(dut.sfp1_rxd, dut.sfp1_rxc, dut.sfp1_rx_clk, dut.sfp1_rx_rst) + cocotb.fork(Clock(dut.sfp1_tx_clk, 6.4, units="ns").start()) + self.sfp1_sink = XgmiiSink(dut.sfp1_txd, dut.sfp1_txc, dut.sfp1_tx_clk, dut.sfp1_tx_rst) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_rxd.setimmediatevalue(0) + dut.uart_rts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.sfp0_rx_rst.setimmediatevalue(0) + self.dut.sfp0_tx_rst.setimmediatevalue(0) + self.dut.sfp1_rx_rst.setimmediatevalue(0) + self.dut.sfp1_tx_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.sfp0_rx_rst <= 1 + self.dut.sfp0_tx_rst <= 1 + self.dut.sfp1_rx_rst <= 1 + self.dut.sfp1_tx_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.sfp0_rx_rst <= 0 + self.dut.sfp0_tx_rst <= 0 + self.dut.sfp1_rx_rst <= 0 + self.dut.sfp1_tx_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.sfp0_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.sfp0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.sfp0_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.sfp0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/ZCU106/fpga/tb/gmii_ep.py b/example/ZCU106/fpga/tb/gmii_ep.py deleted file mode 120000 index 754166f2f..000000000 --- a/example/ZCU106/fpga/tb/gmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/ip_ep.py b/example/ZCU106/fpga/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/ZCU106/fpga/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/test_fpga_core.py b/example/ZCU106/fpga/tb/test_fpga_core.py deleted file mode 100755 index b8d2fc284..000000000 --- a/example/ZCU106/fpga/tb/test_fpga_core.py +++ /dev/null @@ -1,318 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2020 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import gmii_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_1g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_1g.v") -srcs.append("../lib/eth/rtl/axis_gmii_rx.v") -srcs.append("../lib/eth/rtl/axis_gmii_tx.v") -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_adapter.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_switch.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_register.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - btnu = Signal(bool(0)) - btnl = Signal(bool(0)) - btnd = Signal(bool(0)) - btnr = Signal(bool(0)) - btnc = Signal(bool(0)) - sw = Signal(intbv(0)[8:]) - sfp0_tx_clk = Signal(bool(0)) - sfp0_tx_rst = Signal(bool(0)) - sfp0_rx_clk = Signal(bool(0)) - sfp0_rx_rst = Signal(bool(0)) - sfp0_rxd = Signal(intbv(0)[64:]) - sfp0_rxc = Signal(intbv(0)[8:]) - sfp1_tx_clk = Signal(bool(0)) - sfp1_tx_rst = Signal(bool(0)) - sfp1_rx_clk = Signal(bool(0)) - sfp1_rx_rst = Signal(bool(0)) - sfp1_rxd = Signal(intbv(0)[64:]) - sfp1_rxc = Signal(intbv(0)[8:]) - uart_rxd = Signal(bool(0)) - uart_rts = Signal(bool(0)) - - # Outputs - led = Signal(intbv(0)[8:]) - sfp0_txd = Signal(intbv(0)[64:]) - sfp0_txc = Signal(intbv(0)[8:]) - sfp1_txd = Signal(intbv(0)[64:]) - sfp1_txc = Signal(intbv(0)[8:]) - uart_txd = Signal(bool(0)) - uart_cts = Signal(bool(0)) - - # sources and sinks - sfp0_source = xgmii_ep.XGMIISource() - sfp0_source_logic = sfp0_source.create_logic(sfp0_rx_clk, sfp0_rx_rst, txd=sfp0_rxd, txc=sfp0_rxc, name='sfp0_source') - - sfp0_sink = xgmii_ep.XGMIISink() - sfp0_sink_logic = sfp0_sink.create_logic(sfp0_tx_clk, sfp0_tx_rst, rxd=sfp0_txd, rxc=sfp0_txc, name='sfp0_sink') - - sfp1_source = xgmii_ep.XGMIISource() - sfp1_source_logic = sfp1_source.create_logic(sfp1_rx_clk, sfp1_rx_rst, txd=sfp1_rxd, txc=sfp1_rxc, name='sfp1_source') - - sfp1_sink = xgmii_ep.XGMIISink() - sfp1_sink_logic = sfp1_sink.create_logic(sfp1_tx_clk, sfp1_tx_rst, rxd=sfp1_txd, rxc=sfp1_txc, name='sfp1_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - btnu=btnu, - btnl=btnl, - btnd=btnd, - btnr=btnr, - btnc=btnc, - sw=sw, - led=led, - - sfp0_tx_clk=sfp0_tx_clk, - sfp0_tx_rst=sfp0_tx_rst, - sfp0_txd=sfp0_txd, - sfp0_txc=sfp0_txc, - sfp0_rx_clk=sfp0_rx_clk, - sfp0_rx_rst=sfp0_rx_rst, - sfp0_rxd=sfp0_rxd, - sfp0_rxc=sfp0_rxc, - sfp1_tx_clk=sfp1_tx_clk, - sfp1_tx_rst=sfp1_tx_rst, - sfp1_txd=sfp1_txd, - sfp1_txc=sfp1_txc, - sfp1_rx_clk=sfp1_rx_clk, - sfp1_rx_rst=sfp1_rx_rst, - sfp1_rxd=sfp1_rxd, - sfp1_rxc=sfp1_rxc, - - uart_rxd=uart_rxd, - uart_txd=uart_txd, - uart_rts=uart_rts, - uart_cts=uart_cts - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - sfp0_tx_clk.next = not sfp0_tx_clk - sfp0_rx_clk.next = not sfp0_rx_clk - sfp1_tx_clk.next = not sfp1_tx_clk - sfp1_rx_clk.next = not sfp1_rx_clk - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - sfp0_tx_rst.next = 1 - sfp0_rx_rst.next = 1 - sfp1_tx_rst.next = 1 - sfp1_rx_rst.next = 1 - yield clk.posedge - rst.next = 0 - sfp0_tx_rst.next = 0 - sfp0_rx_rst.next = 0 - sfp1_tx_rst.next = 0 - sfp1_rx_rst.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - sfp0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while sfp0_sink.empty(): - yield clk.posedge - - rx_frame = sfp0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - sfp0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while sfp0_sink.empty(): - yield clk.posedge - - rx_frame = sfp0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert sfp0_source.empty() - assert sfp0_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/ZCU106/fpga/tb/test_fpga_core.v b/example/ZCU106/fpga/tb/test_fpga_core.v deleted file mode 100644 index 6edf45e18..000000000 --- a/example/ZCU106/fpga/tb/test_fpga_core.v +++ /dev/null @@ -1,150 +0,0 @@ -/* - -Copyright (c) 2020 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg btnu = 0; -reg btnl = 0; -reg btnd = 0; -reg btnr = 0; -reg btnc = 0; -reg [7:0] sw = 0; -reg sfp0_tx_clk = 0; -reg sfp0_tx_rst = 0; -reg sfp0_rx_clk = 0; -reg sfp0_rx_rst = 0; -reg [63:0] sfp0_rxd = 0; -reg [7:0] sfp0_rxc = 0; -reg sfp1_tx_clk = 0; -reg sfp1_tx_rst = 0; -reg sfp1_rx_clk = 0; -reg sfp1_rx_rst = 0; -reg [63:0] sfp1_rxd = 0; -reg [7:0] sfp1_rxc = 0; -reg uart_rxd = 0; -reg uart_rts = 0; - -// Outputs -wire [7:0] led; -wire [63:0] sfp0_txd; -wire [7:0] sfp0_txc; -wire [63:0] sfp1_txd; -wire [7:0] sfp1_txc; -wire [63:0] sfp_3_txd; -wire [7:0] sfp_3_txc; -wire [63:0] sfp_4_txd; -wire [7:0] sfp_4_txc; -wire uart_txd; -wire uart_cts; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - btnu, - btnl, - btnd, - btnr, - btnc, - sw, - sfp0_tx_clk, - sfp0_tx_rst, - sfp0_rx_clk, - sfp0_rx_rst, - sfp0_rxd, - sfp0_rxc, - sfp1_tx_clk, - sfp1_tx_rst, - sfp1_rx_clk, - sfp1_rx_rst, - sfp1_rxd, - sfp1_rxc, - uart_rxd, - uart_rts - ); - $to_myhdl( - led, - sfp0_txd, - sfp0_txc, - sfp1_txd, - sfp1_txc, - uart_txd, - uart_cts - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .btnu(btnu), - .btnl(btnl), - .btnd(btnd), - .btnr(btnr), - .btnc(btnc), - .sw(sw), - .led(led), - .sfp0_tx_clk(sfp0_tx_clk), - .sfp0_tx_rst(sfp0_tx_rst), - .sfp0_txd(sfp0_txd), - .sfp0_txc(sfp0_txc), - .sfp0_rx_clk(sfp0_rx_clk), - .sfp0_rx_rst(sfp0_rx_rst), - .sfp0_rxd(sfp0_rxd), - .sfp0_rxc(sfp0_rxc), - .sfp1_tx_clk(sfp1_tx_clk), - .sfp1_tx_rst(sfp1_tx_rst), - .sfp1_txd(sfp1_txd), - .sfp1_txc(sfp1_txc), - .sfp1_rx_clk(sfp1_rx_clk), - .sfp1_rx_rst(sfp1_rx_rst), - .sfp1_rxd(sfp1_rxd), - .sfp1_rxc(sfp1_rxc), - .uart_rxd(uart_rxd), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts) -); - -endmodule diff --git a/example/ZCU106/fpga/tb/udp_ep.py b/example/ZCU106/fpga/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/ZCU106/fpga/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/ZCU106/fpga/tb/xgmii_ep.py b/example/ZCU106/fpga/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/ZCU106/fpga/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file diff --git a/example/fb2CG/fpga_10g/tb/arp_ep.py b/example/fb2CG/fpga_10g/tb/arp_ep.py deleted file mode 120000 index 7b3d3ed97..000000000 --- a/example/fb2CG/fpga_10g/tb/arp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/fb2CG/fpga_10g/tb/axis_ep.py b/example/fb2CG/fpga_10g/tb/axis_ep.py deleted file mode 120000 index 385bb0300..000000000 --- a/example/fb2CG/fpga_10g/tb/axis_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/fb2CG/fpga_10g/tb/eth_ep.py b/example/fb2CG/fpga_10g/tb/eth_ep.py deleted file mode 120000 index bac19feea..000000000 --- a/example/fb2CG/fpga_10g/tb/eth_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/fb2CG/fpga_10g/tb/fpga_core/Makefile b/example/fb2CG/fpga_10g/tb/fpga_core/Makefile new file mode 100644 index 000000000..4aff883ec --- /dev/null +++ b/example/fb2CG/fpga_10g/tb/fpga_core/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..9a40af312 --- /dev/null +++ b/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,287 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + # Ethernet + cocotb.fork(Clock(dut.qsfp_0_rx_clk_0, 6.4, 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) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_0, 6.4, units="ns").start()) + self.qsfp_0_0_sink = XgmiiSink(dut.qsfp_0_txd_0, dut.qsfp_0_txc_0, dut.qsfp_0_tx_clk_0, dut.qsfp_0_tx_rst_0) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_1, 6.4, units="ns").start()) + self.qsfp_0_1_source = XgmiiSource(dut.qsfp_0_rxd_1, dut.qsfp_0_rxc_1, dut.qsfp_0_rx_clk_1, dut.qsfp_0_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_1, 6.4, units="ns").start()) + self.qsfp_0_1_sink = XgmiiSink(dut.qsfp_0_txd_1, dut.qsfp_0_txc_1, dut.qsfp_0_tx_clk_1, dut.qsfp_0_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_2, 6.4, units="ns").start()) + self.qsfp_0_2_source = XgmiiSource(dut.qsfp_0_rxd_2, dut.qsfp_0_rxc_2, dut.qsfp_0_rx_clk_2, dut.qsfp_0_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_2, 6.4, units="ns").start()) + self.qsfp_0_2_sink = XgmiiSink(dut.qsfp_0_txd_2, dut.qsfp_0_txc_2, dut.qsfp_0_tx_clk_2, dut.qsfp_0_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_0_rx_clk_3, 6.4, units="ns").start()) + self.qsfp_0_3_source = XgmiiSource(dut.qsfp_0_rxd_3, dut.qsfp_0_rxc_3, dut.qsfp_0_rx_clk_3, dut.qsfp_0_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_0_tx_clk_3, 6.4, units="ns").start()) + self.qsfp_0_3_sink = XgmiiSink(dut.qsfp_0_txd_3, dut.qsfp_0_txc_3, dut.qsfp_0_tx_clk_3, dut.qsfp_0_tx_rst_3) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_0, 6.4, units="ns").start()) + self.qsfp_1_0_source = XgmiiSource(dut.qsfp_1_rxd_0, dut.qsfp_1_rxc_0, dut.qsfp_1_rx_clk_0, dut.qsfp_1_rx_rst_0) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_0, 6.4, units="ns").start()) + self.qsfp_1_0_sink = XgmiiSink(dut.qsfp_1_txd_0, dut.qsfp_1_txc_0, dut.qsfp_1_tx_clk_0, dut.qsfp_1_tx_rst_0) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_1_source = XgmiiSource(dut.qsfp_1_rxd_1, dut.qsfp_1_rxc_1, dut.qsfp_1_rx_clk_1, dut.qsfp_1_rx_rst_1) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_1, 6.4, units="ns").start()) + self.qsfp_1_1_sink = XgmiiSink(dut.qsfp_1_txd_1, dut.qsfp_1_txc_1, dut.qsfp_1_tx_clk_1, dut.qsfp_1_tx_rst_1) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_2, 6.4, units="ns").start()) + self.qsfp_1_2_source = XgmiiSource(dut.qsfp_1_rxd_2, dut.qsfp_1_rxc_2, dut.qsfp_1_rx_clk_2, dut.qsfp_1_rx_rst_2) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_2, 6.4, units="ns").start()) + self.qsfp_1_2_sink = XgmiiSink(dut.qsfp_1_txd_2, dut.qsfp_1_txc_2, dut.qsfp_1_tx_clk_2, dut.qsfp_1_tx_rst_2) + + cocotb.fork(Clock(dut.qsfp_1_rx_clk_3, 6.4, units="ns").start()) + self.qsfp_1_3_source = XgmiiSource(dut.qsfp_1_rxd_3, dut.qsfp_1_rxc_3, dut.qsfp_1_rx_clk_3, dut.qsfp_1_rx_rst_3) + cocotb.fork(Clock(dut.qsfp_1_tx_clk_3, 6.4, units="ns").start()) + self.qsfp_1_3_sink = XgmiiSink(dut.qsfp_1_txd_3, dut.qsfp_1_txc_3, dut.qsfp_1_tx_clk_3, dut.qsfp_1_tx_rst_3) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_0.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_0.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_0_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_0_tx_rst_3.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_0.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_0.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_1.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_1.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_2.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_2.setimmediatevalue(0) + self.dut.qsfp_1_rx_rst_3.setimmediatevalue(0) + self.dut.qsfp_1_tx_rst_3.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.qsfp_0_rx_rst_0 <= 1 + self.dut.qsfp_0_tx_rst_0 <= 1 + self.dut.qsfp_0_rx_rst_1 <= 1 + self.dut.qsfp_0_tx_rst_1 <= 1 + self.dut.qsfp_0_rx_rst_2 <= 1 + self.dut.qsfp_0_tx_rst_2 <= 1 + self.dut.qsfp_0_rx_rst_3 <= 1 + self.dut.qsfp_0_tx_rst_3 <= 1 + self.dut.qsfp_1_rx_rst_0 <= 1 + self.dut.qsfp_1_tx_rst_0 <= 1 + self.dut.qsfp_1_rx_rst_1 <= 1 + self.dut.qsfp_1_tx_rst_1 <= 1 + self.dut.qsfp_1_rx_rst_2 <= 1 + self.dut.qsfp_1_tx_rst_2 <= 1 + self.dut.qsfp_1_rx_rst_3 <= 1 + self.dut.qsfp_1_tx_rst_3 <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.qsfp_0_rx_rst_0 <= 0 + self.dut.qsfp_0_tx_rst_0 <= 0 + self.dut.qsfp_0_rx_rst_1 <= 0 + self.dut.qsfp_0_tx_rst_1 <= 0 + self.dut.qsfp_0_rx_rst_2 <= 0 + self.dut.qsfp_0_tx_rst_2 <= 0 + self.dut.qsfp_0_rx_rst_3 <= 0 + self.dut.qsfp_0_tx_rst_3 <= 0 + self.dut.qsfp_1_rx_rst_0 <= 0 + self.dut.qsfp_1_tx_rst_0 <= 0 + self.dut.qsfp_1_rx_rst_1 <= 0 + self.dut.qsfp_1_tx_rst_1 <= 0 + self.dut.qsfp_1_rx_rst_2 <= 0 + self.dut.qsfp_1_tx_rst_2 <= 0 + self.dut.qsfp_1_rx_rst_3 <= 0 + self.dut.qsfp_1_tx_rst_3 <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = XgmiiFrame.from_payload(test_pkt.build()) + + await tb.qsfp_0_0_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.qsfp_0_0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) + + await tb.qsfp_0_0_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.qsfp_0_0_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_10g.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete_64.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"), + os.path.join(eth_rtl_dir, "udp_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_complete_64.v"), + os.path.join(eth_rtl_dir, "ip_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/example/fb2CG/fpga_10g/tb/ip_ep.py b/example/fb2CG/fpga_10g/tb/ip_ep.py deleted file mode 120000 index 6dfa928a7..000000000 --- a/example/fb2CG/fpga_10g/tb/ip_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/fb2CG/fpga_10g/tb/test_fpga_core.py b/example/fb2CG/fpga_10g/tb/test_fpga_core.py deleted file mode 100755 index d6f438d61..000000000 --- a/example/fb2CG/fpga_10g/tb/test_fpga_core.py +++ /dev/null @@ -1,463 +0,0 @@ -#!/usr/bin/env python -""" - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -from myhdl import * -import os - -import eth_ep -import arp_ep -import udp_ep -import xgmii_ep - -module = 'fpga_core' -testbench = 'test_%s' % module - -srcs = [] - -srcs.append("../rtl/%s.v" % module) -srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v") -srcs.append("../lib/eth/rtl/eth_mac_10g.v") -srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v") -srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v") -srcs.append("../lib/eth/rtl/lfsr.v") -srcs.append("../lib/eth/rtl/eth_axis_rx.v") -srcs.append("../lib/eth/rtl/eth_axis_tx.v") -srcs.append("../lib/eth/rtl/udp_complete_64.v") -srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v") -srcs.append("../lib/eth/rtl/udp_64.v") -srcs.append("../lib/eth/rtl/udp_ip_rx_64.v") -srcs.append("../lib/eth/rtl/udp_ip_tx_64.v") -srcs.append("../lib/eth/rtl/ip_complete_64.v") -srcs.append("../lib/eth/rtl/ip_64.v") -srcs.append("../lib/eth/rtl/ip_eth_rx_64.v") -srcs.append("../lib/eth/rtl/ip_eth_tx_64.v") -srcs.append("../lib/eth/rtl/ip_arb_mux.v") -srcs.append("../lib/eth/rtl/arp.v") -srcs.append("../lib/eth/rtl/arp_cache.v") -srcs.append("../lib/eth/rtl/arp_eth_rx.v") -srcs.append("../lib/eth/rtl/arp_eth_tx.v") -srcs.append("../lib/eth/rtl/eth_arb_mux.v") -srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") -srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v") -srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v") -srcs.append("%s.v" % testbench) - -src = ' '.join(srcs) - -build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) - -def bench(): - - # Parameters - - - # Inputs - clk = Signal(bool(0)) - rst = Signal(bool(0)) - current_test = Signal(intbv(0)[8:]) - - qsfp_0_tx_clk_0 = Signal(bool(0)) - qsfp_0_tx_rst_0 = Signal(bool(0)) - qsfp_0_rx_clk_0 = Signal(bool(0)) - qsfp_0_rx_rst_0 = Signal(bool(0)) - qsfp_0_rxd_0 = Signal(intbv(0)[64:]) - qsfp_0_rxc_0 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_1 = Signal(bool(0)) - qsfp_0_tx_rst_1 = Signal(bool(0)) - qsfp_0_rx_clk_1 = Signal(bool(0)) - qsfp_0_rx_rst_1 = Signal(bool(0)) - qsfp_0_rxd_1 = Signal(intbv(0)[64:]) - qsfp_0_rxc_1 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_2 = Signal(bool(0)) - qsfp_0_tx_rst_2 = Signal(bool(0)) - qsfp_0_rx_clk_2 = Signal(bool(0)) - qsfp_0_rx_rst_2 = Signal(bool(0)) - qsfp_0_rxd_2 = Signal(intbv(0)[64:]) - qsfp_0_rxc_2 = Signal(intbv(0)[8:]) - qsfp_0_tx_clk_3 = Signal(bool(0)) - qsfp_0_tx_rst_3 = Signal(bool(0)) - qsfp_0_rx_clk_3 = Signal(bool(0)) - qsfp_0_rx_rst_3 = Signal(bool(0)) - qsfp_0_rxd_3 = Signal(intbv(0)[64:]) - qsfp_0_rxc_3 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_0 = Signal(bool(0)) - qsfp_1_tx_rst_0 = Signal(bool(0)) - qsfp_1_rx_clk_0 = Signal(bool(0)) - qsfp_1_rx_rst_0 = Signal(bool(0)) - qsfp_1_rxd_0 = Signal(intbv(0)[64:]) - qsfp_1_rxc_0 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_1 = Signal(bool(0)) - qsfp_1_tx_rst_1 = Signal(bool(0)) - qsfp_1_rx_clk_1 = Signal(bool(0)) - qsfp_1_rx_rst_1 = Signal(bool(0)) - qsfp_1_rxd_1 = Signal(intbv(0)[64:]) - qsfp_1_rxc_1 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_2 = Signal(bool(0)) - qsfp_1_tx_rst_2 = Signal(bool(0)) - qsfp_1_rx_clk_2 = Signal(bool(0)) - qsfp_1_rx_rst_2 = Signal(bool(0)) - qsfp_1_rxd_2 = Signal(intbv(0)[64:]) - qsfp_1_rxc_2 = Signal(intbv(0)[8:]) - qsfp_1_tx_clk_3 = Signal(bool(0)) - qsfp_1_tx_rst_3 = Signal(bool(0)) - qsfp_1_rx_clk_3 = Signal(bool(0)) - qsfp_1_rx_rst_3 = Signal(bool(0)) - qsfp_1_rxd_3 = Signal(intbv(0)[64:]) - qsfp_1_rxc_3 = Signal(intbv(0)[8:]) - - # Outputs - led_red = Signal(intbv(0)[8:]) - led_green = Signal(intbv(0)[8:]) - led_bmc = Signal(intbv(0)[2:]) - led_exp = Signal(intbv(0)[2:]) - qsfp_0_txd_0 = Signal(intbv(0)[64:]) - qsfp_0_txc_0 = Signal(intbv(0)[8:]) - qsfp_0_txd_1 = Signal(intbv(0)[64:]) - qsfp_0_txc_1 = Signal(intbv(0)[8:]) - qsfp_0_txd_2 = Signal(intbv(0)[64:]) - qsfp_0_txc_2 = Signal(intbv(0)[8:]) - qsfp_0_txd_3 = Signal(intbv(0)[64:]) - qsfp_0_txc_3 = Signal(intbv(0)[8:]) - qsfp_1_txd_0 = Signal(intbv(0)[64:]) - qsfp_1_txc_0 = Signal(intbv(0)[8:]) - qsfp_1_txd_1 = Signal(intbv(0)[64:]) - qsfp_1_txc_1 = Signal(intbv(0)[8:]) - qsfp_1_txd_2 = Signal(intbv(0)[64:]) - qsfp_1_txc_2 = Signal(intbv(0)[8:]) - qsfp_1_txd_3 = Signal(intbv(0)[64:]) - qsfp_1_txc_3 = Signal(intbv(0)[8:]) - - # sources and sinks - qsfp_0_0_source = xgmii_ep.XGMIISource() - qsfp_0_0_source_logic = qsfp_0_0_source.create_logic(qsfp_0_rx_clk_0, qsfp_0_rx_rst_0, txd=qsfp_0_rxd_0, txc=qsfp_0_rxc_0, name='qsfp_0_0_source') - - qsfp_0_0_sink = xgmii_ep.XGMIISink() - qsfp_0_0_sink_logic = qsfp_0_0_sink.create_logic(qsfp_0_tx_clk_0, qsfp_0_tx_rst_0, rxd=qsfp_0_txd_0, rxc=qsfp_0_txc_0, name='qsfp_0_0_sink') - - qsfp_0_1_source = xgmii_ep.XGMIISource() - qsfp_0_1_source_logic = qsfp_0_1_source.create_logic(qsfp_0_rx_clk_1, qsfp_0_rx_rst_1, txd=qsfp_0_rxd_1, txc=qsfp_0_rxc_1, name='qsfp_0_1_source') - - qsfp_0_1_sink = xgmii_ep.XGMIISink() - qsfp_0_1_sink_logic = qsfp_0_1_sink.create_logic(qsfp_0_tx_clk_1, qsfp_0_tx_rst_1, rxd=qsfp_0_txd_1, rxc=qsfp_0_txc_1, name='qsfp_0_1_sink') - - qsfp_0_2_source = xgmii_ep.XGMIISource() - qsfp_0_2_source_logic = qsfp_0_2_source.create_logic(qsfp_0_rx_clk_2, qsfp_0_rx_rst_2, txd=qsfp_0_rxd_2, txc=qsfp_0_rxc_2, name='qsfp_0_2_source') - - qsfp_0_2_sink = xgmii_ep.XGMIISink() - qsfp_0_2_sink_logic = qsfp_0_2_sink.create_logic(qsfp_0_tx_clk_2, qsfp_0_tx_rst_2, rxd=qsfp_0_txd_2, rxc=qsfp_0_txc_2, name='qsfp_0_2_sink') - - qsfp_0_3_source = xgmii_ep.XGMIISource() - qsfp_0_3_source_logic = qsfp_0_3_source.create_logic(qsfp_0_rx_clk_3, qsfp_0_rx_rst_3, txd=qsfp_0_rxd_3, txc=qsfp_0_rxc_3, name='qsfp_0_3_source') - - qsfp_0_3_sink = xgmii_ep.XGMIISink() - qsfp_0_3_sink_logic = qsfp_0_3_sink.create_logic(qsfp_0_tx_clk_3, qsfp_0_tx_rst_3, rxd=qsfp_0_txd_3, rxc=qsfp_0_txc_3, name='qsfp_0_3_sink') - - qsfp_1_0_source = xgmii_ep.XGMIISource() - qsfp_1_0_source_logic = qsfp_1_0_source.create_logic(qsfp_1_rx_clk_0, qsfp_1_rx_rst_0, txd=qsfp_1_rxd_0, txc=qsfp_1_rxc_0, name='qsfp_1_0_source') - - qsfp_1_0_sink = xgmii_ep.XGMIISink() - qsfp_1_0_sink_logic = qsfp_1_0_sink.create_logic(qsfp_1_tx_clk_0, qsfp_1_tx_rst_0, rxd=qsfp_1_txd_0, rxc=qsfp_1_txc_0, name='qsfp_1_0_sink') - - qsfp_1_1_source = xgmii_ep.XGMIISource() - qsfp_1_1_source_logic = qsfp_1_1_source.create_logic(qsfp_1_rx_clk_1, qsfp_1_rx_rst_1, txd=qsfp_1_rxd_1, txc=qsfp_1_rxc_1, name='qsfp_1_1_source') - - qsfp_1_1_sink = xgmii_ep.XGMIISink() - qsfp_1_1_sink_logic = qsfp_1_1_sink.create_logic(qsfp_1_tx_clk_1, qsfp_1_tx_rst_1, rxd=qsfp_1_txd_1, rxc=qsfp_1_txc_1, name='qsfp_1_1_sink') - - qsfp_1_2_source = xgmii_ep.XGMIISource() - qsfp_1_2_source_logic = qsfp_1_2_source.create_logic(qsfp_1_rx_clk_2, qsfp_1_rx_rst_2, txd=qsfp_1_rxd_2, txc=qsfp_1_rxc_2, name='qsfp_1_2_source') - - qsfp_1_2_sink = xgmii_ep.XGMIISink() - qsfp_1_2_sink_logic = qsfp_1_2_sink.create_logic(qsfp_1_tx_clk_2, qsfp_1_tx_rst_2, rxd=qsfp_1_txd_2, rxc=qsfp_1_txc_2, name='qsfp_1_2_sink') - - qsfp_1_3_source = xgmii_ep.XGMIISource() - qsfp_1_3_source_logic = qsfp_1_3_source.create_logic(qsfp_1_rx_clk_3, qsfp_1_rx_rst_3, txd=qsfp_1_rxd_3, txc=qsfp_1_rxc_3, name='qsfp_1_3_source') - - qsfp_1_3_sink = xgmii_ep.XGMIISink() - qsfp_1_3_sink_logic = qsfp_1_3_sink.create_logic(qsfp_1_tx_clk_3, qsfp_1_tx_rst_3, rxd=qsfp_1_txd_3, rxc=qsfp_1_txc_3, name='qsfp_1_3_sink') - - # DUT - if os.system(build_cmd): - raise Exception("Error running build command") - - dut = Cosimulation( - "vvp -m myhdl %s.vvp -lxt2" % testbench, - clk=clk, - rst=rst, - current_test=current_test, - - led_red=led_red, - led_green=led_green, - led_bmc=led_bmc, - led_exp=led_exp, - - qsfp_0_tx_clk_0=qsfp_0_tx_clk_0, - qsfp_0_tx_rst_0=qsfp_0_tx_rst_0, - qsfp_0_txd_0=qsfp_0_txd_0, - qsfp_0_txc_0=qsfp_0_txc_0, - qsfp_0_rx_clk_0=qsfp_0_rx_clk_0, - qsfp_0_rx_rst_0=qsfp_0_rx_rst_0, - qsfp_0_rxd_0=qsfp_0_rxd_0, - qsfp_0_rxc_0=qsfp_0_rxc_0, - qsfp_0_tx_clk_1=qsfp_0_tx_clk_1, - qsfp_0_tx_rst_1=qsfp_0_tx_rst_1, - qsfp_0_txd_1=qsfp_0_txd_1, - qsfp_0_txc_1=qsfp_0_txc_1, - qsfp_0_rx_clk_1=qsfp_0_rx_clk_1, - qsfp_0_rx_rst_1=qsfp_0_rx_rst_1, - qsfp_0_rxd_1=qsfp_0_rxd_1, - qsfp_0_rxc_1=qsfp_0_rxc_1, - qsfp_0_tx_clk_2=qsfp_0_tx_clk_2, - qsfp_0_tx_rst_2=qsfp_0_tx_rst_2, - qsfp_0_txd_2=qsfp_0_txd_2, - qsfp_0_txc_2=qsfp_0_txc_2, - qsfp_0_rx_clk_2=qsfp_0_rx_clk_2, - qsfp_0_rx_rst_2=qsfp_0_rx_rst_2, - qsfp_0_rxd_2=qsfp_0_rxd_2, - qsfp_0_rxc_2=qsfp_0_rxc_2, - qsfp_0_tx_clk_3=qsfp_0_tx_clk_3, - qsfp_0_tx_rst_3=qsfp_0_tx_rst_3, - qsfp_0_txd_3=qsfp_0_txd_3, - qsfp_0_txc_3=qsfp_0_txc_3, - qsfp_0_rx_clk_3=qsfp_0_rx_clk_3, - qsfp_0_rx_rst_3=qsfp_0_rx_rst_3, - qsfp_0_rxd_3=qsfp_0_rxd_3, - qsfp_0_rxc_3=qsfp_0_rxc_3, - qsfp_1_tx_clk_0=qsfp_1_tx_clk_0, - qsfp_1_tx_rst_0=qsfp_1_tx_rst_0, - qsfp_1_txd_0=qsfp_1_txd_0, - qsfp_1_txc_0=qsfp_1_txc_0, - qsfp_1_rx_clk_0=qsfp_1_rx_clk_0, - qsfp_1_rx_rst_0=qsfp_1_rx_rst_0, - qsfp_1_rxd_0=qsfp_1_rxd_0, - qsfp_1_rxc_0=qsfp_1_rxc_0, - qsfp_1_tx_clk_1=qsfp_1_tx_clk_1, - qsfp_1_tx_rst_1=qsfp_1_tx_rst_1, - qsfp_1_txd_1=qsfp_1_txd_1, - qsfp_1_txc_1=qsfp_1_txc_1, - qsfp_1_rx_clk_1=qsfp_1_rx_clk_1, - qsfp_1_rx_rst_1=qsfp_1_rx_rst_1, - qsfp_1_rxd_1=qsfp_1_rxd_1, - qsfp_1_rxc_1=qsfp_1_rxc_1, - qsfp_1_tx_clk_2=qsfp_1_tx_clk_2, - qsfp_1_tx_rst_2=qsfp_1_tx_rst_2, - qsfp_1_txd_2=qsfp_1_txd_2, - qsfp_1_txc_2=qsfp_1_txc_2, - qsfp_1_rx_clk_2=qsfp_1_rx_clk_2, - qsfp_1_rx_rst_2=qsfp_1_rx_rst_2, - qsfp_1_rxd_2=qsfp_1_rxd_2, - qsfp_1_rxc_2=qsfp_1_rxc_2, - qsfp_1_tx_clk_3=qsfp_1_tx_clk_3, - qsfp_1_tx_rst_3=qsfp_1_tx_rst_3, - qsfp_1_txd_3=qsfp_1_txd_3, - qsfp_1_txc_3=qsfp_1_txc_3, - qsfp_1_rx_clk_3=qsfp_1_rx_clk_3, - qsfp_1_rx_rst_3=qsfp_1_rx_rst_3, - qsfp_1_rxd_3=qsfp_1_rxd_3, - qsfp_1_rxc_3=qsfp_1_rxc_3 - ) - - @always(delay(4)) - def clkgen(): - clk.next = not clk - qsfp_0_tx_clk_0.next = not qsfp_0_tx_clk_0 - qsfp_0_rx_clk_0.next = not qsfp_0_rx_clk_0 - qsfp_0_tx_clk_1.next = not qsfp_0_tx_clk_1 - qsfp_0_rx_clk_1.next = not qsfp_0_rx_clk_1 - qsfp_0_tx_clk_2.next = not qsfp_0_tx_clk_2 - qsfp_0_rx_clk_2.next = not qsfp_0_rx_clk_2 - qsfp_0_tx_clk_3.next = not qsfp_0_tx_clk_3 - qsfp_0_rx_clk_3.next = not qsfp_0_rx_clk_3 - qsfp_1_tx_clk_0.next = not qsfp_1_tx_clk_0 - qsfp_1_rx_clk_0.next = not qsfp_1_rx_clk_0 - qsfp_1_tx_clk_1.next = not qsfp_1_tx_clk_1 - qsfp_1_rx_clk_1.next = not qsfp_1_rx_clk_1 - qsfp_1_tx_clk_2.next = not qsfp_1_tx_clk_2 - qsfp_1_rx_clk_2.next = not qsfp_1_rx_clk_2 - qsfp_1_tx_clk_3.next = not qsfp_1_tx_clk_3 - qsfp_1_rx_clk_3.next = not qsfp_1_rx_clk_3 - - @instance - def check(): - yield delay(100) - yield clk.posedge - rst.next = 1 - qsfp_0_tx_rst_1.next = 1 - qsfp_0_rx_rst_1.next = 1 - qsfp_0_tx_rst_2.next = 1 - qsfp_0_rx_rst_2.next = 1 - qsfp_0_tx_rst_3.next = 1 - qsfp_0_rx_rst_3.next = 1 - qsfp_0_tx_rst_0.next = 1 - qsfp_0_rx_rst_0.next = 1 - qsfp_1_tx_rst_1.next = 1 - qsfp_1_rx_rst_1.next = 1 - qsfp_1_tx_rst_2.next = 1 - qsfp_1_rx_rst_2.next = 1 - qsfp_1_tx_rst_3.next = 1 - qsfp_1_rx_rst_3.next = 1 - qsfp_1_tx_rst_0.next = 1 - qsfp_1_rx_rst_0.next = 1 - yield clk.posedge - rst.next = 0 - qsfp_0_tx_rst_1.next = 0 - qsfp_0_rx_rst_1.next = 0 - qsfp_0_tx_rst_2.next = 0 - qsfp_0_rx_rst_2.next = 0 - qsfp_0_tx_rst_3.next = 0 - qsfp_0_rx_rst_3.next = 0 - qsfp_0_tx_rst_0.next = 0 - qsfp_0_rx_rst_0.next = 0 - qsfp_1_tx_rst_1.next = 0 - qsfp_1_rx_rst_1.next = 0 - qsfp_1_tx_rst_2.next = 0 - qsfp_1_rx_rst_2.next = 0 - qsfp_1_tx_rst_3.next = 0 - qsfp_1_rx_rst_3.next = 0 - qsfp_1_tx_rst_0.next = 0 - qsfp_1_rx_rst_0.next = 0 - yield clk.posedge - yield delay(100) - yield clk.posedge - - # testbench stimulus - - yield clk.posedge - print("test 1: test UDP RX packet") - current_test.next = 1 - - test_frame = udp_ep.UDPFrame() - test_frame.eth_dest_mac = 0x020000000000 - test_frame.eth_src_mac = 0xDAD1D2D3D4D5 - test_frame.eth_type = 0x0800 - test_frame.ip_version = 4 - test_frame.ip_ihl = 5 - test_frame.ip_dscp = 0 - test_frame.ip_ecn = 0 - test_frame.ip_length = None - test_frame.ip_identification = 0 - test_frame.ip_flags = 2 - test_frame.ip_fragment_offset = 0 - test_frame.ip_ttl = 64 - test_frame.ip_protocol = 0x11 - test_frame.ip_header_checksum = None - test_frame.ip_source_ip = 0xc0a80181 - test_frame.ip_dest_ip = 0xc0a80180 - test_frame.udp_source_port = 5678 - test_frame.udp_dest_port = 1234 - test_frame.payload = bytearray(range(32)) - test_frame.build() - - qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data) - - # wait for ARP request packet - while qsfp_0_0_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_0_0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = arp_ep.ARPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0806 - assert check_frame.arp_htype == 0x0001 - assert check_frame.arp_ptype == 0x0800 - assert check_frame.arp_hlen == 6 - assert check_frame.arp_plen == 4 - assert check_frame.arp_oper == 1 - assert check_frame.arp_sha == 0x020000000000 - assert check_frame.arp_spa == 0xc0a80180 - assert check_frame.arp_tha == 0x000000000000 - assert check_frame.arp_tpa == 0xc0a80181 - - # generate response - arp_frame = arp_ep.ARPFrame() - arp_frame.eth_dest_mac = 0x020000000000 - arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 - arp_frame.eth_type = 0x0806 - arp_frame.arp_htype = 0x0001 - arp_frame.arp_ptype = 0x0800 - arp_frame.arp_hlen = 6 - arp_frame.arp_plen = 4 - arp_frame.arp_oper = 2 - arp_frame.arp_sha = 0xDAD1D2D3D4D5 - arp_frame.arp_spa = 0xc0a80181 - arp_frame.arp_tha = 0x020000000000 - arp_frame.arp_tpa = 0xc0a80180 - - qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data) - - while qsfp_0_0_sink.empty(): - yield clk.posedge - - rx_frame = qsfp_0_0_sink.recv() - check_eth_frame = eth_ep.EthFrame() - check_eth_frame.parse_axis_fcs(rx_frame.data[8:]) - check_frame = udp_ep.UDPFrame() - check_frame.parse_eth(check_eth_frame) - - print(check_frame) - - assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 - assert check_frame.eth_src_mac == 0x020000000000 - assert check_frame.eth_type == 0x0800 - assert check_frame.ip_version == 4 - assert check_frame.ip_ihl == 5 - assert check_frame.ip_dscp == 0 - assert check_frame.ip_ecn == 0 - assert check_frame.ip_identification == 0 - assert check_frame.ip_flags == 2 - assert check_frame.ip_fragment_offset == 0 - assert check_frame.ip_ttl == 64 - assert check_frame.ip_protocol == 0x11 - assert check_frame.ip_source_ip == 0xc0a80180 - assert check_frame.ip_dest_ip == 0xc0a80181 - assert check_frame.udp_source_port == 1234 - assert check_frame.udp_dest_port == 5678 - assert check_frame.payload.data == bytearray(range(32)) - - assert qsfp_0_0_source.empty() - assert qsfp_0_0_sink.empty() - - yield delay(100) - - raise StopSimulation - - return instances() - -def test_bench(): - sim = Simulation(bench()) - sim.run() - -if __name__ == '__main__': - print("Running test...") - test_bench() diff --git a/example/fb2CG/fpga_10g/tb/test_fpga_core.v b/example/fb2CG/fpga_10g/tb/test_fpga_core.v deleted file mode 100644 index 91a59fc3a..000000000 --- a/example/fb2CG/fpga_10g/tb/test_fpga_core.v +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * Testbench for fpga_core - */ -module test_fpga_core; - -// Parameters - -// Inputs -reg clk = 0; -reg rst = 0; -reg [7:0] current_test = 0; - -reg qsfp_0_tx_clk_0 = 0; -reg qsfp_0_tx_rst_0 = 0; -reg qsfp_0_rx_clk_0 = 0; -reg qsfp_0_rx_rst_0 = 0; -reg [63:0] qsfp_0_rxd_0 = 0; -reg [7:0] qsfp_0_rxc_0 = 0; -reg qsfp_0_tx_clk_1 = 0; -reg qsfp_0_tx_rst_1 = 0; -reg qsfp_0_rx_clk_1 = 0; -reg qsfp_0_rx_rst_1 = 0; -reg [63:0] qsfp_0_rxd_1 = 0; -reg [7:0] qsfp_0_rxc_1 = 0; -reg qsfp_0_tx_clk_2 = 0; -reg qsfp_0_tx_rst_2 = 0; -reg qsfp_0_rx_clk_2 = 0; -reg qsfp_0_rx_rst_2 = 0; -reg [63:0] qsfp_0_rxd_2 = 0; -reg [7:0] qsfp_0_rxc_2 = 0; -reg qsfp_0_tx_clk_3 = 0; -reg qsfp_0_tx_rst_3 = 0; -reg qsfp_0_rx_clk_3 = 0; -reg qsfp_0_rx_rst_3 = 0; -reg [63:0] qsfp_0_rxd_3 = 0; -reg [7:0] qsfp_0_rxc_3 = 0; -reg qsfp_1_tx_clk_0 = 0; -reg qsfp_1_tx_rst_0 = 0; -reg qsfp_1_rx_clk_0 = 0; -reg qsfp_1_rx_rst_0 = 0; -reg [63:0] qsfp_1_rxd_0 = 0; -reg [7:0] qsfp_1_rxc_0 = 0; -reg qsfp_1_tx_clk_1 = 0; -reg qsfp_1_tx_rst_1 = 0; -reg qsfp_1_rx_clk_1 = 0; -reg qsfp_1_rx_rst_1 = 0; -reg [63:0] qsfp_1_rxd_1 = 0; -reg [7:0] qsfp_1_rxc_1 = 0; -reg qsfp_1_tx_clk_2 = 0; -reg qsfp_1_tx_rst_2 = 0; -reg qsfp_1_rx_clk_2 = 0; -reg qsfp_1_rx_rst_2 = 0; -reg [63:0] qsfp_1_rxd_2 = 0; -reg [7:0] qsfp_1_rxc_2 = 0; -reg qsfp_1_tx_clk_3 = 0; -reg qsfp_1_tx_rst_3 = 0; -reg qsfp_1_rx_clk_3 = 0; -reg qsfp_1_rx_rst_3 = 0; -reg [63:0] qsfp_1_rxd_3 = 0; -reg [7:0] qsfp_1_rxc_3 = 0; - -// Outputs -wire [7:0] led_red; -wire [7:0] led_green; -wire [1:0] led_bmc; -wire [1:0] led_exp; -wire [63:0] qsfp_0_txd_0; -wire [7:0] qsfp_0_txc_0; -wire [63:0] qsfp_0_txd_1; -wire [7:0] qsfp_0_txc_1; -wire [63:0] qsfp_0_txd_2; -wire [7:0] qsfp_0_txc_2; -wire [63:0] qsfp_0_txd_3; -wire [7:0] qsfp_0_txc_3; -wire [63:0] qsfp_1_txd_0; -wire [7:0] qsfp_1_txc_0; -wire [63:0] qsfp_1_txd_1; -wire [7:0] qsfp_1_txc_1; -wire [63:0] qsfp_1_txd_2; -wire [7:0] qsfp_1_txc_2; -wire [63:0] qsfp_1_txd_3; -wire [7:0] qsfp_1_txc_3; - -initial begin - // myhdl integration - $from_myhdl( - clk, - rst, - current_test, - qsfp_0_tx_clk_0, - qsfp_0_tx_rst_0, - qsfp_0_rx_clk_0, - qsfp_0_rx_rst_0, - qsfp_0_rxd_0, - qsfp_0_rxc_0, - qsfp_0_tx_clk_1, - qsfp_0_tx_rst_1, - qsfp_0_rx_clk_1, - qsfp_0_rx_rst_1, - qsfp_0_rxd_1, - qsfp_0_rxc_1, - qsfp_0_tx_clk_2, - qsfp_0_tx_rst_2, - qsfp_0_rx_clk_2, - qsfp_0_rx_rst_2, - qsfp_0_rxd_2, - qsfp_0_rxc_2, - qsfp_0_tx_clk_3, - qsfp_0_tx_rst_3, - qsfp_0_rx_clk_3, - qsfp_0_rx_rst_3, - qsfp_0_rxd_3, - qsfp_0_rxc_3, - qsfp_1_tx_clk_0, - qsfp_1_tx_rst_0, - qsfp_1_rx_clk_0, - qsfp_1_rx_rst_0, - qsfp_1_rxd_0, - qsfp_1_rxc_0, - qsfp_1_tx_clk_1, - qsfp_1_tx_rst_1, - qsfp_1_rx_clk_1, - qsfp_1_rx_rst_1, - qsfp_1_rxd_1, - qsfp_1_rxc_1, - qsfp_1_tx_clk_2, - qsfp_1_tx_rst_2, - qsfp_1_rx_clk_2, - qsfp_1_rx_rst_2, - qsfp_1_rxd_2, - qsfp_1_rxc_2, - qsfp_1_tx_clk_3, - qsfp_1_tx_rst_3, - qsfp_1_rx_clk_3, - qsfp_1_rx_rst_3, - qsfp_1_rxd_3, - qsfp_1_rxc_3 - ); - $to_myhdl( - led_red, - led_green, - led_bmc, - led_exp, - qsfp_0_txd_0, - qsfp_0_txc_0, - qsfp_0_txd_1, - qsfp_0_txc_1, - qsfp_0_txd_2, - qsfp_0_txc_2, - qsfp_0_txd_3, - qsfp_0_txc_3, - qsfp_1_txd_0, - qsfp_1_txc_0, - qsfp_1_txd_1, - qsfp_1_txc_1, - qsfp_1_txd_2, - qsfp_1_txc_2, - qsfp_1_txd_3, - qsfp_1_txc_3 - ); - - // dump file - $dumpfile("test_fpga_core.lxt"); - $dumpvars(0, test_fpga_core); -end - -fpga_core -UUT ( - .clk(clk), - .rst(rst), - .led_red(led_red), - .led_green(led_green), - .led_bmc(led_bmc), - .led_exp(led_exp), - .qsfp_0_tx_clk_0(qsfp_0_tx_clk_0), - .qsfp_0_tx_rst_0(qsfp_0_tx_rst_0), - .qsfp_0_txd_0(qsfp_0_txd_0), - .qsfp_0_txc_0(qsfp_0_txc_0), - .qsfp_0_rx_clk_0(qsfp_0_rx_clk_0), - .qsfp_0_rx_rst_0(qsfp_0_rx_rst_0), - .qsfp_0_rxd_0(qsfp_0_rxd_0), - .qsfp_0_rxc_0(qsfp_0_rxc_0), - .qsfp_0_tx_clk_1(qsfp_0_tx_clk_1), - .qsfp_0_tx_rst_1(qsfp_0_tx_rst_1), - .qsfp_0_txd_1(qsfp_0_txd_1), - .qsfp_0_txc_1(qsfp_0_txc_1), - .qsfp_0_rx_clk_1(qsfp_0_rx_clk_1), - .qsfp_0_rx_rst_1(qsfp_0_rx_rst_1), - .qsfp_0_rxd_1(qsfp_0_rxd_1), - .qsfp_0_rxc_1(qsfp_0_rxc_1), - .qsfp_0_tx_clk_2(qsfp_0_tx_clk_2), - .qsfp_0_tx_rst_2(qsfp_0_tx_rst_2), - .qsfp_0_txd_2(qsfp_0_txd_2), - .qsfp_0_txc_2(qsfp_0_txc_2), - .qsfp_0_rx_clk_2(qsfp_0_rx_clk_2), - .qsfp_0_rx_rst_2(qsfp_0_rx_rst_2), - .qsfp_0_rxd_2(qsfp_0_rxd_2), - .qsfp_0_rxc_2(qsfp_0_rxc_2), - .qsfp_0_tx_clk_3(qsfp_0_tx_clk_3), - .qsfp_0_tx_rst_3(qsfp_0_tx_rst_3), - .qsfp_0_txd_3(qsfp_0_txd_3), - .qsfp_0_txc_3(qsfp_0_txc_3), - .qsfp_0_rx_clk_3(qsfp_0_rx_clk_3), - .qsfp_0_rx_rst_3(qsfp_0_rx_rst_3), - .qsfp_0_rxd_3(qsfp_0_rxd_3), - .qsfp_0_rxc_3(qsfp_0_rxc_3), - .qsfp_1_tx_clk_0(qsfp_1_tx_clk_0), - .qsfp_1_tx_rst_0(qsfp_1_tx_rst_0), - .qsfp_1_txd_0(qsfp_1_txd_0), - .qsfp_1_txc_0(qsfp_1_txc_0), - .qsfp_1_rx_clk_0(qsfp_1_rx_clk_0), - .qsfp_1_rx_rst_0(qsfp_1_rx_rst_0), - .qsfp_1_rxd_0(qsfp_1_rxd_0), - .qsfp_1_rxc_0(qsfp_1_rxc_0), - .qsfp_1_tx_clk_1(qsfp_1_tx_clk_1), - .qsfp_1_tx_rst_1(qsfp_1_tx_rst_1), - .qsfp_1_txd_1(qsfp_1_txd_1), - .qsfp_1_txc_1(qsfp_1_txc_1), - .qsfp_1_rx_clk_1(qsfp_1_rx_clk_1), - .qsfp_1_rx_rst_1(qsfp_1_rx_rst_1), - .qsfp_1_rxd_1(qsfp_1_rxd_1), - .qsfp_1_rxc_1(qsfp_1_rxc_1), - .qsfp_1_tx_clk_2(qsfp_1_tx_clk_2), - .qsfp_1_tx_rst_2(qsfp_1_tx_rst_2), - .qsfp_1_txd_2(qsfp_1_txd_2), - .qsfp_1_txc_2(qsfp_1_txc_2), - .qsfp_1_rx_clk_2(qsfp_1_rx_clk_2), - .qsfp_1_rx_rst_2(qsfp_1_rx_rst_2), - .qsfp_1_rxd_2(qsfp_1_rxd_2), - .qsfp_1_rxc_2(qsfp_1_rxc_2), - .qsfp_1_tx_clk_3(qsfp_1_tx_clk_3), - .qsfp_1_tx_rst_3(qsfp_1_tx_rst_3), - .qsfp_1_txd_3(qsfp_1_txd_3), - .qsfp_1_txc_3(qsfp_1_txc_3), - .qsfp_1_rx_clk_3(qsfp_1_rx_clk_3), - .qsfp_1_rx_rst_3(qsfp_1_rx_rst_3), - .qsfp_1_rxd_3(qsfp_1_rxd_3), - .qsfp_1_rxc_3(qsfp_1_rxc_3) -); - -endmodule diff --git a/example/fb2CG/fpga_10g/tb/udp_ep.py b/example/fb2CG/fpga_10g/tb/udp_ep.py deleted file mode 120000 index 073c5d3c6..000000000 --- a/example/fb2CG/fpga_10g/tb/udp_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/udp_ep.py \ No newline at end of file diff --git a/example/fb2CG/fpga_10g/tb/xgmii_ep.py b/example/fb2CG/fpga_10g/tb/xgmii_ep.py deleted file mode 120000 index 63b6d3567..000000000 --- a/example/fb2CG/fpga_10g/tb/xgmii_ep.py +++ /dev/null @@ -1 +0,0 @@ -../lib/eth/tb/xgmii_ep.py \ No newline at end of file From a894af48158135851a3a6c980d1636fb76ceb243 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 01:12:08 -0800 Subject: [PATCH 17/37] Add tox.ini --- tox.ini | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tox.ini diff --git a/tox.ini b/tox.ini new file mode 100644 index 000000000..ee496f451 --- /dev/null +++ b/tox.ini @@ -0,0 +1,34 @@ +# tox configuration +[tox] +envlist = py39 +skipsdist = True + +[gh-actions] +python = + 3.9: py39 + +[testenv] +deps = + pytest + pytest-xdist + pytest-split + #cocotb + git+https://github.com/cocotb/cocotb.git@e892a3ea48#egg=cocotb + cocotb-test + cocotbext-axi + cocotbext-eth + scapy + jinja2 + +commands = + pytest -n auto + +# pytest configuration +[pytest] +testpaths = + tb + example +addopts = + --ignore-glob=tb/test_*.py + --ignore-glob=*lib* + --import-mode importlib From 0359d8d76a51ad7d36da9592675c1870cd91664e Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 19:25:59 -0800 Subject: [PATCH 18/37] Use absolute path to test directory --- example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py | 2 +- example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/Arty/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/C10LP/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py | 2 +- example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py | 2 +- example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py | 2 +- example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py | 2 +- example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py | 2 +- example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py | 2 +- example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py | 2 +- example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py | 2 +- example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py | 2 +- example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py index 62f39e28a..c66794ee4 100644 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -226,7 +226,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) 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 c7ef127ab..464a73bf0 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 @@ -226,7 +226,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py b/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py index 6ed21ee44..94de5e46b 100644 --- a/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py @@ -147,7 +147,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py index 74a58792d..72030a8e6 100644 --- a/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -226,7 +226,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py index 74a58792d..72030a8e6 100644 --- a/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -226,7 +226,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py index f2e5b20b6..277262d0e 100644 --- a/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -224,7 +224,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py index adcdea6f2..509ce3670 100644 --- a/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -180,7 +180,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/Arty/fpga/tb/fpga_core/test_fpga_core.py b/example/Arty/fpga/tb/fpga_core/test_fpga_core.py index cce8223fd..55b0dda9c 100644 --- a/example/Arty/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/Arty/fpga/tb/fpga_core/test_fpga_core.py @@ -145,7 +145,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py b/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py index 9d69b913f..f45c407c8 100644 --- a/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py @@ -157,7 +157,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py b/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py index 384499719..6439e820c 100644 --- a/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py @@ -161,7 +161,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py b/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py index 1457503af..f795669cd 100644 --- a/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py @@ -151,7 +151,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py b/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py index 512e286b0..130b745fd 100644 --- a/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py @@ -158,7 +158,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py index 512e286b0..130b745fd 100644 --- a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -158,7 +158,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py b/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py index cdbc9125c..9f9b74837 100644 --- a/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py @@ -217,7 +217,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py b/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py index b0649b146..5dca34cbb 100644 --- a/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py +++ b/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py @@ -204,7 +204,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py b/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py index c34cd29c3..188f184e3 100644 --- a/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py +++ b/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py @@ -148,7 +148,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py index 0ab4ab030..0fd55806d 100644 --- a/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py +++ b/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py @@ -148,7 +148,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py index bbd7de706..cdfd4c48f 100644 --- a/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py +++ b/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py @@ -161,7 +161,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py index 1c6bc2301..dde7d8868 100644 --- a/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py +++ b/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py @@ -155,7 +155,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py b/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py index 4c494afd0..18a192c39 100644 --- a/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py @@ -182,7 +182,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py b/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py index 15cd8a67c..0e670fa55 100644 --- a/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py @@ -163,7 +163,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py index 7418e7b2f..cab7b5356 100644 --- a/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -288,7 +288,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py b/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py index 04e3ff69f..1a70b88e3 100644 --- a/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py @@ -155,7 +155,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py index 0a088c921..f0af0c952 100644 --- a/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -332,7 +332,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py index 04e3ff69f..1a70b88e3 100644 --- a/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py @@ -155,7 +155,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py index a0e26ae8b..6c14482b0 100644 --- a/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -332,7 +332,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py index 74a58792d..72030a8e6 100644 --- a/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -226,7 +226,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py b/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py index f8d3abd92..9fb9cbe56 100644 --- a/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py @@ -189,7 +189,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py b/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py index 897809eaa..8835104fe 100644 --- a/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py @@ -167,7 +167,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) diff --git a/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py index 9a40af312..ced78ba8d 100644 --- a/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -224,7 +224,7 @@ async def run_test(dut): # cocotb-test -tests_dir = os.path.dirname(__file__) +tests_dir = os.path.abspath(os.path.dirname(__file__)) rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) From 29dc7498d3bacfabdaf8144d7e67706566170380 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 19:26:46 -0800 Subject: [PATCH 19/37] Add cocotb MAC testbenches --- tb/axis_gmii_rx/Makefile | 83 +++++ tb/axis_gmii_rx/test_axis_gmii_rx.py | 182 ++++++++++ tb/axis_gmii_tx/Makefile | 95 ++++++ tb/axis_gmii_tx/test_axis_gmii_tx.py | 187 +++++++++++ tb/axis_xgmii_rx_32/Makefile | 89 +++++ tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py | 154 +++++++++ tb/axis_xgmii_rx_64/Makefile | 89 +++++ tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py | 154 +++++++++ tb/axis_xgmii_tx_32/Makefile | 104 ++++++ tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py | 235 +++++++++++++ tb/axis_xgmii_tx_64/Makefile | 104 ++++++ tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py | 235 +++++++++++++ tb/eth_mac_10g/Makefile | 124 +++++++ tb/eth_mac_10g/test_eth_mac_10g.py | 287 ++++++++++++++++ tb/eth_mac_10g_fifo/Makefile | 168 ++++++++++ tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py | 310 ++++++++++++++++++ tb/eth_mac_1g/Makefile | 107 ++++++ tb/eth_mac_1g/test_eth_mac_1g.py | 261 +++++++++++++++ tb/eth_mac_1g_fifo/Makefile | 115 +++++++ tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py | 269 +++++++++++++++ tb/eth_mac_1g_gmii/Makefile | 83 +++++ tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py | 218 ++++++++++++ tb/eth_mac_1g_gmii_fifo/Makefile | 120 +++++++ .../test_eth_mac_1g_gmii_fifo.py | 237 +++++++++++++ tb/eth_mac_1g_rgmii/Makefile | 83 +++++ tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py | 225 +++++++++++++ tb/eth_mac_1g_rgmii_fifo/Makefile | 120 +++++++ .../test_eth_mac_1g_rgmii_fifo.py | 246 ++++++++++++++ tb/eth_mac_mii/Makefile | 81 +++++ tb/eth_mac_mii/test_eth_mac_mii.py | 186 +++++++++++ tb/eth_mac_mii_fifo/Makefile | 118 +++++++ tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py | 204 ++++++++++++ 32 files changed, 5273 insertions(+) create mode 100644 tb/axis_gmii_rx/Makefile create mode 100644 tb/axis_gmii_rx/test_axis_gmii_rx.py create mode 100644 tb/axis_gmii_tx/Makefile create mode 100644 tb/axis_gmii_tx/test_axis_gmii_tx.py create mode 100644 tb/axis_xgmii_rx_32/Makefile create mode 100644 tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py create mode 100644 tb/axis_xgmii_rx_64/Makefile create mode 100644 tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py create mode 100644 tb/axis_xgmii_tx_32/Makefile create mode 100644 tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py create mode 100644 tb/axis_xgmii_tx_64/Makefile create mode 100644 tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py create mode 100644 tb/eth_mac_10g/Makefile create mode 100644 tb/eth_mac_10g/test_eth_mac_10g.py create mode 100644 tb/eth_mac_10g_fifo/Makefile create mode 100644 tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py create mode 100644 tb/eth_mac_1g/Makefile create mode 100644 tb/eth_mac_1g/test_eth_mac_1g.py create mode 100644 tb/eth_mac_1g_fifo/Makefile create mode 100644 tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py create mode 100644 tb/eth_mac_1g_gmii/Makefile create mode 100644 tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py create mode 100644 tb/eth_mac_1g_gmii_fifo/Makefile create mode 100644 tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py create mode 100644 tb/eth_mac_1g_rgmii/Makefile create mode 100644 tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py create mode 100644 tb/eth_mac_1g_rgmii_fifo/Makefile create mode 100644 tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py create mode 100644 tb/eth_mac_mii/Makefile create mode 100644 tb/eth_mac_mii/test_eth_mac_mii.py create mode 100644 tb/eth_mac_mii_fifo/Makefile create mode 100644 tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py diff --git a/tb/axis_gmii_rx/Makefile b/tb/axis_gmii_rx/Makefile new file mode 100644 index 000000000..5092d2525 --- /dev/null +++ b/tb/axis_gmii_rx/Makefile @@ -0,0 +1,83 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = axis_gmii_rx +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 8 +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/axis_gmii_rx/test_axis_gmii_rx.py b/tb/axis_gmii_rx/test_axis_gmii_rx.py new file mode 100644 index 000000000..10d5ee2ef --- /dev/null +++ b/tb/axis_gmii_rx/test_axis_gmii_rx.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, GmiiSource +from cocotbext.axi import AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self._enable_generator = None + self._enable_cr = None + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + self.source = GmiiSource(dut.gmii_rxd, dut.gmii_rx_er, dut.gmii_rx_dv, + dut.clk, dut.rst, dut.clk_enable, dut.mii_select) + self.sink = AxiStreamSink(dut, "m_axis", dut.clk, dut.rst) + + dut.clk_enable.setimmediatevalue(1) + dut.mii_select.setimmediatevalue(0) + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + def set_enable_generator(self, generator=None): + if self._enable_cr is not None: + self._enable_cr.kill() + self._enable_cr = None + + self._enable_generator = generator + + if self._enable_generator is not None: + self._enable_cr = cocotb.fork(self._run_enable()) + + def clear_enable_generator(self): + self.set_enable_generator(None) + + async def _run_enable(self): + for val in self._enable_generator: + self.dut.clk_enable <= val + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): + + tb = TB(dut) + + tb.source.ifg = ifg + tb.dut.mii_select <= mii_sel + + if enable_gen is not None: + tb.set_enable_generator(enable_gen()) + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12, 0]) + factory.add_option("enable_gen", [None, cycle_en]) + factory.add_option("mii_sel", [False, True]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_axis_gmii_rx(request): + dut = "axis_gmii_rx" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 8 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/axis_gmii_tx/Makefile b/tb/axis_gmii_tx/Makefile new file mode 100644 index 000000000..1e0915cb1 --- /dev/null +++ b/tb/axis_gmii_tx/Makefile @@ -0,0 +1,95 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = axis_gmii_tx +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 8 +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +export PARAM_PTP_TAG_ENABLE ?= PTP_TS_ENABLE +export PARAM_PTP_TAG_WIDTH ?= 16 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GPTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -GPTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/axis_gmii_tx/test_axis_gmii_tx.py b/tb/axis_gmii_tx/test_axis_gmii_tx.py new file mode 100644 index 000000000..c1a64e466 --- /dev/null +++ b/tb/axis_gmii_tx/test_axis_gmii_tx.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiSink +from cocotbext.axi import AxiStreamSource + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self._enable_generator = None + self._enable_cr = None + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + self.source = AxiStreamSource(dut, "s_axis", dut.clk, dut.rst) + self.sink = GmiiSink(dut.gmii_txd, dut.gmii_tx_er, dut.gmii_tx_en, + dut.clk, dut.rst, dut.clk_enable, dut.mii_select) + + dut.clk_enable.setimmediatevalue(1) + dut.mii_select.setimmediatevalue(0) + dut.ptp_ts.setimmediatevalue(0) + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + def set_enable_generator(self, generator=None): + if self._enable_cr is not None: + self._enable_cr.kill() + self._enable_cr = None + + self._enable_generator = generator + + if self._enable_generator is not None: + self._enable_cr = cocotb.fork(self._run_enable()) + + def clear_enable_generator(self): + self.set_enable_generator(None) + + async def _run_enable(self): + for val in self._enable_generator: + self.dut.clk_enable <= val + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): + + tb = TB(dut) + + tb.dut.ifg_delay <= ifg + tb.dut.mii_select <= mii_sel + + if enable_gen is not None: + tb.set_enable_generator(enable_gen()) + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("enable_gen", [None, cycle_en]) + factory.add_option("mii_sel", [False, True]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_axis_gmii_tx(request): + dut = "axis_gmii_tx" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 8 + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE'] + parameters['PTP_TAG_WIDTH'] = 16 + parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/axis_xgmii_rx_32/Makefile b/tb/axis_xgmii_rx_32/Makefile new file mode 100644 index 000000000..ffc43934a --- /dev/null +++ b/tb/axis_xgmii_rx_32/Makefile @@ -0,0 +1,89 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = axis_xgmii_rx_32 +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 32 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).CTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GCTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py b/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py new file mode 100644 index 000000000..d988bce14 --- /dev/null +++ b/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiFrame, XgmiiSource +from cocotbext.axi import AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 3.2, units="ns").start()) + + self.source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst) + self.sink = AxiStreamSink(dut, "m_axis", dut.clk, dut.rst) + + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.source.ifg = ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = XgmiiFrame.from_payload(test_data) + await tb.source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12, 0]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_axis_xgmii_rx_32(request): + dut = "axis_xgmii_rx_32" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 32 + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/axis_xgmii_rx_64/Makefile b/tb/axis_xgmii_rx_64/Makefile new file mode 100644 index 000000000..d3924d4d2 --- /dev/null +++ b/tb/axis_xgmii_rx_64/Makefile @@ -0,0 +1,89 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = axis_xgmii_rx_64 +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 64 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).CTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GCTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py b/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py new file mode 100644 index 000000000..0f6780f8d --- /dev/null +++ b/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiFrame, XgmiiSource +from cocotbext.axi import AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + self.source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst) + self.sink = AxiStreamSink(dut, "m_axis", dut.clk, dut.rst) + + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.source.ifg = ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = XgmiiFrame.from_payload(test_data) + await tb.source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12, 0]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_axis_xgmii_rx_64(request): + dut = "axis_xgmii_rx_64" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 64 + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/axis_xgmii_tx_32/Makefile b/tb/axis_xgmii_tx_32/Makefile new file mode 100644 index 000000000..9fdee8590 --- /dev/null +++ b/tb/axis_xgmii_tx_32/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = axis_xgmii_tx_32 +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 32 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_ENABLE_DIC ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +export PARAM_PTP_TAG_ENABLE ?= $(PARAM_PTP_TS_ENABLE) +export PARAM_PTP_TAG_WIDTH ?= 16 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_ENABLE_DIC) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).CTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GCTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GPTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -GPTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py b/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py new file mode 100644 index 000000000..dfa76d753 --- /dev/null +++ b/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator +import pytest + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiSink +from cocotbext.axi import AxiStreamSource + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 3.2, units="ns").start()) + + self.source = AxiStreamSource(dut, "s_axis", dut.clk, dut.rst) + self.sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst) + + dut.ifg_delay.setimmediatevalue(0) + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +async def run_test_alignment(dut, payload_data=None, ifg=12): + + enable_dic = int(os.getenv("PARAM_ENABLE_DIC")) + + tb = TB(dut) + + byte_width = tb.source.width // 8 + + tb.dut.ifg_delay <= ifg + + for length in range(60, 92): + + await tb.reset() + + test_frames = [payload_data(length) for k in range(10)] + start_lane = [] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.ctrl is None + + start_lane.append(rx_frame.rx_start_lane) + + tb.log.info("length: %d", length) + tb.log.info("start_lane: %s", start_lane) + + start_lane_ref = [] + + # compute expected starting lanes + lane = 0 + deficit_idle_count = 0 + + for test_data in test_frames: + if ifg == 0: + lane = 0 + + start_lane_ref.append(lane) + lane = (lane + len(test_data)+4+ifg) % byte_width + + if enable_dic: + offset = lane % 4 + if deficit_idle_count+offset >= 4: + offset += 4 + lane = (lane - offset) % byte_width + deficit_idle_count = (deficit_idle_count + offset) % 4 + else: + offset = lane % 4 + if offset > 0: + offset += 4 + lane = (lane - offset) % byte_width + + tb.log.info("start_lane_ref: %s", start_lane_ref) + + assert start_lane_ref == start_lane + + await RisingEdge(dut.clk) + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + factory = TestFactory(run_test_alignment) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("enable_dic", [1, 0]) +def test_axis_xgmii_tx_32(request, enable_dic): + dut = "axis_xgmii_tx_32" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 32 + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['ENABLE_DIC'] = enable_dic + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE'] + parameters['PTP_TAG_WIDTH'] = 16 + parameters['USER_WIDTH'] = (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/axis_xgmii_tx_64/Makefile b/tb/axis_xgmii_tx_64/Makefile new file mode 100644 index 000000000..f7b39e7e4 --- /dev/null +++ b/tb/axis_xgmii_tx_64/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = axis_xgmii_tx_64 +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 64 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_ENABLE_DIC ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +export PARAM_PTP_TAG_ENABLE ?= $(PARAM_PTP_TS_ENABLE) +export PARAM_PTP_TAG_WIDTH ?= 16 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_ENABLE_DIC) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).CTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GCTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GPTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -GPTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py b/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py new file mode 100644 index 000000000..c65b52d72 --- /dev/null +++ b/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator +import pytest + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiSink +from cocotbext.axi import AxiStreamSource + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + self.source = AxiStreamSource(dut, "s_axis", dut.clk, dut.rst) + self.sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst) + + dut.ifg_delay.setimmediatevalue(0) + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +async def run_test_alignment(dut, payload_data=None, ifg=12): + + enable_dic = int(os.getenv("PARAM_ENABLE_DIC")) + + tb = TB(dut) + + byte_width = tb.source.width // 8 + + tb.dut.ifg_delay <= ifg + + for length in range(60, 92): + + await tb.reset() + + test_frames = [payload_data(length) for k in range(10)] + start_lane = [] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.ctrl is None + + start_lane.append(rx_frame.rx_start_lane) + + tb.log.info("length: %d", length) + tb.log.info("start_lane: %s", start_lane) + + start_lane_ref = [] + + # compute expected starting lanes + lane = 0 + deficit_idle_count = 0 + + for test_data in test_frames: + if ifg == 0: + lane = 0 + + start_lane_ref.append(lane) + lane = (lane + len(test_data)+4+ifg) % byte_width + + if enable_dic: + offset = lane % 4 + if deficit_idle_count+offset >= 4: + offset += 4 + lane = (lane - offset) % byte_width + deficit_idle_count = (deficit_idle_count + offset) % 4 + else: + offset = lane % 4 + if offset > 0: + offset += 4 + lane = (lane - offset) % byte_width + + tb.log.info("start_lane_ref: %s", start_lane_ref) + + assert start_lane_ref == start_lane + + await RisingEdge(dut.clk) + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + factory = TestFactory(run_test_alignment) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("enable_dic", [1, 0]) +def test_axis_xgmii_tx_64(request, enable_dic): + dut = "axis_xgmii_tx_64" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 64 + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['ENABLE_DIC'] = enable_dic + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE'] + parameters['PTP_TAG_WIDTH'] = 16 + parameters['USER_WIDTH'] = (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_10g/Makefile b/tb/eth_mac_10g/Makefile new file mode 100644 index 000000000..15d943dd4 --- /dev/null +++ b/tb/eth_mac_10g/Makefile @@ -0,0 +1,124 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_10g +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/axis_xgmii_rx_32.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_tx_32.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 64 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_ENABLE_DIC ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_PTP_PERIOD_NS ?= 6 +export PARAM_PTP_PERIOD_FNS ?= 26214 +export PARAM_TX_PTP_TS_ENABLE ?= 0 +export PARAM_TX_PTP_TS_WIDTH ?= 96 +export PARAM_TX_PTP_TAG_ENABLE ?= $(PARAM_TX_PTP_TS_ENABLE) +export PARAM_TX_PTP_TAG_WIDTH ?= 16 +export PARAM_RX_PTP_TS_ENABLE ?= 0 +export PARAM_RX_PTP_TS_WIDTH ?= 96 +# export PARAM_TX_USER_WIDTH ?= (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1 +export PARAM_TX_USER_WIDTH ?= 1 +# export PARAM_RX_USER_WIDTH ?= (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1 +export PARAM_RX_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH)-$(PARAM_ENABLE_DIC) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).CTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_PERIOD_NS=$(PARAM_PTP_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_PERIOD_FNS=$(PARAM_PTP_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TS_ENABLE=$(PARAM_TX_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TS_WIDTH=$(PARAM_TX_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TAG_ENABLE=$(PARAM_TX_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TAG_WIDTH=$(PARAM_TX_PTP_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_PTP_TS_ENABLE=$(PARAM_RX_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).RX_PTP_TS_WIDTH=$(PARAM_RX_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_USER_WIDTH=$(PARAM_TX_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_USER_WIDTH=$(PARAM_RX_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GCTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GPTP_PERIOD_NS=$(PARAM_PTP_PERIOD_NS) + COMPILE_ARGS += -GPTP_PERIOD_FNS=$(PARAM_PTP_PERIOD_FNS) + COMPILE_ARGS += -GTX_PTP_TS_ENABLE=$(PARAM_TX_PTP_TS_ENABLE) + COMPILE_ARGS += -GTX_PTP_TS_WIDTH=$(PARAM_TX_PTP_TS_WIDTH) + COMPILE_ARGS += -GTX_PTP_TAG_ENABLE=$(PARAM_TX_PTP_TAG_ENABLE) + COMPILE_ARGS += -GTX_PTP_TAG_WIDTH=$(PARAM_TX_PTP_TAG_WIDTH) + COMPILE_ARGS += -GRX_PTP_TS_ENABLE=$(PARAM_RX_PTP_TS_ENABLE) + COMPILE_ARGS += -GRX_PTP_TS_WIDTH=$(PARAM_RX_PTP_TS_WIDTH) + COMPILE_ARGS += -GTX_USER_WIDTH=$(PARAM_TX_USER_WIDTH) + COMPILE_ARGS += -GRX_USER_WIDTH=$(PARAM_RX_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_10g/test_eth_mac_10g.py b/tb/eth_mac_10g/test_eth_mac_10g.py new file mode 100644 index 000000000..32461075e --- /dev/null +++ b/tb/eth_mac_10g/test_eth_mac_10g.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import pytest +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + if len(dut.xgmii_txd) == 64: + cocotb.fork(Clock(dut.rx_clk, 6.4, units="ns").start()) + cocotb.fork(Clock(dut.tx_clk, 6.4, units="ns").start()) + else: + cocotb.fork(Clock(dut.rx_clk, 3.2, units="ns").start()) + cocotb.fork(Clock(dut.tx_clk, 3.2, units="ns").start()) + + self.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) + self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.tx_clk, dut.tx_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.rx_clk, dut.rx_rst) + + dut.rx_ptp_ts.setimmediatevalue(0) + dut.tx_ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rx_rst.setimmediatevalue(0) + self.dut.tx_rst.setimmediatevalue(0) + await RisingEdge(self.dut.rx_clk) + await RisingEdge(self.dut.rx_clk) + self.dut.rx_rst <= 1 + self.dut.tx_rst <= 1 + await RisingEdge(self.dut.rx_clk) + await RisingEdge(self.dut.rx_clk) + self.dut.rx_rst <= 0 + self.dut.tx_rst <= 0 + await RisingEdge(self.dut.rx_clk) + await RisingEdge(self.dut.rx_clk) + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.xgmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = XgmiiFrame.from_payload(test_data) + await tb.xgmii_source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.xgmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.xgmii_sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + + assert tb.xgmii_sink.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +async def run_test_tx_alignment(dut, payload_data=None, ifg=12): + + enable_dic = int(os.getenv("PARAM_ENABLE_DIC")) + + tb = TB(dut) + + byte_width = tb.axis_source.width // 8 + + tb.xgmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + + for length in range(60, 92): + + await tb.reset() + + test_frames = [payload_data(length) for k in range(10)] + start_lane = [] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.xgmii_sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.ctrl is None + + start_lane.append(rx_frame.rx_start_lane) + + tb.log.info("length: %d", length) + tb.log.info("start_lane: %s", start_lane) + + start_lane_ref = [] + + # compute expected starting lanes + lane = 0 + deficit_idle_count = 0 + + for test_data in test_frames: + if ifg == 0: + lane = 0 + + start_lane_ref.append(lane) + lane = (lane + len(test_data)+4+ifg) % byte_width + + if enable_dic: + offset = lane % 4 + if deficit_idle_count+offset >= 4: + offset += 4 + lane = (lane - offset) % byte_width + deficit_idle_count = (deficit_idle_count + offset) % 4 + else: + offset = lane % 4 + if offset > 0: + offset += 4 + lane = (lane - offset) % byte_width + + tb.log.info("start_lane_ref: %s", start_lane_ref) + + assert start_lane_ref == start_lane + + await RisingEdge(dut.tx_clk) + + assert tb.xgmii_sink.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12, 0]) + factory.generate_tests() + + factory = TestFactory(run_test_tx_alignment) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("enable_dic", [1, 0]) +@pytest.mark.parametrize("data_width", [32, 64]) +def test_eth_mac_10g(request, data_width, enable_dic): + dut = "eth_mac_10g" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "axis_xgmii_rx_32.v"), + os.path.join(rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(rtl_dir, "axis_xgmii_tx_32.v"), + os.path.join(rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = data_width + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['ENABLE_DIC'] = enable_dic + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3 + parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333 + parameters['TX_PTP_TS_ENABLE'] = 0 + parameters['TX_PTP_TS_WIDTH'] = 96 + parameters['TX_PTP_TAG_ENABLE'] = parameters['TX_PTP_TS_ENABLE'] + parameters['TX_PTP_TAG_WIDTH'] = 16 + parameters['RX_PTP_TS_ENABLE'] = 0 + parameters['RX_PTP_TS_WIDTH'] = 96 + parameters['TX_USER_WIDTH'] = (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1 + parameters['RX_USER_WIDTH'] = (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_10g_fifo/Makefile b/tb/eth_mac_10g_fifo/Makefile new file mode 100644 index 000000000..397549b2a --- /dev/null +++ b/tb/eth_mac_10g_fifo/Makefile @@ -0,0 +1,168 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_10g_fifo +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/eth_mac_10g.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_rx_32.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_tx_32.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_rx_64.v +VERILOG_SOURCES += ../../rtl/axis_xgmii_tx_64.v +VERILOG_SOURCES += ../../rtl/lfsr.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +export PARAM_DATA_WIDTH ?= 64 +export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_AXIS_DATA_WIDTH ?= $(PARAM_DATA_WIDTH) +export PARAM_AXIS_KEEP_ENABLE ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) \> 8 ) +export PARAM_AXIS_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_ENABLE_DIC ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_TX_FIFO_DEPTH ?= 16384 +export PARAM_TX_FIFO_PIPELINE_OUTPUT ?= 2 +export PARAM_TX_FRAME_FIFO ?= 1 +export PARAM_TX_DROP_BAD_FRAME ?= $(PARAM_TX_FRAME_FIFO) +export PARAM_TX_DROP_WHEN_FULL ?= 0 +export PARAM_RX_FIFO_DEPTH ?= 16384 +export PARAM_RX_FIFO_PIPELINE_OUTPUT ?= 2 +export PARAM_RX_FRAME_FIFO ?= 1 +export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) +export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) +export PARAM_LOGIC_PTP_PERIOD_NS ?= 6 +export PARAM_LOGIC_PTP_PERIOD_FNS ?= 26214 +export PARAM_PTP_PERIOD_NS ?= 6 +export PARAM_PTP_PERIOD_FNS ?= 26214 +export PARAM_PTP_USE_SAMPLE_CLOCK ?= 0 +export PARAM_TX_PTP_TS_ENABLE ?= 0 +export PARAM_RX_PTP_TS_ENABLE ?= 0 +export PARAM_TX_PTP_TS_FIFO_DEPTH ?= 64 +export PARAM_RX_PTP_TS_FIFO_DEPTH ?= 64 +export PARAM_PTP_TS_WIDTH ?= 96 +export PARAM_TX_PTP_TAG_ENABLE ?= 0 +export PARAM_PTP_TAG_WIDTH ?= 16 + +SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH)-$(PARAM_ENABLE_DIC) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).CTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_PIPELINE_OUTPUT=$(PARAM_TX_FIFO_PIPELINE_OUTPUT) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_PIPELINE_OUTPUT=$(PARAM_RX_FIFO_PIPELINE_OUTPUT) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + COMPILE_ARGS += -P $(TOPLEVEL).LOGIC_PTP_PERIOD_NS=$(PARAM_LOGIC_PTP_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).LOGIC_PTP_PERIOD_FNS=$(PARAM_LOGIC_PTP_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_PERIOD_NS=$(PARAM_PTP_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_PERIOD_FNS=$(PARAM_PTP_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_USE_SAMPLE_CLOCK=$(PARAM_PTP_USE_SAMPLE_CLOCK) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TS_ENABLE=$(PARAM_TX_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).RX_PTP_TS_ENABLE=$(PARAM_RX_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TS_FIFO_DEPTH=$(PARAM_TX_PTP_TS_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_PTP_TS_FIFO_DEPTH=$(PARAM_RX_PTP_TS_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TAG_ENABLE=$(PARAM_TX_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GCTRL_WIDTH=$(PARAM_CTRL_WIDTH) + COMPILE_ARGS += -GAXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -GAXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GTX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -GTX_FIFO_PIPELINE_OUTPUT=$(PARAM_TX_FIFO_PIPELINE_OUTPUT) + COMPILE_ARGS += -GTX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -GTX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -GTX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -GRX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -GRX_FIFO_PIPELINE_OUTPUT=$(PARAM_RX_FIFO_PIPELINE_OUTPUT) + COMPILE_ARGS += -GRX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -GRX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -GRX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + COMPILE_ARGS += -GLOGIC_PTP_PERIOD_NS=$(PARAM_LOGIC_PTP_PERIOD_NS) + COMPILE_ARGS += -GLOGIC_PTP_PERIOD_FNS=$(PARAM_LOGIC_PTP_PERIOD_FNS) + COMPILE_ARGS += -GPTP_PERIOD_NS=$(PARAM_PTP_PERIOD_NS) + COMPILE_ARGS += -GPTP_PERIOD_FNS=$(PARAM_PTP_PERIOD_FNS) + COMPILE_ARGS += -GPTP_USE_SAMPLE_CLOCK=$(PARAM_PTP_USE_SAMPLE_CLOCK) + COMPILE_ARGS += -GTX_PTP_TS_ENABLE=$(PARAM_TX_PTP_TS_ENABLE) + COMPILE_ARGS += -GRX_PTP_TS_ENABLE=$(PARAM_RX_PTP_TS_ENABLE) + COMPILE_ARGS += -GTX_PTP_TS_FIFO_DEPTH=$(PARAM_TX_PTP_TS_FIFO_DEPTH) + COMPILE_ARGS += -GRX_PTP_TS_FIFO_DEPTH=$(PARAM_RX_PTP_TS_FIFO_DEPTH) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GTX_PTP_TAG_ENABLE=$(PARAM_TX_PTP_TAG_ENABLE) + COMPILE_ARGS += -GPTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py new file mode 100644 index 000000000..fc2c1e501 --- /dev/null +++ b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import pytest +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + if len(dut.xgmii_txd) == 64: + cocotb.fork(Clock(dut.logic_clk, 6.4, units="ns").start()) + cocotb.fork(Clock(dut.rx_clk, 6.4, units="ns").start()) + cocotb.fork(Clock(dut.tx_clk, 6.4, units="ns").start()) + else: + cocotb.fork(Clock(dut.logic_clk, 3.2, units="ns").start()) + cocotb.fork(Clock(dut.rx_clk, 3.2, units="ns").start()) + cocotb.fork(Clock(dut.tx_clk, 3.2, units="ns").start()) + + self.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) + self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.logic_clk, dut.logic_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.logic_clk, dut.logic_rst) + + dut.ptp_sample_clk.setimmediatevalue(0) + dut.ptp_ts_96.setimmediatevalue(0) + + async def reset(self): + self.dut.logic_rst.setimmediatevalue(0) + self.dut.rx_rst.setimmediatevalue(0) + self.dut.tx_rst.setimmediatevalue(0) + await RisingEdge(self.dut.logic_clk) + await RisingEdge(self.dut.logic_clk) + self.dut.logic_rst <= 1 + self.dut.rx_rst <= 1 + self.dut.tx_rst <= 1 + await RisingEdge(self.dut.logic_clk) + await RisingEdge(self.dut.logic_clk) + self.dut.logic_rst <= 0 + self.dut.rx_rst <= 0 + self.dut.tx_rst <= 0 + await RisingEdge(self.dut.logic_clk) + await RisingEdge(self.dut.logic_clk) + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.xgmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = XgmiiFrame.from_payload(test_data) + await tb.xgmii_source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.xgmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.xgmii_sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + + assert tb.xgmii_sink.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +async def run_test_tx_alignment(dut, payload_data=None, ifg=12): + + enable_dic = int(os.getenv("PARAM_ENABLE_DIC")) + + tb = TB(dut) + + byte_width = tb.axis_source.width // 8 + + tb.xgmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + + for length in range(60, 92): + + await tb.reset() + + test_frames = [payload_data(length) for k in range(10)] + start_lane = [] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.xgmii_sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.ctrl is None + + start_lane.append(rx_frame.rx_start_lane) + + tb.log.info("length: %d", length) + tb.log.info("start_lane: %s", start_lane) + + start_lane_ref = [] + + # compute expected starting lanes + lane = 0 + deficit_idle_count = 0 + + for test_data in test_frames: + if ifg == 0: + lane = 0 + + start_lane_ref.append(lane) + lane = (lane + len(test_data)+4+ifg) % byte_width + + if enable_dic: + offset = lane % 4 + if deficit_idle_count+offset >= 4: + offset += 4 + lane = (lane - offset) % byte_width + deficit_idle_count = (deficit_idle_count + offset) % 4 + else: + offset = lane % 4 + if offset > 0: + offset += 4 + lane = (lane - offset) % byte_width + + tb.log.info("start_lane_ref: %s", start_lane_ref) + + assert start_lane_ref == start_lane + + await RisingEdge(dut.logic_clk) + + assert tb.xgmii_sink.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12, 0]) + factory.generate_tests() + + factory = TestFactory(run_test_tx_alignment) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("enable_dic", [1, 0]) +@pytest.mark.parametrize("data_width", [32, 64]) +def test_eth_mac_10g_fifo(request, data_width, enable_dic): + dut = "eth_mac_10g_fifo" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "eth_mac_10g.v"), + os.path.join(rtl_dir, "axis_xgmii_rx_32.v"), + os.path.join(rtl_dir, "axis_xgmii_rx_64.v"), + os.path.join(rtl_dir, "axis_xgmii_tx_32.v"), + os.path.join(rtl_dir, "axis_xgmii_tx_64.v"), + os.path.join(rtl_dir, "lfsr.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = data_width + parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['AXIS_DATA_WIDTH'] = parameters['DATA_WIDTH'] + parameters['AXIS_KEEP_ENABLE'] = int(parameters['AXIS_DATA_WIDTH'] > 8) + parameters['AXIS_KEEP_WIDTH'] = parameters['AXIS_DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['ENABLE_DIC'] = enable_dic + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['TX_FIFO_DEPTH'] = 16384 + parameters['TX_FIFO_PIPELINE_OUTPUT'] = 2 + parameters['TX_FRAME_FIFO'] = 1 + parameters['TX_DROP_BAD_FRAME'] = parameters['TX_FRAME_FIFO'] + parameters['TX_DROP_WHEN_FULL'] = 0 + parameters['RX_FIFO_DEPTH'] = 16384 + parameters['RX_FIFO_PIPELINE_OUTPUT'] = 2 + parameters['RX_FRAME_FIFO'] = 1 + parameters['RX_DROP_BAD_FRAME'] = parameters['RX_FRAME_FIFO'] + parameters['RX_DROP_WHEN_FULL'] = parameters['RX_FRAME_FIFO'] + parameters['LOGIC_PTP_PERIOD_NS'] = 0x6 if parameters['AXIS_DATA_WIDTH'] == 64 else 0x3 + parameters['LOGIC_PTP_PERIOD_FNS'] = 0x6666 if parameters['AXIS_DATA_WIDTH'] == 64 else 0x3333 + parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3 + parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333 + parameters['PTP_USE_SAMPLE_CLOCK'] = 0 + parameters['TX_PTP_TS_ENABLE'] = 0 + parameters['RX_PTP_TS_ENABLE'] = 0 + parameters['TX_PTP_TS_FIFO_DEPTH'] = 64 + parameters['RX_PTP_TS_FIFO_DEPTH'] = 64 + parameters['PTP_TS_WIDTH'] = 96 + parameters['TX_PTP_TAG_ENABLE'] = 0 + parameters['PTP_TAG_WIDTH'] = 16 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_1g/Makefile b/tb/eth_mac_1g/Makefile new file mode 100644 index 000000000..80b4a50ac --- /dev/null +++ b/tb/eth_mac_1g/Makefile @@ -0,0 +1,107 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_1g +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 8 +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_TX_PTP_TS_ENABLE ?= 0 +export PARAM_TX_PTP_TS_WIDTH ?= 96 +export PARAM_TX_PTP_TAG_ENABLE ?= $(PARAM_TX_PTP_TS_ENABLE) +export PARAM_TX_PTP_TAG_WIDTH ?= 16 +export PARAM_RX_PTP_TS_ENABLE ?= 0 +export PARAM_RX_PTP_TS_WIDTH ?= 96 +# export PARAM_TX_USER_WIDTH ?= (TX_PTP_TAG_WIDTH if TX_PTP_TAG_ENABLE else 0) + 1 +export PARAM_TX_USER_WIDTH ?= 1 +# export PARAM_RX_USER_WIDTH ?= (RX_PTP_TS_WIDTH if RX_PTP_TS_ENABLE else 0) + 1 +export PARAM_RX_USER_WIDTH ?= 1 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TS_ENABLE=$(PARAM_TX_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TS_WIDTH=$(PARAM_TX_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TAG_ENABLE=$(PARAM_TX_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).TX_PTP_TAG_WIDTH=$(PARAM_TX_PTP_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_PTP_TS_ENABLE=$(PARAM_RX_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).RX_PTP_TS_WIDTH=$(PARAM_RX_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_USER_WIDTH=$(PARAM_TX_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_USER_WIDTH=$(PARAM_RX_USER_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GTX_PTP_TS_ENABLE=$(PARAM_TX_PTP_TS_ENABLE) + COMPILE_ARGS += -GTX_PTP_TS_WIDTH=$(PARAM_TX_PTP_TS_WIDTH) + COMPILE_ARGS += -GTX_PTP_TAG_ENABLE=$(PARAM_TX_PTP_TAG_ENABLE) + COMPILE_ARGS += -GTX_PTP_TAG_WIDTH=$(PARAM_TX_PTP_TAG_WIDTH) + COMPILE_ARGS += -GRX_PTP_TS_ENABLE=$(PARAM_RX_PTP_TS_ENABLE) + COMPILE_ARGS += -GRX_PTP_TS_WIDTH=$(PARAM_RX_PTP_TS_WIDTH) + COMPILE_ARGS += -GTX_USER_WIDTH=$(PARAM_TX_USER_WIDTH) + COMPILE_ARGS += -GRX_USER_WIDTH=$(PARAM_RX_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_1g/test_eth_mac_1g.py b/tb/eth_mac_1g/test_eth_mac_1g.py new file mode 100644 index 000000000..a2a053ac0 --- /dev/null +++ b/tb/eth_mac_1g/test_eth_mac_1g.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self._enable_generator_rx = None + self._enable_generator_tx = None + self._enable_cr_rx = None + self._enable_cr_tx = None + + cocotb.fork(Clock(dut.rx_clk, 8, units="ns").start()) + cocotb.fork(Clock(dut.tx_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.gmii_rxd, dut.gmii_rx_er, dut.gmii_rx_dv, + dut.rx_clk, dut.rx_rst, dut.rx_clk_enable, dut.rx_mii_select) + self.gmii_sink = GmiiSink(dut.gmii_txd, dut.gmii_tx_er, dut.gmii_tx_en, + dut.tx_clk, dut.tx_rst, dut.tx_clk_enable, dut.tx_mii_select) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.tx_clk, dut.tx_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.rx_clk, dut.rx_rst) + + dut.rx_clk_enable.setimmediatevalue(1) + dut.tx_clk_enable.setimmediatevalue(1) + dut.rx_mii_select.setimmediatevalue(0) + dut.tx_mii_select.setimmediatevalue(0) + dut.rx_ptp_ts.setimmediatevalue(0) + dut.tx_ptp_ts.setimmediatevalue(0) + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.rx_rst.setimmediatevalue(0) + self.dut.tx_rst.setimmediatevalue(0) + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.rx_rst <= 1 + self.dut.tx_rst <= 1 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.rx_rst <= 0 + self.dut.tx_rst <= 0 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + + def set_enable_generator_rx(self, generator=None): + if self._enable_cr_rx is not None: + self._enable_cr_rx.kill() + self._enable_cr_rx = None + + self._enable_generator_rx = generator + + if self._enable_generator_rx is not None: + self._enable_cr_rx = cocotb.fork(self._run_enable_rx()) + + def set_enable_generator_tx(self, generator=None): + if self._enable_cr_tx is not None: + self._enable_cr_tx.kill() + self._enable_cr_tx = None + + self._enable_generator_tx = generator + + if self._enable_generator_tx is not None: + self._enable_cr_tx = cocotb.fork(self._run_enable_tx()) + + def clear_enable_generator_rx(self): + self.set_enable_generator_rx(None) + + def clear_enable_generator_tx(self): + self.set_enable_generator_tx(None) + + async def _run_enable_rx(self): + for val in self._enable_generator_rx: + self.dut.rx_clk_enable <= val + await RisingEdge(self.dut.rx_clk) + + async def _run_enable_tx(self): + for val in self._enable_generator_tx: + self.dut.tx_clk_enable <= val + await RisingEdge(self.dut.tx_clk) + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): + + tb = TB(dut) + + tb.gmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + tb.dut.rx_mii_select <= mii_sel + tb.dut.tx_mii_select <= mii_sel + + if enable_gen is not None: + tb.set_enable_generator_rx(enable_gen()) + tb.set_enable_generator_tx(enable_gen()) + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.gmii_source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): + + tb = TB(dut) + + tb.gmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + tb.dut.rx_mii_select <= mii_sel + tb.dut.tx_mii_select <= mii_sel + + if enable_gen is not None: + tb.set_enable_generator_rx(enable_gen()) + tb.set_enable_generator_tx(enable_gen()) + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.gmii_sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.gmii_sink.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("enable_gen", [None, cycle_en]) + factory.add_option("mii_sel", [False, True]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_1g(request): + dut = "eth_mac_1g" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 8 + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['TX_PTP_TS_ENABLE'] = 0 + parameters['TX_PTP_TS_WIDTH'] = 96 + parameters['TX_PTP_TAG_ENABLE'] = parameters['TX_PTP_TS_ENABLE'] + parameters['TX_PTP_TAG_WIDTH'] = 16 + parameters['RX_PTP_TS_ENABLE'] = 0 + parameters['RX_PTP_TS_WIDTH'] = 96 + parameters['TX_USER_WIDTH'] = (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1 + parameters['RX_USER_WIDTH'] = (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_1g_fifo/Makefile b/tb/eth_mac_1g_fifo/Makefile new file mode 100644 index 000000000..4859f6560 --- /dev/null +++ b/tb/eth_mac_1g_fifo/Makefile @@ -0,0 +1,115 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_1g_fifo +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +export PARAM_AXIS_DATA_WIDTH ?= 8 +export PARAM_AXIS_KEEP_ENABLE ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) \> 8 ) +export PARAM_AXIS_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_TX_FIFO_DEPTH ?= 16384 +export PARAM_TX_FRAME_FIFO ?= 1 +export PARAM_TX_DROP_BAD_FRAME ?= $(PARAM_TX_FRAME_FIFO) +export PARAM_TX_DROP_WHEN_FULL ?= 0 +export PARAM_RX_FIFO_DEPTH ?= 16384 +export PARAM_RX_FRAME_FIFO ?= 1 +export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) +export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -GAXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GTX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -GTX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -GTX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -GTX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -GRX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -GRX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -GRX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -GRX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py b/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py new file mode 100644 index 000000000..9e0b23774 --- /dev/null +++ b/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self._enable_generator_rx = None + self._enable_generator_tx = None + self._enable_cr_rx = None + self._enable_cr_tx = None + + cocotb.fork(Clock(dut.logic_clk, 8, units="ns").start()) + cocotb.fork(Clock(dut.rx_clk, 8, units="ns").start()) + cocotb.fork(Clock(dut.tx_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.gmii_rxd, dut.gmii_rx_er, dut.gmii_rx_dv, + dut.rx_clk, dut.rx_rst, dut.rx_clk_enable, dut.rx_mii_select) + self.gmii_sink = GmiiSink(dut.gmii_txd, dut.gmii_tx_er, dut.gmii_tx_en, + dut.tx_clk, dut.tx_rst, dut.tx_clk_enable, dut.tx_mii_select) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.logic_clk, dut.logic_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.logic_clk, dut.logic_rst) + + dut.rx_clk_enable.setimmediatevalue(1) + dut.tx_clk_enable.setimmediatevalue(1) + dut.rx_mii_select.setimmediatevalue(0) + dut.tx_mii_select.setimmediatevalue(0) + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.logic_rst.setimmediatevalue(0) + self.dut.rx_rst.setimmediatevalue(0) + self.dut.tx_rst.setimmediatevalue(0) + for k in range(10): + await RisingEdge(self.dut.logic_clk) + self.dut.logic_rst <= 1 + self.dut.rx_rst <= 1 + self.dut.tx_rst <= 1 + for k in range(10): + await RisingEdge(self.dut.logic_clk) + self.dut.logic_rst <= 0 + self.dut.rx_rst <= 0 + self.dut.tx_rst <= 0 + for k in range(10): + await RisingEdge(self.dut.logic_clk) + + def set_enable_generator_rx(self, generator=None): + if self._enable_cr_rx is not None: + self._enable_cr_rx.kill() + self._enable_cr_rx = None + + self._enable_generator_rx = generator + + if self._enable_generator_rx is not None: + self._enable_cr_rx = cocotb.fork(self._run_enable_rx()) + + def set_enable_generator_tx(self, generator=None): + if self._enable_cr_tx is not None: + self._enable_cr_tx.kill() + self._enable_cr_tx = None + + self._enable_generator_tx = generator + + if self._enable_generator_tx is not None: + self._enable_cr_tx = cocotb.fork(self._run_enable_tx()) + + def clear_enable_generator_rx(self): + self.set_enable_generator_rx(None) + + def clear_enable_generator_tx(self): + self.set_enable_generator_tx(None) + + async def _run_enable_rx(self): + for val in self._enable_generator_rx: + self.dut.rx_clk_enable <= val + await RisingEdge(self.dut.rx_clk) + + async def _run_enable_tx(self): + for val in self._enable_generator_tx: + self.dut.tx_clk_enable <= val + await RisingEdge(self.dut.tx_clk) + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): + + tb = TB(dut) + + tb.gmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + tb.dut.rx_mii_select <= mii_sel + tb.dut.tx_mii_select <= mii_sel + + if enable_gen is not None: + tb.set_enable_generator_rx(enable_gen()) + tb.set_enable_generator_tx(enable_gen()) + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.gmii_source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): + + tb = TB(dut) + + tb.gmii_source.ifg = ifg + tb.dut.ifg_delay <= ifg + tb.dut.rx_mii_select <= mii_sel + tb.dut.tx_mii_select <= mii_sel + + if enable_gen is not None: + tb.set_enable_generator_rx(enable_gen()) + tb.set_enable_generator_tx(enable_gen()) + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.gmii_sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.gmii_sink.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("enable_gen", [None, cycle_en]) + factory.add_option("mii_sel", [False, True]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_1g_fifo(request): + dut = "eth_mac_1g_fifo" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + parameters['AXIS_DATA_WIDTH'] = 8 + parameters['AXIS_KEEP_ENABLE'] = int(parameters['AXIS_DATA_WIDTH'] > 8) + parameters['AXIS_KEEP_WIDTH'] = parameters['AXIS_DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['TX_FIFO_DEPTH'] = 16384 + parameters['TX_FRAME_FIFO'] = 1 + parameters['TX_DROP_BAD_FRAME'] = parameters['TX_FRAME_FIFO'] + parameters['TX_DROP_WHEN_FULL'] = 0 + parameters['RX_FIFO_DEPTH'] = 16384 + parameters['RX_FRAME_FIFO'] = 1 + parameters['RX_DROP_BAD_FRAME'] = parameters['RX_FRAME_FIFO'] + parameters['RX_DROP_WHEN_FULL'] = parameters['RX_FRAME_FIFO'] + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_1g_gmii/Makefile b/tb/eth_mac_1g_gmii/Makefile new file mode 100644 index 000000000..f1e9f2fb7 --- /dev/null +++ b/tb/eth_mac_1g_gmii/Makefile @@ -0,0 +1,83 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_1g_gmii +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/gmii_phy_if.v +VERILOG_SOURCES += ../../rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../rtl/ssio_sdr_out.v +VERILOG_SOURCES += ../../rtl/oddr.v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py b/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py new file mode 100644 index 000000000..caa2fbabb --- /dev/null +++ b/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, GmiiPhy +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.gtx_clk, 8, units="ns").start()) + + self.gmii_phy = GmiiPhy(dut.gmii_txd, dut.gmii_tx_er, dut.gmii_tx_en, dut.mii_tx_clk, dut.gmii_tx_clk, + dut.gmii_rxd, dut.gmii_rx_er, dut.gmii_rx_dv, dut.gmii_rx_clk, speed=speed) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.tx_clk, dut.tx_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.rx_clk, dut.rx_rst) + + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.gtx_rst.setimmediatevalue(0) + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.gtx_rst <= 1 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.gtx_rst <= 0 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + + def set_speed(self, speed): + pass + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.gmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + tb.set_speed(speed) + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.gmii_phy.rx.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.gmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + tb.set_speed(speed) + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.gmii_phy.tx.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.gmii_phy.tx.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("speed", [1000e6, 100e6, 10e6]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_1g_gmii(request): + dut = "eth_mac_1g_gmii" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "gmii_phy_if.v"), + os.path.join(rtl_dir, "ssio_sdr_in.v"), + os.path.join(rtl_dir, "ssio_sdr_out.v"), + os.path.join(rtl_dir, "oddr.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_1g_gmii_fifo/Makefile b/tb/eth_mac_1g_gmii_fifo/Makefile new file mode 100644 index 000000000..27f103221 --- /dev/null +++ b/tb/eth_mac_1g_gmii_fifo/Makefile @@ -0,0 +1,120 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_1g_gmii_fifo +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/eth_mac_1g_gmii.v +VERILOG_SOURCES += ../../rtl/gmii_phy_if.v +VERILOG_SOURCES += ../../rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../rtl/ssio_sdr_out.v +VERILOG_SOURCES += ../../rtl/oddr.v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +export PARAM_AXIS_DATA_WIDTH ?= 8 +export PARAM_AXIS_KEEP_ENABLE ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) \> 8 ) +export PARAM_AXIS_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_TX_FIFO_DEPTH ?= 16384 +export PARAM_TX_FRAME_FIFO ?= 1 +export PARAM_TX_DROP_BAD_FRAME ?= $(PARAM_TX_FRAME_FIFO) +export PARAM_TX_DROP_WHEN_FULL ?= 0 +export PARAM_RX_FIFO_DEPTH ?= 16384 +export PARAM_RX_FRAME_FIFO ?= 1 +export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) +export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -GAXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GTX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -GTX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -GTX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -GTX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -GRX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -GRX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -GRX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -GRX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py b/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py new file mode 100644 index 000000000..b0883ad5e --- /dev/null +++ b/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, GmiiPhy +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.gtx_clk, 8, units="ns").start()) + cocotb.fork(Clock(dut.logic_clk, 8, units="ns").start()) + + self.gmii_phy = GmiiPhy(dut.gmii_txd, dut.gmii_tx_er, dut.gmii_tx_en, dut.mii_tx_clk, dut.gmii_tx_clk, + dut.gmii_rxd, dut.gmii_rx_er, dut.gmii_rx_dv, dut.gmii_rx_clk, speed=speed) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.logic_clk, dut.logic_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.logic_clk, dut.logic_rst) + + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.gtx_rst.setimmediatevalue(0) + self.dut.logic_rst.setimmediatevalue(0) + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.gtx_rst <= 1 + self.dut.logic_rst <= 1 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.gtx_rst <= 0 + self.dut.logic_rst <= 0 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + + def set_speed(self, speed): + pass + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.gmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + tb.set_speed(speed) + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.gmii_phy.rx.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.gmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + tb.set_speed(speed) + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.gmii_phy.tx.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.gmii_phy.tx.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("speed", [1000e6, 100e6, 10e6]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_1g_gmii_fifo(request): + dut = "eth_mac_1g_gmii_fifo" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "eth_mac_1g_gmii.v"), + os.path.join(rtl_dir, "gmii_phy_if.v"), + os.path.join(rtl_dir, "ssio_sdr_in.v"), + os.path.join(rtl_dir, "ssio_sdr_out.v"), + os.path.join(rtl_dir, "oddr.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + parameters['AXIS_DATA_WIDTH'] = 8 + parameters['AXIS_KEEP_ENABLE'] = int(parameters['AXIS_DATA_WIDTH'] > 8) + parameters['AXIS_KEEP_WIDTH'] = parameters['AXIS_DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['TX_FIFO_DEPTH'] = 16384 + parameters['TX_FRAME_FIFO'] = 1 + parameters['TX_DROP_BAD_FRAME'] = parameters['TX_FRAME_FIFO'] + parameters['TX_DROP_WHEN_FULL'] = 0 + parameters['RX_FIFO_DEPTH'] = 16384 + parameters['RX_FRAME_FIFO'] = 1 + parameters['RX_DROP_BAD_FRAME'] = parameters['RX_FRAME_FIFO'] + parameters['RX_DROP_WHEN_FULL'] = parameters['RX_FRAME_FIFO'] + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_1g_rgmii/Makefile b/tb/eth_mac_1g_rgmii/Makefile new file mode 100644 index 000000000..c1e095bd1 --- /dev/null +++ b/tb/eth_mac_1g_rgmii/Makefile @@ -0,0 +1,83 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_1g_rgmii +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/iddr.v +VERILOG_SOURCES += ../../rtl/oddr.v +VERILOG_SOURCES += ../../rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py b/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py new file mode 100644 index 000000000..6d2c5693c --- /dev/null +++ b/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.triggers import RisingEdge, Timer +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, RgmiiPhy +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.rgmii_phy = RgmiiPhy(dut.rgmii_txd, dut.rgmii_tx_ctl, dut.rgmii_tx_clk, + dut.rgmii_rxd, dut.rgmii_rx_ctl, dut.rgmii_rx_clk, speed=speed) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.tx_clk, dut.tx_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.rx_clk, dut.rx_rst) + + dut.ifg_delay.setimmediatevalue(0) + + dut.gtx_clk.setimmediatevalue(0) + dut.gtx_clk90.setimmediatevalue(0) + + cocotb.fork(self._run_gtx_clk()) + + async def reset(self): + self.dut.gtx_rst.setimmediatevalue(0) + await RisingEdge(self.dut.gtx_clk) + await RisingEdge(self.dut.gtx_clk) + self.dut.gtx_rst <= 1 + await RisingEdge(self.dut.gtx_clk) + await RisingEdge(self.dut.gtx_clk) + self.dut.gtx_rst <= 0 + await RisingEdge(self.dut.gtx_clk) + await RisingEdge(self.dut.gtx_clk) + + async def _run_gtx_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.gtx_clk <= 1 + await t + self.dut.gtx_clk90 <= 1 + await t + self.dut.gtx_clk <= 0 + await t + self.dut.gtx_clk90 <= 0 + await t + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.rgmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.rgmii_phy.rx.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.rgmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.rgmii_phy.tx.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.rgmii_phy.tx.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("speed", [1000e6, 100e6, 10e6]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_1g_rgmii(request): + dut = "eth_mac_1g_rgmii" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "iddr.v"), + os.path.join(rtl_dir, "oddr.v"), + os.path.join(rtl_dir, "ssio_ddr_in.v"), + os.path.join(rtl_dir, "rgmii_phy_if.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_1g_rgmii_fifo/Makefile b/tb/eth_mac_1g_rgmii_fifo/Makefile new file mode 100644 index 000000000..e51e76b7f --- /dev/null +++ b/tb/eth_mac_1g_rgmii_fifo/Makefile @@ -0,0 +1,120 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_1g_rgmii_fifo +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/eth_mac_1g_rgmii.v +VERILOG_SOURCES += ../../rtl/iddr.v +VERILOG_SOURCES += ../../rtl/oddr.v +VERILOG_SOURCES += ../../rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +export PARAM_AXIS_DATA_WIDTH ?= 8 +export PARAM_AXIS_KEEP_ENABLE ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) \> 8 ) +export PARAM_AXIS_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_TX_FIFO_DEPTH ?= 16384 +export PARAM_TX_FRAME_FIFO ?= 1 +export PARAM_TX_DROP_BAD_FRAME ?= $(PARAM_TX_FRAME_FIFO) +export PARAM_TX_DROP_WHEN_FULL ?= 0 +export PARAM_RX_FIFO_DEPTH ?= 16384 +export PARAM_RX_FRAME_FIFO ?= 1 +export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) +export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -GAXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GTX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -GTX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -GTX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -GTX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -GRX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -GRX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -GRX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -GRX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py b/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py new file mode 100644 index 000000000..57cc78e09 --- /dev/null +++ b/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, RgmiiPhy +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.logic_clk, 8, units="ns").start()) + + self.rgmii_phy = RgmiiPhy(dut.rgmii_txd, dut.rgmii_tx_ctl, dut.rgmii_tx_clk, + dut.rgmii_rxd, dut.rgmii_rx_ctl, dut.rgmii_rx_clk, speed=speed) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.logic_clk, dut.logic_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.logic_clk, dut.logic_rst) + + dut.ifg_delay.setimmediatevalue(0) + + dut.gtx_clk.setimmediatevalue(0) + dut.gtx_clk90.setimmediatevalue(0) + + cocotb.fork(self._run_gtx_clk()) + + async def reset(self): + self.dut.gtx_rst.setimmediatevalue(0) + self.dut.logic_rst.setimmediatevalue(0) + await RisingEdge(self.dut.gtx_clk) + await RisingEdge(self.dut.gtx_clk) + self.dut.gtx_rst <= 1 + self.dut.logic_rst <= 1 + await RisingEdge(self.dut.gtx_clk) + await RisingEdge(self.dut.gtx_clk) + self.dut.gtx_rst <= 0 + self.dut.logic_rst <= 0 + await RisingEdge(self.dut.gtx_clk) + await RisingEdge(self.dut.gtx_clk) + + async def _run_gtx_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.gtx_clk <= 1 + await t + self.dut.gtx_clk90 <= 1 + await t + self.dut.gtx_clk <= 0 + await t + self.dut.gtx_clk90 <= 0 + await t + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.rgmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.rgmii_phy.rx.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=1000e6): + + tb = TB(dut, speed) + + tb.rgmii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + for k in range(100): + await RisingEdge(dut.rx_clk) + + if speed == 10e6: + assert dut.speed == 0 + elif speed == 100e6: + assert dut.speed == 1 + else: + assert dut.speed == 2 + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.rgmii_phy.tx.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.rgmii_phy.tx.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("speed", [1000e6, 100e6, 10e6]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_1g_rgmii_fifo(request): + dut = "eth_mac_1g_rgmii_fifo" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "eth_mac_1g_rgmii.v"), + os.path.join(rtl_dir, "iddr.v"), + os.path.join(rtl_dir, "oddr.v"), + os.path.join(rtl_dir, "ssio_ddr_in.v"), + os.path.join(rtl_dir, "rgmii_phy_if.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + parameters['AXIS_DATA_WIDTH'] = 8 + parameters['AXIS_KEEP_ENABLE'] = int(parameters['AXIS_DATA_WIDTH'] > 8) + parameters['AXIS_KEEP_WIDTH'] = parameters['AXIS_DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['TX_FIFO_DEPTH'] = 16384 + parameters['TX_FRAME_FIFO'] = 1 + parameters['TX_DROP_BAD_FRAME'] = parameters['TX_FRAME_FIFO'] + parameters['TX_DROP_WHEN_FULL'] = 0 + parameters['RX_FIFO_DEPTH'] = 16384 + parameters['RX_FRAME_FIFO'] = 1 + parameters['RX_DROP_BAD_FRAME'] = parameters['RX_FRAME_FIFO'] + parameters['RX_DROP_WHEN_FULL'] = parameters['RX_FRAME_FIFO'] + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_mii/Makefile b/tb/eth_mac_mii/Makefile new file mode 100644 index 000000000..1ec24bebd --- /dev/null +++ b/tb/eth_mac_mii/Makefile @@ -0,0 +1,81 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_mii +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../rtl/mii_phy_if.v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_mii/test_eth_mac_mii.py b/tb/eth_mac_mii/test_eth_mac_mii.py new file mode 100644 index 000000000..0e0c852d1 --- /dev/null +++ b/tb/eth_mac_mii/test_eth_mac_mii.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, MiiPhy +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut, speed=100e6): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.mii_phy = MiiPhy(dut.mii_txd, dut.mii_tx_er, dut.mii_tx_en, dut.mii_tx_clk, + dut.mii_rxd, dut.mii_rx_er, dut.mii_rx_dv, dut.mii_rx_clk, speed=speed) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.tx_clk, dut.tx_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.rx_clk, dut.rx_rst) + + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.tx_clk) + await RisingEdge(self.dut.tx_clk) + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=100e6): + + tb = TB(dut, speed) + + tb.mii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.mii_phy.rx.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.rx_clk) + await RisingEdge(dut.rx_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=100e6): + + tb = TB(dut, speed) + + tb.mii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.mii_phy.tx.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.mii_phy.tx.empty() + + await RisingEdge(dut.tx_clk) + await RisingEdge(dut.tx_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("speed", [100e6, 10e6]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_mii(request): + dut = "eth_mac_mii" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "ssio_sdr_in.v"), + os.path.join(rtl_dir, "mii_phy_if.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_mac_mii_fifo/Makefile b/tb/eth_mac_mii_fifo/Makefile new file mode 100644 index 000000000..b933a9d15 --- /dev/null +++ b/tb/eth_mac_mii_fifo/Makefile @@ -0,0 +1,118 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_mac_mii_fifo +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/eth_mac_mii.v +VERILOG_SOURCES += ../../rtl/ssio_sdr_in.v +VERILOG_SOURCES += ../../rtl/mii_phy_if.v +VERILOG_SOURCES += ../../rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../rtl/lfsr.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +export PARAM_AXIS_DATA_WIDTH ?= 8 +export PARAM_AXIS_KEEP_ENABLE ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) \> 8 ) +export PARAM_AXIS_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_DATA_WIDTH) / 8 ) +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_TX_FIFO_DEPTH ?= 16384 +export PARAM_TX_FRAME_FIFO ?= 1 +export PARAM_TX_DROP_BAD_FRAME ?= $(PARAM_TX_FRAME_FIFO) +export PARAM_TX_DROP_WHEN_FULL ?= 0 +export PARAM_RX_FIFO_DEPTH ?= 16384 +export PARAM_RX_FRAME_FIFO ?= 1 +export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) +export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) + +SIM_BUILD ?= sim_build_$(MODULE) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).TX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).TX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).RX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -P $(TOPLEVEL).RX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_DATA_WIDTH=$(PARAM_AXIS_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_KEEP_ENABLE=$(PARAM_AXIS_KEEP_ENABLE) + COMPILE_ARGS += -GAXIS_KEEP_WIDTH=$(PARAM_AXIS_KEEP_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GTX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH) + COMPILE_ARGS += -GTX_FRAME_FIFO=$(PARAM_TX_FRAME_FIFO) + COMPILE_ARGS += -GTX_DROP_BAD_FRAME=$(PARAM_TX_DROP_BAD_FRAME) + COMPILE_ARGS += -GTX_DROP_WHEN_FULL=$(PARAM_TX_DROP_WHEN_FULL) + COMPILE_ARGS += -GRX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH) + COMPILE_ARGS += -GRX_FRAME_FIFO=$(PARAM_RX_FRAME_FIFO) + COMPILE_ARGS += -GRX_DROP_BAD_FRAME=$(PARAM_RX_DROP_BAD_FRAME) + COMPILE_ARGS += -GRX_DROP_WHEN_FULL=$(PARAM_RX_DROP_WHEN_FULL) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py b/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py new file mode 100644 index 000000000..5672c6f6e --- /dev/null +++ b/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import GmiiFrame, MiiPhy +from cocotbext.axi import AxiStreamSource, AxiStreamSink + + +class TB: + def __init__(self, dut, speed=100e6): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.logic_clk, 40, units="ns").start()) + + self.mii_phy = MiiPhy(dut.mii_txd, dut.mii_tx_er, dut.mii_tx_en, dut.mii_tx_clk, + dut.mii_rxd, dut.mii_rx_er, dut.mii_rx_dv, dut.mii_rx_clk, speed=speed) + + self.axis_source = AxiStreamSource(dut, "tx_axis", dut.logic_clk, dut.logic_rst) + self.axis_sink = AxiStreamSink(dut, "rx_axis", dut.logic_clk, dut.logic_rst) + + dut.ifg_delay.setimmediatevalue(0) + + async def reset(self): + self.dut.logic_rst.setimmediatevalue(0) + for k in range(10): + await RisingEdge(self.dut.logic_clk) + self.dut.logic_rst <= 1 + for k in range(10): + await RisingEdge(self.dut.logic_clk) + self.dut.logic_rst <= 0 + for k in range(10): + await RisingEdge(self.dut.logic_clk) + + +async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=100e6): + + tb = TB(dut, speed) + + tb.mii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = GmiiFrame.from_payload(test_data) + await tb.mii_phy.rx.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.axis_sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.axis_sink.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12, speed=100e6): + + tb = TB(dut, speed) + + tb.mii_phy.rx.ifg = ifg + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.axis_source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.mii_phy.tx.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.error is None + + assert tb.mii_phy.tx.empty() + + await RisingEdge(dut.logic_clk) + await RisingEdge(dut.logic_clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + for test in [run_test_rx, run_test_tx]: + + factory = TestFactory(test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.add_option("speed", [100e6, 10e6]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_eth_mac_mii_fifo(request): + dut = "eth_mac_mii_fifo" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "eth_mac_mii.v"), + os.path.join(rtl_dir, "ssio_sdr_in.v"), + os.path.join(rtl_dir, "mii_phy_if.v"), + os.path.join(rtl_dir, "eth_mac_1g.v"), + os.path.join(rtl_dir, "axis_gmii_rx.v"), + os.path.join(rtl_dir, "axis_gmii_tx.v"), + os.path.join(rtl_dir, "lfsr.v"), + os.path.join(axis_rtl_dir, "axis_adapter.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + parameters['AXIS_DATA_WIDTH'] = 8 + parameters['AXIS_KEEP_ENABLE'] = int(parameters['AXIS_DATA_WIDTH'] > 8) + parameters['AXIS_KEEP_WIDTH'] = parameters['AXIS_DATA_WIDTH'] // 8 + parameters['ENABLE_PADDING'] = 1 + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['TX_FIFO_DEPTH'] = 16384 + parameters['TX_FRAME_FIFO'] = 1 + parameters['TX_DROP_BAD_FRAME'] = parameters['TX_FRAME_FIFO'] + parameters['TX_DROP_WHEN_FULL'] = 0 + parameters['RX_FIFO_DEPTH'] = 16384 + parameters['RX_FRAME_FIFO'] = 1 + parameters['RX_DROP_BAD_FRAME'] = parameters['RX_FRAME_FIFO'] + parameters['RX_DROP_WHEN_FULL'] = parameters['RX_FRAME_FIFO'] + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From cd127215021a11b850630bb2da12f5a223c36ec6 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 19:28:38 -0800 Subject: [PATCH 20/37] Add cococb testbenches for eth_axis_rx and eth_axis_tx --- tb/eth_axis_rx/Makefile | 78 ++++++++++++ tb/eth_axis_rx/test_eth_axis_rx.py | 190 +++++++++++++++++++++++++++++ tb/eth_axis_tx/Makefile | 78 ++++++++++++ tb/eth_axis_tx/test_eth_axis_tx.py | 188 ++++++++++++++++++++++++++++ 4 files changed, 534 insertions(+) create mode 100644 tb/eth_axis_rx/Makefile create mode 100644 tb/eth_axis_rx/test_eth_axis_rx.py create mode 100644 tb/eth_axis_tx/Makefile create mode 100644 tb/eth_axis_tx/test_eth_axis_tx.py diff --git a/tb/eth_axis_rx/Makefile b/tb/eth_axis_rx/Makefile new file mode 100644 index 000000000..e79ae8876 --- /dev/null +++ b/tb/eth_axis_rx/Makefile @@ -0,0 +1,78 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_axis_rx +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_DATA_WIDTH ?= 8 +export PARAM_KEEP_ENABLE ?= $(shell expr $(PARAM_DATA_WIDTH) \> 8 ) +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) + +SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_ENABLE=$(PARAM_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_ENABLE=$(PARAM_KEEP_ENABLE) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_axis_rx/test_eth_axis_rx.py b/tb/eth_axis_rx/test_eth_axis_rx.py new file mode 100644 index 000000000..998b3fc8a --- /dev/null +++ b/tb/eth_axis_rx/test_eth_axis_rx.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +from scapy.layers.l2 import Ether + +import pytest +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiStreamFrame, AxiStreamSource, AxiStreamSink +from cocotbext.axi.stream import define_stream + + +EthHdrTransaction, EthHdrSource, EthHdrSink, EthHdrMonitor = define_stream("EthHdr", + signals=["hdr_valid", "hdr_ready", "dest_mac", "src_mac", "type"] +) + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self._enable_generator = None + self._enable_cr = None + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + self.source = AxiStreamSource(dut, "s_axis", dut.clk, dut.rst) + + self.header_sink = EthHdrSink(dut, "m_eth", dut.clk, dut.rst) + self.payload_sink = AxiStreamSink(dut, "m_eth_payload_axis", dut.clk, dut.rst) + + 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.header_sink.set_pause_generator(generator()) + self.payload_sink.set_pause_generator(generator()) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None): + + tb = TB(dut) + + await tb.reset() + + tb.set_idle_generator(idle_inserter) + tb.set_backpressure_generator(backpressure_inserter) + + test_pkts = [] + test_frames = [] + + for payload in [payload_data(x) for x in payload_lengths()]: + eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5', type=0x8000) + test_pkt = eth / payload + + test_pkts.append(test_pkt.copy()) + test_frame = AxiStreamFrame(test_pkt.build()) + test_frames.append(test_frame) + + await tb.source.send(test_frame) + + for test_pkt, test_frame in zip(test_pkts, test_frames): + rx_header = await tb.header_sink.recv() + rx_payload = await tb.payload_sink.recv() + + eth = Ether() + eth.dst = rx_header.dest_mac.integer.to_bytes(6, 'big') + eth.src = rx_header.src_mac.integer.to_bytes(6, 'big') + eth.type = rx_header.type.integer + rx_pkt = eth / bytes(rx_payload.tdata) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.build() == test_pkt.build() + assert not rx_payload.tuser + + assert tb.header_sink.empty() + assert tb.payload_sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def cycle_pause(): + return itertools.cycle([1, 1, 1, 0]) + + +def size_list(): + return list(range(1, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytes(itertools.islice(itertools.cycle(range(256)), length)) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("idle_inserter", [None, cycle_pause]) + factory.add_option("backpressure_inserter", [None, cycle_pause]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("data_width", [8, 16, 32, 64, 128, 256, 512]) +def test_eth_axis_rx(request, data_width): + dut = "eth_axis_rx" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = data_width + parameters['KEEP_ENABLE'] = int(parameters['DATA_WIDTH'] > 8) + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/tb/eth_axis_tx/Makefile b/tb/eth_axis_tx/Makefile new file mode 100644 index 000000000..450b0b238 --- /dev/null +++ b/tb/eth_axis_tx/Makefile @@ -0,0 +1,78 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = eth_axis_tx +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_DATA_WIDTH ?= 8 +export PARAM_KEEP_ENABLE ?= $(shell expr $(PARAM_DATA_WIDTH) \> 8 ) +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) + +SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH) + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_ENABLE=$(PARAM_KEEP_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_ENABLE=$(PARAM_KEEP_ENABLE) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf sim_build_* + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/tb/eth_axis_tx/test_eth_axis_tx.py b/tb/eth_axis_tx/test_eth_axis_tx.py new file mode 100644 index 000000000..768986aaa --- /dev/null +++ b/tb/eth_axis_tx/test_eth_axis_tx.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os + +from scapy.layers.l2 import Ether + +import pytest +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiStreamFrame, AxiStreamSource, AxiStreamSink +from cocotbext.axi.stream import define_stream + + +EthHdrTransaction, EthHdrSource, EthHdrSink, EthHdrMonitor = define_stream("EthHdr", + signals=["hdr_valid", "hdr_ready", "dest_mac", "src_mac", "type"] +) + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self._enable_generator = None + self._enable_cr = None + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + self.header_source = EthHdrSource(dut, "s_eth", dut.clk, dut.rst) + self.payload_source = AxiStreamSource(dut, "s_eth_payload_axis", dut.clk, dut.rst) + + self.sink = AxiStreamSink(dut, "m_axis", dut.clk, dut.rst) + + def set_idle_generator(self, generator=None): + if generator: + self.header_source.set_pause_generator(generator()) + self.payload_source.set_pause_generator(generator()) + + def set_backpressure_generator(self, generator=None): + if generator: + self.sink.set_pause_generator(generator()) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None): + + tb = TB(dut) + + await tb.reset() + + tb.set_idle_generator(idle_inserter) + tb.set_backpressure_generator(backpressure_inserter) + + test_pkts = [] + + for payload in [payload_data(x) for x in payload_lengths()]: + eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5', type=0x8000) + test_pkt = eth / payload + test_pkts.append(test_pkt.copy()) + + test_frame = test_pkt.build() + + hdr = EthHdrTransaction() + hdr.dest_mac = int.from_bytes(test_frame[0:6], "big") + hdr.src_mac = int.from_bytes(test_frame[6:12], "big") + hdr.type = int.from_bytes(test_frame[12:14], "big") + + await tb.header_source.send(hdr) + await tb.payload_source.send(AxiStreamFrame(payload)) + + for test_pkt in test_pkts: + rx_frame = await tb.sink.recv() + + rx_pkt = Ether(bytes(rx_frame)) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.build() == test_pkt.build() + assert not rx_frame.tuser + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def cycle_pause(): + return itertools.cycle([1, 1, 1, 0]) + + +def size_list(): + return list(range(1, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytes(itertools.islice(itertools.cycle(range(256)), length)) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("idle_inserter", [None, cycle_pause]) + factory.add_option("backpressure_inserter", [None, cycle_pause]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("data_width", [8, 16, 32, 64, 128, 256, 512]) +def test_eth_axis_tx(request, data_width): + dut = "eth_axis_tx" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = data_width + parameters['KEEP_ENABLE'] = int(parameters['DATA_WIDTH'] > 8) + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, + "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From f47c529122027937f7934662b3a3d50d9860464e Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 19:33:56 -0800 Subject: [PATCH 21/37] Add test durations --- .test_durations | 278 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 .test_durations diff --git a/.test_durations b/.test_durations new file mode 100644 index 000000000..d70f59276 --- /dev/null +++ b/.test_durations @@ -0,0 +1,278 @@ +[ + [ + "example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 3.350716139015276 + ], + [ + "example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 3.2391385310329497 + ], + [ + "example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.789005930942949 + ], + [ + "example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 3.0402835980057716 + ], + [ + "example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 3.017408686049748 + ], + [ + "example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 3.0139305790071376 + ], + [ + "example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.3072252210695297 + ], + [ + "example/Arty/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 3.0037750290939584 + ], + [ + "example/C10LP/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.011752209975384 + ], + [ + "example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.67545863596024 + ], + [ + "example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.0110695579787716 + ], + [ + "example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.208118299022317 + ], + [ + "example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.44376450200798 + ], + [ + "example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 4.402108575042803 + ], + [ + "example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.9904032690101303 + ], + [ + "example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.6908840039977804 + ], + [ + "example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.7916936919791624 + ], + [ + "example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.006524741067551 + ], + [ + "example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.8797070909640752 + ], + [ + "example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.31391696294304 + ], + [ + "example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.2516418960294686 + ], + [ + "example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 7.106702796998434 + ], + [ + "example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.9049406169797294 + ], + [ + "example/VCU108/fpga_25g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 10.083096705027856 + ], + [ + "example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 10.943006486049853 + ], + [ + "example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.7586704220157117 + ], + [ + "example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 14.224416063982062 + ], + [ + "example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.535578682029154 + ], + [ + "example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.0530272759497166 + ], + [ + "example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 1.7465879460214637 + ], + [ + "example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py::test_fpga_core", + 2.5806369229685515 + ], + [ + "tb/axis_gmii_rx/test_axis_gmii_rx.py::test_axis_gmii_rx", + 56.64747221703874 + ], + [ + "tb/axis_gmii_tx/test_axis_gmii_tx.py::test_axis_gmii_tx", + 30.442475777002983 + ], + [ + "tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py::test_axis_xgmii_rx_32", + 7.886729437974282 + ], + [ + "tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py::test_axis_xgmii_rx_64", + 6.457998651952948 + ], + [ + "tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py::test_axis_xgmii_tx_32[0]", + 8.96249749296112 + ], + [ + "tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py::test_axis_xgmii_tx_32[1]", + 9.381603470945265 + ], + [ + "tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py::test_axis_xgmii_tx_64[0]", + 11.737518855952658 + ], + [ + "tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py::test_axis_xgmii_tx_64[1]", + 11.806113563012332 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[128]", + 8.863175940059591 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[16]", + 34.96355901501374 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[256]", + 7.622430203016847 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[32]", + 19.80590023502009 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[512]", + 8.202056872076355 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[64]", + 12.095227073063143 + ], + [ + "tb/eth_axis_rx/test_eth_axis_rx.py::test_eth_axis_rx[8]", + 62.279668925039005 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[128]", + 8.613341382006183 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[16]", + 33.45408461202169 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[256]", + 7.692996468977071 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[32]", + 19.495025975920726 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[512]", + 8.79245255002752 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[64]", + 12.404317863984033 + ], + [ + "tb/eth_axis_tx/test_eth_axis_tx.py::test_eth_axis_tx[8]", + 60.92513044789666 + ], + [ + "tb/eth_mac_10g/test_eth_mac_10g.py::test_eth_mac_10g[32-0]", + 21.700028119026683 + ], + [ + "tb/eth_mac_10g/test_eth_mac_10g.py::test_eth_mac_10g[32-1]", + 21.89258627599338 + ], + [ + "tb/eth_mac_10g/test_eth_mac_10g.py::test_eth_mac_10g[64-0]", + 23.73091037006816 + ], + [ + "tb/eth_mac_10g/test_eth_mac_10g.py::test_eth_mac_10g[64-1]", + 23.693007047928404 + ], + [ + "tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py::test_eth_mac_10g_fifo[32-0]", + 27.49537598504685 + ], + [ + "tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py::test_eth_mac_10g_fifo[32-1]", + 26.939815686957445 + ], + [ + "tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py::test_eth_mac_10g_fifo[64-0]", + 26.623203694005497 + ], + [ + "tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py::test_eth_mac_10g_fifo[64-1]", + 26.543768665986136 + ], + [ + "tb/eth_mac_1g/test_eth_mac_1g.py::test_eth_mac_1g", + 88.82490837806836 + ], + [ + "tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py::test_eth_mac_1g_fifo", + 114.0729509309167 + ], + [ + "tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py::test_eth_mac_1g_gmii", + 189.40125144011108 + ], + [ + "tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py::test_eth_mac_1g_gmii_fifo", + 494.74671391100856 + ], + [ + "tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py::test_eth_mac_1g_rgmii", + 511.1402762809885 + ], + [ + "tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py::test_eth_mac_1g_rgmii_fifo", + 711.3097275471082 + ], + [ + "tb/eth_mac_mii/test_eth_mac_mii.py::test_eth_mac_mii", + 25.211533757974394 + ], + [ + "tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py::test_eth_mac_mii_fifo", + 95.03809778194409 + ] +] \ No newline at end of file From 4a98858bea1152ddbf1a3621a7446f248d3fde96 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 20:19:46 -0800 Subject: [PATCH 22/37] Forward arguments to pytest --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index ee496f451..098eb977e 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,7 @@ deps = jinja2 commands = - pytest -n auto + pytest -n auto {posargs} # pytest configuration [pytest] From 731fd859ac6c624f0eedce1d10e550f420a3c6b3 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 20:19:58 -0800 Subject: [PATCH 23/37] Add Github Actions regression tests --- .github/workflows/regression-tests.yml | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/regression-tests.yml diff --git a/.github/workflows/regression-tests.yml b/.github/workflows/regression-tests.yml new file mode 100644 index 000000000..a457c3b44 --- /dev/null +++ b/.github/workflows/regression-tests.yml @@ -0,0 +1,33 @@ +name: Regression Tests + +on: [push, pull_request] + +jobs: + build: + name: Python ${{matrix.python-version}} + runs-on: ubuntu-20.04 + + strategy: + matrix: + python-version: [3.9] + group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + steps: + - uses: actions/checkout@v1 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Icarus Verilog + run: | + sudo apt install -y --no-install-recommends iverilog + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + + - name: Test with tox + run: tox -- --splits 10 --group ${{ matrix.group }} From 782d86a7d1c84b78c6756b09fe39ad6beb6d2fbd Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 20:43:26 -0800 Subject: [PATCH 24/37] Remove readme link --- README | 1 - 1 file changed, 1 deletion(-) delete mode 120000 README diff --git a/README b/README deleted file mode 120000 index 42061c01a..000000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -README.md \ No newline at end of file From 5a3d71823a7b7da0e78c7bf01574ca83e39058ff Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 28 Dec 2020 20:44:00 -0800 Subject: [PATCH 25/37] Update readme --- README.md | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 28f7246fd..b97539232 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Verilog Ethernet Components Readme +[![Build Status](https://github.com/alexforencich/verilog-ethernet/workflows/Regression%20Tests/badge.svg?branch=master)](https://github.com/alexforencich/verilog-ethernet/actions/) + For more information and updates: http://alexforencich.com/wiki/en/verilog/ethernet/start GitHub repository: https://github.com/alexforencich/verilog-ethernet @@ -12,8 +14,8 @@ Ethernet frames as well as IP, UDP, and ARP and the components for constructing a complete UDP/IP stack. Includes MAC modules for gigabit and 10G/25G, a 10G/25G PCS/PMA PHY module, and a 10G/25G combination MAC/PCS/PMA module. Includes various PTP related components for implementing systems that -require precise time synchronization. Also includes full MyHDL testbench with -intelligent bus cosimulation endpoints. +require precise time synchronization. Also includes full cocotb testbenches +that utilize [cocotbext-eth](https://github.com/alexforencich/cocotbext-eth). For IP and ARP support only, use ip_complete (1G) or ip_complete_64 (10G/25G). @@ -569,21 +571,4 @@ bad frame ## Testing -Running the included testbenches requires MyHDL and Icarus Verilog. Make sure -that myhdl.vpi is installed properly for cosimulation to work correctly. The -testbenches can be run with a Python test runner like nose or py.test, or the -individual test scripts can be run with python directly. - -### Testbench Files - - tb/arp_ep.py : MyHDL ARP frame endpoints - tb/axis_ep.py : MyHDL AXI Stream endpoints - tb/baser_serdes.py : MyHDL 10GBASE-R SERDES endpoints - tb/eth_ep.py : MyHDL Ethernet frame endpoints - tb/gmii_ep.py : MyHDL GMII endpoints - tb/ip_ep.py : MyHDL IP frame endpoints - tb/mii_ep.py : MyHDL MII endpoints - tb/ptp.py : MyHDL PTP clock model - tb/rgmii_ep.py : MyHDL RGMII endpoints - tb/udp_ep.py : MyHDL UDP frame endpoints - tb/xgmii_ep.py : MyHDL XGMII endpoints +Running the included testbenches requires [cocotb](https://github.com/cocotb/cocotb), [cocotbext-axi](https://github.com/alexforencich/cocotbext-axi), [cocotbext-eth](https://github.com/alexforencich/cocotbext-eth), and [Icarus Verilog](http://iverilog.icarus.com/). The testbenches can be run with pytest directly (requires [cocotb-test](https://github.com/themperek/cocotb-test)), pytest via tox, or via cocotb makefiles. From 77d22bfde024316ab3da2d713c532b654e81a643 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Dec 2020 14:47:12 -0800 Subject: [PATCH 26/37] Rework sim_build output directory, fix default makefile target --- example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile | 8 ++------ .../ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile | 8 ++------ .../ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ATLYS/fpga/tb/fpga_core/Makefile | 8 ++------ example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/AU200/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/AU250/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/AU280/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/AU50/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/Arty/fpga/tb/fpga_core/Makefile | 8 ++------ example/Arty/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/C10LP/fpga/tb/fpga_core/Makefile | 8 ++------ example/C10LP/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/DE2-115/fpga/tb/fpga_core/Makefile | 8 ++------ example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/DE5-Net/fpga/tb/fpga_core/Makefile | 8 ++------ example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ExaNIC_X10/fpga/tb/fpga_core/Makefile | 8 ++------ example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile | 8 ++------ .../ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/HXT100G/fpga/tb/fpga_core/Makefile | 8 ++------ example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile | 8 ++------ .../HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py | 4 ++-- example/KC705/fpga_gmii/tb/fpga_core/Makefile | 8 ++------ example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ML605/fpga_gmii/tb/fpga_core/Makefile | 8 ++------ example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ML605/fpga_rgmii/tb/fpga_core/Makefile | 8 ++------ example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ML605/fpga_sgmii/tb/fpga_core/Makefile | 8 ++------ example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py | 4 ++-- example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile | 8 ++------ example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/NexysVideo/fpga/tb/fpga_core/Makefile | 8 ++------ example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/VCU108/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/VCU108/fpga_1g/tb/fpga_core/Makefile | 8 ++------ example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/VCU118/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/VCU118/fpga_1g/tb/fpga_core/Makefile | 8 ++------ example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/VCU118/fpga_25g/tb/fpga_core/Makefile | 8 ++------ example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/VCU1525/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ZCU102/fpga/tb/fpga_core/Makefile | 8 ++------ example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/ZCU106/fpga/tb/fpga_core/Makefile | 8 ++------ example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py | 4 ++-- example/fb2CG/fpga_10g/tb/fpga_core/Makefile | 8 ++------ example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py | 4 ++-- tb/axis_gmii_rx/Makefile | 8 ++------ tb/axis_gmii_rx/test_axis_gmii_rx.py | 4 ++-- tb/axis_gmii_tx/Makefile | 8 ++------ tb/axis_gmii_tx/test_axis_gmii_tx.py | 4 ++-- tb/axis_xgmii_rx_32/Makefile | 8 ++------ tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py | 4 ++-- tb/axis_xgmii_rx_64/Makefile | 8 ++------ tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py | 4 ++-- tb/axis_xgmii_tx_32/Makefile | 8 ++------ tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py | 4 ++-- tb/axis_xgmii_tx_64/Makefile | 8 ++------ tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py | 4 ++-- tb/eth_axis_rx/Makefile | 8 ++------ tb/eth_axis_rx/test_eth_axis_rx.py | 4 ++-- tb/eth_axis_tx/Makefile | 8 ++------ tb/eth_axis_tx/test_eth_axis_tx.py | 4 ++-- tb/eth_mac_10g/Makefile | 8 ++------ tb/eth_mac_10g/test_eth_mac_10g.py | 4 ++-- tb/eth_mac_10g_fifo/Makefile | 8 ++------ tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py | 4 ++-- tb/eth_mac_1g/Makefile | 8 ++------ tb/eth_mac_1g/test_eth_mac_1g.py | 4 ++-- tb/eth_mac_1g_fifo/Makefile | 8 ++------ tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py | 4 ++-- tb/eth_mac_1g_gmii/Makefile | 8 ++------ tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py | 4 ++-- tb/eth_mac_1g_gmii_fifo/Makefile | 8 ++------ tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py | 4 ++-- tb/eth_mac_1g_rgmii/Makefile | 8 ++------ tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py | 4 ++-- tb/eth_mac_1g_rgmii_fifo/Makefile | 8 ++------ tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py | 4 ++-- tb/eth_mac_mii/Makefile | 8 ++------ tb/eth_mac_mii/test_eth_mac_mii.py | 4 ++-- tb/eth_mac_mii_fifo/Makefile | 8 ++------ tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py | 4 ++-- 96 files changed, 192 insertions(+), 384 deletions(-) diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py index c66794ee4..cdb9d8ebe 100644 --- a/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -275,8 +275,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], 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 4aff883ec..87e6cf660 100644 --- a/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile +++ b/example/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - 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 464a73bf0..529f2d105 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 @@ -275,8 +275,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ATLYS/fpga/tb/fpga_core/Makefile b/example/ATLYS/fpga/tb/fpga_core/Makefile index 9cef21260..5f583808b 100644 --- a/example/ATLYS/fpga/tb/fpga_core/Makefile +++ b/example/ATLYS/fpga/tb/fpga_core/Makefile @@ -67,8 +67,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -88,6 +86,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -97,9 +97,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py b/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py index 94de5e46b..5814e79ab 100644 --- a/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ATLYS/fpga/tb/fpga_core/test_fpga_core.py @@ -202,8 +202,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/AU200/fpga_10g/tb/fpga_core/Makefile b/example/AU200/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/AU200/fpga_10g/tb/fpga_core/Makefile +++ b/example/AU200/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py index 72030a8e6..187af7189 100644 --- a/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -275,8 +275,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/AU250/fpga_10g/tb/fpga_core/Makefile b/example/AU250/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/AU250/fpga_10g/tb/fpga_core/Makefile +++ b/example/AU250/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py index 72030a8e6..187af7189 100644 --- a/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -275,8 +275,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/AU280/fpga_10g/tb/fpga_core/Makefile b/example/AU280/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/AU280/fpga_10g/tb/fpga_core/Makefile +++ b/example/AU280/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py index 277262d0e..e29cee825 100644 --- a/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -273,8 +273,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/AU50/fpga_10g/tb/fpga_core/Makefile b/example/AU50/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/AU50/fpga_10g/tb/fpga_core/Makefile +++ b/example/AU50/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py index 509ce3670..0733144b9 100644 --- a/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -229,8 +229,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/Arty/fpga/tb/fpga_core/Makefile b/example/Arty/fpga/tb/fpga_core/Makefile index 9eb26f795..1181f3bf4 100644 --- a/example/Arty/fpga/tb/fpga_core/Makefile +++ b/example/Arty/fpga/tb/fpga_core/Makefile @@ -64,8 +64,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -85,6 +83,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -94,9 +94,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/Arty/fpga/tb/fpga_core/test_fpga_core.py b/example/Arty/fpga/tb/fpga_core/test_fpga_core.py index 55b0dda9c..82c4a0dfc 100644 --- a/example/Arty/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/Arty/fpga/tb/fpga_core/test_fpga_core.py @@ -197,8 +197,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/C10LP/fpga/tb/fpga_core/Makefile b/example/C10LP/fpga/tb/fpga_core/Makefile index cf1af8fc7..c6328a449 100644 --- a/example/C10LP/fpga/tb/fpga_core/Makefile +++ b/example/C10LP/fpga/tb/fpga_core/Makefile @@ -66,8 +66,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -87,6 +85,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -96,9 +96,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py b/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py index f45c407c8..cd3a1be2a 100644 --- a/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/C10LP/fpga/tb/fpga_core/test_fpga_core.py @@ -211,8 +211,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/DE2-115/fpga/tb/fpga_core/Makefile b/example/DE2-115/fpga/tb/fpga_core/Makefile index ca736cac6..8c990bc4c 100644 --- a/example/DE2-115/fpga/tb/fpga_core/Makefile +++ b/example/DE2-115/fpga/tb/fpga_core/Makefile @@ -67,8 +67,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -88,6 +86,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -97,9 +97,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py b/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py index 6439e820c..e0b88ec9f 100644 --- a/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/DE2-115/fpga/tb/fpga_core/test_fpga_core.py @@ -216,8 +216,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/DE5-Net/fpga/tb/fpga_core/Makefile b/example/DE5-Net/fpga/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/DE5-Net/fpga/tb/fpga_core/Makefile +++ b/example/DE5-Net/fpga/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py b/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py index f795669cd..d22b15861 100644 --- a/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/DE5-Net/fpga/tb/fpga_core/test_fpga_core.py @@ -200,8 +200,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile b/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile +++ b/example/ExaNIC_X10/fpga/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py b/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py index 130b745fd..0d3a7ddf6 100644 --- a/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py @@ -207,8 +207,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile +++ b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py index 130b745fd..0d3a7ddf6 100644 --- a/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -207,8 +207,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/HXT100G/fpga/tb/fpga_core/Makefile b/example/HXT100G/fpga/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/HXT100G/fpga/tb/fpga_core/Makefile +++ b/example/HXT100G/fpga/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py b/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py index 9f9b74837..62cd72081 100644 --- a/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/HXT100G/fpga/tb/fpga_core/test_fpga_core.py @@ -266,8 +266,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile b/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile index 20ada1fbd..22a78d717 100644 --- a/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile +++ b/example/HXT100G/fpga_cxpt16/tb/fpga_core/Makefile @@ -43,8 +43,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_crosspoint.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -64,6 +62,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -73,9 +73,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py b/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py index 5dca34cbb..cb9e8ae19 100644 --- a/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py +++ b/example/HXT100G/fpga_cxpt16/tb/fpga_core/test_fpga_core.py @@ -235,8 +235,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/KC705/fpga_gmii/tb/fpga_core/Makefile b/example/KC705/fpga_gmii/tb/fpga_core/Makefile index 9cef21260..5f583808b 100644 --- a/example/KC705/fpga_gmii/tb/fpga_core/Makefile +++ b/example/KC705/fpga_gmii/tb/fpga_core/Makefile @@ -67,8 +67,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -88,6 +86,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -97,9 +97,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py b/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py index 188f184e3..9514c1acd 100644 --- a/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py +++ b/example/KC705/fpga_gmii/tb/fpga_core/test_fpga_core.py @@ -203,8 +203,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ML605/fpga_gmii/tb/fpga_core/Makefile b/example/ML605/fpga_gmii/tb/fpga_core/Makefile index 9cef21260..5f583808b 100644 --- a/example/ML605/fpga_gmii/tb/fpga_core/Makefile +++ b/example/ML605/fpga_gmii/tb/fpga_core/Makefile @@ -67,8 +67,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -88,6 +86,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -97,9 +97,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py index 0fd55806d..1542da836 100644 --- a/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py +++ b/example/ML605/fpga_gmii/tb/fpga_core/test_fpga_core.py @@ -203,8 +203,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ML605/fpga_rgmii/tb/fpga_core/Makefile b/example/ML605/fpga_rgmii/tb/fpga_core/Makefile index cf1af8fc7..c6328a449 100644 --- a/example/ML605/fpga_rgmii/tb/fpga_core/Makefile +++ b/example/ML605/fpga_rgmii/tb/fpga_core/Makefile @@ -66,8 +66,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -87,6 +85,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -96,9 +96,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py index cdfd4c48f..750d3477e 100644 --- a/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py +++ b/example/ML605/fpga_rgmii/tb/fpga_core/test_fpga_core.py @@ -215,8 +215,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ML605/fpga_sgmii/tb/fpga_core/Makefile b/example/ML605/fpga_sgmii/tb/fpga_core/Makefile index 4aafe627c..9c8aced94 100644 --- a/example/ML605/fpga_sgmii/tb/fpga_core/Makefile +++ b/example/ML605/fpga_sgmii/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py b/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py index dde7d8868..14988bff7 100644 --- a/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py +++ b/example/ML605/fpga_sgmii/tb/fpga_core/test_fpga_core.py @@ -204,8 +204,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile b/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile +++ b/example/NetFPGA_SUME/fpga/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py b/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py index 18a192c39..b6ec23c1d 100644 --- a/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py @@ -231,8 +231,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/NexysVideo/fpga/tb/fpga_core/Makefile b/example/NexysVideo/fpga/tb/fpga_core/Makefile index cf1af8fc7..c6328a449 100644 --- a/example/NexysVideo/fpga/tb/fpga_core/Makefile +++ b/example/NexysVideo/fpga/tb/fpga_core/Makefile @@ -66,8 +66,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -87,6 +85,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -96,9 +96,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py b/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py index 0e670fa55..2fb6c1449 100644 --- a/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/NexysVideo/fpga/tb/fpga_core/test_fpga_core.py @@ -217,8 +217,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/VCU108/fpga_10g/tb/fpga_core/Makefile b/example/VCU108/fpga_10g/tb/fpga_core/Makefile index 14b7969eb..7641e3f0e 100644 --- a/example/VCU108/fpga_10g/tb/fpga_core/Makefile +++ b/example/VCU108/fpga_10g/tb/fpga_core/Makefile @@ -68,8 +68,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -89,6 +87,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -98,9 +98,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py index cab7b5356..422a0a6e8 100644 --- a/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -344,8 +344,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/VCU108/fpga_1g/tb/fpga_core/Makefile b/example/VCU108/fpga_1g/tb/fpga_core/Makefile index 4aafe627c..9c8aced94 100644 --- a/example/VCU108/fpga_1g/tb/fpga_core/Makefile +++ b/example/VCU108/fpga_1g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py b/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py index 1a70b88e3..633740270 100644 --- a/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU108/fpga_1g/tb/fpga_core/test_fpga_core.py @@ -204,8 +204,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/VCU118/fpga_10g/tb/fpga_core/Makefile b/example/VCU118/fpga_10g/tb/fpga_core/Makefile index 14b7969eb..7641e3f0e 100644 --- a/example/VCU118/fpga_10g/tb/fpga_core/Makefile +++ b/example/VCU118/fpga_10g/tb/fpga_core/Makefile @@ -68,8 +68,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -89,6 +87,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -98,9 +98,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py index f0af0c952..d4a69de5e 100644 --- a/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -388,8 +388,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/VCU118/fpga_1g/tb/fpga_core/Makefile b/example/VCU118/fpga_1g/tb/fpga_core/Makefile index 4aafe627c..9c8aced94 100644 --- a/example/VCU118/fpga_1g/tb/fpga_core/Makefile +++ b/example/VCU118/fpga_1g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py index 1a70b88e3..633740270 100644 --- a/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU118/fpga_1g/tb/fpga_core/test_fpga_core.py @@ -204,8 +204,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/VCU118/fpga_25g/tb/fpga_core/Makefile b/example/VCU118/fpga_25g/tb/fpga_core/Makefile index 14b7969eb..7641e3f0e 100644 --- a/example/VCU118/fpga_25g/tb/fpga_core/Makefile +++ b/example/VCU118/fpga_25g/tb/fpga_core/Makefile @@ -68,8 +68,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -89,6 +87,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -98,9 +98,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py b/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py index 6c14482b0..899374659 100644 --- a/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU118/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -388,8 +388,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/VCU1525/fpga_10g/tb/fpga_core/Makefile b/example/VCU1525/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/VCU1525/fpga_10g/tb/fpga_core/Makefile +++ b/example/VCU1525/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py index 72030a8e6..187af7189 100644 --- a/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -275,8 +275,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ZCU102/fpga/tb/fpga_core/Makefile b/example/ZCU102/fpga/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/ZCU102/fpga/tb/fpga_core/Makefile +++ b/example/ZCU102/fpga/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py b/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py index 9fb9cbe56..a5449be7a 100644 --- a/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py @@ -238,8 +238,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/ZCU106/fpga/tb/fpga_core/Makefile b/example/ZCU106/fpga/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/ZCU106/fpga/tb/fpga_core/Makefile +++ b/example/ZCU106/fpga/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py b/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py index 8835104fe..c6118d6c8 100644 --- a/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py +++ b/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py @@ -216,8 +216,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/example/fb2CG/fpga_10g/tb/fpga_core/Makefile b/example/fb2CG/fpga_10g/tb/fpga_core/Makefile index 4aff883ec..87e6cf660 100644 --- a/example/fb2CG/fpga_10g/tb/fpga_core/Makefile +++ b/example/fb2CG/fpga_10g/tb/fpga_core/Makefile @@ -61,8 +61,6 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v # module parameters #export PARAM_A ?= value -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -82,6 +80,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -91,9 +91,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py b/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py index ced78ba8d..6d7c15896 100644 --- a/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/example/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -273,8 +273,8 @@ def test_fpga_core(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/axis_gmii_rx/Makefile b/tb/axis_gmii_rx/Makefile index 5092d2525..0b1bd171c 100644 --- a/tb/axis_gmii_rx/Makefile +++ b/tb/axis_gmii_rx/Makefile @@ -39,8 +39,6 @@ export PARAM_PTP_TS_WIDTH ?= 96 #export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 export PARAM_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -66,6 +64,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -75,9 +75,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/axis_gmii_rx/test_axis_gmii_rx.py b/tb/axis_gmii_rx/test_axis_gmii_rx.py index 10d5ee2ef..eccf4ade3 100644 --- a/tb/axis_gmii_rx/test_axis_gmii_rx.py +++ b/tb/axis_gmii_rx/test_axis_gmii_rx.py @@ -168,8 +168,8 @@ def test_axis_gmii_rx(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/axis_gmii_tx/Makefile b/tb/axis_gmii_tx/Makefile index 1e0915cb1..29c2209fe 100644 --- a/tb/axis_gmii_tx/Makefile +++ b/tb/axis_gmii_tx/Makefile @@ -43,8 +43,6 @@ export PARAM_PTP_TAG_WIDTH ?= 16 #export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 export PARAM_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -78,6 +76,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -87,9 +87,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/axis_gmii_tx/test_axis_gmii_tx.py b/tb/axis_gmii_tx/test_axis_gmii_tx.py index c1a64e466..686dc4ffe 100644 --- a/tb/axis_gmii_tx/test_axis_gmii_tx.py +++ b/tb/axis_gmii_tx/test_axis_gmii_tx.py @@ -173,8 +173,8 @@ def test_axis_gmii_tx(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/axis_xgmii_rx_32/Makefile b/tb/axis_xgmii_rx_32/Makefile index ffc43934a..9be53c0cf 100644 --- a/tb/axis_xgmii_rx_32/Makefile +++ b/tb/axis_xgmii_rx_32/Makefile @@ -41,8 +41,6 @@ export PARAM_PTP_TS_WIDTH ?= 96 #export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 export PARAM_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -72,6 +70,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -81,9 +81,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py b/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py index d988bce14..29ebb608c 100644 --- a/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py +++ b/tb/axis_xgmii_rx_32/test_axis_xgmii_rx_32.py @@ -140,8 +140,8 @@ def test_axis_xgmii_rx_32(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/axis_xgmii_rx_64/Makefile b/tb/axis_xgmii_rx_64/Makefile index d3924d4d2..90f906b48 100644 --- a/tb/axis_xgmii_rx_64/Makefile +++ b/tb/axis_xgmii_rx_64/Makefile @@ -41,8 +41,6 @@ export PARAM_PTP_TS_WIDTH ?= 96 #export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 export PARAM_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -72,6 +70,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -81,9 +81,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py b/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py index 0f6780f8d..2641d4941 100644 --- a/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py +++ b/tb/axis_xgmii_rx_64/test_axis_xgmii_rx_64.py @@ -140,8 +140,8 @@ def test_axis_xgmii_rx_64(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/axis_xgmii_tx_32/Makefile b/tb/axis_xgmii_tx_32/Makefile index 9fdee8590..30293c7a5 100644 --- a/tb/axis_xgmii_tx_32/Makefile +++ b/tb/axis_xgmii_tx_32/Makefile @@ -46,8 +46,6 @@ export PARAM_PTP_TAG_WIDTH ?= 16 #export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 export PARAM_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_ENABLE_DIC) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -87,6 +85,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -96,9 +96,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py b/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py index dfa76d753..abb71d973 100644 --- a/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py +++ b/tb/axis_xgmii_tx_32/test_axis_xgmii_tx_32.py @@ -221,8 +221,8 @@ def test_axis_xgmii_tx_32(request, enable_dic): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/axis_xgmii_tx_64/Makefile b/tb/axis_xgmii_tx_64/Makefile index f7b39e7e4..fe6c0a350 100644 --- a/tb/axis_xgmii_tx_64/Makefile +++ b/tb/axis_xgmii_tx_64/Makefile @@ -46,8 +46,6 @@ export PARAM_PTP_TAG_WIDTH ?= 16 #export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 export PARAM_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_ENABLE_DIC) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -87,6 +85,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -96,9 +96,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py b/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py index c65b52d72..68f7f6e91 100644 --- a/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py +++ b/tb/axis_xgmii_tx_64/test_axis_xgmii_tx_64.py @@ -221,8 +221,8 @@ def test_axis_xgmii_tx_64(request, enable_dic): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_axis_rx/Makefile b/tb/eth_axis_rx/Makefile index e79ae8876..81ca7d90e 100644 --- a/tb/eth_axis_rx/Makefile +++ b/tb/eth_axis_rx/Makefile @@ -36,8 +36,6 @@ export PARAM_DATA_WIDTH ?= 8 export PARAM_KEEP_ENABLE ?= $(shell expr $(PARAM_DATA_WIDTH) \> 8 ) export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) -SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -61,6 +59,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -70,9 +70,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_axis_rx/test_eth_axis_rx.py b/tb/eth_axis_rx/test_eth_axis_rx.py index 998b3fc8a..7bf0cb7f0 100644 --- a/tb/eth_axis_rx/test_eth_axis_rx.py +++ b/tb/eth_axis_rx/test_eth_axis_rx.py @@ -176,8 +176,8 @@ def test_eth_axis_rx(request, data_width): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_axis_tx/Makefile b/tb/eth_axis_tx/Makefile index 450b0b238..c77d90dee 100644 --- a/tb/eth_axis_tx/Makefile +++ b/tb/eth_axis_tx/Makefile @@ -36,8 +36,6 @@ export PARAM_DATA_WIDTH ?= 8 export PARAM_KEEP_ENABLE ?= $(shell expr $(PARAM_DATA_WIDTH) \> 8 ) export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) -SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -61,6 +59,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -70,9 +70,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_axis_tx/test_eth_axis_tx.py b/tb/eth_axis_tx/test_eth_axis_tx.py index 768986aaa..be15f75f7 100644 --- a/tb/eth_axis_tx/test_eth_axis_tx.py +++ b/tb/eth_axis_tx/test_eth_axis_tx.py @@ -174,8 +174,8 @@ def test_eth_axis_tx(request, data_width): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_10g/Makefile b/tb/eth_mac_10g/Makefile index 15d943dd4..06050990d 100644 --- a/tb/eth_mac_10g/Makefile +++ b/tb/eth_mac_10g/Makefile @@ -56,8 +56,6 @@ export PARAM_TX_USER_WIDTH ?= 1 # export PARAM_RX_USER_WIDTH ?= (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1 export PARAM_RX_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH)-$(PARAM_ENABLE_DIC) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -107,6 +105,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -116,9 +116,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_10g/test_eth_mac_10g.py b/tb/eth_mac_10g/test_eth_mac_10g.py index 32461075e..f742c20d7 100644 --- a/tb/eth_mac_10g/test_eth_mac_10g.py +++ b/tb/eth_mac_10g/test_eth_mac_10g.py @@ -273,8 +273,8 @@ def test_eth_mac_10g(request, data_width, enable_dic): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_10g_fifo/Makefile b/tb/eth_mac_10g_fifo/Makefile index 397549b2a..cf15b7346 100644 --- a/tb/eth_mac_10g_fifo/Makefile +++ b/tb/eth_mac_10g_fifo/Makefile @@ -72,8 +72,6 @@ export PARAM_PTP_TS_WIDTH ?= 96 export PARAM_TX_PTP_TAG_ENABLE ?= 0 export PARAM_PTP_TAG_WIDTH ?= 16 -SIM_BUILD ?= sim_build_$(MODULE)-$(PARAM_DATA_WIDTH)-$(PARAM_ENABLE_DIC) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -151,6 +149,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -160,9 +160,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py index fc2c1e501..238a9c8a8 100644 --- a/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py +++ b/tb/eth_mac_10g_fifo/test_eth_mac_10g_fifo.py @@ -296,8 +296,8 @@ def test_eth_mac_10g_fifo(request, data_width, enable_dic): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_1g/Makefile b/tb/eth_mac_1g/Makefile index 80b4a50ac..4bc6be7eb 100644 --- a/tb/eth_mac_1g/Makefile +++ b/tb/eth_mac_1g/Makefile @@ -49,8 +49,6 @@ export PARAM_TX_USER_WIDTH ?= 1 # export PARAM_RX_USER_WIDTH ?= (RX_PTP_TS_WIDTH if RX_PTP_TS_ENABLE else 0) + 1 export PARAM_RX_USER_WIDTH ?= 1 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -90,6 +88,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -99,9 +99,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_1g/test_eth_mac_1g.py b/tb/eth_mac_1g/test_eth_mac_1g.py index a2a053ac0..6c5c50fc6 100644 --- a/tb/eth_mac_1g/test_eth_mac_1g.py +++ b/tb/eth_mac_1g/test_eth_mac_1g.py @@ -247,8 +247,8 @@ def test_eth_mac_1g(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_1g_fifo/Makefile b/tb/eth_mac_1g_fifo/Makefile index 4859f6560..b714477d4 100644 --- a/tb/eth_mac_1g_fifo/Makefile +++ b/tb/eth_mac_1g_fifo/Makefile @@ -53,8 +53,6 @@ export PARAM_RX_FRAME_FIFO ?= 1 export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -98,6 +96,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -107,9 +107,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py b/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py index 9e0b23774..887022c20 100644 --- a/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py +++ b/tb/eth_mac_1g_fifo/test_eth_mac_1g_fifo.py @@ -255,8 +255,8 @@ def test_eth_mac_1g_fifo(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_1g_gmii/Makefile b/tb/eth_mac_1g_gmii/Makefile index f1e9f2fb7..fed90e2ac 100644 --- a/tb/eth_mac_1g_gmii/Makefile +++ b/tb/eth_mac_1g_gmii/Makefile @@ -43,8 +43,6 @@ VERILOG_SOURCES += ../../rtl/lfsr.v export PARAM_ENABLE_PADDING ?= 1 export PARAM_MIN_FRAME_LENGTH ?= 64 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -66,6 +64,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -75,9 +75,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py b/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py index caa2fbabb..d1ccac4f6 100644 --- a/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py +++ b/tb/eth_mac_1g_gmii/test_eth_mac_1g_gmii.py @@ -204,8 +204,8 @@ def test_eth_mac_1g_gmii(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_1g_gmii_fifo/Makefile b/tb/eth_mac_1g_gmii_fifo/Makefile index 27f103221..e9dcbe8cc 100644 --- a/tb/eth_mac_1g_gmii_fifo/Makefile +++ b/tb/eth_mac_1g_gmii_fifo/Makefile @@ -58,8 +58,6 @@ export PARAM_RX_FRAME_FIFO ?= 1 export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -103,6 +101,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -112,9 +112,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py b/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py index b0883ad5e..a266a373d 100644 --- a/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py +++ b/tb/eth_mac_1g_gmii_fifo/test_eth_mac_1g_gmii_fifo.py @@ -223,8 +223,8 @@ def test_eth_mac_1g_gmii_fifo(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_1g_rgmii/Makefile b/tb/eth_mac_1g_rgmii/Makefile index c1e095bd1..05de52f63 100644 --- a/tb/eth_mac_1g_rgmii/Makefile +++ b/tb/eth_mac_1g_rgmii/Makefile @@ -43,8 +43,6 @@ VERILOG_SOURCES += ../../rtl/lfsr.v export PARAM_ENABLE_PADDING ?= 1 export PARAM_MIN_FRAME_LENGTH ?= 64 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -66,6 +64,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -75,9 +75,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py b/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py index 6d2c5693c..6e47d8335 100644 --- a/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py +++ b/tb/eth_mac_1g_rgmii/test_eth_mac_1g_rgmii.py @@ -211,8 +211,8 @@ def test_eth_mac_1g_rgmii(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_1g_rgmii_fifo/Makefile b/tb/eth_mac_1g_rgmii_fifo/Makefile index e51e76b7f..a1925ebcb 100644 --- a/tb/eth_mac_1g_rgmii_fifo/Makefile +++ b/tb/eth_mac_1g_rgmii_fifo/Makefile @@ -58,8 +58,6 @@ export PARAM_RX_FRAME_FIFO ?= 1 export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -103,6 +101,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -112,9 +112,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py b/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py index 57cc78e09..989cbf8b9 100644 --- a/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py +++ b/tb/eth_mac_1g_rgmii_fifo/test_eth_mac_1g_rgmii_fifo.py @@ -232,8 +232,8 @@ def test_eth_mac_1g_rgmii_fifo(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_mii/Makefile b/tb/eth_mac_mii/Makefile index 1ec24bebd..51720f230 100644 --- a/tb/eth_mac_mii/Makefile +++ b/tb/eth_mac_mii/Makefile @@ -41,8 +41,6 @@ VERILOG_SOURCES += ../../rtl/lfsr.v export PARAM_ENABLE_PADDING ?= 1 export PARAM_MIN_FRAME_LENGTH ?= 64 -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -64,6 +62,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -73,9 +73,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_mii/test_eth_mac_mii.py b/tb/eth_mac_mii/test_eth_mac_mii.py index 0e0c852d1..5632811ac 100644 --- a/tb/eth_mac_mii/test_eth_mac_mii.py +++ b/tb/eth_mac_mii/test_eth_mac_mii.py @@ -172,8 +172,8 @@ def test_eth_mac_mii(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], diff --git a/tb/eth_mac_mii_fifo/Makefile b/tb/eth_mac_mii_fifo/Makefile index b933a9d15..5614e5daa 100644 --- a/tb/eth_mac_mii_fifo/Makefile +++ b/tb/eth_mac_mii_fifo/Makefile @@ -56,8 +56,6 @@ export PARAM_RX_FRAME_FIFO ?= 1 export PARAM_RX_DROP_BAD_FRAME ?= $(PARAM_RX_FRAME_FIFO) export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_FRAME_FIFO) -SIM_BUILD ?= sim_build_$(MODULE) - ifeq ($(SIM), icarus) PLUSARGS += -fst @@ -101,6 +99,8 @@ else ifeq ($(SIM), verilator) endif endif +include $(shell cocotb-config --makefiles)/Makefile.sim + iverilog_dump.v: echo 'module iverilog_dump();' > $@ echo 'initial begin' >> $@ @@ -110,9 +110,5 @@ iverilog_dump.v: echo 'endmodule' >> $@ clean:: - @rm -rf sim_build_* @rm -rf iverilog_dump.v @rm -rf dump.fst $(TOPLEVEL).fst - -include $(shell cocotb-config --makefiles)/Makefile.sim - diff --git a/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py b/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py index 5672c6f6e..25ee74d33 100644 --- a/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py +++ b/tb/eth_mac_mii_fifo/test_eth_mac_mii_fifo.py @@ -190,8 +190,8 @@ def test_eth_mac_mii_fifo(request): extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} - sim_build = os.path.join(tests_dir, - "sim_build_"+request.node.name.replace('[', '-').replace(']', '')) + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) cocotb_test.simulator.run( python_search=[tests_dir], From 25b890f8bbac673a3bbffc2bffad8e0b24a841ca Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Dec 2020 18:55:13 -0800 Subject: [PATCH 27/37] Remove extraneous code --- tb/eth_axis_rx/test_eth_axis_rx.py | 3 --- tb/eth_axis_tx/test_eth_axis_tx.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/tb/eth_axis_rx/test_eth_axis_rx.py b/tb/eth_axis_rx/test_eth_axis_rx.py index 7bf0cb7f0..ab2aa3ecd 100644 --- a/tb/eth_axis_rx/test_eth_axis_rx.py +++ b/tb/eth_axis_rx/test_eth_axis_rx.py @@ -53,9 +53,6 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - self._enable_generator = None - self._enable_cr = None - cocotb.fork(Clock(dut.clk, 8, units="ns").start()) self.source = AxiStreamSource(dut, "s_axis", dut.clk, dut.rst) diff --git a/tb/eth_axis_tx/test_eth_axis_tx.py b/tb/eth_axis_tx/test_eth_axis_tx.py index be15f75f7..449f83362 100644 --- a/tb/eth_axis_tx/test_eth_axis_tx.py +++ b/tb/eth_axis_tx/test_eth_axis_tx.py @@ -53,9 +53,6 @@ class TB: self.log = logging.getLogger("cocotb.tb") self.log.setLevel(logging.DEBUG) - self._enable_generator = None - self._enable_cr = None - cocotb.fork(Clock(dut.clk, 8, units="ns").start()) self.header_source = EthHdrSource(dut, "s_eth", dut.clk, dut.rst) From e5bc5e1f491b3410f073b59c8ab5629a908a0c08 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Dec 2020 22:01:24 -0800 Subject: [PATCH 28/37] Add cocotb testbench for arp_cache --- tb/arp_cache/Makefile | 69 +++++++++ tb/arp_cache/test_arp_cache.py | 253 +++++++++++++++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 tb/arp_cache/Makefile create mode 100644 tb/arp_cache/test_arp_cache.py diff --git a/tb/arp_cache/Makefile b/tb/arp_cache/Makefile new file mode 100644 index 000000000..bbeaa754a --- /dev/null +++ b/tb/arp_cache/Makefile @@ -0,0 +1,69 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = arp_cache +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_CACHE_ADDR_WIDTH ?= 2 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).CACHE_ADDR_WIDTH=$(PARAM_CACHE_ADDR_WIDTH) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GCACHE_ADDR_WIDTH=$(PARAM_CACHE_ADDR_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/tb/arp_cache/test_arp_cache.py b/tb/arp_cache/test_arp_cache.py new file mode 100644 index 000000000..ea06c9807 --- /dev/null +++ b/tb/arp_cache/test_arp_cache.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi.stream import define_stream + + +CacheOpTransaction, CacheOpSource, CacheOpSink, CacheOpMonitor = define_stream("CacheOp", + signals=["valid", "ready"], + optional_signals=["ip", "mac", "error"] +) + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 8, units="ns").start()) + + self.query_request_source = CacheOpSource(dut, "query_request", dut.clk, dut.rst) + self.query_response_sink = CacheOpSink(dut, "query_response", dut.clk, dut.rst) + + self.write_request_source = CacheOpSource(dut, "write_request", dut.clk, dut.rst) + + dut.clear_cache.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut): + + tb = TB(dut) + + await tb.reset() + + await RisingEdge(dut.write_request_ready) + + tb.log.info("Test write") + + await tb.write_request_source.send(CacheOpTransaction(ip=0xc0a80111, mac=0x0000c0a80111)) + await tb.write_request_source.send(CacheOpTransaction(ip=0xc0a80112, mac=0x0000c0a80112)) + + await tb.write_request_source.wait() + + tb.log.info("Test read") + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80111)) + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80112)) + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80113)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80111 + assert not resp.error + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80112 + assert not resp.error + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.error + + tb.log.info("Test write pt. 2") + + await tb.write_request_source.send(CacheOpTransaction(ip=0xc0a80121, mac=0x0000c0a80121)) + await tb.write_request_source.send(CacheOpTransaction(ip=0xc0a80122, mac=0x0000c0a80122)) + # overwrites 0xc0a80112 + await tb.write_request_source.send(CacheOpTransaction(ip=0xc0a80123, mac=0x0000c0a80123)) + + await tb.write_request_source.wait() + + tb.log.info("Test read pt. 2") + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80111)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80111 + assert not resp.error + + # not in cache; was overwritten + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80112)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.error + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80121)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80121 + assert not resp.error + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80122)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80122 + assert not resp.error + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80123)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80123 + assert not resp.error + + tb.log.info("Test overwrite") + + await tb.write_request_source.send(CacheOpTransaction(ip=0xc0a80123, mac=0x0000c0a80164)) + + await tb.write_request_source.wait() + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80111)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80111 + assert not resp.error + + # not in cache; was overwritten + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80112)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.error + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80121)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80121 + assert not resp.error + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80122)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80122 + assert not resp.error + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80123)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.mac == 0x0000c0a80164 + assert not resp.error + + tb.log.info("Clear cache") + + await RisingEdge(dut.clk) + dut.clear_cache <= 1 + await RisingEdge(dut.clk) + dut.clear_cache <= 0 + + await tb.query_request_source.send(CacheOpTransaction(ip=0xc0a80111)) + + resp = await tb.query_response_sink.recv() + tb.log.info(f"Response: {resp}") + assert resp.error + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_arp_cache(request): + dut = "arp_cache" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, "lfsr.v"), + ] + + parameters = {} + + parameters['CACHE_ADDR_WIDTH'] = 2 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From 0171afbb1883946f57306ed0f5398b20ab00afa5 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Dec 2020 22:02:18 -0800 Subject: [PATCH 29/37] Add cocotb testbench for ptp_clock --- tb/ptp_clock/Makefile | 95 ++++++++ tb/ptp_clock/test_ptp_clock.py | 381 +++++++++++++++++++++++++++++++++ 2 files changed, 476 insertions(+) create mode 100644 tb/ptp_clock/Makefile create mode 100644 tb/ptp_clock/test_ptp_clock.py diff --git a/tb/ptp_clock/Makefile b/tb/ptp_clock/Makefile new file mode 100644 index 000000000..be710f6de --- /dev/null +++ b/tb/ptp_clock/Makefile @@ -0,0 +1,95 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = ptp_clock +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_PERIOD_NS_WIDTH ?= 4 +export PARAM_OFFSET_NS_WIDTH ?= 4 +export PARAM_DRIFT_NS_WIDTH ?= 4 +export PARAM_FNS_WIDTH ?= 16 +export PARAM_PERIOD_NS ?= 6 +export PARAM_PERIOD_FNS ?= 26214 +export PARAM_DRIFT_ENABLE ?= 1 +export PARAM_DRIFT_NS ?= 0 +export PARAM_DRIFT_FNS ?= 2 +export PARAM_DRIFT_RATE ?= 5 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).PERIOD_NS_WIDTH=$(PARAM_PERIOD_NS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).OFFSET_NS_WIDTH=$(PARAM_OFFSET_NS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).DRIFT_NS_WIDTH=$(PARAM_DRIFT_NS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).FNS_WIDTH=$(PARAM_FNS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PERIOD_NS=$(PARAM_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).PERIOD_FNS=$(PARAM_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).DRIFT_ENABLE=$(PARAM_DRIFT_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).DRIFT_NS=$(PARAM_DRIFT_NS) + COMPILE_ARGS += -P $(TOPLEVEL).DRIFT_FNS=$(PARAM_DRIFT_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).DRIFT_RATE=$(PARAM_DRIFT_RATE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GPERIOD_NS_WIDTH=$(PARAM_PERIOD_NS_WIDTH) + COMPILE_ARGS += -GOFFSET_NS_WIDTH=$(PARAM_OFFSET_NS_WIDTH) + COMPILE_ARGS += -GDRIFT_NS_WIDTH=$(PARAM_DRIFT_NS_WIDTH) + COMPILE_ARGS += -GFNS_WIDTH=$(PARAM_FNS_WIDTH) + COMPILE_ARGS += -GPERIOD_NS=$(PARAM_PERIOD_NS) + COMPILE_ARGS += -GPERIOD_FNS=$(PARAM_PERIOD_FNS) + COMPILE_ARGS += -GDRIFT_ENABLE=$(PARAM_DRIFT_ENABLE) + COMPILE_ARGS += -GDRIFT_NS=$(PARAM_DRIFT_NS) + COMPILE_ARGS += -GDRIFT_FNS=$(PARAM_DRIFT_FNS) + COMPILE_ARGS += -GDRIFT_RATE=$(PARAM_DRIFT_RATE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/tb/ptp_clock/test_ptp_clock.py b/tb/ptp_clock/test_ptp_clock.py new file mode 100644 index 000000000..a0543873e --- /dev/null +++ b/tb/ptp_clock/test_ptp_clock.py @@ -0,0 +1,381 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.utils import get_sim_time + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + dut.input_ts_96.setimmediatevalue(0) + dut.input_ts_96_valid.setimmediatevalue(0) + dut.input_ts_64.setimmediatevalue(0) + dut.input_ts_64_valid.setimmediatevalue(0) + + dut.input_period_ns.setimmediatevalue(0) + dut.input_period_fns.setimmediatevalue(0) + dut.input_period_valid.setimmediatevalue(0) + + dut.input_adj_ns.setimmediatevalue(0) + dut.input_adj_fns.setimmediatevalue(0) + dut.input_adj_count.setimmediatevalue(0) + dut.input_adj_valid.setimmediatevalue(0) + + dut.input_drift_ns.setimmediatevalue(0) + dut.input_drift_fns.setimmediatevalue(0) + dut.input_drift_rate.setimmediatevalue(0) + dut.input_drift_valid.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +@cocotb.test() +async def run_default_rate(dut): + + tb = TB(dut) + + await tb.reset() + + await RisingEdge(dut.clk) + start_time = get_sim_time('sec') + start_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + for k in range(10000): + await RisingEdge(dut.clk) + + stop_time = get_sim_time('sec') + stop_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + time_delta = stop_time-start_time + ts_96_delta = stop_ts_96-start_ts_96 + ts_64_delta = stop_ts_64-start_ts_64 + + ts_96_diff = time_delta - ts_96_delta + ts_64_diff = time_delta - ts_64_delta + + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("96 bit ts delta : %g s", ts_96_delta) + tb.log.info("64 bit ts delta : %g s", ts_64_delta) + tb.log.info("96 bit ts diff : %g s", ts_96_diff) + tb.log.info("64 bit ts diff : %g s", ts_64_diff) + + assert abs(ts_96_diff) < 1e-12 + assert abs(ts_64_diff) < 1e-12 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +@cocotb.test() +async def run_load_timestamps(dut): + + tb = TB(dut) + + await tb.reset() + + await RisingEdge(dut.clk) + + dut.input_ts_96 <= 12345678 + dut.input_ts_96_valid <= 1 + dut.input_ts_64 <= 12345678 + dut.input_ts_64_valid <= 1 + + await RisingEdge(dut.clk) + + dut.input_ts_96_valid <= 0 + dut.input_ts_64_valid <= 0 + + await RisingEdge(dut.clk) + + assert dut.output_ts_96.value.integer == 12345678 + assert dut.output_ts_64.value.integer == 12345678 + assert dut.output_ts_step.value.integer == 1 + + start_time = get_sim_time('sec') + start_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + for k in range(2000): + await RisingEdge(dut.clk) + + stop_time = get_sim_time('sec') + stop_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + time_delta = stop_time-start_time + ts_96_delta = stop_ts_96-start_ts_96 + ts_64_delta = stop_ts_64-start_ts_64 + + ts_96_diff = time_delta - ts_96_delta + ts_64_diff = time_delta - ts_64_delta + + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("96 bit ts delta : %g s", ts_96_delta) + tb.log.info("64 bit ts delta : %g s", ts_64_delta) + tb.log.info("96 bit ts diff : %g s", ts_96_diff) + tb.log.info("64 bit ts diff : %g s", ts_64_diff) + + assert abs(ts_96_diff) < 1e-12 + assert abs(ts_64_diff) < 1e-12 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +@cocotb.test() +async def run_seconds_increment(dut): + + tb = TB(dut) + + await tb.reset() + + await RisingEdge(dut.clk) + + dut.input_ts_96 <= 999990000*2**16 + dut.input_ts_96_valid <= 1 + dut.input_ts_64 <= 999990000*2**16 + dut.input_ts_64_valid <= 1 + + await RisingEdge(dut.clk) + + dut.input_ts_96_valid <= 0 + dut.input_ts_64_valid <= 0 + + await RisingEdge(dut.clk) + + start_time = get_sim_time('sec') + start_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + saw_pps = False + + for k in range(3000): + await RisingEdge(dut.clk) + + if dut.output_pps.value.integer: + saw_pps = True + assert dut.output_ts_96.value.integer >> 48 == 1 + assert dut.output_ts_96.value.integer & 0xffffffffffff < 10*2**16 + + assert saw_pps + + stop_time = get_sim_time('sec') + stop_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + time_delta = stop_time-start_time + ts_96_delta = stop_ts_96-start_ts_96 + ts_64_delta = stop_ts_64-start_ts_64 + + ts_96_diff = time_delta - ts_96_delta + ts_64_diff = time_delta - ts_64_delta + + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("96 bit ts delta : %g s", ts_96_delta) + tb.log.info("64 bit ts delta : %g s", ts_64_delta) + tb.log.info("96 bit ts diff : %g s", ts_96_diff) + tb.log.info("64 bit ts diff : %g s", ts_64_diff) + + assert abs(ts_96_diff) < 1e-12 + assert abs(ts_64_diff) < 1e-12 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +@cocotb.test() +async def run_frequency_adjustment(dut): + + tb = TB(dut) + + await tb.reset() + + await RisingEdge(dut.clk) + + dut.input_period_ns <= 0x6 + dut.input_period_fns <= 0x6624 + dut.input_period_valid <= 1 + + await RisingEdge(dut.clk) + + dut.input_period_valid <= 0 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + await RisingEdge(dut.clk) + start_time = get_sim_time('sec') + start_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + for k in range(10000): + await RisingEdge(dut.clk) + + stop_time = get_sim_time('sec') + stop_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + time_delta = stop_time-start_time + ts_96_delta = stop_ts_96-start_ts_96 + ts_64_delta = stop_ts_64-start_ts_64 + + ts_96_diff = time_delta - ts_96_delta * 6.4/(6+(0x6624+2/5)/2**16) + ts_64_diff = time_delta - ts_64_delta * 6.4/(6+(0x6624+2/5)/2**16) + + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("96 bit ts delta : %g s", ts_96_delta) + tb.log.info("64 bit ts delta : %g s", ts_64_delta) + tb.log.info("96 bit ts diff : %g s", ts_96_diff) + tb.log.info("64 bit ts diff : %g s", ts_64_diff) + + assert abs(ts_96_diff) < 1e-12 + assert abs(ts_64_diff) < 1e-12 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +@cocotb.test() +async def run_drift_adjustment(dut): + + tb = TB(dut) + + await tb.reset() + + dut.input_drift_ns <= 0 + dut.input_drift_fns <= 20 + dut.input_drift_rate <= 5 + dut.input_drift_valid <= 1 + + await RisingEdge(dut.clk) + + dut.input_drift_valid <= 0 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + await RisingEdge(dut.clk) + start_time = get_sim_time('sec') + start_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + start_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + for k in range(10000): + await RisingEdge(dut.clk) + + stop_time = get_sim_time('sec') + stop_ts_96 = (dut.output_ts_96.value.integer >> 48) + ((dut.output_ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) + stop_ts_64 = dut.output_ts_64.value.integer/2**16*1e-9 + + time_delta = stop_time-start_time + ts_96_delta = stop_ts_96-start_ts_96 + ts_64_delta = stop_ts_64-start_ts_64 + + ts_96_diff = time_delta - ts_96_delta * 6.4/(6+(0x6666+20/5)/2**16) + ts_64_diff = time_delta - ts_64_delta * 6.4/(6+(0x6666+20/5)/2**16) + + tb.log.info("sim time delta : %g s", time_delta) + tb.log.info("96 bit ts delta : %g s", ts_96_delta) + tb.log.info("64 bit ts delta : %g s", ts_64_delta) + tb.log.info("96 bit ts diff : %g s", ts_96_diff) + tb.log.info("64 bit ts diff : %g s", ts_64_diff) + + assert abs(ts_96_diff) < 1e-12 + assert abs(ts_64_diff) < 1e-12 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_ptp_clock(request): + dut = "ptp_clock" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + parameters['PERIOD_NS_WIDTH'] = 4 + parameters['OFFSET_NS_WIDTH'] = 4 + parameters['DRIFT_NS_WIDTH'] = 4 + parameters['FNS_WIDTH'] = 16 + parameters['PERIOD_NS'] = 0x6 + parameters['PERIOD_FNS'] = 0x6666 + parameters['DRIFT_ENABLE'] = 1 + parameters['DRIFT_NS'] = 0x0 + parameters['DRIFT_FNS'] = 0x0002 + parameters['DRIFT_RATE'] = 0x0005 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From 7117de682ad29fb6906aa3f392234a3d0f2280d3 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Dec 2020 22:02:27 -0800 Subject: [PATCH 30/37] Add cocotb testbench for ptp_perout --- tb/ptp_perout/Makefile | 95 ++++++++++++++++++ tb/ptp_perout/test_ptp_perout.py | 165 +++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 tb/ptp_perout/Makefile create mode 100644 tb/ptp_perout/test_ptp_perout.py diff --git a/tb/ptp_perout/Makefile b/tb/ptp_perout/Makefile new file mode 100644 index 000000000..7a6f15cb3 --- /dev/null +++ b/tb/ptp_perout/Makefile @@ -0,0 +1,95 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = ptp_perout +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_FNS_ENABLE ?= 1 +export PARAM_OUT_START_S ?= 0 +export PARAM_OUT_START_NS ?= 0 +export PARAM_OUT_START_FNS ?= 0 +export PARAM_OUT_PERIOD_S ?= 1 +export PARAM_OUT_PERIOD_NS ?= 0 +export PARAM_OUT_PERIOD_FNS ?= 0 +export PARAM_OUT_WIDTH_S ?= 0 +export PARAM_OUT_WIDTH_NS ?= 1000 +export PARAM_OUT_WIDTH_FNS ?= 0 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).FNS_ENABLE=$(PARAM_FNS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_START_S=$(PARAM_OUT_START_S) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_START_NS=$(PARAM_OUT_START_NS) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_START_FNS=$(PARAM_OUT_START_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_PERIOD_S=$(PARAM_OUT_PERIOD_S) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_PERIOD_NS=$(PARAM_OUT_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_PERIOD_FNS=$(PARAM_OUT_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_WIDTH_S=$(PARAM_OUT_WIDTH_S) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_WIDTH_NS=$(PARAM_OUT_WIDTH_NS) + COMPILE_ARGS += -P $(TOPLEVEL).OUT_WIDTH_FNS=$(PARAM_OUT_WIDTH_FNS) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GFNS_ENABLE=$(PARAM_FNS_ENABLE) + COMPILE_ARGS += -GOUT_START_S=$(PARAM_OUT_START_S) + COMPILE_ARGS += -GOUT_START_NS=$(PARAM_OUT_START_NS) + COMPILE_ARGS += -GOUT_START_FNS=$(PARAM_OUT_START_FNS) + COMPILE_ARGS += -GOUT_PERIOD_S=$(PARAM_OUT_PERIOD_S) + COMPILE_ARGS += -GOUT_PERIOD_NS=$(PARAM_OUT_PERIOD_NS) + COMPILE_ARGS += -GOUT_PERIOD_FNS=$(PARAM_OUT_PERIOD_FNS) + COMPILE_ARGS += -GOUT_WIDTH_S=$(PARAM_OUT_WIDTH_S) + COMPILE_ARGS += -GOUT_WIDTH_NS=$(PARAM_OUT_WIDTH_NS) + COMPILE_ARGS += -GOUT_WIDTH_FNS=$(PARAM_OUT_WIDTH_FNS) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/tb/ptp_perout/test_ptp_perout.py b/tb/ptp_perout/test_ptp_perout.py new file mode 100644 index 000000000..f16340002 --- /dev/null +++ b/tb/ptp_perout/test_ptp_perout.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import PtpClock + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + self.ptp_clock = PtpClock( + ts_96=dut.input_ts_96, + ts_step=dut.input_ts_step, + clock=dut.clk, + reset=dut.rst, + period_ns=6.4 + ) + + dut.enable.setimmediatevalue(0) + dut.input_start.setimmediatevalue(0) + dut.input_start_valid.setimmediatevalue(0) + dut.input_period.setimmediatevalue(0) + dut.input_period_valid.setimmediatevalue(0) + dut.input_width.setimmediatevalue(0) + dut.input_width_valid.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.reset() + + dut.enable <= 1 + + await RisingEdge(dut.clk) + + dut.input_start <= 100 << 16 + dut.input_start_valid <= 1 + dut.input_period <= 100 << 16 + dut.input_period_valid <= 1 + dut.input_width <= 50 << 16 + dut.input_width_valid <= 1 + + await RisingEdge(dut.clk) + + dut.input_start_valid <= 0 + dut.input_period_valid <= 0 + dut.input_width_valid <= 0 + + await Timer(10000, 'ns') + + await RisingEdge(dut.clk) + + dut.input_start <= 0 << 16 + dut.input_start_valid <= 1 + dut.input_period <= 100 << 16 + dut.input_period_valid <= 1 + dut.input_width <= 50 << 16 + dut.input_width_valid <= 1 + + await RisingEdge(dut.clk) + + dut.input_start_valid <= 0 + dut.input_period_valid <= 0 + dut.input_width_valid <= 0 + + await Timer(10000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_ptp_perout(request): + dut = "ptp_perout" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + parameters['FNS_ENABLE'] = 1 + parameters['OUT_START_S'] = 0 + parameters['OUT_START_NS'] = 0 + parameters['OUT_START_FNS'] = 0x0000 + parameters['OUT_PERIOD_S'] = 1 + parameters['OUT_PERIOD_NS'] = 0 + parameters['OUT_PERIOD_FNS'] = 0x0000 + parameters['OUT_WIDTH_S'] = 0 + parameters['OUT_WIDTH_NS'] = 1000 + parameters['OUT_WIDTH_FNS'] = 0x0000 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From 8e1ad2eba6e684d91488e50e6f1796de15bf094d Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 29 Dec 2020 22:55:55 -0800 Subject: [PATCH 31/37] Add cocotb testbench for ptp_clock_cdc --- tb/ptp_clock_cdc/Makefile | 95 +++++++++ tb/ptp_clock_cdc/test_ptp_clock_cdc.py | 261 +++++++++++++++++++++++++ 2 files changed, 356 insertions(+) create mode 100644 tb/ptp_clock_cdc/Makefile create mode 100644 tb/ptp_clock_cdc/test_ptp_clock_cdc.py diff --git a/tb/ptp_clock_cdc/Makefile b/tb/ptp_clock_cdc/Makefile new file mode 100644 index 000000000..6cfe4a1d6 --- /dev/null +++ b/tb/ptp_clock_cdc/Makefile @@ -0,0 +1,95 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = ptp_clock_cdc +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_TS_WIDTH ?= 96 +export PARAM_NS_WIDTH ?= 4 +export PARAM_FNS_WIDTH ?= 16 +export PARAM_INPUT_PERIOD_NS ?= 6 +export PARAM_INPUT_PERIOD_FNS ?= 26214 +export PARAM_OUTPUT_PERIOD_NS ?= 6 +export PARAM_OUTPUT_PERIOD_FNS ?= 26214 +export PARAM_USE_SAMPLE_CLOCK ?= 1 +export PARAM_LOG_FIFO_DEPTH ?= 3 +export PARAM_LOG_RATE ?= 3 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).TS_WIDTH=$(PARAM_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).NS_WIDTH=$(PARAM_NS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).FNS_WIDTH=$(PARAM_FNS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).INPUT_PERIOD_NS=$(PARAM_INPUT_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).INPUT_PERIOD_FNS=$(PARAM_INPUT_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).OUTPUT_PERIOD_NS=$(PARAM_OUTPUT_PERIOD_NS) + COMPILE_ARGS += -P $(TOPLEVEL).OUTPUT_PERIOD_FNS=$(PARAM_OUTPUT_PERIOD_FNS) + COMPILE_ARGS += -P $(TOPLEVEL).USE_SAMPLE_CLOCK=$(PARAM_USE_SAMPLE_CLOCK) + COMPILE_ARGS += -P $(TOPLEVEL).LOG_FIFO_DEPTH=$(PARAM_LOG_FIFO_DEPTH) + COMPILE_ARGS += -P $(TOPLEVEL).LOG_RATE=$(PARAM_LOG_RATE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GTS_WIDTH=$(PARAM_TS_WIDTH) + COMPILE_ARGS += -GNS_WIDTH=$(PARAM_NS_WIDTH) + COMPILE_ARGS += -GFNS_WIDTH=$(PARAM_FNS_WIDTH) + COMPILE_ARGS += -GINPUT_PERIOD_NS=$(PARAM_INPUT_PERIOD_NS) + COMPILE_ARGS += -GINPUT_PERIOD_FNS=$(PARAM_INPUT_PERIOD_FNS) + COMPILE_ARGS += -GOUTPUT_PERIOD_NS=$(PARAM_OUTPUT_PERIOD_NS) + COMPILE_ARGS += -GOUTPUT_PERIOD_FNS=$(PARAM_OUTPUT_PERIOD_FNS) + COMPILE_ARGS += -GUSE_SAMPLE_CLOCK=$(PARAM_USE_SAMPLE_CLOCK) + COMPILE_ARGS += -GLOG_FIFO_DEPTH=$(PARAM_LOG_FIFO_DEPTH) + COMPILE_ARGS += -GLOG_RATE=$(PARAM_LOG_RATE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/tb/ptp_clock_cdc/test_ptp_clock_cdc.py b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py new file mode 100644 index 000000000..829e8c3a4 --- /dev/null +++ b/tb/ptp_clock_cdc/test_ptp_clock_cdc.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +import pytest +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer +from cocotb.utils import get_sim_steps + +from cocotbext.eth import PtpClock + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.input_clk, 6.4, units="ns").start()) + + cocotb.fork(Clock(dut.sample_clk, 10, units="ns").start()) + + if len(dut.input_ts) == 64: + self.ptp_clock = PtpClock( + ts_64=dut.input_ts, + clock=dut.input_clk, + reset=dut.input_rst, + period_ns=6.4 + ) + else: + self.ptp_clock = PtpClock( + ts_96=dut.input_ts, + clock=dut.input_clk, + reset=dut.input_rst, + period_ns=6.4 + ) + + self._clock_cr = None + self.set_output_clock_period(6.4) + + async def reset(self): + self.dut.input_rst.setimmediatevalue(0) + self.dut.output_rst.setimmediatevalue(0) + await RisingEdge(self.dut.input_clk) + self.dut.input_rst <= 1 + self.dut.output_rst <= 1 + for k in range(10): + await RisingEdge(self.dut.input_clk) + self.dut.input_rst <= 0 + self.dut.output_rst <= 0 + for k in range(10): + await RisingEdge(self.dut.input_clk) + + def set_output_clock_period(self, period): + if self._clock_cr is not None: + self._clock_cr.kill() + + self._clock_cr = cocotb.fork(self._run_clock(period)) + + async def _run_clock(self, period): + half_period = get_sim_steps(period / 2.0, 'ns') + t = Timer(half_period) + + while True: + await t + self.dut.output_clk <= 1 + await t + self.dut.output_clk <= 0 + + def get_input_ts_ns(self): + ts = self.dut.input_ts.value.integer + if len(self.dut.input_ts) == 64: + return ts/2**16*1e-9 + else: + return (ts >> 48) + ((ts & 0xffffffffffff)/2**16*1e-9) + + def get_output_ts_ns(self): + ts = self.dut.output_ts.value.integer + if len(self.dut.output_ts) == 64: + return ts/2**16*1e-9 + else: + return (ts >> 48) + ((ts & 0xffffffffffff)/2**16*1e-9) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.reset() + + await RisingEdge(dut.input_clk) + tb.log.info("Same clock speed") + + await RisingEdge(dut.input_clk) + + for i in range(20000): + await RisingEdge(dut.input_clk) + + input_stop_ts = tb.get_input_ts_ns() + output_stop_ts = tb.get_output_ts_ns() + + diff = input_stop_ts-output_stop_ts + + tb.log.info(f"Difference: {diff} s") + + assert abs(diff) < 1e-8 + + await RisingEdge(dut.input_clk) + tb.log.info("Slightly faster") + + tb.set_output_clock_period(6.2) + + await RisingEdge(dut.input_clk) + + for i in range(20000): + await RisingEdge(dut.input_clk) + + input_stop_ts = tb.get_input_ts_ns() + output_stop_ts = tb.get_output_ts_ns() + + diff = input_stop_ts-output_stop_ts + + tb.log.info(f"Difference: {diff} s") + + assert abs(diff) < 1e-8 + + await RisingEdge(dut.input_clk) + tb.log.info("Slightly slower") + + tb.set_output_clock_period(6.6) + + await RisingEdge(dut.input_clk) + + for i in range(20000): + await RisingEdge(dut.input_clk) + + input_stop_ts = tb.get_input_ts_ns() + output_stop_ts = tb.get_output_ts_ns() + + diff = input_stop_ts-output_stop_ts + + tb.log.info(f"Difference: {diff} s") + + assert abs(diff) < 1e-8 + + await RisingEdge(dut.input_clk) + tb.log.info("Significantly faster") + + tb.set_output_clock_period(4.0) + + await RisingEdge(dut.input_clk) + + for i in range(20000): + await RisingEdge(dut.input_clk) + + input_stop_ts = tb.get_input_ts_ns() + output_stop_ts = tb.get_output_ts_ns() + + diff = input_stop_ts-output_stop_ts + + tb.log.info(f"Difference: {diff} s") + + assert abs(diff) < 1e-7 + + await RisingEdge(dut.input_clk) + tb.log.info("Significantly slower") + + tb.set_output_clock_period(10.0) + + await RisingEdge(dut.input_clk) + + for i in range(30000): + await RisingEdge(dut.input_clk) + + input_stop_ts = tb.get_input_ts_ns() + output_stop_ts = tb.get_output_ts_ns() + + diff = input_stop_ts-output_stop_ts + + tb.log.info(f"Difference: {diff} s") + + assert abs(diff) < 1e-7 + + await RisingEdge(dut.input_clk) + await RisingEdge(dut.input_clk) + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("ts_width", [96, 64]) +def test_ptp_clock_cdc(request, ts_width): + dut = "ptp_clock_cdc" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + parameters['TS_WIDTH'] = ts_width + parameters['NS_WIDTH'] = 4 + parameters['FNS_WIDTH'] = 16 + parameters['INPUT_PERIOD_NS'] = 0x6 + parameters['INPUT_PERIOD_FNS'] = 0x6666 + parameters['OUTPUT_PERIOD_NS'] = 0x6 + parameters['OUTPUT_PERIOD_FNS'] = 0x6666 + parameters['USE_SAMPLE_CLOCK'] = 1 + parameters['LOG_FIFO_DEPTH'] = 3 + parameters['LOG_RATE'] = 3 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From 22feb53e1dbe86604cdc9e2dde4d058fcefa3a22 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 30 Dec 2020 16:48:37 -0800 Subject: [PATCH 32/37] Update example design readmes --- example/ML605/fpga_gmii/README.md | 2 +- example/ML605/fpga_rgmii/README.md | 2 +- example/ML605/fpga_sgmii/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/ML605/fpga_gmii/README.md b/example/ML605/fpga_gmii/README.md index 5b6159716..730a2f87b 100644 --- a/example/ML605/fpga_gmii/README.md +++ b/example/ML605/fpga_gmii/README.md @@ -11,7 +11,7 @@ to ARP requests. Configure the PHY for GMII by placing J66 and J67 across pins 1 and 2 and opening J68. -FPGA: XC6SlX45-2CSG324 +FPGA: XC6VLX130T-1FF1156 or XC6VLX240T-1FF1156 PHY: Marvell M88E1111 ## How to build diff --git a/example/ML605/fpga_rgmii/README.md b/example/ML605/fpga_rgmii/README.md index 43005aad5..9602d1845 100644 --- a/example/ML605/fpga_rgmii/README.md +++ b/example/ML605/fpga_rgmii/README.md @@ -11,7 +11,7 @@ to ARP requests. Configure the PHY for RGMII by placing J66 across pins 1 and 2, opening J67, and shorting J68. -FPGA: XC6SlX45-2CSG324 +FPGA: XC6VLX130T-1FF1156 or XC6VLX240T-1FF1156 PHY: Marvell M88E1111 ## How to build diff --git a/example/ML605/fpga_sgmii/README.md b/example/ML605/fpga_sgmii/README.md index b08c34422..af3b0b236 100644 --- a/example/ML605/fpga_sgmii/README.md +++ b/example/ML605/fpga_sgmii/README.md @@ -11,7 +11,7 @@ to ARP requests. Configure the PHY for SGMII by placing J66 and J67 across pins 2 and 3 and opening J68. -FPGA: XC6SlX45-2CSG324 +FPGA: XC6VLX130T-1FF1156 or XC6VLX240T-1FF1156 PHY: Marvell M88E1111 ## How to build From 8a021f5c9be59d52a3273b65d5025fd6bbe7086d Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 30 Dec 2020 16:54:30 -0800 Subject: [PATCH 33/37] Update KC705 XDC --- example/KC705/fpga_gmii/fpga.xdc | 61 ++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/example/KC705/fpga_gmii/fpga.xdc b/example/KC705/fpga_gmii/fpga.xdc index e52f2e3b7..40ec7e787 100644 --- a/example/KC705/fpga_gmii/fpga.xdc +++ b/example/KC705/fpga_gmii/fpga.xdc @@ -45,34 +45,41 @@ set_property -dict {LOC L27 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC K23 IOSTANDARD LVCMOS25} [get_ports uart_cts] # Gigabit Ethernet GMII PHY -set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] -set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] -set_property -dict {LOC U25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[1]}] -set_property -dict {LOC T25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[2]}] -set_property -dict {LOC U28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[3]}] -set_property -dict {LOC R19 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[4]}] -set_property -dict {LOC T27 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[5]}] -set_property -dict {LOC T26 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[6]}] -set_property -dict {LOC T28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[7]}] -set_property -dict {LOC R28 IOSTANDARD LVCMOS25} [get_ports phy_rx_dv] -set_property -dict {LOC V26 IOSTANDARD LVCMOS25} [get_ports phy_rx_er] -set_property -dict {LOC K30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_gtx_clk] -set_property -dict {LOC M28 IOSTANDARD LVCMOS25} [get_ports phy_tx_clk] -set_property -dict {LOC N27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[0]}] -set_property -dict {LOC N25 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[1]}] -set_property -dict {LOC M29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[2]}] -set_property -dict {LOC L28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[3]}] -set_property -dict {LOC J26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[4]}] -set_property -dict {LOC K26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[5]}] -set_property -dict {LOC L30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[6]}] -set_property -dict {LOC J28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[7]}] -set_property -dict {LOC M27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_en] -set_property -dict {LOC N29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_er] -set_property -dict {LOC L20 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_reset_n] -set_property -dict {LOC N30 IOSTANDARD LVCMOS25} [get_ports phy_int_n] -#set_property -dict {LOC J21 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdio] -#set_property -dict {LOC R23 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdc] +set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] ;# from U37.C1 RXCLK +set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] ;# from U37.B2 RXD0 +set_property -dict {LOC U25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[1]}] ;# from U37.D3 RXD1 +set_property -dict {LOC T25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[2]}] ;# from U37.C3 RXD2 +set_property -dict {LOC U28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[3]}] ;# from U37.B3 RXD3 +set_property -dict {LOC R19 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[4]}] ;# from U37.C4 RXD4 +set_property -dict {LOC T27 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[5]}] ;# from U37.A1 RXD5 +set_property -dict {LOC T26 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[6]}] ;# from U37.A2 RXD6 +set_property -dict {LOC T28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[7]}] ;# from U37.C5 RXD7 +set_property -dict {LOC R28 IOSTANDARD LVCMOS25} [get_ports phy_rx_dv] ;# from U37.B1 RXCTL_RXDV +set_property -dict {LOC V26 IOSTANDARD LVCMOS25} [get_ports phy_rx_er] ;# from U37.D4 RXER +set_property -dict {LOC K30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_gtx_clk] ;# from U37.E2 TXC_GTXCLK +set_property -dict {LOC M28 IOSTANDARD LVCMOS25} [get_ports phy_tx_clk] ;# from U37.D1 TXCLK +set_property -dict {LOC N27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[0]}] ;# from U37.F1 TXD0 +set_property -dict {LOC N25 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[1]}] ;# from U37.G2 TXD1 +set_property -dict {LOC M29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[2]}] ;# from U37.G3 TXD2 +set_property -dict {LOC L28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[3]}] ;# from U37.H1 TXD3 +set_property -dict {LOC J26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[4]}] ;# from U37.H2 TXD4 +set_property -dict {LOC K26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[5]}] ;# from U37.H3 TXD5 +set_property -dict {LOC L30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[6]}] ;# from U37.J1 TXD6 +set_property -dict {LOC J28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[7]}] ;# from U37.J2 TXD7 +set_property -dict {LOC M27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_en] ;# from U37.E1 TXCTL_TXEN +set_property -dict {LOC N29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_er] ;# from U37.F2 TXER +#set_property -dict {LOC A7 } [get_ports phy_sgmii_rx_p] ;# MGTXRXP1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A7 SOUT_P +#set_property -dict {LOC A8 } [get_ports phy_sgmii_rx_n] ;# MGTXRXN1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A8 SOUT_N +#set_property -dict {LOC A3 } [get_ports phy_sgmii_tx_p] ;# MGTXTXP1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A3 SIN_P +#set_property -dict {LOC A4 } [get_ports phy_sgmii_tx_n] ;# MGTXTXN1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A4 SIN_N +#set_property -dict {LOC G8 } [get_ports phy_sgmii_clk_p] ;# MGTREFCLK0P_117 from U2.7 +#set_property -dict {LOC G7 } [get_ports phy_sgmii_clk_n] ;# MGTREFCLK0N_117 from U2.6 +set_property -dict {LOC L20 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_reset_n] ;# from U37.K3 RESET_B +set_property -dict {LOC N30 IOSTANDARD LVCMOS25} [get_ports phy_int_n] ;# from U37.L1 INT_B +#set_property -dict {LOC J21 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdio] ;# from U37.M1 MDIO +#set_property -dict {LOC R23 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdc] ;# from U37.L3 MDC create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] +#create_clock -period 8.000 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] From 5a7fd984137250e592372b213ea5c4d33e537406 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 30 Dec 2020 17:15:18 -0800 Subject: [PATCH 34/37] Add KC705 RGMII example design --- example/KC705/fpga_rgmii/Makefile | 25 + example/KC705/fpga_rgmii/README.md | 28 + example/KC705/fpga_rgmii/common/vivado.mk | 123 ++++ example/KC705/fpga_rgmii/eth.xdc | 5 + example/KC705/fpga_rgmii/fpga.xdc | 85 +++ example/KC705/fpga_rgmii/fpga/Makefile | 67 ++ .../fpga_rgmii/fpga/generate_bit_iodelay.tcl | 6 + example/KC705/fpga_rgmii/lib/eth | 1 + .../KC705/fpga_rgmii/rtl/debounce_switch.v | 89 +++ example/KC705/fpga_rgmii/rtl/fpga.v | 371 +++++++++++ example/KC705/fpga_rgmii/rtl/fpga_core.v | 584 ++++++++++++++++++ example/KC705/fpga_rgmii/rtl/sync_signal.v | 58 ++ .../KC705/fpga_rgmii/tb/fpga_core/Makefile | 100 +++ .../fpga_rgmii/tb/fpga_core/test_fpga_core.py | 229 +++++++ 14 files changed, 1771 insertions(+) create mode 100644 example/KC705/fpga_rgmii/Makefile create mode 100644 example/KC705/fpga_rgmii/README.md create mode 100644 example/KC705/fpga_rgmii/common/vivado.mk create mode 100644 example/KC705/fpga_rgmii/eth.xdc create mode 100644 example/KC705/fpga_rgmii/fpga.xdc create mode 100644 example/KC705/fpga_rgmii/fpga/Makefile create mode 100644 example/KC705/fpga_rgmii/fpga/generate_bit_iodelay.tcl create mode 120000 example/KC705/fpga_rgmii/lib/eth create mode 100644 example/KC705/fpga_rgmii/rtl/debounce_switch.v create mode 100644 example/KC705/fpga_rgmii/rtl/fpga.v create mode 100644 example/KC705/fpga_rgmii/rtl/fpga_core.v create mode 100644 example/KC705/fpga_rgmii/rtl/sync_signal.v create mode 100644 example/KC705/fpga_rgmii/tb/fpga_core/Makefile create mode 100644 example/KC705/fpga_rgmii/tb/fpga_core/test_fpga_core.py diff --git a/example/KC705/fpga_rgmii/Makefile b/example/KC705/fpga_rgmii/Makefile new file mode 100644 index 000000000..f504bd06f --- /dev/null +++ b/example/KC705/fpga_rgmii/Makefile @@ -0,0 +1,25 @@ +# Targets +TARGETS:= + +# Subdirectories +SUBDIRS = fpga +SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS)) + +# Rules +.PHONY: all +all: $(SUBDIRS) $(TARGETS) + +.PHONY: $(SUBDIRS) +$(SUBDIRS): + cd $@ && $(MAKE) + +.PHONY: $(SUBDIRS_CLEAN) +$(SUBDIRS_CLEAN): + cd $(@:.clean=) && $(MAKE) clean + +.PHONY: clean +clean: $(SUBDIRS_CLEAN) + -rm -rf $(TARGETS) + +program: + #djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit diff --git a/example/KC705/fpga_rgmii/README.md b/example/KC705/fpga_rgmii/README.md new file mode 100644 index 000000000..b5b9eac9d --- /dev/null +++ b/example/KC705/fpga_rgmii/README.md @@ -0,0 +1,28 @@ +# Verilog Ethernet KC705 Example Design + +## Introduction + +This example design targets the Xilinx KC705 FPGA board. + +The design by default listens to UDP port 1234 at IP address 192.168.1.128 and +will echo back any packets received. The design will also respond correctly +to ARP requests. + +Configure the PHY for RGMII by placing J29 across pins 1 and 2, opening J30, +and shorting J64. + +FPGA: XC7K325T-2FFG900C +PHY: Marvell 88E1111 + +## How to build + +Run make to build. Ensure that the Xilinx Vivado toolchain components are +in PATH. + +## How to test + +Run make program to program the KC705 board with Vivado. Then run netcat -u +192.168.1.128 1234 to open a UDP connection to port 1234. Any text entered +into netcat will be echoed back after pressing enter. + + diff --git a/example/KC705/fpga_rgmii/common/vivado.mk b/example/KC705/fpga_rgmii/common/vivado.mk new file mode 100644 index 000000000..ee83637e0 --- /dev/null +++ b/example/KC705/fpga_rgmii/common/vivado.mk @@ -0,0 +1,123 @@ +################################################################### +# +# Xilinx Vivado FPGA Makefile +# +# Copyright (c) 2016 Alex Forencich +# +################################################################### +# +# Parameters: +# FPGA_TOP - Top module name +# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale) +# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e) +# SYN_FILES - space-separated list of source files +# INC_FILES - space-separated list of include files +# XDC_FILES - space-separated list of timing constraint files +# XCI_FILES - space-separated list of IP XCI files +# +# Example: +# +# FPGA_TOP = fpga +# FPGA_FAMILY = VirtexUltrascale +# FPGA_DEVICE = xcvu095-ffva2104-2-e +# SYN_FILES = rtl/fpga.v +# XDC_FILES = fpga.xdc +# XCI_FILES = ip/pcspma.xci +# include ../common/vivado.mk +# +################################################################### + +# phony targets +.PHONY: clean fpga + +# prevent make from deleting intermediate files and reports +.PRECIOUS: %.xpr %.bit %.mcs %.prm +.SECONDARY: + +CONFIG ?= config.mk +-include ../$(CONFIG) + +SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(IP_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).xpr + +tmpclean: + -rm -rf *.log *.jou *.cache *.hbs *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v + -rm -rf create_project.tcl run_synth.tcl run_impl.tcl generate_bit.tcl + +clean: tmpclean + -rm -rf *.bit program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +distclean: clean + -rm -rf rev + +################################################################### +# Target implementations +################################################################### + +# Vivado project file +%.xpr: Makefile $(XCI_FILES_REL) $(IP_TCL_FILES_REL) + rm -rf defines.v + touch defines.v + for x in $(DEFS); do echo '`define' $$x >> defines.v; done + echo "create_project -force -part $(FPGA_PART) $*" > create_project.tcl + echo "add_files -fileset sources_1 defines.v" >> create_project.tcl + for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done + for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done + for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done + for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> create_project.tcl; done + echo "exit" >> create_project.tcl + vivado -nojournal -nolog -mode batch -source create_project.tcl + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) + echo "open_project $*.xpr" > run_synth.tcl + echo "reset_run synth_1" >> run_synth.tcl + echo "launch_runs synth_1" >> run_synth.tcl + echo "wait_on_run synth_1" >> run_synth.tcl + echo "exit" >> run_synth.tcl + vivado -nojournal -nolog -mode batch -source run_synth.tcl + +# implementation run +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_project $*.xpr" > run_impl.tcl + echo "reset_run impl_1" >> run_impl.tcl + echo "launch_runs impl_1" >> run_impl.tcl + echo "wait_on_run impl_1" >> run_impl.tcl + echo "exit" >> run_impl.tcl + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + echo "exit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/example/KC705/fpga_rgmii/eth.xdc b/example/KC705/fpga_rgmii/eth.xdc new file mode 100644 index 000000000..d9780aa1c --- /dev/null +++ b/example/KC705/fpga_rgmii/eth.xdc @@ -0,0 +1,5 @@ +# Ethernet constraints + +# IDELAY on RGMII from PHY chip +set_property IDELAY_VALUE 0 [get_cells {phy_rx_ctl_idelay phy_rxd_idelay_*}] + diff --git a/example/KC705/fpga_rgmii/fpga.xdc b/example/KC705/fpga_rgmii/fpga.xdc new file mode 100644 index 000000000..816827e0f --- /dev/null +++ b/example/KC705/fpga_rgmii/fpga.xdc @@ -0,0 +1,85 @@ +# XDC constraints for the Xilinx KC705 board +# part: xc7k325tffg900-2 + +# General configuration +set_property CFGBVS VCCO [current_design] +set_property CONFIG_VOLTAGE 2.5 [current_design] +set_property BITSTREAM.GENERAL.COMPRESS true [current_design] + +# System clocks +# 200 MHz +set_property -dict {LOC AD12 IOSTANDARD LVDS} [get_ports clk_200mhz_p] +set_property -dict {LOC AD11 IOSTANDARD LVDS} [get_ports clk_200mhz_n] +create_clock -period 5.000 -name clk_200mhz [get_ports clk_200mhz_p] + +# LEDs +set_property -dict {LOC AB8 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[0]}] +set_property -dict {LOC AA8 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[1]}] +set_property -dict {LOC AC9 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[2]}] +set_property -dict {LOC AB9 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[3]}] +set_property -dict {LOC AE26 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[4]}] +set_property -dict {LOC G19 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[5]}] +set_property -dict {LOC E18 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[6]}] +set_property -dict {LOC F16 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[7]}] + +# Reset button +set_property -dict {LOC AB7 IOSTANDARD LVCMOS15} [get_ports reset] + +# Push buttons +set_property -dict {LOC AA12 IOSTANDARD LVCMOS15} [get_ports btnu] +set_property -dict {LOC AC6 IOSTANDARD LVCMOS15} [get_ports btnl] +set_property -dict {LOC AB12 IOSTANDARD LVCMOS15} [get_ports btnd] +set_property -dict {LOC AG5 IOSTANDARD LVCMOS15} [get_ports btnr] +set_property -dict {LOC G12 IOSTANDARD LVCMOS25} [get_ports btnc] + +# Toggle switches +set_property -dict {LOC Y29 IOSTANDARD LVCMOS25} [get_ports {sw[0]}] +set_property -dict {LOC W29 IOSTANDARD LVCMOS25} [get_ports {sw[1]}] +set_property -dict {LOC AA28 IOSTANDARD LVCMOS25} [get_ports {sw[2]}] +set_property -dict {LOC Y28 IOSTANDARD LVCMOS25} [get_ports {sw[3]}] + +# UART +set_property -dict {LOC K24 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_txd] +set_property -dict {LOC M19 IOSTANDARD LVCMOS25} [get_ports uart_rxd] +set_property -dict {LOC L27 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_rts] +set_property -dict {LOC K23 IOSTANDARD LVCMOS25} [get_ports uart_cts] + +# Gigabit Ethernet GMII PHY +set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] ;# from U37.C1 RXCLK +set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] ;# from U37.B2 RXD0 +set_property -dict {LOC U25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[1]}] ;# from U37.D3 RXD1 +set_property -dict {LOC T25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[2]}] ;# from U37.C3 RXD2 +set_property -dict {LOC U28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[3]}] ;# from U37.B3 RXD3 +#set_property -dict {LOC R19 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[4]}] ;# from U37.C4 RXD4 +#set_property -dict {LOC T27 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[5]}] ;# from U37.A1 RXD5 +#set_property -dict {LOC T26 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[6]}] ;# from U37.A2 RXD6 +#set_property -dict {LOC T28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[7]}] ;# from U37.C5 RXD7 +set_property -dict {LOC R28 IOSTANDARD LVCMOS25} [get_ports phy_rx_ctl] ;# from U37.B1 RXCTL_RXDV +#set_property -dict {LOC V26 IOSTANDARD LVCMOS25} [get_ports phy_rx_er] ;# from U37.D4 RXER +set_property -dict {LOC K30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_clk] ;# from U37.E2 TXC_GTXCLK +#set_property -dict {LOC M28 IOSTANDARD LVCMOS25} [get_ports phy_tx_clk] ;# from U37.D1 TXCLK +set_property -dict {LOC N27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[0]}] ;# from U37.F1 TXD0 +set_property -dict {LOC N25 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[1]}] ;# from U37.G2 TXD1 +set_property -dict {LOC M29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[2]}] ;# from U37.G3 TXD2 +set_property -dict {LOC L28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[3]}] ;# from U37.H1 TXD3 +#set_property -dict {LOC J26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[4]}] ;# from U37.H2 TXD4 +#set_property -dict {LOC K26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[5]}] ;# from U37.H3 TXD5 +#set_property -dict {LOC L30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[6]}] ;# from U37.J1 TXD6 +#set_property -dict {LOC J28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[7]}] ;# from U37.J2 TXD7 +set_property -dict {LOC M27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_ctl] ;# from U37.E1 TXCTL_TXEN +#set_property -dict {LOC N29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_er] ;# from U37.F2 TXER +#set_property -dict {LOC A7 } [get_ports phy_sgmii_rx_p] ;# MGTXRXP1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A7 SOUT_P +#set_property -dict {LOC A8 } [get_ports phy_sgmii_rx_n] ;# MGTXRXN1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A8 SOUT_N +#set_property -dict {LOC A3 } [get_ports phy_sgmii_tx_p] ;# MGTXTXP1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A3 SIN_P +#set_property -dict {LOC A4 } [get_ports phy_sgmii_tx_n] ;# MGTXTXN1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X?Y? from U37.A4 SIN_N +#set_property -dict {LOC G8 } [get_ports phy_sgmii_clk_p] ;# MGTREFCLK0P_117 from U2.7 +#set_property -dict {LOC G7 } [get_ports phy_sgmii_clk_n] ;# MGTREFCLK0N_117 from U2.6 +set_property -dict {LOC L20 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_reset_n] ;# from U37.K3 RESET_B +set_property -dict {LOC N30 IOSTANDARD LVCMOS25} [get_ports phy_int_n] ;# from U37.L1 INT_B +#set_property -dict {LOC J21 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdio] ;# from U37.M1 MDIO +#set_property -dict {LOC R23 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdc] ;# from U37.L3 MDC + +#create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] +create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] +#create_clock -period 8.000 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] + diff --git a/example/KC705/fpga_rgmii/fpga/Makefile b/example/KC705/fpga_rgmii/fpga/Makefile new file mode 100644 index 000000000..0f1faf642 --- /dev/null +++ b/example/KC705/fpga_rgmii/fpga/Makefile @@ -0,0 +1,67 @@ + +# FPGA settings +FPGA_PART = xc7k325tffg900-2 +FPGA_TOP = fpga +FPGA_ARCH = kintex7 + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += lib/eth/rtl/iddr.v +SYN_FILES += lib/eth/rtl/oddr.v +SYN_FILES += lib/eth/rtl/ssio_ddr_in.v +SYN_FILES += lib/eth/rtl/rgmii_phy_if.v +SYN_FILES += lib/eth/rtl/eth_mac_1g_rgmii_fifo.v +SYN_FILES += lib/eth/rtl/eth_mac_1g_rgmii.v +SYN_FILES += lib/eth/rtl/eth_mac_1g.v +SYN_FILES += lib/eth/rtl/axis_gmii_rx.v +SYN_FILES += lib/eth/rtl/axis_gmii_tx.v +SYN_FILES += lib/eth/rtl/lfsr.v +SYN_FILES += lib/eth/rtl/eth_axis_rx.v +SYN_FILES += lib/eth/rtl/eth_axis_tx.v +SYN_FILES += lib/eth/rtl/udp_complete.v +SYN_FILES += lib/eth/rtl/udp_checksum_gen.v +SYN_FILES += lib/eth/rtl/udp.v +SYN_FILES += lib/eth/rtl/udp_ip_rx.v +SYN_FILES += lib/eth/rtl/udp_ip_tx.v +SYN_FILES += lib/eth/rtl/ip_complete.v +SYN_FILES += lib/eth/rtl/ip.v +SYN_FILES += lib/eth/rtl/ip_eth_rx.v +SYN_FILES += lib/eth/rtl/ip_eth_tx.v +SYN_FILES += lib/eth/rtl/ip_arb_mux.v +SYN_FILES += lib/eth/rtl/arp.v +SYN_FILES += lib/eth/rtl/arp_cache.v +SYN_FILES += lib/eth/rtl/arp_eth_rx.v +SYN_FILES += lib/eth/rtl/arp_eth_tx.v +SYN_FILES += lib/eth/rtl/eth_arb_mux.v +SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v +SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v +SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v +SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v +SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v +SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v + +# XDC files +XDC_FILES = fpga.xdc +XDC_FILES += eth.xdc +XDC_FILES += lib/eth/syn/rgmii_phy_if.tcl +XDC_FILES += lib/eth/syn/eth_mac_1g_rgmii.tcl +XDC_FILES += lib/eth/syn/eth_mac_fifo.tcl +XDC_FILES += lib/eth/lib/axis/syn/axis_async_fifo.tcl +XDC_FILES += lib/eth/lib/axis/syn/sync_reset.tcl + +include ../common/vivado.mk + +program: $(FPGA_TOP).bit + echo "open_hw" > program.tcl + echo "connect_hw_server" >> program.tcl + echo "open_hw_target" >> program.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl + echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl + echo "program_hw_devices [current_hw_device]" >> program.tcl + echo "exit" >> program.tcl + vivado -nojournal -nolog -mode batch -source program.tcl + diff --git a/example/KC705/fpga_rgmii/fpga/generate_bit_iodelay.tcl b/example/KC705/fpga_rgmii/fpga/generate_bit_iodelay.tcl new file mode 100644 index 000000000..d97f96678 --- /dev/null +++ b/example/KC705/fpga_rgmii/fpga/generate_bit_iodelay.tcl @@ -0,0 +1,6 @@ +open_project fpga.xpr +open_run impl_1 +set_property IDELAY_VALUE 0 [get_cells {phy_rx_ctl_idelay phy_rxd_idelay_*}] +set_property CLKOUT1_PHASE 90 [get_cells clk_mmcm_inst] +write_bitstream -force fpga.bit +exit diff --git a/example/KC705/fpga_rgmii/lib/eth b/example/KC705/fpga_rgmii/lib/eth new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/example/KC705/fpga_rgmii/lib/eth @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/example/KC705/fpga_rgmii/rtl/debounce_switch.v b/example/KC705/fpga_rgmii/rtl/debounce_switch.v new file mode 100644 index 000000000..bb631cc35 --- /dev/null +++ b/example/KC705/fpga_rgmii/rtl/debounce_switch.v @@ -0,0 +1,89 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`timescale 1 ns / 1 ps + +/* + * Synchronizes switch and button inputs with a slow sampled shift register + */ +module debounce_switch #( + parameter WIDTH=1, // width of the input and output signals + parameter N=3, // length of shift register + parameter RATE=125000 // clock division factor +)( + input wire clk, + input wire rst, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [23:0] cnt_reg = 24'd0; + +reg [N-1:0] debounce_reg[WIDTH-1:0]; + +reg [WIDTH-1:0] state; + +/* + * The synchronized output is the state register + */ +assign out = state; + +integer k; + +always @(posedge clk or posedge rst) begin + if (rst) begin + cnt_reg <= 0; + state <= 0; + + for (k = 0; k < WIDTH; k = k + 1) begin + debounce_reg[k] <= 0; + end + end else begin + if (cnt_reg < RATE) begin + cnt_reg <= cnt_reg + 24'd1; + end else begin + cnt_reg <= 24'd0; + end + + if (cnt_reg == 24'd0) begin + for (k = 0; k < WIDTH; k = k + 1) begin + debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]}; + end + end + + for (k = 0; k < WIDTH; k = k + 1) begin + if (|debounce_reg[k] == 0) begin + state[k] <= 0; + end else if (&debounce_reg[k] == 1) begin + state[k] <= 1; + end else begin + state[k] <= state[k]; + end + end + end +end + +endmodule diff --git a/example/KC705/fpga_rgmii/rtl/fpga.v b/example/KC705/fpga_rgmii/rtl/fpga.v new file mode 100644 index 000000000..ba0cad1ed --- /dev/null +++ b/example/KC705/fpga_rgmii/rtl/fpga.v @@ -0,0 +1,371 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * FPGA top-level module + */ +module fpga ( + /* + * Clock: 200MHz + * Reset: Push button, active high + */ + input wire clk_200mhz_p, + input wire clk_200mhz_n, + input wire reset, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [3:0] sw, + output wire [7:0] led, + + /* + * Ethernet: 1000BASE-T RGMII + */ + input wire phy_rx_clk, + input wire [3:0] phy_rxd, + input wire phy_rx_ctl, + output wire phy_tx_clk, + output wire [3:0] phy_txd, + output wire phy_tx_ctl, + output wire phy_reset_n, + input wire phy_int_n, + + /* + * UART: 500000 bps, 8N1 + */ + input wire uart_rxd, + output wire uart_txd, + output wire uart_rts, + input wire uart_cts +); + +// Clock and reset + +wire clk_200mhz_ibufg; + +// Internal 125 MHz clock +wire clk_mmcm_out; +wire clk_int; +wire clk90_mmcm_out; +wire clk90_int; +wire rst_int; + +wire clk_200mhz_mmcm_out; +wire clk_200mhz_int; + +wire mmcm_rst = reset; +wire mmcm_locked; +wire mmcm_clkfb; + +IBUFGDS +clk_200mhz_ibufgds_inst( + .I(clk_200mhz_p), + .IB(clk_200mhz_n), + .O(clk_200mhz_ibufg) +); + +// MMCM instance +// 200 MHz in, 125 MHz out +// PFD range: 10 MHz to 500 MHz +// VCO range: 600 MHz to 1440 MHz +// M = 5, D = 1 sets Fvco = 1000 MHz (in range) +// Divide by 8 to get output frequency of 125 MHz +// Need two 125 MHz outputs with 90 degree offset +// Also need 200 MHz out for IODELAY +// 1000 / 5 = 200 MHz +MMCME2_BASE #( + .BANDWIDTH("OPTIMIZED"), + .CLKOUT0_DIVIDE_F(8), + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT0_PHASE(0), + .CLKOUT1_DIVIDE(8), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT1_PHASE(90), + .CLKOUT2_DIVIDE(5), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT2_PHASE(0), + .CLKOUT3_DIVIDE(1), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT3_PHASE(0), + .CLKOUT4_DIVIDE(1), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT4_PHASE(0), + .CLKOUT5_DIVIDE(1), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT5_PHASE(0), + .CLKOUT6_DIVIDE(1), + .CLKOUT6_DUTY_CYCLE(0.5), + .CLKOUT6_PHASE(0), + .CLKFBOUT_MULT_F(5), + .CLKFBOUT_PHASE(0), + .DIVCLK_DIVIDE(1), + .REF_JITTER1(0.010), + .CLKIN1_PERIOD(5.0), + .STARTUP_WAIT("FALSE"), + .CLKOUT4_CASCADE("FALSE") +) +clk_mmcm_inst ( + .CLKIN1(clk_200mhz_ibufg), + .CLKFBIN(mmcm_clkfb), + .RST(mmcm_rst), + .PWRDWN(1'b0), + .CLKOUT0(clk_mmcm_out), + .CLKOUT0B(), + .CLKOUT1(clk90_mmcm_out), + .CLKOUT1B(), + .CLKOUT2(clk_200mhz_mmcm_out), + .CLKOUT2B(), + .CLKOUT3(), + .CLKOUT3B(), + .CLKOUT4(), + .CLKOUT5(), + .CLKOUT6(), + .CLKFBOUT(mmcm_clkfb), + .CLKFBOUTB(), + .LOCKED(mmcm_locked) +); + +BUFG +clk_bufg_inst ( + .I(clk_mmcm_out), + .O(clk_int) +); + +BUFG +clk90_bufg_inst ( + .I(clk90_mmcm_out), + .O(clk90_int) +); + +BUFG +clk_200mhz_bufg_inst ( + .I(clk_200mhz_mmcm_out), + .O(clk_200mhz_int) +); + +sync_reset #( + .N(4) +) +sync_reset_inst ( + .clk(clk_int), + .rst(~mmcm_locked), + .out(rst_int) +); + +// GPIO +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(9), + .N(4), + .RATE(125000) +) +debounce_switch_inst ( + .clk(clk_int), + .rst(rst_int), + .in({btnu, + btnl, + btnd, + btnr, + btnc, + sw}), + .out({btnu_int, + btnl_int, + btnd_int, + btnr_int, + btnc_int, + sw_int}) +); + +wire uart_rxd_int; +wire uart_cts_int; + +sync_signal #( + .WIDTH(2), + .N(2) +) +sync_signal_inst ( + .clk(clk_int), + .in({uart_rxd, uart_cts}), + .out({uart_rxd_int, uart_cts_int}) +); + +// IODELAY elements for RGMII interface to PHY +wire [3:0] phy_rxd_delay; +wire phy_rx_ctl_delay; + +IDELAYCTRL +idelayctrl_inst ( + .REFCLK(clk_200mhz_int), + .RST(rst_int), + .RDY() +); + +IDELAYE2 #( + .IDELAY_TYPE("FIXED") +) +phy_rxd_idelay_0 ( + .IDATAIN(phy_rxd[0]), + .DATAOUT(phy_rxd_delay[0]), + .DATAIN(1'b0), + .C(1'b0), + .CE(1'b0), + .INC(1'b0), + .CINVCTRL(1'b0), + .CNTVALUEIN(5'd0), + .CNTVALUEOUT(), + .LD(1'b0), + .LDPIPEEN(1'b0), + .REGRST(1'b0) +); + +IDELAYE2 #( + .IDELAY_TYPE("FIXED") +) +phy_rxd_idelay_1 ( + .IDATAIN(phy_rxd[1]), + .DATAOUT(phy_rxd_delay[1]), + .DATAIN(1'b0), + .C(1'b0), + .CE(1'b0), + .INC(1'b0), + .CINVCTRL(1'b0), + .CNTVALUEIN(5'd0), + .CNTVALUEOUT(), + .LD(1'b0), + .LDPIPEEN(1'b0), + .REGRST(1'b0) +); + +IDELAYE2 #( + .IDELAY_TYPE("FIXED") +) +phy_rxd_idelay_2 ( + .IDATAIN(phy_rxd[2]), + .DATAOUT(phy_rxd_delay[2]), + .DATAIN(1'b0), + .C(1'b0), + .CE(1'b0), + .INC(1'b0), + .CINVCTRL(1'b0), + .CNTVALUEIN(5'd0), + .CNTVALUEOUT(), + .LD(1'b0), + .LDPIPEEN(1'b0), + .REGRST(1'b0) +); + +IDELAYE2 #( + .IDELAY_TYPE("FIXED") +) +phy_rxd_idelay_3 ( + .IDATAIN(phy_rxd[3]), + .DATAOUT(phy_rxd_delay[3]), + .DATAIN(1'b0), + .C(1'b0), + .CE(1'b0), + .INC(1'b0), + .CINVCTRL(1'b0), + .CNTVALUEIN(5'd0), + .CNTVALUEOUT(), + .LD(1'b0), + .LDPIPEEN(1'b0), + .REGRST(1'b0) +); + +IDELAYE2 #( + .IDELAY_TYPE("FIXED") +) +phy_rx_ctl_idelay ( + .IDATAIN(phy_rx_ctl), + .DATAOUT(phy_rx_ctl_delay), + .DATAIN(1'b0), + .C(1'b0), + .CE(1'b0), + .INC(1'b0), + .CINVCTRL(1'b0), + .CNTVALUEIN(5'd0), + .CNTVALUEOUT(), + .LD(1'b0), + .LDPIPEEN(1'b0), + .REGRST(1'b0) +); + +fpga_core #( + .TARGET("XILINX") +) +core_inst ( + /* + * Clock: 125MHz + * Synchronous reset + */ + .clk(clk_int), + .clk90(clk90_int), + .rst(rst_int), + /* + * GPIO + */ + .btnu(btnu_int), + .btnl(btnl_int), + .btnd(btnd_int), + .btnr(btnr_int), + .btnc(btnc_int), + .sw(sw_int), + .led(led), + /* + * Ethernet: 1000BASE-T RGMII + */ + .phy_rx_clk(phy_rx_clk), + .phy_rxd(phy_rxd_delay), + .phy_rx_ctl(phy_rx_ctl_delay), + .phy_tx_clk(phy_tx_clk), + .phy_txd(phy_txd), + .phy_tx_ctl(phy_tx_ctl), + .phy_reset_n(phy_reset_n), + .phy_int_n(phy_int_n), + /* + * UART: 115200 bps, 8N1 + */ + .uart_rxd(uart_rxd_int), + .uart_txd(uart_txd), + .uart_rts(uart_rts), + .uart_cts(uart_cts_int) +); + +endmodule diff --git a/example/KC705/fpga_rgmii/rtl/fpga_core.v b/example/KC705/fpga_rgmii/rtl/fpga_core.v new file mode 100644 index 000000000..43075db81 --- /dev/null +++ b/example/KC705/fpga_rgmii/rtl/fpga_core.v @@ -0,0 +1,584 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter TARGET = "GENERIC" +) +( + /* + * Clock: 125MHz + * Synchronous reset + */ + input wire clk, + input wire clk90, + input wire rst, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [7:0] sw, + output wire [7:0] led, + + /* + * Ethernet: 1000BASE-T RGMII + */ + input wire phy_rx_clk, + input wire [3:0] phy_rxd, + input wire phy_rx_ctl, + output wire phy_tx_clk, + output wire [3:0] phy_txd, + output wire phy_tx_ctl, + output wire phy_reset_n, + input wire phy_int_n, + + /* + * UART: 115200 bps, 8N1 + */ + input wire uart_rxd, + output wire uart_txd, + output wire uart_rts, + input wire uart_cts +); + +// AXI between MAC and Ethernet modules +wire [7:0] rx_axis_tdata; +wire rx_axis_tvalid; +wire rx_axis_tready; +wire rx_axis_tlast; +wire rx_axis_tuser; + +wire [7:0] tx_axis_tdata; +wire tx_axis_tvalid; +wire tx_axis_tready; +wire tx_axis_tlast; +wire tx_axis_tuser; + +// Ethernet frame between Ethernet modules and UDP stack +wire rx_eth_hdr_ready; +wire rx_eth_hdr_valid; +wire [47:0] rx_eth_dest_mac; +wire [47:0] rx_eth_src_mac; +wire [15:0] rx_eth_type; +wire [7:0] rx_eth_payload_axis_tdata; +wire rx_eth_payload_axis_tvalid; +wire rx_eth_payload_axis_tready; +wire rx_eth_payload_axis_tlast; +wire rx_eth_payload_axis_tuser; + +wire tx_eth_hdr_ready; +wire tx_eth_hdr_valid; +wire [47:0] tx_eth_dest_mac; +wire [47:0] tx_eth_src_mac; +wire [15:0] tx_eth_type; +wire [7:0] tx_eth_payload_axis_tdata; +wire tx_eth_payload_axis_tvalid; +wire tx_eth_payload_axis_tready; +wire tx_eth_payload_axis_tlast; +wire tx_eth_payload_axis_tuser; + +// IP frame connections +wire rx_ip_hdr_valid; +wire rx_ip_hdr_ready; +wire [47:0] rx_ip_eth_dest_mac; +wire [47:0] rx_ip_eth_src_mac; +wire [15:0] rx_ip_eth_type; +wire [3:0] rx_ip_version; +wire [3:0] rx_ip_ihl; +wire [5:0] rx_ip_dscp; +wire [1:0] rx_ip_ecn; +wire [15:0] rx_ip_length; +wire [15:0] rx_ip_identification; +wire [2:0] rx_ip_flags; +wire [12:0] rx_ip_fragment_offset; +wire [7:0] rx_ip_ttl; +wire [7:0] rx_ip_protocol; +wire [15:0] rx_ip_header_checksum; +wire [31:0] rx_ip_source_ip; +wire [31:0] rx_ip_dest_ip; +wire [7:0] rx_ip_payload_axis_tdata; +wire rx_ip_payload_axis_tvalid; +wire rx_ip_payload_axis_tready; +wire rx_ip_payload_axis_tlast; +wire rx_ip_payload_axis_tuser; + +wire tx_ip_hdr_valid; +wire tx_ip_hdr_ready; +wire [5:0] tx_ip_dscp; +wire [1:0] tx_ip_ecn; +wire [15:0] tx_ip_length; +wire [7:0] tx_ip_ttl; +wire [7:0] tx_ip_protocol; +wire [31:0] tx_ip_source_ip; +wire [31:0] tx_ip_dest_ip; +wire [7:0] tx_ip_payload_axis_tdata; +wire tx_ip_payload_axis_tvalid; +wire tx_ip_payload_axis_tready; +wire tx_ip_payload_axis_tlast; +wire tx_ip_payload_axis_tuser; + +// UDP frame connections +wire rx_udp_hdr_valid; +wire rx_udp_hdr_ready; +wire [47:0] rx_udp_eth_dest_mac; +wire [47:0] rx_udp_eth_src_mac; +wire [15:0] rx_udp_eth_type; +wire [3:0] rx_udp_ip_version; +wire [3:0] rx_udp_ip_ihl; +wire [5:0] rx_udp_ip_dscp; +wire [1:0] rx_udp_ip_ecn; +wire [15:0] rx_udp_ip_length; +wire [15:0] rx_udp_ip_identification; +wire [2:0] rx_udp_ip_flags; +wire [12:0] rx_udp_ip_fragment_offset; +wire [7:0] rx_udp_ip_ttl; +wire [7:0] rx_udp_ip_protocol; +wire [15:0] rx_udp_ip_header_checksum; +wire [31:0] rx_udp_ip_source_ip; +wire [31:0] rx_udp_ip_dest_ip; +wire [15:0] rx_udp_source_port; +wire [15:0] rx_udp_dest_port; +wire [15:0] rx_udp_length; +wire [15:0] rx_udp_checksum; +wire [7:0] rx_udp_payload_axis_tdata; +wire rx_udp_payload_axis_tvalid; +wire rx_udp_payload_axis_tready; +wire rx_udp_payload_axis_tlast; +wire rx_udp_payload_axis_tuser; + +wire tx_udp_hdr_valid; +wire tx_udp_hdr_ready; +wire [5:0] tx_udp_ip_dscp; +wire [1:0] tx_udp_ip_ecn; +wire [7:0] tx_udp_ip_ttl; +wire [31:0] tx_udp_ip_source_ip; +wire [31:0] tx_udp_ip_dest_ip; +wire [15:0] tx_udp_source_port; +wire [15:0] tx_udp_dest_port; +wire [15:0] tx_udp_length; +wire [15:0] tx_udp_checksum; +wire [7:0] tx_udp_payload_axis_tdata; +wire tx_udp_payload_axis_tvalid; +wire tx_udp_payload_axis_tready; +wire tx_udp_payload_axis_tlast; +wire tx_udp_payload_axis_tuser; + +wire [7:0] rx_fifo_udp_payload_axis_tdata; +wire rx_fifo_udp_payload_axis_tvalid; +wire rx_fifo_udp_payload_axis_tready; +wire rx_fifo_udp_payload_axis_tlast; +wire rx_fifo_udp_payload_axis_tuser; + +wire [7:0] tx_fifo_udp_payload_axis_tdata; +wire tx_fifo_udp_payload_axis_tvalid; +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; +assign rx_ip_payload_axis_tready = 1; + +assign tx_ip_hdr_valid = 0; +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_source_ip = 0; +assign tx_ip_dest_ip = 0; +assign tx_ip_payload_axis_tdata = 0; +assign tx_ip_payload_axis_tvalid = 0; +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 no_match = !match_cond; + +reg match_cond_reg = 0; +reg no_match_reg = 0; + +always @(posedge clk) begin + if (rst) begin + match_cond_reg <= 0; + no_match_reg <= 0; + end else begin + if (rx_udp_payload_axis_tvalid) begin + if ((!match_cond_reg && !no_match_reg) || + (rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin + match_cond_reg <= match_cond; + no_match_reg <= no_match; + end + end else begin + match_cond_reg <= 0; + no_match_reg <= 0; + end + end +end + +assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond; +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_length = rx_udp_length; +assign tx_udp_checksum = 0; + +assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata; +assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid; +assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready; +assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast; +assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser; + +assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata; +assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg; +assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg; +assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast; +assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser; + +// Place first payload byte onto LEDs +reg valid_last = 0; +reg [7:0] led_reg = 0; + +always @(posedge clk) begin + if (rst) begin + led_reg <= 0; + end else begin + if (tx_udp_payload_axis_tvalid) begin + if (!valid_last) begin + led_reg <= tx_udp_payload_axis_tdata; + valid_last <= 1'b1; + end + if (tx_udp_payload_axis_tlast) begin + valid_last <= 1'b0; + end + end + end +end + +//assign led = sw; +assign led = led_reg; +assign phy_reset_n = !rst; + +assign uart_txd = 0; +assign uart_rts = 0; + +eth_mac_1g_rgmii_fifo #( + .TARGET(TARGET), + .IODDR_STYLE("IODDR"), + .CLOCK_INPUT_STYLE("BUFR"), + .USE_CLK90("TRUE"), + .ENABLE_PADDING(1), + .MIN_FRAME_LENGTH(64), + .TX_FIFO_DEPTH(4096), + .TX_FRAME_FIFO(1), + .RX_FIFO_DEPTH(4096), + .RX_FRAME_FIFO(1) +) +eth_mac_inst ( + .gtx_clk(clk), + .gtx_clk90(clk90), + .gtx_rst(rst), + .logic_clk(clk), + .logic_rst(rst), + + .tx_axis_tdata(tx_axis_tdata), + .tx_axis_tvalid(tx_axis_tvalid), + .tx_axis_tready(tx_axis_tready), + .tx_axis_tlast(tx_axis_tlast), + .tx_axis_tuser(tx_axis_tuser), + + .rx_axis_tdata(rx_axis_tdata), + .rx_axis_tvalid(rx_axis_tvalid), + .rx_axis_tready(rx_axis_tready), + .rx_axis_tlast(rx_axis_tlast), + .rx_axis_tuser(rx_axis_tuser), + + .rgmii_rx_clk(phy_rx_clk), + .rgmii_rxd(phy_rxd), + .rgmii_rx_ctl(phy_rx_ctl), + .rgmii_tx_clk(phy_tx_clk), + .rgmii_txd(phy_txd), + .rgmii_tx_ctl(phy_tx_ctl), + + .tx_fifo_overflow(), + .tx_fifo_bad_frame(), + .tx_fifo_good_frame(), + .rx_error_bad_frame(), + .rx_error_bad_fcs(), + .rx_fifo_overflow(), + .rx_fifo_bad_frame(), + .rx_fifo_good_frame(), + .speed(), + + .ifg_delay(12) +); + +eth_axis_rx +eth_axis_rx_inst ( + .clk(clk), + .rst(rst), + // AXI input + .s_axis_tdata(rx_axis_tdata), + .s_axis_tvalid(rx_axis_tvalid), + .s_axis_tready(rx_axis_tready), + .s_axis_tlast(rx_axis_tlast), + .s_axis_tuser(rx_axis_tuser), + // Ethernet frame output + .m_eth_hdr_valid(rx_eth_hdr_valid), + .m_eth_hdr_ready(rx_eth_hdr_ready), + .m_eth_dest_mac(rx_eth_dest_mac), + .m_eth_src_mac(rx_eth_src_mac), + .m_eth_type(rx_eth_type), + .m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata), + .m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid), + .m_eth_payload_axis_tready(rx_eth_payload_axis_tready), + .m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast), + .m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser), + // Status signals + .busy(), + .error_header_early_termination() +); + +eth_axis_tx +eth_axis_tx_inst ( + .clk(clk), + .rst(rst), + // Ethernet frame input + .s_eth_hdr_valid(tx_eth_hdr_valid), + .s_eth_hdr_ready(tx_eth_hdr_ready), + .s_eth_dest_mac(tx_eth_dest_mac), + .s_eth_src_mac(tx_eth_src_mac), + .s_eth_type(tx_eth_type), + .s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata), + .s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid), + .s_eth_payload_axis_tready(tx_eth_payload_axis_tready), + .s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast), + .s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser), + // AXI output + .m_axis_tdata(tx_axis_tdata), + .m_axis_tvalid(tx_axis_tvalid), + .m_axis_tready(tx_axis_tready), + .m_axis_tlast(tx_axis_tlast), + .m_axis_tuser(tx_axis_tuser), + // Status signals + .busy() +); + +udp_complete +udp_complete_inst ( + .clk(clk), + .rst(rst), + // Ethernet frame input + .s_eth_hdr_valid(rx_eth_hdr_valid), + .s_eth_hdr_ready(rx_eth_hdr_ready), + .s_eth_dest_mac(rx_eth_dest_mac), + .s_eth_src_mac(rx_eth_src_mac), + .s_eth_type(rx_eth_type), + .s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata), + .s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid), + .s_eth_payload_axis_tready(rx_eth_payload_axis_tready), + .s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast), + .s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser), + // Ethernet frame output + .m_eth_hdr_valid(tx_eth_hdr_valid), + .m_eth_hdr_ready(tx_eth_hdr_ready), + .m_eth_dest_mac(tx_eth_dest_mac), + .m_eth_src_mac(tx_eth_src_mac), + .m_eth_type(tx_eth_type), + .m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata), + .m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid), + .m_eth_payload_axis_tready(tx_eth_payload_axis_tready), + .m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast), + .m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser), + // IP frame input + .s_ip_hdr_valid(tx_ip_hdr_valid), + .s_ip_hdr_ready(tx_ip_hdr_ready), + .s_ip_dscp(tx_ip_dscp), + .s_ip_ecn(tx_ip_ecn), + .s_ip_length(tx_ip_length), + .s_ip_ttl(tx_ip_ttl), + .s_ip_protocol(tx_ip_protocol), + .s_ip_source_ip(tx_ip_source_ip), + .s_ip_dest_ip(tx_ip_dest_ip), + .s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata), + .s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid), + .s_ip_payload_axis_tready(tx_ip_payload_axis_tready), + .s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast), + .s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser), + // IP frame output + .m_ip_hdr_valid(rx_ip_hdr_valid), + .m_ip_hdr_ready(rx_ip_hdr_ready), + .m_ip_eth_dest_mac(rx_ip_eth_dest_mac), + .m_ip_eth_src_mac(rx_ip_eth_src_mac), + .m_ip_eth_type(rx_ip_eth_type), + .m_ip_version(rx_ip_version), + .m_ip_ihl(rx_ip_ihl), + .m_ip_dscp(rx_ip_dscp), + .m_ip_ecn(rx_ip_ecn), + .m_ip_length(rx_ip_length), + .m_ip_identification(rx_ip_identification), + .m_ip_flags(rx_ip_flags), + .m_ip_fragment_offset(rx_ip_fragment_offset), + .m_ip_ttl(rx_ip_ttl), + .m_ip_protocol(rx_ip_protocol), + .m_ip_header_checksum(rx_ip_header_checksum), + .m_ip_source_ip(rx_ip_source_ip), + .m_ip_dest_ip(rx_ip_dest_ip), + .m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata), + .m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid), + .m_ip_payload_axis_tready(rx_ip_payload_axis_tready), + .m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast), + .m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser), + // UDP frame input + .s_udp_hdr_valid(tx_udp_hdr_valid), + .s_udp_hdr_ready(tx_udp_hdr_ready), + .s_udp_ip_dscp(tx_udp_ip_dscp), + .s_udp_ip_ecn(tx_udp_ip_ecn), + .s_udp_ip_ttl(tx_udp_ip_ttl), + .s_udp_ip_source_ip(tx_udp_ip_source_ip), + .s_udp_ip_dest_ip(tx_udp_ip_dest_ip), + .s_udp_source_port(tx_udp_source_port), + .s_udp_dest_port(tx_udp_dest_port), + .s_udp_length(tx_udp_length), + .s_udp_checksum(tx_udp_checksum), + .s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata), + .s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid), + .s_udp_payload_axis_tready(tx_udp_payload_axis_tready), + .s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast), + .s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser), + // UDP frame output + .m_udp_hdr_valid(rx_udp_hdr_valid), + .m_udp_hdr_ready(rx_udp_hdr_ready), + .m_udp_eth_dest_mac(rx_udp_eth_dest_mac), + .m_udp_eth_src_mac(rx_udp_eth_src_mac), + .m_udp_eth_type(rx_udp_eth_type), + .m_udp_ip_version(rx_udp_ip_version), + .m_udp_ip_ihl(rx_udp_ip_ihl), + .m_udp_ip_dscp(rx_udp_ip_dscp), + .m_udp_ip_ecn(rx_udp_ip_ecn), + .m_udp_ip_length(rx_udp_ip_length), + .m_udp_ip_identification(rx_udp_ip_identification), + .m_udp_ip_flags(rx_udp_ip_flags), + .m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset), + .m_udp_ip_ttl(rx_udp_ip_ttl), + .m_udp_ip_protocol(rx_udp_ip_protocol), + .m_udp_ip_header_checksum(rx_udp_ip_header_checksum), + .m_udp_ip_source_ip(rx_udp_ip_source_ip), + .m_udp_ip_dest_ip(rx_udp_ip_dest_ip), + .m_udp_source_port(rx_udp_source_port), + .m_udp_dest_port(rx_udp_dest_port), + .m_udp_length(rx_udp_length), + .m_udp_checksum(rx_udp_checksum), + .m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata), + .m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid), + .m_udp_payload_axis_tready(rx_udp_payload_axis_tready), + .m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast), + .m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser), + // Status signals + .ip_rx_busy(), + .ip_tx_busy(), + .udp_rx_busy(), + .udp_tx_busy(), + .ip_rx_error_header_early_termination(), + .ip_rx_error_payload_early_termination(), + .ip_rx_error_invalid_header(), + .ip_rx_error_invalid_checksum(), + .ip_tx_error_payload_early_termination(), + .ip_tx_error_arp_failed(), + .udp_rx_error_header_early_termination(), + .udp_rx_error_payload_early_termination(), + .udp_tx_error_payload_early_termination(), + // Configuration + .local_mac(local_mac), + .local_ip(local_ip), + .gateway_ip(gateway_ip), + .subnet_mask(subnet_mask), + .clear_arp_cache(0) +); + +axis_fifo #( + .DEPTH(8192), + .DATA_WIDTH(8), + .KEEP_ENABLE(0), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(1), + .USER_WIDTH(1), + .FRAME_FIFO(0) +) +udp_payload_fifo ( + .clk(clk), + .rst(rst), + + // AXI input + .s_axis_tdata(rx_fifo_udp_payload_axis_tdata), + .s_axis_tkeep(0), + .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_tuser(rx_fifo_udp_payload_axis_tuser), + + // AXI output + .m_axis_tdata(tx_fifo_udp_payload_axis_tdata), + .m_axis_tkeep(), + .m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid), + .m_axis_tready(tx_fifo_udp_payload_axis_tready), + .m_axis_tlast(tx_fifo_udp_payload_axis_tlast), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(tx_fifo_udp_payload_axis_tuser), + + // Status + .status_overflow(), + .status_bad_frame(), + .status_good_frame() +); + +endmodule diff --git a/example/KC705/fpga_rgmii/rtl/sync_signal.v b/example/KC705/fpga_rgmii/rtl/sync_signal.v new file mode 100644 index 000000000..b2a8ce3de --- /dev/null +++ b/example/KC705/fpga_rgmii/rtl/sync_signal.v @@ -0,0 +1,58 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`timescale 1 ns / 1 ps + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule diff --git a/example/KC705/fpga_rgmii/tb/fpga_core/Makefile b/example/KC705/fpga_rgmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..c6328a449 --- /dev/null +++ b/example/KC705/fpga_rgmii/tb/fpga_core/Makefile @@ -0,0 +1,100 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_rgmii.v +VERILOG_SOURCES += ../../lib/eth/rtl/iddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/oddr.v +VERILOG_SOURCES += ../../lib/eth/rtl/ssio_ddr_in.v +VERILOG_SOURCES += ../../lib/eth/rtl/rgmii_phy_if.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/example/KC705/fpga_rgmii/tb/fpga_core/test_fpga_core.py b/example/KC705/fpga_rgmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..5302b99f2 --- /dev/null +++ b/example/KC705/fpga_rgmii/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,229 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, Timer + +from cocotbext.eth import GmiiFrame, RgmiiPhy + + +class TB: + def __init__(self, dut, speed=1000e6): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + self.rgmii_phy = RgmiiPhy(dut.phy_txd, dut.phy_tx_ctl, dut.phy_tx_clk, + dut.phy_rxd, dut.phy_rx_ctl, dut.phy_rx_clk, speed=speed) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(1) + dut.uart_rts.setimmediatevalue(1) + + dut.clk.setimmediatevalue(0) + dut.clk90.setimmediatevalue(0) + + cocotb.fork(self._run_clk()) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + + async def _run_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.clk <= 1 + await t + self.dut.clk90 <= 1 + await t + self.dut.clk <= 0 + await t + self.dut.clk90 <= 0 + await t + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.rgmii_phy.rx.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.rgmii_phy.rx.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.rgmii_phy.tx.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_rgmii.v"), + os.path.join(eth_rtl_dir, "iddr.v"), + os.path.join(eth_rtl_dir, "oddr.v"), + os.path.join(eth_rtl_dir, "ssio_ddr_in.v"), + os.path.join(eth_rtl_dir, "rgmii_phy_if.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From a91e2b7e17282fc73c0923bbbe6c55aafdb941e5 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 30 Dec 2020 17:15:34 -0800 Subject: [PATCH 35/37] Add KC705 SGMII example design --- example/KC705/fpga_sgmii/Makefile | 25 + example/KC705/fpga_sgmii/README.md | 28 + example/KC705/fpga_sgmii/common/vivado.mk | 123 ++++ example/KC705/fpga_sgmii/fpga.xdc | 85 +++ example/KC705/fpga_sgmii/fpga/Makefile | 62 ++ .../fpga_sgmii/ip/gig_ethernet_pcs_pma_0.tcl | 9 + example/KC705/fpga_sgmii/lib/eth | 1 + .../KC705/fpga_sgmii/rtl/debounce_switch.v | 89 +++ example/KC705/fpga_sgmii/rtl/fpga.v | 365 +++++++++++ example/KC705/fpga_sgmii/rtl/fpga_core.v | 584 ++++++++++++++++++ example/KC705/fpga_sgmii/rtl/sync_signal.v | 58 ++ .../KC705/fpga_sgmii/tb/fpga_core/Makefile | 95 +++ .../fpga_sgmii/tb/fpga_core/test_fpga_core.py | 218 +++++++ 13 files changed, 1742 insertions(+) create mode 100644 example/KC705/fpga_sgmii/Makefile create mode 100644 example/KC705/fpga_sgmii/README.md create mode 100644 example/KC705/fpga_sgmii/common/vivado.mk create mode 100644 example/KC705/fpga_sgmii/fpga.xdc create mode 100644 example/KC705/fpga_sgmii/fpga/Makefile create mode 100644 example/KC705/fpga_sgmii/ip/gig_ethernet_pcs_pma_0.tcl create mode 120000 example/KC705/fpga_sgmii/lib/eth create mode 100644 example/KC705/fpga_sgmii/rtl/debounce_switch.v create mode 100644 example/KC705/fpga_sgmii/rtl/fpga.v create mode 100644 example/KC705/fpga_sgmii/rtl/fpga_core.v create mode 100644 example/KC705/fpga_sgmii/rtl/sync_signal.v create mode 100644 example/KC705/fpga_sgmii/tb/fpga_core/Makefile create mode 100644 example/KC705/fpga_sgmii/tb/fpga_core/test_fpga_core.py diff --git a/example/KC705/fpga_sgmii/Makefile b/example/KC705/fpga_sgmii/Makefile new file mode 100644 index 000000000..f504bd06f --- /dev/null +++ b/example/KC705/fpga_sgmii/Makefile @@ -0,0 +1,25 @@ +# Targets +TARGETS:= + +# Subdirectories +SUBDIRS = fpga +SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS)) + +# Rules +.PHONY: all +all: $(SUBDIRS) $(TARGETS) + +.PHONY: $(SUBDIRS) +$(SUBDIRS): + cd $@ && $(MAKE) + +.PHONY: $(SUBDIRS_CLEAN) +$(SUBDIRS_CLEAN): + cd $(@:.clean=) && $(MAKE) clean + +.PHONY: clean +clean: $(SUBDIRS_CLEAN) + -rm -rf $(TARGETS) + +program: + #djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit diff --git a/example/KC705/fpga_sgmii/README.md b/example/KC705/fpga_sgmii/README.md new file mode 100644 index 000000000..25cf7da65 --- /dev/null +++ b/example/KC705/fpga_sgmii/README.md @@ -0,0 +1,28 @@ +# Verilog Ethernet KC705 Example Design + +## Introduction + +This example design targets the Xilinx KC705 FPGA board. + +The design by default listens to UDP port 1234 at IP address 192.168.1.128 and +will echo back any packets received. The design will also respond correctly +to ARP requests. + +Configure the PHY for SGMII by placing J29 and J30 across pins 2 and 3 and +opening J64. + +FPGA: XC7K325T-2FFG900C +PHY: Marvell 88E1111 + +## How to build + +Run make to build. Ensure that the Xilinx Vivado toolchain components are +in PATH. + +## How to test + +Run make program to program the KC705 board with Vivado. Then run netcat -u +192.168.1.128 1234 to open a UDP connection to port 1234. Any text entered +into netcat will be echoed back after pressing enter. + + diff --git a/example/KC705/fpga_sgmii/common/vivado.mk b/example/KC705/fpga_sgmii/common/vivado.mk new file mode 100644 index 000000000..ee83637e0 --- /dev/null +++ b/example/KC705/fpga_sgmii/common/vivado.mk @@ -0,0 +1,123 @@ +################################################################### +# +# Xilinx Vivado FPGA Makefile +# +# Copyright (c) 2016 Alex Forencich +# +################################################################### +# +# Parameters: +# FPGA_TOP - Top module name +# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale) +# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e) +# SYN_FILES - space-separated list of source files +# INC_FILES - space-separated list of include files +# XDC_FILES - space-separated list of timing constraint files +# XCI_FILES - space-separated list of IP XCI files +# +# Example: +# +# FPGA_TOP = fpga +# FPGA_FAMILY = VirtexUltrascale +# FPGA_DEVICE = xcvu095-ffva2104-2-e +# SYN_FILES = rtl/fpga.v +# XDC_FILES = fpga.xdc +# XCI_FILES = ip/pcspma.xci +# include ../common/vivado.mk +# +################################################################### + +# phony targets +.PHONY: clean fpga + +# prevent make from deleting intermediate files and reports +.PRECIOUS: %.xpr %.bit %.mcs %.prm +.SECONDARY: + +CONFIG ?= config.mk +-include ../$(CONFIG) + +SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(IP_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).xpr + +tmpclean: + -rm -rf *.log *.jou *.cache *.hbs *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v + -rm -rf create_project.tcl run_synth.tcl run_impl.tcl generate_bit.tcl + +clean: tmpclean + -rm -rf *.bit program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +distclean: clean + -rm -rf rev + +################################################################### +# Target implementations +################################################################### + +# Vivado project file +%.xpr: Makefile $(XCI_FILES_REL) $(IP_TCL_FILES_REL) + rm -rf defines.v + touch defines.v + for x in $(DEFS); do echo '`define' $$x >> defines.v; done + echo "create_project -force -part $(FPGA_PART) $*" > create_project.tcl + echo "add_files -fileset sources_1 defines.v" >> create_project.tcl + for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done + for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done + for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done + for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> create_project.tcl; done + echo "exit" >> create_project.tcl + vivado -nojournal -nolog -mode batch -source create_project.tcl + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) + echo "open_project $*.xpr" > run_synth.tcl + echo "reset_run synth_1" >> run_synth.tcl + echo "launch_runs synth_1" >> run_synth.tcl + echo "wait_on_run synth_1" >> run_synth.tcl + echo "exit" >> run_synth.tcl + vivado -nojournal -nolog -mode batch -source run_synth.tcl + +# implementation run +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_project $*.xpr" > run_impl.tcl + echo "reset_run impl_1" >> run_impl.tcl + echo "launch_runs impl_1" >> run_impl.tcl + echo "wait_on_run impl_1" >> run_impl.tcl + echo "exit" >> run_impl.tcl + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + echo "exit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/example/KC705/fpga_sgmii/fpga.xdc b/example/KC705/fpga_sgmii/fpga.xdc new file mode 100644 index 000000000..cede2589d --- /dev/null +++ b/example/KC705/fpga_sgmii/fpga.xdc @@ -0,0 +1,85 @@ +# XDC constraints for the Xilinx KC705 board +# part: xc7k325tffg900-2 + +# General configuration +set_property CFGBVS VCCO [current_design] +set_property CONFIG_VOLTAGE 2.5 [current_design] +set_property BITSTREAM.GENERAL.COMPRESS true [current_design] + +# System clocks +# 200 MHz +set_property -dict {LOC AD12 IOSTANDARD LVDS} [get_ports clk_200mhz_p] +set_property -dict {LOC AD11 IOSTANDARD LVDS} [get_ports clk_200mhz_n] +create_clock -period 5.000 -name clk_200mhz [get_ports clk_200mhz_p] + +# LEDs +set_property -dict {LOC AB8 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[0]}] +set_property -dict {LOC AA8 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[1]}] +set_property -dict {LOC AC9 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[2]}] +set_property -dict {LOC AB9 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[3]}] +set_property -dict {LOC AE26 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[4]}] +set_property -dict {LOC G19 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[5]}] +set_property -dict {LOC E18 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[6]}] +set_property -dict {LOC F16 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[7]}] + +# Reset button +set_property -dict {LOC AB7 IOSTANDARD LVCMOS15} [get_ports reset] + +# Push buttons +set_property -dict {LOC AA12 IOSTANDARD LVCMOS15} [get_ports btnu] +set_property -dict {LOC AC6 IOSTANDARD LVCMOS15} [get_ports btnl] +set_property -dict {LOC AB12 IOSTANDARD LVCMOS15} [get_ports btnd] +set_property -dict {LOC AG5 IOSTANDARD LVCMOS15} [get_ports btnr] +set_property -dict {LOC G12 IOSTANDARD LVCMOS25} [get_ports btnc] + +# Toggle switches +set_property -dict {LOC Y29 IOSTANDARD LVCMOS25} [get_ports {sw[0]}] +set_property -dict {LOC W29 IOSTANDARD LVCMOS25} [get_ports {sw[1]}] +set_property -dict {LOC AA28 IOSTANDARD LVCMOS25} [get_ports {sw[2]}] +set_property -dict {LOC Y28 IOSTANDARD LVCMOS25} [get_ports {sw[3]}] + +# UART +set_property -dict {LOC K24 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_txd] +set_property -dict {LOC M19 IOSTANDARD LVCMOS25} [get_ports uart_rxd] +set_property -dict {LOC L27 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_rts] +set_property -dict {LOC K23 IOSTANDARD LVCMOS25} [get_ports uart_cts] + +# Gigabit Ethernet GMII PHY +#set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] ;# from U37.C1 RXCLK +#set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] ;# from U37.B2 RXD0 +#set_property -dict {LOC U25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[1]}] ;# from U37.D3 RXD1 +#set_property -dict {LOC T25 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[2]}] ;# from U37.C3 RXD2 +#set_property -dict {LOC U28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[3]}] ;# from U37.B3 RXD3 +#set_property -dict {LOC R19 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[4]}] ;# from U37.C4 RXD4 +#set_property -dict {LOC T27 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[5]}] ;# from U37.A1 RXD5 +#set_property -dict {LOC T26 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[6]}] ;# from U37.A2 RXD6 +#set_property -dict {LOC T28 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[7]}] ;# from U37.C5 RXD7 +#set_property -dict {LOC R28 IOSTANDARD LVCMOS25} [get_ports phy_rx_dv] ;# from U37.B1 RXCTL_RXDV +#set_property -dict {LOC V26 IOSTANDARD LVCMOS25} [get_ports phy_rx_er] ;# from U37.D4 RXER +#set_property -dict {LOC K30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_gtx_clk] ;# from U37.E2 TXC_GTXCLK +#set_property -dict {LOC M28 IOSTANDARD LVCMOS25} [get_ports phy_tx_clk] ;# from U37.D1 TXCLK +#set_property -dict {LOC N27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[0]}] ;# from U37.F1 TXD0 +#set_property -dict {LOC N25 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[1]}] ;# from U37.G2 TXD1 +#set_property -dict {LOC M29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[2]}] ;# from U37.G3 TXD2 +#set_property -dict {LOC L28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[3]}] ;# from U37.H1 TXD3 +#set_property -dict {LOC J26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[4]}] ;# from U37.H2 TXD4 +#set_property -dict {LOC K26 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[5]}] ;# from U37.H3 TXD5 +#set_property -dict {LOC L30 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[6]}] ;# from U37.J1 TXD6 +#set_property -dict {LOC J28 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports {phy_txd[7]}] ;# from U37.J2 TXD7 +#set_property -dict {LOC M27 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_en] ;# from U37.E1 TXCTL_TXEN +#set_property -dict {LOC N29 IOSTANDARD LVCMOS25 SLEW FAST DRIVE 16} [get_ports phy_tx_er] ;# from U37.F2 TXER +set_property -dict {LOC H6 } [get_ports phy_sgmii_rx_p] ;# MGTXRXP1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X0Y2 from U37.A7 SOUT_P +#set_property -dict {LOC H5 } [get_ports phy_sgmii_rx_n] ;# MGTXRXN1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X0Y2 from U37.A8 SOUT_N +set_property -dict {LOC J4 } [get_ports phy_sgmii_tx_p] ;# MGTXTXP1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X0Y2 from U37.A3 SIN_P +#set_property -dict {LOC J3 } [get_ports phy_sgmii_tx_n] ;# MGTXTXN1_117 GTXE2_CHANNEL_X0Y9 / GTXE2_COMMON_X0Y2 from U37.A4 SIN_N +set_property -dict {LOC G8 } [get_ports phy_sgmii_clk_p] ;# MGTREFCLK0P_117 from U2.7 +#set_property -dict {LOC G7 } [get_ports phy_sgmii_clk_n] ;# MGTREFCLK0N_117 from U2.6 +set_property -dict {LOC L20 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_reset_n] ;# from U37.K3 RESET_B +set_property -dict {LOC N30 IOSTANDARD LVCMOS25} [get_ports phy_int_n] ;# from U37.L1 INT_B +#set_property -dict {LOC J21 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdio] ;# from U37.M1 MDIO +#set_property -dict {LOC R23 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports phy_mdc] ;# from U37.L3 MDC + +#create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] +#create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] +create_clock -period 8.000 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] + diff --git a/example/KC705/fpga_sgmii/fpga/Makefile b/example/KC705/fpga_sgmii/fpga/Makefile new file mode 100644 index 000000000..75ae3902d --- /dev/null +++ b/example/KC705/fpga_sgmii/fpga/Makefile @@ -0,0 +1,62 @@ + +# FPGA settings +FPGA_PART = xc7k325tffg900-2 +FPGA_TOP = fpga +FPGA_ARCH = kintex7 + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += lib/eth/rtl/eth_mac_1g_fifo.v +SYN_FILES += lib/eth/rtl/eth_mac_1g.v +SYN_FILES += lib/eth/rtl/axis_gmii_rx.v +SYN_FILES += lib/eth/rtl/axis_gmii_tx.v +SYN_FILES += lib/eth/rtl/lfsr.v +SYN_FILES += lib/eth/rtl/eth_axis_rx.v +SYN_FILES += lib/eth/rtl/eth_axis_tx.v +SYN_FILES += lib/eth/rtl/udp_complete.v +SYN_FILES += lib/eth/rtl/udp_checksum_gen.v +SYN_FILES += lib/eth/rtl/udp.v +SYN_FILES += lib/eth/rtl/udp_ip_rx.v +SYN_FILES += lib/eth/rtl/udp_ip_tx.v +SYN_FILES += lib/eth/rtl/ip_complete.v +SYN_FILES += lib/eth/rtl/ip.v +SYN_FILES += lib/eth/rtl/ip_eth_rx.v +SYN_FILES += lib/eth/rtl/ip_eth_tx.v +SYN_FILES += lib/eth/rtl/ip_arb_mux.v +SYN_FILES += lib/eth/rtl/arp.v +SYN_FILES += lib/eth/rtl/arp_cache.v +SYN_FILES += lib/eth/rtl/arp_eth_rx.v +SYN_FILES += lib/eth/rtl/arp_eth_tx.v +SYN_FILES += lib/eth/rtl/eth_arb_mux.v +SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v +SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v +SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v +SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v +SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v +SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v + +# XDC files +XDC_FILES = fpga.xdc +XDC_FILES += lib/eth/syn/eth_mac_fifo.tcl +XDC_FILES += lib/eth/lib/axis/syn/axis_async_fifo.tcl +XDC_FILES += lib/eth/lib/axis/syn/sync_reset.tcl + +# IP +IP_TCL_FILES = ip/gig_ethernet_pcs_pma_0.tcl + +include ../common/vivado.mk + +program: $(FPGA_TOP).bit + echo "open_hw" > program.tcl + echo "connect_hw_server" >> program.tcl + echo "open_hw_target" >> program.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl + echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl + echo "program_hw_devices [current_hw_device]" >> program.tcl + echo "exit" >> program.tcl + vivado -nojournal -nolog -mode batch -source program.tcl + diff --git a/example/KC705/fpga_sgmii/ip/gig_ethernet_pcs_pma_0.tcl b/example/KC705/fpga_sgmii/ip/gig_ethernet_pcs_pma_0.tcl new file mode 100644 index 000000000..70810f3b1 --- /dev/null +++ b/example/KC705/fpga_sgmii/ip/gig_ethernet_pcs_pma_0.tcl @@ -0,0 +1,9 @@ + +create_ip -name gig_ethernet_pcs_pma -vendor xilinx.com -library ip -module_name gig_ethernet_pcs_pma_0 + +set_property -dict [list \ + CONFIG.Standard {SGMII} \ + CONFIG.Physical_Interface {Transceiver} \ + CONFIG.Management_Interface {false} \ + CONFIG.SupportLevel {Include_Shared_Logic_in_Core} \ +] [get_ips gig_ethernet_pcs_pma_0] diff --git a/example/KC705/fpga_sgmii/lib/eth b/example/KC705/fpga_sgmii/lib/eth new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/example/KC705/fpga_sgmii/lib/eth @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/example/KC705/fpga_sgmii/rtl/debounce_switch.v b/example/KC705/fpga_sgmii/rtl/debounce_switch.v new file mode 100644 index 000000000..bb631cc35 --- /dev/null +++ b/example/KC705/fpga_sgmii/rtl/debounce_switch.v @@ -0,0 +1,89 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`timescale 1 ns / 1 ps + +/* + * Synchronizes switch and button inputs with a slow sampled shift register + */ +module debounce_switch #( + parameter WIDTH=1, // width of the input and output signals + parameter N=3, // length of shift register + parameter RATE=125000 // clock division factor +)( + input wire clk, + input wire rst, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [23:0] cnt_reg = 24'd0; + +reg [N-1:0] debounce_reg[WIDTH-1:0]; + +reg [WIDTH-1:0] state; + +/* + * The synchronized output is the state register + */ +assign out = state; + +integer k; + +always @(posedge clk or posedge rst) begin + if (rst) begin + cnt_reg <= 0; + state <= 0; + + for (k = 0; k < WIDTH; k = k + 1) begin + debounce_reg[k] <= 0; + end + end else begin + if (cnt_reg < RATE) begin + cnt_reg <= cnt_reg + 24'd1; + end else begin + cnt_reg <= 24'd0; + end + + if (cnt_reg == 24'd0) begin + for (k = 0; k < WIDTH; k = k + 1) begin + debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]}; + end + end + + for (k = 0; k < WIDTH; k = k + 1) begin + if (|debounce_reg[k] == 0) begin + state[k] <= 0; + end else if (&debounce_reg[k] == 1) begin + state[k] <= 1; + end else begin + state[k] <= state[k]; + end + end + end +end + +endmodule diff --git a/example/KC705/fpga_sgmii/rtl/fpga.v b/example/KC705/fpga_sgmii/rtl/fpga.v new file mode 100644 index 000000000..82073ea14 --- /dev/null +++ b/example/KC705/fpga_sgmii/rtl/fpga.v @@ -0,0 +1,365 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * FPGA top-level module + */ +module fpga ( + /* + * Clock: 200MHz + * Reset: Push button, active high + */ + input wire clk_200mhz_p, + input wire clk_200mhz_n, + input wire reset, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [3:0] sw, + output wire [7:0] led, + + /* + * Ethernet: 1000BASE-T SGMII + */ + input wire phy_sgmii_rx_p, + input wire phy_sgmii_rx_n, + output wire phy_sgmii_tx_p, + output wire phy_sgmii_tx_n, + input wire phy_sgmii_clk_p, + input wire phy_sgmii_clk_n, + output wire phy_reset_n, + input wire phy_int_n, + + /* + * UART: 500000 bps, 8N1 + */ + input wire uart_rxd, + output wire uart_txd, + output wire uart_rts, + input wire uart_cts +); + +// Clock and reset + +wire clk_200mhz_ibufg; + +// Internal 125 MHz clock +wire clk_mmcm_out; +wire clk_int; +wire rst_int; + +wire mmcm_rst = reset; +wire mmcm_locked; +wire mmcm_clkfb; + +IBUFGDS +clk_200mhz_ibufgds_inst( + .I(clk_200mhz_p), + .IB(clk_200mhz_n), + .O(clk_200mhz_ibufg) +); + +// MMCM instance +// 200 MHz in, 125 MHz out +// PFD range: 10 MHz to 500 MHz +// VCO range: 600 MHz to 1440 MHz +// M = 5, D = 1 sets Fvco = 1000 MHz (in range) +// Divide by 8 to get output frequency of 125 MHz +MMCME2_BASE #( + .BANDWIDTH("OPTIMIZED"), + .CLKOUT0_DIVIDE_F(8), + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT0_PHASE(0), + .CLKOUT1_DIVIDE(8), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT1_PHASE(0), + .CLKOUT2_DIVIDE(1), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT2_PHASE(0), + .CLKOUT3_DIVIDE(1), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT3_PHASE(0), + .CLKOUT4_DIVIDE(1), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT4_PHASE(0), + .CLKOUT5_DIVIDE(1), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT5_PHASE(0), + .CLKOUT6_DIVIDE(1), + .CLKOUT6_DUTY_CYCLE(0.5), + .CLKOUT6_PHASE(0), + .CLKFBOUT_MULT_F(5), + .CLKFBOUT_PHASE(0), + .DIVCLK_DIVIDE(1), + .REF_JITTER1(0.010), + .CLKIN1_PERIOD(5.0), + .STARTUP_WAIT("FALSE"), + .CLKOUT4_CASCADE("FALSE") +) +clk_mmcm_inst ( + .CLKIN1(clk_200mhz_ibufg), + .CLKFBIN(mmcm_clkfb), + .RST(mmcm_rst), + .PWRDWN(1'b0), + .CLKOUT0(clk_mmcm_out), + .CLKOUT0B(), + .CLKOUT1(), + .CLKOUT1B(), + .CLKOUT2(), + .CLKOUT2B(), + .CLKOUT3(), + .CLKOUT3B(), + .CLKOUT4(), + .CLKOUT5(), + .CLKOUT6(), + .CLKFBOUT(mmcm_clkfb), + .CLKFBOUTB(), + .LOCKED(mmcm_locked) +); + +BUFG +clk_bufg_inst ( + .I(clk_mmcm_out), + .O(clk_int) +); + +sync_reset #( + .N(4) +) +sync_reset_inst ( + .clk(clk_int), + .rst(~mmcm_locked), + .out(rst_int) +); + +// GPIO +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(9), + .N(4), + .RATE(125000) +) +debounce_switch_inst ( + .clk(clk_int), + .rst(rst_int), + .in({btnu, + btnl, + btnd, + btnr, + btnc, + sw}), + .out({btnu_int, + btnl_int, + btnd_int, + btnr_int, + btnc_int, + sw_int}) +); + +wire uart_rxd_int; +wire uart_cts_int; + +sync_signal #( + .WIDTH(2), + .N(2) +) +sync_signal_inst ( + .clk(clk_int), + .in({uart_rxd, uart_cts}), + .out({uart_rxd_int, uart_cts_int}) +); + +wire [7:0] led_int; + +// SGMII interface to PHY +wire phy_gmii_clk_int; +wire phy_gmii_rst_int; +wire phy_gmii_clk_en_int; +wire [7:0] phy_gmii_txd_int; +wire phy_gmii_tx_en_int; +wire phy_gmii_tx_er_int; +wire [7:0] phy_gmii_rxd_int; +wire phy_gmii_rx_dv_int; +wire phy_gmii_rx_er_int; + +wire phy_sgmii_userclk2; +wire phy_sgmii_resetdone; + +assign phy_gmii_clk_int = phy_sgmii_userclk2; + +sync_reset #( + .N(4) +) +sync_reset_pcspma_inst ( + .clk(phy_gmii_clk_int), + .rst(rst_int || !phy_sgmii_resetdone), + .out(phy_gmii_rst_int) +); + +wire [15:0] pcspma_status_vector; + +wire pcspma_status_link_status = pcspma_status_vector[0]; +wire pcspma_status_link_synchronization = pcspma_status_vector[1]; +wire pcspma_status_rudi_c = pcspma_status_vector[2]; +wire pcspma_status_rudi_i = pcspma_status_vector[3]; +wire pcspma_status_rudi_invalid = pcspma_status_vector[4]; +wire pcspma_status_rxdisperr = pcspma_status_vector[5]; +wire pcspma_status_rxnotintable = pcspma_status_vector[6]; +wire pcspma_status_phy_link_status = pcspma_status_vector[7]; +wire [1:0] pcspma_status_remote_fault_encdg = pcspma_status_vector[9:8]; +wire [1:0] pcspma_status_speed = pcspma_status_vector[11:10]; +wire pcspma_status_duplex = pcspma_status_vector[12]; +wire pcspma_status_remote_fault = pcspma_status_vector[13]; +wire [1:0] pcspma_status_pause = pcspma_status_vector[15:14]; + +wire [4:0] pcspma_config_vector; + +assign pcspma_config_vector[4] = 1'b1; // autonegotiation enable +assign pcspma_config_vector[3] = 1'b0; // isolate +assign pcspma_config_vector[2] = 1'b0; // power down +assign pcspma_config_vector[1] = 1'b0; // loopback enable +assign pcspma_config_vector[0] = 1'b0; // unidirectional enable + +wire [15:0] pcspma_an_config_vector; + +assign pcspma_an_config_vector[15] = 1'b1; // SGMII link status +assign pcspma_an_config_vector[14] = 1'b1; // SGMII Acknowledge +assign pcspma_an_config_vector[13:12] = 2'b01; // full duplex +assign pcspma_an_config_vector[11:10] = 2'b10; // SGMII speed +assign pcspma_an_config_vector[9] = 1'b0; // reserved +assign pcspma_an_config_vector[8:7] = 2'b00; // pause frames - SGMII reserved +assign pcspma_an_config_vector[6] = 1'b0; // reserved +assign pcspma_an_config_vector[5] = 1'b0; // full duplex - SGMII reserved +assign pcspma_an_config_vector[4:1] = 4'b0000; // reserved +assign pcspma_an_config_vector[0] = 1'b1; // SGMII + +gig_ethernet_pcs_pma_0 +eth_pcspma ( + // Transceiver Interface + .gtrefclk_p (phy_sgmii_clk_p), + .gtrefclk_n (phy_sgmii_clk_n), + .gtrefclk_out (), + .gtrefclk_bufg_out (), + .txp (phy_sgmii_tx_p), + .txn (phy_sgmii_tx_n), + .rxp (phy_sgmii_rx_p), + .rxn (phy_sgmii_rx_n), + .resetdone (phy_sgmii_resetdone), + .userclk_out (), + .userclk2_out (phy_sgmii_userclk2), + .rxuserclk_out (), + .rxuserclk2_out (), + .independent_clock_bufg(clk_int), + .pma_reset_out (), + .mmcm_locked_out (), + .gt0_qplloutclk_out (), + .gt0_qplloutrefclk_out (), + // GMII Interface + .sgmii_clk_r (), + .sgmii_clk_f (), + .sgmii_clk_en (phy_gmii_clk_en_int), + .gmii_txd (phy_gmii_txd_int), + .gmii_tx_en (phy_gmii_tx_en_int), + .gmii_tx_er (phy_gmii_tx_er_int), + .gmii_rxd (phy_gmii_rxd_int), + .gmii_rx_dv (phy_gmii_rx_dv_int), + .gmii_rx_er (phy_gmii_rx_er_int), + .gmii_isolate (), + // Management: Alternative to MDIO Interface + .configuration_vector (pcspma_config_vector), + .an_interrupt (), + .an_adv_config_vector (pcspma_an_config_vector), + .an_restart_config (1'b0), + // Speed Control + .speed_is_10_100 (pcspma_status_speed != 2'b10), + .speed_is_100 (pcspma_status_speed == 2'b01), + // General IO's + .status_vector (pcspma_status_vector), + .reset (rst_int), + .signal_detect (1'b1) +); + +// SGMII interface debug: +// SW1:1 (sw[0]) off for payload byte, on for status vector +// SW1:2 (sw[1]) off for LSB of status vector, on for MSB +assign led = sw[3] ? (sw[2] ? pcspma_status_vector[15:8] : pcspma_status_vector[7:0]) : led_int; + +fpga_core +core_inst ( + /* + * Clock: 125MHz + * Synchronous reset + */ + .clk(clk_int), + .rst(rst_int), + /* + * GPIO + */ + .btnu(btnu_int), + .btnl(btnl_int), + .btnd(btnd_int), + .btnr(btnr_int), + .btnc(btnc_int), + .sw(sw_int), + .led(led_int), + /* + * Ethernet: 1000BASE-T SGMII + */ + .phy_gmii_clk(phy_gmii_clk_int), + .phy_gmii_rst(phy_gmii_rst_int), + .phy_gmii_clk_en(phy_gmii_clk_en_int), + .phy_gmii_rxd(phy_gmii_rxd_int), + .phy_gmii_rx_dv(phy_gmii_rx_dv_int), + .phy_gmii_rx_er(phy_gmii_rx_er_int), + .phy_gmii_txd(phy_gmii_txd_int), + .phy_gmii_tx_en(phy_gmii_tx_en_int), + .phy_gmii_tx_er(phy_gmii_tx_er_int), + .phy_reset_n(phy_reset_n), + .phy_int_n(phy_int_n), + /* + * UART: 115200 bps, 8N1 + */ + .uart_rxd(uart_rxd_int), + .uart_txd(uart_txd), + .uart_rts(uart_rts), + .uart_cts(uart_cts_int) +); + +endmodule diff --git a/example/KC705/fpga_sgmii/rtl/fpga_core.v b/example/KC705/fpga_sgmii/rtl/fpga_core.v new file mode 100644 index 000000000..5d8632863 --- /dev/null +++ b/example/KC705/fpga_sgmii/rtl/fpga_core.v @@ -0,0 +1,584 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * FPGA core logic + */ +module fpga_core +( + /* + * Clock: 125MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [7:0] sw, + output wire [7:0] led, + + /* + * Ethernet: 1000BASE-T SGMII + */ + input wire phy_gmii_clk, + input wire phy_gmii_rst, + input wire phy_gmii_clk_en, + input wire [7:0] phy_gmii_rxd, + input wire phy_gmii_rx_dv, + input wire phy_gmii_rx_er, + output wire [7:0] phy_gmii_txd, + output wire phy_gmii_tx_en, + output wire phy_gmii_tx_er, + output wire phy_reset_n, + input wire phy_int_n, + + /* + * UART: 115200 bps, 8N1 + */ + input wire uart_rxd, + output wire uart_txd, + output wire uart_rts, + input wire uart_cts +); + +// AXI between MAC and Ethernet modules +wire [7:0] rx_axis_tdata; +wire rx_axis_tvalid; +wire rx_axis_tready; +wire rx_axis_tlast; +wire rx_axis_tuser; + +wire [7:0] tx_axis_tdata; +wire tx_axis_tvalid; +wire tx_axis_tready; +wire tx_axis_tlast; +wire tx_axis_tuser; + +// Ethernet frame between Ethernet modules and UDP stack +wire rx_eth_hdr_ready; +wire rx_eth_hdr_valid; +wire [47:0] rx_eth_dest_mac; +wire [47:0] rx_eth_src_mac; +wire [15:0] rx_eth_type; +wire [7:0] rx_eth_payload_axis_tdata; +wire rx_eth_payload_axis_tvalid; +wire rx_eth_payload_axis_tready; +wire rx_eth_payload_axis_tlast; +wire rx_eth_payload_axis_tuser; + +wire tx_eth_hdr_ready; +wire tx_eth_hdr_valid; +wire [47:0] tx_eth_dest_mac; +wire [47:0] tx_eth_src_mac; +wire [15:0] tx_eth_type; +wire [7:0] tx_eth_payload_axis_tdata; +wire tx_eth_payload_axis_tvalid; +wire tx_eth_payload_axis_tready; +wire tx_eth_payload_axis_tlast; +wire tx_eth_payload_axis_tuser; + +// IP frame connections +wire rx_ip_hdr_valid; +wire rx_ip_hdr_ready; +wire [47:0] rx_ip_eth_dest_mac; +wire [47:0] rx_ip_eth_src_mac; +wire [15:0] rx_ip_eth_type; +wire [3:0] rx_ip_version; +wire [3:0] rx_ip_ihl; +wire [5:0] rx_ip_dscp; +wire [1:0] rx_ip_ecn; +wire [15:0] rx_ip_length; +wire [15:0] rx_ip_identification; +wire [2:0] rx_ip_flags; +wire [12:0] rx_ip_fragment_offset; +wire [7:0] rx_ip_ttl; +wire [7:0] rx_ip_protocol; +wire [15:0] rx_ip_header_checksum; +wire [31:0] rx_ip_source_ip; +wire [31:0] rx_ip_dest_ip; +wire [7:0] rx_ip_payload_axis_tdata; +wire rx_ip_payload_axis_tvalid; +wire rx_ip_payload_axis_tready; +wire rx_ip_payload_axis_tlast; +wire rx_ip_payload_axis_tuser; + +wire tx_ip_hdr_valid; +wire tx_ip_hdr_ready; +wire [5:0] tx_ip_dscp; +wire [1:0] tx_ip_ecn; +wire [15:0] tx_ip_length; +wire [7:0] tx_ip_ttl; +wire [7:0] tx_ip_protocol; +wire [31:0] tx_ip_source_ip; +wire [31:0] tx_ip_dest_ip; +wire [7:0] tx_ip_payload_axis_tdata; +wire tx_ip_payload_axis_tvalid; +wire tx_ip_payload_axis_tready; +wire tx_ip_payload_axis_tlast; +wire tx_ip_payload_axis_tuser; + +// UDP frame connections +wire rx_udp_hdr_valid; +wire rx_udp_hdr_ready; +wire [47:0] rx_udp_eth_dest_mac; +wire [47:0] rx_udp_eth_src_mac; +wire [15:0] rx_udp_eth_type; +wire [3:0] rx_udp_ip_version; +wire [3:0] rx_udp_ip_ihl; +wire [5:0] rx_udp_ip_dscp; +wire [1:0] rx_udp_ip_ecn; +wire [15:0] rx_udp_ip_length; +wire [15:0] rx_udp_ip_identification; +wire [2:0] rx_udp_ip_flags; +wire [12:0] rx_udp_ip_fragment_offset; +wire [7:0] rx_udp_ip_ttl; +wire [7:0] rx_udp_ip_protocol; +wire [15:0] rx_udp_ip_header_checksum; +wire [31:0] rx_udp_ip_source_ip; +wire [31:0] rx_udp_ip_dest_ip; +wire [15:0] rx_udp_source_port; +wire [15:0] rx_udp_dest_port; +wire [15:0] rx_udp_length; +wire [15:0] rx_udp_checksum; +wire [7:0] rx_udp_payload_axis_tdata; +wire rx_udp_payload_axis_tvalid; +wire rx_udp_payload_axis_tready; +wire rx_udp_payload_axis_tlast; +wire rx_udp_payload_axis_tuser; + +wire tx_udp_hdr_valid; +wire tx_udp_hdr_ready; +wire [5:0] tx_udp_ip_dscp; +wire [1:0] tx_udp_ip_ecn; +wire [7:0] tx_udp_ip_ttl; +wire [31:0] tx_udp_ip_source_ip; +wire [31:0] tx_udp_ip_dest_ip; +wire [15:0] tx_udp_source_port; +wire [15:0] tx_udp_dest_port; +wire [15:0] tx_udp_length; +wire [15:0] tx_udp_checksum; +wire [7:0] tx_udp_payload_axis_tdata; +wire tx_udp_payload_axis_tvalid; +wire tx_udp_payload_axis_tready; +wire tx_udp_payload_axis_tlast; +wire tx_udp_payload_axis_tuser; + +wire [7:0] rx_fifo_udp_payload_axis_tdata; +wire rx_fifo_udp_payload_axis_tvalid; +wire rx_fifo_udp_payload_axis_tready; +wire rx_fifo_udp_payload_axis_tlast; +wire rx_fifo_udp_payload_axis_tuser; + +wire [7:0] tx_fifo_udp_payload_axis_tdata; +wire tx_fifo_udp_payload_axis_tvalid; +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; +assign rx_ip_payload_axis_tready = 1; + +assign tx_ip_hdr_valid = 0; +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_source_ip = 0; +assign tx_ip_dest_ip = 0; +assign tx_ip_payload_axis_tdata = 0; +assign tx_ip_payload_axis_tvalid = 0; +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 no_match = !match_cond; + +reg match_cond_reg = 0; +reg no_match_reg = 0; + +always @(posedge clk) begin + if (rst) begin + match_cond_reg <= 0; + no_match_reg <= 0; + end else begin + if (rx_udp_payload_axis_tvalid) begin + if ((!match_cond_reg && !no_match_reg) || + (rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin + match_cond_reg <= match_cond; + no_match_reg <= no_match; + end + end else begin + match_cond_reg <= 0; + no_match_reg <= 0; + end + end +end + +assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond; +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_length = rx_udp_length; +assign tx_udp_checksum = 0; + +assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata; +assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid; +assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready; +assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast; +assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser; + +assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata; +assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg; +assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg; +assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast; +assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser; + +// Place first payload byte onto LEDs +reg valid_last = 0; +reg [7:0] led_reg = 0; + +always @(posedge clk) begin + if (rst) begin + led_reg <= 0; + end else begin + if (tx_udp_payload_axis_tvalid) begin + if (!valid_last) begin + led_reg <= tx_udp_payload_axis_tdata; + valid_last <= 1'b1; + end + if (tx_udp_payload_axis_tlast) begin + valid_last <= 1'b0; + end + end + end +end + +//assign led = sw; +assign led = led_reg; +assign phy_reset_n = !rst; + +assign uart_txd = 0; +assign uart_rts = 0; + +eth_mac_1g_fifo #( + .ENABLE_PADDING(1), + .MIN_FRAME_LENGTH(64), + .TX_FIFO_DEPTH(4096), + .TX_FRAME_FIFO(1), + .RX_FIFO_DEPTH(4096), + .RX_FRAME_FIFO(1) +) +eth_mac_inst ( + .rx_clk(phy_gmii_clk), + .rx_rst(phy_gmii_rst), + .tx_clk(phy_gmii_clk), + .tx_rst(phy_gmii_rst), + .logic_clk(clk), + .logic_rst(rst), + + .tx_axis_tdata(tx_axis_tdata), + .tx_axis_tvalid(tx_axis_tvalid), + .tx_axis_tready(tx_axis_tready), + .tx_axis_tlast(tx_axis_tlast), + .tx_axis_tuser(tx_axis_tuser), + + .rx_axis_tdata(rx_axis_tdata), + .rx_axis_tvalid(rx_axis_tvalid), + .rx_axis_tready(rx_axis_tready), + .rx_axis_tlast(rx_axis_tlast), + .rx_axis_tuser(rx_axis_tuser), + + .gmii_rxd(phy_gmii_rxd), + .gmii_rx_dv(phy_gmii_rx_dv), + .gmii_rx_er(phy_gmii_rx_er), + .gmii_txd(phy_gmii_txd), + .gmii_tx_en(phy_gmii_tx_en), + .gmii_tx_er(phy_gmii_tx_er), + + .rx_clk_enable(phy_gmii_clk_en), + .tx_clk_enable(phy_gmii_clk_en), + .rx_mii_select(1'b0), + .tx_mii_select(1'b0), + + .tx_fifo_overflow(), + .tx_fifo_bad_frame(), + .tx_fifo_good_frame(), + .rx_error_bad_frame(), + .rx_error_bad_fcs(), + .rx_fifo_overflow(), + .rx_fifo_bad_frame(), + .rx_fifo_good_frame(), + + .ifg_delay(12) +); + +eth_axis_rx +eth_axis_rx_inst ( + .clk(clk), + .rst(rst), + // AXI input + .s_axis_tdata(rx_axis_tdata), + .s_axis_tvalid(rx_axis_tvalid), + .s_axis_tready(rx_axis_tready), + .s_axis_tlast(rx_axis_tlast), + .s_axis_tuser(rx_axis_tuser), + // Ethernet frame output + .m_eth_hdr_valid(rx_eth_hdr_valid), + .m_eth_hdr_ready(rx_eth_hdr_ready), + .m_eth_dest_mac(rx_eth_dest_mac), + .m_eth_src_mac(rx_eth_src_mac), + .m_eth_type(rx_eth_type), + .m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata), + .m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid), + .m_eth_payload_axis_tready(rx_eth_payload_axis_tready), + .m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast), + .m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser), + // Status signals + .busy(), + .error_header_early_termination() +); + +eth_axis_tx +eth_axis_tx_inst ( + .clk(clk), + .rst(rst), + // Ethernet frame input + .s_eth_hdr_valid(tx_eth_hdr_valid), + .s_eth_hdr_ready(tx_eth_hdr_ready), + .s_eth_dest_mac(tx_eth_dest_mac), + .s_eth_src_mac(tx_eth_src_mac), + .s_eth_type(tx_eth_type), + .s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata), + .s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid), + .s_eth_payload_axis_tready(tx_eth_payload_axis_tready), + .s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast), + .s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser), + // AXI output + .m_axis_tdata(tx_axis_tdata), + .m_axis_tvalid(tx_axis_tvalid), + .m_axis_tready(tx_axis_tready), + .m_axis_tlast(tx_axis_tlast), + .m_axis_tuser(tx_axis_tuser), + // Status signals + .busy() +); + +udp_complete +udp_complete_inst ( + .clk(clk), + .rst(rst), + // Ethernet frame input + .s_eth_hdr_valid(rx_eth_hdr_valid), + .s_eth_hdr_ready(rx_eth_hdr_ready), + .s_eth_dest_mac(rx_eth_dest_mac), + .s_eth_src_mac(rx_eth_src_mac), + .s_eth_type(rx_eth_type), + .s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata), + .s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid), + .s_eth_payload_axis_tready(rx_eth_payload_axis_tready), + .s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast), + .s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser), + // Ethernet frame output + .m_eth_hdr_valid(tx_eth_hdr_valid), + .m_eth_hdr_ready(tx_eth_hdr_ready), + .m_eth_dest_mac(tx_eth_dest_mac), + .m_eth_src_mac(tx_eth_src_mac), + .m_eth_type(tx_eth_type), + .m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata), + .m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid), + .m_eth_payload_axis_tready(tx_eth_payload_axis_tready), + .m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast), + .m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser), + // IP frame input + .s_ip_hdr_valid(tx_ip_hdr_valid), + .s_ip_hdr_ready(tx_ip_hdr_ready), + .s_ip_dscp(tx_ip_dscp), + .s_ip_ecn(tx_ip_ecn), + .s_ip_length(tx_ip_length), + .s_ip_ttl(tx_ip_ttl), + .s_ip_protocol(tx_ip_protocol), + .s_ip_source_ip(tx_ip_source_ip), + .s_ip_dest_ip(tx_ip_dest_ip), + .s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata), + .s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid), + .s_ip_payload_axis_tready(tx_ip_payload_axis_tready), + .s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast), + .s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser), + // IP frame output + .m_ip_hdr_valid(rx_ip_hdr_valid), + .m_ip_hdr_ready(rx_ip_hdr_ready), + .m_ip_eth_dest_mac(rx_ip_eth_dest_mac), + .m_ip_eth_src_mac(rx_ip_eth_src_mac), + .m_ip_eth_type(rx_ip_eth_type), + .m_ip_version(rx_ip_version), + .m_ip_ihl(rx_ip_ihl), + .m_ip_dscp(rx_ip_dscp), + .m_ip_ecn(rx_ip_ecn), + .m_ip_length(rx_ip_length), + .m_ip_identification(rx_ip_identification), + .m_ip_flags(rx_ip_flags), + .m_ip_fragment_offset(rx_ip_fragment_offset), + .m_ip_ttl(rx_ip_ttl), + .m_ip_protocol(rx_ip_protocol), + .m_ip_header_checksum(rx_ip_header_checksum), + .m_ip_source_ip(rx_ip_source_ip), + .m_ip_dest_ip(rx_ip_dest_ip), + .m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata), + .m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid), + .m_ip_payload_axis_tready(rx_ip_payload_axis_tready), + .m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast), + .m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser), + // UDP frame input + .s_udp_hdr_valid(tx_udp_hdr_valid), + .s_udp_hdr_ready(tx_udp_hdr_ready), + .s_udp_ip_dscp(tx_udp_ip_dscp), + .s_udp_ip_ecn(tx_udp_ip_ecn), + .s_udp_ip_ttl(tx_udp_ip_ttl), + .s_udp_ip_source_ip(tx_udp_ip_source_ip), + .s_udp_ip_dest_ip(tx_udp_ip_dest_ip), + .s_udp_source_port(tx_udp_source_port), + .s_udp_dest_port(tx_udp_dest_port), + .s_udp_length(tx_udp_length), + .s_udp_checksum(tx_udp_checksum), + .s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata), + .s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid), + .s_udp_payload_axis_tready(tx_udp_payload_axis_tready), + .s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast), + .s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser), + // UDP frame output + .m_udp_hdr_valid(rx_udp_hdr_valid), + .m_udp_hdr_ready(rx_udp_hdr_ready), + .m_udp_eth_dest_mac(rx_udp_eth_dest_mac), + .m_udp_eth_src_mac(rx_udp_eth_src_mac), + .m_udp_eth_type(rx_udp_eth_type), + .m_udp_ip_version(rx_udp_ip_version), + .m_udp_ip_ihl(rx_udp_ip_ihl), + .m_udp_ip_dscp(rx_udp_ip_dscp), + .m_udp_ip_ecn(rx_udp_ip_ecn), + .m_udp_ip_length(rx_udp_ip_length), + .m_udp_ip_identification(rx_udp_ip_identification), + .m_udp_ip_flags(rx_udp_ip_flags), + .m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset), + .m_udp_ip_ttl(rx_udp_ip_ttl), + .m_udp_ip_protocol(rx_udp_ip_protocol), + .m_udp_ip_header_checksum(rx_udp_ip_header_checksum), + .m_udp_ip_source_ip(rx_udp_ip_source_ip), + .m_udp_ip_dest_ip(rx_udp_ip_dest_ip), + .m_udp_source_port(rx_udp_source_port), + .m_udp_dest_port(rx_udp_dest_port), + .m_udp_length(rx_udp_length), + .m_udp_checksum(rx_udp_checksum), + .m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata), + .m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid), + .m_udp_payload_axis_tready(rx_udp_payload_axis_tready), + .m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast), + .m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser), + // Status signals + .ip_rx_busy(), + .ip_tx_busy(), + .udp_rx_busy(), + .udp_tx_busy(), + .ip_rx_error_header_early_termination(), + .ip_rx_error_payload_early_termination(), + .ip_rx_error_invalid_header(), + .ip_rx_error_invalid_checksum(), + .ip_tx_error_payload_early_termination(), + .ip_tx_error_arp_failed(), + .udp_rx_error_header_early_termination(), + .udp_rx_error_payload_early_termination(), + .udp_tx_error_payload_early_termination(), + // Configuration + .local_mac(local_mac), + .local_ip(local_ip), + .gateway_ip(gateway_ip), + .subnet_mask(subnet_mask), + .clear_arp_cache(0) +); + +axis_fifo #( + .DEPTH(8192), + .DATA_WIDTH(8), + .KEEP_ENABLE(0), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(1), + .USER_WIDTH(1), + .FRAME_FIFO(0) +) +udp_payload_fifo ( + .clk(clk), + .rst(rst), + + // AXI input + .s_axis_tdata(rx_fifo_udp_payload_axis_tdata), + .s_axis_tkeep(0), + .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_tuser(rx_fifo_udp_payload_axis_tuser), + + // AXI output + .m_axis_tdata(tx_fifo_udp_payload_axis_tdata), + .m_axis_tkeep(), + .m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid), + .m_axis_tready(tx_fifo_udp_payload_axis_tready), + .m_axis_tlast(tx_fifo_udp_payload_axis_tlast), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(tx_fifo_udp_payload_axis_tuser), + + // Status + .status_overflow(), + .status_bad_frame(), + .status_good_frame() +); + +endmodule diff --git a/example/KC705/fpga_sgmii/rtl/sync_signal.v b/example/KC705/fpga_sgmii/rtl/sync_signal.v new file mode 100644 index 000000000..b2a8ce3de --- /dev/null +++ b/example/KC705/fpga_sgmii/rtl/sync_signal.v @@ -0,0 +1,58 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`timescale 1 ns / 1 ps + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule diff --git a/example/KC705/fpga_sgmii/tb/fpga_core/Makefile b/example/KC705/fpga_sgmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..9c8aced94 --- /dev/null +++ b/example/KC705/fpga_sgmii/tb/fpga_core/Makefile @@ -0,0 +1,95 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g_fifo.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_1g.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/axis_gmii_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v +VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v +VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v +VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v + +# module parameters +#export PARAM_A ?= value + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + +# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + +# COMPILE_ARGS += -GA=$(PARAM_A) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/example/KC705/fpga_sgmii/tb/fpga_core/test_fpga_core.py b/example/KC705/fpga_sgmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..8354186e8 --- /dev/null +++ b/example/KC705/fpga_sgmii/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,218 @@ +""" + +Copyright (c) 2020 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import logging +import os + +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, UDP + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge + +from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink + + +class TB: + def __init__(self, dut, speed=1000): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + cocotb.fork(Clock(dut.phy_gmii_clk, 8, units="ns").start()) + + self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en, + dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en) + + dut.phy_gmii_clk_en.setimmediatevalue(1) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + dut.uart_txd.setimmediatevalue(0) + dut.uart_rts.setimmediatevalue(0) + + async def init(self): + + self.dut.rst.setimmediatevalue(0) + self.dut.phy_gmii_rst.setimmediatevalue(0) + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 1 + self.dut.phy_gmii_rst <= 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst <= 0 + self.dut.phy_gmii_rst <= 0 + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + tb.log.info("test UDP RX packet") + + payload = bytes([x % 256 for x in range(256)]) + eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') + ip = IP(src='192.168.1.100', dst='192.168.1.128') + udp = UDP(sport=5678, dport=1234) + test_pkt = eth / ip / udp / payload + + test_frame = GmiiFrame.from_payload(test_pkt.build()) + + await tb.gmii_source.send(test_frame) + + tb.log.info("receive ARP request") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' + assert rx_pkt.src == test_pkt.dst + assert rx_pkt[ARP].hwtype == 1 + assert rx_pkt[ARP].ptype == 0x0800 + assert rx_pkt[ARP].hwlen == 6 + assert rx_pkt[ARP].plen == 4 + assert rx_pkt[ARP].op == 1 + assert rx_pkt[ARP].hwsrc == test_pkt.dst + assert rx_pkt[ARP].psrc == test_pkt[IP].dst + assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' + assert rx_pkt[ARP].pdst == test_pkt[IP].src + + tb.log.info("send ARP response") + + eth = Ether(src=test_pkt.src, dst=test_pkt.dst) + arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, + hwsrc=test_pkt.src, psrc=test_pkt[IP].src, + hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) + resp_pkt = eth / arp + + resp_frame = GmiiFrame.from_payload(resp_pkt.build()) + + await tb.gmii_source.send(resp_frame) + + tb.log.info("receive UDP packet") + + rx_frame = await tb.gmii_sink.recv() + + rx_pkt = Ether(bytes(rx_frame.get_payload())) + + tb.log.info("RX packet: %s", repr(rx_pkt)) + + 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 + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = os.path.abspath(os.path.dirname(__file__)) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) +lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl')) +eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl')) + + +def test_fpga_core(request): + dut = "fpga_core" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g_fifo.v"), + os.path.join(eth_rtl_dir, "eth_mac_1g.v"), + os.path.join(eth_rtl_dir, "axis_gmii_rx.v"), + os.path.join(eth_rtl_dir, "axis_gmii_tx.v"), + os.path.join(eth_rtl_dir, "lfsr.v"), + os.path.join(eth_rtl_dir, "eth_axis_rx.v"), + os.path.join(eth_rtl_dir, "eth_axis_tx.v"), + os.path.join(eth_rtl_dir, "udp_complete.v"), + os.path.join(eth_rtl_dir, "udp_checksum_gen.v"), + os.path.join(eth_rtl_dir, "udp.v"), + os.path.join(eth_rtl_dir, "udp_ip_rx.v"), + os.path.join(eth_rtl_dir, "udp_ip_tx.v"), + os.path.join(eth_rtl_dir, "ip_complete.v"), + os.path.join(eth_rtl_dir, "ip.v"), + os.path.join(eth_rtl_dir, "ip_eth_rx.v"), + os.path.join(eth_rtl_dir, "ip_eth_tx.v"), + os.path.join(eth_rtl_dir, "ip_arb_mux.v"), + os.path.join(eth_rtl_dir, "arp.v"), + os.path.join(eth_rtl_dir, "arp_cache.v"), + os.path.join(eth_rtl_dir, "arp_eth_rx.v"), + os.path.join(eth_rtl_dir, "arp_eth_tx.v"), + os.path.join(eth_rtl_dir, "eth_arb_mux.v"), + os.path.join(axis_rtl_dir, "arbiter.v"), + os.path.join(axis_rtl_dir, "priority_encoder.v"), + os.path.join(axis_rtl_dir, "axis_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo.v"), + os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"), + ] + + parameters = {} + + # parameters['A'] = val + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) From eeb04acdd0d1adf3fa76cc470f1023c73b7977cc Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 16 Jan 2021 13:39:56 -0800 Subject: [PATCH 36/37] Update github actions --- .github/workflows/regression-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/regression-tests.yml b/.github/workflows/regression-tests.yml index a457c3b44..d7688d46a 100644 --- a/.github/workflows/regression-tests.yml +++ b/.github/workflows/regression-tests.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: build: - name: Python ${{matrix.python-version}} + name: Python ${{ matrix.python-version }} (${{ matrix.group }}/10) runs-on: ubuntu-20.04 strategy: From c0c2dbce2aeb7110031cb5d3020fbfe23c7609da Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 6 Feb 2021 15:15:34 -0800 Subject: [PATCH 37/37] Update XDC files --- example/ADM_PCIE_9V3/fpga_10g/fpga.xdc | 252 ++++++++++++++----------- example/ADM_PCIE_9V3/fpga_25g/fpga.xdc | 252 ++++++++++++++----------- example/AU200/fpga_10g/fpga.xdc | 117 ++++++++---- example/AU250/fpga_10g/fpga.xdc | 117 ++++++++---- example/AU280/fpga_10g/fpga.xdc | 88 +++++---- example/AU50/fpga_10g/fpga.xdc | 69 +++++-- example/Arty/fpga/fpga.xdc | 24 +++ example/ExaNIC_X10/fpga/fpga.xdc | 123 +++++++----- example/ExaNIC_X25/fpga_10g/fpga.xdc | 122 +++++++----- example/KC705/fpga_gmii/fpga.xdc | 26 +++ example/KC705/fpga_rgmii/fpga.xdc | 26 +++ example/KC705/fpga_sgmii/fpga.xdc | 26 +++ example/NetFPGA_SUME/fpga/fpga.xdc | 63 +++++-- example/NexysVideo/fpga/fpga.xdc | 26 +++ example/VCU108/fpga_10g/fpga.xdc | 103 ++++++++-- example/VCU108/fpga_1g/fpga.xdc | 84 ++++++++- example/VCU118/fpga_10g/fpga.xdc | 126 ++++++++++--- example/VCU118/fpga_1g/fpga.xdc | 92 +++++++-- example/VCU118/fpga_25g/fpga.xdc | 126 ++++++++++--- example/VCU1525/fpga_10g/fpga.xdc | 102 ++++++---- example/ZCU102/fpga/fpga.xdc | 42 ++++- example/ZCU106/fpga/fpga.xdc | 50 +++-- example/fb2CG/fpga_10g/fpga.xdc | 79 ++++++-- 23 files changed, 1513 insertions(+), 622 deletions(-) diff --git a/example/ADM_PCIE_9V3/fpga_10g/fpga.xdc b/example/ADM_PCIE_9V3/fpga_10g/fpga.xdc index 5668ed824..5718ae810 100644 --- a/example/ADM_PCIE_9V3/fpga_10g/fpga.xdc +++ b/example/ADM_PCIE_9V3/fpga_10g/fpga.xdc @@ -24,10 +24,16 @@ set_property -dict {LOC AU23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC AH24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[0]}] set_property -dict {LOC AJ23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[1]}] +set_false_path -to [get_ports {user_led_g[*] user_led_r front_led[*]}] +set_output_delay 0 [get_ports {user_led_g[*] user_led_r front_led[*]}] + # Switches set_property -dict {LOC AV27 IOSTANDARD LVCMOS18} [get_ports {user_sw[0]}] set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}] +set_false_path -from [get_ports {user_sw[*]}] +set_input_delay 0 [get_ports {user_sw[*]}] + # GPIO #set_property -dict {LOC G30 IOSTANDARD LVCMOS18} [get_ports gpio_p[0]] #set_property -dict {LOC F30 IOSTANDARD LVCMOS18} [get_ports gpio_n[0]] @@ -35,124 +41,144 @@ set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}] #set_property -dict {LOC H31 IOSTANDARD LVCMOS18} [get_ports gpio_n[1]] # QSFP28 Interfaces -set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 +set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 set_property -dict {LOC N33 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_128 from ? -#set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ? +set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ? set_property -dict {LOC F29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_0_modprs_l] set_property -dict {LOC D31 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_0_sel_l] # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name qsfp_0_mgt_refclk [get_ports qsfp_0_mgt_refclk_p] -set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 set_property -dict {LOC U33 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_127 from ? -#set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ? +set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ? set_property -dict {LOC F33 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_1_modprs_l] set_property -dict {LOC D30 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_1_sel_l] # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p] -set_property -dict {LOC B29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_reset_l] -set_property -dict {LOC C29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_int_l] -#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_scl] -#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_sda] +set_property -dict {LOC B29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_reset_l] +set_property -dict {LOC C29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_int_l] +#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports qsfp_i2c_scl] +#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports qsfp_i2c_sda] + +set_false_path -to [get_ports {qsfp_0_sel_l qsfp_1_sel_l qsfp_reset_l}] +set_output_delay 0 [get_ports {qsfp_0_sel_l qsfp_1_sel_l qsfp_reset_l}] +set_false_path -from [get_ports {qsfp_0_modprs_l qsfp_1_modprs_l qsfp_int_l}] +set_input_delay 0 [get_ports {qsfp_0_modprs_l qsfp_1_modprs_l qsfp_int_l}] + +#set_false_path -to [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_output_delay 0 [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_false_path -from [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_input_delay 0 [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] + +# I2C interface +#set_property -dict {LOC AT25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl] +#set_property -dict {LOC AT26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda] +#set_property -dict {LOC AP23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_wp] + +#set_false_path -to [get_ports {eeprom_i2c_sda eeprom_i2c_scl eeprom_wp}] +#set_output_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl eeprom_wp}] +#set_false_path -from [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_input_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] # PCIe Interface -#set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE3_CHANNEL_X1Y15 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE3_CHANNEL_X1Y15 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE3_CHANNEL_X1Y15 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE3_CHANNEL_X1Y15 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE3_CHANNEL_X1Y14 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE3_CHANNEL_X1Y14 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE3_CHANNEL_X1Y14 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE3_CHANNEL_X1Y14 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE3_CHANNEL_X1Y13 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE3_CHANNEL_X1Y13 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE3_CHANNEL_X1Y13 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE3_CHANNEL_X1Y13 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE3_CHANNEL_X1Y12 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE3_CHANNEL_X1Y12 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE3_CHANNEL_X1Y12 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE3_CHANNEL_X1Y12 / GTYE3_COMMON_X1Y3 -#set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE3_CHANNEL_X1Y11 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE3_CHANNEL_X1Y11 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE3_CHANNEL_X1Y11 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE3_CHANNEL_X1Y11 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE3_CHANNEL_X1Y10 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE3_CHANNEL_X1Y10 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X1Y10 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X1Y10 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE3_CHANNEL_X1Y9 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE3_CHANNEL_X1Y9 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X1Y9 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X1Y9 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE3_CHANNEL_X1Y8 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE3_CHANNEL_X1Y8 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE3_CHANNEL_X1Y8 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE3_CHANNEL_X1Y8 / GTYE3_COMMON_X1Y2 -#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE3_CHANNEL_X1Y7 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE3_CHANNEL_X1Y7 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X1Y7 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X1Y7 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE3_CHANNEL_X1Y6 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE3_CHANNEL_X1Y6 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X1Y6 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X1Y6 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE3_CHANNEL_X1Y5 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE3_CHANNEL_X1Y5 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X1Y5 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X1Y5 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE3_CHANNEL_X1Y4 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE3_CHANNEL_X1Y4 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X1Y4 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X1Y4 / GTYE3_COMMON_X1Y1 -#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE3_CHANNEL_X1Y3 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE3_CHANNEL_X1Y3 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X1Y3 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X1Y3 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE3_CHANNEL_X1Y2 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE3_CHANNEL_X1Y2 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X1Y2 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X1Y2 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE3_CHANNEL_X1Y1 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE3_CHANNEL_X1Y1 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X1Y1 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X1Y1 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE3_CHANNEL_X1Y0 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE3_CHANNEL_X1Y0 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X1Y0 / GTYE3_COMMON_X1Y0 -#set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X1Y0 / GTYE3_COMMON_X1Y0 +#set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 #set_property -dict {LOC AA7 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_226 #set_property -dict {LOC AA6 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_226 #set_property -dict {LOC AJ7 } [get_ports pcie_refclk_2_p] ;# MGTREFCLK0P_224 @@ -164,13 +190,17 @@ set_property -dict {LOC C29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +#set_false_path -from [get_ports {perst_0}] +#set_input_delay 0 [get_ports {perst_0}] + # QSPI flash -#set_property -dict {LOC AB10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi_clk}] -#set_property -dict {LOC AB8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[0]}] -#set_property -dict {LOC AD8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[1]}] -#set_property -dict {LOC Y8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[2]}] -#set_property -dict {LOC AC8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[3]}] -#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[0]}] -#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[1]}] -#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[2]}] -#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[3]}] +#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC AV30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] + +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/example/ADM_PCIE_9V3/fpga_25g/fpga.xdc b/example/ADM_PCIE_9V3/fpga_25g/fpga.xdc index c01ef2760..5718ae810 100644 --- a/example/ADM_PCIE_9V3/fpga_25g/fpga.xdc +++ b/example/ADM_PCIE_9V3/fpga_25g/fpga.xdc @@ -24,10 +24,16 @@ set_property -dict {LOC AU23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC AH24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[0]}] set_property -dict {LOC AJ23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[1]}] +set_false_path -to [get_ports {user_led_g[*] user_led_r front_led[*]}] +set_output_delay 0 [get_ports {user_led_g[*] user_led_r front_led[*]}] + # Switches set_property -dict {LOC AV27 IOSTANDARD LVCMOS18} [get_ports {user_sw[0]}] set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}] +set_false_path -from [get_ports {user_sw[*]}] +set_input_delay 0 [get_ports {user_sw[*]}] + # GPIO #set_property -dict {LOC G30 IOSTANDARD LVCMOS18} [get_ports gpio_p[0]] #set_property -dict {LOC F30 IOSTANDARD LVCMOS18} [get_ports gpio_n[0]] @@ -35,124 +41,144 @@ set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}] #set_property -dict {LOC H31 IOSTANDARD LVCMOS18} [get_ports gpio_n[1]] # QSFP28 Interfaces -set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 -set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 -#set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4 +set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 set_property -dict {LOC N33 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_128 from ? -#set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ? +set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ? set_property -dict {LOC F29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_0_modprs_l] set_property -dict {LOC D31 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_0_sel_l] # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name qsfp_0_mgt_refclk [get_ports qsfp_0_mgt_refclk_p] -set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 set_property -dict {LOC U33 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_127 from ? -#set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ? +set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ? set_property -dict {LOC F33 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_1_modprs_l] set_property -dict {LOC D30 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_1_sel_l] # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p] -set_property -dict {LOC B29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_reset_l] -set_property -dict {LOC C29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_int_l] -#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_scl] -#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_sda] +set_property -dict {LOC B29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_reset_l] +set_property -dict {LOC C29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_int_l] +#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports qsfp_i2c_scl] +#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports qsfp_i2c_sda] + +set_false_path -to [get_ports {qsfp_0_sel_l qsfp_1_sel_l qsfp_reset_l}] +set_output_delay 0 [get_ports {qsfp_0_sel_l qsfp_1_sel_l qsfp_reset_l}] +set_false_path -from [get_ports {qsfp_0_modprs_l qsfp_1_modprs_l qsfp_int_l}] +set_input_delay 0 [get_ports {qsfp_0_modprs_l qsfp_1_modprs_l qsfp_int_l}] + +#set_false_path -to [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_output_delay 0 [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_false_path -from [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_input_delay 0 [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] + +# I2C interface +#set_property -dict {LOC AT25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl] +#set_property -dict {LOC AT26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda] +#set_property -dict {LOC AP23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_wp] + +#set_false_path -to [get_ports {eeprom_i2c_sda eeprom_i2c_scl eeprom_wp}] +#set_output_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl eeprom_wp}] +#set_false_path -from [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_input_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] # PCIe Interface -#set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 +#set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +#set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 #set_property -dict {LOC AA7 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_226 #set_property -dict {LOC AA6 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_226 #set_property -dict {LOC AJ7 } [get_ports pcie_refclk_2_p] ;# MGTREFCLK0P_224 @@ -164,13 +190,17 @@ set_property -dict {LOC C29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +#set_false_path -from [get_ports {perst_0}] +#set_input_delay 0 [get_ports {perst_0}] + # QSPI flash -#set_property -dict {LOC AB10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi_clk}] -#set_property -dict {LOC AB8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[0]}] -#set_property -dict {LOC AD8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[1]}] -#set_property -dict {LOC Y8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[2]}] -#set_property -dict {LOC AC8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[3]}] -#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[0]}] -#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[1]}] -#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[2]}] -#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[3]}] +#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC AV30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] + +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/example/AU200/fpga_10g/fpga.xdc b/example/AU200/fpga_10g/fpga.xdc index aa61c277f..022ed08ab 100644 --- a/example/AU200/fpga_10g/fpga.xdc +++ b/example/AU200/fpga_10g/fpga.xdc @@ -13,6 +13,8 @@ set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] +set_operating_conditions -design_power_budget 160 + # System clocks # 300 MHz (DDR 0) #set_property -dict {LOC AY37 IOSTANDARD LVDS} [get_ports clk_300mhz_0_p] @@ -44,48 +46,75 @@ set_property -dict {LOC BC21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC BB21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] set_property -dict {LOC BA20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AL20 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # DIP switches set_property -dict {LOC AN22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC AM19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC AL19 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART -set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_txd] -set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_rxd] +set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] +set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_rxd] + +#set_false_path -to [get_ports {uart_txd}] +#set_output_delay 0 [get_ports {uart_txd}] +#set_false_path -from [get_ports {uart_rxd}] +#set_input_delay 0 [get_ports {uart_rxd}] + +# BMC +#set_property -dict {LOC AR20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +#set_property -dict {LOC AM20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +#set_property -dict {LOC AM21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[2]}] +#set_property -dict {LOC AN21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[3]}] +#set_property -dict {LOC BB19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +#set_property -dict {LOC BA19 IOSTANDARD LVCMOS12} [get_ports {msp_uart_rxd}] + +#set_false_path -to [get_ports {msp_uart_txd}] +#set_output_delay 0 [get_ports {msp_uart_txd}] +#set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}] +#set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}] # QSFP28 Interfaces set_property -dict {LOC N4 } [get_ports qsfp0_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC N9 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC M2 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC M7 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC L4 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC L9 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC K2 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 set_property -dict {LOC K7 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 #set_property -dict {LOC M11 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U14.4 via U43.13 #set_property -dict {LOC M10 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U14.5 via U43.14 set_property -dict {LOC K11 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U9.18 -#set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 -set_property -dict {LOC BE16 IOSTANDARD LVCMOS12} [get_ports qsfp0_modsell] -set_property -dict {LOC BE17 IOSTANDARD LVCMOS12} [get_ports qsfp0_resetl] -set_property -dict {LOC BE20 IOSTANDARD LVCMOS12} [get_ports qsfp0_modprsl] -set_property -dict {LOC BE21 IOSTANDARD LVCMOS12} [get_ports qsfp0_intl] -set_property -dict {LOC BD18 IOSTANDARD LVCMOS12} [get_ports qsfp0_lpmode] -set_property -dict {LOC AT22 IOSTANDARD LVCMOS12} [get_ports qsfp0_refclk_reset] -set_property -dict {LOC AT20 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[0]}] -set_property -dict {LOC AU22 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[1]}] +set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 +set_property -dict {LOC BE16 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_modsell] +set_property -dict {LOC BE17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_resetl] +set_property -dict {LOC BE20 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_modprsl] +set_property -dict {LOC BE21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_intl] +set_property -dict {LOC BD18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_lpmode] +set_property -dict {LOC AT22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_reset] +set_property -dict {LOC AT20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[0]}] +set_property -dict {LOC AU22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[1]}] # 156.25 MHz MGT reference clock (from SI570) #create_clock -period 6.400 -name qsfp0_mgt_refclk_0 [get_ports qsfp0_mgt_refclk_0_p] @@ -96,34 +125,39 @@ set_property -dict {LOC AU22 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[1]}] # 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_output_delay 0 [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_false_path -from [get_ports {qsfp0_modprsl qsfp0_intl}] +set_input_delay 0 [get_ports {qsfp0_modprsl qsfp0_intl}] + set_property -dict {LOC U4 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 set_property -dict {LOC U9 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 set_property -dict {LOC T2 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 set_property -dict {LOC R4 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 set_property -dict {LOC R9 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 set_property -dict {LOC P2 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 set_property -dict {LOC P7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 #set_property -dict {LOC T11 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U14.4 via U43.15 #set_property -dict {LOC T10 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U14.5 via U43.16 #set_property -dict {LOC P11 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U12.18 #set_property -dict {LOC P10 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U12.17 -set_property -dict {LOC AY20 IOSTANDARD LVCMOS12} [get_ports qsfp1_modsell] -set_property -dict {LOC BC18 IOSTANDARD LVCMOS12} [get_ports qsfp1_resetl] -set_property -dict {LOC BC19 IOSTANDARD LVCMOS12} [get_ports qsfp1_modprsl] -set_property -dict {LOC AV21 IOSTANDARD LVCMOS12} [get_ports qsfp1_intl] -set_property -dict {LOC AV22 IOSTANDARD LVCMOS12} [get_ports qsfp1_lpmode] -set_property -dict {LOC AR21 IOSTANDARD LVCMOS12} [get_ports qsfp1_refclk_reset] -set_property -dict {LOC AR22 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[0]}] -set_property -dict {LOC AU20 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[1]}] +set_property -dict {LOC AY20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +set_property -dict {LOC BC18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +set_property -dict {LOC BC19 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_modprsl] +set_property -dict {LOC AV21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_intl] +set_property -dict {LOC AV22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] +set_property -dict {LOC AR21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_reset] +set_property -dict {LOC AR22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[0]}] +set_property -dict {LOC AU20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[1]}] # 156.25 MHz MGT reference clock (from SI570) #create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] @@ -134,11 +168,21 @@ set_property -dict {LOC AU20 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[1]}] # 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) #create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + # I2C interface #set_property -dict {LOC BF19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_mux_reset] set_property -dict {LOC BF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_scl] set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 #set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 @@ -211,4 +255,5 @@ set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_p] - +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/example/AU250/fpga_10g/fpga.xdc b/example/AU250/fpga_10g/fpga.xdc index 58a54e6ad..ce92588a4 100644 --- a/example/AU250/fpga_10g/fpga.xdc +++ b/example/AU250/fpga_10g/fpga.xdc @@ -13,6 +13,8 @@ set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] +set_operating_conditions -design_power_budget 160 + # System clocks # 300 MHz (DDR 0) #set_property -dict {LOC AY37 IOSTANDARD LVDS} [get_ports clk_300mhz_0_p] @@ -44,48 +46,75 @@ set_property -dict {LOC BC21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC BB21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] set_property -dict {LOC BA20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AL20 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # DIP switches set_property -dict {LOC AN22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC AM19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC AL19 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART -set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_txd] -set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_rxd] +set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] +set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_rxd] + +#set_false_path -to [get_ports {uart_txd}] +#set_output_delay 0 [get_ports {uart_txd}] +#set_false_path -from [get_ports {uart_rxd}] +#set_input_delay 0 [get_ports {uart_rxd}] + +# BMC +#set_property -dict {LOC AR20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +#set_property -dict {LOC AM20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +#set_property -dict {LOC AM21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[2]}] +#set_property -dict {LOC AN21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[3]}] +#set_property -dict {LOC BB19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +#set_property -dict {LOC BA19 IOSTANDARD LVCMOS12} [get_ports {msp_uart_rxd}] + +#set_false_path -to [get_ports {msp_uart_txd}] +#set_output_delay 0 [get_ports {msp_uart_txd}] +#set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}] +#set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}] # QSFP28 Interfaces set_property -dict {LOC N4 } [get_ports qsfp0_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 set_property -dict {LOC N9 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 set_property -dict {LOC M2 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 set_property -dict {LOC M7 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 set_property -dict {LOC L4 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 set_property -dict {LOC L9 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 set_property -dict {LOC K2 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 set_property -dict {LOC K7 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 #set_property -dict {LOC M11 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U14.4 via U43.13 #set_property -dict {LOC M10 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U14.5 via U43.14 set_property -dict {LOC K11 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U9.18 -#set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 -set_property -dict {LOC BE16 IOSTANDARD LVCMOS12} [get_ports qsfp0_modsell] -set_property -dict {LOC BE17 IOSTANDARD LVCMOS12} [get_ports qsfp0_resetl] -set_property -dict {LOC BE20 IOSTANDARD LVCMOS12} [get_ports qsfp0_modprsl] -set_property -dict {LOC BE21 IOSTANDARD LVCMOS12} [get_ports qsfp0_intl] -set_property -dict {LOC BD18 IOSTANDARD LVCMOS12} [get_ports qsfp0_lpmode] -set_property -dict {LOC AT22 IOSTANDARD LVCMOS12} [get_ports qsfp0_refclk_reset] -set_property -dict {LOC AT20 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[0]}] -set_property -dict {LOC AU22 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[1]}] +set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 +set_property -dict {LOC BE16 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_modsell] +set_property -dict {LOC BE17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_resetl] +set_property -dict {LOC BE20 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_modprsl] +set_property -dict {LOC BE21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_intl] +set_property -dict {LOC BD18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_lpmode] +set_property -dict {LOC AT22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_reset] +set_property -dict {LOC AT20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[0]}] +set_property -dict {LOC AU22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[1]}] # 156.25 MHz MGT reference clock (from SI570) #create_clock -period 6.400 -name qsfp0_mgt_refclk_0 [get_ports qsfp0_mgt_refclk_0_p] @@ -96,34 +125,39 @@ set_property -dict {LOC AU22 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[1]}] # 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_output_delay 0 [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_false_path -from [get_ports {qsfp0_modprsl qsfp0_intl}] +set_input_delay 0 [get_ports {qsfp0_modprsl qsfp0_intl}] + set_property -dict {LOC U4 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 set_property -dict {LOC U9 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 set_property -dict {LOC T2 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 set_property -dict {LOC R4 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 set_property -dict {LOC R9 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 set_property -dict {LOC P2 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 set_property -dict {LOC P7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 -#set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 +set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 #set_property -dict {LOC T11 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U14.4 via U43.15 #set_property -dict {LOC T10 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U14.5 via U43.16 #set_property -dict {LOC P11 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U12.18 #set_property -dict {LOC P10 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U12.17 -set_property -dict {LOC AY20 IOSTANDARD LVCMOS12} [get_ports qsfp1_modsell] -set_property -dict {LOC BC18 IOSTANDARD LVCMOS12} [get_ports qsfp1_resetl] -set_property -dict {LOC BC19 IOSTANDARD LVCMOS12} [get_ports qsfp1_modprsl] -set_property -dict {LOC AV21 IOSTANDARD LVCMOS12} [get_ports qsfp1_intl] -set_property -dict {LOC AV22 IOSTANDARD LVCMOS12} [get_ports qsfp1_lpmode] -set_property -dict {LOC AR21 IOSTANDARD LVCMOS12} [get_ports qsfp1_refclk_reset] -set_property -dict {LOC AR22 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[0]}] -set_property -dict {LOC AU20 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[1]}] +set_property -dict {LOC AY20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +set_property -dict {LOC BC18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +set_property -dict {LOC BC19 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_modprsl] +set_property -dict {LOC AV21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_intl] +set_property -dict {LOC AV22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] +set_property -dict {LOC AR21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_reset] +set_property -dict {LOC AR22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[0]}] +set_property -dict {LOC AU20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[1]}] # 156.25 MHz MGT reference clock (from SI570) #create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] @@ -134,11 +168,21 @@ set_property -dict {LOC AU20 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[1]}] # 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) #create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + # I2C interface #set_property -dict {LOC BF19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_mux_reset] set_property -dict {LOC BF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_scl] set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 #set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 @@ -211,4 +255,5 @@ set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_p] - +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/example/AU280/fpga_10g/fpga.xdc b/example/AU280/fpga_10g/fpga.xdc index 897613b02..45ce3f16e 100644 --- a/example/AU280/fpga_10g/fpga.xdc +++ b/example/AU280/fpga_10g/fpga.xdc @@ -14,6 +14,8 @@ set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] +set_operating_conditions -design_power_budget 160 + # System clocks # 100 MHz (DDR4) #set_property -dict {LOC BJ43 IOSTANDARD LVDS} [get_ports clk_100mhz_0_p] @@ -38,34 +40,45 @@ set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] # Reset button set_property -dict {LOC L30 IOSTANDARD LVCMOS18} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # UART #set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart_txd] #set_property -dict {LOC B33 IOSTANDARD LVCMOS18} [get_ports usb_uart_rxd] +#set_false_path -to [get_ports {uart_txd}] +#set_output_delay 0 [get_ports {uart_txd}] +#set_false_path -from [get_ports {uart_rxd}] +#set_input_delay 0 [get_ports {uart_rxd}] + # HBM overtemp set_property -dict {LOC D32 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip] +set_false_path -to [get_ports {hbm_cattrip}] +set_output_delay 0 [get_ports {hbm_cattrip}] + # QSFP28 Interfaces -set_property -dict {LOC L53 } [get_ports qsfp0_rx1_p] ;# MGTYRXP0_134 GTYE3_CHANNEL_X0Y40 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC L54 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_134 GTYE3_CHANNEL_X0Y40 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC L48 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_134 GTYE3_CHANNEL_X0Y40 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC L49 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_134 GTYE3_CHANNEL_X0Y40 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC K51 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_134 GTYE3_CHANNEL_X0Y41 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC K52 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_134 GTYE3_CHANNEL_X0Y41 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC L44 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_134 GTYE3_CHANNEL_X0Y41 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC L45 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_134 GTYE3_CHANNEL_X0Y41 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC J53 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_134 GTYE3_CHANNEL_X0Y42 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC J54 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_134 GTYE3_CHANNEL_X0Y42 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC K46 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_134 GTYE3_CHANNEL_X0Y42 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC K47 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_134 GTYE3_CHANNEL_X0Y42 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC H51 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_134 GTYE3_CHANNEL_X0Y43 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC H52 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_134 GTYE3_CHANNEL_X0Y43 / GTYE3_COMMON_X0Y10 -set_property -dict {LOC J48 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_134 GTYE3_CHANNEL_X0Y43 / GTYE3_COMMON_X0Y10 -#set_property -dict {LOC J49 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_134 GTYE3_CHANNEL_X0Y43 / GTYE3_COMMON_X0Y10 +set_property -dict {LOC L53 } [get_ports qsfp0_rx1_p] ;# MGTYRXP0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC L54 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC L48 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC L49 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC K51 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC K52 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC L44 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC L45 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC J53 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC J54 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC K46 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC K47 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC H51 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC H52 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC J48 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +set_property -dict {LOC J49 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 #set_property -dict {LOC T42 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_134 from SI570 #set_property -dict {LOC T43 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_134 from SI570 set_property -dict {LOC R40 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_134 from SI546 -#set_property -dict {LOC R41 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_134 from SI546 +set_property -dict {LOC R41 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_134 from SI546 set_property -dict {LOC H32 IOSTANDARD LVCMOS18} [get_ports qsfp0_refclk_oe_b] set_property -dict {LOC G32 IOSTANDARD LVCMOS18} [get_ports qsfp0_refclk_fs] @@ -78,22 +91,25 @@ set_property -dict {LOC G32 IOSTANDARD LVCMOS18} [get_ports qsfp0_refclk_fs] # 161.1328125 MHz MGT reference clock (from SI546, fs = 1) create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] -set_property -dict {LOC G53 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_135 GTYE3_CHANNEL_X0Y44 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC G54 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_135 GTYE3_CHANNEL_X0Y44 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC G48 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_135 GTYE3_CHANNEL_X0Y44 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC G49 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_135 GTYE3_CHANNEL_X0Y44 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC F51 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_135 GTYE3_CHANNEL_X0Y45 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC F52 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_135 GTYE3_CHANNEL_X0Y45 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC E48 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_135 GTYE3_CHANNEL_X0Y45 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC E49 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_135 GTYE3_CHANNEL_X0Y45 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC E53 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_135 GTYE3_CHANNEL_X0Y46 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC E54 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_135 GTYE3_CHANNEL_X0Y46 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC C48 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_135 GTYE3_CHANNEL_X0Y46 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC C49 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_135 GTYE3_CHANNEL_X0Y46 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC D51 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_135 GTYE3_CHANNEL_X0Y47 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC D52 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_135 GTYE3_CHANNEL_X0Y47 / GTYE3_COMMON_X0Y11 -set_property -dict {LOC A49 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_135 GTYE3_CHANNEL_X0Y47 / GTYE3_COMMON_X0Y11 -#set_property -dict {LOC A50 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_135 GTYE3_CHANNEL_X0Y47 / GTYE3_COMMON_X0Y11 +set_false_path -to [get_ports {qsfp0_refclk_oe_b qsfp0_refclk_fs}] +set_output_delay 0 [get_ports {qsfp0_refclk_oe_b qsfp0_refclk_fs}] + +set_property -dict {LOC G53 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC G54 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC G48 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC G49 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC F51 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC F52 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC E48 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC E49 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC E53 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC E54 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC C48 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC C49 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC D51 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC D52 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC A49 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +set_property -dict {LOC A50 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 #set_property -dict {LOC P42 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_135 from SI570 #set_property -dict {LOC P43 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_135 from SI570 #set_property -dict {LOC M42 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_135 from SI546 @@ -110,6 +126,9 @@ set_property -dict {LOC G33 IOSTANDARD LVCMOS18} [get_ports qsfp1_refclk_fs] # 161.1328125 MHz MGT reference clock (from SI546, fs = 1) #create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp1_refclk_oe_b qsfp1_refclk_fs}] +set_output_delay 0 [get_ports {qsfp1_refclk_oe_b qsfp1_refclk_fs}] + # PCIe Interface #set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 #set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 @@ -191,4 +210,5 @@ set_property -dict {LOC G33 IOSTANDARD LVCMOS18} [get_ports qsfp1_refclk_fs] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] #create_clock -period 10 -name pcie_mgt_refclk_3 [get_ports pcie_refclk_3_p] - +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/example/AU50/fpga_10g/fpga.xdc b/example/AU50/fpga_10g/fpga.xdc index ce585b28d..e46f255f4 100644 --- a/example/AU50/fpga_10g/fpga.xdc +++ b/example/AU50/fpga_10g/fpga.xdc @@ -32,6 +32,9 @@ set_property -dict {LOC E18 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qs set_property -dict {LOC E16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_stat_g] set_property -dict {LOC F17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_stat_y] +set_false_path -to [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}] +set_output_delay 0 [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}] + # UART #set_property -dict {LOC BE26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart0_txd] #set_property -dict {LOC BF26 IOSTANDARD LVCMOS18} [get_ports usb_uart0_rxd] @@ -40,9 +43,28 @@ set_property -dict {LOC F17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qs #set_property -dict {LOC A19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart2_txd] #set_property -dict {LOC A18 IOSTANDARD LVCMOS18} [get_ports usb_uart2_rxd] +#set_false_path -to [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}] +#set_output_delay 0 [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}] +#set_false_path -from [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}] +#set_input_delay 0 [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}] + +# BMC +#set_property -dict {LOC C16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +#set_property -dict {LOC C17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +#set_property -dict {LOC BB25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +#set_property -dict {LOC BB26 IOSTANDARD LVCMOS18} [get_ports {msp_uart_rxd}] + +#set_false_path -to [get_ports {msp_uart_txd}] +#set_output_delay 0 [get_ports {msp_uart_txd}] +#set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}] +#set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}] + # HBM overtemp set_property -dict {LOC J18 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip] +set_false_path -to [get_ports {hbm_cattrip}] +set_output_delay 0 [get_ports {hbm_cattrip}] + # SI5394 (SI5394B-A10605-GM) # I2C address 0x68 # IN0: 161.1328125 MHz from qsfp_recclk @@ -56,25 +78,35 @@ set_property -dict {LOC J18 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip] #set_property -dict {LOC J16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_sda] #set_property -dict {LOC L19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_scl] +#set_false_path -to [get_ports {si5394_rst_b}] +#set_output_delay 0 [get_ports {si5394_rst_b}] +#set_false_path -from [get_ports {si5394_int_b si5394_lol_b si5394_los_b}] +#set_input_delay 0 [get_ports {si5394_int_b si5394_lol_b si5394_los_b}] + +#set_false_path -to [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_output_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_false_path -from [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_input_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}] + # QSFP28 Interfaces -set_property -dict {LOC J45 } [get_ports qsfp_rx1_p] ;# MGTYRXP0_131 GTYE3_CHANNEL_X0Y28 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC J46 } [get_ports qsfp_rx1_n] ;# MGTYRXN0_131 GTYE3_CHANNEL_X0Y28 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC D42 } [get_ports qsfp_tx1_p] ;# MGTYTXP0_131 GTYE3_CHANNEL_X0Y28 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC D43 } [get_ports qsfp_tx1_n] ;# MGTYTXN0_131 GTYE3_CHANNEL_X0Y28 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC G45 } [get_ports qsfp_rx2_p] ;# MGTYRXP1_131 GTYE3_CHANNEL_X0Y29 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC G46 } [get_ports qsfp_rx2_n] ;# MGTYRXN1_131 GTYE3_CHANNEL_X0Y29 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC C40 } [get_ports qsfp_tx2_p] ;# MGTYTXP1_131 GTYE3_CHANNEL_X0Y29 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC C41 } [get_ports qsfp_tx2_n] ;# MGTYTXN1_131 GTYE3_CHANNEL_X0Y29 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC F43 } [get_ports qsfp_rx3_p] ;# MGTYRXP2_131 GTYE3_CHANNEL_X0Y30 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC F44 } [get_ports qsfp_rx3_n] ;# MGTYRXN2_131 GTYE3_CHANNEL_X0Y30 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC B42 } [get_ports qsfp_tx3_p] ;# MGTYTXP2_131 GTYE3_CHANNEL_X0Y30 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC B43 } [get_ports qsfp_tx3_n] ;# MGTYTXN2_131 GTYE3_CHANNEL_X0Y30 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC E45 } [get_ports qsfp_rx4_p] ;# MGTYRXP3_131 GTYE3_CHANNEL_X0Y31 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC E46 } [get_ports qsfp_rx4_n] ;# MGTYRXN3_131 GTYE3_CHANNEL_X0Y31 / GTYE3_COMMON_X0Y7 -set_property -dict {LOC A40 } [get_ports qsfp_tx4_p] ;# MGTYTXP3_131 GTYE3_CHANNEL_X0Y31 / GTYE3_COMMON_X0Y7 -#set_property -dict {LOC A41 } [get_ports qsfp_tx4_n] ;# MGTYTXN3_131 GTYE3_CHANNEL_X0Y31 / GTYE3_COMMON_X0Y7 +set_property -dict {LOC J45 } [get_ports qsfp_rx1_p] ;# MGTYRXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC J46 } [get_ports qsfp_rx1_n] ;# MGTYRXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC D42 } [get_ports qsfp_tx1_p] ;# MGTYTXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC D43 } [get_ports qsfp_tx1_n] ;# MGTYTXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC G45 } [get_ports qsfp_rx2_p] ;# MGTYRXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC G46 } [get_ports qsfp_rx2_n] ;# MGTYRXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC C40 } [get_ports qsfp_tx2_p] ;# MGTYTXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC C41 } [get_ports qsfp_tx2_n] ;# MGTYTXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC F43 } [get_ports qsfp_rx3_p] ;# MGTYRXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC F44 } [get_ports qsfp_rx3_n] ;# MGTYRXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC B42 } [get_ports qsfp_tx3_p] ;# MGTYTXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC B43 } [get_ports qsfp_tx3_n] ;# MGTYTXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC E45 } [get_ports qsfp_rx4_p] ;# MGTYRXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC E46 } [get_ports qsfp_rx4_n] ;# MGTYRXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC A40 } [get_ports qsfp_tx4_p] ;# MGTYTXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC A41 } [get_ports qsfp_tx4_n] ;# MGTYTXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 set_property -dict {LOC N36 } [get_ports qsfp_mgt_refclk_0_p] ;# MGTREFCLK0P_131 from SI5394 OUT0 -#set_property -dict {LOC N37 } [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_131 from SI5394 OUT0 +set_property -dict {LOC N37 } [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_131 from SI5394 OUT0 #set_property -dict {LOC M38 } [get_ports qsfp_mgt_refclk_1_p] ;# MGTREFCLK1P_131 from SI5394 OUT2 #set_property -dict {LOC M39 } [get_ports qsfp_mgt_refclk_1_n] ;# MGTREFCLK1N_131 from SI5394 OUT2 #set_property -dict {LOC F19 IOSTANDARD LVDS} [get_ports qsfp_recclk_p] ;# to SI5394 IN0 @@ -167,4 +199,5 @@ create_clock -period 6.206 -name qsfp_mgt_refclk_0 [get_ports qsfp_mgt_refclk_0_ #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] #create_clock -period 10 -name pcie_mgt_refclk_3 [get_ports pcie_refclk_3_p] - +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/example/Arty/fpga/fpga.xdc b/example/Arty/fpga/fpga.xdc index c00c158cc..6c23386f2 100644 --- a/example/Arty/fpga/fpga.xdc +++ b/example/Arty/fpga/fpga.xdc @@ -30,21 +30,33 @@ set_property -dict {LOC J5 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC T9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led6] set_property -dict {LOC T10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led7] +set_false_path -to [get_ports {led0_r led0_g led0_b led1_r led1_g led1_b led2_r led2_g led2_b led3_r led3_g led3_b led4 led5 led6 led7}] +set_output_delay 0 [get_ports {led0_r led0_g led0_b led1_r led1_g led1_b led2_r led2_g led2_b led3_r led3_g led3_b led4 led5 led6 led7}] + # Reset button set_property -dict {LOC C2 IOSTANDARD LVCMOS33} [get_ports reset_n] +set_false_path -from [get_ports {reset_n}] +set_input_delay 0 [get_ports {reset_n}] + # Push buttons set_property -dict {LOC D9 IOSTANDARD LVCMOS33} [get_ports {btn[0]}] set_property -dict {LOC C9 IOSTANDARD LVCMOS33} [get_ports {btn[1]}] set_property -dict {LOC B9 IOSTANDARD LVCMOS33} [get_ports {btn[2]}] set_property -dict {LOC B8 IOSTANDARD LVCMOS33} [get_ports {btn[3]}] +set_false_path -from [get_ports {btn[*]}] +set_input_delay 0 [get_ports {btn[*]}] + # Toggle switches set_property -dict {LOC A8 IOSTANDARD LVCMOS33} [get_ports {sw[0]}] set_property -dict {LOC C11 IOSTANDARD LVCMOS33} [get_ports {sw[1]}] set_property -dict {LOC C10 IOSTANDARD LVCMOS33} [get_ports {sw[2]}] set_property -dict {LOC A10 IOSTANDARD LVCMOS33} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # GPIO # PMOD JA #set_property -dict {LOC G13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja1}] ;# PMOD JA pin 1 @@ -87,6 +99,11 @@ set_property -dict {LOC A10 IOSTANDARD LVCMOS33} [get_ports {sw[3]}] set_property -dict {LOC D10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports uart_txd] set_property -dict {LOC A9 IOSTANDARD LVCMOS33} [get_ports uart_rxd] +set_false_path -to [get_ports {uart_txd}] +set_output_delay 0 [get_ports {uart_txd}] +set_false_path -from [get_ports {uart_rxd}] +set_input_delay 0 [get_ports {uart_rxd}] + # Ethernet MII PHY set_property -dict {LOC F15 IOSTANDARD LVCMOS33} [get_ports phy_rx_clk] set_property -dict {LOC D18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[0]}] @@ -111,3 +128,10 @@ set_property -dict {LOC C16 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports create_clock -period 40.000 -name phy_rx_clk [get_ports phy_rx_clk] create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] +set_false_path -to [get_ports {phy_ref_clk phy_reset_n}] +set_output_delay 0 [get_ports {phy_ref_clk phy_reset_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] diff --git a/example/ExaNIC_X10/fpga/fpga.xdc b/example/ExaNIC_X10/fpga/fpga.xdc index 3713cdb76..f3c5ef2b0 100644 --- a/example/ExaNIC_X10/fpga/fpga.xdc +++ b/example/ExaNIC_X10/fpga/fpga.xdc @@ -23,6 +23,9 @@ set_property -dict {LOC D26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports { set_property -dict {LOC C23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sma_led[0]}] set_property -dict {LOC D23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sma_led[1]}] +set_false_path -to [get_ports {sfp_1_led[*] sfp_2_led[*] sma_led[*]}] +set_output_delay 0 [get_ports {sfp_1_led[*] sfp_2_led[*] sma_led[*]}] + # GPIO #set_property -dict {LOC W26 IOSTANDARD LVCMOS18} [get_ports gpio[0]] #set_property -dict {LOC Y26 IOSTANDARD LVCMOS18} [get_ports gpio[1]] @@ -31,21 +34,26 @@ set_property -dict {LOC D23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports { # SMA #set_property -dict {LOC B17 IOSTANDARD LVCMOS18} [get_ports sma_in] -#set_property -dict {LOC B16 IOSTANDARD LVCMOS18} [get_ports sma_out] -#set_property -dict {LOC B19 IOSTANDARD LVCMOS18} [get_ports sma_out_en] -#set_property -dict {LOC C16 IOSTANDARD LVCMOS18} [get_ports sma_term_en] +#set_property -dict {LOC B16 IOSTANDARD LVCMOS18 SLEW FAST DRIVE 12} [get_ports sma_out] +#set_property -dict {LOC B19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sma_out_en] +#set_property -dict {LOC C16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sma_term_en] -# SFP+ Interface -set_property -dict {LOC D2 } [get_ports sfp_1_rx_p] ;# MGTHTXN0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 -#set_property -dict {LOC D1 } [get_ports sfp_1_rx_n] ;# MGTHTXP0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 -set_property -dict {LOC E4 } [get_ports sfp_1_tx_p] ;# MGTHTXN0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 -#set_property -dict {LOC E3 } [get_ports sfp_1_tx_n] ;# MGTHTXP0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 -set_property -dict {LOC C4 } [get_ports sfp_2_rx_p] ;# MGTHTXN1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 -#set_property -dict {LOC C3 } [get_ports sfp_2_rx_n] ;# MGTHTXP1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 -set_property -dict {LOC D6 } [get_ports sfp_2_tx_p] ;# MGTHTXN1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 -#set_property -dict {LOC D5 } [get_ports sfp_2_tx_n] ;# MGTHTXP1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 +#set_false_path -to [get_ports {sma_out sma_term sma_term_en}] +#set_output_delay 0 [get_ports {sma_out sma_term sma_term_en}] +#set_false_path -from [get_ports {sma_in}] +#set_input_delay 0 [get_ports {sma_in}] + +# SFP+ Interfaces +set_property -dict {LOC D2 } [get_ports sfp_1_rx_p] ;# MGTHRXP0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC D1 } [get_ports sfp_1_rx_n] ;# MGTHRXN0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC E4 } [get_ports sfp_1_tx_p] ;# MGTHTXP0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC E3 } [get_ports sfp_1_tx_n] ;# MGTHTXN0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC C4 } [get_ports sfp_2_rx_p] ;# MGTHRXP1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC C3 } [get_ports sfp_2_rx_n] ;# MGTHRXN1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC D6 } [get_ports sfp_2_tx_p] ;# MGTHTXP1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 +set_property -dict {LOC D5 } [get_ports sfp_2_tx_n] ;# MGTHTXN1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3 set_property -dict {LOC H6 } [get_ports sfp_mgt_refclk_p] ;# MGTREFCLK0P_227 from X2 -#set_property -dict {LOC H5 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_227 from X2 +set_property -dict {LOC H5 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_227 from X2 set_property -dict {LOC AA12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable] set_property -dict {LOC W14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable] set_property -dict {LOC C24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_npres] @@ -61,43 +69,58 @@ set_property -dict {LOC D25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] +set_false_path -to [get_ports {sfp_1_tx_disable sfp_2_tx_disable sfp_1_rs sfp_2_rs}] +set_output_delay 0 [get_ports {sfp_1_tx_disable sfp_2_tx_disable sfp_1_rs sfp_2_rs}] +set_false_path -from [get_ports {sfp_1_npres sfp_2_npres sfp_1_los sfp_2_los}] +set_input_delay 0 [get_ports {sfp_1_npres sfp_2_npres sfp_1_los sfp_2_los}] + +#set_false_path -to [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_output_delay 0 [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_false_path -from [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_input_delay 0 [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] + # I2C interface #set_property -dict {LOC B26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl] #set_property -dict {LOC C26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda] +#set_false_path -to [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_output_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_false_path -from [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_input_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] + # PCIe Interface -#set_property -dict {LOC P2 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC P1 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC R4 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC R3 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC T2 } [get_ports {pcie_rx_p[1]}] ;# MGTHRXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC T1 } [get_ports {pcie_rx_n[1]}] ;# MGTHRXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC U4 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC U3 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC V2 } [get_ports {pcie_rx_p[2]}] ;# MGTHRXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC V1 } [get_ports {pcie_rx_n[2]}] ;# MGTHRXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC W4 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC W3 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC Y2 } [get_ports {pcie_rx_p[3]}] ;# MGTHRXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC Y1 } [get_ports {pcie_rx_n[3]}] ;# MGTHRXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC AA4 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC AA3 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 -#set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[4]}] ;# MGTHRXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[4]}] ;# MGTHRXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AB6 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AB5 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[5]}] ;# MGTHRXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[5]}] ;# MGTHRXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AC4 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AC3 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[6]}] ;# MGTHRXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[6]}] ;# MGTHRXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AD6 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AD5 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[7]}] ;# MGTHRXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[7]}] ;# MGTHRXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AF6 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 -#set_property -dict {LOC AF5 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC P2 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC P1 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC R4 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC R3 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC T2 } [get_ports {pcie_rx_p[1]}] ;# MGTHRXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC T1 } [get_ports {pcie_rx_n[1]}] ;# MGTHRXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC U4 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC U3 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC V2 } [get_ports {pcie_rx_p[2]}] ;# MGTHRXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC V1 } [get_ports {pcie_rx_n[2]}] ;# MGTHRXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC W4 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC W3 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC Y2 } [get_ports {pcie_rx_p[3]}] ;# MGTHRXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC Y1 } [get_ports {pcie_rx_n[3]}] ;# MGTHRXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC AA4 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC AA3 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +#set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[4]}] ;# MGTHRXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[4]}] ;# MGTHRXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AB6 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AB5 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[5]}] ;# MGTHRXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[5]}] ;# MGTHRXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AC4 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AC3 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[6]}] ;# MGTHRXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[6]}] ;# MGTHRXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AD6 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AD5 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[7]}] ;# MGTHRXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[7]}] ;# MGTHRXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AF6 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +#set_property -dict {LOC AF5 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 #set_property -dict {LOC T6 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK0P_225 #set_property -dict {LOC T5 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK0N_225 #set_property -dict {LOC AC22 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] @@ -105,7 +128,10 @@ create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] -# Flash +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + +# BPI flash #set_property -dict {LOC AE10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[0]}] #set_property -dict {LOC AC8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[1]}] #set_property -dict {LOC AD10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[2]}] @@ -150,3 +176,8 @@ create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] #set_property -dict {LOC AC14 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_oe_n}] #set_property -dict {LOC AB10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_we_n}] #set_property -dict {LOC Y10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_adv_n}] + +#set_false_path -to [get_ports {flash_dq[*] flash_addr[*] flash_region flash_ce_n flash_oe_n flash_we_n flash_adv_n}] +#set_output_delay 0 [get_ports {flash_dq[*] flash_addr[*] flash_region flash_ce_n flash_oe_n flash_we_n flash_adv_n}] +#set_false_path -from [get_ports {flash_dq[*]}] +#set_input_delay 0 [get_ports {flash_dq[*]}] diff --git a/example/ExaNIC_X25/fpga_10g/fpga.xdc b/example/ExaNIC_X25/fpga_10g/fpga.xdc index 91567ddb5..0a25aea54 100644 --- a/example/ExaNIC_X25/fpga_10g/fpga.xdc +++ b/example/ExaNIC_X25/fpga_10g/fpga.xdc @@ -24,6 +24,9 @@ set_property -dict {LOC H13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports { set_property -dict {LOC J14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sma_led[0]}] set_property -dict {LOC G12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sma_led[1]}] +set_false_path -to [get_ports {sfp_1_led[*] sfp_2_led[*] sma_led[*]}] +set_output_delay 0 [get_ports {sfp_1_led[*] sfp_2_led[*] sma_led[*]}] + # GPIO #set_property -dict {LOC F9 IOSTANDARD LVCMOS18} [get_ports gpio[0]] #set_property -dict {LOC F10 IOSTANDARD LVCMOS18} [get_ports gpio[1]] @@ -32,24 +35,29 @@ set_property -dict {LOC G12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports { # SMA #set_property -dict {LOC A14 IOSTANDARD LVCMOS33} [get_ports sma_in] -#set_property -dict {LOC A12 IOSTANDARD LVCMOS33} [get_ports sma_out] -#set_property -dict {LOC A13 IOSTANDARD LVCMOS33} [get_ports sma_out_en] -#set_property -dict {LOC B12 IOSTANDARD LVCMOS33} [get_ports sma_term_en] +#set_property -dict {LOC A12 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports sma_out] +#set_property -dict {LOC A13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports sma_out_en] +#set_property -dict {LOC B12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports sma_term_en] + +#set_false_path -to [get_ports {sma_out sma_term sma_term_en}] +#set_output_delay 0 [get_ports {sma_out sma_term sma_term_en}] +#set_false_path -from [get_ports {sma_in}] +#set_input_delay 0 [get_ports {sma_in}] # Config #set_property -dict {LOC C14 IOSTANDARD LVCMOS33} [get_ports ddr_npres] # SFP28 Interfaces -set_property -dict {LOC D2 } [get_ports sfp_1_rx_p] ;# MGTYRXP0_227 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC D1 } [get_ports sfp_1_rx_n] ;# MGTYRXN0_227 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC A4 } [get_ports sfp_2_rx_p] ;# MGTYRXP3_227 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC A3 } [get_ports sfp_2_rx_n] ;# MGTYRXN3_227 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC F7 } [get_ports sfp_1_tx_p] ;# MGTYTXP0_227 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC F6 } [get_ports sfp_1_tx_n] ;# MGTYTXN0_227 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC B7 } [get_ports sfp_2_tx_p] ;# MGTYTXP3_227 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC B6 } [get_ports sfp_2_tx_n] ;# MGTYTXN3_227 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -set_property -dict {LOC K7 } [get_ports sfp_mgt_refclk_p] ;# MGTREFCLK0P_227 from X2 -#set_property -dict {LOC K6 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_227 from X2 +set_property -dict {LOC D2 } [get_ports sfp_1_rx_p] ;# MGTYRXP0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC D1 } [get_ports sfp_1_rx_n] ;# MGTYRXN0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC A4 } [get_ports sfp_2_rx_p] ;# MGTYRXP3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC A3 } [get_ports sfp_2_rx_n] ;# MGTYRXN3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC F7 } [get_ports sfp_1_tx_p] ;# MGTYTXP0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC F6 } [get_ports sfp_1_tx_n] ;# MGTYTXN0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC B7 } [get_ports sfp_2_tx_p] ;# MGTYTXP3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC B6 } [get_ports sfp_2_tx_n] ;# MGTYTXN3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC K7 } [get_ports sfp_mgt_refclk_p] ;# MGTREFCLK0P_227 from X2 +set_property -dict {LOC K6 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_227 from X2 set_property -dict {LOC AC17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable] set_property -dict {LOC AA17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable] set_property -dict {LOC F12 IOSTANDARD LVCMOS33 PULLUP true} [get_ports sfp_1_npres] @@ -65,51 +73,69 @@ set_property -dict {LOC H14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] +set_false_path -to [get_ports {sfp_1_tx_disable sfp_2_tx_disable sfp_1_rs sfp_2_rs}] +set_output_delay 0 [get_ports {sfp_1_tx_disable sfp_2_tx_disable sfp_1_rs sfp_2_rs}] +set_false_path -from [get_ports {sfp_1_npres sfp_2_npres sfp_1_los sfp_2_los}] +set_input_delay 0 [get_ports {sfp_1_npres sfp_2_npres sfp_1_los sfp_2_los}] + +#set_false_path -to [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_output_delay 0 [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_false_path -from [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_input_delay 0 [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] + # I2C interface #set_property -dict {LOC B9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl] #set_property -dict {LOC A9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda] +#set_false_path -to [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_output_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_false_path -from [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_input_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] + # PCIe Interface -#set_property -dict {LOC P2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_225 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC P1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_225 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC R5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC R4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC T2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_225 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC T1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_225 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC U5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC U4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC V2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_225 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC V1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_225 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC W5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC W4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC Y2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_225 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC Y1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_225 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC AA5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC AA4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1 -#set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_224 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_224 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AC5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AC4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_224 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_224 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AD7 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AD6 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_224 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_224 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AE9 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AE8 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 -#set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0 +#set_property -dict {LOC P2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC P1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC R5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC R4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC T2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC T1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC U5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC U4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC V2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC V1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC W5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC W4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC Y2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC Y1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC AA5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC AA4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +#set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AC5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AC4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AD7 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AD6 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AE9 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AE8 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +#set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 #set_property -dict {LOC V7 } [get_ports pcie_refclk_p] ;# MGTREFCLK0P_225 #set_property -dict {LOC V6 } [get_ports pcie_refclk_n] ;# MGTREFCLK0N_225 #set_property -dict {LOC T19 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_refclk_p] -# Flash +# BPI flash #set_property -dict {LOC AF20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[0]}] #set_property -dict {LOC AE18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[1]}] #set_property -dict {LOC AF19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[2]}] @@ -155,3 +181,7 @@ create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] #set_property -dict {LOC AB20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_we_n}] #set_property -dict {LOC AF23 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] +#set_false_path -to [get_ports {flash_dq[*] flash_addr[*] flash_region flash_ce_n flash_oe_n flash_we_n flash_adv_n}] +#set_output_delay 0 [get_ports {flash_dq[*] flash_addr[*] flash_region flash_ce_n flash_oe_n flash_we_n flash_adv_n}] +#set_false_path -from [get_ports {flash_dq[*]}] +#set_input_delay 0 [get_ports {flash_dq[*]}] diff --git a/example/KC705/fpga_gmii/fpga.xdc b/example/KC705/fpga_gmii/fpga.xdc index 40ec7e787..3b4484e67 100644 --- a/example/KC705/fpga_gmii/fpga.xdc +++ b/example/KC705/fpga_gmii/fpga.xdc @@ -22,9 +22,15 @@ set_property -dict {LOC G19 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC E18 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[6]}] set_property -dict {LOC F16 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AB7 IOSTANDARD LVCMOS15} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC AA12 IOSTANDARD LVCMOS15} [get_ports btnu] set_property -dict {LOC AC6 IOSTANDARD LVCMOS15} [get_ports btnl] @@ -32,18 +38,29 @@ set_property -dict {LOC AB12 IOSTANDARD LVCMOS15} [get_ports btnd] set_property -dict {LOC AG5 IOSTANDARD LVCMOS15} [get_ports btnr] set_property -dict {LOC G12 IOSTANDARD LVCMOS25} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # Toggle switches set_property -dict {LOC Y29 IOSTANDARD LVCMOS25} [get_ports {sw[0]}] set_property -dict {LOC W29 IOSTANDARD LVCMOS25} [get_ports {sw[1]}] set_property -dict {LOC AA28 IOSTANDARD LVCMOS25} [get_ports {sw[2]}] set_property -dict {LOC Y28 IOSTANDARD LVCMOS25} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART set_property -dict {LOC K24 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_txd] set_property -dict {LOC M19 IOSTANDARD LVCMOS25} [get_ports uart_rxd] set_property -dict {LOC L27 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_rts] set_property -dict {LOC K23 IOSTANDARD LVCMOS25} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet GMII PHY set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] ;# from U37.C1 RXCLK set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] ;# from U37.B2 RXD0 @@ -83,3 +100,12 @@ create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] #create_clock -period 8.000 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +set_false_path -to [get_ports {phy_reset_n}] +set_output_delay 0 [get_ports {phy_reset_n}] +set_false_path -from [get_ports {phy_int_n}] +set_input_delay 0 [get_ports {phy_int_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] diff --git a/example/KC705/fpga_rgmii/fpga.xdc b/example/KC705/fpga_rgmii/fpga.xdc index 816827e0f..1f6408855 100644 --- a/example/KC705/fpga_rgmii/fpga.xdc +++ b/example/KC705/fpga_rgmii/fpga.xdc @@ -22,9 +22,15 @@ set_property -dict {LOC G19 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC E18 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[6]}] set_property -dict {LOC F16 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AB7 IOSTANDARD LVCMOS15} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC AA12 IOSTANDARD LVCMOS15} [get_ports btnu] set_property -dict {LOC AC6 IOSTANDARD LVCMOS15} [get_ports btnl] @@ -32,18 +38,29 @@ set_property -dict {LOC AB12 IOSTANDARD LVCMOS15} [get_ports btnd] set_property -dict {LOC AG5 IOSTANDARD LVCMOS15} [get_ports btnr] set_property -dict {LOC G12 IOSTANDARD LVCMOS25} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # Toggle switches set_property -dict {LOC Y29 IOSTANDARD LVCMOS25} [get_ports {sw[0]}] set_property -dict {LOC W29 IOSTANDARD LVCMOS25} [get_ports {sw[1]}] set_property -dict {LOC AA28 IOSTANDARD LVCMOS25} [get_ports {sw[2]}] set_property -dict {LOC Y28 IOSTANDARD LVCMOS25} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART set_property -dict {LOC K24 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_txd] set_property -dict {LOC M19 IOSTANDARD LVCMOS25} [get_ports uart_rxd] set_property -dict {LOC L27 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_rts] set_property -dict {LOC K23 IOSTANDARD LVCMOS25} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet GMII PHY set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] ;# from U37.C1 RXCLK set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] ;# from U37.B2 RXD0 @@ -83,3 +100,12 @@ set_property -dict {LOC N30 IOSTANDARD LVCMOS25} [get_ports phy_int_n] ;# from create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] #create_clock -period 8.000 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +set_false_path -to [get_ports {phy_reset_n}] +set_output_delay 0 [get_ports {phy_reset_n}] +set_false_path -from [get_ports {phy_int_n}] +set_input_delay 0 [get_ports {phy_int_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] diff --git a/example/KC705/fpga_sgmii/fpga.xdc b/example/KC705/fpga_sgmii/fpga.xdc index cede2589d..f384048d6 100644 --- a/example/KC705/fpga_sgmii/fpga.xdc +++ b/example/KC705/fpga_sgmii/fpga.xdc @@ -22,9 +22,15 @@ set_property -dict {LOC G19 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC E18 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[6]}] set_property -dict {LOC F16 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AB7 IOSTANDARD LVCMOS15} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC AA12 IOSTANDARD LVCMOS15} [get_ports btnu] set_property -dict {LOC AC6 IOSTANDARD LVCMOS15} [get_ports btnl] @@ -32,18 +38,29 @@ set_property -dict {LOC AB12 IOSTANDARD LVCMOS15} [get_ports btnd] set_property -dict {LOC AG5 IOSTANDARD LVCMOS15} [get_ports btnr] set_property -dict {LOC G12 IOSTANDARD LVCMOS25} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # Toggle switches set_property -dict {LOC Y29 IOSTANDARD LVCMOS25} [get_ports {sw[0]}] set_property -dict {LOC W29 IOSTANDARD LVCMOS25} [get_ports {sw[1]}] set_property -dict {LOC AA28 IOSTANDARD LVCMOS25} [get_ports {sw[2]}] set_property -dict {LOC Y28 IOSTANDARD LVCMOS25} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART set_property -dict {LOC K24 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_txd] set_property -dict {LOC M19 IOSTANDARD LVCMOS25} [get_ports uart_rxd] set_property -dict {LOC L27 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports uart_rts] set_property -dict {LOC K23 IOSTANDARD LVCMOS25} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet GMII PHY #set_property -dict {LOC U27 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] ;# from U37.C1 RXCLK #set_property -dict {LOC U30 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] ;# from U37.B2 RXD0 @@ -83,3 +100,12 @@ set_property -dict {LOC N30 IOSTANDARD LVCMOS25} [get_ports phy_int_n] ;# from #create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] create_clock -period 8.000 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +set_false_path -to [get_ports {phy_reset_n}] +set_output_delay 0 [get_ports {phy_reset_n}] +set_false_path -from [get_ports {phy_int_n}] +set_input_delay 0 [get_ports {phy_int_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] diff --git a/example/NetFPGA_SUME/fpga/fpga.xdc b/example/NetFPGA_SUME/fpga/fpga.xdc index 3f42bd7bf..d5188a5c0 100644 --- a/example/NetFPGA_SUME/fpga/fpga.xdc +++ b/example/NetFPGA_SUME/fpga/fpga.xdc @@ -39,32 +39,38 @@ set_property -dict {LOC K32 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports set_property -dict {LOC AR22 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[0]}] set_property -dict {LOC AR23 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {led[1]}] +set_false_path -to [get_ports {sfp_1_led[*] sfp_2_led[*] sfp_3_led[*] sfp_4_led[*] led[*]}] +set_output_delay 0 [get_ports {sfp_1_led[*] sfp_2_led[*] sfp_3_led[*] sfp_4_led[*] led[*]}] + # Push buttons set_property -dict {LOC AR13 IOSTANDARD LVCMOS15} [get_ports {btn[0]}] set_property -dict {LOC BB12 IOSTANDARD LVCMOS15} [get_ports {btn[1]}] +set_false_path -from [get_ports {btn[*]}] +set_input_delay 0 [get_ports {btn[*]}] + # SFP+ Interfaces -set_property -dict {LOC A6 } [get_ports sfp_1_rx_p] ;# MGTHRXN3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC A5 } [get_ports sfp_1_rx_n] ;# MGTHRXP3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC B4 } [get_ports sfp_1_tx_p] ;# MGTHTXN3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC B3 } [get_ports sfp_1_tx_n] ;# MGTHTXP3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC B8 } [get_ports sfp_2_rx_p] ;# MGTHRXN2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC B7 } [get_ports sfp_2_rx_n] ;# MGTHRXP2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC C2 } [get_ports sfp_2_tx_p] ;# MGTHTXN2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC C1 } [get_ports sfp_2_tx_n] ;# MGTHTXP2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC C6 } [get_ports sfp_3_rx_p] ;# MGTHRXN1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC C5 } [get_ports sfp_3_rx_n] ;# MGTHRXP1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC D4 } [get_ports sfp_3_tx_p] ;# MGTHTXN1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC D3 } [get_ports sfp_3_tx_n] ;# MGTHTXP1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC D8 } [get_ports sfp_4_rx_p] ;# MGTHRXN0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC D7 } [get_ports sfp_4_rx_n] ;# MGTHRXP0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 -set_property -dict {LOC E2 } [get_ports sfp_4_tx_p] ;# MGTHTXN0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 -#set_property -dict {LOC E1 } [get_ports sfp_4_tx_n] ;# MGTHTXP0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC A6 } [get_ports sfp_1_rx_p] ;# MGTHRXP3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC A5 } [get_ports sfp_1_rx_n] ;# MGTHRXN3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC B4 } [get_ports sfp_1_tx_p] ;# MGTHTXP3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC B3 } [get_ports sfp_1_tx_n] ;# MGTHTXN3_119 GTHE2_CHANNEL_X1Y39 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC B8 } [get_ports sfp_2_rx_p] ;# MGTHRXP2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC B7 } [get_ports sfp_2_rx_n] ;# MGTHRXN2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC C2 } [get_ports sfp_2_tx_p] ;# MGTHTXP2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC C1 } [get_ports sfp_2_tx_n] ;# MGTHTXN2_119 GTHE2_CHANNEL_X1Y38 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC C6 } [get_ports sfp_3_rx_p] ;# MGTHRXP1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC C5 } [get_ports sfp_3_rx_n] ;# MGTHRXN1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC D4 } [get_ports sfp_3_tx_p] ;# MGTHTXP1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC D3 } [get_ports sfp_3_tx_n] ;# MGTHTXN1_119 GTHE2_CHANNEL_X1Y37 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC D8 } [get_ports sfp_4_rx_p] ;# MGTHRXP0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC D7 } [get_ports sfp_4_rx_n] ;# MGTHRXN0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC E2 } [get_ports sfp_4_tx_p] ;# MGTHTXP0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 +set_property -dict {LOC E1 } [get_ports sfp_4_tx_n] ;# MGTHTXN0_119 GTHE2_CHANNEL_X1Y36 / GTHE2_COMMON_X1Y9 set_property -dict {LOC E10 } [get_ports sfp_mgt_refclk_p] ;# MGTREFCLK0P_118 from IC20.28 set_property -dict {LOC E9 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_118 from IC20.29 #set_property -dict {LOC AW32 IOSTANDARD LVDS} [get_ports sfp_recclk_p] ;# to IC20.16 #set_property -dict {LOC AW33 IOSTANDARD LVDS} [get_ports sfp_recclk_n] ;# to IC20.17 -set_property -dict {LOC BA29 IOSTANDARD LVCMOS18} [get_ports sfp_clk_rst] +set_property -dict {LOC BA29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_clk_rst] #set_property -dict {LOC AM29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_clk_alarm_b] set_property -dict {LOC N18 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_1_mod_detect] set_property -dict {LOC L19 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_2_mod_detect] @@ -94,11 +100,31 @@ set_property -dict {LOC J26 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_t # 156.25 MHz MGT reference clock #create_clock -period 6.4 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] +set_false_path -to [get_ports {sfp_clk_rst}] +set_output_delay 0 [get_ports {sfp_clk_rst}] +#set_false_path -from [get_ports {sfp_clk_alarm_b}] +#set_input_delay 0 [get_ports {sfp_clk_alarm_b}] +set_false_path -from [get_ports {sfp_1_mod_detect sfp_2_mod_detect sfp_3_mod_detect sfp_4_mod_detect}] +set_input_delay 0 [get_ports {sfp_1_mod_detect sfp_2_mod_detect sfp_3_mod_detect sfp_4_mod_detect}] +set_false_path -to [get_ports {sfp_1_rs[*] sfp_2_rs[*] sfp_3_rs[*] sfp_4_rs[*]}] +set_output_delay 0 [get_ports {sfp_1_rs[*] sfp_2_rs[*] sfp_3_rs[*] sfp_4_rs[*]}] +set_false_path -from [get_ports {get_ports sfp_1_los sfp_2_los sfp_3_los sfp_4_los}] +set_input_delay 0 [get_ports {get_ports sfp_1_los sfp_2_los sfp_3_los sfp_4_los}] +set_false_path -to [get_ports {get_ports sfp_1_tx_disable sfp_2_tx_disable sfp_3_tx_disable sfp_4_tx_disable}] +set_output_delay 0 [get_ports {get_ports sfp_1_tx_disable sfp_2_tx_disable sfp_3_tx_disable sfp_4_tx_disable}] +set_false_path -from [get_ports {get_ports sfp_1_tx_fault sfp_2_tx_fault sfp_3_tx_fault get_ports sfp_4_tx_fault}] +set_input_delay 0 [get_ports {get_ports sfp_1_tx_fault sfp_2_tx_fault sfp_3_tx_fault get_ports sfp_4_tx_fault}] + # I2C interface set_property -dict {LOC AK24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports i2c_scl] set_property -dict {LOC AK25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports i2c_sda] set_property -dict {LOC AM39 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports i2c_mux_reset] +set_false_path -to [get_ports {i2c_sda i2c_scl i2c_mux_reset}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl i2c_mux_reset}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC Y4 } [get_ports {pcie_rx_p[0]}] ;# MGTHTXP3_115 GTHE2_CHANNEL_X1Y23 / GTHE2_COMMON_X1Y5 #set_property -dict {LOC Y3 } [get_ports {pcie_rx_n[0]}] ;# MGTHTXN3_115 GTHE2_CHANNEL_X1Y23 / GTHE2_COMMON_X1Y5 @@ -139,3 +165,6 @@ set_property -dict {LOC AM39 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + diff --git a/example/NexysVideo/fpga/fpga.xdc b/example/NexysVideo/fpga/fpga.xdc index 2b5c9d3cd..05cd5d125 100644 --- a/example/NexysVideo/fpga/fpga.xdc +++ b/example/NexysVideo/fpga/fpga.xdc @@ -20,9 +20,15 @@ set_property -dict {LOC W16 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports { set_property -dict {LOC W15 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[6]}] set_property -dict {LOC Y13 IOSTANDARD LVCMOS25 SLEW SLOW DRIVE 12} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC G4 IOSTANDARD LVCMOS15} [get_ports reset_n] +set_false_path -from [get_ports {reset_n}] +set_input_delay 0 [get_ports {reset_n}] + # Push buttons set_property -dict {LOC F15 IOSTANDARD LVCMOS12} [get_ports btnu] set_property -dict {LOC C22 IOSTANDARD LVCMOS12} [get_ports btnl] @@ -30,6 +36,9 @@ set_property -dict {LOC D22 IOSTANDARD LVCMOS12} [get_ports btnd] set_property -dict {LOC D14 IOSTANDARD LVCMOS12} [get_ports btnr] set_property -dict {LOC B22 IOSTANDARD LVCMOS12} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # Toggle switches set_property -dict {LOC E22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC F21 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] @@ -40,10 +49,18 @@ set_property -dict {LOC J16 IOSTANDARD LVCMOS12} [get_ports {sw[5]}] set_property -dict {LOC K13 IOSTANDARD LVCMOS12} [get_ports {sw[6]}] set_property -dict {LOC M17 IOSTANDARD LVCMOS12} [get_ports {sw[7]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART set_property -dict {LOC AA19 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports uart_txd] set_property -dict {LOC V18 IOSTANDARD LVCMOS33} [get_ports uart_rxd] +set_false_path -to [get_ports {uart_txd}] +set_output_delay 0 [get_ports {uart_txd}] +set_false_path -from [get_ports {uart_rxd}] +set_input_delay 0 [get_ports {uart_rxd}] + # Gigabit Ethernet RGMII PHY set_property -dict {LOC V13 IOSTANDARD LVCMOS25} [get_ports phy_rx_clk] set_property -dict {LOC AB16 IOSTANDARD LVCMOS25} [get_ports {phy_rxd[0]}] @@ -65,3 +82,12 @@ set_property -dict {LOC W14 IOSTANDARD LVCMOS25} [get_ports phy_pme_n] create_clock -period 8.000 -name phy_rx_clk [get_ports phy_rx_clk] +set_false_path -to [get_ports {phy_reset_n}] +set_output_delay 0 [get_ports {phy_reset_n}] +set_false_path -from [get_ports {phy_int_n phy_pme_n}] +set_input_delay 0 [get_ports {phy_int_n phy_pme_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] diff --git a/example/VCU108/fpga_10g/fpga.xdc b/example/VCU108/fpga_10g/fpga.xdc index 934fdab3f..8a45c7706 100644 --- a/example/VCU108/fpga_10g/fpga.xdc +++ b/example/VCU108/fpga_10g/fpga.xdc @@ -38,9 +38,15 @@ set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AY35 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC E36 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC E34 IOSTANDARD LVCMOS12} [get_ports btnu] set_property -dict {LOC M22 IOSTANDARD LVCMOS12} [get_ports btnl] @@ -48,18 +54,55 @@ set_property -dict {LOC D9 IOSTANDARD LVCMOS12} [get_ports btnd] set_property -dict {LOC A10 IOSTANDARD LVCMOS12} [get_ports btnr] set_property -dict {LOC AW27 IOSTANDARD LVCMOS12} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC BC40 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC C37 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC C38 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC BC14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC BA10 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC BB16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC BC13 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC BF7 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AW12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC BC16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC P22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC N22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC J20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC K24 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC J24 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC T23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC R23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + # UART set_property -dict {LOC BE24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC BC24 IOSTANDARD LVCMOS18} [get_ports uart_rxd] set_property -dict {LOC BF24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] set_property -dict {LOC BD22 IOSTANDARD LVCMOS18} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet SGMII PHY set_property -dict {LOC AR24 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_rx_p] set_property -dict {LOC AT24 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_rx_n] @@ -73,44 +116,64 @@ set_property -dict {LOC AT21 IOSTANDARD LVCMOS18} [get_ports phy_int_n] #set_property -dict {LOC AV21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_mdc] # 625 MHz ref clock from SGMII PHY -create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +#create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] + +set_false_path -to [get_ports {phy_reset_n}] +set_output_delay 0 [get_ports {phy_reset_n}] +set_false_path -from [get_ports {phy_int_n}] +set_input_delay 0 [get_ports {phy_int_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] # QSFP+ Interface set_property -dict {LOC AG45} [get_ports qsfp_rx1_p] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AG46} [get_ports qsfp_rx1_n] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AG46} [get_ports qsfp_rx1_n] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AK42} [get_ports qsfp_tx1_p] ;# MGTYTXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AK43} [get_ports qsfp_tx1_n] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AK43} [get_ports qsfp_tx1_n] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AF43} [get_ports qsfp_rx2_p] ;# MGTYRXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AF44} [get_ports qsfp_rx2_n] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AF44} [get_ports qsfp_rx2_n] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AJ40} [get_ports qsfp_tx2_p] ;# MGTYTXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AJ41} [get_ports qsfp_tx2_n] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AJ41} [get_ports qsfp_tx2_n] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AE45} [get_ports qsfp_rx3_p] ;# MGTYRXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AE46} [get_ports qsfp_rx3_n] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AE46} [get_ports qsfp_rx3_n] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AG40} [get_ports qsfp_tx3_p] ;# MGTYTXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AG41} [get_ports qsfp_tx3_n] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AG41} [get_ports qsfp_tx3_n] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AD43} [get_ports qsfp_rx4_p] ;# MGTYRXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AD44} [get_ports qsfp_rx4_n] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AD44} [get_ports qsfp_rx4_n] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AE40} [get_ports qsfp_tx4_p] ;# MGTYTXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 -#set_property -dict {LOC AE41} [get_ports qsfp_tx4_n] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +set_property -dict {LOC AE41} [get_ports qsfp_tx4_n] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 set_property -dict {LOC AF38} [get_ports qsfp_mgt_refclk_0_p] ;# MGTREFCLK0P_127 from U32 SI570 via U102 SI53340 -#set_property -dict {LOC AF39} [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_127 from U32 SI570 via U102 SI53340 +set_property -dict {LOC AF39} [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_127 from U32 SI570 via U102 SI53340 #set_property -dict {LOC AD38} [get_ports qsfp_mgt_refclk_1_p] ;# MGTREFCLK1P_127 from U57 CKOUT2 SI5328 #set_property -dict {LOC AD39} [get_ports qsfp_mgt_refclk_1_n] ;# MGTREFCLK1N_127 from U57 CKOUT2 SI5328 #set_property -dict {LOC AG34 IOSTANDARD LVDS} [get_ports qsfp_recclk_p] ;# to U57 CKIN1 SI5328 #set_property -dict {LOC AH35 IOSTANDARD LVDS} [get_ports qsfp_recclk_n] ;# to U57 CKIN1 SI5328 -set_property -dict {LOC AL24 IOSTANDARD LVCMOS18} [get_ports qsfp_modsell] -set_property -dict {LOC AM24 IOSTANDARD LVCMOS18} [get_ports qsfp_resetl] -set_property -dict {LOC AL25 IOSTANDARD LVCMOS18} [get_ports qsfp_modprsl] -set_property -dict {LOC AL21 IOSTANDARD LVCMOS18} [get_ports qsfp_intl] -set_property -dict {LOC AM21 IOSTANDARD LVCMOS18} [get_ports qsfp_lpmode] +set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_modsell] +set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_resetl] +set_property -dict {LOC AL25 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_modprsl] +set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_intl] +set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_lpmode] # 156.25 MHz MGT reference clock create_clock -period 6.400 -name qsfp_mgt_refclk_0 [get_ports qsfp_mgt_refclk_0_p] +set_false_path -to [get_ports {qsfp_modsell qsfp_resetl qsfp_lpmode}] +set_output_delay 0 [get_ports {qsfp_modsell qsfp_resetl qsfp_lpmode}] +set_false_path -from [get_ports {qsfp_modprsl qsfp_intl}] +set_input_delay 0 [get_ports {qsfp_modprsl qsfp_intl}] + # I2C interface set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AJ4 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 #set_property -dict {LOC AJ3 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 @@ -151,7 +214,10 @@ set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] -# Flash +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + +# BPI flash #set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[4]}] #set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[5]}] #set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[6]}] @@ -195,4 +261,7 @@ set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i #set_property -dict {LOC AW17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] #set_property -dict {LOC BC23 IOSTANDARD LVCMOS18} [get_ports {flash_wait}] - +#set_false_path -to [get_ports {flash_dq[*] flash_addr[*] flash_region[*] flash_oe_n flash_we_n flash_adv_n}] +#set_output_delay 0 [get_ports {flash_dq[*] flash_addr[*] flash_region[*] flash_oe_n flash_we_n flash_adv_n}] +#set_false_path -from [get_ports {flash_dq[*] flash_wait}] +#set_input_delay 0 [get_ports {flash_dq[*] flash_wait}] diff --git a/example/VCU108/fpga_1g/fpga.xdc b/example/VCU108/fpga_1g/fpga.xdc index 163c9a1bd..03f163a5c 100644 --- a/example/VCU108/fpga_1g/fpga.xdc +++ b/example/VCU108/fpga_1g/fpga.xdc @@ -38,9 +38,15 @@ set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AY35 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC E36 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC E34 IOSTANDARD LVCMOS12} [get_ports btnu] set_property -dict {LOC M22 IOSTANDARD LVCMOS12} [get_ports btnl] @@ -48,18 +54,55 @@ set_property -dict {LOC D9 IOSTANDARD LVCMOS12} [get_ports btnd] set_property -dict {LOC A10 IOSTANDARD LVCMOS12} [get_ports btnr] set_property -dict {LOC AW27 IOSTANDARD LVCMOS12} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC BC40 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC C37 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC C38 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC BC14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC BA10 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC BB16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC BC13 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC BF7 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AW12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC BC16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC P22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC N22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC J20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC K24 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC J24 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC T23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC R23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + # UART set_property -dict {LOC BE24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC BC24 IOSTANDARD LVCMOS18} [get_ports uart_rxd] set_property -dict {LOC BF24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] set_property -dict {LOC BD22 IOSTANDARD LVCMOS18} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet SGMII PHY set_property -dict {LOC AR24 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_rx_p] set_property -dict {LOC AT24 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_rx_n] @@ -73,7 +116,17 @@ set_property -dict {LOC AT21 IOSTANDARD LVCMOS18} [get_ports phy_int_n] #set_property -dict {LOC AV21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_mdc] # 625 MHz ref clock from SGMII PHY -create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +#create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] + +set_false_path -to [get_ports {phy_reset_n}] +set_output_delay 0 [get_ports {phy_reset_n}] +set_false_path -from [get_ports {phy_int_n}] +set_input_delay 0 [get_ports {phy_int_n}] + +#set_false_path -to [get_ports {phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_mdio}] +#set_input_delay 0 [get_ports {phy_mdio}] # QSFP+ Interface #set_property -dict {LOC AG45} [get_ports qsfp_rx1_p] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 @@ -98,19 +151,29 @@ create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] #set_property -dict {LOC AD39} [get_ports qsfp_mgt_refclk_1_n] ;# MGTREFCLK1N_127 from U57 CKOUT2 SI5328 #set_property -dict {LOC AG34 IOSTANDARD LVDS} [get_ports qsfp_recclk_p] ;# to U57 CKIN1 SI5328 #set_property -dict {LOC AH35 IOSTANDARD LVDS} [get_ports qsfp_recclk_n] ;# to U57 CKIN1 SI5328 -#set_property -dict {LOC AL24 IOSTANDARD LVCMOS18} [get_ports qsfp_modsell] -#set_property -dict {LOC AM24 IOSTANDARD LVCMOS18} [get_ports qsfp_resetl] -#set_property -dict {LOC AL25 IOSTANDARD LVCMOS18} [get_ports qsfp_modprsl] -#set_property -dict {LOC AL21 IOSTANDARD LVCMOS18} [get_ports qsfp_intl] -#set_property -dict {LOC AM21 IOSTANDARD LVCMOS18} [get_ports qsfp_lpmode] +#set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_modsell] +#set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_resetl] +#set_property -dict {LOC AL25 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_modprsl] +#set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_intl] +#set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_lpmode] # 156.25 MHz MGT reference clock #create_clock -period 6.400 -name qsfp_mgt_refclk_0 [get_ports qsfp_mgt_refclk_0_p] +#set_false_path -to [get_ports {qsfp_modsell qsfp_resetl qsfp_lpmode}] +#set_output_delay 0 [get_ports {qsfp_modsell qsfp_resetl qsfp_lpmode}] +#set_false_path -from [get_ports {qsfp_modprsl qsfp_intl}] +#set_input_delay 0 [get_ports {qsfp_modprsl qsfp_intl}] + # I2C interface #set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] #set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +#set_false_path -to [get_ports {i2c_sda i2c_scl}] +#set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +#set_false_path -from [get_ports {i2c_sda i2c_scl}] +#set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AJ4 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 #set_property -dict {LOC AJ3 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 @@ -151,7 +214,10 @@ create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] -# Flash +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + +# BPI flash #set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[4]}] #set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[5]}] #set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[6]}] @@ -195,3 +261,7 @@ create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] #set_property -dict {LOC AW17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] #set_property -dict {LOC BC23 IOSTANDARD LVCMOS18} [get_ports {flash_wait}] +#set_false_path -to [get_ports {flash_dq[*] flash_addr[*] flash_region[*] flash_oe_n flash_we_n flash_adv_n}] +#set_output_delay 0 [get_ports {flash_dq[*] flash_addr[*] flash_region[*] flash_oe_n flash_we_n flash_adv_n}] +#set_false_path -from [get_ports {flash_dq[*] flash_wait}] +#set_input_delay 0 [get_ports {flash_dq[*] flash_wait}] diff --git a/example/VCU118/fpga_10g/fpga.xdc b/example/VCU118/fpga_10g/fpga.xdc index 1773b7485..1b51dd362 100644 --- a/example/VCU118/fpga_10g/fpga.xdc +++ b/example/VCU118/fpga_10g/fpga.xdc @@ -44,9 +44,15 @@ set_property -dict {LOC AU37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC BB24 IOSTANDARD LVCMOS18} [get_ports btnu] set_property -dict {LOC BF22 IOSTANDARD LVCMOS18} [get_ports btnl] @@ -54,18 +60,55 @@ set_property -dict {LOC BE22 IOSTANDARD LVCMOS18} [get_ports btnd] set_property -dict {LOC BE23 IOSTANDARD LVCMOS18} [get_ports btnr] set_property -dict {LOC BD23 IOSTANDARD LVCMOS18} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC B17 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC G16 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC J16 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC D21 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC AY14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC AY15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC AV15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC AV16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC AU16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AT15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC AT16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC N28 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC M30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC N30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC P30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC P29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC L31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC M31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + # UART set_property -dict {LOC BB21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC AW25 IOSTANDARD LVCMOS18} [get_ports uart_rxd] set_property -dict {LOC BB22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] set_property -dict {LOC AY25 IOSTANDARD LVCMOS18} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet SGMII PHY set_property -dict {LOC AU24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_p] set_property -dict {LOC AV24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_n] @@ -81,73 +124,93 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p # 625 MHz ref clock from SGMII PHY #create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +set_false_path -to [get_ports {phy_reset_n phy_mdio phy_mdc}] +set_output_delay 0 [get_ports {phy_reset_n phy_mdio phy_mdc}] +set_false_path -from [get_ports {phy_int_n phy_mdio}] +set_input_delay 0 [get_ports {phy_int_n phy_mdio}] + # QSFP28 Interfaces set_property -dict {LOC Y2 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC Y1 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC Y1 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC V7 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC V6 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC V6 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC W4 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC W3 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC W3 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC V2 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC V1 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC V1 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC P7 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC P6 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC P6 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC U4 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC U3 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC U3 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 set_property -dict {LOC M7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC M6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 set_property -dict {LOC W9 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U38.4 -#set_property -dict {LOC W8 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U38.5 +set_property -dict {LOC W8 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U38.5 #set_property -dict {LOC U9 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U57.28 #set_property -dict {LOC U8 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U57.29 #set_property -dict {LOC AM23 IOSTANDARD LVDS} [get_ports qsfp1_recclk_p] ;# to U57.16 #set_property -dict {LOC AM22 IOSTANDARD LVDS} [get_ports qsfp1_recclk_n] ;# to U57.17 -set_property -dict {LOC AM21 IOSTANDARD LVCMOS18} [get_ports qsfp1_modsell] -set_property -dict {LOC BA22 IOSTANDARD LVCMOS18} [get_ports qsfp1_resetl] -set_property -dict {LOC AL21 IOSTANDARD LVCMOS18} [get_ports qsfp1_modprsl] -set_property -dict {LOC AP21 IOSTANDARD LVCMOS18} [get_ports qsfp1_intl] -set_property -dict {LOC AN21 IOSTANDARD LVCMOS18} [get_ports qsfp1_lpmode] +set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +set_property -dict {LOC BA22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_modprsl] +set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_intl] +set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] # 156.25 MHz MGT reference clock create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] +set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + set_property -dict {LOC T2 } [get_ports qsfp2_rx1_p] ;# MGTYRXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC T1 } [get_ports qsfp2_rx1_n] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC T1 } [get_ports qsfp2_rx1_n] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 set_property -dict {LOC L5 } [get_ports qsfp2_tx1_p] ;# MGTYTXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC L4 } [get_ports qsfp2_tx1_n] ;# MGTYTXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC L4 } [get_ports qsfp2_tx1_n] ;# MGTYTXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 set_property -dict {LOC R4 } [get_ports qsfp2_rx2_p] ;# MGTYRXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC R3 } [get_ports qsfp2_rx2_n] ;# MGTYRXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC R3 } [get_ports qsfp2_rx2_n] ;# MGTYRXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 set_property -dict {LOC K7 } [get_ports qsfp2_tx2_p] ;# MGTYTXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC K6 } [get_ports qsfp2_tx2_n] ;# MGTYTXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC K6 } [get_ports qsfp2_tx2_n] ;# MGTYTXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 set_property -dict {LOC P2 } [get_ports qsfp2_rx3_p] ;# MGTYRXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC P1 } [get_ports qsfp2_rx3_n] ;# MGTYRXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC P1 } [get_ports qsfp2_rx3_n] ;# MGTYRXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 set_property -dict {LOC J5 } [get_ports qsfp2_tx3_p] ;# MGTYTXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC J4 } [get_ports qsfp2_tx3_n] ;# MGTYTXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC J4 } [get_ports qsfp2_tx3_n] ;# MGTYTXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 set_property -dict {LOC M2 } [get_ports qsfp2_rx4_p] ;# MGTYRXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC M1 } [get_ports qsfp2_rx4_n] ;# MGTYRXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC M1 } [get_ports qsfp2_rx4_n] ;# MGTYRXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 set_property -dict {LOC H7 } [get_ports qsfp2_tx4_p] ;# MGTYTXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC H6 } [get_ports qsfp2_tx4_n] ;# MGTYTXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC H6 } [get_ports qsfp2_tx4_n] ;# MGTYTXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 #set_property -dict {LOC R9 } [get_ports qsfp2_mgt_refclk_0_p] ;# MGTREFCLK0P_232 from U104.13 #set_property -dict {LOC R8 } [get_ports qsfp2_mgt_refclk_0_n] ;# MGTREFCLK0N_232 from U104.14 #set_property -dict {LOC N9 } [get_ports qsfp2_mgt_refclk_1_p] ;# MGTREFCLK1P_232 from U57.35 #set_property -dict {LOC N8 } [get_ports qsfp2_mgt_refclk_1_n] ;# MGTREFCLK1N_232 from U57.34 #set_property -dict {LOC AP23 IOSTANDARD LVDS} [get_ports qsfp2_recclk_p] ;# to U57.12 #set_property -dict {LOC AP22 IOSTANDARD LVDS} [get_ports qsfp2_recclk_n] ;# to U57.13 -set_property -dict {LOC AN23 IOSTANDARD LVCMOS18} [get_ports qsfp2_modsell] -set_property -dict {LOC AY22 IOSTANDARD LVCMOS18} [get_ports qsfp2_resetl] -set_property -dict {LOC AN24 IOSTANDARD LVCMOS18} [get_ports qsfp2_modprsl] -set_property -dict {LOC AT21 IOSTANDARD LVCMOS18} [get_ports qsfp2_intl] -set_property -dict {LOC AT24 IOSTANDARD LVCMOS18} [get_ports qsfp2_lpmode] +set_property -dict {LOC AN23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_modsell] +set_property -dict {LOC AY22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_resetl] +set_property -dict {LOC AN24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_modprsl] +set_property -dict {LOC AT21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_intl] +set_property -dict {LOC AT24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_lpmode] # 156.25 MHz MGT reference clock #create_clock -period 6.400 -name qsfp2_mgt_refclk_0 [get_ports qsfp2_mgt_refclk_0_p] +set_false_path -to [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +set_output_delay 0 [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +set_false_path -from [get_ports {qsfp2_modprsl qsfp2_intl}] +set_input_delay 0 [get_ports {qsfp2_modprsl qsfp2_intl}] + # I2C interface set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AA4 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 #set_property -dict {LOC AA3 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 @@ -223,10 +286,17 @@ set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] -# Flash +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + +# QSPI flash #set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] #set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] #set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] #set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] #set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/example/VCU118/fpga_1g/fpga.xdc b/example/VCU118/fpga_1g/fpga.xdc index 0ef436d71..1d822a853 100644 --- a/example/VCU118/fpga_1g/fpga.xdc +++ b/example/VCU118/fpga_1g/fpga.xdc @@ -44,9 +44,15 @@ set_property -dict {LOC AU37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC BB24 IOSTANDARD LVCMOS18} [get_ports btnu] set_property -dict {LOC BF22 IOSTANDARD LVCMOS18} [get_ports btnl] @@ -54,18 +60,55 @@ set_property -dict {LOC BE22 IOSTANDARD LVCMOS18} [get_ports btnd] set_property -dict {LOC BE23 IOSTANDARD LVCMOS18} [get_ports btnr] set_property -dict {LOC BD23 IOSTANDARD LVCMOS18} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC B17 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC G16 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC J16 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC D21 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC AY14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC AY15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC AV15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC AV16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC AU16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AT15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC AT16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC N28 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC M30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC N30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC P30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC P29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC L31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC M31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + # UART set_property -dict {LOC BB21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC AW25 IOSTANDARD LVCMOS18} [get_ports uart_rxd] set_property -dict {LOC BB22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] set_property -dict {LOC AY25 IOSTANDARD LVCMOS18} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet SGMII PHY set_property -dict {LOC AU24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_p] set_property -dict {LOC AV24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_n] @@ -81,6 +124,11 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p # 625 MHz ref clock from SGMII PHY #create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +set_false_path -to [get_ports {phy_reset_n phy_mdio phy_mdc}] +set_output_delay 0 [get_ports {phy_reset_n phy_mdio phy_mdc}] +set_false_path -from [get_ports {phy_int_n phy_mdio}] +set_input_delay 0 [get_ports {phy_int_n phy_mdio}] + # QSFP28 Interfaces #set_property -dict {LOC Y2 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 #set_property -dict {LOC Y1 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 @@ -104,15 +152,20 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p #set_property -dict {LOC U8 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U57.29 #set_property -dict {LOC AM23 IOSTANDARD LVDS} [get_ports qsfp1_recclk_p] ;# to U57.16 #set_property -dict {LOC AM22 IOSTANDARD LVDS} [get_ports qsfp1_recclk_n] ;# to U57.17 -#set_property -dict {LOC AM21 IOSTANDARD LVCMOS18} [get_ports qsfp1_modsell] -#set_property -dict {LOC BA22 IOSTANDARD LVCMOS18} [get_ports qsfp1_resetl] -#set_property -dict {LOC AL21 IOSTANDARD LVCMOS18} [get_ports qsfp1_modprsl] -#set_property -dict {LOC AP21 IOSTANDARD LVCMOS18} [get_ports qsfp1_intl] -#set_property -dict {LOC AN21 IOSTANDARD LVCMOS18} [get_ports qsfp1_lpmode] +#set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +#set_property -dict {LOC BA22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +#set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_modprsl] +#set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_intl] +#set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] # 156.25 MHz MGT reference clock #create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] +#set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +#set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +#set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +#set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + #set_property -dict {LOC T2 } [get_ports qsfp2_rx1_p] ;# MGTYRXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 #set_property -dict {LOC T1 } [get_ports qsfp2_rx1_n] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 #set_property -dict {LOC L5 } [get_ports qsfp2_tx1_p] ;# MGTYTXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 @@ -135,19 +188,29 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p #set_property -dict {LOC N8 } [get_ports qsfp2_mgt_refclk_1_n] ;# MGTREFCLK1N_232 from U57.34 #set_property -dict {LOC AP23 IOSTANDARD LVDS} [get_ports qsfp2_recclk_p] ;# to U57.12 #set_property -dict {LOC AP22 IOSTANDARD LVDS} [get_ports qsfp2_recclk_n] ;# to U57.13 -#set_property -dict {LOC AN23 IOSTANDARD LVCMOS18} [get_ports qsfp2_modsell] -#set_property -dict {LOC AY22 IOSTANDARD LVCMOS18} [get_ports qsfp2_resetl] -#set_property -dict {LOC AN24 IOSTANDARD LVCMOS18} [get_ports qsfp2_modprsl] -#set_property -dict {LOC AT21 IOSTANDARD LVCMOS18} [get_ports qsfp2_intl] -#set_property -dict {LOC AT24 IOSTANDARD LVCMOS18} [get_ports qsfp2_lpmode] +#set_property -dict {LOC AN23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_modsell] +#set_property -dict {LOC AY22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_resetl] +#set_property -dict {LOC AN24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_modprsl] +#set_property -dict {LOC AT21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_intl] +#set_property -dict {LOC AT24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_lpmode] # 156.25 MHz MGT reference clock #create_clock -period 6.400 -name qsfp2_mgt_refclk_0 [get_ports qsfp2_mgt_refclk_0_p] +#set_false_path -to [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +#set_output_delay 0 [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +#set_false_path -from [get_ports {qsfp2_modprsl qsfp2_intl}] +#set_input_delay 0 [get_ports {qsfp2_modprsl qsfp2_intl}] + # I2C interface #set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] #set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +#set_false_path -to [get_ports {i2c_sda i2c_scl}] +#set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +#set_false_path -from [get_ports {i2c_sda i2c_scl}] +#set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AA4 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 #set_property -dict {LOC AA3 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 @@ -223,10 +286,17 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] -# Flash +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + +# QSPI flash #set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] #set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] #set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] #set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] #set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/example/VCU118/fpga_25g/fpga.xdc b/example/VCU118/fpga_25g/fpga.xdc index 1773b7485..1b51dd362 100644 --- a/example/VCU118/fpga_25g/fpga.xdc +++ b/example/VCU118/fpga_25g/fpga.xdc @@ -44,9 +44,15 @@ set_property -dict {LOC AU37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC BB24 IOSTANDARD LVCMOS18} [get_ports btnu] set_property -dict {LOC BF22 IOSTANDARD LVCMOS18} [get_ports btnl] @@ -54,18 +60,55 @@ set_property -dict {LOC BE22 IOSTANDARD LVCMOS18} [get_ports btnd] set_property -dict {LOC BE23 IOSTANDARD LVCMOS18} [get_ports btnr] set_property -dict {LOC BD23 IOSTANDARD LVCMOS18} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC B17 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC G16 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC J16 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC D21 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC AY14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC AY15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC AV15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC AV16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC AU16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AT15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC AT16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC N28 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC M30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC N30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC P30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC P29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC L31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC M31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + # UART set_property -dict {LOC BB21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC AW25 IOSTANDARD LVCMOS18} [get_ports uart_rxd] set_property -dict {LOC BB22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] set_property -dict {LOC AY25 IOSTANDARD LVCMOS18} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_rts}] +set_output_delay 0 [get_ports {uart_txd uart_rts}] +set_false_path -from [get_ports {uart_rxd uart_cts}] +set_input_delay 0 [get_ports {uart_rxd uart_cts}] + # Gigabit Ethernet SGMII PHY set_property -dict {LOC AU24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_p] set_property -dict {LOC AV24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_n] @@ -81,73 +124,93 @@ set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports p # 625 MHz ref clock from SGMII PHY #create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] +set_false_path -to [get_ports {phy_reset_n phy_mdio phy_mdc}] +set_output_delay 0 [get_ports {phy_reset_n phy_mdio phy_mdc}] +set_false_path -from [get_ports {phy_int_n phy_mdio}] +set_input_delay 0 [get_ports {phy_int_n phy_mdio}] + # QSFP28 Interfaces set_property -dict {LOC Y2 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC Y1 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC Y1 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC V7 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC V6 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC V6 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC W4 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC W3 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC W3 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC V2 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC V1 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC V1 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC P7 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC P6 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC P6 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC U4 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC U3 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC U3 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 set_property -dict {LOC M7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC M6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 set_property -dict {LOC W9 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U38.4 -#set_property -dict {LOC W8 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U38.5 +set_property -dict {LOC W8 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U38.5 #set_property -dict {LOC U9 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U57.28 #set_property -dict {LOC U8 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U57.29 #set_property -dict {LOC AM23 IOSTANDARD LVDS} [get_ports qsfp1_recclk_p] ;# to U57.16 #set_property -dict {LOC AM22 IOSTANDARD LVDS} [get_ports qsfp1_recclk_n] ;# to U57.17 -set_property -dict {LOC AM21 IOSTANDARD LVCMOS18} [get_ports qsfp1_modsell] -set_property -dict {LOC BA22 IOSTANDARD LVCMOS18} [get_ports qsfp1_resetl] -set_property -dict {LOC AL21 IOSTANDARD LVCMOS18} [get_ports qsfp1_modprsl] -set_property -dict {LOC AP21 IOSTANDARD LVCMOS18} [get_ports qsfp1_intl] -set_property -dict {LOC AN21 IOSTANDARD LVCMOS18} [get_ports qsfp1_lpmode] +set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +set_property -dict {LOC BA22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_modprsl] +set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_intl] +set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] # 156.25 MHz MGT reference clock create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] +set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + set_property -dict {LOC T2 } [get_ports qsfp2_rx1_p] ;# MGTYRXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC T1 } [get_ports qsfp2_rx1_n] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC T1 } [get_ports qsfp2_rx1_n] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 set_property -dict {LOC L5 } [get_ports qsfp2_tx1_p] ;# MGTYTXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC L4 } [get_ports qsfp2_tx1_n] ;# MGTYTXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC L4 } [get_ports qsfp2_tx1_n] ;# MGTYTXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 set_property -dict {LOC R4 } [get_ports qsfp2_rx2_p] ;# MGTYRXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC R3 } [get_ports qsfp2_rx2_n] ;# MGTYRXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC R3 } [get_ports qsfp2_rx2_n] ;# MGTYRXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 set_property -dict {LOC K7 } [get_ports qsfp2_tx2_p] ;# MGTYTXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC K6 } [get_ports qsfp2_tx2_n] ;# MGTYTXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC K6 } [get_ports qsfp2_tx2_n] ;# MGTYTXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 set_property -dict {LOC P2 } [get_ports qsfp2_rx3_p] ;# MGTYRXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC P1 } [get_ports qsfp2_rx3_n] ;# MGTYRXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC P1 } [get_ports qsfp2_rx3_n] ;# MGTYRXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 set_property -dict {LOC J5 } [get_ports qsfp2_tx3_p] ;# MGTYTXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC J4 } [get_ports qsfp2_tx3_n] ;# MGTYTXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC J4 } [get_ports qsfp2_tx3_n] ;# MGTYTXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 set_property -dict {LOC M2 } [get_ports qsfp2_rx4_p] ;# MGTYRXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC M1 } [get_ports qsfp2_rx4_n] ;# MGTYRXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC M1 } [get_ports qsfp2_rx4_n] ;# MGTYRXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 set_property -dict {LOC H7 } [get_ports qsfp2_tx4_p] ;# MGTYTXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 -#set_property -dict {LOC H6 } [get_ports qsfp2_tx4_n] ;# MGTYTXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +set_property -dict {LOC H6 } [get_ports qsfp2_tx4_n] ;# MGTYTXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 #set_property -dict {LOC R9 } [get_ports qsfp2_mgt_refclk_0_p] ;# MGTREFCLK0P_232 from U104.13 #set_property -dict {LOC R8 } [get_ports qsfp2_mgt_refclk_0_n] ;# MGTREFCLK0N_232 from U104.14 #set_property -dict {LOC N9 } [get_ports qsfp2_mgt_refclk_1_p] ;# MGTREFCLK1P_232 from U57.35 #set_property -dict {LOC N8 } [get_ports qsfp2_mgt_refclk_1_n] ;# MGTREFCLK1N_232 from U57.34 #set_property -dict {LOC AP23 IOSTANDARD LVDS} [get_ports qsfp2_recclk_p] ;# to U57.12 #set_property -dict {LOC AP22 IOSTANDARD LVDS} [get_ports qsfp2_recclk_n] ;# to U57.13 -set_property -dict {LOC AN23 IOSTANDARD LVCMOS18} [get_ports qsfp2_modsell] -set_property -dict {LOC AY22 IOSTANDARD LVCMOS18} [get_ports qsfp2_resetl] -set_property -dict {LOC AN24 IOSTANDARD LVCMOS18} [get_ports qsfp2_modprsl] -set_property -dict {LOC AT21 IOSTANDARD LVCMOS18} [get_ports qsfp2_intl] -set_property -dict {LOC AT24 IOSTANDARD LVCMOS18} [get_ports qsfp2_lpmode] +set_property -dict {LOC AN23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_modsell] +set_property -dict {LOC AY22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_resetl] +set_property -dict {LOC AN24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_modprsl] +set_property -dict {LOC AT21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_intl] +set_property -dict {LOC AT24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_lpmode] # 156.25 MHz MGT reference clock #create_clock -period 6.400 -name qsfp2_mgt_refclk_0 [get_ports qsfp2_mgt_refclk_0_p] +set_false_path -to [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +set_output_delay 0 [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +set_false_path -from [get_ports {qsfp2_modprsl qsfp2_intl}] +set_input_delay 0 [get_ports {qsfp2_modprsl qsfp2_intl}] + # I2C interface set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AA4 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 #set_property -dict {LOC AA3 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 @@ -223,10 +286,17 @@ set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] #create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] -# Flash +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + +# QSPI flash #set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] #set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] #set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] #set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] #set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/example/VCU1525/fpga_10g/fpga.xdc b/example/VCU1525/fpga_10g/fpga.xdc index 5b1dd8e2b..104a62988 100644 --- a/example/VCU1525/fpga_10g/fpga.xdc +++ b/example/VCU1525/fpga_10g/fpga.xdc @@ -44,48 +44,62 @@ set_property -dict {LOC BC21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC BB21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] set_property -dict {LOC BA20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AL20 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # DIP switches set_property -dict {LOC AN22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] set_property -dict {LOC AM19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] set_property -dict {LOC AL19 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART -set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_txd] -set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_rxd] +set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] +set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_rxd] + +#set_false_path -to [get_ports {uart_txd}] +#set_output_delay 0 [get_ports {uart_txd}] +#set_false_path -from [get_ports {uart_rxd}] +#set_input_delay 0 [get_ports {uart_rxd}] # QSFP28 Interfaces set_property -dict {LOC N4 } [get_ports qsfp0_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC N9 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 set_property -dict {LOC M2 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC M7 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 set_property -dict {LOC L4 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC L9 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 set_property -dict {LOC K2 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 set_property -dict {LOC K7 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 -#set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 #set_property -dict {LOC M11 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U14.4 via U43.13 #set_property -dict {LOC M10 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U14.5 via U43.14 set_property -dict {LOC K11 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U9.18 -#set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 -set_property -dict {LOC BE16 IOSTANDARD LVCMOS12} [get_ports qsfp0_modsell] -set_property -dict {LOC BE17 IOSTANDARD LVCMOS12} [get_ports qsfp0_resetl] -set_property -dict {LOC BE20 IOSTANDARD LVCMOS12} [get_ports qsfp0_modprsl] -set_property -dict {LOC BE21 IOSTANDARD LVCMOS12} [get_ports qsfp0_intl] -set_property -dict {LOC BD18 IOSTANDARD LVCMOS12} [get_ports qsfp0_lpmode] -set_property -dict {LOC AT22 IOSTANDARD LVCMOS12} [get_ports qsfp0_refclk_reset] -set_property -dict {LOC AT20 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[0]}] -set_property -dict {LOC AU22 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[1]}] +set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 +set_property -dict {LOC BE16 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_modsell] +set_property -dict {LOC BE17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_resetl] +set_property -dict {LOC BE20 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_modprsl] +set_property -dict {LOC BE21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_intl] +set_property -dict {LOC BD18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_lpmode] +set_property -dict {LOC AT22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_reset] +set_property -dict {LOC AT20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[0]}] +set_property -dict {LOC AU22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[1]}] # 156.25 MHz MGT reference clock (from SI570) #create_clock -period 6.400 -name qsfp0_mgt_refclk_0 [get_ports qsfp0_mgt_refclk_0_p] @@ -96,34 +110,39 @@ set_property -dict {LOC AU22 IOSTANDARD LVCMOS12} [get_ports {qsfp0_fs[1]}] # 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_output_delay 0 [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_false_path -from [get_ports {qsfp0_modprsl qsfp0_intl}] +set_input_delay 0 [get_ports {qsfp0_modprsl qsfp0_intl}] + set_property -dict {LOC U4 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 set_property -dict {LOC U9 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 set_property -dict {LOC T2 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 set_property -dict {LOC R4 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 set_property -dict {LOC R9 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 set_property -dict {LOC P2 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 set_property -dict {LOC P7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 -#set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 #set_property -dict {LOC T11 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U14.4 via U43.15 #set_property -dict {LOC T10 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U14.5 via U43.16 #set_property -dict {LOC P11 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U12.18 #set_property -dict {LOC P10 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U12.17 -set_property -dict {LOC AY20 IOSTANDARD LVCMOS12} [get_ports qsfp1_modsell] -set_property -dict {LOC BC18 IOSTANDARD LVCMOS12} [get_ports qsfp1_resetl] -set_property -dict {LOC BC19 IOSTANDARD LVCMOS12} [get_ports qsfp1_modprsl] -set_property -dict {LOC AV21 IOSTANDARD LVCMOS12} [get_ports qsfp1_intl] -set_property -dict {LOC AV22 IOSTANDARD LVCMOS12} [get_ports qsfp1_lpmode] -set_property -dict {LOC AR21 IOSTANDARD LVCMOS12} [get_ports qsfp1_refclk_reset] -set_property -dict {LOC AR22 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[0]}] -set_property -dict {LOC AU20 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[1]}] +set_property -dict {LOC AY20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +set_property -dict {LOC BC18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +set_property -dict {LOC BC19 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_modprsl] +set_property -dict {LOC AV21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_intl] +set_property -dict {LOC AV22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] +set_property -dict {LOC AR21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_reset] +set_property -dict {LOC AR22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[0]}] +set_property -dict {LOC AU20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[1]}] # 156.25 MHz MGT reference clock (from SI570) #create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] @@ -134,11 +153,21 @@ set_property -dict {LOC AU20 IOSTANDARD LVCMOS12} [get_ports {qsfp1_fs[1]}] # 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) #create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] +set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + # I2C interface #set_property -dict {LOC BF19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_mux_reset] set_property -dict {LOC BF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_scl] set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_sda] +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + # PCIe Interface #set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 #set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 @@ -211,4 +240,5 @@ set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_p] - +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/example/ZCU102/fpga/fpga.xdc b/example/ZCU102/fpga/fpga.xdc index 3c10bd43b..4393baeeb 100644 --- a/example/ZCU102/fpga/fpga.xdc +++ b/example/ZCU102/fpga/fpga.xdc @@ -20,9 +20,15 @@ set_property -dict {LOC AH13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AH14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC AL12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC AM13 IOSTANDARD LVCMOS33} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC AG15 IOSTANDARD LVCMOS33} [get_ports btnu] set_property -dict {LOC AF15 IOSTANDARD LVCMOS33} [get_ports btnl] @@ -30,6 +36,9 @@ set_property -dict {LOC AE15 IOSTANDARD LVCMOS33} [get_ports btnd] set_property -dict {LOC AE14 IOSTANDARD LVCMOS33} [get_ports btnr] set_property -dict {LOC AG13 IOSTANDARD LVCMOS33} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC AN14 IOSTANDARD LVCMOS33} [get_ports {sw[0]}] set_property -dict {LOC AP14 IOSTANDARD LVCMOS33} [get_ports {sw[1]}] @@ -40,35 +49,49 @@ set_property -dict {LOC AP12 IOSTANDARD LVCMOS33} [get_ports {sw[5]}] set_property -dict {LOC AL13 IOSTANDARD LVCMOS33} [get_ports {sw[6]}] set_property -dict {LOC AK13 IOSTANDARD LVCMOS33} [get_ports {sw[7]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART set_property -dict {LOC F13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC E13 IOSTANDARD LVCMOS33} [get_ports uart_rxd] set_property -dict {LOC D12 IOSTANDARD LVCMOS33} [get_ports uart_rts] set_property -dict {LOC E12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_cts}] +set_output_delay 0 [get_ports {uart_txd uart_cts}] +set_false_path -from [get_ports {uart_rxd uart_rts}] +set_input_delay 0 [get_ports {uart_rxd uart_rts}] + + # I2C interfaces #set_property -dict {LOC J10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c0_scl] #set_property -dict {LOC J11 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c0_sda] #set_property -dict {LOC K20 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c1_scl] #set_property -dict {LOC L20 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c1_sda] +#set_false_path -to [get_ports {i2c1_sda i2c1_scl}] +#set_output_delay 0 [get_ports {i2c1_sda i2c1_scl}] +#set_false_path -from [get_ports {i2c1_sda i2c1_scl}] +#set_input_delay 0 [get_ports {i2c1_sda i2c1_scl}] + # SFP+ Interface set_property -dict {LOC D2 } [get_ports sfp0_rx_p] ;# MGTHRXP0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC D1 } [get_ports sfp0_rx_n] ;# MGTHRXN0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC D1 } [get_ports sfp0_rx_n] ;# MGTHRXN0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3 set_property -dict {LOC E4 } [get_ports sfp0_tx_p] ;# MGTHTXP0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC E3 } [get_ports sfp0_tx_n] ;# MGTHTXN0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC E3 } [get_ports sfp0_tx_n] ;# MGTHTXN0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3 set_property -dict {LOC C4 } [get_ports sfp1_rx_p] ;# MGTHRXP1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC C3 } [get_ports sfp1_rx_n] ;# MGTHRXN1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC C3 } [get_ports sfp1_rx_n] ;# MGTHRXN1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3 set_property -dict {LOC D6 } [get_ports sfp1_tx_p] ;# MGTHTXP1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC D5 } [get_ports sfp1_tx_n] ;# MGTHTXN1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC D5 } [get_ports sfp1_tx_n] ;# MGTHTXN1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3 set_property -dict {LOC B2 } [get_ports sfp2_rx_p] ;# MGTHRXP2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC B1 } [get_ports sfp2_rx_n] ;# MGTHRXN2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC B1 } [get_ports sfp2_rx_n] ;# MGTHRXN2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3 set_property -dict {LOC B6 } [get_ports sfp2_tx_p] ;# MGTHTXP2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC B5 } [get_ports sfp2_tx_n] ;# MGTHTXN2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC B5 } [get_ports sfp2_tx_n] ;# MGTHTXN2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3 set_property -dict {LOC A4 } [get_ports sfp3_rx_p] ;# MGTHRXP3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC A3 } [get_ports sfp3_rx_n] ;# MGTHRXN3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC A3 } [get_ports sfp3_rx_n] ;# MGTHRXN3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3 set_property -dict {LOC A8 } [get_ports sfp3_tx_p] ;# MGTHTXP3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3 -#set_property -dict {LOC A7 } [get_ports sfp3_tx_n] ;# MGTHTXN3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3 +set_property -dict {LOC A7 } [get_ports sfp3_tx_n] ;# MGTHTXN3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3 set_property -dict {LOC C8 } [get_ports sfp_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U56 SI570 via U51 SI53340 set_property -dict {LOC C7 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U56 SI570 via U51 SI53340 #set_property -dict {LOC B10 } [get_ports sfp_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U20 CKOUT2 SI5328 @@ -83,4 +106,5 @@ set_property -dict {LOC C13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports s # 156.25 MHz MGT reference clock create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p] - +set_false_path -to [get_ports {sfp0_tx_disable_b sfp1_tx_disable_b sfp2_tx_disable_b sfp3_tx_disable_b}] +set_output_delay 0 [get_ports {sfp0_tx_disable_b sfp1_tx_disable_b sfp2_tx_disable_b sfp3_tx_disable_b}] diff --git a/example/ZCU106/fpga/fpga.xdc b/example/ZCU106/fpga/fpga.xdc index a3f6a0955..64ff67e22 100644 --- a/example/ZCU106/fpga/fpga.xdc +++ b/example/ZCU106/fpga/fpga.xdc @@ -20,9 +20,15 @@ set_property -dict {LOC AM9 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports { set_property -dict {LOC AM10 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] set_property -dict {LOC AM11 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + # Reset button set_property -dict {LOC G13 IOSTANDARD LVCMOS12} [get_ports reset] +set_false_path -from [get_ports {reset}] +set_input_delay 0 [get_ports {reset}] + # Push buttons set_property -dict {LOC AG13 IOSTANDARD LVCMOS12} [get_ports btnu] set_property -dict {LOC AK12 IOSTANDARD LVCMOS12} [get_ports btnl] @@ -30,6 +36,9 @@ set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports btnd] set_property -dict {LOC AC14 IOSTANDARD LVCMOS12} [get_ports btnr] set_property -dict {LOC AL10 IOSTANDARD LVCMOS12} [get_ports btnc] +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + # DIP switches set_property -dict {LOC A17 IOSTANDARD LVCMOS18} [get_ports {sw[0]}] set_property -dict {LOC A16 IOSTANDARD LVCMOS18} [get_ports {sw[1]}] @@ -40,39 +49,55 @@ set_property -dict {LOC A14 IOSTANDARD LVCMOS18} [get_ports {sw[5]}] set_property -dict {LOC B14 IOSTANDARD LVCMOS18} [get_ports {sw[6]}] set_property -dict {LOC B13 IOSTANDARD LVCMOS18} [get_ports {sw[7]}] +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + # UART set_property -dict {LOC AL17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] set_property -dict {LOC AH17 IOSTANDARD LVCMOS12} [get_ports uart_rxd] set_property -dict {LOC AM15 IOSTANDARD LVCMOS12} [get_ports uart_rts] set_property -dict {LOC AP17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_cts] +set_false_path -to [get_ports {uart_txd uart_cts}] +set_output_delay 0 [get_ports {uart_txd uart_cts}] +set_false_path -from [get_ports {uart_rxd uart_rts}] +set_input_delay 0 [get_ports {uart_rxd uart_rts}] + # I2C interfaces #set_property -dict {LOC AE19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c0_scl] #set_property -dict {LOC AH23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c0_sda] #set_property -dict {LOC AH19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c1_scl] #set_property -dict {LOC AL21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c1_sda] +#set_false_path -to [get_ports {i2c1_sda i2c1_scl}] +#set_output_delay 0 [get_ports {i2c1_sda i2c1_scl}] +#set_false_path -from [get_ports {i2c1_sda i2c1_scl}] +#set_input_delay 0 [get_ports {i2c1_sda i2c1_scl}] + # SFP+ Interface -set_property -dict {LOC AA2 } [get_ports sfp0_rx_p] ;# MGTYRXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 -#set_property -dict {LOC AA1 } [get_ports sfp0_rx_n] ;# MGTYRXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 -set_property -dict {LOC Y4 } [get_ports sfp0_tx_p] ;# MGTYTXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 -#set_property -dict {LOC Y3 } [get_ports sfp0_tx_n] ;# MGTYTXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 -set_property -dict {LOC W2 } [get_ports sfp1_rx_p] ;# MGTYRXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 -#set_property -dict {LOC W1 } [get_ports sfp1_rx_n] ;# MGTYRXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 -set_property -dict {LOC W6 } [get_ports sfp1_tx_p] ;# MGTYTXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 -#set_property -dict {LOC W5 } [get_ports sfp1_tx_n] ;# MGTYTXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC AA2 } [get_ports sfp0_rx_p] ;# MGTHRXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC AA1 } [get_ports sfp0_rx_n] ;# MGTHRXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC Y4 } [get_ports sfp0_tx_p] ;# MGTHTXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC Y3 } [get_ports sfp0_tx_n] ;# MGTHTXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC W2 } [get_ports sfp1_rx_p] ;# MGTHRXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC W1 } [get_ports sfp1_rx_n] ;# MGTHRXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC W6 } [get_ports sfp1_tx_p] ;# MGTHTXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +set_property -dict {LOC W5 } [get_ports sfp1_tx_n] ;# MGTHTXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 set_property -dict {LOC U10 } [get_ports sfp_mgt_refclk_0_p] ;# MGTREFCLK1P_226 from U56 SI570 via U51 SI53340 -#set_property -dict {LOC U9 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK1N_226 from U56 SI570 via U51 SI53340 +set_property -dict {LOC U9 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK1N_226 from U56 SI570 via U51 SI53340 #set_property -dict {LOC W10 } [get_ports sfp_mgt_refclk_1_p] ;# MGTREFCLK1P_225 from U20 CKOUT2 SI5328 #set_property -dict {LOC W9 } [get_ports sfp_mgt_refclk_1_n] ;# MGTREFCLK1N_225 from U20 CKOUT2 SI5328 #set_property -dict {LOC H11 IOSTANDARD LVDS} [get_ports sfp_recclk_p] ;# to U20 CKIN1 SI5328 #set_property -dict {LOC G11 IOSTANDARD LVDS} [get_ports sfp_recclk_n] ;# to U20 CKIN1 SI5328 -set_property -dict {LOC AE22 IOSTANDARD LVCMOS12} [get_ports sfp0_tx_disable_b] -set_property -dict {LOC AF20 IOSTANDARD LVCMOS12} [get_ports sfp1_tx_disable_b] +set_property -dict {LOC AE22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports sfp0_tx_disable_b] +set_property -dict {LOC AF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports sfp1_tx_disable_b] # 156.25 MHz MGT reference clock create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p] +set_false_path -to [get_ports {sfp0_tx_disable_b sfp1_tx_disable_b}] +set_output_delay 0 [get_ports {sfp0_tx_disable_b sfp1_tx_disable_b}] + # PCIe Interface #set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1 #set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1 @@ -97,4 +122,7 @@ create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p] # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] +#set_false_path -from [get_ports {pcie_reset_n}] +#set_input_delay 0 [get_ports {pcie_reset_n}] + diff --git a/example/fb2CG/fpga_10g/fpga.xdc b/example/fb2CG/fpga_10g/fpga.xdc index 94440c0ec..e4e426737 100644 --- a/example/fb2CG/fpga_10g/fpga.xdc +++ b/example/fb2CG/fpga_10g/fpga.xdc @@ -36,17 +36,25 @@ set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets init_clk_bufg] set_property -dict {LOC C4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports led_sreg_d] set_property -dict {LOC B3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports led_sreg_ld] set_property -dict {LOC G3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports led_sreg_clk] -set_property -dict {LOC C5 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led_bmc[0]}] -set_property -dict {LOC C6 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led_bmc[1]}] +set_property -dict {LOC C5 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {led_bmc[0]}] +set_property -dict {LOC C6 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {led_bmc[1]}] set_property -dict {LOC D3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[0]}] set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[1]}] +set_false_path -to [get_ports {led_sreg_d led_sreg_ld led_sreg_clk led_bmc[*] led_exp[*]}] +set_output_delay 0 [get_ports {led_sreg_d led_sreg_ld led_sreg_clk led_bmc[*] led_exp[*]}] + # GPIO #set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) #set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 #set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) #set_property -dict {LOC H2 IOSTANDARD LVCMOS33} [get_ports misc_ucoax] ; from u.FL J5 (PPS IN) +#set_false_path -to [get_ports {pps_out pps_out_en}] +#set_output_delay 0 [get_ports {pps_out pps_out_en}] +#set_false_path -from [get_ports {pps_in}] +#set_input_delay 0 [get_ports {pps_in}] + # BMC interface #set_property -dict {LOC D7 IOSTANDARD LVCMOS18} [get_ports bmc_miso] #set_property -dict {LOC J4 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports bmc_nss] @@ -54,6 +62,11 @@ set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports { #set_property -dict {LOC D5 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports bmc_mosi] #set_property -dict {LOC H4 IOSTANDARD LVCMOS18} [get_ports bmc_int] +#set_false_path -to [get_ports {bmc_nss bmc_clk bmc_mosi}] +#set_output_delay 0 [get_ports {bmc_nss bmc_clk bmc_mosi}] +#set_false_path -from [get_ports {bmc_miso bmc_int}] +#set_input_delay 0 [get_ports {bmc_miso bmc_int}] + # Board status #set_property -dict {LOC J2 IOSTANDARD LVCMOS33} [get_ports {fan_tacho[0]}] #set_property -dict {LOC J3 IOSTANDARD LVCMOS33} [get_ports {fan_tacho[1]}] @@ -61,25 +74,28 @@ set_property -dict {LOC A6 IOSTANDARD LVCMOS18} [get_ports {pg[0]}] set_property -dict {LOC C7 IOSTANDARD LVCMOS18} [get_ports {pg[1]}] #set_property -dict {LOC E2 IOSTANDARD LVCMOS33} [get_ports pwrbrk] +set_false_path -from [get_ports {pg[*]}] +set_input_delay 0 [get_ports {pg[*]}] + # QSFP28 Interfaces set_property -dict {LOC Y39 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC Y40 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC Y40 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 set_property -dict {LOC Y34 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC Y35 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC Y35 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 set_property -dict {LOC W41 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC W42 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC W42 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 set_property -dict {LOC W36 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC W37 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC W37 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 set_property -dict {LOC V39 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC V40 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC V40 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 set_property -dict {LOC V34 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC V35 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC V35 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 set_property -dict {LOC U41 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC U42 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC U42 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 set_property -dict {LOC U36 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 -#set_property -dict {LOC U37 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +set_property -dict {LOC U37 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 set_property -dict {LOC W32 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_130 from U28 -#set_property -dict {LOC W33 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_130 from U28 +set_property -dict {LOC W33 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_130 from U28 set_property -dict {LOC B9 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_0_mod_prsnt_n] set_property -dict {LOC A8 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_0_reset_n] set_property -dict {LOC A9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_0_lp_mode] @@ -90,24 +106,34 @@ set_property -dict {LOC A10 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_0_ # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name qsfp_0_mgt_refclk [get_ports qsfp_0_mgt_refclk_p] +set_false_path -to [get_ports {qsfp_0_reset_n qsfp_0_lp_mode}] +set_output_delay 0 [get_ports {qsfp_0_reset_n qsfp_0_lp_mode}] +set_false_path -from [get_ports {qsfp_0_mod_prsnt_n qsfp_0_intr_n}] +set_input_delay 0 [get_ports {qsfp_0_mod_prsnt_n qsfp_0_intr_n}] + +#set_false_path -to [get_ports {qsfp_0_i2c_scl qsfp_0_i2c_sda}] +#set_output_delay 0 [get_ports {qsfp_0_i2c_scl qsfp_0_i2c_sda}] +#set_false_path -from [get_ports {qsfp_0_i2c_scl qsfp_0_i2c_sda}] +#set_input_delay 0 [get_ports {qsfp_0_i2c_scl qsfp_0_i2c_sda}] + set_property -dict {LOC M39 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC M40 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC M40 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5 set_property -dict {LOC M34 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC M35 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC M35 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5 set_property -dict {LOC L41 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC L42 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC L42 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5 set_property -dict {LOC L36 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC L37 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC L37 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5 set_property -dict {LOC K39 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC K40 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC K40 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5 set_property -dict {LOC K34 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5 set_property -dict {LOC J41 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC J42 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC J42 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5 set_property -dict {LOC J36 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5 -#set_property -dict {LOC J37 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5 +set_property -dict {LOC J37 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5 set_property -dict {LOC P30 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_132 from U28 -#set_property -dict {LOC P31 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_132 from U28 +set_property -dict {LOC P31 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_132 from U28 set_property -dict {LOC E10 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_1_mod_prsnt_n] set_property -dict {LOC C10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_1_reset_n] set_property -dict {LOC D9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_1_lp_mode] @@ -118,6 +144,16 @@ set_property -dict {LOC D10 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_1_ # 161.1328125 MHz MGT reference clock create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p] +set_false_path -to [get_ports {qsfp_1_reset_n qsfp_1_lp_mode}] +set_output_delay 0 [get_ports {qsfp_1_reset_n qsfp_1_lp_mode}] +set_false_path -from [get_ports {qsfp_1_mod_prsnt_n qsfp_1_intr_n}] +set_input_delay 0 [get_ports {qsfp_1_mod_prsnt_n qsfp_1_intr_n}] + +#set_false_path -to [get_ports {qsfp_1_i2c_scl qsfp_1_i2c_sda}] +#set_output_delay 0 [get_ports {qsfp_1_i2c_scl qsfp_1_i2c_sda}] +#set_false_path -from [get_ports {qsfp_1_i2c_scl qsfp_1_i2c_sda}] +#set_input_delay 0 [get_ports {qsfp_1_i2c_scl qsfp_1_i2c_sda}] + # Expansion connector #set_property -dict {LOC AG41} [get_ports {exp_rx_p[0]}] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 #set_property -dict {LOC AG42} [get_ports {exp_rx_n[0]}] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 @@ -225,3 +261,6 @@ create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_ # 100 MHz MGT reference clock #create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_refclk_p] + +#set_false_path -from [get_ports {pcie_rst_n}] +#set_input_delay 0 [get_ports {pcie_rst_n}]