1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

added eth as a subproject

git-subtree-dir: fpga/lib/eth
git-subtree-mainline: 4cdce8caa74728a4973261dae0e00fcd479af9ac
git-subtree-split: e5171d874916b3e23a02d5621e91dd9ff02b7fcb
This commit is contained in:
Alex Forencich 2019-07-15 14:55:25 -07:00
commit de181120b8
820 changed files with 197419 additions and 0 deletions

6
fpga/lib/eth/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*~
*.lxt
*.pyc
*.vvp
*.kate-swp

15
fpga/lib/eth/.travis.yml Normal file
View File

@ -0,0 +1,15 @@
language: python
python:
- "3.6"
before_install:
- export d=`pwd`
- export PYTHON_EXE=`which python`
- sudo apt-get update -qq
- sudo apt-get install -y iverilog
- git clone https://github.com/jandecaluwe/myhdl.git
- cd $d/myhdl && sudo $PYTHON_EXE setup.py install
- cd $d/myhdl/cosimulation/icarus && make && sudo install -m 0755 -D ./myhdl.vpi /usr/lib/x86_64-linux-gnu/ivl/myhdl.vpi
- cd $d
script:
- cd tb && py.test

1
fpga/lib/eth/AUTHORS Normal file
View File

@ -0,0 +1 @@
Alex Forencich <alex@alexforencich.com>

19
fpga/lib/eth/COPYING Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1
fpga/lib/eth/README Symbolic link
View File

@ -0,0 +1 @@
README.md

562
fpga/lib/eth/README.md Normal file
View File

@ -0,0 +1,562 @@
# Verilog Ethernet Components Readme
For more information and updates: http://alexforencich.com/wiki/en/verilog/ethernet/start
GitHub repository: https://github.com/alexforencich/verilog-ethernet
## Introduction
Collection of Ethernet-related components for gigabit, 10G, and 25G packet
processing (8 bit and 64 bit datapaths). Includes modules for handling
Ethernet frames as well as IP, UDP, and ARP and the components for
constructing a complete UDP/IP stack. Includes MAC modules for gigabit and
10G/25G, a 10G/25G PCS/PMA PHY module, and a 10G/25G combination MAC/PCS/PMA
module. Also includes full MyHDL testbench with intelligent bus cosimulation
endpoints.
For IP and ARP support only, use ip_complete (1G) or ip_complete_64 (10G/25G).
For UDP, IP, and ARP support, use udp_complete (1G) or udp_complete_64
(10G/25G).
Top level gigabit and 10G/25G MAC modules are eth_mac_*, with various
interfaces and with/without FIFOs. Top level 10G/25G PCS/PMA PHY module is
eth_phy_10g. Top level 10G/25G MAC/PCS/PMA combination module is
eth_mac_phy_10g.
## Documentation
### arp module
ARP handling logic with parametrizable retry timeout parameters.
### arp_64 module
ARP handling logic with parametrizable retry timeout parameters and 64 bit
datapath for 10G/25G Ethernet.
### arp_cache module
Basic hash-based cache for ARP entries. Parametrizable depth.
### arp_eth_rx module
ARP frame receiver.
### arp_eth_rx_64 module
ARP frame receiver with 64 bit datapath for 10G/25G Ethernet.
### arp_eth_tx module
ARP frame transmitter.
### arp_eth_tx_64 module
ARP frame transmitter with 64 bit datapath for 10G/25G Ethernet.
### axis_eth_fcs module
Ethernet frame check sequence calculator.
### axis_eth_fcs_64 module
Ethernet frame check sequence calculator with 64 bit datapath for 10G/25G
Ethernet.
### axis_eth_fcs_check module
Ethernet frame check sequence checker.
### axis_eth_fcs_insert module
Ethernet frame check sequence inserter.
### axis_gmii_rx module
AXI stream GMII/MII frame receiver with clock enable and MII select.
### axis_gmii_tx module
AXI stream GMII/MII frame transmitter with clock enable and MII select.
### axis_xgmii_rx_32 module
AXI stream XGMII frame receiver with 32 bit datapath.
### axis_xgmii_rx_64 module
AXI stream XGMII frame receiver with 64 bit datapath.
### axis_xgmii_tx_32 module
AXI stream XGMII frame transmitter with 32 bit datapath.
### axis_xgmii_tx_64 module
AXI stream XGMII frame transmitter with 64 bit datapath.
### eth_arb_mux module
Ethernet frame arbitrated muliplexer with parametrizable data width and port
count. Supports priority and round-robin arbitration.
### eth_axis_rx module
Ethernet frame receiver.
### eth_axis_rx_64 module
Ethernet frame receiver with 64 bit datapath for 10G/25G Ethernet.
### eth_axis_tx module
Ethernet frame transmitter.
### eth_axis_tx_64 module
Ethernet frame transmitter with 64 bit datapath for 10G/25G Ethernet.
### eth_demux module
Ethernet frame demuliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### eth_mac_1g module
Gigabit Ethernet MAC with GMII interface.
### eth_mac_1g_fifo module
Gigabit Ethernet MAC with GMII interface and FIFOs.
### eth_mac_1g_gmii module
Tri-mode Ethernet MAC with GMII/MII interface and automatic PHY rate
adaptation logic.
### eth_mac_1g_gmii_fifo module
Tri-mode Ethernet MAC with GMII/MII interface, FIFOs, and automatic PHY rate
adaptation logic.
### eth_mac_1g_rgmii module
Tri-mode Ethernet MAC with RGMII interface and automatic PHY rate adaptation
logic.
### eth_mac_1g_rgmii_fifo module
Tri-mode Ethernet MAC with RGMII interface, FIFOs, and automatic PHY rate
adaptation logic.
### eth_mac_10g module
10G/25G Ethernet MAC with XGMII interface. Datapath selectable between 32 and
64 bits.
### eth_mac_10g_fifo module
10G/25G Ethernet MAC with XGMII interface and FIFOs. Datapath selectable
between 32 and 64 bits.
### eth_mac_mii module
Ethernet MAC with MII interface.
### eth_mac_mii_fifo module
Ethernet MAC with MII interface and FIFOs.
### eth_mac_phy_10g module
10G/25G Ethernet MAC/PHY combination module with SERDES interface.
### eth_mac_phy_10g_fifo module
10G/25G Ethernet MAC/PHY combination module with SERDES interface and FIFOs.
### eth_mac_phy_10g_rx module
10G/25G Ethernet MAC/PHY combination module with SERDES interface, RX path.
### eth_mac_phy_10g_tx module
10G/25G Ethernet MAC/PHY combination module with SERDES interface, TX path.
### eth_mux module
Ethernet frame muliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### eth_phy_10g module
10G/25G Ethernet PCS/PMA PHY.
### eth_phy_10g_rx module
10G/25G Ethernet PCS/PMA PHY receive-side logic.
### eth_phy_10g_rx_ber_mon module
10G/25G Ethernet PCS/PMA PHY BER monitor.
### eth_phy_10g_rx_frame_sync module
10G/25G Ethernet PCS/PMA PHY frame synchronizer.
### eth_phy_10g_tx module
10G/25G Ethernet PCS/PMA PHY transmit-side logic.
### gmii_phy_if module
GMII/MII PHY interface and clocking logic.
### ip module
IPv4 block with 8 bit data width for gigabit Ethernet. Manages IPv4 packet
transmssion and reception. Interfaces with ARP module for MAC address lookup.
### ip_64 module
IPv4 block with 64 bit data width for 10G/25G Ethernet. Manages IPv4 packet
transmssion and reception. Interfaces with ARP module for MAC address lookup.
### ip_arb_mux module
IP frame arbitrated muliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### ip_complete module
IPv4 module with ARP integration.
Top level for gigabit IP stack.
### ip_complete_64 module
IPv4 module with ARP integration and 64 bit data width for 10G/25G Ethernet.
Top level for 10G/25G IP stack.
### ip_demux module
IP frame demuliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### ip_eth_rx module
IP frame receiver.
### ip_eth_rx_64 module
IP frame receiver with 64 bit datapath for 10G/25G Ethernet.
### ip_eth_tx module
IP frame transmitter.
### ip_eth_tx_64 module
IP frame transmitter with 64 bit datapath for 10G/25G Ethernet.
### ip_mux module
IP frame muliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### lfsr module
Fully parametrizable combinatorial parallel LFSR/CRC module.
### mii_phy_if module
MII PHY interface and clocking logic.
### ptp_clock module
PTP clock module with PPS output. Generates both 64 bit and 96 bit timestamp
formats. Fine frequeny adjustment supported with configurable fractional
nanoseconds field.
### rgmii_phy_if module
RGMII PHY interface and clocking logic.
### udp module
UDP block with 8 bit data width for gigabit Ethernet. Manages UDP packet
transmssion and reception.
### udp_64 module
UDP block with 64 bit data width for 10G/25G Ethernet. Manages UDP packet
transmssion and reception.
### udp_arb_mux module
UDP frame arbitrated muliplexer with parametrizable data width and port
count. Supports priority and round-robin arbitration.
### udp_checksum_gen module
UDP checksum generator module. Calculates UDP length, IP length, and
UDP checksum fields.
### udp_checksum_gen_64 module
UDP checksum generator module with 64 bit datapath. Calculates UDP
length, IP length, and UDP checksum fields.
### udp_complete module
UDP module with IPv4 and ARP integration.
Top level for gigabit UDP stack.
### udp_complete_64 module
UDP module with IPv4 and ARP integration and 64 bit data width for 10G
Ethernet.
Top level for 10G/25G UDP stack.
### udp_demux module
UDP frame demuliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### udp_ip_rx module
UDP frame receiver.
### udp_ip_rx_64 module
UDP frame receiver with 64 bit datapath for 10G/25G Ethernet.
### udp_ip_tx module
UDP frame transmitter.
### udp_ip_tx_64 module
UDP frame transmitter with 64 bit datapath for 10G/25G Ethernet.
### udp_mux module
UDP frame muliplexer with parametrizable data width and port count.
Supports priority and round-robin arbitration.
### xgmii_baser_dec_64 module
XGMII 10GBASE-R decoder for 10G PCS/PMA PHY.
### xgmii_baser_enc_64 module
XGMII 10GBASE-R encoder for 10G PCS/PMA PHY.
### xgmii_deinterleave module
XGMII de-interleaver for interfacing with PHY cores that interleave the
control and data lines.
### xgmii_interleave module
XGMII interleaver for interfacing with PHY cores that interleave the control
and data lines.
### Common signals
tdata : Data (width generally DATA_WIDTH)
tkeep : Data word valid (width generally KEEP_WIDTH, present on _64 modules)
tvalid : Data valid
tready : Sink ready
tlast : End-of-frame
tuser : Bad frame (valid with tlast & tvalid)
### Source Files
rtl/arp.v : ARP handling logic
rtl/arp_64.v : ARP handling logic (64 bit)
rtl/arp_cache.v : ARP LRU cache
rtl/arp_eth_rx.v : ARP frame receiver
rtl/arp_eth_rx_64.v : ARP frame receiver (64 bit)
rtl/arp_eth_tx.v : ARP frame transmitter
rtl/arp_eth_tx_64.v : ARP frame transmitter (64 bit)
rtl/eth_arb_mux.py : Ethernet frame arbitrated multiplexer generator
rtl/axis_eth_fcs.v : Ethernet FCS calculator
rtl/axis_eth_fcs_64.v : Ethernet FCS calculator (64 bit)
rtl/axis_eth_fcs_insert.v : Ethernet FCS inserter
rtl/axis_eth_fcs_check.v : Ethernet FCS checker
rtl/axis_gmii_rx.v : AXI stream GMII/MII receiver
rtl/axis_gmii_tx.v : AXI stream GMII/MII transmitter
rtl/axis_xgmii_rx_32.v : AXI stream XGMII receiver (32 bit)
rtl/axis_xgmii_rx_64.v : AXI stream XGMII receiver (64 bit)
rtl/axis_xgmii_tx_32.v : AXI stream XGMII transmitter (32 bit)
rtl/axis_xgmii_tx_64.v : AXI stream XGMII transmitter (64 bit)
rtl/eth_arb_mux.v : Ethernet frame arbitrated multiplexer
rtl/eth_axis_rx.v : Ethernet frame receiver
rtl/eth_axis_rx_64.v : Ethernet frame receiver (64 bit)
rtl/eth_axis_tx.v : Ethernet frame transmitter
rtl/eth_axis_tx_64.v : Ethernet frame transmitter (64 bit)
rtl/eth_demux.v : Ethernet frame demultiplexer
rtl/eth_mac_1g.v : Gigabit Ethernet GMII MAC
rtl/eth_mac_1g_fifo.v : Gigabit Ethernet GMII MAC with FIFO
rtl/eth_mac_1g_gmii.v : Tri-mode Ethernet GMII/MII MAC
rtl/eth_mac_1g_gmii_fifo.v : Tri-mode Ethernet GMII/MII MAC with FIFO
rtl/eth_mac_1g_rgmii.v : Tri-mode Ethernet RGMII MAC
rtl/eth_mac_1g_rgmii_fifo.v : Tri-mode Ethernet RGMII MAC with FIFO
rtl/eth_mac_10g.v : 10G/25G Ethernet XGMII MAC
rtl/eth_mac_10g_fifo.v : 10G/25G Ethernet XGMII MAC with FIFO
rtl/eth_mac_mii.v : Ethernet MII MAC
rtl/eth_mac_mii_fifo.v : Ethernet MII MAC with FIFO
rtl/eth_mac_phy_10g.v : 10G/25G Ethernet XGMII MAC/PHY
rtl/eth_mac_phy_10g_fifo.v : 10G/25G Ethernet XGMII MAC/PHY with FIFO
rtl/eth_mac_phy_10g_rx.v : 10G/25G Ethernet XGMII MAC/PHY RX with FIFO
rtl/eth_mac_phy_10g_tx.v : 10G/25G Ethernet XGMII MAC/PHY TX with FIFO
rtl/eth_mux.v : Ethernet frame multiplexer
rtl/gmii_phy_if.v : GMII PHY interface
rtl/iddr.v : Generic DDR input register
rtl/ip.v : IPv4 block
rtl/ip_64.v : IPv4 block (64 bit)
rtl/ip_arb_mux.v : IP frame arbitrated multiplexer
rtl/ip_complete.v : IPv4 stack (IP-ARP integration)
rtl/ip_complete_64.v : IPv4 stack (IP-ARP integration) (64 bit)
rtl/ip_demux.v : IP frame demultiplexer
rtl/ip_eth_rx.v : IPv4 frame receiver
rtl/ip_eth_rx_64.v : IPv4 frame receiver (64 bit)
rtl/ip_eth_tx.v : IPv4 frame transmitter
rtl/ip_eth_tx_64.v : IPv4 frame transmitter (64 bit)
rtl/ip_mux.v : IP frame multiplexer
rtl/lfsr.v : Generic LFSR/CRC module
rtl/mii_phy_if.v : MII PHY interface
rtl/oddr.v : Generic DDR output register
rtl/ptp_clock.v : PTP clock
rtl/rgmii_phy_if.v : RGMII PHY interface
rtl/ssio_ddr_in.v : Generic source synchronous IO DDR input module
rtl/ssio_ddr_in_diff.v : Generic source synchronous IO DDR differential input module
rtl/ssio_ddr_out.v : Generic source synchronous IO DDR output module
rtl/ssio_ddr_out_diff.v : Generic source synchronous IO DDR differential output module
rtl/ssio_sdr_in.v : Generic source synchronous IO SDR input module
rtl/ssio_sdr_in_diff.v : Generic source synchronous IO SDR differential input module
rtl/ssio_sdr_out.v : Generic source synchronous IO SDR output module
rtl/ssio_sdr_out_diff.v : Generic source synchronous IO SDR differential output module
rtl/udp.v : UDP block
rtl/udp_64.v : UDP block (64 bit)
rtl/udp_arb_mux.v : UDP frame arbitrated multiplexer
rtl/udp_checksum_gen.v : UDP checksum generator
rtl/udp_checksum_gen_64.v : UDP checksum generator (64 bit)
rtl/udp_complete.v : UDP stack (IP-ARP-UDP)
rtl/udp_complete_64.v : UDP stack (IP-ARP-UDP) (64 bit)
rtl/udp_demux.v : UDP frame demultiplexer
rtl/udp_ip_rx.v : UDP frame receiver
rtl/udp_ip_rx_64.v : UDP frame receiver (64 bit)
rtl/udp_ip_tx.v : UDP frame transmitter
rtl/udp_ip_tx_64.v : UDP frame transmitter (64 bit)
rtl/udp_mux.v : UDP frame multiplexer
rtl/xgmii_baser_dec_64.v : XGMII 10GBASE-R decoder
rtl/xgmii_baser_enc_64.v : XGMII 10GBASE-R encoder
rtl/xgmii_deinterleave.v : XGMII data/control de-interleaver
rtl/xgmii_interleave.v : XGMII data/control interleaver
### AXI Stream Interface Example
transfer with header data
__ __ __ __ __ __ __
clk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__
______________ ___________
hdr_ready \_________________/
_____
hdr_valid ________/ \_____________________________
_____
hdr_data XXXXXXXXX_HDR_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
___________ _____ _____
tdata XXXXXXXXX_A0________X_A1__X_A2__XXXXXXXXXXXX
___________ _____ _____
tkeep XXXXXXXXX_K0________X_K1__X_K2__XXXXXXXXXXXX
_______________________
tvalid ________/ \___________
_________________
tready ______________/ \___________
_____
tlast __________________________/ \___________
tuser ____________________________________________
two byte transfer with sink pause after each byte
__ __ __ __ __ __ __ __ __
clk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__
_____ _________________
tdata XXXXXXXXX_D0__X_D1______________XXXXXXXXXXXXXXXXXXXXXXXX
_____ _________________
tkeep XXXXXXXXX_K0__X_K1______________XXXXXXXXXXXXXXXXXXXXXXXX
_______________________
tvalid ________/ \_______________________
______________ _____ ___________
tready \___________/ \___________/
_________________
tlast ______________/ \_______________________
tuser ________________________________________________________
two back-to-back packets, no pauses
__ __ __ __ __ __ __ __ __
clk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__
_____ _____ _____ _____ _____ _____
tdata XXXXXXXXX_A0__X_A1__X_A2__X_B0__X_B1__X_B2__XXXXXXXXXXXX
_____ _____ _____ _____ _____ _____
tkeep XXXXXXXXX_K0__X_K1__X_K2__X_K0__X_K1__X_K2__XXXXXXXXXXXX
___________________________________
tvalid ________/ \___________
________________________________________________________
tready
_____ _____
tlast ____________________/ \___________/ \___________
tuser ________________________________________________________
bad frame
__ __ __ __ __ __
clk __/ \__/ \__/ \__/ \__/ \__/ \__
_____ _____ _____
tdata XXXXXXXXX_A0__X_A1__X_A2__XXXXXXXXXXXX
_____ _____ _____
tkeep XXXXXXXXX_K0__X_K1__X_K2__XXXXXXXXXXXX
_________________
tvalid ________/ \___________
______________________________________
tready
_____
tlast ____________________/ \___________
_____
tuser ____________________/ \___________
## Testing
Running the included testbenches requires MyHDL and Icarus Verilog. Make sure
that myhdl.vpi is installed properly for cosimulation to work correctly. The
testbenches can be run with a Python test runner like nose or py.test, or the
individual test scripts can be run with python directly.
### Testbench Files
tb/arp_ep.py : MyHDL ARP frame endpoints
tb/axis_ep.py : MyHDL AXI Stream endpoints
tb/baser_serdes.py : MyHDL 10GBASE-R SERDES endpoints
tb/eth_ep.py : MyHDL Ethernet frame endpoints
tb/gmii_ep.py : MyHDL GMII endpoints
tb/ip_ep.py : MyHDL IP frame endpoints
tb/mii_ep.py : MyHDL MII endpoints
tb/ptp.py : MyHDL PTP clock model
tb/rgmii_ep.py : MyHDL RGMII endpoints
tb/udp_ep.py : MyHDL UDP frame endpoints
tb/xgmii_ep.py : MyHDL XGMII endpoints

View File

@ -0,0 +1,25 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -0,0 +1,24 @@
# Verilog Ethernet ADM-PCIE-9V3 Example Design
## Introduction
This example design targets the Alpha Data ADM-PCIE-9V3 FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
FPGA: xcvu3p-ffvc1517-2-i
PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the ADM-PCIE-9V3 board with Vivado. Then run
netcat -u 192.168.1.128 1234 to open a UDP connection to port 1234. Any text
entered into netcat will be echoed back after pressing enter.

View File

@ -0,0 +1,118 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale)
# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e)
# SYN_FILES - space-separated list of source files
# INC_FILES - space-separated list of include files
# XDC_FILES - space-separated list of timing constraint files
# XCI_FILES - space-separated list of IP XCI files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = VirtexUltrascale
# FPGA_DEVICE = xcvu095-ffva2104-2-e
# SYN_FILES = rtl/fpga.v
# XDC_FILES = fpga.xdc
# XCI_FILES = ip/pcspma.xci
# include ../common/vivado.mk
#
###################################################################
# phony targets
.PHONY: clean fpga
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES))
INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES))
XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES))
ifdef XDC_FILES
XDC_FILES_REL = $(patsubst %, ../%, $(XDC_FILES))
else
XDC_FILES_REL = $(FPGA_TOP).xdc
endif
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and project files
###################################################################
all: fpga
fpga: $(FPGA_TOP).bit
tmpclean:
-rm -rf *.log *.jou *.cache *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.tcl run_synth.tcl run_impl.tcl generate_bit.tcl
clean: tmpclean
-rm -rf *.bit program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl
distclean: clean
-rm -rf rev
###################################################################
# Target implementations
###################################################################
# Vivado project file
%.xpr: Makefile $(XCI_FILES_REL)
rm -rf defines.v
touch defines.v
for x in $(DEFS); do echo '`define' $$x >> defines.v; done
echo "create_project -force -part $(FPGA_PART) $*" > create_project.tcl
echo "add_files -fileset sources_1 defines.v" >> create_project.tcl
for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done
for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done
echo "exit" >> create_project.tcl
vivado -nojournal -nolog -mode batch -source create_project.tcl
# synthesis run
%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project $*.xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
echo "exit" >> run_synth.tcl
vivado -nojournal -nolog -mode batch -source run_synth.tcl
# implementation run
%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp
echo "open_project $*.xpr" > run_impl.tcl
echo "reset_run impl_1" >> run_impl.tcl
echo "launch_runs impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "exit" >> run_impl.tcl
vivado -nojournal -nolog -mode batch -source run_impl.tcl
# bit file
%.bit: %.runs/impl_1/%_routed.dcp
echo "open_project $*.xpr" > generate_bit.tcl
echo "open_run impl_1" >> generate_bit.tcl
echo "write_bitstream -force $*.bit" >> generate_bit.tcl
echo "exit" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
mkdir -p rev
EXT=bit; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do COUNT=$$((COUNT+1)); done; \
cp $@ rev/$*_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_rev$$COUNT.$$EXT";

View File

@ -0,0 +1,176 @@
# XDC constraints for the ADM-PCIE-9V3
# part: xcvu3p-ffvc1517-2-i
# General configuration
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN {DIV-1} [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 8 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.CONFIG.UNUSEDPIN {Pullnone} [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
# 300 MHz system clock
set_property -dict {LOC AP26 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports clk_300mhz_p]
set_property -dict {LOC AP27 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports clk_300mhz_n]
create_clock -period 3.333 -name clk_300mhz [get_ports clk_300mhz_p]
# LEDs
set_property -dict {LOC AT27 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_g[0]}]
set_property -dict {LOC AU27 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_g[1]}]
set_property -dict {LOC AU23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_r}]
set_property -dict {LOC AH24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[0]}]
set_property -dict {LOC AJ23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[1]}]
# Switches
set_property -dict {LOC AV27 IOSTANDARD LVCMOS18} [get_ports {user_sw[0]}]
set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}]
# GPIO
#set_property -dict {LOC G30 IOSTANDARD LVCMOS18} [get_ports gpio_p[0]]
#set_property -dict {LOC F30 IOSTANDARD LVCMOS18} [get_ports gpio_n[0]]
#set_property -dict {LOC J31 IOSTANDARD LVCMOS18} [get_ports gpio_p[1]]
#set_property -dict {LOC H31 IOSTANDARD LVCMOS18} [get_ports gpio_n[1]]
# QSFP28 Interfaces
set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
set_property -dict {LOC N33 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_128 from ?
#set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ?
set_property -dict {LOC F29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_0_modprs_l]
set_property -dict {LOC D31 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_0_sel_l]
# 161.1328125 MHz MGT reference clock
create_clock -period 6.206 -name qsfp_0_mgt_refclk [get_ports qsfp_0_mgt_refclk_p]
set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
set_property -dict {LOC U33 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_127 from ?
#set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ?
set_property -dict {LOC F33 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_1_modprs_l]
set_property -dict {LOC D30 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_1_sel_l]
# 161.1328125 MHz MGT reference clock
create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p]
set_property -dict {LOC B29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_reset_l]
set_property -dict {LOC C29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_int_l]
#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_scl]
#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_sda]
# PCIe Interface
#set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYTXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXN3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYTXN2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYTXP2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXN2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXP2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYTXN1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYTXP1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXN1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXP1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYTXN0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYTXP0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXN0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXP0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYTXN3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYTXP3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXN3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXP3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYTXN0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYTXP0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXN0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXP0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AA7 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_226
#set_property -dict {LOC AA6 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_226
#set_property -dict {LOC AJ7 } [get_ports pcie_refclk_2_p] ;# MGTREFCLK0P_224
#set_property -dict {LOC AJ6 } [get_ports pcie_refclk_2_n] ;# MGTREFCLK0N_224
#set_property -dict {LOC AJ31 IOSTANDARD LVCMOS18 PULLUP true} [get_ports perst_0]
#set_property -dict {LOC AH29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports perst_1]
# 100 MHz MGT reference clock
#create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p]
#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p]
# QSPI flash
#set_property -dict {LOC AB10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi_clk}]
#set_property -dict {LOC AB8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[0]}]
#set_property -dict {LOC AD8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[1]}]
#set_property -dict {LOC Y8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[2]}]
#set_property -dict {LOC AC8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[3]}]
#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[0]}]
#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[1]}]
#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[2]}]
#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[3]}]

View File

@ -0,0 +1,106 @@
# FPGA settings
FPGA_PART = xcvu3p-ffvc1517-2-i
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx_64.v
SYN_FILES += lib/eth/rtl/eth_axis_tx_64.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp_64.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx_64.v
SYN_FILES += lib/eth/rtl/arp_eth_tx_64.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/axis_async_fifo.tcl
# IP
XCI_FILES += ip/gtwizard_ultrascale_0.xci
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 64 -interface SPIx8 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu256-spi-x1_x2_x4_x8}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,89 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule

View File

@ -0,0 +1,880 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 300MHz LVDS
*/
input wire clk_300mhz_p,
input wire clk_300mhz_n,
/*
* GPIO
*/
output wire [1:0] user_led_g,
output wire user_led_r,
output wire [1:0] front_led,
input wire [1:0] user_sw,
/*
* Ethernet: QSFP28
*/
output wire qsfp_0_tx_0_p,
output wire qsfp_0_tx_0_n,
input wire qsfp_0_rx_0_p,
input wire qsfp_0_rx_0_n,
output wire qsfp_0_tx_1_p,
output wire qsfp_0_tx_1_n,
input wire qsfp_0_rx_1_p,
input wire qsfp_0_rx_1_n,
output wire qsfp_0_tx_2_p,
output wire qsfp_0_tx_2_n,
input wire qsfp_0_rx_2_p,
input wire qsfp_0_rx_2_n,
output wire qsfp_0_tx_3_p,
output wire qsfp_0_tx_3_n,
input wire qsfp_0_rx_3_p,
input wire qsfp_0_rx_3_n,
input wire qsfp_0_mgt_refclk_p,
input wire qsfp_0_mgt_refclk_n,
input wire qsfp_0_modprs_l,
output wire qsfp_0_sel_l,
output wire qsfp_1_tx_0_p,
output wire qsfp_1_tx_0_n,
input wire qsfp_1_rx_0_p,
input wire qsfp_1_rx_0_n,
output wire qsfp_1_tx_1_p,
output wire qsfp_1_tx_1_n,
input wire qsfp_1_rx_1_p,
input wire qsfp_1_rx_1_n,
output wire qsfp_1_tx_2_p,
output wire qsfp_1_tx_2_n,
input wire qsfp_1_rx_2_p,
input wire qsfp_1_rx_2_n,
output wire qsfp_1_tx_3_p,
output wire qsfp_1_tx_3_n,
input wire qsfp_1_rx_3_p,
input wire qsfp_1_rx_3_n,
input wire qsfp_1_mgt_refclk_p,
input wire qsfp_1_mgt_refclk_n,
input wire qsfp_1_modprs_l,
output wire qsfp_1_sel_l,
output wire qsfp_reset_l,
input wire qsfp_int_l
);
// Clock and reset
wire clk_300mhz_ibufg;
wire clk_125mhz_mmcm_out;
// Internal 125 MHz clock
wire clk_125mhz_int;
wire rst_125mhz_int;
// Internal 156.25 MHz clock
wire clk_156mhz_int;
wire rst_156mhz_int;
wire mmcm_rst = 1'b0;
wire mmcm_locked;
wire mmcm_clkfb;
IBUFGDS #(
.DIFF_TERM("FALSE"),
.IBUF_LOW_PWR("FALSE")
)
clk_300mhz_ibufg_inst (
.O (clk_300mhz_ibufg),
.I (clk_300mhz_p),
.IB (clk_300mhz_n)
);
// MMCM instance
// 300 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 10, D = 3 sets Fvco = 1000 MHz (in range)
// Divide by 8 to get output frequency of 125 MHz
MMCME3_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(8),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0),
.CLKOUT1_DIVIDE(1),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT1_PHASE(0),
.CLKOUT2_DIVIDE(1),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT2_PHASE(0),
.CLKOUT3_DIVIDE(1),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0),
.CLKOUT4_DIVIDE(1),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT5_DIVIDE(1),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT5_PHASE(0),
.CLKOUT6_DIVIDE(1),
.CLKOUT6_DUTY_CYCLE(0.5),
.CLKOUT6_PHASE(0),
.CLKFBOUT_MULT_F(10),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(3),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(3.333),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_300mhz_ibufg),
.CLKFBIN(mmcm_clkfb),
.RST(mmcm_rst),
.PWRDWN(1'b0),
.CLKOUT0(clk_125mhz_mmcm_out),
.CLKOUT0B(),
.CLKOUT1(),
.CLKOUT1B(),
.CLKOUT2(),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
.CLKOUT4(),
.CLKOUT5(),
.CLKOUT6(),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
.LOCKED(mmcm_locked)
);
BUFG
clk_125mhz_bufg_inst (
.I(clk_125mhz_mmcm_out),
.O(clk_125mhz_int)
);
sync_reset #(
.N(4)
)
sync_reset_125mhz_inst (
.clk(clk_125mhz_int),
.rst(~mmcm_locked),
.sync_reset_out(rst_125mhz_int)
);
// GPIO
wire [1:0] user_sw_int;
debounce_switch #(
.WIDTH(2),
.N(4),
.RATE(125000)
)
debounce_switch_inst (
.clk(clk_125mhz_int),
.rst(rst_125mhz_int),
.in({user_sw}),
.out({user_sw_int})
);
// XGMII 10G PHY
assign qsfp_0_sel_l = 1'b0;
wire qsfp_0_tx_clk_0_int;
wire qsfp_0_tx_rst_0_int;
wire [63:0] qsfp_0_txd_0_int;
wire [7:0] qsfp_0_txc_0_int;
wire qsfp_0_rx_clk_0_int;
wire qsfp_0_rx_rst_0_int;
wire [63:0] qsfp_0_rxd_0_int;
wire [7:0] qsfp_0_rxc_0_int;
wire qsfp_0_tx_clk_1_int;
wire qsfp_0_tx_rst_1_int;
wire [63:0] qsfp_0_txd_1_int;
wire [7:0] qsfp_0_txc_1_int;
wire qsfp_0_rx_clk_1_int;
wire qsfp_0_rx_rst_1_int;
wire [63:0] qsfp_0_rxd_1_int;
wire [7:0] qsfp_0_rxc_1_int;
wire qsfp_0_tx_clk_2_int;
wire qsfp_0_tx_rst_2_int;
wire [63:0] qsfp_0_txd_2_int;
wire [7:0] qsfp_0_txc_2_int;
wire qsfp_0_rx_clk_2_int;
wire qsfp_0_rx_rst_2_int;
wire [63:0] qsfp_0_rxd_2_int;
wire [7:0] qsfp_0_rxc_2_int;
wire qsfp_0_tx_clk_3_int;
wire qsfp_0_tx_rst_3_int;
wire [63:0] qsfp_0_txd_3_int;
wire [7:0] qsfp_0_txc_3_int;
wire qsfp_0_rx_clk_3_int;
wire qsfp_0_rx_rst_3_int;
wire [63:0] qsfp_0_rxd_3_int;
wire [7:0] qsfp_0_rxc_3_int;
assign qsfp_1_sel_l = 1'b0;
wire qsfp_1_tx_clk_0_int;
wire qsfp_1_tx_rst_0_int;
wire [63:0] qsfp_1_txd_0_int;
wire [7:0] qsfp_1_txc_0_int;
wire qsfp_1_rx_clk_0_int;
wire qsfp_1_rx_rst_0_int;
wire [63:0] qsfp_1_rxd_0_int;
wire [7:0] qsfp_1_rxc_0_int;
wire qsfp_1_tx_clk_1_int;
wire qsfp_1_tx_rst_1_int;
wire [63:0] qsfp_1_txd_1_int;
wire [7:0] qsfp_1_txc_1_int;
wire qsfp_1_rx_clk_1_int;
wire qsfp_1_rx_rst_1_int;
wire [63:0] qsfp_1_rxd_1_int;
wire [7:0] qsfp_1_rxc_1_int;
wire qsfp_1_tx_clk_2_int;
wire qsfp_1_tx_rst_2_int;
wire [63:0] qsfp_1_txd_2_int;
wire [7:0] qsfp_1_txc_2_int;
wire qsfp_1_rx_clk_2_int;
wire qsfp_1_rx_rst_2_int;
wire [63:0] qsfp_1_rxd_2_int;
wire [7:0] qsfp_1_rxc_2_int;
wire qsfp_1_tx_clk_3_int;
wire qsfp_1_tx_rst_3_int;
wire [63:0] qsfp_1_txd_3_int;
wire [7:0] qsfp_1_txc_3_int;
wire qsfp_1_rx_clk_3_int;
wire qsfp_1_rx_rst_3_int;
wire [63:0] qsfp_1_rxd_3_int;
wire [7:0] qsfp_1_rxc_3_int;
assign qsfp_reset_l = 1'b1;
wire qsfp_0_rx_block_lock_0;
wire qsfp_0_rx_block_lock_1;
wire qsfp_0_rx_block_lock_2;
wire qsfp_0_rx_block_lock_3;
wire qsfp_1_rx_block_lock_0;
wire qsfp_1_rx_block_lock_1;
wire qsfp_1_rx_block_lock_2;
wire qsfp_1_rx_block_lock_3;
wire qsfp_0_mgt_refclk;
wire qsfp_1_mgt_refclk;
wire [7:0] gt_txclkout;
wire gt_txusrclk;
wire [7:0] gt_rxclkout;
wire [7:0] gt_rxusrclk;
wire gt_reset_tx_done;
wire gt_reset_rx_done;
wire [7:0] gt_txprgdivresetdone;
wire [7:0] gt_txpmaresetdone;
wire [7:0] gt_rxprgdivresetdone;
wire [7:0] gt_rxpmaresetdone;
wire gt_tx_reset = ~((&gt_txprgdivresetdone) & (&gt_txpmaresetdone));
wire gt_rx_reset = ~&gt_rxpmaresetdone;
reg gt_userclk_tx_active = 1'b0;
reg [7:0] gt_userclk_rx_active = 1'b0;
IBUFDS_GTE4 ibufds_gte4_qsfp_0_mgt_refclk_inst (
.I (qsfp_0_mgt_refclk_p),
.IB (qsfp_0_mgt_refclk_n),
.CEB (1'b0),
.O (qsfp_0_mgt_refclk),
.ODIV2 ()
);
IBUFDS_GTE4 ibufds_gte4_qsfp_1_mgt_refclk_inst (
.I (qsfp_1_mgt_refclk_p),
.IB (qsfp_1_mgt_refclk_n),
.CEB (1'b0),
.O (qsfp_1_mgt_refclk),
.ODIV2 ()
);
BUFG_GT bufg_gt_tx_usrclk_inst (
.CE (1'b1),
.CEMASK (1'b0),
.CLR (gt_tx_reset),
.CLRMASK (1'b0),
.DIV (3'd0),
.I (gt_txclkout[0]),
.O (gt_txusrclk)
);
assign clk_156mhz_int = gt_txusrclk;
always @(posedge gt_txusrclk, posedge gt_tx_reset) begin
if (gt_tx_reset) begin
gt_userclk_tx_active <= 1'b0;
end else begin
gt_userclk_tx_active <= 1'b1;
end
end
generate
genvar n;
for (n = 0; n < 8; n = n + 1) begin
BUFG_GT bufg_gt_rx_usrclk_inst (
.CE (1'b1),
.CEMASK (1'b0),
.CLR (gt_rx_reset),
.CLRMASK (1'b0),
.DIV (3'd0),
.I (gt_rxclkout[n]),
.O (gt_rxusrclk[n])
);
always @(posedge gt_rxusrclk[n], posedge gt_rx_reset) begin
if (gt_rx_reset) begin
gt_userclk_rx_active[n] <= 1'b0;
end else begin
gt_userclk_rx_active[n] <= 1'b1;
end
end
end
endgenerate
sync_reset #(
.N(4)
)
sync_reset_156mhz_inst (
.clk(clk_156mhz_int),
.rst(~gt_reset_tx_done),
.sync_reset_out(rst_156mhz_int)
);
wire [5:0] qsfp_0_gt_txheader_0;
wire [63:0] qsfp_0_gt_txdata_0;
wire qsfp_0_gt_rxgearboxslip_0;
wire [5:0] qsfp_0_gt_rxheader_0;
wire [1:0] qsfp_0_gt_rxheadervalid_0;
wire [63:0] qsfp_0_gt_rxdata_0;
wire [1:0] qsfp_0_gt_rxdatavalid_0;
wire [5:0] qsfp_0_gt_txheader_1;
wire [63:0] qsfp_0_gt_txdata_1;
wire qsfp_0_gt_rxgearboxslip_1;
wire [5:0] qsfp_0_gt_rxheader_1;
wire [1:0] qsfp_0_gt_rxheadervalid_1;
wire [63:0] qsfp_0_gt_rxdata_1;
wire [1:0] qsfp_0_gt_rxdatavalid_1;
wire [5:0] qsfp_0_gt_txheader_2;
wire [63:0] qsfp_0_gt_txdata_2;
wire qsfp_0_gt_rxgearboxslip_2;
wire [5:0] qsfp_0_gt_rxheader_2;
wire [1:0] qsfp_0_gt_rxheadervalid_2;
wire [63:0] qsfp_0_gt_rxdata_2;
wire [1:0] qsfp_0_gt_rxdatavalid_2;
wire [5:0] qsfp_0_gt_txheader_3;
wire [63:0] qsfp_0_gt_txdata_3;
wire qsfp_0_gt_rxgearboxslip_3;
wire [5:0] qsfp_0_gt_rxheader_3;
wire [1:0] qsfp_0_gt_rxheadervalid_3;
wire [63:0] qsfp_0_gt_rxdata_3;
wire [1:0] qsfp_0_gt_rxdatavalid_3;
wire [5:0] qsfp_1_gt_txheader_0;
wire [63:0] qsfp_1_gt_txdata_0;
wire qsfp_1_gt_rxgearboxslip_0;
wire [5:0] qsfp_1_gt_rxheader_0;
wire [1:0] qsfp_1_gt_rxheadervalid_0;
wire [63:0] qsfp_1_gt_rxdata_0;
wire [1:0] qsfp_1_gt_rxdatavalid_0;
wire [5:0] qsfp_1_gt_txheader_1;
wire [63:0] qsfp_1_gt_txdata_1;
wire qsfp_1_gt_rxgearboxslip_1;
wire [5:0] qsfp_1_gt_rxheader_1;
wire [1:0] qsfp_1_gt_rxheadervalid_1;
wire [63:0] qsfp_1_gt_rxdata_1;
wire [1:0] qsfp_1_gt_rxdatavalid_1;
wire [5:0] qsfp_1_gt_txheader_2;
wire [63:0] qsfp_1_gt_txdata_2;
wire qsfp_1_gt_rxgearboxslip_2;
wire [5:0] qsfp_1_gt_rxheader_2;
wire [1:0] qsfp_1_gt_rxheadervalid_2;
wire [63:0] qsfp_1_gt_rxdata_2;
wire [1:0] qsfp_1_gt_rxdatavalid_2;
wire [5:0] qsfp_1_gt_txheader_3;
wire [63:0] qsfp_1_gt_txdata_3;
wire qsfp_1_gt_rxgearboxslip_3;
wire [5:0] qsfp_1_gt_rxheader_3;
wire [1:0] qsfp_1_gt_rxheadervalid_3;
wire [63:0] qsfp_1_gt_rxdata_3;
wire [1:0] qsfp_1_gt_rxdatavalid_3;
gtwizard_ultrascale_0
qsfp_gty_inst (
.gtwiz_userclk_tx_active_in(&gt_userclk_tx_active),
.gtwiz_userclk_rx_active_in(&gt_userclk_rx_active),
.gtwiz_reset_clk_freerun_in(clk_125mhz_int),
.gtwiz_reset_all_in(rst_125mhz_int),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(1'b0),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(1'b0),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.gtrefclk00_in({qsfp_0_mgt_refclk, qsfp_1_mgt_refclk}),
.qpll0outclk_out(),
.qpll0outrefclk_out(),
.gtyrxn_in({qsfp_0_rx_3_n, qsfp_0_rx_2_n, qsfp_0_rx_1_n, qsfp_0_rx_0_n, qsfp_1_rx_3_n, qsfp_1_rx_2_n, qsfp_1_rx_1_n, qsfp_1_rx_0_n}),
.gtyrxp_in({qsfp_0_rx_3_p, qsfp_0_rx_2_p, qsfp_0_rx_1_p, qsfp_0_rx_0_p, qsfp_1_rx_3_p, qsfp_1_rx_2_p, qsfp_1_rx_1_p, qsfp_1_rx_0_p}),
.rxusrclk_in(gt_rxusrclk),
.rxusrclk2_in(gt_rxusrclk),
.gtwiz_userdata_tx_in({qsfp_0_gt_txdata_3, qsfp_0_gt_txdata_2, qsfp_0_gt_txdata_1, qsfp_0_gt_txdata_0, qsfp_1_gt_txdata_3, qsfp_1_gt_txdata_2, qsfp_1_gt_txdata_1, qsfp_1_gt_txdata_0}),
.txheader_in({qsfp_0_gt_txheader_3, qsfp_0_gt_txheader_2, qsfp_0_gt_txheader_1, qsfp_0_gt_txheader_0, qsfp_1_gt_txheader_3, qsfp_1_gt_txheader_2, qsfp_1_gt_txheader_1, qsfp_1_gt_txheader_0}),
.txsequence_in({8{1'b0}}),
.txusrclk_in({8{gt_txusrclk}}),
.txusrclk2_in({8{gt_txusrclk}}),
.gtpowergood_out(),
.gtytxn_out({qsfp_0_tx_3_n, qsfp_0_tx_2_n, qsfp_0_tx_1_n, qsfp_0_tx_0_n, qsfp_1_tx_3_n, qsfp_1_tx_2_n, qsfp_1_tx_1_n, qsfp_1_tx_0_n}),
.gtytxp_out({qsfp_0_tx_3_p, qsfp_0_tx_2_p, qsfp_0_tx_1_p, qsfp_0_tx_0_p, qsfp_1_tx_3_p, qsfp_1_tx_2_p, qsfp_1_tx_1_p, qsfp_1_tx_0_p}),
.rxgearboxslip_in({qsfp_0_gt_rxgearboxslip_3, qsfp_0_gt_rxgearboxslip_2, qsfp_0_gt_rxgearboxslip_1, qsfp_0_gt_rxgearboxslip_0, qsfp_1_gt_rxgearboxslip_3, qsfp_1_gt_rxgearboxslip_2, qsfp_1_gt_rxgearboxslip_1, qsfp_1_gt_rxgearboxslip_0}),
.gtwiz_userdata_rx_out({qsfp_0_gt_rxdata_3, qsfp_0_gt_rxdata_2, qsfp_0_gt_rxdata_1, qsfp_0_gt_rxdata_0, qsfp_1_gt_rxdata_3, qsfp_1_gt_rxdata_2, qsfp_1_gt_rxdata_1, qsfp_1_gt_rxdata_0}),
.rxdatavalid_out({qsfp_0_gt_rxdatavalid_3, qsfp_0_gt_rxdatavalid_2, qsfp_0_gt_rxdatavalid_1, qsfp_0_gt_rxdatavalid_0, qsfp_1_gt_rxdatavalid_3, qsfp_1_gt_rxdatavalid_2, qsfp_1_gt_rxdatavalid_1, qsfp_1_gt_rxdatavalid_0}),
.rxheader_out({qsfp_0_gt_rxheader_3, qsfp_0_gt_rxheader_2, qsfp_0_gt_rxheader_1, qsfp_0_gt_rxheader_0, qsfp_1_gt_rxheader_3, qsfp_1_gt_rxheader_2, qsfp_1_gt_rxheader_1, qsfp_1_gt_rxheader_0}),
.rxheadervalid_out({qsfp_0_gt_rxheadervalid_3, qsfp_0_gt_rxheadervalid_2, qsfp_0_gt_rxheadervalid_1, qsfp_0_gt_rxheadervalid_0, qsfp_1_gt_rxheadervalid_3, qsfp_1_gt_rxheadervalid_2, qsfp_1_gt_rxheadervalid_1, qsfp_1_gt_rxheadervalid_0}),
.rxoutclk_out(gt_rxclkout),
.rxpmaresetdone_out(gt_rxpmaresetdone),
.rxprgdivresetdone_out(gt_rxprgdivresetdone),
.rxstartofseq_out(),
.txoutclk_out(gt_txclkout),
.txpmaresetdone_out(gt_txpmaresetdone),
.txprgdivresetdone_out(gt_txprgdivresetdone)
);
assign qsfp_0_tx_clk_0_int = clk_156mhz_int;
assign qsfp_0_tx_rst_0_int = rst_156mhz_int;
assign qsfp_0_rx_clk_0_int = gt_rxusrclk[4];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_0_reset_sync_inst (
.clk(qsfp_0_rx_clk_0_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_0_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_0_phy_0_inst (
.tx_clk(qsfp_0_tx_clk_0_int),
.tx_rst(qsfp_0_tx_rst_0_int),
.rx_clk(qsfp_0_rx_clk_0_int),
.rx_rst(qsfp_0_rx_rst_0_int),
.xgmii_txd(qsfp_0_txd_0_int),
.xgmii_txc(qsfp_0_txc_0_int),
.xgmii_rxd(qsfp_0_rxd_0_int),
.xgmii_rxc(qsfp_0_rxc_0_int),
.serdes_tx_data(qsfp_0_gt_txdata_0),
.serdes_tx_hdr(qsfp_0_gt_txheader_0),
.serdes_rx_data(qsfp_0_gt_rxdata_0),
.serdes_rx_hdr(qsfp_0_gt_rxheader_0),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_0),
.rx_block_lock(qsfp_0_rx_block_lock_0),
.rx_high_ber()
);
assign qsfp_0_tx_clk_1_int = clk_156mhz_int;
assign qsfp_0_tx_rst_1_int = rst_156mhz_int;
assign qsfp_0_rx_clk_1_int = gt_rxusrclk[5];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_1_reset_sync_inst (
.clk(qsfp_0_rx_clk_1_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_1_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_0_phy_1_inst (
.tx_clk(qsfp_0_tx_clk_1_int),
.tx_rst(qsfp_0_tx_rst_1_int),
.rx_clk(qsfp_0_rx_clk_1_int),
.rx_rst(qsfp_0_rx_rst_1_int),
.xgmii_txd(qsfp_0_txd_1_int),
.xgmii_txc(qsfp_0_txc_1_int),
.xgmii_rxd(qsfp_0_rxd_1_int),
.xgmii_rxc(qsfp_0_rxc_1_int),
.serdes_tx_data(qsfp_0_gt_txdata_1),
.serdes_tx_hdr(qsfp_0_gt_txheader_1),
.serdes_rx_data(qsfp_0_gt_rxdata_1),
.serdes_rx_hdr(qsfp_0_gt_rxheader_1),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_1),
.rx_block_lock(qsfp_0_rx_block_lock_1),
.rx_high_ber()
);
assign qsfp_0_tx_clk_2_int = clk_156mhz_int;
assign qsfp_0_tx_rst_2_int = rst_156mhz_int;
assign qsfp_0_rx_clk_2_int = gt_rxusrclk[6];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_2_reset_sync_inst (
.clk(qsfp_0_rx_clk_2_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_2_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_0_phy_2_inst (
.tx_clk(qsfp_0_tx_clk_2_int),
.tx_rst(qsfp_0_tx_rst_2_int),
.rx_clk(qsfp_0_rx_clk_2_int),
.rx_rst(qsfp_0_rx_rst_2_int),
.xgmii_txd(qsfp_0_txd_2_int),
.xgmii_txc(qsfp_0_txc_2_int),
.xgmii_rxd(qsfp_0_rxd_2_int),
.xgmii_rxc(qsfp_0_rxc_2_int),
.serdes_tx_data(qsfp_0_gt_txdata_2),
.serdes_tx_hdr(qsfp_0_gt_txheader_2),
.serdes_rx_data(qsfp_0_gt_rxdata_2),
.serdes_rx_hdr(qsfp_0_gt_rxheader_2),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_2),
.rx_block_lock(qsfp_0_rx_block_lock_2),
.rx_high_ber()
);
assign qsfp_0_tx_clk_3_int = clk_156mhz_int;
assign qsfp_0_tx_rst_3_int = rst_156mhz_int;
assign qsfp_0_rx_clk_3_int = gt_rxusrclk[7];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_3_reset_sync_inst (
.clk(qsfp_0_rx_clk_3_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_3_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_0_phy_3_inst (
.tx_clk(qsfp_0_tx_clk_3_int),
.tx_rst(qsfp_0_tx_rst_3_int),
.rx_clk(qsfp_0_rx_clk_3_int),
.rx_rst(qsfp_0_rx_rst_3_int),
.xgmii_txd(qsfp_0_txd_3_int),
.xgmii_txc(qsfp_0_txc_3_int),
.xgmii_rxd(qsfp_0_rxd_3_int),
.xgmii_rxc(qsfp_0_rxc_3_int),
.serdes_tx_data(qsfp_0_gt_txdata_3),
.serdes_tx_hdr(qsfp_0_gt_txheader_3),
.serdes_rx_data(qsfp_0_gt_rxdata_3),
.serdes_rx_hdr(qsfp_0_gt_rxheader_3),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_3),
.rx_block_lock(qsfp_0_rx_block_lock_3),
.rx_high_ber()
);
assign qsfp_1_tx_clk_0_int = clk_156mhz_int;
assign qsfp_1_tx_rst_0_int = rst_156mhz_int;
assign qsfp_1_rx_clk_0_int = gt_rxusrclk[0];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_0_reset_sync_inst (
.clk(qsfp_1_rx_clk_0_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_0_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_1_phy_0_inst (
.tx_clk(qsfp_1_tx_clk_0_int),
.tx_rst(qsfp_1_tx_rst_0_int),
.rx_clk(qsfp_1_rx_clk_0_int),
.rx_rst(qsfp_1_rx_rst_0_int),
.xgmii_txd(qsfp_1_txd_0_int),
.xgmii_txc(qsfp_1_txc_0_int),
.xgmii_rxd(qsfp_1_rxd_0_int),
.xgmii_rxc(qsfp_1_rxc_0_int),
.serdes_tx_data(qsfp_1_gt_txdata_0),
.serdes_tx_hdr(qsfp_1_gt_txheader_0),
.serdes_rx_data(qsfp_1_gt_rxdata_0),
.serdes_rx_hdr(qsfp_1_gt_rxheader_0),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_0),
.rx_block_lock(qsfp_1_rx_block_lock_0),
.rx_high_ber()
);
assign qsfp_1_tx_clk_1_int = clk_156mhz_int;
assign qsfp_1_tx_rst_1_int = rst_156mhz_int;
assign qsfp_1_rx_clk_1_int = gt_rxusrclk[1];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_1_reset_sync_inst (
.clk(qsfp_1_rx_clk_1_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_1_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_1_phy_1_inst (
.tx_clk(qsfp_1_tx_clk_1_int),
.tx_rst(qsfp_1_tx_rst_1_int),
.rx_clk(qsfp_1_rx_clk_1_int),
.rx_rst(qsfp_1_rx_rst_1_int),
.xgmii_txd(qsfp_1_txd_1_int),
.xgmii_txc(qsfp_1_txc_1_int),
.xgmii_rxd(qsfp_1_rxd_1_int),
.xgmii_rxc(qsfp_1_rxc_1_int),
.serdes_tx_data(qsfp_1_gt_txdata_1),
.serdes_tx_hdr(qsfp_1_gt_txheader_1),
.serdes_rx_data(qsfp_1_gt_rxdata_1),
.serdes_rx_hdr(qsfp_1_gt_rxheader_1),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_1),
.rx_block_lock(qsfp_1_rx_block_lock_1),
.rx_high_ber()
);
assign qsfp_1_tx_clk_2_int = clk_156mhz_int;
assign qsfp_1_tx_rst_2_int = rst_156mhz_int;
assign qsfp_1_rx_clk_2_int = gt_rxusrclk[2];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_2_reset_sync_inst (
.clk(qsfp_1_rx_clk_2_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_2_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_1_phy_2_inst (
.tx_clk(qsfp_1_tx_clk_2_int),
.tx_rst(qsfp_1_tx_rst_2_int),
.rx_clk(qsfp_1_rx_clk_2_int),
.rx_rst(qsfp_1_rx_rst_2_int),
.xgmii_txd(qsfp_1_txd_2_int),
.xgmii_txc(qsfp_1_txc_2_int),
.xgmii_rxd(qsfp_1_rxd_2_int),
.xgmii_rxc(qsfp_1_rxc_2_int),
.serdes_tx_data(qsfp_1_gt_txdata_2),
.serdes_tx_hdr(qsfp_1_gt_txheader_2),
.serdes_rx_data(qsfp_1_gt_rxdata_2),
.serdes_rx_hdr(qsfp_1_gt_rxheader_2),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_2),
.rx_block_lock(qsfp_1_rx_block_lock_2),
.rx_high_ber()
);
assign qsfp_1_tx_clk_3_int = clk_156mhz_int;
assign qsfp_1_tx_rst_3_int = rst_156mhz_int;
assign qsfp_1_rx_clk_3_int = gt_rxusrclk[3];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_3_reset_sync_inst (
.clk(qsfp_1_rx_clk_3_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_3_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
qsfp_1_phy_3_inst (
.tx_clk(qsfp_1_tx_clk_3_int),
.tx_rst(qsfp_1_tx_rst_3_int),
.rx_clk(qsfp_1_rx_clk_3_int),
.rx_rst(qsfp_1_rx_rst_3_int),
.xgmii_txd(qsfp_1_txd_3_int),
.xgmii_txc(qsfp_1_txc_3_int),
.xgmii_rxd(qsfp_1_rxd_3_int),
.xgmii_rxc(qsfp_1_rxc_3_int),
.serdes_tx_data(qsfp_1_gt_txdata_3),
.serdes_tx_hdr(qsfp_1_gt_txheader_3),
.serdes_rx_data(qsfp_1_gt_rxdata_3),
.serdes_rx_hdr(qsfp_1_gt_rxheader_3),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_3),
.rx_block_lock(qsfp_1_rx_block_lock_3),
.rx_high_ber()
);
//assign led = sw[0] ? {qsfp_1_rx_block_lock_4, qsfp_1_rx_block_lock_3, qsfp_1_rx_block_lock_2, qsfp_1_rx_block_lock_1, qsfp_0_rx_block_lock_4, qsfp_0_rx_block_lock_3, qsfp_0_rx_block_lock_2, qsfp_0_rx_block_lock_1} : led_int;
assign front_led = {1'b0, qsfp_0_rx_block_lock_0};
fpga_core
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.user_led_g(user_led_g),
.user_led_r(user_led_r),
//.front_led(front_led),
.user_sw(user_sw_int),
/*
* Ethernet: QSFP28
*/
.qsfp_0_tx_clk_0(qsfp_0_tx_clk_0_int),
.qsfp_0_tx_rst_0(qsfp_0_tx_rst_0_int),
.qsfp_0_txd_0(qsfp_0_txd_0_int),
.qsfp_0_txc_0(qsfp_0_txc_0_int),
.qsfp_0_rx_clk_0(qsfp_0_rx_clk_0_int),
.qsfp_0_rx_rst_0(qsfp_0_rx_rst_0_int),
.qsfp_0_rxd_0(qsfp_0_rxd_0_int),
.qsfp_0_rxc_0(qsfp_0_rxc_0_int),
.qsfp_0_tx_clk_1(qsfp_0_tx_clk_1_int),
.qsfp_0_tx_rst_1(qsfp_0_tx_rst_1_int),
.qsfp_0_txd_1(qsfp_0_txd_1_int),
.qsfp_0_txc_1(qsfp_0_txc_1_int),
.qsfp_0_rx_clk_1(qsfp_0_rx_clk_1_int),
.qsfp_0_rx_rst_1(qsfp_0_rx_rst_1_int),
.qsfp_0_rxd_1(qsfp_0_rxd_1_int),
.qsfp_0_rxc_1(qsfp_0_rxc_1_int),
.qsfp_0_tx_clk_2(qsfp_0_tx_clk_2_int),
.qsfp_0_tx_rst_2(qsfp_0_tx_rst_2_int),
.qsfp_0_txd_2(qsfp_0_txd_2_int),
.qsfp_0_txc_2(qsfp_0_txc_2_int),
.qsfp_0_rx_clk_2(qsfp_0_rx_clk_2_int),
.qsfp_0_rx_rst_2(qsfp_0_rx_rst_2_int),
.qsfp_0_rxd_2(qsfp_0_rxd_2_int),
.qsfp_0_rxc_2(qsfp_0_rxc_2_int),
.qsfp_0_tx_clk_3(qsfp_0_tx_clk_3_int),
.qsfp_0_tx_rst_3(qsfp_0_tx_rst_3_int),
.qsfp_0_txd_3(qsfp_0_txd_3_int),
.qsfp_0_txc_3(qsfp_0_txc_3_int),
.qsfp_0_rx_clk_3(qsfp_0_rx_clk_3_int),
.qsfp_0_rx_rst_3(qsfp_0_rx_rst_3_int),
.qsfp_0_rxd_3(qsfp_0_rxd_3_int),
.qsfp_0_rxc_3(qsfp_0_rxc_3_int),
.qsfp_1_tx_clk_0(qsfp_1_tx_clk_0_int),
.qsfp_1_tx_rst_0(qsfp_1_tx_rst_0_int),
.qsfp_1_txd_0(qsfp_1_txd_0_int),
.qsfp_1_txc_0(qsfp_1_txc_0_int),
.qsfp_1_rx_clk_0(qsfp_1_rx_clk_0_int),
.qsfp_1_rx_rst_0(qsfp_1_rx_rst_0_int),
.qsfp_1_rxd_0(qsfp_1_rxd_0_int),
.qsfp_1_rxc_0(qsfp_1_rxc_0_int),
.qsfp_1_tx_clk_1(qsfp_1_tx_clk_1_int),
.qsfp_1_tx_rst_1(qsfp_1_tx_rst_1_int),
.qsfp_1_txd_1(qsfp_1_txd_1_int),
.qsfp_1_txc_1(qsfp_1_txc_1_int),
.qsfp_1_rx_clk_1(qsfp_1_rx_clk_1_int),
.qsfp_1_rx_rst_1(qsfp_1_rx_rst_1_int),
.qsfp_1_rxd_1(qsfp_1_rxd_1_int),
.qsfp_1_rxc_1(qsfp_1_rxc_1_int),
.qsfp_1_tx_clk_2(qsfp_1_tx_clk_2_int),
.qsfp_1_tx_rst_2(qsfp_1_tx_rst_2_int),
.qsfp_1_txd_2(qsfp_1_txd_2_int),
.qsfp_1_txc_2(qsfp_1_txc_2_int),
.qsfp_1_rx_clk_2(qsfp_1_rx_clk_2_int),
.qsfp_1_rx_rst_2(qsfp_1_rx_rst_2_int),
.qsfp_1_rxd_2(qsfp_1_rxd_2_int),
.qsfp_1_rxc_2(qsfp_1_rxc_2_int),
.qsfp_1_tx_clk_3(qsfp_1_tx_clk_3_int),
.qsfp_1_tx_rst_3(qsfp_1_tx_rst_3_int),
.qsfp_1_txd_3(qsfp_1_txd_3_int),
.qsfp_1_txc_3(qsfp_1_txc_3_int),
.qsfp_1_rx_clk_3(qsfp_1_rx_clk_3_int),
.qsfp_1_rx_rst_3(qsfp_1_rx_rst_3_int),
.qsfp_1_rxd_3(qsfp_1_rxd_3_int),
.qsfp_1_rxc_3(qsfp_1_rxc_3_int)
);
endmodule

View File

@ -0,0 +1,659 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA core logic
*/
module fpga_core #
(
parameter TARGET = "XILINX"
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
output wire [1:0] user_led_g,
output wire user_led_r,
output wire [1:0] front_led,
input wire [1:0] user_sw,
/*
* Ethernet: QSFP28
*/
input wire qsfp_0_tx_clk_0,
input wire qsfp_0_tx_rst_0,
output wire [63:0] qsfp_0_txd_0,
output wire [7:0] qsfp_0_txc_0,
input wire qsfp_0_rx_clk_0,
input wire qsfp_0_rx_rst_0,
input wire [63:0] qsfp_0_rxd_0,
input wire [7:0] qsfp_0_rxc_0,
input wire qsfp_0_tx_clk_1,
input wire qsfp_0_tx_rst_1,
output wire [63:0] qsfp_0_txd_1,
output wire [7:0] qsfp_0_txc_1,
input wire qsfp_0_rx_clk_1,
input wire qsfp_0_rx_rst_1,
input wire [63:0] qsfp_0_rxd_1,
input wire [7:0] qsfp_0_rxc_1,
input wire qsfp_0_tx_clk_2,
input wire qsfp_0_tx_rst_2,
output wire [63:0] qsfp_0_txd_2,
output wire [7:0] qsfp_0_txc_2,
input wire qsfp_0_rx_clk_2,
input wire qsfp_0_rx_rst_2,
input wire [63:0] qsfp_0_rxd_2,
input wire [7:0] qsfp_0_rxc_2,
input wire qsfp_0_tx_clk_3,
input wire qsfp_0_tx_rst_3,
output wire [63:0] qsfp_0_txd_3,
output wire [7:0] qsfp_0_txc_3,
input wire qsfp_0_rx_clk_3,
input wire qsfp_0_rx_rst_3,
input wire [63:0] qsfp_0_rxd_3,
input wire [7:0] qsfp_0_rxc_3,
input wire qsfp_1_tx_clk_0,
input wire qsfp_1_tx_rst_0,
output wire [63:0] qsfp_1_txd_0,
output wire [7:0] qsfp_1_txc_0,
input wire qsfp_1_rx_clk_0,
input wire qsfp_1_rx_rst_0,
input wire [63:0] qsfp_1_rxd_0,
input wire [7:0] qsfp_1_rxc_0,
input wire qsfp_1_tx_clk_1,
input wire qsfp_1_tx_rst_1,
output wire [63:0] qsfp_1_txd_1,
output wire [7:0] qsfp_1_txc_1,
input wire qsfp_1_rx_clk_1,
input wire qsfp_1_rx_rst_1,
input wire [63:0] qsfp_1_rxd_1,
input wire [7:0] qsfp_1_rxc_1,
input wire qsfp_1_tx_clk_2,
input wire qsfp_1_tx_rst_2,
output wire [63:0] qsfp_1_txd_2,
output wire [7:0] qsfp_1_txc_2,
input wire qsfp_1_rx_clk_2,
input wire qsfp_1_rx_rst_2,
input wire [63:0] qsfp_1_rxd_2,
input wire [7:0] qsfp_1_rxc_2,
input wire qsfp_1_tx_clk_3,
input wire qsfp_1_tx_rst_3,
output wire [63:0] qsfp_1_txd_3,
output wire [7:0] qsfp_1_txc_3,
input wire qsfp_1_rx_clk_3,
input wire qsfp_1_rx_rst_3,
input wire [63:0] qsfp_1_rxd_3,
input wire [7:0] qsfp_1_rxc_3
);
// AXI between MAC and Ethernet modules
wire [63:0] rx_axis_tdata;
wire [7:0] rx_axis_tkeep;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [63:0] tx_axis_tdata;
wire [7:0] tx_axis_tkeep;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [63:0] rx_eth_payload_axis_tdata;
wire [7:0] rx_eth_payload_axis_tkeep;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [63:0] tx_eth_payload_axis_tdata;
wire [7:0] tx_eth_payload_axis_tkeep;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [63:0] rx_ip_payload_axis_tdata;
wire [7:0] rx_ip_payload_axis_tkeep;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [63:0] tx_ip_payload_axis_tdata;
wire [7:0] tx_ip_payload_axis_tkeep;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [63:0] rx_udp_payload_axis_tdata;
wire [7:0] rx_udp_payload_axis_tkeep;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [63:0] tx_udp_payload_axis_tdata;
wire [7:0] tx_udp_payload_axis_tkeep;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [63:0] rx_fifo_udp_payload_axis_tdata;
wire [7:0] rx_fifo_udp_payload_axis_tkeep;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [63:0] tx_fifo_udp_payload_axis_tdata;
wire [7:0] tx_fifo_udp_payload_axis_tkeep;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tkeep = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tkeep = tx_fifo_udp_payload_axis_tkeep;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tkeep = rx_udp_payload_axis_tkeep;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
valid_last <= tx_udp_payload_axis_tvalid;
if (tx_udp_payload_axis_tvalid && !valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
end
end
end
assign user_led_g = ~led_reg[1:0];
assign user_led_r = 1'b1;
assign front_led = 2'b00;
assign phy_reset_n = !rst;
assign qsfp_0_txd_1 = 64'h0707070707070707;
assign qsfp_0_txc_1 = 8'hff;
assign qsfp_0_txd_2 = 64'h0707070707070707;
assign qsfp_0_txc_2 = 8'hff;
assign qsfp_0_txd_3 = 64'h0707070707070707;
assign qsfp_0_txc_3 = 8'hff;
assign qsfp_1_txd_0 = 64'h0707070707070707;
assign qsfp_1_txc_0 = 8'hff;
assign qsfp_1_txd_1 = 64'h0707070707070707;
assign qsfp_1_txc_1 = 8'hff;
assign qsfp_1_txd_2 = 64'h0707070707070707;
assign qsfp_1_txc_2 = 8'hff;
assign qsfp_1_txd_3 = 64'h0707070707070707;
assign qsfp_1_txc_3 = 8'hff;
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
.ENABLE_DIC(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_ADDR_WIDTH(9),
.TX_FRAME_FIFO(1),
.RX_FIFO_ADDR_WIDTH(9),
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(qsfp_0_rx_clk_0),
.rx_rst(qsfp_0_rx_rst_0),
.tx_clk(qsfp_0_tx_clk_0),
.tx_rst(qsfp_0_tx_rst_0),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tkeep(tx_axis_tkeep),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tkeep(rx_axis_tkeep),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(qsfp_0_rxd_0),
.xgmii_rxc(qsfp_0_rxc_0),
.xgmii_txd(qsfp_0_txd_0),
.xgmii_txc(qsfp_0_txc_0),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),
.tx_fifo_good_frame(),
.rx_error_bad_frame(),
.rx_error_bad_fcs(),
.rx_fifo_overflow(),
.rx_fifo_bad_frame(),
.rx_fifo_good_frame(),
.ifg_delay(8'd12)
);
eth_axis_rx_64
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tkeep(rx_axis_tkeep),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx_64
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tkeep(tx_axis_tkeep),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete_64
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tkeep(tx_ip_payload_axis_tkeep),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tkeep(rx_ip_payload_axis_tkeep),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tkeep(tx_udp_payload_axis_tkeep),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tkeep(rx_udp_payload_axis_tkeep),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(1'b0)
);
axis_fifo #(
.ADDR_WIDTH(10),
.DATA_WIDTH(64),
.KEEP_ENABLE(1),
.KEEP_WIDTH(8),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(rx_fifo_udp_payload_axis_tkeep),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule

View File

@ -0,0 +1,52 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an 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-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule

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/ip_ep.py

View File

@ -0,0 +1,462 @@
#!/usr/bin/env python
"""
Copyright (c) 2016-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import eth_ep
import arp_ep
import udp_ep
import xgmii_ep
module = 'fpga_core'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v")
srcs.append("../lib/eth/rtl/eth_mac_10g.v")
srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v")
srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v")
srcs.append("../lib/eth/rtl/lfsr.v")
srcs.append("../lib/eth/rtl/eth_axis_rx_64.v")
srcs.append("../lib/eth/rtl/eth_axis_tx_64.v")
srcs.append("../lib/eth/rtl/udp_complete_64.v")
srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v")
srcs.append("../lib/eth/rtl/udp_64.v")
srcs.append("../lib/eth/rtl/udp_ip_rx_64.v")
srcs.append("../lib/eth/rtl/udp_ip_tx_64.v")
srcs.append("../lib/eth/rtl/ip_complete_64.v")
srcs.append("../lib/eth/rtl/ip_64.v")
srcs.append("../lib/eth/rtl/ip_eth_rx_64.v")
srcs.append("../lib/eth/rtl/ip_eth_tx_64.v")
srcs.append("../lib/eth/rtl/ip_arb_mux.v")
srcs.append("../lib/eth/rtl/arp_64.v")
srcs.append("../lib/eth/rtl/arp_cache.v")
srcs.append("../lib/eth/rtl/arp_eth_rx_64.v")
srcs.append("../lib/eth/rtl/arp_eth_tx_64.v")
srcs.append("../lib/eth/rtl/eth_arb_mux.v")
srcs.append("../lib/eth/lib/axis/rtl/arbiter.v")
srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
user_sw = Signal(intbv(0)[2:])
qsfp_0_tx_clk_0 = Signal(bool(0))
qsfp_0_tx_rst_0 = Signal(bool(0))
qsfp_0_rx_clk_0 = Signal(bool(0))
qsfp_0_rx_rst_0 = Signal(bool(0))
qsfp_0_rxd_0 = Signal(intbv(0)[64:])
qsfp_0_rxc_0 = Signal(intbv(0)[8:])
qsfp_0_tx_clk_1 = Signal(bool(0))
qsfp_0_tx_rst_1 = Signal(bool(0))
qsfp_0_rx_clk_1 = Signal(bool(0))
qsfp_0_rx_rst_1 = Signal(bool(0))
qsfp_0_rxd_1 = Signal(intbv(0)[64:])
qsfp_0_rxc_1 = Signal(intbv(0)[8:])
qsfp_0_tx_clk_2 = Signal(bool(0))
qsfp_0_tx_rst_2 = Signal(bool(0))
qsfp_0_rx_clk_2 = Signal(bool(0))
qsfp_0_rx_rst_2 = Signal(bool(0))
qsfp_0_rxd_2 = Signal(intbv(0)[64:])
qsfp_0_rxc_2 = Signal(intbv(0)[8:])
qsfp_0_tx_clk_3 = Signal(bool(0))
qsfp_0_tx_rst_3 = Signal(bool(0))
qsfp_0_rx_clk_3 = Signal(bool(0))
qsfp_0_rx_rst_3 = Signal(bool(0))
qsfp_0_rxd_3 = Signal(intbv(0)[64:])
qsfp_0_rxc_3 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_0 = Signal(bool(0))
qsfp_1_tx_rst_0 = Signal(bool(0))
qsfp_1_rx_clk_0 = Signal(bool(0))
qsfp_1_rx_rst_0 = Signal(bool(0))
qsfp_1_rxd_0 = Signal(intbv(0)[64:])
qsfp_1_rxc_0 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_1 = Signal(bool(0))
qsfp_1_tx_rst_1 = Signal(bool(0))
qsfp_1_rx_clk_1 = Signal(bool(0))
qsfp_1_rx_rst_1 = Signal(bool(0))
qsfp_1_rxd_1 = Signal(intbv(0)[64:])
qsfp_1_rxc_1 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_2 = Signal(bool(0))
qsfp_1_tx_rst_2 = Signal(bool(0))
qsfp_1_rx_clk_2 = Signal(bool(0))
qsfp_1_rx_rst_2 = Signal(bool(0))
qsfp_1_rxd_2 = Signal(intbv(0)[64:])
qsfp_1_rxc_2 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_3 = Signal(bool(0))
qsfp_1_tx_rst_3 = Signal(bool(0))
qsfp_1_rx_clk_3 = Signal(bool(0))
qsfp_1_rx_rst_3 = Signal(bool(0))
qsfp_1_rxd_3 = Signal(intbv(0)[64:])
qsfp_1_rxc_3 = Signal(intbv(0)[8:])
# Outputs
user_led_g = Signal(intbv(0)[2:])
user_led_r = Signal(bool(0))
front_led = Signal(intbv(0)[2:])
qsfp_0_txd_0 = Signal(intbv(0)[64:])
qsfp_0_txc_0 = Signal(intbv(0)[8:])
qsfp_0_txd_1 = Signal(intbv(0)[64:])
qsfp_0_txc_1 = Signal(intbv(0)[8:])
qsfp_0_txd_2 = Signal(intbv(0)[64:])
qsfp_0_txc_2 = Signal(intbv(0)[8:])
qsfp_0_txd_3 = Signal(intbv(0)[64:])
qsfp_0_txc_3 = Signal(intbv(0)[8:])
qsfp_1_txd_0 = Signal(intbv(0)[64:])
qsfp_1_txc_0 = Signal(intbv(0)[8:])
qsfp_1_txd_1 = Signal(intbv(0)[64:])
qsfp_1_txc_1 = Signal(intbv(0)[8:])
qsfp_1_txd_2 = Signal(intbv(0)[64:])
qsfp_1_txc_2 = Signal(intbv(0)[8:])
qsfp_1_txd_3 = Signal(intbv(0)[64:])
qsfp_1_txc_3 = Signal(intbv(0)[8:])
# sources and sinks
qsfp_0_0_source = xgmii_ep.XGMIISource()
qsfp_0_0_source_logic = qsfp_0_0_source.create_logic(qsfp_0_rx_clk_0, qsfp_0_rx_rst_0, txd=qsfp_0_rxd_0, txc=qsfp_0_rxc_0, name='qsfp_0_0_source')
qsfp_0_0_sink = xgmii_ep.XGMIISink()
qsfp_0_0_sink_logic = qsfp_0_0_sink.create_logic(qsfp_0_tx_clk_0, qsfp_0_tx_rst_0, rxd=qsfp_0_txd_0, rxc=qsfp_0_txc_0, name='qsfp_0_0_sink')
qsfp_0_1_source = xgmii_ep.XGMIISource()
qsfp_0_1_source_logic = qsfp_0_1_source.create_logic(qsfp_0_rx_clk_1, qsfp_0_rx_rst_1, txd=qsfp_0_rxd_1, txc=qsfp_0_rxc_1, name='qsfp_0_1_source')
qsfp_0_1_sink = xgmii_ep.XGMIISink()
qsfp_0_1_sink_logic = qsfp_0_1_sink.create_logic(qsfp_0_tx_clk_1, qsfp_0_tx_rst_1, rxd=qsfp_0_txd_1, rxc=qsfp_0_txc_1, name='qsfp_0_1_sink')
qsfp_0_2_source = xgmii_ep.XGMIISource()
qsfp_0_2_source_logic = qsfp_0_2_source.create_logic(qsfp_0_rx_clk_2, qsfp_0_rx_rst_2, txd=qsfp_0_rxd_2, txc=qsfp_0_rxc_2, name='qsfp_0_2_source')
qsfp_0_2_sink = xgmii_ep.XGMIISink()
qsfp_0_2_sink_logic = qsfp_0_2_sink.create_logic(qsfp_0_tx_clk_2, qsfp_0_tx_rst_2, rxd=qsfp_0_txd_2, rxc=qsfp_0_txc_2, name='qsfp_0_2_sink')
qsfp_0_3_source = xgmii_ep.XGMIISource()
qsfp_0_3_source_logic = qsfp_0_3_source.create_logic(qsfp_0_rx_clk_3, qsfp_0_rx_rst_3, txd=qsfp_0_rxd_3, txc=qsfp_0_rxc_3, name='qsfp_0_3_source')
qsfp_0_3_sink = xgmii_ep.XGMIISink()
qsfp_0_3_sink_logic = qsfp_0_3_sink.create_logic(qsfp_0_tx_clk_3, qsfp_0_tx_rst_3, rxd=qsfp_0_txd_3, rxc=qsfp_0_txc_3, name='qsfp_0_3_sink')
qsfp_1_0_source = xgmii_ep.XGMIISource()
qsfp_1_0_source_logic = qsfp_1_0_source.create_logic(qsfp_1_rx_clk_0, qsfp_1_rx_rst_0, txd=qsfp_1_rxd_0, txc=qsfp_1_rxc_0, name='qsfp_1_0_source')
qsfp_1_0_sink = xgmii_ep.XGMIISink()
qsfp_1_0_sink_logic = qsfp_1_0_sink.create_logic(qsfp_1_tx_clk_0, qsfp_1_tx_rst_0, rxd=qsfp_1_txd_0, rxc=qsfp_1_txc_0, name='qsfp_1_0_sink')
qsfp_1_1_source = xgmii_ep.XGMIISource()
qsfp_1_1_source_logic = qsfp_1_1_source.create_logic(qsfp_1_rx_clk_1, qsfp_1_rx_rst_1, txd=qsfp_1_rxd_1, txc=qsfp_1_rxc_1, name='qsfp_1_1_source')
qsfp_1_1_sink = xgmii_ep.XGMIISink()
qsfp_1_1_sink_logic = qsfp_1_1_sink.create_logic(qsfp_1_tx_clk_1, qsfp_1_tx_rst_1, rxd=qsfp_1_txd_1, rxc=qsfp_1_txc_1, name='qsfp_1_1_sink')
qsfp_1_2_source = xgmii_ep.XGMIISource()
qsfp_1_2_source_logic = qsfp_1_2_source.create_logic(qsfp_1_rx_clk_2, qsfp_1_rx_rst_2, txd=qsfp_1_rxd_2, txc=qsfp_1_rxc_2, name='qsfp_1_2_source')
qsfp_1_2_sink = xgmii_ep.XGMIISink()
qsfp_1_2_sink_logic = qsfp_1_2_sink.create_logic(qsfp_1_tx_clk_2, qsfp_1_tx_rst_2, rxd=qsfp_1_txd_2, rxc=qsfp_1_txc_2, name='qsfp_1_2_sink')
qsfp_1_3_source = xgmii_ep.XGMIISource()
qsfp_1_3_source_logic = qsfp_1_3_source.create_logic(qsfp_1_rx_clk_3, qsfp_1_rx_rst_3, txd=qsfp_1_rxd_3, txc=qsfp_1_rxc_3, name='qsfp_1_3_source')
qsfp_1_3_sink = xgmii_ep.XGMIISink()
qsfp_1_3_sink_logic = qsfp_1_3_sink.create_logic(qsfp_1_tx_clk_3, qsfp_1_tx_rst_3, rxd=qsfp_1_txd_3, rxc=qsfp_1_txc_3, name='qsfp_1_3_sink')
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
user_led_g=user_led_g,
user_led_r=user_led_r,
front_led=front_led,
user_sw=user_sw,
qsfp_0_tx_clk_0=qsfp_0_tx_clk_0,
qsfp_0_tx_rst_0=qsfp_0_tx_rst_0,
qsfp_0_txd_0=qsfp_0_txd_0,
qsfp_0_txc_0=qsfp_0_txc_0,
qsfp_0_rx_clk_0=qsfp_0_rx_clk_0,
qsfp_0_rx_rst_0=qsfp_0_rx_rst_0,
qsfp_0_rxd_0=qsfp_0_rxd_0,
qsfp_0_rxc_0=qsfp_0_rxc_0,
qsfp_0_tx_clk_1=qsfp_0_tx_clk_1,
qsfp_0_tx_rst_1=qsfp_0_tx_rst_1,
qsfp_0_txd_1=qsfp_0_txd_1,
qsfp_0_txc_1=qsfp_0_txc_1,
qsfp_0_rx_clk_1=qsfp_0_rx_clk_1,
qsfp_0_rx_rst_1=qsfp_0_rx_rst_1,
qsfp_0_rxd_1=qsfp_0_rxd_1,
qsfp_0_rxc_1=qsfp_0_rxc_1,
qsfp_0_tx_clk_2=qsfp_0_tx_clk_2,
qsfp_0_tx_rst_2=qsfp_0_tx_rst_2,
qsfp_0_txd_2=qsfp_0_txd_2,
qsfp_0_txc_2=qsfp_0_txc_2,
qsfp_0_rx_clk_2=qsfp_0_rx_clk_2,
qsfp_0_rx_rst_2=qsfp_0_rx_rst_2,
qsfp_0_rxd_2=qsfp_0_rxd_2,
qsfp_0_rxc_2=qsfp_0_rxc_2,
qsfp_0_tx_clk_3=qsfp_0_tx_clk_3,
qsfp_0_tx_rst_3=qsfp_0_tx_rst_3,
qsfp_0_txd_3=qsfp_0_txd_3,
qsfp_0_txc_3=qsfp_0_txc_3,
qsfp_0_rx_clk_3=qsfp_0_rx_clk_3,
qsfp_0_rx_rst_3=qsfp_0_rx_rst_3,
qsfp_0_rxd_3=qsfp_0_rxd_3,
qsfp_0_rxc_3=qsfp_0_rxc_3,
qsfp_1_tx_clk_0=qsfp_1_tx_clk_0,
qsfp_1_tx_rst_0=qsfp_1_tx_rst_0,
qsfp_1_txd_0=qsfp_1_txd_0,
qsfp_1_txc_0=qsfp_1_txc_0,
qsfp_1_rx_clk_0=qsfp_1_rx_clk_0,
qsfp_1_rx_rst_0=qsfp_1_rx_rst_0,
qsfp_1_rxd_0=qsfp_1_rxd_0,
qsfp_1_rxc_0=qsfp_1_rxc_0,
qsfp_1_tx_clk_1=qsfp_1_tx_clk_1,
qsfp_1_tx_rst_1=qsfp_1_tx_rst_1,
qsfp_1_txd_1=qsfp_1_txd_1,
qsfp_1_txc_1=qsfp_1_txc_1,
qsfp_1_rx_clk_1=qsfp_1_rx_clk_1,
qsfp_1_rx_rst_1=qsfp_1_rx_rst_1,
qsfp_1_rxd_1=qsfp_1_rxd_1,
qsfp_1_rxc_1=qsfp_1_rxc_1,
qsfp_1_tx_clk_2=qsfp_1_tx_clk_2,
qsfp_1_tx_rst_2=qsfp_1_tx_rst_2,
qsfp_1_txd_2=qsfp_1_txd_2,
qsfp_1_txc_2=qsfp_1_txc_2,
qsfp_1_rx_clk_2=qsfp_1_rx_clk_2,
qsfp_1_rx_rst_2=qsfp_1_rx_rst_2,
qsfp_1_rxd_2=qsfp_1_rxd_2,
qsfp_1_rxc_2=qsfp_1_rxc_2,
qsfp_1_tx_clk_3=qsfp_1_tx_clk_3,
qsfp_1_tx_rst_3=qsfp_1_tx_rst_3,
qsfp_1_txd_3=qsfp_1_txd_3,
qsfp_1_txc_3=qsfp_1_txc_3,
qsfp_1_rx_clk_3=qsfp_1_rx_clk_3,
qsfp_1_rx_rst_3=qsfp_1_rx_rst_3,
qsfp_1_rxd_3=qsfp_1_rxd_3,
qsfp_1_rxc_3=qsfp_1_rxc_3
)
@always(delay(4))
def clkgen():
clk.next = not clk
qsfp_0_tx_clk_0.next = not qsfp_0_tx_clk_0
qsfp_0_rx_clk_0.next = not qsfp_0_rx_clk_0
qsfp_0_tx_clk_1.next = not qsfp_0_tx_clk_1
qsfp_0_rx_clk_1.next = not qsfp_0_rx_clk_1
qsfp_0_tx_clk_2.next = not qsfp_0_tx_clk_2
qsfp_0_rx_clk_2.next = not qsfp_0_rx_clk_2
qsfp_0_tx_clk_3.next = not qsfp_0_tx_clk_3
qsfp_0_rx_clk_3.next = not qsfp_0_rx_clk_3
qsfp_1_tx_clk_0.next = not qsfp_1_tx_clk_0
qsfp_1_rx_clk_0.next = not qsfp_1_rx_clk_0
qsfp_1_tx_clk_1.next = not qsfp_1_tx_clk_1
qsfp_1_rx_clk_1.next = not qsfp_1_rx_clk_1
qsfp_1_tx_clk_2.next = not qsfp_1_tx_clk_2
qsfp_1_rx_clk_2.next = not qsfp_1_rx_clk_2
qsfp_1_tx_clk_3.next = not qsfp_1_tx_clk_3
qsfp_1_rx_clk_3.next = not qsfp_1_rx_clk_3
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
qsfp_0_tx_rst_1.next = 1
qsfp_0_rx_rst_1.next = 1
qsfp_0_tx_rst_2.next = 1
qsfp_0_rx_rst_2.next = 1
qsfp_0_tx_rst_3.next = 1
qsfp_0_rx_rst_3.next = 1
qsfp_0_tx_rst_0.next = 1
qsfp_0_rx_rst_0.next = 1
qsfp_1_tx_rst_1.next = 1
qsfp_1_rx_rst_1.next = 1
qsfp_1_tx_rst_2.next = 1
qsfp_1_rx_rst_2.next = 1
qsfp_1_tx_rst_3.next = 1
qsfp_1_rx_rst_3.next = 1
qsfp_1_tx_rst_0.next = 1
qsfp_1_rx_rst_0.next = 1
yield clk.posedge
rst.next = 0
qsfp_0_tx_rst_1.next = 0
qsfp_0_rx_rst_1.next = 0
qsfp_0_tx_rst_2.next = 0
qsfp_0_rx_rst_2.next = 0
qsfp_0_tx_rst_3.next = 0
qsfp_0_rx_rst_3.next = 0
qsfp_0_tx_rst_0.next = 0
qsfp_0_rx_rst_0.next = 0
qsfp_1_tx_rst_1.next = 0
qsfp_1_rx_rst_1.next = 0
qsfp_1_tx_rst_2.next = 0
qsfp_1_rx_rst_2.next = 0
qsfp_1_tx_rst_3.next = 0
qsfp_1_rx_rst_3.next = 0
qsfp_1_tx_rst_0.next = 0
qsfp_1_rx_rst_0.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test UDP RX packet")
current_test.next = 1
test_frame = udp_ep.UDPFrame()
test_frame.eth_dest_mac = 0x020000000000
test_frame.eth_src_mac = 0xDAD1D2D3D4D5
test_frame.eth_type = 0x0800
test_frame.ip_version = 4
test_frame.ip_ihl = 5
test_frame.ip_dscp = 0
test_frame.ip_ecn = 0
test_frame.ip_length = None
test_frame.ip_identification = 0
test_frame.ip_flags = 2
test_frame.ip_fragment_offset = 0
test_frame.ip_ttl = 64
test_frame.ip_protocol = 0x11
test_frame.ip_header_checksum = None
test_frame.ip_source_ip = 0xc0a80181
test_frame.ip_dest_ip = 0xc0a80180
test_frame.udp_source_port = 5678
test_frame.udp_dest_port = 1234
test_frame.payload = bytearray(range(32))
test_frame.build()
qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data)
# wait for ARP request packet
while qsfp_0_0_sink.empty():
yield clk.posedge
rx_frame = qsfp_0_0_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0806
assert check_frame.arp_htype == 0x0001
assert check_frame.arp_ptype == 0x0800
assert check_frame.arp_hlen == 6
assert check_frame.arp_plen == 4
assert check_frame.arp_oper == 1
assert check_frame.arp_sha == 0x020000000000
assert check_frame.arp_spa == 0xc0a80180
assert check_frame.arp_tha == 0x000000000000
assert check_frame.arp_tpa == 0xc0a80181
# generate response
arp_frame = arp_ep.ARPFrame()
arp_frame.eth_dest_mac = 0x020000000000
arp_frame.eth_src_mac = 0xDAD1D2D3D4D5
arp_frame.eth_type = 0x0806
arp_frame.arp_htype = 0x0001
arp_frame.arp_ptype = 0x0800
arp_frame.arp_hlen = 6
arp_frame.arp_plen = 4
arp_frame.arp_oper = 2
arp_frame.arp_sha = 0xDAD1D2D3D4D5
arp_frame.arp_spa = 0xc0a80181
arp_frame.arp_tha = 0x020000000000
arp_frame.arp_tpa = 0xc0a80180
qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data)
while qsfp_0_0_sink.empty():
yield clk.posedge
rx_frame = qsfp_0_0_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = udp_ep.UDPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0800
assert check_frame.ip_version == 4
assert check_frame.ip_ihl == 5
assert check_frame.ip_dscp == 0
assert check_frame.ip_ecn == 0
assert check_frame.ip_identification == 0
assert check_frame.ip_flags == 2
assert check_frame.ip_fragment_offset == 0
assert check_frame.ip_ttl == 64
assert check_frame.ip_protocol == 0x11
assert check_frame.ip_source_ip == 0xc0a80180
assert check_frame.ip_dest_ip == 0xc0a80181
assert check_frame.udp_source_port == 1234
assert check_frame.udp_dest_port == 5678
assert check_frame.payload.data == bytearray(range(32))
assert qsfp_0_0_source.empty()
assert qsfp_0_0_sink.empty()
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,269 @@
/*
Copyright (c) 2016-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for fpga_core
*/
module test_fpga_core;
// Parameters
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [1:0] user_sw = 0;
reg qsfp_0_tx_clk_0 = 0;
reg qsfp_0_tx_rst_0 = 0;
reg qsfp_0_rx_clk_0 = 0;
reg qsfp_0_rx_rst_0 = 0;
reg [63:0] qsfp_0_rxd_0 = 0;
reg [7:0] qsfp_0_rxc_0 = 0;
reg qsfp_0_tx_clk_1 = 0;
reg qsfp_0_tx_rst_1 = 0;
reg qsfp_0_rx_clk_1 = 0;
reg qsfp_0_rx_rst_1 = 0;
reg [63:0] qsfp_0_rxd_1 = 0;
reg [7:0] qsfp_0_rxc_1 = 0;
reg qsfp_0_tx_clk_2 = 0;
reg qsfp_0_tx_rst_2 = 0;
reg qsfp_0_rx_clk_2 = 0;
reg qsfp_0_rx_rst_2 = 0;
reg [63:0] qsfp_0_rxd_2 = 0;
reg [7:0] qsfp_0_rxc_2 = 0;
reg qsfp_0_tx_clk_3 = 0;
reg qsfp_0_tx_rst_3 = 0;
reg qsfp_0_rx_clk_3 = 0;
reg qsfp_0_rx_rst_3 = 0;
reg [63:0] qsfp_0_rxd_3 = 0;
reg [7:0] qsfp_0_rxc_3 = 0;
reg qsfp_1_tx_clk_0 = 0;
reg qsfp_1_tx_rst_0 = 0;
reg qsfp_1_rx_clk_0 = 0;
reg qsfp_1_rx_rst_0 = 0;
reg [63:0] qsfp_1_rxd_0 = 0;
reg [7:0] qsfp_1_rxc_0 = 0;
reg qsfp_1_tx_clk_1 = 0;
reg qsfp_1_tx_rst_1 = 0;
reg qsfp_1_rx_clk_1 = 0;
reg qsfp_1_rx_rst_1 = 0;
reg [63:0] qsfp_1_rxd_1 = 0;
reg [7:0] qsfp_1_rxc_1 = 0;
reg qsfp_1_tx_clk_2 = 0;
reg qsfp_1_tx_rst_2 = 0;
reg qsfp_1_rx_clk_2 = 0;
reg qsfp_1_rx_rst_2 = 0;
reg [63:0] qsfp_1_rxd_2 = 0;
reg [7:0] qsfp_1_rxc_2 = 0;
reg qsfp_1_tx_clk_3 = 0;
reg qsfp_1_tx_rst_3 = 0;
reg qsfp_1_rx_clk_3 = 0;
reg qsfp_1_rx_rst_3 = 0;
reg [63:0] qsfp_1_rxd_3 = 0;
reg [7:0] qsfp_1_rxc_3 = 0;
// Outputs
wire [1:0] user_led_g;
wire user_led_r;
wire [1:0] front_led;
wire [63:0] qsfp_0_txd_0;
wire [7:0] qsfp_0_txc_0;
wire [63:0] qsfp_0_txd_1;
wire [7:0] qsfp_0_txc_1;
wire [63:0] qsfp_0_txd_2;
wire [7:0] qsfp_0_txc_2;
wire [63:0] qsfp_0_txd_3;
wire [7:0] qsfp_0_txc_3;
wire [63:0] qsfp_1_txd_0;
wire [7:0] qsfp_1_txc_0;
wire [63:0] qsfp_1_txd_1;
wire [7:0] qsfp_1_txc_1;
wire [63:0] qsfp_1_txd_2;
wire [7:0] qsfp_1_txc_2;
wire [63:0] qsfp_1_txd_3;
wire [7:0] qsfp_1_txc_3;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
user_sw,
qsfp_0_tx_clk_0,
qsfp_0_tx_rst_0,
qsfp_0_rx_clk_0,
qsfp_0_rx_rst_0,
qsfp_0_rxd_0,
qsfp_0_rxc_0,
qsfp_0_tx_clk_1,
qsfp_0_tx_rst_1,
qsfp_0_rx_clk_1,
qsfp_0_rx_rst_1,
qsfp_0_rxd_1,
qsfp_0_rxc_1,
qsfp_0_tx_clk_2,
qsfp_0_tx_rst_2,
qsfp_0_rx_clk_2,
qsfp_0_rx_rst_2,
qsfp_0_rxd_2,
qsfp_0_rxc_2,
qsfp_0_tx_clk_3,
qsfp_0_tx_rst_3,
qsfp_0_rx_clk_3,
qsfp_0_rx_rst_3,
qsfp_0_rxd_3,
qsfp_0_rxc_3,
qsfp_1_tx_clk_0,
qsfp_1_tx_rst_0,
qsfp_1_rx_clk_0,
qsfp_1_rx_rst_0,
qsfp_1_rxd_0,
qsfp_1_rxc_0,
qsfp_1_tx_clk_1,
qsfp_1_tx_rst_1,
qsfp_1_rx_clk_1,
qsfp_1_rx_rst_1,
qsfp_1_rxd_1,
qsfp_1_rxc_1,
qsfp_1_tx_clk_2,
qsfp_1_tx_rst_2,
qsfp_1_rx_clk_2,
qsfp_1_rx_rst_2,
qsfp_1_rxd_2,
qsfp_1_rxc_2,
qsfp_1_tx_clk_3,
qsfp_1_tx_rst_3,
qsfp_1_rx_clk_3,
qsfp_1_rx_rst_3,
qsfp_1_rxd_3,
qsfp_1_rxc_3
);
$to_myhdl(
user_led_g,
user_led_r,
front_led,
qsfp_0_txd_0,
qsfp_0_txc_0,
qsfp_0_txd_1,
qsfp_0_txc_1,
qsfp_0_txd_2,
qsfp_0_txc_2,
qsfp_0_txd_3,
qsfp_0_txc_3,
qsfp_1_txd_0,
qsfp_1_txc_0,
qsfp_1_txd_1,
qsfp_1_txc_1,
qsfp_1_txd_2,
qsfp_1_txc_2,
qsfp_1_txd_3,
qsfp_1_txc_3
);
// dump file
$dumpfile("test_fpga_core.lxt");
$dumpvars(0, test_fpga_core);
end
fpga_core
UUT (
.clk(clk),
.rst(rst),
.user_led_g(user_led_g),
.user_led_r(user_led_r),
.front_led(front_led),
.user_sw(user_sw),
.qsfp_0_tx_clk_0(qsfp_0_tx_clk_0),
.qsfp_0_tx_rst_0(qsfp_0_tx_rst_0),
.qsfp_0_txd_0(qsfp_0_txd_0),
.qsfp_0_txc_0(qsfp_0_txc_0),
.qsfp_0_rx_clk_0(qsfp_0_rx_clk_0),
.qsfp_0_rx_rst_0(qsfp_0_rx_rst_0),
.qsfp_0_rxd_0(qsfp_0_rxd_0),
.qsfp_0_rxc_0(qsfp_0_rxc_0),
.qsfp_0_tx_clk_1(qsfp_0_tx_clk_1),
.qsfp_0_tx_rst_1(qsfp_0_tx_rst_1),
.qsfp_0_txd_1(qsfp_0_txd_1),
.qsfp_0_txc_1(qsfp_0_txc_1),
.qsfp_0_rx_clk_1(qsfp_0_rx_clk_1),
.qsfp_0_rx_rst_1(qsfp_0_rx_rst_1),
.qsfp_0_rxd_1(qsfp_0_rxd_1),
.qsfp_0_rxc_1(qsfp_0_rxc_1),
.qsfp_0_tx_clk_2(qsfp_0_tx_clk_2),
.qsfp_0_tx_rst_2(qsfp_0_tx_rst_2),
.qsfp_0_txd_2(qsfp_0_txd_2),
.qsfp_0_txc_2(qsfp_0_txc_2),
.qsfp_0_rx_clk_2(qsfp_0_rx_clk_2),
.qsfp_0_rx_rst_2(qsfp_0_rx_rst_2),
.qsfp_0_rxd_2(qsfp_0_rxd_2),
.qsfp_0_rxc_2(qsfp_0_rxc_2),
.qsfp_0_tx_clk_3(qsfp_0_tx_clk_3),
.qsfp_0_tx_rst_3(qsfp_0_tx_rst_3),
.qsfp_0_txd_3(qsfp_0_txd_3),
.qsfp_0_txc_3(qsfp_0_txc_3),
.qsfp_0_rx_clk_3(qsfp_0_rx_clk_3),
.qsfp_0_rx_rst_3(qsfp_0_rx_rst_3),
.qsfp_0_rxd_3(qsfp_0_rxd_3),
.qsfp_0_rxc_3(qsfp_0_rxc_3),
.qsfp_1_tx_clk_0(qsfp_1_tx_clk_0),
.qsfp_1_tx_rst_0(qsfp_1_tx_rst_0),
.qsfp_1_txd_0(qsfp_1_txd_0),
.qsfp_1_txc_0(qsfp_1_txc_0),
.qsfp_1_rx_clk_0(qsfp_1_rx_clk_0),
.qsfp_1_rx_rst_0(qsfp_1_rx_rst_0),
.qsfp_1_rxd_0(qsfp_1_rxd_0),
.qsfp_1_rxc_0(qsfp_1_rxc_0),
.qsfp_1_tx_clk_1(qsfp_1_tx_clk_1),
.qsfp_1_tx_rst_1(qsfp_1_tx_rst_1),
.qsfp_1_txd_1(qsfp_1_txd_1),
.qsfp_1_txc_1(qsfp_1_txc_1),
.qsfp_1_rx_clk_1(qsfp_1_rx_clk_1),
.qsfp_1_rx_rst_1(qsfp_1_rx_rst_1),
.qsfp_1_rxd_1(qsfp_1_rxd_1),
.qsfp_1_rxc_1(qsfp_1_rxc_1),
.qsfp_1_tx_clk_2(qsfp_1_tx_clk_2),
.qsfp_1_tx_rst_2(qsfp_1_tx_rst_2),
.qsfp_1_txd_2(qsfp_1_txd_2),
.qsfp_1_txc_2(qsfp_1_txc_2),
.qsfp_1_rx_clk_2(qsfp_1_rx_clk_2),
.qsfp_1_rx_rst_2(qsfp_1_rx_rst_2),
.qsfp_1_rxd_2(qsfp_1_rxd_2),
.qsfp_1_rxc_2(qsfp_1_rxc_2),
.qsfp_1_tx_clk_3(qsfp_1_tx_clk_3),
.qsfp_1_tx_rst_3(qsfp_1_tx_rst_3),
.qsfp_1_txd_3(qsfp_1_txd_3),
.qsfp_1_txc_3(qsfp_1_txc_3),
.qsfp_1_rx_clk_3(qsfp_1_rx_clk_3),
.qsfp_1_rx_rst_3(qsfp_1_rx_rst_3),
.qsfp_1_rxd_3(qsfp_1_rxd_3),
.qsfp_1_rxc_3(qsfp_1_rxc_3)
);
endmodule

View File

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

View File

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

View File

@ -0,0 +1,25 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -0,0 +1,24 @@
# Verilog Ethernet ADM-PCIE-9V3 Example Design
## Introduction
This example design targets the Alpha Data ADM-PCIE-9V3 FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
FPGA: xcvu3p-ffvc1517-2-i
PHY: 25G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the ADM-PCIE-9V3 board with Vivado. Then run
netcat -u 192.168.1.128 1234 to open a UDP connection to port 1234. Any text
entered into netcat will be echoed back after pressing enter.

View File

@ -0,0 +1,118 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale)
# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e)
# SYN_FILES - space-separated list of source files
# INC_FILES - space-separated list of include files
# XDC_FILES - space-separated list of timing constraint files
# XCI_FILES - space-separated list of IP XCI files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = VirtexUltrascale
# FPGA_DEVICE = xcvu095-ffva2104-2-e
# SYN_FILES = rtl/fpga.v
# XDC_FILES = fpga.xdc
# XCI_FILES = ip/pcspma.xci
# include ../common/vivado.mk
#
###################################################################
# phony targets
.PHONY: clean fpga
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES))
INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES))
XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES))
ifdef XDC_FILES
XDC_FILES_REL = $(patsubst %, ../%, $(XDC_FILES))
else
XDC_FILES_REL = $(FPGA_TOP).xdc
endif
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and project files
###################################################################
all: fpga
fpga: $(FPGA_TOP).bit
tmpclean:
-rm -rf *.log *.jou *.cache *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.tcl run_synth.tcl run_impl.tcl generate_bit.tcl
clean: tmpclean
-rm -rf *.bit program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl
distclean: clean
-rm -rf rev
###################################################################
# Target implementations
###################################################################
# Vivado project file
%.xpr: Makefile $(XCI_FILES_REL)
rm -rf defines.v
touch defines.v
for x in $(DEFS); do echo '`define' $$x >> defines.v; done
echo "create_project -force -part $(FPGA_PART) $*" > create_project.tcl
echo "add_files -fileset sources_1 defines.v" >> create_project.tcl
for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done
for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done
echo "exit" >> create_project.tcl
vivado -nojournal -nolog -mode batch -source create_project.tcl
# synthesis run
%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project $*.xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
echo "exit" >> run_synth.tcl
vivado -nojournal -nolog -mode batch -source run_synth.tcl
# implementation run
%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp
echo "open_project $*.xpr" > run_impl.tcl
echo "reset_run impl_1" >> run_impl.tcl
echo "launch_runs impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "exit" >> run_impl.tcl
vivado -nojournal -nolog -mode batch -source run_impl.tcl
# bit file
%.bit: %.runs/impl_1/%_routed.dcp
echo "open_project $*.xpr" > generate_bit.tcl
echo "open_run impl_1" >> generate_bit.tcl
echo "write_bitstream -force $*.bit" >> generate_bit.tcl
echo "exit" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
mkdir -p rev
EXT=bit; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do COUNT=$$((COUNT+1)); done; \
cp $@ rev/$*_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_rev$$COUNT.$$EXT";

View File

@ -0,0 +1,176 @@
# XDC constraints for the ADM-PCIE-9V3
# part: xcvu3p-ffvc1517-2-i
# General configuration
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN {DIV-1} [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 8 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.CONFIG.UNUSEDPIN {Pullnone} [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
# 300 MHz system clock
set_property -dict {LOC AP26 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports clk_300mhz_p]
set_property -dict {LOC AP27 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports clk_300mhz_n]
create_clock -period 3.333 -name clk_300mhz [get_ports clk_300mhz_p]
# LEDs
set_property -dict {LOC AT27 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_g[0]}]
set_property -dict {LOC AU27 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_g[1]}]
set_property -dict {LOC AU23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_r}]
set_property -dict {LOC AH24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[0]}]
set_property -dict {LOC AJ23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[1]}]
# Switches
set_property -dict {LOC AV27 IOSTANDARD LVCMOS18} [get_ports {user_sw[0]}]
set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}]
# GPIO
#set_property -dict {LOC G30 IOSTANDARD LVCMOS18} [get_ports gpio_p[0]]
#set_property -dict {LOC F30 IOSTANDARD LVCMOS18} [get_ports gpio_n[0]]
#set_property -dict {LOC J31 IOSTANDARD LVCMOS18} [get_ports gpio_p[1]]
#set_property -dict {LOC H31 IOSTANDARD LVCMOS18} [get_ports gpio_n[1]]
# QSFP28 Interfaces
set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXN0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXP0_128 GTYE3_CHANNEL_X0Y16 / GTYE3_COMMON_X0Y4
set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXN1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXP1_128 GTYE3_CHANNEL_X0Y17 / GTYE3_COMMON_X0Y4
set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXN2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXP2_128 GTYE3_CHANNEL_X0Y18 / GTYE3_COMMON_X0Y4
set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXN3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
#set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXP3_128 GTYE3_CHANNEL_X0Y19 / GTYE3_COMMON_X0Y4
set_property -dict {LOC N33 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_128 from ?
#set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ?
set_property -dict {LOC F29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_0_modprs_l]
set_property -dict {LOC D31 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_0_sel_l]
# 161.1328125 MHz MGT reference clock
create_clock -period 6.206 -name qsfp_0_mgt_refclk [get_ports qsfp_0_mgt_refclk_p]
set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3
set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3
set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3
set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
#set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3
set_property -dict {LOC U33 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_127 from ?
#set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ?
set_property -dict {LOC F33 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_1_modprs_l]
set_property -dict {LOC D30 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_1_sel_l]
# 161.1328125 MHz MGT reference clock
create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p]
set_property -dict {LOC B29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_reset_l]
set_property -dict {LOC C29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_int_l]
#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_scl]
#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_i2c_sda]
# PCIe Interface
#set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYTXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXN3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXP3_227 GTYE3_CHANNEL_X0Y7 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYTXN2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYTXP2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXN2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXP2_227 GTYE3_CHANNEL_X0Y6 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYTXN1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYTXP1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXN1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXP1_227 GTYE3_CHANNEL_X0Y5 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYTXN0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYTXP0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXN0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXP0_227 GTYE3_CHANNEL_X0Y4 / GTYE3_COMMON_X0Y1
#set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYTXN3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYTXP3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXN3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXP3_226 GTYE3_CHANNEL_X0Y3 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y2 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y1 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYTXN0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYTXP0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXN0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXP0_226 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXN3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXP3_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXN2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXP2_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXN1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXP1_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXN0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXP0_225 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXN3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXP3_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXN2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXP2_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXN1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXP1_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXN0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXP0_224 GTYE3_CHANNEL_X0Y0 / GTYE3_COMMON_X0Y0
#set_property -dict {LOC AA7 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_226
#set_property -dict {LOC AA6 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_226
#set_property -dict {LOC AJ7 } [get_ports pcie_refclk_2_p] ;# MGTREFCLK0P_224
#set_property -dict {LOC AJ6 } [get_ports pcie_refclk_2_n] ;# MGTREFCLK0N_224
#set_property -dict {LOC AJ31 IOSTANDARD LVCMOS18 PULLUP true} [get_ports perst_0]
#set_property -dict {LOC AH29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports perst_1]
# 100 MHz MGT reference clock
#create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p]
#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p]
# QSPI flash
#set_property -dict {LOC AB10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi_clk}]
#set_property -dict {LOC AB8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[0]}]
#set_property -dict {LOC AD8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[1]}]
#set_property -dict {LOC Y8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[2]}]
#set_property -dict {LOC AC8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi0_dq[3]}]
#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[0]}]
#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[1]}]
#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[2]}]
#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {qspi1_dq[3]}]

View File

@ -0,0 +1,106 @@
# FPGA settings
FPGA_PART = xcvu3p-ffvc1517-2-i
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx_64.v
SYN_FILES += lib/eth/rtl/eth_axis_tx_64.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp_64.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx_64.v
SYN_FILES += lib/eth/rtl/arp_eth_tx_64.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/axis_async_fifo.tcl
# IP
XCI_FILES += ip/gtwizard_ultrascale_0.xci
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 64 -interface SPIx8 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu256-spi-x1_x2_x4_x8}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,89 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule

View File

@ -0,0 +1,904 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 300MHz LVDS
*/
input wire clk_300mhz_p,
input wire clk_300mhz_n,
/*
* GPIO
*/
output wire [1:0] user_led_g,
output wire user_led_r,
output wire [1:0] front_led,
input wire [1:0] user_sw,
/*
* Ethernet: QSFP28
*/
output wire qsfp_0_tx_0_p,
output wire qsfp_0_tx_0_n,
input wire qsfp_0_rx_0_p,
input wire qsfp_0_rx_0_n,
output wire qsfp_0_tx_1_p,
output wire qsfp_0_tx_1_n,
input wire qsfp_0_rx_1_p,
input wire qsfp_0_rx_1_n,
output wire qsfp_0_tx_2_p,
output wire qsfp_0_tx_2_n,
input wire qsfp_0_rx_2_p,
input wire qsfp_0_rx_2_n,
output wire qsfp_0_tx_3_p,
output wire qsfp_0_tx_3_n,
input wire qsfp_0_rx_3_p,
input wire qsfp_0_rx_3_n,
input wire qsfp_0_mgt_refclk_p,
input wire qsfp_0_mgt_refclk_n,
input wire qsfp_0_modprs_l,
output wire qsfp_0_sel_l,
output wire qsfp_1_tx_0_p,
output wire qsfp_1_tx_0_n,
input wire qsfp_1_rx_0_p,
input wire qsfp_1_rx_0_n,
output wire qsfp_1_tx_1_p,
output wire qsfp_1_tx_1_n,
input wire qsfp_1_rx_1_p,
input wire qsfp_1_rx_1_n,
output wire qsfp_1_tx_2_p,
output wire qsfp_1_tx_2_n,
input wire qsfp_1_rx_2_p,
input wire qsfp_1_rx_2_n,
output wire qsfp_1_tx_3_p,
output wire qsfp_1_tx_3_n,
input wire qsfp_1_rx_3_p,
input wire qsfp_1_rx_3_n,
input wire qsfp_1_mgt_refclk_p,
input wire qsfp_1_mgt_refclk_n,
input wire qsfp_1_modprs_l,
output wire qsfp_1_sel_l,
output wire qsfp_reset_l,
input wire qsfp_int_l
);
// Clock and reset
wire clk_300mhz_ibufg;
wire clk_125mhz_mmcm_out;
// Internal 125 MHz clock
wire clk_125mhz_int;
wire rst_125mhz_int;
// Internal 156.25 MHz clock
wire clk_156mhz_int;
wire rst_156mhz_int;
wire mmcm_rst = 1'b0;
wire mmcm_locked;
wire mmcm_clkfb;
IBUFGDS #(
.DIFF_TERM("FALSE"),
.IBUF_LOW_PWR("FALSE")
)
clk_300mhz_ibufg_inst (
.O (clk_300mhz_ibufg),
.I (clk_300mhz_p),
.IB (clk_300mhz_n)
);
// MMCM instance
// 300 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 10, D = 3 sets Fvco = 1000 MHz (in range)
// Divide by 8 to get output frequency of 125 MHz
MMCME3_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(8),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0),
.CLKOUT1_DIVIDE(1),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT1_PHASE(0),
.CLKOUT2_DIVIDE(1),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT2_PHASE(0),
.CLKOUT3_DIVIDE(1),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0),
.CLKOUT4_DIVIDE(1),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT5_DIVIDE(1),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT5_PHASE(0),
.CLKOUT6_DIVIDE(1),
.CLKOUT6_DUTY_CYCLE(0.5),
.CLKOUT6_PHASE(0),
.CLKFBOUT_MULT_F(10),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(3),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(3.333),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_300mhz_ibufg),
.CLKFBIN(mmcm_clkfb),
.RST(mmcm_rst),
.PWRDWN(1'b0),
.CLKOUT0(clk_125mhz_mmcm_out),
.CLKOUT0B(),
.CLKOUT1(),
.CLKOUT1B(),
.CLKOUT2(),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
.CLKOUT4(),
.CLKOUT5(),
.CLKOUT6(),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
.LOCKED(mmcm_locked)
);
BUFG
clk_125mhz_bufg_inst (
.I(clk_125mhz_mmcm_out),
.O(clk_125mhz_int)
);
sync_reset #(
.N(4)
)
sync_reset_125mhz_inst (
.clk(clk_125mhz_int),
.rst(~mmcm_locked),
.sync_reset_out(rst_125mhz_int)
);
// GPIO
wire [1:0] user_sw_int;
debounce_switch #(
.WIDTH(2),
.N(4),
.RATE(125000)
)
debounce_switch_inst (
.clk(clk_125mhz_int),
.rst(rst_125mhz_int),
.in({user_sw}),
.out({user_sw_int})
);
// XGMII 10G PHY
assign qsfp_0_sel_l = 1'b0;
wire qsfp_0_tx_clk_0_int;
wire qsfp_0_tx_rst_0_int;
wire [63:0] qsfp_0_txd_0_int;
wire [7:0] qsfp_0_txc_0_int;
wire qsfp_0_rx_clk_0_int;
wire qsfp_0_rx_rst_0_int;
wire [63:0] qsfp_0_rxd_0_int;
wire [7:0] qsfp_0_rxc_0_int;
wire qsfp_0_tx_clk_1_int;
wire qsfp_0_tx_rst_1_int;
wire [63:0] qsfp_0_txd_1_int;
wire [7:0] qsfp_0_txc_1_int;
wire qsfp_0_rx_clk_1_int;
wire qsfp_0_rx_rst_1_int;
wire [63:0] qsfp_0_rxd_1_int;
wire [7:0] qsfp_0_rxc_1_int;
wire qsfp_0_tx_clk_2_int;
wire qsfp_0_tx_rst_2_int;
wire [63:0] qsfp_0_txd_2_int;
wire [7:0] qsfp_0_txc_2_int;
wire qsfp_0_rx_clk_2_int;
wire qsfp_0_rx_rst_2_int;
wire [63:0] qsfp_0_rxd_2_int;
wire [7:0] qsfp_0_rxc_2_int;
wire qsfp_0_tx_clk_3_int;
wire qsfp_0_tx_rst_3_int;
wire [63:0] qsfp_0_txd_3_int;
wire [7:0] qsfp_0_txc_3_int;
wire qsfp_0_rx_clk_3_int;
wire qsfp_0_rx_rst_3_int;
wire [63:0] qsfp_0_rxd_3_int;
wire [7:0] qsfp_0_rxc_3_int;
assign qsfp_1_sel_l = 1'b0;
wire qsfp_1_tx_clk_0_int;
wire qsfp_1_tx_rst_0_int;
wire [63:0] qsfp_1_txd_0_int;
wire [7:0] qsfp_1_txc_0_int;
wire qsfp_1_rx_clk_0_int;
wire qsfp_1_rx_rst_0_int;
wire [63:0] qsfp_1_rxd_0_int;
wire [7:0] qsfp_1_rxc_0_int;
wire qsfp_1_tx_clk_1_int;
wire qsfp_1_tx_rst_1_int;
wire [63:0] qsfp_1_txd_1_int;
wire [7:0] qsfp_1_txc_1_int;
wire qsfp_1_rx_clk_1_int;
wire qsfp_1_rx_rst_1_int;
wire [63:0] qsfp_1_rxd_1_int;
wire [7:0] qsfp_1_rxc_1_int;
wire qsfp_1_tx_clk_2_int;
wire qsfp_1_tx_rst_2_int;
wire [63:0] qsfp_1_txd_2_int;
wire [7:0] qsfp_1_txc_2_int;
wire qsfp_1_rx_clk_2_int;
wire qsfp_1_rx_rst_2_int;
wire [63:0] qsfp_1_rxd_2_int;
wire [7:0] qsfp_1_rxc_2_int;
wire qsfp_1_tx_clk_3_int;
wire qsfp_1_tx_rst_3_int;
wire [63:0] qsfp_1_txd_3_int;
wire [7:0] qsfp_1_txc_3_int;
wire qsfp_1_rx_clk_3_int;
wire qsfp_1_rx_rst_3_int;
wire [63:0] qsfp_1_rxd_3_int;
wire [7:0] qsfp_1_rxc_3_int;
assign qsfp_reset_l = 1'b1;
wire qsfp_0_rx_block_lock_0;
wire qsfp_0_rx_block_lock_1;
wire qsfp_0_rx_block_lock_2;
wire qsfp_0_rx_block_lock_3;
wire qsfp_1_rx_block_lock_0;
wire qsfp_1_rx_block_lock_1;
wire qsfp_1_rx_block_lock_2;
wire qsfp_1_rx_block_lock_3;
wire qsfp_0_mgt_refclk;
wire qsfp_1_mgt_refclk;
wire [7:0] gt_txclkout;
wire gt_txusrclk;
wire [7:0] gt_rxclkout;
wire [7:0] gt_rxusrclk;
wire gt_reset_tx_done;
wire gt_reset_rx_done;
wire [7:0] gt_txprgdivresetdone;
wire [7:0] gt_txpmaresetdone;
wire [7:0] gt_rxprgdivresetdone;
wire [7:0] gt_rxpmaresetdone;
wire gt_tx_reset = ~((&gt_txprgdivresetdone) & (&gt_txpmaresetdone));
wire gt_rx_reset = ~&gt_rxpmaresetdone;
reg gt_userclk_tx_active = 1'b0;
reg [7:0] gt_userclk_rx_active = 1'b0;
IBUFDS_GTE4 ibufds_gte4_qsfp_0_mgt_refclk_inst (
.I (qsfp_0_mgt_refclk_p),
.IB (qsfp_0_mgt_refclk_n),
.CEB (1'b0),
.O (qsfp_0_mgt_refclk),
.ODIV2 ()
);
IBUFDS_GTE4 ibufds_gte4_qsfp_1_mgt_refclk_inst (
.I (qsfp_1_mgt_refclk_p),
.IB (qsfp_1_mgt_refclk_n),
.CEB (1'b0),
.O (qsfp_1_mgt_refclk),
.ODIV2 ()
);
BUFG_GT bufg_gt_tx_usrclk_inst (
.CE (1'b1),
.CEMASK (1'b0),
.CLR (gt_tx_reset),
.CLRMASK (1'b0),
.DIV (3'd0),
.I (gt_txclkout[0]),
.O (gt_txusrclk)
);
assign clk_156mhz_int = gt_txusrclk;
always @(posedge gt_txusrclk, posedge gt_tx_reset) begin
if (gt_tx_reset) begin
gt_userclk_tx_active <= 1'b0;
end else begin
gt_userclk_tx_active <= 1'b1;
end
end
generate
genvar n;
for (n = 0; n < 8; n = n + 1) begin
BUFG_GT bufg_gt_rx_usrclk_inst (
.CE (1'b1),
.CEMASK (1'b0),
.CLR (gt_rx_reset),
.CLRMASK (1'b0),
.DIV (3'd0),
.I (gt_rxclkout[n]),
.O (gt_rxusrclk[n])
);
always @(posedge gt_rxusrclk[n], posedge gt_rx_reset) begin
if (gt_rx_reset) begin
gt_userclk_rx_active[n] <= 1'b0;
end else begin
gt_userclk_rx_active[n] <= 1'b1;
end
end
end
endgenerate
sync_reset #(
.N(4)
)
sync_reset_156mhz_inst (
.clk(clk_156mhz_int),
.rst(~gt_reset_tx_done),
.sync_reset_out(rst_156mhz_int)
);
wire [5:0] qsfp_0_gt_txheader_0;
wire [63:0] qsfp_0_gt_txdata_0;
wire qsfp_0_gt_rxgearboxslip_0;
wire [5:0] qsfp_0_gt_rxheader_0;
wire [1:0] qsfp_0_gt_rxheadervalid_0;
wire [63:0] qsfp_0_gt_rxdata_0;
wire [1:0] qsfp_0_gt_rxdatavalid_0;
wire [5:0] qsfp_0_gt_txheader_1;
wire [63:0] qsfp_0_gt_txdata_1;
wire qsfp_0_gt_rxgearboxslip_1;
wire [5:0] qsfp_0_gt_rxheader_1;
wire [1:0] qsfp_0_gt_rxheadervalid_1;
wire [63:0] qsfp_0_gt_rxdata_1;
wire [1:0] qsfp_0_gt_rxdatavalid_1;
wire [5:0] qsfp_0_gt_txheader_2;
wire [63:0] qsfp_0_gt_txdata_2;
wire qsfp_0_gt_rxgearboxslip_2;
wire [5:0] qsfp_0_gt_rxheader_2;
wire [1:0] qsfp_0_gt_rxheadervalid_2;
wire [63:0] qsfp_0_gt_rxdata_2;
wire [1:0] qsfp_0_gt_rxdatavalid_2;
wire [5:0] qsfp_0_gt_txheader_3;
wire [63:0] qsfp_0_gt_txdata_3;
wire qsfp_0_gt_rxgearboxslip_3;
wire [5:0] qsfp_0_gt_rxheader_3;
wire [1:0] qsfp_0_gt_rxheadervalid_3;
wire [63:0] qsfp_0_gt_rxdata_3;
wire [1:0] qsfp_0_gt_rxdatavalid_3;
wire [5:0] qsfp_1_gt_txheader_0;
wire [63:0] qsfp_1_gt_txdata_0;
wire qsfp_1_gt_rxgearboxslip_0;
wire [5:0] qsfp_1_gt_rxheader_0;
wire [1:0] qsfp_1_gt_rxheadervalid_0;
wire [63:0] qsfp_1_gt_rxdata_0;
wire [1:0] qsfp_1_gt_rxdatavalid_0;
wire [5:0] qsfp_1_gt_txheader_1;
wire [63:0] qsfp_1_gt_txdata_1;
wire qsfp_1_gt_rxgearboxslip_1;
wire [5:0] qsfp_1_gt_rxheader_1;
wire [1:0] qsfp_1_gt_rxheadervalid_1;
wire [63:0] qsfp_1_gt_rxdata_1;
wire [1:0] qsfp_1_gt_rxdatavalid_1;
wire [5:0] qsfp_1_gt_txheader_2;
wire [63:0] qsfp_1_gt_txdata_2;
wire qsfp_1_gt_rxgearboxslip_2;
wire [5:0] qsfp_1_gt_rxheader_2;
wire [1:0] qsfp_1_gt_rxheadervalid_2;
wire [63:0] qsfp_1_gt_rxdata_2;
wire [1:0] qsfp_1_gt_rxdatavalid_2;
wire [5:0] qsfp_1_gt_txheader_3;
wire [63:0] qsfp_1_gt_txdata_3;
wire qsfp_1_gt_rxgearboxslip_3;
wire [5:0] qsfp_1_gt_rxheader_3;
wire [1:0] qsfp_1_gt_rxheadervalid_3;
wire [63:0] qsfp_1_gt_rxdata_3;
wire [1:0] qsfp_1_gt_rxdatavalid_3;
gtwizard_ultrascale_0
qsfp_gty_inst (
.gtwiz_userclk_tx_active_in(&gt_userclk_tx_active),
.gtwiz_userclk_rx_active_in(&gt_userclk_rx_active),
.gtwiz_reset_clk_freerun_in(clk_125mhz_int),
.gtwiz_reset_all_in(rst_125mhz_int),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(1'b0),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(1'b0),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.gtrefclk00_in({qsfp_0_mgt_refclk, qsfp_1_mgt_refclk}),
.qpll0outclk_out(),
.qpll0outrefclk_out(),
.gtyrxn_in({qsfp_0_rx_3_n, qsfp_0_rx_2_n, qsfp_0_rx_1_n, qsfp_0_rx_0_n, qsfp_1_rx_3_n, qsfp_1_rx_2_n, qsfp_1_rx_1_n, qsfp_1_rx_0_n}),
.gtyrxp_in({qsfp_0_rx_3_p, qsfp_0_rx_2_p, qsfp_0_rx_1_p, qsfp_0_rx_0_p, qsfp_1_rx_3_p, qsfp_1_rx_2_p, qsfp_1_rx_1_p, qsfp_1_rx_0_p}),
.rxusrclk_in(gt_rxusrclk),
.rxusrclk2_in(gt_rxusrclk),
.gtwiz_userdata_tx_in({qsfp_0_gt_txdata_3, qsfp_0_gt_txdata_2, qsfp_0_gt_txdata_1, qsfp_0_gt_txdata_0, qsfp_1_gt_txdata_3, qsfp_1_gt_txdata_2, qsfp_1_gt_txdata_1, qsfp_1_gt_txdata_0}),
.txheader_in({qsfp_0_gt_txheader_3, qsfp_0_gt_txheader_2, qsfp_0_gt_txheader_1, qsfp_0_gt_txheader_0, qsfp_1_gt_txheader_3, qsfp_1_gt_txheader_2, qsfp_1_gt_txheader_1, qsfp_1_gt_txheader_0}),
.txsequence_in({8{1'b0}}),
.txusrclk_in({8{gt_txusrclk}}),
.txusrclk2_in({8{gt_txusrclk}}),
.gtpowergood_out(),
.gtytxn_out({qsfp_0_tx_3_n, qsfp_0_tx_2_n, qsfp_0_tx_1_n, qsfp_0_tx_0_n, qsfp_1_tx_3_n, qsfp_1_tx_2_n, qsfp_1_tx_1_n, qsfp_1_tx_0_n}),
.gtytxp_out({qsfp_0_tx_3_p, qsfp_0_tx_2_p, qsfp_0_tx_1_p, qsfp_0_tx_0_p, qsfp_1_tx_3_p, qsfp_1_tx_2_p, qsfp_1_tx_1_p, qsfp_1_tx_0_p}),
.rxgearboxslip_in({qsfp_0_gt_rxgearboxslip_3, qsfp_0_gt_rxgearboxslip_2, qsfp_0_gt_rxgearboxslip_1, qsfp_0_gt_rxgearboxslip_0, qsfp_1_gt_rxgearboxslip_3, qsfp_1_gt_rxgearboxslip_2, qsfp_1_gt_rxgearboxslip_1, qsfp_1_gt_rxgearboxslip_0}),
.gtwiz_userdata_rx_out({qsfp_0_gt_rxdata_3, qsfp_0_gt_rxdata_2, qsfp_0_gt_rxdata_1, qsfp_0_gt_rxdata_0, qsfp_1_gt_rxdata_3, qsfp_1_gt_rxdata_2, qsfp_1_gt_rxdata_1, qsfp_1_gt_rxdata_0}),
.rxdatavalid_out({qsfp_0_gt_rxdatavalid_3, qsfp_0_gt_rxdatavalid_2, qsfp_0_gt_rxdatavalid_1, qsfp_0_gt_rxdatavalid_0, qsfp_1_gt_rxdatavalid_3, qsfp_1_gt_rxdatavalid_2, qsfp_1_gt_rxdatavalid_1, qsfp_1_gt_rxdatavalid_0}),
.rxheader_out({qsfp_0_gt_rxheader_3, qsfp_0_gt_rxheader_2, qsfp_0_gt_rxheader_1, qsfp_0_gt_rxheader_0, qsfp_1_gt_rxheader_3, qsfp_1_gt_rxheader_2, qsfp_1_gt_rxheader_1, qsfp_1_gt_rxheader_0}),
.rxheadervalid_out({qsfp_0_gt_rxheadervalid_3, qsfp_0_gt_rxheadervalid_2, qsfp_0_gt_rxheadervalid_1, qsfp_0_gt_rxheadervalid_0, qsfp_1_gt_rxheadervalid_3, qsfp_1_gt_rxheadervalid_2, qsfp_1_gt_rxheadervalid_1, qsfp_1_gt_rxheadervalid_0}),
.rxoutclk_out(gt_rxclkout),
.rxpmaresetdone_out(gt_rxpmaresetdone),
.rxprgdivresetdone_out(gt_rxprgdivresetdone),
.rxstartofseq_out(),
.txoutclk_out(gt_txclkout),
.txpmaresetdone_out(gt_txpmaresetdone),
.txprgdivresetdone_out(gt_txprgdivresetdone)
);
assign qsfp_0_tx_clk_0_int = clk_156mhz_int;
assign qsfp_0_tx_rst_0_int = rst_156mhz_int;
assign qsfp_0_rx_clk_0_int = gt_rxusrclk[4];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_0_reset_sync_inst (
.clk(qsfp_0_rx_clk_0_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_0_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_0_phy_0_inst (
.tx_clk(qsfp_0_tx_clk_0_int),
.tx_rst(qsfp_0_tx_rst_0_int),
.rx_clk(qsfp_0_rx_clk_0_int),
.rx_rst(qsfp_0_rx_rst_0_int),
.xgmii_txd(qsfp_0_txd_0_int),
.xgmii_txc(qsfp_0_txc_0_int),
.xgmii_rxd(qsfp_0_rxd_0_int),
.xgmii_rxc(qsfp_0_rxc_0_int),
.serdes_tx_data(qsfp_0_gt_txdata_0),
.serdes_tx_hdr(qsfp_0_gt_txheader_0),
.serdes_rx_data(qsfp_0_gt_rxdata_0),
.serdes_rx_hdr(qsfp_0_gt_rxheader_0),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_0),
.rx_block_lock(qsfp_0_rx_block_lock_0),
.rx_high_ber()
);
assign qsfp_0_tx_clk_1_int = clk_156mhz_int;
assign qsfp_0_tx_rst_1_int = rst_156mhz_int;
assign qsfp_0_rx_clk_1_int = gt_rxusrclk[5];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_1_reset_sync_inst (
.clk(qsfp_0_rx_clk_1_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_1_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_0_phy_1_inst (
.tx_clk(qsfp_0_tx_clk_1_int),
.tx_rst(qsfp_0_tx_rst_1_int),
.rx_clk(qsfp_0_rx_clk_1_int),
.rx_rst(qsfp_0_rx_rst_1_int),
.xgmii_txd(qsfp_0_txd_1_int),
.xgmii_txc(qsfp_0_txc_1_int),
.xgmii_rxd(qsfp_0_rxd_1_int),
.xgmii_rxc(qsfp_0_rxc_1_int),
.serdes_tx_data(qsfp_0_gt_txdata_1),
.serdes_tx_hdr(qsfp_0_gt_txheader_1),
.serdes_rx_data(qsfp_0_gt_rxdata_1),
.serdes_rx_hdr(qsfp_0_gt_rxheader_1),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_1),
.rx_block_lock(qsfp_0_rx_block_lock_1),
.rx_high_ber()
);
assign qsfp_0_tx_clk_2_int = clk_156mhz_int;
assign qsfp_0_tx_rst_2_int = rst_156mhz_int;
assign qsfp_0_rx_clk_2_int = gt_rxusrclk[6];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_2_reset_sync_inst (
.clk(qsfp_0_rx_clk_2_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_2_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_0_phy_2_inst (
.tx_clk(qsfp_0_tx_clk_2_int),
.tx_rst(qsfp_0_tx_rst_2_int),
.rx_clk(qsfp_0_rx_clk_2_int),
.rx_rst(qsfp_0_rx_rst_2_int),
.xgmii_txd(qsfp_0_txd_2_int),
.xgmii_txc(qsfp_0_txc_2_int),
.xgmii_rxd(qsfp_0_rxd_2_int),
.xgmii_rxc(qsfp_0_rxc_2_int),
.serdes_tx_data(qsfp_0_gt_txdata_2),
.serdes_tx_hdr(qsfp_0_gt_txheader_2),
.serdes_rx_data(qsfp_0_gt_rxdata_2),
.serdes_rx_hdr(qsfp_0_gt_rxheader_2),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_2),
.rx_block_lock(qsfp_0_rx_block_lock_2),
.rx_high_ber()
);
assign qsfp_0_tx_clk_3_int = clk_156mhz_int;
assign qsfp_0_tx_rst_3_int = rst_156mhz_int;
assign qsfp_0_rx_clk_3_int = gt_rxusrclk[7];
sync_reset #(
.N(4)
)
qsfp_0_rx_rst_3_reset_sync_inst (
.clk(qsfp_0_rx_clk_3_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_0_rx_rst_3_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_0_phy_3_inst (
.tx_clk(qsfp_0_tx_clk_3_int),
.tx_rst(qsfp_0_tx_rst_3_int),
.rx_clk(qsfp_0_rx_clk_3_int),
.rx_rst(qsfp_0_rx_rst_3_int),
.xgmii_txd(qsfp_0_txd_3_int),
.xgmii_txc(qsfp_0_txc_3_int),
.xgmii_rxd(qsfp_0_rxd_3_int),
.xgmii_rxc(qsfp_0_rxc_3_int),
.serdes_tx_data(qsfp_0_gt_txdata_3),
.serdes_tx_hdr(qsfp_0_gt_txheader_3),
.serdes_rx_data(qsfp_0_gt_rxdata_3),
.serdes_rx_hdr(qsfp_0_gt_rxheader_3),
.serdes_rx_bitslip(qsfp_0_gt_rxgearboxslip_3),
.rx_block_lock(qsfp_0_rx_block_lock_3),
.rx_high_ber()
);
assign qsfp_1_tx_clk_0_int = clk_156mhz_int;
assign qsfp_1_tx_rst_0_int = rst_156mhz_int;
assign qsfp_1_rx_clk_0_int = gt_rxusrclk[0];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_0_reset_sync_inst (
.clk(qsfp_1_rx_clk_0_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_0_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_1_phy_0_inst (
.tx_clk(qsfp_1_tx_clk_0_int),
.tx_rst(qsfp_1_tx_rst_0_int),
.rx_clk(qsfp_1_rx_clk_0_int),
.rx_rst(qsfp_1_rx_rst_0_int),
.xgmii_txd(qsfp_1_txd_0_int),
.xgmii_txc(qsfp_1_txc_0_int),
.xgmii_rxd(qsfp_1_rxd_0_int),
.xgmii_rxc(qsfp_1_rxc_0_int),
.serdes_tx_data(qsfp_1_gt_txdata_0),
.serdes_tx_hdr(qsfp_1_gt_txheader_0),
.serdes_rx_data(qsfp_1_gt_rxdata_0),
.serdes_rx_hdr(qsfp_1_gt_rxheader_0),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_0),
.rx_block_lock(qsfp_1_rx_block_lock_0),
.rx_high_ber()
);
assign qsfp_1_tx_clk_1_int = clk_156mhz_int;
assign qsfp_1_tx_rst_1_int = rst_156mhz_int;
assign qsfp_1_rx_clk_1_int = gt_rxusrclk[1];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_1_reset_sync_inst (
.clk(qsfp_1_rx_clk_1_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_1_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_1_phy_1_inst (
.tx_clk(qsfp_1_tx_clk_1_int),
.tx_rst(qsfp_1_tx_rst_1_int),
.rx_clk(qsfp_1_rx_clk_1_int),
.rx_rst(qsfp_1_rx_rst_1_int),
.xgmii_txd(qsfp_1_txd_1_int),
.xgmii_txc(qsfp_1_txc_1_int),
.xgmii_rxd(qsfp_1_rxd_1_int),
.xgmii_rxc(qsfp_1_rxc_1_int),
.serdes_tx_data(qsfp_1_gt_txdata_1),
.serdes_tx_hdr(qsfp_1_gt_txheader_1),
.serdes_rx_data(qsfp_1_gt_rxdata_1),
.serdes_rx_hdr(qsfp_1_gt_rxheader_1),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_1),
.rx_block_lock(qsfp_1_rx_block_lock_1),
.rx_high_ber()
);
assign qsfp_1_tx_clk_2_int = clk_156mhz_int;
assign qsfp_1_tx_rst_2_int = rst_156mhz_int;
assign qsfp_1_rx_clk_2_int = gt_rxusrclk[2];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_2_reset_sync_inst (
.clk(qsfp_1_rx_clk_2_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_2_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_1_phy_2_inst (
.tx_clk(qsfp_1_tx_clk_2_int),
.tx_rst(qsfp_1_tx_rst_2_int),
.rx_clk(qsfp_1_rx_clk_2_int),
.rx_rst(qsfp_1_rx_rst_2_int),
.xgmii_txd(qsfp_1_txd_2_int),
.xgmii_txc(qsfp_1_txc_2_int),
.xgmii_rxd(qsfp_1_rxd_2_int),
.xgmii_rxc(qsfp_1_rxc_2_int),
.serdes_tx_data(qsfp_1_gt_txdata_2),
.serdes_tx_hdr(qsfp_1_gt_txheader_2),
.serdes_rx_data(qsfp_1_gt_rxdata_2),
.serdes_rx_hdr(qsfp_1_gt_rxheader_2),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_2),
.rx_block_lock(qsfp_1_rx_block_lock_2),
.rx_high_ber()
);
assign qsfp_1_tx_clk_3_int = clk_156mhz_int;
assign qsfp_1_tx_rst_3_int = rst_156mhz_int;
assign qsfp_1_rx_clk_3_int = gt_rxusrclk[3];
sync_reset #(
.N(4)
)
qsfp_1_rx_rst_3_reset_sync_inst (
.clk(qsfp_1_rx_clk_3_int),
.rst(~gt_reset_rx_done),
.sync_reset_out(qsfp_1_rx_rst_3_int)
);
eth_phy_10g #(
.BIT_REVERSE(1),
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp_1_phy_3_inst (
.tx_clk(qsfp_1_tx_clk_3_int),
.tx_rst(qsfp_1_tx_rst_3_int),
.rx_clk(qsfp_1_rx_clk_3_int),
.rx_rst(qsfp_1_rx_rst_3_int),
.xgmii_txd(qsfp_1_txd_3_int),
.xgmii_txc(qsfp_1_txc_3_int),
.xgmii_rxd(qsfp_1_rxd_3_int),
.xgmii_rxc(qsfp_1_rxc_3_int),
.serdes_tx_data(qsfp_1_gt_txdata_3),
.serdes_tx_hdr(qsfp_1_gt_txheader_3),
.serdes_rx_data(qsfp_1_gt_rxdata_3),
.serdes_rx_hdr(qsfp_1_gt_rxheader_3),
.serdes_rx_bitslip(qsfp_1_gt_rxgearboxslip_3),
.rx_block_lock(qsfp_1_rx_block_lock_3),
.rx_high_ber()
);
//assign led = sw[0] ? {qsfp_1_rx_block_lock_4, qsfp_1_rx_block_lock_3, qsfp_1_rx_block_lock_2, qsfp_1_rx_block_lock_1, qsfp_0_rx_block_lock_4, qsfp_0_rx_block_lock_3, qsfp_0_rx_block_lock_2, qsfp_0_rx_block_lock_1} : led_int;
assign front_led = {1'b0, qsfp_0_rx_block_lock_0};
fpga_core
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.user_led_g(user_led_g),
.user_led_r(user_led_r),
//.front_led(front_led),
.user_sw(user_sw_int),
/*
* Ethernet: QSFP28
*/
.qsfp_0_tx_clk_0(qsfp_0_tx_clk_0_int),
.qsfp_0_tx_rst_0(qsfp_0_tx_rst_0_int),
.qsfp_0_txd_0(qsfp_0_txd_0_int),
.qsfp_0_txc_0(qsfp_0_txc_0_int),
.qsfp_0_rx_clk_0(qsfp_0_rx_clk_0_int),
.qsfp_0_rx_rst_0(qsfp_0_rx_rst_0_int),
.qsfp_0_rxd_0(qsfp_0_rxd_0_int),
.qsfp_0_rxc_0(qsfp_0_rxc_0_int),
.qsfp_0_tx_clk_1(qsfp_0_tx_clk_1_int),
.qsfp_0_tx_rst_1(qsfp_0_tx_rst_1_int),
.qsfp_0_txd_1(qsfp_0_txd_1_int),
.qsfp_0_txc_1(qsfp_0_txc_1_int),
.qsfp_0_rx_clk_1(qsfp_0_rx_clk_1_int),
.qsfp_0_rx_rst_1(qsfp_0_rx_rst_1_int),
.qsfp_0_rxd_1(qsfp_0_rxd_1_int),
.qsfp_0_rxc_1(qsfp_0_rxc_1_int),
.qsfp_0_tx_clk_2(qsfp_0_tx_clk_2_int),
.qsfp_0_tx_rst_2(qsfp_0_tx_rst_2_int),
.qsfp_0_txd_2(qsfp_0_txd_2_int),
.qsfp_0_txc_2(qsfp_0_txc_2_int),
.qsfp_0_rx_clk_2(qsfp_0_rx_clk_2_int),
.qsfp_0_rx_rst_2(qsfp_0_rx_rst_2_int),
.qsfp_0_rxd_2(qsfp_0_rxd_2_int),
.qsfp_0_rxc_2(qsfp_0_rxc_2_int),
.qsfp_0_tx_clk_3(qsfp_0_tx_clk_3_int),
.qsfp_0_tx_rst_3(qsfp_0_tx_rst_3_int),
.qsfp_0_txd_3(qsfp_0_txd_3_int),
.qsfp_0_txc_3(qsfp_0_txc_3_int),
.qsfp_0_rx_clk_3(qsfp_0_rx_clk_3_int),
.qsfp_0_rx_rst_3(qsfp_0_rx_rst_3_int),
.qsfp_0_rxd_3(qsfp_0_rxd_3_int),
.qsfp_0_rxc_3(qsfp_0_rxc_3_int),
.qsfp_1_tx_clk_0(qsfp_1_tx_clk_0_int),
.qsfp_1_tx_rst_0(qsfp_1_tx_rst_0_int),
.qsfp_1_txd_0(qsfp_1_txd_0_int),
.qsfp_1_txc_0(qsfp_1_txc_0_int),
.qsfp_1_rx_clk_0(qsfp_1_rx_clk_0_int),
.qsfp_1_rx_rst_0(qsfp_1_rx_rst_0_int),
.qsfp_1_rxd_0(qsfp_1_rxd_0_int),
.qsfp_1_rxc_0(qsfp_1_rxc_0_int),
.qsfp_1_tx_clk_1(qsfp_1_tx_clk_1_int),
.qsfp_1_tx_rst_1(qsfp_1_tx_rst_1_int),
.qsfp_1_txd_1(qsfp_1_txd_1_int),
.qsfp_1_txc_1(qsfp_1_txc_1_int),
.qsfp_1_rx_clk_1(qsfp_1_rx_clk_1_int),
.qsfp_1_rx_rst_1(qsfp_1_rx_rst_1_int),
.qsfp_1_rxd_1(qsfp_1_rxd_1_int),
.qsfp_1_rxc_1(qsfp_1_rxc_1_int),
.qsfp_1_tx_clk_2(qsfp_1_tx_clk_2_int),
.qsfp_1_tx_rst_2(qsfp_1_tx_rst_2_int),
.qsfp_1_txd_2(qsfp_1_txd_2_int),
.qsfp_1_txc_2(qsfp_1_txc_2_int),
.qsfp_1_rx_clk_2(qsfp_1_rx_clk_2_int),
.qsfp_1_rx_rst_2(qsfp_1_rx_rst_2_int),
.qsfp_1_rxd_2(qsfp_1_rxd_2_int),
.qsfp_1_rxc_2(qsfp_1_rxc_2_int),
.qsfp_1_tx_clk_3(qsfp_1_tx_clk_3_int),
.qsfp_1_tx_rst_3(qsfp_1_tx_rst_3_int),
.qsfp_1_txd_3(qsfp_1_txd_3_int),
.qsfp_1_txc_3(qsfp_1_txc_3_int),
.qsfp_1_rx_clk_3(qsfp_1_rx_clk_3_int),
.qsfp_1_rx_rst_3(qsfp_1_rx_rst_3_int),
.qsfp_1_rxd_3(qsfp_1_rxd_3_int),
.qsfp_1_rxc_3(qsfp_1_rxc_3_int)
);
endmodule

View File

@ -0,0 +1,659 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA core logic
*/
module fpga_core #
(
parameter TARGET = "XILINX"
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
output wire [1:0] user_led_g,
output wire user_led_r,
output wire [1:0] front_led,
input wire [1:0] user_sw,
/*
* Ethernet: QSFP28
*/
input wire qsfp_0_tx_clk_0,
input wire qsfp_0_tx_rst_0,
output wire [63:0] qsfp_0_txd_0,
output wire [7:0] qsfp_0_txc_0,
input wire qsfp_0_rx_clk_0,
input wire qsfp_0_rx_rst_0,
input wire [63:0] qsfp_0_rxd_0,
input wire [7:0] qsfp_0_rxc_0,
input wire qsfp_0_tx_clk_1,
input wire qsfp_0_tx_rst_1,
output wire [63:0] qsfp_0_txd_1,
output wire [7:0] qsfp_0_txc_1,
input wire qsfp_0_rx_clk_1,
input wire qsfp_0_rx_rst_1,
input wire [63:0] qsfp_0_rxd_1,
input wire [7:0] qsfp_0_rxc_1,
input wire qsfp_0_tx_clk_2,
input wire qsfp_0_tx_rst_2,
output wire [63:0] qsfp_0_txd_2,
output wire [7:0] qsfp_0_txc_2,
input wire qsfp_0_rx_clk_2,
input wire qsfp_0_rx_rst_2,
input wire [63:0] qsfp_0_rxd_2,
input wire [7:0] qsfp_0_rxc_2,
input wire qsfp_0_tx_clk_3,
input wire qsfp_0_tx_rst_3,
output wire [63:0] qsfp_0_txd_3,
output wire [7:0] qsfp_0_txc_3,
input wire qsfp_0_rx_clk_3,
input wire qsfp_0_rx_rst_3,
input wire [63:0] qsfp_0_rxd_3,
input wire [7:0] qsfp_0_rxc_3,
input wire qsfp_1_tx_clk_0,
input wire qsfp_1_tx_rst_0,
output wire [63:0] qsfp_1_txd_0,
output wire [7:0] qsfp_1_txc_0,
input wire qsfp_1_rx_clk_0,
input wire qsfp_1_rx_rst_0,
input wire [63:0] qsfp_1_rxd_0,
input wire [7:0] qsfp_1_rxc_0,
input wire qsfp_1_tx_clk_1,
input wire qsfp_1_tx_rst_1,
output wire [63:0] qsfp_1_txd_1,
output wire [7:0] qsfp_1_txc_1,
input wire qsfp_1_rx_clk_1,
input wire qsfp_1_rx_rst_1,
input wire [63:0] qsfp_1_rxd_1,
input wire [7:0] qsfp_1_rxc_1,
input wire qsfp_1_tx_clk_2,
input wire qsfp_1_tx_rst_2,
output wire [63:0] qsfp_1_txd_2,
output wire [7:0] qsfp_1_txc_2,
input wire qsfp_1_rx_clk_2,
input wire qsfp_1_rx_rst_2,
input wire [63:0] qsfp_1_rxd_2,
input wire [7:0] qsfp_1_rxc_2,
input wire qsfp_1_tx_clk_3,
input wire qsfp_1_tx_rst_3,
output wire [63:0] qsfp_1_txd_3,
output wire [7:0] qsfp_1_txc_3,
input wire qsfp_1_rx_clk_3,
input wire qsfp_1_rx_rst_3,
input wire [63:0] qsfp_1_rxd_3,
input wire [7:0] qsfp_1_rxc_3
);
// AXI between MAC and Ethernet modules
wire [63:0] rx_axis_tdata;
wire [7:0] rx_axis_tkeep;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [63:0] tx_axis_tdata;
wire [7:0] tx_axis_tkeep;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [63:0] rx_eth_payload_axis_tdata;
wire [7:0] rx_eth_payload_axis_tkeep;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [63:0] tx_eth_payload_axis_tdata;
wire [7:0] tx_eth_payload_axis_tkeep;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [63:0] rx_ip_payload_axis_tdata;
wire [7:0] rx_ip_payload_axis_tkeep;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [63:0] tx_ip_payload_axis_tdata;
wire [7:0] tx_ip_payload_axis_tkeep;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [63:0] rx_udp_payload_axis_tdata;
wire [7:0] rx_udp_payload_axis_tkeep;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [63:0] tx_udp_payload_axis_tdata;
wire [7:0] tx_udp_payload_axis_tkeep;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [63:0] rx_fifo_udp_payload_axis_tdata;
wire [7:0] rx_fifo_udp_payload_axis_tkeep;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [63:0] tx_fifo_udp_payload_axis_tdata;
wire [7:0] tx_fifo_udp_payload_axis_tkeep;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tkeep = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tkeep = tx_fifo_udp_payload_axis_tkeep;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tkeep = rx_udp_payload_axis_tkeep;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
valid_last <= tx_udp_payload_axis_tvalid;
if (tx_udp_payload_axis_tvalid && !valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
end
end
end
assign user_led_g = ~led_reg[1:0];
assign user_led_r = 1'b1;
assign front_led = 2'b00;
assign phy_reset_n = !rst;
assign qsfp_0_txd_1 = 64'h0707070707070707;
assign qsfp_0_txc_1 = 8'hff;
assign qsfp_0_txd_2 = 64'h0707070707070707;
assign qsfp_0_txc_2 = 8'hff;
assign qsfp_0_txd_3 = 64'h0707070707070707;
assign qsfp_0_txc_3 = 8'hff;
assign qsfp_1_txd_0 = 64'h0707070707070707;
assign qsfp_1_txc_0 = 8'hff;
assign qsfp_1_txd_1 = 64'h0707070707070707;
assign qsfp_1_txc_1 = 8'hff;
assign qsfp_1_txd_2 = 64'h0707070707070707;
assign qsfp_1_txc_2 = 8'hff;
assign qsfp_1_txd_3 = 64'h0707070707070707;
assign qsfp_1_txc_3 = 8'hff;
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
.ENABLE_DIC(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_ADDR_WIDTH(9),
.TX_FRAME_FIFO(1),
.RX_FIFO_ADDR_WIDTH(9),
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(qsfp_0_rx_clk_0),
.rx_rst(qsfp_0_rx_rst_0),
.tx_clk(qsfp_0_tx_clk_0),
.tx_rst(qsfp_0_tx_rst_0),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tkeep(tx_axis_tkeep),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tkeep(rx_axis_tkeep),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(qsfp_0_rxd_0),
.xgmii_rxc(qsfp_0_rxc_0),
.xgmii_txd(qsfp_0_txd_0),
.xgmii_txc(qsfp_0_txc_0),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),
.tx_fifo_good_frame(),
.rx_error_bad_frame(),
.rx_error_bad_fcs(),
.rx_fifo_overflow(),
.rx_fifo_bad_frame(),
.rx_fifo_good_frame(),
.ifg_delay(8'd12)
);
eth_axis_rx_64
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tkeep(rx_axis_tkeep),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx_64
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tkeep(tx_axis_tkeep),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete_64
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tkeep(tx_ip_payload_axis_tkeep),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tkeep(rx_ip_payload_axis_tkeep),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tkeep(tx_udp_payload_axis_tkeep),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tkeep(rx_udp_payload_axis_tkeep),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(1'b0)
);
axis_fifo #(
.ADDR_WIDTH(10),
.DATA_WIDTH(64),
.KEEP_ENABLE(1),
.KEEP_WIDTH(8),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(rx_fifo_udp_payload_axis_tkeep),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule

View File

@ -0,0 +1,52 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an 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-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule

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/ip_ep.py

View File

@ -0,0 +1,462 @@
#!/usr/bin/env python
"""
Copyright (c) 2016-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import eth_ep
import arp_ep
import udp_ep
import xgmii_ep
module = 'fpga_core'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../lib/eth/rtl/eth_mac_10g_fifo.v")
srcs.append("../lib/eth/rtl/eth_mac_10g.v")
srcs.append("../lib/eth/rtl/axis_xgmii_rx_64.v")
srcs.append("../lib/eth/rtl/axis_xgmii_tx_64.v")
srcs.append("../lib/eth/rtl/lfsr.v")
srcs.append("../lib/eth/rtl/eth_axis_rx_64.v")
srcs.append("../lib/eth/rtl/eth_axis_tx_64.v")
srcs.append("../lib/eth/rtl/udp_complete_64.v")
srcs.append("../lib/eth/rtl/udp_checksum_gen_64.v")
srcs.append("../lib/eth/rtl/udp_64.v")
srcs.append("../lib/eth/rtl/udp_ip_rx_64.v")
srcs.append("../lib/eth/rtl/udp_ip_tx_64.v")
srcs.append("../lib/eth/rtl/ip_complete_64.v")
srcs.append("../lib/eth/rtl/ip_64.v")
srcs.append("../lib/eth/rtl/ip_eth_rx_64.v")
srcs.append("../lib/eth/rtl/ip_eth_tx_64.v")
srcs.append("../lib/eth/rtl/ip_arb_mux.v")
srcs.append("../lib/eth/rtl/arp_64.v")
srcs.append("../lib/eth/rtl/arp_cache.v")
srcs.append("../lib/eth/rtl/arp_eth_rx_64.v")
srcs.append("../lib/eth/rtl/arp_eth_tx_64.v")
srcs.append("../lib/eth/rtl/eth_arb_mux.v")
srcs.append("../lib/eth/lib/axis/rtl/arbiter.v")
srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
user_sw = Signal(intbv(0)[2:])
qsfp_0_tx_clk_0 = Signal(bool(0))
qsfp_0_tx_rst_0 = Signal(bool(0))
qsfp_0_rx_clk_0 = Signal(bool(0))
qsfp_0_rx_rst_0 = Signal(bool(0))
qsfp_0_rxd_0 = Signal(intbv(0)[64:])
qsfp_0_rxc_0 = Signal(intbv(0)[8:])
qsfp_0_tx_clk_1 = Signal(bool(0))
qsfp_0_tx_rst_1 = Signal(bool(0))
qsfp_0_rx_clk_1 = Signal(bool(0))
qsfp_0_rx_rst_1 = Signal(bool(0))
qsfp_0_rxd_1 = Signal(intbv(0)[64:])
qsfp_0_rxc_1 = Signal(intbv(0)[8:])
qsfp_0_tx_clk_2 = Signal(bool(0))
qsfp_0_tx_rst_2 = Signal(bool(0))
qsfp_0_rx_clk_2 = Signal(bool(0))
qsfp_0_rx_rst_2 = Signal(bool(0))
qsfp_0_rxd_2 = Signal(intbv(0)[64:])
qsfp_0_rxc_2 = Signal(intbv(0)[8:])
qsfp_0_tx_clk_3 = Signal(bool(0))
qsfp_0_tx_rst_3 = Signal(bool(0))
qsfp_0_rx_clk_3 = Signal(bool(0))
qsfp_0_rx_rst_3 = Signal(bool(0))
qsfp_0_rxd_3 = Signal(intbv(0)[64:])
qsfp_0_rxc_3 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_0 = Signal(bool(0))
qsfp_1_tx_rst_0 = Signal(bool(0))
qsfp_1_rx_clk_0 = Signal(bool(0))
qsfp_1_rx_rst_0 = Signal(bool(0))
qsfp_1_rxd_0 = Signal(intbv(0)[64:])
qsfp_1_rxc_0 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_1 = Signal(bool(0))
qsfp_1_tx_rst_1 = Signal(bool(0))
qsfp_1_rx_clk_1 = Signal(bool(0))
qsfp_1_rx_rst_1 = Signal(bool(0))
qsfp_1_rxd_1 = Signal(intbv(0)[64:])
qsfp_1_rxc_1 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_2 = Signal(bool(0))
qsfp_1_tx_rst_2 = Signal(bool(0))
qsfp_1_rx_clk_2 = Signal(bool(0))
qsfp_1_rx_rst_2 = Signal(bool(0))
qsfp_1_rxd_2 = Signal(intbv(0)[64:])
qsfp_1_rxc_2 = Signal(intbv(0)[8:])
qsfp_1_tx_clk_3 = Signal(bool(0))
qsfp_1_tx_rst_3 = Signal(bool(0))
qsfp_1_rx_clk_3 = Signal(bool(0))
qsfp_1_rx_rst_3 = Signal(bool(0))
qsfp_1_rxd_3 = Signal(intbv(0)[64:])
qsfp_1_rxc_3 = Signal(intbv(0)[8:])
# Outputs
user_led_g = Signal(intbv(0)[2:])
user_led_r = Signal(bool(0))
front_led = Signal(intbv(0)[2:])
qsfp_0_txd_0 = Signal(intbv(0)[64:])
qsfp_0_txc_0 = Signal(intbv(0)[8:])
qsfp_0_txd_1 = Signal(intbv(0)[64:])
qsfp_0_txc_1 = Signal(intbv(0)[8:])
qsfp_0_txd_2 = Signal(intbv(0)[64:])
qsfp_0_txc_2 = Signal(intbv(0)[8:])
qsfp_0_txd_3 = Signal(intbv(0)[64:])
qsfp_0_txc_3 = Signal(intbv(0)[8:])
qsfp_1_txd_0 = Signal(intbv(0)[64:])
qsfp_1_txc_0 = Signal(intbv(0)[8:])
qsfp_1_txd_1 = Signal(intbv(0)[64:])
qsfp_1_txc_1 = Signal(intbv(0)[8:])
qsfp_1_txd_2 = Signal(intbv(0)[64:])
qsfp_1_txc_2 = Signal(intbv(0)[8:])
qsfp_1_txd_3 = Signal(intbv(0)[64:])
qsfp_1_txc_3 = Signal(intbv(0)[8:])
# sources and sinks
qsfp_0_0_source = xgmii_ep.XGMIISource()
qsfp_0_0_source_logic = qsfp_0_0_source.create_logic(qsfp_0_rx_clk_0, qsfp_0_rx_rst_0, txd=qsfp_0_rxd_0, txc=qsfp_0_rxc_0, name='qsfp_0_0_source')
qsfp_0_0_sink = xgmii_ep.XGMIISink()
qsfp_0_0_sink_logic = qsfp_0_0_sink.create_logic(qsfp_0_tx_clk_0, qsfp_0_tx_rst_0, rxd=qsfp_0_txd_0, rxc=qsfp_0_txc_0, name='qsfp_0_0_sink')
qsfp_0_1_source = xgmii_ep.XGMIISource()
qsfp_0_1_source_logic = qsfp_0_1_source.create_logic(qsfp_0_rx_clk_1, qsfp_0_rx_rst_1, txd=qsfp_0_rxd_1, txc=qsfp_0_rxc_1, name='qsfp_0_1_source')
qsfp_0_1_sink = xgmii_ep.XGMIISink()
qsfp_0_1_sink_logic = qsfp_0_1_sink.create_logic(qsfp_0_tx_clk_1, qsfp_0_tx_rst_1, rxd=qsfp_0_txd_1, rxc=qsfp_0_txc_1, name='qsfp_0_1_sink')
qsfp_0_2_source = xgmii_ep.XGMIISource()
qsfp_0_2_source_logic = qsfp_0_2_source.create_logic(qsfp_0_rx_clk_2, qsfp_0_rx_rst_2, txd=qsfp_0_rxd_2, txc=qsfp_0_rxc_2, name='qsfp_0_2_source')
qsfp_0_2_sink = xgmii_ep.XGMIISink()
qsfp_0_2_sink_logic = qsfp_0_2_sink.create_logic(qsfp_0_tx_clk_2, qsfp_0_tx_rst_2, rxd=qsfp_0_txd_2, rxc=qsfp_0_txc_2, name='qsfp_0_2_sink')
qsfp_0_3_source = xgmii_ep.XGMIISource()
qsfp_0_3_source_logic = qsfp_0_3_source.create_logic(qsfp_0_rx_clk_3, qsfp_0_rx_rst_3, txd=qsfp_0_rxd_3, txc=qsfp_0_rxc_3, name='qsfp_0_3_source')
qsfp_0_3_sink = xgmii_ep.XGMIISink()
qsfp_0_3_sink_logic = qsfp_0_3_sink.create_logic(qsfp_0_tx_clk_3, qsfp_0_tx_rst_3, rxd=qsfp_0_txd_3, rxc=qsfp_0_txc_3, name='qsfp_0_3_sink')
qsfp_1_0_source = xgmii_ep.XGMIISource()
qsfp_1_0_source_logic = qsfp_1_0_source.create_logic(qsfp_1_rx_clk_0, qsfp_1_rx_rst_0, txd=qsfp_1_rxd_0, txc=qsfp_1_rxc_0, name='qsfp_1_0_source')
qsfp_1_0_sink = xgmii_ep.XGMIISink()
qsfp_1_0_sink_logic = qsfp_1_0_sink.create_logic(qsfp_1_tx_clk_0, qsfp_1_tx_rst_0, rxd=qsfp_1_txd_0, rxc=qsfp_1_txc_0, name='qsfp_1_0_sink')
qsfp_1_1_source = xgmii_ep.XGMIISource()
qsfp_1_1_source_logic = qsfp_1_1_source.create_logic(qsfp_1_rx_clk_1, qsfp_1_rx_rst_1, txd=qsfp_1_rxd_1, txc=qsfp_1_rxc_1, name='qsfp_1_1_source')
qsfp_1_1_sink = xgmii_ep.XGMIISink()
qsfp_1_1_sink_logic = qsfp_1_1_sink.create_logic(qsfp_1_tx_clk_1, qsfp_1_tx_rst_1, rxd=qsfp_1_txd_1, rxc=qsfp_1_txc_1, name='qsfp_1_1_sink')
qsfp_1_2_source = xgmii_ep.XGMIISource()
qsfp_1_2_source_logic = qsfp_1_2_source.create_logic(qsfp_1_rx_clk_2, qsfp_1_rx_rst_2, txd=qsfp_1_rxd_2, txc=qsfp_1_rxc_2, name='qsfp_1_2_source')
qsfp_1_2_sink = xgmii_ep.XGMIISink()
qsfp_1_2_sink_logic = qsfp_1_2_sink.create_logic(qsfp_1_tx_clk_2, qsfp_1_tx_rst_2, rxd=qsfp_1_txd_2, rxc=qsfp_1_txc_2, name='qsfp_1_2_sink')
qsfp_1_3_source = xgmii_ep.XGMIISource()
qsfp_1_3_source_logic = qsfp_1_3_source.create_logic(qsfp_1_rx_clk_3, qsfp_1_rx_rst_3, txd=qsfp_1_rxd_3, txc=qsfp_1_rxc_3, name='qsfp_1_3_source')
qsfp_1_3_sink = xgmii_ep.XGMIISink()
qsfp_1_3_sink_logic = qsfp_1_3_sink.create_logic(qsfp_1_tx_clk_3, qsfp_1_tx_rst_3, rxd=qsfp_1_txd_3, rxc=qsfp_1_txc_3, name='qsfp_1_3_sink')
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
user_led_g=user_led_g,
user_led_r=user_led_r,
front_led=front_led,
user_sw=user_sw,
qsfp_0_tx_clk_0=qsfp_0_tx_clk_0,
qsfp_0_tx_rst_0=qsfp_0_tx_rst_0,
qsfp_0_txd_0=qsfp_0_txd_0,
qsfp_0_txc_0=qsfp_0_txc_0,
qsfp_0_rx_clk_0=qsfp_0_rx_clk_0,
qsfp_0_rx_rst_0=qsfp_0_rx_rst_0,
qsfp_0_rxd_0=qsfp_0_rxd_0,
qsfp_0_rxc_0=qsfp_0_rxc_0,
qsfp_0_tx_clk_1=qsfp_0_tx_clk_1,
qsfp_0_tx_rst_1=qsfp_0_tx_rst_1,
qsfp_0_txd_1=qsfp_0_txd_1,
qsfp_0_txc_1=qsfp_0_txc_1,
qsfp_0_rx_clk_1=qsfp_0_rx_clk_1,
qsfp_0_rx_rst_1=qsfp_0_rx_rst_1,
qsfp_0_rxd_1=qsfp_0_rxd_1,
qsfp_0_rxc_1=qsfp_0_rxc_1,
qsfp_0_tx_clk_2=qsfp_0_tx_clk_2,
qsfp_0_tx_rst_2=qsfp_0_tx_rst_2,
qsfp_0_txd_2=qsfp_0_txd_2,
qsfp_0_txc_2=qsfp_0_txc_2,
qsfp_0_rx_clk_2=qsfp_0_rx_clk_2,
qsfp_0_rx_rst_2=qsfp_0_rx_rst_2,
qsfp_0_rxd_2=qsfp_0_rxd_2,
qsfp_0_rxc_2=qsfp_0_rxc_2,
qsfp_0_tx_clk_3=qsfp_0_tx_clk_3,
qsfp_0_tx_rst_3=qsfp_0_tx_rst_3,
qsfp_0_txd_3=qsfp_0_txd_3,
qsfp_0_txc_3=qsfp_0_txc_3,
qsfp_0_rx_clk_3=qsfp_0_rx_clk_3,
qsfp_0_rx_rst_3=qsfp_0_rx_rst_3,
qsfp_0_rxd_3=qsfp_0_rxd_3,
qsfp_0_rxc_3=qsfp_0_rxc_3,
qsfp_1_tx_clk_0=qsfp_1_tx_clk_0,
qsfp_1_tx_rst_0=qsfp_1_tx_rst_0,
qsfp_1_txd_0=qsfp_1_txd_0,
qsfp_1_txc_0=qsfp_1_txc_0,
qsfp_1_rx_clk_0=qsfp_1_rx_clk_0,
qsfp_1_rx_rst_0=qsfp_1_rx_rst_0,
qsfp_1_rxd_0=qsfp_1_rxd_0,
qsfp_1_rxc_0=qsfp_1_rxc_0,
qsfp_1_tx_clk_1=qsfp_1_tx_clk_1,
qsfp_1_tx_rst_1=qsfp_1_tx_rst_1,
qsfp_1_txd_1=qsfp_1_txd_1,
qsfp_1_txc_1=qsfp_1_txc_1,
qsfp_1_rx_clk_1=qsfp_1_rx_clk_1,
qsfp_1_rx_rst_1=qsfp_1_rx_rst_1,
qsfp_1_rxd_1=qsfp_1_rxd_1,
qsfp_1_rxc_1=qsfp_1_rxc_1,
qsfp_1_tx_clk_2=qsfp_1_tx_clk_2,
qsfp_1_tx_rst_2=qsfp_1_tx_rst_2,
qsfp_1_txd_2=qsfp_1_txd_2,
qsfp_1_txc_2=qsfp_1_txc_2,
qsfp_1_rx_clk_2=qsfp_1_rx_clk_2,
qsfp_1_rx_rst_2=qsfp_1_rx_rst_2,
qsfp_1_rxd_2=qsfp_1_rxd_2,
qsfp_1_rxc_2=qsfp_1_rxc_2,
qsfp_1_tx_clk_3=qsfp_1_tx_clk_3,
qsfp_1_tx_rst_3=qsfp_1_tx_rst_3,
qsfp_1_txd_3=qsfp_1_txd_3,
qsfp_1_txc_3=qsfp_1_txc_3,
qsfp_1_rx_clk_3=qsfp_1_rx_clk_3,
qsfp_1_rx_rst_3=qsfp_1_rx_rst_3,
qsfp_1_rxd_3=qsfp_1_rxd_3,
qsfp_1_rxc_3=qsfp_1_rxc_3
)
@always(delay(4))
def clkgen():
clk.next = not clk
qsfp_0_tx_clk_0.next = not qsfp_0_tx_clk_0
qsfp_0_rx_clk_0.next = not qsfp_0_rx_clk_0
qsfp_0_tx_clk_1.next = not qsfp_0_tx_clk_1
qsfp_0_rx_clk_1.next = not qsfp_0_rx_clk_1
qsfp_0_tx_clk_2.next = not qsfp_0_tx_clk_2
qsfp_0_rx_clk_2.next = not qsfp_0_rx_clk_2
qsfp_0_tx_clk_3.next = not qsfp_0_tx_clk_3
qsfp_0_rx_clk_3.next = not qsfp_0_rx_clk_3
qsfp_1_tx_clk_0.next = not qsfp_1_tx_clk_0
qsfp_1_rx_clk_0.next = not qsfp_1_rx_clk_0
qsfp_1_tx_clk_1.next = not qsfp_1_tx_clk_1
qsfp_1_rx_clk_1.next = not qsfp_1_rx_clk_1
qsfp_1_tx_clk_2.next = not qsfp_1_tx_clk_2
qsfp_1_rx_clk_2.next = not qsfp_1_rx_clk_2
qsfp_1_tx_clk_3.next = not qsfp_1_tx_clk_3
qsfp_1_rx_clk_3.next = not qsfp_1_rx_clk_3
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
qsfp_0_tx_rst_1.next = 1
qsfp_0_rx_rst_1.next = 1
qsfp_0_tx_rst_2.next = 1
qsfp_0_rx_rst_2.next = 1
qsfp_0_tx_rst_3.next = 1
qsfp_0_rx_rst_3.next = 1
qsfp_0_tx_rst_0.next = 1
qsfp_0_rx_rst_0.next = 1
qsfp_1_tx_rst_1.next = 1
qsfp_1_rx_rst_1.next = 1
qsfp_1_tx_rst_2.next = 1
qsfp_1_rx_rst_2.next = 1
qsfp_1_tx_rst_3.next = 1
qsfp_1_rx_rst_3.next = 1
qsfp_1_tx_rst_0.next = 1
qsfp_1_rx_rst_0.next = 1
yield clk.posedge
rst.next = 0
qsfp_0_tx_rst_1.next = 0
qsfp_0_rx_rst_1.next = 0
qsfp_0_tx_rst_2.next = 0
qsfp_0_rx_rst_2.next = 0
qsfp_0_tx_rst_3.next = 0
qsfp_0_rx_rst_3.next = 0
qsfp_0_tx_rst_0.next = 0
qsfp_0_rx_rst_0.next = 0
qsfp_1_tx_rst_1.next = 0
qsfp_1_rx_rst_1.next = 0
qsfp_1_tx_rst_2.next = 0
qsfp_1_rx_rst_2.next = 0
qsfp_1_tx_rst_3.next = 0
qsfp_1_rx_rst_3.next = 0
qsfp_1_tx_rst_0.next = 0
qsfp_1_rx_rst_0.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test UDP RX packet")
current_test.next = 1
test_frame = udp_ep.UDPFrame()
test_frame.eth_dest_mac = 0x020000000000
test_frame.eth_src_mac = 0xDAD1D2D3D4D5
test_frame.eth_type = 0x0800
test_frame.ip_version = 4
test_frame.ip_ihl = 5
test_frame.ip_dscp = 0
test_frame.ip_ecn = 0
test_frame.ip_length = None
test_frame.ip_identification = 0
test_frame.ip_flags = 2
test_frame.ip_fragment_offset = 0
test_frame.ip_ttl = 64
test_frame.ip_protocol = 0x11
test_frame.ip_header_checksum = None
test_frame.ip_source_ip = 0xc0a80181
test_frame.ip_dest_ip = 0xc0a80180
test_frame.udp_source_port = 5678
test_frame.udp_dest_port = 1234
test_frame.payload = bytearray(range(32))
test_frame.build()
qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data)
# wait for ARP request packet
while qsfp_0_0_sink.empty():
yield clk.posedge
rx_frame = qsfp_0_0_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0806
assert check_frame.arp_htype == 0x0001
assert check_frame.arp_ptype == 0x0800
assert check_frame.arp_hlen == 6
assert check_frame.arp_plen == 4
assert check_frame.arp_oper == 1
assert check_frame.arp_sha == 0x020000000000
assert check_frame.arp_spa == 0xc0a80180
assert check_frame.arp_tha == 0x000000000000
assert check_frame.arp_tpa == 0xc0a80181
# generate response
arp_frame = arp_ep.ARPFrame()
arp_frame.eth_dest_mac = 0x020000000000
arp_frame.eth_src_mac = 0xDAD1D2D3D4D5
arp_frame.eth_type = 0x0806
arp_frame.arp_htype = 0x0001
arp_frame.arp_ptype = 0x0800
arp_frame.arp_hlen = 6
arp_frame.arp_plen = 4
arp_frame.arp_oper = 2
arp_frame.arp_sha = 0xDAD1D2D3D4D5
arp_frame.arp_spa = 0xc0a80181
arp_frame.arp_tha = 0x020000000000
arp_frame.arp_tpa = 0xc0a80180
qsfp_0_0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data)
while qsfp_0_0_sink.empty():
yield clk.posedge
rx_frame = qsfp_0_0_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = udp_ep.UDPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0800
assert check_frame.ip_version == 4
assert check_frame.ip_ihl == 5
assert check_frame.ip_dscp == 0
assert check_frame.ip_ecn == 0
assert check_frame.ip_identification == 0
assert check_frame.ip_flags == 2
assert check_frame.ip_fragment_offset == 0
assert check_frame.ip_ttl == 64
assert check_frame.ip_protocol == 0x11
assert check_frame.ip_source_ip == 0xc0a80180
assert check_frame.ip_dest_ip == 0xc0a80181
assert check_frame.udp_source_port == 1234
assert check_frame.udp_dest_port == 5678
assert check_frame.payload.data == bytearray(range(32))
assert qsfp_0_0_source.empty()
assert qsfp_0_0_sink.empty()
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,269 @@
/*
Copyright (c) 2016-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for fpga_core
*/
module test_fpga_core;
// Parameters
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [1:0] user_sw = 0;
reg qsfp_0_tx_clk_0 = 0;
reg qsfp_0_tx_rst_0 = 0;
reg qsfp_0_rx_clk_0 = 0;
reg qsfp_0_rx_rst_0 = 0;
reg [63:0] qsfp_0_rxd_0 = 0;
reg [7:0] qsfp_0_rxc_0 = 0;
reg qsfp_0_tx_clk_1 = 0;
reg qsfp_0_tx_rst_1 = 0;
reg qsfp_0_rx_clk_1 = 0;
reg qsfp_0_rx_rst_1 = 0;
reg [63:0] qsfp_0_rxd_1 = 0;
reg [7:0] qsfp_0_rxc_1 = 0;
reg qsfp_0_tx_clk_2 = 0;
reg qsfp_0_tx_rst_2 = 0;
reg qsfp_0_rx_clk_2 = 0;
reg qsfp_0_rx_rst_2 = 0;
reg [63:0] qsfp_0_rxd_2 = 0;
reg [7:0] qsfp_0_rxc_2 = 0;
reg qsfp_0_tx_clk_3 = 0;
reg qsfp_0_tx_rst_3 = 0;
reg qsfp_0_rx_clk_3 = 0;
reg qsfp_0_rx_rst_3 = 0;
reg [63:0] qsfp_0_rxd_3 = 0;
reg [7:0] qsfp_0_rxc_3 = 0;
reg qsfp_1_tx_clk_0 = 0;
reg qsfp_1_tx_rst_0 = 0;
reg qsfp_1_rx_clk_0 = 0;
reg qsfp_1_rx_rst_0 = 0;
reg [63:0] qsfp_1_rxd_0 = 0;
reg [7:0] qsfp_1_rxc_0 = 0;
reg qsfp_1_tx_clk_1 = 0;
reg qsfp_1_tx_rst_1 = 0;
reg qsfp_1_rx_clk_1 = 0;
reg qsfp_1_rx_rst_1 = 0;
reg [63:0] qsfp_1_rxd_1 = 0;
reg [7:0] qsfp_1_rxc_1 = 0;
reg qsfp_1_tx_clk_2 = 0;
reg qsfp_1_tx_rst_2 = 0;
reg qsfp_1_rx_clk_2 = 0;
reg qsfp_1_rx_rst_2 = 0;
reg [63:0] qsfp_1_rxd_2 = 0;
reg [7:0] qsfp_1_rxc_2 = 0;
reg qsfp_1_tx_clk_3 = 0;
reg qsfp_1_tx_rst_3 = 0;
reg qsfp_1_rx_clk_3 = 0;
reg qsfp_1_rx_rst_3 = 0;
reg [63:0] qsfp_1_rxd_3 = 0;
reg [7:0] qsfp_1_rxc_3 = 0;
// Outputs
wire [1:0] user_led_g;
wire user_led_r;
wire [1:0] front_led;
wire [63:0] qsfp_0_txd_0;
wire [7:0] qsfp_0_txc_0;
wire [63:0] qsfp_0_txd_1;
wire [7:0] qsfp_0_txc_1;
wire [63:0] qsfp_0_txd_2;
wire [7:0] qsfp_0_txc_2;
wire [63:0] qsfp_0_txd_3;
wire [7:0] qsfp_0_txc_3;
wire [63:0] qsfp_1_txd_0;
wire [7:0] qsfp_1_txc_0;
wire [63:0] qsfp_1_txd_1;
wire [7:0] qsfp_1_txc_1;
wire [63:0] qsfp_1_txd_2;
wire [7:0] qsfp_1_txc_2;
wire [63:0] qsfp_1_txd_3;
wire [7:0] qsfp_1_txc_3;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
user_sw,
qsfp_0_tx_clk_0,
qsfp_0_tx_rst_0,
qsfp_0_rx_clk_0,
qsfp_0_rx_rst_0,
qsfp_0_rxd_0,
qsfp_0_rxc_0,
qsfp_0_tx_clk_1,
qsfp_0_tx_rst_1,
qsfp_0_rx_clk_1,
qsfp_0_rx_rst_1,
qsfp_0_rxd_1,
qsfp_0_rxc_1,
qsfp_0_tx_clk_2,
qsfp_0_tx_rst_2,
qsfp_0_rx_clk_2,
qsfp_0_rx_rst_2,
qsfp_0_rxd_2,
qsfp_0_rxc_2,
qsfp_0_tx_clk_3,
qsfp_0_tx_rst_3,
qsfp_0_rx_clk_3,
qsfp_0_rx_rst_3,
qsfp_0_rxd_3,
qsfp_0_rxc_3,
qsfp_1_tx_clk_0,
qsfp_1_tx_rst_0,
qsfp_1_rx_clk_0,
qsfp_1_rx_rst_0,
qsfp_1_rxd_0,
qsfp_1_rxc_0,
qsfp_1_tx_clk_1,
qsfp_1_tx_rst_1,
qsfp_1_rx_clk_1,
qsfp_1_rx_rst_1,
qsfp_1_rxd_1,
qsfp_1_rxc_1,
qsfp_1_tx_clk_2,
qsfp_1_tx_rst_2,
qsfp_1_rx_clk_2,
qsfp_1_rx_rst_2,
qsfp_1_rxd_2,
qsfp_1_rxc_2,
qsfp_1_tx_clk_3,
qsfp_1_tx_rst_3,
qsfp_1_rx_clk_3,
qsfp_1_rx_rst_3,
qsfp_1_rxd_3,
qsfp_1_rxc_3
);
$to_myhdl(
user_led_g,
user_led_r,
front_led,
qsfp_0_txd_0,
qsfp_0_txc_0,
qsfp_0_txd_1,
qsfp_0_txc_1,
qsfp_0_txd_2,
qsfp_0_txc_2,
qsfp_0_txd_3,
qsfp_0_txc_3,
qsfp_1_txd_0,
qsfp_1_txc_0,
qsfp_1_txd_1,
qsfp_1_txc_1,
qsfp_1_txd_2,
qsfp_1_txc_2,
qsfp_1_txd_3,
qsfp_1_txc_3
);
// dump file
$dumpfile("test_fpga_core.lxt");
$dumpvars(0, test_fpga_core);
end
fpga_core
UUT (
.clk(clk),
.rst(rst),
.user_led_g(user_led_g),
.user_led_r(user_led_r),
.front_led(front_led),
.user_sw(user_sw),
.qsfp_0_tx_clk_0(qsfp_0_tx_clk_0),
.qsfp_0_tx_rst_0(qsfp_0_tx_rst_0),
.qsfp_0_txd_0(qsfp_0_txd_0),
.qsfp_0_txc_0(qsfp_0_txc_0),
.qsfp_0_rx_clk_0(qsfp_0_rx_clk_0),
.qsfp_0_rx_rst_0(qsfp_0_rx_rst_0),
.qsfp_0_rxd_0(qsfp_0_rxd_0),
.qsfp_0_rxc_0(qsfp_0_rxc_0),
.qsfp_0_tx_clk_1(qsfp_0_tx_clk_1),
.qsfp_0_tx_rst_1(qsfp_0_tx_rst_1),
.qsfp_0_txd_1(qsfp_0_txd_1),
.qsfp_0_txc_1(qsfp_0_txc_1),
.qsfp_0_rx_clk_1(qsfp_0_rx_clk_1),
.qsfp_0_rx_rst_1(qsfp_0_rx_rst_1),
.qsfp_0_rxd_1(qsfp_0_rxd_1),
.qsfp_0_rxc_1(qsfp_0_rxc_1),
.qsfp_0_tx_clk_2(qsfp_0_tx_clk_2),
.qsfp_0_tx_rst_2(qsfp_0_tx_rst_2),
.qsfp_0_txd_2(qsfp_0_txd_2),
.qsfp_0_txc_2(qsfp_0_txc_2),
.qsfp_0_rx_clk_2(qsfp_0_rx_clk_2),
.qsfp_0_rx_rst_2(qsfp_0_rx_rst_2),
.qsfp_0_rxd_2(qsfp_0_rxd_2),
.qsfp_0_rxc_2(qsfp_0_rxc_2),
.qsfp_0_tx_clk_3(qsfp_0_tx_clk_3),
.qsfp_0_tx_rst_3(qsfp_0_tx_rst_3),
.qsfp_0_txd_3(qsfp_0_txd_3),
.qsfp_0_txc_3(qsfp_0_txc_3),
.qsfp_0_rx_clk_3(qsfp_0_rx_clk_3),
.qsfp_0_rx_rst_3(qsfp_0_rx_rst_3),
.qsfp_0_rxd_3(qsfp_0_rxd_3),
.qsfp_0_rxc_3(qsfp_0_rxc_3),
.qsfp_1_tx_clk_0(qsfp_1_tx_clk_0),
.qsfp_1_tx_rst_0(qsfp_1_tx_rst_0),
.qsfp_1_txd_0(qsfp_1_txd_0),
.qsfp_1_txc_0(qsfp_1_txc_0),
.qsfp_1_rx_clk_0(qsfp_1_rx_clk_0),
.qsfp_1_rx_rst_0(qsfp_1_rx_rst_0),
.qsfp_1_rxd_0(qsfp_1_rxd_0),
.qsfp_1_rxc_0(qsfp_1_rxc_0),
.qsfp_1_tx_clk_1(qsfp_1_tx_clk_1),
.qsfp_1_tx_rst_1(qsfp_1_tx_rst_1),
.qsfp_1_txd_1(qsfp_1_txd_1),
.qsfp_1_txc_1(qsfp_1_txc_1),
.qsfp_1_rx_clk_1(qsfp_1_rx_clk_1),
.qsfp_1_rx_rst_1(qsfp_1_rx_rst_1),
.qsfp_1_rxd_1(qsfp_1_rxd_1),
.qsfp_1_rxc_1(qsfp_1_rxc_1),
.qsfp_1_tx_clk_2(qsfp_1_tx_clk_2),
.qsfp_1_tx_rst_2(qsfp_1_tx_rst_2),
.qsfp_1_txd_2(qsfp_1_txd_2),
.qsfp_1_txc_2(qsfp_1_txc_2),
.qsfp_1_rx_clk_2(qsfp_1_rx_clk_2),
.qsfp_1_rx_rst_2(qsfp_1_rx_rst_2),
.qsfp_1_rxd_2(qsfp_1_rxd_2),
.qsfp_1_rxc_2(qsfp_1_rxc_2),
.qsfp_1_tx_clk_3(qsfp_1_tx_clk_3),
.qsfp_1_tx_rst_3(qsfp_1_tx_rst_3),
.qsfp_1_txd_3(qsfp_1_txd_3),
.qsfp_1_txc_3(qsfp_1_txc_3),
.qsfp_1_rx_clk_3(qsfp_1_rx_clk_3),
.qsfp_1_rx_rst_3(qsfp_1_rx_rst_3),
.qsfp_1_rxd_3(qsfp_1_rxd_3),
.qsfp_1_rxc_3(qsfp_1_rxc_3)
);
endmodule

View File

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

View File

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

View File

@ -0,0 +1,25 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -0,0 +1,6 @@
# UCF file for clock module domain crossing constraints
NET "clk_int" TNM = "ffs_clk_int";
NET "core_inst/eth_mac_inst/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,194 @@
# 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_tx_clk" LOC = "K16" | IOSTANDARD=LVCMOS25; # IO_L41N_GCLK8_M1CASN (E-TXCLK)
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
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,65 @@
# 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/debounce_switch.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/iddr.v
SYN_FILES += lib/eth/rtl/oddr.v
SYN_FILES += lib/eth/rtl/ssio_sdr_in.v
SYN_FILES += lib/eth/rtl/ssio_sdr_out.v
SYN_FILES += lib/eth/rtl/gmii_phy_if.v
SYN_FILES += lib/eth/rtl/eth_mac_1g_gmii_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_1g_gmii.v
SYN_FILES += lib/eth/rtl/eth_mac_1g.v
SYN_FILES += lib/eth/rtl/axis_gmii_rx.v
SYN_FILES += lib/eth/rtl/axis_gmii_tx.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen.v
SYN_FILES += lib/eth/rtl/udp.v
SYN_FILES += lib/eth/rtl/udp_ip_rx.v
SYN_FILES += lib/eth/rtl/udp_ip_tx.v
SYN_FILES += lib/eth/rtl/ip_complete.v
SYN_FILES += lib/eth/rtl/ip.v
SYN_FILES += lib/eth/rtl/ip_eth_rx.v
SYN_FILES += lib/eth/rtl/ip_eth_tx.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
#SYN_FILES += 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

View File

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

View File

@ -0,0 +1,89 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule

View File

@ -0,0 +1,221 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 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,
input wire phy_tx_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 and reset
wire clk_ibufg;
wire clk_bufg;
wire clk_dcm_out;
// Internal 125 MHz clock
wire clk_int;
wire rst_int;
wire dcm_rst;
wire [7:0] dcm_status;
wire dcm_locked;
wire dcm_clkfx_stopped = dcm_status[2];
assign dcm_rst = ~reset_n | (dcm_clkfx_stopped & ~dcm_locked);
IBUFG
clk_ibufg_inst(
.I(clk),
.O(clk_ibufg)
);
DCM_SP #(
.CLKIN_PERIOD(10),
.CLK_FEEDBACK("NONE"),
.CLKDV_DIVIDE(2.0),
.CLKFX_MULTIPLY(5.0),
.CLKFX_DIVIDE(4.0),
.PHASE_SHIFT(0),
.CLKOUT_PHASE_SHIFT("NONE"),
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"),
.STARTUP_WAIT("FALSE"),
.CLKIN_DIVIDE_BY_2("FALSE")
)
clk_dcm_inst (
.CLKIN(clk_ibufg),
.CLKFB(1'b0),
.RST(dcm_rst),
.PSEN(1'b0),
.PSINCDEC(1'b0),
.PSCLK(1'b0),
.CLK0(),
.CLK90(),
.CLK180(),
.CLK270(),
.CLK2X(),
.CLK2X180(),
.CLKDV(),
.CLKFX(clk_dcm_out),
.CLKFX180(),
.STATUS(dcm_status),
.LOCKED(dcm_locked),
.PSDONE()
);
BUFG
clk_bufg_inst (
.I(clk_dcm_out),
.O(clk_int)
);
sync_reset #(
.N(4)
)
sync_reset_inst (
.clk(clk_int),
.rst(~dcm_locked),
.sync_reset_out(rst_int)
);
// GPIO
wire btnu_int;
wire btnl_int;
wire btnd_int;
wire btnr_int;
wire btnc_int;
wire [7:0] sw_int;
debounce_switch #(
.WIDTH(13),
.N(4),
.RATE(125000)
)
debounce_switch_inst (
.clk(clk_int),
.rst(rst_int),
.in({btnu,
btnl,
btnd,
btnr,
btnc,
sw}),
.out({btnu_int,
btnl_int,
btnd_int,
btnr_int,
btnc_int,
sw_int})
);
sync_signal #(
.WIDTH(1),
.N(2)
)
sync_signal_inst (
.clk(clk_int),
.in({uart_rxd}),
.out({uart_rxd_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),
/*
* Ethernet: 1000BASE-T GMII
*/
.phy_rx_clk(phy_rx_clk),
.phy_rxd(phy_rxd),
.phy_rx_dv(phy_rx_dv),
.phy_rx_er(phy_rx_er),
.phy_gtx_clk(phy_gtx_clk),
.phy_tx_clk(phy_tx_clk),
.phy_txd(phy_txd),
.phy_tx_en(phy_tx_en),
.phy_tx_er(phy_tx_er),
.phy_reset_n(phy_reset_n),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd_int),
.uart_txd(uart_txd)
);
endmodule

View File

@ -0,0 +1,583 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA core logic
*/
module fpga_core #
(
parameter TARGET = "XILINX"
)
(
/*
* 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,
input wire phy_tx_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
);
// AXI between MAC and Ethernet modules
wire [7:0] rx_axis_tdata;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [7:0] tx_axis_tdata;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [7:0] rx_eth_payload_axis_tdata;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [7:0] tx_eth_payload_axis_tdata;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [7:0] rx_ip_payload_axis_tdata;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [7:0] tx_ip_payload_axis_tdata;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [7:0] rx_udp_payload_axis_tdata;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [7:0] tx_udp_payload_axis_tdata;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [7:0] rx_fifo_udp_payload_axis_tdata;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [7:0] tx_fifo_udp_payload_axis_tdata;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
if (tx_udp_payload_axis_tvalid) begin
if (!valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
valid_last <= 1'b1;
end
if (tx_udp_payload_axis_tlast) begin
valid_last <= 1'b0;
end
end
end
end
//assign led = sw;
assign led = led_reg;
assign phy_reset_n = !rst;
assign uart_txd = 0;
eth_mac_1g_gmii_fifo #(
.TARGET(TARGET),
.IODDR_STYLE("IODDR2"),
.CLOCK_INPUT_STYLE("BUFIO2"),
.ENABLE_PADDING(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_ADDR_WIDTH(12),
.TX_FRAME_FIFO(1),
.RX_FIFO_ADDR_WIDTH(12),
.RX_FRAME_FIFO(1)
)
eth_mac_inst (
.gtx_clk(clk),
.gtx_rst(rst),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.gmii_rx_clk(phy_rx_clk),
.gmii_rxd(phy_rxd),
.gmii_rx_dv(phy_rx_dv),
.gmii_rx_er(phy_rx_er),
.gmii_tx_clk(phy_gtx_clk),
.mii_tx_clk(phy_tx_clk),
.gmii_txd(phy_txd),
.gmii_tx_en(phy_tx_en),
.gmii_tx_er(phy_tx_er),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),
.tx_fifo_good_frame(),
.rx_error_bad_frame(),
.rx_error_bad_fcs(),
.rx_fifo_overflow(),
.rx_fifo_bad_frame(),
.rx_fifo_good_frame(),
.speed(),
.ifg_delay(12)
);
eth_axis_rx
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(0)
);
axis_fifo #(
.ADDR_WIDTH(12),
.DATA_WIDTH(8),
.KEEP_ENABLE(0),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(0),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule

View File

@ -0,0 +1,52 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an 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-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule

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,310 @@
#!/usr/bin/env python
"""
Copyright (c) 2015-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import eth_ep
import arp_ep
import udp_ep
import gmii_ep
module = 'fpga_core'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../lib/eth/rtl/iddr.v")
srcs.append("../lib/eth/rtl/oddr.v")
srcs.append("../lib/eth/rtl/ssio_sdr_in.v")
srcs.append("../lib/eth/rtl/ssio_sdr_out.v")
srcs.append("../lib/eth/rtl/gmii_phy_if.v")
srcs.append("../lib/eth/rtl/eth_mac_1g_gmii_fifo.v")
srcs.append("../lib/eth/rtl/eth_mac_1g_gmii.v")
srcs.append("../lib/eth/rtl/eth_mac_1g.v")
srcs.append("../lib/eth/rtl/axis_gmii_rx.v")
srcs.append("../lib/eth/rtl/axis_gmii_tx.v")
srcs.append("../lib/eth/rtl/lfsr.v")
srcs.append("../lib/eth/rtl/eth_axis_rx.v")
srcs.append("../lib/eth/rtl/eth_axis_tx.v")
srcs.append("../lib/eth/rtl/udp_complete.v")
srcs.append("../lib/eth/rtl/udp_checksum_gen.v")
srcs.append("../lib/eth/rtl/udp.v")
srcs.append("../lib/eth/rtl/udp_ip_rx.v")
srcs.append("../lib/eth/rtl/udp_ip_tx.v")
srcs.append("../lib/eth/rtl/ip_complete.v")
srcs.append("../lib/eth/rtl/ip.v")
srcs.append("../lib/eth/rtl/ip_eth_rx.v")
srcs.append("../lib/eth/rtl/ip_eth_tx.v")
srcs.append("../lib/eth/rtl/ip_arb_mux.v")
srcs.append("../lib/eth/rtl/arp.v")
srcs.append("../lib/eth/rtl/arp_cache.v")
srcs.append("../lib/eth/rtl/arp_eth_rx.v")
srcs.append("../lib/eth/rtl/arp_eth_tx.v")
srcs.append("../lib/eth/rtl/eth_arb_mux.v")
srcs.append("../lib/eth/lib/axis/rtl/arbiter.v")
srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
TARGET = "SIM"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
btnu = Signal(bool(0))
btnl = Signal(bool(0))
btnd = Signal(bool(0))
btnr = Signal(bool(0))
btnc = Signal(bool(0))
sw = Signal(intbv(0)[8:])
phy_rx_clk = Signal(bool(0))
phy_rxd = Signal(intbv(0)[8:])
phy_rx_dv = Signal(bool(0))
phy_rx_er = Signal(bool(0))
phy_tx_clk = Signal(bool(0))
uart_rxd = Signal(bool(0))
# Outputs
led = Signal(intbv(0)[8:])
phy_gtx_clk = Signal(bool(0))
phy_txd = Signal(intbv(0)[8:])
phy_tx_en = Signal(bool(0))
phy_tx_er = Signal(bool(0))
phy_reset_n = Signal(bool(0))
uart_txd = Signal(bool(0))
# sources and sinks
mii_select = Signal(bool(0))
gmii_source = gmii_ep.GMIISource()
gmii_source_logic = gmii_source.create_logic(
phy_rx_clk,
rst,
txd=phy_rxd,
tx_en=phy_rx_dv,
tx_er=phy_rx_er,
mii_select=mii_select,
name='gmii_source'
)
gmii_sink = gmii_ep.GMIISink()
gmii_sink_logic = gmii_sink.create_logic(
phy_tx_clk,
rst,
rxd=phy_txd,
rx_dv=phy_tx_en,
rx_er=phy_tx_er,
mii_select=mii_select,
name='gmii_sink'
)
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
btnu=btnu,
btnl=btnl,
btnd=btnd,
btnr=btnr,
btnc=btnc,
sw=sw,
led=led,
phy_rx_clk=phy_rx_clk,
phy_rxd=phy_rxd,
phy_rx_dv=phy_rx_dv,
phy_rx_er=phy_rx_er,
phy_gtx_clk=phy_gtx_clk,
phy_tx_clk=phy_tx_clk,
phy_txd=phy_txd,
phy_tx_en=phy_tx_en,
phy_tx_er=phy_tx_er,
phy_reset_n=phy_reset_n,
uart_rxd=uart_rxd,
uart_txd=uart_txd
)
@always(delay(4))
def clkgen():
clk.next = not clk
rx_clk_hp = Signal(int(4))
@instance
def rx_clk_gen():
while True:
yield delay(int(rx_clk_hp))
phy_rx_clk.next = not phy_rx_clk
phy_tx_clk.next = not phy_tx_clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test UDP RX packet")
current_test.next = 1
test_frame = udp_ep.UDPFrame()
test_frame.eth_dest_mac = 0x020000000000
test_frame.eth_src_mac = 0xDAD1D2D3D4D5
test_frame.eth_type = 0x0800
test_frame.ip_version = 4
test_frame.ip_ihl = 5
test_frame.ip_dscp = 0
test_frame.ip_ecn = 0
test_frame.ip_length = None
test_frame.ip_identification = 0
test_frame.ip_flags = 2
test_frame.ip_fragment_offset = 0
test_frame.ip_ttl = 64
test_frame.ip_protocol = 0x11
test_frame.ip_header_checksum = None
test_frame.ip_source_ip = 0xc0a80181
test_frame.ip_dest_ip = 0xc0a80180
test_frame.udp_source_port = 5678
test_frame.udp_dest_port = 1234
test_frame.payload = bytearray(range(32))
test_frame.build()
gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data)
# wait for ARP request packet
while gmii_sink.empty():
yield clk.posedge
rx_frame = gmii_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0806
assert check_frame.arp_htype == 0x0001
assert check_frame.arp_ptype == 0x0800
assert check_frame.arp_hlen == 6
assert check_frame.arp_plen == 4
assert check_frame.arp_oper == 1
assert check_frame.arp_sha == 0x020000000000
assert check_frame.arp_spa == 0xc0a80180
assert check_frame.arp_tha == 0x000000000000
assert check_frame.arp_tpa == 0xc0a80181
# generate response
arp_frame = arp_ep.ARPFrame()
arp_frame.eth_dest_mac = 0x020000000000
arp_frame.eth_src_mac = 0xDAD1D2D3D4D5
arp_frame.eth_type = 0x0806
arp_frame.arp_htype = 0x0001
arp_frame.arp_ptype = 0x0800
arp_frame.arp_hlen = 6
arp_frame.arp_plen = 4
arp_frame.arp_oper = 2
arp_frame.arp_sha = 0xDAD1D2D3D4D5
arp_frame.arp_spa = 0xc0a80181
arp_frame.arp_tha = 0x020000000000
arp_frame.arp_tpa = 0xc0a80180
gmii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data)
while gmii_sink.empty():
yield clk.posedge
rx_frame = gmii_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = udp_ep.UDPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0800
assert check_frame.ip_version == 4
assert check_frame.ip_ihl == 5
assert check_frame.ip_dscp == 0
assert check_frame.ip_ecn == 0
assert check_frame.ip_identification == 0
assert check_frame.ip_flags == 2
assert check_frame.ip_fragment_offset == 0
assert check_frame.ip_ttl == 64
assert check_frame.ip_protocol == 0x11
assert check_frame.ip_source_ip == 0xc0a80180
assert check_frame.ip_dest_ip == 0xc0a80181
assert check_frame.udp_source_port == 1234
assert check_frame.udp_dest_port == 5678
assert check_frame.payload.data == bytearray(range(32))
assert gmii_source.empty()
assert gmii_sink.empty()
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,125 @@
/*
Copyright (c) 2015-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for fpga_core
*/
module test_fpga_core;
// Parameters
parameter TARGET = "SIM";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg btnu = 0;
reg btnl = 0;
reg btnd = 0;
reg btnr = 0;
reg btnc = 0;
reg [7:0] sw = 0;
reg phy_rx_clk = 0;
reg [7:0] phy_rxd = 0;
reg phy_rx_dv = 0;
reg phy_rx_er = 0;
reg phy_tx_clk = 0;
reg uart_rxd = 0;
// Outputs
wire [7:0] led;
wire phy_gtx_clk;
wire [7:0] phy_txd;
wire phy_tx_en;
wire phy_tx_er;
wire phy_reset_n;
wire uart_txd;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
btnu,
btnl,
btnd,
btnr,
btnc,
sw,
phy_rx_clk,
phy_rxd,
phy_rx_dv,
phy_rx_er,
phy_tx_clk,
uart_rxd
);
$to_myhdl(
led,
phy_gtx_clk,
phy_txd,
phy_tx_en,
phy_tx_er,
phy_reset_n,
uart_txd
);
// dump file
$dumpfile("test_fpga_core.lxt");
$dumpvars(0, test_fpga_core);
end
fpga_core #(
.TARGET(TARGET)
)
UUT (
.clk(clk),
.rst(rst),
.btnu(btnu),
.btnl(btnl),
.btnd(btnd),
.btnr(btnr),
.btnc(btnc),
.sw(sw),
.led(led),
.phy_rx_clk(phy_rx_clk),
.phy_rxd(phy_rxd),
.phy_rx_dv(phy_rx_dv),
.phy_rx_er(phy_rx_er),
.phy_gtx_clk(phy_gtx_clk),
.phy_tx_clk(phy_tx_clk),
.phy_txd(phy_txd),
.phy_tx_en(phy_tx_en),
.phy_tx_er(phy_tx_er),
.phy_reset_n(phy_reset_n),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd)
);
endmodule

View File

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

View File

@ -0,0 +1,25 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -0,0 +1,25 @@
# Verilog Ethernet Arty Example Design
## Introduction
This example design targets the Digilent Arty FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
FPGA: XC7A35TICSG324-1L
PHY: TI DP83848J
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the Arty board with Vivado. Then run netcat -u
192.168.1.128 1234 to open a UDP connection to port 1234. Any text entered
into netcat will be echoed back after pressing enter.

View File

@ -0,0 +1,118 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale)
# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e)
# SYN_FILES - space-separated list of source files
# INC_FILES - space-separated list of include files
# XDC_FILES - space-separated list of timing constraint files
# XCI_FILES - space-separated list of IP XCI files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = VirtexUltrascale
# FPGA_DEVICE = xcvu095-ffva2104-2-e
# SYN_FILES = rtl/fpga.v
# XDC_FILES = fpga.xdc
# XCI_FILES = ip/pcspma.xci
# include ../common/vivado.mk
#
###################################################################
# phony targets
.PHONY: clean fpga
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES))
INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES))
XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES))
ifdef XDC_FILES
XDC_FILES_REL = $(patsubst %, ../%, $(XDC_FILES))
else
XDC_FILES_REL = $(FPGA_TOP).xdc
endif
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and project files
###################################################################
all: fpga
fpga: $(FPGA_TOP).bit
tmpclean:
-rm -rf *.log *.jou *.cache *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.tcl run_synth.tcl run_impl.tcl generate_bit.tcl
clean: tmpclean
-rm -rf *.bit program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl
distclean: clean
-rm -rf rev
###################################################################
# Target implementations
###################################################################
# Vivado project file
%.xpr: Makefile $(XCI_FILES_REL)
rm -rf defines.v
touch defines.v
for x in $(DEFS); do echo '`define' $$x >> defines.v; done
echo "create_project -force -part $(FPGA_PART) $*" > create_project.tcl
echo "add_files -fileset sources_1 defines.v" >> create_project.tcl
for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done
for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done
echo "exit" >> create_project.tcl
vivado -nojournal -nolog -mode batch -source create_project.tcl
# synthesis run
%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project $*.xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
echo "exit" >> run_synth.tcl
vivado -nojournal -nolog -mode batch -source run_synth.tcl
# implementation run
%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp
echo "open_project $*.xpr" > run_impl.tcl
echo "reset_run impl_1" >> run_impl.tcl
echo "launch_runs impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "exit" >> run_impl.tcl
vivado -nojournal -nolog -mode batch -source run_impl.tcl
# bit file
%.bit: %.runs/impl_1/%_routed.dcp
echo "open_project $*.xpr" > generate_bit.tcl
echo "open_run impl_1" >> generate_bit.tcl
echo "write_bitstream -force $*.bit" >> generate_bit.tcl
echo "exit" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
mkdir -p rev
EXT=bit; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do COUNT=$$((COUNT+1)); done; \
cp $@ rev/$*_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_rev$$COUNT.$$EXT";

View File

@ -0,0 +1,113 @@
# XDC constraints for the Digilent Arty board
# part: xc7a35t-csg324-1
# General configuration
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
# 100 MHz clock
set_property -dict {LOC E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 10.000 -name clk [get_ports clk]
# LEDs
set_property -dict {LOC G6 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led0_r]
set_property -dict {LOC F6 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led0_g]
set_property -dict {LOC E1 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led0_b]
set_property -dict {LOC G3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led1_r]
set_property -dict {LOC J4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led1_g]
set_property -dict {LOC G4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led1_b]
set_property -dict {LOC J3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led2_r]
set_property -dict {LOC J2 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led2_g]
set_property -dict {LOC H4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led2_b]
set_property -dict {LOC K1 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led3_r]
set_property -dict {LOC H6 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led3_g]
set_property -dict {LOC K2 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led3_b]
set_property -dict {LOC H5 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led4]
set_property -dict {LOC J5 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led5]
set_property -dict {LOC T9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led6]
set_property -dict {LOC T10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports led7]
# Reset button
set_property -dict {LOC C2 IOSTANDARD LVCMOS33} [get_ports reset_n]
# Push buttons
set_property -dict {LOC D9 IOSTANDARD LVCMOS33} [get_ports {btn[0]}]
set_property -dict {LOC C9 IOSTANDARD LVCMOS33} [get_ports {btn[1]}]
set_property -dict {LOC B9 IOSTANDARD LVCMOS33} [get_ports {btn[2]}]
set_property -dict {LOC B8 IOSTANDARD LVCMOS33} [get_ports {btn[3]}]
# Toggle switches
set_property -dict {LOC A8 IOSTANDARD LVCMOS33} [get_ports {sw[0]}]
set_property -dict {LOC C11 IOSTANDARD LVCMOS33} [get_ports {sw[1]}]
set_property -dict {LOC C10 IOSTANDARD LVCMOS33} [get_ports {sw[2]}]
set_property -dict {LOC A10 IOSTANDARD LVCMOS33} [get_ports {sw[3]}]
# GPIO
# PMOD JA
#set_property -dict {LOC G13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja1}] ;# PMOD JA pin 1
#set_property -dict {LOC B11 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja2}] ;# PMOD JA pin 2
#set_property -dict {LOC A11 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja3}] ;# PMOD JA pin 3
#set_property -dict {LOC D12 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja4}] ;# PMOD JA pin 4
#set_property -dict {LOC D13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja7}] ;# PMOD JA pin 7
#set_property -dict {LOC B18 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja8}] ;# PMOD JA pin 8
#set_property -dict {LOC A18 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja9}] ;# PMOD JA pin 9
#set_property -dict {LOC K16 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_ja10}] ;# PMOD JA pin 10
# PMOD JB
#set_property -dict {LOC E15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb1}] ;# PMOD JB pin 1
#set_property -dict {LOC E16 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb2}] ;# PMOD JB pin 2
#set_property -dict {LOC D15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb3}] ;# PMOD JB pin 3
#set_property -dict {LOC C15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb4}] ;# PMOD JB pin 4
#set_property -dict {LOC J17 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb7}] ;# PMOD JB pin 7
#set_property -dict {LOC J18 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb8}] ;# PMOD JB pin 8
#set_property -dict {LOC K15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb9}] ;# PMOD JB pin 9
#set_property -dict {LOC J15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jb10}] ;# PMOD JB pin 10
# PMOD JC
#set_property -dict {LOC U12 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc1}] ;# PMOD JC pin 1
#set_property -dict {LOC V12 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc2}] ;# PMOD JC pin 2
#set_property -dict {LOC V10 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc3}] ;# PMOD JC pin 3
#set_property -dict {LOC V11 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc4}] ;# PMOD JC pin 4
#set_property -dict {LOC U14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc7}] ;# PMOD JC pin 7
#set_property -dict {LOC V14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc8}] ;# PMOD JC pin 8
#set_property -dict {LOC T13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc9}] ;# PMOD JC pin 9
#set_property -dict {LOC U13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jc10}] ;# PMOD JC pin 10
# PMOD JD
#set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd1}] ;# PMOD JD pin 1
#set_property -dict {LOC D3 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd2}] ;# PMOD JD pin 2
#set_property -dict {LOC F4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd3}] ;# PMOD JD pin 3
#set_property -dict {LOC F3 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd4}] ;# PMOD JD pin 4
#set_property -dict {LOC E2 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd7}] ;# PMOD JD pin 7
#set_property -dict {LOC D2 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd8}] ;# PMOD JD pin 8
#set_property -dict {LOC H2 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd9}] ;# PMOD JD pin 9
#set_property -dict {LOC G2 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {gpio_jd10}] ;# PMOD JD pin 10
# UART
set_property -dict {LOC D10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports uart_txd]
set_property -dict {LOC A9 IOSTANDARD LVCMOS33} [get_ports uart_rxd]
# Ethernet MII PHY
set_property -dict {LOC F15 IOSTANDARD LVCMOS33} [get_ports phy_rx_clk]
set_property -dict {LOC D18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[0]}]
set_property -dict {LOC E17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[1]}]
set_property -dict {LOC E18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[2]}]
set_property -dict {LOC G17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[3]}]
set_property -dict {LOC G16 IOSTANDARD LVCMOS33} [get_ports phy_rx_dv]
set_property -dict {LOC C17 IOSTANDARD LVCMOS33} [get_ports phy_rx_er]
set_property -dict {LOC H16 IOSTANDARD LVCMOS33} [get_ports phy_tx_clk]
set_property -dict {LOC H14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[0]}]
set_property -dict {LOC J14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[1]}]
set_property -dict {LOC J13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[2]}]
set_property -dict {LOC H17 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[3]}]
set_property -dict {LOC H15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports phy_tx_en]
set_property -dict {LOC D17 IOSTANDARD LVCMOS33} [get_ports phy_col]
set_property -dict {LOC G14 IOSTANDARD LVCMOS33} [get_ports phy_crs]
set_property -dict {LOC G18 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_ref_clk]
set_property -dict {LOC C16 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_reset_n]
#set_property -dict {LOC K13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_mdio]
#set_property -dict {LOC F16 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_mdc]
create_clock -period 40.000 -name phy_rx_clk [get_ports phy_rx_clk]
create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk]

View File

@ -0,0 +1,98 @@
# FPGA settings
FPGA_PART = xc7a35t-csg324-1
FPGA_TOP = fpga
FPGA_ARCH = artix7
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/ssio_sdr_in.v
SYN_FILES += lib/eth/rtl/mii_phy_if.v
SYN_FILES += lib/eth/rtl/eth_mac_mii_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_mii.v
SYN_FILES += lib/eth/rtl/eth_mac_1g.v
SYN_FILES += lib/eth/rtl/axis_gmii_rx.v
SYN_FILES += lib/eth/rtl/axis_gmii_tx.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen.v
SYN_FILES += lib/eth/rtl/udp.v
SYN_FILES += lib/eth/rtl/udp_ip_rx.v
SYN_FILES += lib/eth/rtl/udp_ip_tx.v
SYN_FILES += lib/eth/rtl/ip_complete.v
SYN_FILES += lib/eth/rtl/ip.v
SYN_FILES += lib/eth/rtl/ip_eth_rx.v
SYN_FILES += lib/eth/rtl/ip_eth_tx.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/mii_phy_if.tcl
XDC_FILES += lib/eth/syn/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/axis_async_fifo.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%.mcs %.prm: %.bit
echo "write_cfgmem -force -format mcs -size 16 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25ql128-spi-x1_x2_x4}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

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

View File

@ -0,0 +1,89 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule

View File

@ -0,0 +1,267 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 100MHz
* Reset: Push button, active low
*/
input wire clk,
input wire reset_n,
/*
* GPIO
*/
input wire [3:0] sw,
input wire [3:0] btn,
output wire led0_r,
output wire led0_g,
output wire led0_b,
output wire led1_r,
output wire led1_g,
output wire led1_b,
output wire led2_r,
output wire led2_g,
output wire led2_b,
output wire led3_r,
output wire led3_g,
output wire led3_b,
output wire led4,
output wire led5,
output wire led6,
output wire led7,
/*
* Ethernet: 100BASE-T MII
*/
output wire phy_ref_clk,
input wire phy_rx_clk,
input wire [3:0] phy_rxd,
input wire phy_rx_dv,
input wire phy_rx_er,
input wire phy_tx_clk,
output wire [3:0] phy_txd,
output wire phy_tx_en,
input wire phy_col,
input wire phy_crs,
output wire phy_reset_n,
/*
* UART: 500000 bps, 8N1
*/
input wire uart_rxd,
output wire uart_txd
);
// Clock and reset
wire clk_ibufg;
wire clk_bufg;
wire clk_mmcm_out;
// Internal 125 MHz clock
wire clk_int;
wire rst_int;
wire mmcm_rst = ~reset_n;
wire mmcm_locked;
wire mmcm_clkfb;
IBUFG
clk_ibufg_inst(
.I(clk),
.O(clk_ibufg)
);
wire clk_25mhz_mmcm_out;
wire clk_25mhz_int;
// MMCM instance
// 100 MHz in, 125 MHz out
// PFD range: 10 MHz to 550 MHz
// VCO range: 600 MHz to 1200 MHz
// M = 10, D = 1 sets Fvco = 1000 MHz (in range)
// Divide by 8 to get output frequency of 125 MHz
// Divide by 40 to get output frequency of 25 MHz
// 1000 / 5 = 200 MHz
MMCME2_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(8),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0),
.CLKOUT1_DIVIDE(40),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT1_PHASE(0),
.CLKOUT2_DIVIDE(1),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT2_PHASE(0),
.CLKOUT3_DIVIDE(1),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0),
.CLKOUT4_DIVIDE(1),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT5_DIVIDE(1),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT5_PHASE(0),
.CLKOUT6_DIVIDE(1),
.CLKOUT6_DUTY_CYCLE(0.5),
.CLKOUT6_PHASE(0),
.CLKFBOUT_MULT_F(10),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(1),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(10.0),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_ibufg),
.CLKFBIN(mmcm_clkfb),
.RST(mmcm_rst),
.PWRDWN(1'b0),
.CLKOUT0(clk_mmcm_out),
.CLKOUT0B(),
.CLKOUT1(clk_25mhz_mmcm_out),
.CLKOUT1B(),
.CLKOUT2(),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
.CLKOUT4(),
.CLKOUT5(),
.CLKOUT6(),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
.LOCKED(mmcm_locked)
);
BUFG
clk_bufg_inst (
.I(clk_mmcm_out),
.O(clk_int)
);
BUFG
clk_25mhz_bufg_inst (
.I(clk_25mhz_mmcm_out),
.O(clk_25mhz_int)
);
sync_reset #(
.N(4)
)
sync_reset_inst (
.clk(clk_int),
.rst(~mmcm_locked),
.sync_reset_out(rst_int)
);
// GPIO
wire [3:0] btn_int;
wire [3:0] sw_int;
debounce_switch #(
.WIDTH(8),
.N(4),
.RATE(125000)
)
debounce_switch_inst (
.clk(clk_int),
.rst(rst_int),
.in({btn,
sw}),
.out({btn_int,
sw_int})
);
sync_signal #(
.WIDTH(1),
.N(2)
)
sync_signal_inst (
.clk(clk_int),
.in({uart_rxd}),
.out({uart_rxd_int})
);
assign phy_ref_clk = clk_25mhz_int;
fpga_core
core_inst (
/*
* Clock: 125MHz
* Synchronous reset
*/
.clk(clk_int),
.rst(rst_int),
/*
* GPIO
*/
.btn(btn_int),
.sw(sw_int),
.led0_r(led0_r),
.led0_g(led0_g),
.led0_b(led0_b),
.led1_r(led1_r),
.led1_g(led1_g),
.led1_b(led1_b),
.led2_r(led2_r),
.led2_g(led2_g),
.led2_b(led2_b),
.led3_r(led3_r),
.led3_g(led3_g),
.led3_b(led3_b),
.led4(led4),
.led5(led5),
.led6(led6),
.led7(led7),
/*
* Ethernet: 100BASE-T MII
*/
.phy_rx_clk(phy_rx_clk),
.phy_rxd(phy_rxd),
.phy_rx_dv(phy_rx_dv),
.phy_rx_er(phy_rx_er),
.phy_tx_clk(phy_tx_clk),
.phy_txd(phy_txd),
.phy_tx_en(phy_tx_en),
.phy_col(phy_col),
.phy_crs(phy_crs),
.phy_reset_n(phy_reset_n),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd_int),
.uart_txd(uart_txd)
);
endmodule

View File

@ -0,0 +1,590 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA core logic
*/
module fpga_core #
(
parameter TARGET = "XILINX"
)
(
/*
* Clock: 125MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [3:0] btn,
input wire [3:0] sw,
output wire led0_r,
output wire led0_g,
output wire led0_b,
output wire led1_r,
output wire led1_g,
output wire led1_b,
output wire led2_r,
output wire led2_g,
output wire led2_b,
output wire led3_r,
output wire led3_g,
output wire led3_b,
output wire led4,
output wire led5,
output wire led6,
output wire led7,
/*
* Ethernet: 100BASE-T MII
*/
input wire phy_rx_clk,
input wire [3:0] phy_rxd,
input wire phy_rx_dv,
input wire phy_rx_er,
input wire phy_tx_clk,
output wire [3:0] phy_txd,
output wire phy_tx_en,
input wire phy_col,
input wire phy_crs,
output wire phy_reset_n,
/*
* UART: 115200 bps, 8N1
*/
input wire uart_rxd,
output wire uart_txd
);
// AXI between MAC and Ethernet modules
wire [7:0] rx_axis_tdata;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [7:0] tx_axis_tdata;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [7:0] rx_eth_payload_axis_tdata;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [7:0] tx_eth_payload_axis_tdata;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [7:0] rx_ip_payload_axis_tdata;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [7:0] tx_ip_payload_axis_tdata;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [7:0] rx_udp_payload_axis_tdata;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [7:0] tx_udp_payload_axis_tdata;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [7:0] rx_fifo_udp_payload_axis_tdata;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [7:0] tx_fifo_udp_payload_axis_tdata;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
if (tx_udp_payload_axis_tvalid) begin
if (!valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
valid_last <= 1'b1;
end
if (tx_udp_payload_axis_tlast) begin
valid_last <= 1'b0;
end
end
end
end
//assign led = sw;
assign {led0_g, led1_g, led2_g, led3_g, led4, led5, led6, led7} = led_reg;
assign phy_reset_n = !rst;
assign uart_txd = 0;
eth_mac_mii_fifo #(
.TARGET(TARGET),
.CLOCK_INPUT_STYLE("BUFR"),
.ENABLE_PADDING(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_ADDR_WIDTH(12),
.TX_FRAME_FIFO(1),
.RX_FIFO_ADDR_WIDTH(12),
.RX_FRAME_FIFO(1)
)
eth_mac_inst (
.rst(rst),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.mii_rx_clk(phy_rx_clk),
.mii_rxd(phy_rxd),
.mii_rx_dv(phy_rx_dv),
.mii_rx_er(phy_rx_er),
.mii_tx_clk(phy_tx_clk),
.mii_txd(phy_txd),
.mii_tx_en(phy_tx_en),
.mii_tx_er(),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),
.tx_fifo_good_frame(),
.rx_error_bad_frame(),
.rx_error_bad_fcs(),
.rx_fifo_overflow(),
.rx_fifo_bad_frame(),
.rx_fifo_good_frame(),
.ifg_delay(12)
);
eth_axis_rx
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(0)
);
axis_fifo #(
.ADDR_WIDTH(12),
.DATA_WIDTH(8),
.KEEP_ENABLE(0),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(0),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule

View File

@ -0,0 +1,52 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an 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-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule

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/ip_ep.py

View File

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

View File

@ -0,0 +1,325 @@
#!/usr/bin/env python
"""
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import eth_ep
import arp_ep
import udp_ep
import mii_ep
module = 'fpga_core'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../lib/eth/rtl/ssio_sdr_in.v")
srcs.append("../lib/eth/rtl/mii_phy_if.v")
srcs.append("../lib/eth/rtl/eth_mac_mii_fifo.v")
srcs.append("../lib/eth/rtl/eth_mac_mii.v")
srcs.append("../lib/eth/rtl/eth_mac_1g.v")
srcs.append("../lib/eth/rtl/axis_gmii_rx.v")
srcs.append("../lib/eth/rtl/axis_gmii_tx.v")
srcs.append("../lib/eth/rtl/lfsr.v")
srcs.append("../lib/eth/rtl/eth_axis_rx.v")
srcs.append("../lib/eth/rtl/eth_axis_tx.v")
srcs.append("../lib/eth/rtl/udp_complete.v")
srcs.append("../lib/eth/rtl/udp_checksum_gen.v")
srcs.append("../lib/eth/rtl/udp.v")
srcs.append("../lib/eth/rtl/udp_ip_rx.v")
srcs.append("../lib/eth/rtl/udp_ip_tx.v")
srcs.append("../lib/eth/rtl/ip_complete.v")
srcs.append("../lib/eth/rtl/ip.v")
srcs.append("../lib/eth/rtl/ip_eth_rx.v")
srcs.append("../lib/eth/rtl/ip_eth_tx.v")
srcs.append("../lib/eth/rtl/ip_arb_mux.v")
srcs.append("../lib/eth/rtl/arp.v")
srcs.append("../lib/eth/rtl/arp_cache.v")
srcs.append("../lib/eth/rtl/arp_eth_rx.v")
srcs.append("../lib/eth/rtl/arp_eth_tx.v")
srcs.append("../lib/eth/rtl/eth_arb_mux.v")
srcs.append("../lib/eth/lib/axis/rtl/arbiter.v")
srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
TARGET = "SIM"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
btn = Signal(intbv(0)[4:])
sw = Signal(intbv(0)[4:])
phy_rx_clk = Signal(bool(0))
phy_rxd = Signal(intbv(0)[4:])
phy_rx_dv = Signal(bool(0))
phy_rx_er = Signal(bool(0))
phy_col = Signal(bool(0))
phy_crs = Signal(bool(0))
uart_rxd = Signal(bool(0))
# Outputs
led0_r = Signal(bool(0))
led0_g = Signal(bool(0))
led0_b = Signal(bool(0))
led1_r = Signal(bool(0))
led1_g = Signal(bool(0))
led1_b = Signal(bool(0))
led2_r = Signal(bool(0))
led2_g = Signal(bool(0))
led2_b = Signal(bool(0))
led3_r = Signal(bool(0))
led3_g = Signal(bool(0))
led3_b = Signal(bool(0))
led4 = Signal(bool(0))
led5 = Signal(bool(0))
led6 = Signal(bool(0))
led7 = Signal(bool(0))
phy_tx_clk = Signal(bool(0))
phy_txd = Signal(intbv(0)[4:])
phy_tx_en = Signal(bool(0))
phy_reset_n = Signal(bool(0))
uart_txd = Signal(bool(0))
# sources and sinks
mii_source = mii_ep.MIISource()
mii_source_logic = mii_source.create_logic(
phy_rx_clk,
rst,
txd=phy_rxd,
tx_en=phy_rx_dv,
tx_er=phy_rx_er,
name='mii_source'
)
mii_sink = mii_ep.MIISink()
mii_sink_logic = mii_sink.create_logic(
phy_tx_clk,
rst,
rxd=phy_txd,
rx_dv=phy_tx_en,
rx_er=False,
name='mii_sink'
)
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
btn=btn,
sw=sw,
led0_r=led0_r,
led0_g=led0_g,
led0_b=led0_b,
led1_r=led1_r,
led1_g=led1_g,
led1_b=led1_b,
led2_r=led2_r,
led2_g=led2_g,
led2_b=led2_b,
led3_r=led3_r,
led3_g=led3_g,
led3_b=led3_b,
led4=led4,
led5=led5,
led6=led6,
led7=led7,
phy_rx_clk=phy_rx_clk,
phy_rxd=phy_rxd,
phy_rx_dv=phy_rx_dv,
phy_rx_er=phy_rx_er,
phy_tx_clk=phy_tx_clk,
phy_txd=phy_txd,
phy_tx_en=phy_tx_en,
phy_col=phy_col,
phy_crs=phy_crs,
phy_reset_n=phy_reset_n,
uart_rxd=uart_rxd,
uart_txd=uart_txd
)
@always(delay(4))
def clkgen():
clk.next = not clk
phy_clk_hp = Signal(int(20))
@instance
def phy_clk_gen():
while True:
yield delay(int(phy_clk_hp))
phy_rx_clk.next = not phy_rx_clk
phy_tx_clk.next = not phy_tx_clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test UDP RX packet")
current_test.next = 1
test_frame = udp_ep.UDPFrame()
test_frame.eth_dest_mac = 0x020000000000
test_frame.eth_src_mac = 0xDAD1D2D3D4D5
test_frame.eth_type = 0x0800
test_frame.ip_version = 4
test_frame.ip_ihl = 5
test_frame.ip_dscp = 0
test_frame.ip_ecn = 0
test_frame.ip_length = None
test_frame.ip_identification = 0
test_frame.ip_flags = 2
test_frame.ip_fragment_offset = 0
test_frame.ip_ttl = 64
test_frame.ip_protocol = 0x11
test_frame.ip_header_checksum = None
test_frame.ip_source_ip = 0xc0a80181
test_frame.ip_dest_ip = 0xc0a80180
test_frame.udp_source_port = 5678
test_frame.udp_dest_port = 1234
test_frame.payload = bytearray(range(32))
test_frame.build()
mii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data)
# wait for ARP request packet
while mii_sink.empty():
yield clk.posedge
rx_frame = mii_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xFFFFFFFFFFFF
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0806
assert check_frame.arp_htype == 0x0001
assert check_frame.arp_ptype == 0x0800
assert check_frame.arp_hlen == 6
assert check_frame.arp_plen == 4
assert check_frame.arp_oper == 1
assert check_frame.arp_sha == 0x020000000000
assert check_frame.arp_spa == 0xc0a80180
assert check_frame.arp_tha == 0x000000000000
assert check_frame.arp_tpa == 0xc0a80181
# generate response
arp_frame = arp_ep.ARPFrame()
arp_frame.eth_dest_mac = 0x020000000000
arp_frame.eth_src_mac = 0xDAD1D2D3D4D5
arp_frame.eth_type = 0x0806
arp_frame.arp_htype = 0x0001
arp_frame.arp_ptype = 0x0800
arp_frame.arp_hlen = 6
arp_frame.arp_plen = 4
arp_frame.arp_oper = 2
arp_frame.arp_sha = 0xDAD1D2D3D4D5
arp_frame.arp_spa = 0xc0a80181
arp_frame.arp_tha = 0x020000000000
arp_frame.arp_tpa = 0xc0a80180
mii_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data)
while mii_sink.empty():
yield clk.posedge
rx_frame = mii_sink.recv()
check_eth_frame = eth_ep.EthFrame()
check_eth_frame.parse_axis_fcs(rx_frame.data[8:])
check_frame = udp_ep.UDPFrame()
check_frame.parse_eth(check_eth_frame)
print(check_frame)
assert check_frame.eth_dest_mac == 0xDAD1D2D3D4D5
assert check_frame.eth_src_mac == 0x020000000000
assert check_frame.eth_type == 0x0800
assert check_frame.ip_version == 4
assert check_frame.ip_ihl == 5
assert check_frame.ip_dscp == 0
assert check_frame.ip_ecn == 0
assert check_frame.ip_identification == 0
assert check_frame.ip_flags == 2
assert check_frame.ip_fragment_offset == 0
assert check_frame.ip_ttl == 64
assert check_frame.ip_protocol == 0x11
assert check_frame.ip_source_ip == 0xc0a80180
assert check_frame.ip_dest_ip == 0xc0a80181
assert check_frame.udp_source_port == 1234
assert check_frame.udp_dest_port == 5678
assert check_frame.payload.data == bytearray(range(32))
assert mii_source.empty()
assert mii_sink.empty()
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,158 @@
/*
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for fpga_core
*/
module test_fpga_core;
// Parameters
parameter TARGET = "SIM";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [3:0] btn = 0;
reg [3:0] sw = 0;
reg phy_rx_clk = 0;
reg [3:0] phy_rxd = 0;
reg phy_rx_dv = 0;
reg phy_rx_er = 0;
reg phy_col = 0;
reg phy_crs = 0;
reg phy_tx_clk = 0;
reg uart_rxd = 0;
// Outputs
wire led0_r;
wire led0_g;
wire led0_b;
wire led1_r;
wire led1_g;
wire led1_b;
wire led2_r;
wire led2_g;
wire led2_b;
wire led3_r;
wire led3_g;
wire led3_b;
wire led4;
wire led5;
wire led6;
wire led7;
wire [3:0] phy_txd;
wire phy_tx_en;
wire phy_reset_n;
wire uart_txd;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
btn,
sw,
phy_rx_clk,
phy_rxd,
phy_rx_dv,
phy_rx_er,
phy_tx_clk,
phy_col,
phy_crs,
uart_rxd
);
$to_myhdl(
led0_r,
led0_g,
led0_b,
led1_r,
led1_g,
led1_b,
led2_r,
led2_g,
led2_b,
led3_r,
led3_g,
led3_b,
led4,
led5,
led6,
led7,
phy_txd,
phy_tx_en,
phy_reset_n,
uart_txd
);
// dump file
$dumpfile("test_fpga_core.lxt");
$dumpvars(0, test_fpga_core);
end
fpga_core #(
.TARGET(TARGET)
)
UUT (
.clk(clk),
.rst(rst),
.btn(btn),
.sw(sw),
.led0_r(led0_r),
.led0_g(led0_g),
.led0_b(led0_b),
.led1_r(led1_r),
.led1_g(led1_g),
.led1_b(led1_b),
.led2_r(led2_r),
.led2_g(led2_g),
.led2_b(led2_b),
.led3_r(led3_r),
.led3_g(led3_g),
.led3_b(led3_b),
.led4(led4),
.led5(led5),
.led6(led6),
.led7(led7),
.phy_rx_clk(phy_rx_clk),
.phy_rxd(phy_rxd),
.phy_rx_dv(phy_rx_dv),
.phy_rx_er(phy_rx_er),
.phy_tx_clk(phy_tx_clk),
.phy_txd(phy_txd),
.phy_tx_en(phy_tx_en),
.phy_col(phy_col),
.phy_crs(phy_crs),
.phy_reset_n(phy_reset_n),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd)
);
endmodule

View File

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

View File

@ -0,0 +1,25 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = cores 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:
#program commands

View File

@ -0,0 +1,25 @@
# Verilog Ethernet DE5-Net Example Design
## Introduction
This example design targets the Terasic DE5-Net FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
FPGA: 5SGXEA7N2F45C2
PHY: 10G BASE-R PHY MegaCore
## How to build
Run make to build. Ensure that the Altera Quartus toolchain components are
in PATH.
## How to test
Run make program to program the DE5-Net board with the Altera software. Then
run netcat -u 192.168.1.128 1234 to open a UDP connection to port 1234. Any
text entered into netcat will be echoed back after pressing enter.

View File

@ -0,0 +1,141 @@
###################################################################
#
# Altera FPGA Makefile
#
# Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. Stratix V)
# FPGA_DEVICE - FPGA device (e.g. 5SGXEA7N2F45C2)
# SYN_FILES - space-separated list of source files
# QSF_FILES - space-separated list of settings files
# SDC_FILES - space-separated list of timing constraint files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = "Stratix V"
# FPGA_DEVICE = 5SGXEA7N2F45C2
# SYN_FILES = rtl/fpga.v rtl/clocks.v
# QSF_FILES = fpga.qsf
# SDC_FILES = fpga.sdc
# include ../common/altera.mk
#
###################################################################
# phony targets
.PHONY: clean fpga
# output files to hang on to
.PRECIOUS: %.sof %.map.rpt %.fit.rpt %.asm.rpt %.sta.rpt
# any project specific settings
-include ../config.mk
SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES))
ifdef QSF_FILES
QSF_FILES_REL = $(patsubst %, ../%, $(QSF_FILES))
else
QSF_FILES_REL = ../$(FPGA_TOP).qsf
endif
SDC_FILES_REL = $(patsubst %, ../%, $(SDC_FILES))
ASSIGNMENT_FILES = $(FPGA_TOP).qpf $(FPGA_TOP).qsf
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and database
###################################################################
all: fpga
fpga: $(FPGA_TOP).sof
clean:
rm -rf *.rpt *.summary *.smsg *.chg smart.log *.htm *.eqn *.pin *.sof *.pof *.qsf *.qpf *.jdi *.sld *.txt db incremental_db reconfig_mif
map: smart.log $(PROJECT).map.rpt
fit: smart.log $(PROJECT).fit.rpt
asm: smart.log $(PROJECT).asm.rpt
sta: smart.log $(PROJECT).sta.rpt
smart: smart.log
###################################################################
# Executable Configuration
###################################################################
MAP_ARGS = --family=$(FPGA_FAMILY)
FIT_ARGS = --part=$(FPGA_DEVICE)
ASM_ARGS =
STA_ARGS =
###################################################################
# Target implementations
###################################################################
STAMP = echo done >
%.map.rpt: map.chg $(SYN_FILES_REL)
quartus_map $(MAP_ARGS) $(FPGA_TOP)
%.fit.rpt: fit.chg %.map.rpt
quartus_fit $(FIT_ARGS) $(FPGA_TOP)
%.sta.rpt: sta.chg %.fit.rpt
quartus_sta $(STA_ARGS) $(FPGA_TOP)
%.asm.rpt: asm.chg %.sta.rpt
quartus_asm $(ASM_ARGS) $(FPGA_TOP)
mkdir -p rev
EXT=sof; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do let COUNT=COUNT+1; done; \
cp $*.$$EXT rev/$*_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_rev$$COUNT.$$EXT";
%.sof: smart.log %.asm.rpt
smart.log: $(ASSIGNMENT_FILES)
quartus_sh --determine_smart_action $(FPGA_TOP) > smart.log
###################################################################
# Project initialization
###################################################################
$(ASSIGNMENT_FILES): $(QSF_FILES_REL) $(SYN_FILES_REL)
rm -f $(FPGA_TOP).qsf
quartus_sh --prepare -f $(FPGA_FAMILY) -d $(FPGA_DEVICE) -t $(FPGA_TOP) $(FPGA_TOP)
echo >> $(FPGA_TOP).qsf
echo >> $(FPGA_TOP).qsf
echo "# Source files" >> $(FPGA_TOP).qsf
for x in $(SYN_FILES_REL); do \
case $${x##*.} in \
v|V) echo set_global_assignment -name VERILOG_FILE $$x >> $(FPGA_TOP).qsf ;;\
vhd|VHD) echo set_global_assignment -name VHDL_FILE $$x >> $(FPGA_TOP).qsf ;;\
qip|QIP) echo set_global_assignment -name QIP_FILE $$x >> $(FPGA_TOP).qsf ;;\
*) echo set_global_assignment -name SOURCE_FILE $$x >> $(FPGA_TOP).qsf ;;\
esac; \
done
echo >> $(FPGA_TOP).qsf
echo "# SDC files" >> $(FPGA_TOP).qsf
for x in $(SDC_FILES_REL); do echo set_global_assignment -name SDC_FILE $$x >> $(FPGA_TOP).qsf; done
for x in $(QSF_FILES_REL); do printf "\n#\n# Included QSF file $$x\n#\n" >> $(FPGA_TOP).qsf; cat $$x >> $(FPGA_TOP).qsf; done
map.chg:
$(STAMP) map.chg
fit.chg:
$(STAMP) fit.chg
sta.chg:
$(STAMP) sta.chg
asm.chg:
$(STAMP) asm.chg

View File

@ -0,0 +1,23 @@
# Tools
QMEGAWIZ=qmegawiz
# Sources
QMWSRC=phy.v
QMWSRC+=phy_reconfig.v
# Targets
TARGETS=$(QMWSRC:.v=)
# Rules
.PHONY: all
all: $(TARGETS)
.PHONY: clean
clean:
-rm -rf $(TARGETS)
%: %.v
mkdir -p $@
cp -a $< $@
cd $@ && $(QMEGAWIZ) -silent $<

View File

@ -0,0 +1,192 @@
// megafunction wizard: %10GBASE-R PHY v15.0%
// GENERATION: XML
// phy.v
// Generated using ACDS version 15.0 153
`timescale 1 ps / 1 ps
module phy (
input wire pll_ref_clk, // pll_ref_clk.clk
output wire xgmii_rx_clk, // xgmii_rx_clk.clk
output wire pll_locked, // pll_locked.export
output wire tx_ready, // tx_ready.export
input wire xgmii_tx_clk, // xgmii_tx_clk.clk
output wire rx_ready, // rx_ready.export
output wire [3:0] rx_data_ready, // rx_data_ready.export
output wire [71:0] xgmii_rx_dc_0, // xgmii_rx_dc_0.data
input wire rx_serial_data_0, // rx_serial_data_0.export
output wire [71:0] xgmii_rx_dc_1, // xgmii_rx_dc_1.data
input wire rx_serial_data_1, // rx_serial_data_1.export
output wire [71:0] xgmii_rx_dc_2, // xgmii_rx_dc_2.data
input wire rx_serial_data_2, // rx_serial_data_2.export
output wire [71:0] xgmii_rx_dc_3, // xgmii_rx_dc_3.data
input wire rx_serial_data_3, // rx_serial_data_3.export
input wire [71:0] xgmii_tx_dc_0, // xgmii_tx_dc_0.data
output wire [0:0] tx_serial_data_0, // tx_serial_data_0.export
input wire [71:0] xgmii_tx_dc_1, // xgmii_tx_dc_1.data
output wire [0:0] tx_serial_data_1, // tx_serial_data_1.export
input wire [71:0] xgmii_tx_dc_2, // xgmii_tx_dc_2.data
output wire [0:0] tx_serial_data_2, // tx_serial_data_2.export
input wire [71:0] xgmii_tx_dc_3, // xgmii_tx_dc_3.data
output wire [0:0] tx_serial_data_3, // tx_serial_data_3.export
output wire [367:0] reconfig_from_xcvr, // reconfig_from_xcvr.reconfig_from_xcvr
input wire [559:0] reconfig_to_xcvr, // reconfig_to_xcvr.reconfig_to_xcvr
input wire phy_mgmt_clk, // phy_mgmt_clk.clk
input wire phy_mgmt_clk_reset, // phy_mgmt_clk_reset.reset
input wire [8:0] phy_mgmt_address, // phy_mgmt.address
input wire phy_mgmt_read, // .read
output wire [31:0] phy_mgmt_readdata, // .readdata
input wire phy_mgmt_write, // .write
input wire [31:0] phy_mgmt_writedata, // .writedata
output wire phy_mgmt_waitrequest // .waitrequest
);
wire [3:0] phy_inst_tx_serial_data; // port fragment
wire [287:0] phy_inst_xgmii_rx_dc; // port fragment
altera_xcvr_10gbaser #(
.device_family ("Stratix V"),
.num_channels (4),
.operation_mode ("duplex"),
.external_pma_ctrl_config (0),
.control_pin_out (0),
.recovered_clk_out (0),
.pll_locked_out (1),
.ref_clk_freq ("644.53125 MHz"),
.pma_mode (40),
.pll_type ("CMU"),
.starting_channel_number (0),
.reconfig_interfaces (8),
.rx_use_coreclk (0),
.embedded_reset (1),
.latadj (0),
.high_precision_latadj (1),
.tx_termination ("OCT_100_OHMS"),
.tx_vod_selection (7),
.tx_preemp_pretap (0),
.tx_preemp_pretap_inv (0),
.tx_preemp_tap_1 (15),
.tx_preemp_tap_2 (0),
.tx_preemp_tap_2_inv (0),
.rx_common_mode ("0.82v"),
.rx_termination ("OCT_100_OHMS"),
.rx_eq_dc_gain (0),
.rx_eq_ctrl (0),
.mgmt_clk_in_mhz (150)
) phy_inst (
.pll_ref_clk (pll_ref_clk), // pll_ref_clk.clk
.xgmii_rx_clk (xgmii_rx_clk), // xgmii_rx_clk.clk
.pll_locked (pll_locked), // pll_locked.export
.tx_ready (tx_ready), // tx_ready.export
.xgmii_tx_clk (xgmii_tx_clk), // xgmii_tx_clk.clk
.rx_ready (rx_ready), // rx_ready.export
.rx_data_ready (rx_data_ready), // rx_data_ready.export
.xgmii_rx_dc (phy_inst_xgmii_rx_dc), // xgmii_rx_dc_0.data
.rx_serial_data ({rx_serial_data_3,rx_serial_data_2,rx_serial_data_1,rx_serial_data_0}), // rx_serial_data_0.export
.xgmii_tx_dc ({xgmii_tx_dc_3[71:0],xgmii_tx_dc_2[71:0],xgmii_tx_dc_1[71:0],xgmii_tx_dc_0[71:0]}), // xgmii_tx_dc_0.data
.tx_serial_data (phy_inst_tx_serial_data), // tx_serial_data_0.export
.reconfig_from_xcvr (reconfig_from_xcvr), // reconfig_from_xcvr.reconfig_from_xcvr
.reconfig_to_xcvr (reconfig_to_xcvr), // reconfig_to_xcvr.reconfig_to_xcvr
.phy_mgmt_clk (phy_mgmt_clk), // phy_mgmt_clk.clk
.phy_mgmt_clk_reset (phy_mgmt_clk_reset), // phy_mgmt_clk_reset.reset
.phy_mgmt_address (phy_mgmt_address), // phy_mgmt.address
.phy_mgmt_read (phy_mgmt_read), // .read
.phy_mgmt_readdata (phy_mgmt_readdata), // .readdata
.phy_mgmt_write (phy_mgmt_write), // .write
.phy_mgmt_writedata (phy_mgmt_writedata), // .writedata
.phy_mgmt_waitrequest (phy_mgmt_waitrequest), // .waitrequest
.rx_block_lock (), // (terminated)
.rx_hi_ber (), // (terminated)
.rx_recovered_clk (), // (terminated)
.rx_coreclkin (1'b0), // (terminated)
.gxb_pdn (1'b0), // (terminated)
.pll_pdn (1'b0), // (terminated)
.cal_blk_pdn (1'b0), // (terminated)
.cal_blk_clk (1'b0), // (terminated)
.tx_digitalreset (4'b0000), // (terminated)
.tx_analogreset (4'b0000), // (terminated)
.tx_cal_busy (), // (terminated)
.pll_powerdown (4'b0000), // (terminated)
.rx_digitalreset (4'b0000), // (terminated)
.rx_analogreset (4'b0000), // (terminated)
.rx_cal_busy (), // (terminated)
.rx_is_lockedtodata (), // (terminated)
.rx_latency_adj (), // (terminated)
.tx_latency_adj () // (terminated)
);
assign tx_serial_data_0 = { phy_inst_tx_serial_data[0:0] };
assign xgmii_rx_dc_0 = { phy_inst_xgmii_rx_dc[71:0] };
assign tx_serial_data_1 = { phy_inst_tx_serial_data[1:1] };
assign xgmii_rx_dc_1 = { phy_inst_xgmii_rx_dc[143:72] };
assign xgmii_rx_dc_2 = { phy_inst_xgmii_rx_dc[215:144] };
assign xgmii_rx_dc_3 = { phy_inst_xgmii_rx_dc[287:216] };
assign tx_serial_data_2 = { phy_inst_tx_serial_data[2:2] };
assign tx_serial_data_3 = { phy_inst_tx_serial_data[3:3] };
endmodule
// Retrieval info: <?xml version="1.0"?>
//<!--
// Generated by Altera MegaWizard Launcher Utility version 1.0
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
// ************************************************************
// Copyright (C) 1991-2016 Altera Corporation
// Any megafunction design, and related net list (encrypted or decrypted),
// support information, device programming or simulation file, and any other
// associated documentation or information provided by Altera or a partner
// under Altera's Megafunction Partnership Program may be used only to
// program PLD devices (but not masked PLD devices) from Altera. Any other
// use of such megafunction design, net list, support information, device
// programming or simulation file, or any other related documentation or
// information is prohibited for any other purpose, including, but not
// limited to modification, reverse engineering, de-compiling, or use with
// any other silicon devices, unless such use is explicitly licensed under
// a separate agreement with Altera or a megafunction partner. Title to
// the intellectual property, including patents, copyrights, trademarks,
// trade secrets, or maskworks, embodied in any such megafunction design,
// net list, support information, device programming or simulation file, or
// any other related documentation or information provided by Altera or a
// megafunction partner, remains with Altera, the megafunction partner, or
// their respective licensors. No other licenses, including any licenses
// needed under any third party's intellectual property, are provided herein.
//-->
// Retrieval info: <instance entity-name="altera_xcvr_10gbaser" version="15.0" >
// Retrieval info: <generic name="device_family" value="Stratix V" />
// Retrieval info: <generic name="num_channels" value="4" />
// Retrieval info: <generic name="operation_mode" value="duplex" />
// Retrieval info: <generic name="external_pma_ctrl_config" value="0" />
// Retrieval info: <generic name="control_pin_out" value="0" />
// Retrieval info: <generic name="recovered_clk_out" value="0" />
// Retrieval info: <generic name="pll_locked_out" value="1" />
// Retrieval info: <generic name="gui_pll_type" value="CMU" />
// Retrieval info: <generic name="ref_clk_freq" value="644.53125 MHz" />
// Retrieval info: <generic name="pma_mode" value="40" />
// Retrieval info: <generic name="starting_channel_number" value="0" />
// Retrieval info: <generic name="sys_clk_in_hz" value="150000000" />
// Retrieval info: <generic name="rx_use_coreclk" value="0" />
// Retrieval info: <generic name="gui_embedded_reset" value="1" />
// Retrieval info: <generic name="latadj" value="0" />
// Retrieval info: <generic name="high_precision_latadj" value="1" />
// Retrieval info: <generic name="tx_termination" value="OCT_100_OHMS" />
// Retrieval info: <generic name="tx_vod_selection" value="7" />
// Retrieval info: <generic name="tx_preemp_pretap" value="0" />
// Retrieval info: <generic name="tx_preemp_pretap_inv" value="0" />
// Retrieval info: <generic name="tx_preemp_tap_1" value="15" />
// Retrieval info: <generic name="tx_preemp_tap_2" value="0" />
// Retrieval info: <generic name="tx_preemp_tap_2_inv" value="0" />
// Retrieval info: <generic name="rx_common_mode" value="0.82v" />
// Retrieval info: <generic name="rx_termination" value="OCT_100_OHMS" />
// Retrieval info: <generic name="rx_eq_dc_gain" value="0" />
// Retrieval info: <generic name="rx_eq_ctrl" value="0" />
// Retrieval info: <generic name="mgmt_clk_in_hz" value="150000000" />
// Retrieval info: </instance>
// IPFS_FILES : phy.vo
// RELATED_FILES: phy.v, altera_xcvr_functions.sv, alt_reset_ctrl_lego.sv, alt_reset_ctrl_tgx_cdrauto.sv, alt_xcvr_resync.sv, alt_xcvr_csr_common_h.sv, alt_xcvr_csr_common.sv, alt_xcvr_csr_pcs8g_h.sv, alt_xcvr_csr_pcs8g.sv, alt_xcvr_csr_selector.sv, alt_xcvr_mgmt2dec.sv, altera_wait_generate.v, altera_10gbaser_phy_handshake_clock_crosser.v, altera_10gbaser_phy_clock_crosser.v, altera_10gbaser_phy_pipeline_stage.sv, altera_10gbaser_phy_pipeline_base.v, csr_pcs10gbaser_h.sv, csr_pcs10gbaser.sv, sv_pcs.sv, sv_pcs_ch.sv, sv_pma.sv, sv_reconfig_bundle_to_xcvr.sv, sv_reconfig_bundle_to_ip.sv, sv_reconfig_bundle_merger.sv, sv_rx_pma.sv, sv_tx_pma.sv, sv_tx_pma_ch.sv, sv_xcvr_h.sv, sv_xcvr_avmm_csr.sv, sv_xcvr_avmm_dcd.sv, sv_xcvr_avmm.sv, sv_xcvr_data_adapter.sv, sv_xcvr_native.sv, sv_xcvr_plls.sv, sv_hssi_10g_rx_pcs_rbc.sv, sv_hssi_10g_tx_pcs_rbc.sv, sv_hssi_8g_rx_pcs_rbc.sv, sv_hssi_8g_tx_pcs_rbc.sv, sv_hssi_8g_pcs_aggregate_rbc.sv, sv_hssi_common_pcs_pma_interface_rbc.sv, sv_hssi_common_pld_pcs_interface_rbc.sv, sv_hssi_pipe_gen1_2_rbc.sv, sv_hssi_pipe_gen3_rbc.sv, sv_hssi_rx_pcs_pma_interface_rbc.sv, sv_hssi_rx_pld_pcs_interface_rbc.sv, sv_hssi_tx_pcs_pma_interface_rbc.sv, sv_hssi_tx_pld_pcs_interface_rbc.sv, sv_xcvr_10gbaser_nr.sv, sv_xcvr_10gbaser_native.sv, altera_xcvr_10gbaser.sv, altera_xcvr_reset_control.sv, alt_xcvr_reset_counter.sv, alt_xcvr_arbiter.sv, alt_xcvr_m2s.sv

View File

@ -0,0 +1,101 @@
// megafunction wizard: %Transceiver Reconfiguration Controller v15.0%
// GENERATION: XML
// phy_reconfig.v
// Generated using ACDS version 15.0 153
`timescale 1 ps / 1 ps
module phy_reconfig (
output wire reconfig_busy, // reconfig_busy.reconfig_busy
input wire mgmt_clk_clk, // mgmt_clk_clk.clk
input wire mgmt_rst_reset, // mgmt_rst_reset.reset
input wire [6:0] reconfig_mgmt_address, // reconfig_mgmt.address
input wire reconfig_mgmt_read, // .read
output wire [31:0] reconfig_mgmt_readdata, // .readdata
output wire reconfig_mgmt_waitrequest, // .waitrequest
input wire reconfig_mgmt_write, // .write
input wire [31:0] reconfig_mgmt_writedata, // .writedata
output wire [559:0] reconfig_to_xcvr, // reconfig_to_xcvr.reconfig_to_xcvr
input wire [367:0] reconfig_from_xcvr // reconfig_from_xcvr.reconfig_from_xcvr
);
alt_xcvr_reconfig #(
.device_family ("Stratix V"),
.number_of_reconfig_interfaces (8),
.enable_offset (1),
.enable_lc (1),
.enable_dcd (0),
.enable_dcd_power_up (1),
.enable_analog (1),
.enable_eyemon (0),
.enable_ber (0),
.enable_dfe (0),
.enable_adce (0),
.enable_mif (0),
.enable_pll (0)
) phy_reconfig_inst (
.reconfig_busy (reconfig_busy), // reconfig_busy.reconfig_busy
.mgmt_clk_clk (mgmt_clk_clk), // mgmt_clk_clk.clk
.mgmt_rst_reset (mgmt_rst_reset), // mgmt_rst_reset.reset
.reconfig_mgmt_address (reconfig_mgmt_address), // reconfig_mgmt.address
.reconfig_mgmt_read (reconfig_mgmt_read), // .read
.reconfig_mgmt_readdata (reconfig_mgmt_readdata), // .readdata
.reconfig_mgmt_waitrequest (reconfig_mgmt_waitrequest), // .waitrequest
.reconfig_mgmt_write (reconfig_mgmt_write), // .write
.reconfig_mgmt_writedata (reconfig_mgmt_writedata), // .writedata
.reconfig_to_xcvr (reconfig_to_xcvr), // reconfig_to_xcvr.reconfig_to_xcvr
.reconfig_from_xcvr (reconfig_from_xcvr), // reconfig_from_xcvr.reconfig_from_xcvr
.tx_cal_busy (), // (terminated)
.rx_cal_busy (), // (terminated)
.cal_busy_in (1'b0), // (terminated)
.reconfig_mif_address (), // (terminated)
.reconfig_mif_read (), // (terminated)
.reconfig_mif_readdata (16'b0000000000000000), // (terminated)
.reconfig_mif_waitrequest (1'b0) // (terminated)
);
endmodule
// Retrieval info: <?xml version="1.0"?>
//<!--
// Generated by Altera MegaWizard Launcher Utility version 1.0
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
// ************************************************************
// Copyright (C) 1991-2016 Altera Corporation
// Any megafunction design, and related net list (encrypted or decrypted),
// support information, device programming or simulation file, and any other
// associated documentation or information provided by Altera or a partner
// under Altera's Megafunction Partnership Program may be used only to
// program PLD devices (but not masked PLD devices) from Altera. Any other
// use of such megafunction design, net list, support information, device
// programming or simulation file, or any other related documentation or
// information is prohibited for any other purpose, including, but not
// limited to modification, reverse engineering, de-compiling, or use with
// any other silicon devices, unless such use is explicitly licensed under
// a separate agreement with Altera or a megafunction partner. Title to
// the intellectual property, including patents, copyrights, trademarks,
// trade secrets, or maskworks, embodied in any such megafunction design,
// net list, support information, device programming or simulation file, or
// any other related documentation or information provided by Altera or a
// megafunction partner, remains with Altera, the megafunction partner, or
// their respective licensors. No other licenses, including any licenses
// needed under any third party's intellectual property, are provided herein.
//-->
// Retrieval info: <instance entity-name="alt_xcvr_reconfig" version="15.0" >
// Retrieval info: <generic name="device_family" value="Stratix V" />
// Retrieval info: <generic name="number_of_reconfig_interfaces" value="8" />
// Retrieval info: <generic name="gui_split_sizes" value="" />
// Retrieval info: <generic name="enable_offset" value="1" />
// Retrieval info: <generic name="enable_dcd" value="0" />
// Retrieval info: <generic name="enable_dcd_power_up" value="1" />
// Retrieval info: <generic name="enable_analog" value="1" />
// Retrieval info: <generic name="enable_eyemon" value="0" />
// Retrieval info: <generic name="ber_en" value="0" />
// Retrieval info: <generic name="enable_dfe" value="0" />
// Retrieval info: <generic name="enable_adce" value="0" />
// Retrieval info: <generic name="enable_mif" value="0" />
// Retrieval info: <generic name="gui_enable_pll" value="0" />
// Retrieval info: <generic name="gui_cal_status_port" value="false" />
// Retrieval info: </instance>
// IPFS_FILES : phy_reconfig.vo
// RELATED_FILES: phy_reconfig.v, altera_xcvr_functions.sv, sv_xcvr_h.sv, alt_xcvr_resync.sv, alt_xcvr_reconfig_h.sv, sv_xcvr_dfe_cal_sweep_h.sv, alt_xcvr_reconfig.sv, alt_xcvr_reconfig_sv.sv, alt_xcvr_reconfig_cal_seq.sv, alt_xreconf_cif.sv, alt_xreconf_uif.sv, alt_xreconf_basic_acq.sv, alt_xcvr_reconfig_analog.sv, alt_xcvr_reconfig_analog_sv.sv, alt_xreconf_analog_datactrl.sv, alt_xreconf_analog_rmw.sv, alt_xreconf_analog_ctrlsm.sv, alt_xcvr_reconfig_offset_cancellation.sv, alt_xcvr_reconfig_offset_cancellation_sv.sv, alt_xcvr_reconfig_eyemon.sv, alt_xcvr_reconfig_eyemon_sv.sv, alt_xcvr_reconfig_eyemon_ctrl_sv.sv, alt_xcvr_reconfig_eyemon_ber_sv.sv, ber_reader_dcfifo.v, step_to_mon_sv.sv, mon_to_step_sv.sv, alt_xcvr_reconfig_dfe.sv, alt_xcvr_reconfig_dfe_sv.sv, alt_xcvr_reconfig_dfe_reg_sv.sv, alt_xcvr_reconfig_dfe_cal_sv.sv, alt_xcvr_reconfig_dfe_cal_sweep_sv.sv, alt_xcvr_reconfig_dfe_cal_sweep_datapath_sv.sv, alt_xcvr_reconfig_dfe_oc_cal_sv.sv, alt_xcvr_reconfig_dfe_pi_phase_sv.sv, alt_xcvr_reconfig_dfe_step_to_mon_en_sv.sv, alt_xcvr_reconfig_dfe_adapt_tap_sv.sv, alt_xcvr_reconfig_dfe_ctrl_mux_sv.sv, alt_xcvr_reconfig_dfe_local_reset_sv.sv, alt_xcvr_reconfig_dfe_cal_sim_sv.sv, alt_xcvr_reconfig_dfe_adapt_tap_sim_sv.sv, alt_xcvr_reconfig_adce.sv, alt_xcvr_reconfig_adce_sv.sv, alt_xcvr_reconfig_adce_datactrl_sv.sv, alt_xcvr_reconfig_dcd.sv, alt_xcvr_reconfig_dcd_sv.sv, alt_xcvr_reconfig_dcd_cal.sv, alt_xcvr_reconfig_dcd_control.sv, alt_xcvr_reconfig_dcd_datapath.sv, alt_xcvr_reconfig_dcd_pll_reset.sv, alt_xcvr_reconfig_dcd_eye_width.sv, alt_xcvr_reconfig_dcd_align_clk.sv, alt_xcvr_reconfig_dcd_get_sum.sv, alt_xcvr_reconfig_dcd_cal_sim_model.sv, alt_xcvr_reconfig_mif.sv, sv_xcvr_reconfig_mif.sv, sv_xcvr_reconfig_mif_ctrl.sv, sv_xcvr_reconfig_mif_avmm.sv, alt_xcvr_reconfig_pll.sv, sv_xcvr_reconfig_pll.sv, sv_xcvr_reconfig_pll_ctrl.sv, alt_xcvr_reconfig_soc.sv, alt_xcvr_reconfig_cpu_ram.sv, alt_xcvr_reconfig_direct.sv, sv_xrbasic_l2p_addr.sv, sv_xrbasic_l2p_ch.sv, sv_xrbasic_l2p_rom.sv, sv_xrbasic_lif_csr.sv, sv_xrbasic_lif.sv, sv_xcvr_reconfig_basic.sv, alt_arbiter_acq.sv, alt_xcvr_reconfig_basic.sv, alt_xcvr_arbiter.sv, alt_xcvr_m2s.sv, altera_wait_generate.v, alt_xcvr_csr_selector.sv, sv_reconfig_bundle_to_basic.sv, alt_xcvr_reconfig_cpu.v, alt_xcvr_reconfig_cpu_reconfig_cpu.v, alt_xcvr_reconfig_cpu_reconfig_cpu_test_bench.v, alt_xcvr_reconfig_cpu_mm_interconnect_0.v, alt_xcvr_reconfig_cpu_irq_mapper.sv, altera_reset_controller.v, altera_reset_synchronizer.v, altera_merlin_master_translator.sv, altera_merlin_slave_translator.sv, altera_merlin_master_agent.sv, altera_merlin_slave_agent.sv, altera_merlin_burst_uncompressor.sv, altera_avalon_sc_fifo.v, alt_xcvr_reconfig_cpu_mm_interconnect_0_router.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_router_001.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_router_002.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_router_003.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_cmd_demux.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_cmd_demux_001.sv, altera_merlin_arbitrator.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_cmd_mux.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_cmd_mux_001.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_rsp_mux.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_rsp_mux_001.sv, alt_xcvr_reconfig_cpu_mm_interconnect_0_avalon_st_adapter.v, alt_xcvr_reconfig_cpu_mm_interconnect_0_avalon_st_adapter_error_adapter_0.sv

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
#**************************************************************
# Create Clock
#**************************************************************
create_clock -period 20 [get_ports OSC_50_B3B]
create_clock -period 20 [get_ports OSC_50_B3D]
create_clock -period 20 [get_ports OSC_50_B4A]
create_clock -period 20 [get_ports OSC_50_B4D]
create_clock -period 20 [get_ports OSC_50_B7A]
create_clock -period 20 [get_ports OSC_50_B7D]
create_clock -period 20 [get_ports OSC_50_B8A]
create_clock -period 20 [get_ports OSC_50_B8D]
create_clock -period 1.5515 [get_ports SFP_REFCLK_P]
#**************************************************************
# Create Generated Clock
#**************************************************************
derive_pll_clocks
#**************************************************************
# Set Clock Latency
#**************************************************************
#**************************************************************
# Set Clock Uncertainty
#**************************************************************
derive_clock_uncertainty
#**************************************************************
# Set Input Delay
#**************************************************************
#**************************************************************
# Set Output Delay
#**************************************************************
#**************************************************************
# Set Clock Groups
#**************************************************************
#**************************************************************
# Set False Path
#**************************************************************
#**************************************************************
# Set Multicycle Path
#**************************************************************
#**************************************************************
# Set Maximum Delay
#**************************************************************
#**************************************************************
# Set Minimum Delay
#**************************************************************
#**************************************************************
# Set Input Transition
#**************************************************************
#**************************************************************
# Set Load
#**************************************************************

View File

@ -0,0 +1,60 @@
# FPGA settings
FPGA_TOP = fpga
FPGA_FAMILY = "Stratix V"
FPGA_DEVICE = 5SGXEA7N2F45C2
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += rtl/si570_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx_64.v
SYN_FILES += lib/eth/rtl/eth_axis_tx_64.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp_64.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx_64.v
SYN_FILES += lib/eth/rtl/arp_eth_tx_64.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/rtl/xgmii_interleave.v
SYN_FILES += lib/eth/rtl/xgmii_deinterleave.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += cores/phy/phy.qip
SYN_FILES += cores/phy_reconfig/phy_reconfig.qip
# QSF files
QSF_FILES = fpga.qsf
# SDC files
SDC_FILES = fpga.sdc
include ../common/altera.mk
program: fpga
quartus_pgm --no_banner --mode=jtag -o "P;$(FPGA_TOP).sof"
# program with 'factory default' parallel flash loader design (or something else with a NIOS2 that can see the flash chips)
program_flash_pfl: fpga
nios2_command_shell.sh sof2flash --input="$(FPGA_TOP).sof" --output="$(FPGA_TOP).flash" --offset=0x20C0000 --pfl --optionbit=0x00030000 --programmingmode=PS
nios2_command_shell.sh nios2-flash-programmer --base=0x0 "$(FPGA_TOP).flash"

View File

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

View File

@ -0,0 +1,89 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule

View File

@ -0,0 +1,470 @@
/*
Copyright (c) 2016-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
// CPU reset button
input wire CPU_RESET_n,
// buttons
input wire [3:0] BUTTON,
input wire [3:0] SW,
// LEDs
output wire [6:0] HEX0_D,
output wire HEX0_DP,
output wire [6:0] HEX1_D,
output wire HEX1_DP,
output wire [3:0] LED,
output wire [3:0] LED_BRACKET,
output wire LED_RJ45_L,
output wire LED_RJ45_R,
// Temperature control
//inout wire TEMP_CLK,
//inout wire TEMP_DATA,
//input wire TEMP_INT_n,
//input wire TEMP_OVERT_n,
output wire FAN_CTRL,
// 50 MHz clock inputs
input wire OSC_50_B3B,
input wire OSC_50_B3D,
input wire OSC_50_B4A,
input wire OSC_50_B4D,
input wire OSC_50_B7A,
input wire OSC_50_B7D,
input wire OSC_50_B8A,
input wire OSC_50_B8D,
// PCIe interface
//input wire PCIE_PERST_n,
//input wire PCIE_REFCLK_p,
//input wire [7:0] PCIE_RX_p,
//output wire [7:0] PCIE_TX_p,
//input wire PCIE_WAKE_n,
//inout wire PCIE_SMBCLK,
//inout wire PCIE_SMBDAT,
// Si570
inout wire CLOCK_SCL,
inout wire CLOCK_SDA,
// 10G Ethernet
input wire SFPA_LOS,
input wire SFPA_TXFAULT,
input wire SFPA_MOD0_PRESNT_n,
inout wire SFPA_MOD1_SCL,
inout wire SFPA_MOD2_SDA,
output wire SFPA_TXDISABLE,
output wire [1:0] SPFA_RATESEL,
input wire SFPA_RX_p,
output wire SFPA_TX_p,
input wire SFPB_LOS,
input wire SFPB_TXFAULT,
input wire SFPB_MOD0_PRESNT_n,
inout wire SFPB_MOD1_SCL,
inout wire SFPB_MOD2_SDA,
output wire SFPB_TXDISABLE,
output wire [1:0] SPFB_RATESEL,
input wire SFPB_RX_p,
output wire SFPB_TX_p,
input wire SFPC_LOS,
input wire SFPC_TXFAULT,
input wire SFPC_MOD0_PRESNT_n,
inout wire SFPC_MOD1_SCL,
inout wire SFPC_MOD2_SDA,
output wire SFPC_TXDISABLE,
output wire [1:0] SPFC_RATESEL,
input wire SFPC_RX_p,
output wire SFPC_TX_p,
input wire SFPD_LOS,
input wire SFPD_TXFAULT,
input wire SFPD_MOD0_PRESNT_n,
inout wire SFPD_MOD1_SCL,
inout wire SFPD_MOD2_SDA,
output wire SFPD_TXDISABLE,
output wire [1:0] SPFD_RATESEL,
input wire SFPD_RX_p,
output wire SFPD_TX_p,
input wire SFP_REFCLK_P
);
// Clock and reset
wire clk_50mhz = OSC_50_B3B;
wire rst_50mhz;
sync_reset #(
.N(4)
)
sync_reset_50mhz_inst (
.clk(clk_50mhz),
.rst(~CPU_RESET_n),
.sync_reset_out(rst_50mhz)
);
wire clk_156mhz;
wire rst_156mhz;
wire phy_pll_locked;
sync_reset #(
.N(4)
)
sync_reset_156mhz_inst (
.clk(clk_156mhz),
.rst(rst_50mhz | ~phy_pll_locked),
.sync_reset_out(rst_156mhz)
);
// GPIO
wire [3:0] btn_int;
wire [3:0] sw_int;
wire [3:0] led_int;
wire [3:0] led_bkt_int;
wire [6:0] led_hex0_d_int;
wire led_hex0_dp_int;
wire [6:0] led_hex1_d_int;
wire led_hex1_dp_int;
debounce_switch #(
.WIDTH(8),
.N(4),
.RATE(156250)
)
debounce_switch_inst (
.clk(clk_156mhz),
.rst(rst_156mhz),
.in({BUTTON,
SW}),
.out({btn_int,
sw_int})
);
assign LED = ~led_int;
assign LED_BRACKET = ~led_bkt_int;
assign HEX0_D = ~led_hex0_d_int;
assign HEX0_DP = ~led_hex0_dp_int;
assign HEX1_D = ~led_hex1_d_int;
assign HEX1_DP = ~led_hex1_dp_int;
assign FAN_CTRL = 1;
// Si570 oscillator I2C init
wire si570_scl_i;
wire si570_scl_o;
wire si570_scl_t;
wire si570_sda_i;
wire si570_sda_o;
wire si570_sda_t;
assign si570_sda_i = CLOCK_SDA;
assign CLOCK_SDA = si570_sda_t ? 1'bz : si570_sda_o;
assign si570_scl_i = CLOCK_SCL;
assign CLOCK_SCL = si570_scl_t ? 1'bz : si570_scl_o;
wire [6:0] si570_i2c_cmd_address;
wire si570_i2c_cmd_start;
wire si570_i2c_cmd_read;
wire si570_i2c_cmd_write;
wire si570_i2c_cmd_write_multiple;
wire si570_i2c_cmd_stop;
wire si570_i2c_cmd_valid;
wire si570_i2c_cmd_ready;
wire [7:0] si570_i2c_data;
wire si570_i2c_data_valid;
wire si570_i2c_data_ready;
wire si570_i2c_data_last;
si570_i2c_init
si570_i2c_init_inst (
.clk(clk_50mhz),
.rst(rst_50mhz),
.cmd_address(si570_i2c_cmd_address),
.cmd_start(si570_i2c_cmd_start),
.cmd_read(si570_i2c_cmd_read),
.cmd_write(si570_i2c_cmd_write),
.cmd_write_multiple(si570_i2c_cmd_write_multiple),
.cmd_stop(si570_i2c_cmd_stop),
.cmd_valid(si570_i2c_cmd_valid),
.cmd_ready(si570_i2c_cmd_ready),
.data_out(si570_i2c_data),
.data_out_valid(si570_i2c_data_valid),
.data_out_ready(si570_i2c_data_ready),
.data_out_last(si570_i2c_data_last),
.busy(),
.start(1)
);
i2c_master
si570_i2c_master_inst (
.clk(clk_50mhz),
.rst(rst_50mhz),
.cmd_address(si570_i2c_cmd_address),
.cmd_start(si570_i2c_cmd_start),
.cmd_read(si570_i2c_cmd_read),
.cmd_write(si570_i2c_cmd_write),
.cmd_write_multiple(si570_i2c_cmd_write_multiple),
.cmd_stop(si570_i2c_cmd_stop),
.cmd_valid(si570_i2c_cmd_valid),
.cmd_ready(si570_i2c_cmd_ready),
.data_in(si570_i2c_data),
.data_in_valid(si570_i2c_data_valid),
.data_in_ready(si570_i2c_data_ready),
.data_in_last(si570_i2c_data_last),
.data_out(),
.data_out_valid(),
.data_out_ready(1),
.data_out_last(),
.scl_i(si570_scl_i),
.scl_o(si570_scl_o),
.scl_t(si570_scl_t),
.sda_i(si570_sda_i),
.sda_o(si570_sda_o),
.sda_t(si570_sda_t),
.busy(),
.bus_control(),
.bus_active(),
.missed_ack(),
.prescale(312),
.stop_on_idle(1)
);
// 10G Ethernet PHY
wire [71:0] sfp_a_tx_dc;
wire [71:0] sfp_a_rx_dc;
wire [71:0] sfp_b_tx_dc;
wire [71:0] sfp_b_rx_dc;
wire [71:0] sfp_c_tx_dc;
wire [71:0] sfp_c_rx_dc;
wire [71:0] sfp_d_tx_dc;
wire [71:0] sfp_d_rx_dc;
wire [367:0] phy_reconfig_from_xcvr;
wire [559:0] phy_reconfig_to_xcvr;
assign SFPA_MOD1_SCL = 1'bz;
assign SFPA_MOD2_SDA = 1'bz;
assign SFPA_TXDISABLE = 1'b0;
assign SPFA_RATESEL = 2'b00;
assign SFPB_MOD1_SCL = 1'bz;
assign SFPB_MOD2_SDA = 1'bz;
assign SFPB_TXDISABLE = 1'b0;
assign SPFB_RATESEL = 2'b00;
assign SFPC_MOD1_SCL = 1'bz;
assign SFPC_MOD2_SDA = 1'bz;
assign SFPC_TXDISABLE = 1'b0;
assign SPFC_RATESEL = 2'b00;
assign SFPD_MOD1_SCL = 1'bz;
assign SFPD_MOD2_SDA = 1'bz;
assign SFPD_TXDISABLE = 1'b0;
assign SPFD_RATESEL = 2'b00;
phy
phy_inst (
.pll_ref_clk(SFP_REFCLK_P),
.pll_locked(phy_pll_locked),
.tx_serial_data_0(SFPA_TX_p),
.rx_serial_data_0(SFPA_RX_p),
.tx_serial_data_1(SFPB_TX_p),
.rx_serial_data_1(SFPB_RX_p),
.tx_serial_data_2(SFPC_TX_p),
.rx_serial_data_2(SFPC_RX_p),
.tx_serial_data_3(SFPD_TX_p),
.rx_serial_data_3(SFPD_RX_p),
.xgmii_tx_dc_0(sfp_a_tx_dc),
.xgmii_rx_dc_0(sfp_a_rx_dc),
.xgmii_tx_dc_1(sfp_b_tx_dc),
.xgmii_rx_dc_1(sfp_b_rx_dc),
.xgmii_tx_dc_2(sfp_c_tx_dc),
.xgmii_rx_dc_2(sfp_c_rx_dc),
.xgmii_tx_dc_3(sfp_d_tx_dc),
.xgmii_rx_dc_3(sfp_d_rx_dc),
.xgmii_rx_clk(clk_156mhz),
.xgmii_tx_clk(clk_156mhz),
.tx_ready(~rst_156mhz),
.rx_ready(),
.rx_data_ready(),
.phy_mgmt_clk(clk_50mhz),
.phy_mgmt_clk_reset(rst_50mhz),
.phy_mgmt_address(9'd0),
.phy_mgmt_read(1'b0),
.phy_mgmt_readdata(),
.phy_mgmt_waitrequest(),
.phy_mgmt_write(1'b0),
.phy_mgmt_writedata(32'd0),
.reconfig_from_xcvr(phy_reconfig_from_xcvr),
.reconfig_to_xcvr(phy_reconfig_to_xcvr)
);
phy_reconfig
phy_reconfig_inst (
.reconfig_busy(),
.mgmt_clk_clk(clk_50mhz),
.mgmt_rst_reset(rst_50mhz),
.reconfig_mgmt_address(7'd0),
.reconfig_mgmt_read(1'b0),
.reconfig_mgmt_readdata(),
.reconfig_mgmt_waitrequest(),
.reconfig_mgmt_write(1'b0),
.reconfig_mgmt_writedata(32'd0),
.reconfig_to_xcvr(phy_reconfig_to_xcvr),
.reconfig_from_xcvr(phy_reconfig_from_xcvr)
);
// Convert XGMII interfaces
wire [63:0] sfp_a_txd_int;
wire [7:0] sfp_a_txc_int;
wire [63:0] sfp_a_rxd_int;
wire [7:0] sfp_a_rxc_int;
wire [63:0] sfp_b_txd_int;
wire [7:0] sfp_b_txc_int;
wire [63:0] sfp_b_rxd_int;
wire [7:0] sfp_b_rxc_int;
wire [63:0] sfp_c_txd_int;
wire [7:0] sfp_c_txc_int;
wire [63:0] sfp_c_rxd_int;
wire [7:0] sfp_c_rxc_int;
wire [63:0] sfp_d_txd_int;
wire [7:0] sfp_d_txc_int;
wire [63:0] sfp_d_rxd_int;
wire [7:0] sfp_d_rxc_int;
xgmii_interleave
xgmii_interleave_inst_a (
.input_xgmii_d(sfp_a_txd_int),
.input_xgmii_c(sfp_a_txc_int),
.output_xgmii_dc(sfp_a_tx_dc)
);
xgmii_deinterleave
xgmii_deinterleave_inst_a (
.input_xgmii_dc(sfp_a_rx_dc),
.output_xgmii_d(sfp_a_rxd_int),
.output_xgmii_c(sfp_a_rxc_int)
);
xgmii_interleave
xgmii_interleave_inst_b (
.input_xgmii_d(sfp_b_txd_int),
.input_xgmii_c(sfp_b_txc_int),
.output_xgmii_dc(sfp_b_tx_dc)
);
xgmii_deinterleave
xgmii_deinterleave_inst_b (
.input_xgmii_dc(sfp_b_rx_dc),
.output_xgmii_d(sfp_b_rxd_int),
.output_xgmii_c(sfp_b_rxc_int)
);
xgmii_interleave
xgmii_interleave_inst_c (
.input_xgmii_d(sfp_c_txd_int),
.input_xgmii_c(sfp_c_txc_int),
.output_xgmii_dc(sfp_c_tx_dc)
);
xgmii_deinterleave
xgmii_deinterleave_inst_c (
.input_xgmii_dc(sfp_c_rx_dc),
.output_xgmii_d(sfp_c_rxd_int),
.output_xgmii_c(sfp_c_rxc_int)
);
xgmii_interleave
xgmii_interleave_inst_d (
.input_xgmii_d(sfp_d_txd_int),
.input_xgmii_c(sfp_d_txc_int),
.output_xgmii_dc(sfp_d_tx_dc)
);
xgmii_deinterleave
xgmii_deinterleave_inst_d (
.input_xgmii_dc(sfp_d_rx_dc),
.output_xgmii_d(sfp_d_rxd_int),
.output_xgmii_c(sfp_d_rxc_int)
);
// Core logic
fpga_core
core_inst (
/*
* Clock: 156.25MHz
* Synchronous reset
*/
.clk(clk_156mhz),
.rst(rst_156mhz),
/*
* GPIO
*/
.btn(btn_int),
.sw(sw_int),
.led(led_int),
.led_bkt(led_bkt_int),
.led_hex0_d(led_hex0_d_int),
.led_hex0_dp(led_hex0_dp_int),
.led_hex1_d(led_hex1_d_int),
.led_hex1_dp(led_hex1_dp_int),
/*
* 10G Ethernet
*/
.sfp_a_txd(sfp_a_txd_int),
.sfp_a_txc(sfp_a_txc_int),
.sfp_a_rxd(sfp_a_rxd_int),
.sfp_a_rxc(sfp_a_rxc_int),
.sfp_b_txd(sfp_b_txd_int),
.sfp_b_txc(sfp_b_txc_int),
.sfp_b_rxd(sfp_b_rxd_int),
.sfp_b_rxc(sfp_b_rxc_int),
.sfp_c_txd(sfp_c_txd_int),
.sfp_c_txc(sfp_c_txc_int),
.sfp_c_rxd(sfp_c_rxd_int),
.sfp_c_rxc(sfp_c_rxc_int),
.sfp_d_txd(sfp_d_txd_int),
.sfp_d_txc(sfp_d_txc_int),
.sfp_d_rxd(sfp_d_rxd_int),
.sfp_d_rxc(sfp_d_rxc_int)
);
endmodule

View File

@ -0,0 +1,610 @@
/*
Copyright (c) 2016-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA core logic
*/
module fpga_core
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [3:0] btn,
input wire [3:0] sw,
output wire [3:0] led,
output wire [3:0] led_bkt,
output wire [6:0] led_hex0_d,
output wire led_hex0_dp,
output wire [6:0] led_hex1_d,
output wire led_hex1_dp,
/*
* 10G Ethernet
*/
output wire [63:0] sfp_a_txd,
output wire [7:0] sfp_a_txc,
input wire [63:0] sfp_a_rxd,
input wire [7:0] sfp_a_rxc,
output wire [63:0] sfp_b_txd,
output wire [7:0] sfp_b_txc,
input wire [63:0] sfp_b_rxd,
input wire [7:0] sfp_b_rxc,
output wire [63:0] sfp_c_txd,
output wire [7:0] sfp_c_txc,
input wire [63:0] sfp_c_rxd,
input wire [7:0] sfp_c_rxc,
output wire [63:0] sfp_d_txd,
output wire [7:0] sfp_d_txc,
input wire [63:0] sfp_d_rxd,
input wire [7:0] sfp_d_rxc
);
// AXI between MAC and Ethernet modules
wire [63:0] rx_axis_tdata;
wire [7:0] rx_axis_tkeep;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [63:0] tx_axis_tdata;
wire [7:0] tx_axis_tkeep;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [63:0] rx_eth_payload_axis_tdata;
wire [7:0] rx_eth_payload_axis_tkeep;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [63:0] tx_eth_payload_axis_tdata;
wire [7:0] tx_eth_payload_axis_tkeep;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [63:0] rx_ip_payload_axis_tdata;
wire [7:0] rx_ip_payload_axis_tkeep;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [63:0] tx_ip_payload_axis_tdata;
wire [7:0] tx_ip_payload_axis_tkeep;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [63:0] rx_udp_payload_axis_tdata;
wire [7:0] rx_udp_payload_axis_tkeep;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [63:0] tx_udp_payload_axis_tdata;
wire [7:0] tx_udp_payload_axis_tkeep;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [63:0] rx_fifo_udp_payload_axis_tdata;
wire [7:0] rx_fifo_udp_payload_axis_tkeep;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [63:0] tx_fifo_udp_payload_axis_tdata;
wire [7:0] tx_fifo_udp_payload_axis_tkeep;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tkeep = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tkeep = tx_fifo_udp_payload_axis_tkeep;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tkeep = rx_udp_payload_axis_tkeep;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
if (tx_udp_payload_axis_tvalid) begin
if (!valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
valid_last <= 1'b1;
end
if (tx_udp_payload_axis_tlast) begin
valid_last <= 1'b0;
end
end
end
end
//assign led = sw;
assign led = led_reg;
assign led_bkt = led_reg;
assign led_hex0_d = 7'h00;
assign led_hex0_dp = 1'b0;
assign led_hex1_d = 7'h00;
assign led_hex1_dp = 1'b0;
assign sfp_b_txd = 64'h0707070707070707;
assign sfp_b_txc = 8'hff;
assign sfp_c_txd = 64'h0707070707070707;
assign sfp_c_txc = 8'hff;
assign sfp_d_txd = 64'h0707070707070707;
assign sfp_d_txc = 8'hff;
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
.ENABLE_DIC(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_ADDR_WIDTH(9),
.TX_FRAME_FIFO(1),
.RX_FIFO_ADDR_WIDTH(9),
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(clk),
.rx_rst(rst),
.tx_clk(clk),
.tx_rst(rst),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tkeep(tx_axis_tkeep),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tkeep(rx_axis_tkeep),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(sfp_a_rxd),
.xgmii_rxc(sfp_a_rxc),
.xgmii_txd(sfp_a_txd),
.xgmii_txc(sfp_a_txc),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),
.tx_fifo_good_frame(),
.rx_error_bad_frame(),
.rx_error_bad_fcs(),
.rx_fifo_overflow(),
.rx_fifo_bad_frame(),
.rx_fifo_good_frame(),
.ifg_delay(8'd12)
);
eth_axis_rx_64
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tkeep(rx_axis_tkeep),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx_64
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tkeep(tx_axis_tkeep),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete_64
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tkeep(tx_ip_payload_axis_tkeep),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tkeep(rx_ip_payload_axis_tkeep),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tkeep(tx_udp_payload_axis_tkeep),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tkeep(rx_udp_payload_axis_tkeep),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(1'b0)
);
axis_fifo #(
.ADDR_WIDTH(10),
.DATA_WIDTH(64),
.KEEP_ENABLE(1),
.KEEP_WIDTH(8),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(rx_fifo_udp_payload_axis_tkeep),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule

View File

@ -0,0 +1,895 @@
/*
Copyright (c) 2015-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* I2C master
*/
module i2c_master (
input wire clk,
input wire rst,
/*
* Host interface
*/
input wire [6:0] cmd_address,
input wire cmd_start,
input wire cmd_read,
input wire cmd_write,
input wire cmd_write_multiple,
input wire cmd_stop,
input wire cmd_valid,
output wire cmd_ready,
input wire [7:0] data_in,
input wire data_in_valid,
output wire data_in_ready,
input wire data_in_last,
output wire [7:0] data_out,
output wire data_out_valid,
input wire data_out_ready,
output wire data_out_last,
/*
* I2C interface
*/
input wire scl_i,
output wire scl_o,
output wire scl_t,
input wire sda_i,
output wire sda_o,
output wire sda_t,
/*
* Status
*/
output wire busy,
output wire bus_control,
output wire bus_active,
output wire missed_ack,
/*
* Configuration
*/
input wire [15:0] prescale,
input wire stop_on_idle
);
/*
I2C
Read
__ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ __
sda \__/_6_X_5_X_4_X_3_X_2_X_1_X_0_\_R___A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A____/
____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____
scl ST \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ SP
Write
__ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ __
sda \__/_6_X_5_X_4_X_3_X_2_X_1_X_0_/_W_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_/_N_\__/
____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____
scl ST \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ SP
Commands:
read
read data byte
set start to force generation of a start condition
start is implied when bus is inactive or active with write or different address
set stop to issue a stop condition after reading current byte
if stop is set with read command, then data_out_last will be set
write
write data byte
set start to force generation of a start condition
start is implied when bus is inactive or active with read or different address
set stop to issue a stop condition after writing current byte
write multiple
write multiple data bytes (until data_in_last)
set start to force generation of a start condition
start is implied when bus is inactive or active with read or different address
set stop to issue a stop condition after writing block
stop
issue stop condition if bus is active
Status:
busy
module is communicating over the bus
bus_control
module has control of bus in active state
bus_active
bus is active, not necessarily controlled by this module
missed_ack
strobed when a slave ack is missed
Parameters:
prescale
set prescale to 1/4 of the minimum clock period in units
of input clk cycles (prescale = Fclk / (FI2Cclk * 4))
stop_on_idle
automatically issue stop when command input is not valid
Example of interfacing with tristate pins:
(this will work for any tristate bus)
assign scl_i = scl_pin;
assign scl_pin = scl_t ? 1'bz : scl_o;
assign sda_i = sda_pin;
assign sda_pin = sda_t ? 1'bz : sda_o;
Equivalent code that does not use *_t connections:
(we can get away with this because I2C is open-drain)
assign scl_i = scl_pin;
assign scl_pin = scl_o ? 1'bz : 1'b0;
assign sda_i = sda_pin;
assign sda_pin = sda_o ? 1'bz : 1'b0;
Example of two interconnected I2C devices:
assign scl_1_i = scl_1_o & scl_2_o;
assign scl_2_i = scl_1_o & scl_2_o;
assign sda_1_i = sda_1_o & sda_2_o;
assign sda_2_i = sda_1_o & sda_2_o;
Example of two I2C devices sharing the same pins:
assign scl_1_i = scl_pin;
assign scl_2_i = scl_pin;
assign scl_pin = (scl_1_o & scl_2_o) ? 1'bz : 1'b0;
assign sda_1_i = sda_pin;
assign sda_2_i = sda_pin;
assign sda_pin = (sda_1_o & sda_2_o) ? 1'bz : 1'b0;
Notes:
scl_o should not be connected directly to scl_i, only via AND logic or a tristate
I/O pin. This would prevent devices from stretching the clock period.
*/
localparam [4:0]
STATE_IDLE = 4'd0,
STATE_ACTIVE_WRITE = 4'd1,
STATE_ACTIVE_READ = 4'd2,
STATE_START_WAIT = 4'd3,
STATE_START = 4'd4,
STATE_ADDRESS_1 = 4'd5,
STATE_ADDRESS_2 = 4'd6,
STATE_WRITE_1 = 4'd7,
STATE_WRITE_2 = 4'd8,
STATE_WRITE_3 = 4'd9,
STATE_READ = 4'd10,
STATE_STOP = 4'd11;
reg [4:0] state_reg = STATE_IDLE, state_next;
localparam [4:0]
PHY_STATE_IDLE = 5'd0,
PHY_STATE_ACTIVE = 5'd1,
PHY_STATE_REPEATED_START_1 = 5'd2,
PHY_STATE_REPEATED_START_2 = 5'd3,
PHY_STATE_START_1 = 5'd4,
PHY_STATE_START_2 = 5'd5,
PHY_STATE_WRITE_BIT_1 = 5'd6,
PHY_STATE_WRITE_BIT_2 = 5'd7,
PHY_STATE_WRITE_BIT_3 = 5'd8,
PHY_STATE_READ_BIT_1 = 5'd9,
PHY_STATE_READ_BIT_2 = 5'd10,
PHY_STATE_READ_BIT_3 = 5'd11,
PHY_STATE_READ_BIT_4 = 5'd12,
PHY_STATE_STOP_1 = 5'd13,
PHY_STATE_STOP_2 = 5'd14,
PHY_STATE_STOP_3 = 5'd15;
reg [4:0] phy_state_reg = STATE_IDLE, phy_state_next;
reg phy_start_bit;
reg phy_stop_bit;
reg phy_write_bit;
reg phy_read_bit;
reg phy_release_bus;
reg phy_tx_data;
reg phy_rx_data_reg = 1'b0, phy_rx_data_next;
reg [6:0] addr_reg = 7'd0, addr_next;
reg [7:0] data_reg = 8'd0, data_next;
reg last_reg = 1'b0, last_next;
reg mode_read_reg = 1'b0, mode_read_next;
reg mode_write_multiple_reg = 1'b0, mode_write_multiple_next;
reg mode_stop_reg = 1'b0, mode_stop_next;
reg [16:0] delay_reg = 16'd0, delay_next;
reg delay_scl_reg = 1'b0, delay_scl_next;
reg delay_sda_reg = 1'b0, delay_sda_next;
reg [3:0] bit_count_reg = 4'd0, bit_count_next;
reg cmd_ready_reg = 1'b0, cmd_ready_next;
reg data_in_ready_reg = 1'b0, data_in_ready_next;
reg [7:0] data_out_reg = 8'd0, data_out_next;
reg data_out_valid_reg = 1'b0, data_out_valid_next;
reg data_out_last_reg = 1'b0, data_out_last_next;
reg scl_i_reg = 1'b1;
reg sda_i_reg = 1'b1;
reg scl_o_reg = 1'b1, scl_o_next;
reg sda_o_reg = 1'b1, sda_o_next;
reg last_scl_i_reg = 1'b1;
reg last_sda_i_reg = 1'b1;
reg busy_reg = 1'b0;
reg bus_active_reg = 1'b0;
reg bus_control_reg = 1'b0, bus_control_next;
reg missed_ack_reg = 1'b0, missed_ack_next;
assign cmd_ready = cmd_ready_reg;
assign data_in_ready = data_in_ready_reg;
assign data_out = data_out_reg;
assign data_out_valid = data_out_valid_reg;
assign data_out_last = data_out_last_reg;
assign scl_o = scl_o_reg;
assign scl_t = scl_o_reg;
assign sda_o = sda_o_reg;
assign sda_t = sda_o_reg;
assign busy = busy_reg;
assign bus_active = bus_active_reg;
assign bus_control = bus_control_reg;
assign missed_ack = missed_ack_reg;
wire scl_posedge = scl_i_reg & ~last_scl_i_reg;
wire scl_negedge = ~scl_i_reg & last_scl_i_reg;
wire sda_posedge = sda_i_reg & ~last_sda_i_reg;
wire sda_negedge = ~sda_i_reg & last_sda_i_reg;
wire start_bit = sda_negedge & scl_i_reg;
wire stop_bit = sda_posedge & scl_i_reg;
always @* begin
state_next = STATE_IDLE;
phy_start_bit = 1'b0;
phy_stop_bit = 1'b0;
phy_write_bit = 1'b0;
phy_read_bit = 1'b0;
phy_tx_data = 1'b0;
phy_release_bus = 1'b0;
addr_next = addr_reg;
data_next = data_reg;
last_next = last_reg;
mode_read_next = mode_read_reg;
mode_write_multiple_next = mode_write_multiple_reg;
mode_stop_next = mode_stop_reg;
bit_count_next = bit_count_reg;
cmd_ready_next = 1'b0;
data_in_ready_next = 1'b0;
data_out_next = data_out_reg;
data_out_valid_next = data_out_valid_reg & ~data_out_ready;
data_out_last_next = data_out_last_reg;
missed_ack_next = 1'b0;
// generate delays
if (phy_state_reg != PHY_STATE_IDLE && phy_state_reg != PHY_STATE_ACTIVE) begin
// wait for phy operation
state_next = state_reg;
end else begin
// process states
case (state_reg)
STATE_IDLE: begin
// line idle
cmd_ready_next = 1'b1;
if (cmd_ready & cmd_valid) begin
// command valid
if (cmd_read ^ (cmd_write | cmd_write_multiple)) begin
// read or write command
addr_next = cmd_address;
mode_read_next = cmd_read;
mode_write_multiple_next = cmd_write_multiple;
mode_stop_next = cmd_stop;
cmd_ready_next = 1'b0;
// start bit
if (bus_active) begin
state_next = STATE_START_WAIT;
end else begin
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end
end else begin
// invalid or unspecified - ignore
state_next = STATE_IDLE;
end
end else begin
state_next = STATE_IDLE;
end
end
STATE_ACTIVE_WRITE: begin
// line active with current address and read/write mode
cmd_ready_next = 1'b1;
if (cmd_ready & cmd_valid) begin
// command valid
if (cmd_read ^ (cmd_write | cmd_write_multiple)) begin
// read or write command
addr_next = cmd_address;
mode_read_next = cmd_read;
mode_write_multiple_next = cmd_write_multiple;
mode_stop_next = cmd_stop;
cmd_ready_next = 1'b0;
if (cmd_start || cmd_address != addr_reg || cmd_read) begin
// address or mode mismatch or forced start - repeated start
// repeated start bit
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end else begin
// address and mode match
// start write
data_in_ready_next = 1'b1;
state_next = STATE_WRITE_1;
end
end else if (cmd_stop && !(cmd_read || cmd_write || cmd_write_multiple)) begin
// stop command
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid or unspecified - ignore
state_next = STATE_ACTIVE_WRITE;
end
end else begin
if (stop_on_idle & cmd_ready & ~cmd_valid) begin
// no waiting command and stop_on_idle selected, issue stop condition
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end else begin
state_next = STATE_ACTIVE_WRITE;
end
end
end
STATE_ACTIVE_READ: begin
// line active to current address
cmd_ready_next = ~data_out_valid;
if (cmd_ready & cmd_valid) begin
// command valid
if (cmd_read ^ (cmd_write | cmd_write_multiple)) begin
// read or write command
addr_next = cmd_address;
mode_read_next = cmd_read;
mode_write_multiple_next = cmd_write_multiple;
mode_stop_next = cmd_stop;
cmd_ready_next = 1'b0;
if (cmd_start || cmd_address != addr_reg || cmd_write) begin
// address or mode mismatch or forced start - repeated start
// write nack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
// repeated start bit
state_next = STATE_START;
end else begin
// address and mode match
// write ack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b0;
// start next read
bit_count_next = 4'd8;
data_next = 8'd0;
state_next = STATE_READ;
end
end else if (cmd_stop && !(cmd_read || cmd_write || cmd_write_multiple)) begin
// stop command
// write nack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
// send stop bit
state_next = STATE_STOP;
end else begin
// invalid or unspecified - ignore
state_next = STATE_ACTIVE_READ;
end
end else begin
if (stop_on_idle & cmd_ready & ~cmd_valid) begin
// no waiting command and stop_on_idle selected, issue stop condition
// write ack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
// send stop bit
state_next = STATE_STOP;
end else begin
state_next = STATE_ACTIVE_READ;
end
end
end
STATE_START_WAIT: begin
// wait for bus idle
if (bus_active) begin
state_next = STATE_START_WAIT;
end else begin
// bus is idle, take control
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end
end
STATE_START: begin
// send start bit
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end
STATE_ADDRESS_1: begin
// send address
bit_count_next = bit_count_reg - 1;
if (bit_count_reg > 1) begin
// send address
phy_write_bit = 1'b1;
phy_tx_data = addr_reg[bit_count_reg-2];
state_next = STATE_ADDRESS_1;
end else if (bit_count_reg > 0) begin
// send read/write bit
phy_write_bit = 1'b1;
phy_tx_data = mode_read_reg;
state_next = STATE_ADDRESS_1;
end else begin
// read ack bit
phy_read_bit = 1'b1;
state_next = STATE_ADDRESS_2;
end
end
STATE_ADDRESS_2: begin
// read ack bit
missed_ack_next = phy_rx_data_reg;
if (mode_read_reg) begin
// start read
bit_count_next = 4'd8;
data_next = 1'b0;
state_next = STATE_READ;
end else begin
// start write
data_in_ready_next = 1'b1;
state_next = STATE_WRITE_1;
end
end
STATE_WRITE_1: begin
data_in_ready_next = 1'b1;
if (data_in_ready & data_in_valid) begin
// got data, start write
data_next = data_in;
last_next = data_in_last;
bit_count_next = 4'd8;
data_in_ready_next = 1'b0;
state_next = STATE_WRITE_2;
end else begin
// wait for data
state_next = STATE_WRITE_1;
end
end
STATE_WRITE_2: begin
// send data
bit_count_next = bit_count_reg - 1;
if (bit_count_reg > 0) begin
// write data bit
phy_write_bit = 1'b1;
phy_tx_data = data_reg[bit_count_reg-1];
state_next = STATE_WRITE_2;
end else begin
// read ack bit
phy_read_bit = 1'b1;
state_next = STATE_WRITE_3;
end
end
STATE_WRITE_3: begin
// read ack bit
missed_ack_next = phy_rx_data_reg;
if (mode_write_multiple_reg && !last_reg) begin
// more to write
state_next = STATE_WRITE_1;
end else if (mode_stop_reg) begin
// last cycle and stop selected
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end else begin
// otherwise, return to bus active state
state_next = STATE_ACTIVE_WRITE;
end
end
STATE_READ: begin
// read data
bit_count_next = bit_count_reg - 1;
data_next = {data_reg[6:0], phy_rx_data_reg};
if (bit_count_reg > 0) begin
// read next bit
phy_read_bit = 1'b1;
state_next = STATE_READ;
end else begin
// output data word
data_out_next = data_next;
data_out_valid_next = 1'b1;
data_out_last_next = 1'b0;
if (mode_stop_reg) begin
// send nack and stop
data_out_last_next = 1'b1;
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
state_next = STATE_STOP;
end else begin
// return to bus active state
state_next = STATE_ACTIVE_READ;
end
end
end
STATE_STOP: begin
// send stop bit
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end
endcase
end
end
always @* begin
phy_state_next = PHY_STATE_IDLE;
phy_rx_data_next = phy_rx_data_reg;
delay_next = delay_reg;
delay_scl_next = delay_scl_reg;
delay_sda_next = delay_sda_reg;
scl_o_next = scl_o_reg;
sda_o_next = sda_o_reg;
bus_control_next = bus_control_reg;
if (phy_release_bus) begin
// release bus and return to idle state
sda_o_next = 1'b1;
scl_o_next = 1'b1;
delay_scl_next = 1'b0;
delay_sda_next = 1'b0;
delay_next = 1'b0;
phy_state_next = PHY_STATE_IDLE;
end else if (delay_scl_reg) begin
// wait for SCL to match command
delay_scl_next = scl_o_reg & ~scl_i_reg;
phy_state_next = phy_state_reg;
end else if (delay_sda_reg) begin
// wait for SDA to match command
delay_sda_next = sda_o_reg & ~sda_i_reg;
phy_state_next = phy_state_reg;
end else if (delay_reg > 0) begin
// time delay
delay_next = delay_reg - 1;
phy_state_next = phy_state_reg;
end else begin
case (phy_state_reg)
PHY_STATE_IDLE: begin
// bus idle - wait for start command
sda_o_next = 1'b1;
scl_o_next = 1'b1;
if (phy_start_bit) begin
sda_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_START_1;
end else begin
phy_state_next = PHY_STATE_IDLE;
end
end
PHY_STATE_ACTIVE: begin
// bus active
if (phy_start_bit) begin
sda_o_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_REPEATED_START_1;
end else if (phy_write_bit) begin
sda_o_next = phy_tx_data;
delay_next = prescale;
phy_state_next = PHY_STATE_WRITE_BIT_1;
end else if (phy_read_bit) begin
sda_o_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_1;
end else if (phy_stop_bit) begin
sda_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_STOP_1;
end else begin
phy_state_next = PHY_STATE_ACTIVE;
end
end
PHY_STATE_REPEATED_START_1: begin
// generate repeated start bit
// ______
// sda XXX/ \_______
// _______
// scl ______/ \___
//
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_REPEATED_START_2;
end
PHY_STATE_REPEATED_START_2: begin
// generate repeated start bit
// ______
// sda XXX/ \_______
// _______
// scl ______/ \___
//
sda_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_START_1;
end
PHY_STATE_START_1: begin
// generate start bit
// ___
// sda \_______
// _______
// scl \___
//
scl_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_START_2;
end
PHY_STATE_START_2: begin
// generate start bit
// ___
// sda \_______
// _______
// scl \___
//
bus_control_next = 1'b1;
phy_state_next = PHY_STATE_ACTIVE;
end
PHY_STATE_WRITE_BIT_1: begin
// write bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale << 1;
phy_state_next = PHY_STATE_WRITE_BIT_2;
end
PHY_STATE_WRITE_BIT_2: begin
// write bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_WRITE_BIT_3;
end
PHY_STATE_WRITE_BIT_3: begin
// write bit
// ________
// sda X________X
// ____
// scl __/ \__
phy_state_next = PHY_STATE_ACTIVE;
end
PHY_STATE_READ_BIT_1: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_2;
end
PHY_STATE_READ_BIT_2: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
phy_rx_data_next = sda_i_reg;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_3;
end
PHY_STATE_READ_BIT_3: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_4;
end
PHY_STATE_READ_BIT_4: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
phy_state_next = PHY_STATE_ACTIVE;
end
PHY_STATE_STOP_1: begin
// stop bit
// ___
// sda XXX\_______/
// _______
// scl _______/
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_STOP_2;
end
PHY_STATE_STOP_2: begin
// stop bit
// ___
// sda XXX\_______/
// _______
// scl _______/
sda_o_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_STOP_3;
end
PHY_STATE_STOP_3: begin
// stop bit
// ___
// sda XXX\_______/
// _______
// scl _______/
bus_control_next = 1'b0;
phy_state_next = PHY_STATE_IDLE;
end
endcase
end
end
always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
phy_state_reg <= PHY_STATE_IDLE;
delay_reg <= 16'd0;
delay_scl_reg <= 1'b0;
delay_sda_reg <= 1'b0;
cmd_ready_reg <= 1'b0;
data_in_ready_reg <= 1'b0;
data_out_valid_reg <= 1'b0;
scl_o_reg <= 1'b1;
sda_o_reg <= 1'b1;
busy_reg <= 1'b0;
bus_active_reg <= 1'b0;
bus_control_reg <= 1'b0;
missed_ack_reg <= 1'b0;
end else begin
state_reg <= state_next;
phy_state_reg <= phy_state_next;
delay_reg <= delay_next;
delay_scl_reg <= delay_scl_next;
delay_sda_reg <= delay_sda_next;
cmd_ready_reg <= cmd_ready_next;
data_in_ready_reg <= data_in_ready_next;
data_out_valid_reg <= data_out_valid_next;
scl_o_reg <= scl_o_next;
sda_o_reg <= sda_o_next;
busy_reg <= !(state_reg == STATE_IDLE || state_reg == STATE_ACTIVE_WRITE || state_reg == STATE_ACTIVE_READ);
if (start_bit) begin
bus_active_reg <= 1'b1;
end else if (stop_bit) begin
bus_active_reg <= 1'b0;
end else begin
bus_active_reg <= bus_active_reg;
end
bus_control_reg <= bus_control_next;
missed_ack_reg <= missed_ack_next;
end
phy_rx_data_reg <= phy_rx_data_next;
addr_reg <= addr_next;
data_reg <= data_next;
last_reg <= last_next;
mode_read_reg <= mode_read_next;
mode_write_multiple_reg <= mode_write_multiple_next;
mode_stop_reg <= mode_stop_next;
bit_count_reg <= bit_count_next;
data_out_reg <= data_out_next;
data_out_last_reg <= data_out_last_next;
scl_i_reg <= scl_i;
sda_i_reg <= sda_i;
last_scl_i_reg <= scl_i_reg;
last_sda_i_reg <= sda_i_reg;
end
endmodule

View File

@ -0,0 +1,455 @@
/*
Copyright (c) 2015-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* si570_i2c_init
*/
module si570_i2c_init (
input wire clk,
input wire rst,
/*
* I2C master interface
*/
output wire [6:0] cmd_address,
output wire cmd_start,
output wire cmd_read,
output wire cmd_write,
output wire cmd_write_multiple,
output wire cmd_stop,
output wire cmd_valid,
input wire cmd_ready,
output wire [7:0] data_out,
output wire data_out_valid,
input wire data_out_ready,
output wire data_out_last,
/*
* Status
*/
output wire busy,
/*
* Configuration
*/
input wire start
);
/*
Generic module for I2C bus initialization. Good for use when multiple devices
on an I2C bus must be initialized on system start without intervention of a
general-purpose processor.
Copy this file and change init_data and INIT_DATA_LEN as needed.
This module can be used in two modes: simple device initalization, or multiple
device initialization. In multiple device mode, the same initialization sequence
can be performed on multiple different device addresses.
To use single device mode, only use the start write to address and write data commands.
The module will generate the I2C commands in sequential order. Terminate the list
with a 0 entry.
To use the multiple device mode, use the start data and start address block commands
to set up lists of initialization data and device addresses. The module enters
multiple device mode upon seeing a start data block command. The module stores the
offset of the start of the data block and then skips ahead until it reaches a start
address block command. The module will store the offset to the address block and
read the first address in the block. Then it will jump back to the data block
and execute it, substituting the stored address for each current address write
command. Upon reaching the start address block command, the module will read out the
next address and start again at the top of the data block. If the module encounters
a start data block command while looking for an address, then it will store a new data
offset and then look for a start address block command. Terminate the list with a 0
entry. Normal address commands will operate normally inside a data block.
Commands:
00 0000000 : stop
00 0000001 : exit multiple device mode
00 0000011 : start write to current address
00 0001000 : start address block
00 0001001 : start data block
01 aaaaaaa : start write to address
1 dddddddd : write 8-bit data
Examples
write 0x11223344 to register 0x0004 on device at 0x50
01 1010000 start write to 0x50
1 00000000 write address 0x0004
1 00000100
1 00010001 write data 0x11223344
1 00100010
1 00110011
1 01000100
0 00000000 stop
write 0x11223344 to register 0x0004 on devices at 0x50, 0x51, 0x52, and 0x53
00 0001001 start data block
00 0000011 start write to current address
1 00000000 write address 0x0004
1 00000100
1 00010001 write data 0x11223344
1 00100010
1 00110011
1 01000100
00 0001000 start address block
01 1010000 address 0x50
01 1010001 address 0x51
01 1010010 address 0x52
01 1010011 address 0x53
00 0000000 stop
*/
// init_data ROM
localparam INIT_DATA_LEN = 18;
reg [8:0] init_data [INIT_DATA_LEN-1:0];
initial begin
// Set Si570 to generate 644.53125 MHz
init_data[0] = {2'b01, 7'h00}; // start write to address 0x00
init_data[1] = {1'b1, 8'd137}; // write address 137
init_data[2] = {1'b1, 8'h10}; // write data 0x10 (freeze DCO)
init_data[3] = {2'b01, 7'h00}; // start write to address 0x00
init_data[4] = {1'b1, 8'd7}; // write address 7
init_data[5] = {1'b1, {3'b000, 5'b000000}}; // write data (address 7) (HS_DIV = 3'b000)
init_data[6] = {1'b1, {2'b01, 6'h2}}; // write data (address 8) (N1 = 7'b000001)
init_data[7] = {1'b1, 8'hD1}; // write data (address 9)
init_data[8] = {1'b1, 8'hE1}; // write data (address 10)
init_data[9] = {1'b1, 8'h27}; // write data (address 11)
init_data[10] = {1'b1, 8'hAF}; // write data (address 12) (RFREQ = 38'h2D1E127AF)
init_data[11] = {2'b01, 7'h00}; // start write to address 0x00
init_data[12] = {1'b1, 8'd137}; // write address 137
init_data[13] = {1'b1, 8'h00}; // write data 0x00 (un-freeze DCO)
init_data[14] = {2'b01, 7'h00}; // start write to address 0x00
init_data[15] = {1'b1, 8'd135}; // write address 135
init_data[16] = {1'b1, 8'h40}; // write data 0x40 (new frequency applied)
init_data[17] = 9'd0; // stop
end
localparam [3:0]
STATE_IDLE = 3'd0,
STATE_RUN = 3'd1,
STATE_TABLE_1 = 3'd2,
STATE_TABLE_2 = 3'd3,
STATE_TABLE_3 = 3'd4;
reg [4:0] state_reg = STATE_IDLE, state_next;
parameter AW = $clog2(INIT_DATA_LEN);
reg [8:0] init_data_reg = 9'd0;
reg [AW-1:0] address_reg = {AW{1'b0}}, address_next;
reg [AW-1:0] address_ptr_reg = {AW{1'b0}}, address_ptr_next;
reg [AW-1:0] data_ptr_reg = {AW{1'b0}}, data_ptr_next;
reg [6:0] cur_address_reg = 7'd0, cur_address_next;
reg [6:0] cmd_address_reg = 7'd0, cmd_address_next;
reg cmd_start_reg = 1'b0, cmd_start_next;
reg cmd_write_reg = 1'b0, cmd_write_next;
reg cmd_stop_reg = 1'b0, cmd_stop_next;
reg cmd_valid_reg = 1'b0, cmd_valid_next;
reg [7:0] data_out_reg = 8'd0, data_out_next;
reg data_out_valid_reg = 1'b0, data_out_valid_next;
reg start_flag_reg = 1'b0, start_flag_next;
reg busy_reg = 1'b0;
assign cmd_address = cmd_address_reg;
assign cmd_start = cmd_start_reg;
assign cmd_read = 1'b0;
assign cmd_write = cmd_write_reg;
assign cmd_write_multiple = 1'b0;
assign cmd_stop = cmd_stop_reg;
assign cmd_valid = cmd_valid_reg;
assign data_out = data_out_reg;
assign data_out_valid = data_out_valid_reg;
assign data_out_last = 1'b1;
assign busy = busy_reg;
always @* begin
state_next = STATE_IDLE;
address_next = address_reg;
address_ptr_next = address_ptr_reg;
data_ptr_next = data_ptr_reg;
cur_address_next = cur_address_reg;
cmd_address_next = cmd_address_reg;
cmd_start_next = cmd_start_reg & ~(cmd_valid & cmd_ready);
cmd_write_next = cmd_write_reg & ~(cmd_valid & cmd_ready);
cmd_stop_next = cmd_stop_reg & ~(cmd_valid & cmd_ready);
cmd_valid_next = cmd_valid_reg & ~cmd_ready;
data_out_next = data_out_reg;
data_out_valid_next = data_out_valid_reg & ~data_out_ready;
start_flag_next = start_flag_reg;
if (cmd_valid | data_out_valid) begin
// wait for output registers to clear
state_next = state_reg;
end else begin
case (state_reg)
STATE_IDLE: begin
// wait for start signal
if (~start_flag_reg & start) begin
address_next = {AW{1'b0}};
start_flag_next = 1'b1;
state_next = STATE_RUN;
end else begin
state_next = STATE_IDLE;
end
end
STATE_RUN: begin
// process commands
if (init_data_reg[8] == 1'b1) begin
// write data
cmd_write_next = 1'b1;
cmd_stop_next = 1'b0;
cmd_valid_next = 1'b1;
data_out_next = init_data_reg[7:0];
data_out_valid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg[8:7] == 2'b01) begin
// write address
cmd_address_next = init_data_reg[6:0];
cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'd0) begin
// stop
cmd_start_next = 1'b0;
cmd_write_next = 1'b0;
cmd_stop_next = 1'b1;
cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_RUN;
end
end
STATE_TABLE_1: begin
// find address table start
if (init_data_reg == 9'b000001000) begin
// address table start
address_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_2;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
cmd_start_next = 1'b0;
cmd_write_next = 1'b0;
cmd_stop_next = 1'b1;
cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end
end
STATE_TABLE_2: begin
// find next address
if (init_data_reg[8:7] == 2'b01) begin
// write address command
// store address and move to data table
cur_address_next = init_data_reg[6:0];
address_ptr_next = address_reg + 1;
address_next = data_ptr_reg;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'd1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
cmd_start_next = 1'b0;
cmd_write_next = 1'b0;
cmd_stop_next = 1'b1;
cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_2;
end
end
STATE_TABLE_3: begin
// process data table with selected address
if (init_data_reg[8] == 1'b1) begin
// write data
cmd_write_next = 1'b1;
cmd_stop_next = 1'b0;
cmd_valid_next = 1'b1;
data_out_next = init_data_reg[7:0];
data_out_valid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg[8:7] == 2'b01) begin
// write address
cmd_address_next = init_data_reg[6:0];
cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000000011) begin
// write current address
cmd_address_next = cur_address_reg;
cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'b000001000) begin
// address table start
address_next = address_ptr_reg;
state_next = STATE_TABLE_2;
end else if (init_data_reg == 9'd1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
cmd_start_next = 1'b0;
cmd_write_next = 1'b0;
cmd_stop_next = 1'b1;
cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end
end
endcase
end
end
always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
init_data_reg <= 9'd0;
address_reg <= {AW{1'b0}};
address_ptr_reg <= {AW{1'b0}};
data_ptr_reg <= {AW{1'b0}};
cur_address_reg <= 7'd0;
cmd_valid_reg <= 1'b0;
data_out_valid_reg <= 1'b0;
start_flag_reg <= 1'b0;
busy_reg <= 1'b0;
end else begin
state_reg <= state_next;
// read init_data ROM
init_data_reg <= init_data[address_next];
address_reg <= address_next;
address_ptr_reg <= address_ptr_next;
data_ptr_reg <= data_ptr_next;
cur_address_reg <= cur_address_next;
cmd_valid_reg <= cmd_valid_next;
data_out_valid_reg <= data_out_valid_next;
start_flag_reg <= start & start_flag_next;
busy_reg <= (state_reg != STATE_IDLE);
end
cmd_address_reg <= cmd_address_next;
cmd_start_reg <= cmd_start_next;
cmd_write_reg <= cmd_write_next;
cmd_stop_reg <= cmd_stop_next;
data_out_reg <= data_out_next;
end
endmodule

View File

@ -0,0 +1,52 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`timescale 1 ns / 1 ps
/*
* Synchronizes an 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

Some files were not shown because too many files have changed in this diff Show More