1
0
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:
Alex Forencich 2016-01-25 00:53:06 -08:00
parent 3f2d096249
commit eb8dd775a1
25 changed files with 5431 additions and 0 deletions

View File

@ -0,0 +1,25 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = cores fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#program commands

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,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"

View File

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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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()

View 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

View File

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

View File

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