mirror of
https://github.com/corundum/corundum.git
synced 2025-01-30 08:32:52 +08:00
Add 10G reference design for DE5-Net
This commit is contained in:
parent
3f2d096249
commit
eb8dd775a1
25
example/DE5-Net/fpga/Makefile
Normal file
25
example/DE5-Net/fpga/Makefile
Normal 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
|
25
example/DE5-Net/fpga/README.md
Normal file
25
example/DE5-Net/fpga/README.md
Normal 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.
|
||||
|
||||
|
141
example/DE5-Net/fpga/common/altera.mk
Normal file
141
example/DE5-Net/fpga/common/altera.mk
Normal 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
|
||||
|
||||
# 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
|
||||
|
||||
|
23
example/DE5-Net/fpga/cores/Makefile
Normal file
23
example/DE5-Net/fpga/cores/Makefile
Normal 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 $<
|
||||
|
192
example/DE5-Net/fpga/cores/phy.v
Normal file
192
example/DE5-Net/fpga/cores/phy.v
Normal 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
|
101
example/DE5-Net/fpga/cores/phy_reconfig.v
Normal file
101
example/DE5-Net/fpga/cores/phy_reconfig.v
Normal 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
|
1646
example/DE5-Net/fpga/fpga.qsf
Normal file
1646
example/DE5-Net/fpga/fpga.qsf
Normal file
File diff suppressed because it is too large
Load Diff
98
example/DE5-Net/fpga/fpga.sdc
Normal file
98
example/DE5-Net/fpga/fpga.sdc
Normal 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
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
68
example/DE5-Net/fpga/fpga/Makefile
Normal file
68
example/DE5-Net/fpga/fpga/Makefile
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
# 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/eth_mac_10g_rx.v
|
||||
SYN_FILES += lib/eth/rtl/eth_mac_10g_tx.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_8.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_16.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_24.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_32.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_40.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_48.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_56.v
|
||||
SYN_FILES += lib/eth/rtl/eth_crc_64.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_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_64_2.v
|
||||
SYN_FILES += lib/eth/rtl/ip_mux_64_2.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_64_2.v
|
||||
SYN_FILES += lib/eth/rtl/eth_mux_64_2.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_64.v
|
||||
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_frame_fifo_64.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"
|
1
example/DE5-Net/fpga/lib/eth
Symbolic link
1
example/DE5-Net/fpga/lib/eth
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../
|
89
example/DE5-Net/fpga/rtl/debounce_switch.v
Normal file
89
example/DE5-Net/fpga/rtl/debounce_switch.v
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014-2016 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
|
422
example/DE5-Net/fpga/rtl/fpga.v
Normal file
422
example/DE5-Net/fpga/rtl/fpga.v
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2016 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_RX_p,
|
||||
output wire SFPA_TX_p,
|
||||
input wire SFPB_RX_p,
|
||||
output wire SFPB_TX_p,
|
||||
input wire SFPC_RX_p,
|
||||
output wire SFPC_TX_p,
|
||||
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;
|
||||
|
||||
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
|
589
example/DE5-Net/fpga/rtl/fpga_core.v
Normal file
589
example/DE5-Net/fpga/rtl/fpga_core.v
Normal file
@ -0,0 +1,589 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2016 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_tdata;
|
||||
wire [7:0] rx_eth_payload_tkeep;
|
||||
wire rx_eth_payload_tvalid;
|
||||
wire rx_eth_payload_tready;
|
||||
wire rx_eth_payload_tlast;
|
||||
wire rx_eth_payload_tuser;
|
||||
|
||||
wire tx_eth_hdr_ready;
|
||||
wire tx_eth_hdr_valid;
|
||||
wire [47:0] tx_eth_dest_mac;
|
||||
wire [47:0] tx_eth_src_mac;
|
||||
wire [15:0] tx_eth_type;
|
||||
wire [63:0] tx_eth_payload_tdata;
|
||||
wire [7:0] tx_eth_payload_tkeep;
|
||||
wire tx_eth_payload_tvalid;
|
||||
wire tx_eth_payload_tready;
|
||||
wire tx_eth_payload_tlast;
|
||||
wire tx_eth_payload_tuser;
|
||||
|
||||
// IP frame connections
|
||||
wire rx_ip_hdr_valid;
|
||||
wire rx_ip_hdr_ready;
|
||||
wire [47:0] rx_ip_eth_dest_mac;
|
||||
wire [47:0] rx_ip_eth_src_mac;
|
||||
wire [15:0] rx_ip_eth_type;
|
||||
wire [3:0] rx_ip_version;
|
||||
wire [3:0] rx_ip_ihl;
|
||||
wire [5:0] rx_ip_dscp;
|
||||
wire [1:0] rx_ip_ecn;
|
||||
wire [15:0] rx_ip_length;
|
||||
wire [15:0] rx_ip_identification;
|
||||
wire [2:0] rx_ip_flags;
|
||||
wire [12:0] rx_ip_fragment_offset;
|
||||
wire [7:0] rx_ip_ttl;
|
||||
wire [7:0] rx_ip_protocol;
|
||||
wire [15:0] rx_ip_header_checksum;
|
||||
wire [31:0] rx_ip_source_ip;
|
||||
wire [31:0] rx_ip_dest_ip;
|
||||
wire [63:0] rx_ip_payload_tdata;
|
||||
wire [7:0] rx_ip_payload_tkeep;
|
||||
wire rx_ip_payload_tvalid;
|
||||
wire rx_ip_payload_tready;
|
||||
wire rx_ip_payload_tlast;
|
||||
wire rx_ip_payload_tuser;
|
||||
|
||||
wire tx_ip_hdr_valid;
|
||||
wire tx_ip_hdr_ready;
|
||||
wire [5:0] tx_ip_dscp;
|
||||
wire [1:0] tx_ip_ecn;
|
||||
wire [15:0] tx_ip_length;
|
||||
wire [7:0] tx_ip_ttl;
|
||||
wire [7:0] tx_ip_protocol;
|
||||
wire [31:0] tx_ip_source_ip;
|
||||
wire [31:0] tx_ip_dest_ip;
|
||||
wire [63:0] tx_ip_payload_tdata;
|
||||
wire [7:0] tx_ip_payload_tkeep;
|
||||
wire tx_ip_payload_tvalid;
|
||||
wire tx_ip_payload_tready;
|
||||
wire tx_ip_payload_tlast;
|
||||
wire tx_ip_payload_tuser;
|
||||
|
||||
// UDP frame connections
|
||||
wire rx_udp_hdr_valid;
|
||||
wire rx_udp_hdr_ready;
|
||||
wire [47:0] rx_udp_eth_dest_mac;
|
||||
wire [47:0] rx_udp_eth_src_mac;
|
||||
wire [15:0] rx_udp_eth_type;
|
||||
wire [3:0] rx_udp_ip_version;
|
||||
wire [3:0] rx_udp_ip_ihl;
|
||||
wire [5:0] rx_udp_ip_dscp;
|
||||
wire [1:0] rx_udp_ip_ecn;
|
||||
wire [15:0] rx_udp_ip_length;
|
||||
wire [15:0] rx_udp_ip_identification;
|
||||
wire [2:0] rx_udp_ip_flags;
|
||||
wire [12:0] rx_udp_ip_fragment_offset;
|
||||
wire [7:0] rx_udp_ip_ttl;
|
||||
wire [7:0] rx_udp_ip_protocol;
|
||||
wire [15:0] rx_udp_ip_header_checksum;
|
||||
wire [31:0] rx_udp_ip_source_ip;
|
||||
wire [31:0] rx_udp_ip_dest_ip;
|
||||
wire [15:0] rx_udp_source_port;
|
||||
wire [15:0] rx_udp_dest_port;
|
||||
wire [15:0] rx_udp_length;
|
||||
wire [15:0] rx_udp_checksum;
|
||||
wire [63:0] rx_udp_payload_tdata;
|
||||
wire [7:0] rx_udp_payload_tkeep;
|
||||
wire rx_udp_payload_tvalid;
|
||||
wire rx_udp_payload_tready;
|
||||
wire rx_udp_payload_tlast;
|
||||
wire rx_udp_payload_tuser;
|
||||
|
||||
wire tx_udp_hdr_valid;
|
||||
wire tx_udp_hdr_ready;
|
||||
wire [5:0] tx_udp_ip_dscp;
|
||||
wire [1:0] tx_udp_ip_ecn;
|
||||
wire [7:0] tx_udp_ip_ttl;
|
||||
wire [31:0] tx_udp_ip_source_ip;
|
||||
wire [31:0] tx_udp_ip_dest_ip;
|
||||
wire [15:0] tx_udp_source_port;
|
||||
wire [15:0] tx_udp_dest_port;
|
||||
wire [15:0] tx_udp_length;
|
||||
wire [15:0] tx_udp_checksum;
|
||||
wire [63:0] tx_udp_payload_tdata;
|
||||
wire [7:0] tx_udp_payload_tkeep;
|
||||
wire tx_udp_payload_tvalid;
|
||||
wire tx_udp_payload_tready;
|
||||
wire tx_udp_payload_tlast;
|
||||
wire tx_udp_payload_tuser;
|
||||
|
||||
wire [63:0] rx_fifo_udp_payload_tdata;
|
||||
wire [7:0] rx_fifo_udp_payload_tkeep;
|
||||
wire rx_fifo_udp_payload_tvalid;
|
||||
wire rx_fifo_udp_payload_tready;
|
||||
wire rx_fifo_udp_payload_tlast;
|
||||
wire rx_fifo_udp_payload_tuser;
|
||||
|
||||
wire [63:0] tx_fifo_udp_payload_tdata;
|
||||
wire [7:0] tx_fifo_udp_payload_tkeep;
|
||||
wire tx_fifo_udp_payload_tvalid;
|
||||
wire tx_fifo_udp_payload_tready;
|
||||
wire tx_fifo_udp_payload_tlast;
|
||||
wire tx_fifo_udp_payload_tuser;
|
||||
|
||||
// Configuration
|
||||
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
|
||||
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
|
||||
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
|
||||
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
|
||||
|
||||
// IP ports not used
|
||||
assign rx_ip_hdr_ready = 1;
|
||||
assign rx_ip_payload_tready = 1;
|
||||
|
||||
assign tx_ip_hdr_valid = 0;
|
||||
assign tx_ip_dscp = 0;
|
||||
assign tx_ip_ecn = 0;
|
||||
assign tx_ip_length = 0;
|
||||
assign tx_ip_ttl = 0;
|
||||
assign tx_ip_protocol = 0;
|
||||
assign tx_ip_source_ip = 0;
|
||||
assign tx_ip_dest_ip = 0;
|
||||
assign tx_ip_payload_tdata = 0;
|
||||
assign tx_ip_payload_tkeep = 0;
|
||||
assign tx_ip_payload_tvalid = 0;
|
||||
assign tx_ip_payload_tlast = 0;
|
||||
assign tx_ip_payload_tuser = 0;
|
||||
|
||||
// Loop back UDP
|
||||
wire match_cond = rx_udp_dest_port == 1234;
|
||||
wire no_match = ~match_cond;
|
||||
|
||||
reg match_cond_reg = 0;
|
||||
reg no_match_reg = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
match_cond_reg <= 0;
|
||||
no_match_reg <= 0;
|
||||
end else begin
|
||||
if (rx_udp_payload_tvalid) begin
|
||||
if ((~match_cond_reg & ~no_match_reg) |
|
||||
(rx_udp_payload_tvalid & rx_udp_payload_tready & rx_udp_payload_tlast)) begin
|
||||
match_cond_reg <= match_cond;
|
||||
no_match_reg <= no_match;
|
||||
end
|
||||
end else begin
|
||||
match_cond_reg <= 0;
|
||||
no_match_reg <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign tx_udp_hdr_valid = rx_udp_hdr_valid & match_cond;
|
||||
assign rx_udp_hdr_ready = (tx_eth_hdr_ready & match_cond) | no_match;
|
||||
assign tx_udp_ip_dscp = 0;
|
||||
assign tx_udp_ip_ecn = 0;
|
||||
assign tx_udp_ip_ttl = 64;
|
||||
assign tx_udp_ip_source_ip = local_ip;
|
||||
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
|
||||
assign tx_udp_source_port = rx_udp_dest_port;
|
||||
assign tx_udp_dest_port = rx_udp_source_port;
|
||||
assign tx_udp_length = rx_udp_length;
|
||||
assign tx_udp_checksum = 0;
|
||||
//assign tx_udp_payload_tdata = rx_udp_payload_tdata;
|
||||
//assign tx_udp_payload_tkeep = rx_udp_payload_tkeep;
|
||||
//assign tx_udp_payload_tvalid = rx_udp_payload_tvalid;
|
||||
//assign rx_udp_payload_tready = tx_udp_payload_tready;
|
||||
//assign tx_udp_payload_tlast = rx_udp_payload_tlast;
|
||||
//assign tx_udp_payload_tuser = rx_udp_payload_tuser;
|
||||
|
||||
assign tx_udp_payload_tdata = tx_fifo_udp_payload_tdata;
|
||||
assign tx_udp_payload_tkeep = tx_fifo_udp_payload_tkeep;
|
||||
assign tx_udp_payload_tvalid = tx_fifo_udp_payload_tvalid;
|
||||
assign tx_fifo_udp_payload_tready = tx_udp_payload_tready;
|
||||
assign tx_udp_payload_tlast = tx_fifo_udp_payload_tlast;
|
||||
assign tx_udp_payload_tuser = tx_fifo_udp_payload_tuser;
|
||||
|
||||
assign rx_fifo_udp_payload_tdata = rx_udp_payload_tdata;
|
||||
assign rx_fifo_udp_payload_tkeep = rx_udp_payload_tkeep;
|
||||
assign rx_fifo_udp_payload_tvalid = rx_udp_payload_tvalid & match_cond_reg;
|
||||
assign rx_udp_payload_tready = (rx_fifo_udp_payload_tready & match_cond_reg) | no_match_reg;
|
||||
assign rx_fifo_udp_payload_tlast = rx_udp_payload_tlast;
|
||||
assign rx_fifo_udp_payload_tuser = rx_udp_payload_tuser;
|
||||
|
||||
// Place first payload byte onto LEDs
|
||||
reg valid_last = 0;
|
||||
reg [7:0] led_reg = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
led_reg <= 0;
|
||||
end else begin
|
||||
valid_last <= tx_udp_payload_tvalid;
|
||||
if (tx_udp_payload_tvalid & ~valid_last) begin
|
||||
led_reg <= tx_udp_payload_tdata;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//assign led = sw;
|
||||
assign led = ~led_reg;
|
||||
assign led_bkt = ~led_reg;
|
||||
assign led_hex0_d = 7'h7F;
|
||||
assign led_hex0_dp = 1'b1;
|
||||
assign led_hex1_d = 7'h7F;
|
||||
assign led_hex1_dp = 1'b1;
|
||||
|
||||
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),
|
||||
.RX_FIFO_ADDR_WIDTH(9)
|
||||
)
|
||||
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),
|
||||
|
||||
.rx_error_bad_frame(rx_error_bad_frame),
|
||||
.rx_error_bad_fcs(rx_error_bad_fcs),
|
||||
|
||||
.ifg_delay(8'd12)
|
||||
);
|
||||
|
||||
eth_axis_rx_64
|
||||
eth_axis_rx_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
// AXI input
|
||||
.input_axis_tdata(rx_axis_tdata),
|
||||
.input_axis_tkeep(rx_axis_tkeep),
|
||||
.input_axis_tvalid(rx_axis_tvalid),
|
||||
.input_axis_tready(rx_axis_tready),
|
||||
.input_axis_tlast(rx_axis_tlast),
|
||||
.input_axis_tuser(rx_axis_tuser),
|
||||
// Ethernet frame output
|
||||
.output_eth_hdr_valid(rx_eth_hdr_valid),
|
||||
.output_eth_hdr_ready(rx_eth_hdr_ready),
|
||||
.output_eth_dest_mac(rx_eth_dest_mac),
|
||||
.output_eth_src_mac(rx_eth_src_mac),
|
||||
.output_eth_type(rx_eth_type),
|
||||
.output_eth_payload_tdata(rx_eth_payload_tdata),
|
||||
.output_eth_payload_tkeep(rx_eth_payload_tkeep),
|
||||
.output_eth_payload_tvalid(rx_eth_payload_tvalid),
|
||||
.output_eth_payload_tready(rx_eth_payload_tready),
|
||||
.output_eth_payload_tlast(rx_eth_payload_tlast),
|
||||
.output_eth_payload_tuser(rx_eth_payload_tuser),
|
||||
// Status signals
|
||||
.busy(),
|
||||
.error_header_early_termination()
|
||||
);
|
||||
|
||||
eth_axis_tx_64
|
||||
eth_axis_tx_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
// Ethernet frame input
|
||||
.input_eth_hdr_valid(tx_eth_hdr_valid),
|
||||
.input_eth_hdr_ready(tx_eth_hdr_ready),
|
||||
.input_eth_dest_mac(tx_eth_dest_mac),
|
||||
.input_eth_src_mac(tx_eth_src_mac),
|
||||
.input_eth_type(tx_eth_type),
|
||||
.input_eth_payload_tdata(tx_eth_payload_tdata),
|
||||
.input_eth_payload_tkeep(tx_eth_payload_tkeep),
|
||||
.input_eth_payload_tvalid(tx_eth_payload_tvalid),
|
||||
.input_eth_payload_tready(tx_eth_payload_tready),
|
||||
.input_eth_payload_tlast(tx_eth_payload_tlast),
|
||||
.input_eth_payload_tuser(tx_eth_payload_tuser),
|
||||
// AXI output
|
||||
.output_axis_tdata(tx_axis_tdata),
|
||||
.output_axis_tkeep(tx_axis_tkeep),
|
||||
.output_axis_tvalid(tx_axis_tvalid),
|
||||
.output_axis_tready(tx_axis_tready),
|
||||
.output_axis_tlast(tx_axis_tlast),
|
||||
.output_axis_tuser(tx_axis_tuser),
|
||||
// Status signals
|
||||
.busy()
|
||||
);
|
||||
|
||||
udp_complete_64 #(
|
||||
.UDP_CHECKSUM_ENABLE(0)
|
||||
)
|
||||
udp_complete_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
// Ethernet frame input
|
||||
.input_eth_hdr_valid(rx_eth_hdr_valid),
|
||||
.input_eth_hdr_ready(rx_eth_hdr_ready),
|
||||
.input_eth_dest_mac(rx_eth_dest_mac),
|
||||
.input_eth_src_mac(rx_eth_src_mac),
|
||||
.input_eth_type(rx_eth_type),
|
||||
.input_eth_payload_tdata(rx_eth_payload_tdata),
|
||||
.input_eth_payload_tkeep(rx_eth_payload_tkeep),
|
||||
.input_eth_payload_tvalid(rx_eth_payload_tvalid),
|
||||
.input_eth_payload_tready(rx_eth_payload_tready),
|
||||
.input_eth_payload_tlast(rx_eth_payload_tlast),
|
||||
.input_eth_payload_tuser(rx_eth_payload_tuser),
|
||||
// Ethernet frame output
|
||||
.output_eth_hdr_valid(tx_eth_hdr_valid),
|
||||
.output_eth_hdr_ready(tx_eth_hdr_ready),
|
||||
.output_eth_dest_mac(tx_eth_dest_mac),
|
||||
.output_eth_src_mac(tx_eth_src_mac),
|
||||
.output_eth_type(tx_eth_type),
|
||||
.output_eth_payload_tdata(tx_eth_payload_tdata),
|
||||
.output_eth_payload_tkeep(tx_eth_payload_tkeep),
|
||||
.output_eth_payload_tvalid(tx_eth_payload_tvalid),
|
||||
.output_eth_payload_tready(tx_eth_payload_tready),
|
||||
.output_eth_payload_tlast(tx_eth_payload_tlast),
|
||||
.output_eth_payload_tuser(tx_eth_payload_tuser),
|
||||
// IP frame input
|
||||
.input_ip_hdr_valid(tx_ip_hdr_valid),
|
||||
.input_ip_hdr_ready(tx_ip_hdr_ready),
|
||||
.input_ip_dscp(tx_ip_dscp),
|
||||
.input_ip_ecn(tx_ip_ecn),
|
||||
.input_ip_length(tx_ip_length),
|
||||
.input_ip_ttl(tx_ip_ttl),
|
||||
.input_ip_protocol(tx_ip_protocol),
|
||||
.input_ip_source_ip(tx_ip_source_ip),
|
||||
.input_ip_dest_ip(tx_ip_dest_ip),
|
||||
.input_ip_payload_tdata(tx_ip_payload_tdata),
|
||||
.input_ip_payload_tkeep(tx_ip_payload_tkeep),
|
||||
.input_ip_payload_tvalid(tx_ip_payload_tvalid),
|
||||
.input_ip_payload_tready(tx_ip_payload_tready),
|
||||
.input_ip_payload_tlast(tx_ip_payload_tlast),
|
||||
.input_ip_payload_tuser(tx_ip_payload_tuser),
|
||||
// IP frame output
|
||||
.output_ip_hdr_valid(rx_ip_hdr_valid),
|
||||
.output_ip_hdr_ready(rx_ip_hdr_ready),
|
||||
.output_ip_eth_dest_mac(rx_ip_eth_dest_mac),
|
||||
.output_ip_eth_src_mac(rx_ip_eth_src_mac),
|
||||
.output_ip_eth_type(rx_ip_eth_type),
|
||||
.output_ip_version(rx_ip_version),
|
||||
.output_ip_ihl(rx_ip_ihl),
|
||||
.output_ip_dscp(rx_ip_dscp),
|
||||
.output_ip_ecn(rx_ip_ecn),
|
||||
.output_ip_length(rx_ip_length),
|
||||
.output_ip_identification(rx_ip_identification),
|
||||
.output_ip_flags(rx_ip_flags),
|
||||
.output_ip_fragment_offset(rx_ip_fragment_offset),
|
||||
.output_ip_ttl(rx_ip_ttl),
|
||||
.output_ip_protocol(rx_ip_protocol),
|
||||
.output_ip_header_checksum(rx_ip_header_checksum),
|
||||
.output_ip_source_ip(rx_ip_source_ip),
|
||||
.output_ip_dest_ip(rx_ip_dest_ip),
|
||||
.output_ip_payload_tdata(rx_ip_payload_tdata),
|
||||
.output_ip_payload_tkeep(rx_ip_payload_tkeep),
|
||||
.output_ip_payload_tvalid(rx_ip_payload_tvalid),
|
||||
.output_ip_payload_tready(rx_ip_payload_tready),
|
||||
.output_ip_payload_tlast(rx_ip_payload_tlast),
|
||||
.output_ip_payload_tuser(rx_ip_payload_tuser),
|
||||
// UDP frame input
|
||||
.input_udp_hdr_valid(tx_udp_hdr_valid),
|
||||
.input_udp_hdr_ready(tx_udp_hdr_ready),
|
||||
.input_udp_ip_dscp(tx_udp_ip_dscp),
|
||||
.input_udp_ip_ecn(tx_udp_ip_ecn),
|
||||
.input_udp_ip_ttl(tx_udp_ip_ttl),
|
||||
.input_udp_ip_source_ip(tx_udp_ip_source_ip),
|
||||
.input_udp_ip_dest_ip(tx_udp_ip_dest_ip),
|
||||
.input_udp_source_port(tx_udp_source_port),
|
||||
.input_udp_dest_port(tx_udp_dest_port),
|
||||
.input_udp_length(tx_udp_length),
|
||||
.input_udp_checksum(tx_udp_checksum),
|
||||
.input_udp_payload_tdata(tx_udp_payload_tdata),
|
||||
.input_udp_payload_tkeep(tx_udp_payload_tkeep),
|
||||
.input_udp_payload_tvalid(tx_udp_payload_tvalid),
|
||||
.input_udp_payload_tready(tx_udp_payload_tready),
|
||||
.input_udp_payload_tlast(tx_udp_payload_tlast),
|
||||
.input_udp_payload_tuser(tx_udp_payload_tuser),
|
||||
// UDP frame output
|
||||
.output_udp_hdr_valid(rx_udp_hdr_valid),
|
||||
.output_udp_hdr_ready(rx_udp_hdr_ready),
|
||||
.output_udp_eth_dest_mac(rx_udp_eth_dest_mac),
|
||||
.output_udp_eth_src_mac(rx_udp_eth_src_mac),
|
||||
.output_udp_eth_type(rx_udp_eth_type),
|
||||
.output_udp_ip_version(rx_udp_ip_version),
|
||||
.output_udp_ip_ihl(rx_udp_ip_ihl),
|
||||
.output_udp_ip_dscp(rx_udp_ip_dscp),
|
||||
.output_udp_ip_ecn(rx_udp_ip_ecn),
|
||||
.output_udp_ip_length(rx_udp_ip_length),
|
||||
.output_udp_ip_identification(rx_udp_ip_identification),
|
||||
.output_udp_ip_flags(rx_udp_ip_flags),
|
||||
.output_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
|
||||
.output_udp_ip_ttl(rx_udp_ip_ttl),
|
||||
.output_udp_ip_protocol(rx_udp_ip_protocol),
|
||||
.output_udp_ip_header_checksum(rx_udp_ip_header_checksum),
|
||||
.output_udp_ip_source_ip(rx_udp_ip_source_ip),
|
||||
.output_udp_ip_dest_ip(rx_udp_ip_dest_ip),
|
||||
.output_udp_source_port(rx_udp_source_port),
|
||||
.output_udp_dest_port(rx_udp_dest_port),
|
||||
.output_udp_length(rx_udp_length),
|
||||
.output_udp_checksum(rx_udp_checksum),
|
||||
.output_udp_payload_tdata(rx_udp_payload_tdata),
|
||||
.output_udp_payload_tkeep(rx_udp_payload_tkeep),
|
||||
.output_udp_payload_tvalid(rx_udp_payload_tvalid),
|
||||
.output_udp_payload_tready(rx_udp_payload_tready),
|
||||
.output_udp_payload_tlast(rx_udp_payload_tlast),
|
||||
.output_udp_payload_tuser(rx_udp_payload_tuser),
|
||||
// Status signals
|
||||
.ip_rx_busy(),
|
||||
.ip_tx_busy(),
|
||||
.udp_rx_busy(),
|
||||
.udp_tx_busy(),
|
||||
.ip_rx_error_header_early_termination(),
|
||||
.ip_rx_error_payload_early_termination(),
|
||||
.ip_rx_error_invalid_header(),
|
||||
.ip_rx_error_invalid_checksum(),
|
||||
.ip_tx_error_payload_early_termination(),
|
||||
.ip_tx_error_arp_failed(),
|
||||
.udp_rx_error_header_early_termination(),
|
||||
.udp_rx_error_payload_early_termination(),
|
||||
.udp_tx_error_payload_early_termination(),
|
||||
// Configuration
|
||||
.local_mac(local_mac),
|
||||
.local_ip(local_ip),
|
||||
.gateway_ip(gateway_ip),
|
||||
.subnet_mask(subnet_mask),
|
||||
.clear_arp_cache(1'b0)
|
||||
);
|
||||
|
||||
axis_fifo_64 #(
|
||||
.ADDR_WIDTH(10),
|
||||
.DATA_WIDTH(64)
|
||||
)
|
||||
udp_payload_fifo (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
// AXI input
|
||||
.input_axis_tdata(rx_fifo_udp_payload_tdata),
|
||||
.input_axis_tkeep(rx_fifo_udp_payload_tkeep),
|
||||
.input_axis_tvalid(rx_fifo_udp_payload_tvalid),
|
||||
.input_axis_tready(rx_fifo_udp_payload_tready),
|
||||
.input_axis_tlast(rx_fifo_udp_payload_tlast),
|
||||
.input_axis_tuser(rx_fifo_udp_payload_tuser),
|
||||
|
||||
// AXI output
|
||||
.output_axis_tdata(tx_fifo_udp_payload_tdata),
|
||||
.output_axis_tkeep(tx_fifo_udp_payload_tkeep),
|
||||
.output_axis_tvalid(tx_fifo_udp_payload_tvalid),
|
||||
.output_axis_tready(tx_fifo_udp_payload_tready),
|
||||
.output_axis_tlast(tx_fifo_udp_payload_tlast),
|
||||
.output_axis_tuser(tx_fifo_udp_payload_tuser)
|
||||
);
|
||||
|
||||
endmodule
|
895
example/DE5-Net/fpga/rtl/i2c_master.v
Normal file
895
example/DE5-Net/fpga/rtl/i2c_master.v
Normal file
@ -0,0 +1,895 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015-2016 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
|
455
example/DE5-Net/fpga/rtl/si570_i2c_init.v
Normal file
455
example/DE5-Net/fpga/rtl/si570_i2c_init.v
Normal file
@ -0,0 +1,455 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015-2016 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
|
52
example/DE5-Net/fpga/rtl/sync_reset.v
Normal file
52
example/DE5-Net/fpga/rtl/sync_reset.v
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014-2016 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
|
58
example/DE5-Net/fpga/rtl/sync_signal.v
Normal file
58
example/DE5-Net/fpga/rtl/sync_signal.v
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014-2016 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
|
1
example/DE5-Net/fpga/tb/arp_ep.py
Symbolic link
1
example/DE5-Net/fpga/tb/arp_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/eth/tb/arp_ep.py
|
1
example/DE5-Net/fpga/tb/axis_ep.py
Symbolic link
1
example/DE5-Net/fpga/tb/axis_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/eth/tb/axis_ep.py
|
1
example/DE5-Net/fpga/tb/eth_ep.py
Symbolic link
1
example/DE5-Net/fpga/tb/eth_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/eth/tb/eth_ep.py
|
1
example/DE5-Net/fpga/tb/ip_ep.py
Symbolic link
1
example/DE5-Net/fpga/tb/ip_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/eth/tb/ip_ep.py
|
412
example/DE5-Net/fpga/tb/test_fpga_core.py
Executable file
412
example/DE5-Net/fpga/tb/test_fpga_core.py
Executable file
@ -0,0 +1,412 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2016 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
|
||||
|
||||
try:
|
||||
from queue import Queue
|
||||
except ImportError:
|
||||
from Queue import Queue
|
||||
|
||||
import eth_ep
|
||||
import arp_ep
|
||||
import udp_ep
|
||||
import xgmii_ep
|
||||
|
||||
module = 'fpga_core'
|
||||
|
||||
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/eth_mac_10g_rx.v")
|
||||
srcs.append("../lib/eth/rtl/eth_mac_10g_tx.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_8.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_16.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_24.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_32.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_40.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_48.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_56.v")
|
||||
srcs.append("../lib/eth/rtl/eth_crc_64.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_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_64_2.v")
|
||||
srcs.append("../lib/eth/rtl/ip_mux_64_2.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_64_2.v")
|
||||
srcs.append("../lib/eth/rtl/eth_mux_64_2.v")
|
||||
srcs.append("../lib/eth/lib/axis/rtl/arbiter.v")
|
||||
srcs.append("../lib/eth/lib/axis/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/eth/lib/axis/rtl/axis_fifo_64.v")
|
||||
srcs.append("../lib/eth/lib/axis/rtl/axis_async_frame_fifo_64.v")
|
||||
srcs.append("test_%s.v" % module)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o test_%s.vvp %s" % (module, src)
|
||||
|
||||
def dut_fpga_core(clk,
|
||||
rst,
|
||||
current_test,
|
||||
|
||||
btn,
|
||||
sw,
|
||||
led,
|
||||
led_bkt,
|
||||
led_hex0_d,
|
||||
led_hex0_dp,
|
||||
led_hex1_d,
|
||||
led_hex1_dp,
|
||||
|
||||
sfp_a_txd,
|
||||
sfp_a_txc,
|
||||
sfp_a_rxd,
|
||||
sfp_a_rxc,
|
||||
sfp_b_txd,
|
||||
sfp_b_txc,
|
||||
sfp_b_rxd,
|
||||
sfp_b_rxc,
|
||||
sfp_c_txd,
|
||||
sfp_c_txc,
|
||||
sfp_c_rxd,
|
||||
sfp_c_rxc,
|
||||
sfp_d_txd,
|
||||
sfp_d_txc,
|
||||
sfp_d_rxd,
|
||||
sfp_d_rxc):
|
||||
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
return Cosimulation("vvp -m myhdl test_%s.vvp -lxt2" % module,
|
||||
clk=clk,
|
||||
rst=rst,
|
||||
current_test=current_test,
|
||||
|
||||
btn=btn,
|
||||
sw=sw,
|
||||
led=led,
|
||||
led_bkt=led_bkt,
|
||||
led_hex0_d=led_hex0_d,
|
||||
led_hex0_dp=led_hex0_dp,
|
||||
led_hex1_d=led_hex1_d,
|
||||
led_hex1_dp=led_hex1_dp,
|
||||
|
||||
sfp_a_txd=sfp_a_txd,
|
||||
sfp_a_txc=sfp_a_txc,
|
||||
sfp_a_rxd=sfp_a_rxd,
|
||||
sfp_a_rxc=sfp_a_rxc,
|
||||
sfp_b_txd=sfp_b_txd,
|
||||
sfp_b_txc=sfp_b_txc,
|
||||
sfp_b_rxd=sfp_b_rxd,
|
||||
sfp_b_rxc=sfp_b_rxc,
|
||||
sfp_c_txd=sfp_c_txd,
|
||||
sfp_c_txc=sfp_c_txc,
|
||||
sfp_c_rxd=sfp_c_rxd,
|
||||
sfp_c_rxc=sfp_c_rxc,
|
||||
sfp_d_txd=sfp_d_txd,
|
||||
sfp_d_txc=sfp_d_txc,
|
||||
sfp_d_rxd=sfp_d_rxd,
|
||||
sfp_d_rxc=sfp_d_rxc)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
|
||||
|
||||
# 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:])
|
||||
sfp_a_rxd = Signal(intbv(0)[64:])
|
||||
sfp_a_rxc = Signal(intbv(0)[8:])
|
||||
sfp_b_rxd = Signal(intbv(0)[64:])
|
||||
sfp_b_rxc = Signal(intbv(0)[8:])
|
||||
sfp_c_rxd = Signal(intbv(0)[64:])
|
||||
sfp_c_rxc = Signal(intbv(0)[8:])
|
||||
sfp_d_rxd = Signal(intbv(0)[64:])
|
||||
sfp_d_rxc = Signal(intbv(0)[8:])
|
||||
|
||||
# Outputs
|
||||
led = Signal(intbv(0)[4:])
|
||||
led_bkt = Signal(intbv(0)[4:])
|
||||
led_hex0_d = Signal(intbv(0)[7:])
|
||||
led_hex0_dp = Signal(bool(0))
|
||||
led_hex1_d = Signal(intbv(0)[7:])
|
||||
led_hex1_dp = Signal(bool(0))
|
||||
sfp_a_txd = Signal(intbv(0)[64:])
|
||||
sfp_a_txc = Signal(intbv(0)[8:])
|
||||
sfp_b_txd = Signal(intbv(0)[64:])
|
||||
sfp_b_txc = Signal(intbv(0)[8:])
|
||||
sfp_c_txd = Signal(intbv(0)[64:])
|
||||
sfp_c_txc = Signal(intbv(0)[8:])
|
||||
sfp_d_txd = Signal(intbv(0)[64:])
|
||||
sfp_d_txc = Signal(intbv(0)[8:])
|
||||
|
||||
# sources and sinks
|
||||
xgmii_a_source_queue = Queue()
|
||||
xgmii_a_sink_queue = Queue()
|
||||
xgmii_b_source_queue = Queue()
|
||||
xgmii_b_sink_queue = Queue()
|
||||
xgmii_c_source_queue = Queue()
|
||||
xgmii_c_sink_queue = Queue()
|
||||
xgmii_d_source_queue = Queue()
|
||||
xgmii_d_sink_queue = Queue()
|
||||
|
||||
xgmii_a_source = xgmii_ep.XGMIISource(clk,
|
||||
rst,
|
||||
txd=sfp_a_rxd,
|
||||
txc=sfp_a_rxc,
|
||||
fifo=xgmii_a_source_queue,
|
||||
name='xgmii_a_source')
|
||||
|
||||
xgmii_a_sink = xgmii_ep.XGMIISink(clk,
|
||||
rst,
|
||||
rxd=sfp_a_txd,
|
||||
rxc=sfp_a_txc,
|
||||
fifo=xgmii_a_sink_queue,
|
||||
name='xgmii_a_sink')
|
||||
|
||||
xgmii_b_source = xgmii_ep.XGMIISource(clk,
|
||||
rst,
|
||||
txd=sfp_b_rxd,
|
||||
txc=sfp_b_rxc,
|
||||
fifo=xgmii_b_source_queue,
|
||||
name='xgmii_b_source')
|
||||
|
||||
xgmii_b_sink = xgmii_ep.XGMIISink(clk,
|
||||
rst,
|
||||
rxd=sfp_b_txd,
|
||||
rxc=sfp_b_txc,
|
||||
fifo=xgmii_b_sink_queue,
|
||||
name='xgmii_b_sink')
|
||||
|
||||
xgmii_c_source = xgmii_ep.XGMIISource(clk,
|
||||
rst,
|
||||
txd=sfp_c_rxd,
|
||||
txc=sfp_c_rxc,
|
||||
fifo=xgmii_c_source_queue,
|
||||
name='xgmii_c_source')
|
||||
|
||||
xgmii_c_sink = xgmii_ep.XGMIISink(clk,
|
||||
rst,
|
||||
rxd=sfp_c_txd,
|
||||
rxc=sfp_c_txc,
|
||||
fifo=xgmii_c_sink_queue,
|
||||
name='xgmii_c_sink')
|
||||
|
||||
xgmii_d_source = xgmii_ep.XGMIISource(clk,
|
||||
rst,
|
||||
txd=sfp_d_rxd,
|
||||
txc=sfp_d_rxc,
|
||||
fifo=xgmii_d_source_queue,
|
||||
name='xgmii_d_source')
|
||||
|
||||
xgmii_d_sink = xgmii_ep.XGMIISink(clk,
|
||||
rst,
|
||||
rxd=sfp_d_txd,
|
||||
rxc=sfp_d_txc,
|
||||
fifo=xgmii_d_sink_queue,
|
||||
name='xgmii_d_sink')
|
||||
|
||||
# DUT
|
||||
dut = dut_fpga_core(clk,
|
||||
rst,
|
||||
current_test,
|
||||
|
||||
btn,
|
||||
sw,
|
||||
led,
|
||||
led_bkt,
|
||||
led_hex0_d,
|
||||
led_hex0_dp,
|
||||
led_hex1_d,
|
||||
led_hex1_dp,
|
||||
|
||||
sfp_a_txd,
|
||||
sfp_a_txc,
|
||||
sfp_a_rxd,
|
||||
sfp_a_rxc,
|
||||
sfp_b_txd,
|
||||
sfp_b_txc,
|
||||
sfp_b_rxd,
|
||||
sfp_b_rxc,
|
||||
sfp_c_txd,
|
||||
sfp_c_txc,
|
||||
sfp_c_rxd,
|
||||
sfp_c_rxc,
|
||||
sfp_d_txd,
|
||||
sfp_d_txc,
|
||||
sfp_d_rxd,
|
||||
sfp_d_rxc)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not 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()
|
||||
|
||||
xgmii_a_source_queue.put(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+test_frame.build_eth().build_axis_fcs().data)
|
||||
|
||||
# wait for ARP request packet
|
||||
while xgmii_a_sink_queue.empty():
|
||||
yield clk.posedge
|
||||
|
||||
rx_frame = xgmii_a_sink_queue.get(False)
|
||||
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
|
||||
|
||||
xgmii_a_source_queue.put(b'\x55\x55\x55\x55\x55\x55\x55\xD5'+arp_frame.build_eth().build_axis_fcs().data)
|
||||
|
||||
while xgmii_a_sink_queue.empty():
|
||||
yield clk.posedge
|
||||
|
||||
rx_frame = xgmii_a_sink_queue.get(False)
|
||||
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 xgmii_a_source_queue.empty()
|
||||
assert xgmii_a_sink_queue.empty()
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return dut, xgmii_a_source, xgmii_a_sink, xgmii_b_source, xgmii_b_sink, xgmii_c_source, xgmii_c_sink, xgmii_d_source, xgmii_d_sink, clkgen, check
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
133
example/DE5-Net/fpga/tb/test_fpga_core.v
Normal file
133
example/DE5-Net/fpga/tb/test_fpga_core.v
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2016 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 [3:0] btn = 0;
|
||||
reg [3:0] sw = 0;
|
||||
reg [63:0] sfp_a_rxd = 0;
|
||||
reg [7:0] sfp_a_rxc = 0;
|
||||
reg [63:0] sfp_b_rxd = 0;
|
||||
reg [7:0] sfp_b_rxc = 0;
|
||||
reg [63:0] sfp_c_rxd = 0;
|
||||
reg [7:0] sfp_c_rxc = 0;
|
||||
reg [63:0] sfp_d_rxd = 0;
|
||||
reg [7:0] sfp_d_rxc = 0;
|
||||
|
||||
// Outputs
|
||||
wire [3:0] led;
|
||||
wire [3:0] led_bkt;
|
||||
wire [6:0] led_hex0_d;
|
||||
wire led_hex0_dp;
|
||||
wire [6:0] led_hex1_d;
|
||||
wire led_hex1_dp;
|
||||
wire [63:0] sfp_a_txd;
|
||||
wire [7:0] sfp_a_txc;
|
||||
wire [63:0] sfp_b_txd;
|
||||
wire [7:0] sfp_b_txc;
|
||||
wire [63:0] sfp_c_txd;
|
||||
wire [7:0] sfp_c_txc;
|
||||
wire [63:0] sfp_d_txd;
|
||||
wire [7:0] sfp_d_txc;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(clk,
|
||||
rst,
|
||||
current_test,
|
||||
btn,
|
||||
sw,
|
||||
sfp_a_rxd,
|
||||
sfp_a_rxc,
|
||||
sfp_b_rxd,
|
||||
sfp_b_rxc,
|
||||
sfp_c_rxd,
|
||||
sfp_c_rxc,
|
||||
sfp_d_rxd,
|
||||
sfp_d_rxc);
|
||||
$to_myhdl(led,
|
||||
led_bkt,
|
||||
led_hex0_d,
|
||||
led_hex0_dp,
|
||||
led_hex1_d,
|
||||
led_hex1_dp,
|
||||
sfp_a_txd,
|
||||
sfp_a_txc,
|
||||
sfp_b_txd,
|
||||
sfp_b_txc,
|
||||
sfp_c_txd,
|
||||
sfp_c_txc,
|
||||
sfp_d_txd,
|
||||
sfp_d_txc);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.btn(btn),
|
||||
.sw(sw),
|
||||
.led(led),
|
||||
.led_bkt(led_bkt),
|
||||
.led_hex0_d(led_hex0_d),
|
||||
.led_hex0_dp(led_hex0_dp),
|
||||
.led_hex1_d(led_hex1_d),
|
||||
.led_hex1_dp(led_hex1_dp),
|
||||
.sfp_a_txd(sfp_a_txd),
|
||||
.sfp_a_txc(sfp_a_txc),
|
||||
.sfp_a_rxd(sfp_a_rxd),
|
||||
.sfp_a_rxc(sfp_a_rxc),
|
||||
.sfp_b_txd(sfp_b_txd),
|
||||
.sfp_b_txc(sfp_b_txc),
|
||||
.sfp_b_rxd(sfp_b_rxd),
|
||||
.sfp_b_rxc(sfp_b_rxc),
|
||||
.sfp_c_txd(sfp_c_txd),
|
||||
.sfp_c_txc(sfp_c_txc),
|
||||
.sfp_c_rxd(sfp_c_rxd),
|
||||
.sfp_c_rxc(sfp_c_rxc),
|
||||
.sfp_d_txd(sfp_d_txd),
|
||||
.sfp_d_txc(sfp_d_txc),
|
||||
.sfp_d_rxd(sfp_d_rxd),
|
||||
.sfp_d_rxc(sfp_d_rxc)
|
||||
);
|
||||
|
||||
endmodule
|
1
example/DE5-Net/fpga/tb/udp_ep.py
Symbolic link
1
example/DE5-Net/fpga/tb/udp_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/eth/tb/udp_ep.py
|
1
example/DE5-Net/fpga/tb/xgmii_ep.py
Symbolic link
1
example/DE5-Net/fpga/tb/xgmii_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/eth/tb/xgmii_ep.py
|
Loading…
x
Reference in New Issue
Block a user