From c148b1b367e544afa16eafbdb3fcc7e7be66c211 Mon Sep 17 00:00:00 2001 From: Christer Weinigel Date: Sun, 3 Jan 2021 21:09:01 +0100 Subject: [PATCH 1/2] Create examples/VC709 based on NetFPGA_SUME --- example/VC709/fpga/Makefile | 25 + example/VC709/fpga/README.md | 25 + example/VC709/fpga/common/vivado.mk | 123 +++ example/VC709/fpga/fpga.xdc | 141 +++ example/VC709/fpga/fpga/Makefile | 73 ++ .../VC709/fpga/ip/ten_gig_eth_pcs_pma_0.tcl | 9 + .../VC709/fpga/ip/ten_gig_eth_pcs_pma_1.tcl | 9 + example/VC709/fpga/lib/eth | 1 + example/VC709/fpga/rtl/debounce_switch.v | 89 ++ example/VC709/fpga/rtl/fpga.v | 707 ++++++++++++++ example/VC709/fpga/rtl/fpga_core.v | 627 ++++++++++++ example/VC709/fpga/rtl/i2c_master.v | 895 ++++++++++++++++++ example/VC709/fpga/rtl/si5324_i2c_init.v | 494 ++++++++++ example/VC709/fpga/tb/fpga_core/Makefile | 95 ++ .../VC709/fpga/tb/fpga_core/test_fpga_core.py | 245 +++++ 15 files changed, 3558 insertions(+) create mode 100644 example/VC709/fpga/Makefile create mode 100644 example/VC709/fpga/README.md create mode 100644 example/VC709/fpga/common/vivado.mk create mode 100644 example/VC709/fpga/fpga.xdc create mode 100644 example/VC709/fpga/fpga/Makefile create mode 100644 example/VC709/fpga/ip/ten_gig_eth_pcs_pma_0.tcl create mode 100644 example/VC709/fpga/ip/ten_gig_eth_pcs_pma_1.tcl create mode 120000 example/VC709/fpga/lib/eth create mode 100644 example/VC709/fpga/rtl/debounce_switch.v create mode 100644 example/VC709/fpga/rtl/fpga.v create mode 100644 example/VC709/fpga/rtl/fpga_core.v create mode 100644 example/VC709/fpga/rtl/i2c_master.v create mode 100644 example/VC709/fpga/rtl/si5324_i2c_init.v create mode 100644 example/VC709/fpga/tb/fpga_core/Makefile create mode 100644 example/VC709/fpga/tb/fpga_core/test_fpga_core.py diff --git a/example/VC709/fpga/Makefile b/example/VC709/fpga/Makefile new file mode 100644 index 000000000..f504bd06f --- /dev/null +++ b/example/VC709/fpga/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/VC709/fpga/README.md b/example/VC709/fpga/README.md new file mode 100644 index 000000000..e6f0cba76 --- /dev/null +++ b/example/VC709/fpga/README.md @@ -0,0 +1,25 @@ +# Verilog Ethernet NetFPGA SUME Example Design + +## Introduction + +This example design targets the NetFPGA SUME 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. + +FPGA: xc7vx690tffg1761-3 +PHY: 10G BASE-R PHY IP core and internal GTH transceiver + +## 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 NetFPGA SUME 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/VC709/fpga/common/vivado.mk b/example/VC709/fpga/common/vivado.mk new file mode 100644 index 000000000..ee83637e0 --- /dev/null +++ b/example/VC709/fpga/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/VC709/fpga/fpga.xdc b/example/VC709/fpga/fpga.xdc new file mode 100644 index 000000000..3f42bd7bf --- /dev/null +++ b/example/VC709/fpga/fpga.xdc @@ -0,0 +1,141 @@ +# XDC constraints for the NetFPGA SUME +# part: xc7vx690tffg1761-3 + +# General configuration +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.UNUSEDPIN Pullup [current_design] + +# 200 MHz system clock +set_property -dict {LOC H19 IOSTANDARD LVDS} [get_ports clk_200mhz_p] +set_property -dict {LOC G18 IOSTANDARD LVDS} [get_ports clk_200mhz_n] +create_clock -period 5 -name clk_200mhz [get_ports clk_200mhz_p] + +# 200 MHz QDRII A/B MIG clock +# set_property -dict {LOC AD32 IOSTANDARD LVDS} [get_ports clk_qdrii_200mhz_p] +# set_property -dict {LOC AD33 IOSTANDARD LVDS} [get_ports clk_qdrii_200mhz_n] +# create_clock -period 5 -name clk_qdrii_200mhz [get_ports clk_qdrii_200mhz_p] + +# 200 MHz QDRII C MIG clock +# set_property -dict {LOC AU14 IOSTANDARD LVDS} [get_ports clk_qdriic_200mhz_p] +# set_property -dict {LOC AU13 IOSTANDARD LVDS} [get_ports clk_qdriic_200mhz_n] +# create_clock -period 5 -name clk_qdriic_200mhz [get_ports clk_qdriic_200mhz_p] + +# 233.33 MHz DDR3 MIG clock +# set_property -dict {LOC E34 IOSTANDARD LVDS} [get_ports clk_ddr_233mhz_p] +# set_property -dict {LOC E35 IOSTANDARD LVDS} [get_ports clk_ddr_233mhz_n] +# create_clock -period 4.286 -name clk_ddr_233mhz [get_ports clk_ddr_233mhz_p] + +# LEDs +set_property -dict {LOC G13 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[0]}] +set_property -dict {LOC L15 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[1]}] +set_property -dict {LOC AL22 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[0]}] +set_property -dict {LOC BA20 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[1]}] +set_property -dict {LOC AY18 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_led[0]}] +set_property -dict {LOC AY17 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_led[1]}] +set_property -dict {LOC P31 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_led[0]}] +set_property -dict {LOC K32 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_led[1]}] +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]}] + +# Push buttons +set_property -dict {LOC AR13 IOSTANDARD LVCMOS15} [get_ports {btn[0]}] +set_property -dict {LOC BB12 IOSTANDARD LVCMOS15} [get_ports {btn[1]}] + +# 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 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 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] +set_property -dict {LOC J37 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_3_mod_detect] +set_property -dict {LOC H36 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_mod_detect] +set_property -dict {LOC N19 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_rs[0]}] +set_property -dict {LOC P18 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_rs[1]}] +set_property -dict {LOC P20 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_rs[0]}] +set_property -dict {LOC N20 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_rs[1]}] +set_property -dict {LOC F39 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_rs[0]}] +set_property -dict {LOC G36 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_rs[1]}] +set_property -dict {LOC H38 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_rs[0]}] +set_property -dict {LOC G38 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_rs[1]}] +set_property -dict {LOC L17 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_1_los] +set_property -dict {LOC L20 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_2_los] +set_property -dict {LOC G37 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_3_los] +set_property -dict {LOC J36 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_los] +set_property -dict {LOC M18 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable] +set_property -dict {LOC B31 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable] +set_property -dict {LOC J38 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_3_tx_disable] +set_property -dict {LOC L21 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_4_tx_disable] +set_property -dict {LOC M19 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_1_tx_fault] +set_property -dict {LOC C26 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_2_tx_fault] +set_property -dict {LOC E39 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_3_tx_fault] +set_property -dict {LOC J26 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_tx_fault] + +# 156.25 MHz MGT reference clock +#create_clock -period 6.4 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] + +# 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] + +# 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 +#set_property -dict {LOC W2 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_115 GTHE2_CHANNEL_X1Y23 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC W1 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_115 GTHE2_CHANNEL_X1Y23 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AA6 } [get_ports {pcie_rx_p[1]}] ;# MGTHTXP2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AA5 } [get_ports {pcie_rx_n[1]}] ;# MGTHTXN2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AA2 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AA1 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AB4 } [get_ports {pcie_rx_p[2]}] ;# MGTHTXP1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AB3 } [get_ports {pcie_rx_n[2]}] ;# MGTHTXN1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AC2 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AC1 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AC6 } [get_ports {pcie_rx_p[3]}] ;# MGTHTXP0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AC5 } [get_ports {pcie_rx_n[3]}] ;# MGTHTXN0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AE2 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AE1 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 +#set_property -dict {LOC AD4 } [get_ports {pcie_rx_p[4]}] ;# MGTHTXP3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AD3 } [get_ports {pcie_rx_n[4]}] ;# MGTHTXN3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AG2 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXP3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AG1 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXN3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AE6 } [get_ports {pcie_rx_p[5]}] ;# MGTHTXP2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AE5 } [get_ports {pcie_rx_n[5]}] ;# MGTHTXN2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AH4 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXP2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AH3 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXN2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AF4 } [get_ports {pcie_rx_p[6]}] ;# MGTHTXP1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AF3 } [get_ports {pcie_rx_n[6]}] ;# MGTHTXN1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AJ2 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXP1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AJ1 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXN1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AG6 } [get_ports {pcie_rx_p[7]}] ;# MGTHTXP0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AG5 } [get_ports {pcie_rx_n[7]}] ;# MGTHTXN0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AK4 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXP0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AK3 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXN0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 +#set_property -dict {LOC AB8 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK1P_115 +#set_property -dict {LOC AB7 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK1N_115 +#set_property -dict {LOC AY35 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +#create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] + diff --git a/example/VC709/fpga/fpga/Makefile b/example/VC709/fpga/fpga/Makefile new file mode 100644 index 000000000..6f8ad6cb9 --- /dev/null +++ b/example/VC709/fpga/fpga/Makefile @@ -0,0 +1,73 @@ + +# FPGA settings +FPGA_PART = xc7vx690tffg1761-3 +FPGA_TOP = fpga +FPGA_ARCH = virtex7 + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/i2c_master.v +SYN_FILES += rtl/si5324_i2c_init.v +SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v +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/eth_phy_10g.v +SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v +SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v +SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v +SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v +SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v +SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v +SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v +SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.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_64.v +SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v +SYN_FILES += lib/eth/rtl/udp_64.v +SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v +SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v +SYN_FILES += lib/eth/rtl/ip_complete_64.v +SYN_FILES += lib/eth/rtl/ip_64.v +SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v +SYN_FILES += lib/eth/rtl/ip_eth_tx_64.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/ten_gig_eth_pcs_pma_0.tcl +IP_TCL_FILES += ip/ten_gig_eth_pcs_pma_1.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/VC709/fpga/ip/ten_gig_eth_pcs_pma_0.tcl b/example/VC709/fpga/ip/ten_gig_eth_pcs_pma_0.tcl new file mode 100644 index 000000000..d8359592e --- /dev/null +++ b/example/VC709/fpga/ip/ten_gig_eth_pcs_pma_0.tcl @@ -0,0 +1,9 @@ + +create_ip -name ten_gig_eth_pcs_pma -vendor xilinx.com -library ip -module_name ten_gig_eth_pcs_pma_0 + +set_property -dict [list \ + CONFIG.MDIO_Management {false} \ + CONFIG.base_kr {BASE-R} \ + CONFIG.SupportLevel {1} \ + CONFIG.DClkRate {125} \ +] [get_ips ten_gig_eth_pcs_pma_0] diff --git a/example/VC709/fpga/ip/ten_gig_eth_pcs_pma_1.tcl b/example/VC709/fpga/ip/ten_gig_eth_pcs_pma_1.tcl new file mode 100644 index 000000000..448e42ac4 --- /dev/null +++ b/example/VC709/fpga/ip/ten_gig_eth_pcs_pma_1.tcl @@ -0,0 +1,9 @@ + +create_ip -name ten_gig_eth_pcs_pma -vendor xilinx.com -library ip -module_name ten_gig_eth_pcs_pma_1 + +set_property -dict [list \ + CONFIG.MDIO_Management {false} \ + CONFIG.base_kr {BASE-R} \ + CONFIG.SupportLevel {0} \ + CONFIG.DClkRate {125} \ +] [get_ips ten_gig_eth_pcs_pma_1] diff --git a/example/VC709/fpga/lib/eth b/example/VC709/fpga/lib/eth new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/example/VC709/fpga/lib/eth @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/example/VC709/fpga/rtl/debounce_switch.v b/example/VC709/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..bb631cc35 --- /dev/null +++ b/example/VC709/fpga/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/VC709/fpga/rtl/fpga.v b/example/VC709/fpga/rtl/fpga.v new file mode 100644 index 000000000..91a32575e --- /dev/null +++ b/example/VC709/fpga/rtl/fpga.v @@ -0,0 +1,707 @@ +/* + +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 LVDS + */ + input wire clk_200mhz_p, + input wire clk_200mhz_n, + + /* + * GPIO + */ + input wire [1:0] btn, + output wire [1:0] sfp_1_led, + output wire [1:0] sfp_2_led, + output wire [1:0] sfp_3_led, + output wire [1:0] sfp_4_led, + output wire [1:0] led, + + /* + * I2C + */ + inout wire i2c_scl, + inout wire i2c_sda, + output wire i2c_mux_reset, + + /* + * Ethernet: SFP+ + */ + input wire sfp_1_rx_p, + input wire sfp_1_rx_n, + output wire sfp_1_tx_p, + output wire sfp_1_tx_n, + input wire sfp_2_rx_p, + input wire sfp_2_rx_n, + output wire sfp_2_tx_p, + output wire sfp_2_tx_n, + input wire sfp_3_rx_p, + input wire sfp_3_rx_n, + output wire sfp_3_tx_p, + output wire sfp_3_tx_n, + input wire sfp_4_rx_p, + input wire sfp_4_rx_n, + output wire sfp_4_tx_p, + output wire sfp_4_tx_n, + input wire sfp_mgt_refclk_p, + input wire sfp_mgt_refclk_n, + output wire sfp_clk_rst, + input wire sfp_1_mod_detect, + input wire sfp_2_mod_detect, + input wire sfp_3_mod_detect, + input wire sfp_4_mod_detect, + output wire [1:0] sfp_1_rs, + output wire [1:0] sfp_2_rs, + output wire [1:0] sfp_3_rs, + output wire [1:0] sfp_4_rs, + input wire sfp_1_los, + input wire sfp_2_los, + input wire sfp_3_los, + input wire sfp_4_los, + output wire sfp_1_tx_disable, + output wire sfp_2_tx_disable, + output wire sfp_3_tx_disable, + output wire sfp_4_tx_disable, + input wire sfp_1_tx_fault, + input wire sfp_2_tx_fault, + input wire sfp_3_tx_fault, + input wire sfp_4_tx_fault +); + +// Clock and reset + +wire clk_200mhz_ibufg; + +// Internal 125 MHz clock +wire clk_125mhz_mmcm_out; +wire clk_125mhz_int; +wire rst_125mhz_int; + +// Internal 156.25 MHz clock +wire clk_156mhz_int; +wire rst_156mhz_int; + +wire mmcm_rst = 1'b0; +wire mmcm_locked; +wire mmcm_clkfb; + +IBUFGDS #( + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") +) +clk_200mhz_ibufg_inst ( + .O (clk_200mhz_ibufg), + .I (clk_200mhz_p), + .IB (clk_200mhz_n) +); + +// 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(1), + .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_125mhz_mmcm_out), + .CLKOUT0B(), + .CLKOUT1(), + .CLKOUT1B(), + .CLKOUT2(), + .CLKOUT2B(), + .CLKOUT3(), + .CLKOUT3B(), + .CLKOUT4(), + .CLKOUT5(), + .CLKOUT6(), + .CLKFBOUT(mmcm_clkfb), + .CLKFBOUTB(), + .LOCKED(mmcm_locked) +); + +BUFG +clk_125mhz_bufg_inst ( + .I(clk_125mhz_mmcm_out), + .O(clk_125mhz_int) +); + +sync_reset #( + .N(4) +) +sync_reset_125mhz_inst ( + .clk(clk_125mhz_int), + .rst(~mmcm_locked), + .out(rst_125mhz_int) +); + +// GPIO +wire [1:0] btn_int; +wire [1:0] sfp_1_led_int; +wire [1:0] sfp_2_led_int; +wire [1:0] sfp_3_led_int; +wire [1:0] sfp_4_led_int; +wire [1:0] led_int; + +debounce_switch #( + .WIDTH(2), + .N(4), + .RATE(156250) +) +debounce_switch_inst ( + .clk(clk_156mhz_int), + .rst(rst_156mhz_int), + .in({btn}), + .out({btn_int}) +); + +// I2C +assign i2c_scl_i = i2c_scl; +assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o; +assign i2c_sda_i = i2c_sda; +assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o; + +wire [6:0] si5324_i2c_cmd_address; +wire si5324_i2c_cmd_start; +wire si5324_i2c_cmd_read; +wire si5324_i2c_cmd_write; +wire si5324_i2c_cmd_write_multiple; +wire si5324_i2c_cmd_stop; +wire si5324_i2c_cmd_valid; +wire si5324_i2c_cmd_ready; + +wire [7:0] si5324_i2c_data; +wire si5324_i2c_data_valid; +wire si5324_i2c_data_ready; +wire si5324_i2c_data_last; + +wire si5324_i2c_init_busy; + +assign i2c_mux_reset = rst_125mhz_int; +assign sfp_clk_rst = rst_125mhz_int; + +// delay start by ~10 ms +reg [20:0] si5324_i2c_init_start_delay = 21'd0; + +always @(posedge clk_125mhz_int) begin + if (rst_125mhz_int) begin + si5324_i2c_init_start_delay <= 21'd0; + end else begin + if (!si5324_i2c_init_start_delay[20]) begin + si5324_i2c_init_start_delay <= si5324_i2c_init_start_delay + 21'd1; + end + end +end + +si5324_i2c_init +si5324_i2c_init_inst ( + .clk(clk_125mhz_int), + .rst(rst_125mhz_int), + .cmd_address(si5324_i2c_cmd_address), + .cmd_start(si5324_i2c_cmd_start), + .cmd_read(si5324_i2c_cmd_read), + .cmd_write(si5324_i2c_cmd_write), + .cmd_write_multiple(si5324_i2c_cmd_write_multiple), + .cmd_stop(si5324_i2c_cmd_stop), + .cmd_valid(si5324_i2c_cmd_valid), + .cmd_ready(si5324_i2c_cmd_ready), + .data_out(si5324_i2c_data), + .data_out_valid(si5324_i2c_data_valid), + .data_out_ready(si5324_i2c_data_ready), + .data_out_last(si5324_i2c_data_last), + .busy(si5324_i2c_init_busy), + .start(si5324_i2c_init_start_delay[20]) +); + +i2c_master +si5324_i2c_master_inst ( + .clk(clk_125mhz_int), + .rst(rst_125mhz_int), + .cmd_address(si5324_i2c_cmd_address), + .cmd_start(si5324_i2c_cmd_start), + .cmd_read(si5324_i2c_cmd_read), + .cmd_write(si5324_i2c_cmd_write), + .cmd_write_multiple(si5324_i2c_cmd_write_multiple), + .cmd_stop(si5324_i2c_cmd_stop), + .cmd_valid(si5324_i2c_cmd_valid), + .cmd_ready(si5324_i2c_cmd_ready), + .data_in(si5324_i2c_data), + .data_in_valid(si5324_i2c_data_valid), + .data_in_ready(si5324_i2c_data_ready), + .data_in_last(si5324_i2c_data_last), + .data_out(), + .data_out_valid(), + .data_out_ready(1), + .data_out_last(), + .scl_i(i2c_scl_i), + .scl_o(i2c_scl_o), + .scl_t(i2c_scl_t), + .sda_i(i2c_sda_i), + .sda_o(i2c_sda_o), + .sda_t(i2c_sda_t), + .busy(), + .bus_control(), + .bus_active(), + .missed_ack(), + .prescale(312), + .stop_on_idle(1) +); + +// XGMII 10G PHY + +assign sfp_1_tx_disable = 1'b0; +assign sfp_2_tx_disable = 1'b0; +assign sfp_3_tx_disable = 1'b0; +assign sfp_4_tx_disable = 1'b0; +assign sfp_1_rs = 1'b1; +assign sfp_2_rs = 1'b1; +assign sfp_3_rs = 1'b1; +assign sfp_4_rs = 1'b1; + +wire sfp_1_tx_clk_int = clk_156mhz_int; +wire sfp_1_tx_rst_int = rst_156mhz_int; +wire [63:0] sfp_1_txd_int; +wire [7:0] sfp_1_txc_int; +wire sfp_1_rx_clk_int = clk_156mhz_int; +wire sfp_1_rx_rst_int = rst_156mhz_int; +wire [63:0] sfp_1_rxd_int; +wire [7:0] sfp_1_rxc_int; +wire sfp_2_tx_clk_int = clk_156mhz_int; +wire sfp_2_tx_rst_int = rst_156mhz_int; +wire [63:0] sfp_2_txd_int; +wire [7:0] sfp_2_txc_int; +wire sfp_2_rx_clk_int = clk_156mhz_int; +wire sfp_2_rx_rst_int = rst_156mhz_int; +wire [63:0] sfp_2_rxd_int; +wire [7:0] sfp_2_rxc_int; +wire sfp_3_tx_clk_int = clk_156mhz_int; +wire sfp_3_tx_rst_int = rst_156mhz_int; +wire [63:0] sfp_3_txd_int; +wire [7:0] sfp_3_txc_int; +wire sfp_3_rx_clk_int = clk_156mhz_int; +wire sfp_3_rx_rst_int = rst_156mhz_int; +wire [63:0] sfp_3_rxd_int; +wire [7:0] sfp_3_rxc_int; +wire sfp_4_tx_clk_int = clk_156mhz_int; +wire sfp_4_tx_rst_int = rst_156mhz_int; +wire [63:0] sfp_4_txd_int; +wire [7:0] sfp_4_txc_int; +wire sfp_4_rx_clk_int = clk_156mhz_int; +wire sfp_4_rx_rst_int = rst_156mhz_int; +wire [63:0] sfp_4_rxd_int; +wire [7:0] sfp_4_rxc_int; + +wire sfp_reset_in; +wire sfp_txusrclk; +wire sfp_txusrclk2; +wire sfp_coreclk; +wire sfp_qplloutclk; +wire sfp_qplloutrefclk; +wire sfp_qplllock; +wire sfp_gttxreset; +wire sfp_gtrxreset; +wire sfp_txuserrdy; +wire sfp_areset_datapathclk; +wire sfp_resetdone; +wire sfp_reset_counter_done; + +sync_reset #( + .N(4) +) +sync_reset_sfp_inst ( + .clk(sfp_coreclk), + .rst(rst_125mhz_int || si5324_i2c_init_busy), + .out(sfp_reset_in) +); + +//assign sfp_reset_in = rst_125mhz_int || si5324_i2c_init_busy; + +assign clk_156mhz_int = sfp_coreclk; + +sync_reset #( + .N(4) +) +sync_reset_156mhz_inst ( + .clk(clk_156mhz_int), + .rst(!sfp_resetdone), + .out(rst_156mhz_int) +); + +wire [535:0] sfp_config_vector; + +assign sfp_config_vector[14:1] = 0; +assign sfp_config_vector[79:17] = 0; +assign sfp_config_vector[109:84] = 0; +assign sfp_config_vector[175:170] = 0; +assign sfp_config_vector[239:234] = 0; +assign sfp_config_vector[269:246] = 0; +assign sfp_config_vector[511:272] = 0; +assign sfp_config_vector[515:513] = 0; +assign sfp_config_vector[517:517] = 0; +assign sfp_config_vector[0] = 0; // pma_loopback; +assign sfp_config_vector[15] = 0; // pma_reset; +assign sfp_config_vector[16] = 0; // global_tx_disable; +assign sfp_config_vector[83:80] = 0; // pma_vs_loopback; +assign sfp_config_vector[110] = 0; // pcs_loopback; +assign sfp_config_vector[111] = 0; // pcs_reset; +assign sfp_config_vector[169:112] = 0; // test_patt_a; +assign sfp_config_vector[233:176] = 0; // test_patt_b; +assign sfp_config_vector[240] = 0; // data_patt_sel; +assign sfp_config_vector[241] = 0; // test_patt_sel; +assign sfp_config_vector[242] = 0; // rx_test_patt_en; +assign sfp_config_vector[243] = 0; // tx_test_patt_en; +assign sfp_config_vector[244] = 0; // prbs31_tx_en; +assign sfp_config_vector[245] = 0; // prbs31_rx_en; +assign sfp_config_vector[271:270] = 0; // pcs_vs_loopback; +assign sfp_config_vector[512] = 0; // set_pma_link_status; +assign sfp_config_vector[516] = 0; // set_pcs_link_status; +assign sfp_config_vector[518] = 0; // clear_pcs_status2; +assign sfp_config_vector[519] = 0; // clear_test_patt_err_count; +assign sfp_config_vector[535:520] = 0; + +wire [447:0] sfp_1_status_vector; +wire [447:0] sfp_2_status_vector; +wire [447:0] sfp_3_status_vector; +wire [447:0] sfp_4_status_vector; + +wire sfp_1_rx_block_lock = sfp_1_status_vector[256]; +wire sfp_2_rx_block_lock = sfp_2_status_vector[256]; +wire sfp_3_rx_block_lock = sfp_3_status_vector[256]; +wire sfp_4_rx_block_lock = sfp_4_status_vector[256]; + +wire [7:0] sfp_1_core_status; +wire [7:0] sfp_2_core_status; +wire [7:0] sfp_3_core_status; +wire [7:0] sfp_4_core_status; + +ten_gig_eth_pcs_pma_0 +sfp_1_pcs_pma_inst ( + .dclk(clk_125mhz_int), + .rxrecclk_out(), + .refclk_p(sfp_mgt_refclk_p), + .refclk_n(sfp_mgt_refclk_n), + .sim_speedup_control(1'b0), + .coreclk_out(sfp_coreclk), + .qplloutclk_out(sfp_qplloutclk), + .qplloutrefclk_out(sfp_qplloutrefclk), + .qplllock_out(sfp_qplllock), + .txusrclk_out(sfp_txusrclk), + .txusrclk2_out(sfp_txusrclk2), + .areset_datapathclk_out(sfp_areset_datapathclk), + .gttxreset_out(sfp_gttxreset), + .gtrxreset_out(sfp_gtrxreset), + .txuserrdy_out(sfp_txuserrdy), + .reset_counter_done_out(sfp_reset_counter_done), + .reset(sfp_reset_in), + .xgmii_txd(sfp_1_txd_int), + .xgmii_txc(sfp_1_txc_int), + .xgmii_rxd(sfp_1_rxd_int), + .xgmii_rxc(sfp_1_rxc_int), + .txp(sfp_1_tx_p), + .txn(sfp_1_tx_n), + .rxp(sfp_1_rx_p), + .rxn(sfp_1_rx_n), + .configuration_vector(sfp_config_vector), + .status_vector(sfp_1_status_vector), + .core_status(sfp_1_core_status), + .resetdone_out(sfp_resetdone), + .signal_detect(1'b1), + .tx_fault(1'b0), + .drp_req(), + .drp_gnt(1'b1), + .drp_den_o(), + .drp_dwe_o(), + .drp_daddr_o(), + .drp_di_o(), + .drp_drdy_o(), + .drp_drpdo_o(), + .drp_den_i(1'b0), + .drp_dwe_i(1'b0), + .drp_daddr_i(16'd0), + .drp_di_i(16'd0), + .drp_drdy_i(1'b0), + .drp_drpdo_i(16'd0), + .pma_pmd_type(3'd0), + .tx_disable() +); + +ten_gig_eth_pcs_pma_1 +sfp_2_pcs_pma_inst ( + .dclk(clk_125mhz_int), + .rxrecclk_out(), + .coreclk(sfp_coreclk), + .txusrclk(sfp_txusrclk), + .txusrclk2(sfp_txusrclk2), + .txoutclk(), + .areset(sfp_reset_in), + .areset_coreclk(sfp_areset_datapathclk), + .gttxreset(sfp_gttxreset), + .gtrxreset(sfp_gtrxreset), + .sim_speedup_control(1'b0), + .txuserrdy(sfp_txuserrdy), + .qplllock(sfp_qplllock), + .qplloutclk(sfp_qplloutclk), + .qplloutrefclk(sfp_qplloutrefclk), + .reset_counter_done(sfp_reset_counter_done), + .xgmii_txd(sfp_2_txd_int), + .xgmii_txc(sfp_2_txc_int), + .xgmii_rxd(sfp_2_rxd_int), + .xgmii_rxc(sfp_2_rxc_int), + .txp(sfp_2_tx_p), + .txn(sfp_2_tx_n), + .rxp(sfp_2_rx_p), + .rxn(sfp_2_rx_n), + .configuration_vector(sfp_config_vector), + .status_vector(sfp_2_status_vector), + .core_status(sfp_2_core_status), + .tx_resetdone(), + .rx_resetdone(), + .signal_detect(1'b1), + .tx_fault(1'b0), + .drp_req(), + .drp_gnt(1'b1), + .drp_den_o(), + .drp_dwe_o(), + .drp_daddr_o(), + .drp_di_o(), + .drp_drdy_o(), + .drp_drpdo_o(), + .drp_den_i(1'b0), + .drp_dwe_i(1'b0), + .drp_daddr_i(16'd0), + .drp_di_i(16'd0), + .drp_drdy_i(1'b0), + .drp_drpdo_i(16'd0), + .pma_pmd_type(3'd0), + .tx_disable() +); + +ten_gig_eth_pcs_pma_1 +sfp_3_pcs_pma_inst ( + .dclk(clk_125mhz_int), + .rxrecclk_out(), + .coreclk(sfp_coreclk), + .txusrclk(sfp_txusrclk), + .txusrclk2(sfp_txusrclk2), + .txoutclk(), + .areset(sfp_reset_in), + .areset_coreclk(sfp_areset_datapathclk), + .gttxreset(sfp_gttxreset), + .gtrxreset(sfp_gtrxreset), + .sim_speedup_control(1'b0), + .txuserrdy(sfp_txuserrdy), + .qplllock(sfp_qplllock), + .qplloutclk(sfp_qplloutclk), + .qplloutrefclk(sfp_qplloutrefclk), + .reset_counter_done(sfp_reset_counter_done), + .xgmii_txd(sfp_3_txd_int), + .xgmii_txc(sfp_3_txc_int), + .xgmii_rxd(sfp_3_rxd_int), + .xgmii_rxc(sfp_3_rxc_int), + .txp(sfp_3_tx_p), + .txn(sfp_3_tx_n), + .rxp(sfp_3_rx_p), + .rxn(sfp_3_rx_n), + .configuration_vector(sfp_config_vector), + .status_vector(sfp_3_status_vector), + .core_status(sfp_3_core_status), + .tx_resetdone(), + .rx_resetdone(), + .signal_detect(1'b1), + .tx_fault(1'b0), + .drp_req(), + .drp_gnt(1'b1), + .drp_den_o(), + .drp_dwe_o(), + .drp_daddr_o(), + .drp_di_o(), + .drp_drdy_o(), + .drp_drpdo_o(), + .drp_den_i(1'b0), + .drp_dwe_i(1'b0), + .drp_daddr_i(16'd0), + .drp_di_i(16'd0), + .drp_drdy_i(1'b0), + .drp_drpdo_i(16'd0), + .pma_pmd_type(3'd0), + .tx_disable() +); + +ten_gig_eth_pcs_pma_1 +sfp_4_pcs_pma_inst ( + .dclk(clk_125mhz_int), + .rxrecclk_out(), + .coreclk(sfp_coreclk), + .txusrclk(sfp_txusrclk), + .txusrclk2(sfp_txusrclk2), + .txoutclk(), + .areset(sfp_reset_in), + .areset_coreclk(sfp_areset_datapathclk), + .gttxreset(sfp_gttxreset), + .gtrxreset(sfp_gtrxreset), + .sim_speedup_control(1'b0), + .txuserrdy(sfp_txuserrdy), + .qplllock(sfp_qplllock), + .qplloutclk(sfp_qplloutclk), + .qplloutrefclk(sfp_qplloutrefclk), + .reset_counter_done(sfp_reset_counter_done), + .xgmii_txd(sfp_4_txd_int), + .xgmii_txc(sfp_4_txc_int), + .xgmii_rxd(sfp_4_rxd_int), + .xgmii_rxc(sfp_4_rxc_int), + .txp(sfp_4_tx_p), + .txn(sfp_4_tx_n), + .rxp(sfp_4_rx_p), + .rxn(sfp_4_rx_n), + .configuration_vector(sfp_config_vector), + .status_vector(sfp_4_status_vector), + .core_status(sfp_4_core_status), + .tx_resetdone(), + .rx_resetdone(), + .signal_detect(1'b1), + .tx_fault(1'b0), + .drp_req(), + .drp_gnt(1'b1), + .drp_den_o(), + .drp_dwe_o(), + .drp_daddr_o(), + .drp_di_o(), + .drp_drdy_o(), + .drp_drpdo_o(), + .drp_den_i(1'b0), + .drp_dwe_i(1'b0), + .drp_daddr_i(16'd0), + .drp_di_i(16'd0), + .drp_drdy_i(1'b0), + .drp_drpdo_i(16'd0), + .pma_pmd_type(3'd0), + .tx_disable() +); + +assign sfp_1_led[0] = sfp_1_rx_block_lock; +assign sfp_1_led[1] = 1'b0; +assign sfp_2_led[0] = sfp_2_rx_block_lock; +assign sfp_2_led[1] = 1'b0; +assign sfp_3_led[0] = sfp_3_rx_block_lock; +assign sfp_3_led[1] = 1'b0; +assign sfp_4_led[0] = sfp_4_rx_block_lock; +assign sfp_4_led[1] = 1'b0; +assign led = led_int; + +fpga_core +core_inst ( + /* + * Clock: 156.25 MHz + * Synchronous reset + */ + .clk(clk_156mhz_int), + .rst(rst_156mhz_int), + /* + * GPIO + */ + .btn(btn_int), + .sfp_1_led(sfp_1_led_int), + .sfp_2_led(sfp_2_led_int), + .sfp_3_led(sfp_3_led_int), + .sfp_4_led(sfp_4_led_int), + .led(led_int), + /* + * Ethernet: SFP+ + */ + .sfp_1_tx_clk(sfp_1_tx_clk_int), + .sfp_1_tx_rst(sfp_1_tx_rst_int), + .sfp_1_txd(sfp_1_txd_int), + .sfp_1_txc(sfp_1_txc_int), + .sfp_1_rx_clk(sfp_1_rx_clk_int), + .sfp_1_rx_rst(sfp_1_rx_rst_int), + .sfp_1_rxd(sfp_1_rxd_int), + .sfp_1_rxc(sfp_1_rxc_int), + .sfp_2_tx_clk(sfp_2_tx_clk_int), + .sfp_2_tx_rst(sfp_2_tx_rst_int), + .sfp_2_txd(sfp_2_txd_int), + .sfp_2_txc(sfp_2_txc_int), + .sfp_2_rx_clk(sfp_2_rx_clk_int), + .sfp_2_rx_rst(sfp_2_rx_rst_int), + .sfp_2_rxd(sfp_2_rxd_int), + .sfp_2_rxc(sfp_2_rxc_int), + .sfp_3_tx_clk(sfp_3_tx_clk_int), + .sfp_3_tx_rst(sfp_3_tx_rst_int), + .sfp_3_txd(sfp_3_txd_int), + .sfp_3_txc(sfp_3_txc_int), + .sfp_3_rx_clk(sfp_3_rx_clk_int), + .sfp_3_rx_rst(sfp_3_rx_rst_int), + .sfp_3_rxd(sfp_3_rxd_int), + .sfp_3_rxc(sfp_3_rxc_int), + .sfp_4_tx_clk(sfp_4_tx_clk_int), + .sfp_4_tx_rst(sfp_4_tx_rst_int), + .sfp_4_txd(sfp_4_txd_int), + .sfp_4_txc(sfp_4_txc_int), + .sfp_4_rx_clk(sfp_4_rx_clk_int), + .sfp_4_rx_rst(sfp_4_rx_rst_int), + .sfp_4_rxd(sfp_4_rxd_int), + .sfp_4_rxc(sfp_4_rxc_int) +); + +endmodule diff --git a/example/VC709/fpga/rtl/fpga_core.v b/example/VC709/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..c72ccecd6 --- /dev/null +++ b/example/VC709/fpga/rtl/fpga_core.v @@ -0,0 +1,627 @@ +/* + +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: 156.25MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire [1:0] btn, + output wire [1:0] sfp_1_led, + output wire [1:0] sfp_2_led, + output wire [1:0] sfp_3_led, + output wire [1:0] sfp_4_led, + output wire [1:0] led, + + /* + * I2C + */ + input wire i2c_scl_i, + output wire i2c_scl_o, + output wire i2c_scl_t, + input wire i2c_sda_i, + output wire i2c_sda_o, + output wire i2c_sda_t, + + /* + * Ethernet: SFP+ + */ + input wire sfp_1_tx_clk, + input wire sfp_1_tx_rst, + output wire [63:0] sfp_1_txd, + output wire [7:0] sfp_1_txc, + input wire sfp_1_rx_clk, + input wire sfp_1_rx_rst, + input wire [63:0] sfp_1_rxd, + input wire [7:0] sfp_1_rxc, + input wire sfp_2_tx_clk, + input wire sfp_2_tx_rst, + output wire [63:0] sfp_2_txd, + output wire [7:0] sfp_2_txc, + input wire sfp_2_rx_clk, + input wire sfp_2_rx_rst, + input wire [63:0] sfp_2_rxd, + input wire [7:0] sfp_2_rxc, + input wire sfp_3_tx_clk, + input wire sfp_3_tx_rst, + output wire [63:0] sfp_3_txd, + output wire [7:0] sfp_3_txc, + input wire sfp_3_rx_clk, + input wire sfp_3_rx_rst, + input wire [63:0] sfp_3_rxd, + input wire [7:0] sfp_3_rxc, + input wire sfp_4_tx_clk, + input wire sfp_4_tx_rst, + output wire [63:0] sfp_4_txd, + output wire [7:0] sfp_4_txc, + input wire sfp_4_rx_clk, + input wire sfp_4_rx_rst, + input wire [63:0] sfp_4_rxd, + input wire [7:0] sfp_4_rxc +); + +// AXI between MAC and Ethernet modules +wire [63:0] rx_axis_tdata; +wire [7:0] rx_axis_tkeep; +wire rx_axis_tvalid; +wire rx_axis_tready; +wire rx_axis_tlast; +wire rx_axis_tuser; + +wire [63:0] tx_axis_tdata; +wire [7:0] tx_axis_tkeep; +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 [63:0] rx_eth_payload_axis_tdata; +wire [7:0] rx_eth_payload_axis_tkeep; +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 [63:0] tx_eth_payload_axis_tdata; +wire [7:0] tx_eth_payload_axis_tkeep; +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 [63:0] rx_ip_payload_axis_tdata; +wire [7:0] rx_ip_payload_axis_tkeep; +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 [63:0] tx_ip_payload_axis_tdata; +wire [7:0] tx_ip_payload_axis_tkeep; +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 [63:0] rx_udp_payload_axis_tdata; +wire [7:0] rx_udp_payload_axis_tkeep; +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 [63:0] tx_udp_payload_axis_tdata; +wire [7:0] tx_udp_payload_axis_tkeep; +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 [63:0] rx_fifo_udp_payload_axis_tdata; +wire [7:0] rx_fifo_udp_payload_axis_tkeep; +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 [63:0] tx_fifo_udp_payload_axis_tdata; +wire [7:0] tx_fifo_udp_payload_axis_tkeep; +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_tkeep = 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_tkeep = tx_fifo_udp_payload_axis_tkeep; +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_tkeep = rx_udp_payload_axis_tkeep; +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 + valid_last <= tx_udp_payload_axis_tvalid; + if (tx_udp_payload_axis_tvalid & ~valid_last) begin + led_reg <= tx_udp_payload_axis_tdata; + end + end +end + +assign led = led_reg; + +assign sfp_2_txd = 64'h0707070707070707; +assign sfp_2_txc = 8'hff; +assign sfp_3_txd = 64'h0707070707070707; +assign sfp_3_txc = 8'hff; +assign sfp_4_txd = 64'h0707070707070707; +assign sfp_4_txc = 8'hff; + +eth_mac_10g_fifo #( + .ENABLE_PADDING(1), + .ENABLE_DIC(1), + .MIN_FRAME_LENGTH(64), + .TX_FIFO_DEPTH(4096), + .TX_FRAME_FIFO(1), + .RX_FIFO_DEPTH(4096), + .RX_FRAME_FIFO(1) +) +eth_mac_10g_fifo_inst ( + .rx_clk(sfp_1_rx_clk), + .rx_rst(sfp_1_rx_rst), + .tx_clk(sfp_1_tx_clk), + .tx_rst(sfp_1_tx_rst), + .logic_clk(clk), + .logic_rst(rst), + + .tx_axis_tdata(tx_axis_tdata), + .tx_axis_tkeep(tx_axis_tkeep), + .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_tkeep(rx_axis_tkeep), + .rx_axis_tvalid(rx_axis_tvalid), + .rx_axis_tready(rx_axis_tready), + .rx_axis_tlast(rx_axis_tlast), + .rx_axis_tuser(rx_axis_tuser), + + .xgmii_rxd(sfp_1_rxd), + .xgmii_rxc(sfp_1_rxc), + .xgmii_txd(sfp_1_txd), + .xgmii_txc(sfp_1_txc), + + .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(8'd12) +); + +eth_axis_rx #( + .DATA_WIDTH(64) +) +eth_axis_rx_inst ( + .clk(clk), + .rst(rst), + // AXI input + .s_axis_tdata(rx_axis_tdata), + .s_axis_tkeep(rx_axis_tkeep), + .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_tkeep(rx_eth_payload_axis_tkeep), + .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 #( + .DATA_WIDTH(64) +) +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_tkeep(tx_eth_payload_axis_tkeep), + .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_tkeep(tx_axis_tkeep), + .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_64 +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_tkeep(rx_eth_payload_axis_tkeep), + .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_tkeep(tx_eth_payload_axis_tkeep), + .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_tkeep(tx_ip_payload_axis_tkeep), + .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_tkeep(rx_ip_payload_axis_tkeep), + .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_tkeep(tx_udp_payload_axis_tkeep), + .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_tkeep(rx_udp_payload_axis_tkeep), + .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(1'b0) +); + +axis_fifo #( + .DEPTH(8192), + .DATA_WIDTH(64), + .KEEP_ENABLE(1), + .KEEP_WIDTH(8), + .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(rx_fifo_udp_payload_axis_tkeep), + .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(tx_fifo_udp_payload_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/VC709/fpga/rtl/i2c_master.v b/example/VC709/fpga/rtl/i2c_master.v new file mode 100644 index 000000000..95d3a5212 --- /dev/null +++ b/example/VC709/fpga/rtl/i2c_master.v @@ -0,0 +1,895 @@ +/* + +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 + +/* + * I2C master + */ +module i2c_master ( + input wire clk, + input wire rst, + + /* + * Host interface + */ + input wire [6:0] cmd_address, + input wire cmd_start, + input wire cmd_read, + input wire cmd_write, + input wire cmd_write_multiple, + input wire cmd_stop, + input wire cmd_valid, + output wire cmd_ready, + + input wire [7:0] data_in, + input wire data_in_valid, + output wire data_in_ready, + input wire data_in_last, + + output wire [7:0] data_out, + output wire data_out_valid, + input wire data_out_ready, + output wire data_out_last, + + /* + * I2C interface + */ + input wire scl_i, + output wire scl_o, + output wire scl_t, + input wire sda_i, + output wire sda_o, + output wire sda_t, + + /* + * Status + */ + output wire busy, + output wire bus_control, + output wire bus_active, + output wire missed_ack, + + /* + * Configuration + */ + input wire [15:0] prescale, + input wire stop_on_idle +); + +/* + +I2C + +Read + __ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ __ +sda \__/_6_X_5_X_4_X_3_X_2_X_1_X_0_\_R___A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A____/ + ____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____ +scl ST \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ SP + +Write + __ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ __ +sda \__/_6_X_5_X_4_X_3_X_2_X_1_X_0_/_W_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_/_N_\__/ + ____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____ +scl ST \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ SP + +Commands: + +read + read data byte + set start to force generation of a start condition + start is implied when bus is inactive or active with write or different address + set stop to issue a stop condition after reading current byte + if stop is set with read command, then data_out_last will be set + +write + write data byte + set start to force generation of a start condition + start is implied when bus is inactive or active with read or different address + set stop to issue a stop condition after writing current byte + +write multiple + write multiple data bytes (until data_in_last) + set start to force generation of a start condition + start is implied when bus is inactive or active with read or different address + set stop to issue a stop condition after writing block + +stop + issue stop condition if bus is active + +Status: + +busy + module is communicating over the bus + +bus_control + module has control of bus in active state + +bus_active + bus is active, not necessarily controlled by this module + +missed_ack + strobed when a slave ack is missed + +Parameters: + +prescale + set prescale to 1/4 of the minimum clock period in units + of input clk cycles (prescale = Fclk / (FI2Cclk * 4)) + +stop_on_idle + automatically issue stop when command input is not valid + +Example of interfacing with tristate pins: +(this will work for any tristate bus) + +assign scl_i = scl_pin; +assign scl_pin = scl_t ? 1'bz : scl_o; +assign sda_i = sda_pin; +assign sda_pin = sda_t ? 1'bz : sda_o; + +Equivalent code that does not use *_t connections: +(we can get away with this because I2C is open-drain) + +assign scl_i = scl_pin; +assign scl_pin = scl_o ? 1'bz : 1'b0; +assign sda_i = sda_pin; +assign sda_pin = sda_o ? 1'bz : 1'b0; + +Example of two interconnected I2C devices: + +assign scl_1_i = scl_1_o & scl_2_o; +assign scl_2_i = scl_1_o & scl_2_o; +assign sda_1_i = sda_1_o & sda_2_o; +assign sda_2_i = sda_1_o & sda_2_o; + +Example of two I2C devices sharing the same pins: + +assign scl_1_i = scl_pin; +assign scl_2_i = scl_pin; +assign scl_pin = (scl_1_o & scl_2_o) ? 1'bz : 1'b0; +assign sda_1_i = sda_pin; +assign sda_2_i = sda_pin; +assign sda_pin = (sda_1_o & sda_2_o) ? 1'bz : 1'b0; + +Notes: + +scl_o should not be connected directly to scl_i, only via AND logic or a tristate +I/O pin. This would prevent devices from stretching the clock period. + +*/ + +localparam [4:0] + STATE_IDLE = 4'd0, + STATE_ACTIVE_WRITE = 4'd1, + STATE_ACTIVE_READ = 4'd2, + STATE_START_WAIT = 4'd3, + STATE_START = 4'd4, + STATE_ADDRESS_1 = 4'd5, + STATE_ADDRESS_2 = 4'd6, + STATE_WRITE_1 = 4'd7, + STATE_WRITE_2 = 4'd8, + STATE_WRITE_3 = 4'd9, + STATE_READ = 4'd10, + STATE_STOP = 4'd11; + +reg [4:0] state_reg = STATE_IDLE, state_next; + +localparam [4:0] + PHY_STATE_IDLE = 5'd0, + PHY_STATE_ACTIVE = 5'd1, + PHY_STATE_REPEATED_START_1 = 5'd2, + PHY_STATE_REPEATED_START_2 = 5'd3, + PHY_STATE_START_1 = 5'd4, + PHY_STATE_START_2 = 5'd5, + PHY_STATE_WRITE_BIT_1 = 5'd6, + PHY_STATE_WRITE_BIT_2 = 5'd7, + PHY_STATE_WRITE_BIT_3 = 5'd8, + PHY_STATE_READ_BIT_1 = 5'd9, + PHY_STATE_READ_BIT_2 = 5'd10, + PHY_STATE_READ_BIT_3 = 5'd11, + PHY_STATE_READ_BIT_4 = 5'd12, + PHY_STATE_STOP_1 = 5'd13, + PHY_STATE_STOP_2 = 5'd14, + PHY_STATE_STOP_3 = 5'd15; + +reg [4:0] phy_state_reg = STATE_IDLE, phy_state_next; + +reg phy_start_bit; +reg phy_stop_bit; +reg phy_write_bit; +reg phy_read_bit; +reg phy_release_bus; + +reg phy_tx_data; + +reg phy_rx_data_reg = 1'b0, phy_rx_data_next; + +reg [6:0] addr_reg = 7'd0, addr_next; +reg [7:0] data_reg = 8'd0, data_next; +reg last_reg = 1'b0, last_next; + +reg mode_read_reg = 1'b0, mode_read_next; +reg mode_write_multiple_reg = 1'b0, mode_write_multiple_next; +reg mode_stop_reg = 1'b0, mode_stop_next; + +reg [16:0] delay_reg = 16'd0, delay_next; +reg delay_scl_reg = 1'b0, delay_scl_next; +reg delay_sda_reg = 1'b0, delay_sda_next; + +reg [3:0] bit_count_reg = 4'd0, bit_count_next; + +reg cmd_ready_reg = 1'b0, cmd_ready_next; + +reg data_in_ready_reg = 1'b0, data_in_ready_next; + +reg [7:0] data_out_reg = 8'd0, data_out_next; +reg data_out_valid_reg = 1'b0, data_out_valid_next; +reg data_out_last_reg = 1'b0, data_out_last_next; + +reg scl_i_reg = 1'b1; +reg sda_i_reg = 1'b1; + +reg scl_o_reg = 1'b1, scl_o_next; +reg sda_o_reg = 1'b1, sda_o_next; + +reg last_scl_i_reg = 1'b1; +reg last_sda_i_reg = 1'b1; + +reg busy_reg = 1'b0; +reg bus_active_reg = 1'b0; +reg bus_control_reg = 1'b0, bus_control_next; +reg missed_ack_reg = 1'b0, missed_ack_next; + +assign cmd_ready = cmd_ready_reg; + +assign data_in_ready = data_in_ready_reg; + +assign data_out = data_out_reg; +assign data_out_valid = data_out_valid_reg; +assign data_out_last = data_out_last_reg; + +assign scl_o = scl_o_reg; +assign scl_t = scl_o_reg; +assign sda_o = sda_o_reg; +assign sda_t = sda_o_reg; + +assign busy = busy_reg; +assign bus_active = bus_active_reg; +assign bus_control = bus_control_reg; +assign missed_ack = missed_ack_reg; + +wire scl_posedge = scl_i_reg & ~last_scl_i_reg; +wire scl_negedge = ~scl_i_reg & last_scl_i_reg; +wire sda_posedge = sda_i_reg & ~last_sda_i_reg; +wire sda_negedge = ~sda_i_reg & last_sda_i_reg; + +wire start_bit = sda_negedge & scl_i_reg; +wire stop_bit = sda_posedge & scl_i_reg; + +always @* begin + state_next = STATE_IDLE; + + phy_start_bit = 1'b0; + phy_stop_bit = 1'b0; + phy_write_bit = 1'b0; + phy_read_bit = 1'b0; + phy_tx_data = 1'b0; + phy_release_bus = 1'b0; + + addr_next = addr_reg; + data_next = data_reg; + last_next = last_reg; + + mode_read_next = mode_read_reg; + mode_write_multiple_next = mode_write_multiple_reg; + mode_stop_next = mode_stop_reg; + + bit_count_next = bit_count_reg; + + cmd_ready_next = 1'b0; + + data_in_ready_next = 1'b0; + + data_out_next = data_out_reg; + data_out_valid_next = data_out_valid_reg & ~data_out_ready; + data_out_last_next = data_out_last_reg; + + missed_ack_next = 1'b0; + + // generate delays + if (phy_state_reg != PHY_STATE_IDLE && phy_state_reg != PHY_STATE_ACTIVE) begin + // wait for phy operation + state_next = state_reg; + end else begin + // process states + case (state_reg) + STATE_IDLE: begin + // line idle + cmd_ready_next = 1'b1; + + if (cmd_ready & cmd_valid) begin + // command valid + if (cmd_read ^ (cmd_write | cmd_write_multiple)) begin + // read or write command + addr_next = cmd_address; + mode_read_next = cmd_read; + mode_write_multiple_next = cmd_write_multiple; + mode_stop_next = cmd_stop; + + cmd_ready_next = 1'b0; + + // start bit + if (bus_active) begin + state_next = STATE_START_WAIT; + end else begin + phy_start_bit = 1'b1; + bit_count_next = 4'd8; + state_next = STATE_ADDRESS_1; + end + end else begin + // invalid or unspecified - ignore + state_next = STATE_IDLE; + end + end else begin + state_next = STATE_IDLE; + end + end + STATE_ACTIVE_WRITE: begin + // line active with current address and read/write mode + cmd_ready_next = 1'b1; + + if (cmd_ready & cmd_valid) begin + // command valid + if (cmd_read ^ (cmd_write | cmd_write_multiple)) begin + // read or write command + addr_next = cmd_address; + mode_read_next = cmd_read; + mode_write_multiple_next = cmd_write_multiple; + mode_stop_next = cmd_stop; + + cmd_ready_next = 1'b0; + + if (cmd_start || cmd_address != addr_reg || cmd_read) begin + // address or mode mismatch or forced start - repeated start + + // repeated start bit + phy_start_bit = 1'b1; + bit_count_next = 4'd8; + state_next = STATE_ADDRESS_1; + end else begin + // address and mode match + + // start write + data_in_ready_next = 1'b1; + state_next = STATE_WRITE_1; + end + end else if (cmd_stop && !(cmd_read || cmd_write || cmd_write_multiple)) begin + // stop command + phy_stop_bit = 1'b1; + state_next = STATE_IDLE; + end else begin + // invalid or unspecified - ignore + state_next = STATE_ACTIVE_WRITE; + end + end else begin + if (stop_on_idle & cmd_ready & ~cmd_valid) begin + // no waiting command and stop_on_idle selected, issue stop condition + phy_stop_bit = 1'b1; + state_next = STATE_IDLE; + end else begin + state_next = STATE_ACTIVE_WRITE; + end + end + end + STATE_ACTIVE_READ: begin + // line active to current address + cmd_ready_next = ~data_out_valid; + + if (cmd_ready & cmd_valid) begin + // command valid + if (cmd_read ^ (cmd_write | cmd_write_multiple)) begin + // read or write command + addr_next = cmd_address; + mode_read_next = cmd_read; + mode_write_multiple_next = cmd_write_multiple; + mode_stop_next = cmd_stop; + + cmd_ready_next = 1'b0; + + if (cmd_start || cmd_address != addr_reg || cmd_write) begin + // address or mode mismatch or forced start - repeated start + + // write nack for previous read + phy_write_bit = 1'b1; + phy_tx_data = 1'b1; + // repeated start bit + state_next = STATE_START; + end else begin + // address and mode match + + // write ack for previous read + phy_write_bit = 1'b1; + phy_tx_data = 1'b0; + // start next read + bit_count_next = 4'd8; + data_next = 8'd0; + state_next = STATE_READ; + end + end else if (cmd_stop && !(cmd_read || cmd_write || cmd_write_multiple)) begin + // stop command + // write nack for previous read + phy_write_bit = 1'b1; + phy_tx_data = 1'b1; + // send stop bit + state_next = STATE_STOP; + end else begin + // invalid or unspecified - ignore + state_next = STATE_ACTIVE_READ; + end + end else begin + if (stop_on_idle & cmd_ready & ~cmd_valid) begin + // no waiting command and stop_on_idle selected, issue stop condition + // write ack for previous read + phy_write_bit = 1'b1; + phy_tx_data = 1'b1; + // send stop bit + state_next = STATE_STOP; + end else begin + state_next = STATE_ACTIVE_READ; + end + end + end + STATE_START_WAIT: begin + // wait for bus idle + + if (bus_active) begin + state_next = STATE_START_WAIT; + end else begin + // bus is idle, take control + phy_start_bit = 1'b1; + bit_count_next = 4'd8; + state_next = STATE_ADDRESS_1; + end + end + STATE_START: begin + // send start bit + + phy_start_bit = 1'b1; + bit_count_next = 4'd8; + state_next = STATE_ADDRESS_1; + end + STATE_ADDRESS_1: begin + // send address + bit_count_next = bit_count_reg - 1; + if (bit_count_reg > 1) begin + // send address + phy_write_bit = 1'b1; + phy_tx_data = addr_reg[bit_count_reg-2]; + state_next = STATE_ADDRESS_1; + end else if (bit_count_reg > 0) begin + // send read/write bit + phy_write_bit = 1'b1; + phy_tx_data = mode_read_reg; + state_next = STATE_ADDRESS_1; + end else begin + // read ack bit + phy_read_bit = 1'b1; + state_next = STATE_ADDRESS_2; + end + end + STATE_ADDRESS_2: begin + // read ack bit + missed_ack_next = phy_rx_data_reg; + + if (mode_read_reg) begin + // start read + bit_count_next = 4'd8; + data_next = 1'b0; + state_next = STATE_READ; + end else begin + // start write + data_in_ready_next = 1'b1; + state_next = STATE_WRITE_1; + end + end + STATE_WRITE_1: begin + data_in_ready_next = 1'b1; + + if (data_in_ready & data_in_valid) begin + // got data, start write + data_next = data_in; + last_next = data_in_last; + bit_count_next = 4'd8; + data_in_ready_next = 1'b0; + state_next = STATE_WRITE_2; + end else begin + // wait for data + state_next = STATE_WRITE_1; + end + end + STATE_WRITE_2: begin + // send data + bit_count_next = bit_count_reg - 1; + if (bit_count_reg > 0) begin + // write data bit + phy_write_bit = 1'b1; + phy_tx_data = data_reg[bit_count_reg-1]; + state_next = STATE_WRITE_2; + end else begin + // read ack bit + phy_read_bit = 1'b1; + state_next = STATE_WRITE_3; + end + end + STATE_WRITE_3: begin + // read ack bit + missed_ack_next = phy_rx_data_reg; + + if (mode_write_multiple_reg && !last_reg) begin + // more to write + state_next = STATE_WRITE_1; + end else if (mode_stop_reg) begin + // last cycle and stop selected + phy_stop_bit = 1'b1; + state_next = STATE_IDLE; + end else begin + // otherwise, return to bus active state + state_next = STATE_ACTIVE_WRITE; + end + end + STATE_READ: begin + // read data + + bit_count_next = bit_count_reg - 1; + data_next = {data_reg[6:0], phy_rx_data_reg}; + if (bit_count_reg > 0) begin + // read next bit + phy_read_bit = 1'b1; + state_next = STATE_READ; + end else begin + // output data word + data_out_next = data_next; + data_out_valid_next = 1'b1; + data_out_last_next = 1'b0; + if (mode_stop_reg) begin + // send nack and stop + data_out_last_next = 1'b1; + phy_write_bit = 1'b1; + phy_tx_data = 1'b1; + state_next = STATE_STOP; + end else begin + // return to bus active state + state_next = STATE_ACTIVE_READ; + end + end + end + STATE_STOP: begin + // send stop bit + phy_stop_bit = 1'b1; + state_next = STATE_IDLE; + end + endcase + end +end + +always @* begin + phy_state_next = PHY_STATE_IDLE; + + phy_rx_data_next = phy_rx_data_reg; + + delay_next = delay_reg; + delay_scl_next = delay_scl_reg; + delay_sda_next = delay_sda_reg; + + scl_o_next = scl_o_reg; + sda_o_next = sda_o_reg; + + bus_control_next = bus_control_reg; + + if (phy_release_bus) begin + // release bus and return to idle state + sda_o_next = 1'b1; + scl_o_next = 1'b1; + delay_scl_next = 1'b0; + delay_sda_next = 1'b0; + delay_next = 1'b0; + phy_state_next = PHY_STATE_IDLE; + end else if (delay_scl_reg) begin + // wait for SCL to match command + delay_scl_next = scl_o_reg & ~scl_i_reg; + phy_state_next = phy_state_reg; + end else if (delay_sda_reg) begin + // wait for SDA to match command + delay_sda_next = sda_o_reg & ~sda_i_reg; + phy_state_next = phy_state_reg; + end else if (delay_reg > 0) begin + // time delay + delay_next = delay_reg - 1; + phy_state_next = phy_state_reg; + end else begin + case (phy_state_reg) + PHY_STATE_IDLE: begin + // bus idle - wait for start command + sda_o_next = 1'b1; + scl_o_next = 1'b1; + if (phy_start_bit) begin + sda_o_next = 1'b0; + delay_next = prescale; + phy_state_next = PHY_STATE_START_1; + end else begin + phy_state_next = PHY_STATE_IDLE; + end + end + PHY_STATE_ACTIVE: begin + // bus active + if (phy_start_bit) begin + sda_o_next = 1'b1; + delay_next = prescale; + phy_state_next = PHY_STATE_REPEATED_START_1; + end else if (phy_write_bit) begin + sda_o_next = phy_tx_data; + delay_next = prescale; + phy_state_next = PHY_STATE_WRITE_BIT_1; + end else if (phy_read_bit) begin + sda_o_next = 1'b1; + delay_next = prescale; + phy_state_next = PHY_STATE_READ_BIT_1; + end else if (phy_stop_bit) begin + sda_o_next = 1'b0; + delay_next = prescale; + phy_state_next = PHY_STATE_STOP_1; + end else begin + phy_state_next = PHY_STATE_ACTIVE; + end + end + PHY_STATE_REPEATED_START_1: begin + // generate repeated start bit + // ______ + // sda XXX/ \_______ + // _______ + // scl ______/ \___ + // + + scl_o_next = 1'b1; + delay_scl_next = 1'b1; + delay_next = prescale; + phy_state_next = PHY_STATE_REPEATED_START_2; + end + PHY_STATE_REPEATED_START_2: begin + // generate repeated start bit + // ______ + // sda XXX/ \_______ + // _______ + // scl ______/ \___ + // + + sda_o_next = 1'b0; + delay_next = prescale; + phy_state_next = PHY_STATE_START_1; + end + PHY_STATE_START_1: begin + // generate start bit + // ___ + // sda \_______ + // _______ + // scl \___ + // + + scl_o_next = 1'b0; + delay_next = prescale; + phy_state_next = PHY_STATE_START_2; + end + PHY_STATE_START_2: begin + // generate start bit + // ___ + // sda \_______ + // _______ + // scl \___ + // + + bus_control_next = 1'b1; + phy_state_next = PHY_STATE_ACTIVE; + end + PHY_STATE_WRITE_BIT_1: begin + // write bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + scl_o_next = 1'b1; + delay_scl_next = 1'b1; + delay_next = prescale << 1; + phy_state_next = PHY_STATE_WRITE_BIT_2; + end + PHY_STATE_WRITE_BIT_2: begin + // write bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + scl_o_next = 1'b0; + delay_next = prescale; + phy_state_next = PHY_STATE_WRITE_BIT_3; + end + PHY_STATE_WRITE_BIT_3: begin + // write bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + phy_state_next = PHY_STATE_ACTIVE; + end + PHY_STATE_READ_BIT_1: begin + // read bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + scl_o_next = 1'b1; + delay_scl_next = 1'b1; + delay_next = prescale; + phy_state_next = PHY_STATE_READ_BIT_2; + end + PHY_STATE_READ_BIT_2: begin + // read bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + phy_rx_data_next = sda_i_reg; + delay_next = prescale; + phy_state_next = PHY_STATE_READ_BIT_3; + end + PHY_STATE_READ_BIT_3: begin + // read bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + scl_o_next = 1'b0; + delay_next = prescale; + phy_state_next = PHY_STATE_READ_BIT_4; + end + PHY_STATE_READ_BIT_4: begin + // read bit + // ________ + // sda X________X + // ____ + // scl __/ \__ + + phy_state_next = PHY_STATE_ACTIVE; + end + PHY_STATE_STOP_1: begin + // stop bit + // ___ + // sda XXX\_______/ + // _______ + // scl _______/ + + scl_o_next = 1'b1; + delay_scl_next = 1'b1; + delay_next = prescale; + phy_state_next = PHY_STATE_STOP_2; + end + PHY_STATE_STOP_2: begin + // stop bit + // ___ + // sda XXX\_______/ + // _______ + // scl _______/ + + sda_o_next = 1'b1; + delay_next = prescale; + phy_state_next = PHY_STATE_STOP_3; + end + PHY_STATE_STOP_3: begin + // stop bit + // ___ + // sda XXX\_______/ + // _______ + // scl _______/ + + bus_control_next = 1'b0; + phy_state_next = PHY_STATE_IDLE; + end + endcase + end +end + +always @(posedge clk) begin + if (rst) begin + state_reg <= STATE_IDLE; + phy_state_reg <= PHY_STATE_IDLE; + delay_reg <= 16'd0; + delay_scl_reg <= 1'b0; + delay_sda_reg <= 1'b0; + cmd_ready_reg <= 1'b0; + data_in_ready_reg <= 1'b0; + data_out_valid_reg <= 1'b0; + scl_o_reg <= 1'b1; + sda_o_reg <= 1'b1; + busy_reg <= 1'b0; + bus_active_reg <= 1'b0; + bus_control_reg <= 1'b0; + missed_ack_reg <= 1'b0; + end else begin + state_reg <= state_next; + phy_state_reg <= phy_state_next; + + delay_reg <= delay_next; + delay_scl_reg <= delay_scl_next; + delay_sda_reg <= delay_sda_next; + + cmd_ready_reg <= cmd_ready_next; + data_in_ready_reg <= data_in_ready_next; + data_out_valid_reg <= data_out_valid_next; + + scl_o_reg <= scl_o_next; + sda_o_reg <= sda_o_next; + + busy_reg <= !(state_reg == STATE_IDLE || state_reg == STATE_ACTIVE_WRITE || state_reg == STATE_ACTIVE_READ); + + if (start_bit) begin + bus_active_reg <= 1'b1; + end else if (stop_bit) begin + bus_active_reg <= 1'b0; + end else begin + bus_active_reg <= bus_active_reg; + end + + bus_control_reg <= bus_control_next; + missed_ack_reg <= missed_ack_next; + end + + phy_rx_data_reg <= phy_rx_data_next; + + addr_reg <= addr_next; + data_reg <= data_next; + last_reg <= last_next; + + mode_read_reg <= mode_read_next; + mode_write_multiple_reg <= mode_write_multiple_next; + mode_stop_reg <= mode_stop_next; + + bit_count_reg <= bit_count_next; + + data_out_reg <= data_out_next; + data_out_last_reg <= data_out_last_next; + + scl_i_reg <= scl_i; + sda_i_reg <= sda_i; + last_scl_i_reg <= scl_i_reg; + last_sda_i_reg <= sda_i_reg; +end + +endmodule diff --git a/example/VC709/fpga/rtl/si5324_i2c_init.v b/example/VC709/fpga/rtl/si5324_i2c_init.v new file mode 100644 index 000000000..3669903e1 --- /dev/null +++ b/example/VC709/fpga/rtl/si5324_i2c_init.v @@ -0,0 +1,494 @@ +/* + +Copyright (c) 2015-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 + +/* + * si5324_i2c_init + */ +module si5324_i2c_init ( + input wire clk, + input wire rst, + + /* + * I2C master interface + */ + output wire [6:0] cmd_address, + output wire cmd_start, + output wire cmd_read, + output wire cmd_write, + output wire cmd_write_multiple, + output wire cmd_stop, + output wire cmd_valid, + input wire cmd_ready, + + output wire [7:0] data_out, + output wire data_out_valid, + input wire data_out_ready, + output wire data_out_last, + + /* + * Status + */ + output wire busy, + + /* + * Configuration + */ + input wire start +); + +/* + +Generic module for I2C bus initialization. Good for use when multiple devices +on an I2C bus must be initialized on system start without intervention of a +general-purpose processor. + +Copy this file and change init_data and INIT_DATA_LEN as needed. + +This module can be used in two modes: simple device initalization, or multiple +device initialization. In multiple device mode, the same initialization sequence +can be performed on multiple different device addresses. + +To use single device mode, only use the start write to address and write data commands. +The module will generate the I2C commands in sequential order. Terminate the list +with a 0 entry. + +To use the multiple device mode, use the start data and start address block commands +to set up lists of initialization data and device addresses. The module enters +multiple device mode upon seeing a start data block command. The module stores the +offset of the start of the data block and then skips ahead until it reaches a start +address block command. The module will store the offset to the address block and +read the first address in the block. Then it will jump back to the data block +and execute it, substituting the stored address for each current address write +command. Upon reaching the start address block command, the module will read out the +next address and start again at the top of the data block. If the module encounters +a start data block command while looking for an address, then it will store a new data +offset and then look for a start address block command. Terminate the list with a 0 +entry. Normal address commands will operate normally inside a data block. + +Commands: + +00 0000000 : stop +00 0000001 : exit multiple device mode +00 0000011 : start write to current address +00 0001000 : start address block +00 0001001 : start data block +00 1000001 : send I2C stop +01 aaaaaaa : start write to address +1 dddddddd : write 8-bit data + +Examples + +write 0x11223344 to register 0x0004 on device at 0x50 + +01 1010000 start write to 0x50 +1 00000000 write address 0x0004 +1 00000100 +1 00010001 write data 0x11223344 +1 00100010 +1 00110011 +1 01000100 +0 00000000 stop + +write 0x11223344 to register 0x0004 on devices at 0x50, 0x51, 0x52, and 0x53 + +00 0001001 start data block +00 0000011 start write to current address +1 00000100 +1 00010001 write data 0x11223344 +1 00100010 +1 00110011 +1 01000100 +00 0001000 start address block +01 1010000 address 0x50 +01 1010000 address 0x51 +01 1010000 address 0x52 +01 1010000 address 0x53 +00 0000000 stop + +*/ + +// init_data ROM +localparam INIT_DATA_LEN = 37; + +reg [8:0] init_data [INIT_DATA_LEN-1:0]; + +initial begin + // init Si5324 registers + init_data[0] = {2'b01, 7'h74}; // start write to 0x74 (I2C mux) + init_data[1] = {1'b1, 8'h10}; // select Si5324 + init_data[2] = {2'b00, 7'b1000001}; // I2C stop + init_data[3] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) + init_data[4] = {1'b1, 8'd0}; // register 0 + init_data[5] = {1'b1, 8'h54}; // Reg 0: Free run, Clock off before ICAL, Bypass off (normal operation) + init_data[6] = {1'b1, 8'hE4}; // Reg 1: CKIN2 second priority, CKIN1 first priority + init_data[7] = {1'b1, 8'h12}; // Reg 2: BWSEL = 1 + init_data[8] = {1'b1, 8'h15}; // Reg 3: CKIN1 selected, Digital Hold off, Output clocks disabled during ICAL + init_data[9] = {1'b1, 8'h92}; // Reg 4: Automatic Revertive, HIST_DEL = 0x12 + init_data[10] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) + init_data[11] = {1'b1, 8'd10}; // register 10 + init_data[12] = {1'b1, 8'h08}; // Reg 10: CKOUT2 disabled, CKOUT1 enabled + init_data[13] = {1'b1, 8'h40}; // Reg 11: CKIN2 enabled, CKIN1 enabled + init_data[14] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) + init_data[15] = {1'b1, 8'd25}; // register 25 + init_data[16] = {1'b1, 8'hA0}; // Reg 25: N1_HS = 9 + init_data[17] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) + init_data[18] = {1'b1, 8'd31}; // register 31 + init_data[19] = {1'b1, 8'h00}; // Regs 31,32,33: NC1_LS = 4 + init_data[20] = {1'b1, 8'h00}; + init_data[21] = {1'b1, 8'h03}; + init_data[22] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) + init_data[23] = {1'b1, 8'd40}; // register 40 + init_data[24] = {1'b1, 8'hC2}; // Regs 40,41,42: N2_HS = 10, N2_LS = 150000 + init_data[25] = {1'b1, 8'h49}; + init_data[26] = {1'b1, 8'hEF}; + init_data[27] = {1'b1, 8'h00}; // Regs 43,44,45: N31 = 30475 + init_data[28] = {1'b1, 8'h77}; + init_data[29] = {1'b1, 8'h0B}; + init_data[30] = {1'b1, 8'h00}; // Regs 46,47,48: N32 = 30475 + init_data[31] = {1'b1, 8'h77}; + init_data[32] = {1'b1, 8'h0B}; + init_data[33] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) + init_data[34] = {1'b1, 8'd136}; // register 136 + init_data[35] = {1'b1, 8'h40}; // Reg 136: ICAL = 1 + init_data[36] = 9'd0; // stop +end + +localparam [3:0] + STATE_IDLE = 3'd0, + STATE_RUN = 3'd1, + STATE_TABLE_1 = 3'd2, + STATE_TABLE_2 = 3'd3, + STATE_TABLE_3 = 3'd4; + +reg [4:0] state_reg = STATE_IDLE, state_next; + +parameter AW = $clog2(INIT_DATA_LEN); + +reg [8:0] init_data_reg = 9'd0; + +reg [AW-1:0] address_reg = {AW{1'b0}}, address_next; +reg [AW-1:0] address_ptr_reg = {AW{1'b0}}, address_ptr_next; +reg [AW-1:0] data_ptr_reg = {AW{1'b0}}, data_ptr_next; + +reg [6:0] cur_address_reg = 7'd0, cur_address_next; + +reg [6:0] cmd_address_reg = 7'd0, cmd_address_next; +reg cmd_start_reg = 1'b0, cmd_start_next; +reg cmd_write_reg = 1'b0, cmd_write_next; +reg cmd_stop_reg = 1'b0, cmd_stop_next; +reg cmd_valid_reg = 1'b0, cmd_valid_next; + +reg [7:0] data_out_reg = 8'd0, data_out_next; +reg data_out_valid_reg = 1'b0, data_out_valid_next; + +reg start_flag_reg = 1'b0, start_flag_next; + +reg busy_reg = 1'b0; + +assign cmd_address = cmd_address_reg; +assign cmd_start = cmd_start_reg; +assign cmd_read = 1'b0; +assign cmd_write = cmd_write_reg; +assign cmd_write_multiple = 1'b0; +assign cmd_stop = cmd_stop_reg; +assign cmd_valid = cmd_valid_reg; + +assign data_out = data_out_reg; +assign data_out_valid = data_out_valid_reg; +assign data_out_last = 1'b1; + +assign busy = busy_reg; + +always @* begin + state_next = STATE_IDLE; + + address_next = address_reg; + address_ptr_next = address_ptr_reg; + data_ptr_next = data_ptr_reg; + + cur_address_next = cur_address_reg; + + cmd_address_next = cmd_address_reg; + cmd_start_next = cmd_start_reg & ~(cmd_valid & cmd_ready); + cmd_write_next = cmd_write_reg & ~(cmd_valid & cmd_ready); + cmd_stop_next = cmd_stop_reg & ~(cmd_valid & cmd_ready); + cmd_valid_next = cmd_valid_reg & ~cmd_ready; + + data_out_next = data_out_reg; + data_out_valid_next = data_out_valid_reg & ~data_out_ready; + + start_flag_next = start_flag_reg; + + if (cmd_valid | data_out_valid) begin + // wait for output registers to clear + state_next = state_reg; + end else begin + case (state_reg) + STATE_IDLE: begin + // wait for start signal + if (~start_flag_reg & start) begin + address_next = {AW{1'b0}}; + start_flag_next = 1'b1; + state_next = STATE_RUN; + end else begin + state_next = STATE_IDLE; + end + end + STATE_RUN: begin + // process commands + if (init_data_reg[8] == 1'b1) begin + // write data + cmd_write_next = 1'b1; + cmd_stop_next = 1'b0; + cmd_valid_next = 1'b1; + + data_out_next = init_data_reg[7:0]; + data_out_valid_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_RUN; + end else if (init_data_reg[8:7] == 2'b01) begin + // write address + cmd_address_next = init_data_reg[6:0]; + cmd_start_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_RUN; + end else if (init_data_reg == 9'b001000001) begin + // send stop + cmd_write_next = 1'b0; + cmd_start_next = 1'b0; + cmd_stop_next = 1'b1; + cmd_valid_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_RUN; + end else if (init_data_reg == 9'b000001001) begin + // data table start + data_ptr_next = address_reg + 1; + address_next = address_reg + 1; + state_next = STATE_TABLE_1; + end else if (init_data_reg == 9'd0) begin + // stop + cmd_start_next = 1'b0; + cmd_write_next = 1'b0; + cmd_stop_next = 1'b1; + cmd_valid_next = 1'b1; + + state_next = STATE_IDLE; + end else begin + // invalid command, skip + address_next = address_reg + 1; + state_next = STATE_RUN; + end + end + STATE_TABLE_1: begin + // find address table start + if (init_data_reg == 9'b000001000) begin + // address table start + address_ptr_next = address_reg + 1; + address_next = address_reg + 1; + state_next = STATE_TABLE_2; + end else if (init_data_reg == 9'b000001001) begin + // data table start + data_ptr_next = address_reg + 1; + address_next = address_reg + 1; + state_next = STATE_TABLE_1; + end else if (init_data_reg == 1) begin + // exit mode + address_next = address_reg + 1; + state_next = STATE_RUN; + end else if (init_data_reg == 9'd0) begin + // stop + cmd_start_next = 1'b0; + cmd_write_next = 1'b0; + cmd_stop_next = 1'b1; + cmd_valid_next = 1'b1; + + state_next = STATE_IDLE; + end else begin + // invalid command, skip + address_next = address_reg + 1; + state_next = STATE_TABLE_1; + end + end + STATE_TABLE_2: begin + // find next address + if (init_data_reg[8:7] == 2'b01) begin + // write address command + // store address and move to data table + cur_address_next = init_data_reg[6:0]; + address_ptr_next = address_reg + 1; + address_next = data_ptr_reg; + state_next = STATE_TABLE_3; + end else if (init_data_reg == 9'b000001001) begin + // data table start + data_ptr_next = address_reg + 1; + address_next = address_reg + 1; + state_next = STATE_TABLE_1; + end else if (init_data_reg == 9'd1) begin + // exit mode + address_next = address_reg + 1; + state_next = STATE_RUN; + end else if (init_data_reg == 9'd0) begin + // stop + cmd_start_next = 1'b0; + cmd_write_next = 1'b0; + cmd_stop_next = 1'b1; + cmd_valid_next = 1'b1; + + state_next = STATE_IDLE; + end else begin + // invalid command, skip + address_next = address_reg + 1; + state_next = STATE_TABLE_2; + end + end + STATE_TABLE_3: begin + // process data table with selected address + if (init_data_reg[8] == 1'b1) begin + // write data + cmd_write_next = 1'b1; + cmd_stop_next = 1'b0; + cmd_valid_next = 1'b1; + + data_out_next = init_data_reg[7:0]; + data_out_valid_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_TABLE_3; + end else if (init_data_reg[8:7] == 2'b01) begin + // write address + cmd_address_next = init_data_reg[6:0]; + cmd_start_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_TABLE_3; + end else if (init_data_reg == 9'b000000011) begin + // write current address + cmd_address_next = cur_address_reg; + cmd_start_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_TABLE_3; + end else if (init_data_reg == 9'b001000001) begin + // send stop + cmd_write_next = 1'b0; + cmd_start_next = 1'b0; + cmd_stop_next = 1'b1; + cmd_valid_next = 1'b1; + + address_next = address_reg + 1; + + state_next = STATE_TABLE_3; + end else if (init_data_reg == 9'b000001001) begin + // data table start + data_ptr_next = address_reg + 1; + address_next = address_reg + 1; + state_next = STATE_TABLE_1; + end else if (init_data_reg == 9'b000001000) begin + // address table start + address_next = address_ptr_reg; + state_next = STATE_TABLE_2; + end else if (init_data_reg == 9'd1) begin + // exit mode + address_next = address_reg + 1; + state_next = STATE_RUN; + end else if (init_data_reg == 9'd0) begin + // stop + cmd_start_next = 1'b0; + cmd_write_next = 1'b0; + cmd_stop_next = 1'b1; + cmd_valid_next = 1'b1; + + state_next = STATE_IDLE; + end else begin + // invalid command, skip + address_next = address_reg + 1; + state_next = STATE_TABLE_3; + end + end + endcase + end +end + +always @(posedge clk) begin + if (rst) begin + state_reg <= STATE_IDLE; + + init_data_reg <= 9'd0; + + address_reg <= {AW{1'b0}}; + address_ptr_reg <= {AW{1'b0}}; + data_ptr_reg <= {AW{1'b0}}; + + cur_address_reg <= 7'd0; + + cmd_valid_reg <= 1'b0; + + data_out_valid_reg <= 1'b0; + + start_flag_reg <= 1'b0; + + busy_reg <= 1'b0; + end else begin + state_reg <= state_next; + + // read init_data ROM + init_data_reg <= init_data[address_next]; + + address_reg <= address_next; + address_ptr_reg <= address_ptr_next; + data_ptr_reg <= data_ptr_next; + + cur_address_reg <= cur_address_next; + + cmd_valid_reg <= cmd_valid_next; + + data_out_valid_reg <= data_out_valid_next; + + start_flag_reg <= start & start_flag_next; + + busy_reg <= (state_reg != STATE_IDLE); + end + + cmd_address_reg <= cmd_address_next; + cmd_start_reg <= cmd_start_next; + cmd_write_reg <= cmd_write_next; + cmd_stop_reg <= cmd_stop_next; + + data_out_reg <= data_out_next; +end + +endmodule diff --git a/example/VC709/fpga/tb/fpga_core/Makefile b/example/VC709/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..87e6cf660 --- /dev/null +++ b/example/VC709/fpga/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_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 + +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/VC709/fpga/tb/fpga_core/test_fpga_core.py b/example/VC709/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..b6ec23c1d --- /dev/null +++ b/example/VC709/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.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_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, + ) From 8f038fc9daf8843b2f7f700983146e078aab4b00 Mon Sep 17 00:00:00 2001 From: Christer Weinigel Date: Sun, 3 Jan 2021 23:18:48 +0100 Subject: [PATCH 2/2] Make examples/VC709 work The VC709 and NetFPGA_SUME are very similar. The same gtx transceiver IP blocks are used, just with different pin assigmnents. The I2C MUX and SI5324 resets are active low on the VC709 compared to active high on the NetFPGA_SUME. Additionally, the SI5324 is connected to port 7 of the I2C mux on VC709 compared to being connected to port 4 on the NetFPGA. Other than that the LEDs and buttons are different. --- example/VC709/fpga/Makefile | 3 - example/VC709/fpga/fpga.xdc | 185 +++++++---------------- example/VC709/fpga/fpga/Makefile | 3 +- example/VC709/fpga/rtl/fpga.v | 74 ++++----- example/VC709/fpga/rtl/si5324_i2c_init.v | 2 +- 5 files changed, 87 insertions(+), 180 deletions(-) diff --git a/example/VC709/fpga/Makefile b/example/VC709/fpga/Makefile index f504bd06f..3a968e304 100644 --- a/example/VC709/fpga/Makefile +++ b/example/VC709/fpga/Makefile @@ -20,6 +20,3 @@ $(SUBDIRS_CLEAN): .PHONY: clean clean: $(SUBDIRS_CLEAN) -rm -rf $(TARGETS) - -program: - #djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit diff --git a/example/VC709/fpga/fpga.xdc b/example/VC709/fpga/fpga.xdc index 3f42bd7bf..b07af5bf7 100644 --- a/example/VC709/fpga/fpga.xdc +++ b/example/VC709/fpga/fpga.xdc @@ -1,141 +1,72 @@ -# XDC constraints for the NetFPGA SUME -# part: xc7vx690tffg1761-3 +# XDC constraints for the Xilinx VC709 +# part: xc7vx690tffg1761-2 # General configuration -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.UNUSEDPIN Pullup [current_design] +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.CONFIG.BPI_SYNC_MODE Type1 [current_design] +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN div-1 [current_design] +set_property BITSTREAM.GENERAL.COMPRESS true [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN Pulldown [current_design] +set_property CONFIG_MODE BPI16 [current_design] # 200 MHz system clock set_property -dict {LOC H19 IOSTANDARD LVDS} [get_ports clk_200mhz_p] set_property -dict {LOC G18 IOSTANDARD LVDS} [get_ports clk_200mhz_n] create_clock -period 5 -name clk_200mhz [get_ports clk_200mhz_p] -# 200 MHz QDRII A/B MIG clock -# set_property -dict {LOC AD32 IOSTANDARD LVDS} [get_ports clk_qdrii_200mhz_p] -# set_property -dict {LOC AD33 IOSTANDARD LVDS} [get_ports clk_qdrii_200mhz_n] -# create_clock -period 5 -name clk_qdrii_200mhz [get_ports clk_qdrii_200mhz_p] - -# 200 MHz QDRII C MIG clock -# set_property -dict {LOC AU14 IOSTANDARD LVDS} [get_ports clk_qdriic_200mhz_p] -# set_property -dict {LOC AU13 IOSTANDARD LVDS} [get_ports clk_qdriic_200mhz_n] -# create_clock -period 5 -name clk_qdriic_200mhz [get_ports clk_qdriic_200mhz_p] - -# 233.33 MHz DDR3 MIG clock -# set_property -dict {LOC E34 IOSTANDARD LVDS} [get_ports clk_ddr_233mhz_p] -# set_property -dict {LOC E35 IOSTANDARD LVDS} [get_ports clk_ddr_233mhz_n] -# create_clock -period 4.286 -name clk_ddr_233mhz [get_ports clk_ddr_233mhz_p] - -# LEDs -set_property -dict {LOC G13 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[0]}] -set_property -dict {LOC L15 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[1]}] -set_property -dict {LOC AL22 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[0]}] -set_property -dict {LOC BA20 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[1]}] -set_property -dict {LOC AY18 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_led[0]}] -set_property -dict {LOC AY17 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_led[1]}] -set_property -dict {LOC P31 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_led[0]}] -set_property -dict {LOC K32 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_led[1]}] -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]}] +# LEDs 0-7 +set_property -dict {LOC AM39 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[0]}] +set_property -dict {LOC AN39 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[1]}] +set_property -dict {LOC AR37 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[2]}] +set_property -dict {LOC AT37 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[3]}] +set_property -dict {LOC AR35 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[4]}] +set_property -dict {LOC AP41 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[5]}] +set_property -dict {LOC AP42 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[6]}] +set_property -dict {LOC AU39 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led[7]}] # 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_property -dict {LOC AU38 IOSTANDARD LVCMOS18} [get_ports {btn[0]}] +set_property -dict {LOC AW40 IOSTANDARD LVCMOS18} [get_ports {btn[1]}] # 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 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 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] -set_property -dict {LOC J37 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_3_mod_detect] -set_property -dict {LOC H36 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_mod_detect] -set_property -dict {LOC N19 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_rs[0]}] -set_property -dict {LOC P18 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_1_rs[1]}] -set_property -dict {LOC P20 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_rs[0]}] -set_property -dict {LOC N20 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_2_rs[1]}] -set_property -dict {LOC F39 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_rs[0]}] -set_property -dict {LOC G36 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_3_rs[1]}] -set_property -dict {LOC H38 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_rs[0]}] -set_property -dict {LOC G38 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports {sfp_4_rs[1]}] -set_property -dict {LOC L17 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_1_los] -set_property -dict {LOC L20 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_2_los] -set_property -dict {LOC G37 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_3_los] -set_property -dict {LOC J36 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_los] -set_property -dict {LOC M18 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable] -set_property -dict {LOC B31 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable] -set_property -dict {LOC J38 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_3_tx_disable] -set_property -dict {LOC L21 IOSTANDARD LVCMOS15 SLEW SLOW DRIVE 12} [get_ports sfp_4_tx_disable] -set_property -dict {LOC M19 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_1_tx_fault] -set_property -dict {LOC C26 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_2_tx_fault] -set_property -dict {LOC E39 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_3_tx_fault] -set_property -dict {LOC J26 IOSTANDARD LVCMOS15 PULLUP true} [get_ports sfp_4_tx_fault] - -# 156.25 MHz MGT reference clock -#create_clock -period 6.4 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] +set_property -dict {LOC AM8 } [get_ports sfp_1_rx_p] +set_property -dict {LOC AN2 } [get_ports sfp_1_tx_p] +set_property -dict {LOC AN6 } [get_ports sfp_2_rx_p] +set_property -dict {LOC AP4 } [get_ports sfp_2_tx_p] +set_property -dict {LOC AL6 } [get_ports sfp_3_rx_p] +set_property -dict {LOC AM4 } [get_ports sfp_3_tx_p] +set_property -dict {LOC AJ6 } [get_ports sfp_4_rx_p] +set_property -dict {LOC AL2 } [get_ports sfp_4_tx_p] +set_property -dict {LOC AH8 } [get_ports sfp_mgt_refclk_p] +set_property -dict {LOC AH7 } [get_ports sfp_mgt_refclk_n] +set_property -dict {LOC AT36 IOSTANDARD LVCMOS18} [get_ports sfp_clk_rst_n] +set_property -dict {LOC AA42 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_mod_detect] +set_property -dict {LOC AB42 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_2_mod_detect] +set_property -dict {LOC AC39 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_3_mod_detect] +set_property -dict {LOC AC41 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_4_mod_detect] +set_property -dict {LOC W40 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_1_rs[0]}] +set_property -dict {LOC Y40 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_1_rs[1]}] +set_property -dict {LOC AB38 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_2_rs[0]}] +set_property -dict {LOC AB39 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_2_rs[1]}] +set_property -dict {LOC AD42 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_3_rs[0]}] +set_property -dict {LOC AE42 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_3_rs[1]}] +set_property -dict {LOC AE39 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_4_rs[0]}] +set_property -dict {LOC AE40 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_4_rs[1]}] +set_property -dict {LOC AA40 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_los] +set_property -dict {LOC Y39 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_2_los] +set_property -dict {LOC AD38 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_3_los] +set_property -dict {LOC AD40 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_4_los] +set_property -dict {LOC Y42 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable] +set_property -dict {LOC AB41 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable] +set_property -dict {LOC AC38 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_3_tx_disable] +set_property -dict {LOC AC40 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_4_tx_disable] +set_property -dict {LOC AA39 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_tx_fault] +set_property -dict {LOC Y38 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_2_tx_fault] +set_property -dict {LOC AA41 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_3_tx_fault] +set_property -dict {LOC AE38 IOSTANDARD LVCMOS18 PULLUP true} [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] - -# 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 -#set_property -dict {LOC W2 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_115 GTHE2_CHANNEL_X1Y23 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC W1 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_115 GTHE2_CHANNEL_X1Y23 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AA6 } [get_ports {pcie_rx_p[1]}] ;# MGTHTXP2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AA5 } [get_ports {pcie_rx_n[1]}] ;# MGTHTXN2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AA2 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AA1 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_115 GTHE2_CHANNEL_X1Y22 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AB4 } [get_ports {pcie_rx_p[2]}] ;# MGTHTXP1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AB3 } [get_ports {pcie_rx_n[2]}] ;# MGTHTXN1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AC2 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AC1 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_115 GTHE2_CHANNEL_X1Y21 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AC6 } [get_ports {pcie_rx_p[3]}] ;# MGTHTXP0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AC5 } [get_ports {pcie_rx_n[3]}] ;# MGTHTXN0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AE2 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AE1 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_115 GTHE2_CHANNEL_X1Y20 / GTHE2_COMMON_X1Y5 -#set_property -dict {LOC AD4 } [get_ports {pcie_rx_p[4]}] ;# MGTHTXP3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AD3 } [get_ports {pcie_rx_n[4]}] ;# MGTHTXN3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AG2 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXP3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AG1 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXN3_114 GTHE2_CHANNEL_X1Y19 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AE6 } [get_ports {pcie_rx_p[5]}] ;# MGTHTXP2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AE5 } [get_ports {pcie_rx_n[5]}] ;# MGTHTXN2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AH4 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXP2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AH3 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXN2_114 GTHE2_CHANNEL_X1Y18 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AF4 } [get_ports {pcie_rx_p[6]}] ;# MGTHTXP1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AF3 } [get_ports {pcie_rx_n[6]}] ;# MGTHTXN1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AJ2 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXP1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AJ1 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXN1_114 GTHE2_CHANNEL_X1Y17 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AG6 } [get_ports {pcie_rx_p[7]}] ;# MGTHTXP0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AG5 } [get_ports {pcie_rx_n[7]}] ;# MGTHTXN0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AK4 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXP0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AK3 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXN0_114 GTHE2_CHANNEL_X1Y16 / GTHE2_COMMON_X1Y4 -#set_property -dict {LOC AB8 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK1P_115 -#set_property -dict {LOC AB7 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK1N_115 -#set_property -dict {LOC AY35 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] - -# 100 MHz MGT reference clock -#create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] - +set_property -dict {LOC AT35 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports i2c_scl] +set_property -dict {LOC AU32 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports i2c_sda] +set_property -dict {LOC AY42 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports i2c_mux_reset_n] diff --git a/example/VC709/fpga/fpga/Makefile b/example/VC709/fpga/fpga/Makefile index 6f8ad6cb9..a63f25adb 100644 --- a/example/VC709/fpga/fpga/Makefile +++ b/example/VC709/fpga/fpga/Makefile @@ -1,6 +1,5 @@ - # FPGA settings -FPGA_PART = xc7vx690tffg1761-3 +FPGA_PART = xc7vx690tffg1761-2 FPGA_TOP = fpga FPGA_ARCH = virtex7 diff --git a/example/VC709/fpga/rtl/fpga.v b/example/VC709/fpga/rtl/fpga.v index 91a32575e..359f8e3a8 100644 --- a/example/VC709/fpga/rtl/fpga.v +++ b/example/VC709/fpga/rtl/fpga.v @@ -25,6 +25,7 @@ THE SOFTWARE. // Language: Verilog 2001 `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -39,19 +40,14 @@ module fpga ( /* * GPIO */ - input wire [1:0] btn, - output wire [1:0] sfp_1_led, - output wire [1:0] sfp_2_led, - output wire [1:0] sfp_3_led, - output wire [1:0] sfp_4_led, - output wire [1:0] led, + output wire [7:0] led, /* * I2C */ inout wire i2c_scl, inout wire i2c_sda, - output wire i2c_mux_reset, + output wire i2c_mux_reset_n, /* * Ethernet: SFP+ @@ -74,7 +70,7 @@ module fpga ( output wire sfp_4_tx_n, input wire sfp_mgt_refclk_p, input wire sfp_mgt_refclk_n, - output wire sfp_clk_rst, + output wire sfp_clk_rst_n, input wire sfp_1_mod_detect, input wire sfp_2_mod_detect, input wire sfp_3_mod_detect, @@ -116,12 +112,12 @@ wire mmcm_clkfb; IBUFGDS #( .DIFF_TERM("FALSE"), - .IBUF_LOW_PWR("FALSE") + .IBUF_LOW_PWR("FALSE") ) clk_200mhz_ibufg_inst ( .O (clk_200mhz_ibufg), .I (clk_200mhz_p), - .IB (clk_200mhz_n) + .IB (clk_200mhz_n) ); // MMCM instance @@ -197,27 +193,10 @@ sync_reset_125mhz_inst ( .out(rst_125mhz_int) ); -// GPIO -wire [1:0] btn_int; -wire [1:0] sfp_1_led_int; -wire [1:0] sfp_2_led_int; -wire [1:0] sfp_3_led_int; -wire [1:0] sfp_4_led_int; -wire [1:0] led_int; - -debounce_switch #( - .WIDTH(2), - .N(4), - .RATE(156250) -) -debounce_switch_inst ( - .clk(clk_156mhz_int), - .rst(rst_156mhz_int), - .in({btn}), - .out({btn_int}) -); - // I2C +wire i2c_scl_i, i2c_scl_o, i2c_scl_t; +wire i2c_sda_i, i2c_sda_o, i2c_sda_t; + assign i2c_scl_i = i2c_scl; assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o; assign i2c_sda_i = i2c_sda; @@ -239,8 +218,8 @@ wire si5324_i2c_data_last; wire si5324_i2c_init_busy; -assign i2c_mux_reset = rst_125mhz_int; -assign sfp_clk_rst = rst_125mhz_int; +assign i2c_mux_reset_n = !rst_125mhz_int; +assign sfp_clk_rst_n = !rst_125mhz_int; // delay start by ~10 ms reg [20:0] si5324_i2c_init_start_delay = 21'd0; @@ -640,15 +619,14 @@ sfp_4_pcs_pma_inst ( .tx_disable() ); -assign sfp_1_led[0] = sfp_1_rx_block_lock; -assign sfp_1_led[1] = 1'b0; -assign sfp_2_led[0] = sfp_2_rx_block_lock; -assign sfp_2_led[1] = 1'b0; -assign sfp_3_led[0] = sfp_3_rx_block_lock; -assign sfp_3_led[1] = 1'b0; -assign sfp_4_led[0] = sfp_4_rx_block_lock; -assign sfp_4_led[1] = 1'b0; -assign led = led_int; +assign led[0] = sfp_1_rx_block_lock; +assign led[1] = 1'b0; +assign led[2] = sfp_2_rx_block_lock; +assign led[3] = 1'b0; +assign led[4] = sfp_3_rx_block_lock; +assign led[5] = 1'b0; +assign led[6] = sfp_4_rx_block_lock; +assign led[7] = 1'b0; fpga_core core_inst ( @@ -661,12 +639,12 @@ core_inst ( /* * GPIO */ - .btn(btn_int), - .sfp_1_led(sfp_1_led_int), - .sfp_2_led(sfp_2_led_int), - .sfp_3_led(sfp_3_led_int), - .sfp_4_led(sfp_4_led_int), - .led(led_int), + .btn(), + .sfp_1_led(), + .sfp_2_led(), + .sfp_3_led(), + .sfp_4_led(), + .led(), /* * Ethernet: SFP+ */ @@ -705,3 +683,5 @@ core_inst ( ); endmodule + +`default_nettype wire diff --git a/example/VC709/fpga/rtl/si5324_i2c_init.v b/example/VC709/fpga/rtl/si5324_i2c_init.v index 3669903e1..0d01e721e 100644 --- a/example/VC709/fpga/rtl/si5324_i2c_init.v +++ b/example/VC709/fpga/rtl/si5324_i2c_init.v @@ -140,7 +140,7 @@ reg [8:0] init_data [INIT_DATA_LEN-1:0]; initial begin // init Si5324 registers init_data[0] = {2'b01, 7'h74}; // start write to 0x74 (I2C mux) - init_data[1] = {1'b1, 8'h10}; // select Si5324 + init_data[1] = {1'b1, 8'h80}; // select Si5324 init_data[2] = {2'b00, 7'b1000001}; // I2C stop init_data[3] = {2'b01, 7'h68}; // start write to 0x68 (Si5324) init_data[4] = {1'b1, 8'd0}; // register 0