From 3ff40e355a4655018e7171fcd0a4e0610b4692ca Mon Sep 17 00:00:00 2001 From: Viktor Prutyanov Date: Tue, 7 Feb 2023 20:28:51 +0300 Subject: [PATCH 1/5] example: copy KC705 RGMII example as Genesys2 RGMII example Signed-off-by: Viktor Prutyanov --- example/Genesys2/fpga_rgmii/Makefile | 25 + example/Genesys2/fpga_rgmii/README.md | 33 + example/Genesys2/fpga_rgmii/common/vivado.mk | 131 ++++ example/Genesys2/fpga_rgmii/eth.xdc | 5 + example/Genesys2/fpga_rgmii/fpga.xdc | 111 ++++ example/Genesys2/fpga_rgmii/fpga/Makefile | 67 ++ .../fpga_rgmii/fpga/generate_bit_iodelay.tcl | 6 + example/Genesys2/fpga_rgmii/lib/eth | 1 + .../Genesys2/fpga_rgmii/rtl/debounce_switch.v | 93 +++ example/Genesys2/fpga_rgmii/rtl/fpga.v | 375 +++++++++++ example/Genesys2/fpga_rgmii/rtl/fpga_core.v | 588 ++++++++++++++++++ example/Genesys2/fpga_rgmii/rtl/sync_signal.v | 62 ++ .../Genesys2/fpga_rgmii/tb/fpga_core/Makefile | 100 +++ .../fpga_rgmii/tb/fpga_core/test_fpga_core.py | 229 +++++++ 14 files changed, 1826 insertions(+) create mode 100644 example/Genesys2/fpga_rgmii/Makefile create mode 100644 example/Genesys2/fpga_rgmii/README.md create mode 100644 example/Genesys2/fpga_rgmii/common/vivado.mk create mode 100644 example/Genesys2/fpga_rgmii/eth.xdc create mode 100644 example/Genesys2/fpga_rgmii/fpga.xdc create mode 100644 example/Genesys2/fpga_rgmii/fpga/Makefile create mode 100644 example/Genesys2/fpga_rgmii/fpga/generate_bit_iodelay.tcl create mode 120000 example/Genesys2/fpga_rgmii/lib/eth create mode 100644 example/Genesys2/fpga_rgmii/rtl/debounce_switch.v create mode 100644 example/Genesys2/fpga_rgmii/rtl/fpga.v create mode 100644 example/Genesys2/fpga_rgmii/rtl/fpga_core.v create mode 100644 example/Genesys2/fpga_rgmii/rtl/sync_signal.v create mode 100644 example/Genesys2/fpga_rgmii/tb/fpga_core/Makefile create mode 100644 example/Genesys2/fpga_rgmii/tb/fpga_core/test_fpga_core.py diff --git a/example/Genesys2/fpga_rgmii/Makefile b/example/Genesys2/fpga_rgmii/Makefile new file mode 100644 index 000000000..f504bd06f --- /dev/null +++ b/example/Genesys2/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/Genesys2/fpga_rgmii/README.md b/example/Genesys2/fpga_rgmii/README.md new file mode 100644 index 000000000..831019854 --- /dev/null +++ b/example/Genesys2/fpga_rgmii/README.md @@ -0,0 +1,33 @@ +# 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. + +It is also possible to use hping to test the design by running + + hping 192.168.1.128 -2 -p 1234 -d 1024 diff --git a/example/Genesys2/fpga_rgmii/common/vivado.mk b/example/Genesys2/fpga_rgmii/common/vivado.mk new file mode 100644 index 000000000..21e6a5fed --- /dev/null +++ b/example/Genesys2/fpga_rgmii/common/vivado.mk @@ -0,0 +1,131 @@ +################################################################### +# +# 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) + +FPGA_TOP ?= fpga +PROJECT ?= $(FPGA_TOP) + +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 *.gen *.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 *.ltx program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + -rm -rf *_utilization.rpt *_utilization_hierarchical.rpt + +distclean: clean + -rm -rf rev + +################################################################### +# Target implementations +################################################################### + +# Vivado project file +create_project.tcl: 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) $(PROJECT)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + echo "set_property top $(FPGA_TOP) [current_fileset]" >> $@ + echo "add_files -fileset constrs_1 $(XDC_FILES_REL)" >> $@ + for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> $@; done + for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(PROJECT).xpr: create_project.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +$(PROJECT).runs/synth_1/$(PROJECT).dcp: $(PROJECT).xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) + echo "open_project $(PROJECT).xpr" > run_synth.tcl + echo "reset_run synth_1" >> run_synth.tcl + echo "launch_runs -jobs 4 synth_1" >> run_synth.tcl + echo "wait_on_run synth_1" >> run_synth.tcl + vivado -nojournal -nolog -mode batch -source run_synth.tcl + +# implementation run +$(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp: $(PROJECT).runs/synth_1/$(PROJECT).dcp + echo "open_project $(PROJECT).xpr" > run_impl.tcl + echo "reset_run impl_1" >> run_impl.tcl + echo "launch_runs -jobs 4 impl_1" >> run_impl.tcl + echo "wait_on_run impl_1" >> run_impl.tcl + echo "open_run impl_1" >> run_impl.tcl + echo "report_utilization -file $(PROJECT)_utilization.rpt" >> run_impl.tcl + echo "report_utilization -hierarchical -file $(PROJECT)_utilization_hierarchical.rpt" >> run_impl.tcl + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +$(PROJECT).bit $(PROJECT).ltx: $(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp + echo "open_project $(PROJECT).xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $(PROJECT).runs/impl_1/$(PROJECT).bit" >> generate_bit.tcl + echo "write_debug_probes -force $(PROJECT).runs/impl_1/$(PROJECT).ltx" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).bit . + if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).ltx .; fi + mkdir -p rev + COUNT=100; \ + while [ -e rev/$(PROJECT)_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp -pv $(PROJECT).runs/impl_1/$(PROJECT).bit rev/$(PROJECT)_rev$$COUNT.bit; \ + if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then cp -pv $(PROJECT).runs/impl_1/$(PROJECT).ltx rev/$(PROJECT)_rev$$COUNT.ltx; fi diff --git a/example/Genesys2/fpga_rgmii/eth.xdc b/example/Genesys2/fpga_rgmii/eth.xdc new file mode 100644 index 000000000..d9780aa1c --- /dev/null +++ b/example/Genesys2/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/Genesys2/fpga_rgmii/fpga.xdc b/example/Genesys2/fpga_rgmii/fpga.xdc new file mode 100644 index 000000000..1f6408855 --- /dev/null +++ b/example/Genesys2/fpga_rgmii/fpga.xdc @@ -0,0 +1,111 @@ +# 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]}] + +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] +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 +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] + +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/Genesys2/fpga_rgmii/fpga/Makefile b/example/Genesys2/fpga_rgmii/fpga/Makefile new file mode 100644 index 000000000..17ba63b2f --- /dev/null +++ b/example/Genesys2/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/vivado/rgmii_phy_if.tcl +XDC_FILES += lib/eth/syn/vivado/eth_mac_1g_rgmii.tcl +XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl +XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl +XDC_FILES += lib/eth/lib/axis/syn/vivado/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/Genesys2/fpga_rgmii/fpga/generate_bit_iodelay.tcl b/example/Genesys2/fpga_rgmii/fpga/generate_bit_iodelay.tcl new file mode 100644 index 000000000..d97f96678 --- /dev/null +++ b/example/Genesys2/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/Genesys2/fpga_rgmii/lib/eth b/example/Genesys2/fpga_rgmii/lib/eth new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/example/Genesys2/fpga_rgmii/lib/eth @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/example/Genesys2/fpga_rgmii/rtl/debounce_switch.v b/example/Genesys2/fpga_rgmii/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/example/Genesys2/fpga_rgmii/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * 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 + +`resetall diff --git a/example/Genesys2/fpga_rgmii/rtl/fpga.v b/example/Genesys2/fpga_rgmii/rtl/fpga.v new file mode 100644 index 000000000..92188383b --- /dev/null +++ b/example/Genesys2/fpga_rgmii/rtl/fpga.v @@ -0,0 +1,375 @@ +/* + +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 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * 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 + +`resetall diff --git a/example/Genesys2/fpga_rgmii/rtl/fpga_core.v b/example/Genesys2/fpga_rgmii/rtl/fpga_core.v new file mode 100644 index 000000000..1505d3309 --- /dev/null +++ b/example/Genesys2/fpga_rgmii/rtl/fpga_core.v @@ -0,0 +1,588 @@ +/* + +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 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * 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 + +`resetall diff --git a/example/Genesys2/fpga_rgmii/rtl/sync_signal.v b/example/Genesys2/fpga_rgmii/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/example/Genesys2/fpga_rgmii/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +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 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * 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 + +`resetall diff --git a/example/Genesys2/fpga_rgmii/tb/fpga_core/Makefile b/example/Genesys2/fpga_rgmii/tb/fpga_core/Makefile new file mode 100644 index 000000000..c6328a449 --- /dev/null +++ b/example/Genesys2/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/Genesys2/fpga_rgmii/tb/fpga_core/test_fpga_core.py b/example/Genesys2/fpga_rgmii/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..e2a4b09f6 --- /dev/null +++ b/example/Genesys2/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.start_soon(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.value = 1 + + for k in range(10): + await RisingEdge(self.dut.clk) + + self.dut.rst.value = 0 + + async def _run_clk(self): + t = Timer(2, 'ns') + while True: + self.dut.clk.value = 1 + await t + self.dut.clk90.value = 1 + await t + self.dut.clk.value = 0 + await t + self.dut.clk90.value = 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 e93a85df079f12e501eeb409fc333b231df8a431 Mon Sep 17 00:00:00 2001 From: Viktor Prutyanov Date: Tue, 7 Feb 2023 20:54:10 +0300 Subject: [PATCH 2/5] example: Genesys2: use proper XDC Signed-off-by: Viktor Prutyanov --- example/Genesys2/fpga_rgmii/fpga.xdc | 110 +++++++++++---------------- 1 file changed, 43 insertions(+), 67 deletions(-) diff --git a/example/Genesys2/fpga_rgmii/fpga.xdc b/example/Genesys2/fpga_rgmii/fpga.xdc index 1f6408855..8b9f78da2 100644 --- a/example/Genesys2/fpga_rgmii/fpga.xdc +++ b/example/Genesys2/fpga_rgmii/fpga.xdc @@ -1,104 +1,80 @@ -# XDC constraints for the Xilinx KC705 board +# XDC constraints for the Digilent Genesys 2 Rev. H board # part: xc7k325tffg900-2 # General configuration set_property CFGBVS VCCO [current_design] -set_property CONFIG_VOLTAGE 2.5 [current_design] +set_property CONFIG_VOLTAGE 3.3 [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] +set_property -dict {PACKAGE_PIN AD12 IOSTANDARD LVDS} [get_ports clk_200mhz_p] +set_property -dict {PACKAGE_PIN 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]}] +set_property -dict {PACKAGE_PIN T28 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[0]}] +set_property -dict {PACKAGE_PIN V19 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[1]}] +set_property -dict {PACKAGE_PIN U30 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[2]}] +set_property -dict {PACKAGE_PIN U29 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[3]}] +set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[4]}] +set_property -dict {PACKAGE_PIN V26 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[5]}] +set_property -dict {PACKAGE_PIN W24 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {led[6]}] +set_property -dict {PACKAGE_PIN W23 IOSTANDARD LVCMOS33 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_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports reset_n] -set_false_path -from [get_ports {reset}] -set_input_delay 0 [get_ports {reset}] +set_false_path -from [get_ports {reset_n}] +set_input_delay 0 [get_ports {reset_n}] # 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] +set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS12} [get_ports btnu] +set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS12} [get_ports btnl] +set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS12} [get_ports btnd] +set_property -dict {PACKAGE_PIN C19 IOSTANDARD LVCMOS12} [get_ports btnr] +set_property -dict {PACKAGE_PIN E18 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 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_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] +set_property -dict {PACKAGE_PIN G25 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] +set_property -dict {PACKAGE_PIN H24 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] +set_property -dict {PACKAGE_PIN K19 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 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}] +set_property -dict {PACKAGE_PIN Y23 IOSTANDARD LVCMOS33} [get_ports uart_txd] +set_property -dict {PACKAGE_PIN Y20 IOSTANDARD LVCMOS33} [get_ports uart_rxd] # 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 +set_property -dict {PACKAGE_PIN AG10 IOSTANDARD LVCMOS15 } [get_ports { phy_rx_clk }] +set_property -dict {PACKAGE_PIN AJ14 IOSTANDARD LVCMOS15 } [get_ports { phy_rxd[0] }] +set_property -dict {PACKAGE_PIN AH14 IOSTANDARD LVCMOS15 } [get_ports { phy_rxd[1] }] +set_property -dict {PACKAGE_PIN AK13 IOSTANDARD LVCMOS15 } [get_ports { phy_rxd[2] }] +set_property -dict {PACKAGE_PIN AJ13 IOSTANDARD LVCMOS15 } [get_ports { phy_rxd[3] }] +set_property -dict {PACKAGE_PIN AH11 IOSTANDARD LVCMOS15 } [get_ports { phy_rx_ctl }] +set_property -dict {PACKAGE_PIN AE10 IOSTANDARD LVCMOS15 SLEW FAST DRIVE 16} [get_ports { phy_tx_clk }] +set_property -dict {PACKAGE_PIN AJ12 IOSTANDARD LVCMOS15 SLEW FAST DRIVE 16} [get_ports { phy_txd[0] }] +set_property -dict {PACKAGE_PIN AK11 IOSTANDARD LVCMOS15 SLEW FAST DRIVE 16} [get_ports { phy_txd[1] }] +set_property -dict {PACKAGE_PIN AJ11 IOSTANDARD LVCMOS15 SLEW FAST DRIVE 16} [get_ports { phy_txd[2] }] +set_property -dict {PACKAGE_PIN AK10 IOSTANDARD LVCMOS15 SLEW FAST DRIVE 16} [get_ports { phy_txd[3] }] +set_property -dict {PACKAGE_PIN AK14 IOSTANDARD LVCMOS15 SLEW FAST DRIVE 16} [get_ports { phy_tx_ctl }] +set_property -dict {PACKAGE_PIN AH24 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports { phy_reset_n }] +set_property -dict {PACKAGE_PIN AK16 IOSTANDARD LVCMOS18 } [get_ports { phy_int_n }] +#set_property -dict {PACKAGE_PIN AK15 IOSTANDARD LVCMOS18} [get_ports phy_pme_n] +#set_property -dict {PACKAGE_PIN AG12 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports phy_mdio] +#set_property -dict {PACKAGE_PIN AF12 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports phy_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] set_false_path -to [get_ports {phy_reset_n}] set_output_delay 0 [get_ports {phy_reset_n}] From 66dcb9cbf36fdbc2935d7aa071920013d9029ac6 Mon Sep 17 00:00:00 2001 From: Viktor Prutyanov Date: Tue, 7 Feb 2023 20:57:02 +0300 Subject: [PATCH 3/5] example: Genesys2: fix reset, remove UART RTS/CTS ports The Genesys2 board has active-low reset instead of active-high. Also, it hasn't UART RTS/CTS ports. Signed-off-by: Viktor Prutyanov --- example/Genesys2/fpga_rgmii/rtl/fpga.v | 20 ++++++++------------ example/Genesys2/fpga_rgmii/rtl/fpga_core.v | 5 +---- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/example/Genesys2/fpga_rgmii/rtl/fpga.v b/example/Genesys2/fpga_rgmii/rtl/fpga.v index 92188383b..4df480f3f 100644 --- a/example/Genesys2/fpga_rgmii/rtl/fpga.v +++ b/example/Genesys2/fpga_rgmii/rtl/fpga.v @@ -34,11 +34,11 @@ THE SOFTWARE. module fpga ( /* * Clock: 200MHz - * Reset: Push button, active high + * Reset: Push button, active low */ input wire clk_200mhz_p, input wire clk_200mhz_n, - input wire reset, + input wire reset_n, /* * GPIO @@ -67,9 +67,7 @@ module fpga ( * UART: 500000 bps, 8N1 */ input wire uart_rxd, - output wire uart_txd, - output wire uart_rts, - input wire uart_cts + output wire uart_txd ); // Clock and reset @@ -86,7 +84,7 @@ wire rst_int; wire clk_200mhz_mmcm_out; wire clk_200mhz_int; -wire mmcm_rst = reset; +wire mmcm_rst = ~reset_n; wire mmcm_locked; wire mmcm_clkfb; @@ -219,13 +217,13 @@ wire uart_rxd_int; wire uart_cts_int; sync_signal #( - .WIDTH(2), + .WIDTH(1), .N(2) ) sync_signal_inst ( .clk(clk_int), - .in({uart_rxd, uart_cts}), - .out({uart_rxd_int, uart_cts_int}) + .in(uart_rxd), + .out(uart_rxd_int) ); // IODELAY elements for RGMII interface to PHY @@ -365,9 +363,7 @@ core_inst ( * UART: 115200 bps, 8N1 */ .uart_rxd(uart_rxd_int), - .uart_txd(uart_txd), - .uart_rts(uart_rts), - .uart_cts(uart_cts_int) + .uart_txd(uart_txd) ); endmodule diff --git a/example/Genesys2/fpga_rgmii/rtl/fpga_core.v b/example/Genesys2/fpga_rgmii/rtl/fpga_core.v index 1505d3309..5971706d5 100644 --- a/example/Genesys2/fpga_rgmii/rtl/fpga_core.v +++ b/example/Genesys2/fpga_rgmii/rtl/fpga_core.v @@ -71,9 +71,7 @@ module fpga_core # * UART: 115200 bps, 8N1 */ input wire uart_rxd, - output wire uart_txd, - output wire uart_rts, - input wire uart_cts + output wire uart_txd ); // AXI between MAC and Ethernet modules @@ -307,7 +305,6 @@ assign led = led_reg; assign phy_reset_n = !rst; assign uart_txd = 0; -assign uart_rts = 0; eth_mac_1g_rgmii_fifo #( .TARGET(TARGET), From f0a606f287f1306f05adb125fc93b46edf5aeb3f Mon Sep 17 00:00:00 2001 From: Viktor Prutyanov Date: Tue, 7 Feb 2023 21:01:51 +0300 Subject: [PATCH 4/5] example: Genesys2: fix README Signed-off-by: Viktor Prutyanov --- example/Genesys2/fpga_rgmii/README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/example/Genesys2/fpga_rgmii/README.md b/example/Genesys2/fpga_rgmii/README.md index 831019854..e70fda81d 100644 --- a/example/Genesys2/fpga_rgmii/README.md +++ b/example/Genesys2/fpga_rgmii/README.md @@ -1,18 +1,15 @@ -# Verilog Ethernet KC705 Example Design +# Verilog Ethernet Genesys2 Example Design ## Introduction -This example design targets the Xilinx KC705 FPGA board. +This example design targets the Digilent Genesys2 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 +* PHY: Realtek RTL8211E-VL ## How to build @@ -21,7 +18,7 @@ in PATH. ## How to test -Run make program to program the KC705 board with Vivado. Then run +Run make program to program the Genesys2 board with Vivado. Then run netcat -u 192.168.1.128 1234 From 9e6c137787834a850f2a3cc5c3efe2369f295958 Mon Sep 17 00:00:00 2001 From: Viktor Prutyanov Date: Wed, 8 Feb 2023 00:05:27 +0300 Subject: [PATCH 5/5] README: add Genesys2 (Xilinx Kintex 7 XC7K325T) Signed-off-by: Viktor Prutyanov --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b7f6e64aa..8bfee63d4 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ following boards: * HiTech Global HTG-V6HXT-100GIG-565 (Xilinx Virtex 6 XC6VHX565T) * Silicom fb2CG@KU15P (Xilinx Kintex UltraScale+ XCKU15P) * Xilinx KC705 (Xilinx Kintex 7 XC7K325T) +* Digilent Genesys2 (Xilinx Kintex 7 XC7K325T) * Xilinx ML605 (Xilinx Virtex 6 XC6VLX240T) * NetFPGA SUME (Xilinx Virtex 7 XC7V690T) * Digilent Nexys Video (Xilinx Artix 7 XC7A200T)