Add example design for Digilent Atlys board

This commit is contained in:
Alex Forencich 2015-02-28 20:05:05 -08:00
parent 5a5c78be64
commit d489468776
23 changed files with 2455 additions and 0 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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) $@

View File

@ -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

View File

@ -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

193
example/ATLYS/fpga/fpga.ucf Normal file
View File

@ -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)

View File

@ -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

1
example/ATLYS/fpga/lib/eth Symbolic link
View File

@ -0,0 +1 @@
../../../../

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
../lib/eth/tb/arp_ep.py

View File

@ -0,0 +1 @@
../lib/eth/tb/axis_ep.py

View File

@ -0,0 +1 @@
../lib/eth/tb/eth_ep.py

View File

@ -0,0 +1 @@
../lib/eth/tb/gmii_ep.py

View File

@ -0,0 +1 @@
../lib/eth/tb/ip_ep.py

View File

@ -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()

View File

@ -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

View File

@ -0,0 +1 @@
../lib/eth/tb/udp_ep.py