diff options
author | Martin Braun <martin.braun@ettus.com> | 2020-01-23 16:10:22 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2020-01-28 09:35:36 -0800 |
commit | bafa9d95453387814ef25e6b6256ba8db2df612f (patch) | |
tree | 39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/top/n3xx/dboards/mg/cpld | |
parent | 3075b981503002df3115d5f1d0b97d2619ba30f2 (diff) | |
download | uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2 uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip |
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce
the size of the repository. However, over the last half-decade, the
split between the repositories has proven more burdensome than it has
been helpful. By merging the FPGA code back, it will be possible to
create atomic commits that touch both FPGA and UHD codebases. Continuous
integration testing is also simplified by merging the repositories,
because it was previously difficult to automatically derive the correct
UHD branch when testing a feature branch on the FPGA repository.
This commit also updates the license files and paths therein.
We are therefore merging the repositories again. Future development for
FPGA code will happen in the same repository as the UHD host code and
MPM code.
== Original Codebase and Rebasing ==
The original FPGA repository will be hosted for the foreseeable future
at its original local location: https://github.com/EttusResearch/fpga/
It can be used for bisecting, reference, and a more detailed history.
The final commit from said repository to be merged here is
05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as
v4.0.0.0-pre-uhd-merge.
If you have changes in the FPGA repository that you want to rebase onto
the UHD repository, simply run the following commands:
- Create a directory to store patches (this should be an empty
directory):
mkdir ~/patches
- Now make sure that your FPGA codebase is based on the same state as
the code that was merged:
cd src/fpga # Or wherever your FPGA code is stored
git rebase v4.0.0.0-pre-uhd-merge
Note: The rebase command may look slightly different depending on what
exactly you're trying to rebase.
- Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge:
git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches
Note: Make sure that only patches are stored in your output directory.
It should otherwise be empty. Make sure that you picked the correct
range of commits, and only commits you wanted to rebase were exported
as patch files.
- Go to the UHD repository and apply the patches:
cd src/uhd # Or wherever your UHD repository is stored
git am --directory fpga ~/patches/*
rm -rf ~/patches # This is for cleanup
== Contributors ==
The following people have contributed mainly to these files (this list
is not complete):
Co-authored-by: Alex Williams <alex.williams@ni.com>
Co-authored-by: Andrej Rode <andrej.rode@ettus.com>
Co-authored-by: Ashish Chaudhari <ashish@ettus.com>
Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Derek Kozel <derek.kozel@ettus.com>
Co-authored-by: EJ Kreinar <ej@he360.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Ian Buckley <ian.buckley@gmail.com>
Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Jon Kiser <jon.kiser@ni.com>
Co-authored-by: Josh Blum <josh@joshknows.com>
Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Matt Ettus <matt@ettus.com>
Co-authored-by: Michael West <michael.west@ettus.com>
Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com>
Co-authored-by: Nick Foster <nick@ettus.com>
Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Paul David <paul.david@ettus.com>
Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com>
Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com>
Co-authored-by: Sylvain Munaut <tnt@246tNt.com>
Co-authored-by: Trung Tran <trung.tran@ettus.com>
Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/top/n3xx/dboards/mg/cpld')
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/Makefile | 22 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgMgCpld.vhd | 424 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/PkgSetup.vhd | 259 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/Timing.sdc | 160 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qpf | 31 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.qsf | 313 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/cpld/TopCpld.vhd | 1228 |
7 files changed, 2437 insertions, 0 deletions
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 + + + |