diff options
author | Martin Braun <martin.braun@ettus.com> | 2020-01-23 16:10:22 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2020-01-28 09:35:36 -0800 |
commit | bafa9d95453387814ef25e6b6256ba8db2df612f (patch) | |
tree | 39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/top/n3xx/dboards/mg | |
parent | 3075b981503002df3115d5f1d0b97d2619ba30f2 (diff) | |
download | uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2 uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip |
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce
the size of the repository. However, over the last half-decade, the
split between the repositories has proven more burdensome than it has
been helpful. By merging the FPGA code back, it will be possible to
create atomic commits that touch both FPGA and UHD codebases. Continuous
integration testing is also simplified by merging the repositories,
because it was previously difficult to automatically derive the correct
UHD branch when testing a feature branch on the FPGA repository.
This commit also updates the license files and paths therein.
We are therefore merging the repositories again. Future development for
FPGA code will happen in the same repository as the UHD host code and
MPM code.
== Original Codebase and Rebasing ==
The original FPGA repository will be hosted for the foreseeable future
at its original local location: https://github.com/EttusResearch/fpga/
It can be used for bisecting, reference, and a more detailed history.
The final commit from said repository to be merged here is
05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as
v4.0.0.0-pre-uhd-merge.
If you have changes in the FPGA repository that you want to rebase onto
the UHD repository, simply run the following commands:
- Create a directory to store patches (this should be an empty
directory):
mkdir ~/patches
- Now make sure that your FPGA codebase is based on the same state as
the code that was merged:
cd src/fpga # Or wherever your FPGA code is stored
git rebase v4.0.0.0-pre-uhd-merge
Note: The rebase command may look slightly different depending on what
exactly you're trying to rebase.
- Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge:
git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches
Note: Make sure that only patches are stored in your output directory.
It should otherwise be empty. Make sure that you picked the correct
range of commits, and only commits you wanted to rebase were exported
as patch files.
- Go to the UHD repository and apply the patches:
cd src/uhd # Or wherever your UHD repository is stored
git am --directory fpga ~/patches/*
rm -rf ~/patches # This is for cleanup
== Contributors ==
The following people have contributed mainly to these files (this list
is not complete):
Co-authored-by: Alex Williams <alex.williams@ni.com>
Co-authored-by: Andrej Rode <andrej.rode@ettus.com>
Co-authored-by: Ashish Chaudhari <ashish@ettus.com>
Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Derek Kozel <derek.kozel@ettus.com>
Co-authored-by: EJ Kreinar <ej@he360.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Ian Buckley <ian.buckley@gmail.com>
Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Jon Kiser <jon.kiser@ni.com>
Co-authored-by: Josh Blum <josh@joshknows.com>
Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Matt Ettus <matt@ettus.com>
Co-authored-by: Michael West <michael.west@ettus.com>
Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com>
Co-authored-by: Nick Foster <nick@ettus.com>
Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Paul David <paul.david@ettus.com>
Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com>
Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com>
Co-authored-by: Sylvain Munaut <tnt@246tNt.com>
Co-authored-by: Trung Tran <trung.tran@ettus.com>
Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/top/n3xx/dboards/mg')
24 files changed, 8888 insertions, 0 deletions
diff --git a/fpga/usrp3/top/n3xx/dboards/mg/Makefile.srcs b/fpga/usrp3/top/n3xx/dboards/mg/Makefile.srcs new file mode 100644 index 000000000..85bb60752 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/Makefile.srcs @@ -0,0 +1,34 @@ +# +# Copyright 2017 Ettus Research LLC +# + +################################################## +# DB IFC Sources +################################################## +MAGNESIUM_DB_SRCS = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/mg/db_ifc/, \ +DbCore.vhd \ +DaughterboardRegs.vhd \ +ClockingRegs.vhd \ +PkgMgPersonality.vhd \ +PkgDaughterboardRegMap.vhd \ +PkgClockingRegMap.vhd \ +PkgJesdConfig.vhd \ +RadioClocking.vhd \ +Jesd204bXcvrCore.edf \ +)) + +MAGNESIUM_TOP_SRCS = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/mg/, \ +n3xx.v \ +)) + +MAGNESIUM_DB_TIMING_XDC = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/mg/, \ +db_timing.xdc \ +)) + +MAGNESIUM_DB0_XDC = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/mg/, \ +db0_pins.xdc \ +)) + +MAGNESIUM_DB1_XDC = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/mg/, \ +db1_pins.xdc \ +)) diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/Makefile b/fpga/usrp3/top/n3xx/dboards/mg/cpld/Makefile new file mode 100644 index 000000000..3fbb7d3bb --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/Makefile @@ -0,0 +1,22 @@ +# +# Copyright 2018 Ettus Research, a National Instruments Company +# + +.PHONY: all clean + +SRCS=TopCpld.qpf TopCpld.qsf Timing.sdc PkgMgCpld.vhd PkgSetup.vhd TopCpld.vhd + +all: output_files/TopCpld.svf + +cpld-magnesium-revc.svf: output_files/TopCpld.pof + quartus_cpf --convert --frequency 10.0MHz --voltage 3.3 --operation p $? $@ + +output_files/TopCpld.pof: $(SRCS) + quartus_map TopCpld + quartus_fit TopCpld + quartus_asm TopCpld + quartus_sta TopCpld + +clean: + rm -rf db incremental_db output_files simulation cpld-magnesium-revc.svf + diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgMgCpld.vhd b/fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgMgCpld.vhd new file mode 100644 index 000000000..327183bea --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgMgCpld.vhd @@ -0,0 +1,424 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgMgCpld.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: GPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgMgCpld is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- SignatureReg : 0x0 (TopCpld.vhd) + -- MinorRevReg : 0x1 (TopCpld.vhd) + -- MajorRevReg : 0x2 (TopCpld.vhd) + -- BuildCodeLSB : 0x3 (TopCpld.vhd) + -- BuildCodeMSB : 0x4 (TopCpld.vhd) + -- Scratch : 0x5 (TopCpld.vhd) + -- CpldControl : 0x10 (TopCpld.vhd) + -- LmkControl : 0x11 (TopCpld.vhd) + -- LoStatus : 0x12 (TopCpld.vhd) + -- MykonosControl : 0x13 (TopCpld.vhd) + -- PlScratch : 0x40 (TopCpld.vhd) + -- PlCpldControl : 0x41 (TopCpld.vhd) + -- TxCh1_Idle : 0x50 (TopCpld.vhd) + -- RxCh1_0_Idle : 0x51 (TopCpld.vhd) + -- RxCh1_1_Idle : 0x52 (TopCpld.vhd) + -- TxCh1_TxOn : 0x53 (TopCpld.vhd) + -- RxCh1_0_RxOn : 0x54 (TopCpld.vhd) + -- RxCh1_1_RxOn : 0x55 (TopCpld.vhd) + -- TxCh2_Idle : 0x60 (TopCpld.vhd) + -- RxCh2_0_Idle : 0x61 (TopCpld.vhd) + -- RxCh2_1_Idle : 0x62 (TopCpld.vhd) + -- TxCh2_TxOn : 0x63 (TopCpld.vhd) + -- RxCh2_0_RxOn : 0x64 (TopCpld.vhd) + -- RxCh2_1_RxOn : 0x65 (TopCpld.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group PsSpi_CpldRegisters +--=============================================================================== + + -- SignatureReg Register (from TopCpld.vhd) + constant kSignatureReg : integer := 16#0#; -- Register Offset + constant kSignatureRegSize: integer := 16; -- register width in bits + constant kSignatureRegMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kProductSignatureSize : integer := 16; --SignatureReg:ProductSignature + constant kProductSignatureMsb : integer := 15; --SignatureReg:ProductSignature + constant kProductSignature : integer := 0; --SignatureReg:ProductSignature + + -- MinorRevReg Register (from TopCpld.vhd) + constant kMinorRevReg : integer := 16#1#; -- Register Offset + constant kMinorRevRegSize: integer := 16; -- register width in bits + constant kMinorRevRegMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kCpldMinorRevisionSize : integer := 16; --MinorRevReg:CpldMinorRevision + constant kCpldMinorRevisionMsb : integer := 15; --MinorRevReg:CpldMinorRevision + constant kCpldMinorRevision : integer := 0; --MinorRevReg:CpldMinorRevision + + -- MajorRevReg Register (from TopCpld.vhd) + constant kMajorRevReg : integer := 16#2#; -- Register Offset + constant kMajorRevRegSize: integer := 16; -- register width in bits + constant kMajorRevRegMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kCpldMajorRevisionSize : integer := 16; --MajorRevReg:CpldMajorRevision + constant kCpldMajorRevisionMsb : integer := 15; --MajorRevReg:CpldMajorRevision + constant kCpldMajorRevision : integer := 0; --MajorRevReg:CpldMajorRevision + + -- BuildCodeLSB Register (from TopCpld.vhd) + constant kBuildCodeLSB : integer := 16#3#; -- Register Offset + constant kBuildCodeLSBSize: integer := 16; -- register width in bits + constant kBuildCodeLSBMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kBuildCodeHHSize : integer := 8; --BuildCodeLSB:BuildCodeHH + constant kBuildCodeHHMsb : integer := 7; --BuildCodeLSB:BuildCodeHH + constant kBuildCodeHH : integer := 0; --BuildCodeLSB:BuildCodeHH + constant kBuildCodeDDSize : integer := 8; --BuildCodeLSB:BuildCodeDD + constant kBuildCodeDDMsb : integer := 15; --BuildCodeLSB:BuildCodeDD + constant kBuildCodeDD : integer := 8; --BuildCodeLSB:BuildCodeDD + + -- BuildCodeMSB Register (from TopCpld.vhd) + constant kBuildCodeMSB : integer := 16#4#; -- Register Offset + constant kBuildCodeMSBSize: integer := 16; -- register width in bits + constant kBuildCodeMSBMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kBuildCodeMMSize : integer := 8; --BuildCodeMSB:BuildCodeMM + constant kBuildCodeMMMsb : integer := 7; --BuildCodeMSB:BuildCodeMM + constant kBuildCodeMM : integer := 0; --BuildCodeMSB:BuildCodeMM + constant kBuildCodeYYSize : integer := 8; --BuildCodeMSB:BuildCodeYY + constant kBuildCodeYYMsb : integer := 15; --BuildCodeMSB:BuildCodeYY + constant kBuildCodeYY : integer := 8; --BuildCodeMSB:BuildCodeYY + + -- Scratch Register (from TopCpld.vhd) + constant kScratch : integer := 16#5#; -- Register Offset + constant kScratchSize: integer := 16; -- register width in bits + constant kScratchMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kScratchValSize : integer := 16; --Scratch:ScratchVal + constant kScratchValMsb : integer := 15; --Scratch:ScratchVal + constant kScratchVal : integer := 0; --Scratch:ScratchVal + + -- CpldControl Register (from TopCpld.vhd) + constant kCpldControl : integer := 16#10#; -- Register Offset + constant kCpldControlSize: integer := 16; -- register width in bits + constant kCpldControlMask : std_logic_vector(15 downto 0) := X"0001"; + constant kCpldResetSize : integer := 1; --CpldControl:CpldReset + constant kCpldResetMsb : integer := 0; --CpldControl:CpldReset + constant kCpldReset : integer := 0; --CpldControl:CpldReset + + -- LmkControl Register (from TopCpld.vhd) + constant kLmkControl : integer := 16#11#; -- Register Offset + constant kLmkControlSize: integer := 16; -- register width in bits + constant kLmkControlMask : std_logic_vector(15 downto 0) := X"0010"; + constant kVcxoControlSize : integer := 1; --LmkControl:VcxoControl + constant kVcxoControlMsb : integer := 4; --LmkControl:VcxoControl + constant kVcxoControl : integer := 4; --LmkControl:VcxoControl + + -- LoStatus Register (from TopCpld.vhd) + constant kLoStatus : integer := 16#12#; -- Register Offset + constant kLoStatusSize: integer := 16; -- register width in bits + constant kLoStatusMask : std_logic_vector(15 downto 0) := X"0011"; + constant kRxLoLockDetectSize : integer := 1; --LoStatus:RxLoLockDetect + constant kRxLoLockDetectMsb : integer := 0; --LoStatus:RxLoLockDetect + constant kRxLoLockDetect : integer := 0; --LoStatus:RxLoLockDetect + constant kTxLoLockDetectSize : integer := 1; --LoStatus:TxLoLockDetect + constant kTxLoLockDetectMsb : integer := 4; --LoStatus:TxLoLockDetect + constant kTxLoLockDetect : integer := 4; --LoStatus:TxLoLockDetect + + -- MykonosControl Register (from TopCpld.vhd) + constant kMykonosControl : integer := 16#13#; -- Register Offset + constant kMykonosControlSize: integer := 16; -- register width in bits + constant kMykonosControlMask : std_logic_vector(15 downto 0) := X"0001"; + constant kMykonosResetSize : integer := 1; --MykonosControl:MykonosReset + constant kMykonosResetMsb : integer := 0; --MykonosControl:MykonosReset + constant kMykonosReset : integer := 0; --MykonosControl:MykonosReset + +--=============================================================================== +-- Register Group PlSpi_FrontEndControl +--=============================================================================== + + -- Enumerated type Rx1Switch1 + constant kRx1Switch1Size : integer := 4; + constant kTxRxInput : integer := 0; -- Rx1Switch1:TxRxInput + constant kRxLoCalInput : integer := 1; -- Rx1Switch1:RxLoCalInput + constant kTrxSwitchOutput : integer := 2; -- Rx1Switch1:TrxSwitchOutput + constant kRx2Input : integer := 3; -- Rx1Switch1:Rx2Input + + -- Enumerated type Rx1Switch2 + constant kRx1Switch2Size : integer := 4; + constant kShutdownSw2 : integer := 0; -- Rx1Switch2:ShutdownSw2 + constant kLowerFilterBankToSwitch3 : integer := 1; -- Rx1Switch2:LowerFilterBankToSwitch3 + constant kBypassPathToSwitch6 : integer := 2; -- Rx1Switch2:BypassPathToSwitch6 + constant kUpperFilterBankToSwitch4 : integer := 3; -- Rx1Switch2:UpperFilterBankToSwitch4 + + -- Enumerated type Rx1Switch3 + constant kRx1Switch3Size : integer := 7; + constant kFilter2100x2850MHz : integer := 0; -- Rx1Switch3:Filter2100x2850MHz + constant kFilter0490LpMHz : integer := 1; -- Rx1Switch3:Filter0490LpMHz + constant kFilter1600x2250MHz : integer := 2; -- Rx1Switch3:Filter1600x2250MHz + constant kFilter0440x0530MHz : integer := 4; -- Rx1Switch3:Filter0440x0530MHz + constant kFilter0650x1000MHz : integer := 5; -- Rx1Switch3:Filter0650x1000MHz + constant kFilter1100x1575MHz : integer := 6; -- Rx1Switch3:Filter1100x1575MHz + constant kShutdownSw3 : integer := 7; -- Rx1Switch3:ShutdownSw3 + + -- Enumerated type Rx1Switch4 + constant kRx1Switch4Size : integer := 3; + constant kFilter2100x2850MHzFrom : integer := 1; -- Rx1Switch4:Filter2100x2850MHzFrom + constant kFilter1600x2250MHzFrom : integer := 2; -- Rx1Switch4:Filter1600x2250MHzFrom + constant kFilter2700HpMHz : integer := 4; -- Rx1Switch4:Filter2700HpMHz + + -- Enumerated type Rx1Switch5 + constant kRx1Switch5Size : integer := 4; + constant kFilter0440x0530MHzFrom : integer := 1; -- Rx1Switch5:Filter0440x0530MHzFrom + constant kFilter1100x1575MHzFrom : integer := 2; -- Rx1Switch5:Filter1100x1575MHzFrom + constant kFilter0490LpMHzFrom : integer := 4; -- Rx1Switch5:Filter0490LpMHzFrom + constant kFilter0650x1000MHzFrom : integer := 8; -- Rx1Switch5:Filter0650x1000MHzFrom + + -- Enumerated type Rx1Switch6 + constant kRx1Switch6Size : integer := 3; + constant kLowerFilterBankFromSwitch5 : integer := 1; -- Rx1Switch6:LowerFilterBankFromSwitch5 + constant kUpperFilterBankFromSwitch4 : integer := 2; -- Rx1Switch6:UpperFilterBankFromSwitch4 + constant kBypassPathFromSwitch2 : integer := 4; -- Rx1Switch6:BypassPathFromSwitch2 + + -- Enumerated type TrxSwitch + constant kTrxSwitchSize : integer := 4; + constant kFromLowerFilterBankTxSw1 : integer := 0; -- TrxSwitch:FromLowerFilterBankTxSw1 + constant kFromTxUpperFilterBankLp6400MHz : integer := 1; -- TrxSwitch:FromTxUpperFilterBankLp6400MHz + constant kRxChannelPath : integer := 2; -- TrxSwitch:RxChannelPath + constant kBypassPathToTxSw3 : integer := 3; -- TrxSwitch:BypassPathToTxSw3 + + -- Enumerated type TxSwitch1 + constant kTxSwitch1Size : integer := 4; + constant kShutdownTxSw1 : integer := 0; -- TxSwitch1:ShutdownTxSw1 + constant kFromTxFilterLp1700MHz : integer := 1; -- TxSwitch1:FromTxFilterLp1700MHz + constant kFromTxFilterLp3400MHz : integer := 2; -- TxSwitch1:FromTxFilterLp3400MHz + constant kFromTxFilterLp0800MHz : integer := 3; -- TxSwitch1:FromTxFilterLp0800MHz + + -- Enumerated type TxSwitch2 + constant kTxSwitch2Size : integer := 4; + constant kToTxFilterLp3400MHz : integer := 1; -- TxSwitch2:ToTxFilterLp3400MHz + constant kToTxFilterLp1700MHz : integer := 2; -- TxSwitch2:ToTxFilterLp1700MHz + constant kToTxFilterLp0800MHz : integer := 4; -- TxSwitch2:ToTxFilterLp0800MHz + constant kToTxFilterLp6400MHz : integer := 8; -- TxSwitch2:ToTxFilterLp6400MHz + + -- Enumerated type TxSwitch3 + constant kTxSwitch3Size : integer := 2; + constant kToTxFilterBanks : integer := 0; -- TxSwitch3:ToTxFilterBanks + constant kBypassPathToTrxSw : integer := 1; -- TxSwitch3:BypassPathToTrxSw + + -- PlScratch Register (from TopCpld.vhd) + constant kPlScratch : integer := 16#40#; -- Register Offset + constant kPlScratchSize: integer := 16; -- register width in bits + constant kPlScratchMask : std_logic_vector(15 downto 0) := X"ffff"; + constant kPlScratchValSize : integer := 16; --PlScratch:PlScratchVal + constant kPlScratchValMsb : integer := 15; --PlScratch:PlScratchVal + constant kPlScratchVal : integer := 0; --PlScratch:PlScratchVal + + -- PlCpldControl Register (from TopCpld.vhd) + constant kPlCpldControl : integer := 16#41#; -- Register Offset + constant kPlCpldControlSize: integer := 16; -- register width in bits + constant kPlCpldControlMask : std_logic_vector(15 downto 0) := X"0001"; + constant kPlCpldResetSize : integer := 1; --PlCpldControl:PlCpldReset + constant kPlCpldResetMsb : integer := 0; --PlCpldControl:PlCpldReset + constant kPlCpldReset : integer := 0; --PlCpldControl:PlCpldReset + + -- TxCh1_Idle Register (from TopCpld.vhd) + constant kTxCh1_Idle : integer := 16#50#; -- Register Offset + constant kTxCh1_IdleSize: integer := 16; -- register width in bits + constant kTxCh1_IdleMask : std_logic_vector(15 downto 0) := X"7fff"; + constant kCh1TxSw1Size : integer := 2; --TxCh1_Idle:Ch1TxSw1 + constant kCh1TxSw1Msb : integer := 1; --TxCh1_Idle:Ch1TxSw1 + constant kCh1TxSw1 : integer := 0; --TxCh1_Idle:Ch1TxSw1 + constant kCh1TxSw2Size : integer := 4; --TxCh1_Idle:Ch1TxSw2 + constant kCh1TxSw2Msb : integer := 5; --TxCh1_Idle:Ch1TxSw2 + constant kCh1TxSw2 : integer := 2; --TxCh1_Idle:Ch1TxSw2 + constant kCh1TxSw3Size : integer := 1; --TxCh1_Idle:Ch1TxSw3 + constant kCh1TxSw3Msb : integer := 6; --TxCh1_Idle:Ch1TxSw3 + constant kCh1TxSw3 : integer := 6; --TxCh1_Idle:Ch1TxSw3 + constant kCh1TxLowbandMixerPathSelectSize : integer := 1; --TxCh1_Idle:Ch1TxLowbandMixerPathSelect + constant kCh1TxLowbandMixerPathSelectMsb : integer := 7; --TxCh1_Idle:Ch1TxLowbandMixerPathSelect + constant kCh1TxLowbandMixerPathSelect : integer := 7; --TxCh1_Idle:Ch1TxLowbandMixerPathSelect + constant kCh1TxMixerEnSize : integer := 1; --TxCh1_Idle:Ch1TxMixerEn + constant kCh1TxMixerEnMsb : integer := 8; --TxCh1_Idle:Ch1TxMixerEn + constant kCh1TxMixerEn : integer := 8; --TxCh1_Idle:Ch1TxMixerEn + constant kCh1TxAmpEnSize : integer := 1; --TxCh1_Idle:Ch1TxAmpEn + constant kCh1TxAmpEnMsb : integer := 9; --TxCh1_Idle:Ch1TxAmpEn + constant kCh1TxAmpEn : integer := 9; --TxCh1_Idle:Ch1TxAmpEn + constant kCh1TxPaEnSize : integer := 1; --TxCh1_Idle:Ch1TxPaEn + constant kCh1TxPaEnMsb : integer := 10; --TxCh1_Idle:Ch1TxPaEn + constant kCh1TxPaEn : integer := 10; --TxCh1_Idle:Ch1TxPaEn + constant kCh1SwTrxSize : integer := 2; --TxCh1_Idle:Ch1SwTrx + constant kCh1SwTrxMsb : integer := 12; --TxCh1_Idle:Ch1SwTrx + constant kCh1SwTrx : integer := 11; --TxCh1_Idle:Ch1SwTrx + constant kCh1TxLedSize : integer := 1; --TxCh1_Idle:Ch1TxLed + constant kCh1TxLedMsb : integer := 13; --TxCh1_Idle:Ch1TxLed + constant kCh1TxLed : integer := 13; --TxCh1_Idle:Ch1TxLed + constant kCh1MykEnTxSize : integer := 1; --TxCh1_Idle:Ch1MykEnTx + constant kCh1MykEnTxMsb : integer := 14; --TxCh1_Idle:Ch1MykEnTx + constant kCh1MykEnTx : integer := 14; --TxCh1_Idle:Ch1MykEnTx + + -- RxCh1_0_Idle Register (from TopCpld.vhd) + constant kRxCh1_0_Idle : integer := 16#51#; -- Register Offset + constant kRxCh1_0_IdleSize: integer := 16; -- register width in bits + constant kRxCh1_0_IdleMask : std_logic_vector(15 downto 0) := X"3fff"; + constant kCh1RxSw1Size : integer := 2; --RxCh1_0_Idle:Ch1RxSw1 + constant kCh1RxSw1Msb : integer := 1; --RxCh1_0_Idle:Ch1RxSw1 + constant kCh1RxSw1 : integer := 0; --RxCh1_0_Idle:Ch1RxSw1 + constant kCh1RxSw2Size : integer := 2; --RxCh1_0_Idle:Ch1RxSw2 + constant kCh1RxSw2Msb : integer := 3; --RxCh1_0_Idle:Ch1RxSw2 + constant kCh1RxSw2 : integer := 2; --RxCh1_0_Idle:Ch1RxSw2 + constant kCh1RxSw3Size : integer := 3; --RxCh1_0_Idle:Ch1RxSw3 + constant kCh1RxSw3Msb : integer := 6; --RxCh1_0_Idle:Ch1RxSw3 + constant kCh1RxSw3 : integer := 4; --RxCh1_0_Idle:Ch1RxSw3 + constant kCh1RxSw4Size : integer := 3; --RxCh1_0_Idle:Ch1RxSw4 + constant kCh1RxSw4Msb : integer := 9; --RxCh1_0_Idle:Ch1RxSw4 + constant kCh1RxSw4 : integer := 7; --RxCh1_0_Idle:Ch1RxSw4 + constant kCh1RxSw5Size : integer := 4; --RxCh1_0_Idle:Ch1RxSw5 + constant kCh1RxSw5Msb : integer := 13; --RxCh1_0_Idle:Ch1RxSw5 + constant kCh1RxSw5 : integer := 10; --RxCh1_0_Idle:Ch1RxSw5 + + -- RxCh1_1_Idle Register (from TopCpld.vhd) + constant kRxCh1_1_Idle : integer := 16#52#; -- Register Offset + constant kRxCh1_1_IdleSize: integer := 16; -- register width in bits + constant kRxCh1_1_IdleMask : std_logic_vector(15 downto 0) := X"07ff"; + constant kCh1RxSw6Size : integer := 3; --RxCh1_1_Idle:Ch1RxSw6 + constant kCh1RxSw6Msb : integer := 2; --RxCh1_1_Idle:Ch1RxSw6 + constant kCh1RxSw6 : integer := 0; --RxCh1_1_Idle:Ch1RxSw6 + constant kCh1RxLowbandMixerPathSelectSize : integer := 1; --RxCh1_1_Idle:Ch1RxLowbandMixerPathSelect + constant kCh1RxLowbandMixerPathSelectMsb : integer := 3; --RxCh1_1_Idle:Ch1RxLowbandMixerPathSelect + constant kCh1RxLowbandMixerPathSelect : integer := 3; --RxCh1_1_Idle:Ch1RxLowbandMixerPathSelect + constant kCh1RxMixerEnSize : integer := 1; --RxCh1_1_Idle:Ch1RxMixerEn + constant kCh1RxMixerEnMsb : integer := 4; --RxCh1_1_Idle:Ch1RxMixerEn + constant kCh1RxMixerEn : integer := 4; --RxCh1_1_Idle:Ch1RxMixerEn + constant kCh1RxAmpEnSize : integer := 1; --RxCh1_1_Idle:Ch1RxAmpEn + constant kCh1RxAmpEnMsb : integer := 5; --RxCh1_1_Idle:Ch1RxAmpEn + constant kCh1RxAmpEn : integer := 5; --RxCh1_1_Idle:Ch1RxAmpEn + constant kCh1RxLna1EnSize : integer := 1; --RxCh1_1_Idle:Ch1RxLna1En + constant kCh1RxLna1EnMsb : integer := 6; --RxCh1_1_Idle:Ch1RxLna1En + constant kCh1RxLna1En : integer := 6; --RxCh1_1_Idle:Ch1RxLna1En + constant kCh1RxLna2EnSize : integer := 1; --RxCh1_1_Idle:Ch1RxLna2En + constant kCh1RxLna2EnMsb : integer := 7; --RxCh1_1_Idle:Ch1RxLna2En + constant kCh1RxLna2En : integer := 7; --RxCh1_1_Idle:Ch1RxLna2En + constant kCh1Rx2LedSize : integer := 1; --RxCh1_1_Idle:Ch1Rx2Led + constant kCh1Rx2LedMsb : integer := 8; --RxCh1_1_Idle:Ch1Rx2Led + constant kCh1Rx2Led : integer := 8; --RxCh1_1_Idle:Ch1Rx2Led + constant kCh1RxLedSize : integer := 1; --RxCh1_1_Idle:Ch1RxLed + constant kCh1RxLedMsb : integer := 9; --RxCh1_1_Idle:Ch1RxLed + constant kCh1RxLed : integer := 9; --RxCh1_1_Idle:Ch1RxLed + constant kCh1MykEnRxSize : integer := 1; --RxCh1_1_Idle:Ch1MykEnRx + constant kCh1MykEnRxMsb : integer := 10; --RxCh1_1_Idle:Ch1MykEnRx + constant kCh1MykEnRx : integer := 10; --RxCh1_1_Idle:Ch1MykEnRx + + -- TxCh1_TxOn Register (from TopCpld.vhd) + constant kTxCh1_TxOn : integer := 16#53#; -- Register Offset + constant kTxCh1_TxOnSize: integer := 16; -- register width in bits + constant kTxCh1_TxOnMask : std_logic_vector(15 downto 0) := X"0000"; + + -- RxCh1_0_RxOn Register (from TopCpld.vhd) + constant kRxCh1_0_RxOn : integer := 16#54#; -- Register Offset + constant kRxCh1_0_RxOnSize: integer := 16; -- register width in bits + constant kRxCh1_0_RxOnMask : std_logic_vector(15 downto 0) := X"0000"; + + -- RxCh1_1_RxOn Register (from TopCpld.vhd) + constant kRxCh1_1_RxOn : integer := 16#55#; -- Register Offset + constant kRxCh1_1_RxOnSize: integer := 16; -- register width in bits + constant kRxCh1_1_RxOnMask : std_logic_vector(15 downto 0) := X"0000"; + + -- TxCh2_Idle Register (from TopCpld.vhd) + constant kTxCh2_Idle : integer := 16#60#; -- Register Offset + constant kTxCh2_IdleSize: integer := 16; -- register width in bits + constant kTxCh2_IdleMask : std_logic_vector(15 downto 0) := X"0000"; + + -- RxCh2_0_Idle Register (from TopCpld.vhd) + constant kRxCh2_0_Idle : integer := 16#61#; -- Register Offset + constant kRxCh2_0_IdleSize: integer := 16; -- register width in bits + constant kRxCh2_0_IdleMask : std_logic_vector(15 downto 0) := X"0000"; + + -- RxCh2_1_Idle Register (from TopCpld.vhd) + constant kRxCh2_1_Idle : integer := 16#62#; -- Register Offset + constant kRxCh2_1_IdleSize: integer := 16; -- register width in bits + constant kRxCh2_1_IdleMask : std_logic_vector(15 downto 0) := X"0000"; + + -- TxCh2_TxOn Register (from TopCpld.vhd) + constant kTxCh2_TxOn : integer := 16#63#; -- Register Offset + constant kTxCh2_TxOnSize: integer := 16; -- register width in bits + constant kTxCh2_TxOnMask : std_logic_vector(15 downto 0) := X"0000"; + + -- RxCh2_0_RxOn Register (from TopCpld.vhd) + constant kRxCh2_0_RxOn : integer := 16#64#; -- Register Offset + constant kRxCh2_0_RxOnSize: integer := 16; -- register width in bits + constant kRxCh2_0_RxOnMask : std_logic_vector(15 downto 0) := X"0000"; + + -- RxCh2_1_RxOn Register (from TopCpld.vhd) + constant kRxCh2_1_RxOn : integer := 16#65#; -- Register Offset + constant kRxCh2_1_RxOnSize: integer := 16; -- register width in bits + constant kRxCh2_1_RxOnMask : std_logic_vector(15 downto 0) := X"0000"; + +end package; + +package body PkgMgCpld is + + -- function kSignatureRegRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kMinorRevRegRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kMajorRevRegRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kBuildCodeLSBRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kBuildCodeMSBRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kScratchRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kCpldControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kLmkControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kLoStatusRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kMykonosControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kPlScratchRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kPlCpldControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kTxCh1_IdleRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh1_0_IdleRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh1_1_IdleRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kTxCh1_TxOnRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh1_0_RxOnRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh1_1_RxOnRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kTxCh2_IdleRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh2_0_IdleRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh2_1_IdleRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kTxCh2_TxOnRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh2_0_RxOnRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRxCh2_1_RxOnRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgSetup.vhd b/fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgSetup.vhd new file mode 100644 index 000000000..e19358912 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgSetup.vhd @@ -0,0 +1,259 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgSetup.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 22 September 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: GPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Default values for front end config and CPLD constants. +-- +-- Contains the revision constants that must be bumped when the CPLD is updated. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgMgCpld.all; + +package PkgSetup is + + + constant kRdWtWidth : integer := 1; + constant kAddrWidth : integer := 7; + constant kDataWidth : integer := 16; + constant kTotalWidth : integer := kRdWtWidth + kAddrWidth + kDataWidth; + + subtype InterfaceData_t is std_logic_vector(kDataWidth-1 downto 0); + + constant kSignature : InterfaceData_t := x"CAFE"; + + + -- UPDATE THESE REVISIONS when making changes to the CPLD ----------------------------- + -- ------------------------------------------------------------------------------------ + constant kMinorRev : InterfaceData_t := std_logic_vector(to_unsigned(0,kDataWidth)); + constant kMajorRev : InterfaceData_t := std_logic_vector(to_unsigned(5,kDataWidth)); + -- Currently just the timestamp of the build time/date: yymmddhh + constant kBuildCode : std_logic_vector(31 downto 0) := X"18010408"; + + + function kTxChDefault return InterfaceData_t; + function kTxChDefaultRun return InterfaceData_t; + function kRxChDefault0 return InterfaceData_t; + function kRxChDefault1 return InterfaceData_t; + function kRxChDefault0Run return InterfaceData_t; + function kRxChDefault1Run return InterfaceData_t; + + function Tx2Switch2Mod(kCh1Val : std_logic_vector) return std_logic_vector; + function Tx2TrxMod (kCh1Val : std_logic_vector) return std_logic_vector; + + function Rx2Switch1Mod(kCh1Val : std_logic_vector) return std_logic_vector; + function Rx2Switch2Mod(kCh1Val : std_logic_vector) return std_logic_vector; + function Rx2Switch3Mod(kCh1Val : std_logic_vector) return std_logic_vector; + function Rx2Switch4Mod(kCh1Val : std_logic_vector) return std_logic_vector; + function Rx2Switch5Mod(kCh1Val : std_logic_vector) return std_logic_vector; + function Rx2Switch6Mod(kCh1Val : std_logic_vector) return std_logic_vector; + + +end package; + +package body PkgSetup is + + function kTxChDefault return InterfaceData_t is + variable RetVal : InterfaceData_t := (others => '0'); + begin + RetVal(kCh1SwTrxMsb downto kCh1SwTrx) := std_logic_vector(to_unsigned(kFromLowerFilterBankTxSw1, kCh1SwTrxSize)); + RetVal(kCh1TxSw1Msb downto kCh1TxSw1) := std_logic_vector(to_unsigned(kShutdownTxSw1, kCh1TxSw1Size)); + RetVal(kCh1TxSw2Msb downto kCh1TxSw2) := std_logic_vector(to_unsigned(kToTxFilterLp3400MHz, kCh1TxSw2Size)); + RetVal(kCh1TxSw3 downto kCh1TxSw3) := std_logic_vector(to_unsigned(kToTxFilterBanks, kCh1TxSw3Size)); + RetVal(kCh1TxLowbandMixerPathSelect) := '0'; + RetVal(kCh1TxMixerEn) := '0'; + RetVal(kCh1TxAmpEn) := '0'; + RetVal(kCh1TxPaEn) := '0'; + RetVal(kCh1TxLed) := '0'; + RetVal(kCh1MykEnTx) := '1'; + return RetVal; + end kTxChDefault; + + function kTxChDefaultRun return InterfaceData_t is + variable RetVal : InterfaceData_t := (others => '0'); + begin + RetVal(kCh1SwTrxMsb downto kCh1SwTrx) := std_logic_vector(to_unsigned(kFromLowerFilterBankTxSw1, kCh1SwTrxSize)); + RetVal(kCh1TxSw1Msb downto kCh1TxSw1) := std_logic_vector(to_unsigned(kFromTxFilterLp3400MHz, kCh1TxSw1Size)); + RetVal(kCh1TxSw2Msb downto kCh1TxSw2) := std_logic_vector(to_unsigned(kToTxFilterLp3400MHz, kCh1TxSw2Size)); + RetVal(kCh1TxSw3 downto kCh1TxSw3) := std_logic_vector(to_unsigned(kToTxFilterBanks, kCh1TxSw3Size)); + RetVal(kCh1TxLowbandMixerPathSelect) := '0'; + RetVal(kCh1TxMixerEn) := '0'; + RetVal(kCh1TxAmpEn) := '1'; + RetVal(kCh1TxPaEn) := '1'; + RetVal(kCh1TxLed) := '1'; + RetVal(kCh1MykEnTx) := '1'; + return RetVal; + end kTxChDefaultRun; + + + + + function kRxChDefault0 return InterfaceData_t is + variable RetVal : InterfaceData_t := (others => '0'); + begin + RetVal(kCh1RxSw1Msb downto kCh1RxSw1) := std_logic_vector(to_unsigned(kRx2Input, kCh1RxSw1Size)); + RetVal(kCh1RxSw2Msb downto kCh1RxSw2) := std_logic_vector(to_unsigned(kShutdownSw2, kCh1RxSw2Size)); + RetVal(kCh1RxSw3Msb downto kCh1RxSw3) := std_logic_vector(to_unsigned(kShutdownSw3, kCh1RxSw3Size)); + RetVal(kCh1RxSw4Msb downto kCh1RxSw4) := std_logic_vector(to_unsigned(kFilter2100x2850MHzFrom, kCh1RxSw4Size)); + RetVal(kCh1RxSw5Msb downto kCh1RxSw5) := std_logic_vector(to_unsigned(kFilter0490LpMHzFrom, kCh1RxSw5Size)); + return RetVal; + end kRxChDefault0; + + function kRxChDefault1 return InterfaceData_t is + variable RetVal : InterfaceData_t := (others => '0'); + begin + RetVal(kCh1RxSw6Msb downto kCh1RxSw6) := std_logic_vector(to_unsigned(kUpperFilterBankFromSwitch4, kCh1RxSw6Size)); + RetVal(kCh1RxLowbandMixerPathSelect) := '0'; + RetVal(kCh1RxMixerEn) := '0'; + RetVal(kCh1RxAmpEn) := '0'; + RetVal(kCh1RxLna1En) := '0'; + RetVal(kCh1RxLna2En) := '0'; + RetVal(kCh1Rx2Led) := '0'; + RetVal(kCh1RxLed) := '0'; + RetVal(kCh1MykEnRx) := '1'; + return RetVal; + end kRxChDefault1; + + function kRxChDefault0Run return InterfaceData_t is + variable RetVal : InterfaceData_t := (others => '0'); + begin + RetVal(kCh1RxSw1Msb downto kCh1RxSw1) := std_logic_vector(to_unsigned(kRx2Input, kCh1RxSw1Size)); + RetVal(kCh1RxSw2Msb downto kCh1RxSw2) := std_logic_vector(to_unsigned(kLowerFilterBankToSwitch3, kCh1RxSw2Size)); + RetVal(kCh1RxSw3Msb downto kCh1RxSw3) := std_logic_vector(to_unsigned(kFilter2100x2850MHz, kCh1RxSw3Size)); + RetVal(kCh1RxSw4Msb downto kCh1RxSw4) := std_logic_vector(to_unsigned(kFilter2100x2850MHzFrom, kCh1RxSw4Size)); + RetVal(kCh1RxSw5Msb downto kCh1RxSw5) := std_logic_vector(to_unsigned(kFilter0490LpMHzFrom, kCh1RxSw5Size)); + return RetVal; + end kRxChDefault0Run; + + function kRxChDefault1Run return InterfaceData_t is + variable RetVal : InterfaceData_t := (others => '0'); + begin + RetVal(kCh1RxSw6Msb downto kCh1RxSw6) := std_logic_vector(to_unsigned(kUpperFilterBankFromSwitch4, kCh1RxSw6Size)); + RetVal(kCh1RxLowbandMixerPathSelect) := '0'; + RetVal(kCh1RxMixerEn) := '0'; + RetVal(kCh1RxAmpEn) := '1'; + RetVal(kCh1RxLna1En) := '1'; + RetVal(kCh1RxLna2En) := '1'; + RetVal(kCh1Rx2Led) := '1'; -- turn on a LED for grins + RetVal(kCh1RxLed) := '0'; + RetVal(kCh1MykEnRx) := '1'; + return RetVal; + end kRxChDefault1Run; + + + + + + + function Tx2Switch2Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is one-hot, so we just flip around the bits here. + RetVal(kCh1Val'low + 0) := kCh1Val(kCh1Val'low + 0); + RetVal(kCh1Val'low + 3) := kCh1Val(kCh1Val'low + 1); + RetVal(kCh1Val'low + 1) := kCh1Val(kCh1Val'low + 2); + RetVal(kCh1Val'low + 2) := kCh1Val(kCh1Val'low + 3); + return RetVal; + end Tx2Switch2Mod; + + function Tx2TrxMod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + if kCh1Val = "00" then RetVal := "00"; + elsif kCh1Val = "01" then RetVal := "10"; + elsif kCh1Val = "10" then RetVal := "01"; + elsif kCh1Val = "11" then RetVal := "11"; + else RetVal := "00"; end if; + return RetVal; + end Tx2TrxMod; + + + + function Rx2Switch1Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is binary, so we need to mux. + if kCh1Val = "00" then RetVal := "01"; + elsif kCh1Val = "01" then RetVal := "00"; + elsif kCh1Val = "10" then RetVal := "11"; + elsif kCh1Val = "11" then RetVal := "10"; + else RetVal := "00"; end if; + return RetVal; + end Rx2Switch1Mod; + + function Rx2Switch2Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is binary, so we need to mux. + if kCh1Val = "00" then RetVal := "00"; + elsif kCh1Val = "01" then RetVal := "11"; + elsif kCh1Val = "10" then RetVal := "10"; + elsif kCh1Val = "11" then RetVal := "01"; + else RetVal := "00"; end if; + return RetVal; + end Rx2Switch2Mod; + + function Rx2Switch3Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is binary, so we need to mux. + if kCh1Val = "000" then RetVal := "100"; + elsif kCh1Val = "001" then RetVal := "101"; + elsif kCh1Val = "010" then RetVal := "110"; + elsif kCh1Val = "011" then RetVal := "011"; + elsif kCh1Val = "100" then RetVal := "001"; + elsif kCh1Val = "101" then RetVal := "000"; + elsif kCh1Val = "110" then RetVal := "010"; + elsif kCh1Val = "111" then RetVal := "111"; + else RetVal := "000"; end if; + return RetVal; + end Rx2Switch3Mod; + + function Rx2Switch4Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is one-hot, so we just flip around the bits here. + RetVal(kCh1Val'low + 2) := kCh1Val(kCh1Val'low + 0); + RetVal(kCh1Val'low + 1) := kCh1Val(kCh1Val'low + 1); + RetVal(kCh1Val'low + 0) := kCh1Val(kCh1Val'low + 2); + return RetVal; + end Rx2Switch4Mod; + + function Rx2Switch5Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is one-hot, so we just flip around the bits here. + RetVal(kCh1Val'low + 1) := kCh1Val(kCh1Val'low + 0); + RetVal(kCh1Val'low + 0) := kCh1Val(kCh1Val'low + 1); + RetVal(kCh1Val'low + 3) := kCh1Val(kCh1Val'low + 2); + RetVal(kCh1Val'low + 2) := kCh1Val(kCh1Val'low + 3); + return RetVal; + end Rx2Switch5Mod; + + function Rx2Switch6Mod(kCh1Val : std_logic_vector) return std_logic_vector is + variable RetVal : std_logic_vector(kCh1Val'range) := (others => '0'); + begin + -- Encoding for this switch is one-hot, so we just flip around the bits here. + RetVal(kCh1Val'low + 2) := kCh1Val(kCh1Val'low + 0); + RetVal(kCh1Val'low + 1) := kCh1Val(kCh1Val'low + 1); + RetVal(kCh1Val'low + 0) := kCh1Val(kCh1Val'low + 2); + return RetVal; + end Rx2Switch6Mod; + + +end package body;
\ No newline at end of file diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/Timing.sdc b/fpga/usrp3/top/n3xx/dboards/mg/cpld/Timing.sdc new file mode 100644 index 000000000..496814662 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/Timing.sdc @@ -0,0 +1,160 @@ +# +# Copyright 2017 Ettus Research, A National Instruments Company +# SPDX-License-Identifier: LGPL-3.0 +# + +# All the magic numbers come from the "/n3xx/dboards/mg/doc/mg_timing.xlsx" timing +# analysis spreadsheet. Analysis should be re-performed every time a board rev occurs +# that affects the CPLD interfaces. + +## PS Slave Constraints ################################################################# +# - PsClk Rate +# - PsClk to SDI +# - PsClk to LE (sync and async paths) +# - PsClk to SDO + +# Maximum 4 MHz clock rate! This is heavily limited by the read data turnaround time... +# and could be up to 20 MHz if only performing writes. +create_clock -name PsClk -period 250 [get_ports {PsSpiSck}] + +# SDI is both registered in the CPLD and used as a direct passthrough. First constrain +# the input delay on the local paths inside the CPLD. Passthrough constraints +# are handled elsewhere. + +set PsSdiInputDelayMax 22.303 +set PsSdiInputDelayMin -19.019 + +# SDI is driven from the PS on the falling edge of the Clk. Worst-case data-clock skew +# is around +/-20ns due to FPGA routing delays and board buffering. Complete timing +# analysis is performed and recorded elsewhere. +set_input_delay -clock PsClk -max $PsSdiInputDelayMax [get_ports sPsSpiSdi] -clock_fall +set_input_delay -clock PsClk -min $PsSdiInputDelayMin [get_ports sPsSpiSdi] -clock_fall + +# For the CPLD Cs_n, the latch enable is used both as an asynchronous reset and +# synchronously to latch data. First, constrain the overall input delay for sync use. +# Technically, Cs_n is asserted and de-asserted many nanoseconds before the clock arrives +# but we still constrain it identically to the SDI in case something goes amiss. +set_input_delay -clock PsClk -max $PsSdiInputDelayMax [get_ports sPsSpiLe] -clock_fall +set_input_delay -clock PsClk -min $PsSdiInputDelayMin [get_ports sPsSpiLe] -clock_fall +# Then set a false path only on the async reset flops. +set_false_path -from [get_ports {sPsSpiLe}] -to [get_pins sPsMosiIndex[*]|*] +set_false_path -from [get_ports {sPsSpiLe}] -to [get_pins sPsMisoIndex[*]|*] + +# Constrain MISO as snugly as possible through the CPLD without making the tools work +# too hard. At a 200 ns period, this sets the clock-to-out for the CPLD at [10, 65]ns. +# Math for Max = T_clk/2 - 60 = 250/2 - 60 = 65 ns. +set PsSdoOutputDelayMax 60 +set PsSdoOutputDelayMin -10 + +set_output_delay -clock PsClk -max $PsSdoOutputDelayMax [get_ports sPsSpiSdo] +set_output_delay -clock PsClk -min $PsSdoOutputDelayMin [get_ports sPsSpiSdo] + + + +## PL Slave Constraints ################################################################# +# - PlClk Rate +# - PlClk to SDI +# - PlClk to LE (sync and async paths) +# - PlClk to SDO + +# Maximum 5 MHz clock rate! +create_clock -name PlClk -period 200 [get_ports {PlSpiSck}] + +# SDI is both registered in the CPLD and used as a direct passthrough. First constrain +# the input delay on the local paths inside the CPLD. Passthrough constraints +# are handled elsewhere. + +set PlSdiInputDelayMax 10.445 +set PlSdiInputDelayMin -10.378 + +# SDI is driven from the FPGA on the falling edge of the Clk. Worst-case data-clock skew +# is around +/-10ns. Complete timing analysis is performed and recorded elsewhere. +set_input_delay -clock PlClk -max $PlSdiInputDelayMax [get_ports lPlSpiSdi] -clock_fall +set_input_delay -clock PlClk -min $PlSdiInputDelayMin [get_ports lPlSpiSdi] -clock_fall + +# For the CPLD Cs_n, the latch enable is used both as an asynchronous reset and +# synchronously to latch data. First, constrain the overall input delay for sync use. +# Technically, Cs_n is asserted and de-asserted many nanoseconds before the clock arrives +# but we still constrain it identically to the SDI in case something goes amiss. +set_input_delay -clock PlClk -max $PlSdiInputDelayMax [get_ports lPlSpiLe] -clock_fall +set_input_delay -clock PlClk -min $PlSdiInputDelayMin [get_ports lPlSpiLe] -clock_fall +# Then set a false path only on the async reset flops. +set_false_path -from [get_ports {lPlSpiLe}] -to [get_pins {lPlMosiIndex[*]|*}] +set_false_path -from [get_ports {lPlSpiLe}] -to [get_pins {lPlMisoIndex[*]|*}] + +# Constrain MISO as snugly as possible through the CPLD without making the tools work +# too hard. At a 200 ns period, this sets the clock-to-out for the CPLD at [10, 65]ns. +# Math for Max = T_clk/2 - 35 = 200/2 - 35 = 65 ns. +set PlSdoOutputDelayMax 35 +set PlSdoOutputDelayMin -10 + +set_output_delay -clock PlClk -max $PlSdoOutputDelayMax [get_ports lPlSpiSdo] +set_output_delay -clock PlClk -min $PlSdoOutputDelayMin [get_ports lPlSpiSdo] + + + +## Passthrough Constraints ############################################################## +# - LMK SYNC +# - PlClk/PsClk passthrough +# - SDI passthrough for both +# - SDO return mux passthrough for both +# - Cs_n passthrough for both + +# LMK Sync Passthrough: constrain min and max delays for output +set_max_delay -from [get_ports {aPlSpiAddr[2]}] -to [get_ports {aLmkSync}] 17 +set_min_delay -from [get_ports {aPlSpiAddr[2]}] -to [get_ports {aLmkSync}] 2 + +# SPI Passthroughs: constrain min and max delays for outputs and inputs. +# Since the SDI ports have input delays pre-defined above, we have to remove those from +# the delay analysis here by adding the input delay to the constraint. +# Similarly, for the SDO pins add the output delay to the constraint. +set SpiMaxDelay 25 +set SpiMinDelay 5 + +# PS +set_max_delay -to [get_ports {aDacDin aLmkSpiSdio}] [expr $PsSdiInputDelayMax + $SpiMaxDelay] +set_min_delay -to [get_ports {aDacDin aLmkSpiSdio}] [expr $PsSdiInputDelayMin + $SpiMinDelay] +set_max_delay -to [get_ports {aDacSync_n aLmkSpiCs_n}] $SpiMaxDelay +set_min_delay -to [get_ports {aDacSync_n aLmkSpiCs_n}] $SpiMinDelay +set_max_delay -to [get_ports {aDacSck aLmkSpiSck}] $SpiMaxDelay +set_min_delay -to [get_ports {aDacSck aLmkSpiSck}] $SpiMinDelay +set_max_delay -from [get_ports {aLmkClkinSel*}] [expr $SpiMaxDelay + $PsSdoOutputDelayMax] +set_min_delay -from [get_ports {aLmkClkinSel*}] [expr $SpiMinDelay + $PsSdoOutputDelayMin] + +# PL +set_max_delay -to [get_ports {aRxLoDin aTxLoDin}] [expr $PlSdiInputDelayMax + $SpiMaxDelay] +set_min_delay -to [get_ports {aRxLoDin aTxLoDin}] [expr $PlSdiInputDelayMin + $SpiMinDelay] +set_max_delay -to [get_ports {aRxLoCs_n aTxLoCs_n}] $SpiMaxDelay +set_min_delay -to [get_ports {aRxLoCs_n aTxLoCs_n}] $SpiMinDelay +set_max_delay -to [get_ports {aRxLoSck aTxLoSck}] $SpiMaxDelay +set_min_delay -to [get_ports {aRxLoSck aTxLoSck}] $SpiMinDelay +set_max_delay -from [get_ports {aTxLoMuxOut aRxLoMuxOut}] [expr $SpiMaxDelay + $PlSdoOutputDelayMax] +set_min_delay -from [get_ports {aTxLoMuxOut aRxLoMuxOut}] [expr $SpiMinDelay + $PlSdoOutputDelayMin] + + + +## Async Inputs ######################################################################### +# aLmkStatus2 aRxLoLockDetect aTxLoLockDetect +set_false_path -from [get_ports {aRxLoLockDetect}] +set_false_path -from [get_ports {aTxLoLockDetect}] + + + +## Async Outputs ######################################################################## +# aMkReset_n aVcxoCtrl +set_false_path -to [get_ports {aMkReset_n}] +set_false_path -to [get_ports {aVcxoCtrl}] + + + +## Sync Front End Outputs ############################################################### +# All we need to do here is constrain for maximum path delay from the aAtr(Rx|Tx)(1|2) +# control bits toggling to the outputs for aCh1* and aCh2* toggling. Just in case the +# user attempts to write the ATR while it's in use, we also constrain from the flops +# to the pins... which covers all paths... so just to -to option is needed. +set_max_delay -to [get_ports {aCh1* aCh2* aMk*x*En}] 40 +set_min_delay -to [get_ports {aCh1* aCh2* aMk*x*En}] 5 + +# We don't care about the LED timing whatsoever. Let's not have them clogging up our +# precious timing paths. +set_false_path -to [get_ports {aCh*Led*}] diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qpf b/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qpf new file mode 100644 index 000000000..e16aaf0af --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition +# Date created = 14:51:27 February 24, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "16.1" +DATE = "14:51:27 February 24, 2017" + +# Revisions + +PROJECT_REVISION = "TopCpld" diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qsf b/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qsf new file mode 100644 index 000000000..64238c87a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qsf @@ -0,0 +1,313 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition +# Date created = 14:51:27 February 24, 2017 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# TopCpld_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus Prime software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "MAX V" +set_global_assignment -name DEVICE 5M570ZF256I5 +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 16.1.2 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "14:51:27 FEBRUARY 24, 2017" +set_global_assignment -name LAST_QUARTUS_VERSION "16.1.2 Lite Edition" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 125 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1" +set_global_assignment -name SDC_FILE Timing.sdc +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR" +set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF +set_global_assignment -name ENABLE_OCT_DONE OFF +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name USE_CONFIGURATION_DEVICE ON +set_global_assignment -name GENERATE_SVF_FILE ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" + +set_location_assignment PIN_C3 -to aCh2RxSw4[0] +set_location_assignment PIN_C2 -to aCh2TxPaEn +set_location_assignment PIN_D3 -to aCh2RxSw6[0] +set_location_assignment PIN_D1 -to aCh2RxSw4[1] +set_location_assignment PIN_D2 -to aCh2TxSw3 +set_location_assignment PIN_E1 -to aCh2RxSw4[2] +set_location_assignment PIN_E4 -to aCh2RxSw7[1] +set_location_assignment PIN_F2 -to aCh2RxSw6[1] +set_location_assignment PIN_E3 -to aCh2RxSw7[0] +set_location_assignment PIN_F1 -to aCh2RxSw5[0] +set_location_assignment PIN_E2 -to aCh2RxSw5[1] +set_location_assignment PIN_G2 -to aCh2RxSw5[3] +set_location_assignment PIN_F3 -to aCh2TxSw4[0] +set_location_assignment PIN_G1 -to aCh2RxSw6[2] +set_location_assignment PIN_G3 -to aCh2TxSw4[1] +set_location_assignment PIN_H2 -to aCh2TxAmpEn +set_location_assignment PIN_H1 -to aCh2RxSw5[2] +set_location_assignment PIN_J1 -to aCh2TxMixerEn +set_location_assignment PIN_H5 -to aLoSpiSync +set_location_assignment PIN_J2 -to aCh2RxMixerEn +#set_location_assignment PIN_L3 -to aLmkSpiSdio +set_location_assignment PIN_K1 -to aCh2TxSw5[1] +set_location_assignment PIN_K2 -to aCh2TxSw5[0] +set_location_assignment PIN_M2 -to aLmkSpiSdio +set_location_assignment PIN_L1 -to aCh2RxSw8[0] +set_location_assignment PIN_M3 -to lPlSpiSdi +set_location_assignment PIN_L2 -to aCh2RxSw8[1] +set_location_assignment PIN_M1 -to aCh2RxAmpEn +set_location_assignment PIN_N2 -to aLmkSpiSck +set_location_assignment PIN_N1 -to aLmkSpiCs_n +set_location_assignment PIN_N3 -to PlSpiSck +# set_location_assignment PIN_P2 -to lPlSpiLe +set_location_assignment PIN_R3 -to aMkReset_n +set_location_assignment PIN_R1 -to lPlSpiLe +set_location_assignment PIN_T2 -to aLmkSync +set_location_assignment PIN_R4 -to aVcxoCtrl +set_location_assignment PIN_T4 -to aDacDin +set_location_assignment PIN_T5 -to aDacSync_n +set_location_assignment PIN_R6 -to aPlSpiAddr[2] +set_location_assignment PIN_R5 -to aDacSck +set_location_assignment PIN_T6 -to aPlSpiAddr[1] +set_location_assignment PIN_R7 -to aLmkClkinSel[0] +set_location_assignment PIN_T7 -to lPlSpiSdo +set_location_assignment PIN_P8 -to sPsSpiLe +set_location_assignment PIN_R8 -to aPsSpiAddr[1] +set_location_assignment PIN_P9 -to aPlSpiAddr[0] +set_location_assignment PIN_T8 -to PsSpiSck +set_location_assignment PIN_T9 -to aPsSpiAddr[0] +set_location_assignment PIN_R9 -to sPsSpiSdi +set_location_assignment PIN_P10 -to aAtrRx1 +set_location_assignment PIN_T10 -to sPsSpiSdo +set_location_assignment PIN_P11 -to aAtrTx2 +set_location_assignment PIN_R10 -to aRxLoLockDetect +set_location_assignment PIN_R12 -to aRxLoSck +set_location_assignment PIN_T11 -to aTxLoLockDetect +set_location_assignment PIN_P12 -to aAtrRx2 +set_location_assignment PIN_R11 -to aRxLoDin +set_location_assignment PIN_T12 -to aRxLoCs_n +set_location_assignment PIN_R13 -to aTxLoDin +set_location_assignment PIN_T13 -to aRxLoMuxOut +set_location_assignment PIN_P13 -to aAtrTx1 +set_location_assignment PIN_T15 -to aTxLoSck +set_location_assignment PIN_R14 -to aTxLoCs_n +set_location_assignment PIN_R16 -to aTxLoMuxOut +set_location_assignment PIN_P14 -to aMkTx1En +set_location_assignment PIN_N15 -to aMkRx2En +set_location_assignment PIN_P15 -to aMkRx1En +set_location_assignment PIN_N16 -to aMkTx2En +set_location_assignment PIN_K15 -to aCh1TxSw5[1] +set_location_assignment PIN_L14 -to aCh1RxMixerEn +set_location_assignment PIN_K16 -to aCh1TxMixerEn +set_location_assignment PIN_K14 -to aCh1RxSw8[0] +set_location_assignment PIN_J15 -to aCh1TxAmpEn +set_location_assignment PIN_J14 -to aCh1RxSw8[1] +set_location_assignment PIN_J16 -to aCh1TxSw5[0] +set_location_assignment PIN_H14 -to aCh1RxAmpEn +set_location_assignment PIN_H16 -to aCh1TxSw4[0] +set_location_assignment PIN_G14 -to aCh1TxSw4[1] +set_location_assignment PIN_H15 -to aCh1RxSw5[1] +set_location_assignment PIN_F14 -to aCh1RxSw7[1] +set_location_assignment PIN_G16 -to aCh1RxSw5[0] +set_location_assignment PIN_G15 -to aCh1RxSw4[0] +set_location_assignment PIN_E14 -to aCh1RxSw6[1] +set_location_assignment PIN_F16 -to aCh1RxSw2[1] +set_location_assignment PIN_E13 -to aCh1RxSw7[0] +set_location_assignment PIN_F15 -to aCh1RxSw2[0] +set_location_assignment PIN_D14 -to aCh1RxSw6[2] +set_location_assignment PIN_E16 -to aCh1RxSw6[0] +set_location_assignment PIN_E15 -to aCh1TxSw3 +set_location_assignment PIN_C15 -to aCh1RxSw5[2] +set_location_assignment PIN_D16 -to aCh1TxPaEn +set_location_assignment PIN_C14 -to aCh1RxSw4[1] +set_location_assignment PIN_D15 -to aCh1RxSw5[3] +set_location_assignment PIN_B14 -to aCh1TxSw2[3] +set_location_assignment PIN_B16 -to aCh1RxLna2En +set_location_assignment PIN_C13 -to aCh1RxSw4[2] +set_location_assignment PIN_A15 -to aCh1TxSw2[2] +set_location_assignment PIN_B13 -to aCh1TxSw2[1] +set_location_assignment PIN_A13 -to aCh1TxSw2[0] +set_location_assignment PIN_C12 -to aCh1RxSw1[0] +set_location_assignment PIN_B12 -to aCh1TxSw1[0] +set_location_assignment PIN_D12 -to aCh1RxSw1[1] +set_location_assignment PIN_A12 -to aCh1TxSw1[1] +set_location_assignment PIN_C11 -to aCh1LedTx +set_location_assignment PIN_B11 -to aCh1RxLna1En +set_location_assignment PIN_D11 -to aCh2RxSw1[1] +set_location_assignment PIN_A11 -to aCh1RxSw3[2] +set_location_assignment PIN_C10 -to aCh1LedRx +set_location_assignment PIN_B10 -to aCh1RxSw3[1] +set_location_assignment PIN_C9 -to aCh1LedRx2 +set_location_assignment PIN_A10 -to aCh1RxSw3[0] +set_location_assignment PIN_C8 -to aCh2LedRx2 +set_location_assignment PIN_B9 -to aCh1SwTrx[1] +set_location_assignment PIN_A9 -to aCh1SwTrx[0] +set_location_assignment PIN_A8 -to aCh2SwTrx[0] +set_location_assignment PIN_C7 -to aCh2RxSw3[0] +set_location_assignment PIN_B8 -to aCh2SwTrx[1] +set_location_assignment PIN_C6 -to aCh2LedRx +set_location_assignment PIN_A7 -to aCh2RxSw3[1] +set_location_assignment PIN_B5 -to aCh2TxSw1[0] +set_location_assignment PIN_C5 -to aCh2RxSw1[0] +set_location_assignment PIN_A6 -to aCh2TxSw1[1] +set_location_assignment PIN_D5 -to aCh2LedTx +set_location_assignment PIN_B6 -to aCh2RxSw3[2] +set_location_assignment PIN_B4 -to aCh2RxLna2En +set_location_assignment PIN_A5 -to aCh2RxLna1En +set_location_assignment PIN_C4 -to aCh2RxSw2[0] +set_location_assignment PIN_A4 -to aCh2TxSw2[1] +set_location_assignment PIN_D4 -to aCh2RxSw2[1] +set_location_assignment PIN_A2 -to aCh2TxSw2[3] +set_location_assignment PIN_B3 -to aCh2TxSw2[0] +set_location_assignment PIN_B1 -to aCh2TxSw2[2] + +set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 256 +set_global_assignment -name GENERATE_JAM_FILE ON +set_global_assignment -name GENERATE_JBC_FILE ON +set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "AS INPUT TRI-STATED" +set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw4[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxPaEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw6[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw4[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw3 +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw7[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw4[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw6[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw7[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw5[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw5[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw4[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw5[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw6[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw4[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxAmpEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw5[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxMixerEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxMixerEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw5[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw5[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aLmkSpiSdio +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw8[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw8[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxAmpEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aLmkSpiSck +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aLmkSpiCs_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aMkReset_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aLmkSync +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aVcxoCtrl +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aDacDin +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aDacSync_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aDacSck +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to lPlSpiSdo +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to sPsSpiSdo +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aRxLoSck +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aRxLoDin +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aRxLoCs_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aTxLoDin +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aTxLoSck +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aTxLoCs_n +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aMkTx1En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aMkRx2En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aMkRx1En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aMkTx2En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxMixerEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw5[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxMixerEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw8[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxAmpEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw8[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw5[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxAmpEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw4[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw4[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw5[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw7[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw4[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw5[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw6[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw2[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw7[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw2[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw6[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw6[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw3 +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw5[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxPaEn +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw4[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw5[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw2[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw4[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxLna2En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw2[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw2[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw2[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw1[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw1[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw1[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1TxSw1[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1LedTx +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxLna1En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw1[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw3[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1LedRx +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw3[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1LedRx2 +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1RxSw3[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2LedRx2 +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1SwTrx[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh1SwTrx[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2SwTrx[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw3[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2SwTrx[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2LedRx +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw3[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw1[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw1[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw1[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2LedTx +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw3[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxLna2En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxLna1En +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw2[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw2[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2RxSw2[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw2[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw2[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to aCh2TxSw2[2] +set_global_assignment -name SEED 11 +set_global_assignment -name VHDL_FILE PkgMgCpld.vhd +set_global_assignment -name VHDL_FILE PkgSetup.vhd +set_global_assignment -name VHDL_FILE TopCpld.vhd +set_global_assignment -name TOP_LEVEL_ENTITY TopCpld diff --git a/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.vhd b/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.vhd new file mode 100644 index 000000000..4e3488f54 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.vhd @@ -0,0 +1,1228 @@ +------------------------------------------------------------------------------- +-- +-- File: TopCpld.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 24 October 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: GPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Top level file for the Magnesium CPLD. +-- +-- This file instantiates two SPI slave ports. One slave port comes from the PS +-- of the motherboard Zynq. It has three slave select pins, mapped as follows: +-- sPlsSpiLe = CPLD Internal Registers +-- aPsSpiAddr(0) = LMK Endpoint +-- aPsSpiAddr(1) = Phase DAC Endpoint +-- +-- The other slave port comes from the PL of the motherboard Zynq. It also has +-- three slave select pins: +-- lPlSpiLe = CPLD Internal Registers +-- aPlSpiAddr(0) = TX Lowband LO +-- aPlSpiAddr(1) = RX Lowband LO +-- +-- The final address line for the PL slave is used as a passthrough for the LMK +-- SYNC pin. +-- +-- +-- For either SPI interface, the CPLD has internal registers that can be addressed +-- whenever the appropriate slave select is driven asserted. These register groups +-- are completely independent from one another, meaning the PS SPI interface cannot +-- access the PL registers, and vice-versa. +-- +-- See the register interface XML at the bottom of this file for details on how +-- each SPI port is expected to be driven, and for the register maps for the PS +-- and PL slaves. +-- +-- +-- BUMPING THE REVISION: +-- In PkgSetup the kMinorRev and kMajorRev are defined. Whenever a change +-- is made to the CPLD, no matter how small, bump the kMinorRev value. If this change +-- breaks compatibility with current HW or SW drivers, increment the kMajorRev value +-- and reset the kMinorRev to zero. Similarly, there is a constant to define the build +-- code, kBuildCode. Currently this is simply the year, month, day, and hour the CPLD is +-- built, but could be user-definable. +-- +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + use ieee.math_real.all; + +library work; + use work.PkgMgCpld.all; + use work.PkgSetup.all; + +entity TopCpld is + port( + + -- SPI Port Incoming from FPGA -- + PlSpiSck : in std_logic; + lPlSpiSdi : in std_logic; + lPlSpiSdo : out std_logic; + lPlSpiLe : in std_logic; + aPlSpiAddr : in std_logic_vector(2 downto 0); + + -- SPI Port Incoming from PS -- + PsSpiSck : in std_logic; + sPsSpiSdi : in std_logic; + sPsSpiSdo : out std_logic; + sPsSpiLe : in std_logic; + aPsSpiAddr : in std_logic_vector(1 downto 0); + + -- ATR bits from FPGA -- + aAtrRx1 : in std_logic; + aAtrRx2 : in std_logic; + aAtrTx1 : in std_logic; + aAtrTx2 : in std_logic; + + -- Ch 1 TX (15 bits) -- + aCh1LedTx : out std_logic; + + aCh1TxPaEn : out std_logic; + aCh1TxAmpEn : out std_logic; + aCh1TxMixerEn : out std_logic; + + aCh1TxSw1 : out std_logic_vector(1 downto 0); + aCh1TxSw2 : out std_logic_vector(3 downto 0); + aCh1TxSw3 : out std_logic; + aCh1TxSw4 : out std_logic_vector(1 downto 0); + aCh1TxSw5 : out std_logic_vector(1 downto 0); + + -- Ch 1 RX (29 bits) -- + aCh1LedRx : out std_logic; + aCh1LedRx2 : out std_logic; + + aCh1RxAmpEn : out std_logic; + aCh1RxMixerEn : out std_logic; + aCh1RxLna1En : out std_logic; + aCh1RxLna2En : out std_logic; + aCh1SwTrx : out std_logic_vector(1 downto 0); + + aCh1RxSw1 : out std_logic_vector(1 downto 0); + aCh1RxSw2 : out std_logic_vector(1 downto 0); + aCh1RxSw3 : out std_logic_vector(2 downto 0); + aCh1RxSw4 : out std_logic_vector(2 downto 0); + aCh1RxSw5 : out std_logic_vector(3 downto 0); + aCh1RxSw6 : out std_logic_vector(2 downto 0); + aCh1RxSw7 : out std_logic_vector(1 downto 0); + aCh1RxSw8 : out std_logic_vector(1 downto 0); + + -- Ch 2 TX -- + aCh2LedTx : out std_logic; + + aCh2TxPaEn : out std_logic; + aCh2TxAmpEn : out std_logic; + aCh2TxMixerEn : out std_logic; + + aCh2TxSw1 : out std_logic_vector(1 downto 0); + aCh2TxSw2 : out std_logic_vector(3 downto 0); + aCh2TxSw3 : out std_logic; + aCh2TxSw4 : out std_logic_vector(1 downto 0); + aCh2TxSw5 : out std_logic_vector(1 downto 0); + + -- Ch 2 RX -- + aCh2LedRx : out std_logic; + aCh2LedRx2 : out std_logic; + + aCh2RxAmpEn : out std_logic; + aCh2RxMixerEn : out std_logic; + aCh2RxLna1En : out std_logic; + aCh2RxLna2En : out std_logic; + aCh2SwTrx : out std_logic_vector(1 downto 0); + + aCh2RxSw1 : out std_logic_vector(1 downto 0); + aCh2RxSw2 : out std_logic_vector(1 downto 0); + aCh2RxSw3 : out std_logic_vector(2 downto 0); + aCh2RxSw4 : out std_logic_vector(2 downto 0); + aCh2RxSw5 : out std_logic_vector(3 downto 0); + aCh2RxSw6 : out std_logic_vector(2 downto 0); + aCh2RxSw7 : out std_logic_vector(1 downto 0); + aCh2RxSw8 : out std_logic_vector(1 downto 0); + + -- LMK -- + aLmkSpiSdio : out std_logic; + aLmkSpiSck : out std_logic; + aLmkSpiCs_n : out std_logic; + aLmkClkinSel : in std_logic_vector(0 downto 0); -- SDO + aLmkSync : out std_logic; -- direct connect to aPlSpiAddr(2) + + -- Phase DAC -- + aDacDin : out std_logic; + aDacSync_n : out std_logic; + aDacSck : out std_logic; + aVcxoCtrl : out std_logic; -- @PS-REG-WR + + -- RX and TX LOs -- (timed) + aLoSpiSync : in std_logic; -- Clock! (unused atm, only for reclocking + aRxLoSck : out std_logic; -- the SPI bus if needed for sync) + aRxLoDin : out std_logic; + aRxLoCs_n : out std_logic; + aRxLoMuxOut : in std_logic; + aRxLoLockDetect : in std_logic; -- @PS-REG-RD + aTxLoSck : out std_logic; + aTxLoDin : out std_logic; + aTxLoCs_n : out std_logic; + aTxLoMuxOut : in std_logic; + aTxLoLockDetect : in std_logic; -- @PS-REG-RD + + -- Mykonos Interface -- + aMkReset_n : out std_logic; -- @PS-REG-WR + aMkRx1En : out std_logic; + aMkRx2En : out std_logic; + aMkTx1En : out std_logic; + aMkTx2En : out std_logic + + ); +end TopCpld; + + +architecture RTL of TopCpld is + + -- PS MOSI + signal sCpldPsSpiActive : boolean; + signal sPsMosiIndex : unsigned(integer(ceil(log2(real(kTotalWidth)))) downto 0); + signal sPsMosiBuffer : InterfaceData_t := (others => '0'); + signal sPsRd : boolean := false; + signal sPsRegAddr : unsigned(kAddrWidth-1 downto 0) := (others => '0'); + + -- PS MISO + signal sPsCpldMiso : std_logic; + signal sPsMisoIndex : unsigned(integer(ceil(log2(real(kTotalWidth)))) downto 0); + signal sPsMisoBuffer : std_logic_vector(kTotalWidth-1 downto 0); + + -- PS Register Signals + signal aRxLoLockDetect_ms, sRxLoLockDetect, + aTxLoLockDetect_ms, sTxLoLockDetect : std_logic := '0'; + signal sReset : boolean := false; + signal sScratchVal : InterfaceData_t := (others => '0'); + signal sVcxoControl : std_logic := '1'; + signal sMykonosReset : std_logic := '0'; + + -- PL MOSI + signal lCpldPlSpiActive : boolean; + signal lPlMosiIndex : unsigned(integer(ceil(log2(real(kTotalWidth)))) downto 0); + signal lPlMosiBuffer : InterfaceData_t := (others => '0'); + signal lPlRd : boolean := false; + signal lPlRegAddr : unsigned(kAddrWidth-1 downto 0) := (others => '0'); + + -- PL MISO + signal lPlCpldMiso : std_logic; + signal lPlMisoIndex : unsigned(integer(ceil(log2(real(kTotalWidth)))) downto 0); + signal lPlMisoBuffer : std_logic_vector(kTotalWidth-1 downto 0); + + -- PL Register Signals + signal lScratchVal : InterfaceData_t := (others => '0'); + signal lReset : boolean := false; + + -- See PkgSetup for each Default definition. + signal lTxCh1IdleReg : InterfaceData_t := kTxChDefault; + signal lTxCh2IdleReg : InterfaceData_t := kTxChDefault; + + signal lTxCh1TxOnReg : InterfaceData_t := kTxChDefaultRun; + signal lTxCh2TxOnReg : InterfaceData_t := kTxChDefaultRun; + + signal lRxCh1_0IdleReg : InterfaceData_t := kRxChDefault0; + signal lRxCh1_1IdleReg : InterfaceData_t := kRxChDefault1; + signal lRxCh2_0IdleReg : InterfaceData_t := kRxChDefault0; + signal lRxCh2_1IdleReg : InterfaceData_t := kRxChDefault1; + + signal lRxCh1_0RxOnReg : InterfaceData_t := kRxChDefault0Run; + signal lRxCh1_1RxOnReg : InterfaceData_t := kRxChDefault1Run; + signal lRxCh2_0RxOnReg : InterfaceData_t := kRxChDefault0Run; + signal lRxCh2_1RxOnReg : InterfaceData_t := kRxChDefault1Run; + + signal lTxCh1 : InterfaceData_t; + signal lTxCh2 : InterfaceData_t; + signal lRxCh1_0 : InterfaceData_t; + signal lRxCh1_1 : InterfaceData_t; + signal lRxCh2_0 : InterfaceData_t; + signal lRxCh2_1 : InterfaceData_t; + +begin + + + -- Direct Pass-through Pins : --------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + + -- LMK SYNC assignment for direct passthrough to LMK from SPI Addr line. + aLmkSync <= aPlSpiAddr(2); + + + + -- PS SPI Interface : ----------------------------------------------------------------- + -- Composed of a few modules: + -- 1) PsMosiIndex - generate pointer for MOSI Buffer + -- 2) PsMosiBuffer - actually implement the buffer, only when the CPLD is targeted. + -- 3) PsMosiProcessing - process the MOSI data: sort into Rd/!Wt, Address, and Data. + -- This process works on the falling edge of the clock to register the pieces + -- of the MOSI packet as they are complete. The final falling edge registers + -- the data into the individual registers, so it is critical that the clock idle + -- LOW after the transaction is complete such that this final falling edge occurs. + -- 4) PsMisoBuffer - generate pointer for the MISO buffer. The buffer itself is + -- completely async. + -- 5) PsMisoBufferMux - Mux all the register data back into the MISO buffer. + -- 6) StatusSynchronizer - double-synchronizers for status bits from the LMK and LOs. + -- ------------------------------------------------------------------------------------ + + -- Decode the PS SPI Address bits... which are actually going to be used as individual + -- chip selects coming from the PS. + sCpldPsSpiActive <= sPsSpiLe = '0'; + aLmkSpiCs_n <= aPsSpiAddr(0); + aDacSync_n <= aPsSpiAddr(1); + + -- Assign the remainder of the SPI lines to the LMK and DAC. + aLmkSpiSck <= PsSpiSck; + aLmkSpiSdio <= sPsSpiSdi; + aDacSck <= PsSpiSck; + aDacDin <= sPsSpiSdi; + + -- Output mux for data back to the FPGA (PS core). The LMK and CPLD are the only + -- endpoints that have readback enabled. + sPsSpiSdo <= aLmkClkinSel(0) when aPsSpiAddr(0) = '0' else + sPsCpldMiso; + + + + -- Use the LE signal (Cs_n) as the asynchronous reset to the shift register counter. + -- LE will hold the counter in reset until this endpoint is targeted, when it will + -- release the reset (long before the clock toggles) and allow the shift operation + -- to begin. + -- + -- !!! SAFE COUNTER STARTUP!!! + -- This counter starts safely from reset because the PsSpiSck will not start toggling + -- until long after the asynchronous reset (sCpldPsSpiActive) de-asserts. Similarly, + -- the reset will only assert long after the last clock edge is received. + PsMosiIndex : process(PsSpiSck, sCpldPsSpiActive) + begin + if not sCpldPsSpiActive then + sPsMosiIndex <= (others => '0'); + elsif rising_edge(PsSpiSck) then + sPsMosiIndex <= sPsMosiIndex + 1; + end if; + end process PsMosiIndex; + + + -- Shift in SDI (MOSI) data from the PS on the rising edge of the clock. Only use + -- synchronous resets from here on out. + PsMosiBuffer : process(PsSpiSck) + begin + if rising_edge(PsSpiSck) then + if sReset then + sPsMosiBuffer <= (others => '0'); + else + if sCpldPsSpiActive then + sPsMosiBuffer <= sPsMosiBuffer(sPsMosiBuffer'high-1 downto 0) & sPsSpiSdi; -- left shift + end if; + end if; + end if; + end process PsMosiBuffer; + + + -- As portions of the command and data packets become available, register them here + -- using the falling edge of the PS SPI clock. + PsMosiProcessing : process(PsSpiSck) + begin + if falling_edge(PsSpiSck) then + if sReset then + -- sReset is intentionally self-clearing. It clears on the first falling edge of + -- the next SPI transaction after it is set. Logic on the first rising edge of + -- that next transaction is therefore held in reset. This will not matter + -- as long as SW follows the recommended reset procedure (writing a '1' to reset + -- then writing a '0'), since the first bit of the transaction is '0' for a + -- write operation. + sReset <= false; + sScratchVal <= (others => '0'); + sVcxoControl <= '1'; + sMykonosReset <= '0'; + sPsRd <= false; + sPsRegAddr <= (others => '0'); + else + -- After the first bit is captured, we can determine if it is a write or read. + if (sPsMosiIndex = (kRdWtWidth)) then + sPsRd <= sPsMosiBuffer(0) = '1'; + end if; + + -- After the entire command word is captured, the address is ready for capture. + if (sPsMosiIndex = (kAddrWidth + kRdWtWidth)) then + sPsRegAddr <= unsigned(sPsMosiBuffer(kAddrWidth - 1 downto 0)); + end if; + + -- And finally after the entire transaction is complete we can save off the data + -- on the final falling edge of the SPI clock into it's appropriate place, based + -- off the address value captured above. + if (sPsMosiIndex = kTotalWidth) and (not sPsRd) then + + -- ---------------------------------------------------------------------------- + -- Assign writable register values here! -------------------------------------- + -- ---------------------------------------------------------------------------- + if (sPsRegAddr = kScratch) then + sScratchVal <= sPsMosiBuffer; + end if; + + if (sPsRegAddr = kCpldControl) then + sReset <= sPsMosiBuffer(kCpldReset) = '1'; + end if; + + if (sPsRegAddr = kLmkControl) then + sVcxoControl <= sPsMosiBuffer(kVcxoControl); + end if; + + if (sPsRegAddr = kMykonosControl) then + sMykonosReset <= sPsMosiBuffer(kMykonosReset); + end if; + + end if; + end if; + end if; + end process PsMosiProcessing; + + + -- Send MISO back to FPGA (PS) on the falling edge as well. + -- + -- !!! SAFE COUNTER STARTUP!!! + -- This counter starts safely from reset because the PsSpiSck will not start toggling + -- until long after the asynchronous reset (sCpldPsSpiActive) de-asserts. Similarly, + -- the reset will only assert long after the last clock edge is received. + PsMisoBuffer : process(PsSpiSck, sCpldPsSpiActive) + begin + if not sCpldPsSpiActive then + sPsMisoIndex <= to_unsigned(kTotalWidth-1, sPsMisoIndex'length); + elsif falling_edge(PsSpiSck) then + if sPsMisoIndex > 0 then + sPsMisoIndex <= sPsMisoIndex - 1; + end if; + end if; + end process PsMisoBuffer; + + sPsCpldMiso <= sPsMisoBuffer(to_integer(sPsMisoIndex)); + + + -- Mux the register data from the CPLD back to the FPGA. + PsMisoBufferMux : process(sPsRegAddr, sScratchVal, sVcxoControl, + sTxLoLockDetect, sRxLoLockDetect, sMykonosReset) + begin + sPsMisoBuffer <= (others => '0'); + case to_integer(sPsRegAddr) is + when kSignatureReg => sPsMisoBuffer(kDataWidth-1 downto 0) <= kSignature; + when kMinorRevReg => sPsMisoBuffer(kDataWidth-1 downto 0) <= kMinorRev; + when kMajorRevReg => sPsMisoBuffer(kDataWidth-1 downto 0) <= kMajorRev; + when kBuildCodeLSB => sPsMisoBuffer(kDataWidth-1 downto 0) <= kBuildCode(15 downto 0); + when kBuildCodeMSB => sPsMisoBuffer(kDataWidth-1 downto 0) <= kBuildCode(31 downto 16); + when kScratch => sPsMisoBuffer(kDataWidth-1 downto 0) <= sScratchVal; + when kLmkControl => sPsMisoBuffer(kVcxoControl) <= sVcxoControl; + when kLoStatus => sPsMisoBuffer(kTxLoLockDetect) <= sTxLoLockDetect; + sPsMisoBuffer(kRxLoLockDetect) <= sRxLoLockDetect; + when kMykonosControl => sPsMisoBuffer(kMykonosReset) <= sMykonosReset; + when others => sPsMisoBuffer(kDataWidth-1 downto 0) <= (others => '0'); + end case; + end process PsMisoBufferMux; + + + -- Double-synchronize the async inputs to the PS clock domain. However, this clock + -- isn't toggling all the time. Whenever it is toggling, let's capture these bits. + StatusSynchronizer : process(PsSpiSck) + begin + if rising_edge(PsSpiSck) then + aRxLoLockDetect_ms <= aRxLoLockDetect; + sRxLoLockDetect <= aRxLoLockDetect_ms; + + aTxLoLockDetect_ms <= aTxLoLockDetect; + sTxLoLockDetect <= aTxLoLockDetect_ms; + end if; + end process; + + + -- PS SPI locals to outputs. + aVcxoCtrl <= sVcxoControl; + aMkReset_n <= not sMykonosReset; + + + + -- PL SPI Interface : ----------------------------------------------------------------- + -- Composed of a few modules: + -- 1) PlMosiIndex - generate pointer for MOSI Buffer + -- 2) PlMosiBuffer - actually implement the buffer, only when the CPLD is targeted. + -- 3) PlMosiProcessing - process the MOSI data: sort into Rd/!Wt, Address, and Data. + -- This process works on the falling edge of the clock to register the pieces + -- of the MOSI packet as they are complete. The final falling edge registers + -- the data into the individual registers, so it is critical that the clock idle + -- LOW after the transaction is complete such that this final falling edge occurs. + -- 4) PlMisoBuffer - generate pointer for the MISO buffer. The buffer itself is + -- completely async. + -- 5) PlMisoBufferMux - Mux all the register data back into the MISO buffer. + -- 6) StatusSynchronizer - double-synchronizers for status bits from the LMK and LOs. + -- ------------------------------------------------------------------------------------ + + -- Decode the PL SPI Address bits... which are actually going to be used as individual + -- chip selects coming from the PL. + lCpldPlSpiActive <= lPlSpiLe = '0'; + aTxLoCs_n <= aPlSpiAddr(0); + aRxLoCs_n <= aPlSpiAddr(1); + + -- Assign the remainder of the SPI lines to the LOs. + aRxLoSck <= PlSpiSck; + aRxLoDin <= lPlSpiSdi; + aTxLoSck <= PlSpiSck; + aTxLoDin <= lPlSpiSdi; + + -- Output mux for data back to the FPGA (PL core). The LMK and CPLD are the only + -- endpoints that have readback enabled. + lPlSpiSdo <= aTxLoMuxOut when aPlSpiAddr(0) = '0' else + aRxLoMuxOut when aPlSpiAddr(1) = '0' else + lPlCpldMiso; + + + + -- Use the LE signal (Cs_n) as the asynchronous reset to the shift register counter. + -- LE will hold the counter in reset until this endpoint is targeted, when it will + -- release the reset (long before the clock toggles) and allow the shift operation + -- to begin. + -- + -- !!! SAFE COUNTER STARTUP!!! + -- This counter starts safely from reset because the PlSpiSck will not start toggling + -- until long after the asynchronous reset (lCpldPlSpiActive) de-asserts. Similarly, + -- the reset will only assert long after the last clock edge is received. + PlMosiIndex : process(PlSpiSck, lCpldPlSpiActive) + begin + if not lCpldPlSpiActive then + lPlMosiIndex <= (others => '0'); + elsif rising_edge(PlSpiSck) then + lPlMosiIndex <= lPlMosiIndex + 1; + end if; + end process PlMosiIndex; + + + -- Shift in SDI (MOSI) data from the PL on the rising edge of the clock. Only use + -- synchronous resets from here on out. + PlMosiBuffer : process(PlSpiSck) + begin + if rising_edge(PlSpiSck) then + if lReset then + lPlMosiBuffer <= (others => '0'); + else + if lCpldPlSpiActive then + lPlMosiBuffer <= lPlMosiBuffer(lPlMosiBuffer'high-1 downto 0) & lPlSpiSdi; -- left shift + end if; + end if; + end if; + end process PlMosiBuffer; + + + -- As portions of the command and data packets become available, register them here + -- using the falling edge of the PL SPI clock. + PlMosiProcessing : process(PlSpiSck) + begin + if falling_edge(PlSpiSck) then + if lReset then + -- lReset is intentionally self-clearing. It clears on the first falling edge of + -- the next SPI transaction after it is set. Logic on the first rising edge of + -- that next transaction is therefore held in reset. This will not matter + -- as long as SW follows the recommended reset procedure (writing a '1' to reset + -- then writing a '0'), since the first bit of the transaction is '0' for a + -- write operation. + lReset <= false; + lScratchVal <= (others => '0'); + lTxCh1IdleReg <= kTxChDefault; + lTxCh1TxOnReg <= kTxChDefault; + lTxCh2IdleReg <= kTxChDefault; + lTxCh2TxOnReg <= kTxChDefault; + lRxCh1_0IdleReg <= kRxChDefault0; + lRxCh1_1IdleReg <= kRxChDefault1; + lRxCh1_0RxOnReg <= kRxChDefault0; + lRxCh1_1RxOnReg <= kRxChDefault1; + lRxCh2_0IdleReg <= kRxChDefault0; + lRxCh2_1IdleReg <= kRxChDefault1; + lRxCh2_0RxOnReg <= kRxChDefault0; + lRxCh2_1RxOnReg <= kRxChDefault1; + lPlRd <= false; + lPlRegAddr <= (others => '0'); + else + -- After the first bit is captured, we can determine if it is a write or read. + if (lPlMosiIndex = (kRdWtWidth)) then + lPlRd <= lPlMosiBuffer(0) = '1'; + end if; + + -- After the entire command word is captured, the address is ready for capture. + if (lPlMosiIndex = (kAddrWidth + kRdWtWidth)) then + lPlRegAddr <= unsigned(lPlMosiBuffer(kAddrWidth - 1 downto 0)); + end if; + + -- And finally after the entire transaction is complete we can save off the data + -- on the final falling edge of the SPI clock into it's appropriate place, based + -- off the address value captured above. + if (lPlMosiIndex = kTotalWidth) and (not lPlRd) then + + -- ---------------------------------------------------------------------------- + -- Assign writable register values here! -------------------------------------- + -- ---------------------------------------------------------------------------- + if (lPlRegAddr = kPlScratch) then + lScratchVal <= lPlMosiBuffer; + end if; + + if (lPlRegAddr = kPlCpldControl) then + lReset <= lPlMosiBuffer(kCpldReset) = '1'; + end if; + + if (lPlRegAddr = kTxCh1_Idle) then + lTxCh1IdleReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kTxCh1_TxOn) then + lTxCh1TxOnReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kTxCh2_Idle) then + lTxCh2IdleReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kTxCh2_TxOn) then + lTxCh2TxOnReg <= lPlMosiBuffer; + end if; + + if (lPlRegAddr = kRxCh1_0_Idle) then + lRxCh1_0IdleReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kRxCh1_1_Idle) then + lRxCh1_1IdleReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kRxCh1_0_RxOn) then + lRxCh1_0RxOnReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kRxCh1_1_RxOn) then + lRxCh1_1RxOnReg <= lPlMosiBuffer; + end if; + + if (lPlRegAddr = kRxCh2_0_Idle) then + lRxCh2_0IdleReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kRxCh2_1_Idle) then + lRxCh2_1IdleReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kRxCh2_0_RxOn) then + lRxCh2_0RxOnReg <= lPlMosiBuffer; + end if; + if (lPlRegAddr = kRxCh2_1_RxOn) then + lRxCh2_1RxOnReg <= lPlMosiBuffer; + end if; + + end if; + end if; + end if; + end process PlMosiProcessing; + + + -- Send MISO back to FPGA (PL) on the falling edge as well. + -- + -- !!! SAFE COUNTER STARTUP!!! + -- This counter starts safely from reset because the PlSpiSck will not start toggling + -- until long after the asynchronous reset (lCpldPlSpiActive) de-asserts. Similarly, + -- the reset will only assert long after the last clock edge is received. + PlMisoBuffer : process(PlSpiSck, lCpldPlSpiActive) + begin + if not lCpldPlSpiActive then + lPlMisoIndex <= to_unsigned(kTotalWidth-1, lPlMisoIndex'length); + elsif falling_edge(PlSpiSck) then + if lPlMisoIndex > 0 then + lPlMisoIndex <= lPlMisoIndex - 1; + end if; + end if; + end process PlMisoBuffer; + + lPlCpldMiso <= lPlMisoBuffer(to_integer(lPlMisoIndex)); + + + -- Mux the register data from the CPLD back to the FPGA. + PlMisoBufferMux : process(lPlRegAddr, lScratchVal, lTxCh1IdleReg, lTxCh1TxOnReg, + lTxCh2IdleReg, lTxCh2TxOnReg, lRxCh1_0IdleReg, + lRxCh1_1IdleReg, lRxCh1_0RxOnReg, lRxCh1_1RxOnReg, + lRxCh2_0IdleReg, lRxCh2_1IdleReg, lRxCh2_0RxOnReg, + lRxCh2_1RxOnReg) + begin + lPlMisoBuffer <= (others => '0'); + case to_integer(lPlRegAddr) is + when kPlScratch => lPlMisoBuffer(kDataWidth-1 downto 0) <= lScratchVal; + when kTxCh1_Idle => lPlMisoBuffer(kDataWidth-1 downto 0) <= lTxCh1IdleReg; + when kTxCh1_TxOn => lPlMisoBuffer(kDataWidth-1 downto 0) <= lTxCh1TxOnReg; + when kTxCh2_Idle => lPlMisoBuffer(kDataWidth-1 downto 0) <= lTxCh2IdleReg; + when kTxCh2_TxOn => lPlMisoBuffer(kDataWidth-1 downto 0) <= lTxCh2TxOnReg; + when kRxCh1_0_Idle => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh1_0IdleReg; + when kRxCh1_1_Idle => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh1_1IdleReg; + when kRxCh1_0_RxOn => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh1_0RxOnReg; + when kRxCh1_1_RxOn => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh1_1RxOnReg; + when kRxCh2_0_Idle => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh2_0IdleReg; + when kRxCh2_1_Idle => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh2_1IdleReg; + when kRxCh2_0_RxOn => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh2_0RxOnReg; + when kRxCh2_1_RxOn => lPlMisoBuffer(kDataWidth-1 downto 0) <= lRxCh2_1RxOnReg; + when others => lPlMisoBuffer(kDataWidth-1 downto 0) <= (others => '0'); + end case; + end process PlMisoBufferMux; + + + -- Use the ATR bits to mux the output values. + lTxCh1 <= lTxCh1IdleReg when aAtrTx1 = '0' else lTxCh1TxOnReg; + lTxCh2 <= lTxCh2IdleReg when aAtrTx2 = '0' else lTxCh2TxOnReg; + + lRxCh1_0 <= lRxCh1_0IdleReg when aAtrRx1 = '0' else lRxCh1_0RxOnReg; + lRxCh1_1 <= lRxCh1_1IdleReg when aAtrRx1 = '0' else lRxCh1_1RxOnReg; + lRxCh2_0 <= lRxCh2_0IdleReg when aAtrRx2 = '0' else lRxCh2_0RxOnReg; + lRxCh2_1 <= lRxCh2_1IdleReg when aAtrRx2 = '0' else lRxCh2_1RxOnReg; + + -- PL SPI locals to outputs. All the register values are set for Channel 1. Channel 2 + -- values are mixed around here in order for the same register settings to work for + -- Channel 1 and Channel 2, even though Ch2 switch configuration is different in HW. + aCh1LedTx <= lTxCh1(kCh1TxLed); + aCh1TxPaEn <= lTxCh1(kCh1TxPaEn); + aCh1TxAmpEn <= lTxCh1(kCh1TxAmpEn); + aCh1TxMixerEn <= lTxCh1(kCh1TxMixerEn); + aCh1TxSw1 <= lTxCh1(kCh1TxSw1Msb downto kCh1TxSw1); + aCh1TxSw2 <= lTxCh1(kCh1TxSw2Msb downto kCh1TxSw2); + aCh1TxSw3 <= lTxCh1(kCh1TxSw3); + aCh1TxSw4 <= "01" when lTxCh1(kCh1TxLowbandMixerPathSelect) = '1' else "10"; + aCh1TxSw5 <= "10" when lTxCh1(kCh1TxLowbandMixerPathSelect) = '1' else "01"; + aCh1SwTrx <= lTxCh1(kCh1SwTrxMsb downto kCh1SwTrx); + aMkTx1En <= lTxCh1(kCh1MykEnTx); + + aCh2LedTx <= lTxCh2(kCh1TxLed); + aCh2TxPaEn <= lTxCh2(kCh1TxPaEn); + aCh2TxAmpEn <= lTxCh2(kCh1TxAmpEn); + aCh2TxMixerEn <= lTxCh2(kCh1TxMixerEn); + aCh2TxSw1 <= lTxCh2(kCh1TxSw1Msb downto kCh1TxSw1); + aCh2TxSw2 <= Tx2Switch2Mod(lTxCh2(kCh1TxSw2Msb downto kCh1TxSw2)); + aCh2TxSw3 <= lTxCh2(kCh1TxSw3); + aCh2TxSw4 <= "10" when lTxCh2(kCh1TxLowbandMixerPathSelect) = '1' else "01"; + aCh2TxSw5 <= "01" when lTxCh2(kCh1TxLowbandMixerPathSelect) = '1' else "10"; + aCh2SwTrx <= Tx2TrxMod(lTxCh2(kCh1SwTrxMsb downto kCh1SwTrx)); + aMkTx2En <= lTxCh2(kCh1MykEnTx); + + aCh1RxSw1 <= lRxCh1_0(kCh1RxSw1Msb downto kCh1RxSw1); + aCh1RxSw2 <= lRxCh1_0(kCh1RxSw2Msb downto kCh1RxSw2); + aCh1RxSw3 <= lRxCh1_0(kCh1RxSw3Msb downto kCh1RxSw3); + aCh1RxSw4 <= lRxCh1_0(kCh1RxSw4Msb downto kCh1RxSw4); + aCh1RxSw5 <= lRxCh1_0(kCh1RxSw5Msb downto kCh1RxSw5); + aCh1RxSw6 <= lRxCh1_1(kCh1RxSw6Msb downto kCh1RxSw6); + aCh1RxSw7 <= "01" when lRxCh1_1(kCh1RxLowbandMixerPathSelect) = '1' else "10"; + aCh1RxSw8 <= "01" when lRxCh1_1(kCh1RxLowbandMixerPathSelect) = '1' else "10"; + aCh1LedRx <= lRxCh1_1(kCh1RxLed) and not lTxCh1(kCh1TxLed); + aCh1LedRx2 <= lRxCh1_1(kCh1Rx2Led); + aCh1RxAmpEn <= lRxCh1_1(kCh1RxAmpEn); + aCh1RxMixerEn <= lRxCh1_1(kCh1RxMixerEn); + aCh1RxLna1En <= lRxCh1_1(kCh1RxLna1En); + aCh1RxLna2En <= lRxCh1_1(kCh1RxLna2En); + aMkRx1En <= lRxCh1_1(kCh1MykEnRx); + + aCh2RxSw1 <= Rx2Switch1Mod(lRxCh2_0(kCh1RxSw1Msb downto kCh1RxSw1)); + aCh2RxSw2 <= Rx2Switch2Mod(lRxCh2_0(kCh1RxSw2Msb downto kCh1RxSw2)); + aCh2RxSw3 <= Rx2Switch3Mod(lRxCh2_0(kCh1RxSw3Msb downto kCh1RxSw3)); + aCh2RxSw4 <= Rx2Switch4Mod(lRxCh2_0(kCh1RxSw4Msb downto kCh1RxSw4)); + aCh2RxSw5 <= Rx2Switch5Mod(lRxCh2_0(kCh1RxSw5Msb downto kCh1RxSw5)); + aCh2RxSw6 <= Rx2Switch6Mod(lRxCh2_1(kCh1RxSw6Msb downto kCh1RxSw6)); + aCh2RxSw7 <= "10" when lRxCh2_1(kCh1RxLowbandMixerPathSelect) = '1' else "01"; + aCh2RxSw8 <= "10" when lRxCh2_1(kCh1RxLowbandMixerPathSelect) = '1' else "01"; + aCh2LedRx <= lRxCh2_1(kCh1RxLed) and not lTxCh2(kCh1TxLed); + aCh2LedRx2 <= lRxCh2_1(kCh1Rx2Led); + aCh2RxAmpEn <= lRxCh2_1(kCh1RxAmpEn); + aCh2RxMixerEn <= lRxCh2_1(kCh1RxMixerEn); + aCh2RxLna1En <= lRxCh2_1(kCh1RxLna1En); + aCh2RxLna2En <= lRxCh2_1(kCh1RxLna2En); + aMkRx2En <= lRxCh2_1(kCh1MykEnRx); + + +end RTL; + + + + +--XmlParse xml_on +--<top name="MgCpld"></top> +--<regmap name="MgCpld"> +-- <group name="PsSpi_CpldRegisters" order="1"> +-- +-- <info> +-- These registers are accessed via the PS SPI interface to the CPLD. They are all +-- internal to the CPLD. The SPI format is 24 bits total. On MOSI, shift (msb first) +-- Rd/!Wt | Addr(6:0) | Data(15:0) (lsb). The SPI clock {b}MUST{/b} idle LOW before +-- and after the transaction. CPOL=CPHA=0. To access these registers, use the chip +-- select line named "CPLD-PS-SPI-SLE-33" as an active-low select. +-- </info> +-- +-- <register name="SignatureReg" size="16" offset="0x00" attributes="Readable"> +-- <info> +-- This register contains the device signature. +-- </info> +-- <bitfield name="ProductSignature" range="15..0"> +-- <info> +-- Represents the product family name/number. This field reads back as +-- 0xCAFE. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="MinorRevReg" size="16" offset="0x01" attributes="Readable"> +-- <info> +-- This register contains the device revision numeric code. +-- </info> +-- <bitfield name="CpldMinorRevision" range="15..0"> +-- <info> +-- Contains minor revision code (0,1,2,...). +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="MajorRevReg" size="16" offset="0x02" attributes="Readable"> +-- <info> +-- This register contains the major revision value. +-- </info> +-- <bitfield name="CpldMajorRevision" range="15..0"> +-- <info> +-- Contains major revision code. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="BuildCodeLSB" size="16" offset="0x03" attributes="Readable"> +-- <info> +-- Build code... right now it's the date it was built. LSB in this register. +-- </info> +-- <bitfield name="BuildCodeHH" range="7..0"> +-- <info> +-- Contains build code hour code. +-- </info> +-- </bitfield> +-- <bitfield name="BuildCodeDD" range="15..8"> +-- <info> +-- Contains build code day code. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="BuildCodeMSB" size="16" offset="0x04" attributes="Readable"> +-- <info> +-- Build code... right now it's the date it was built. MSB in this register. +-- </info> +-- <bitfield name="BuildCodeMM" range="7..0"> +-- <info> +-- Contains build code month code. +-- </info> +-- </bitfield> +-- <bitfield name="BuildCodeYY" range="15..8"> +-- <info> +-- Contains build code revision year code. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="Scratch" size="16" offset="0x05" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="ScratchVal" range="15..0"> +-- <info> +-- Contains scratch value for testing. The state of this register has +-- no effect on any other operation in the CPLD. +-- </info> +-- </bitfield> +-- </register> +-- +-- +-- <register name="CpldControl" size="16" offset="0x10" attributes="Writable"> +-- <info> +-- </info> +-- <bitfield name="CpldReset" range="0"> +-- <info> +-- Asserting this bit resets all the CPLD logic. +-- This reset will return all registers on the PS SPI interface to their default +-- state! To use this reset correctly, first write CpldReset to '1', then write +-- it to '0'. Registers will be reset on the _falling_ edge of CpldReset. +-- </info> +-- </bitfield> +-- </register> +-- +-- +-- <register name="LmkControl" size="16" offset="0x11" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="VcxoControl" range="4"> +-- <info> +-- Setting this bit to '0' will allow the Phase DAC to exclusively control the +-- VCXO voltage. Defaults to '1', which allows the Phase DAC to adjust the +-- voltage (but the LMK still has control as well). +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="LoStatus" size="16" offset="0x12" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="RxLoLockDetect" range="0" attributes="Readable"> +-- <info> +-- Live lock detect status from the RX LO. +-- </info> +-- </bitfield> +-- <bitfield name="TxLoLockDetect" range="4" attributes="Readable"> +-- <info> +-- Live lock detect status from the TX LO. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="MykonosControl" size="16" offset="0x13" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="MykonosReset" range="0"> +-- <info> +-- Drives the Mykonos hard reset line. Defaults to de-asserted. Write a '1' to +-- assert the reset, and a '0' to de-assert. +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +-- +-- +-- <group name="PlSpi_FrontEndControl" order="2"> +-- +-- <info> +-- These registers are accessed via the PL SPI interface to the CPLD. They are all +-- internal to the CPLD. The SPI format is 24 bits total. On MOSI, shift (msb first) +-- Rd/!Wt | Addr(6:0) | Data(15:0) (lsb). The SPI clock {b}MUST{/b} idle LOW before +-- and after the transaction. CPOL=CPHA=0. To access these registers, use the chip +-- select line named "CPLD-PL-SPI-LE-25" as an active-low select. {br}{br} +-- +-- The ATR bits ultimately control which of these registers actually control +-- the RF front end. +-- </info> +-- +-- <register name="PlScratch" size="16" offset="0x40" attributes="Readable|Writable"> +-- <bitfield name="PlScratchVal" range="15..0"> +-- <info> +-- Contains scratch value for testing. The state of this register has no effect +-- on any other operation in the CPLD. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="PlCpldControl" size="16" offset="0x41" attributes="Writable"> +-- <info> +-- </info> +-- <bitfield name="PlCpldReset" range="0"> +-- <info> +-- Asserting this bit resets all the CPLD logic on the PL SPI interface. +-- This reset will return all registers to their default state! To use this +-- reset correctly, first write PlCpldReset to '1', then write it to '0'. +-- Registers will be reset on the _falling_ edge of PlCpldReset. +-- </info> +-- </bitfield> +-- </register> +-- +-- +-- +-- <enumeratedtype name="TrxSwitch"> +-- <value name="FromLowerFilterBankTxSw1" integer="0"/> +-- <value name="FromTxUpperFilterBankLp6400MHz" integer="1"/> +-- <value name="RxChannelPath" integer="2"/> +-- <value name="BypassPathToTxSw3" integer="3"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="TxSwitch1"> +-- <value name="ShutdownTxSw1" integer="0"/> +-- <value name="FromTxFilterLp1700MHz" integer="1"/> +-- <value name="FromTxFilterLp3400MHz" integer="2"/> +-- <value name="FromTxFilterLp0800MHz" integer="3"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="TxSwitch2"> +-- <value name="ToTxFilterLp3400MHz" integer="1"/> +-- <value name="ToTxFilterLp1700MHz" integer="2"/> +-- <value name="ToTxFilterLp0800MHz" integer="4"/> +-- <value name="ToTxFilterLp6400MHz" integer="8"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="TxSwitch3"> +-- <value name="ToTxFilterBanks" integer="0"/> +-- <value name="BypassPathToTrxSw" integer="1"/> +-- </enumeratedtype> +-- +-- +-- <register name="TxCh1_Idle" size="16" offset="0x50" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel TX 1 when the +-- ATR bits are configured: TX = 0, RX = don't-care. +-- </info> +-- <bitfield name="Ch1TxSw1" type="TxSwitch1" range="1..0"> +-- <info> +-- Controls Switch 1. Filter bank receive switch. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxSw2" type="TxSwitch2" range="5..2"> +-- <info> +-- Controls Switch 2. Filter bank distribution switch. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxSw3" type="TxSwitch3" range="6"> +-- <info> +-- Controls Switch 3. Bypasses the filter bank and PA, or doesn't. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxLowbandMixerPathSelect" range="7"> +-- <info> +-- Controls Switches 4 and 5. Write a '1' to select the Lowband Mixer path. +-- Writing '0' will select the bypass path around the mixer. Default is '0'. Note: +-- Individual control over these switches was removed as an optimization to +-- allow all TX controls to fit in one 16 bit register. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxMixerEn" range="8"> +-- <info> +-- Write a '1' to enable the lowband mixer. Note that Ch1TxLowbandMixerPathSelect +-- must be properly configured to select the mixer path. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxAmpEn" range="9"> +-- <info> +-- Write a '1' to enable the TX path Amp in between TX switches 3 and 4. The path +-- (from Mykonos) is: TxSw4 -> Amp -> DSA -> TxSw3. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxPaEn" range="10"> +-- <info> +-- Write a '1' to enable the TX path PA in between TX switches 2 and 3. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1SwTrx" type="TrxSwitch" range="12..11"> +-- <info> +-- TRX switch control. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1TxLed" range="13"> +-- <info> +-- Red/Green combo LED for the TRX channel. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1MykEnTx" range="14"> +-- <info> +-- Drives the Mykonos input port TX1_ENABLE. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="TxCh1_TxOn" size="16" offset="0x53" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel TX 1 when the +-- ATR bits are configured: TX = 1, RX = don't-care. The bitfields are the same +-- as for the Tx1_Off register. +-- </info> +-- </register> +-- +-- <register name="TxCh2_Idle" size="16" offset="0x60" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel TX 2 when the +-- ATR bits are configured: TX = 0, RX = don't-care. The bitfields are the same +-- as for the Tx1_Off register. +-- </info> +-- </register> +-- +-- <register name="TxCh2_TxOn" size="16" offset="0x63" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel TX 2 when the +-- ATR bits are configured: TX = 1, RX = don't-care. The bitfields are the same +-- as for the Tx1_Off register. +-- </info> +-- </register> +-- +-- +-- <enumeratedtype name="Rx1Switch1"> +-- <value name="TxRxInput" integer="0"/> +-- <value name="RxLoCalInput" integer="1"/> +-- <value name="TrxSwitchOutput" integer="2"/> +-- <value name="Rx2Input" integer="3"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="Rx1Switch2"> +-- <value name="ShutdownSw2" integer="0"/> +-- <value name="LowerFilterBankToSwitch3" integer="1"/> +-- <value name="BypassPathToSwitch6" integer="2"/> +-- <value name="UpperFilterBankToSwitch4" integer="3"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="Rx1Switch3"> +-- <value name="Filter2100x2850MHz" integer="0"/> +-- <value name="Filter0490LpMHz" integer="1"/> +-- <value name="Filter1600x2250MHz" integer="2"/> +-- <value name="Filter0440x0530MHz" integer="4"/> +-- <value name="Filter0650x1000MHz" integer="5"/> +-- <value name="Filter1100x1575MHz" integer="6"/> +-- <value name="ShutdownSw3" integer="7"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="Rx1Switch4"> +-- <value name="Filter2100x2850MHzFrom" integer="1"/> +-- <value name="Filter1600x2250MHzFrom" integer="2"/> +-- <value name="Filter2700HpMHz" integer="4"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="Rx1Switch5"> +-- <value name="Filter0440x0530MHzFrom" integer="1"/> +-- <value name="Filter1100x1575MHzFrom" integer="2"/> +-- <value name="Filter0490LpMHzFrom" integer="4"/> +-- <value name="Filter0650x1000MHzFrom" integer="8"/> +-- </enumeratedtype> +-- +-- <enumeratedtype name="Rx1Switch6"> +-- <value name="LowerFilterBankFromSwitch5" integer="1"/> +-- <value name="UpperFilterBankFromSwitch4" integer="2"/> +-- <value name="BypassPathFromSwitch2" integer="4"/> +-- </enumeratedtype> +-- +-- +-- +-- <register name="RxCh1_0_Idle" size="16" offset="0x51" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 1 when the +-- ATR bits are configured: TX = don't-care, RX = 0. +-- </info> +-- <bitfield name="Ch1RxSw1" type="Rx1Switch1" range="1..0"> +-- <info> +-- Controls Switch 1. Selects between the cal, bypass, RX2, and TRX paths. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxSw2" type="Rx1Switch2" range="3..2"> +-- <info> +-- Controls Switch 2. First filter switch. Selects between bypass path and +-- the upper/lower filter banks. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxSw3" type="Rx1Switch3" range="6..4"> +-- <info> +-- Controls Switch 3. Lower filter bank transmit switch. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxSw4" type="Rx1Switch4" range="9..7"> +-- <info> +-- Controls Switch 4. Upper filter bank receive switch. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxSw5" type="Rx1Switch5" range="13..10"> +-- <info> +-- Controls Switch 5. Lower filter bank receive switch. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="RxCh1_1_Idle" size="16" offset="0x52" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 1 when the +-- ATR bits are configured: TX = don't-care, RX = 0. +-- </info> +-- <bitfield name="Ch1RxSw6" type="Rx1Switch6" range="2..0"> +-- <info> +-- Controls Switch 6. Selects between the upper and lower filter banks and +-- bypass path. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxLowbandMixerPathSelect" range="3"> +-- <info> +-- Controls Switches 7 and 8. Write a '1' to select the Lowband Mixer path. +-- Writing '0' will select the bypass path around the mixer. Default is '0'. Note: +-- Individual control over these switches was removed as an optimization to +-- allow all TX controls to fit in one 16 bit register... so the same was done +-- for the RX path for continuity. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxMixerEn" range="4"> +-- <info> +-- Write a '1' to enable the lowband mixer. Note that Ch1RxLowbandMixerPathSelect +-- must be properly configured to select the mixer path. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxAmpEn" range="5"> +-- <info> +-- Write a '1' to enable the RX path Amp directly before the Mykonos inputs. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxLna1En" range="6"> +-- <info> +-- Write a '1' to enable the RX path LNA1 between RxSw4 and RxSw6. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxLna2En" range="7"> +-- <info> +-- Write a '1' to enable the RX path LNA2 between RxSw5 and RxSw6. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1Rx2Led" range="8"> +-- <info> +-- Green LED for RX2 channel. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1RxLed" range="9"> +-- <info> +-- Red/Green combo LED for the TRX channel. +-- </info> +-- </bitfield> +-- <bitfield name="Ch1MykEnRx" range="10"> +-- <info> +-- Drives the Mykonos input port RX1_ENABLE. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="RxCh1_0_RxOn" size="16" offset="0x54" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 1 when the +-- ATR bits are configured: TX = don't-care, RX = 1. The bitfields are the same +-- as for the RxCh1_0_Idle register. +-- </info> +-- </register> +-- +-- <register name="RxCh1_1_RxOn" size="16" offset="0x55" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 1 when the +-- ATR bits are configured: TX = don't-care, RX = 1. The bitfields are the same +-- as for the RxCh1_1_Idle register. +-- </info> +-- </register> +-- +-- <register name="RxCh2_0_Idle" size="16" offset="0x61" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 2 when the +-- ATR bits are configured: TX = don't-care, RX = 0. The bitfields are the same +-- as for the RxCh1_0_Idle register. +-- </info> +-- </register> +-- +-- <register name="RxCh2_1_Idle" size="16" offset="0x62" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 2 when the +-- ATR bits are configured: TX = don't-care, RX = 0. The bitfields are the same +-- as for the RxCh1_1_Idle register. +-- </info> +-- </register> +-- +-- <register name="RxCh2_0_RxOn" size="16" offset="0x64" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 2 when the +-- ATR bits are configured: TX = don't-care, RX = 1. The bitfields are the same +-- as for the RxCh1_0_Idle register. +-- </info> +-- </register> +-- +-- <register name="RxCh2_1_RxOn" size="16" offset="0x65" attributes="Readable|Writable"> +-- <info> +-- Load this register with the front-end configuration for channel RX 2 when the +-- ATR bits are configured: TX = don't-care, RX = 1. The bitfields are the same +-- as for the RxCh1_1_Idle register. +-- </info> +-- </register> +-- +-- </group> +-- +--</regmap> +--XmlParse xml_off + + + diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db0_pins.xdc b/fpga/usrp3/top/n3xx/dboards/mg/db0_pins.xdc new file mode 100644 index 000000000..b89183a2e --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db0_pins.xdc @@ -0,0 +1,156 @@ +# +# Copyright 2017 Ettus Research, A National Instruments Company +# SPDX-License-Identifier: LGPL-3.0 +# +# Daughterboard Pin Definitions for the N310. +# + +## TDC : ################################################################################ +## Bank 10, 2.5V (DB A) +######################################################################################### + +set_property PACKAGE_PIN AB15 [get_ports {UNUSED_PIN_TDCA_0}] +set_property PACKAGE_PIN AB14 [get_ports {UNUSED_PIN_TDCA_1}] +set_property PACKAGE_PIN AB16 [get_ports {UNUSED_PIN_TDCA_2}] +set_property PACKAGE_PIN AB17 [get_ports {UNUSED_PIN_TDCA_3}] +set_property IOSTANDARD LVCMOS25 [get_ports {UNUSED_PIN_TDCA_*}] +set_property IOB TRUE [get_ports {UNUSED_PIN_TDCA_*}] + +## USRP IO A : ########################################################################## +## Banks 10/33 +######################################################################################### + +## HP GPIO, Bank 33, 1.8V + +set_property PACKAGE_PIN G1 [get_ports {DBA_CPLD_PS_SPI_LE}] +set_property PACKAGE_PIN H2 [get_ports {DBA_CPLD_PS_SPI_SCLK}] +set_property PACKAGE_PIN D1 [get_ports {DBA_CH1_TX_DSA_DATA[5]}] +# set_property PACKAGE_PIN E1 [get_ports {nc}] +set_property PACKAGE_PIN H1 [get_ports {DBA_CPLD_PS_SPI_ADDR[0]}] +set_property PACKAGE_PIN J1 [get_ports {DBA_CPLD_PS_SPI_ADDR[1]}] +set_property PACKAGE_PIN A5 [get_ports {DBA_CH1_TX_DSA_DATA[3]}] +set_property PACKAGE_PIN A4 [get_ports {DBA_CH1_TX_DSA_DATA[4]}] +set_property PACKAGE_PIN F5 [get_ports {DBA_CPLD_PS_SPI_SDO}] +set_property PACKAGE_PIN E5 [get_ports {DBA_CPLD_PS_SPI_SDI}] +set_property PACKAGE_PIN E3 [get_ports {DBA_CH1_RX_DSA_DATA[0]}] +set_property PACKAGE_PIN E2 [get_ports {DBA_CH1_RX_DSA_DATA[1]}] +set_property PACKAGE_PIN A3 [get_ports {DBA_CH1_TX_DSA_DATA[2]}] +set_property PACKAGE_PIN A2 [get_ports {DBA_CH1_TX_DSA_DATA[1]}] +set_property PACKAGE_PIN K1 [get_ports {DBA_ATR_RX_1}] +set_property PACKAGE_PIN L1 [get_ports {DBA_ATR_TX_2}] +set_property PACKAGE_PIN C4 [get_ports {DBA_CH1_TX_DSA_DATA[0]}] +set_property PACKAGE_PIN C3 [get_ports {DBA_CH1_RX_DSA_DATA[5]}] +set_property PACKAGE_PIN F4 [get_ports {DBA_ATR_TX_1}] +set_property PACKAGE_PIN F3 [get_ports {DBA_ATR_RX_2}] +# set_property PACKAGE_PIN B1 [get_ports {nc}] +set_property PACKAGE_PIN B2 [get_ports {DBA_CH1_RX_DSA_DATA[3]}] +set_property PACKAGE_PIN C1 [get_ports {DBA_CH1_RX_DSA_DATA[4]}] +set_property PACKAGE_PIN C2 [get_ports {DBA_CH1_RX_DSA_DATA[2]}] + +## HR GPIO, Bank 10, 2.5V + +set_property PACKAGE_PIN AG12 [get_ports {DBA_MYK_SYNC_IN_n}] +set_property PACKAGE_PIN AH12 [get_ports {DBA_CPLD_PL_SPI_ADDR[0]}] +set_property PACKAGE_PIN AJ13 [get_ports {DBA_MYK_SPI_SDO}] +set_property PACKAGE_PIN AJ14 [get_ports {DBA_MYK_SPI_SDIO}] +set_property PACKAGE_PIN AG15 [get_ports {DBA_CPLD_PL_SPI_ADDR[1]}] +set_property PACKAGE_PIN AF15 [get_ports {DBA_CH2_TX_DSA_DATA[5]}] +set_property PACKAGE_PIN AH13 [get_ports {DBA_CPLD_JTAG_TDI}] +set_property PACKAGE_PIN AH14 [get_ports {DBA_CPLD_JTAG_TDO}] +set_property PACKAGE_PIN AK15 [get_ports {DBA_MYK_GPIO_1}] +set_property PACKAGE_PIN AJ15 [get_ports {DBA_MYK_GPIO_4}] +set_property PACKAGE_PIN AH16 [get_ports {DBA_CH2_TX_DSA_DATA[4]}] +set_property PACKAGE_PIN AH17 [get_ports {DBA_CH2_TX_DSA_DATA[3]}] +set_property PACKAGE_PIN AE12 [get_ports {DBA_MYK_SYNC_OUT_n}] +set_property PACKAGE_PIN AF12 [get_ports {DBA_CPLD_PL_SPI_SDO}] +set_property PACKAGE_PIN AK12 [get_ports {DBA_MYK_GPIO_13}] +set_property PACKAGE_PIN AK13 [get_ports {DBA_MYK_GPIO_0}] +set_property PACKAGE_PIN AK16 [get_ports {DBA_MYK_INTRQ}] +set_property PACKAGE_PIN AJ16 [get_ports {DBA_CH2_TX_DSA_DATA[2]}] +set_property PACKAGE_PIN AH18 [get_ports {DBA_CH2_TX_DSA_DATA[0]}] +set_property PACKAGE_PIN AJ18 [get_ports {DBA_CH2_TX_DSA_DATA[1]}] +set_property PACKAGE_PIN AF14 [get_ports {DBA_FPGA_CLK_P}] +set_property PACKAGE_PIN AG14 [get_ports {DBA_FPGA_CLK_N}] +set_property PACKAGE_PIN AG17 [get_ports {DBA_FPGA_SYSREF_P}] +set_property PACKAGE_PIN AG16 [get_ports {DBA_FPGA_SYSREF_N}] +set_property PACKAGE_PIN AD15 [get_ports {DBA_CH2_RX_DSA_DATA[3]}] +set_property PACKAGE_PIN AD16 [get_ports {DBA_CH2_RX_DSA_DATA[5]}] +set_property PACKAGE_PIN AE13 [get_ports {DBA_CPLD_JTAG_TMS}] +set_property PACKAGE_PIN AF13 [get_ports {DBA_CPLD_JTAG_TCK}] +set_property PACKAGE_PIN AE15 [get_ports {DBA_MYK_GPIO_15}] +set_property PACKAGE_PIN AE16 [get_ports {DBA_MYK_SPI_CS_n}] +set_property PACKAGE_PIN AF17 [get_ports {DBA_CH2_RX_DSA_DATA[1]}] +set_property PACKAGE_PIN AF18 [get_ports {DBA_CH2_RX_DSA_DATA[2]}] +set_property PACKAGE_PIN AC16 [get_ports {DBA_CPLD_PL_SPI_LE}] +set_property PACKAGE_PIN AC17 [get_ports {DBA_CPLD_PL_SPI_SDI}] +set_property PACKAGE_PIN AD13 [get_ports {DBA_MYK_GPIO_12}] +set_property PACKAGE_PIN AD14 [get_ports {DBA_MYK_GPIO_14}] +set_property PACKAGE_PIN AE17 [get_ports {DBA_MYK_SPI_SCLK}] +set_property PACKAGE_PIN AE18 [get_ports {DBA_MYK_GPIO_3}] +set_property PACKAGE_PIN AB12 [get_ports {DBA_CH2_RX_DSA_DATA[0]}] +set_property PACKAGE_PIN AC12 [get_ports {DBA_CH2_RX_DSA_DATA[4]}] +set_property PACKAGE_PIN AC13 [get_ports {DBA_CPLD_PL_SPI_ADDR[2]}] +set_property PACKAGE_PIN AC14 [get_ports {DBA_CPLD_PL_SPI_SCLK}] + +# set_property PACKAGE_PIN AB25 [get_ports {DBA_SWITCHER_CLOCK}] +# set_property IOSTANDARD LVCMOS33 [get_ports {DBA_SWITCHER_CLOCK}] +# set_property DRIVE 4 [get_ports {DBA_SWITCHER_CLOCK}] +# set_property SLEW SLOW [get_ports {DBA_SWITCHER_CLOCK}] + +# During SI measurements with default drive strength, many of the FPGA-driven lines to +# the DB were showing high over/undershoot. Therefore for single-ended lines to the DBs +# we are decreasing the drive strength to the minimum value (4mA) and explicitly +# declaring the (default) slew rate as SLOW. + +set UsrpIoAHpPinsSe [get_ports {DBA_CPLD_PS_* \ + DBA_CH1_* \ + DBA_ATR*}] +set_property IOSTANDARD LVCMOS18 $UsrpIoAHpPinsSe +set_property DRIVE 4 $UsrpIoAHpPinsSe +set_property SLEW SLOW $UsrpIoAHpPinsSe + +set UsrpIoAHrPinsSe [get_ports {DBA_MYK_SPI_* \ + DBA_MYK_INTRQ \ + DBA_MYK_SYNC* \ + DBA_MYK_GPIO* \ + DBA_CPLD_PL_* \ + DBA_CPLD_JTAG_* \ + DBA_CH2*}] +set_property IOSTANDARD LVCMOS25 $UsrpIoAHrPinsSe +set_property DRIVE 4 $UsrpIoAHrPinsSe +set_property SLEW SLOW $UsrpIoAHrPinsSe + +set UsrpIoAHrPinsDiff [get_ports {DBA_FPGA_CLK_* \ + DBA_FPGA_SYSREF_*}] +set_property IOSTANDARD LVDS_25 $UsrpIoAHrPinsDiff +set_property DIFF_TERM TRUE $UsrpIoAHrPinsDiff + +# Do not allow the DSA lines to float... give them a weak pull if undriven. +set_property PULLUP TRUE [get_ports {DBA_CH*_*X_DSA_DATA[*]}] + + +### MGTs, Bank 112 + +set_property PACKAGE_PIN N8 [get_ports {USRPIO_A_MGTCLK_P}] +set_property PACKAGE_PIN N7 [get_ports {USRPIO_A_MGTCLK_N}] + +# This mapping uses the TX pins as the "master" and mimics RX off of them so Vivado +# places the transceivers in the correct places. The mixup in lanes is accounted for +# in the Mykonos lane crossbar settings. +set_property PACKAGE_PIN V6 [get_ports {USRPIO_A_RX_P[0]}] +set_property PACKAGE_PIN V5 [get_ports {USRPIO_A_RX_N[0]}] +set_property PACKAGE_PIN U4 [get_ports {USRPIO_A_RX_P[1]}] +set_property PACKAGE_PIN U3 [get_ports {USRPIO_A_RX_N[1]}] +set_property PACKAGE_PIN T6 [get_ports {USRPIO_A_RX_P[2]}] +set_property PACKAGE_PIN T5 [get_ports {USRPIO_A_RX_N[2]}] +set_property PACKAGE_PIN P6 [get_ports {USRPIO_A_RX_P[3]}] +set_property PACKAGE_PIN P5 [get_ports {USRPIO_A_RX_N[3]}] + +set_property PACKAGE_PIN T2 [get_ports {USRPIO_A_TX_P[0]}] +set_property PACKAGE_PIN T1 [get_ports {USRPIO_A_TX_N[0]}] +set_property PACKAGE_PIN R4 [get_ports {USRPIO_A_TX_P[1]}] +set_property PACKAGE_PIN R3 [get_ports {USRPIO_A_TX_N[1]}] +set_property PACKAGE_PIN P2 [get_ports {USRPIO_A_TX_P[2]}] +set_property PACKAGE_PIN P1 [get_ports {USRPIO_A_TX_N[2]}] +set_property PACKAGE_PIN N4 [get_ports {USRPIO_A_TX_P[3]}] +set_property PACKAGE_PIN N3 [get_ports {USRPIO_A_TX_N[3]}] diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db1_pins.xdc b/fpga/usrp3/top/n3xx/dboards/mg/db1_pins.xdc new file mode 100644 index 000000000..f95051ba7 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db1_pins.xdc @@ -0,0 +1,156 @@ +# +# Copyright 2017 Ettus Research, A National Instruments Company +# SPDX-License-Identifier: LGPL-3.0 +# +# Daughterboard Pin Definitions for the N310. +# + +## TDC : ################################################################################ +## Bank 11, 2.5V (DB B) +######################################################################################### + +set_property PACKAGE_PIN W21 [get_ports {UNUSED_PIN_TDCB_0}] +set_property PACKAGE_PIN Y21 [get_ports {UNUSED_PIN_TDCB_1}] +set_property PACKAGE_PIN Y22 [get_ports {UNUSED_PIN_TDCB_2}] +set_property PACKAGE_PIN Y23 [get_ports {UNUSED_PIN_TDCB_3}] +set_property IOSTANDARD LVCMOS25 [get_ports {UNUSED_PIN_TDCB_*}] +set_property IOB TRUE [get_ports {UNUSED_PIN_TDCB_*}] + +### USRP IO B : ######################################################################### +## Bank 11/33 +######################################################################################### + +## HP GPIO, Bank 33, 1.8V + +set_property PACKAGE_PIN J4 [get_ports {DBB_CPLD_PS_SPI_LE}] +set_property PACKAGE_PIN J3 [get_ports {DBB_CPLD_PS_SPI_SCLK}] +set_property PACKAGE_PIN D4 [get_ports {DBB_CH1_TX_DSA_DATA[5]}] +# set_property PACKAGE_PIN D3 [get_ports {nc}] +set_property PACKAGE_PIN K2 [get_ports {DBB_CPLD_PS_SPI_ADDR[0]}] +set_property PACKAGE_PIN K3 [get_ports {DBB_CPLD_PS_SPI_ADDR[1]}] +set_property PACKAGE_PIN B5 [get_ports {DBB_CH1_TX_DSA_DATA[3]}] +set_property PACKAGE_PIN B4 [get_ports {DBB_CH1_TX_DSA_DATA[4]}] +set_property PACKAGE_PIN G5 [get_ports {DBB_CPLD_PS_SPI_SDO}] +set_property PACKAGE_PIN G4 [get_ports {DBB_CPLD_PS_SPI_SDI}] +set_property PACKAGE_PIN J5 [get_ports {DBB_CH1_RX_DSA_DATA[0]}] +set_property PACKAGE_PIN K5 [get_ports {DBB_CH1_RX_DSA_DATA[1]}] +set_property PACKAGE_PIN D5 [get_ports {DBB_CH1_TX_DSA_DATA[2]}] +set_property PACKAGE_PIN E6 [get_ports {DBB_CH1_TX_DSA_DATA[1]}] +set_property PACKAGE_PIN L3 [get_ports {DBB_ATR_RX_1}] +set_property PACKAGE_PIN L2 [get_ports {DBB_ATR_TX_2}] +set_property PACKAGE_PIN G6 [get_ports {DBB_CH1_TX_DSA_DATA[0]}] +set_property PACKAGE_PIN H6 [get_ports {DBB_CH1_RX_DSA_DATA[5]}] +set_property PACKAGE_PIN H4 [get_ports {DBB_ATR_TX_1}] +set_property PACKAGE_PIN H3 [get_ports {DBB_ATR_RX_2}] +# set_property PACKAGE_PIN F2 [get_ports {nc}] +set_property PACKAGE_PIN G2 [get_ports {DBB_CH1_RX_DSA_DATA[3]}] +set_property PACKAGE_PIN J6 [get_ports {DBB_CH1_RX_DSA_DATA[4]}] +set_property PACKAGE_PIN K6 [get_ports {DBB_CH1_RX_DSA_DATA[2]}] + +## HR GPIO, Bank 10, 2.5V + +set_property PACKAGE_PIN AK17 [get_ports {DBB_MYK_SYNC_IN_n}] +set_property PACKAGE_PIN AK18 [get_ports {DBB_CPLD_PL_SPI_ADDR[0]}] +set_property PACKAGE_PIN AK21 [get_ports {DBB_MYK_SPI_SDO}] +set_property PACKAGE_PIN AJ21 [get_ports {DBB_MYK_SPI_SDIO}] +set_property PACKAGE_PIN AF19 [get_ports {DBB_CPLD_PL_SPI_ADDR[1]}] +set_property PACKAGE_PIN AG19 [get_ports {DBB_CH2_TX_DSA_DATA[5]}] +set_property PACKAGE_PIN AH19 [get_ports {DBB_CPLD_JTAG_TDI}] +set_property PACKAGE_PIN AJ19 [get_ports {DBB_CPLD_JTAG_TDO}] +set_property PACKAGE_PIN AK22 [get_ports {DBB_MYK_GPIO_1}] +set_property PACKAGE_PIN AK23 [get_ports {DBB_MYK_GPIO_4}] +set_property PACKAGE_PIN AF20 [get_ports {DBB_CH2_TX_DSA_DATA[4]}] +set_property PACKAGE_PIN AG20 [get_ports {DBB_CH2_TX_DSA_DATA[3]}] +set_property PACKAGE_PIN AF23 [get_ports {DBB_MYK_SYNC_OUT_n}] +set_property PACKAGE_PIN AF24 [get_ports {DBB_CPLD_PL_SPI_SDO}] +set_property PACKAGE_PIN AK20 [get_ports {DBB_MYK_GPIO_13}] +set_property PACKAGE_PIN AJ20 [get_ports {DBB_MYK_GPIO_0}] +set_property PACKAGE_PIN AJ23 [get_ports {DBB_MYK_INTRQ}] +set_property PACKAGE_PIN AJ24 [get_ports {DBB_CH2_TX_DSA_DATA[2]}] +set_property PACKAGE_PIN AG24 [get_ports {DBB_CH2_TX_DSA_DATA[0]}] +set_property PACKAGE_PIN AG25 [get_ports {DBB_CH2_TX_DSA_DATA[1]}] +set_property PACKAGE_PIN AG21 [get_ports {DBB_FPGA_CLK_P}] +set_property PACKAGE_PIN AH21 [get_ports {DBB_FPGA_CLK_N}] +set_property PACKAGE_PIN AE22 [get_ports {DBB_FPGA_SYSREF_P}] +set_property PACKAGE_PIN AF22 [get_ports {DBB_FPGA_SYSREF_N}] +set_property PACKAGE_PIN AJ25 [get_ports {DBB_CH2_RX_DSA_DATA[3]}] +set_property PACKAGE_PIN AK25 [get_ports {DBB_CH2_RX_DSA_DATA[5]}] +set_property PACKAGE_PIN AB21 [get_ports {DBB_CPLD_JTAG_TMS}] +set_property PACKAGE_PIN AB22 [get_ports {DBB_CPLD_JTAG_TCK}] +set_property PACKAGE_PIN AD23 [get_ports {DBB_MYK_GPIO_15}] +set_property PACKAGE_PIN AE23 [get_ports {DBB_MYK_SPI_CS_n}] +set_property PACKAGE_PIN AB24 [get_ports {DBB_CH2_RX_DSA_DATA[1]}] +set_property PACKAGE_PIN AA24 [get_ports {DBB_CH2_RX_DSA_DATA[2]}] +set_property PACKAGE_PIN AG22 [get_ports {DBB_CPLD_PL_SPI_LE}] +set_property PACKAGE_PIN AH22 [get_ports {DBB_CPLD_PL_SPI_SDI}] +set_property PACKAGE_PIN AD21 [get_ports {DBB_MYK_GPIO_12}] +set_property PACKAGE_PIN AE21 [get_ports {DBB_MYK_GPIO_14}] +set_property PACKAGE_PIN AC22 [get_ports {DBB_MYK_SPI_SCLK}] +set_property PACKAGE_PIN AC23 [get_ports {DBB_MYK_GPIO_3}] +set_property PACKAGE_PIN AC24 [get_ports {DBB_CH2_RX_DSA_DATA[0]}] +set_property PACKAGE_PIN AD24 [get_ports {DBB_CH2_RX_DSA_DATA[4]}] +set_property PACKAGE_PIN AH23 [get_ports {DBB_CPLD_PL_SPI_ADDR[2]}] +set_property PACKAGE_PIN AH24 [get_ports {DBB_CPLD_PL_SPI_SCLK}] + +# set_property PACKAGE_PIN AA25 [get_ports DBB_SWITCHER_CLOCK] +# set_property IOSTANDARD LVCMOS33 [get_ports DBB_SWITCHER_CLOCK] +# set_property DRIVE 4 [get_ports DBB_SWITCHER_CLOCK] +# set_property SLEW SLOW [get_ports DBB_SWITCHER_CLOCK] + +# During SI measurements with default drive strength, many of the FPGA-driven lines to +# the DB were showing high over/undershoot. Therefore for single-ended lines to the DBs +# we are decreasing the drive strength to the minimum value (4mA) and explicitly +# declaring the (default) slew rate as SLOW. + +set UsrpIoBHpPinsSe [get_ports {DBB_CPLD_PS_* \ + DBB_CH1_* \ + DBB_ATR*}] +set_property IOSTANDARD LVCMOS18 $UsrpIoBHpPinsSe +set_property DRIVE 4 $UsrpIoBHpPinsSe +set_property SLEW SLOW $UsrpIoBHpPinsSe + +set UsrpIoBHrPinsSe [get_ports {DBB_MYK_SPI_* \ + DBB_MYK_INTRQ \ + DBB_MYK_SYNC* \ + DBB_MYK_GPIO* \ + DBB_CPLD_PL_* \ + DBB_CPLD_JTAG_* \ + DBB_CH2*}] +set_property IOSTANDARD LVCMOS25 $UsrpIoBHrPinsSe +set_property DRIVE 4 $UsrpIoBHrPinsSe +set_property SLEW SLOW $UsrpIoBHrPinsSe + +set UsrpIoBHrPinsDiff [get_ports {DBB_FPGA_CLK_* \ + DBB_FPGA_SYSREF_*}] +set_property IOSTANDARD LVDS_25 $UsrpIoBHrPinsDiff +set_property DIFF_TERM TRUE $UsrpIoBHrPinsDiff + +# Do not allow the DSA lines to float... give them a weak pull if undriven. +set_property PULLUP TRUE [get_ports {DBB_CH*_*X_DSA_DATA[*]}] + + +### MGTs, Bank 112 + +set_property PACKAGE_PIN W8 [get_ports {USRPIO_B_MGTCLK_P}] +set_property PACKAGE_PIN W7 [get_ports {USRPIO_B_MGTCLK_N}] + +# This mapping uses the TX pins as the "master" and mimics RX off of them so Vivado +# places the transceivers in the correct places. The mixup in lanes is accounted for +# in the Mykonos lane crossbar settings. +set_property PACKAGE_PIN AC4 [get_ports {USRPIO_B_RX_P[0]}] +set_property PACKAGE_PIN AC3 [get_ports {USRPIO_B_RX_N[0]}] +set_property PACKAGE_PIN AB6 [get_ports {USRPIO_B_RX_P[1]}] +set_property PACKAGE_PIN AB5 [get_ports {USRPIO_B_RX_N[1]}] +set_property PACKAGE_PIN Y6 [get_ports {USRPIO_B_RX_P[2]}] +set_property PACKAGE_PIN Y5 [get_ports {USRPIO_B_RX_N[2]}] +set_property PACKAGE_PIN AA4 [get_ports {USRPIO_B_RX_P[3]}] +set_property PACKAGE_PIN AA3 [get_ports {USRPIO_B_RX_N[3]}] + +set_property PACKAGE_PIN AB2 [get_ports {USRPIO_B_TX_P[0]}] +set_property PACKAGE_PIN AB1 [get_ports {USRPIO_B_TX_N[0]}] +set_property PACKAGE_PIN Y2 [get_ports {USRPIO_B_TX_P[1]}] +set_property PACKAGE_PIN Y1 [get_ports {USRPIO_B_TX_N[1]}] +set_property PACKAGE_PIN W4 [get_ports {USRPIO_B_TX_P[2]}] +set_property PACKAGE_PIN W3 [get_ports {USRPIO_B_TX_N[2]}] +set_property PACKAGE_PIN V2 [get_ports {USRPIO_B_TX_P[3]}] +set_property PACKAGE_PIN V1 [get_ports {USRPIO_B_TX_N[3]}] diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd new file mode 100644 index 000000000..ffaa64f68 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd @@ -0,0 +1,345 @@ +------------------------------------------------------------------------------- +-- +-- File: ClockingRegs.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 17 March 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Register access to the control/status bits and interfaces for the +-- RadioClocking module. +-- +-- XML register definition is included below the module. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library work; + use work.PkgClockingRegMap.all; + use work.PkgRegs.all; + + +entity ClockingRegs is + port( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + -- Register Bus Clock -- this module connects the BusClk to PsClk, so it's limited + -- to 200 MHz! + BusClk : in std_logic; + + bRegPortOut : out RegPortOut_t; + bRegPortIn : in RegPortIn_t; + + -- Phase shift interface to the RadioClkMmcm. + -- There is a reset crossing here between the MMCM reset and aReset. The outgoing + -- crossing is safe because (a) the enable signal driven to the MMCM is a strobe-only + -- signal and (b) this interface should only be used when the MMCM is not in reset + -- (SW waits for the MMCM to be out of reset and locked before using this interface). + -- The only input signal, pPsDone, is double-synced in this file before being used. + -- This is OK (even though it is a strobe signal) because there is only a reset + -- crossing and not a clock domain crossing. + pPsInc : out std_logic; + pPsEn : out std_logic; + pPsDone : in std_logic; + + -- PsClk is driven directly by BusClk, so p = b in the logic below! + PsClk : out std_logic; + + -- Sync reset strobes from the register bus to the RadioClkMmcm. + bRadioClkMmcmReset : out std_logic; + -- Status of RadioClk MMCM lock to register bus. + aRadioClksValid : in std_logic; + + bRadioClk1xEnabled : out std_logic; + bRadioClk2xEnabled : out std_logic; + bRadioClk3xEnabled : out std_logic; + + bJesdRefClkPresent : in std_logic + ); +end ClockingRegs; + + +architecture RTL of ClockingRegs is + + --vhook_sigstart + --vhook_sigend + + signal bRadioClkMmcmResetInt : std_logic := '1'; + + signal bRegPortOutLcl : RegPortOut_t := kRegPortOutZero; + + signal bPsDone, + bPsEn, + bPsInc, + pPsDoneDs_ms, + pPsDoneDs : std_logic := '0'; + + signal bRadioClk1xEnabledInt, + bRadioClk2xEnabledInt, + bRadioClk3xEnabledInt, + bRadioClksValid_ms, + bRadioClksValid : std_logic := '0'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of bRadioClksValid_ms : signal is "true"; + attribute ASYNC_REG of bRadioClksValid : signal is "true"; + attribute ASYNC_REG of pPsDoneDs_ms : signal is "true"; + attribute ASYNC_REG of pPsDoneDs : signal is "true"; + +begin + + -- Locals to outputs. + PsClk <= BusClk; + pPsInc <= bPsInc; + pPsEn <= bPsEn; + + bRadioClkMmcmReset <= bRadioClkMmcmResetInt; + + bRadioClk1xEnabled <= bRadioClk1xEnabledInt; + bRadioClk2xEnabled <= bRadioClk2xEnabledInt; + bRadioClk3xEnabled <= bRadioClk3xEnabledInt; + + + -- Write Registers : ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + WriteRegisters: process(aReset, BusClk) + begin + if aReset then + bRadioClkMmcmResetInt <= '1'; + bPsInc <= '0'; + bPsEn <= '0'; + bRadioClk1xEnabledInt <= '0'; + bRadioClk2xEnabledInt <= '0'; + bRadioClk3xEnabledInt <= '0'; + elsif rising_edge(BusClk) then + + if bReset then + bRadioClkMmcmResetInt <= '1'; + bPsInc <= '0'; + bPsEn <= '0'; + bRadioClk1xEnabledInt <= '0'; + bRadioClk2xEnabledInt <= '0'; + bRadioClk3xEnabledInt <= '0'; + else + -- Clear strobe + bPsEn <= '0'; + + if RegWrite(kPhaseShiftControl, bRegPortIn) then + if bRegPortIn.Data(kPsInc) = '1' then + bPsInc <= '1'; + bPsEn <= '1'; + elsif bRegPortIn.Data(kPsDec) = '1' then + bPsInc <= '0'; + bPsEn <= '1'; + end if; + end if; + + if RegWrite(kRadioClkMmcm, bRegPortIn) then + -- Set/Clear pair + if bRegPortIn.Data(kRadioClkMmcmResetSet) = '1' then + bRadioClkMmcmResetInt <= '1'; + elsif bRegPortIn.Data(kRadioClkMmcmResetClear) = '1' then + bRadioClkMmcmResetInt <= '0'; + end if; + end if; + + if RegWrite(kRadioClkEnables, bRegPortIn) then + bRadioClk1xEnabledInt <= bRegPortIn.Data(kRadioClk1xEnabled); + bRadioClk2xEnabledInt <= bRegPortIn.Data(kRadioClk2xEnabled); + bRadioClk3xEnabledInt <= bRegPortIn.Data(kRadioClk3xEnabled); + end if; + + end if; + end if; + end process WriteRegisters; + + + DoubleSyncs : process (aReset, BusClk) + begin + if aReset then + bRadioClksValid_ms <= '0'; + bRadioClksValid <= '0'; + pPsDoneDs_ms <= '0'; + pPsDoneDs <= '0'; + elsif rising_edge(BusClk) then + -- No sync reset on double-syncs (however there are default assignments above)! + bRadioClksValid_ms <= aRadioClksValid; + bRadioClksValid <= bRadioClksValid_ms; + pPsDoneDs_ms <= pPsDone; + pPsDoneDs <= pPsDoneDs_ms; + end if; + end process; + + + -- Read Registers : ------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + ReadRegisters: process(aReset, BusClk) + begin + if aReset then + bRegPortOutLcl <= kRegPortOutZero; + bPsDone <= '0'; + elsif rising_edge(BusClk) then + + if bReset then + bRegPortOutLcl <= kRegPortOutZero; + bPsDone <= '0'; + else + -- Deassert strobes + bRegPortOutLcl.Data <= kRegPortDataZero; + + -- All of these transactions only take one clock cycle, so we do not have to + -- de-assert the Ready signal (ever). + bRegPortOutLcl.Ready <= true; + + -- Process the returned data from the phase shifter in the MMCM. Note that even + -- though the prefixes are different (p and b), we drive the PsClk from the BusClk + -- so this "crossing" is actually safe. Whenever the Done signal asserts (pPsDone - + -- pay attention to the prefix!) from the MMCM, we set a sticky bit to tell SW + -- that the shift operation is complete. + -- + -- However, if pPsDone asserts at the same time that SW tries to read the register, + -- we should accurately report that the operation is indeed complete and then NOT + -- store the sticky (since it has already been read by SW). If a read does not come + -- through at the same time pPsDone is asserted, then we store the done state as a + -- sticky, bPsDone, which is only cleared by a read to this register. + if RegRead(kPhaseShiftControl, bRegPortIn) then + -- The phase shift is always enabled for the feedback clock in RadioClocking.vhd + bRegPortOutLcl.Data(kPsEnabledForFdbClk) <= '1'; + bRegPortOutLcl.Data(kPsDone) <= bPsDone or pPsDoneDs; + bPsDone <= '0'; + elsif pPsDoneDs = '1' then + bPsDone <= '1'; + end if; + + if RegRead(kRadioClkMmcm, bRegPortIn) then + bRegPortOutLcl.Data(kRadioClkMmcmLocked) <= bRadioClksValid; + end if; + + if RegRead(kRadioClkEnables, bRegPortIn) then + bRegPortOutLcl.Data(kRadioClk1xEnabled) <= bRadioClk1xEnabledInt; + bRegPortOutLcl.Data(kRadioClk2xEnabled) <= bRadioClk2xEnabledInt; + bRegPortOutLcl.Data(kRadioClk3xEnabled) <= bRadioClk3xEnabledInt; + end if; + + if RegRead(kMgtRefClkStatus, bRegPortIn) then + bRegPortOutLcl.Data(kJesdRefClkPresent) <= bJesdRefClkPresent; + end if; + + end if; + end if; + end process ReadRegisters; + + -- Local to output + bRegPortOut <= bRegPortOutLcl; + + +end RTL; + + +--XmlParse xml_on +--<regmap name="ClockingRegMap"> +-- <group name="ClockingRegs"> +-- +-- <register name="RadioClkMmcm" size="32" offset="0x20" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="RadioClkMmcmLocked" range="4"> +-- <info> +-- Reflects the locked status of the MMCM. '1' = locked. This bit is only valid +-- when the MMCM reset is de-asserted. Read-only. +-- </info> +-- </bitfield> +-- <bitfield name="RadioClkMmcmResetClear" range="1" attributes="Strobe"> +-- <info> +-- Controls the reset to the Radio Clock MMCM. Strobe this bit to de-assert the +-- reset to the MMCM. Default is reset asserted. Write-only. +-- </info> +-- </bitfield> +-- <bitfield name="RadioClkMmcmResetSet" range="0" attributes="Strobe"> +-- <info> +-- Controls the reset to the Radio Clock MMCM. Strobe this bit to assert the +-- reset to the MMCM. Default is reset asserted. Write-only. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="PhaseShiftControl" size="32" offset="0x24" attributes="Readable|Writable"> +-- <info> +-- Phase Shift for RadioClkMmcm. +-- </info> +-- <bitfield name="PsDone" range="28"> +-- <info> +-- This bit should set after a shift operation successfully completes. +-- Reading this register will clear this bit. Read-only. +-- </info> +-- </bitfield> +-- <bitfield name="PsInc" range="0" attributes="Strobe"> +-- <info> +-- Strobe this bit to increment the phase. This bit is self-clearing and will +-- always return '0' when read. If PsInc and PsDec are asserted together, +-- the phase will increment. +-- </info> +-- </bitfield> +-- <bitfield name="PsDec" range="4" attributes="Strobe"> +-- <info> +-- Strobe this bit to decrement the phase. This bit is self-clearing and will +-- always return '0' when read. If PsInc and PsDec are asserted together, +-- the phase will increment. +-- </info> +-- </bitfield> +-- <bitfield name="PsEnabledForFdbClk" range="16"> +-- <info> +-- Read-only. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="RadioClkEnables" size="32" offset="0x28" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="RadioClk3xEnabled" range="8"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- <bitfield name="RadioClk2xEnabled" range="4"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- <bitfield name="RadioClk1xEnabled" range="0"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="MgtRefClkStatus" size="32" offset="0x30" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="JesdRefClkPresent" range="0"> +-- <info> +-- Live indicator of the MGT Reference Clock toggling and within expected +-- frequency limits. If this bit is de-asserted, then the JESD204b core will +-- not function correctly! +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +--</regmap> +--XmlParse xml_off diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd new file mode 100644 index 000000000..7f8ef388a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd @@ -0,0 +1,116 @@ +------------------------------------------------------------------------------- +-- +-- File: DaughterboardRegs.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 27 April 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Register interface to the semi-static control lines for the Mg +-- Daughterboard. +-- +-- XML register definition is included below the module. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library work; + use work.PkgDaughterboardRegMap.all; + use work.PkgRegs.all; + + +entity DaughterboardRegs is + port( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + BusClk : in std_logic; + + bRegPortOut : out RegPortOut_t; + bRegPortIn : in RegPortIn_t; + + -- Slot and DB ID values. These should be tied to constants! + kDbId : in std_logic_vector(15 downto 0); + kSlotId : in std_logic + + ); +end DaughterboardRegs; + + +architecture RTL of DaughterboardRegs is + + --vhook_sigstart + --vhook_sigend + + signal bRegPortOutLcl : RegPortOut_t := kRegPortOutZero; + +begin + + + -- Read Registers : ------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + ReadRegisters: process(aReset, BusClk) + begin + if aReset then + bRegPortOutLcl <= kRegPortOutZero; + elsif rising_edge(BusClk) then + if bReset then + bRegPortOutLcl <= kRegPortOutZero; + else + -- De-assert strobes + bRegPortOutLcl.Data <= kRegPortDataZero; + + -- All of these transactions only take one clock cycle, so we do not have to + -- de-assert the Ready signal (ever). + bRegPortOutLcl.Ready <= true; + + if RegRead(kDaughterboardId, bRegPortIn) then + bRegPortOutLcl.Data(kDbIdValMsb downto kDbIdVal) <= kDbId; + bRegPortOutLcl.Data(kSlotIdVal) <= kSlotId; + end if; + + end if; + end if; + end process ReadRegisters; + + -- Local to output + bRegPortOut <= bRegPortOutLcl; + + +end RTL; + + +--XmlParse xml_on +--<regmap name="DaughterboardRegMap"> +-- <group name="StaticControl" order="1"> +-- +-- <register name="DaughterboardId" size="32" offset="0x30" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="DbIdVal" range="15..0"> +-- <info> +-- ID for the DB with which this file is designed to communicate. Matches the DB +-- EEPROM ID. +-- </info> +-- </bitfield> +-- <bitfield name="SlotIdVal" range="16"> +-- <info> +-- ID for the Slot this module controls. Options are 0 and 1 for the N310 MB. +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +-- +--</regmap> +--XmlParse xml_off diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd new file mode 100644 index 000000000..e1369ec00 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd @@ -0,0 +1,562 @@ +------------------------------------------------------------------------------- +-- +-- File: DbCore.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 12 April 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2017-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Wrapper file for Daughterboard Control. This includes the semi-static control +-- and status registers, clocking, synchronization, and JESD204B cores. +-- +-- There is no version register for the plain-text files here. +-- Version control for the Sync and JESD204B cores is internal to the netlists. +-- +-- The resets for this core are almost entirely local and/or synchronous. +-- bBusReset is a Synchronous reset on the BusClk domain that resets all of the +-- registers connected to the RegPort, as well as any other stray registers +-- connected to the BusClk. All other resets are local to the modules they touch. +-- No other reset drives all modules universally. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgMgPersonality.all; + use work.PkgRegs.all; + use work.PkgJesdConfig.all; + + +entity DbCore is + generic( + -- Set to '1' to include the White Rabbit TDC. + kInclWhiteRabbitTdc : std_logic := '0' + ); + port( + + -- Resets -- + -- Synchronous Reset for the BusClk domain (mainly for the RegPort) + bBusReset : in std_logic; + + -- Clocks -- + -- Register Bus Clock (any frequency) + BusClk : in std_logic; + -- Always-on at 40 MHz + Clk40 : in std_logic; + -- Super secret crazy awesome measurement clock at weird frequencies. + MeasClk : in std_logic; + -- FPGA Sample Clock from DB LMK + FpgaClk_p : in std_logic; + FpgaClk_n : in std_logic; + + -- Sample Clock Sharing. The clocks generated in this module are exported out to the + -- top level so they can be shared amongst daughterboards. Therefore they must be + -- driven back into the SampleClk*x inputs at a higher level in order for this module + -- to work correctly. There are a few isolated cases where SampleClk*xOut is used + -- directly in this module, and those are documented below. + SampleClk1xOut : out std_logic; + SampleClk1x : in std_logic; + SampleClk2xOut : out std_logic; + SampleClk2x : in std_logic; + + + -- Register Ports -- + -- + -- Only synchronous resets can be used for these ports! + bRegPortInFlat : in std_logic_vector(49 downto 0); + bRegPortOutFlat : out std_logic_vector(33 downto 0); + + -- Slot ID value. This should be tied to a constant! + kSlotId : in std_logic; + + + -- SYSREF -- + -- + -- SYSREF direct from the LMK + sSysRefFpgaLvds_p, + sSysRefFpgaLvds_n : in std_logic; + -- SYNC directly to the LMK + aLmkSync : out std_logic; + + + -- JESD Signals -- + -- + -- GTX Sample Clock Reference Input. Direct connect to FPGA pins. + JesdRefClk_p, + JesdRefClk_n : in std_logic; + + -- ADC JESD PHY Interface. Direct connect to FPGA pins. + aAdcRx_p, + aAdcRx_n : in std_logic_vector(3 downto 0); + aSyncAdcOut_n : out std_logic; + + -- DAC JESD PHY Interface. Direct connect to FPGA pins. + aDacTx_p, + aDacTx_n : out std_logic_vector(3 downto 0); + aSyncDacIn_n : in std_logic; + + + -- Data Pipes to/from the DACs/ADCs -- + -- + -- - Data is presented as one sample per cycle. + -- - sAdcDataValid asserts when ADC data is valid. + -- - sDacReadyForInput asserts when DAC data is ready to be received. + -- + -- Reset Crossings: + -- The ADC data and valid outputs are synchronously cleared before the asynchronous + -- reset is asserted--preventing any reset crossing issues here between the RX + -- (internal to the core) reset and the no-reset domain of RFNoC. + -- + -- The DAC samples should be zeros on reset de-assertion due to RFI being de-asserted + -- in reset. If they are not zeros, then it is still OK because data is ignored until + -- RFI is asserted. DAC RFI is double-synchronized to protect against the reset + -- crossing. This is safe to do because it simply delays the output of RFI by two + -- cycles on the assertion edge, and as long as reset is held for more than two + -- cycles, the de-assertion edge of RFI should come long before the TX module is + -- taken out of reset. + sAdcDataValid : out std_logic; + sAdcDataSamples0I : out std_logic_vector(15 downto 0); + sAdcDataSamples0Q : out std_logic_vector(15 downto 0); + sAdcDataSamples1I : out std_logic_vector(15 downto 0); + sAdcDataSamples1Q : out std_logic_vector(15 downto 0); + sDacReadyForInput : out std_logic; + sDacDataSamples0I : in std_logic_vector(15 downto 0); + sDacDataSamples0Q : in std_logic_vector(15 downto 0); + sDacDataSamples1I : in std_logic_vector(15 downto 0); + sDacDataSamples1Q : in std_logic_vector(15 downto 0); + + + -- RefClk & Timing & Sync -- + RefClk : in std_logic; + rPpsPulse : in std_logic; + rGatedPulseToPin : inout std_logic; -- straight to pin + sGatedPulseToPin : inout std_logic; -- straight to pin + sPps : out std_logic; + sPpsToIob : out std_logic; + + -- White Rabbit Timing & Sync -- + WrRefClk : in std_logic; + rWrPpsPulse : in std_logic; + rWrGatedPulseToPin : inout std_logic; -- straight to pin + sWrGatedPulseToPin : inout std_logic; -- straight to pin + aPpsSfpSel : in std_logic_vector(1 downto 0); + + + -- Debug for JESD + sAdcSync : out std_logic; + sDacSync : out std_logic; + sSysRef : out std_logic; + + -- Debug for Timing & Sync + rRpTransfer : out std_logic; + sSpTransfer : out std_logic; + rWrRpTransfer : out std_logic; + sWrSpTransfer : out std_logic + ); + +end DbCore; + + +architecture RTL of DbCore is + + component Jesd204bXcvrCore + port ( + bBusReset : in STD_LOGIC; + BusClk : in STD_LOGIC; + ReliableClk40 : in STD_LOGIC; + FpgaClk1x : in STD_LOGIC; + FpgaClk2x : in STD_LOGIC; + bFpgaClksStable : in STD_LOGIC; + bRegPortInFlat : in STD_LOGIC_VECTOR(49 downto 0); + bRegPortOutFlat : out STD_LOGIC_VECTOR(33 downto 0); + aLmkSync : out STD_LOGIC; + cSysRefFpgaLvds_p : in STD_LOGIC; + cSysRefFpgaLvds_n : in STD_LOGIC; + fSysRef : out STD_LOGIC; + CaptureSysRefClk : in STD_LOGIC; + JesdRefClk_p : in STD_LOGIC; + JesdRefClk_n : in STD_LOGIC; + bJesdRefClkPresent : out STD_LOGIC; + aAdcRx_p : in STD_LOGIC_VECTOR(3 downto 0); + aAdcRx_n : in STD_LOGIC_VECTOR(3 downto 0); + aSyncAdcOut_n : out STD_LOGIC; + aDacTx_p : out STD_LOGIC_VECTOR(3 downto 0); + aDacTx_n : out STD_LOGIC_VECTOR(3 downto 0); + aSyncDacIn_n : in STD_LOGIC; + fAdc0DataFlat : out STD_LOGIC_VECTOR(31 downto 0); + fAdc1DataFlat : out STD_LOGIC_VECTOR(31 downto 0); + fDac0DataFlat : in STD_LOGIC_VECTOR(31 downto 0); + fDac1DataFlat : in STD_LOGIC_VECTOR(31 downto 0); + fAdcDataValid : out STD_LOGIC; + fDacReadyForInput : out STD_LOGIC; + aDacSync : out STD_LOGIC; + aAdcSync : out STD_LOGIC); + end component; + + function to_Boolean (s : std_ulogic) return boolean is + begin + return (To_X01(s)='1'); + end to_Boolean; + + function to_StdLogic(b : boolean) return std_ulogic is + begin + if b then + return '1'; + else + return '0'; + end if; + end to_StdLogic; + + --vhook_sigstart + signal aAdcSync: STD_LOGIC; + signal aDacSync: STD_LOGIC; + signal bClockingRegPortOut: RegPortOut_t; + signal bDbRegPortOut: RegPortOut_t; + signal bFpgaClksStable: STD_LOGIC; + signal bJesdCoreRegPortInFlat: STD_LOGIC_VECTOR(49 downto 0); + signal bJesdCoreRegPortOutFlat: STD_LOGIC_VECTOR(33 downto 0); + signal bJesdRefClkPresent: STD_LOGIC; + signal bRadioClk1xEnabled: std_logic; + signal bRadioClk2xEnabled: std_logic; + signal bRadioClk3xEnabled: std_logic; + signal bRadioClkMmcmReset: std_logic; + signal bRadioClksValid: std_logic; + signal pPsDone: std_logic; + signal pPsEn: std_logic; + signal pPsInc: std_logic; + signal PsClk: std_logic; + signal sAdc0DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal sAdc1DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal SampleClk1xOutLcl: std_logic; + signal sDac0DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal sDac1DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal sDacReadyForInputAsyncReset: STD_LOGIC; + signal sRegPps: std_logic; + signal sSysRefAsyncReset: STD_LOGIC; + signal sWrPps: std_logic; + --vhook_sigend + + signal bJesdRegPortInGrp, bSyncRegPortIn, bWrSyncRegPortIn, bRegPortIn : RegPortIn_t; + signal bJesdRegPortOut, bSyncRegPortOut, bWrSyncRegPortOut, bRegPortOut : RegPortOut_t; + + signal sDacReadyForInput_ms, sDacReadyForInputLcl, + sDacSync_ms, sDacSyncLcl, + sAdcSync_ms, sAdcSyncLcl, + sSysRef_ms, sSysRefLcl : std_logic := '0'; + + signal sAdc0Data, sAdc1Data : AdcData_t; + signal sDac0Data, sDac1Data : DacData_t; + + signal sPpsSfpSel_ms, sPpsSfpSel : std_logic_vector(1 downto 0) := (others => '0'); + signal sUseWrTdcPps : boolean := false; + signal sPpsInt, sPpsMuxed : std_logic := '0'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of sDacReadyForInput_ms : signal is "true"; + attribute ASYNC_REG of sDacReadyForInputLcl : signal is "true"; + attribute ASYNC_REG of sDacSync_ms : signal is "true"; + attribute ASYNC_REG of sDacSyncLcl : signal is "true"; + attribute ASYNC_REG of sAdcSync_ms : signal is "true"; + attribute ASYNC_REG of sAdcSyncLcl : signal is "true"; + attribute ASYNC_REG of sSysRef_ms : signal is "true"; + attribute ASYNC_REG of sSysRefLcl : signal is "true"; + attribute ASYNC_REG of sPpsSfpSel_ms : signal is "true"; + attribute ASYNC_REG of sPpsSfpSel : signal is "true"; + +begin + + bRegPortOutFlat <= Flatten(bRegPortOut); + bRegPortIn <= Unflatten(bRegPortInFlat); + + + -- Combine return RegPorts. + bRegPortOut <= bJesdRegPortOut + + bClockingRegPortOut + + bSyncRegPortOut + bWrSyncRegPortOut + + bDbRegPortOut; + + + -- Clocking : ------------------------------------------------------------------------- + -- Automatically export the Sample Clocks and only use the incoming clocks in the + -- remainder of the logic. For a single module, the clocks must be looped back + -- in at a higher level! + -- ------------------------------------------------------------------------------------ + + --vhook_e RadioClocking + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a RadioClk1x SampleClk1xOutLcl + --vhook_a RadioClk2x SampleClk2xOut + --vhook_a RadioClk3x open + RadioClockingx: entity work.RadioClocking (rtl) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRadioClkMmcmReset => bRadioClkMmcmReset, --in std_logic + bRadioClksValid => bRadioClksValid, --out std_logic + bRadioClk1xEnabled => bRadioClk1xEnabled, --in std_logic + bRadioClk2xEnabled => bRadioClk2xEnabled, --in std_logic + bRadioClk3xEnabled => bRadioClk3xEnabled, --in std_logic + pPsInc => pPsInc, --in std_logic + pPsEn => pPsEn, --in std_logic + PsClk => PsClk, --in std_logic + pPsDone => pPsDone, --out std_logic + FpgaClk_n => FpgaClk_n, --in std_logic + FpgaClk_p => FpgaClk_p, --in std_logic + RadioClk1x => SampleClk1xOutLcl, --out std_logic + RadioClk2x => SampleClk2xOut, --out std_logic + RadioClk3x => open); --out std_logic + + -- We need an internal copy of SampleClk1x for the TDC, since we don't want to try + -- and align the other DB's clock accidentally. + SampleClk1xOut <= SampleClk1xOutLcl; + + --vhook_e ClockingRegs + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a bRegPortOut bClockingRegPortOut + --vhook_a aRadioClksValid bRadioClksValid + ClockingRegsx: entity work.ClockingRegs (RTL) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRegPortOut => bClockingRegPortOut, --out RegPortOut_t + bRegPortIn => bRegPortIn, --in RegPortIn_t + pPsInc => pPsInc, --out std_logic + pPsEn => pPsEn, --out std_logic + pPsDone => pPsDone, --in std_logic + PsClk => PsClk, --out std_logic + bRadioClkMmcmReset => bRadioClkMmcmReset, --out std_logic + aRadioClksValid => bRadioClksValid, --in std_logic + bRadioClk1xEnabled => bRadioClk1xEnabled, --out std_logic + bRadioClk2xEnabled => bRadioClk2xEnabled, --out std_logic + bRadioClk3xEnabled => bRadioClk3xEnabled, --out std_logic + bJesdRefClkPresent => bJesdRefClkPresent); --in std_logic + + + + -- JESD204B : ------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + + bJesdRegPortInGrp <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kJesdRegGroupInDbRegs); -- 0x2000 to 0x3FFC + + -- Expand/compress the RegPort for moving through the netlist boundary. + bJesdRegPortOut <= Unflatten(bJesdCoreRegPortOutFlat); + bJesdCoreRegPortInFlat <= Flatten(bJesdRegPortInGrp); + + --vhook Jesd204bXcvrCore + --vhook_a bRegPortInFlat bJesdCoreRegPortInFlat + --vhook_a bRegPortOutFlat bJesdCoreRegPortOutFlat + --vhook_a FpgaClk1x SampleClk1x + --vhook_a FpgaClk2x SampleClk2x + --vhook_a ReliableClk40 Clk40 + --vhook_a CaptureSysRefClk SampleClk1xOutLcl + --vhook_a cSysRefFpgaLvds_p sSysRefFpgaLvds_p + --vhook_a cSysRefFpgaLvds_n sSysRefFpgaLvds_n + --vhook_a fSysRef sSysRefAsyncReset + --vhook_a fDacReadyForInput sDacReadyForInputAsyncReset + --vhook_a {^f(.*)} s$1 + Jesd204bXcvrCorex: Jesd204bXcvrCore + port map ( + bBusReset => bBusReset, --in STD_LOGIC + BusClk => BusClk, --in STD_LOGIC + ReliableClk40 => Clk40, --in STD_LOGIC + FpgaClk1x => SampleClk1x, --in STD_LOGIC + FpgaClk2x => SampleClk2x, --in STD_LOGIC + bFpgaClksStable => bFpgaClksStable, --in STD_LOGIC + bRegPortInFlat => bJesdCoreRegPortInFlat, --in STD_LOGIC_VECTOR(49:0) + bRegPortOutFlat => bJesdCoreRegPortOutFlat, --out STD_LOGIC_VECTOR(33:0) + aLmkSync => aLmkSync, --out STD_LOGIC + cSysRefFpgaLvds_p => sSysRefFpgaLvds_p, --in STD_LOGIC + cSysRefFpgaLvds_n => sSysRefFpgaLvds_n, --in STD_LOGIC + fSysRef => sSysRefAsyncReset, --out STD_LOGIC + CaptureSysRefClk => SampleClk1xOutLcl, --in STD_LOGIC + JesdRefClk_p => JesdRefClk_p, --in STD_LOGIC + JesdRefClk_n => JesdRefClk_n, --in STD_LOGIC + bJesdRefClkPresent => bJesdRefClkPresent, --out STD_LOGIC + aAdcRx_p => aAdcRx_p, --in STD_LOGIC_VECTOR(3:0) + aAdcRx_n => aAdcRx_n, --in STD_LOGIC_VECTOR(3:0) + aSyncAdcOut_n => aSyncAdcOut_n, --out STD_LOGIC + aDacTx_p => aDacTx_p, --out STD_LOGIC_VECTOR(3:0) + aDacTx_n => aDacTx_n, --out STD_LOGIC_VECTOR(3:0) + aSyncDacIn_n => aSyncDacIn_n, --in STD_LOGIC + fAdc0DataFlat => sAdc0DataFlat, --out STD_LOGIC_VECTOR(31:0) + fAdc1DataFlat => sAdc1DataFlat, --out STD_LOGIC_VECTOR(31:0) + fDac0DataFlat => sDac0DataFlat, --in STD_LOGIC_VECTOR(31:0) + fDac1DataFlat => sDac1DataFlat, --in STD_LOGIC_VECTOR(31:0) + fAdcDataValid => sAdcDataValid, --out STD_LOGIC + fDacReadyForInput => sDacReadyForInputAsyncReset, --out STD_LOGIC + aDacSync => aDacSync, --out STD_LOGIC + aAdcSync => aAdcSync); --out STD_LOGIC + + JesdDoubleSyncToNoResetSampleClk : process (SampleClk1x) + begin + if rising_edge(SampleClk1x) then + sDacReadyForInput_ms <= sDacReadyForInputAsyncReset; + sDacReadyForInputLcl <= sDacReadyForInput_ms; + -- No clock crossing here -- just reset, although the prefix declares otherwise... + sDacSync_ms <= aDacSync; + sDacSyncLcl <= sDacSync_ms; + sAdcSync_ms <= aAdcSync; + sAdcSyncLcl <= sAdcSync_ms; + sSysRef_ms <= sSysRefAsyncReset; + sSysRefLcl <= sSysRef_ms; + end if; + end process; + + -- Locals to outputs. + sDacReadyForInput <= sDacReadyForInputLcl; + sDacSync <= sDacSyncLcl; + sAdcSync <= sAdcSyncLcl; + sSysRef <= sSysRefLcl; + + -- Just combine the first two enables, since they're the ones that are used for JESD. + -- No reset crossing here, since bFpgaClksStable is only received by a no-reset domain + -- and the MGTs directly. + bFpgaClksStable <= bRadioClksValid and bRadioClk1xEnabled and bRadioClk2xEnabled; + + -- Compress/expand the flat data types from the netlist and route to top level. + sAdc0Data <= Unflatten(sAdc0DataFlat); + sAdc1Data <= Unflatten(sAdc1DataFlat); + sDac0DataFlat <= Flatten(sDac0Data); + sDac1DataFlat <= Flatten(sDac1Data); + + sAdcDataSamples0I <= sAdc0Data.I; + sAdcDataSamples0Q <= sAdc0Data.Q; + sAdcDataSamples1I <= sAdc1Data.I; + sAdcDataSamples1Q <= sAdc1Data.Q; + + sDac0Data.I <= sDacDataSamples0I; + sDac0Data.Q <= sDacDataSamples0Q; + sDac1Data.I <= sDacDataSamples1I; + sDac1Data.Q <= sDacDataSamples1Q; + + + -- Timing and Sync : ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + + bSyncRegPortIn <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kTdc0OffsetsInEndpoint); -- 0x0200 + + --vhook_e TdcWrapper + --vhook_# Use the local copy of the SampleClock, since we want the TDC to measure the + --vhook_# clock offset for this daughterboard, not the global SampleClock. + --vhook_a SampleClk SampleClk1xOutLcl + --vhook_a sPpsPulse sRegPps + TdcWrapperx: entity work.TdcWrapper (struct) + port map ( + BusClk => BusClk, --in std_logic + bBusReset => bBusReset, --in std_logic + RefClk => RefClk, --in std_logic + SampleClk => SampleClk1xOutLcl, --in std_logic + MeasClk => MeasClk, --in std_logic + bSyncRegPortOut => bSyncRegPortOut, --out RegPortOut_t + bSyncRegPortIn => bSyncRegPortIn, --in RegPortIn_t + rPpsPulse => rPpsPulse, --in std_logic + sPpsPulse => sRegPps, --out std_logic + rRpTransfer => rRpTransfer, --out std_logic + sSpTransfer => sSpTransfer, --out std_logic + rGatedPulseToPin => rGatedPulseToPin, --inout std_logic + sGatedPulseToPin => sGatedPulseToPin); --inout std_logic + + WrTdcGen: if kInclWhiteRabbitTdc = '1' generate + bWrSyncRegPortIn <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kTdc1OffsetsInEndpoint); -- 0x0400 + + --vhook_e TdcWrapper WrTdcWrapperx + --vhook_# Use the local copy of the SampleClock, since we want the TDC to measure the + --vhook_# clock offset for this daughterboard, not the global SampleClock. + --vhook_a bSyncRegPortIn bWrSyncRegPortIn + --vhook_a bSyncRegPortOut bWrSyncRegPortOut + --vhook_a SampleClk SampleClk1xOutLcl + --vhook_a RefClk WrRefClk + --vhook_a rPpsPulse rWrPpsPulse + --vhook_a sPpsPulse sWrPps + --vhook_a rRpTransfer rWrRpTransfer + --vhook_a sSpTransfer sWrSpTransfer + --vhook_a rGatedPulseToPin rWrGatedPulseToPin + --vhook_a sGatedPulseToPin sWrGatedPulseToPin + WrTdcWrapperx: entity work.TdcWrapper (struct) + port map ( + BusClk => BusClk, --in std_logic + bBusReset => bBusReset, --in std_logic + RefClk => WrRefClk, --in std_logic + SampleClk => SampleClk1xOutLcl, --in std_logic + MeasClk => MeasClk, --in std_logic + bSyncRegPortOut => bWrSyncRegPortOut, --out RegPortOut_t + bSyncRegPortIn => bWrSyncRegPortIn, --in RegPortIn_t + rPpsPulse => rWrPpsPulse, --in std_logic + sPpsPulse => sWrPps, --out std_logic + rRpTransfer => rWrRpTransfer, --out std_logic + sSpTransfer => sWrSpTransfer, --out std_logic + rGatedPulseToPin => rWrGatedPulseToPin, --inout std_logic + sGatedPulseToPin => sWrGatedPulseToPin); --inout std_logic + end generate WrTdcGen; + + WrTdcNotGen: if kInclWhiteRabbitTdc = '0' generate + bWrSyncRegPortOut <= kRegPortOutZero; + sWrPps <= '0'; + rWrRpTransfer <= '0'; + sWrSpTransfer <= '0'; + rWrGatedPulseToPin <= '0'; + sWrGatedPulseToPin <= '0'; + end generate WrTdcNotGen; + + -- Mux the output PPS based on the SFP selection bits. Encoding is one-hot, with zero + -- also a valid state. Regardless of whether the user selects SFP0 or SFP1 as the time + -- source, there is only one White Rabbit TDC, so '01' and '10' are equivalent. + -- '00': Use the PPS output from the "regular" TDC. + -- '01': Use the PPS output from the "white rabbit" TDC. + -- '10': Use the PPS output from the "white rabbit" TDC. + PpsOutputMux : process (SampleClk1xOutLcl) + begin + if rising_edge(SampleClk1xOutLcl) then + -- Double-sync the control bits to the Sample Clock domain. + sPpsSfpSel_ms <= aPpsSfpSel; + sPpsSfpSel <= sPpsSfpSel_ms; + + -- OR the control bits together to produce a single override enable for the WR TDC. + sUseWrTdcPps <= to_boolean(sPpsSfpSel(0) or sPpsSfpSel(1)); + + -- Flop the outputs. One flop for the PPS output IOB, the other for use internally. + sPpsInt <= sPpsMuxed; + end if; + end process PpsOutputMux; + + sPpsMuxed <= sWrPps when sUseWrTdcPps else sRegPps; + sPps <= sPpsInt; + sPpsToIob <= sPpsMuxed; -- No added flop here since there's an IOB outside this module. + + -- Daughterboard Control : ------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + + --vhook_e DaughterboardRegs + --vhook_# Tying this low is safe because the sync reset is used inside DaughterboardRegs. + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a bRegPortOut bDbRegPortOut + --vhook_a kDbId std_logic_vector(to_unsigned(16#150#,16)) + DaughterboardRegsx: entity work.DaughterboardRegs (RTL) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRegPortOut => bDbRegPortOut, --out RegPortOut_t + bRegPortIn => bRegPortIn, --in RegPortIn_t + kDbId => std_logic_vector(to_unsigned(16#150#,16)), --in std_logic_vector(15:0) + kSlotId => kSlotId); --in std_logic + + +end RTL; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf Binary files differnew file mode 100644 index 000000000..27619d2a0 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd new file mode 100644 index 000000000..84c461d26 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd @@ -0,0 +1,56 @@ +-- Copyright 1986-2015 Xilinx, Inc. All Rights Reserved. +-- -------------------------------------------------------------------------------- +-- Tool Version: Vivado v.2015.4.2 (win64) Build 1494164 Fri Feb 26 04:18:56 MST 2016 +-- Date : Wed Jan 10 10:53:33 2018 +-- Host : djepson-lt running 64-bit major release (build 9200) +-- Command : write_vhdl -mode synth_stub -force -file ./Jesd204bXcvrCore_stub.vhd +-- Design : Jesd204bXcvrCore +-- Purpose : Stub declaration of top-level module interface +-- Device : xc7z100ffg900-2 +-- -------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +entity Jesd204bXcvrCore is + Port ( + bBusReset : in STD_LOGIC; + BusClk : in STD_LOGIC; + ReliableClk40 : in STD_LOGIC; + FpgaClk1x : in STD_LOGIC; + FpgaClk2x : in STD_LOGIC; + bFpgaClksStable : in STD_LOGIC; + bRegPortInFlat : in STD_LOGIC_VECTOR ( 49 downto 0 ); + bRegPortOutFlat : out STD_LOGIC_VECTOR ( 33 downto 0 ); + aLmkSync : out STD_LOGIC; + cSysRefFpgaLvds_p : in STD_LOGIC; + cSysRefFpgaLvds_n : in STD_LOGIC; + fSysRef : out STD_LOGIC; + CaptureSysRefClk : in STD_LOGIC; + JesdRefClk_p : in STD_LOGIC; + JesdRefClk_n : in STD_LOGIC; + bJesdRefClkPresent : out STD_LOGIC; + aAdcRx_p : in STD_LOGIC_VECTOR ( 3 downto 0 ); + aAdcRx_n : in STD_LOGIC_VECTOR ( 3 downto 0 ); + aSyncAdcOut_n : out STD_LOGIC; + aDacTx_p : out STD_LOGIC_VECTOR ( 3 downto 0 ); + aDacTx_n : out STD_LOGIC_VECTOR ( 3 downto 0 ); + aSyncDacIn_n : in STD_LOGIC; + fAdc0DataFlat : out STD_LOGIC_VECTOR ( 31 downto 0 ); + fAdc1DataFlat : out STD_LOGIC_VECTOR ( 31 downto 0 ); + fDac0DataFlat : in STD_LOGIC_VECTOR ( 31 downto 0 ); + fDac1DataFlat : in STD_LOGIC_VECTOR ( 31 downto 0 ); + fAdcDataValid : out STD_LOGIC; + fDacReadyForInput : out STD_LOGIC; + aDacSync : out STD_LOGIC; + aAdcSync : out STD_LOGIC + ); + +end Jesd204bXcvrCore; + +architecture stub of Jesd204bXcvrCore is +attribute syn_black_box : boolean; +attribute black_box_pad_pin : string; +attribute syn_black_box of stub : architecture is true; +attribute black_box_pad_pin of stub : architecture is "bBusReset,BusClk,ReliableClk40,FpgaClk1x,FpgaClk2x,bFpgaClksStable,bRegPortInFlat[49:0],bRegPortOutFlat[33:0],aLmkSync,cSysRefFpgaLvds_p,cSysRefFpgaLvds_n,fSysRef,CaptureSysRefClk,JesdRefClk_p,JesdRefClk_n,bJesdRefClkPresent,aAdcRx_p[3:0],aAdcRx_n[3:0],aSyncAdcOut_n,aDacTx_p[3:0],aDacTx_n[3:0],aSyncDacIn_n,fAdc0DataFlat[31:0],fAdc1DataFlat[31:0],fDac0DataFlat[31:0],fDac1DataFlat[31:0],fAdcDataValid,fDacReadyForInput,aDacSync,aAdcSync"; +begin +end; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd new file mode 100644 index 000000000..03b95c100 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd @@ -0,0 +1,107 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgClockingRegMap.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgClockingRegMap is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- RadioClkMmcm : 0x20 (ClockingRegs.vhd) + -- PhaseShiftControl : 0x24 (ClockingRegs.vhd) + -- RadioClkEnables : 0x28 (ClockingRegs.vhd) + -- MgtRefClkStatus : 0x30 (ClockingRegs.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group ClockingRegs +--=============================================================================== + + -- RadioClkMmcm Register (from ClockingRegs.vhd) + constant kRadioClkMmcm : integer := 16#20#; -- Register Offset + constant kRadioClkMmcmSize: integer := 32; -- register width in bits + constant kRadioClkMmcmMask : std_logic_vector(31 downto 0) := X"00000013"; + constant kRadioClkMmcmResetSetSize : integer := 1; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetSetMsb : integer := 0; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetSet : integer := 0; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetClearSize : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmResetClearMsb : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmResetClear : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmLockedSize : integer := 1; --RadioClkMmcm:RadioClkMmcmLocked + constant kRadioClkMmcmLockedMsb : integer := 4; --RadioClkMmcm:RadioClkMmcmLocked + constant kRadioClkMmcmLocked : integer := 4; --RadioClkMmcm:RadioClkMmcmLocked + + -- PhaseShiftControl Register (from ClockingRegs.vhd) + constant kPhaseShiftControl : integer := 16#24#; -- Register Offset + constant kPhaseShiftControlSize: integer := 32; -- register width in bits + constant kPhaseShiftControlMask : std_logic_vector(31 downto 0) := X"10010011"; + constant kPsIncSize : integer := 1; --PhaseShiftControl:PsInc + constant kPsIncMsb : integer := 0; --PhaseShiftControl:PsInc + constant kPsInc : integer := 0; --PhaseShiftControl:PsInc + constant kPsDecSize : integer := 1; --PhaseShiftControl:PsDec + constant kPsDecMsb : integer := 4; --PhaseShiftControl:PsDec + constant kPsDec : integer := 4; --PhaseShiftControl:PsDec + constant kPsEnabledForFdbClkSize : integer := 1; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsEnabledForFdbClkMsb : integer := 16; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsEnabledForFdbClk : integer := 16; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsDoneSize : integer := 1; --PhaseShiftControl:PsDone + constant kPsDoneMsb : integer := 28; --PhaseShiftControl:PsDone + constant kPsDone : integer := 28; --PhaseShiftControl:PsDone + + -- RadioClkEnables Register (from ClockingRegs.vhd) + constant kRadioClkEnables : integer := 16#28#; -- Register Offset + constant kRadioClkEnablesSize: integer := 32; -- register width in bits + constant kRadioClkEnablesMask : std_logic_vector(31 downto 0) := X"00000111"; + constant kRadioClk1xEnabledSize : integer := 1; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk1xEnabledMsb : integer := 0; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk1xEnabled : integer := 0; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk2xEnabledSize : integer := 1; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk2xEnabledMsb : integer := 4; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk2xEnabled : integer := 4; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk3xEnabledSize : integer := 1; --RadioClkEnables:RadioClk3xEnabled + constant kRadioClk3xEnabledMsb : integer := 8; --RadioClkEnables:RadioClk3xEnabled + constant kRadioClk3xEnabled : integer := 8; --RadioClkEnables:RadioClk3xEnabled + + -- MgtRefClkStatus Register (from ClockingRegs.vhd) + constant kMgtRefClkStatus : integer := 16#30#; -- Register Offset + constant kMgtRefClkStatusSize: integer := 32; -- register width in bits + constant kMgtRefClkStatusMask : std_logic_vector(31 downto 0) := X"00000001"; + constant kJesdRefClkPresentSize : integer := 1; --MgtRefClkStatus:JesdRefClkPresent + constant kJesdRefClkPresentMsb : integer := 0; --MgtRefClkStatus:JesdRefClkPresent + constant kJesdRefClkPresent : integer := 0; --MgtRefClkStatus:JesdRefClkPresent + +end package; + +package body PkgClockingRegMap is + + -- function kRadioClkMmcmRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kPhaseShiftControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRadioClkEnablesRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kMgtRefClkStatusRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd new file mode 100644 index 000000000..06708cde3 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd @@ -0,0 +1,56 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgDaughterboardRegMap.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgDaughterboardRegMap is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- DaughterboardId : 0x630 (DaughterboardRegs.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group StaticControl +--=============================================================================== + + -- DaughterboardId Register (from DaughterboardRegs.vhd) + constant kDaughterboardId : integer := 16#630#; -- Register Offset + constant kDaughterboardIdSize: integer := 32; -- register width in bits + constant kDaughterboardIdMask : std_logic_vector(31 downto 0) := X"0001ffff"; + constant kDbIdValSize : integer := 16; --DaughterboardId:DbIdVal + constant kDbIdValMsb : integer := 15; --DaughterboardId:DbIdVal + constant kDbIdVal : integer := 0; --DaughterboardId:DbIdVal + constant kSlotIdValSize : integer := 1; --DaughterboardId:SlotIdVal + constant kSlotIdValMsb : integer := 16; --DaughterboardId:SlotIdVal + constant kSlotIdVal : integer := 16; --DaughterboardId:SlotIdVal + +end package; + +package body PkgDaughterboardRegMap is + + -- function kDaughterboardIdRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd new file mode 100644 index 000000000..c0f5244b5 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd @@ -0,0 +1,234 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgJesdConfig.vhd +-- Author: National Instruments +-- Original Project: NI 5840 +-- Date: 11 March 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: JESD204B setup constants and functions. These constants are shared +-- between RX and TX JESD cores. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRegs.all; + + +package PkgJesdConfig is + + -- "JESD" in ASCII - with the core number 0 or 1 on the LSb. + constant kJesdSignature : std_logic_vector(31 downto 0) := x"4a455344"; + + -- Register endpoints + constant kJesdDrpRegsInEndpoint : RegOffset_t := (kOffset => 16#0800#, -- 0x2800 to + kWidth => 16#0800#); -- 0x2FFF + + -- Selects the UsrClk2 for the transceivers. For 64-bit wide transceivers, the + -- UsrClk = 2*UserClk2 frequency. For 32-bit wide transceivers, UsrClk = UserClk2 + -- frequency. This is a generalization, the clock ratio should be confirmed based on + -- the transceiver configuration. + -- The N310 transceivers use the single rate reference, hence = false. + constant kDoubleRateUsrClk : boolean := false; + + -- For the N310, all lanes are in one quad and we use the QPLL. + constant kJesdUseQpll : boolean := true; + + constant kAdcDataWidth : integer := 16; -- ADC data width in bits + constant kDacDataWidth : integer := 16; -- DAC data width in bits + constant kSamplesPerCycle : integer := 1; -- Number of samples per SampleClk1x + + constant kGtxDrpAddrWidth : natural := 9; + constant kQpllDrpAddrWidth : natural := 8; + -- Max supported number of lanes + constant kMaxNumLanes : natural := 4; + -- Max supported number of quads (normally there is 1 quad per 4 lanes but disconnect + -- the definitions to allow quad sharing) + constant kMaxNumQuads : natural := 1; + + + -- JESD shared setup - LMFS = 4421, HD = 0 + constant kNumLanes : natural := 4; -- L + constant kNumConvs : positive := 4; -- M + constant kOctetsPerFrame : natural := 2; -- F + constant kDacJesdSamplesPerCycle : integer := 1; -- S + constant kOctetsPerLane : natural := 2; -- MGT data is kOctetsPerLane*8 = 16 bits wide + constant kNumQuads : natural := kNumLanes/4; -- 4 lanes per quad + constant kHighDensity : boolean := false; -- HD + constant kConvResBits : positive := kDacDataWidth-2; -- Converter resolution in bits + constant kConvSampleBits : positive := kDacDataWidth; -- Sample Length in bits + constant kInitLaneAlignCnt : positive := 4; + constant kFramesPerMulti : natural := 20; -- K + + -- In the N310 case we are one SPC, so this value is simply the number of frames + -- (samples) per multiframe. + constant kUserClksPerMulti : integer := kFramesPerMulti; + + + type NaturalVector is array ( natural range <>) of natural; + + -- The PCB connections are as follows: + -- + -- Transceiver MGT Channel ADC Lane DAC Lane + -- *********** *********** ******** ******** + -- GT0: X0Y8 0 0 0 + -- GT1: X0Y9 1 1 1 + -- GT2: X0Y10 2 2 2 + -- GT3: X0Y11 3 3 3 + constant kRxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- MGT => ADC (in above table) + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3 + ); + + constant kTxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- MGT => DAC lane + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3 + ); + + constant kLaneToQuadMap : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- All lanes are in one quad + 0 => 0, + 1 => 0, + 2 => 0, + 3 => 0 + ); + + + -- The master transceiver channel for channel bonding. E(kMasterBondingChannel) + -- must have the highest value decrementing to b"000" for that last channels to bond. + constant kMasterBondingChannel : integer := 1; + + -- Channel bonding occurs when a master detects a K-char sequence and aligns its + -- internal FIFO to the start of this sequence. A signal is then generated to other + -- slave transceivers that cause them to bond to the sequence - this bonding signal is + -- cascaded from master to slave to slave to slave, etc where each slave must know how + -- many levels to the master there are. The last slave to bond must be at level b"000" + -- and the master is at the highest level; the number of levels in the sequence is + -- governed by the size of the transceiver FIFO (see the Xilinx user guides for more + -- information). + type BondLevels_t is array(0 to kNumLanes - 1) of std_logic_vector(2 downto 0); + constant kBondLevel : BondLevels_t := ( + 0 => b"000", -- Control from 1 + 1 => b"001", -- Master + 2 => b"000", -- Control from 1 + 3 => b"000" -- Control from 1 + ); + + -- Option to pipeline stages to improve timing, if needed + constant kPipelineDetectCharsStage : boolean := false; + constant kPipelineCharReplStage : boolean := false; + + + -- ADC & DAC Data Types + -- + + -- ADC Words from JESD204B RX Core. The array is 4 elements wide to accommodate the + -- I & Q elements from both RX channels. + subtype AdcWord_t is std_logic_vector(kAdcDataWidth - 1 downto 0); + type AdcWordArray_t is array(4 - 1 downto 0) of AdcWord_t; + + -- Data types for manipulation and presentation to outside world. + type AdcData_t is record + I : std_logic_vector(kAdcDataWidth - 1 downto 0); + Q : std_logic_vector(kAdcDataWidth - 1 downto 0); + end record; + + type DacData_t is record + I : std_logic_vector(kDacDataWidth - 1 downto 0); + Q : std_logic_vector(kDacDataWidth - 1 downto 0); + end record; + + + -- Flattened data types for passing into and out of pre-synthesized components. + subtype AdcDataFlat_t is std_logic_vector(2*kAdcDataWidth - 1 downto 0); + subtype DacDataFlat_t is std_logic_vector(2*kDacDataWidth - 1 downto 0); + + -- Functions to convert to/from types defined above. + function Flatten (AdcData : AdcData_t) return AdcDataFlat_t; + function Unflatten(AdcData : AdcDataFlat_t) return AdcData_t; + + function Flatten (DacData : DacData_t) return DacDataFlat_t; + function Unflatten(DacData : DacDataFlat_t) return DacData_t; + + +end package; + + +package body PkgJesdConfig is + + + + + + -- Flattens AdcData_t to AdcDataFlat_t + function Flatten (AdcData : AdcData_t) return AdcDataFlat_t + is + variable ReturnVar : AdcDataFlat_t; + begin + ReturnVar := (others => '0'); + -- MSB is I + ReturnVar := AdcData.I & AdcData.Q; + return ReturnVar; + end function Flatten; + + + -- UnFlattens AdcDataFlat_t to AdcData_t + function Unflatten(AdcData : AdcDataFlat_t) return AdcData_t + is + variable ReturnVar : AdcData_t; + begin + ReturnVar := (others => (others => '0')); + -- MSB is I + ReturnVar.I := AdcData(2*kAdcDataWidth - 1 downto kAdcDataWidth); + ReturnVar.Q := AdcData( kAdcDataWidth - 1 downto 0); + return ReturnVar; + end function Unflatten; + + + + -- Flattens DacData_t to DacDataFlat_t + function Flatten (DacData : DacData_t) return DacDataFlat_t + is + variable ReturnVar : DacDataFlat_t; + begin + ReturnVar := (others => '0'); + -- MSB is I + ReturnVar := DacData.I & DacData.Q; + return ReturnVar; + end function Flatten; + + + -- UnFlattens DacDataFlat_t to DacData_t + function Unflatten(DacData : DacDataFlat_t) return DacData_t + is + variable ReturnVar : DacData_t; + begin + ReturnVar := (others => (others => '0')); + -- MSB is I + ReturnVar.I := DacData(2*kDacDataWidth - 1 downto kDacDataWidth); + ReturnVar.Q := DacData( kDacDataWidth - 1 downto 0); + return ReturnVar; + end function Unflatten; + + + + + +end package body;
\ No newline at end of file diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd new file mode 100644 index 000000000..904653a8e --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd @@ -0,0 +1,61 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgMgPersonality.vhd +-- Author: National Instruments +-- Original Project: N310 +-- Date: 13 April 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: This package contains constants and helpful functions that enable +-- the FPGA to be compiled with different features. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRegs.all; + + +package PkgMgPersonality is + + + -- RegPort Address Definitions : ------------------------------------------------------ + -- + -- DB Regs ... + -- + -- Clocking Offset: 0x 000 Width: 0x 200 + -- Tdco0 Offset: 0x 200 Width: 0x 200 + -- Tdco1 Offset: 0x 400 Width: 0x 200 + -- Daughterboard Ctrl Offset: 0x 600 Width: 0x 200 + -- Total: 0x2000 + -- JESD 2x - A Offset: 0x2000 Width: 0x1000 + -- JESD 2x - B Offset: 0x3000 Width: 0x1000 + -- Total: 0x4000 + -- Total: 0x8000 for two DBs + -- ------------------------------------------------------------------------------------ + + -- A single RegPort runs to the JESD204B Core. + constant kJesdRegGroupInDbRegs : RegOffset_t := (kOffset => 16#2000#, -- 0x2000 to + kWidth => 16#1000#); -- 0x2FFF + + -- DB Regs : -------------------------------------------------------------------------- + constant kClockingOffsetInEndpoint : RegOffset_t := (kOffset => 16#0000#, -- 0x0000 to + kWidth => 16#0200#); -- 0x01FF + constant kTdc0OffsetsInEndpoint : RegOffset_t := (kOffset => 16#0200#, -- 0x0200 to + kWidth => 16#0200#); -- 0x03FF + constant kTdc1OffsetsInEndpoint : RegOffset_t := (kOffset => 16#0400#, -- 0x0400 to + kWidth => 16#0200#); -- 0x05FF + constant kDaughterboardOffsetInEndpoint : RegOffset_t := (kOffset => 16#0600#, -- 0x0600 to + kWidth => 16#0200#); -- 0x07FF + + + + +end package PkgMgPersonality; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd new file mode 100644 index 000000000..ee0da9f84 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd @@ -0,0 +1,304 @@ +------------------------------------------------------------------------------- +-- +-- File: RadioClocking.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 22 February 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Instantiates a MMCM to produce 1x, 2x, and 3x versions of the Radio Clock +-- coming from the FPGA input pin. Handles all the buffering for the input clock. +-- Additionally allows the clocks to be turned on and off, and phase shifted. +-- +-- NOTE: This module hard-codes the MMCM settings for a SPECIFIC clock rate! +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library unisim; + use unisim.vcomponents.all; + + +entity RadioClocking is + port ( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + + -- Should be a always-on clock + BusClk : in std_logic; + + -- Sync reset to the RadioClkMmcm. + bRadioClkMmcmReset : in std_logic; + + -- Locked indication from the RadioClkMmcm in BusClk and aReset domains. + bRadioClksValid : out std_logic; + + bRadioClk1xEnabled : in std_logic; + bRadioClk2xEnabled : in std_logic; + bRadioClk3xEnabled : in std_logic; + + -- Phase shift interface for the RadioClkMmcm. PsClk must be <= 200 MHz. + pPsInc : in std_logic; + pPsEn : in std_logic; + PsClk : in std_logic; + pPsDone : out std_logic; + + -- Straight from pins. Buffer included in here. + FpgaClk_n : in std_logic; + FpgaClk_p : in std_logic; + + RadioClk1x : out std_logic; + RadioClk2x : out std_logic; + RadioClk3x : out std_logic + + ); +end RadioClocking; + + +architecture rtl of RadioClocking is + + --vhook_sigstart + signal RadioClk1xLcl: std_logic; + signal RadioClk1xPll: std_logic; + signal RadioClk2xLcl: std_logic; + signal RadioClk2xPll: std_logic; + signal RadioClk3xLcl: std_logic; + signal RadioClk3xPll: std_logic; + --vhook_sigend + + signal RadioClkMmcmFeedbackIn, + RadioClkMmcmFeedbackOut, + FpgaClkSE, + aRadioClkMmcmLocked : std_logic; + + signal bRadioClkMmcmLocked_ms, + bRadioClkMmcmLocked, + bEnableRadioClkBufgOutputs, + bEnableRadioClk1xBufgOutput, + bEnableRadioClk2xBufgOutput, + bEnableRadioClk3xBufgOutput : std_logic := '0'; + + signal aRadioClkMmcmResetInternal : std_logic := '1'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of bRadioClkMmcmLocked_ms : signal is "true"; + attribute ASYNC_REG of bRadioClkMmcmLocked : signal is "true"; + +begin + + -- Radio Clock Buffering : ------------------------------------------------------------ + -- + -- ------------------------------------------------------------------------------------ + --vhook_i IBUFDS FpgaClkIbufg hidegeneric=true + --vhook_a I FpgaClk_p + --vhook_a IB FpgaClk_n + --vhook_a O FpgaClkSE + FpgaClkIbufg: IBUFDS + port map ( + O => FpgaClkSE, --out std_ulogic + I => FpgaClk_p, --in std_ulogic + IB => FpgaClk_n); --in std_ulogic + + ResetDelay : process(aReset, BusClk) + begin + if aReset then + aRadioClkMmcmResetInternal <= '1'; + elsif rising_edge(BusClk) then + if bReset then + aRadioClkMmcmResetInternal <= '1'; + else + -- Delay by 1 to allow the BUFGs to turn off before the MMCM is reset. + aRadioClkMmcmResetInternal <= bRadioClkMmcmReset; + end if; + end if; + end process ResetDelay; + + + RadioClkMmcm: MMCME2_ADV + generic map( + COMPENSATION => "ZHOLD", + BANDWIDTH => "OPTIMIZED", + CLKFBOUT_MULT_F => 6.000, -- Feedback + CLKOUT0_DIVIDE_F => 6.000, -- Data Clock 1x, RadioClk1xPll + CLKOUT1_DIVIDE => 3, -- Data Clock 2x, RadioClk2xPll + CLKOUT2_DIVIDE => 2, -- Data Clock 3x, RadioClk3xPll + CLKOUT3_DIVIDE => 1, -- unused + CLKOUT4_DIVIDE => 1, -- unused + CLKOUT5_DIVIDE => 1, -- unused + CLKOUT6_DIVIDE => 1, -- unused + CLKFBOUT_PHASE => 0.000, -- Feedback + CLKOUT0_PHASE => 0.000, -- Data Clock 1x + CLKOUT1_PHASE => 0.000, -- Data Clock 2x + CLKOUT2_PHASE => 0.000, -- Data Clock 3x + CLKOUT3_PHASE => 0.000, -- unused + CLKOUT4_PHASE => 0.000, -- unused + CLKOUT5_PHASE => 0.000, -- unused + CLKOUT6_PHASE => 0.000, -- unused + CLKOUT0_DUTY_CYCLE => 0.500, + CLKOUT1_DUTY_CYCLE => 0.500, + CLKOUT2_DUTY_CYCLE => 0.500, + CLKOUT3_DUTY_CYCLE => 0.500, + CLKOUT4_DUTY_CYCLE => 0.500, + CLKOUT5_DUTY_CYCLE => 0.500, + CLKOUT6_DUTY_CYCLE => 0.500, + DIVCLK_DIVIDE => 1, + REF_JITTER1 => 0.010, + CLKIN1_PERIOD => 6.510, -- 153.6 MHz max + CLKFBOUT_USE_FINE_PS => true, + CLKOUT0_USE_FINE_PS => false, + CLKOUT1_USE_FINE_PS => false, + CLKOUT2_USE_FINE_PS => false, + CLKOUT3_USE_FINE_PS => false, + CLKOUT4_USE_FINE_PS => false, + CLKOUT5_USE_FINE_PS => false, + CLKOUT6_USE_FINE_PS => false, + STARTUP_WAIT => false, + CLKOUT4_CASCADE => false) + port map ( + CLKINSEL => '1', + CLKIN1 => FpgaClkSE, + CLKIN2 => '0', + CLKFBIN => RadioClkMmcmFeedbackIn, + RST => aRadioClkMmcmResetInternal, + PWRDWN => '0', + DADDR => (others => '0'), + DI => (others => '0'), + DWE => '0', + DEN => '0', + DCLK => '0', + DO => open, + DRDY => open, + PSINCDEC => pPsInc, + PSEN => pPsEn, + PSCLK => PsClk, + PSDONE => pPsDone, + CLKOUT0 => RadioClk1xPll, + CLKOUT0B => open, + CLKOUT1 => RadioClk2xPll, + CLKOUT1B => open, + CLKOUT2 => RadioClk3xPll, + CLKOUT2B => open, + CLKOUT3 => open, + CLKOUT3B => open, + CLKOUT4 => open, + CLKOUT5 => open, + CLKOUT6 => open, + CLKFBOUT => RadioClkMmcmFeedbackOut, + CLKFBOUTB => open, + LOCKED => aRadioClkMmcmLocked, + CLKINSTOPPED => open, + CLKFBSTOPPED => open); + + RadioClkMmcmFeedbackBufg: BUFG + port map ( + I => RadioClkMmcmFeedbackOut, + O => RadioClkMmcmFeedbackIn + ); + + + -- Only enable the WRAPBUFGs when the MMCM is locked. If the MMCM is ever placed in + -- reset, we turn off the clocks one cycle before the asynchronous version + -- (aRadioClkMmcmResetInternal) reaches the MMCM inputs in order to prevent + -- output glitches. + CombineEnablesForBuffers : process(aReset, BusClk) + begin + if aReset then + bRadioClkMmcmLocked_ms <= '0'; + bRadioClkMmcmLocked <= '0'; + bEnableRadioClk1xBufgOutput <= '0'; + bEnableRadioClk2xBufgOutput <= '0'; + bEnableRadioClk3xBufgOutput <= '0'; + bEnableRadioClkBufgOutputs <= '0'; + elsif rising_edge(BusClk) then + if bReset then + bRadioClkMmcmLocked_ms <= '0'; + bRadioClkMmcmLocked <= '0'; + bEnableRadioClk1xBufgOutput <= '0'; + bEnableRadioClk2xBufgOutput <= '0'; + bEnableRadioClk3xBufgOutput <= '0'; + bEnableRadioClkBufgOutputs <= '0'; + else + bRadioClkMmcmLocked_ms <= aRadioClkMmcmLocked; + bRadioClkMmcmLocked <= bRadioClkMmcmLocked_ms; + + bEnableRadioClkBufgOutputs <= bRadioClkMmcmLocked and + not bRadioClkMmcmReset; + bEnableRadioClk1xBufgOutput <= bRadioClk1xEnabled and bEnableRadioClkBufgOutputs; + bEnableRadioClk2xBufgOutput <= bRadioClk2xEnabled and bEnableRadioClkBufgOutputs; + bEnableRadioClk3xBufgOutput <= bRadioClk3xEnabled and bEnableRadioClkBufgOutputs; + end if; + end if; + end process CombineEnablesForBuffers; + + bRadioClksValid <= bEnableRadioClkBufgOutputs; + + --vhook_e WrapBufg RadioClk1xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk1xPll + --vhook_a aCe bEnableRadioClk1xBufgOutput + --vhook_a ClkOut RadioClk1xLcl + RadioClk1xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk1xPll, --in std_logic + aCe => bEnableRadioClk1xBufgOutput, --in std_logic + ClkOut => RadioClk1xLcl); --out std_logic + + --vhook_e WrapBufg RadioClk2xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk2xPll + --vhook_a aCe bEnableRadioClk2xBufgOutput + --vhook_a ClkOut RadioClk2xLcl + RadioClk2xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk2xPll, --in std_logic + aCe => bEnableRadioClk2xBufgOutput, --in std_logic + ClkOut => RadioClk2xLcl); --out std_logic + + --vhook_e WrapBufg RadioClk3xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk3xPll + --vhook_a aCe bEnableRadioClk3xBufgOutput + --vhook_a ClkOut RadioClk3xLcl + RadioClk3xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk3xPll, --in std_logic + aCe => bEnableRadioClk3xBufgOutput, --in std_logic + ClkOut => RadioClk3xLcl); --out std_logic + + + -- Assign outputs from locals. + RadioClk1x <= RadioClk1xLcl; + RadioClk2x <= RadioClk2xLcl; + RadioClk3x <= RadioClk3xLcl; + + + +end rtl; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_timing.xdc b/fpga/usrp3/top/n3xx/dboards/mg/db_timing.xdc new file mode 100644 index 000000000..142ba9ab4 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_timing.xdc @@ -0,0 +1,347 @@ +# +# Copyright 2017 Ettus Research, A National Instruments Company +# SPDX-License-Identifier: LGPL-3.0 +# +# Timing analysis is performed in "/n3xx/dboards/mg/doc/mg_timing.xlsx". See +# the spreadsheet for more details and explanations. + +#******************************************************************************* +## Daughterboard Clocks + +# 122.88, 125, and 153.6 MHz Sample Clocks are allowable. Constrain the paths to the max +# rate in order to support all rates in a single FPGA image. +set SAMPLE_CLK_PERIOD 6.510 +create_clock -name fpga_clk_a -period $SAMPLE_CLK_PERIOD [get_ports DBA_FPGA_CLK_P] +create_clock -name fpga_clk_b -period $SAMPLE_CLK_PERIOD [get_ports DBB_FPGA_CLK_P] +create_clock -name mgt_clk_dba -period $SAMPLE_CLK_PERIOD [get_ports USRPIO_A_MGTCLK_P] +create_clock -name mgt_clk_dbb -period $SAMPLE_CLK_PERIOD [get_ports USRPIO_B_MGTCLK_P] + +# The Radio Clocks coming from the DBs are synchronized together (at the ADCs) to a +# typical value of less than 100ps. To give ourselves and Vivado some margin, we claim +# here that the DB-B Radio Clock can arrive 500ps before or after the DB-A clock at +# the FPGA (note that the trace lengths of the Radio Clocks coming from the DBs to the +# FPGA are about 0.5" different, thereby incurring ~80ps of additional skew at the FPGA). +# There is one spot in the FPGA where we cross domains between the DB-A and +# DB-B clock, so we must ensure that Vivado can analyze that path safely. +set FPGA_CLK_EARLY -0.5 +set FPGA_CLK_LATE 0.5 +set_clock_latency -source -early $FPGA_CLK_EARLY [get_clocks fpga_clk_b] +set_clock_latency -source -late $FPGA_CLK_LATE [get_clocks fpga_clk_b] + +# Virtual clocks for constraining I/O (used below) +create_clock -name fpga_clk_a_v -period $SAMPLE_CLK_PERIOD +create_clock -name fpga_clk_b_v -period $SAMPLE_CLK_PERIOD + +# The set_clock_latency constraints set on fpga_clk_b are problematic when used with +# I/O timing, since the analyzer gives us a double-hit on the latency. One workaround +# (used here) is to simply swap the early and late times for the virtual clock so that +# it cancels out the source latency during analysis. I tested this by setting the +# early and late numbers to zero and then their actual value, running timing reports +# on each. The slack report matches for both cases, showing that the reversed early/late +# numbers on the virtual clock zero out the latency effects on the actual clock. +# +# Note this is not a problem for the fpga_clk_a, since no latency is added. So only apply +# it to fpga_clk_b_v. +set_clock_latency -source -early $FPGA_CLK_LATE [get_clocks fpga_clk_b_v] +set_clock_latency -source -late $FPGA_CLK_EARLY [get_clocks fpga_clk_b_v] + + + +#******************************************************************************* +## Aliases for auto-generated clocks + +create_generated_clock -name radio_clk_fb [get_pins {dba_core/RadioClockingx/RadioClkMmcm/CLKFBOUT}] +create_generated_clock -name radio_clk [get_pins {dba_core/RadioClockingx/RadioClkMmcm/CLKOUT0}] +create_generated_clock -name radio_clk_2x [get_pins {dba_core/RadioClockingx/RadioClkMmcm/CLKOUT1}] + +create_generated_clock -name radio_clk_b_fb [get_pins {dbb_core/RadioClockingx/RadioClkMmcm/CLKFBOUT}] +create_generated_clock -name radio_clk_b [get_pins {dbb_core/RadioClockingx/RadioClkMmcm/CLKOUT0}] +create_generated_clock -name radio_clk_b_2x [get_pins {dbb_core/RadioClockingx/RadioClkMmcm/CLKOUT1}] + + + +#******************************************************************************* +## Generated clocks for output busses to the daughterboard +# +# These clock definitions need to come above the set_clock_groups commands below to work! + +# Define clocks on the PL SPI clock output pins for both DBs. Actual divider values are +# set by SW at run-time. Divider values are 123, 125, or 154 based on what radio clock +# rate is set. To be ultra-conservative (which still provides 10s of ns of slack), we +# set an over-constrained divider value of 50. +set PL_SPI_DIVIDE_VAL 50 +set PL_SPI_CLK_A [get_ports DBA_CPLD_PL_SPI_SCLK] +create_generated_clock -name pl_spi_clk_a \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $PL_SPI_CLK_A]/C] \ + -divide_by $PL_SPI_DIVIDE_VAL $PL_SPI_CLK_A +set PL_SPI_CLK_B [get_ports DBB_CPLD_PL_SPI_SCLK] +create_generated_clock -name pl_spi_clk_b \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $PL_SPI_CLK_B]/C] \ + -divide_by $PL_SPI_DIVIDE_VAL $PL_SPI_CLK_B + +# Define one of the outputs of each bus as a clock (even though it isn't a clock). This +# allows us to constrain the overall bus skew with respect to one of the bus outputs. +# See the remainder of this constraint below for more details. +set DSA_CLK [get_ports {DBA_CH1_RX_DSA_DATA[0]}] +create_generated_clock -name dsa_bus_clk \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $DSA_CLK]/C] \ + -divide_by 2 $DSA_CLK + +set ATR_CLK [get_ports DBA_ATR_RX_1] +create_generated_clock -name atr_bus_clk \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $ATR_CLK]/C] \ + -divide_by 2 $ATR_CLK + +# Interface Unused +# set MGPIO_CLK [get_ports DBA_MYK_GPIO_0] +# create_generated_clock -name myk_gpio_bus_clk \ + # -source [get_pins [all_fanin -flat -only_cells -startpoints_only [get_ports $MGPIO_CLK]]/C] \ + # -divide_by 2 [get_ports $MGPIO_CLK] + + + +#******************************************************************************* +## Asynchronous clock groups + +# MGT reference clocks are also async to everything. +set_clock_groups -asynchronous -group [get_clocks mgt_clk_dba -include_generated_clocks] +set_clock_groups -asynchronous -group [get_clocks mgt_clk_dbb -include_generated_clocks] + +# fpga_clk_a and fpga_clk_b are related to one another after synchronization. +# However, we do need to declare that these clocks (both a and b) and their children +# are async to the remainder of the design. Use the wildcard at the end to grab the +# virtual clock as well as the real ones. +set_clock_groups -asynchronous -group [get_clocks {fpga_clk_a* fpga_clk_b*} -include_generated_clocks] + + + +#******************************************************************************* +## PS SPI: since these lines all come from the PS and I don't have access to the +# driving clock (or anything for that matter), I'm left with constraining the maximum +# and minimum delay on these lines, per a Xilinx AR: +# https://www.xilinx.com/support/answers/62122.html +set CPLD_SPI_OUTS [get_ports {DB*_CPLD_PS_SPI_SCLK \ + DB*_CPLD_PS_SPI_SDI \ + DB*_CPLD_PS_SPI_LE \ + DB*_CPLD_PS_SPI_ADDR[0] \ + DB*_CPLD_PS_SPI_ADDR[1]}] + +set_max_delay 12.0 -to $CPLD_SPI_OUTS +set_min_delay 3.0 -to $CPLD_SPI_OUTS + +set MYK_SPI_OUTS [get_ports {DB*_MYK_SPI_SCLK \ + DB*_MYK_SPI_SDIO \ + DB*_MYK_SPI_CS_n}] + +set_max_delay 14.0 -to $MYK_SPI_OUTS +set_min_delay 3.0 -to $MYK_SPI_OUTS + +# report_timing -to $CPLD_SPI_OUTS -max_paths 20 -delay_type min_max -name CpldSpiOutTiming +# report_timing -to $MYK_SPI_OUTS -max_paths 20 -delay_type min_max -name MykSpiOutTiming + +set MIN_IN_DELAY 2.0 +set MAX_IN_DELAY 10.0 + +set PS_SPI_INPUTS_0 [get_pins -hierarchical -filter {NAME =~ "*/PS7_i/EMIOSPI0MI"}] +set PS_SPI_INPUTS_1 [get_pins -hierarchical -filter {NAME =~ "*/PS7_i/EMIOSPI1MI"}] + +set_max_delay $MAX_IN_DELAY -to $PS_SPI_INPUTS_0 +set_min_delay $MIN_IN_DELAY -to $PS_SPI_INPUTS_0 +set_max_delay $MAX_IN_DELAY -to $PS_SPI_INPUTS_1 +set_min_delay $MIN_IN_DELAY -to $PS_SPI_INPUTS_1 + +# report_timing -to $PS_SPI_INPUTS_0 -max_paths 30 -delay_type min_max -nworst 30 -name Spi0InTiming +# report_timing -to $PS_SPI_INPUTS_1 -max_paths 30 -delay_type min_max -nworst 30 -name Spi1InTiming + + + +#******************************************************************************* +## PL SPI to the CPLD +# +# All of these lines are driven or received from flops in simple_spi_core. The CPLD +# calculations assume the FPGA has less than 20 ns of skew between the SCK and +# SDI/CS_n. Pretty easy constraint to write! See above for the clock definition. +# Do this for DBA and DBB independently. +set MAX_SKEW 20.0 +set SETUP_SKEW [expr {$MAX_SKEW / 2}] +set HOLD_SKEW [expr {$MAX_SKEW / 2}] +# Do not set the output delay constraint on the clock line! +set PORT_LIST_A [get_ports {DBA_CPLD_PL_SPI_LE \ + DBA_CPLD_PL_SPI_SDI \ + DBA_CPLD_PL_SPI_ADDR[0] \ + DBA_CPLD_PL_SPI_ADDR[1]}] +set PORT_LIST_B [get_ports {DBB_CPLD_PL_SPI_LE \ + DBB_CPLD_PL_SPI_SDI \ + DBB_CPLD_PL_SPI_ADDR[0] \ + DBB_CPLD_PL_SPI_ADDR[1]}] +# Then add the output delay on each of the ports. +set_output_delay -clock [get_clocks pl_spi_clk_a] -max -$SETUP_SKEW $PORT_LIST_A +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_a] -max -$SETUP_SKEW $PORT_LIST_A +set_output_delay -clock [get_clocks pl_spi_clk_a] -min $HOLD_SKEW $PORT_LIST_A +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_a] -min $HOLD_SKEW $PORT_LIST_A +set_output_delay -clock [get_clocks pl_spi_clk_b] -max -$SETUP_SKEW $PORT_LIST_B +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_b] -max -$SETUP_SKEW $PORT_LIST_B +set_output_delay -clock [get_clocks pl_spi_clk_b] -min $HOLD_SKEW $PORT_LIST_B +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_b] -min $HOLD_SKEW $PORT_LIST_B +# Finally, make both the setup and hold checks use the same launching and latching edges. +set_multicycle_path -setup -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_a] -start 0 +set_multicycle_path -hold -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_a] -1 +set_multicycle_path -setup -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_b] -start 0 +set_multicycle_path -hold -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_b] -1 + +# For SDO input timing (MISO), we need to look at the CPLD's constraints on turnaround +# time plus any board propagation delay. +set MISO_INPUT_A [get_ports DBA_CPLD_PL_SPI_SDO] +set MISO_INPUT_B [get_ports DBB_CPLD_PL_SPI_SDO] +set_input_delay -clock [get_clocks pl_spi_clk_a] -clock_fall -max 68.041 $MISO_INPUT_A +set_input_delay -clock [get_clocks pl_spi_clk_a] -clock_fall -min 12.218 $MISO_INPUT_A +set_input_delay -clock [get_clocks pl_spi_clk_b] -clock_fall -max 68.041 $MISO_INPUT_B +set_input_delay -clock [get_clocks pl_spi_clk_b] -clock_fall -min 12.218 $MISO_INPUT_B +# Since the input delay span is clearly more than a period of the radio_clk, we need to +# add a multicycle path here as well to define the clock divider ratio. The MISO data +# is driven on the falling edge of the SPI clock and captured on the rising edge, so we +# only have one half of a SPI clock cycle for our setup. Hold is left alone and is OK +# as-is due to the delays in the CPLD and board. +set SETUP_CYCLES [expr {$PL_SPI_DIVIDE_VAL / 2}] +set HOLD_CYCLES 0 +set_multicycle_path -setup -from [get_clocks pl_spi_clk_a] -through $MISO_INPUT_A \ + $SETUP_CYCLES +set_multicycle_path -hold -from [get_clocks pl_spi_clk_a] -through $MISO_INPUT_A -end \ + [expr {$SETUP_CYCLES + $HOLD_CYCLES - 1}] +set_multicycle_path -setup -from [get_clocks pl_spi_clk_b] -through $MISO_INPUT_B \ + $SETUP_CYCLES +set_multicycle_path -hold -from [get_clocks pl_spi_clk_b] -through $MISO_INPUT_B -end \ + [expr {$SETUP_CYCLES + $HOLD_CYCLES - 1}] + +# One of the PL_SPI_ADDR lines is used instead for the LMK SYNC strobe. This line is +# driven asynchronously. +set_output_delay -clock [get_clocks async_out_clk] 0.000 [get_ports DB*_CPLD_PL_SPI_ADDR[2]] +set_max_delay -to [get_ports DB*_CPLD_PL_SPI_ADDR[2]] 50.000 +set_min_delay -to [get_ports DB*_CPLD_PL_SPI_ADDR[2]] 0.000 + + + +#******************************************************************************* +## DSA Bus +# The DSA controls are driven from the DB-A radio clock. Although they are received async +# at the DSAs, they should be tightly constrained in the FPGA to arrive as closely as +# possible. The best way to do this is a skew constraint across all the bits. +set MAX_SKEW 2.5 +set SETUP_SKEW [expr {($MAX_SKEW / 2)+0.5}] +set HOLD_SKEW [expr {($MAX_SKEW / 2)-0.5}] +set PORT_LIST [get_ports {DB*_CH*_*X_DSA_DATA[*]}] +# Then add the output delay on each of the ports. +set_output_delay -clock [get_clocks dsa_bus_clk] -max -$SETUP_SKEW $PORT_LIST +set_output_delay -add_delay -clock_fall -clock [get_clocks dsa_bus_clk] -max -$SETUP_SKEW $PORT_LIST +set_output_delay -clock [get_clocks dsa_bus_clk] -min $HOLD_SKEW $PORT_LIST +set_output_delay -add_delay -clock_fall -clock [get_clocks dsa_bus_clk] -min $HOLD_SKEW $PORT_LIST +# Finally, make both the setup and hold checks use the same launching and latching edges. +# The clock, which is essentially one of the data lines, should arrive at the pin +# +/- MAX_DELAY compared to the other data lines, so setup and hold checks need to be +# relative to the SAME edges for both the clock and the data. +set_multicycle_path -setup -from [get_clocks radio_clk] -to [get_clocks dsa_bus_clk] -start 0 +set_multicycle_path -hold -from [get_clocks radio_clk] -to [get_clocks dsa_bus_clk] -1 +# Remove analysis from the output "clock" pin. There are ways to do this using TCL, but +# they aren't supported in XDC files... so we do it the old fashioned way. +set_output_delay -clock [get_clocks async_out_clk] 0.000 $DSA_CLK +set_max_delay -to $DSA_CLK 50.000 +set_min_delay -to $DSA_CLK 0.000 + + + +#******************************************************************************* +## ATR Bus +# The ATR bits are driven from the DB-A radio clock. Although they are received async in +# the CPLD, they should be tightly constrained in the FPGA to avoid any race conditions. +# The best way to do this is a skew constraint across all the bits. +set MAX_SKEW 2.5 +set SETUP_SKEW [expr {($MAX_SKEW / 2)+0.5}] +set HOLD_SKEW [expr {($MAX_SKEW / 2)-0.5}] +set PORT_LIST [get_ports DB*_ATR_*X_*] +# Then add the output delay on each of the ports. +set_output_delay -clock [get_clocks atr_bus_clk] -max -$SETUP_SKEW $PORT_LIST +set_output_delay -add_delay -clock_fall -clock [get_clocks atr_bus_clk] -max -$SETUP_SKEW $PORT_LIST +set_output_delay -clock [get_clocks atr_bus_clk] -min $HOLD_SKEW $PORT_LIST +set_output_delay -add_delay -clock_fall -clock [get_clocks atr_bus_clk] -min $HOLD_SKEW $PORT_LIST +# Finally, make both the setup and hold checks use the same launching and latching edges. +set_multicycle_path -setup -to [get_clocks atr_bus_clk] -start 0 +set_multicycle_path -hold -to [get_clocks atr_bus_clk] -1 +# Remove analysis from the output "clock" pin. There are ways to do this using TCL, but +# they aren't supported in XDC files... so we do it the old fashioned way. +set_output_delay -clock [get_clocks async_out_clk] 0.000 $ATR_CLK +set_max_delay -to $ATR_CLK 50.000 +set_min_delay -to $ATR_CLK 0.000 + + + +#******************************************************************************* +## Mykonos Ports +# Mykonos GPIO is driven from the DB-A radio clock. Although they are received async in +# Mykonos, they should be tightly constrained in the FPGA to avoid any race conditions. +# The best way to do this is a skew constraint across all the bits. +# set MAX_SKEW 2.5 +# set SETUP_SKEW [expr {($MAX_SKEW / 2)+0.5}] +# set HOLD_SKEW [expr {($MAX_SKEW / 2)-0.5}] +# set PORT_LIST [get_ports DB*_ATR_*X_*] +# # Then add the output delay on each of the ports. +# set_output_delay -clock [get_clocks myk_gpio_bus_clk] -max -$SETUP_SKEW $PORT_LIST +# set_output_delay -add_delay -clock_fall -clock [get_clocks myk_gpio_bus_clk] -max -$SETUP_SKEW $PORT_LIST +# set_output_delay -clock [get_clocks myk_gpio_bus_clk] -min $HOLD_SKEW $PORT_LIST +# set_output_delay -add_delay -clock_fall -clock [get_clocks myk_gpio_bus_clk] -min $HOLD_SKEW $PORT_LIST +# # Finally, make both the setup and hold checks use the same launching and latching edges. +# set_multicycle_path -setup -to [get_clocks myk_gpio_bus_clk] -start 0 +# set_multicycle_path -hold -to [get_clocks myk_gpio_bus_clk] -1 +# # Remove analysis from the output "clock" pin. There are ways to do this using TCL, but +# # they aren't supported in XDC files... so we do it the old fashioned way. +# set_output_delay -clock [get_clocks async_out_clk] 0.000 $MGPIO_CLK +# set_max_delay -to $MGPIO_CLK 50.000 +# set_min_delay -to $MGPIO_CLK 0.000 + +# Mykonos Interrupt is received asynchronously, and driven directly to the PS. +set_input_delay -clock [get_clocks async_in_clk] 0.000 [get_ports DB*_MYK_INTRQ] +set_max_delay -from [get_ports DB*_MYK_INTRQ] 50.000 +set_min_delay -from [get_ports DB*_MYK_INTRQ] 0.000 + + + +#******************************************************************************* +## SYSREF/SYNC JESD Timing +# +# SYNC is async, SYSREF is tightly timed. + +# The SYNC output for both DBs is governed by the JESD cores, which are solely driven by +# DB-A clock... but it is an asynchronous signal so we use the async_out_clk. +set_output_delay -clock [get_clocks async_out_clk] 0.000 [get_ports DB*_MYK_SYNC_IN_n] +set_max_delay -to [get_ports DB*_MYK_SYNC_IN_n] 50.000 +set_min_delay -to [get_ports DB*_MYK_SYNC_IN_n] 0.000 + +# The SYNC input for both DBs is received by the DB-A clock inside the JESD cores... but +# again, it is asynchronous and therefore uses the async_in_clk. +set_input_delay -clock [get_clocks async_in_clk] 0.000 [get_ports DB*_MYK_SYNC_OUT_n] +set_max_delay -from [get_ports DB*_MYK_SYNC_OUT_n] 50.000 +set_min_delay -from [get_ports DB*_MYK_SYNC_OUT_n] 0.000 + +# SYSREF is driven by the LMK directly to the FPGA. Timing analysis was performed once +# for the worst-case numbers across both DBs to produce one set of numbers for both DBs. +# Since we easily meet setup and hold in Vivado, then this is an acceptable approach. +# SYSREF is captured by the local clock from each DB, so we have two sets of constraints. +set_input_delay -clock fpga_clk_a_v -min -0.906 [get_ports DBA_FPGA_SYSREF_*] +set_input_delay -clock fpga_clk_a_v -max 0.646 [get_ports DBA_FPGA_SYSREF_*] + +set_input_delay -clock fpga_clk_b_v -min -0.906 [get_ports DBB_FPGA_SYSREF_*] +set_input_delay -clock fpga_clk_b_v -max 0.646 [get_ports DBB_FPGA_SYSREF_*] + + + +#******************************************************************************* +## PPS Timing + +# Due to the N3xx synchronization and clocking structure, the PPS output is driven from +# the Sample Clock domain instead of the input Reference Clock. Constrain the output as +# tightly as possible to accurately mimic the internal Sample Clock timing. +set SETUP_SKEW 2.0 +set HOLD_SKEW -0.5 +set_output_delay -clock [get_clocks fpga_clk_a_v] -max -$SETUP_SKEW [get_ports REF_1PPS_OUT] +set_output_delay -clock [get_clocks fpga_clk_a_v] -min $HOLD_SKEW [get_ports REF_1PPS_OUT] +set_multicycle_path -setup -to [get_ports REF_1PPS_OUT] -start 0 +set_multicycle_path -hold -to [get_ports REF_1PPS_OUT] -1 diff --git a/fpga/usrp3/top/n3xx/dboards/mg/doc/CPLD.md b/fpga/usrp3/top/n3xx/dboards/mg/doc/CPLD.md new file mode 100644 index 000000000..2071c46ba --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/doc/CPLD.md @@ -0,0 +1,2 @@ +Timing closure of the CPLD design relies on the pre-set seed value. The build +requires Quartus 16.1.2. diff --git a/fpga/usrp3/top/n3xx/dboards/mg/doc/mg_timing.xlsx b/fpga/usrp3/top/n3xx/dboards/mg/doc/mg_timing.xlsx Binary files differnew file mode 100644 index 000000000..c4ad8ac5c --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/doc/mg_timing.xlsx diff --git a/fpga/usrp3/top/n3xx/dboards/mg/n3xx.v b/fpga/usrp3/top/n3xx/dboards/mg/n3xx.v new file mode 100644 index 000000000..32fa84153 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/n3xx.v @@ -0,0 +1,3915 @@ +/////////////////////////////////////////////////////////////////// +/// +// Copyright 2016-2019 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: n3xx +// Description: +// Top Level for N3xx devices +// +////////////////////////////////////////////////////////////////////// + +module n3xx ( + inout [11:0] FPGA_GPIO, + + input FPGA_REFCLK_P, + input FPGA_REFCLK_N, + input REF_1PPS_IN, + input NETCLK_REF_P, + input NETCLK_REF_N, + //input REF_1PPS_IN_MGMT, + output REF_1PPS_OUT, + + //TDC + inout UNUSED_PIN_TDCA_0, + inout UNUSED_PIN_TDCA_1, + inout UNUSED_PIN_TDCA_2, + inout UNUSED_PIN_TDCA_3, + inout UNUSED_PIN_TDCB_0, + inout UNUSED_PIN_TDCB_1, + inout UNUSED_PIN_TDCB_2, + inout UNUSED_PIN_TDCB_3, + +`ifdef NPIO_LANES + input NPIO_RX0_P, + input NPIO_RX0_N, + output NPIO_TX0_P, + output NPIO_TX0_N, + input NPIO_RX1_P, + input NPIO_RX1_N, + output NPIO_TX1_P, + output NPIO_TX1_N, +`endif +`ifdef QSFP_LANES + input [`QSFP_LANES-1:0] QSFP_RX_P, + input [`QSFP_LANES-1:0] QSFP_RX_N, + output [`QSFP_LANES-1:0] QSFP_TX_P, + output [`QSFP_LANES-1:0] QSFP_TX_N, + output QSFP_RESET_B, + output QSFP_LED, + output QSFP_MODSEL_B, + output QSFP_LPMODE, + input QSFP_PRESENT_B, + input QSFP_INT_B, + inout QSFP_I2C_SCL, + inout QSFP_I2C_SDA, +`endif + //TODO: Uncomment when connected here + //input NPIO_0_RXSYNC_0_P, NPIO_0_RXSYNC_1_P, + //input NPIO_0_RXSYNC_0_N, NPIO_0_RXSYNC_1_N, + //output NPIO_0_TXSYNC_0_P, NPIO_0_TXSYNC_1_P, + //output NPIO_0_TXSYNC_0_N, NPIO_0_TXSYNC_1_N, + //input NPIO_1_RXSYNC_0_P, NPIO_1_RXSYNC_1_P, + //input NPIO_1_RXSYNC_0_N, NPIO_1_RXSYNC_1_N, + //output NPIO_1_TXSYNC_0_P, NPIO_1_TXSYNC_1_P, + //output NPIO_1_TXSYNC_0_N, NPIO_1_TXSYNC_1_N, + //input NPIO_2_RXSYNC_0_P, NPIO_2_RXSYNC_1_P, + //input NPIO_2_RXSYNC_0_N, NPIO_2_RXSYNC_1_N, + //output NPIO_2_TXSYNC_0_P, NPIO_2_TXSYNC_1_P, + //output NPIO_2_TXSYNC_0_N, NPIO_2_TXSYNC_1_N, + + //GPS + input GPS_1PPS, + //input GPS_1PPS_RAW, + + //Misc + input ENET0_CLK125, + //inout ENET0_PTP, + //output ENET0_PTP_DIR, + //inout ATSHA204_SDA, + input FPGA_PL_RESETN, // TODO: Add to reset logic + // output reg [1:0] FPGA_TEST, + //input PWR_CLK_FPGA, // TODO: check direction + input FPGA_PUDC_B, + + //White Rabbit + input WB_20MHZ_P, + input WB_20MHZ_N, + output WB_DAC_DIN, + output WB_DAC_NCLR, + output WB_DAC_NLDAC, + output WB_DAC_NSYNC, + output WB_DAC_SCLK, + + //LEDS + output PANEL_LED_GPS, + output PANEL_LED_LINK, + output PANEL_LED_PPS, + output PANEL_LED_REF, + + // ARM Connections (PS) + inout [53:0] MIO, + inout PS_SRSTB, + inout PS_CLK, + inout PS_PORB, + inout DDR_Clk, + inout DDR_Clk_n, + inout DDR_CKE, + inout DDR_CS_n, + inout DDR_RAS_n, + inout DDR_CAS_n, + inout DDR_WEB, + inout [2:0] DDR_BankAddr, + inout [14:0] DDR_Addr, + inout DDR_ODT, + inout DDR_DRSTB, + inout [31:0] DDR_DQ, + inout [3:0] DDR_DM, + inout [3:0] DDR_DQS, + inout [3:0] DDR_DQS_n, + inout DDR_VRP, + inout DDR_VRN, + + + /////////////////////////////////// + // + // High Speed SPF+ signals and clocking + // + /////////////////////////////////// + + // These clock inputs must always be enabled with a buffer regardless of the build + // target to avoid damage to the FPGA. + input NETCLK_P, + input NETCLK_N, + input MGT156MHZ_CLK1_P, + input MGT156MHZ_CLK1_N, + + input SFP_0_RX_P, input SFP_0_RX_N, + output SFP_0_TX_P, output SFP_0_TX_N, + input SFP_1_RX_P, input SFP_1_RX_N, + output SFP_1_TX_P, output SFP_1_TX_N, + + + /////////////////////////////////// + // + // DRAM Interface + // + /////////////////////////////////// + inout [31:0] ddr3_dq, // Data pins. Input for Reads, Output for Writes. + inout [3:0] ddr3_dqs_n, // Data Strobes. Input for Reads, Output for Writes. + inout [3:0] ddr3_dqs_p, + // + output [15:0] ddr3_addr, // Address + output [2:0] ddr3_ba, // Bank Address + output ddr3_ras_n, // Row Address Strobe. + output ddr3_cas_n, // Column address select + output ddr3_we_n, // Write Enable + output ddr3_reset_n, // SDRAM reset pin. + output [0:0] ddr3_ck_p, // Differential clock + output [0:0] ddr3_ck_n, + output [0:0] ddr3_cke, // Clock Enable + output [0:0] ddr3_cs_n, // Chip Select + output [3:0] ddr3_dm, // Data Mask [3] = UDM.U26, [2] = LDM.U26, ... + output [0:0] ddr3_odt, // On-Die termination enable. + // + input sys_clk_p, // Differential + input sys_clk_n, // 100MHz clock source to generate DDR3 clocking. + + + /////////////////////////////////// + // + // Supporting I/O for SPF+ interfaces + // (non high speed stuff) + // + /////////////////////////////////// + + //SFP+ 0, Slow Speed, Bank 13 3.3V + input SFP_0_I2C_NPRESENT, + output SFP_0_LED_A, + output SFP_0_LED_B, + input SFP_0_LOS, + output SFP_0_RS0, + output SFP_0_RS1, + output SFP_0_TXDISABLE, + input SFP_0_TXFAULT, + + //SFP+ 1, Slow Speed, Bank 13 3.3V + //input SFP_1_I2C_NPRESENT, + output SFP_1_LED_A, + output SFP_1_LED_B, + input SFP_1_LOS, + output SFP_1_RS0, + output SFP_1_RS1, + output SFP_1_TXDISABLE, + input SFP_1_TXFAULT, + + //USRP IO A + output DBA_CPLD_PS_SPI_SCLK, + output DBA_CPLD_PS_SPI_LE, + output DBA_CPLD_PS_SPI_SDI, + input DBA_CPLD_PS_SPI_SDO, + output [1:0] DBA_CPLD_PS_SPI_ADDR, + + output DBA_ATR_RX_1, + output DBA_ATR_RX_2, + output DBA_ATR_TX_1, + output DBA_ATR_TX_2, + + output [5:0] DBA_CH1_TX_DSA_DATA, + output [5:0] DBA_CH1_RX_DSA_DATA, + output [5:0] DBA_CH2_TX_DSA_DATA, + output [5:0] DBA_CH2_RX_DSA_DATA, + + output DBA_CPLD_PL_SPI_SCLK, + output DBA_CPLD_PL_SPI_LE, + output DBA_CPLD_PL_SPI_SDI, + input DBA_CPLD_PL_SPI_SDO, + output [2:0] DBA_CPLD_PL_SPI_ADDR, + + output DBA_MYK_SPI_SCLK, + output DBA_MYK_SPI_CS_n, + input DBA_MYK_SPI_SDO, + output DBA_MYK_SPI_SDIO, + input DBA_MYK_INTRQ, + + output DBA_MYK_SYNC_IN_n, + input DBA_MYK_SYNC_OUT_n, + + inout DBA_CPLD_JTAG_TCK, + inout DBA_CPLD_JTAG_TMS, + inout DBA_CPLD_JTAG_TDI, + input DBA_CPLD_JTAG_TDO, + + output DBA_MYK_GPIO_0, + output DBA_MYK_GPIO_1, + output DBA_MYK_GPIO_3, + output DBA_MYK_GPIO_4, + output DBA_MYK_GPIO_12, + output DBA_MYK_GPIO_13, + output DBA_MYK_GPIO_14, + output DBA_MYK_GPIO_15, + + input DBA_FPGA_CLK_P, + input DBA_FPGA_CLK_N, + input DBA_FPGA_SYSREF_P, + input DBA_FPGA_SYSREF_N, + + input USRPIO_A_MGTCLK_P, + input USRPIO_A_MGTCLK_N, + + input [3:0] USRPIO_A_RX_P, + input [3:0] USRPIO_A_RX_N, + output [3:0] USRPIO_A_TX_P, + output [3:0] USRPIO_A_TX_N + +`ifndef N300 + //USRP IO B + ,output DBB_CPLD_PS_SPI_SCLK, + output DBB_CPLD_PS_SPI_LE, + output DBB_CPLD_PS_SPI_SDI, + input DBB_CPLD_PS_SPI_SDO, + output [1:0] DBB_CPLD_PS_SPI_ADDR, + + output DBB_ATR_RX_1, + output DBB_ATR_RX_2, + output DBB_ATR_TX_1, + output DBB_ATR_TX_2, + + output [5:0] DBB_CH1_TX_DSA_DATA, + output [5:0] DBB_CH1_RX_DSA_DATA, + output [5:0] DBB_CH2_TX_DSA_DATA, + output [5:0] DBB_CH2_RX_DSA_DATA, + + output DBB_CPLD_PL_SPI_SCLK, + output DBB_CPLD_PL_SPI_LE, + output DBB_CPLD_PL_SPI_SDI, + input DBB_CPLD_PL_SPI_SDO, + output [2:0] DBB_CPLD_PL_SPI_ADDR, + + output DBB_MYK_SPI_SCLK, + output DBB_MYK_SPI_CS_n, + input DBB_MYK_SPI_SDO, + output DBB_MYK_SPI_SDIO, + input DBB_MYK_INTRQ, + + output DBB_MYK_SYNC_IN_n, + input DBB_MYK_SYNC_OUT_n, + + inout DBB_CPLD_JTAG_TCK, + inout DBB_CPLD_JTAG_TMS, + inout DBB_CPLD_JTAG_TDI, + input DBB_CPLD_JTAG_TDO, + + output DBB_MYK_GPIO_0, + output DBB_MYK_GPIO_1, + output DBB_MYK_GPIO_3, + output DBB_MYK_GPIO_4, + output DBB_MYK_GPIO_12, + output DBB_MYK_GPIO_13, + output DBB_MYK_GPIO_14, + output DBB_MYK_GPIO_15, + + input DBB_FPGA_CLK_P, + input DBB_FPGA_CLK_N, + input DBB_FPGA_SYSREF_P, + input DBB_FPGA_SYSREF_N, + + input USRPIO_B_MGTCLK_P, + input USRPIO_B_MGTCLK_N, + + input [3:0] USRPIO_B_RX_P, + input [3:0] USRPIO_B_RX_N, + output [3:0] USRPIO_B_TX_P, + output [3:0] USRPIO_B_TX_N +`endif +); + + localparam N_AXILITE_SLAVES = 4; + localparam REG_AWIDTH = 14; // log2(0x4000) + localparam QSFP_REG_AWIDTH = 17; // log2(0x20000) + localparam REG_DWIDTH = 32; + localparam FP_GPIO_OFFSET = 32; + localparam FP_GPIO_WIDTH = 12; + +`ifdef N310 + localparam NUM_RADIOS = 2; + localparam NUM_CHANNELS_PER_RADIO = 2; + localparam NUM_DBOARDS = 2; +`elsif N300 + localparam NUM_RADIOS = 1; + localparam NUM_CHANNELS_PER_RADIO = 2; + localparam NUM_DBOARDS = 1; +`endif + localparam NUM_CHANNELS = NUM_RADIOS * NUM_CHANNELS_PER_RADIO; + localparam [15:0] RFNOC_PROTOVER = {8'd1, 8'd0}; + + // Internal connections to PS + // HP0 -- High Performance port 0, FPGA is the master + wire [5:0] S_AXI_HP0_AWID; + wire [31:0] S_AXI_HP0_AWADDR; + wire [2:0] S_AXI_HP0_AWPROT; + wire S_AXI_HP0_AWVALID; + wire S_AXI_HP0_AWREADY; + wire [63:0] S_AXI_HP0_WDATA; + wire [7:0] S_AXI_HP0_WSTRB; + wire S_AXI_HP0_WVALID; + wire S_AXI_HP0_WREADY; + wire [1:0] S_AXI_HP0_BRESP; + wire S_AXI_HP0_BVALID; + wire S_AXI_HP0_BREADY; + wire [5:0] S_AXI_HP0_ARID; + wire [31:0] S_AXI_HP0_ARADDR; + wire [2:0] S_AXI_HP0_ARPROT; + wire S_AXI_HP0_ARVALID; + wire S_AXI_HP0_ARREADY; + wire [63:0] S_AXI_HP0_RDATA; + wire [1:0] S_AXI_HP0_RRESP; + wire S_AXI_HP0_RVALID; + wire S_AXI_HP0_RREADY; + wire S_AXI_HP0_RLAST; + wire [3:0] S_AXI_HP0_ARCACHE; + wire [7:0] S_AXI_HP0_AWLEN; + wire [2:0] S_AXI_HP0_AWSIZE; + wire [1:0] S_AXI_HP0_AWBURST; + wire [3:0] S_AXI_HP0_AWCACHE; + wire S_AXI_HP0_WLAST; + wire [7:0] S_AXI_HP0_ARLEN; + wire [1:0] S_AXI_HP0_ARBURST; + wire [2:0] S_AXI_HP0_ARSIZE; + + // GP0 -- General Purpose port 0, FPGA is the master + wire [4:0] S_AXI_GP0_AWID; + wire [31:0] S_AXI_GP0_AWADDR; + wire [2:0] S_AXI_GP0_AWPROT; + wire S_AXI_GP0_AWVALID; + wire S_AXI_GP0_AWREADY; + wire [31:0] S_AXI_GP0_WDATA; + wire [3:0] S_AXI_GP0_WSTRB; + wire S_AXI_GP0_WVALID; + wire S_AXI_GP0_WREADY; + wire [1:0] S_AXI_GP0_BRESP; + wire S_AXI_GP0_BVALID; + wire S_AXI_GP0_BREADY; + wire [4:0] S_AXI_GP0_ARID; + wire [31:0] S_AXI_GP0_ARADDR; + wire [2:0] S_AXI_GP0_ARPROT; + wire S_AXI_GP0_ARVALID; + wire S_AXI_GP0_ARREADY; + wire [31:0] S_AXI_GP0_RDATA; + wire [1:0] S_AXI_GP0_RRESP; + wire S_AXI_GP0_RVALID; + wire S_AXI_GP0_RREADY; + wire S_AXI_GP0_RLAST; + wire [3:0] S_AXI_GP0_ARCACHE; + wire [7:0] S_AXI_GP0_AWLEN; + wire [2:0] S_AXI_GP0_AWSIZE; + wire [1:0] S_AXI_GP0_AWBURST; + wire [3:0] S_AXI_GP0_AWCACHE; + wire S_AXI_GP0_WLAST; + wire [7:0] S_AXI_GP0_ARLEN; + wire [1:0] S_AXI_GP0_ARBURST; + wire [2:0] S_AXI_GP0_ARSIZE; + + // HP1 -- High Performance port 1, FPGA is the master + wire [5:0] S_AXI_HP1_AWID; + wire [31:0] S_AXI_HP1_AWADDR; + wire [2:0] S_AXI_HP1_AWPROT; + wire S_AXI_HP1_AWVALID; + wire S_AXI_HP1_AWREADY; + wire [63:0] S_AXI_HP1_WDATA; + wire [7:0] S_AXI_HP1_WSTRB; + wire S_AXI_HP1_WVALID; + wire S_AXI_HP1_WREADY; + wire [1:0] S_AXI_HP1_BRESP; + wire S_AXI_HP1_BVALID; + wire S_AXI_HP1_BREADY; + wire [5:0] S_AXI_HP1_ARID; + wire [31:0] S_AXI_HP1_ARADDR; + wire [2:0] S_AXI_HP1_ARPROT; + wire S_AXI_HP1_ARVALID; + wire S_AXI_HP1_ARREADY; + wire [63:0] S_AXI_HP1_RDATA; + wire [1:0] S_AXI_HP1_RRESP; + wire S_AXI_HP1_RVALID; + wire S_AXI_HP1_RREADY; + wire S_AXI_HP1_RLAST; + wire [3:0] S_AXI_HP1_ARCACHE; + wire [7:0] S_AXI_HP1_AWLEN; + wire [2:0] S_AXI_HP1_AWSIZE; + wire [1:0] S_AXI_HP1_AWBURST; + wire [3:0] S_AXI_HP1_AWCACHE; + wire S_AXI_HP1_WLAST; + wire [7:0] S_AXI_HP1_ARLEN; + wire [1:0] S_AXI_HP1_ARBURST; + wire [2:0] S_AXI_HP1_ARSIZE; + + // GP1 -- General Purpose port 1, FPGA is the master + wire [4:0] S_AXI_GP1_AWID; + wire [31:0] S_AXI_GP1_AWADDR; + wire [2:0] S_AXI_GP1_AWPROT; + wire S_AXI_GP1_AWVALID; + wire S_AXI_GP1_AWREADY; + wire [31:0] S_AXI_GP1_WDATA; + wire [3:0] S_AXI_GP1_WSTRB; + wire S_AXI_GP1_WVALID; + wire S_AXI_GP1_WREADY; + wire [1:0] S_AXI_GP1_BRESP; + wire S_AXI_GP1_BVALID; + wire S_AXI_GP1_BREADY; + wire [4:0] S_AXI_GP1_ARID; + wire [31:0] S_AXI_GP1_ARADDR; + wire [2:0] S_AXI_GP1_ARPROT; + wire S_AXI_GP1_ARVALID; + wire S_AXI_GP1_ARREADY; + wire [31:0] S_AXI_GP1_RDATA; + wire [1:0] S_AXI_GP1_RRESP; + wire S_AXI_GP1_RVALID; + wire S_AXI_GP1_RREADY; + wire S_AXI_GP1_RLAST; + wire [3:0] S_AXI_GP1_ARCACHE; + wire [7:0] S_AXI_GP1_AWLEN; + wire [2:0] S_AXI_GP1_AWSIZE; + wire [1:0] S_AXI_GP1_AWBURST; + wire [3:0] S_AXI_GP1_AWCACHE; + wire S_AXI_GP1_WLAST; + wire [7:0] S_AXI_GP1_ARLEN; + wire [1:0] S_AXI_GP1_ARBURST; + wire [2:0] S_AXI_GP1_ARSIZE; + + // GP0 -- General Purpose port 0, FPGA is the slave + wire M_AXI_GP0_ARVALID; + wire M_AXI_GP0_AWVALID; + wire M_AXI_GP0_BREADY; + wire M_AXI_GP0_RREADY; + wire M_AXI_GP0_WVALID; + wire [11:0] M_AXI_GP0_ARID; + wire [11:0] M_AXI_GP0_AWID; + wire [11:0] M_AXI_GP0_WID; + wire [31:0] M_AXI_GP0_ARADDR; + wire [31:0] M_AXI_GP0_AWADDR; + wire [31:0] M_AXI_GP0_WDATA; + wire [3:0] M_AXI_GP0_WSTRB; + wire M_AXI_GP0_ARREADY; + wire M_AXI_GP0_AWREADY; + wire M_AXI_GP0_BVALID; + wire M_AXI_GP0_RLAST; + wire M_AXI_GP0_RVALID; + wire M_AXI_GP0_WREADY; + wire [1:0] M_AXI_GP0_BRESP; + wire [1:0] M_AXI_GP0_RRESP; + wire [31:0] M_AXI_GP0_RDATA; + + wire M_AXI_ETH_DMA0_ARVALID; + wire M_AXI_ETH_DMA0_AWVALID; + wire M_AXI_ETH_DMA0_BREADY; + wire M_AXI_ETH_DMA0_RREADY; + wire M_AXI_ETH_DMA0_WVALID; + wire [11:0] M_AXI_ETH_DMA0_ARID; + wire [11:0] M_AXI_ETH_DMA0_AWID; + wire [11:0] M_AXI_ETH_DMA0_WID; + wire [31:0] M_AXI_ETH_DMA0_ARADDR; + wire [31:0] M_AXI_ETH_DMA0_AWADDR; + wire [31:0] M_AXI_ETH_DMA0_WDATA; + wire [3:0] M_AXI_ETH_DMA0_WSTRB; + wire M_AXI_ETH_DMA0_ARREADY; + wire M_AXI_ETH_DMA0_AWREADY; + wire M_AXI_ETH_DMA0_BVALID; + wire M_AXI_ETH_DMA0_RLAST; + wire M_AXI_ETH_DMA0_RVALID; + wire M_AXI_ETH_DMA0_WREADY; + wire [1:0] M_AXI_ETH_DMA0_BRESP; + wire [1:0] M_AXI_ETH_DMA0_RRESP; + wire [31:0] M_AXI_ETH_DMA0_RDATA; + + wire M_AXI_NET0_ARVALID; + wire M_AXI_NET0_AWVALID; + wire M_AXI_NET0_BREADY; + wire M_AXI_NET0_RREADY; + wire M_AXI_NET0_WVALID; + wire [11:0] M_AXI_NET0_ARID; + wire [11:0] M_AXI_NET0_AWID; + wire [11:0] M_AXI_NET0_WID; + wire [31:0] M_AXI_NET0_ARADDR; + wire [31:0] M_AXI_NET0_AWADDR; + wire [31:0] M_AXI_NET0_WDATA; + wire [3:0] M_AXI_NET0_WSTRB; + wire M_AXI_NET0_ARREADY; + wire M_AXI_NET0_AWREADY; + wire M_AXI_NET0_BVALID; + wire M_AXI_NET0_RLAST; + wire M_AXI_NET0_RVALID; + wire M_AXI_NET0_WREADY; + wire [1:0] M_AXI_NET0_BRESP; + wire [1:0] M_AXI_NET0_RRESP; + wire [31:0] M_AXI_NET0_RDATA; + + wire M_AXI_ETH_DMA1_ARVALID; + wire M_AXI_ETH_DMA1_AWVALID; + wire M_AXI_ETH_DMA1_BREADY; + wire M_AXI_ETH_DMA1_RREADY; + wire M_AXI_ETH_DMA1_WVALID; + wire [11:0] M_AXI_ETH_DMA1_ARID; + wire [11:0] M_AXI_ETH_DMA1_AWID; + wire [11:0] M_AXI_ETH_DMA1_WID; + wire [31:0] M_AXI_ETH_DMA1_ARADDR; + wire [31:0] M_AXI_ETH_DMA1_AWADDR; + wire [31:0] M_AXI_ETH_DMA1_WDATA; + wire [3:0] M_AXI_ETH_DMA1_WSTRB; + wire M_AXI_ETH_DMA1_ARREADY; + wire M_AXI_ETH_DMA1_AWREADY; + wire M_AXI_ETH_DMA1_BVALID; + wire M_AXI_ETH_DMA1_RLAST; + wire M_AXI_ETH_DMA1_RVALID; + wire M_AXI_ETH_DMA1_WREADY; + wire [1:0] M_AXI_ETH_DMA1_BRESP; + wire [1:0] M_AXI_ETH_DMA1_RRESP; + wire [31:0] M_AXI_ETH_DMA1_RDATA; + + wire M_AXI_NET1_ARVALID; + wire M_AXI_NET1_AWVALID; + wire M_AXI_NET1_BREADY; + wire M_AXI_NET1_RREADY; + wire M_AXI_NET1_WVALID; + wire [11:0] M_AXI_NET1_ARID; + wire [11:0] M_AXI_NET1_AWID; + wire [11:0] M_AXI_NET1_WID; + wire [31:0] M_AXI_NET1_ARADDR; + wire [31:0] M_AXI_NET1_AWADDR; + wire [31:0] M_AXI_NET1_WDATA; + wire [3:0] M_AXI_NET1_WSTRB; + wire M_AXI_NET1_ARREADY; + wire M_AXI_NET1_AWREADY; + wire M_AXI_NET1_BVALID; + wire M_AXI_NET1_RLAST; + wire M_AXI_NET1_RVALID; + wire M_AXI_NET1_WREADY; + wire [1:0] M_AXI_NET1_BRESP; + wire [1:0] M_AXI_NET1_RRESP; + wire [31:0] M_AXI_NET1_RDATA; + + wire M_AXI_NET2_ARVALID; + wire M_AXI_NET2_AWVALID; + wire M_AXI_NET2_BREADY; + wire M_AXI_NET2_RREADY; + wire M_AXI_NET2_WVALID; + wire [11:0] M_AXI_NET2_ARID; + wire [11:0] M_AXI_NET2_AWID; + wire [11:0] M_AXI_NET2_WID; + wire [31:0] M_AXI_NET2_ARADDR; + wire [31:0] M_AXI_NET2_AWADDR; + wire [31:0] M_AXI_NET2_WDATA; + wire [3:0] M_AXI_NET2_WSTRB; + wire M_AXI_NET2_ARREADY; + wire M_AXI_NET2_AWREADY; + wire M_AXI_NET2_BVALID; + wire M_AXI_NET2_RLAST; + wire M_AXI_NET2_RVALID; + wire M_AXI_NET2_WREADY; + wire [1:0] M_AXI_NET2_BRESP; + wire [1:0] M_AXI_NET2_RRESP; + wire [31:0] M_AXI_NET2_RDATA; + + wire M_AXI_XBAR_ARVALID; + wire M_AXI_XBAR_AWVALID; + wire M_AXI_XBAR_BREADY; + wire M_AXI_XBAR_RREADY; + wire M_AXI_XBAR_WVALID; + wire [11:0] M_AXI_XBAR_ARID; + wire [11:0] M_AXI_XBAR_AWID; + wire [11:0] M_AXI_XBAR_WID; + wire [31:0] M_AXI_XBAR_ARADDR; + wire [31:0] M_AXI_XBAR_AWADDR; + wire [31:0] M_AXI_XBAR_WDATA; + wire [3:0] M_AXI_XBAR_WSTRB; + wire M_AXI_XBAR_ARREADY; + wire M_AXI_XBAR_AWREADY; + wire M_AXI_XBAR_BVALID; + wire M_AXI_XBAR_RLAST; + wire M_AXI_XBAR_RVALID; + wire M_AXI_XBAR_WREADY; + wire [1:0] M_AXI_XBAR_BRESP; + wire [1:0] M_AXI_XBAR_RRESP; + wire [31:0] M_AXI_XBAR_RDATA; + + wire M_AXI_JESD0_ARVALID; + wire M_AXI_JESD0_AWVALID; + wire M_AXI_JESD0_BREADY; + wire M_AXI_JESD0_RREADY; + wire M_AXI_JESD0_WVALID; + wire [11:0] M_AXI_JESD0_ARID; + wire [11:0] M_AXI_JESD0_AWID; + wire [11:0] M_AXI_JESD0_WID; + wire [31:0] M_AXI_JESD0_ARADDR; + wire [31:0] M_AXI_JESD0_AWADDR; + wire [31:0] M_AXI_JESD0_WDATA; + wire [3:0] M_AXI_JESD0_WSTRB; + wire M_AXI_JESD0_ARREADY; + wire M_AXI_JESD0_AWREADY; + wire M_AXI_JESD0_BVALID; + wire M_AXI_JESD0_RLAST; + wire M_AXI_JESD0_RVALID; + wire M_AXI_JESD0_WREADY; + wire [1:0] M_AXI_JESD0_BRESP; + wire [1:0] M_AXI_JESD0_RRESP; + wire [31:0] M_AXI_JESD0_RDATA; + + wire M_AXI_JESD1_ARVALID; + wire M_AXI_JESD1_AWVALID; + wire M_AXI_JESD1_BREADY; + wire M_AXI_JESD1_RREADY; + wire M_AXI_JESD1_WVALID; + wire [11:0] M_AXI_JESD1_ARID; + wire [11:0] M_AXI_JESD1_AWID; + wire [11:0] M_AXI_JESD1_WID; + wire [31:0] M_AXI_JESD1_ARADDR; + wire [31:0] M_AXI_JESD1_AWADDR; + wire [31:0] M_AXI_JESD1_WDATA; + wire [3:0] M_AXI_JESD1_WSTRB; + wire M_AXI_JESD1_ARREADY; + wire M_AXI_JESD1_AWREADY; + wire M_AXI_JESD1_BVALID; + wire M_AXI_JESD1_RLAST; + wire M_AXI_JESD1_RVALID; + wire M_AXI_JESD1_WREADY; + wire [1:0] M_AXI_JESD1_BRESP; + wire [1:0] M_AXI_JESD1_RRESP; + wire [31:0] M_AXI_JESD1_RDATA; + + // White Rabbit + wire wr_uart_txd; + wire wr_uart_rxd; + wire pps_wr_refclk; + wire wr_ref_clk; + + // AXI bus from PS to WR Core + wire m_axi_wr_clk; + wire [31:0] m_axi_wr_araddr; + wire [0:0] m_axi_wr_arready; + wire [0:0] m_axi_wr_arvalid; + wire [31:0] m_axi_wr_awaddr; + wire [0:0] m_axi_wr_awready; + wire [0:0] m_axi_wr_awvalid; + wire [0:0] m_axi_wr_bready; + wire [1:0] m_axi_wr_bresp; + wire [0:0] m_axi_wr_bvalid; + wire [31:0] m_axi_wr_rdata; + wire [0:0] m_axi_wr_rready; + wire [1:0] m_axi_wr_rresp; + wire [0:0] m_axi_wr_rvalid; + wire [31:0] m_axi_wr_wdata; + wire [0:0] m_axi_wr_wready; + wire [3:0] m_axi_wr_wstrb; + wire [0:0] m_axi_wr_wvalid; + + wire [63:0] ps_gpio_out; + wire [63:0] ps_gpio_in; + wire [63:0] ps_gpio_tri; + + wire [15:0] IRQ_F2P; + wire FCLK_CLK0; + wire FCLK_CLK1; + wire FCLK_CLK2; + wire FCLK_CLK3; + wire clk100; + wire clk40; + wire meas_clk_ref; + wire bus_clk; + wire gige_refclk; + wire gige_refclk_bufg; + wire xgige_refclk; + wire xgige_clk156; + wire xgige_dclk; + + wire global_rst; + wire radio_rst; + wire bus_rst; + wire FCLK_RESET0_N; + wire clk40_rst; + wire clk40_rstn; + + wire [1:0] USB0_PORT_INDCTL; + wire USB0_VBUS_PWRSELECT; + wire USB0_VBUS_PWRFAULT; + + wire ref_clk; + wire wr_refclk_buf; + wire netclk_buf; + wire meas_clk; + wire ddr3_dma_clk; + wire meas_clk_reset; + wire meas_clk_locked; + wire enable_ref_clk_async; + wire pps_radioclk1x_iob; + wire pps_radioclk1x; + wire [3:0] pps_select; + wire pps_out_enb; + wire [1:0] pps_select_sfp; + wire pps_refclk; + wire export_pps_radioclk; + wire radio_clk; + wire radio_clk_2x; + + wire qsfp_sda_i; + wire qsfp_sda_o; + wire qsfp_sda_t; + wire qsfp_scl_i; + wire qsfp_scl_o; + wire qsfp_scl_t; + + ///////////////////////////////////////////////////////////////////// + // + // Resets + // + ////////////////////////////////////////////////////////////////////// + + // Global synchronous reset, on the bus_clk domain. De-asserts after 85 + // bus_clk cycles. Asserted by default. + por_gen por_gen(.clk(bus_clk), .reset_out(global_rst)); + + // Synchronous reset for the radio_clk domain, based on the global_rst. + reset_sync radio_reset_gen ( + .clk(radio_clk), + .reset_in(global_rst), + .reset_out(radio_rst) + ); + + // Synchronous reset for the bus_clk domain, based on the global_rst. + reset_sync bus_reset_gen ( + .clk(bus_clk), + .reset_in(global_rst), + .reset_out(bus_rst) + ); + + + // PS-based Resets // + // + // Synchronous reset for the clk40 domain. This is derived from the PS reset 0. + reset_sync clk40_reset_gen ( + .clk(clk40), + .reset_in(~FCLK_RESET0_N), + .reset_out(clk40_rst) + ); + // Invert for various modules. + assign clk40_rstn = ~clk40_rst; + + + ///////////////////////////////////////////////////////////////////// + // + // Timing + // + ////////////////////////////////////////////////////////////////////// + + // Clocks from the PS + // + // These clocks appear to have BUFGs already instantiated by the ip generator. + // Simply rename them here for clarity. + // FCLK_CLK0 : 100 MHz + // FCLK_CLK1 : 40 MHz + // FCLK_CLK2 : 166.6667 MHz + // FCLK_CLK3 : 200 MHz + assign clk100 = FCLK_CLK0; + assign clk40 = FCLK_CLK1; + assign meas_clk_ref = FCLK_CLK2; + assign bus_clk = FCLK_CLK3; + + //If bus_clk freq ever changes, update this paramter accordingly. + localparam BUS_CLK_RATE = 32'd200000000; //200 MHz bus_clk rate. + + n3xx_clocking n3xx_clocking_i ( + .enable_ref_clk_async(enable_ref_clk_async), + .FPGA_REFCLK_P(FPGA_REFCLK_P), + .FPGA_REFCLK_N(FPGA_REFCLK_N), + .ref_clk(ref_clk), + .WB_20MHz_P(WB_20MHZ_P), + .WB_20MHz_N(WB_20MHZ_N), + .wr_refclk_buf(wr_refclk_buf), + .NETCLK_REF_P(NETCLK_REF_P), + .NETCLK_REF_N(NETCLK_REF_N), + .netclk_buf(netclk_buf), + .NETCLK_P(NETCLK_P), + .NETCLK_N(NETCLK_N), + .gige_refclk_buf(gige_refclk), + .MGT156MHZ_CLK1_P(MGT156MHZ_CLK1_P), + .MGT156MHZ_CLK1_N(MGT156MHZ_CLK1_N), + .xgige_refclk_buf(xgige_refclk), + .misc_clks_ref(meas_clk_ref), + .meas_clk(meas_clk), + .ddr3_dma_clk(ddr3_dma_clk), + .misc_clks_reset(meas_clk_reset), + .misc_clks_locked(meas_clk_locked), + .ext_pps_from_pin(REF_1PPS_IN), + .gps_pps_from_pin(GPS_1PPS), + .pps_select(pps_select), + .pps_refclk(pps_refclk) + ); + + // Drive the rear panel connector with another controllable copy of the post-TDC PPS + // that SW can enable/disable. The user is free to hack this to be whatever + // they desire. Flop the PPS signal one more time in order that it can be packed into + // an IOB. This extra flop stage matches the additional flop inside DbCore to allow + // pps_radioclk1x and pps_out_radioclk to be in sync with one another. + synchronizer #( + .FALSE_PATH_TO_IN(0) + ) pps_export_dsync ( + .clk(radio_clk), .rst(1'b0), .in(pps_out_enb), .out(export_pps_radioclk) + ); + + // The radio_clk rate is between [122.88M, 250M] for all known N3xx variants, + // resulting in approximately [8ns, 4ns] periods. To pulse-extend the PPS output, + // we create a 25 bit-wide counter, creating ~[.262s, .131s] long output high pulses, + // variable depending on our radio_clk rate. Create two of the same output signal + // in order that the PPS_OUT gets packed into an IOB for tight timing. + reg [24:0] pps_out_count = 'b0; + reg pps_out_radioclk = 1'b0; + reg pps_led_radioclk = 1'b0; + + always @(posedge radio_clk) begin + if (export_pps_radioclk) begin + if (pps_radioclk1x_iob) begin + pps_out_radioclk <= 1'b1; + pps_led_radioclk <= 1'b1; + pps_out_count <= {25{1'b1}}; + end else begin + if (pps_out_count > 0) begin + pps_out_count <= pps_out_count - 1'b1; + end else begin + pps_out_radioclk <= 1'b0; + pps_led_radioclk <= 1'b0; + end + end + end else begin + pps_out_radioclk <= 1'b0; + pps_led_radioclk <= 1'b0; + end + end + // Local to output. + assign REF_1PPS_OUT = pps_out_radioclk; + assign PANEL_LED_PPS = pps_led_radioclk; + + ///////////////////////////////////////////////////////////////////// + // + // SFP, QSFP and NPIO MGT Connections + // + ////////////////////////////////////////////////////////////////////// + wire reg_wr_req_npio; + wire [REG_AWIDTH-1:0] reg_wr_addr_npio; + wire [REG_DWIDTH-1:0] reg_wr_data_npio; + wire reg_rd_req_npio; + wire [REG_AWIDTH-1:0] reg_rd_addr_npio; + wire reg_rd_resp_npio, reg_rd_resp_npio0, reg_rd_resp_npio1; + wire [REG_DWIDTH-1:0] reg_rd_data_npio, reg_rd_data_npio0, reg_rd_data_npio1; + + localparam NPIO_REG_BASE = 14'h0200; + + regport_resp_mux #( + .WIDTH (REG_DWIDTH), + .NUM_SLAVES (2) + ) npio_resp_mux_i( + .clk(bus_clk), .reset(bus_rst), + .sla_rd_resp({reg_rd_resp_npio0, reg_rd_resp_npio1}), + .sla_rd_data({reg_rd_data_npio0, reg_rd_data_npio1}), + .mst_rd_resp(reg_rd_resp_npio), .mst_rd_data(reg_rd_data_npio) + ); + + //-------------------------------------------------------------- + // SFP/MGT Reference Clocks + //-------------------------------------------------------------- + + // We support the HG, XG, XA, AA targets, all of which require + // the 156.25MHz reference clock. Instantiate it here. + ten_gige_phy_clk_gen xgige_clk_gen_i ( + .refclk_ibuf(xgige_refclk), + .clk156(xgige_clk156), + .dclk(xgige_dclk) + ); + + wire qpllreset; + wire qpllreset_sfp0, qpllreset_sfp1, qpllreset_npio0, qpllreset_npio1; + wire qplllock; + wire qplloutclk; + wire qplloutrefclk; + + // We reuse this GT_COMMON wrapper for both ethernet and Aurora because + // the behavior is identical + ten_gig_eth_pcs_pma_gt_common # ( + .WRAPPER_SIM_GTRESET_SPEEDUP("TRUE") //Does not affect hardware + ) ten_gig_eth_pcs_pma_gt_common_block ( + .refclk(xgige_refclk), + .qpllreset(qpllreset), //from 2nd sfp + .qplllock(qplllock), + .qplloutclk(qplloutclk), + .qplloutrefclk(qplloutrefclk), + .qpllrefclksel(3'b101 /*GTSOUTHREFCLK0*/) + ); + + // The quad's QPLL should reset if any of the channels request it + // This should never really happen because we are not changing the reference clock + // source for the QPLL. + assign qpllreset = qpllreset_sfp0 | qpllreset_sfp1 | qpllreset_npio0 | qpllreset_npio1; + + // Use the 156.25MHz reference clock for Aurora + wire aurora_refclk = xgige_refclk; + wire aurora_clk156 = xgige_clk156; + wire aurora_init_clk = xgige_dclk; + + // White Rabbit and 1GbE both use the same clocking +`ifdef SFP0_1GBE + `define SFP0_WR_1GBE +`endif +`ifdef SFP0_WR + `define SFP0_WR_1GBE +`endif + +`ifdef SFP0_WR_1GBE + // HG and WX targets require the 1GbE clock support + BUFG bufg_gige_refclk_i ( + .I(gige_refclk), + .O(gige_refclk_bufg) + ); + assign SFP_0_RS0 = 1'b0; + assign SFP_0_RS1 = 1'b0; +`else + assign SFP_0_RS0 = 1'b1; + assign SFP_0_RS1 = 1'b1; +`endif + + // SFP 1 is always set to run at ~10Gbps rates. + assign SFP_1_RS0 = 1'b1; + assign SFP_1_RS1 = 1'b1; + + // SFP port specific reference clocks + wire sfp0_gt_refclk, sfp1_gt_refclk; + wire sfp0_gb_refclk, sfp1_gb_refclk; + wire sfp0_misc_clk, sfp1_misc_clk; + +`ifdef SFP0_10GBE + assign sfp0_gt_refclk = xgige_refclk; + assign sfp0_gb_refclk = xgige_clk156; + assign sfp0_misc_clk = xgige_dclk; +`endif +`ifdef SFP0_WR_1GBE + assign sfp0_gt_refclk = gige_refclk; + assign sfp0_gb_refclk = gige_refclk_bufg; + assign sfp0_misc_clk = gige_refclk_bufg; +`endif +`ifdef SFP0_AURORA + assign sfp0_gt_refclk = aurora_refclk; + assign sfp0_gb_refclk = aurora_clk156; + assign sfp0_misc_clk = aurora_init_clk; +`endif + +`ifdef SFP1_10GBE + assign sfp1_gt_refclk = xgige_refclk; + assign sfp1_gb_refclk = xgige_clk156; + assign sfp1_misc_clk = xgige_dclk; +`endif +`ifdef SFP1_1GBE + assign sfp1_gt_refclk = gige_refclk; + assign sfp1_gb_refclk = gige_refclk_bufg; + assign sfp1_misc_clk = gige_refclk_bufg; +`endif +`ifdef SFP1_AURORA + assign sfp1_gt_refclk = aurora_refclk; + assign sfp1_gb_refclk = aurora_clk156; + assign sfp1_misc_clk = aurora_init_clk; +`endif + + // Instantiate Aurora MMCM if either of the SFPs + // or NPIOs are Aurora + wire au_tx_clk; + wire au_mmcm_reset; + wire au_user_clk; + wire au_sync_clk; + wire au_mmcm_locked; + wire sfp0_tx_out_clk, sfp1_tx_out_clk; + wire sfp0_gt_pll_lock, sfp1_gt_pll_lock; + wire npio0_tx_out_clk, npio1_tx_out_clk; + wire npio0_gt_pll_lock, npio1_gt_pll_lock; + + //NOTE: need to declare one of these defines in order to enable Aurora on + //any SFP or NPIO lane. +`ifdef SFP1_AURORA + `define SFP_AU_MMCM + assign au_tx_clk = sfp1_tx_out_clk; + assign au_mmcm_reset = ~sfp1_gt_pll_lock; +`elsif NPIO0 + `define SFP_AU_MMCM + assign au_tx_clk = npio0_tx_out_clk; + assign au_mmcm_reset = ~npio0_gt_pll_lock; +`elsif NPIO1 + `define SFP_AU_MMCM + assign au_tx_clk = npio1_tx_out_clk; + assign au_mmcm_reset = ~npio1_gt_pll_lock; +`endif + + +`ifdef SFP_AU_MMCM + aurora_phy_mmcm au_phy_mmcm_i ( + .aurora_tx_clk_unbuf(au_tx_clk), + .mmcm_reset(au_mmcm_reset), + .user_clk(au_user_clk), + .sync_clk(au_sync_clk), + .mmcm_locked(au_mmcm_locked) + ); +`else + assign au_user_clk = 1'b0; + assign au_sync_clk = 1'b0; + assign au_mmcm_locked = 1'b0; +`endif + + //-------------------------------------------------------------- + // NPIO-QSFP MGT Lanes (Example loopback config) + //-------------------------------------------------------------- + +`ifdef QSFP_LANES + localparam NUM_QSFP_LANES = `QSFP_LANES; + + // QSFP wires to the ARM core and the crossbar + // These will only be connected if QSFP is 2x10 GbE + wire [NUM_QSFP_LANES*64-1:0] arm_eth_qsfp_tx_tdata_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_tx_tvalid_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_tx_tlast_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_tx_tready_b; + wire [NUM_QSFP_LANES*4-1:0] arm_eth_qsfp_tx_tuser_b; + wire [NUM_QSFP_LANES*8-1:0] arm_eth_qsfp_tx_tkeep_b; + + wire [NUM_QSFP_LANES*64-1:0] arm_eth_qsfp_rx_tdata_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_rx_tvalid_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_rx_tlast_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_rx_tready_b; + wire [NUM_QSFP_LANES*4-1:0] arm_eth_qsfp_rx_tuser_b; + wire [NUM_QSFP_LANES*8-1:0] arm_eth_qsfp_rx_tkeep_b; + + wire [NUM_QSFP_LANES*64-1:0] v2e_qsfp_tdata; + wire [NUM_QSFP_LANES-1:0] v2e_qsfp_tlast; + wire [NUM_QSFP_LANES-1:0] v2e_qsfp_tvalid; + wire [NUM_QSFP_LANES-1:0] v2e_qsfp_tready; + + wire [NUM_QSFP_LANES*64-1:0] e2v_qsfp_tdata; + wire [NUM_QSFP_LANES-1:0] e2v_qsfp_tlast; + wire [NUM_QSFP_LANES-1:0] e2v_qsfp_tvalid; + wire [NUM_QSFP_LANES-1:0] e2v_qsfp_tready; + + wire [NUM_QSFP_LANES-1:0] qsfp_link_up; + + // QSFP quad's specific reference clocks + wire qsfp_gt_refclk; + wire qsfp_gb_refclk; + wire qsfp_misc_clk; + + wire qsfp_qplloutclk; + wire qsfp_qplloutrefclk; + wire qsfp_qplllock; + wire qsfp_qpllreset; + + wire qsfp_gt_tx_out_clk; + wire qsfp_gt_pll_lock; + + wire qsfp_au_user_clk; + wire qsfp_au_sync_clk; + wire qsfp_au_mmcm_locked; + + +`ifdef QSFP_10GBE + assign qsfp_gt_refclk = xgige_refclk; + assign qsfp_gb_refclk = xgige_clk156; + assign qsfp_misc_clk = xgige_dclk; +`endif +`ifdef QSFP_AURORA + assign qsfp_gt_refclk = aurora_refclk; + assign qsfp_gb_refclk = aurora_clk156; + assign qsfp_misc_clk = aurora_init_clk; +`endif + + // We reuse this GT_COMMON wrapper for both ethernet and Aurora because + // the behavior is identical + ten_gig_eth_pcs_pma_gt_common # ( + .WRAPPER_SIM_GTRESET_SPEEDUP("TRUE") //Does not affect hardware + ) qsfp_gt_common_block ( + .refclk(xgige_refclk), + .qpllreset(qsfp_qpllreset), + .qplllock(qsfp_qplllock), + .qplloutclk(qsfp_qplloutclk), + .qplloutrefclk(qsfp_qplloutrefclk), + .qpllrefclksel(3'b001 /*GTREFCLK0*/) + ); + + `ifdef QSFP_AURORA + aurora_phy_mmcm aurora_phy_mmcm ( + .aurora_tx_clk_unbuf(qsfp_gt_tx_out_clk), + .mmcm_reset(~qsfp_gt_pll_lock), + .user_clk(qsfp_au_user_clk), + .sync_clk(qsfp_au_sync_clk), + .mmcm_locked(qsfp_au_mmcm_locked) + ); + `else + assign qsfp_au_user_clk = 1'b0; + assign qsfp_au_sync_clk = 1'b0; + assign qsfp_au_mmcm_locked = 1'b0; + `endif + + n3xx_mgt_channel_wrapper #( + `ifdef QSFP_10GBE + .PROTOCOL ("10GbE"), + .MDIO_EN (1'b1), + .MDIO_PHYADDR (5'd4), + `elsif QSFP_AURORA + .PROTOCOL ("Aurora"), + .MDIO_EN (1'b0), + `endif + .LANES (NUM_QSFP_LANES), + .PORTNUM_BASE (4), + .REG_DWIDTH (REG_DWIDTH), + .REG_AWIDTH (QSFP_REG_AWIDTH) + ) qsfp_wrapper_i ( + .areset (global_rst), + .gt_refclk (qsfp_gt_refclk), + .gb_refclk (qsfp_gb_refclk), + .misc_clk (qsfp_misc_clk), + .user_clk (qsfp_au_user_clk), + .sync_clk (qsfp_au_sync_clk), + .gt_tx_out_clk_unbuf(qsfp_gt_tx_out_clk), + + .bus_clk (bus_clk), + .bus_rst (bus_rst), + + // GT Common + .qpllrefclklost (), + .qplllock (qsfp_qplllock), + .qplloutclk (qsfp_qplloutclk), + .qplloutrefclk (qsfp_qplloutrefclk), + .qpllreset (qsfp_qpllreset), + + // Aurora MMCM + .mmcm_locked (qsfp_au_mmcm_locked), + .gt_pll_lock (qsfp_gt_pll_lock), + + .txp (QSFP_TX_P), + .txn (QSFP_TX_N), + .rxp (QSFP_RX_P), + .rxn (QSFP_RX_N), + + .mod_present_n (QSFP_PRESENT_B), + .mod_rxlos (1'b0), + .mod_tx_fault (1'b0), + .mod_tx_disable (), + .mod_int_n (QSFP_INT_B), + .mod_reset_n (QSFP_RESET_B), + .mod_lpmode (QSFP_LPMODE), + .mod_sel_n (QSFP_MODSEL_B), + + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_aresetn (clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr (M_AXI_NET2_AWADDR[QSFP_REG_AWIDTH-1:0]), + .s_axi_awvalid (M_AXI_NET2_AWVALID), + .s_axi_awready (M_AXI_NET2_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata (M_AXI_NET2_WDATA), + .s_axi_wstrb (M_AXI_NET2_WSTRB), + .s_axi_wvalid (M_AXI_NET2_WVALID), + .s_axi_wready (M_AXI_NET2_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp (M_AXI_NET2_BRESP), + .s_axi_bvalid (M_AXI_NET2_BVALID), + .s_axi_bready (M_AXI_NET2_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr (M_AXI_NET2_ARADDR[QSFP_REG_AWIDTH-1:0]), + .s_axi_arvalid (M_AXI_NET2_ARVALID), + .s_axi_arready (M_AXI_NET2_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata (M_AXI_NET2_RDATA), + .s_axi_rresp (M_AXI_NET2_RRESP), + .s_axi_rvalid (M_AXI_NET2_RVALID), + .s_axi_rready (M_AXI_NET2_RREADY), + + // Ethernet to Vita + .e2v_tdata (e2v_qsfp_tdata), + .e2v_tlast (e2v_qsfp_tlast), + .e2v_tvalid (e2v_qsfp_tvalid), + .e2v_tready (e2v_qsfp_tready), + + // Vita to Ethernet + .v2e_tdata (v2e_qsfp_tdata), + .v2e_tlast (v2e_qsfp_tlast), + .v2e_tvalid (v2e_qsfp_tvalid), + .v2e_tready (v2e_qsfp_tready), + + // Ethernet to CPU + .e2c_tdata (arm_eth_qsfp_rx_tdata_b), + .e2c_tkeep (arm_eth_qsfp_rx_tkeep_b), + .e2c_tlast (arm_eth_qsfp_rx_tlast_b), + .e2c_tvalid (arm_eth_qsfp_rx_tvalid_b), + .e2c_tready (arm_eth_qsfp_rx_tready_b), + + // CPU to Ethernet + .c2e_tdata (arm_eth_qsfp_tx_tdata_b), + .c2e_tkeep (arm_eth_qsfp_tx_tkeep_b), + .c2e_tlast (arm_eth_qsfp_tx_tlast_b), + .c2e_tvalid (arm_eth_qsfp_tx_tvalid_b), + .c2e_tready (arm_eth_qsfp_tx_tready_b), + + // Sideband White Rabbit Control + .wr_reset_n (1'b1), + .wr_refclk (1'b0), + + .wr_dac_sclk (), + .wr_dac_din (), + .wr_dac_clr_n (), + .wr_dac_cs_n (), + .wr_dac_ldac_n (), + + .wr_eeprom_scl_o(), + .wr_eeprom_scl_i(1'b0), + .wr_eeprom_sda_o(), + .wr_eeprom_sda_i(1'b0), + + .wr_uart_rx (1'b0), + .wr_uart_tx (), + + .mod_pps (), + .mod_refclk (), + + // WR AXI Control + .wr_axi_aclk (), + .wr_axi_aresetn (1'b1), + .wr_axi_awaddr (), + .wr_axi_awvalid (), + .wr_axi_awready (), + .wr_axi_wdata (), + .wr_axi_wstrb (), + .wr_axi_wvalid (), + .wr_axi_wready (), + .wr_axi_bresp (), + .wr_axi_bvalid (), + .wr_axi_bready (), + .wr_axi_araddr (), + .wr_axi_arvalid (), + .wr_axi_arready (), + .wr_axi_rdata (), + .wr_axi_rresp (), + .wr_axi_rvalid (), + .wr_axi_rready (), + .wr_axi_rlast (), + + .port_info (), + .device_id (device_id), + + .link_up (qsfp_link_up), + .activity () + ); + + assign QSFP_I2C_SCL = qsfp_scl_t ? 1'bz : qsfp_scl_o; + assign qsfp_scl_i = QSFP_I2C_SCL; + assign QSFP_I2C_SDA = qsfp_sda_t ? 1'bz : qsfp_sda_o; + assign qsfp_sda_i = QSFP_I2C_SDA; + + assign QSFP_LED = |qsfp_link_up; +`else + + axi_dummy #( + .DEC_ERR(1'b0) + ) inst_axi_dummy_qsfp ( + .s_axi_aclk(bus_clk), + .s_axi_areset(bus_rst), + + .s_axi_awaddr(M_AXI_NET2_AWADDR), + .s_axi_awvalid(M_AXI_NET2_AWVALID), + .s_axi_awready(M_AXI_NET2_AWREADY), + + .s_axi_wdata(M_AXI_NET2_WDATA), + .s_axi_wvalid(M_AXI_NET2_WVALID), + .s_axi_wready(M_AXI_NET2_WREADY), + + .s_axi_bresp(M_AXI_NET2_BRESP), + .s_axi_bvalid(M_AXI_NET2_BVALID), + .s_axi_bready(M_AXI_NET2_BREADY), + + .s_axi_araddr(M_AXI_NET2_ARADDR), + .s_axi_arvalid(M_AXI_NET2_ARVALID), + .s_axi_arready(M_AXI_NET2_ARREADY), + + .s_axi_rdata(M_AXI_NET2_RDATA), + .s_axi_rresp(M_AXI_NET2_RRESP), + .s_axi_rvalid(M_AXI_NET2_RVALID), + .s_axi_rready(M_AXI_NET2_RREADY) + + ); + + assign qsfp_scl_i = qsfp_scl_t ? 1'b1 : qsfp_scl_o; + assign qsfp_sda_i = qsfp_sda_t ? 1'b1 : qsfp_sda_o; + +`endif + + //-------------------------------------------------------------- + // NPIO MGT Lanes (Example loopback config) + //-------------------------------------------------------------- + +`ifdef NPIO_LANES + + wire [127:0] npio_loopback_tdata; + wire [1:0] npio_loopback_tvalid; + wire [1:0] npio_loopback_tready; + wire [1:0] npio_loopback_tlast; + + n3xx_mgt_io_core #( + .PROTOCOL ("Aurora"), + .REG_BASE (NPIO_REG_BASE + 14'h00), + .REG_DWIDTH (REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH (REG_AWIDTH), // Width of the address bus + .PORTNUM (8'd2), + .MDIO_EN (0) + ) npio_ln_0_i ( + .areset (global_rst), + .gt_refclk (aurora_refclk), + .gb_refclk (aurora_clk156), + .misc_clk (aurora_init_clk), + .user_clk (au_user_clk), + .sync_clk (au_sync_clk), + .gt_tx_out_clk_unbuf(npio0_tx_out_clk), + + .bus_clk (bus_clk),//clk for status reg reads to mdio interface + .bus_rst (bus_rst), + .qpllreset (qpllreset_npio0), + .qplloutclk (qplloutclk), + .qplloutrefclk (qplloutrefclk), + .qplllock (qplllock), + .qpllrefclklost (), + + .rxp (NPIO_RX0_P), + .rxn (NPIO_RX0_N), + .txp (NPIO_TX0_P), + .txn (NPIO_TX0_N), + + .sfpp_rxlos (1'b0), + .sfpp_tx_fault (1'b0), + + //RegPort + .reg_wr_req (reg_wr_req_npio), + .reg_wr_addr (reg_wr_addr_npio), + .reg_wr_data (reg_wr_data_npio), + .reg_rd_req (reg_rd_req_npio), + .reg_rd_addr (reg_rd_addr_npio), + .reg_rd_resp (reg_rd_resp_npio0), + .reg_rd_data (reg_rd_data_npio0), + + //DATA (loopback mode) + .s_axis_tdata (npio_loopback_tdata[63:0]), //Data to aurora core + .s_axis_tuser (4'b0), + .s_axis_tvalid (npio_loopback_tvalid[0]), + .s_axis_tlast (npio_loopback_tlast[0]), + .s_axis_tready (npio_loopback_tready[0]), + .m_axis_tdata (npio_loopback_tdata[63:0]), //Data from aurora core + .m_axis_tuser (), + .m_axis_tvalid (npio_loopback_tvalid[0]), + .m_axis_tlast (npio_loopback_tlast[0]), + .m_axis_tready (npio_loopback_tready[0]), + + .mmcm_locked (au_mmcm_locked), + .gt_pll_lock (npio0_gt_pll_lock) + ); + + n3xx_mgt_io_core #( + .PROTOCOL ("Aurora"), + .REG_BASE (NPIO_REG_BASE + 14'h40), + .REG_DWIDTH (REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH (REG_AWIDTH), // Width of the address bus + .PORTNUM (8'd3), + .MDIO_EN (0) + ) npio_ln_1_i ( + .areset (global_rst), + .gt_refclk (aurora_refclk), + .gb_refclk (aurora_clk156), + .misc_clk (aurora_init_clk), + .user_clk (au_user_clk), + .sync_clk (au_sync_clk), + .gt_tx_out_clk_unbuf(npio1_tx_out_clk), + + .bus_clk (bus_clk),//clk for status reg reads to mdio interface + .bus_rst (bus_rst), + .qpllreset (qpllreset_npio1), + .qplloutclk (qplloutclk), + .qplloutrefclk (qplloutrefclk), + .qplllock (qplllock), + .qpllrefclklost (), + + .rxp (NPIO_RX1_P), + .rxn (NPIO_RX1_N), + .txp (NPIO_TX1_P), + .txn (NPIO_TX1_N), + + .sfpp_rxlos (1'b0), + .sfpp_tx_fault (1'b0), + + //RegPort + .reg_wr_req (reg_wr_req_npio), + .reg_wr_addr (reg_wr_addr_npio), + .reg_wr_data (reg_wr_data_npio), + .reg_rd_req (reg_rd_req_npio), + .reg_rd_addr (reg_rd_addr_npio), + .reg_rd_resp (reg_rd_resp_npio1), + .reg_rd_data (reg_rd_data_npio1), + + //DATA (loopback mode) + .s_axis_tdata (npio_loopback_tdata[127:64]), //Data to aurora core + .s_axis_tuser (4'b0), + .s_axis_tvalid (npio_loopback_tvalid[1]), + .s_axis_tlast (npio_loopback_tlast[1]), + .s_axis_tready (npio_loopback_tready[1]), + .m_axis_tdata (npio_loopback_tdata[127:64]), //Data from aurora core + .m_axis_tuser (), + .m_axis_tvalid (npio_loopback_tvalid[1]), + .m_axis_tlast (npio_loopback_tlast[1]), + .m_axis_tready (npio_loopback_tready[1]), + + .mmcm_locked (au_mmcm_locked), + .gt_pll_lock (npio1_gt_pll_lock) + ); + +`else + + assign reg_rd_resp_npio0 = 1'b0; + assign reg_rd_data_npio0 = 'h0; + assign reg_rd_resp_npio1 = 1'b0; + assign reg_rd_data_npio1 = 'h0; + assign npio0_gt_pll_lock = 1'b1; + assign npio1_gt_pll_lock = 1'b1; + assign qpllreset_npio0 = 1'b0; + assign qpllreset_npio1 = 1'b0; + +`endif + + + // ARM ethernet 0 bridge signals + wire [63:0] arm_eth0_tx_tdata; + wire arm_eth0_tx_tvalid; + wire arm_eth0_tx_tlast; + wire arm_eth0_tx_tready; + wire [3:0] arm_eth0_tx_tuser; + wire [7:0] arm_eth0_tx_tkeep; + + wire [63:0] arm_eth0_tx_tdata_b; + wire arm_eth0_tx_tvalid_b; + wire arm_eth0_tx_tlast_b; + wire arm_eth0_tx_tready_b; + wire [3:0] arm_eth0_tx_tuser_b; + wire [7:0] arm_eth0_tx_tkeep_b; + + wire [63:0] arm_eth_sfp0_tx_tdata_b; + wire arm_eth_sfp0_tx_tvalid_b; + wire arm_eth_sfp0_tx_tlast_b; + wire arm_eth_sfp0_tx_tready_b; + wire [3:0] arm_eth_sfp0_tx_tuser_b; + wire [7:0] arm_eth_sfp0_tx_tkeep_b; + + wire [63:0] arm_eth0_rx_tdata; + wire arm_eth0_rx_tvalid; + wire arm_eth0_rx_tlast; + wire arm_eth0_rx_tready; + wire [3:0] arm_eth0_rx_tuser; + wire [7:0] arm_eth0_rx_tkeep; + + wire [63:0] arm_eth0_rx_tdata_b; + wire arm_eth0_rx_tvalid_b; + wire arm_eth0_rx_tlast_b; + wire arm_eth0_rx_tready_b; + wire [3:0] arm_eth0_rx_tuser_b; + wire [7:0] arm_eth0_rx_tkeep_b; + + wire [63:0] arm_eth_sfp0_rx_tdata_b; + wire arm_eth_sfp0_rx_tvalid_b; + wire arm_eth_sfp0_rx_tlast_b; + wire arm_eth_sfp0_rx_tready_b; + wire [3:0] arm_eth_sfp0_rx_tuser_b; + wire [7:0] arm_eth_sfp0_rx_tkeep_b; + + wire arm_eth0_rx_irq; + wire arm_eth0_tx_irq; + + // ARM ethernet 1 bridge signals + wire [63:0] arm_eth1_tx_tdata; + wire arm_eth1_tx_tvalid; + wire arm_eth1_tx_tlast; + wire arm_eth1_tx_tready; + wire [3:0] arm_eth1_tx_tuser; + wire [7:0] arm_eth1_tx_tkeep; + + wire [63:0] arm_eth1_tx_tdata_b; + wire arm_eth1_tx_tvalid_b; + wire arm_eth1_tx_tlast_b; + wire arm_eth1_tx_tready_b; + wire [3:0] arm_eth1_tx_tuser_b; + wire [7:0] arm_eth1_tx_tkeep_b; + + wire [63:0] arm_eth_sfp1_tx_tdata_b; + wire arm_eth_sfp1_tx_tvalid_b; + wire arm_eth_sfp1_tx_tlast_b; + wire arm_eth_sfp1_tx_tready_b; + wire [3:0] arm_eth_sfp1_tx_tuser_b; + wire [7:0] arm_eth_sfp1_tx_tkeep_b; + + wire [63:0] arm_eth1_rx_tdata; + wire arm_eth1_rx_tvalid; + wire arm_eth1_rx_tlast; + wire arm_eth1_rx_tready; + wire [3:0] arm_eth1_rx_tuser; + wire [7:0] arm_eth1_rx_tkeep; + + wire [63:0] arm_eth1_rx_tdata_b; + wire arm_eth1_rx_tvalid_b; + wire arm_eth1_rx_tlast_b; + wire arm_eth1_rx_tready_b; + wire [3:0] arm_eth1_rx_tuser_b; + wire [7:0] arm_eth1_rx_tkeep_b; + + wire [63:0] arm_eth_sfp1_rx_tdata_b; + wire arm_eth_sfp1_rx_tvalid_b; + wire arm_eth_sfp1_rx_tlast_b; + wire arm_eth_sfp1_rx_tready_b; + wire [3:0] arm_eth_sfp1_rx_tuser_b; + wire [7:0] arm_eth_sfp1_rx_tkeep_b; + + wire arm_eth1_tx_irq; + wire arm_eth1_rx_irq; + + // Vita to Ethernet + wire [63:0] v2e0_tdata; + wire v2e0_tlast; + wire v2e0_tvalid; + wire v2e0_tready; + + wire [63:0] v2e1_tdata; + wire v2e1_tlast; + wire v2e1_tvalid; + wire v2e1_tready; + + wire [63:0] v2e_sfp0_tdata; + wire v2e_sfp0_tlast; + wire v2e_sfp0_tvalid; + wire v2e_sfp0_tready; + + wire [63:0] v2e_sfp1_tdata; + wire v2e_sfp1_tlast; + wire v2e_sfp1_tvalid; + wire v2e_sfp1_tready; + + // Ethernet to Vita + wire [63:0] e2v0_tdata; + wire e2v0_tlast; + wire e2v0_tvalid; + wire e2v0_tready; + + wire [63:0] e2v1_tdata; + wire e2v1_tlast; + wire e2v1_tvalid; + wire e2v1_tready; + + wire [63:0] e2v_sfp0_tdata; + wire e2v_sfp0_tlast; + wire e2v_sfp0_tvalid; + wire e2v_sfp0_tready; + + wire [63:0] e2v_sfp1_tdata; + wire e2v_sfp1_tlast; + wire e2v_sfp1_tvalid; + wire e2v_sfp1_tready; + + // Ethernet crossover + wire [63:0] e01_tdata, e10_tdata; + wire [3:0] e01_tuser, e10_tuser; + wire e01_tlast, e01_tvalid, e01_tready; + wire e10_tlast, e10_tvalid, e10_tready; + + + // DMA xport adapter to PS + wire [63:0] m_axis_dma_tdata; + wire [3:0] m_axis_dma_tuser; + wire m_axis_dma_tlast; + wire m_axis_dma_tready; + wire m_axis_dma_tvalid; + + wire [63:0] s_axis_dma_tdata; + wire [3:0] s_axis_dma_tdest; + wire s_axis_dma_tlast; + wire s_axis_dma_tready; + wire s_axis_dma_tvalid; + + // Misc + wire [31:0] sfp_port0_info; + wire [31:0] sfp_port1_info; + wire sfp0_link_up, sfp1_link_up; + wire [15:0] device_id; + + ///////////////////////////////////////////////////////////////////// + // + // SFP Wrapper 0: Network Interface (1/10G or Aurora) + // + ////////////////////////////////////////////////////////////////////// + + n3xx_mgt_channel_wrapper #( + .LANES(1), + `ifdef SFP0_10GBE + .PROTOCOL("10GbE"), + .MDIO_EN(1'b1), + .MDIO_PHYADDR(5'd4), // PHYADDR must match the "reg" property for PHY in DTS file + `elsif SFP0_AURORA + .PROTOCOL("Aurora"), + .MDIO_EN(1'b0), + `elsif SFP0_1GBE + .PROTOCOL("1GbE"), + .MDIO_EN(1'b1), + .MDIO_PHYADDR(5'd4), // PHYADDR must match the "reg" property for PHY in DTS file + `elsif SFP0_WR + .PROTOCOL("WhiteRabbit"), + .MDIO_EN(1'b0), + `endif + .REG_DWIDTH(REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH(REG_AWIDTH), // Width of the address bus + .PORTNUM_BASE(8'd0) + ) sfp_wrapper_0 ( + .areset(global_rst), + .gt_refclk(sfp0_gt_refclk), + .gb_refclk(sfp0_gb_refclk), + .misc_clk(sfp0_misc_clk), + .user_clk(au_user_clk), + .sync_clk(au_sync_clk), + .gt_tx_out_clk_unbuf(sfp0_tx_out_clk), + + .bus_rst(bus_rst), + .bus_clk(bus_clk), + + .qpllreset(qpllreset_sfp0), + .qplllock(qplllock), + .qplloutclk(qplloutclk), + .qplloutrefclk(qplloutrefclk), + .qpllrefclklost(), + + .mmcm_locked(au_mmcm_locked), + .gt_pll_lock(sfp0_gt_pll_lock), + + .txp(SFP_0_TX_P), + .txn(SFP_0_TX_N), + .rxp(SFP_0_RX_P), + .rxn(SFP_0_RX_N), + + .mod_present_n(SFP_0_I2C_NPRESENT), + .mod_rxlos(SFP_0_LOS), + .mod_tx_fault(SFP_0_TXFAULT), + .mod_tx_disable(SFP_0_TXDISABLE), + + // Clock and reset + .s_axi_aclk(clk40), + .s_axi_aresetn(clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_NET0_AWADDR[REG_AWIDTH-1:0]), + .s_axi_awvalid(M_AXI_NET0_AWVALID), + .s_axi_awready(M_AXI_NET0_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_NET0_WDATA), + .s_axi_wstrb(M_AXI_NET0_WSTRB), + .s_axi_wvalid(M_AXI_NET0_WVALID), + .s_axi_wready(M_AXI_NET0_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_NET0_BRESP), + .s_axi_bvalid(M_AXI_NET0_BVALID), + .s_axi_bready(M_AXI_NET0_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_NET0_ARADDR[REG_AWIDTH-1:0]), + .s_axi_arvalid(M_AXI_NET0_ARVALID), + .s_axi_arready(M_AXI_NET0_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_NET0_RDATA), + .s_axi_rresp(M_AXI_NET0_RRESP), + .s_axi_rvalid(M_AXI_NET0_RVALID), + .s_axi_rready(M_AXI_NET0_RREADY), + + // Ethernet to Vita + .e2v_tdata(e2v_sfp0_tdata), + .e2v_tlast(e2v_sfp0_tlast), + .e2v_tvalid(e2v_sfp0_tvalid), + .e2v_tready(e2v_sfp0_tready), + + // Vita to Ethernet + .v2e_tdata(v2e_sfp0_tdata), + .v2e_tlast(v2e_sfp0_tlast), + .v2e_tvalid(v2e_sfp0_tvalid), + .v2e_tready(v2e_sfp0_tready), + + // Ethernet to CPU + .e2c_tdata(arm_eth_sfp0_rx_tdata_b), + .e2c_tkeep(arm_eth_sfp0_rx_tkeep_b), + .e2c_tlast(arm_eth_sfp0_rx_tlast_b), + .e2c_tvalid(arm_eth_sfp0_rx_tvalid_b), + .e2c_tready(arm_eth_sfp0_rx_tready_b), + + // CPU to Ethernet + .c2e_tdata(arm_eth_sfp0_tx_tdata_b), + .c2e_tkeep(arm_eth_sfp0_tx_tkeep_b), + .c2e_tlast(arm_eth_sfp0_tx_tlast_b), + .c2e_tvalid(arm_eth_sfp0_tx_tvalid_b), + .c2e_tready(arm_eth_sfp0_tx_tready_b), + + // White Rabbit Specific +`ifdef SFP0_WR + .wr_reset_n (~ps_gpio_out[48]), // reset for WR only + .wr_refclk (wr_refclk_buf), + .wr_dac_sclk (WB_DAC_SCLK), + .wr_dac_din (WB_DAC_DIN), + .wr_dac_clr_n (WB_DAC_NCLR), + .wr_dac_cs_n (WB_DAC_NSYNC), + .wr_dac_ldac_n(WB_DAC_NLDAC), + .wr_eeprom_scl_o(), // storage for delay characterization + .wr_eeprom_scl_i(1'b0), // temp + .wr_eeprom_sda_o(), + .wr_eeprom_sda_i(1'b0), // temp + .wr_uart_rx(wr_uart_rxd), // to/from PS + .wr_uart_tx(wr_uart_txd), + .mod_pps(pps_wr_refclk), // out, reference clock and pps + .mod_refclk(wr_ref_clk), + // WR Slave Port to PS + .wr_axi_aclk(m_axi_wr_clk), // out to PS + .wr_axi_aresetn(1'b1), // in + .wr_axi_awaddr(m_axi_wr_awaddr), + .wr_axi_awvalid(m_axi_wr_awvalid), + .wr_axi_awready(m_axi_wr_awready), + .wr_axi_wdata(m_axi_wr_wdata), + .wr_axi_wstrb(m_axi_wr_wstrb), + .wr_axi_wvalid(m_axi_wr_wvalid), + .wr_axi_wready(m_axi_wr_wready), + .wr_axi_bresp(m_axi_wr_bresp), + .wr_axi_bvalid(m_axi_wr_bvalid), + .wr_axi_bready(m_axi_wr_bready), + .wr_axi_araddr(m_axi_wr_araddr), + .wr_axi_arvalid(m_axi_wr_arvalid), + .wr_axi_arready(m_axi_wr_arready), + .wr_axi_rdata(m_axi_wr_rdata), + .wr_axi_rresp(m_axi_wr_rresp), + .wr_axi_rvalid(m_axi_wr_rvalid), + .wr_axi_rready(m_axi_wr_rready), + .wr_axi_rlast(), +`else + .wr_reset_n(1'b1), + .wr_refclk(1'b0), + .wr_eeprom_scl_i(1'b0), + .wr_eeprom_sda_i(1'b0), + .wr_uart_rx(1'b0), +`endif + + // Misc + .port_info(sfp_port0_info), + .device_id(device_id), + + // LED + .link_up(sfp0_link_up), + .activity(SFP_0_LED_A) + ); + + assign ps_gpio_in[60] = ps_gpio_tri[60] ? sfp0_link_up : ps_gpio_out[60]; + assign SFP_0_LED_B = sfp0_link_up; + +`ifndef SFP0_WR + assign WB_DAC_SCLK = 1'b0; + assign WB_DAC_DIN = 1'b0; + assign WB_DAC_NCLR = 1'b1; + assign WB_DAC_NSYNC = 1'b1; + assign WB_DAC_NLDAC = 1'b1; + assign pps_wr_refclk = 1'b0; + assign wr_ref_clk = 1'b0; +`endif + + + ///////////////////////////////////////////////////////////////////// + // + // SFP Wrapper 1: Network Interface (1/10G or Aurora) + // + ////////////////////////////////////////////////////////////////////// + + n3xx_mgt_channel_wrapper #( + .LANES(1), + `ifdef SFP1_10GBE + .PROTOCOL("10GbE"), + .MDIO_EN(1'b1), + .MDIO_PHYADDR(5'd4), // PHYADDR must match the "reg" property for PHY in DTS file + `elsif SFP1_AURORA + .PROTOCOL("Aurora"), + .MDIO_EN(1'b0), + `endif + .REG_DWIDTH(REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH(REG_AWIDTH), // Width of the address bus + .PORTNUM_BASE(8'd1) + ) sfp_wrapper_1 ( + .areset(global_rst), + + .gt_refclk(sfp1_gt_refclk), + .gb_refclk(sfp1_gb_refclk), + .misc_clk(sfp1_misc_clk), + .user_clk(au_user_clk), + .sync_clk(au_sync_clk), + .gt_tx_out_clk_unbuf(sfp1_tx_out_clk), + + .bus_rst(bus_rst), + .bus_clk(bus_clk), + + .qpllreset(qpllreset_sfp1), + .qplllock(qplllock), + .qplloutclk(qplloutclk), + .qplloutrefclk(qplloutrefclk), + .qpllrefclklost(), + + .mmcm_locked(au_mmcm_locked), + .gt_pll_lock(sfp1_gt_pll_lock), + + .txp(SFP_1_TX_P), + .txn(SFP_1_TX_N), + .rxp(SFP_1_RX_P), + .rxn(SFP_1_RX_N), + + .mod_rxlos(SFP_1_LOS), + .mod_tx_fault(SFP_1_TXFAULT), + .mod_tx_disable(SFP_1_TXDISABLE), + + // Clock and reset + .s_axi_aclk(clk40), + .s_axi_aresetn(clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_NET1_AWADDR[REG_AWIDTH-1:0]), + .s_axi_awvalid(M_AXI_NET1_AWVALID), + .s_axi_awready(M_AXI_NET1_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_NET1_WDATA), + .s_axi_wstrb(M_AXI_NET1_WSTRB), + .s_axi_wvalid(M_AXI_NET1_WVALID), + .s_axi_wready(M_AXI_NET1_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_NET1_BRESP), + .s_axi_bvalid(M_AXI_NET1_BVALID), + .s_axi_bready(M_AXI_NET1_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_NET1_ARADDR[REG_AWIDTH-1:0]), + .s_axi_arvalid(M_AXI_NET1_ARVALID), + .s_axi_arready(M_AXI_NET1_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_NET1_RDATA), + .s_axi_rresp(M_AXI_NET1_RRESP), + .s_axi_rvalid(M_AXI_NET1_RVALID), + .s_axi_rready(M_AXI_NET1_RREADY), + + // Ethernet to Vita + .e2v_tdata(e2v_sfp1_tdata), + .e2v_tlast(e2v_sfp1_tlast), + .e2v_tvalid(e2v_sfp1_tvalid), + .e2v_tready(e2v_sfp1_tready), + + // Vita to Ethernet + .v2e_tdata(v2e_sfp1_tdata), + .v2e_tlast(v2e_sfp1_tlast), + .v2e_tvalid(v2e_sfp1_tvalid), + .v2e_tready(v2e_sfp1_tready), + + // Ethernet to CPU + .e2c_tdata(arm_eth_sfp1_rx_tdata_b), + .e2c_tkeep(arm_eth_sfp1_rx_tkeep_b), + .e2c_tlast(arm_eth_sfp1_rx_tlast_b), + .e2c_tvalid(arm_eth_sfp1_rx_tvalid_b), + .e2c_tready(arm_eth_sfp1_rx_tready_b), + + // CPU to Ethernet + .c2e_tdata(arm_eth_sfp1_tx_tdata_b), + .c2e_tkeep(arm_eth_sfp1_tx_tkeep_b), + .c2e_tlast(arm_eth_sfp1_tx_tlast_b), + .c2e_tvalid(arm_eth_sfp1_tx_tvalid_b), + .c2e_tready(arm_eth_sfp1_tx_tready_b), + + // Misc + .port_info(sfp_port1_info), + .device_id(device_id), + + // LED + .link_up(sfp1_link_up), + .activity(SFP_1_LED_A) + ); + + assign ps_gpio_in[61] = ps_gpio_tri[61] ? sfp1_link_up : ps_gpio_out[61]; + assign SFP_1_LED_B = sfp1_link_up; + + ///////////////////////////////////////////////////////////////////// + // + // Ethernet DMA 0 + // + ////////////////////////////////////////////////////////////////////// + + assign IRQ_F2P[0] = arm_eth0_rx_irq; + assign IRQ_F2P[1] = arm_eth0_tx_irq; + + assign {S_AXI_HP0_AWID, S_AXI_HP0_ARID} = 12'd0; + assign {S_AXI_GP0_AWID, S_AXI_GP0_ARID} = 10'd0; + +`ifdef QSFP_10GBE + // QSFP+ lanes connect to DMA engines and crossbar + // Connect first QSFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_qsfp_tx_tdata_b[0*64 +: 64] = arm_eth0_tx_tdata_b; + assign arm_eth_qsfp_tx_tvalid_b[0] = arm_eth0_tx_tvalid_b; + assign arm_eth_qsfp_tx_tlast_b[0] = arm_eth0_tx_tlast_b; + assign arm_eth0_tx_tready_b = arm_eth_qsfp_tx_tready_b[0]; + assign arm_eth_qsfp_tx_tuser_b[0*4 +: 4] = arm_eth0_tx_tuser_b; + assign arm_eth_qsfp_tx_tkeep_b[0*8 +: 8] = arm_eth0_tx_tkeep_b; + + assign arm_eth0_rx_tdata_b = arm_eth_qsfp_rx_tdata_b[0*64 +: 64]; + assign arm_eth0_rx_tvalid_b = arm_eth_qsfp_rx_tvalid_b[0]; + assign arm_eth0_rx_tlast_b = arm_eth_qsfp_rx_tlast_b[0]; + assign arm_eth_qsfp_rx_tready_b[0] = arm_eth0_rx_tready_b; + assign arm_eth0_rx_tuser_b = arm_eth_qsfp_rx_tuser_b[0*4 +: 4]; + assign arm_eth0_rx_tkeep_b = arm_eth_qsfp_rx_tkeep_b[0*8 +: 8]; + + // Connect first QSFP+ 10 GbE port to the crossbar + assign v2e_qsfp_tdata[0*64 +: 64] = v2e0_tdata; + assign v2e_qsfp_tlast[0] = v2e0_tlast; + assign v2e_qsfp_tvalid[0] = v2e0_tvalid; + assign v2e0_tready = v2e_qsfp_tready[0]; + + assign e2v0_tdata = e2v_qsfp_tdata[0*64 +: 64]; + assign e2v0_tlast = e2v_qsfp_tlast[0]; + assign e2v0_tvalid = e2v_qsfp_tvalid[0]; + assign e2v_qsfp_tready[0] = e2v0_tready; + + // Connect second QSFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_qsfp_tx_tdata_b[1*64 +: 64] = arm_eth1_tx_tdata_b; + assign arm_eth_qsfp_tx_tvalid_b[1] = arm_eth1_tx_tvalid_b; + assign arm_eth_qsfp_tx_tlast_b[1] = arm_eth1_tx_tlast_b; + assign arm_eth1_tx_tready_b = arm_eth_qsfp_tx_tready_b[1]; + assign arm_eth_qsfp_tx_tuser_b[1*4 +: 4] = arm_eth1_tx_tuser_b; + assign arm_eth_qsfp_tx_tkeep_b[1*8 +: 8] = arm_eth1_tx_tkeep_b; + + assign arm_eth1_rx_tdata_b = arm_eth_qsfp_rx_tdata_b[1*64 +: 64]; + assign arm_eth1_rx_tvalid_b = arm_eth_qsfp_rx_tvalid_b[1]; + assign arm_eth1_rx_tlast_b = arm_eth_qsfp_rx_tlast_b[1]; + assign arm_eth_qsfp_rx_tready_b[1] = arm_eth1_rx_tready_b; + assign arm_eth1_rx_tuser_b = arm_eth_qsfp_rx_tuser_b[1*4 +: 4]; + assign arm_eth1_rx_tkeep_b = arm_eth_qsfp_rx_tkeep_b[1*8 +: 8]; + + // Connect second QSFP+ 10 GbE port to the crossbar + assign v2e_qsfp_tdata[1*64 +: 64] = v2e1_tdata; + assign v2e_qsfp_tlast[1] = v2e1_tlast; + assign v2e_qsfp_tvalid[1] = v2e1_tvalid; + assign v2e1_tready = v2e_qsfp_tready[1]; + + assign e2v1_tdata = e2v_qsfp_tdata[1*64 +: 64]; + assign e2v1_tlast = e2v_qsfp_tlast[1]; + assign e2v1_tvalid = e2v_qsfp_tvalid[1]; + assign e2v_qsfp_tready[1] = e2v1_tready; +`else + // SFP+ ports connects to DMA engines and crossbar + // Connect first SFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_sfp0_tx_tdata_b = arm_eth0_tx_tdata_b; + assign arm_eth_sfp0_tx_tvalid_b = arm_eth0_tx_tvalid_b; + assign arm_eth_sfp0_tx_tlast_b = arm_eth0_tx_tlast_b; + assign arm_eth0_tx_tready_b = arm_eth_sfp0_tx_tready_b; + assign arm_eth_sfp0_tx_tuser_b = arm_eth0_tx_tuser_b; + assign arm_eth_sfp0_tx_tkeep_b = arm_eth0_tx_tkeep_b; + + assign arm_eth0_rx_tdata_b = arm_eth_sfp0_rx_tdata_b; + assign arm_eth0_rx_tvalid_b = arm_eth_sfp0_rx_tvalid_b; + assign arm_eth0_rx_tlast_b = arm_eth_sfp0_rx_tlast_b; + assign arm_eth_sfp0_rx_tready_b = arm_eth0_rx_tready_b; + assign arm_eth0_rx_tuser_b = arm_eth_sfp0_rx_tuser_b; + assign arm_eth0_rx_tkeep_b = arm_eth_sfp0_rx_tkeep_b; + + // Connect first SFP+ 10 GbE port to the crossbar + assign v2e_sfp0_tdata = v2e0_tdata; + assign v2e_sfp0_tlast = v2e0_tlast; + assign v2e_sfp0_tvalid = v2e0_tvalid; + assign v2e0_tready = v2e_sfp0_tready; + + assign e2v0_tdata = e2v_sfp0_tdata; + assign e2v0_tlast = e2v_sfp0_tlast; + assign e2v0_tvalid = e2v_sfp0_tvalid; + assign e2v_sfp0_tready = e2v0_tready; + + // Connect second SFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_sfp1_tx_tdata_b = arm_eth1_tx_tdata_b; + assign arm_eth_sfp1_tx_tvalid_b = arm_eth1_tx_tvalid_b; + assign arm_eth_sfp1_tx_tlast_b = arm_eth1_tx_tlast_b; + assign arm_eth1_tx_tready_b = arm_eth_sfp1_tx_tready_b; + assign arm_eth_sfp1_tx_tuser_b = arm_eth1_tx_tuser_b; + assign arm_eth_sfp1_tx_tkeep_b = arm_eth1_tx_tkeep_b; + + assign arm_eth1_rx_tdata_b = arm_eth_sfp1_rx_tdata_b; + assign arm_eth1_rx_tvalid_b = arm_eth_sfp1_rx_tvalid_b; + assign arm_eth1_rx_tlast_b = arm_eth_sfp1_rx_tlast_b; + assign arm_eth_sfp1_rx_tready_b = arm_eth1_rx_tready_b; + assign arm_eth1_rx_tuser_b = arm_eth_sfp1_rx_tuser_b; + assign arm_eth1_rx_tkeep_b = arm_eth_sfp1_rx_tkeep_b; + + // Connect first SFP+ 10 GbE port to the crossbar + assign v2e_sfp1_tdata = v2e1_tdata; + assign v2e_sfp1_tlast = v2e1_tlast; + assign v2e_sfp1_tvalid = v2e1_tvalid; + assign v2e1_tready = v2e_sfp1_tready; + + assign e2v1_tdata = e2v_sfp1_tdata; + assign e2v1_tlast = e2v_sfp1_tlast; + assign e2v1_tvalid = e2v_sfp1_tvalid; + assign e2v_sfp1_tready = e2v1_tready; + + // Don't actually instantiate DMA engines if protocols can't use them + `ifdef SFP0_AURORA + `define NO_ETH_DMA_0 + `elsif SFP0_WR + `define NO_ETH_DMA_0 + `endif + + `ifdef SFP1_AURORA + `define NO_ETH_DMA_1 + `endif +`endif + +`ifdef NO_ETH_DMA_0 + //If inst Aurora, tie off each axi/axi-lite interface + axi_dummy #( + .DEC_ERR(1'b0) + ) inst_axi_dummy_sfp0_eth_dma ( + .s_axi_aclk(bus_clk), + .s_axi_areset(bus_rst), + + .s_axi_awaddr(M_AXI_ETH_DMA0_AWADDR), + .s_axi_awvalid(M_AXI_ETH_DMA0_AWVALID), + .s_axi_awready(M_AXI_ETH_DMA0_AWREADY), + + .s_axi_wdata(M_AXI_ETH_DMA0_WDATA), + .s_axi_wvalid(M_AXI_ETH_DMA0_WVALID), + .s_axi_wready(M_AXI_ETH_DMA0_WREADY), + + .s_axi_bresp(M_AXI_ETH_DMA0_BRESP), + .s_axi_bvalid(M_AXI_ETH_DMA0_BVALID), + .s_axi_bready(M_AXI_ETH_DMA0_BREADY), + + .s_axi_araddr(M_AXI_ETH_DMA0_ARADDR), + .s_axi_arvalid(M_AXI_ETH_DMA0_ARVALID), + .s_axi_arready(M_AXI_ETH_DMA0_ARREADY), + + .s_axi_rdata(M_AXI_ETH_DMA0_RDATA), + .s_axi_rresp(M_AXI_ETH_DMA0_RRESP), + .s_axi_rvalid(M_AXI_ETH_DMA0_RVALID), + .s_axi_rready(M_AXI_ETH_DMA0_RREADY) + + ); + //S_AXI_GP0 outputs from axi_eth_dma, so needs some sort of controller/tie off + assign S_AXI_GP0_AWADDR = 32'h0; + assign S_AXI_GP0_AWLEN = 8'h0; + assign S_AXI_GP0_AWSIZE = 4'h0; + assign S_AXI_GP0_AWBURST = 3'h0; + assign S_AXI_GP0_AWPROT = 3'h0; + assign S_AXI_GP0_AWCACHE = 4'h0; + assign S_AXI_GP0_AWVALID = 1'b0; + //S_AXI_GP0_AWREADY output from PS + assign S_AXI_GP0_WDATA = 32'h0; + assign S_AXI_GP0_WSTRB = 4'h0; + assign S_AXI_GP0_WLAST = 1'b0; + assign S_AXI_GP0_WVALID = 1'b0; + //S_AXI_GP0_WREADY output from PS + //S_AXI_GP0_BRESP + //S_AXI_GP0_BVALID + assign S_AXI_GP0_BREADY = 1'b1; + assign S_AXI_GP0_ARADDR = 32'h0; + assign S_AXI_GP0_ARLEN = 8'h0; + assign S_AXI_GP0_ARSIZE = 3'h0; + assign S_AXI_GP0_ARBURST = 2'h0; + assign S_AXI_GP0_ARPROT = 3'h0; + assign S_AXI_GP0_ARCACHE = 4'h0; + assign S_AXI_GP0_ARVALID = 1'b0; + //S_AXI_GP0_ARREADY + //S_AXI_GP0_RDATA + //S_AXI_GP0_RRESP + //S_AXI_GP0_RLAST + //S_AXI_GP0_RVALID + assign S_AXI_GP0_RREADY = 1'b1; + + //S_AXI_HP0 from axi_eth_dma + assign S_AXI_HP0_ARADDR = 32'h0; + assign S_AXI_HP0_ARLEN = 8'h0; + assign S_AXI_HP0_ARSIZE = 3'h0; + assign S_AXI_HP0_ARBURST = 2'h0; + assign S_AXI_HP0_ARPROT = 3'h0; + assign S_AXI_HP0_ARCACHE = 4'h0; + assign S_AXI_HP0_ARVALID = 1'b0; + //S_AXI_HP0_ARREADY + //S_AXI_HP0_RDATA + //S_AXI_HP0_RRESP + //S_AXI_HP0_RLAST + //S_AXI_HP0_RVALID + assign S_AXI_HP0_RREADY = 1'b1; + assign S_AXI_HP0_AWADDR = 32'h0; + assign S_AXI_HP0_AWLEN = 8'h0; + assign S_AXI_HP0_AWSIZE = 3'h0; + assign S_AXI_HP0_AWBURST = 2'h0; + assign S_AXI_HP0_AWPROT = 3'h0; + assign S_AXI_HP0_AWCACHE = 4'h0; + assign S_AXI_HP0_AWVALID = 1'b0; + //S_AXI_HP0_AWREADY + assign S_AXI_HP0_WDATA = 64'h0; + assign S_AXI_HP0_WSTRB = 8'h0; + assign S_AXI_HP0_WLAST = 1'b0; + assign S_AXI_HP0_WVALID = 1'b0; + //S_AXI_HP0_WREADY + //S_AXI_HP0_BRESP + //S_AXI_HP0_BVALID + assign S_AXI_HP0_BREADY = 1'b1; + +`else + + axi_eth_dma inst_axi_eth_dma0 ( + .s_axi_lite_aclk(clk40), + .m_axi_sg_aclk(clk40), + .m_axi_mm2s_aclk(clk40), + .m_axi_s2mm_aclk(clk40), + .axi_resetn(clk40_rstn), + + .s_axi_lite_awaddr(M_AXI_ETH_DMA0_AWADDR), + .s_axi_lite_awvalid(M_AXI_ETH_DMA0_AWVALID), + .s_axi_lite_awready(M_AXI_ETH_DMA0_AWREADY), + + .s_axi_lite_wdata(M_AXI_ETH_DMA0_WDATA), + .s_axi_lite_wvalid(M_AXI_ETH_DMA0_WVALID), + .s_axi_lite_wready(M_AXI_ETH_DMA0_WREADY), + + .s_axi_lite_bresp(M_AXI_ETH_DMA0_BRESP), + .s_axi_lite_bvalid(M_AXI_ETH_DMA0_BVALID), + .s_axi_lite_bready(M_AXI_ETH_DMA0_BREADY), + + .s_axi_lite_araddr(M_AXI_ETH_DMA0_ARADDR), + .s_axi_lite_arvalid(M_AXI_ETH_DMA0_ARVALID), + .s_axi_lite_arready(M_AXI_ETH_DMA0_ARREADY), + + .s_axi_lite_rdata(M_AXI_ETH_DMA0_RDATA), + .s_axi_lite_rresp(M_AXI_ETH_DMA0_RRESP), + .s_axi_lite_rvalid(M_AXI_ETH_DMA0_RVALID), + .s_axi_lite_rready(M_AXI_ETH_DMA0_RREADY), + + .m_axi_sg_awaddr(S_AXI_GP0_AWADDR), + .m_axi_sg_awlen(S_AXI_GP0_AWLEN), + .m_axi_sg_awsize(S_AXI_GP0_AWSIZE), + .m_axi_sg_awburst(S_AXI_GP0_AWBURST), + .m_axi_sg_awprot(S_AXI_GP0_AWPROT), + .m_axi_sg_awcache(S_AXI_GP0_AWCACHE), + .m_axi_sg_awvalid(S_AXI_GP0_AWVALID), + .m_axi_sg_awready(S_AXI_GP0_AWREADY), + .m_axi_sg_wdata(S_AXI_GP0_WDATA), + .m_axi_sg_wstrb(S_AXI_GP0_WSTRB), + .m_axi_sg_wlast(S_AXI_GP0_WLAST), + .m_axi_sg_wvalid(S_AXI_GP0_WVALID), + .m_axi_sg_wready(S_AXI_GP0_WREADY), + .m_axi_sg_bresp(S_AXI_GP0_BRESP), + .m_axi_sg_bvalid(S_AXI_GP0_BVALID), + .m_axi_sg_bready(S_AXI_GP0_BREADY), + .m_axi_sg_araddr(S_AXI_GP0_ARADDR), + .m_axi_sg_arlen(S_AXI_GP0_ARLEN), + .m_axi_sg_arsize(S_AXI_GP0_ARSIZE), + .m_axi_sg_arburst(S_AXI_GP0_ARBURST), + .m_axi_sg_arprot(S_AXI_GP0_ARPROT), + .m_axi_sg_arcache(S_AXI_GP0_ARCACHE), + .m_axi_sg_arvalid(S_AXI_GP0_ARVALID), + .m_axi_sg_arready(S_AXI_GP0_ARREADY), + .m_axi_sg_rdata(S_AXI_GP0_RDATA), + .m_axi_sg_rresp(S_AXI_GP0_RRESP), + .m_axi_sg_rlast(S_AXI_GP0_RLAST), + .m_axi_sg_rvalid(S_AXI_GP0_RVALID), + .m_axi_sg_rready(S_AXI_GP0_RREADY), + + .m_axi_mm2s_araddr(S_AXI_HP0_ARADDR), + .m_axi_mm2s_arlen(S_AXI_HP0_ARLEN), + .m_axi_mm2s_arsize(S_AXI_HP0_ARSIZE), + .m_axi_mm2s_arburst(S_AXI_HP0_ARBURST), + .m_axi_mm2s_arprot(S_AXI_HP0_ARPROT), + .m_axi_mm2s_arcache(S_AXI_HP0_ARCACHE), + .m_axi_mm2s_arvalid(S_AXI_HP0_ARVALID), + .m_axi_mm2s_arready(S_AXI_HP0_ARREADY), + .m_axi_mm2s_rdata(S_AXI_HP0_RDATA), + .m_axi_mm2s_rresp(S_AXI_HP0_RRESP), + .m_axi_mm2s_rlast(S_AXI_HP0_RLAST), + .m_axi_mm2s_rvalid(S_AXI_HP0_RVALID), + .m_axi_mm2s_rready(S_AXI_HP0_RREADY), + + .mm2s_prmry_reset_out_n(), + .m_axis_mm2s_tdata(arm_eth0_tx_tdata), + .m_axis_mm2s_tkeep(arm_eth0_tx_tkeep), + .m_axis_mm2s_tvalid(arm_eth0_tx_tvalid), + .m_axis_mm2s_tready(arm_eth0_tx_tready), + .m_axis_mm2s_tlast(arm_eth0_tx_tlast), + + .m_axi_s2mm_awaddr(S_AXI_HP0_AWADDR), + .m_axi_s2mm_awlen(S_AXI_HP0_AWLEN), + .m_axi_s2mm_awsize(S_AXI_HP0_AWSIZE), + .m_axi_s2mm_awburst(S_AXI_HP0_AWBURST), + .m_axi_s2mm_awprot(S_AXI_HP0_AWPROT), + .m_axi_s2mm_awcache(S_AXI_HP0_AWCACHE), + .m_axi_s2mm_awvalid(S_AXI_HP0_AWVALID), + .m_axi_s2mm_awready(S_AXI_HP0_AWREADY), + .m_axi_s2mm_wdata(S_AXI_HP0_WDATA), + .m_axi_s2mm_wstrb(S_AXI_HP0_WSTRB), + .m_axi_s2mm_wlast(S_AXI_HP0_WLAST), + .m_axi_s2mm_wvalid(S_AXI_HP0_WVALID), + .m_axi_s2mm_wready(S_AXI_HP0_WREADY), + .m_axi_s2mm_bresp(S_AXI_HP0_BRESP), + .m_axi_s2mm_bvalid(S_AXI_HP0_BVALID), + .m_axi_s2mm_bready(S_AXI_HP0_BREADY), + + .s2mm_prmry_reset_out_n(), + .s_axis_s2mm_tdata(arm_eth0_rx_tdata), + .s_axis_s2mm_tkeep(arm_eth0_rx_tkeep), + .s_axis_s2mm_tvalid(arm_eth0_rx_tvalid), + .s_axis_s2mm_tready(arm_eth0_rx_tready), + .s_axis_s2mm_tlast(arm_eth0_rx_tlast), + + .mm2s_introut(arm_eth0_tx_irq), + .s2mm_introut(arm_eth0_rx_irq), + .axi_dma_tstvec() + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_tx_0_fifo_2clk_i ( + .reset(clk40_rst), + .i_aclk(clk40), + .i_tdata({arm_eth0_tx_tlast, arm_eth0_tx_tkeep, arm_eth0_tx_tdata}), + .i_tvalid(arm_eth0_tx_tvalid), + .i_tready(arm_eth0_tx_tready), + .o_aclk(bus_clk), + .o_tdata({arm_eth0_tx_tlast_b, arm_eth0_tx_tkeep_b, arm_eth0_tx_tdata_b}), + .o_tvalid(arm_eth0_tx_tvalid_b), + .o_tready(arm_eth0_tx_tready_b) + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_rx_0_fifo_2clk_i ( + .reset(bus_rst), + .i_aclk(bus_clk), + .i_tdata({arm_eth0_rx_tlast_b, arm_eth0_rx_tkeep_b, arm_eth0_rx_tdata_b}), + .i_tvalid(arm_eth0_rx_tvalid_b), + .i_tready(arm_eth0_rx_tready_b), + .o_aclk(clk40), + .o_tdata({arm_eth0_rx_tlast, arm_eth0_rx_tkeep, arm_eth0_rx_tdata}), + .o_tvalid(arm_eth0_rx_tvalid), + .o_tready(arm_eth0_rx_tready) + ); + +`endif + + ///////////////////////////////////////////////////////////////////// + // + // Ethernet DMA 1 + // + ////////////////////////////////////////////////////////////////////// + + assign IRQ_F2P[2] = arm_eth1_rx_irq; + assign IRQ_F2P[3] = arm_eth1_tx_irq; + + assign {S_AXI_HP1_AWID, S_AXI_HP1_ARID} = 12'd0; + assign {S_AXI_GP1_AWID, S_AXI_GP1_ARID} = 10'd0; + +`ifdef NO_ETH_DMA_1 + //If inst Aurora, tie off each axi/axi-lite interface + axi_dummy #(.DEC_ERR(1'b0)) inst_axi_dummy_sfp1_eth_dma + ( + .s_axi_aclk(bus_clk), + .s_axi_areset(bus_rst), + + .s_axi_awaddr(M_AXI_ETH_DMA1_AWADDR), + .s_axi_awvalid(M_AXI_ETH_DMA1_AWVALID), + .s_axi_awready(M_AXI_ETH_DMA1_AWREADY), + + .s_axi_wdata(M_AXI_ETH_DMA1_WDATA), + .s_axi_wvalid(M_AXI_ETH_DMA1_WVALID), + .s_axi_wready(M_AXI_ETH_DMA1_WREADY), + + .s_axi_bresp(M_AXI_ETH_DMA1_BRESP), + .s_axi_bvalid(M_AXI_ETH_DMA1_BVALID), + .s_axi_bready(M_AXI_ETH_DMA1_BREADY), + + .s_axi_araddr(M_AXI_ETH_DMA1_ARADDR), + .s_axi_arvalid(M_AXI_ETH_DMA1_ARVALID), + .s_axi_arready(M_AXI_ETH_DMA1_ARREADY), + + .s_axi_rdata(M_AXI_ETH_DMA1_RDATA), + .s_axi_rresp(M_AXI_ETH_DMA1_RRESP), + .s_axi_rvalid(M_AXI_ETH_DMA1_RVALID), + .s_axi_rready(M_AXI_ETH_DMA1_RREADY) + + ); + //S_AXI_GP0 outputs from axi_eth_dma, so needs some sort of controller/tie off + assign S_AXI_GP1_AWADDR = 32'h0; + assign S_AXI_GP1_AWLEN = 8'h0; + assign S_AXI_GP1_AWSIZE = 4'h0; + assign S_AXI_GP1_AWBURST = 3'h0; + assign S_AXI_GP1_AWPROT = 3'h0; + assign S_AXI_GP1_AWCACHE = 4'h0; + assign S_AXI_GP1_AWVALID = 1'b0; + //S_AXI_GP1_AWREADY output from PS + assign S_AXI_GP1_WDATA = 32'h0; + assign S_AXI_GP1_WSTRB = 4'h0; + assign S_AXI_GP1_WLAST = 1'b0; + assign S_AXI_GP1_WVALID = 1'b0; + //S_AXI_GP1_WREADY output from PS + //S_AXI_GP1_BRESP + //S_AXI_GP1_BVALID + assign S_AXI_GP1_BREADY = 1'b1; + assign S_AXI_GP1_ARADDR = 32'h0; + assign S_AXI_GP1_ARLEN = 8'h0; + assign S_AXI_GP1_ARSIZE = 3'h0; + assign S_AXI_GP1_ARBURST = 2'h0; + assign S_AXI_GP1_ARPROT = 3'h0; + assign S_AXI_GP1_ARCACHE = 4'h0; + assign S_AXI_GP1_ARVALID = 1'b0; + //S_AXI_GP1_ARREADY + //S_AXI_GP1_RDATA + //S_AXI_GP1_RRESP + //S_AXI_GP1_RLAST + //S_AXI_GP1_RVALID + assign S_AXI_GP1_RREADY = 1'b1; + + //S_AXI_HP0 from axi_eth_dma + assign S_AXI_HP1_ARADDR = 32'h0; + assign S_AXI_HP1_ARLEN = 8'h0; + assign S_AXI_HP1_ARSIZE = 3'h0; + assign S_AXI_HP1_ARBURST = 2'h0; + assign S_AXI_HP1_ARPROT = 3'h0; + assign S_AXI_HP1_ARCACHE = 4'h0; + assign S_AXI_HP1_ARVALID = 1'b0; + //S_AXI_HP1_ARREADY + //S_AXI_HP1_RDATA + //S_AXI_HP1_RRESP + //S_AXI_HP1_RLAST + //S_AXI_HP1_RVALID + assign S_AXI_HP1_RREADY = 1'b1; + assign S_AXI_HP1_AWADDR = 32'h0; + assign S_AXI_HP1_AWLEN = 8'h0; + assign S_AXI_HP1_AWSIZE = 3'h0; + assign S_AXI_HP1_AWBURST = 2'h0; + assign S_AXI_HP1_AWPROT = 3'h0; + assign S_AXI_HP1_AWCACHE = 4'h0; + assign S_AXI_HP1_AWVALID = 1'b0; + //S_AXI_HP1_AWREADY + assign S_AXI_HP1_WDATA = 64'h0; + assign S_AXI_HP1_WSTRB = 8'h0; + assign S_AXI_HP1_WLAST = 1'b0; + assign S_AXI_HP1_WVALID = 1'b0; + //S_AXI_HP1_WREADY + //S_AXI_HP1_BRESP + //S_AXI_HP1_BVALID + assign S_AXI_HP1_BREADY = 1'b1; + +`else + + axi_eth_dma inst_axi_eth_dma1 ( + .s_axi_lite_aclk(clk40), + .m_axi_sg_aclk(clk40), + .m_axi_mm2s_aclk(clk40), + .m_axi_s2mm_aclk(clk40), + .axi_resetn(clk40_rstn), + + .s_axi_lite_awaddr(M_AXI_ETH_DMA1_AWADDR), + .s_axi_lite_awvalid(M_AXI_ETH_DMA1_AWVALID), + .s_axi_lite_awready(M_AXI_ETH_DMA1_AWREADY), + + .s_axi_lite_wdata(M_AXI_ETH_DMA1_WDATA), + .s_axi_lite_wvalid(M_AXI_ETH_DMA1_WVALID), + .s_axi_lite_wready(M_AXI_ETH_DMA1_WREADY), + + .s_axi_lite_bresp(M_AXI_ETH_DMA1_BRESP), + .s_axi_lite_bvalid(M_AXI_ETH_DMA1_BVALID), + .s_axi_lite_bready(M_AXI_ETH_DMA1_BREADY), + + .s_axi_lite_araddr(M_AXI_ETH_DMA1_ARADDR), + .s_axi_lite_arvalid(M_AXI_ETH_DMA1_ARVALID), + .s_axi_lite_arready(M_AXI_ETH_DMA1_ARREADY), + + .s_axi_lite_rdata(M_AXI_ETH_DMA1_RDATA), + .s_axi_lite_rresp(M_AXI_ETH_DMA1_RRESP), + .s_axi_lite_rvalid(M_AXI_ETH_DMA1_RVALID), + .s_axi_lite_rready(M_AXI_ETH_DMA1_RREADY), + + .m_axi_sg_awaddr(S_AXI_GP1_AWADDR), + .m_axi_sg_awlen(S_AXI_GP1_AWLEN), + .m_axi_sg_awsize(S_AXI_GP1_AWSIZE), + .m_axi_sg_awburst(S_AXI_GP1_AWBURST), + .m_axi_sg_awprot(S_AXI_GP1_AWPROT), + .m_axi_sg_awcache(S_AXI_GP1_AWCACHE), + .m_axi_sg_awvalid(S_AXI_GP1_AWVALID), + .m_axi_sg_awready(S_AXI_GP1_AWREADY), + .m_axi_sg_wdata(S_AXI_GP1_WDATA), + .m_axi_sg_wstrb(S_AXI_GP1_WSTRB), + .m_axi_sg_wlast(S_AXI_GP1_WLAST), + .m_axi_sg_wvalid(S_AXI_GP1_WVALID), + .m_axi_sg_wready(S_AXI_GP1_WREADY), + .m_axi_sg_bresp(S_AXI_GP1_BRESP), + .m_axi_sg_bvalid(S_AXI_GP1_BVALID), + .m_axi_sg_bready(S_AXI_GP1_BREADY), + .m_axi_sg_araddr(S_AXI_GP1_ARADDR), + .m_axi_sg_arlen(S_AXI_GP1_ARLEN), + .m_axi_sg_arsize(S_AXI_GP1_ARSIZE), + .m_axi_sg_arburst(S_AXI_GP1_ARBURST), + .m_axi_sg_arprot(S_AXI_GP1_ARPROT), + .m_axi_sg_arcache(S_AXI_GP1_ARCACHE), + .m_axi_sg_arvalid(S_AXI_GP1_ARVALID), + .m_axi_sg_arready(S_AXI_GP1_ARREADY), + .m_axi_sg_rdata(S_AXI_GP1_RDATA), + .m_axi_sg_rresp(S_AXI_GP1_RRESP), + .m_axi_sg_rlast(S_AXI_GP1_RLAST), + .m_axi_sg_rvalid(S_AXI_GP1_RVALID), + .m_axi_sg_rready(S_AXI_GP1_RREADY), + + .m_axi_mm2s_araddr(S_AXI_HP1_ARADDR), + .m_axi_mm2s_arlen(S_AXI_HP1_ARLEN), + .m_axi_mm2s_arsize(S_AXI_HP1_ARSIZE), + .m_axi_mm2s_arburst(S_AXI_HP1_ARBURST), + .m_axi_mm2s_arprot(S_AXI_HP1_ARPROT), + .m_axi_mm2s_arcache(S_AXI_HP1_ARCACHE), + .m_axi_mm2s_arvalid(S_AXI_HP1_ARVALID), + .m_axi_mm2s_arready(S_AXI_HP1_ARREADY), + .m_axi_mm2s_rdata(S_AXI_HP1_RDATA), + .m_axi_mm2s_rresp(S_AXI_HP1_RRESP), + .m_axi_mm2s_rlast(S_AXI_HP1_RLAST), + .m_axi_mm2s_rvalid(S_AXI_HP1_RVALID), + .m_axi_mm2s_rready(S_AXI_HP1_RREADY), + + .mm2s_prmry_reset_out_n(), + .m_axis_mm2s_tdata(arm_eth1_tx_tdata), + .m_axis_mm2s_tkeep(arm_eth1_tx_tkeep), + .m_axis_mm2s_tvalid(arm_eth1_tx_tvalid), + .m_axis_mm2s_tready(arm_eth1_tx_tready), + .m_axis_mm2s_tlast(arm_eth1_tx_tlast), + + .m_axi_s2mm_awaddr(S_AXI_HP1_AWADDR), + .m_axi_s2mm_awlen(S_AXI_HP1_AWLEN), + .m_axi_s2mm_awsize(S_AXI_HP1_AWSIZE), + .m_axi_s2mm_awburst(S_AXI_HP1_AWBURST), + .m_axi_s2mm_awprot(S_AXI_HP1_AWPROT), + .m_axi_s2mm_awcache(S_AXI_HP1_AWCACHE), + .m_axi_s2mm_awvalid(S_AXI_HP1_AWVALID), + .m_axi_s2mm_awready(S_AXI_HP1_AWREADY), + .m_axi_s2mm_wdata(S_AXI_HP1_WDATA), + .m_axi_s2mm_wstrb(S_AXI_HP1_WSTRB), + .m_axi_s2mm_wlast(S_AXI_HP1_WLAST), + .m_axi_s2mm_wvalid(S_AXI_HP1_WVALID), + .m_axi_s2mm_wready(S_AXI_HP1_WREADY), + .m_axi_s2mm_bresp(S_AXI_HP1_BRESP), + .m_axi_s2mm_bvalid(S_AXI_HP1_BVALID), + .m_axi_s2mm_bready(S_AXI_HP1_BREADY), + + .s2mm_prmry_reset_out_n(), + .s_axis_s2mm_tdata(arm_eth1_rx_tdata), + .s_axis_s2mm_tkeep(arm_eth1_rx_tkeep), + .s_axis_s2mm_tvalid(arm_eth1_rx_tvalid), + .s_axis_s2mm_tready(arm_eth1_rx_tready), + .s_axis_s2mm_tlast(arm_eth1_rx_tlast), + + .mm2s_introut(arm_eth1_tx_irq), + .s2mm_introut(arm_eth1_rx_irq), + .axi_dma_tstvec() + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_tx_1_fifo_2clk_i ( + .reset(clk40_rst), + .i_aclk(clk40), + .i_tdata({arm_eth1_tx_tlast, arm_eth1_tx_tkeep, arm_eth1_tx_tdata}), + .i_tvalid(arm_eth1_tx_tvalid), + .i_tready(arm_eth1_tx_tready), + .o_aclk(bus_clk), + .o_tdata({arm_eth1_tx_tlast_b, arm_eth1_tx_tkeep_b, arm_eth1_tx_tdata_b}), + .o_tvalid(arm_eth1_tx_tvalid_b), + .o_tready(arm_eth1_tx_tready_b) + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_rx_1_fifo_2clk_i ( + .reset(bus_rst), + .i_aclk(bus_clk), + .i_tdata({arm_eth1_rx_tlast_b, arm_eth1_rx_tkeep_b, arm_eth1_rx_tdata_b}), + .i_tvalid(arm_eth1_rx_tvalid_b), + .i_tready(arm_eth1_rx_tready_b), + .o_aclk(clk40), + .o_tdata({arm_eth1_rx_tlast, arm_eth1_rx_tkeep, arm_eth1_rx_tdata}), + .o_tvalid(arm_eth1_rx_tvalid), + .o_tready(arm_eth1_rx_tready) + ); +`endif + + ///////////////////////////////////////////////////////////////////// + // + // Processing System + // + ////////////////////////////////////////////////////////////////////// + + wire spi0_sclk; + wire spi0_mosi; + wire spi0_miso; + wire spi0_ss0; + wire spi0_ss1; + wire spi0_ss2; + wire spi1_sclk; + wire spi1_mosi; + wire spi1_miso; + wire spi1_ss0; + wire spi1_ss1; + wire spi1_ss2; + + assign ps_gpio_in[10] = DBA_MYK_INTRQ; +`ifndef N300 + assign ps_gpio_in[11] = DBB_MYK_INTRQ; +`else + assign ps_gpio_in[11] = 1'b0; +`endif + + // Processing System + n310_ps_bd inst_n310_ps ( + .SPI0_SCLK_I(1'b0), + .SPI0_SCLK_O(spi0_sclk), + .SPI0_SCLK_T(), + .SPI0_MOSI_I(1'b0), + .SPI0_MOSI_O(spi0_mosi), + .SPI0_MOSI_T(), + .SPI0_MISO_I(spi0_miso), + .SPI0_MISO_O(), + .SPI0_MISO_T(), + .SPI0_SS_I(1'b1), + .SPI0_SS_O(spi0_ss0), + .SPI0_SS1_O(spi0_ss1), + .SPI0_SS2_O(spi0_ss2), + .SPI0_SS_T(), + + `ifndef N300 + .SPI1_SCLK_I(1'b0), + .SPI1_SCLK_O(spi1_sclk), + .SPI1_SCLK_T(), + .SPI1_MOSI_I(1'b0), + .SPI1_MOSI_O(spi1_mosi), + .SPI1_MOSI_T(), + .SPI1_MISO_I(spi1_miso), + .SPI1_MISO_O(), + .SPI1_MISO_T(), + .SPI1_SS_I(1'b1), + .SPI1_SS_O(spi1_ss0), + .SPI1_SS1_O(spi1_ss1), + .SPI1_SS2_O(spi1_ss2), + .SPI1_SS_T(), + `else + .SPI1_SCLK_I(1'b0), + .SPI1_SCLK_O(), + .SPI1_SCLK_T(), + .SPI1_MOSI_I(1'b0), + .SPI1_MOSI_O(), + .SPI1_MOSI_T(), + .SPI1_MISO_I(1'b0), + .SPI1_MISO_O(), + .SPI1_MISO_T(), + .SPI1_SS_I(1'b1), + .SPI1_SS_O(), + .SPI1_SS1_O(), + .SPI1_SS2_O(), + .SPI1_SS_T(), + `endif + + .bus_clk(bus_clk), + .bus_rstn(~bus_rst), + .clk40(clk40), + .clk40_rstn(clk40_rstn), + + .M_AXI_ETH_DMA0_araddr(M_AXI_ETH_DMA0_ARADDR), + .M_AXI_ETH_DMA0_arprot(), + .M_AXI_ETH_DMA0_arready(M_AXI_ETH_DMA0_ARREADY), + .M_AXI_ETH_DMA0_arvalid(M_AXI_ETH_DMA0_ARVALID), + + .M_AXI_ETH_DMA0_awaddr(M_AXI_ETH_DMA0_AWADDR), + .M_AXI_ETH_DMA0_awprot(), + .M_AXI_ETH_DMA0_awready(M_AXI_ETH_DMA0_AWREADY), + .M_AXI_ETH_DMA0_awvalid(M_AXI_ETH_DMA0_AWVALID), + + .M_AXI_ETH_DMA0_wdata(M_AXI_ETH_DMA0_WDATA), + .M_AXI_ETH_DMA0_wready(M_AXI_ETH_DMA0_WREADY), + .M_AXI_ETH_DMA0_wstrb(M_AXI_ETH_DMA0_WSTRB), + .M_AXI_ETH_DMA0_wvalid(M_AXI_ETH_DMA0_WVALID), + + .M_AXI_ETH_DMA0_rdata(M_AXI_ETH_DMA0_RDATA), + .M_AXI_ETH_DMA0_rready(M_AXI_ETH_DMA0_RREADY), + .M_AXI_ETH_DMA0_rresp(M_AXI_ETH_DMA0_RRESP), + .M_AXI_ETH_DMA0_rvalid(M_AXI_ETH_DMA0_RVALID), + + .M_AXI_ETH_DMA0_bready(M_AXI_ETH_DMA0_BREADY), + .M_AXI_ETH_DMA0_bresp(M_AXI_ETH_DMA0_BRESP), + .M_AXI_ETH_DMA0_bvalid(M_AXI_ETH_DMA0_BVALID), + + .M_AXI_ETH_DMA1_araddr(M_AXI_ETH_DMA1_ARADDR), + .M_AXI_ETH_DMA1_arprot(), + .M_AXI_ETH_DMA1_arready(M_AXI_ETH_DMA1_ARREADY), + .M_AXI_ETH_DMA1_arvalid(M_AXI_ETH_DMA1_ARVALID), + + .M_AXI_ETH_DMA1_awaddr(M_AXI_ETH_DMA1_AWADDR), + .M_AXI_ETH_DMA1_awprot(), + .M_AXI_ETH_DMA1_awready(M_AXI_ETH_DMA1_AWREADY), + .M_AXI_ETH_DMA1_awvalid(M_AXI_ETH_DMA1_AWVALID), + + .M_AXI_ETH_DMA1_bready(M_AXI_ETH_DMA1_BREADY), + .M_AXI_ETH_DMA1_bresp(M_AXI_ETH_DMA1_BRESP), + .M_AXI_ETH_DMA1_bvalid(M_AXI_ETH_DMA1_BVALID), + + .M_AXI_ETH_DMA1_rdata(M_AXI_ETH_DMA1_RDATA), + .M_AXI_ETH_DMA1_rready(M_AXI_ETH_DMA1_RREADY), + .M_AXI_ETH_DMA1_rresp(M_AXI_ETH_DMA1_RRESP), + .M_AXI_ETH_DMA1_rvalid(M_AXI_ETH_DMA1_RVALID), + + .M_AXI_ETH_DMA1_wdata(M_AXI_ETH_DMA1_WDATA), + .M_AXI_ETH_DMA1_wready(M_AXI_ETH_DMA1_WREADY), + .M_AXI_ETH_DMA1_wstrb(M_AXI_ETH_DMA1_WSTRB), + .M_AXI_ETH_DMA1_wvalid(M_AXI_ETH_DMA1_WVALID), + + .M_AXI_JESD0_araddr(M_AXI_JESD0_ARADDR), + .M_AXI_JESD0_arprot(), + .M_AXI_JESD0_arready(M_AXI_JESD0_ARREADY), + .M_AXI_JESD0_arvalid(M_AXI_JESD0_ARVALID), + + .M_AXI_JESD0_awaddr(M_AXI_JESD0_AWADDR), + .M_AXI_JESD0_awprot(), + .M_AXI_JESD0_awready(M_AXI_JESD0_AWREADY), + .M_AXI_JESD0_awvalid(M_AXI_JESD0_AWVALID), + + .M_AXI_JESD0_bready(M_AXI_JESD0_BREADY), + .M_AXI_JESD0_bresp(M_AXI_JESD0_BRESP), + .M_AXI_JESD0_bvalid(M_AXI_JESD0_BVALID), + + .M_AXI_JESD0_rdata(M_AXI_JESD0_RDATA), + .M_AXI_JESD0_rready(M_AXI_JESD0_RREADY), + .M_AXI_JESD0_rresp(M_AXI_JESD0_RRESP), + .M_AXI_JESD0_rvalid(M_AXI_JESD0_RVALID), + + .M_AXI_JESD0_wdata(M_AXI_JESD0_WDATA), + .M_AXI_JESD0_wready(M_AXI_JESD0_WREADY), + .M_AXI_JESD0_wstrb(M_AXI_JESD0_WSTRB), + .M_AXI_JESD0_wvalid(M_AXI_JESD0_WVALID), + + .M_AXI_JESD1_araddr(M_AXI_JESD1_ARADDR), + .M_AXI_JESD1_arprot(), + .M_AXI_JESD1_arready(M_AXI_JESD1_ARREADY), + .M_AXI_JESD1_arvalid(M_AXI_JESD1_ARVALID), + + .M_AXI_JESD1_awaddr(M_AXI_JESD1_AWADDR), + .M_AXI_JESD1_awprot(), + .M_AXI_JESD1_awready(M_AXI_JESD1_AWREADY), + .M_AXI_JESD1_awvalid(M_AXI_JESD1_AWVALID), + + .M_AXI_JESD1_bready(M_AXI_JESD1_BREADY), + .M_AXI_JESD1_bresp(M_AXI_JESD1_BRESP), + .M_AXI_JESD1_bvalid(M_AXI_JESD1_BVALID), + + .M_AXI_JESD1_rdata(M_AXI_JESD1_RDATA), + .M_AXI_JESD1_rready(M_AXI_JESD1_RREADY), + .M_AXI_JESD1_rresp(M_AXI_JESD1_RRESP), + .M_AXI_JESD1_rvalid(M_AXI_JESD1_RVALID), + + .M_AXI_JESD1_wdata(M_AXI_JESD1_WDATA), + .M_AXI_JESD1_wready(M_AXI_JESD1_WREADY), + .M_AXI_JESD1_wstrb(M_AXI_JESD1_WSTRB), + .M_AXI_JESD1_wvalid(M_AXI_JESD1_WVALID), + + .M_AXI_NET0_araddr(M_AXI_NET0_ARADDR), + .M_AXI_NET0_arprot(), + .M_AXI_NET0_arready(M_AXI_NET0_ARREADY), + .M_AXI_NET0_arvalid(M_AXI_NET0_ARVALID), + + .M_AXI_NET0_awaddr(M_AXI_NET0_AWADDR), + .M_AXI_NET0_awprot(), + .M_AXI_NET0_awready(M_AXI_NET0_AWREADY), + .M_AXI_NET0_awvalid(M_AXI_NET0_AWVALID), + + .M_AXI_NET0_bready(M_AXI_NET0_BREADY), + .M_AXI_NET0_bresp(M_AXI_NET0_BRESP), + .M_AXI_NET0_bvalid(M_AXI_NET0_BVALID), + + .M_AXI_NET0_rdata(M_AXI_NET0_RDATA), + .M_AXI_NET0_rready(M_AXI_NET0_RREADY), + .M_AXI_NET0_rresp(M_AXI_NET0_RRESP), + .M_AXI_NET0_rvalid(M_AXI_NET0_RVALID), + + .M_AXI_NET0_wdata(M_AXI_NET0_WDATA), + .M_AXI_NET0_wready(M_AXI_NET0_WREADY), + .M_AXI_NET0_wstrb(M_AXI_NET0_WSTRB), + .M_AXI_NET0_wvalid(M_AXI_NET0_WVALID), + + .M_AXI_NET1_araddr(M_AXI_NET1_ARADDR), + .M_AXI_NET1_arprot(), + .M_AXI_NET1_arready(M_AXI_NET1_ARREADY), + .M_AXI_NET1_arvalid(M_AXI_NET1_ARVALID), + + .M_AXI_NET1_awaddr(M_AXI_NET1_AWADDR), + .M_AXI_NET1_awprot(), + .M_AXI_NET1_awready(M_AXI_NET1_AWREADY), + .M_AXI_NET1_awvalid(M_AXI_NET1_AWVALID), + + .M_AXI_NET1_bready(M_AXI_NET1_BREADY), + .M_AXI_NET1_bresp(M_AXI_NET1_BRESP), + .M_AXI_NET1_bvalid(M_AXI_NET1_BVALID), + + .M_AXI_NET1_rdata(M_AXI_NET1_RDATA), + .M_AXI_NET1_rready(M_AXI_NET1_RREADY), + .M_AXI_NET1_rresp(M_AXI_NET1_RRESP), + .M_AXI_NET1_rvalid(M_AXI_NET1_RVALID), + + .M_AXI_NET1_wdata(M_AXI_NET1_WDATA), + .M_AXI_NET1_wready(M_AXI_NET1_WREADY), + .M_AXI_NET1_wstrb(M_AXI_NET1_WSTRB), + .M_AXI_NET1_wvalid(M_AXI_NET1_WVALID), + + .M_AXI_NET2_araddr(M_AXI_NET2_ARADDR), + .M_AXI_NET2_arprot(), + .M_AXI_NET2_arready(M_AXI_NET2_ARREADY), + .M_AXI_NET2_arvalid(M_AXI_NET2_ARVALID), + + .M_AXI_NET2_awaddr(M_AXI_NET2_AWADDR), + .M_AXI_NET2_awprot(), + .M_AXI_NET2_awready(M_AXI_NET2_AWREADY), + .M_AXI_NET2_awvalid(M_AXI_NET2_AWVALID), + + .M_AXI_NET2_bready(M_AXI_NET2_BREADY), + .M_AXI_NET2_bresp(M_AXI_NET2_BRESP), + .M_AXI_NET2_bvalid(M_AXI_NET2_BVALID), + + .M_AXI_NET2_rdata(M_AXI_NET2_RDATA), + .M_AXI_NET2_rready(M_AXI_NET2_RREADY), + .M_AXI_NET2_rresp(M_AXI_NET2_RRESP), + .M_AXI_NET2_rvalid(M_AXI_NET2_RVALID), + + .M_AXI_NET2_wdata(M_AXI_NET2_WDATA), + .M_AXI_NET2_wready(M_AXI_NET2_WREADY), + .M_AXI_NET2_wstrb(M_AXI_NET2_WSTRB), + .M_AXI_NET2_wvalid(M_AXI_NET2_WVALID), + + .M_AXI_WR_CLK(m_axi_wr_clk), + .M_AXI_WR_RSTn(1'b1), + .M_AXI_WR_araddr(m_axi_wr_araddr), + .M_AXI_WR_arready(m_axi_wr_arready), + .M_AXI_WR_arvalid(m_axi_wr_arvalid), + .M_AXI_WR_awaddr(m_axi_wr_awaddr), + .M_AXI_WR_awready(m_axi_wr_awready), + .M_AXI_WR_awvalid(m_axi_wr_awvalid), + .M_AXI_WR_bready(m_axi_wr_bready), + .M_AXI_WR_bresp(m_axi_wr_bresp), + .M_AXI_WR_bvalid(m_axi_wr_bvalid), + .M_AXI_WR_rdata(m_axi_wr_rdata), + .M_AXI_WR_rready(m_axi_wr_rready), + .M_AXI_WR_rresp(m_axi_wr_rresp), + .M_AXI_WR_rvalid(m_axi_wr_rvalid), + .M_AXI_WR_wdata(m_axi_wr_wdata), + .M_AXI_WR_wready(m_axi_wr_wready), + .M_AXI_WR_wstrb(m_axi_wr_wstrb), + .M_AXI_WR_wvalid(m_axi_wr_wvalid), + + .M_AXI_XBAR_araddr(M_AXI_XBAR_ARADDR), + .M_AXI_XBAR_arprot(), + .M_AXI_XBAR_arready(M_AXI_XBAR_ARREADY), + .M_AXI_XBAR_arvalid(M_AXI_XBAR_ARVALID), + + .M_AXI_XBAR_awaddr(M_AXI_XBAR_AWADDR), + .M_AXI_XBAR_awprot(), + .M_AXI_XBAR_awready(M_AXI_XBAR_AWREADY), + .M_AXI_XBAR_awvalid(M_AXI_XBAR_AWVALID), + + .M_AXI_XBAR_bready(M_AXI_XBAR_BREADY), + .M_AXI_XBAR_bresp(M_AXI_XBAR_BRESP), + .M_AXI_XBAR_bvalid(M_AXI_XBAR_BVALID), + + .M_AXI_XBAR_rdata(M_AXI_XBAR_RDATA), + .M_AXI_XBAR_rready(M_AXI_XBAR_RREADY), + .M_AXI_XBAR_rresp(M_AXI_XBAR_RRESP), + .M_AXI_XBAR_rvalid(M_AXI_XBAR_RVALID), + + .M_AXI_XBAR_wdata(M_AXI_XBAR_WDATA), + .M_AXI_XBAR_wready(M_AXI_XBAR_WREADY), + .M_AXI_XBAR_wstrb(M_AXI_XBAR_WSTRB), + .M_AXI_XBAR_wvalid(M_AXI_XBAR_WVALID), + + .S_AXI_GP0_ACLK(clk40), + .S_AXI_GP0_ARESETN(clk40_rstn), + .S_AXI_GP0_araddr(S_AXI_GP0_ARADDR), + .S_AXI_GP0_arburst(S_AXI_GP0_ARBURST), + .S_AXI_GP0_arcache(S_AXI_GP0_ARCACHE), + .S_AXI_GP0_arid(S_AXI_GP0_ARID), + .S_AXI_GP0_arlen(S_AXI_GP0_ARLEN), + .S_AXI_GP0_arlock(1'b0), + .S_AXI_GP0_arprot(S_AXI_GP0_ARPROT), + .S_AXI_GP0_arqos(4'b0000), + .S_AXI_GP0_arready(S_AXI_GP0_ARREADY), + .S_AXI_GP0_arsize(S_AXI_GP0_ARSIZE), + .S_AXI_GP0_arvalid(S_AXI_GP0_ARVALID), + .S_AXI_GP0_awaddr(S_AXI_GP0_AWADDR), + .S_AXI_GP0_awburst(S_AXI_GP0_AWBURST), + .S_AXI_GP0_awcache(S_AXI_GP0_AWCACHE), + .S_AXI_GP0_awid(S_AXI_GP0_AWID), + .S_AXI_GP0_awlen(S_AXI_GP0_AWLEN), + .S_AXI_GP0_awlock(1'b0), + .S_AXI_GP0_awprot(S_AXI_GP0_AWPROT), + .S_AXI_GP0_awqos(4'b0000), + .S_AXI_GP0_awregion(4'b0000), + .S_AXI_GP0_awready(S_AXI_GP0_AWREADY), + .S_AXI_GP0_awsize(S_AXI_GP0_AWSIZE), + .S_AXI_GP0_awvalid(S_AXI_GP0_AWVALID), + .S_AXI_GP0_bid(), + .S_AXI_GP0_bready(S_AXI_GP0_BREADY), + .S_AXI_GP0_bresp(S_AXI_GP0_BRESP), + .S_AXI_GP0_bvalid(S_AXI_GP0_BVALID), + .S_AXI_GP0_rdata(S_AXI_GP0_RDATA), + .S_AXI_GP0_rid(), + .S_AXI_GP0_rlast(S_AXI_GP0_RLAST), + .S_AXI_GP0_rready(S_AXI_GP0_RREADY), + .S_AXI_GP0_rresp(S_AXI_GP0_RRESP), + .S_AXI_GP0_rvalid(S_AXI_GP0_RVALID), + .S_AXI_GP0_wdata(S_AXI_GP0_WDATA), + .S_AXI_GP0_wlast(S_AXI_GP0_WLAST), + .S_AXI_GP0_wready(S_AXI_GP0_WREADY), + .S_AXI_GP0_wstrb(S_AXI_GP0_WSTRB), + .S_AXI_GP0_wvalid(S_AXI_GP0_WVALID), + + .S_AXI_GP1_ACLK(clk40), + .S_AXI_GP1_ARESETN(clk40_rstn), + .S_AXI_GP1_araddr(S_AXI_GP1_ARADDR), + .S_AXI_GP1_arburst(S_AXI_GP1_ARBURST), + .S_AXI_GP1_arcache(S_AXI_GP1_ARCACHE), + .S_AXI_GP1_arid(S_AXI_GP1_ARID), + .S_AXI_GP1_arlen(S_AXI_GP1_ARLEN), + .S_AXI_GP1_arlock(1'b0), + .S_AXI_GP1_arprot(S_AXI_GP1_ARPROT), + .S_AXI_GP1_arqos(4'b000), + .S_AXI_GP1_arready(S_AXI_GP1_ARREADY), + .S_AXI_GP1_arsize(S_AXI_GP1_ARSIZE), + .S_AXI_GP1_arvalid(S_AXI_GP1_ARVALID), + .S_AXI_GP1_awaddr(S_AXI_GP1_AWADDR), + .S_AXI_GP1_awburst(S_AXI_GP1_AWBURST), + .S_AXI_GP1_awcache(S_AXI_GP1_AWCACHE), + .S_AXI_GP1_awid(S_AXI_GP1_AWID), + .S_AXI_GP1_awlen(S_AXI_GP1_AWLEN), + .S_AXI_GP1_awlock(1'b0), + .S_AXI_GP1_awprot(S_AXI_GP1_AWPROT), + .S_AXI_GP1_awqos(4'b0000), + .S_AXI_GP1_awregion(4'b0000), + .S_AXI_GP1_awready(S_AXI_GP1_AWREADY), + .S_AXI_GP1_awsize(S_AXI_GP1_AWSIZE), + .S_AXI_GP1_awvalid(S_AXI_GP1_AWVALID), + .S_AXI_GP1_bid(), + .S_AXI_GP1_bready(S_AXI_GP1_BREADY), + .S_AXI_GP1_bresp(S_AXI_GP1_BRESP), + .S_AXI_GP1_bvalid(S_AXI_GP1_BVALID), + .S_AXI_GP1_rdata(S_AXI_GP1_RDATA), + .S_AXI_GP1_rid(), + .S_AXI_GP1_rlast(S_AXI_GP1_RLAST), + .S_AXI_GP1_rready(S_AXI_GP1_RREADY), + .S_AXI_GP1_rresp(S_AXI_GP1_RRESP), + .S_AXI_GP1_rvalid(S_AXI_GP1_RVALID), + .S_AXI_GP1_wdata(S_AXI_GP1_WDATA), + .S_AXI_GP1_wlast(S_AXI_GP1_WLAST), + .S_AXI_GP1_wready(S_AXI_GP1_WREADY), + .S_AXI_GP1_wstrb(S_AXI_GP1_WSTRB), + .S_AXI_GP1_wvalid(S_AXI_GP1_WVALID), + + .S_AXI_HP0_ACLK(clk40), + .S_AXI_HP0_ARESETN(clk40_rstn), + .S_AXI_HP0_araddr(S_AXI_HP0_ARADDR), + .S_AXI_HP0_arburst(S_AXI_HP0_ARBURST), + .S_AXI_HP0_arcache(S_AXI_HP0_ARCACHE), + .S_AXI_HP0_arid(S_AXI_HP0_ARID), + .S_AXI_HP0_arlen(S_AXI_HP0_ARLEN), + .S_AXI_HP0_arlock(1'b0), + .S_AXI_HP0_arprot(S_AXI_HP0_ARPROT), + .S_AXI_HP0_arqos(4'b0000), + .S_AXI_HP0_arready(S_AXI_HP0_ARREADY), + .S_AXI_HP0_arsize(S_AXI_HP0_ARSIZE), + .S_AXI_HP0_arvalid(S_AXI_HP0_ARVALID), + .S_AXI_HP0_awaddr(S_AXI_HP0_AWADDR), + .S_AXI_HP0_awburst(S_AXI_HP0_AWBURST), + .S_AXI_HP0_awcache(S_AXI_HP0_AWCACHE), + .S_AXI_HP0_awid(S_AXI_HP0_AWID), + .S_AXI_HP0_awlen(S_AXI_HP0_AWLEN), + .S_AXI_HP0_awlock(1'b0), + .S_AXI_HP0_awprot(S_AXI_HP0_AWPROT), + .S_AXI_HP0_awqos(4'b0000), + .S_AXI_HP0_awready(S_AXI_HP0_AWREADY), + .S_AXI_HP0_awsize(S_AXI_HP0_AWSIZE), + .S_AXI_HP0_awvalid(S_AXI_HP0_AWVALID), + .S_AXI_HP0_bid(), + .S_AXI_HP0_bready(S_AXI_HP0_BREADY), + .S_AXI_HP0_bresp(S_AXI_HP0_BRESP), + .S_AXI_HP0_bvalid(S_AXI_HP0_BVALID), + .S_AXI_HP0_rdata(S_AXI_HP0_RDATA), + .S_AXI_HP0_rid(), + .S_AXI_HP0_rlast(S_AXI_HP0_RLAST), + .S_AXI_HP0_rready(S_AXI_HP0_RREADY), + .S_AXI_HP0_rresp(S_AXI_HP0_RRESP), + .S_AXI_HP0_rvalid(S_AXI_HP0_RVALID), + .S_AXI_HP0_wdata(S_AXI_HP0_WDATA), + .S_AXI_HP0_wlast(S_AXI_HP0_WLAST), + .S_AXI_HP0_wready(S_AXI_HP0_WREADY), + .S_AXI_HP0_wstrb(S_AXI_HP0_WSTRB), + .S_AXI_HP0_wvalid(S_AXI_HP0_WVALID), + + .S_AXI_HP1_ACLK(clk40), + .S_AXI_HP1_ARESETN(clk40_rstn), + .S_AXI_HP1_araddr(S_AXI_HP1_ARADDR), + .S_AXI_HP1_arburst(S_AXI_HP1_ARBURST), + .S_AXI_HP1_arcache(S_AXI_HP1_ARCACHE), + .S_AXI_HP1_arid(S_AXI_HP1_ARID), + .S_AXI_HP1_arlen(S_AXI_HP1_ARLEN), + .S_AXI_HP1_arlock(1'b0), + .S_AXI_HP1_arprot(S_AXI_HP1_ARPROT), + .S_AXI_HP1_arqos(4'b0000), + .S_AXI_HP1_arready(S_AXI_HP1_ARREADY), + .S_AXI_HP1_arsize(S_AXI_HP1_ARSIZE), + .S_AXI_HP1_arvalid(S_AXI_HP1_ARVALID), + .S_AXI_HP1_awaddr(S_AXI_HP1_AWADDR), + .S_AXI_HP1_awburst(S_AXI_HP1_AWBURST), + .S_AXI_HP1_awcache(S_AXI_HP1_AWCACHE), + .S_AXI_HP1_awid(S_AXI_HP1_AWID), + .S_AXI_HP1_awlen(S_AXI_HP1_AWLEN), + .S_AXI_HP1_awlock(1'b0), + .S_AXI_HP1_awprot(S_AXI_HP1_AWPROT), + .S_AXI_HP1_awqos(4'b0000), + .S_AXI_HP1_awready(S_AXI_HP1_AWREADY), + .S_AXI_HP1_awsize(S_AXI_HP1_AWSIZE), + .S_AXI_HP1_awvalid(S_AXI_HP1_AWVALID), + .S_AXI_HP1_bid(), + .S_AXI_HP1_bready(S_AXI_HP1_BREADY), + .S_AXI_HP1_bresp(S_AXI_HP1_BRESP), + .S_AXI_HP1_bvalid(S_AXI_HP1_BVALID), + .S_AXI_HP1_rdata(S_AXI_HP1_RDATA), + .S_AXI_HP1_rid(), + .S_AXI_HP1_rlast(S_AXI_HP1_RLAST), + .S_AXI_HP1_rready(S_AXI_HP1_RREADY), + .S_AXI_HP1_rresp(S_AXI_HP1_RRESP), + .S_AXI_HP1_rvalid(S_AXI_HP1_RVALID), + .S_AXI_HP1_wdata(S_AXI_HP1_WDATA), + .S_AXI_HP1_wlast(S_AXI_HP1_WLAST), + .S_AXI_HP1_wready(S_AXI_HP1_WREADY), + .S_AXI_HP1_wstrb(S_AXI_HP1_WSTRB), + .S_AXI_HP1_wvalid(S_AXI_HP1_WVALID), + + // ARM DMA + .s_axis_dma_tdata(s_axis_dma_tdata), + .s_axis_dma_tdest(s_axis_dma_tdest), + .s_axis_dma_tlast(s_axis_dma_tlast), + .s_axis_dma_tready(s_axis_dma_tready), + .s_axis_dma_tvalid(s_axis_dma_tvalid), + .m_axis_dma_tdata(m_axis_dma_tdata), + .m_axis_dma_tuser(m_axis_dma_tuser), + .m_axis_dma_tlast(m_axis_dma_tlast), + .m_axis_dma_tready(m_axis_dma_tready), + .m_axis_dma_tvalid(m_axis_dma_tvalid), + + // Misc Interrupts, GPIO, clk + .IRQ_F2P(IRQ_F2P), + + .GPIO_0_tri_i(ps_gpio_in), + .GPIO_0_tri_o(ps_gpio_out), + .GPIO_0_tri_t(ps_gpio_tri), + + .JTAG0_TCK(DBA_CPLD_JTAG_TCK), + .JTAG0_TMS(DBA_CPLD_JTAG_TMS), + .JTAG0_TDI(DBA_CPLD_JTAG_TDI), + .JTAG0_TDO(DBA_CPLD_JTAG_TDO), + + `ifndef N300 + .JTAG1_TCK(DBB_CPLD_JTAG_TCK), + .JTAG1_TMS(DBB_CPLD_JTAG_TMS), + .JTAG1_TDI(DBB_CPLD_JTAG_TDI), + .JTAG1_TDO(DBB_CPLD_JTAG_TDO), + `else + .JTAG1_TCK(), + .JTAG1_TMS(), + .JTAG1_TDI(), + .JTAG1_TDO('b0), + `endif + + .FCLK_CLK0(FCLK_CLK0), + .FCLK_RESET0_N(FCLK_RESET0_N), + .FCLK_CLK1(FCLK_CLK1), + .FCLK_RESET1_N(), + .FCLK_CLK2(FCLK_CLK2), + .FCLK_RESET2_N(), + .FCLK_CLK3(FCLK_CLK3), + .FCLK_RESET3_N(), + + .WR_UART_txd(wr_uart_rxd), // rx <-> tx + .WR_UART_rxd(wr_uart_txd), // rx <-> tx + + .qsfp_sda_i(qsfp_sda_i), + .qsfp_sda_o(qsfp_sda_o), + .qsfp_sda_t(qsfp_sda_t), + .qsfp_scl_i(qsfp_scl_i), + .qsfp_scl_o(qsfp_scl_o), + .qsfp_scl_t(qsfp_scl_t), + + .USBIND_0_port_indctl(), + .USBIND_0_vbus_pwrfault(), + .USBIND_0_vbus_pwrselect(), + + // Outward connections to the pins + .MIO(MIO), + .DDR_cas_n(DDR_CAS_n), + .DDR_cke(DDR_CKE), + .DDR_ck_n(DDR_Clk_n), + .DDR_ck_p(DDR_Clk), + .DDR_cs_n(DDR_CS_n), + .DDR_reset_n(DDR_DRSTB), + .DDR_odt(DDR_ODT), + .DDR_ras_n(DDR_RAS_n), + .DDR_we_n(DDR_WEB), + .DDR_ba(DDR_BankAddr), + .DDR_addr(DDR_Addr), + .DDR_VRN(DDR_VRN), + .DDR_VRP(DDR_VRP), + .DDR_dm(DDR_DM), + .DDR_dq(DDR_DQ), + .DDR_dqs_n(DDR_DQS_n), + .DDR_dqs_p(DDR_DQS), + .PS_SRSTB(PS_SRSTB), + .PS_CLK(PS_CLK), + .PS_PORB(PS_PORB) + ); + + /////////////////////////////////////////////////////////////////////////////////// + // + // Xilinx DDR3 Controller and PHY. + // + /////////////////////////////////////////////////////////////////////////////////// + + wire ddr3_axi_clk; // 1/4 DDR external clock rate (200MHz) + wire ddr3_axi_rst; // Synchronized to ddr_sys_clk + wire ddr3_running; // DRAM calibration complete. + wire [11:0] device_temp; + + // Slave Interface Write Address Ports + wire [3:0] ddr3_axi_awid; + wire [31:0] ddr3_axi_awaddr; + wire [7:0] ddr3_axi_awlen; + wire [2:0] ddr3_axi_awsize; + wire [1:0] ddr3_axi_awburst; + wire [0:0] ddr3_axi_awlock; + wire [3:0] ddr3_axi_awcache; + wire [2:0] ddr3_axi_awprot; + wire [3:0] ddr3_axi_awqos; + wire ddr3_axi_awvalid; + wire ddr3_axi_awready; + // Slave Interface Write Data Ports + wire [255:0] ddr3_axi_wdata; + wire [31:0] ddr3_axi_wstrb; + wire ddr3_axi_wlast; + wire ddr3_axi_wvalid; + wire ddr3_axi_wready; + // Slave Interface Write Response Ports + wire ddr3_axi_bready; + wire [3:0] ddr3_axi_bid; + wire [1:0] ddr3_axi_bresp; + wire ddr3_axi_bvalid; + // Slave Interface Read Address Ports + wire [3:0] ddr3_axi_arid; + wire [31:0] ddr3_axi_araddr; + wire [7:0] ddr3_axi_arlen; + wire [2:0] ddr3_axi_arsize; + wire [1:0] ddr3_axi_arburst; + wire [0:0] ddr3_axi_arlock; + wire [3:0] ddr3_axi_arcache; + wire [2:0] ddr3_axi_arprot; + wire [3:0] ddr3_axi_arqos; + wire ddr3_axi_arvalid; + wire ddr3_axi_arready; + // Slave Interface Read Data Ports + wire ddr3_axi_rready; + wire [3:0] ddr3_axi_rid; + wire [255:0] ddr3_axi_rdata; + wire [1:0] ddr3_axi_rresp; + wire ddr3_axi_rlast; + wire ddr3_axi_rvalid; + + reg ddr3_axi_rst_reg_n; + + // Copied this reset circuit from example design. + always @(posedge ddr3_axi_clk) + ddr3_axi_rst_reg_n <= ~ddr3_axi_rst; + + + // Instantiate the DDR3 MIG core + // + // The top-level IP block has no parameters defined for some reason. + // Most of configurable parameters are hard-coded in the mig so get + // some additional knobs we pull those out into verilog headers. + // + // Synthesis params: ip/ddr3_32bit/ddr3_32bit_mig_parameters.vh + // Simulation params: ip/ddr3_32bit/ddr3_32bit_mig_sim_parameters.vh + + ddr3_32bit u_ddr3_32bit ( + // Memory interface ports + .ddr3_addr (ddr3_addr), + .ddr3_ba (ddr3_ba), + .ddr3_cas_n (ddr3_cas_n), + .ddr3_ck_n (ddr3_ck_n), + .ddr3_ck_p (ddr3_ck_p), + .ddr3_cke (ddr3_cke), + .ddr3_ras_n (ddr3_ras_n), + .ddr3_reset_n (ddr3_reset_n), + .ddr3_we_n (ddr3_we_n), + .ddr3_dq (ddr3_dq), + .ddr3_dqs_n (ddr3_dqs_n), + .ddr3_dqs_p (ddr3_dqs_p), + .init_calib_complete (ddr3_running), + .device_temp_i (device_temp), + + .ddr3_cs_n (ddr3_cs_n), + .ddr3_dm (ddr3_dm), + .ddr3_odt (ddr3_odt), + // Application interface ports + .ui_clk (ddr3_axi_clk), // 200Hz clock out + .ui_clk_sync_rst (ddr3_axi_rst), // Active high Reset signal synchronised to 200 MHz. + .aresetn (ddr3_axi_rst_reg_n), + .app_sr_req (1'b0), + .app_sr_active (), + .app_ref_req (1'b0), + .app_ref_ack (), + .app_zq_req (1'b0), + .app_zq_ack (), + // Slave Interface Write Address Ports + .s_axi_awid (ddr3_axi_awid), + .s_axi_awaddr (ddr3_axi_awaddr), + .s_axi_awlen (ddr3_axi_awlen), + .s_axi_awsize (ddr3_axi_awsize), + .s_axi_awburst (ddr3_axi_awburst), + .s_axi_awlock (ddr3_axi_awlock), + .s_axi_awcache (ddr3_axi_awcache), + .s_axi_awprot (ddr3_axi_awprot), + .s_axi_awqos (ddr3_axi_awqos), + .s_axi_awvalid (ddr3_axi_awvalid), + .s_axi_awready (ddr3_axi_awready), + // Slave Interface Write Data Ports + .s_axi_wdata (ddr3_axi_wdata), + .s_axi_wstrb (ddr3_axi_wstrb), + .s_axi_wlast (ddr3_axi_wlast), + .s_axi_wvalid (ddr3_axi_wvalid), + .s_axi_wready (ddr3_axi_wready), + // Slave Interface Write Response Ports + .s_axi_bid (ddr3_axi_bid), + .s_axi_bresp (ddr3_axi_bresp), + .s_axi_bvalid (ddr3_axi_bvalid), + .s_axi_bready (ddr3_axi_bready), + // Slave Interface Read Address Ports + .s_axi_arid (ddr3_axi_arid), + .s_axi_araddr (ddr3_axi_araddr), + .s_axi_arlen (ddr3_axi_arlen), + .s_axi_arsize (ddr3_axi_arsize), + .s_axi_arburst (ddr3_axi_arburst), + .s_axi_arlock (ddr3_axi_arlock), + .s_axi_arcache (ddr3_axi_arcache), + .s_axi_arprot (ddr3_axi_arprot), + .s_axi_arqos (ddr3_axi_arqos), + .s_axi_arvalid (ddr3_axi_arvalid), + .s_axi_arready (ddr3_axi_arready), + // Slave Interface Read Data Ports + .s_axi_rid (ddr3_axi_rid), + .s_axi_rdata (ddr3_axi_rdata), + .s_axi_rresp (ddr3_axi_rresp), + .s_axi_rlast (ddr3_axi_rlast), + .s_axi_rvalid (ddr3_axi_rvalid), + .s_axi_rready (ddr3_axi_rready), + // System Clock Ports + .sys_clk_p (sys_clk_p), + .sys_clk_n (sys_clk_n), + .clk_ref_i (bus_clk), + + .sys_rst (~global_rst) // IJB. Poorly named active low. Should change RST_ACT_LOW. + ); + + // Temperature monitor module + mig_7series_v4_2_tempmon #( + .TEMP_MON_CONTROL("INTERNAL"), + .XADC_CLK_PERIOD(5000 /* 200MHz clock period in ps */) + ) tempmon_i ( + .clk(bus_clk), .xadc_clk(bus_clk), .rst(bus_rst), + .device_temp_i(12'd0 /* ignored */), .device_temp(device_temp) + ); + + /////////////////////////////////////////////////////// + // + // DB PS SPI Connections + // + /////////////////////////////////////////////////////// + wire [NUM_CHANNELS-1:0] rx_atr; + wire [NUM_CHANNELS-1:0] tx_atr; + (* IOB = "true" *) reg [NUM_CHANNELS-1:0] rx_atr_reg; + (* IOB = "true" *) reg [NUM_CHANNELS-1:0] tx_atr_reg; + + // Radio GPIO control for DSA + wire [16*NUM_CHANNELS-1:0] db_gpio_out; + wire [16*NUM_CHANNELS-1:0] db_gpio_ddr; + wire [16*NUM_CHANNELS-1:0] db_gpio_in; + wire [16*NUM_CHANNELS-1:0] db_gpio_fab; + + // DB A SPI Connections + wire cpld_a_cs_n; + wire lmk_a_cs_n; + wire dac_a_cs_n; + wire myk_a_cs_n; + + // Split out the SCLK and MOSI data to Mykonos and the CPLD. + assign DBA_CPLD_PS_SPI_SCLK = spi0_sclk; + assign DBA_CPLD_PS_SPI_SDI = spi0_mosi; + + assign DBA_MYK_SPI_SCLK = spi0_sclk; + assign DBA_MYK_SPI_SDIO = spi0_mosi; + // Assign individual chip selects from PS SPI MASTER 0. + assign cpld_a_cs_n = spi0_ss0; + assign lmk_a_cs_n = spi0_ss1; + assign dac_a_cs_n = ps_gpio_out[8]; // DAC select driven through GPIO. + assign myk_a_cs_n = spi0_ss2; + + // Returned data mux from the SPI interfaces. + assign spi0_miso = ~myk_a_cs_n ? DBA_MYK_SPI_SDO : // From Mykonos + DBA_CPLD_PS_SPI_SDO; + + // For the PS SPI connection to the CPLD, we use the LE and ADDR lines as individual + // chip selects for the CPLD endpoint as well as the LMK and DAC endpoints. + // LE = CPLD + // ADDR[0] = LMK + // ADDR[1] = DAC + assign DBA_CPLD_PS_SPI_LE = cpld_a_cs_n; + assign DBA_CPLD_PS_SPI_ADDR[0] = lmk_a_cs_n; + assign DBA_CPLD_PS_SPI_ADDR[1] = dac_a_cs_n; + assign DBA_MYK_SPI_CS_n = myk_a_cs_n; + + // Instantiate DSA registers in the IOB + (* IOB = "true" *) reg [5:0] dsa_tx1_a_out_iob, dsa_rx1_a_out_iob; + (* IOB = "true" *) reg [5:0] dsa_tx2_a_out_iob, dsa_rx2_a_out_iob; + always @(posedge radio_clk) begin + dsa_tx1_a_out_iob <= db_gpio_out[16*0+11:16*0+6]; + dsa_rx1_a_out_iob <= db_gpio_out[16*0+5:16*0+0]; + dsa_tx2_a_out_iob <= db_gpio_out[16*1+11:16*1+6]; + dsa_rx2_a_out_iob <= db_gpio_out[16*1+5:16*1+0]; + end + + assign DBA_CH1_TX_DSA_DATA = dsa_tx1_a_out_iob; + assign DBA_CH1_RX_DSA_DATA = dsa_rx1_a_out_iob; + assign DBA_CH2_TX_DSA_DATA = dsa_tx2_a_out_iob; + assign DBA_CH2_RX_DSA_DATA = dsa_rx2_a_out_iob; + + assign DBA_ATR_RX_1 = rx_atr_reg[0]; + assign DBA_ATR_RX_2 = rx_atr_reg[1]; + assign DBA_ATR_TX_1 = tx_atr_reg[0]; + assign DBA_ATR_TX_2 = tx_atr_reg[1]; + + assign DBA_MYK_GPIO_0 = 1'b0; + assign DBA_MYK_GPIO_1 = 1'b0; + assign DBA_MYK_GPIO_3 = 1'b0; + assign DBA_MYK_GPIO_4 = 1'b0; + assign DBA_MYK_GPIO_12 = 1'b0; + assign DBA_MYK_GPIO_13 = 1'b0; + assign DBA_MYK_GPIO_14 = 1'b0; + assign DBA_MYK_GPIO_15 = 1'b0; + +`ifndef N300 + + // DB B SPI Connections + wire cpld_b_cs_n; + wire lmk_b_cs_n; + wire dac_b_cs_n; + wire myk_b_cs_n; + + // Split out the SCLK and MOSI data to Mykonos and the CPLD. + assign DBB_CPLD_PS_SPI_SCLK = spi1_sclk; + assign DBB_CPLD_PS_SPI_SDI = spi1_mosi; + + assign DBB_MYK_SPI_SCLK = spi1_sclk; + assign DBB_MYK_SPI_SDIO = spi1_mosi; + + // Assign individual chip selects from PS SPI MASTER 1. + assign cpld_b_cs_n = spi1_ss0; + assign lmk_b_cs_n = spi1_ss1; + assign dac_b_cs_n = ps_gpio_out[9]; // DAC select driven through GPIO. + assign myk_b_cs_n = spi1_ss2; + + // Returned data mux from the SPI interfaces. + assign spi1_miso = ~myk_b_cs_n ? DBB_MYK_SPI_SDO : // From Mykonos + DBB_CPLD_PS_SPI_SDO; + + // For the PS SPI connection to the CPLD, we use the LE and ADDR lines as individual + // chip selects for the CPLD endpoint as well as the LMK and DAC endpoints. + // LE = CPLD + // ADDR[0] = LMK + // ADDR[1] = DAC + assign DBB_CPLD_PS_SPI_LE = cpld_b_cs_n; + assign DBB_CPLD_PS_SPI_ADDR[0] = lmk_b_cs_n; + assign DBB_CPLD_PS_SPI_ADDR[1] = dac_b_cs_n; + assign DBB_MYK_SPI_CS_n = myk_b_cs_n; + + // Instantiate DSA registers in the IOB + (* IOB = "true" *) reg [5:0] dsa_tx1_b_out_iob, dsa_rx1_b_out_iob; + (* IOB = "true" *) reg [5:0] dsa_tx2_b_out_iob, dsa_rx2_b_out_iob; + always @(posedge radio_clk) begin + dsa_tx1_b_out_iob <= db_gpio_out[16*2+11:16*2+6]; + dsa_rx1_b_out_iob <= db_gpio_out[16*2+5:16*2+0]; + dsa_tx2_b_out_iob <= db_gpio_out[16*3+11:16*3+6]; + dsa_rx2_b_out_iob <= db_gpio_out[16*3+5:16*3+0]; + end + + assign DBB_CH1_TX_DSA_DATA = dsa_tx1_b_out_iob; + assign DBB_CH1_RX_DSA_DATA = dsa_rx1_b_out_iob; + assign DBB_CH2_TX_DSA_DATA = dsa_tx2_b_out_iob; + assign DBB_CH2_RX_DSA_DATA = dsa_rx2_b_out_iob; + + assign DBB_ATR_RX_1 = rx_atr_reg[2]; + assign DBB_ATR_RX_2 = rx_atr_reg[3]; + assign DBB_ATR_TX_1 = tx_atr_reg[2]; + assign DBB_ATR_TX_2 = tx_atr_reg[3]; + + assign DBB_MYK_GPIO_0 = 1'b0; + assign DBB_MYK_GPIO_1 = 1'b0; + assign DBB_MYK_GPIO_3 = 1'b0; + assign DBB_MYK_GPIO_4 = 1'b0; + assign DBB_MYK_GPIO_12 = 1'b0; + assign DBB_MYK_GPIO_13 = 1'b0; + assign DBB_MYK_GPIO_14 = 1'b0; + assign DBB_MYK_GPIO_15 = 1'b0; + +`endif + + /////////////////////////////////////////////////////// + // + // N3xx CORE + // + /////////////////////////////////////////////////////// + + wire [31:0] rx[NUM_CHANNELS-1:0]; + wire [31:0] tx[NUM_CHANNELS-1:0]; + wire [32*NUM_CHANNELS-1:0] rx_flat; + wire [32*NUM_CHANNELS-1:0] tx_flat; + + wire [NUM_CHANNELS-1:0] rx_stb; + wire [NUM_CHANNELS-1:0] tx_stb; + + wire [31:0] build_datestamp; + + genvar i; + generate + for (i = 0; i < NUM_CHANNELS; i = i + 1) begin + // Radio Data + assign rx_flat[32*i+31:32*i] = rx[i]; + assign tx[i] = tx_flat[32*i+31:32*i]; + end + endgenerate + + USR_ACCESSE2 usr_access_i ( + .DATA(build_datestamp), .CFGCLK(), .DATAVALID() + ); + + n3xx_core #( + .REG_AWIDTH(14), + .BUS_CLK_RATE(BUS_CLK_RATE), + .FP_GPIO_WIDTH(FP_GPIO_WIDTH), + .NUM_CHANNELS_PER_RADIO(NUM_CHANNELS_PER_RADIO), + .NUM_CHANNELS(NUM_CHANNELS), + .NUM_DBOARDS(NUM_DBOARDS), + `ifdef USE_REPLAY + .USE_REPLAY(1) + `else + .USE_REPLAY(0) + `endif + ) n3xx_core( + // Clocks and resets + `ifdef NO_DB + .radio_clk(bus_clk), + .radio_rst(bus_rst), + `else + .radio_clk(radio_clk), + .radio_rst(radio_rst), + `endif + .bus_clk(bus_clk), + .bus_rst(bus_rst), + .ddr3_dma_clk(ddr3_dma_clk), + .clk40(clk40), + + // Clocking and PPS Controls/Indicators + .pps(pps_radioclk1x), + .pps_select(pps_select), + .pps_out_enb(pps_out_enb), + .pps_select_sfp(pps_select_sfp), + .ref_clk_reset(), + .meas_clk_reset(meas_clk_reset), + .ref_clk_locked(1'b1), + .meas_clk_locked(meas_clk_locked), + .enable_ref_clk_async(enable_ref_clk_async), + + .s_axi_aclk(clk40), + .s_axi_aresetn(clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_XBAR_AWADDR), + .s_axi_awvalid(M_AXI_XBAR_AWVALID), + .s_axi_awready(M_AXI_XBAR_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_XBAR_WDATA), + .s_axi_wstrb(M_AXI_XBAR_WSTRB), + .s_axi_wvalid(M_AXI_XBAR_WVALID), + .s_axi_wready(M_AXI_XBAR_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_XBAR_BRESP), + .s_axi_bvalid(M_AXI_XBAR_BVALID), + .s_axi_bready(M_AXI_XBAR_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_XBAR_ARADDR), + .s_axi_arvalid(M_AXI_XBAR_ARVALID), + .s_axi_arready(M_AXI_XBAR_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_XBAR_RDATA), + .s_axi_rresp(M_AXI_XBAR_RRESP), + .s_axi_rvalid(M_AXI_XBAR_RVALID), + .s_axi_rready(M_AXI_XBAR_RREADY), + // ps gpio source + .ps_gpio_tri(ps_gpio_tri[FP_GPIO_WIDTH+FP_GPIO_OFFSET-1:FP_GPIO_OFFSET]), + .ps_gpio_out(ps_gpio_out[FP_GPIO_WIDTH+FP_GPIO_OFFSET-1:FP_GPIO_OFFSET]), + .ps_gpio_in(ps_gpio_in[FP_GPIO_WIDTH+FP_GPIO_OFFSET-1:FP_GPIO_OFFSET]), + // FP_GPIO + .fp_gpio_inout(FPGA_GPIO), + // Radio ATR + .rx_atr(rx_atr), + .tx_atr(tx_atr), + // Radio GPIO DSA + .db_gpio_out_flat(db_gpio_out), + .db_gpio_in_flat(db_gpio_in), + .db_gpio_ddr_flat(db_gpio_ddr), + .db_gpio_fab_flat(db_gpio_fab), + // Radio Strobes + .rx_stb(rx_stb), + .tx_stb(tx_stb), + // Radio Data + .rx(rx_flat), + .tx(tx_flat), + // CPLD RX_LO TX_LO SPI + `ifndef N300 + .sclk_flat({DBB_CPLD_PL_SPI_SCLK, + DBA_CPLD_PL_SPI_SCLK}), + .sen_flat({5'b0,DBB_CPLD_PL_SPI_ADDR[1],DBB_CPLD_PL_SPI_ADDR[0],DBB_CPLD_PL_SPI_LE, + 5'b0,DBA_CPLD_PL_SPI_ADDR[1],DBA_CPLD_PL_SPI_ADDR[0],DBA_CPLD_PL_SPI_LE}), + .mosi_flat({DBB_CPLD_PL_SPI_SDI, + DBA_CPLD_PL_SPI_SDI}), + .miso_flat({DBB_CPLD_PL_SPI_SDO, + DBA_CPLD_PL_SPI_SDO}), + `else + .sclk_flat(DBA_CPLD_PL_SPI_SCLK), + .sen_flat({5'b0,DBA_CPLD_PL_SPI_ADDR[1],DBA_CPLD_PL_SPI_ADDR[0],DBA_CPLD_PL_SPI_LE}), + .mosi_flat(DBA_CPLD_PL_SPI_SDI), + .miso_flat(DBA_CPLD_PL_SPI_SDO), + `endif + // DRAM signals + .ddr3_axi_clk (ddr3_axi_clk), + .ddr3_axi_rst (ddr3_axi_rst), + .ddr3_running (ddr3_running), + // Slave Interface Write Address Ports + .ddr3_axi_awid (ddr3_axi_awid), + .ddr3_axi_awaddr (ddr3_axi_awaddr), + .ddr3_axi_awlen (ddr3_axi_awlen), + .ddr3_axi_awsize (ddr3_axi_awsize), + .ddr3_axi_awburst (ddr3_axi_awburst), + .ddr3_axi_awlock (ddr3_axi_awlock), + .ddr3_axi_awcache (ddr3_axi_awcache), + .ddr3_axi_awprot (ddr3_axi_awprot), + .ddr3_axi_awqos (ddr3_axi_awqos), + .ddr3_axi_awvalid (ddr3_axi_awvalid), + .ddr3_axi_awready (ddr3_axi_awready), + // Slave Interface Write Data Ports + .ddr3_axi_wdata (ddr3_axi_wdata), + .ddr3_axi_wstrb (ddr3_axi_wstrb), + .ddr3_axi_wlast (ddr3_axi_wlast), + .ddr3_axi_wvalid (ddr3_axi_wvalid), + .ddr3_axi_wready (ddr3_axi_wready), + // Slave Interface Write Response Ports + .ddr3_axi_bid (ddr3_axi_bid), + .ddr3_axi_bresp (ddr3_axi_bresp), + .ddr3_axi_bvalid (ddr3_axi_bvalid), + .ddr3_axi_bready (ddr3_axi_bready), + // Slave Interface Read Address Ports + .ddr3_axi_arid (ddr3_axi_arid), + .ddr3_axi_araddr (ddr3_axi_araddr), + .ddr3_axi_arlen (ddr3_axi_arlen), + .ddr3_axi_arsize (ddr3_axi_arsize), + .ddr3_axi_arburst (ddr3_axi_arburst), + .ddr3_axi_arlock (ddr3_axi_arlock), + .ddr3_axi_arcache (ddr3_axi_arcache), + .ddr3_axi_arprot (ddr3_axi_arprot), + .ddr3_axi_arqos (ddr3_axi_arqos), + .ddr3_axi_arvalid (ddr3_axi_arvalid), + .ddr3_axi_arready (ddr3_axi_arready), + // Slave Interface Read Data Ports + .ddr3_axi_rid (ddr3_axi_rid), + .ddr3_axi_rdata (ddr3_axi_rdata), + .ddr3_axi_rresp (ddr3_axi_rresp), + .ddr3_axi_rlast (ddr3_axi_rlast), + .ddr3_axi_rvalid (ddr3_axi_rvalid), + .ddr3_axi_rready (ddr3_axi_rready), + + // DMA to PS + .m_dma_tdata(s_axis_dma_tdata), + .m_dma_tdest(s_axis_dma_tdest), + .m_dma_tlast(s_axis_dma_tlast), + .m_dma_tready(s_axis_dma_tready), + .m_dma_tvalid(s_axis_dma_tvalid), + + .s_dma_tdata(m_axis_dma_tdata), + .s_dma_tuser(m_axis_dma_tuser), + .s_dma_tlast(m_axis_dma_tlast), + .s_dma_tready(m_axis_dma_tready), + .s_dma_tvalid(m_axis_dma_tvalid), + + // VITA to Ethernet + .v2e0_tdata(v2e0_tdata), + .v2e0_tvalid(v2e0_tvalid), + .v2e0_tlast(v2e0_tlast), + .v2e0_tready(v2e0_tready), + + .v2e1_tdata(v2e1_tdata), + .v2e1_tlast(v2e1_tlast), + .v2e1_tvalid(v2e1_tvalid), + .v2e1_tready(v2e1_tready), + + // Ethernet to VITA + .e2v0_tdata(e2v0_tdata), + .e2v0_tlast(e2v0_tlast), + .e2v0_tvalid(e2v0_tvalid), + .e2v0_tready(e2v0_tready), + + .e2v1_tdata(e2v1_tdata), + .e2v1_tlast(e2v1_tlast), + .e2v1_tvalid(e2v1_tvalid), + .e2v1_tready(e2v1_tready), + + //regport interface to npio + .reg_wr_req_npio(reg_wr_req_npio), + .reg_wr_addr_npio(reg_wr_addr_npio), + .reg_wr_data_npio(reg_wr_data_npio), + .reg_rd_req_npio(reg_rd_req_npio), + .reg_rd_addr_npio(reg_rd_addr_npio), + .reg_rd_resp_npio(reg_rd_resp_npio), + .reg_rd_data_npio(reg_rd_data_npio), + + .build_datestamp(build_datestamp), + .xadc_readback({20'h0, device_temp}), + .sfp_ports_info({sfp_port1_info, sfp_port0_info}), + .device_id(device_id) + ); + + // Register the ATR bits once between sending them out to the CPLD to avoid + // glitches on the outputs! + always @(posedge radio_clk) begin + rx_atr_reg <= rx_atr; + tx_atr_reg <= tx_atr; + end + + // ////////////////////////////////////////////////////////////////////// + // + // Daughterboard Cores + // + // ////////////////////////////////////////////////////////////////////// + + wire [49:0] bRegPortInFlatA; + wire [33:0] bRegPortOutFlatA; + wire rx_a_valid; + wire tx_a_rfi; +`ifndef N300 + wire [49:0] bRegPortInFlatB; + wire [33:0] bRegPortOutFlatB; + wire rx_b_valid; + wire tx_b_rfi; +`endif + +`ifdef BUILD_WR + localparam INCL_WR_TDC = 1'b1; +`else + localparam INCL_WR_TDC = 1'b0; +`endif + + wire reg_portA_rd; + wire reg_portA_wr; + wire [14-1:0] reg_portA_addr; + wire [32-1:0] reg_portA_wr_data; + wire [32-1:0] reg_portA_rd_data; + wire reg_portA_ready; + wire validA_unused; + + assign bRegPortInFlatA = {2'b0, reg_portA_addr, reg_portA_wr_data, reg_portA_rd, reg_portA_wr}; + assign {reg_portA_rd_data, validA_unused, reg_portA_ready} = bRegPortOutFlatA; + + DbCore #( + .kInclWhiteRabbitTdc(INCL_WR_TDC) + ) dba_core ( + .bBusReset(clk40_rst), //in std_logic + .BusClk(clk40), //in std_logic + .Clk40(clk40), //in std_logic + .MeasClk(meas_clk), //in std_logic + .FpgaClk_p(DBA_FPGA_CLK_P), //in std_logic + .FpgaClk_n(DBA_FPGA_CLK_N), //in std_logic + .SampleClk1xOut(radio_clk), //out std_logic + .SampleClk1x(radio_clk), //in std_logic + .SampleClk2xOut(radio_clk_2x), //out std_logic + .SampleClk2x(radio_clk_2x), //in std_logic + .bRegPortInFlat(bRegPortInFlatA), //in std_logic_vector(49:0) + .bRegPortOutFlat(bRegPortOutFlatA), //out std_logic_vector(33:0) + .kSlotId(1'b0), //in std_logic + .sSysRefFpgaLvds_p(DBA_FPGA_SYSREF_P), //in std_logic + .sSysRefFpgaLvds_n(DBA_FPGA_SYSREF_N), //in std_logic + .aLmkSync(DBA_CPLD_PL_SPI_ADDR[2]), //out std_logic + .JesdRefClk_p(USRPIO_A_MGTCLK_P), //in std_logic + .JesdRefClk_n(USRPIO_A_MGTCLK_N), //in std_logic + .aAdcRx_p(USRPIO_A_RX_P), //in std_logic_vector(3:0) + .aAdcRx_n(USRPIO_A_RX_N), //in std_logic_vector(3:0) + .aSyncAdcOut_n(DBA_MYK_SYNC_IN_n), //out std_logic + .aDacTx_p(USRPIO_A_TX_P), //out std_logic_vector(3:0) + .aDacTx_n(USRPIO_A_TX_N), //out std_logic_vector(3:0) + .aSyncDacIn_n(DBA_MYK_SYNC_OUT_n), //in std_logic + .sAdcDataValid(rx_a_valid), //out std_logic + .sAdcDataSamples0I(rx[0][31:16]), //out std_logic_vector(15:0) + .sAdcDataSamples0Q(rx[0][15:0]), //out std_logic_vector(15:0) + .sAdcDataSamples1I(rx[1][31:16]), //out std_logic_vector(15:0) + .sAdcDataSamples1Q(rx[1][15:0]), //out std_logic_vector(15:0) + .sDacReadyForInput(tx_a_rfi), //out std_logic + .sDacDataSamples0I(tx[0][31:16]), //in std_logic_vector(15:0) + .sDacDataSamples0Q(tx[0][15:0]), //in std_logic_vector(15:0) + .sDacDataSamples1I(tx[1][31:16]), //in std_logic_vector(15:0) + .sDacDataSamples1Q(tx[1][15:0]), //in std_logic_vector(15:0) + .RefClk(ref_clk), //in std_logic + .rPpsPulse(pps_refclk), //in std_logic + .rGatedPulseToPin(UNUSED_PIN_TDCA_0), //inout std_logic + .sGatedPulseToPin(UNUSED_PIN_TDCA_1), //inout std_logic + .sPps(pps_radioclk1x), //out std_logic + .sPpsToIob(pps_radioclk1x_iob), //out std_logic + .WrRefClk(wr_ref_clk), //in std_logic + .rWrPpsPulse(pps_wr_refclk), //in std_logic + .rWrGatedPulseToPin(UNUSED_PIN_TDCA_2), //inout std_logic + .sWrGatedPulseToPin(UNUSED_PIN_TDCA_3), //inout std_logic + .aPpsSfpSel(pps_select_sfp), //out std_logic_vector(1:0) + .sAdcSync(), //out std_logic + .sDacSync(), //out std_logic + .sSysRef(), //out std_logic + .rRpTransfer(), //out std_logic + .sSpTransfer(), //out std_logic + .rWrRpTransfer(), //out std_logic + .sWrSpTransfer() //out std_logic + ); + + assign rx_stb[0] = rx_a_valid; + assign rx_stb[1] = rx_a_valid; + assign tx_stb[0] = tx_a_rfi; + assign tx_stb[1] = tx_a_rfi; + + axil_to_ni_regport #( + .RP_DWIDTH (32), + .RP_AWIDTH (14), + .TIMEOUT (512) + ) ni_regportA_inst ( + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_areset (clk40_rst), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_JESD0_AWADDR), + .s_axi_awvalid(M_AXI_JESD0_AWVALID), + .s_axi_awready(M_AXI_JESD0_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_JESD0_WDATA), + .s_axi_wstrb(M_AXI_JESD0_WSTRB), + .s_axi_wvalid(M_AXI_JESD0_WVALID), + .s_axi_wready(M_AXI_JESD0_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_JESD0_BRESP), + .s_axi_bvalid(M_AXI_JESD0_BVALID), + .s_axi_bready(M_AXI_JESD0_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_JESD0_ARADDR), + .s_axi_arvalid(M_AXI_JESD0_ARVALID), + .s_axi_arready(M_AXI_JESD0_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_JESD0_RDATA), + .s_axi_rresp(M_AXI_JESD0_RRESP), + .s_axi_rvalid(M_AXI_JESD0_RVALID), + .s_axi_rready(M_AXI_JESD0_RREADY), + // Register port + .reg_port_in_rd (reg_portA_rd), + .reg_port_in_wt (reg_portA_wr), + .reg_port_in_addr (reg_portA_addr), + .reg_port_in_data (reg_portA_wr_data), + .reg_port_out_data (reg_portA_rd_data), + .reg_port_out_ready(reg_portA_ready) + ); + +`ifndef N300 + wire reg_portB_rd; + wire reg_portB_wr; + wire [14-1:0] reg_portB_addr; + wire [32-1:0] reg_portB_wr_data; + wire [32-1:0] reg_portB_rd_data; + wire reg_portB_ready; + wire validB_unused; + + assign bRegPortInFlatB = {2'b0, reg_portB_addr, reg_portB_wr_data, reg_portB_rd, reg_portB_wr}; + assign {reg_portB_rd_data, validB_unused, reg_portB_ready} = bRegPortOutFlatB; + + DbCore #( + .kInclWhiteRabbitTdc(INCL_WR_TDC) + ) dbb_core ( + .bBusReset(clk40_rst), //in std_logic + .BusClk(clk40), //in std_logic + .Clk40(clk40), //in std_logic + .MeasClk(meas_clk), //in std_logic + .FpgaClk_p(DBB_FPGA_CLK_P), //in std_logic + .FpgaClk_n(DBB_FPGA_CLK_N), //in std_logic + .SampleClk1xOut(), //out std_logic + .SampleClk1x(radio_clk), //in std_logic + .SampleClk2xOut(), //out std_logic + .SampleClk2x(radio_clk_2x), //in std_logic + .bRegPortInFlat(bRegPortInFlatB), //in std_logic_vector(49:0) + .bRegPortOutFlat(bRegPortOutFlatB), //out std_logic_vector(33:0) + .kSlotId(1'b1), //in std_logic + .sSysRefFpgaLvds_p(DBB_FPGA_SYSREF_P), //in std_logic + .sSysRefFpgaLvds_n(DBB_FPGA_SYSREF_N), //in std_logic + .aLmkSync(DBB_CPLD_PL_SPI_ADDR[2]), //out std_logic + .JesdRefClk_p(USRPIO_B_MGTCLK_P), //in std_logic + .JesdRefClk_n(USRPIO_B_MGTCLK_N), //in std_logic + .aAdcRx_p(USRPIO_B_RX_P), //in std_logic_vector(3:0) + .aAdcRx_n(USRPIO_B_RX_N), //in std_logic_vector(3:0) + .aSyncAdcOut_n(DBB_MYK_SYNC_IN_n), //out std_logic + .aDacTx_p(USRPIO_B_TX_P), //out std_logic_vector(3:0) + .aDacTx_n(USRPIO_B_TX_N), //out std_logic_vector(3:0) + .aSyncDacIn_n(DBB_MYK_SYNC_OUT_n), //in std_logic + .sAdcDataValid(rx_b_valid), //out std_logic + .sAdcDataSamples0I(rx[2][31:16]), //out std_logic_vector(15:0) + .sAdcDataSamples0Q(rx[2][15:0]), //out std_logic_vector(15:0) + .sAdcDataSamples1I(rx[3][31:16]), //out std_logic_vector(15:0) + .sAdcDataSamples1Q(rx[3][15:0]), //out std_logic_vector(15:0) + .sDacReadyForInput(tx_b_rfi), //out std_logic + .sDacDataSamples0I(tx[2][31:16]), //in std_logic_vector(15:0) + .sDacDataSamples0Q(tx[2][15:0]), //in std_logic_vector(15:0) + .sDacDataSamples1I(tx[3][31:16]), //in std_logic_vector(15:0) + .sDacDataSamples1Q(tx[3][15:0]), //in std_logic_vector(15:0) + .RefClk(ref_clk), //in std_logic + .rPpsPulse(pps_refclk), //in std_logic + .rGatedPulseToPin(UNUSED_PIN_TDCB_0), //inout std_logic + .sGatedPulseToPin(UNUSED_PIN_TDCB_1), //inout std_logic + .sPps(), //out std_logic + .sPpsToIob(), //out std_logic + .WrRefClk(wr_ref_clk), //in std_logic + .rWrPpsPulse(pps_wr_refclk), //in std_logic + .rWrGatedPulseToPin(UNUSED_PIN_TDCB_2), //inout std_logic + .sWrGatedPulseToPin(UNUSED_PIN_TDCB_3), //inout std_logic + .aPpsSfpSel(2'b0), //out std_logic_vector(1:0) + .sAdcSync(), //out std_logic + .sDacSync(), //out std_logic + .sSysRef(), //out std_logic + .rRpTransfer(), //out std_logic + .sSpTransfer(), //out std_logic + .rWrRpTransfer(), //out std_logic + .sWrSpTransfer() //out std_logic + ); + + assign rx_stb[2] = rx_b_valid; + assign rx_stb[3] = rx_b_valid; + assign tx_stb[2] = tx_b_rfi; + assign tx_stb[3] = tx_b_rfi; + + axil_to_ni_regport #( + .RP_DWIDTH (32), + .RP_AWIDTH (14), + .TIMEOUT (512) + ) ni_regportB_inst ( + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_areset (clk40_rst), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_JESD1_AWADDR), + .s_axi_awvalid(M_AXI_JESD1_AWVALID), + .s_axi_awready(M_AXI_JESD1_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_JESD1_WDATA), + .s_axi_wstrb(M_AXI_JESD1_WSTRB), + .s_axi_wvalid(M_AXI_JESD1_WVALID), + .s_axi_wready(M_AXI_JESD1_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_JESD1_BRESP), + .s_axi_bvalid(M_AXI_JESD1_BVALID), + .s_axi_bready(M_AXI_JESD1_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_JESD1_ARADDR), + .s_axi_arvalid(M_AXI_JESD1_ARVALID), + .s_axi_arready(M_AXI_JESD1_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata (M_AXI_JESD1_RDATA), + .s_axi_rresp (M_AXI_JESD1_RRESP), + .s_axi_rvalid (M_AXI_JESD1_RVALID), + .s_axi_rready (M_AXI_JESD1_RREADY), + // Register port + .reg_port_in_rd (reg_portB_rd), + .reg_port_in_wt (reg_portB_wr), + .reg_port_in_addr (reg_portB_addr), + .reg_port_in_data (reg_portB_wr_data), + .reg_port_out_data (reg_portB_rd_data), + .reg_port_out_ready(reg_portB_ready) + ); +`else + // Tie off second daughterboard interface + axi_dummy #( + .DEC_ERR(1'b0) + ) inst_axi_dummy_dbb_core ( + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_areset (clk40_rst), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_JESD1_AWADDR), + .s_axi_awvalid(M_AXI_JESD1_AWVALID), + .s_axi_awready(M_AXI_JESD1_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_JESD1_WDATA), + .s_axi_wstrb(M_AXI_JESD1_WSTRB), + .s_axi_wvalid(M_AXI_JESD1_WVALID), + .s_axi_wready(M_AXI_JESD1_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_JESD1_BRESP), + .s_axi_bvalid(M_AXI_JESD1_BVALID), + .s_axi_bready(M_AXI_JESD1_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_JESD1_ARADDR), + .s_axi_arvalid(M_AXI_JESD1_ARVALID), + .s_axi_arready(M_AXI_JESD1_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata (M_AXI_JESD1_RDATA), + .s_axi_rresp (M_AXI_JESD1_RRESP), + .s_axi_rvalid (M_AXI_JESD1_RVALID), + .s_axi_rready (M_AXI_JESD1_RREADY) + ); + +`endif + + // ////////////////////////////////////////////////////////////////////// + // + // LEDS + // + // ////////////////////////////////////////////////////////////////////// + + assign PANEL_LED_LINK = ps_gpio_out[45]; + assign PANEL_LED_REF = ps_gpio_out[46]; + assign PANEL_LED_GPS = ps_gpio_out[47]; + + + ///////////////////////////////////////////////////////////////////// + // + // PUDC Workaround + // + ////////////////////////////////////////////////////////////////////// + // This is a workaround for a silicon bug in Series 7 FPGA where a + // race condition with the reading of PUDC during the erase of the FPGA + // image cause glitches on output IO pins. + // + // Workaround: + // - Define the PUDC pin in the XDC file with a pullup. + // - Implements an IBUF on the PUDC input and make sure that it does + // not get optimized out. + (* dont_touch = "true" *) wire fpga_pudc_b_buf; + IBUF pudc_ibuf_i ( + .I(FPGA_PUDC_B), + .O(fpga_pudc_b_buf)); + +endmodule |