diff options
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 |