1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Add ZCU102 example design

This commit is contained in:
Alex Forencich 2020-09-18 00:15:21 -07:00
parent 6df648ef54
commit 9a8ba2f0f2
20 changed files with 2384 additions and 0 deletions

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

View File

@ -0,0 +1,86 @@
# XDC constraints for the Xilinx ZCU102 board
# part: xczu9eg-ffvb1156-2-e
# General configuration
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
# System clocks
# 125 MHz
set_property -dict {LOC G21 IOSTANDARD LVDS_25} [get_ports clk_125mhz_p]
set_property -dict {LOC F21 IOSTANDARD LVDS_25} [get_ports clk_125mhz_n]
create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
# LEDs
set_property -dict {LOC AG14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AF13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[1]}]
set_property -dict {LOC AE13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[2]}]
set_property -dict {LOC AJ14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[3]}]
set_property -dict {LOC AJ15 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[4]}]
set_property -dict {LOC AH13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[5]}]
set_property -dict {LOC AH14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[6]}]
set_property -dict {LOC AL12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports {led[7]}]
# Reset button
set_property -dict {LOC AM13 IOSTANDARD LVCMOS33} [get_ports reset]
# Push buttons
set_property -dict {LOC AG15 IOSTANDARD LVCMOS33} [get_ports btnu]
set_property -dict {LOC AF15 IOSTANDARD LVCMOS33} [get_ports btnl]
set_property -dict {LOC AE15 IOSTANDARD LVCMOS33} [get_ports btnd]
set_property -dict {LOC AE14 IOSTANDARD LVCMOS33} [get_ports btnr]
set_property -dict {LOC AG13 IOSTANDARD LVCMOS33} [get_ports btnc]
# DIP switches
set_property -dict {LOC AN14 IOSTANDARD LVCMOS33} [get_ports {sw[0]}]
set_property -dict {LOC AP14 IOSTANDARD LVCMOS33} [get_ports {sw[1]}]
set_property -dict {LOC AM14 IOSTANDARD LVCMOS33} [get_ports {sw[2]}]
set_property -dict {LOC AN13 IOSTANDARD LVCMOS33} [get_ports {sw[3]}]
set_property -dict {LOC AN12 IOSTANDARD LVCMOS33} [get_ports {sw[4]}]
set_property -dict {LOC AP12 IOSTANDARD LVCMOS33} [get_ports {sw[5]}]
set_property -dict {LOC AL13 IOSTANDARD LVCMOS33} [get_ports {sw[6]}]
set_property -dict {LOC AK13 IOSTANDARD LVCMOS33} [get_ports {sw[7]}]
# UART
set_property -dict {LOC F13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports uart_txd]
set_property -dict {LOC E13 IOSTANDARD LVCMOS33} [get_ports uart_rxd]
set_property -dict {LOC D12 IOSTANDARD LVCMOS33} [get_ports uart_rts]
set_property -dict {LOC E12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports uart_cts]
# I2C interfaces
#set_property -dict {LOC J10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c0_scl]
#set_property -dict {LOC J11 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c0_sda]
#set_property -dict {LOC K20 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c1_scl]
#set_property -dict {LOC L20 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports i2c1_sda]
# SFP+ Interface
set_property -dict {LOC D2 } [get_ports sfp0_rx_p] ;# MGTHRXP0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC D1 } [get_ports sfp0_rx_n] ;# MGTHRXN0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3
set_property -dict {LOC E4 } [get_ports sfp0_tx_p] ;# MGTHTXP0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC E3 } [get_ports sfp0_tx_n] ;# MGTHTXN0_230 GTHE4_CHANNEL_X1Y12 / GTHE4_COMMON_X1Y3
set_property -dict {LOC C4 } [get_ports sfp1_rx_p] ;# MGTHRXP1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC C3 } [get_ports sfp1_rx_n] ;# MGTHRXN1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3
set_property -dict {LOC D6 } [get_ports sfp1_tx_p] ;# MGTHTXP1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC D5 } [get_ports sfp1_tx_n] ;# MGTHTXN1_230 GTHE4_CHANNEL_X1Y13 / GTHE4_COMMON_X1Y3
set_property -dict {LOC B2 } [get_ports sfp2_rx_p] ;# MGTHRXP2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC B1 } [get_ports sfp2_rx_n] ;# MGTHRXN2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3
set_property -dict {LOC B6 } [get_ports sfp2_tx_p] ;# MGTHTXP2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC B5 } [get_ports sfp2_tx_n] ;# MGTHTXN2_230 GTHE4_CHANNEL_X1Y14 / GTHE4_COMMON_X1Y3
set_property -dict {LOC A4 } [get_ports sfp3_rx_p] ;# MGTHRXP3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC A3 } [get_ports sfp3_rx_n] ;# MGTHRXN3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3
set_property -dict {LOC A8 } [get_ports sfp3_tx_p] ;# MGTHTXP3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3
#set_property -dict {LOC A7 } [get_ports sfp3_tx_n] ;# MGTHTXN3_230 GTHE4_CHANNEL_X1Y15 / GTHE4_COMMON_X1Y3
set_property -dict {LOC C8 } [get_ports sfp_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U56 SI570 via U51 SI53340
set_property -dict {LOC C7 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U56 SI570 via U51 SI53340
#set_property -dict {LOC B10 } [get_ports sfp_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U20 CKOUT2 SI5328
#set_property -dict {LOC B9 } [get_ports sfp_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U20 CKOUT2 SI5328
#set_property -dict {LOC R10 IOSTANDARD LVDS} [get_ports sfp_recclk_p] ;# to U20 CKIN1 SI5328
#set_property -dict {LOC R9 IOSTANDARD LVDS} [get_ports sfp_recclk_n] ;# to U20 CKIN1 SI5328
set_property -dict {LOC A12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports sfp0_tx_disable_b]
set_property -dict {LOC A13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports sfp1_tx_disable_b]
set_property -dict {LOC B13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports sfp2_tx_disable_b]
set_property -dict {LOC C13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 8} [get_ports sfp3_tx_disable_b]
# 156.25 MHz MGT reference clock
create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p]

View File

@ -0,0 +1,71 @@
# FPGA settings
FPGA_PART = xczu9eg-ffvb1156-2-e
FPGA_TOP = fpga
FPGA_ARCH = zynquplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/sync_reset.tcl
# IP
IP_TCL_FILES = ip/gtwizard_ultrascale_0.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

View File

@ -0,0 +1,21 @@
create_ip -name gtwizard_ultrascale -vendor xilinx.com -library ip -module_name gtwizard_ultrascale_0
set_property -dict [list CONFIG.preset {GTH-10GBASE-R}] [get_ips gtwizard_ultrascale_0]
set_property -dict [list \
CONFIG.CHANNEL_ENABLE {X1Y15 X1Y14 X1Y13 X1Y12} \
CONFIG.TX_MASTER_CHANNEL {X1Y12} \
CONFIG.RX_MASTER_CHANNEL {X1Y12} \
CONFIG.TX_LINE_RATE {10.3125} \
CONFIG.TX_REFCLK_FREQUENCY {156.25} \
CONFIG.TX_USER_DATA_WIDTH {64} \
CONFIG.TX_INT_DATA_WIDTH {32} \
CONFIG.RX_LINE_RATE {10.3125} \
CONFIG.RX_REFCLK_FREQUENCY {156.25} \
CONFIG.RX_USER_DATA_WIDTH {64} \
CONFIG.RX_INT_DATA_WIDTH {32} \
CONFIG.RX_REFCLK_SOURCE {X1Y15 clk0 X1Y14 clk0 X1Y13 clk0 X1Y12 clk0} \
CONFIG.TX_REFCLK_SOURCE {X1Y15 clk0 X1Y14 clk0 X1Y13 clk0 X1Y12 clk0} \
CONFIG.FREERUN_FREQUENCY {125} \
] [get_ips gtwizard_ultrascale_0]

1
example/ZCU102/fpga/lib/eth Symbolic link
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,684 @@
/*
Copyright (c) 2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 125MHz LVDS
* Reset: Push button, active low
*/
input wire clk_125mhz_p,
input wire clk_125mhz_n,
input wire reset,
/*
* 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,
/*
* UART: 115200 bps, 8N1
*/
input wire uart_rxd,
output wire uart_txd,
input wire uart_rts,
output wire uart_cts,
/*
* Ethernet: SFP+
*/
input wire sfp0_rx_p,
input wire sfp0_rx_n,
output wire sfp0_tx_p,
output wire sfp0_tx_n,
input wire sfp1_rx_p,
input wire sfp1_rx_n,
output wire sfp1_tx_p,
output wire sfp1_tx_n,
input wire sfp2_rx_p,
input wire sfp2_rx_n,
output wire sfp2_tx_p,
output wire sfp2_tx_n,
input wire sfp3_rx_p,
input wire sfp3_rx_n,
output wire sfp3_tx_p,
output wire sfp3_tx_n,
input wire sfp_mgt_refclk_0_p,
input wire sfp_mgt_refclk_0_n,
output wire sfp0_tx_disable_b,
output wire sfp1_tx_disable_b,
output wire sfp2_tx_disable_b,
output wire sfp3_tx_disable_b
);
// Clock and reset
wire clk_125mhz_ibufg;
wire clk_125mhz_bufg;
// Internal 125 MHz clock
wire clk_125mhz_mmcm_out;
wire clk_125mhz_int;
wire rst_125mhz_int;
// Internal 156.25 MHz clock
wire clk_156mhz_int;
wire rst_156mhz_int;
wire mmcm_rst = reset;
wire mmcm_locked;
wire mmcm_clkfb;
IBUFGDS #(
.DIFF_TERM("FALSE"),
.IBUF_LOW_PWR("FALSE")
)
clk_125mhz_ibufg_inst (
.O (clk_125mhz_ibufg),
.I (clk_125mhz_p),
.IB (clk_125mhz_n)
);
BUFG
clk_125mhz_bufg_in_inst (
.I(clk_125mhz_ibufg),
.O(clk_125mhz_bufg)
);
// MMCM instance
// 125 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 8, D = 1 sets Fvco = 1000 MHz (in range)
// Divide by 8 to get output frequency of 125 MHz
MMCME4_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(8),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(1),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(8.0),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_125mhz_bufg),
.CLKFBIN(mmcm_clkfb),
.RST(mmcm_rst),
.PWRDWN(1'b0),
.CLKOUT0(clk_125mhz_mmcm_out),
.CLKOUT0B(),
.CLKOUT1(),
.CLKOUT1B(),
.CLKOUT2(),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
.CLKOUT4(),
.CLKOUT5(),
.CLKOUT6(),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
.LOCKED(mmcm_locked)
);
BUFG
clk_125mhz_bufg_inst (
.I(clk_125mhz_mmcm_out),
.O(clk_125mhz_int)
);
sync_reset #(
.N(4)
)
sync_reset_125mhz_inst (
.clk(clk_125mhz_int),
.rst(~mmcm_locked),
.out(rst_125mhz_int)
);
// GPIO
wire btnu_int;
wire btnl_int;
wire btnd_int;
wire btnr_int;
wire btnc_int;
wire [7:0] sw_int;
debounce_switch #(
.WIDTH(9),
.N(8),
.RATE(156000)
)
debounce_switch_inst (
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
.in({btnu,
btnl,
btnd,
btnr,
btnc,
sw}),
.out({btnu_int,
btnl_int,
btnd_int,
btnr_int,
btnc_int,
sw_int})
);
wire uart_rxd_int;
wire uart_rts_int;
sync_signal #(
.WIDTH(2),
.N(2)
)
sync_signal_inst (
.clk(clk_156mhz_int),
.in({uart_rxd, uart_rts}),
.out({uart_rxd_int, uart_rts_int})
);
// XGMII 10G PHY
assign sfp0_tx_disable_b = 1'b1;
assign sfp1_tx_disable_b = 1'b1;
assign sfp2_tx_disable_b = 1'b1;
assign sfp3_tx_disable_b = 1'b1;
wire sfp0_tx_clk_int;
wire sfp0_tx_rst_int;
wire [63:0] sfp0_txd_int;
wire [7:0] sfp0_txc_int;
wire sfp0_rx_clk_int;
wire sfp0_rx_rst_int;
wire [63:0] sfp0_rxd_int;
wire [7:0] sfp0_rxc_int;
wire sfp1_tx_clk_int;
wire sfp1_tx_rst_int;
wire [63:0] sfp1_txd_int;
wire [7:0] sfp1_txc_int;
wire sfp1_rx_clk_int;
wire sfp1_rx_rst_int;
wire [63:0] sfp1_rxd_int;
wire [7:0] sfp1_rxc_int;
wire sfp2_tx_clk_int;
wire sfp2_tx_rst_int;
wire [63:0] sfp2_txd_int;
wire [7:0] sfp2_txc_int;
wire sfp2_rx_clk_int;
wire sfp2_rx_rst_int;
wire [63:0] sfp2_rxd_int;
wire [7:0] sfp2_rxc_int;
wire sfp3_tx_clk_int;
wire sfp3_tx_rst_int;
wire [63:0] sfp3_txd_int;
wire [7:0] sfp3_txc_int;
wire sfp3_rx_clk_int;
wire sfp3_rx_rst_int;
wire [63:0] sfp3_rxd_int;
wire [7:0] sfp3_rxc_int;
wire sfp0_rx_block_lock;
wire sfp1_rx_block_lock;
wire sfp2_rx_block_lock;
wire sfp3_rx_block_lock;
wire sfp_mgt_refclk;
wire [3:0] gt_txclkout;
wire gt_txusrclk;
wire gt_txusrclk2;
wire [3:0] gt_rxclkout;
wire [3:0] gt_rxusrclk;
wire [3:0] gt_rxusrclk2;
wire gt_reset_tx_done;
wire gt_reset_rx_done;
wire [3:0] gt_txprgdivresetdone;
wire [3:0] gt_txpmaresetdone;
wire [3:0] gt_rxprgdivresetdone;
wire [3: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 [3:0] gt_userclk_rx_active = 1'b0;
IBUFDS_GTE4 ibufds_gte4_sfp_mgt_refclk_inst (
.I (sfp_mgt_refclk_0_p),
.IB (sfp_mgt_refclk_0_n),
.CEB (1'b0),
.O (sfp_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)
);
BUFG_GT bufg_gt_tx_usrclk2_inst (
.CE (1'b1),
.CEMASK (1'b0),
.CLR (gt_tx_reset),
.CLRMASK (1'b0),
.DIV (3'd1),
.I (gt_txclkout[0]),
.O (gt_txusrclk2)
);
assign clk_156mhz_int = gt_txusrclk2;
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
genvar n;
generate
for (n = 0 ; n < 4; n = n + 1) begin
BUFG_GT bufg_gt_rx_usrclk_0_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])
);
BUFG_GT bufg_gt_rx_usrclk2_0_inst (
.CE (1'b1),
.CEMASK (1'b0),
.CLR (gt_rx_reset),
.CLRMASK (1'b0),
.DIV (3'd1),
.I (gt_rxclkout[n]),
.O (gt_rxusrclk2[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),
.out(rst_156mhz_int)
);
wire [5:0] sfp0_gt_txheader;
wire [63:0] sfp0_gt_txdata;
wire sfp0_gt_rxgearboxslip;
wire [5:0] sfp0_gt_rxheader;
wire [1:0] sfp0_gt_rxheadervalid;
wire [63:0] sfp0_gt_rxdata;
wire [1:0] sfp0_gt_rxdatavalid;
wire [5:0] sfp1_gt_txheader;
wire [63:0] sfp1_gt_txdata;
wire sfp1_gt_rxgearboxslip;
wire [5:0] sfp1_gt_rxheader;
wire [1:0] sfp1_gt_rxheadervalid;
wire [63:0] sfp1_gt_rxdata;
wire [1:0] sfp1_gt_rxdatavalid;
wire [5:0] sfp2_gt_txheader;
wire [63:0] sfp2_gt_txdata;
wire sfp2_gt_rxgearboxslip;
wire [5:0] sfp2_gt_rxheader;
wire [1:0] sfp2_gt_rxheadervalid;
wire [63:0] sfp2_gt_rxdata;
wire [1:0] sfp2_gt_rxdatavalid;
wire [5:0] sfp3_gt_txheader;
wire [63:0] sfp3_gt_txdata;
wire sfp3_gt_rxgearboxslip;
wire [5:0] sfp3_gt_rxheader;
wire [1:0] sfp3_gt_rxheadervalid;
wire [63:0] sfp3_gt_rxdata;
wire [1:0] sfp3_gt_rxdatavalid;
gtwizard_ultrascale_0
sfp_gth_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(sfp_mgt_refclk),
.qpll0outclk_out(),
.qpll0outrefclk_out(),
.gthrxn_in({sfp3_rx_n, sfp2_rx_n, sfp1_rx_n, sfp0_rx_n}),
.gthrxp_in({sfp3_rx_p, sfp2_rx_p, sfp1_rx_p, sfp0_rx_p}),
.rxusrclk_in(gt_rxusrclk),
.rxusrclk2_in(gt_rxusrclk2),
.gtwiz_userdata_tx_in({sfp3_gt_txdata, sfp2_gt_txdata, sfp1_gt_txdata, sfp0_gt_txdata}),
.txheader_in({sfp3_gt_txheader, sfp2_gt_txheader, sfp1_gt_txheader, sfp0_gt_txheader}),
.txsequence_in({4{7'b0}}),
.txusrclk_in({4{gt_txusrclk}}),
.txusrclk2_in({4{gt_txusrclk2}}),
.gtpowergood_out(),
.gthtxn_out({sfp3_tx_n, sfp2_tx_n, sfp1_tx_n, sfp0_tx_n}),
.gthtxp_out({sfp3_tx_p, sfp2_tx_p, sfp1_tx_p, sfp0_tx_p}),
.rxgearboxslip_in({sfp3_gt_rxgearboxslip, sfp2_gt_rxgearboxslip, sfp1_gt_rxgearboxslip, sfp0_gt_rxgearboxslip}),
.gtwiz_userdata_rx_out({sfp3_gt_rxdata, sfp2_gt_rxdata, sfp1_gt_rxdata, sfp0_gt_rxdata}),
.rxdatavalid_out({sfp3_gt_rxdatavalid, sfp2_gt_rxdatavalid, sfp1_gt_rxdatavalid, sfp0_gt_rxdatavalid}),
.rxheader_out({sfp3_gt_rxheader, sfp2_gt_rxheader, sfp1_gt_rxheader, sfp0_gt_rxheader}),
.rxheadervalid_out({sfp3_gt_rxheadervalid, sfp2_gt_rxheadervalid, sfp1_gt_rxheadervalid, sfp0_gt_rxheadervalid}),
.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 sfp0_tx_clk_int = clk_156mhz_int;
assign sfp0_tx_rst_int = rst_156mhz_int;
assign sfp0_rx_clk_int = gt_rxusrclk2[0];
sync_reset #(
.N(4)
)
sfp0_rx_rst_reset_sync_inst (
.clk(sfp0_rx_clk_int),
.rst(~gt_reset_rx_done),
.out(sfp0_rx_rst_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
sfp0_phy_inst (
.tx_clk(sfp0_tx_clk_int),
.tx_rst(sfp0_tx_rst_int),
.rx_clk(sfp0_rx_clk_int),
.rx_rst(sfp0_rx_rst_int),
.xgmii_txd(sfp0_txd_int),
.xgmii_txc(sfp0_txc_int),
.xgmii_rxd(sfp0_rxd_int),
.xgmii_rxc(sfp0_rxc_int),
.serdes_tx_data(sfp0_gt_txdata),
.serdes_tx_hdr(sfp0_gt_txheader),
.serdes_rx_data(sfp0_gt_rxdata),
.serdes_rx_hdr(sfp0_gt_rxheader),
.serdes_rx_bitslip(sfp0_gt_rxgearboxslip),
.rx_block_lock(sfp0_rx_block_lock),
.rx_high_ber()
);
assign sfp1_tx_clk_int = clk_156mhz_int;
assign sfp1_tx_rst_int = rst_156mhz_int;
assign sfp1_rx_clk_int = gt_rxusrclk2[1];
sync_reset #(
.N(4)
)
sfp1_rx_rst_reset_sync_inst (
.clk(sfp1_rx_clk_int),
.rst(~gt_reset_rx_done),
.out(sfp1_rx_rst_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
sfp1_phy_inst (
.tx_clk(sfp1_tx_clk_int),
.tx_rst(sfp1_tx_rst_int),
.rx_clk(sfp1_rx_clk_int),
.rx_rst(sfp1_rx_rst_int),
.xgmii_txd(sfp1_txd_int),
.xgmii_txc(sfp1_txc_int),
.xgmii_rxd(sfp1_rxd_int),
.xgmii_rxc(sfp1_rxc_int),
.serdes_tx_data(sfp1_gt_txdata),
.serdes_tx_hdr(sfp1_gt_txheader),
.serdes_rx_data(sfp1_gt_rxdata),
.serdes_rx_hdr(sfp1_gt_rxheader),
.serdes_rx_bitslip(sfp1_gt_rxgearboxslip),
.rx_block_lock(sfp1_rx_block_lock),
.rx_high_ber()
);
assign sfp2_tx_clk_int = clk_156mhz_int;
assign sfp2_tx_rst_int = rst_156mhz_int;
assign sfp2_rx_clk_int = gt_rxusrclk2[2];
sync_reset #(
.N(4)
)
sfp2_rx_rst_reset_sync_inst (
.clk(sfp2_rx_clk_int),
.rst(~gt_reset_rx_done),
.out(sfp2_rx_rst_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
sfp2_phy_inst (
.tx_clk(sfp2_tx_clk_int),
.tx_rst(sfp2_tx_rst_int),
.rx_clk(sfp2_rx_clk_int),
.rx_rst(sfp2_rx_rst_int),
.xgmii_txd(sfp2_txd_int),
.xgmii_txc(sfp2_txc_int),
.xgmii_rxd(sfp2_rxd_int),
.xgmii_rxc(sfp2_rxc_int),
.serdes_tx_data(sfp2_gt_txdata),
.serdes_tx_hdr(sfp2_gt_txheader),
.serdes_rx_data(sfp2_gt_rxdata),
.serdes_rx_hdr(sfp2_gt_rxheader),
.serdes_rx_bitslip(sfp2_gt_rxgearboxslip),
.rx_block_lock(sfp2_rx_block_lock),
.rx_high_ber()
);
assign sfp3_tx_clk_int = clk_156mhz_int;
assign sfp3_tx_rst_int = rst_156mhz_int;
assign sfp3_rx_clk_int = gt_rxusrclk2[3];
sync_reset #(
.N(4)
)
sfp3_rx_rst_reset_sync_inst (
.clk(sfp3_rx_clk_int),
.rst(~gt_reset_rx_done),
.out(sfp3_rx_rst_int)
);
eth_phy_10g #(
.BIT_REVERSE(1)
)
sfp3_phy_inst (
.tx_clk(sfp3_tx_clk_int),
.tx_rst(sfp3_tx_rst_int),
.rx_clk(sfp3_rx_clk_int),
.rx_rst(sfp3_rx_rst_int),
.xgmii_txd(sfp3_txd_int),
.xgmii_txc(sfp3_txc_int),
.xgmii_rxd(sfp3_rxd_int),
.xgmii_rxc(sfp3_rxc_int),
.serdes_tx_data(sfp3_gt_txdata),
.serdes_tx_hdr(sfp3_gt_txheader),
.serdes_rx_data(sfp3_gt_rxdata),
.serdes_rx_hdr(sfp3_gt_rxheader),
.serdes_rx_bitslip(sfp3_gt_rxgearboxslip),
.rx_block_lock(sfp3_rx_block_lock),
.rx_high_ber()
);
fpga_core
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.btnu(btnu_int),
.btnl(btnl_int),
.btnd(btnd_int),
.btnr(btnr_int),
.btnc(btnc_int),
.sw(sw_int),
.led(led),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd_int),
.uart_txd(uart_txd),
.uart_rts(uart_rts_int),
.uart_cts(uart_cts),
/*
* Ethernet: SFP+
*/
.sfp0_tx_clk(sfp0_tx_clk_int),
.sfp0_tx_rst(sfp0_tx_rst_int),
.sfp0_txd(sfp0_txd_int),
.sfp0_txc(sfp0_txc_int),
.sfp0_rx_clk(sfp0_rx_clk_int),
.sfp0_rx_rst(sfp0_rx_rst_int),
.sfp0_rxd(sfp0_rxd_int),
.sfp0_rxc(sfp0_rxc_int),
.sfp1_tx_clk(sfp1_tx_clk_int),
.sfp1_tx_rst(sfp1_tx_rst_int),
.sfp1_txd(sfp1_txd_int),
.sfp1_txc(sfp1_txc_int),
.sfp1_rx_clk(sfp1_rx_clk_int),
.sfp1_rx_rst(sfp1_rx_rst_int),
.sfp1_rxd(sfp1_rxd_int),
.sfp1_rxc(sfp1_rxc_int),
.sfp2_tx_clk(sfp2_tx_clk_int),
.sfp2_tx_rst(sfp2_tx_rst_int),
.sfp2_txd(sfp2_txd_int),
.sfp2_txc(sfp2_txc_int),
.sfp2_rx_clk(sfp2_rx_clk_int),
.sfp2_rx_rst(sfp2_rx_rst_int),
.sfp2_rxd(sfp2_rxd_int),
.sfp2_rxc(sfp2_rxc_int),
.sfp3_tx_clk(sfp3_tx_clk_int),
.sfp3_tx_rst(sfp3_tx_rst_int),
.sfp3_txd(sfp3_txd_int),
.sfp3_txc(sfp3_txc_int),
.sfp3_rx_clk(sfp3_rx_clk_int),
.sfp3_rx_rst(sfp3_rx_rst_int),
.sfp3_rxd(sfp3_rxd_int),
.sfp3_rxc(sfp3_rxc_int)
);
endmodule

View File

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

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,374 @@
#!/usr/bin/env python
"""
Copyright (c) 2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import eth_ep
import arp_ep
import udp_ep
import gmii_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_1g_fifo.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/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.v")
srcs.append("../lib/eth/rtl/eth_axis_tx.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.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_adapter.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_fifo.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_switch.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_register.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo.v")
srcs.append("../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.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:])
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:])
sfp0_tx_clk = Signal(bool(0))
sfp0_tx_rst = Signal(bool(0))
sfp0_rx_clk = Signal(bool(0))
sfp0_rx_rst = Signal(bool(0))
sfp0_rxd = Signal(intbv(0)[64:])
sfp0_rxc = Signal(intbv(0)[8:])
sfp1_tx_clk = Signal(bool(0))
sfp1_tx_rst = Signal(bool(0))
sfp1_rx_clk = Signal(bool(0))
sfp1_rx_rst = Signal(bool(0))
sfp1_rxd = Signal(intbv(0)[64:])
sfp1_rxc = Signal(intbv(0)[8:])
sfp2_tx_clk = Signal(bool(0))
sfp2_tx_rst = Signal(bool(0))
sfp2_rx_clk = Signal(bool(0))
sfp2_rx_rst = Signal(bool(0))
sfp2_rxd = Signal(intbv(0)[64:])
sfp2_rxc = Signal(intbv(0)[8:])
sfp3_tx_clk = Signal(bool(0))
sfp3_tx_rst = Signal(bool(0))
sfp3_rx_clk = Signal(bool(0))
sfp3_rx_rst = Signal(bool(0))
sfp3_rxd = Signal(intbv(0)[64:])
sfp3_rxc = Signal(intbv(0)[8:])
uart_rxd = Signal(bool(0))
uart_rts = Signal(bool(0))
# Outputs
led = Signal(intbv(0)[8:])
sfp0_txd = Signal(intbv(0)[64:])
sfp0_txc = Signal(intbv(0)[8:])
sfp1_txd = Signal(intbv(0)[64:])
sfp1_txc = Signal(intbv(0)[8:])
sfp2_txd = Signal(intbv(0)[64:])
sfp2_txc = Signal(intbv(0)[8:])
sfp3_txd = Signal(intbv(0)[64:])
sfp3_txc = Signal(intbv(0)[8:])
uart_txd = Signal(bool(0))
uart_cts = Signal(bool(0))
# sources and sinks
sfp0_source = xgmii_ep.XGMIISource()
sfp0_source_logic = sfp0_source.create_logic(sfp0_rx_clk, sfp0_rx_rst, txd=sfp0_rxd, txc=sfp0_rxc, name='sfp0_source')
sfp0_sink = xgmii_ep.XGMIISink()
sfp0_sink_logic = sfp0_sink.create_logic(sfp0_tx_clk, sfp0_tx_rst, rxd=sfp0_txd, rxc=sfp0_txc, name='sfp0_sink')
sfp1_source = xgmii_ep.XGMIISource()
sfp1_source_logic = sfp1_source.create_logic(sfp1_rx_clk, sfp1_rx_rst, txd=sfp1_rxd, txc=sfp1_rxc, name='sfp1_source')
sfp1_sink = xgmii_ep.XGMIISink()
sfp1_sink_logic = sfp1_sink.create_logic(sfp1_tx_clk, sfp1_tx_rst, rxd=sfp1_txd, rxc=sfp1_txc, name='sfp1_sink')
sfp2_source = xgmii_ep.XGMIISource()
sfp2_source_logic = sfp2_source.create_logic(sfp2_rx_clk, sfp2_rx_rst, txd=sfp2_rxd, txc=sfp2_rxc, name='sfp2_source')
sfp2_sink = xgmii_ep.XGMIISink()
sfp2_sink_logic = sfp2_sink.create_logic(sfp2_tx_clk, sfp2_tx_rst, rxd=sfp2_txd, rxc=sfp2_txc, name='sfp2_sink')
sfp3_source = xgmii_ep.XGMIISource()
sfp3_source_logic = sfp3_source.create_logic(sfp3_rx_clk, sfp3_rx_rst, txd=sfp3_rxd, txc=sfp3_rxc, name='sfp3_source')
sfp3_sink = xgmii_ep.XGMIISink()
sfp3_sink_logic = sfp3_sink.create_logic(sfp3_tx_clk, sfp3_tx_rst, rxd=sfp3_txd, rxc=sfp3_txc, name='sfp3_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,
sfp0_tx_clk=sfp0_tx_clk,
sfp0_tx_rst=sfp0_tx_rst,
sfp0_txd=sfp0_txd,
sfp0_txc=sfp0_txc,
sfp0_rx_clk=sfp0_rx_clk,
sfp0_rx_rst=sfp0_rx_rst,
sfp0_rxd=sfp0_rxd,
sfp0_rxc=sfp0_rxc,
sfp1_tx_clk=sfp1_tx_clk,
sfp1_tx_rst=sfp1_tx_rst,
sfp1_txd=sfp1_txd,
sfp1_txc=sfp1_txc,
sfp1_rx_clk=sfp1_rx_clk,
sfp1_rx_rst=sfp1_rx_rst,
sfp1_rxd=sfp1_rxd,
sfp1_rxc=sfp1_rxc,
sfp2_tx_clk=sfp2_tx_clk,
sfp2_tx_rst=sfp2_tx_rst,
sfp2_txd=sfp2_txd,
sfp2_txc=sfp2_txc,
sfp2_rx_clk=sfp2_rx_clk,
sfp2_rx_rst=sfp2_rx_rst,
sfp2_rxd=sfp2_rxd,
sfp2_rxc=sfp2_rxc,
sfp3_tx_clk=sfp3_tx_clk,
sfp3_tx_rst=sfp3_tx_rst,
sfp3_txd=sfp3_txd,
sfp3_txc=sfp3_txc,
sfp3_rx_clk=sfp3_rx_clk,
sfp3_rx_rst=sfp3_rx_rst,
sfp3_rxd=sfp3_rxd,
sfp3_rxc=sfp3_rxc,
uart_rxd=uart_rxd,
uart_txd=uart_txd,
uart_rts=uart_rts,
uart_cts=uart_cts
)
@always(delay(4))
def clkgen():
clk.next = not clk
sfp0_tx_clk.next = not sfp0_tx_clk
sfp0_rx_clk.next = not sfp0_rx_clk
sfp1_tx_clk.next = not sfp1_tx_clk
sfp1_rx_clk.next = not sfp1_rx_clk
sfp2_tx_clk.next = not sfp2_tx_clk
sfp2_rx_clk.next = not sfp2_rx_clk
sfp3_tx_clk.next = not sfp3_tx_clk
sfp3_rx_clk.next = not sfp3_rx_clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
sfp0_tx_rst.next = 1
sfp0_rx_rst.next = 1
sfp1_tx_rst.next = 1
sfp1_rx_rst.next = 1
sfp2_tx_rst.next = 1
sfp2_rx_rst.next = 1
sfp3_tx_rst.next = 1
sfp3_rx_rst.next = 1
yield clk.posedge
rst.next = 0
sfp0_tx_rst.next = 0
sfp0_rx_rst.next = 0
sfp1_tx_rst.next = 0
sfp1_rx_rst.next = 0
sfp2_tx_rst.next = 0
sfp2_rx_rst.next = 0
sfp3_tx_rst.next = 0
sfp3_rx_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()
sfp0_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 sfp0_sink.empty():
yield clk.posedge
rx_frame = sfp0_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
sfp0_source.send(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data)
while sfp0_sink.empty():
yield clk.posedge
rx_frame = sfp0_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 sfp0_source.empty()
assert sfp0_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,194 @@
/*
Copyright (c) 2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// 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 btnu = 0;
reg btnl = 0;
reg btnd = 0;
reg btnr = 0;
reg btnc = 0;
reg [7:0] sw = 0;
reg sfp0_tx_clk = 0;
reg sfp0_tx_rst = 0;
reg sfp0_rx_clk = 0;
reg sfp0_rx_rst = 0;
reg [63:0] sfp0_rxd = 0;
reg [7:0] sfp0_rxc = 0;
reg sfp1_tx_clk = 0;
reg sfp1_tx_rst = 0;
reg sfp1_rx_clk = 0;
reg sfp1_rx_rst = 0;
reg [63:0] sfp1_rxd = 0;
reg [7:0] sfp1_rxc = 0;
reg sfp2_tx_clk = 0;
reg sfp2_tx_rst = 0;
reg sfp2_rx_clk = 0;
reg sfp2_rx_rst = 0;
reg [63:0] sfp2_rxd = 0;
reg [7:0] sfp2_rxc = 0;
reg sfp3_tx_clk = 0;
reg sfp3_tx_rst = 0;
reg sfp3_rx_clk = 0;
reg sfp3_rx_rst = 0;
reg [63:0] sfp3_rxd = 0;
reg [7:0] sfp3_rxc = 0;
reg uart_rxd = 0;
reg uart_rts = 0;
// Outputs
wire [7:0] led;
wire [63:0] sfp0_txd;
wire [7:0] sfp0_txc;
wire [63:0] sfp1_txd;
wire [7:0] sfp1_txc;
wire [63:0] sfp_2_txd;
wire [7:0] sfp_2_txc;
wire [63:0] sfp_3_txd;
wire [7:0] sfp_3_txc;
wire uart_txd;
wire uart_cts;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
btnu,
btnl,
btnd,
btnr,
btnc,
sw,
sfp0_tx_clk,
sfp0_tx_rst,
sfp0_rx_clk,
sfp0_rx_rst,
sfp0_rxd,
sfp0_rxc,
sfp1_tx_clk,
sfp1_tx_rst,
sfp1_rx_clk,
sfp1_rx_rst,
sfp1_rxd,
sfp1_rxc,
sfp2_tx_clk,
sfp2_tx_rst,
sfp2_rx_clk,
sfp2_rx_rst,
sfp2_rxd,
sfp2_rxc,
sfp3_tx_clk,
sfp3_tx_rst,
sfp3_rx_clk,
sfp3_rx_rst,
sfp3_rxd,
sfp3_rxc,
uart_rxd,
uart_rts
);
$to_myhdl(
led,
sfp0_txd,
sfp0_txc,
sfp1_txd,
sfp1_txc,
sfp2_txd,
sfp2_txc,
sfp3_txd,
sfp3_txc,
uart_txd,
uart_cts
);
// dump file
$dumpfile("test_fpga_core.lxt");
$dumpvars(0, test_fpga_core);
end
fpga_core
UUT (
.clk(clk),
.rst(rst),
.btnu(btnu),
.btnl(btnl),
.btnd(btnd),
.btnr(btnr),
.btnc(btnc),
.sw(sw),
.led(led),
.sfp0_tx_clk(sfp0_tx_clk),
.sfp0_tx_rst(sfp0_tx_rst),
.sfp0_txd(sfp0_txd),
.sfp0_txc(sfp0_txc),
.sfp0_rx_clk(sfp0_rx_clk),
.sfp0_rx_rst(sfp0_rx_rst),
.sfp0_rxd(sfp0_rxd),
.sfp0_rxc(sfp0_rxc),
.sfp1_tx_clk(sfp1_tx_clk),
.sfp1_tx_rst(sfp1_tx_rst),
.sfp1_txd(sfp1_txd),
.sfp1_txc(sfp1_txc),
.sfp1_rx_clk(sfp1_rx_clk),
.sfp1_rx_rst(sfp1_rx_rst),
.sfp1_rxd(sfp1_rxd),
.sfp1_rxc(sfp1_rxc),
.sfp2_tx_clk(sfp2_tx_clk),
.sfp2_tx_rst(sfp2_tx_rst),
.sfp2_txd(sfp2_txd),
.sfp2_txc(sfp2_txc),
.sfp2_rx_clk(sfp2_rx_clk),
.sfp2_rx_rst(sfp2_rx_rst),
.sfp2_rxd(sfp2_rxd),
.sfp2_rxc(sfp2_rxc),
.sfp3_tx_clk(sfp3_tx_clk),
.sfp3_tx_rst(sfp3_tx_rst),
.sfp3_txd(sfp3_txd),
.sfp3_txc(sfp3_txc),
.sfp3_rx_clk(sfp3_rx_clk),
.sfp3_rx_rst(sfp3_rx_rst),
.sfp3_rxd(sfp3_rxd),
.sfp3_rxc(sfp3_rxc),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd),
.uart_rts(uart_rts),
.uart_cts(uart_cts)
);
endmodule

View File

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

View File

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