From d489468776dbbdce60b14232b90572b210a15b59 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 28 Feb 2015 20:05:05 -0800 Subject: [PATCH] Add example design for Digilent Atlys board --- example/ATLYS/fpga/Makefile | 25 + example/ATLYS/fpga/clock.ucf | 6 + example/ATLYS/fpga/common/xilinx.mk | 191 ++++++ example/ATLYS/fpga/coregen/Makefile | 33 + example/ATLYS/fpga/coregen/coregen.cgp | 20 + example/ATLYS/fpga/coregen/dcm_i100_o125.xco | 269 ++++++++ example/ATLYS/fpga/fpga.ucf | 193 ++++++ example/ATLYS/fpga/fpga/Makefile | 61 ++ example/ATLYS/fpga/lib/eth | 1 + example/ATLYS/fpga/rtl/debounce_switch.v | 89 +++ example/ATLYS/fpga/rtl/fpga.v | 182 ++++++ example/ATLYS/fpga/rtl/fpga_core.v | 646 +++++++++++++++++++ example/ATLYS/fpga/rtl/fpga_pads.v | 170 +++++ example/ATLYS/fpga/rtl/sync_reset.v | 52 ++ example/ATLYS/fpga/rtl/sync_signal.v | 58 ++ example/ATLYS/fpga/tb/arp_ep.py | 1 + example/ATLYS/fpga/tb/axis_ep.py | 1 + example/ATLYS/fpga/tb/eth_ep.py | 1 + example/ATLYS/fpga/tb/gmii_ep.py | 1 + example/ATLYS/fpga/tb/ip_ep.py | 1 + example/ATLYS/fpga/tb/test_fpga_core.py | 335 ++++++++++ example/ATLYS/fpga/tb/test_fpga_core.v | 118 ++++ example/ATLYS/fpga/tb/udp_ep.py | 1 + 23 files changed, 2455 insertions(+) create mode 100644 example/ATLYS/fpga/Makefile create mode 100644 example/ATLYS/fpga/clock.ucf create mode 100644 example/ATLYS/fpga/common/xilinx.mk create mode 100644 example/ATLYS/fpga/coregen/Makefile create mode 100644 example/ATLYS/fpga/coregen/coregen.cgp create mode 100644 example/ATLYS/fpga/coregen/dcm_i100_o125.xco create mode 100644 example/ATLYS/fpga/fpga.ucf create mode 100644 example/ATLYS/fpga/fpga/Makefile create mode 120000 example/ATLYS/fpga/lib/eth create mode 100644 example/ATLYS/fpga/rtl/debounce_switch.v create mode 100644 example/ATLYS/fpga/rtl/fpga.v create mode 100644 example/ATLYS/fpga/rtl/fpga_core.v create mode 100644 example/ATLYS/fpga/rtl/fpga_pads.v create mode 100644 example/ATLYS/fpga/rtl/sync_reset.v create mode 100644 example/ATLYS/fpga/rtl/sync_signal.v create mode 120000 example/ATLYS/fpga/tb/arp_ep.py create mode 120000 example/ATLYS/fpga/tb/axis_ep.py create mode 120000 example/ATLYS/fpga/tb/eth_ep.py create mode 120000 example/ATLYS/fpga/tb/gmii_ep.py create mode 120000 example/ATLYS/fpga/tb/ip_ep.py create mode 100755 example/ATLYS/fpga/tb/test_fpga_core.py create mode 100644 example/ATLYS/fpga/tb/test_fpga_core.v create mode 120000 example/ATLYS/fpga/tb/udp_ep.py diff --git a/example/ATLYS/fpga/Makefile b/example/ATLYS/fpga/Makefile new file mode 100644 index 00000000..9f8bd404 --- /dev/null +++ b/example/ATLYS/fpga/Makefile @@ -0,0 +1,25 @@ +# Targets +TARGETS:= + +# Subdirectories +SUBDIRS = coregen 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/ATLYS/fpga/clock.ucf b/example/ATLYS/fpga/clock.ucf new file mode 100644 index 00000000..d954d3a0 --- /dev/null +++ b/example/ATLYS/fpga/clock.ucf @@ -0,0 +1,6 @@ +# UCF file for clock module domain crossing constraints + +NET "clk_int" TNM = "ffs_clk_int"; +NET "core_inst/gmii_rx_clk" TNM = "ffs_gmii_rx_clk"; +TIMESPEC "TS_clk_int_to_gmii_rx_clk" = FROM "ffs_clk_int" TO "ffs_gmii_rx_clk" 10 ns; +TIMESPEC "TS_gmii_rx_clk_to_clk_int" = FROM "ffs_gmii_rx_clk" TO "ffs_clk_int" 10 ns; diff --git a/example/ATLYS/fpga/common/xilinx.mk b/example/ATLYS/fpga/common/xilinx.mk new file mode 100644 index 00000000..f10a45f8 --- /dev/null +++ b/example/ATLYS/fpga/common/xilinx.mk @@ -0,0 +1,191 @@ +############################################################################# +# Author: Lane Brooks/Keith Fife +# Date: 04/28/2006 +# License: GPL +# Desc: This is a Makefile intended to take a verilog rtl design +# through the Xilinx ISE tools to generate configuration files for +# Xilinx FPGAs. This file is generic and just a template. As such +# all design specific options such as synthesis files, fpga part type, +# prom part type, etc should be set in the top Makefile prior to +# including this file. Alternatively, all parameters can be passed +# in from the command line as well. +# +############################################################################## +# +# Parameter: +# SYN_FILES - Space seperated list of files to be synthesized +# PART - FPGA part (see Xilinx documentation) +# PROM - PROM part +# NGC_PATHS - Space seperated list of any dirs with pre-compiled ngc files. +# UCF_FILES - Space seperated list of user constraint files. Defaults to xilinx/$(FPGA_TOP).ucf +# +# +# Example Calling Makefile: +# +# SYN_FILES = fpga.v fifo.v clks.v +# PART = xc3s1000 +# FPGA_TOP = fpga +# PROM = xc18v04 +# NGC_PATH = ipLib1 ipLib2 +# FPGA_ARCH = spartan6 +# SPI_PROM_SIZE = (in bytes) +# include xilinx.mk +############################################################################# +# +# Command Line Example: +# make -f xilinx.mk PART=xc3s1000-4fg320 SYN_FILES="fpga.v test.v" FPGA_TOP=fpga +# +############################################################################## +# +# Required Setup: +# +# %.ucf - user constraint file. Needed by ngdbuild +# +# Optional Files: +# %.xcf - user constraint file. Needed by xst. +# %.ut - File for pin states needed by bitgen + + +.PHONY: clean bit prom fpga spi + + +# Mark the intermediate files as PRECIOUS to prevent make from +# deleting them (see make manual section 10.4). +.PRECIOUS: %.ngc %.ngd %_map.ncd %.ncd %.twr %.bit %_timesim.v + +# include the local Makefile for project for any project specific targets +CONFIG ?= config.mk +-include ../$(CONFIG) + +SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES)) +INC_PATHS_REL = $(patsubst %, ../%, $(INC_PATHS)) +NGC_PATHS_REL = $(patsubst %, ../%, $(NGC_PATHS)) + +ifdef UCF_FILES + UCF_FILES_REL = $(patsubst %, ../%, $(UCF_FILES)) +else + UCF_FILES_REL = $(FPGA_TOP).ucf +endif + + + +fpga: $(FPGA_TOP).bit + +mcs: $(FPGA_TOP).mcs + +prom: $(FPGA_TOP).spi + +spi: $(FPGA_TOP).spi + +fpgasim: $(FPGA_TOP)_sim.v + + +########################### XST TEMPLATES ############################ +# There are 2 files that XST uses for synthesis that we auto generate. +# The first is a project file which is just a list of all the verilog +# files. The second is the src file which passes XST all the options. +# See XST user manual for XST options. +%.ngc: $(SYN_FILES_REL) $(INC_FILES_REL) + rm -rf xst $*.prj $*.xst defines.v + touch defines.v + mkdir -p xst/tmp + for x in $(DEFS); do echo '`define' $$x >> defines.v; done + echo verilog work defines.v > $*.prj + for x in $(SYN_FILES_REL); do echo verilog work $$x >> $*.prj; done + @echo "set -tmpdir ./xst/tmp" >> $*.xst + @echo "set -xsthdpdir ./xst" >> $*.xst + @echo "run" >> $*.xst + @echo "-ifn $*.prj" >> $*.xst + @echo "-ifmt mixed" >> $*.xst + @echo "-top $*" >> $*.xst + @echo "-ofn $*" >> $*.xst + @echo "-ofmt NGC" >> $*.xst + @echo "-opt_mode Speed" >> $*.xst + @echo "-opt_level 1" >> $*.xst + # @echo "-verilog2001 YES" >> $*.xst + @echo "-keep_hierarchy NO" >> $*.xst + @echo "-p $(FPGA_PART)" >> $*.xst + xst -ifn $*.xst -ofn $*.log + + +########################### ISE TRANSLATE ############################ +# ngdbuild will automatically use a ucf called %.ucf if one is found. +# We setup the dependancy such that %.ucf file is required. If any +# pre-compiled ncd files are needed, set the NGC_PATH variable as a space +# seperated list of directories that include the pre-compiled ngc files. +%.ngd: %.ngc $(UCF_FILES_REL) + ngdbuild -dd ngdbuild $(patsubst %,-sd %, $(NGC_PATHS_REL)) $(patsubst %,-uc %, $(UCF_FILES_REL)) -p $(FPGA_PART) $< $@ + + +########################### ISE MAP ################################### +ifeq ($(FPGA_ARCH),spartan6) + MAP_OPTS= -register_duplication on -timing -xe n +else + MAP_OPTS= -cm speed -register_duplication on -timing -xe n -pr b +endif + +%_map.ncd: %.ngd + map -p $(FPGA_PART) $(MAP_OPTS) -w -o $@ $< $*.pcf + +# map -p $(FPGA_PART) -cm area -pr b -k 4 -c 100 -o $@ $< $*.pcf + + +########################### ISE PnR ################################### +%.ncd: %_map.ncd + par -w -ol high $< $@ $*.pcf + +# par -w -ol std -t 1 $< $@ $*.pcf + + +##################### ISE Static Timing Analysis ##################### +%.twr: %.ncd + -trce -e 3 -l 3 -u -xml $* $< -o $@ $*.pcf + +%_sim.v: %.ncd + netgen -s 4 -pcf $*.pcf -sdf_anno true -ism -sdf_path netgen -w -dir . -ofmt verilog -sim $< $@ + +# netgen -ise "/home/lane/Second/xilinx/Second/Second" -intstyle ise -s 4 -pcf Second.pcf -sdf_anno true -sdf_path netgen/par -w -dir netgen/par -ofmt verilog -sim Second.ncd Second_timesim.v + + +########################### ISE Bitgen ############################# +%.bit: %.twr + bitgen $(BITGEN_OPTIONS) -w $*.ncd $*.bit + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do let COUNT=COUNT+1; done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; + + +########################### ISE Promgen ############################# +%.mcs: %.bit + promgen -spi -w -p mcs -s $(SPI_PROM_SIZE) -o $@ -u 0 $< + # promgen -w -p mcs -c FF -o $@ -u 0 $< -x $(PROM) + mkdir -p rev + EXT=mcs; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do let COUNT=COUNT+1; done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; + + +%.spi: %.mcs + objcopy -I ihex -O binary $< $@ + EXT=spi; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do let COUNT=COUNT+1; done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + + +tmpclean: + -rm -rf xst ngdbuild *_map.* *.ncd *.ngc *.log *.xst *.prj *.lso *~ *.pcf *.bld *.ngd *.xpi *_pad.* *.unroutes *.twx *.par *.twr *.pad *.drc *.bgn *.prm *.sig netgen *.v *.nlf *.xml + +clean: tmpclean + -rm -rf *.bit *.mcs + +# clean everything +distclean: clean + -rm -rf rev + diff --git a/example/ATLYS/fpga/coregen/Makefile b/example/ATLYS/fpga/coregen/Makefile new file mode 100644 index 00000000..71406906 --- /dev/null +++ b/example/ATLYS/fpga/coregen/Makefile @@ -0,0 +1,33 @@ +# Tools +COREGEN:=coregen +XAW2VERILOG:=xaw2verilog + +# Source +XCO:=dcm_i100_o125.xco +XAW:= + +# Targets +TARGETS += $(XCO:.xco=) +TARGETS += $(XAW:.xaw=) + +# Rules +.PHONY: all +all: $(TARGETS) + +.PHONY: clean +clean: + -rm -rf $(TARGETS) + +%: %.xco + $(eval $@_TMP := $(shell mktemp -d)) + cp -a coregen.cgp $($@_TMP) + cp -a $< $($@_TMP) + cd $($@_TMP) && $(COREGEN) -p coregen.cgp -b $(notdir $<) + mv $($@_TMP) $@ + +%: %.xaw + $(eval $@_TMP := $(shell mktemp -d)) + cp -a coregen.cgp $($@_TMP) + cp -a $< $($@_TMP) + cd $($@_TMP) && $(XAW2VERILOG) -st $(notdir $<) $(notdir $*) + mv $($@_TMP) $@ diff --git a/example/ATLYS/fpga/coregen/coregen.cgp b/example/ATLYS/fpga/coregen/coregen.cgp new file mode 100644 index 00000000..773be0a8 --- /dev/null +++ b/example/ATLYS/fpga/coregen/coregen.cgp @@ -0,0 +1,20 @@ +# Date: Sat Jan 07 00:34:24 2012 +SET addpads = false +SET asysymbol = true +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = Verilog +SET device = xc6slx45 +SET devicefamily = spartan6 +SET flowvendor = Foundation_ISE +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = csg324 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -2 +SET verilogsim = true +SET vhdlsim = false +SET workingdirectory = .\tmp\ +# CRC: 90246c5 diff --git a/example/ATLYS/fpga/coregen/dcm_i100_o125.xco b/example/ATLYS/fpga/coregen/dcm_i100_o125.xco new file mode 100644 index 00000000..18ce9318 --- /dev/null +++ b/example/ATLYS/fpga/coregen/dcm_i100_o125.xco @@ -0,0 +1,269 @@ +############################################################## +# +# Xilinx Core Generator version 14.7 +# Date: Sun Mar 1 03:45:12 2015 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:clk_wiz:3.6 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = true +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = Verilog +SET device = xc6slx45 +SET devicefamily = spartan6 +SET flowvendor = Foundation_ISE +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = csg324 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -2 +SET verilogsim = true +SET vhdlsim = false +# END Project Options +# BEGIN Select +SELECT Clocking_Wizard xilinx.com:ip:clk_wiz:3.6 +# END Select +# BEGIN Parameters +CSET calc_done=DONE +CSET clk_in_sel_port=CLK_IN_SEL +CSET clk_out1_port=CLK_OUT1 +CSET clk_out1_use_fine_ps_gui=false +CSET clk_out2_port=CLK_OUT2 +CSET clk_out2_use_fine_ps_gui=false +CSET clk_out3_port=CLK_OUT3 +CSET clk_out3_use_fine_ps_gui=false +CSET clk_out4_port=CLK_OUT4 +CSET clk_out4_use_fine_ps_gui=false +CSET clk_out5_port=CLK_OUT5 +CSET clk_out5_use_fine_ps_gui=false +CSET clk_out6_port=CLK_OUT6 +CSET clk_out6_use_fine_ps_gui=false +CSET clk_out7_port=CLK_OUT7 +CSET clk_out7_use_fine_ps_gui=false +CSET clk_valid_port=CLK_VALID +CSET clkfb_in_n_port=CLKFB_IN_N +CSET clkfb_in_p_port=CLKFB_IN_P +CSET clkfb_in_port=CLKFB_IN +CSET clkfb_in_signaling=SINGLE +CSET clkfb_out_n_port=CLKFB_OUT_N +CSET clkfb_out_p_port=CLKFB_OUT_P +CSET clkfb_out_port=CLKFB_OUT +CSET clkfb_stopped_port=CLKFB_STOPPED +CSET clkin1_jitter_ps=100.0 +CSET clkin1_ui_jitter=0.010 +CSET clkin2_jitter_ps=100.0 +CSET clkin2_ui_jitter=0.010 +CSET clkout1_drives=BUFG +CSET clkout1_requested_duty_cycle=50.000 +CSET clkout1_requested_out_freq=125.000 +CSET clkout1_requested_phase=0.000 +CSET clkout2_drives=BUFG +CSET clkout2_requested_duty_cycle=50.000 +CSET clkout2_requested_out_freq=100.000 +CSET clkout2_requested_phase=0.000 +CSET clkout2_used=false +CSET clkout3_drives=BUFG +CSET clkout3_requested_duty_cycle=50.000 +CSET clkout3_requested_out_freq=100.000 +CSET clkout3_requested_phase=0.000 +CSET clkout3_used=false +CSET clkout4_drives=BUFG +CSET clkout4_requested_duty_cycle=50.000 +CSET clkout4_requested_out_freq=100.000 +CSET clkout4_requested_phase=0.000 +CSET clkout4_used=false +CSET clkout5_drives=BUFG +CSET clkout5_requested_duty_cycle=50.000 +CSET clkout5_requested_out_freq=100.000 +CSET clkout5_requested_phase=0.000 +CSET clkout5_used=false +CSET clkout6_drives=BUFG +CSET clkout6_requested_duty_cycle=50.000 +CSET clkout6_requested_out_freq=100.000 +CSET clkout6_requested_phase=0.000 +CSET clkout6_used=false +CSET clkout7_drives=BUFG +CSET clkout7_requested_duty_cycle=50.000 +CSET clkout7_requested_out_freq=100.000 +CSET clkout7_requested_phase=0.000 +CSET clkout7_used=false +CSET clock_mgr_type=AUTO +CSET component_name=dcm_i100_o125 +CSET daddr_port=DADDR +CSET dclk_port=DCLK +CSET dcm_clk_feedback=1X +CSET dcm_clk_out1_port=CLKFX +CSET dcm_clk_out2_port=CLK0 +CSET dcm_clk_out3_port=CLK0 +CSET dcm_clk_out4_port=CLK0 +CSET dcm_clk_out5_port=CLK0 +CSET dcm_clk_out6_port=CLK0 +CSET dcm_clkdv_divide=2.0 +CSET dcm_clkfx_divide=4 +CSET dcm_clkfx_multiply=5 +CSET dcm_clkgen_clk_out1_port=CLKFX +CSET dcm_clkgen_clk_out2_port=CLKFX +CSET dcm_clkgen_clk_out3_port=CLKFX +CSET dcm_clkgen_clkfx_divide=1 +CSET dcm_clkgen_clkfx_md_max=0.000 +CSET dcm_clkgen_clkfx_multiply=4 +CSET dcm_clkgen_clkfxdv_divide=2 +CSET dcm_clkgen_clkin_period=10.000 +CSET dcm_clkgen_notes=None +CSET dcm_clkgen_spread_spectrum=NONE +CSET dcm_clkgen_startup_wait=false +CSET dcm_clkin_divide_by_2=false +CSET dcm_clkin_period=10.000 +CSET dcm_clkout_phase_shift=NONE +CSET dcm_deskew_adjust=SYSTEM_SYNCHRONOUS +CSET dcm_notes=None +CSET dcm_phase_shift=0 +CSET dcm_pll_cascade=NONE +CSET dcm_startup_wait=false +CSET den_port=DEN +CSET din_port=DIN +CSET dout_port=DOUT +CSET drdy_port=DRDY +CSET dwe_port=DWE +CSET feedback_source=FDBK_AUTO +CSET in_freq_units=Units_MHz +CSET in_jitter_units=Units_UI +CSET input_clk_stopped_port=INPUT_CLK_STOPPED +CSET jitter_options=UI +CSET jitter_sel=No_Jitter +CSET locked_port=LOCKED +CSET mmcm_bandwidth=OPTIMIZED +CSET mmcm_clkfbout_mult_f=4.000 +CSET mmcm_clkfbout_phase=0.000 +CSET mmcm_clkfbout_use_fine_ps=false +CSET mmcm_clkin1_period=10.000 +CSET mmcm_clkin2_period=10.000 +CSET mmcm_clkout0_divide_f=4.000 +CSET mmcm_clkout0_duty_cycle=0.500 +CSET mmcm_clkout0_phase=0.000 +CSET mmcm_clkout0_use_fine_ps=false +CSET mmcm_clkout1_divide=1 +CSET mmcm_clkout1_duty_cycle=0.500 +CSET mmcm_clkout1_phase=0.000 +CSET mmcm_clkout1_use_fine_ps=false +CSET mmcm_clkout2_divide=1 +CSET mmcm_clkout2_duty_cycle=0.500 +CSET mmcm_clkout2_phase=0.000 +CSET mmcm_clkout2_use_fine_ps=false +CSET mmcm_clkout3_divide=1 +CSET mmcm_clkout3_duty_cycle=0.500 +CSET mmcm_clkout3_phase=0.000 +CSET mmcm_clkout3_use_fine_ps=false +CSET mmcm_clkout4_cascade=false +CSET mmcm_clkout4_divide=1 +CSET mmcm_clkout4_duty_cycle=0.500 +CSET mmcm_clkout4_phase=0.000 +CSET mmcm_clkout4_use_fine_ps=false +CSET mmcm_clkout5_divide=1 +CSET mmcm_clkout5_duty_cycle=0.500 +CSET mmcm_clkout5_phase=0.000 +CSET mmcm_clkout5_use_fine_ps=false +CSET mmcm_clkout6_divide=1 +CSET mmcm_clkout6_duty_cycle=0.500 +CSET mmcm_clkout6_phase=0.000 +CSET mmcm_clkout6_use_fine_ps=false +CSET mmcm_clock_hold=false +CSET mmcm_compensation=ZHOLD +CSET mmcm_divclk_divide=1 +CSET mmcm_notes=None +CSET mmcm_ref_jitter1=0.010 +CSET mmcm_ref_jitter2=0.010 +CSET mmcm_startup_wait=false +CSET num_out_clks=1 +CSET override_dcm=false +CSET override_dcm_clkgen=false +CSET override_mmcm=false +CSET override_pll=false +CSET platform=lin64 +CSET pll_bandwidth=OPTIMIZED +CSET pll_clk_feedback=CLKFBOUT +CSET pll_clkfbout_mult=4 +CSET pll_clkfbout_phase=0.000 +CSET pll_clkin_period=10.000 +CSET pll_clkout0_divide=1 +CSET pll_clkout0_duty_cycle=0.500 +CSET pll_clkout0_phase=0.000 +CSET pll_clkout1_divide=1 +CSET pll_clkout1_duty_cycle=0.500 +CSET pll_clkout1_phase=0.000 +CSET pll_clkout2_divide=1 +CSET pll_clkout2_duty_cycle=0.500 +CSET pll_clkout2_phase=0.000 +CSET pll_clkout3_divide=1 +CSET pll_clkout3_duty_cycle=0.500 +CSET pll_clkout3_phase=0.000 +CSET pll_clkout4_divide=1 +CSET pll_clkout4_duty_cycle=0.500 +CSET pll_clkout4_phase=0.000 +CSET pll_clkout5_divide=1 +CSET pll_clkout5_duty_cycle=0.500 +CSET pll_clkout5_phase=0.000 +CSET pll_compensation=SYSTEM_SYNCHRONOUS +CSET pll_divclk_divide=1 +CSET pll_notes=None +CSET pll_ref_jitter=0.010 +CSET power_down_port=POWER_DOWN +CSET prim_in_freq=100.000 +CSET prim_in_jitter=0.010 +CSET prim_source=Single_ended_clock_capable_pin +CSET primary_port=CLK_IN1 +CSET primitive=MMCM +CSET primtype_sel=PLL_BASE +CSET psclk_port=PSCLK +CSET psdone_port=PSDONE +CSET psen_port=PSEN +CSET psincdec_port=PSINCDEC +CSET relative_inclk=REL_PRIMARY +CSET reset_port=RESET +CSET secondary_in_freq=100.000 +CSET secondary_in_jitter=0.010 +CSET secondary_port=CLK_IN2 +CSET secondary_source=Single_ended_clock_capable_pin +CSET ss_mod_freq=250 +CSET ss_mode=CENTER_HIGH +CSET status_port=STATUS +CSET summary_strings=empty +CSET use_clk_valid=false +CSET use_clkfb_stopped=false +CSET use_dyn_phase_shift=false +CSET use_dyn_reconfig=false +CSET use_freeze=false +CSET use_freq_synth=true +CSET use_inclk_stopped=false +CSET use_inclk_switchover=false +CSET use_locked=true +CSET use_max_i_jitter=false +CSET use_min_o_jitter=false +CSET use_min_power=false +CSET use_phase_alignment=true +CSET use_power_down=false +CSET use_reset=true +CSET use_spread_spectrum=false +CSET use_spread_spectrum_1=false +CSET use_status=false +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2012-05-10T12:44:55Z +# END Extra information +GENERATE +# CRC: fe0bbd35 diff --git a/example/ATLYS/fpga/fpga.ucf b/example/ATLYS/fpga/fpga.ucf new file mode 100644 index 00000000..5dd47d22 --- /dev/null +++ b/example/ATLYS/fpga/fpga.ucf @@ -0,0 +1,193 @@ +# User Constraints File for the Digilent Atlys board, rev C + +CONFIG PART = xc6slx45-2csg324; + +# 100MHz Clock: I/O Bank 1 +NET "clk" LOC = "L15" | IOSTANDARD=LVCMOS33; # IO_L42P_GCLK7_M1UDM (GCLK) +NET "clk" TNM_NET = "sys_clk_pin"; +TIMESPEC "TS_sys_clk_pin" = PERIOD "sys_clk_pin" 100000 kHz; + +# Light Emitting Diodes (not used) +NET "led<0>" LOC = "U18" | IOSTANDARD=LVCMOS25 | SLEW=QUIETIO | DRIVE=2; # Bank = 1, IO_L52N_M1DQ15 (LD0) +NET "led<1>" LOC = "M14" | IOSTANDARD=LVCMOS25 | SLEW=QUIETIO | DRIVE=2; # Bank = 1, IO_L53P (LD1) +NET "led<2>" LOC = "N14" | IOSTANDARD=LVCMOS25 | SLEW=QUIETIO | DRIVE=2; # Bank = 1, IO_L53N_VREF (LD2) +NET "led<3>" LOC = "L14" | IOSTANDARD=LVCMOS25 | SLEW=QUIETIO | DRIVE=2; # Bank = 1, IO_L61P (LD3) +NET "led<4>" LOC = "M13" | IOSTANDARD=LVCMOS25 | SLEW=QUIETIO | DRIVE=2; # Bank = 1, IO_L61N (LD4) +NET "led<5>" LOC = "D4" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; # Bank = 0, IO_L1P_HSWAPEN_0 (HSWAP/LD5) +NET "led<6>" LOC = "P16" | IOSTANDARD=LVCMOS25 | SLEW=QUIETIO | DRIVE=2; # Bank = 1, IO_L74N_DOUT_BUSY_1 (LD6) +NET "led<7>" LOC = "N12" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; # Bank = 2, IO_L13P_M1_2 (M1/LD7) + +# Reset Button: I/O Bank 2 (not used) +NET "reset_n" LOC = "T15" | IOSTANDARD=LVCMOS33; # IO_L1N_M0_CMPMISO_2 (M0/RESET) + +# Push Buttons: I/O Bank 3 (not used) +NET "btnu" LOC = "N4"; # IO_L1P (BTNU) +NET "btnl" LOC = "P4"; # IO_L2P (BTNL) +NET "btnd" LOC = "P3"; # IO_L2N (BTND) +NET "btnr" LOC = "F6"; # IO_L55P_M3A13 (BTNR) +NET "btnc" LOC = "F5"; # IO_L55N_M3A14 (BTNC) + +# Toggle Switches (not used) +NET "sw<0>" LOC = "A10"; # Bank = 0, IO_L37N_GCLK12 (SW0) +NET "sw<1>" LOC = "D14"; # Bank = 0, IO_L65P_SCP3 (SW1) +NET "sw<2>" LOC = "C14"; # Bank = 0, IO_L65N_SCP2 (SW2) +NET "sw<3>" LOC = "P15"; # Bank = 1, IO_L74P_AWAKE_1 (SW3) +NET "sw<4>" LOC = "P12"; # Bank = 2, IO_L13N_D10 (SW4) +NET "sw<5>" LOC = "R5"; # Bank = 2, IO_L48P_D7 (SW5) +NET "sw<6>" LOC = "T5"; # Bank = 2, IO_L48N_RDWR_B_VREF_2 (SW6) +NET "sw<7>" LOC = "E4"; # Bank = 3, IO_L54P_M3RESET (SW7) + +# Marvell M88E1111 Tri-Mode Ethernet PHY (1000BASE-T): I/O Bank 1 +# Interrupt, Reset, MDIO +#NET "phy_int_n" LOC = "L16" | IOSTANDARD=LVCMOS25; # IO_L42N_GCLK6_TRDY1_M1LDM (E-INT) +NET "phy_reset_n" LOC = "G13" | IOSTANDARD=LVCMOS25; # IO_L32N_A16_M1A9 (E-RESET) +#NET "phy_mdc" LOC = "F16" | IOSTANDARD=LVCMOS25; # IO_L1N_A24_VREF (E-MDC) +#NET "phy_mdio" LOC = "N17" | IOSTANDARD=LVCMOS25; # IO_L48P_HDC_M1DQ8 (E-MDIO) +# GMII Transmit +NET "phy_gtx_clk" LOC = "L12" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L40P_GCLK11_M1A5 (E-GTXCLK) +NET "phy_txd<0>" LOC = "H16" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L37N_A6_M1A1 (E-TXD0) +NET "phy_txd<1>" LOC = "H13" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L36P_A9_M1BA0 (E-TXD1) +NET "phy_txd<2>" LOC = "K14" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L39N_M1ODT (E-TXD2) +NET "phy_txd<3>" LOC = "K13" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L34N_A12_M1BA2 (E-TXD3) +NET "phy_txd<4>" LOC = "J13" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L39P_M1A3 (E-TXD4) +NET "phy_txd<5>" LOC = "G14" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L30N_A20_M1A11 (E-TXD5) +NET "phy_txd<6>" LOC = "H12" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L32P_A17_M1A8 (E-TXD6) +NET "phy_txd<7>" LOC = "K12" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L34P_A13_M1WE (E-TXD7) +NET "phy_tx_en" LOC = "H15" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L37P_A7_M1A0 (E-TXEN) +NET "phy_tx_er" LOC = "G18" | IOSTANDARD=LVCMOS25 | SLEW = FAST; # IO_L38N_A4_M1CLKN (E-TXER) +# GMII Receive (not used) +NET "phy_rx_clk" LOC = "K15" | IOSTANDARD=LVCMOS25 | TNM_NET = "clk_rx_local"; # IO_L41P_GCLK9_IRDY1_M1RASN (E-RXCLK) +NET "phy_rxd<0>" LOC = "G16" | IOSTANDARD=LVCMOS25; # IO_L38P_A5_M1CLK (E-RXD0) +NET "phy_rxd<1>" LOC = "H14" | IOSTANDARD=LVCMOS25; # IO_L36N_A8_M1BA1 (E-RXD1) +NET "phy_rxd<2>" LOC = "E16" | IOSTANDARD=LVCMOS25; # IO_L33P_A15_M1A10 (E-RXD2) +NET "phy_rxd<3>" LOC = "F15" | IOSTANDARD=LVCMOS25; # IO_L1P_A25 (E-RXD3) +NET "phy_rxd<4>" LOC = "F14" | IOSTANDARD=LVCMOS25; # IO_L30P_A21_M1RESET (E-RXD4) +NET "phy_rxd<5>" LOC = "E18" | IOSTANDARD=LVCMOS25; # IO_L33N_A14_M1A4 (E-RXD5) +NET "phy_rxd<6>" LOC = "D18" | IOSTANDARD=LVCMOS25; # IO_L31N_A18_M1A12 (E-RXD6) +NET "phy_rxd<7>" LOC = "D17" | IOSTANDARD=LVCMOS25; # IO_L31P_A19_M1CKE (E-RXD7) +NET "phy_rx_dv" LOC = "F17" | IOSTANDARD=LVCMOS25; # IO_L35P_A11_M1A7 (E-RXDV) +NET "phy_rx_er" LOC = "F18" | IOSTANDARD=LVCMOS25; # IO_L35N_A10_M1A2 (E-RXER) + +# Timing constraints for Ethernet PHY +TIMESPEC "TS_rx_clk_root" = PERIOD "clk_rx_local" 8000 ps HIGH 50 %; +# WARNING: Receiving Ethernet frames will not work without these constraints. +# WARNING: Meeting these constraints will require instantiating an IODELAY2 primitive. +#INST "phy_rxd" TNM = IN_GMII; +#INST "phy_rx_er" TNM = IN_GMII; +#INST "phy_rx_dv" TNM = IN_GMII; +#TIMEGRP "IN_GMII" OFFSET = IN 2.4 ns VALID 2.8 ns BEFORE "phy_rx_clk125"; + +# PMOD Connector (FPGA Bank 2) +# +# FPGA | Atlys +# ------------------------------------ +# T3 | IO_L62N_D6 | JA1 (TOP) +# R3 | IO_L62P_D5 | JA2 (TOP) +# P6 | IO_L64N_D9 | JA3 (TOP) +# N5 | IO_L64P_D8 | JA4 (TOP) +# | GND | JA5 (TOP) +# | Vcc | JA6 (TOP) +# V9 | IO_L32N_GCLK28 | JA7 (BOTTOM) +# T9 | IO_L32P_GCLK29 | JA8 (BOTTOM) +# V4 | IO_L63N | JA9 (BOTTOM) +# T4 | IO_L63P | JA10 (BOTTOM) +# | GND | JA11 (BOTTOM) +# | Vcc | JA12 (BOTTOM) +# +#NET "ready<1>" LOC = "T3" | IOSTANDARD=LVCMOS33 | PULLDOWN; +#NET "trigger<1>" LOC = "V9" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; +#NET "spi_mosi<1>" LOC = "R3" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; +#NET "spi_cs_n<1>" LOC = "T9" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; +#NET "spi_clk<1>" LOC = "P6" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; +#NET "spi_gnd<1>" LOC = "V4" | IOSTANDARD=LVCMOS33 | SLEW=QUIETIO | DRIVE=2; + +# VHDCI Connector (FPGA Bank 2) +# Note: Channnel 1 connects to P signals, Channel 2 to N signals +# +# FPGA | Atlys | VmodMIB +# ----------------------------------------------------------------------------- +# U16 | IO_L2P_CMPCLK | EXP-IO1_P | JC.1 | JC-CLK_P | JC8 (BOTTOM) +# U15 | *IO_L5P | EXP-IO2_P | JC.3 | JC-D0_P | JC2 (TOP) +# U13 | IO_L14P_D11 | EXP-IO3_P | JC.4 | JC-D1_P | JC10 (BOTTOM) +# M11 | *IO_L15P | EXP-IO4_P | JC.6 | JC-D2_P | JC4 (TOP) +# R11 | IO_L16P | EXP-IO5_P | JC.7 | JA-D0_P | JA2 (TOP) +# T12 | *IO_L19P | EXP-IO6_P | JC.9 | JA-D1_P | JA10 (BOTTOM) +# N10 | *IO_L20P | EXP-IO7_P | JC.10 | JA-D2_P | JA4 (TOP) +# M10 | *IO_L22P | EXP-IO8_P | JC.12 | JB-D0_P | JB2 (TOP) +# U11 | IO_L23P | EXP-IO9_P | JC.13 | JB-D1_P | JB10 (BOTTOM) +# R10 | IO_L29P_GCLK3 | EXP-IO10_P | JC.15 | JA-CLK_P | JA8 (BOTTOM) +# U10 | IO_L30P_GCLK1_D13 | EXP-IO11_P | JC.20 | JB-CLK_P | JB8 (BOTTOM) +# R8 | IO_L31P_GCLK31_D14 | EXP-IO12_P | JC.22 | JB-D2_P | JB4 (TOP) +# M8 | *IO_L40P | EXP-IO13_P | JC.23 | JE8 | JE8 (BOTTOM) +# U8 | IO_L41P | EXP-IO14_P | JC.25 | JE2 | JE2 (TOP) +# U7 | IO_L43P | EXP-IO15_P | JC.26 | JE10 | JE10 (BOTTOM) +# N7 | *IO_L44P | EXP-IO16_P | JC.28 | JE4 | JE4 (TOP) +# T6 | IO_L45P | EXP-IO17_P | JC.29 | JD-CLK_P | JD8 (BOTTOM) +# R7 | IO_L46P | EXP-IO18_P | JC.31 | JD-D0_P | JD2 (TOP) +# N6 | *IO_L47P | EXP-IO19_P | JC.32 | JD-D1_P | JD10 (BOTTOM) +# U5 | IO_49P_D3 | EXP-IO20_P | JC.34 | JD-D2_P | JD4 (TOP) +# V16 | IO_L2N_CMPMOSI | EXP-IO1_N | JC.35 | JC-CLK_N | JC7 (BOTTOM) +# V15 | *IO_L5N | EXP-IO2_N | JC.37 | JC-D0_N | JC1 (TOP) +# V13 | IO_L14N_D12 | EXP-IO3_N | JC.38 | JC-D1_N | JC9 (BOTTOM) +# N11 | *IO_L15N | EXP-IO4_N | JC.40 | JC-D2_N | JC3 (TOP) +# T11 | IO_L16N_VREF | EXP-IO5_N | JC.41 | JA-D0_N | JA1 (TOP) +# V12 | *IO_L19N | EXP-IO6_N | JC.43 | JA-D1_N | JA9 (BOTTOM) +# P11 | *IO_L20N | EXP-IO7_N | JC.44 | JA-D2_N | JA3 (TOP) +# N9 | *IO_L22N | EXP-IO8_N | JC.46 | JB-D0_N | JB1 (TOP) +# V11 | IO_L23N | EXP-IO9_N | JC.47 | JB-D1_N | JB9 (BOTTOM) +# T10 | IO_L29N_GCLK2 | EXP-IO10_N | JC.49 | JA-CLK_N | JA7 (BOTTOM) +# V10 | IO_L30N_GCLK0_USERCCLK | EXP-IO11_N | JC.54 | JB-CLK_N | JB7 (BOTTOM) +# T8 | IO_L31N_GCLK30_D15 | EXP-IO12_N | JC.56 | JB-D2_N | JB3 (TOP) +# N8 | *IO_L40N | EXP-IO13_N | JC.57 | JE7 | JE7 (BOTTOM) +# V8 | IO_L41N_VREF | EXP-IO14_N | JC.59 | JE1 | JE1 (TOP) +# V7 | IO_L43N | EXP-IO15_N | JC.60 | JE9 | JE9 (BOTTOM) +# P8 | *IO_L44N | EXP-IO16_N | JC.62 | JE3 | JE3 (TOP) +# V6 | IO_L45N | EXP-IO17_N | JC.63 | JD-CLK_N | JD7 (BOTTOM) +# T7 | IO_L46N | EXP-IO18_N | JC.65 | JD-D0_N | JD1 (TOP) +# P7 | *IO_L47N | EXP-IO19_N | JC.66 | JD-D1_N | JD9 (BOTTOM) +# V5 | IO_49N_D4 | EXP-IO20_N | JC.68 | JD-D2_N | JD3 (TOP) + +#NET "" LOC = "U16" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO1_P +#NET "" LOC = "U15" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO2_P +#NET "" LOC = "U13" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO3_P +#NET "" LOC = "M11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO4_P +#NET "" LOC = "R11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO5_P +#NET "" LOC = "T12" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO6_P +#NET "" LOC = "N10" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO7_P +#NET "" LOC = "M10" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO8_P +#NET "" LOC = "U11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO9_P +#NET "" LOC = "R10" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO10_P +#NET "" LOC = "U10" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO11_P +#NET "" LOC = "R8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO12_P +#NET "" LOC = "M8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO13_P +#NET "" LOC = "U8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO14_P +#NET "" LOC = "U7" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO15_P +#NET "" LOC = "N7" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO16_P +#NET "" LOC = "T6" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO17_P +#NET "" LOC = "R7" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO18_P +#NET "" LOC = "N6" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO19_P +#NET "" LOC = "U5" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO20_P +#NET "" LOC = "V16" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO1_N +#NET "" LOC = "V15" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO2_N +#NET "" LOC = "V13" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO3_N +#NET "" LOC = "N11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO4_N +#NET "" LOC = "T11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=8; # EXP-IO5_N +#NET "" LOC = "V12" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO6_N +#NET "" LOC = "P11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO7_N +#NET "" LOC = "N9" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO8_N +#NET "" LOC = "V11" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO9_N +#NET "" LOC = "T10" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO10_N +#NET "" LOC = "V10" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO11_N +#NET "" LOC = "T8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO12_N +#NET "" LOC = "N8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO13_N +#NET "" LOC = "V8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO14_N +#NET "" LOC = "V7" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO15_N +#NET "" LOC = "P8" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO16_N +#NET "" LOC = "V6" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO17_N +#NET "" LOC = "T7" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO18_N +#NET "" LOC = "P7" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO19_N +#NET "" LOC = "V5" | IOSTANDARD=LVCMOS33 | SLEW=FAST | DRIVE=2; # EXP-IO20_N + +# Exar UART: I/O Bank 0 +NET "uart_rxd" LOC = "A16" | IOSTANDARD=LVCMOS33; # IO_L66N_SCP0 (USBB-RXD) +NET "uart_txd" LOC = "B16" | IOSTANDARD=LVCMOS33; # IO_L66P_SCP1 (USBB-TXD) diff --git a/example/ATLYS/fpga/fpga/Makefile b/example/ATLYS/fpga/fpga/Makefile new file mode 100644 index 00000000..aed16c07 --- /dev/null +++ b/example/ATLYS/fpga/fpga/Makefile @@ -0,0 +1,61 @@ + +# FPGA settings +FPGA_PART = xc6slx45-2csg324 +FPGA_TOP = fpga +FPGA_ARCH = spartan6 + +# PROM settings +#PROM = xc18v04 +#SPI_PROM_SIZE = (in bytes) + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/fpga_pads.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += lib/eth/rtl/gmii_phy_if.v +SYN_FILES += lib/eth/rtl/eth_mac_1g.v +SYN_FILES += lib/eth/rtl/eth_mac_1g_rx.v +SYN_FILES += lib/eth/rtl/eth_mac_1g_tx.v +SYN_FILES += lib/eth/rtl/eth_crc_8.v +SYN_FILES += lib/eth/rtl/eth_axis_rx.v +SYN_FILES += lib/eth/rtl/eth_axis_tx.v +SYN_FILES += lib/eth/rtl/udp_complete.v +SYN_FILES += lib/eth/rtl/udp.v +SYN_FILES += lib/eth/rtl/udp_ip_rx.v +SYN_FILES += lib/eth/rtl/udp_ip_tx.v +SYN_FILES += lib/eth/rtl/ip_complete.v +SYN_FILES += lib/eth/rtl/ip.v +SYN_FILES += lib/eth/rtl/ip_eth_rx.v +SYN_FILES += lib/eth/rtl/ip_eth_tx.v +SYN_FILES += lib/eth/rtl/ip_arb_mux_2.v +SYN_FILES += lib/eth/rtl/ip_mux_2.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_2.v +SYN_FILES += lib/eth/rtl/eth_mux_2.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_frame_fifo.v +SYN_FILES += coregen/dcm_i100_o125/dcm_i100_o125.v + +# UCF files +UCF_FILES = fpga.ucf +UCF_FILES += clock.ucf + +# NGC paths for ngdbuild +NGC_PATHS = coregen/dcm_i100_o125 + +# Bitgen options +BITGEN_OPTIONS = -g StartupClk:Cclk -g ConfigRate:26 + +include ../common/xilinx.mk + +program: $(FPGA_TOP).bit + djtgcfg prog -d Atlys --index 0 --file $(FPGA_TOP).bit + diff --git a/example/ATLYS/fpga/lib/eth b/example/ATLYS/fpga/lib/eth new file mode 120000 index 00000000..11a54ed3 --- /dev/null +++ b/example/ATLYS/fpga/lib/eth @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/example/ATLYS/fpga/rtl/debounce_switch.v b/example/ATLYS/fpga/rtl/debounce_switch.v new file mode 100644 index 00000000..f3fb77a1 --- /dev/null +++ b/example/ATLYS/fpga/rtl/debounce_switch.v @@ -0,0 +1,89 @@ +/* + +Copyright (c) 2014 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/ATLYS/fpga/rtl/fpga.v b/example/ATLYS/fpga/rtl/fpga.v new file mode 100644 index 00000000..0aa317e4 --- /dev/null +++ b/example/ATLYS/fpga/rtl/fpga.v @@ -0,0 +1,182 @@ +/* + +Copyright (c) 2014 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. + +*/ + +module fpga ( + /* + * Clock: 100MHz + * Reset: Push button, active low + */ + input wire clk, + input wire reset_n, + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [7:0] sw, + output wire [7:0] led, + /* + * Ethernet: 1000BASE-T GMII + */ + input wire phy_rx_clk, + input wire [7:0] phy_rxd, + input wire phy_rx_dv, + input wire phy_rx_er, + output wire phy_gtx_clk, + output wire [7:0] phy_txd, + output wire phy_tx_en, + output wire phy_tx_er, + output wire phy_reset_n, + /* + * UART: 500000 bps, 8N1 + */ + input wire uart_rxd, + output wire uart_txd +); + +/* + * Clock: 125MHz + * Synchronous reset + */ +wire clk_int; +wire rst_int; +/* + * GPIO + */ +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [7:0] sw_int; +wire [7:0] led_int; +/* + * Ethernet: 1000BASE-T GMII + */ +wire phy_rx_clk_int; +wire [7:0] phy_rxd_int; +wire phy_rx_dv_int; +wire phy_rx_er_int; +wire phy_gtx_clk_int; +wire [7:0] phy_txd_int; +wire phy_tx_en_int; +wire phy_tx_er_int; +wire phy_reset_n_int; +/* + * UART: 115200 bps, 8N1 + */ +wire uart_rxd_int; +wire uart_txd_int; + +fpga_core +core_inst ( + /* + * Clock: 125MHz + * Synchronous reset + */ + .clk(clk_int), + .rst(rst_int), + /* + * GPIO + */ + .btnu(btnu_int), + .btnl(btnl_int), + .btnd(btnd_int), + .btnr(btnr_int), + .btnc(btnc_int), + .sw(sw_int), + .led(led_int), + /* + * Ethernet: 1000BASE-T GMII + */ + .phy_rx_clk(phy_rx_clk_int), + .phy_rxd(phy_rxd_int), + .phy_rx_dv(phy_rx_dv_int), + .phy_rx_er(phy_rx_er_int), + .phy_gtx_clk(phy_gtx_clk_int), + .phy_txd(phy_txd_int), + .phy_tx_en(phy_tx_en_int), + .phy_tx_er(phy_tx_er_int), + .phy_reset_n(phy_reset_n_int), + /* + * UART: 115200 bps, 8N1 + */ + .uart_rxd(uart_rxd_int), + .uart_txd(uart_txd_int) +); + +fpga_pads +pads_inst ( + /* + * Pads + */ + .clk_pad(clk), + .reset_n_pad(reset_n), + .btnu_pad(btnu), + .btnl_pad(btnl), + .btnd_pad(btnd), + .btnr_pad(btnr), + .btnc_pad(btnc), + .sw_pad(sw), + .led_pad(led), + .phy_rx_clk_pad(phy_rx_clk), + .phy_rxd_pad(phy_rxd), + .phy_rx_dv_pad(phy_rx_dv), + .phy_rx_er_pad(phy_rx_er), + .phy_gtx_clk_pad(phy_gtx_clk), + .phy_txd_pad(phy_txd), + .phy_tx_en_pad(phy_tx_en), + .phy_tx_er_pad(phy_tx_er), + .phy_reset_n_pad(phy_reset_n), + .uart_rxd_pad(uart_rxd), + .uart_txd_pad(uart_txd), + /* + * Internal + */ + .clk_int(clk_int), + .rst_int(rst_int), + .btnu_int(btnu_int), + .btnl_int(btnl_int), + .btnd_int(btnd_int), + .btnr_int(btnr_int), + .btnc_int(btnc_int), + .sw_int(sw_int), + .led_int(led_int), + .phy_rx_clk_int(phy_rx_clk_int), + .phy_rxd_int(phy_rxd_int), + .phy_rx_dv_int(phy_rx_dv_int), + .phy_rx_er_int(phy_rx_er_int), + .phy_gtx_clk_int(phy_gtx_clk_int), + .phy_txd_int(phy_txd_int), + .phy_tx_en_int(phy_tx_en_int), + .phy_tx_er_int(phy_tx_er_int), + .phy_reset_n_int(phy_reset_n_int), + .uart_rxd_int(uart_rxd_int), + .uart_txd_int(uart_txd_int) +); + +endmodule diff --git a/example/ATLYS/fpga/rtl/fpga_core.v b/example/ATLYS/fpga/rtl/fpga_core.v new file mode 100644 index 00000000..aedb04de --- /dev/null +++ b/example/ATLYS/fpga/rtl/fpga_core.v @@ -0,0 +1,646 @@ +/* + +Copyright (c) 2014 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 + +module fpga_core # +( + parameter TARGET_XILINX = 1 +) +( + /* + * Clock: 125MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [7:0] sw, + output wire [7:0] led, + /* + * Ethernet: 1000BASE-T GMII + */ + input wire phy_rx_clk, + input wire [7:0] phy_rxd, + input wire phy_rx_dv, + input wire phy_rx_er, + output wire phy_gtx_clk, + output wire [7:0] phy_txd, + output wire phy_tx_en, + output wire phy_tx_er, + output wire phy_reset_n, + /* + * UART: 115200 bps, 8N1 + */ + input wire uart_rxd, + output wire uart_txd +); + +// GMII between MAC and PHY IF +wire gmii_rx_clk; +wire gmii_rx_rst; +wire [7:0] gmii_rxd; +wire gmii_rx_dv; +wire gmii_rx_er; + +wire gmii_tx_clk; +wire gmii_tx_rst; +wire [7:0] gmii_txd; +wire gmii_tx_en; +wire gmii_tx_er; + +// AXI between MAC and FIFO +wire [7:0] rx_axis_tdata; +wire rx_axis_tvalid; +wire rx_axis_tlast; +wire rx_axis_tuser; + +wire [7:0] tx_axis_tdata; +wire tx_axis_tvalid; +wire tx_axis_tready; +wire tx_axis_tlast; + +// AXI between FIFO and Ethernet modules +wire [7:0] rx_fifo_axis_tdata; +wire rx_fifo_axis_tvalid; +wire rx_fifo_axis_tready; +wire rx_fifo_axis_tlast; +wire rx_fifo_axis_tuser = 0; + +wire [7:0] tx_fifo_axis_tdata; +wire tx_fifo_axis_tvalid; +wire tx_fifo_axis_tready; +wire tx_fifo_axis_tlast; +wire tx_fifo_axis_tuser; + +// Ethernet frame between Ethernet modules and UDP stack +wire rx_eth_hdr_ready; +wire rx_eth_hdr_valid; +wire [47:0] rx_eth_dest_mac; +wire [47:0] rx_eth_src_mac; +wire [15:0] rx_eth_type; +wire [7:0] rx_eth_payload_tdata; +wire rx_eth_payload_tvalid; +wire rx_eth_payload_tready; +wire rx_eth_payload_tlast; +wire rx_eth_payload_tuser; + +wire tx_eth_hdr_ready; +wire tx_eth_hdr_valid; +wire [47:0] tx_eth_dest_mac; +wire [47:0] tx_eth_src_mac; +wire [15:0] tx_eth_type; +wire [7:0] tx_eth_payload_tdata; +wire tx_eth_payload_tvalid; +wire tx_eth_payload_tready; +wire tx_eth_payload_tlast; +wire tx_eth_payload_tuser; + +// IP frame connections +wire rx_ip_hdr_valid; +wire rx_ip_hdr_ready; +wire [47:0] rx_ip_eth_dest_mac; +wire [47:0] rx_ip_eth_src_mac; +wire [15:0] rx_ip_eth_type; +wire [3:0] rx_ip_version; +wire [3:0] rx_ip_ihl; +wire [5:0] rx_ip_dscp; +wire [1:0] rx_ip_ecn; +wire [15:0] rx_ip_length; +wire [15:0] rx_ip_identification; +wire [2:0] rx_ip_flags; +wire [12:0] rx_ip_fragment_offset; +wire [7:0] rx_ip_ttl; +wire [7:0] rx_ip_protocol; +wire [15:0] rx_ip_header_checksum; +wire [31:0] rx_ip_source_ip; +wire [31:0] rx_ip_dest_ip; +wire [7:0] rx_ip_payload_tdata; +wire rx_ip_payload_tvalid; +wire rx_ip_payload_tready; +wire rx_ip_payload_tlast; +wire rx_ip_payload_tuser; + +wire tx_ip_hdr_valid; +wire tx_ip_hdr_ready; +wire [5:0] tx_ip_dscp; +wire [1:0] tx_ip_ecn; +wire [15:0] tx_ip_length; +wire [7:0] tx_ip_ttl; +wire [7:0] tx_ip_protocol; +wire [31:0] tx_ip_source_ip; +wire [31:0] tx_ip_dest_ip; +wire [7:0] tx_ip_payload_tdata; +wire tx_ip_payload_tvalid; +wire tx_ip_payload_tready; +wire tx_ip_payload_tlast; +wire tx_ip_payload_tuser; + +// UDP frame connections +wire rx_udp_hdr_valid; +wire rx_udp_hdr_ready; +wire [47:0] rx_udp_eth_dest_mac; +wire [47:0] rx_udp_eth_src_mac; +wire [15:0] rx_udp_eth_type; +wire [3:0] rx_udp_ip_version; +wire [3:0] rx_udp_ip_ihl; +wire [5:0] rx_udp_ip_dscp; +wire [1:0] rx_udp_ip_ecn; +wire [15:0] rx_udp_ip_length; +wire [15:0] rx_udp_ip_identification; +wire [2:0] rx_udp_ip_flags; +wire [12:0] rx_udp_ip_fragment_offset; +wire [7:0] rx_udp_ip_ttl; +wire [7:0] rx_udp_ip_protocol; +wire [15:0] rx_udp_ip_header_checksum; +wire [31:0] rx_udp_ip_source_ip; +wire [31:0] rx_udp_ip_dest_ip; +wire [15:0] rx_udp_source_port; +wire [15:0] rx_udp_dest_port; +wire [15:0] rx_udp_length; +wire [15:0] rx_udp_checksum; +wire [7:0] rx_udp_payload_tdata; +wire rx_udp_payload_tvalid; +wire rx_udp_payload_tready; +wire rx_udp_payload_tlast; +wire rx_udp_payload_tuser; + +wire tx_udp_hdr_valid; +wire tx_udp_hdr_ready; +wire [5:0] tx_udp_ip_dscp; +wire [1:0] tx_udp_ip_ecn; +wire [7:0] tx_udp_ip_ttl; +wire [31:0] tx_udp_ip_source_ip; +wire [31:0] tx_udp_ip_dest_ip; +wire [15:0] tx_udp_source_port; +wire [15:0] tx_udp_dest_port; +wire [15:0] tx_udp_length; +wire [15:0] tx_udp_checksum; +wire [7:0] tx_udp_payload_tdata; +wire tx_udp_payload_tvalid; +wire tx_udp_payload_tready; +wire tx_udp_payload_tlast; +wire tx_udp_payload_tuser; + +wire [7:0] rx_fifo_udp_payload_tdata; +wire rx_fifo_udp_payload_tvalid; +wire rx_fifo_udp_payload_tready; +wire rx_fifo_udp_payload_tlast; +wire rx_fifo_udp_payload_tuser; + +wire [7:0] tx_fifo_udp_payload_tdata; +wire tx_fifo_udp_payload_tvalid; +wire tx_fifo_udp_payload_tready; +wire tx_fifo_udp_payload_tlast; +wire tx_fifo_udp_payload_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_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_tdata = 0; +assign tx_ip_payload_tvalid = 0; +assign tx_ip_payload_tlast = 0; +assign tx_ip_payload_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_tvalid) begin + if ((~match_cond_reg & ~no_match_reg) | + (rx_udp_payload_tvalid & rx_udp_payload_tready & rx_udp_payload_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_tdata = rx_udp_payload_tdata; +//assign tx_udp_payload_tvalid = rx_udp_payload_tvalid; +//assign rx_udp_payload_tready = tx_udp_payload_tready; +//assign tx_udp_payload_tlast = rx_udp_payload_tlast; +//assign tx_udp_payload_tuser = rx_udp_payload_tuser; + +assign tx_udp_payload_tdata = tx_fifo_udp_payload_tdata; +assign tx_udp_payload_tvalid = tx_fifo_udp_payload_tvalid; +assign tx_fifo_udp_payload_tready = tx_udp_payload_tready; +assign tx_udp_payload_tlast = tx_fifo_udp_payload_tlast; +assign tx_udp_payload_tuser = tx_fifo_udp_payload_tuser; + +assign rx_fifo_udp_payload_tdata = rx_udp_payload_tdata; +assign rx_fifo_udp_payload_tvalid = rx_udp_payload_tvalid & match_cond_reg; +assign rx_udp_payload_tready = (rx_fifo_udp_payload_tready & match_cond_reg) | no_match_reg; +assign rx_fifo_udp_payload_tlast = rx_udp_payload_tlast; +assign rx_fifo_udp_payload_tuser = rx_udp_payload_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_tvalid; + if (tx_udp_payload_tvalid & ~valid_last) begin + led_reg <= tx_udp_payload_tdata; + end + end +end + +//assign led = sw; +assign led = led_reg; +assign phy_reset_n = ~rst; + +assign uart_txd = 0; + +gmii_phy_if #( + .TARGET_XILINX(TARGET_XILINX) +) +gmii_phy_if_inst ( + .clk(clk), + .rst(rst), + + .mac_gmii_rx_clk(gmii_rx_clk), + .mac_gmii_rx_rst(gmii_rx_rst), + .mac_gmii_rxd(gmii_rxd), + .mac_gmii_rx_dv(gmii_rx_dv), + .mac_gmii_rx_er(gmii_rx_er), + .mac_gmii_tx_clk(gmii_tx_clk), + .mac_gmii_tx_rst(gmii_tx_rst), + .mac_gmii_txd(gmii_txd), + .mac_gmii_tx_en(gmii_tx_en), + .mac_gmii_tx_er(gmii_tx_er), + + .phy_gmii_rx_clk(phy_rx_clk), + .phy_gmii_rxd(phy_rxd), + .phy_gmii_rx_dv(phy_rx_dv), + .phy_gmii_rx_er(phy_rx_er), + .phy_gmii_tx_clk(phy_gtx_clk), + .phy_gmii_txd(phy_txd), + .phy_gmii_tx_en(phy_tx_en), + .phy_gmii_tx_er(phy_tx_er) +); + +eth_mac_1g #( + .ENABLE_PADDING(1), + .MIN_FRAME_LENGTH(64) +) +eth_mac_1g_inst ( + .rx_clk(gmii_rx_clk), + .rx_rst(gmii_rx_rst), + .tx_clk(gmii_tx_clk), + .tx_rst(gmii_tx_rst), + + .tx_axis_tdata(tx_axis_tdata), + .tx_axis_tvalid(tx_axis_tvalid), + .tx_axis_tready(tx_axis_tready), + .tx_axis_tlast(tx_axis_tlast), + .tx_axis_tuser(0), + + .rx_axis_tdata(rx_axis_tdata), + .rx_axis_tvalid(rx_axis_tvalid), + .rx_axis_tlast(rx_axis_tlast), + .rx_axis_tuser(rx_axis_tuser), + + .gmii_rxd(gmii_rxd), + .gmii_rx_dv(gmii_rx_dv), + .gmii_rx_er(gmii_rx_er), + .gmii_txd(gmii_txd), + .gmii_tx_en(gmii_tx_en), + .gmii_tx_er(gmii_tx_er), + + .rx_error_bad_frame(rx_error_bad_frame), + .rx_error_bad_fcs(rx_error_bad_fcs), + + .ifg_delay(12) +); + +axis_async_frame_fifo #( + .ADDR_WIDTH(12), + .DATA_WIDTH(8), + .DROP_WHEN_FULL(1) +) +rx_fifo ( + // AXI input + .input_clk(gmii_rx_clk), + .input_rst(gmii_rx_rst), + + .input_axis_tdata(rx_axis_tdata), + .input_axis_tvalid(rx_axis_tvalid), + .input_axis_tready(), + .input_axis_tlast(rx_axis_tlast), + .input_axis_tuser(rx_axis_tuser), + + // AXI output + .output_clk(clk), + .output_rst(rst), + + .output_axis_tdata(rx_fifo_axis_tdata), + .output_axis_tvalid(rx_fifo_axis_tvalid), + .output_axis_tready(rx_fifo_axis_tready), + .output_axis_tlast(rx_fifo_axis_tlast) +); + +axis_async_frame_fifo #( + .ADDR_WIDTH(12), + .DATA_WIDTH(8) +) +tx_fifo ( + // AXI input + .input_clk(clk), + .input_rst(rst), + + .input_axis_tdata(tx_fifo_axis_tdata), + .input_axis_tvalid(tx_fifo_axis_tvalid), + .input_axis_tready(tx_fifo_axis_tready), + .input_axis_tlast(tx_fifo_axis_tlast), + .input_axis_tuser(tx_fifo_axis_tuser), + + // AXI output + .output_clk(gmii_tx_clk), + .output_rst(gmii_tx_rst), + + .output_axis_tdata(tx_axis_tdata), + .output_axis_tvalid(tx_axis_tvalid), + .output_axis_tready(tx_axis_tready), + .output_axis_tlast(tx_axis_tlast) +); + +eth_axis_rx +eth_axis_rx_inst ( + .clk(clk), + .rst(rst), + // AXI input + .input_axis_tdata(rx_fifo_axis_tdata), + .input_axis_tvalid(rx_fifo_axis_tvalid), + .input_axis_tready(rx_fifo_axis_tready), + .input_axis_tlast(rx_fifo_axis_tlast), + .input_axis_tuser(rx_fifo_axis_tuser), + // Ethernet frame output + .output_eth_hdr_valid(rx_eth_hdr_valid), + .output_eth_hdr_ready(rx_eth_hdr_ready), + .output_eth_dest_mac(rx_eth_dest_mac), + .output_eth_src_mac(rx_eth_src_mac), + .output_eth_type(rx_eth_type), + .output_eth_payload_tdata(rx_eth_payload_tdata), + .output_eth_payload_tvalid(rx_eth_payload_tvalid), + .output_eth_payload_tready(rx_eth_payload_tready), + .output_eth_payload_tlast(rx_eth_payload_tlast), + .output_eth_payload_tuser(rx_eth_payload_tuser), + // Status signals + .busy(), + .error_header_early_termination() +); + +eth_axis_tx +eth_axis_tx_inst ( + .clk(clk), + .rst(rst), + // Ethernet frame input + .input_eth_hdr_valid(tx_eth_hdr_valid), + .input_eth_hdr_ready(tx_eth_hdr_ready), + .input_eth_dest_mac(tx_eth_dest_mac), + .input_eth_src_mac(tx_eth_src_mac), + .input_eth_type(tx_eth_type), + .input_eth_payload_tdata(tx_eth_payload_tdata), + .input_eth_payload_tvalid(tx_eth_payload_tvalid), + .input_eth_payload_tready(tx_eth_payload_tready), + .input_eth_payload_tlast(tx_eth_payload_tlast), + .input_eth_payload_tuser(tx_eth_payload_tuser), + // AXI output + .output_axis_tdata(tx_fifo_axis_tdata), + .output_axis_tvalid(tx_fifo_axis_tvalid), + .output_axis_tready(tx_fifo_axis_tready), + .output_axis_tlast(tx_fifo_axis_tlast), + .output_axis_tuser(tx_fifo_axis_tuser), + // Status signals + .busy() +); + +udp_complete #( + .UDP_CHECKSUM_ENABLE(0) +) +udp_complete_inst ( + .clk(clk), + .rst(rst), + // Ethernet frame input + .input_eth_hdr_valid(rx_eth_hdr_valid), + .input_eth_hdr_ready(rx_eth_hdr_ready), + .input_eth_dest_mac(rx_eth_dest_mac), + .input_eth_src_mac(rx_eth_src_mac), + .input_eth_type(rx_eth_type), + .input_eth_payload_tdata(rx_eth_payload_tdata), + .input_eth_payload_tvalid(rx_eth_payload_tvalid), + .input_eth_payload_tready(rx_eth_payload_tready), + .input_eth_payload_tlast(rx_eth_payload_tlast), + .input_eth_payload_tuser(rx_eth_payload_tuser), + // Ethernet frame output + .output_eth_hdr_valid(tx_eth_hdr_valid), + .output_eth_hdr_ready(tx_eth_hdr_ready), + .output_eth_dest_mac(tx_eth_dest_mac), + .output_eth_src_mac(tx_eth_src_mac), + .output_eth_type(tx_eth_type), + .output_eth_payload_tdata(tx_eth_payload_tdata), + .output_eth_payload_tvalid(tx_eth_payload_tvalid), + .output_eth_payload_tready(tx_eth_payload_tready), + .output_eth_payload_tlast(tx_eth_payload_tlast), + .output_eth_payload_tuser(tx_eth_payload_tuser), + // IP frame input + .input_ip_hdr_valid(tx_ip_hdr_valid), + .input_ip_hdr_ready(tx_ip_hdr_ready), + .input_ip_dscp(tx_ip_dscp), + .input_ip_ecn(tx_ip_ecn), + .input_ip_length(tx_ip_length), + .input_ip_ttl(tx_ip_ttl), + .input_ip_protocol(tx_ip_protocol), + .input_ip_source_ip(tx_ip_source_ip), + .input_ip_dest_ip(tx_ip_dest_ip), + .input_ip_payload_tdata(tx_ip_payload_tdata), + .input_ip_payload_tvalid(tx_ip_payload_tvalid), + .input_ip_payload_tready(tx_ip_payload_tready), + .input_ip_payload_tlast(tx_ip_payload_tlast), + .input_ip_payload_tuser(tx_ip_payload_tuser), + // IP frame output + .output_ip_hdr_valid(rx_ip_hdr_valid), + .output_ip_hdr_ready(rx_ip_hdr_ready), + .output_ip_eth_dest_mac(rx_ip_eth_dest_mac), + .output_ip_eth_src_mac(rx_ip_eth_src_mac), + .output_ip_eth_type(rx_ip_eth_type), + .output_ip_version(rx_ip_version), + .output_ip_ihl(rx_ip_ihl), + .output_ip_dscp(rx_ip_dscp), + .output_ip_ecn(rx_ip_ecn), + .output_ip_length(rx_ip_length), + .output_ip_identification(rx_ip_identification), + .output_ip_flags(rx_ip_flags), + .output_ip_fragment_offset(rx_ip_fragment_offset), + .output_ip_ttl(rx_ip_ttl), + .output_ip_protocol(rx_ip_protocol), + .output_ip_header_checksum(rx_ip_header_checksum), + .output_ip_source_ip(rx_ip_source_ip), + .output_ip_dest_ip(rx_ip_dest_ip), + .output_ip_payload_tdata(rx_ip_payload_tdata), + .output_ip_payload_tvalid(rx_ip_payload_tvalid), + .output_ip_payload_tready(rx_ip_payload_tready), + .output_ip_payload_tlast(rx_ip_payload_tlast), + .output_ip_payload_tuser(rx_ip_payload_tuser), + // UDP frame input + .input_udp_hdr_valid(tx_udp_hdr_valid), + .input_udp_hdr_ready(tx_udp_hdr_ready), + .input_udp_ip_dscp(tx_udp_ip_dscp), + .input_udp_ip_ecn(tx_udp_ip_ecn), + .input_udp_ip_ttl(tx_udp_ip_ttl), + .input_udp_ip_source_ip(tx_udp_ip_source_ip), + .input_udp_ip_dest_ip(tx_udp_ip_dest_ip), + .input_udp_source_port(tx_udp_source_port), + .input_udp_dest_port(tx_udp_dest_port), + .input_udp_length(tx_udp_length), + .input_udp_checksum(tx_udp_checksum), + .input_udp_payload_tdata(tx_udp_payload_tdata), + .input_udp_payload_tvalid(tx_udp_payload_tvalid), + .input_udp_payload_tready(tx_udp_payload_tready), + .input_udp_payload_tlast(tx_udp_payload_tlast), + .input_udp_payload_tuser(tx_udp_payload_tuser), + // UDP frame output + .output_udp_hdr_valid(rx_udp_hdr_valid), + .output_udp_hdr_ready(rx_udp_hdr_ready), + .output_udp_eth_dest_mac(rx_udp_eth_dest_mac), + .output_udp_eth_src_mac(rx_udp_eth_src_mac), + .output_udp_eth_type(rx_udp_eth_type), + .output_udp_ip_version(rx_udp_ip_version), + .output_udp_ip_ihl(rx_udp_ip_ihl), + .output_udp_ip_dscp(rx_udp_ip_dscp), + .output_udp_ip_ecn(rx_udp_ip_ecn), + .output_udp_ip_length(rx_udp_ip_length), + .output_udp_ip_identification(rx_udp_ip_identification), + .output_udp_ip_flags(rx_udp_ip_flags), + .output_udp_ip_fragment_offset(rx_udp_ip_fragment_offset), + .output_udp_ip_ttl(rx_udp_ip_ttl), + .output_udp_ip_protocol(rx_udp_ip_protocol), + .output_udp_ip_header_checksum(rx_udp_ip_header_checksum), + .output_udp_ip_source_ip(rx_udp_ip_source_ip), + .output_udp_ip_dest_ip(rx_udp_ip_dest_ip), + .output_udp_source_port(rx_udp_source_port), + .output_udp_dest_port(rx_udp_dest_port), + .output_udp_length(rx_udp_length), + .output_udp_checksum(rx_udp_checksum), + .output_udp_payload_tdata(rx_udp_payload_tdata), + .output_udp_payload_tvalid(rx_udp_payload_tvalid), + .output_udp_payload_tready(rx_udp_payload_tready), + .output_udp_payload_tlast(rx_udp_payload_tlast), + .output_udp_payload_tuser(rx_udp_payload_tuser), + // Status signals + .ip_rx_busy(), + .ip_tx_busy(), + .udp_rx_busy(), + .udp_tx_busy(), + .ip_rx_error_header_early_termination(), + .ip_rx_error_payload_early_termination(), + .ip_rx_error_invalid_header(), + .ip_rx_error_invalid_checksum(), + .ip_tx_error_payload_early_termination(), + .ip_tx_error_arp_failed(), + .udp_rx_error_header_early_termination(), + .udp_rx_error_payload_early_termination(), + .udp_tx_error_payload_early_termination(), + // Configuration + .local_mac(local_mac), + .local_ip(local_ip), + .gateway_ip(gateway_ip), + .subnet_mask(subnet_mask), + .clear_arp_cache(0) +); + +axis_fifo #( + .ADDR_WIDTH(12), + .DATA_WIDTH(8) +) +udp_payload_fifo ( + .clk(clk), + .rst(rst), + + // AXI input + .input_axis_tdata(rx_fifo_udp_payload_tdata), + .input_axis_tvalid(rx_fifo_udp_payload_tvalid), + .input_axis_tready(rx_fifo_udp_payload_tready), + .input_axis_tlast(rx_fifo_udp_payload_tlast), + .input_axis_tuser(rx_fifo_udp_payload_tuser), + + // AXI output + .output_axis_tdata(tx_fifo_udp_payload_tdata), + .output_axis_tvalid(tx_fifo_udp_payload_tvalid), + .output_axis_tready(tx_fifo_udp_payload_tready), + .output_axis_tlast(tx_fifo_udp_payload_tlast), + .output_axis_tuser(tx_fifo_udp_payload_tuser) +); + +endmodule diff --git a/example/ATLYS/fpga/rtl/fpga_pads.v b/example/ATLYS/fpga/rtl/fpga_pads.v new file mode 100644 index 00000000..82222816 --- /dev/null +++ b/example/ATLYS/fpga/rtl/fpga_pads.v @@ -0,0 +1,170 @@ +/* + +Copyright (c) 2014 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 + +module fpga_pads ( + /* + * Pads + */ + input wire clk_pad, + input wire reset_n_pad, + input wire btnu_pad, + input wire btnl_pad, + input wire btnd_pad, + input wire btnr_pad, + input wire btnc_pad, + input wire [7:0] sw_pad, + output wire [7:0] led_pad, + input wire phy_rx_clk_pad, + input wire [7:0] phy_rxd_pad, + input wire phy_rx_dv_pad, + input wire phy_rx_er_pad, + output wire phy_gtx_clk_pad, + output wire [7:0] phy_txd_pad, + output wire phy_tx_en_pad, + output wire phy_tx_er_pad, + output wire phy_reset_n_pad, + input wire uart_rxd_pad, + output wire uart_txd_pad, + /* + * Internal + */ + output wire clk_int, + output wire rst_int, + output wire btnu_int, + output wire btnl_int, + output wire btnd_int, + output wire btnr_int, + output wire btnc_int, + output wire [7:0] sw_int, + input wire [7:0] led_int, + output wire phy_rx_clk_int, + output wire [7:0] phy_rxd_int, + output wire phy_rx_dv_int, + output wire phy_rx_er_int, + input wire phy_gtx_clk_int, + input wire [7:0] phy_txd_int, + input wire phy_tx_en_int, + input wire phy_tx_er_int, + input wire phy_reset_n_int, + output wire uart_rxd_int, + input wire uart_txd_int +); + +wire clk_valid; +/* + * Asynchronous reset created by from the combination of the external + * asyncrhonous reset input and the DCM clk_valid output. + */ +wire reset0 = ~reset_n_pad; +wire reset1 = ~clk_valid; + +/* + * Create a 125MHz clock from a 100MHz clock. + */ +dcm_i100_o125 +dcm_inst ( + .CLK_IN1(clk_pad), // IN(1) + .RESET(reset0), // IN(1) + .CLK_OUT1(clk_int), // OUT(1) + .LOCKED(clk_valid) // OUT(1) +); + +/* + * Create a synchronous reset in the 125MHz domain. + */ +sync_reset #( + .N(6) +) +sync_reset_inst ( + .clk(clk_int), // IN(1) + .rst(reset1), // IN(1) + .sync_reset_out(rst_int) // OUT(1) +); + +/* + * Synchronize the inputs. + */ +sync_signal #( + .WIDTH(1), + .N(2) +) +sync_signal_inst ( + .clk(clk_int), //IN(1) + .in({uart_rxd_pad}), //IN(1) + .out({uart_rxd_int}) // OUT(1) +); + +/* + * Debounce the switches + */ +debounce_switch #( + .WIDTH(13), + .N(4), + .RATE(125000) +) +debounce_switch_inst ( + .clk(clk_int), // IN(1) + .rst(rst_int), // IN(1) + .in({btnu_pad, + btnl_pad, + btnd_pad, + btnr_pad, + btnc_pad, + sw_pad}), // IN(13) + .out({btnu_int, + btnl_int, + btnd_int, + btnr_int, + btnc_int, + sw_int}) // OUT(13) +); + +/* + * PHY inputs not synchronized here + */ +assign phy_rx_clk_int = phy_rx_clk_pad; +assign phy_rxd_int = phy_rxd_pad; +assign phy_rx_dv_int = phy_rx_dv_pad; +assign phy_rx_er_int = phy_rx_er_pad; + +/* + * PHY outputs not synchronized here + */ +assign phy_gtx_clk_pad = phy_gtx_clk_int; +assign phy_txd_pad = phy_txd_int; +assign phy_tx_en_pad = phy_tx_en_int; +assign phy_tx_er_pad = phy_tx_er_int; +assign phy_reset_n_pad = phy_reset_n_int; + +/* + * Outputs not synchronized here + */ +assign led_pad = led_int; +assign uart_txd_pad = uart_txd_int; + +endmodule diff --git a/example/ATLYS/fpga/rtl/sync_reset.v b/example/ATLYS/fpga/rtl/sync_reset.v new file mode 100644 index 00000000..ffa0530b --- /dev/null +++ b/example/ATLYS/fpga/rtl/sync_reset.v @@ -0,0 +1,52 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`timescale 1 ns / 1 ps + +/* + * Synchronizes an active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule diff --git a/example/ATLYS/fpga/rtl/sync_signal.v b/example/ATLYS/fpga/rtl/sync_signal.v new file mode 100644 index 00000000..705d4f8e --- /dev/null +++ b/example/ATLYS/fpga/rtl/sync_signal.v @@ -0,0 +1,58 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`timescale 1 ns / 1 ps + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule diff --git a/example/ATLYS/fpga/tb/arp_ep.py b/example/ATLYS/fpga/tb/arp_ep.py new file mode 120000 index 00000000..7b3d3ed9 --- /dev/null +++ b/example/ATLYS/fpga/tb/arp_ep.py @@ -0,0 +1 @@ +../lib/eth/tb/arp_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/axis_ep.py b/example/ATLYS/fpga/tb/axis_ep.py new file mode 120000 index 00000000..385bb030 --- /dev/null +++ b/example/ATLYS/fpga/tb/axis_ep.py @@ -0,0 +1 @@ +../lib/eth/tb/axis_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/eth_ep.py b/example/ATLYS/fpga/tb/eth_ep.py new file mode 120000 index 00000000..bac19fee --- /dev/null +++ b/example/ATLYS/fpga/tb/eth_ep.py @@ -0,0 +1 @@ +../lib/eth/tb/eth_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/gmii_ep.py b/example/ATLYS/fpga/tb/gmii_ep.py new file mode 120000 index 00000000..754166f2 --- /dev/null +++ b/example/ATLYS/fpga/tb/gmii_ep.py @@ -0,0 +1 @@ +../lib/eth/tb/gmii_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/ip_ep.py b/example/ATLYS/fpga/tb/ip_ep.py new file mode 120000 index 00000000..6dfa928a --- /dev/null +++ b/example/ATLYS/fpga/tb/ip_ep.py @@ -0,0 +1 @@ +../lib/eth/tb/ip_ep.py \ No newline at end of file diff --git a/example/ATLYS/fpga/tb/test_fpga_core.py b/example/ATLYS/fpga/tb/test_fpga_core.py new file mode 100755 index 00000000..18d082d6 --- /dev/null +++ b/example/ATLYS/fpga/tb/test_fpga_core.py @@ -0,0 +1,335 @@ +#!/usr/bin/env python2 +""" + +Copyright (c) 2015 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +from myhdl import * +import os +from Queue import Queue + +import eth_ep +import arp_ep +import udp_ep +import gmii_ep + +module = 'fpga_core' + +srcs = [] + +srcs.append("../rtl/%s.v" % module) +srcs.append("../lib/eth/rtl/gmii_phy_if.v") +srcs.append("../lib/eth/rtl/eth_mac_1g.v") +srcs.append("../lib/eth/rtl/eth_mac_1g_rx.v") +srcs.append("../lib/eth/rtl/eth_mac_1g_tx.v") +srcs.append("../lib/eth/rtl/eth_crc_8.v") +srcs.append("../lib/eth/rtl/eth_axis_rx.v") +srcs.append("../lib/eth/rtl/eth_axis_tx.v") +srcs.append("../lib/eth/rtl/udp_complete.v") +srcs.append("../lib/eth/rtl/udp.v") +srcs.append("../lib/eth/rtl/udp_ip_rx.v") +srcs.append("../lib/eth/rtl/udp_ip_tx.v") +srcs.append("../lib/eth/rtl/ip_complete.v") +srcs.append("../lib/eth/rtl/ip.v") +srcs.append("../lib/eth/rtl/ip_eth_rx.v") +srcs.append("../lib/eth/rtl/ip_eth_tx.v") +srcs.append("../lib/eth/rtl/ip_arb_mux_2.v") +srcs.append("../lib/eth/rtl/ip_mux_2.v") +srcs.append("../lib/eth/rtl/arp.v") +srcs.append("../lib/eth/rtl/arp_cache.v") +srcs.append("../lib/eth/rtl/arp_eth_rx.v") +srcs.append("../lib/eth/rtl/arp_eth_tx.v") +srcs.append("../lib/eth/rtl/eth_arb_mux_2.v") +srcs.append("../lib/eth/rtl/eth_mux_2.v") +srcs.append("../lib/eth/lib/axis/rtl/arbiter.v") +srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v") +srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v") +srcs.append("../lib/eth/lib/axis/rtl/axis_async_frame_fifo.v") +srcs.append("test_%s.v" % module) + +src = ' '.join(srcs) + +build_cmd = "iverilog -o test_%s.vvp %s" % (module, src) + +def dut_fpga_core(clk, + rst, + + current_test, + btnu, + btnl, + btnd, + btnr, + btnc, + sw, + led, + + phy_rx_clk, + phy_rxd, + phy_rx_dv, + phy_rx_er, + phy_gtx_clk, + phy_txd, + phy_tx_en, + phy_tx_er, + phy_reset_n, + + uart_rxd, + uart_txd): + + if os.system(build_cmd): + raise Exception("Error running build command") + return Cosimulation("vvp -m myhdl test_%s.vvp -lxt2" % module, + clk=clk, + rst=rst, + current_test=current_test, + + btnu=btnu, + btnl=btnl, + btnd=btnd, + btnr=btnr, + btnc=btnc, + sw=sw, + led=led, + + phy_rx_clk=phy_rx_clk, + phy_rxd=phy_rxd, + phy_rx_dv=phy_rx_dv, + phy_rx_er=phy_rx_er, + phy_gtx_clk=phy_gtx_clk, + phy_txd=phy_txd, + phy_tx_en=phy_tx_en, + phy_tx_er=phy_tx_er, + phy_reset_n=phy_reset_n, + + uart_rxd=uart_rxd, + uart_txd=uart_txd) + +def bench(): + + # Parameters + TARGET_XILINX = 1 + + # Inputs + clk = Signal(bool(0)) + rst = Signal(bool(0)) + current_test = Signal(intbv(0)[8:]) + + btnu = Signal(bool(0)) + btnl = Signal(bool(0)) + btnd = Signal(bool(0)) + btnr = Signal(bool(0)) + btnc = Signal(bool(0)) + sw = Signal(intbv(0)[8:]) + phy_rx_clk = Signal(bool(0)) + phy_rxd = Signal(intbv(0)[8:]) + phy_rx_dv = Signal(bool(0)) + phy_rx_er = Signal(bool(0)) + uart_rxd = Signal(bool(0)) + + # Outputs + led = Signal(intbv(0)[8:]) + phy_gtx_clk = Signal(bool(0)) + phy_txd = Signal(intbv(0)[8:]) + phy_tx_en = Signal(bool(0)) + phy_tx_er = Signal(bool(0)) + phy_reset_n = Signal(bool(0)) + uart_txd = Signal(bool(0)) + + # sources and sinks + gmii_source_queue = Queue() + gmii_sink_queue = Queue() + + gmii_source = gmii_ep.GMIISource(phy_rx_clk, + rst, + txd=phy_rxd, + tx_en=phy_rx_dv, + tx_er=phy_rx_er, + fifo=gmii_source_queue, + name='gmii_source') + + gmii_sink = gmii_ep.GMIISink(phy_gtx_clk, + rst, + rxd=phy_txd, + rx_dv=phy_tx_en, + rx_er=phy_tx_er, + fifo=gmii_sink_queue, + name='gmii_sink') + + # DUT + dut = dut_fpga_core(clk, + rst, + current_test, + + btnu, + btnl, + btnd, + btnr, + btnc, + sw, + led, + + phy_rx_clk, + phy_rxd, + phy_rx_dv, + phy_rx_er, + phy_gtx_clk, + phy_txd, + phy_tx_en, + phy_tx_er, + phy_reset_n, + + uart_rxd, + uart_txd) + + @always(delay(4)) + def clkgen(): + clk.next = not clk + phy_rx_clk.next = not phy_rx_clk + + @instance + def check(): + yield delay(100) + yield clk.posedge + rst.next = 1 + yield clk.posedge + rst.next = 0 + yield clk.posedge + yield delay(100) + yield clk.posedge + + # testbench stimulus + + yield clk.posedge + print("test 1: test UDP RX packet") + current_test.next = 1 + + test_frame = udp_ep.UDPFrame() + test_frame.eth_dest_mac = 0x020000000000 + test_frame.eth_src_mac = 0xDAD1D2D3D4D5 + test_frame.eth_type = 0x0800 + test_frame.ip_version = 4 + test_frame.ip_ihl = 5 + test_frame.ip_dscp = 0 + test_frame.ip_ecn = 0 + test_frame.ip_length = None + test_frame.ip_identification = 0 + test_frame.ip_flags = 2 + test_frame.ip_fragment_offset = 0 + test_frame.ip_ttl = 64 + test_frame.ip_protocol = 0x11 + test_frame.ip_header_checksum = None + test_frame.ip_source_ip = 0xc0a80181 + test_frame.ip_dest_ip = 0xc0a80180 + test_frame.udp_source_port = 5678 + test_frame.udp_dest_port = 1234 + test_frame.payload = bytearray(range(32)) + test_frame.build() + + gmii_source_queue.put(test_frame.build_eth().build_axis_fcs()) + + # wait for ARP request packet + while gmii_sink_queue.empty(): + yield clk.posedge + + rx_frame = gmii_sink_queue.get(False) + check_eth_frame = eth_ep.EthFrame() + check_eth_frame.parse_axis_fcs(bytearray(rx_frame)) + check_frame = arp_ep.ARPFrame() + check_frame.parse_eth(check_eth_frame) + + print(check_frame) + + assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF + assert check_frame.eth_src_mac == 0x020000000000 + assert check_frame.eth_type == 0x0806 + assert check_frame.arp_htype == 0x0001 + assert check_frame.arp_ptype == 0x0800 + assert check_frame.arp_hlen == 6 + assert check_frame.arp_plen == 4 + assert check_frame.arp_oper == 1 + assert check_frame.arp_sha == 0x020000000000 + assert check_frame.arp_spa == 0xc0a80180 + assert check_frame.arp_tha == 0x000000000000 + assert check_frame.arp_tpa == 0xc0a80181 + + # generate response + arp_frame = arp_ep.ARPFrame() + arp_frame.eth_dest_mac = 0x020000000000 + arp_frame.eth_src_mac = 0xDAD1D2D3D4D5 + arp_frame.eth_type = 0x0806 + arp_frame.arp_htype = 0x0001 + arp_frame.arp_ptype = 0x0800 + arp_frame.arp_hlen = 6 + arp_frame.arp_plen = 4 + arp_frame.arp_oper = 2 + arp_frame.arp_sha = 0xDAD1D2D3D4D5 + arp_frame.arp_spa = 0xc0a80181 + arp_frame.arp_tha = 0x020000000000 + arp_frame.arp_tpa = 0xc0a80180 + + gmii_source_queue.put(arp_frame.build_eth().build_axis_fcs()) + + while gmii_sink_queue.empty(): + yield clk.posedge + + rx_frame = gmii_sink_queue.get(False) + check_eth_frame = eth_ep.EthFrame() + check_eth_frame.parse_axis_fcs(bytearray(rx_frame)) + check_frame = udp_ep.UDPFrame() + check_frame.parse_eth(check_eth_frame) + + print(check_frame) + + assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5 + assert check_frame.eth_src_mac == 0x020000000000 + assert check_frame.eth_type == 0x0800 + assert check_frame.ip_version == 4 + assert check_frame.ip_ihl == 5 + assert check_frame.ip_dscp == 0 + assert check_frame.ip_ecn == 0 + assert check_frame.ip_identification == 0 + assert check_frame.ip_flags == 2 + assert check_frame.ip_fragment_offset == 0 + assert check_frame.ip_ttl == 64 + assert check_frame.ip_protocol == 0x11 + assert check_frame.ip_source_ip == 0xc0a80180 + assert check_frame.ip_dest_ip == 0xc0a80181 + assert check_frame.udp_source_port == 1234 + assert check_frame.udp_dest_port == 5678 + assert check_frame.payload.data == bytearray(range(32)) + + assert gmii_source_queue.empty() + assert gmii_sink_queue.empty() + + yield delay(100) + + raise StopSimulation + + return dut, gmii_source, gmii_sink, clkgen, check + +def test_bench(): + sim = Simulation(bench()) + sim.run() + +if __name__ == '__main__': + print("Running test...") + test_bench() diff --git a/example/ATLYS/fpga/tb/test_fpga_core.v b/example/ATLYS/fpga/tb/test_fpga_core.v new file mode 100644 index 00000000..cf9bf642 --- /dev/null +++ b/example/ATLYS/fpga/tb/test_fpga_core.v @@ -0,0 +1,118 @@ +/* + +Copyright (c) 2015 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * Testbench for fpga_core + */ +module test_fpga_core; + +// Parameters +parameter TARGET_XILINX = 0; + +// Inputs +reg clk = 0; +reg rst = 0; +reg [7:0] current_test = 0; + +reg btnu = 0; +reg btnl = 0; +reg btnd = 0; +reg btnr = 0; +reg btnc = 0; +reg [7:0] sw = 0; +reg phy_rx_clk = 0; +reg [7:0] phy_rxd = 0; +reg phy_rx_dv = 0; +reg phy_rx_er = 0; +reg uart_rxd = 0; + +// Outputs +wire [7:0] led; +wire phy_gtx_clk; +wire [7:0] phy_txd; +wire phy_tx_en; +wire phy_tx_er; +wire phy_reset_n; +wire uart_txd; + +initial begin + // myhdl integration + $from_myhdl(clk, + rst, + current_test, + btnu, + btnl, + btnd, + btnr, + btnc, + sw, + phy_rx_clk, + phy_rxd, + phy_rx_dv, + phy_rx_er, + uart_rxd); + $to_myhdl(led, + phy_gtx_clk, + phy_txd, + phy_tx_en, + phy_tx_er, + phy_reset_n, + uart_txd); + + // dump file + $dumpfile("test_fpga_core.lxt"); + $dumpvars(0, test_fpga_core); +end + +fpga_core #( + .TARGET_XILINX(TARGET_XILINX) +) +UUT ( + .clk(clk), + .rst(rst), + .btnu(btnu), + .btnl(btnl), + .btnd(btnd), + .btnr(btnr), + .btnc(btnc), + .sw(sw), + .led(led), + .phy_rx_clk(phy_rx_clk), + .phy_rxd(phy_rxd), + .phy_rx_dv(phy_rx_dv), + .phy_rx_er(phy_rx_er), + .phy_gtx_clk(phy_gtx_clk), + .phy_txd(phy_txd), + .phy_tx_en(phy_tx_en), + .phy_tx_er(phy_tx_er), + .phy_reset_n(phy_reset_n), + .uart_rxd(uart_rxd), + .uart_txd(uart_txd) +); + +endmodule diff --git a/example/ATLYS/fpga/tb/udp_ep.py b/example/ATLYS/fpga/tb/udp_ep.py new file mode 120000 index 00000000..073c5d3c --- /dev/null +++ b/example/ATLYS/fpga/tb/udp_ep.py @@ -0,0 +1 @@ +../lib/eth/tb/udp_ep.py \ No newline at end of file