diff options
Diffstat (limited to 'fpga/usrp3/top/n3xx/dboards/mg/db_ifc')
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd | 345 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd | 116 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd | 562 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf | bin | 0 -> 216640 bytes | |||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd | 56 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd | 107 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd | 56 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd | 234 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd | 61 | ||||
-rw-r--r-- | fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd | 304 |
10 files changed, 1841 insertions, 0 deletions
diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd new file mode 100644 index 000000000..ffaa64f68 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/ClockingRegs.vhd @@ -0,0 +1,345 @@ +------------------------------------------------------------------------------- +-- +-- File: ClockingRegs.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 17 March 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Register access to the control/status bits and interfaces for the +-- RadioClocking module. +-- +-- XML register definition is included below the module. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library work; + use work.PkgClockingRegMap.all; + use work.PkgRegs.all; + + +entity ClockingRegs is + port( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + -- Register Bus Clock -- this module connects the BusClk to PsClk, so it's limited + -- to 200 MHz! + BusClk : in std_logic; + + bRegPortOut : out RegPortOut_t; + bRegPortIn : in RegPortIn_t; + + -- Phase shift interface to the RadioClkMmcm. + -- There is a reset crossing here between the MMCM reset and aReset. The outgoing + -- crossing is safe because (a) the enable signal driven to the MMCM is a strobe-only + -- signal and (b) this interface should only be used when the MMCM is not in reset + -- (SW waits for the MMCM to be out of reset and locked before using this interface). + -- The only input signal, pPsDone, is double-synced in this file before being used. + -- This is OK (even though it is a strobe signal) because there is only a reset + -- crossing and not a clock domain crossing. + pPsInc : out std_logic; + pPsEn : out std_logic; + pPsDone : in std_logic; + + -- PsClk is driven directly by BusClk, so p = b in the logic below! + PsClk : out std_logic; + + -- Sync reset strobes from the register bus to the RadioClkMmcm. + bRadioClkMmcmReset : out std_logic; + -- Status of RadioClk MMCM lock to register bus. + aRadioClksValid : in std_logic; + + bRadioClk1xEnabled : out std_logic; + bRadioClk2xEnabled : out std_logic; + bRadioClk3xEnabled : out std_logic; + + bJesdRefClkPresent : in std_logic + ); +end ClockingRegs; + + +architecture RTL of ClockingRegs is + + --vhook_sigstart + --vhook_sigend + + signal bRadioClkMmcmResetInt : std_logic := '1'; + + signal bRegPortOutLcl : RegPortOut_t := kRegPortOutZero; + + signal bPsDone, + bPsEn, + bPsInc, + pPsDoneDs_ms, + pPsDoneDs : std_logic := '0'; + + signal bRadioClk1xEnabledInt, + bRadioClk2xEnabledInt, + bRadioClk3xEnabledInt, + bRadioClksValid_ms, + bRadioClksValid : std_logic := '0'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of bRadioClksValid_ms : signal is "true"; + attribute ASYNC_REG of bRadioClksValid : signal is "true"; + attribute ASYNC_REG of pPsDoneDs_ms : signal is "true"; + attribute ASYNC_REG of pPsDoneDs : signal is "true"; + +begin + + -- Locals to outputs. + PsClk <= BusClk; + pPsInc <= bPsInc; + pPsEn <= bPsEn; + + bRadioClkMmcmReset <= bRadioClkMmcmResetInt; + + bRadioClk1xEnabled <= bRadioClk1xEnabledInt; + bRadioClk2xEnabled <= bRadioClk2xEnabledInt; + bRadioClk3xEnabled <= bRadioClk3xEnabledInt; + + + -- Write Registers : ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + WriteRegisters: process(aReset, BusClk) + begin + if aReset then + bRadioClkMmcmResetInt <= '1'; + bPsInc <= '0'; + bPsEn <= '0'; + bRadioClk1xEnabledInt <= '0'; + bRadioClk2xEnabledInt <= '0'; + bRadioClk3xEnabledInt <= '0'; + elsif rising_edge(BusClk) then + + if bReset then + bRadioClkMmcmResetInt <= '1'; + bPsInc <= '0'; + bPsEn <= '0'; + bRadioClk1xEnabledInt <= '0'; + bRadioClk2xEnabledInt <= '0'; + bRadioClk3xEnabledInt <= '0'; + else + -- Clear strobe + bPsEn <= '0'; + + if RegWrite(kPhaseShiftControl, bRegPortIn) then + if bRegPortIn.Data(kPsInc) = '1' then + bPsInc <= '1'; + bPsEn <= '1'; + elsif bRegPortIn.Data(kPsDec) = '1' then + bPsInc <= '0'; + bPsEn <= '1'; + end if; + end if; + + if RegWrite(kRadioClkMmcm, bRegPortIn) then + -- Set/Clear pair + if bRegPortIn.Data(kRadioClkMmcmResetSet) = '1' then + bRadioClkMmcmResetInt <= '1'; + elsif bRegPortIn.Data(kRadioClkMmcmResetClear) = '1' then + bRadioClkMmcmResetInt <= '0'; + end if; + end if; + + if RegWrite(kRadioClkEnables, bRegPortIn) then + bRadioClk1xEnabledInt <= bRegPortIn.Data(kRadioClk1xEnabled); + bRadioClk2xEnabledInt <= bRegPortIn.Data(kRadioClk2xEnabled); + bRadioClk3xEnabledInt <= bRegPortIn.Data(kRadioClk3xEnabled); + end if; + + end if; + end if; + end process WriteRegisters; + + + DoubleSyncs : process (aReset, BusClk) + begin + if aReset then + bRadioClksValid_ms <= '0'; + bRadioClksValid <= '0'; + pPsDoneDs_ms <= '0'; + pPsDoneDs <= '0'; + elsif rising_edge(BusClk) then + -- No sync reset on double-syncs (however there are default assignments above)! + bRadioClksValid_ms <= aRadioClksValid; + bRadioClksValid <= bRadioClksValid_ms; + pPsDoneDs_ms <= pPsDone; + pPsDoneDs <= pPsDoneDs_ms; + end if; + end process; + + + -- Read Registers : ------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + ReadRegisters: process(aReset, BusClk) + begin + if aReset then + bRegPortOutLcl <= kRegPortOutZero; + bPsDone <= '0'; + elsif rising_edge(BusClk) then + + if bReset then + bRegPortOutLcl <= kRegPortOutZero; + bPsDone <= '0'; + else + -- Deassert strobes + bRegPortOutLcl.Data <= kRegPortDataZero; + + -- All of these transactions only take one clock cycle, so we do not have to + -- de-assert the Ready signal (ever). + bRegPortOutLcl.Ready <= true; + + -- Process the returned data from the phase shifter in the MMCM. Note that even + -- though the prefixes are different (p and b), we drive the PsClk from the BusClk + -- so this "crossing" is actually safe. Whenever the Done signal asserts (pPsDone - + -- pay attention to the prefix!) from the MMCM, we set a sticky bit to tell SW + -- that the shift operation is complete. + -- + -- However, if pPsDone asserts at the same time that SW tries to read the register, + -- we should accurately report that the operation is indeed complete and then NOT + -- store the sticky (since it has already been read by SW). If a read does not come + -- through at the same time pPsDone is asserted, then we store the done state as a + -- sticky, bPsDone, which is only cleared by a read to this register. + if RegRead(kPhaseShiftControl, bRegPortIn) then + -- The phase shift is always enabled for the feedback clock in RadioClocking.vhd + bRegPortOutLcl.Data(kPsEnabledForFdbClk) <= '1'; + bRegPortOutLcl.Data(kPsDone) <= bPsDone or pPsDoneDs; + bPsDone <= '0'; + elsif pPsDoneDs = '1' then + bPsDone <= '1'; + end if; + + if RegRead(kRadioClkMmcm, bRegPortIn) then + bRegPortOutLcl.Data(kRadioClkMmcmLocked) <= bRadioClksValid; + end if; + + if RegRead(kRadioClkEnables, bRegPortIn) then + bRegPortOutLcl.Data(kRadioClk1xEnabled) <= bRadioClk1xEnabledInt; + bRegPortOutLcl.Data(kRadioClk2xEnabled) <= bRadioClk2xEnabledInt; + bRegPortOutLcl.Data(kRadioClk3xEnabled) <= bRadioClk3xEnabledInt; + end if; + + if RegRead(kMgtRefClkStatus, bRegPortIn) then + bRegPortOutLcl.Data(kJesdRefClkPresent) <= bJesdRefClkPresent; + end if; + + end if; + end if; + end process ReadRegisters; + + -- Local to output + bRegPortOut <= bRegPortOutLcl; + + +end RTL; + + +--XmlParse xml_on +--<regmap name="ClockingRegMap"> +-- <group name="ClockingRegs"> +-- +-- <register name="RadioClkMmcm" size="32" offset="0x20" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="RadioClkMmcmLocked" range="4"> +-- <info> +-- Reflects the locked status of the MMCM. '1' = locked. This bit is only valid +-- when the MMCM reset is de-asserted. Read-only. +-- </info> +-- </bitfield> +-- <bitfield name="RadioClkMmcmResetClear" range="1" attributes="Strobe"> +-- <info> +-- Controls the reset to the Radio Clock MMCM. Strobe this bit to de-assert the +-- reset to the MMCM. Default is reset asserted. Write-only. +-- </info> +-- </bitfield> +-- <bitfield name="RadioClkMmcmResetSet" range="0" attributes="Strobe"> +-- <info> +-- Controls the reset to the Radio Clock MMCM. Strobe this bit to assert the +-- reset to the MMCM. Default is reset asserted. Write-only. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="PhaseShiftControl" size="32" offset="0x24" attributes="Readable|Writable"> +-- <info> +-- Phase Shift for RadioClkMmcm. +-- </info> +-- <bitfield name="PsDone" range="28"> +-- <info> +-- This bit should set after a shift operation successfully completes. +-- Reading this register will clear this bit. Read-only. +-- </info> +-- </bitfield> +-- <bitfield name="PsInc" range="0" attributes="Strobe"> +-- <info> +-- Strobe this bit to increment the phase. This bit is self-clearing and will +-- always return '0' when read. If PsInc and PsDec are asserted together, +-- the phase will increment. +-- </info> +-- </bitfield> +-- <bitfield name="PsDec" range="4" attributes="Strobe"> +-- <info> +-- Strobe this bit to decrement the phase. This bit is self-clearing and will +-- always return '0' when read. If PsInc and PsDec are asserted together, +-- the phase will increment. +-- </info> +-- </bitfield> +-- <bitfield name="PsEnabledForFdbClk" range="16"> +-- <info> +-- Read-only. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="RadioClkEnables" size="32" offset="0x28" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="RadioClk3xEnabled" range="8"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- <bitfield name="RadioClk2xEnabled" range="4"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- <bitfield name="RadioClk1xEnabled" range="0"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="MgtRefClkStatus" size="32" offset="0x30" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="JesdRefClkPresent" range="0"> +-- <info> +-- Live indicator of the MGT Reference Clock toggling and within expected +-- frequency limits. If this bit is de-asserted, then the JESD204b core will +-- not function correctly! +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +--</regmap> +--XmlParse xml_off diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd new file mode 100644 index 000000000..7f8ef388a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DaughterboardRegs.vhd @@ -0,0 +1,116 @@ +------------------------------------------------------------------------------- +-- +-- File: DaughterboardRegs.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 27 April 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Register interface to the semi-static control lines for the Mg +-- Daughterboard. +-- +-- XML register definition is included below the module. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library work; + use work.PkgDaughterboardRegMap.all; + use work.PkgRegs.all; + + +entity DaughterboardRegs is + port( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + BusClk : in std_logic; + + bRegPortOut : out RegPortOut_t; + bRegPortIn : in RegPortIn_t; + + -- Slot and DB ID values. These should be tied to constants! + kDbId : in std_logic_vector(15 downto 0); + kSlotId : in std_logic + + ); +end DaughterboardRegs; + + +architecture RTL of DaughterboardRegs is + + --vhook_sigstart + --vhook_sigend + + signal bRegPortOutLcl : RegPortOut_t := kRegPortOutZero; + +begin + + + -- Read Registers : ------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + ReadRegisters: process(aReset, BusClk) + begin + if aReset then + bRegPortOutLcl <= kRegPortOutZero; + elsif rising_edge(BusClk) then + if bReset then + bRegPortOutLcl <= kRegPortOutZero; + else + -- De-assert strobes + bRegPortOutLcl.Data <= kRegPortDataZero; + + -- All of these transactions only take one clock cycle, so we do not have to + -- de-assert the Ready signal (ever). + bRegPortOutLcl.Ready <= true; + + if RegRead(kDaughterboardId, bRegPortIn) then + bRegPortOutLcl.Data(kDbIdValMsb downto kDbIdVal) <= kDbId; + bRegPortOutLcl.Data(kSlotIdVal) <= kSlotId; + end if; + + end if; + end if; + end process ReadRegisters; + + -- Local to output + bRegPortOut <= bRegPortOutLcl; + + +end RTL; + + +--XmlParse xml_on +--<regmap name="DaughterboardRegMap"> +-- <group name="StaticControl" order="1"> +-- +-- <register name="DaughterboardId" size="32" offset="0x30" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="DbIdVal" range="15..0"> +-- <info> +-- ID for the DB with which this file is designed to communicate. Matches the DB +-- EEPROM ID. +-- </info> +-- </bitfield> +-- <bitfield name="SlotIdVal" range="16"> +-- <info> +-- ID for the Slot this module controls. Options are 0 and 1 for the N310 MB. +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +-- +--</regmap> +--XmlParse xml_off diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd new file mode 100644 index 000000000..e1369ec00 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/DbCore.vhd @@ -0,0 +1,562 @@ +------------------------------------------------------------------------------- +-- +-- File: DbCore.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 12 April 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2017-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Wrapper file for Daughterboard Control. This includes the semi-static control +-- and status registers, clocking, synchronization, and JESD204B cores. +-- +-- There is no version register for the plain-text files here. +-- Version control for the Sync and JESD204B cores is internal to the netlists. +-- +-- The resets for this core are almost entirely local and/or synchronous. +-- bBusReset is a Synchronous reset on the BusClk domain that resets all of the +-- registers connected to the RegPort, as well as any other stray registers +-- connected to the BusClk. All other resets are local to the modules they touch. +-- No other reset drives all modules universally. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgMgPersonality.all; + use work.PkgRegs.all; + use work.PkgJesdConfig.all; + + +entity DbCore is + generic( + -- Set to '1' to include the White Rabbit TDC. + kInclWhiteRabbitTdc : std_logic := '0' + ); + port( + + -- Resets -- + -- Synchronous Reset for the BusClk domain (mainly for the RegPort) + bBusReset : in std_logic; + + -- Clocks -- + -- Register Bus Clock (any frequency) + BusClk : in std_logic; + -- Always-on at 40 MHz + Clk40 : in std_logic; + -- Super secret crazy awesome measurement clock at weird frequencies. + MeasClk : in std_logic; + -- FPGA Sample Clock from DB LMK + FpgaClk_p : in std_logic; + FpgaClk_n : in std_logic; + + -- Sample Clock Sharing. The clocks generated in this module are exported out to the + -- top level so they can be shared amongst daughterboards. Therefore they must be + -- driven back into the SampleClk*x inputs at a higher level in order for this module + -- to work correctly. There are a few isolated cases where SampleClk*xOut is used + -- directly in this module, and those are documented below. + SampleClk1xOut : out std_logic; + SampleClk1x : in std_logic; + SampleClk2xOut : out std_logic; + SampleClk2x : in std_logic; + + + -- Register Ports -- + -- + -- Only synchronous resets can be used for these ports! + bRegPortInFlat : in std_logic_vector(49 downto 0); + bRegPortOutFlat : out std_logic_vector(33 downto 0); + + -- Slot ID value. This should be tied to a constant! + kSlotId : in std_logic; + + + -- SYSREF -- + -- + -- SYSREF direct from the LMK + sSysRefFpgaLvds_p, + sSysRefFpgaLvds_n : in std_logic; + -- SYNC directly to the LMK + aLmkSync : out std_logic; + + + -- JESD Signals -- + -- + -- GTX Sample Clock Reference Input. Direct connect to FPGA pins. + JesdRefClk_p, + JesdRefClk_n : in std_logic; + + -- ADC JESD PHY Interface. Direct connect to FPGA pins. + aAdcRx_p, + aAdcRx_n : in std_logic_vector(3 downto 0); + aSyncAdcOut_n : out std_logic; + + -- DAC JESD PHY Interface. Direct connect to FPGA pins. + aDacTx_p, + aDacTx_n : out std_logic_vector(3 downto 0); + aSyncDacIn_n : in std_logic; + + + -- Data Pipes to/from the DACs/ADCs -- + -- + -- - Data is presented as one sample per cycle. + -- - sAdcDataValid asserts when ADC data is valid. + -- - sDacReadyForInput asserts when DAC data is ready to be received. + -- + -- Reset Crossings: + -- The ADC data and valid outputs are synchronously cleared before the asynchronous + -- reset is asserted--preventing any reset crossing issues here between the RX + -- (internal to the core) reset and the no-reset domain of RFNoC. + -- + -- The DAC samples should be zeros on reset de-assertion due to RFI being de-asserted + -- in reset. If they are not zeros, then it is still OK because data is ignored until + -- RFI is asserted. DAC RFI is double-synchronized to protect against the reset + -- crossing. This is safe to do because it simply delays the output of RFI by two + -- cycles on the assertion edge, and as long as reset is held for more than two + -- cycles, the de-assertion edge of RFI should come long before the TX module is + -- taken out of reset. + sAdcDataValid : out std_logic; + sAdcDataSamples0I : out std_logic_vector(15 downto 0); + sAdcDataSamples0Q : out std_logic_vector(15 downto 0); + sAdcDataSamples1I : out std_logic_vector(15 downto 0); + sAdcDataSamples1Q : out std_logic_vector(15 downto 0); + sDacReadyForInput : out std_logic; + sDacDataSamples0I : in std_logic_vector(15 downto 0); + sDacDataSamples0Q : in std_logic_vector(15 downto 0); + sDacDataSamples1I : in std_logic_vector(15 downto 0); + sDacDataSamples1Q : in std_logic_vector(15 downto 0); + + + -- RefClk & Timing & Sync -- + RefClk : in std_logic; + rPpsPulse : in std_logic; + rGatedPulseToPin : inout std_logic; -- straight to pin + sGatedPulseToPin : inout std_logic; -- straight to pin + sPps : out std_logic; + sPpsToIob : out std_logic; + + -- White Rabbit Timing & Sync -- + WrRefClk : in std_logic; + rWrPpsPulse : in std_logic; + rWrGatedPulseToPin : inout std_logic; -- straight to pin + sWrGatedPulseToPin : inout std_logic; -- straight to pin + aPpsSfpSel : in std_logic_vector(1 downto 0); + + + -- Debug for JESD + sAdcSync : out std_logic; + sDacSync : out std_logic; + sSysRef : out std_logic; + + -- Debug for Timing & Sync + rRpTransfer : out std_logic; + sSpTransfer : out std_logic; + rWrRpTransfer : out std_logic; + sWrSpTransfer : out std_logic + ); + +end DbCore; + + +architecture RTL of DbCore is + + component Jesd204bXcvrCore + port ( + bBusReset : in STD_LOGIC; + BusClk : in STD_LOGIC; + ReliableClk40 : in STD_LOGIC; + FpgaClk1x : in STD_LOGIC; + FpgaClk2x : in STD_LOGIC; + bFpgaClksStable : in STD_LOGIC; + bRegPortInFlat : in STD_LOGIC_VECTOR(49 downto 0); + bRegPortOutFlat : out STD_LOGIC_VECTOR(33 downto 0); + aLmkSync : out STD_LOGIC; + cSysRefFpgaLvds_p : in STD_LOGIC; + cSysRefFpgaLvds_n : in STD_LOGIC; + fSysRef : out STD_LOGIC; + CaptureSysRefClk : in STD_LOGIC; + JesdRefClk_p : in STD_LOGIC; + JesdRefClk_n : in STD_LOGIC; + bJesdRefClkPresent : out STD_LOGIC; + aAdcRx_p : in STD_LOGIC_VECTOR(3 downto 0); + aAdcRx_n : in STD_LOGIC_VECTOR(3 downto 0); + aSyncAdcOut_n : out STD_LOGIC; + aDacTx_p : out STD_LOGIC_VECTOR(3 downto 0); + aDacTx_n : out STD_LOGIC_VECTOR(3 downto 0); + aSyncDacIn_n : in STD_LOGIC; + fAdc0DataFlat : out STD_LOGIC_VECTOR(31 downto 0); + fAdc1DataFlat : out STD_LOGIC_VECTOR(31 downto 0); + fDac0DataFlat : in STD_LOGIC_VECTOR(31 downto 0); + fDac1DataFlat : in STD_LOGIC_VECTOR(31 downto 0); + fAdcDataValid : out STD_LOGIC; + fDacReadyForInput : out STD_LOGIC; + aDacSync : out STD_LOGIC; + aAdcSync : out STD_LOGIC); + end component; + + function to_Boolean (s : std_ulogic) return boolean is + begin + return (To_X01(s)='1'); + end to_Boolean; + + function to_StdLogic(b : boolean) return std_ulogic is + begin + if b then + return '1'; + else + return '0'; + end if; + end to_StdLogic; + + --vhook_sigstart + signal aAdcSync: STD_LOGIC; + signal aDacSync: STD_LOGIC; + signal bClockingRegPortOut: RegPortOut_t; + signal bDbRegPortOut: RegPortOut_t; + signal bFpgaClksStable: STD_LOGIC; + signal bJesdCoreRegPortInFlat: STD_LOGIC_VECTOR(49 downto 0); + signal bJesdCoreRegPortOutFlat: STD_LOGIC_VECTOR(33 downto 0); + signal bJesdRefClkPresent: STD_LOGIC; + signal bRadioClk1xEnabled: std_logic; + signal bRadioClk2xEnabled: std_logic; + signal bRadioClk3xEnabled: std_logic; + signal bRadioClkMmcmReset: std_logic; + signal bRadioClksValid: std_logic; + signal pPsDone: std_logic; + signal pPsEn: std_logic; + signal pPsInc: std_logic; + signal PsClk: std_logic; + signal sAdc0DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal sAdc1DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal SampleClk1xOutLcl: std_logic; + signal sDac0DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal sDac1DataFlat: STD_LOGIC_VECTOR(31 downto 0); + signal sDacReadyForInputAsyncReset: STD_LOGIC; + signal sRegPps: std_logic; + signal sSysRefAsyncReset: STD_LOGIC; + signal sWrPps: std_logic; + --vhook_sigend + + signal bJesdRegPortInGrp, bSyncRegPortIn, bWrSyncRegPortIn, bRegPortIn : RegPortIn_t; + signal bJesdRegPortOut, bSyncRegPortOut, bWrSyncRegPortOut, bRegPortOut : RegPortOut_t; + + signal sDacReadyForInput_ms, sDacReadyForInputLcl, + sDacSync_ms, sDacSyncLcl, + sAdcSync_ms, sAdcSyncLcl, + sSysRef_ms, sSysRefLcl : std_logic := '0'; + + signal sAdc0Data, sAdc1Data : AdcData_t; + signal sDac0Data, sDac1Data : DacData_t; + + signal sPpsSfpSel_ms, sPpsSfpSel : std_logic_vector(1 downto 0) := (others => '0'); + signal sUseWrTdcPps : boolean := false; + signal sPpsInt, sPpsMuxed : std_logic := '0'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of sDacReadyForInput_ms : signal is "true"; + attribute ASYNC_REG of sDacReadyForInputLcl : signal is "true"; + attribute ASYNC_REG of sDacSync_ms : signal is "true"; + attribute ASYNC_REG of sDacSyncLcl : signal is "true"; + attribute ASYNC_REG of sAdcSync_ms : signal is "true"; + attribute ASYNC_REG of sAdcSyncLcl : signal is "true"; + attribute ASYNC_REG of sSysRef_ms : signal is "true"; + attribute ASYNC_REG of sSysRefLcl : signal is "true"; + attribute ASYNC_REG of sPpsSfpSel_ms : signal is "true"; + attribute ASYNC_REG of sPpsSfpSel : signal is "true"; + +begin + + bRegPortOutFlat <= Flatten(bRegPortOut); + bRegPortIn <= Unflatten(bRegPortInFlat); + + + -- Combine return RegPorts. + bRegPortOut <= bJesdRegPortOut + + bClockingRegPortOut + + bSyncRegPortOut + bWrSyncRegPortOut + + bDbRegPortOut; + + + -- Clocking : ------------------------------------------------------------------------- + -- Automatically export the Sample Clocks and only use the incoming clocks in the + -- remainder of the logic. For a single module, the clocks must be looped back + -- in at a higher level! + -- ------------------------------------------------------------------------------------ + + --vhook_e RadioClocking + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a RadioClk1x SampleClk1xOutLcl + --vhook_a RadioClk2x SampleClk2xOut + --vhook_a RadioClk3x open + RadioClockingx: entity work.RadioClocking (rtl) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRadioClkMmcmReset => bRadioClkMmcmReset, --in std_logic + bRadioClksValid => bRadioClksValid, --out std_logic + bRadioClk1xEnabled => bRadioClk1xEnabled, --in std_logic + bRadioClk2xEnabled => bRadioClk2xEnabled, --in std_logic + bRadioClk3xEnabled => bRadioClk3xEnabled, --in std_logic + pPsInc => pPsInc, --in std_logic + pPsEn => pPsEn, --in std_logic + PsClk => PsClk, --in std_logic + pPsDone => pPsDone, --out std_logic + FpgaClk_n => FpgaClk_n, --in std_logic + FpgaClk_p => FpgaClk_p, --in std_logic + RadioClk1x => SampleClk1xOutLcl, --out std_logic + RadioClk2x => SampleClk2xOut, --out std_logic + RadioClk3x => open); --out std_logic + + -- We need an internal copy of SampleClk1x for the TDC, since we don't want to try + -- and align the other DB's clock accidentally. + SampleClk1xOut <= SampleClk1xOutLcl; + + --vhook_e ClockingRegs + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a bRegPortOut bClockingRegPortOut + --vhook_a aRadioClksValid bRadioClksValid + ClockingRegsx: entity work.ClockingRegs (RTL) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRegPortOut => bClockingRegPortOut, --out RegPortOut_t + bRegPortIn => bRegPortIn, --in RegPortIn_t + pPsInc => pPsInc, --out std_logic + pPsEn => pPsEn, --out std_logic + pPsDone => pPsDone, --in std_logic + PsClk => PsClk, --out std_logic + bRadioClkMmcmReset => bRadioClkMmcmReset, --out std_logic + aRadioClksValid => bRadioClksValid, --in std_logic + bRadioClk1xEnabled => bRadioClk1xEnabled, --out std_logic + bRadioClk2xEnabled => bRadioClk2xEnabled, --out std_logic + bRadioClk3xEnabled => bRadioClk3xEnabled, --out std_logic + bJesdRefClkPresent => bJesdRefClkPresent); --in std_logic + + + + -- JESD204B : ------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + + bJesdRegPortInGrp <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kJesdRegGroupInDbRegs); -- 0x2000 to 0x3FFC + + -- Expand/compress the RegPort for moving through the netlist boundary. + bJesdRegPortOut <= Unflatten(bJesdCoreRegPortOutFlat); + bJesdCoreRegPortInFlat <= Flatten(bJesdRegPortInGrp); + + --vhook Jesd204bXcvrCore + --vhook_a bRegPortInFlat bJesdCoreRegPortInFlat + --vhook_a bRegPortOutFlat bJesdCoreRegPortOutFlat + --vhook_a FpgaClk1x SampleClk1x + --vhook_a FpgaClk2x SampleClk2x + --vhook_a ReliableClk40 Clk40 + --vhook_a CaptureSysRefClk SampleClk1xOutLcl + --vhook_a cSysRefFpgaLvds_p sSysRefFpgaLvds_p + --vhook_a cSysRefFpgaLvds_n sSysRefFpgaLvds_n + --vhook_a fSysRef sSysRefAsyncReset + --vhook_a fDacReadyForInput sDacReadyForInputAsyncReset + --vhook_a {^f(.*)} s$1 + Jesd204bXcvrCorex: Jesd204bXcvrCore + port map ( + bBusReset => bBusReset, --in STD_LOGIC + BusClk => BusClk, --in STD_LOGIC + ReliableClk40 => Clk40, --in STD_LOGIC + FpgaClk1x => SampleClk1x, --in STD_LOGIC + FpgaClk2x => SampleClk2x, --in STD_LOGIC + bFpgaClksStable => bFpgaClksStable, --in STD_LOGIC + bRegPortInFlat => bJesdCoreRegPortInFlat, --in STD_LOGIC_VECTOR(49:0) + bRegPortOutFlat => bJesdCoreRegPortOutFlat, --out STD_LOGIC_VECTOR(33:0) + aLmkSync => aLmkSync, --out STD_LOGIC + cSysRefFpgaLvds_p => sSysRefFpgaLvds_p, --in STD_LOGIC + cSysRefFpgaLvds_n => sSysRefFpgaLvds_n, --in STD_LOGIC + fSysRef => sSysRefAsyncReset, --out STD_LOGIC + CaptureSysRefClk => SampleClk1xOutLcl, --in STD_LOGIC + JesdRefClk_p => JesdRefClk_p, --in STD_LOGIC + JesdRefClk_n => JesdRefClk_n, --in STD_LOGIC + bJesdRefClkPresent => bJesdRefClkPresent, --out STD_LOGIC + aAdcRx_p => aAdcRx_p, --in STD_LOGIC_VECTOR(3:0) + aAdcRx_n => aAdcRx_n, --in STD_LOGIC_VECTOR(3:0) + aSyncAdcOut_n => aSyncAdcOut_n, --out STD_LOGIC + aDacTx_p => aDacTx_p, --out STD_LOGIC_VECTOR(3:0) + aDacTx_n => aDacTx_n, --out STD_LOGIC_VECTOR(3:0) + aSyncDacIn_n => aSyncDacIn_n, --in STD_LOGIC + fAdc0DataFlat => sAdc0DataFlat, --out STD_LOGIC_VECTOR(31:0) + fAdc1DataFlat => sAdc1DataFlat, --out STD_LOGIC_VECTOR(31:0) + fDac0DataFlat => sDac0DataFlat, --in STD_LOGIC_VECTOR(31:0) + fDac1DataFlat => sDac1DataFlat, --in STD_LOGIC_VECTOR(31:0) + fAdcDataValid => sAdcDataValid, --out STD_LOGIC + fDacReadyForInput => sDacReadyForInputAsyncReset, --out STD_LOGIC + aDacSync => aDacSync, --out STD_LOGIC + aAdcSync => aAdcSync); --out STD_LOGIC + + JesdDoubleSyncToNoResetSampleClk : process (SampleClk1x) + begin + if rising_edge(SampleClk1x) then + sDacReadyForInput_ms <= sDacReadyForInputAsyncReset; + sDacReadyForInputLcl <= sDacReadyForInput_ms; + -- No clock crossing here -- just reset, although the prefix declares otherwise... + sDacSync_ms <= aDacSync; + sDacSyncLcl <= sDacSync_ms; + sAdcSync_ms <= aAdcSync; + sAdcSyncLcl <= sAdcSync_ms; + sSysRef_ms <= sSysRefAsyncReset; + sSysRefLcl <= sSysRef_ms; + end if; + end process; + + -- Locals to outputs. + sDacReadyForInput <= sDacReadyForInputLcl; + sDacSync <= sDacSyncLcl; + sAdcSync <= sAdcSyncLcl; + sSysRef <= sSysRefLcl; + + -- Just combine the first two enables, since they're the ones that are used for JESD. + -- No reset crossing here, since bFpgaClksStable is only received by a no-reset domain + -- and the MGTs directly. + bFpgaClksStable <= bRadioClksValid and bRadioClk1xEnabled and bRadioClk2xEnabled; + + -- Compress/expand the flat data types from the netlist and route to top level. + sAdc0Data <= Unflatten(sAdc0DataFlat); + sAdc1Data <= Unflatten(sAdc1DataFlat); + sDac0DataFlat <= Flatten(sDac0Data); + sDac1DataFlat <= Flatten(sDac1Data); + + sAdcDataSamples0I <= sAdc0Data.I; + sAdcDataSamples0Q <= sAdc0Data.Q; + sAdcDataSamples1I <= sAdc1Data.I; + sAdcDataSamples1Q <= sAdc1Data.Q; + + sDac0Data.I <= sDacDataSamples0I; + sDac0Data.Q <= sDacDataSamples0Q; + sDac1Data.I <= sDacDataSamples1I; + sDac1Data.Q <= sDacDataSamples1Q; + + + -- Timing and Sync : ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + + bSyncRegPortIn <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kTdc0OffsetsInEndpoint); -- 0x0200 + + --vhook_e TdcWrapper + --vhook_# Use the local copy of the SampleClock, since we want the TDC to measure the + --vhook_# clock offset for this daughterboard, not the global SampleClock. + --vhook_a SampleClk SampleClk1xOutLcl + --vhook_a sPpsPulse sRegPps + TdcWrapperx: entity work.TdcWrapper (struct) + port map ( + BusClk => BusClk, --in std_logic + bBusReset => bBusReset, --in std_logic + RefClk => RefClk, --in std_logic + SampleClk => SampleClk1xOutLcl, --in std_logic + MeasClk => MeasClk, --in std_logic + bSyncRegPortOut => bSyncRegPortOut, --out RegPortOut_t + bSyncRegPortIn => bSyncRegPortIn, --in RegPortIn_t + rPpsPulse => rPpsPulse, --in std_logic + sPpsPulse => sRegPps, --out std_logic + rRpTransfer => rRpTransfer, --out std_logic + sSpTransfer => sSpTransfer, --out std_logic + rGatedPulseToPin => rGatedPulseToPin, --inout std_logic + sGatedPulseToPin => sGatedPulseToPin); --inout std_logic + + WrTdcGen: if kInclWhiteRabbitTdc = '1' generate + bWrSyncRegPortIn <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kTdc1OffsetsInEndpoint); -- 0x0400 + + --vhook_e TdcWrapper WrTdcWrapperx + --vhook_# Use the local copy of the SampleClock, since we want the TDC to measure the + --vhook_# clock offset for this daughterboard, not the global SampleClock. + --vhook_a bSyncRegPortIn bWrSyncRegPortIn + --vhook_a bSyncRegPortOut bWrSyncRegPortOut + --vhook_a SampleClk SampleClk1xOutLcl + --vhook_a RefClk WrRefClk + --vhook_a rPpsPulse rWrPpsPulse + --vhook_a sPpsPulse sWrPps + --vhook_a rRpTransfer rWrRpTransfer + --vhook_a sSpTransfer sWrSpTransfer + --vhook_a rGatedPulseToPin rWrGatedPulseToPin + --vhook_a sGatedPulseToPin sWrGatedPulseToPin + WrTdcWrapperx: entity work.TdcWrapper (struct) + port map ( + BusClk => BusClk, --in std_logic + bBusReset => bBusReset, --in std_logic + RefClk => WrRefClk, --in std_logic + SampleClk => SampleClk1xOutLcl, --in std_logic + MeasClk => MeasClk, --in std_logic + bSyncRegPortOut => bWrSyncRegPortOut, --out RegPortOut_t + bSyncRegPortIn => bWrSyncRegPortIn, --in RegPortIn_t + rPpsPulse => rWrPpsPulse, --in std_logic + sPpsPulse => sWrPps, --out std_logic + rRpTransfer => rWrRpTransfer, --out std_logic + sSpTransfer => sWrSpTransfer, --out std_logic + rGatedPulseToPin => rWrGatedPulseToPin, --inout std_logic + sGatedPulseToPin => sWrGatedPulseToPin); --inout std_logic + end generate WrTdcGen; + + WrTdcNotGen: if kInclWhiteRabbitTdc = '0' generate + bWrSyncRegPortOut <= kRegPortOutZero; + sWrPps <= '0'; + rWrRpTransfer <= '0'; + sWrSpTransfer <= '0'; + rWrGatedPulseToPin <= '0'; + sWrGatedPulseToPin <= '0'; + end generate WrTdcNotGen; + + -- Mux the output PPS based on the SFP selection bits. Encoding is one-hot, with zero + -- also a valid state. Regardless of whether the user selects SFP0 or SFP1 as the time + -- source, there is only one White Rabbit TDC, so '01' and '10' are equivalent. + -- '00': Use the PPS output from the "regular" TDC. + -- '01': Use the PPS output from the "white rabbit" TDC. + -- '10': Use the PPS output from the "white rabbit" TDC. + PpsOutputMux : process (SampleClk1xOutLcl) + begin + if rising_edge(SampleClk1xOutLcl) then + -- Double-sync the control bits to the Sample Clock domain. + sPpsSfpSel_ms <= aPpsSfpSel; + sPpsSfpSel <= sPpsSfpSel_ms; + + -- OR the control bits together to produce a single override enable for the WR TDC. + sUseWrTdcPps <= to_boolean(sPpsSfpSel(0) or sPpsSfpSel(1)); + + -- Flop the outputs. One flop for the PPS output IOB, the other for use internally. + sPpsInt <= sPpsMuxed; + end if; + end process PpsOutputMux; + + sPpsMuxed <= sWrPps when sUseWrTdcPps else sRegPps; + sPps <= sPpsInt; + sPpsToIob <= sPpsMuxed; -- No added flop here since there's an IOB outside this module. + + -- Daughterboard Control : ------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + + --vhook_e DaughterboardRegs + --vhook_# Tying this low is safe because the sync reset is used inside DaughterboardRegs. + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a bRegPortOut bDbRegPortOut + --vhook_a kDbId std_logic_vector(to_unsigned(16#150#,16)) + DaughterboardRegsx: entity work.DaughterboardRegs (RTL) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRegPortOut => bDbRegPortOut, --out RegPortOut_t + bRegPortIn => bRegPortIn, --in RegPortIn_t + kDbId => std_logic_vector(to_unsigned(16#150#,16)), --in std_logic_vector(15:0) + kSlotId => kSlotId); --in std_logic + + +end RTL; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf Binary files differnew file mode 100644 index 000000000..27619d2a0 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore.edf diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd new file mode 100644 index 000000000..84c461d26 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/Jesd204bXcvrCore_stub.vhd @@ -0,0 +1,56 @@ +-- Copyright 1986-2015 Xilinx, Inc. All Rights Reserved. +-- -------------------------------------------------------------------------------- +-- Tool Version: Vivado v.2015.4.2 (win64) Build 1494164 Fri Feb 26 04:18:56 MST 2016 +-- Date : Wed Jan 10 10:53:33 2018 +-- Host : djepson-lt running 64-bit major release (build 9200) +-- Command : write_vhdl -mode synth_stub -force -file ./Jesd204bXcvrCore_stub.vhd +-- Design : Jesd204bXcvrCore +-- Purpose : Stub declaration of top-level module interface +-- Device : xc7z100ffg900-2 +-- -------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +entity Jesd204bXcvrCore is + Port ( + bBusReset : in STD_LOGIC; + BusClk : in STD_LOGIC; + ReliableClk40 : in STD_LOGIC; + FpgaClk1x : in STD_LOGIC; + FpgaClk2x : in STD_LOGIC; + bFpgaClksStable : in STD_LOGIC; + bRegPortInFlat : in STD_LOGIC_VECTOR ( 49 downto 0 ); + bRegPortOutFlat : out STD_LOGIC_VECTOR ( 33 downto 0 ); + aLmkSync : out STD_LOGIC; + cSysRefFpgaLvds_p : in STD_LOGIC; + cSysRefFpgaLvds_n : in STD_LOGIC; + fSysRef : out STD_LOGIC; + CaptureSysRefClk : in STD_LOGIC; + JesdRefClk_p : in STD_LOGIC; + JesdRefClk_n : in STD_LOGIC; + bJesdRefClkPresent : out STD_LOGIC; + aAdcRx_p : in STD_LOGIC_VECTOR ( 3 downto 0 ); + aAdcRx_n : in STD_LOGIC_VECTOR ( 3 downto 0 ); + aSyncAdcOut_n : out STD_LOGIC; + aDacTx_p : out STD_LOGIC_VECTOR ( 3 downto 0 ); + aDacTx_n : out STD_LOGIC_VECTOR ( 3 downto 0 ); + aSyncDacIn_n : in STD_LOGIC; + fAdc0DataFlat : out STD_LOGIC_VECTOR ( 31 downto 0 ); + fAdc1DataFlat : out STD_LOGIC_VECTOR ( 31 downto 0 ); + fDac0DataFlat : in STD_LOGIC_VECTOR ( 31 downto 0 ); + fDac1DataFlat : in STD_LOGIC_VECTOR ( 31 downto 0 ); + fAdcDataValid : out STD_LOGIC; + fDacReadyForInput : out STD_LOGIC; + aDacSync : out STD_LOGIC; + aAdcSync : out STD_LOGIC + ); + +end Jesd204bXcvrCore; + +architecture stub of Jesd204bXcvrCore is +attribute syn_black_box : boolean; +attribute black_box_pad_pin : string; +attribute syn_black_box of stub : architecture is true; +attribute black_box_pad_pin of stub : architecture is "bBusReset,BusClk,ReliableClk40,FpgaClk1x,FpgaClk2x,bFpgaClksStable,bRegPortInFlat[49:0],bRegPortOutFlat[33:0],aLmkSync,cSysRefFpgaLvds_p,cSysRefFpgaLvds_n,fSysRef,CaptureSysRefClk,JesdRefClk_p,JesdRefClk_n,bJesdRefClkPresent,aAdcRx_p[3:0],aAdcRx_n[3:0],aSyncAdcOut_n,aDacTx_p[3:0],aDacTx_n[3:0],aSyncDacIn_n,fAdc0DataFlat[31:0],fAdc1DataFlat[31:0],fDac0DataFlat[31:0],fDac1DataFlat[31:0],fAdcDataValid,fDacReadyForInput,aDacSync,aAdcSync"; +begin +end; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd new file mode 100644 index 000000000..03b95c100 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgClockingRegMap.vhd @@ -0,0 +1,107 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgClockingRegMap.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgClockingRegMap is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- RadioClkMmcm : 0x20 (ClockingRegs.vhd) + -- PhaseShiftControl : 0x24 (ClockingRegs.vhd) + -- RadioClkEnables : 0x28 (ClockingRegs.vhd) + -- MgtRefClkStatus : 0x30 (ClockingRegs.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group ClockingRegs +--=============================================================================== + + -- RadioClkMmcm Register (from ClockingRegs.vhd) + constant kRadioClkMmcm : integer := 16#20#; -- Register Offset + constant kRadioClkMmcmSize: integer := 32; -- register width in bits + constant kRadioClkMmcmMask : std_logic_vector(31 downto 0) := X"00000013"; + constant kRadioClkMmcmResetSetSize : integer := 1; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetSetMsb : integer := 0; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetSet : integer := 0; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetClearSize : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmResetClearMsb : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmResetClear : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmLockedSize : integer := 1; --RadioClkMmcm:RadioClkMmcmLocked + constant kRadioClkMmcmLockedMsb : integer := 4; --RadioClkMmcm:RadioClkMmcmLocked + constant kRadioClkMmcmLocked : integer := 4; --RadioClkMmcm:RadioClkMmcmLocked + + -- PhaseShiftControl Register (from ClockingRegs.vhd) + constant kPhaseShiftControl : integer := 16#24#; -- Register Offset + constant kPhaseShiftControlSize: integer := 32; -- register width in bits + constant kPhaseShiftControlMask : std_logic_vector(31 downto 0) := X"10010011"; + constant kPsIncSize : integer := 1; --PhaseShiftControl:PsInc + constant kPsIncMsb : integer := 0; --PhaseShiftControl:PsInc + constant kPsInc : integer := 0; --PhaseShiftControl:PsInc + constant kPsDecSize : integer := 1; --PhaseShiftControl:PsDec + constant kPsDecMsb : integer := 4; --PhaseShiftControl:PsDec + constant kPsDec : integer := 4; --PhaseShiftControl:PsDec + constant kPsEnabledForFdbClkSize : integer := 1; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsEnabledForFdbClkMsb : integer := 16; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsEnabledForFdbClk : integer := 16; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsDoneSize : integer := 1; --PhaseShiftControl:PsDone + constant kPsDoneMsb : integer := 28; --PhaseShiftControl:PsDone + constant kPsDone : integer := 28; --PhaseShiftControl:PsDone + + -- RadioClkEnables Register (from ClockingRegs.vhd) + constant kRadioClkEnables : integer := 16#28#; -- Register Offset + constant kRadioClkEnablesSize: integer := 32; -- register width in bits + constant kRadioClkEnablesMask : std_logic_vector(31 downto 0) := X"00000111"; + constant kRadioClk1xEnabledSize : integer := 1; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk1xEnabledMsb : integer := 0; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk1xEnabled : integer := 0; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk2xEnabledSize : integer := 1; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk2xEnabledMsb : integer := 4; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk2xEnabled : integer := 4; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk3xEnabledSize : integer := 1; --RadioClkEnables:RadioClk3xEnabled + constant kRadioClk3xEnabledMsb : integer := 8; --RadioClkEnables:RadioClk3xEnabled + constant kRadioClk3xEnabled : integer := 8; --RadioClkEnables:RadioClk3xEnabled + + -- MgtRefClkStatus Register (from ClockingRegs.vhd) + constant kMgtRefClkStatus : integer := 16#30#; -- Register Offset + constant kMgtRefClkStatusSize: integer := 32; -- register width in bits + constant kMgtRefClkStatusMask : std_logic_vector(31 downto 0) := X"00000001"; + constant kJesdRefClkPresentSize : integer := 1; --MgtRefClkStatus:JesdRefClkPresent + constant kJesdRefClkPresentMsb : integer := 0; --MgtRefClkStatus:JesdRefClkPresent + constant kJesdRefClkPresent : integer := 0; --MgtRefClkStatus:JesdRefClkPresent + +end package; + +package body PkgClockingRegMap is + + -- function kRadioClkMmcmRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kPhaseShiftControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRadioClkEnablesRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kMgtRefClkStatusRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd new file mode 100644 index 000000000..06708cde3 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgDaughterboardRegMap.vhd @@ -0,0 +1,56 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgDaughterboardRegMap.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgDaughterboardRegMap is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- DaughterboardId : 0x630 (DaughterboardRegs.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group StaticControl +--=============================================================================== + + -- DaughterboardId Register (from DaughterboardRegs.vhd) + constant kDaughterboardId : integer := 16#630#; -- Register Offset + constant kDaughterboardIdSize: integer := 32; -- register width in bits + constant kDaughterboardIdMask : std_logic_vector(31 downto 0) := X"0001ffff"; + constant kDbIdValSize : integer := 16; --DaughterboardId:DbIdVal + constant kDbIdValMsb : integer := 15; --DaughterboardId:DbIdVal + constant kDbIdVal : integer := 0; --DaughterboardId:DbIdVal + constant kSlotIdValSize : integer := 1; --DaughterboardId:SlotIdVal + constant kSlotIdValMsb : integer := 16; --DaughterboardId:SlotIdVal + constant kSlotIdVal : integer := 16; --DaughterboardId:SlotIdVal + +end package; + +package body PkgDaughterboardRegMap is + + -- function kDaughterboardIdRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd new file mode 100644 index 000000000..c0f5244b5 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgJesdConfig.vhd @@ -0,0 +1,234 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgJesdConfig.vhd +-- Author: National Instruments +-- Original Project: NI 5840 +-- Date: 11 March 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: JESD204B setup constants and functions. These constants are shared +-- between RX and TX JESD cores. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRegs.all; + + +package PkgJesdConfig is + + -- "JESD" in ASCII - with the core number 0 or 1 on the LSb. + constant kJesdSignature : std_logic_vector(31 downto 0) := x"4a455344"; + + -- Register endpoints + constant kJesdDrpRegsInEndpoint : RegOffset_t := (kOffset => 16#0800#, -- 0x2800 to + kWidth => 16#0800#); -- 0x2FFF + + -- Selects the UsrClk2 for the transceivers. For 64-bit wide transceivers, the + -- UsrClk = 2*UserClk2 frequency. For 32-bit wide transceivers, UsrClk = UserClk2 + -- frequency. This is a generalization, the clock ratio should be confirmed based on + -- the transceiver configuration. + -- The N310 transceivers use the single rate reference, hence = false. + constant kDoubleRateUsrClk : boolean := false; + + -- For the N310, all lanes are in one quad and we use the QPLL. + constant kJesdUseQpll : boolean := true; + + constant kAdcDataWidth : integer := 16; -- ADC data width in bits + constant kDacDataWidth : integer := 16; -- DAC data width in bits + constant kSamplesPerCycle : integer := 1; -- Number of samples per SampleClk1x + + constant kGtxDrpAddrWidth : natural := 9; + constant kQpllDrpAddrWidth : natural := 8; + -- Max supported number of lanes + constant kMaxNumLanes : natural := 4; + -- Max supported number of quads (normally there is 1 quad per 4 lanes but disconnect + -- the definitions to allow quad sharing) + constant kMaxNumQuads : natural := 1; + + + -- JESD shared setup - LMFS = 4421, HD = 0 + constant kNumLanes : natural := 4; -- L + constant kNumConvs : positive := 4; -- M + constant kOctetsPerFrame : natural := 2; -- F + constant kDacJesdSamplesPerCycle : integer := 1; -- S + constant kOctetsPerLane : natural := 2; -- MGT data is kOctetsPerLane*8 = 16 bits wide + constant kNumQuads : natural := kNumLanes/4; -- 4 lanes per quad + constant kHighDensity : boolean := false; -- HD + constant kConvResBits : positive := kDacDataWidth-2; -- Converter resolution in bits + constant kConvSampleBits : positive := kDacDataWidth; -- Sample Length in bits + constant kInitLaneAlignCnt : positive := 4; + constant kFramesPerMulti : natural := 20; -- K + + -- In the N310 case we are one SPC, so this value is simply the number of frames + -- (samples) per multiframe. + constant kUserClksPerMulti : integer := kFramesPerMulti; + + + type NaturalVector is array ( natural range <>) of natural; + + -- The PCB connections are as follows: + -- + -- Transceiver MGT Channel ADC Lane DAC Lane + -- *********** *********** ******** ******** + -- GT0: X0Y8 0 0 0 + -- GT1: X0Y9 1 1 1 + -- GT2: X0Y10 2 2 2 + -- GT3: X0Y11 3 3 3 + constant kRxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- MGT => ADC (in above table) + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3 + ); + + constant kTxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- MGT => DAC lane + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3 + ); + + constant kLaneToQuadMap : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- All lanes are in one quad + 0 => 0, + 1 => 0, + 2 => 0, + 3 => 0 + ); + + + -- The master transceiver channel for channel bonding. E(kMasterBondingChannel) + -- must have the highest value decrementing to b"000" for that last channels to bond. + constant kMasterBondingChannel : integer := 1; + + -- Channel bonding occurs when a master detects a K-char sequence and aligns its + -- internal FIFO to the start of this sequence. A signal is then generated to other + -- slave transceivers that cause them to bond to the sequence - this bonding signal is + -- cascaded from master to slave to slave to slave, etc where each slave must know how + -- many levels to the master there are. The last slave to bond must be at level b"000" + -- and the master is at the highest level; the number of levels in the sequence is + -- governed by the size of the transceiver FIFO (see the Xilinx user guides for more + -- information). + type BondLevels_t is array(0 to kNumLanes - 1) of std_logic_vector(2 downto 0); + constant kBondLevel : BondLevels_t := ( + 0 => b"000", -- Control from 1 + 1 => b"001", -- Master + 2 => b"000", -- Control from 1 + 3 => b"000" -- Control from 1 + ); + + -- Option to pipeline stages to improve timing, if needed + constant kPipelineDetectCharsStage : boolean := false; + constant kPipelineCharReplStage : boolean := false; + + + -- ADC & DAC Data Types + -- + + -- ADC Words from JESD204B RX Core. The array is 4 elements wide to accommodate the + -- I & Q elements from both RX channels. + subtype AdcWord_t is std_logic_vector(kAdcDataWidth - 1 downto 0); + type AdcWordArray_t is array(4 - 1 downto 0) of AdcWord_t; + + -- Data types for manipulation and presentation to outside world. + type AdcData_t is record + I : std_logic_vector(kAdcDataWidth - 1 downto 0); + Q : std_logic_vector(kAdcDataWidth - 1 downto 0); + end record; + + type DacData_t is record + I : std_logic_vector(kDacDataWidth - 1 downto 0); + Q : std_logic_vector(kDacDataWidth - 1 downto 0); + end record; + + + -- Flattened data types for passing into and out of pre-synthesized components. + subtype AdcDataFlat_t is std_logic_vector(2*kAdcDataWidth - 1 downto 0); + subtype DacDataFlat_t is std_logic_vector(2*kDacDataWidth - 1 downto 0); + + -- Functions to convert to/from types defined above. + function Flatten (AdcData : AdcData_t) return AdcDataFlat_t; + function Unflatten(AdcData : AdcDataFlat_t) return AdcData_t; + + function Flatten (DacData : DacData_t) return DacDataFlat_t; + function Unflatten(DacData : DacDataFlat_t) return DacData_t; + + +end package; + + +package body PkgJesdConfig is + + + + + + -- Flattens AdcData_t to AdcDataFlat_t + function Flatten (AdcData : AdcData_t) return AdcDataFlat_t + is + variable ReturnVar : AdcDataFlat_t; + begin + ReturnVar := (others => '0'); + -- MSB is I + ReturnVar := AdcData.I & AdcData.Q; + return ReturnVar; + end function Flatten; + + + -- UnFlattens AdcDataFlat_t to AdcData_t + function Unflatten(AdcData : AdcDataFlat_t) return AdcData_t + is + variable ReturnVar : AdcData_t; + begin + ReturnVar := (others => (others => '0')); + -- MSB is I + ReturnVar.I := AdcData(2*kAdcDataWidth - 1 downto kAdcDataWidth); + ReturnVar.Q := AdcData( kAdcDataWidth - 1 downto 0); + return ReturnVar; + end function Unflatten; + + + + -- Flattens DacData_t to DacDataFlat_t + function Flatten (DacData : DacData_t) return DacDataFlat_t + is + variable ReturnVar : DacDataFlat_t; + begin + ReturnVar := (others => '0'); + -- MSB is I + ReturnVar := DacData.I & DacData.Q; + return ReturnVar; + end function Flatten; + + + -- UnFlattens DacDataFlat_t to DacData_t + function Unflatten(DacData : DacDataFlat_t) return DacData_t + is + variable ReturnVar : DacData_t; + begin + ReturnVar := (others => (others => '0')); + -- MSB is I + ReturnVar.I := DacData(2*kDacDataWidth - 1 downto kDacDataWidth); + ReturnVar.Q := DacData( kDacDataWidth - 1 downto 0); + return ReturnVar; + end function Unflatten; + + + + + +end package body;
\ No newline at end of file diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd new file mode 100644 index 000000000..904653a8e --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/PkgMgPersonality.vhd @@ -0,0 +1,61 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgMgPersonality.vhd +-- Author: National Instruments +-- Original Project: N310 +-- Date: 13 April 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: This package contains constants and helpful functions that enable +-- the FPGA to be compiled with different features. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRegs.all; + + +package PkgMgPersonality is + + + -- RegPort Address Definitions : ------------------------------------------------------ + -- + -- DB Regs ... + -- + -- Clocking Offset: 0x 000 Width: 0x 200 + -- Tdco0 Offset: 0x 200 Width: 0x 200 + -- Tdco1 Offset: 0x 400 Width: 0x 200 + -- Daughterboard Ctrl Offset: 0x 600 Width: 0x 200 + -- Total: 0x2000 + -- JESD 2x - A Offset: 0x2000 Width: 0x1000 + -- JESD 2x - B Offset: 0x3000 Width: 0x1000 + -- Total: 0x4000 + -- Total: 0x8000 for two DBs + -- ------------------------------------------------------------------------------------ + + -- A single RegPort runs to the JESD204B Core. + constant kJesdRegGroupInDbRegs : RegOffset_t := (kOffset => 16#2000#, -- 0x2000 to + kWidth => 16#1000#); -- 0x2FFF + + -- DB Regs : -------------------------------------------------------------------------- + constant kClockingOffsetInEndpoint : RegOffset_t := (kOffset => 16#0000#, -- 0x0000 to + kWidth => 16#0200#); -- 0x01FF + constant kTdc0OffsetsInEndpoint : RegOffset_t := (kOffset => 16#0200#, -- 0x0200 to + kWidth => 16#0200#); -- 0x03FF + constant kTdc1OffsetsInEndpoint : RegOffset_t := (kOffset => 16#0400#, -- 0x0400 to + kWidth => 16#0200#); -- 0x05FF + constant kDaughterboardOffsetInEndpoint : RegOffset_t := (kOffset => 16#0600#, -- 0x0600 to + kWidth => 16#0200#); -- 0x07FF + + + + +end package PkgMgPersonality; diff --git a/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd new file mode 100644 index 000000000..ee0da9f84 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/mg/db_ifc/RadioClocking.vhd @@ -0,0 +1,304 @@ +------------------------------------------------------------------------------- +-- +-- File: RadioClocking.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 22 February 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Instantiates a MMCM to produce 1x, 2x, and 3x versions of the Radio Clock +-- coming from the FPGA input pin. Handles all the buffering for the input clock. +-- Additionally allows the clocks to be turned on and off, and phase shifted. +-- +-- NOTE: This module hard-codes the MMCM settings for a SPECIFIC clock rate! +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library unisim; + use unisim.vcomponents.all; + + +entity RadioClocking is + port ( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + + -- Should be a always-on clock + BusClk : in std_logic; + + -- Sync reset to the RadioClkMmcm. + bRadioClkMmcmReset : in std_logic; + + -- Locked indication from the RadioClkMmcm in BusClk and aReset domains. + bRadioClksValid : out std_logic; + + bRadioClk1xEnabled : in std_logic; + bRadioClk2xEnabled : in std_logic; + bRadioClk3xEnabled : in std_logic; + + -- Phase shift interface for the RadioClkMmcm. PsClk must be <= 200 MHz. + pPsInc : in std_logic; + pPsEn : in std_logic; + PsClk : in std_logic; + pPsDone : out std_logic; + + -- Straight from pins. Buffer included in here. + FpgaClk_n : in std_logic; + FpgaClk_p : in std_logic; + + RadioClk1x : out std_logic; + RadioClk2x : out std_logic; + RadioClk3x : out std_logic + + ); +end RadioClocking; + + +architecture rtl of RadioClocking is + + --vhook_sigstart + signal RadioClk1xLcl: std_logic; + signal RadioClk1xPll: std_logic; + signal RadioClk2xLcl: std_logic; + signal RadioClk2xPll: std_logic; + signal RadioClk3xLcl: std_logic; + signal RadioClk3xPll: std_logic; + --vhook_sigend + + signal RadioClkMmcmFeedbackIn, + RadioClkMmcmFeedbackOut, + FpgaClkSE, + aRadioClkMmcmLocked : std_logic; + + signal bRadioClkMmcmLocked_ms, + bRadioClkMmcmLocked, + bEnableRadioClkBufgOutputs, + bEnableRadioClk1xBufgOutput, + bEnableRadioClk2xBufgOutput, + bEnableRadioClk3xBufgOutput : std_logic := '0'; + + signal aRadioClkMmcmResetInternal : std_logic := '1'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of bRadioClkMmcmLocked_ms : signal is "true"; + attribute ASYNC_REG of bRadioClkMmcmLocked : signal is "true"; + +begin + + -- Radio Clock Buffering : ------------------------------------------------------------ + -- + -- ------------------------------------------------------------------------------------ + --vhook_i IBUFDS FpgaClkIbufg hidegeneric=true + --vhook_a I FpgaClk_p + --vhook_a IB FpgaClk_n + --vhook_a O FpgaClkSE + FpgaClkIbufg: IBUFDS + port map ( + O => FpgaClkSE, --out std_ulogic + I => FpgaClk_p, --in std_ulogic + IB => FpgaClk_n); --in std_ulogic + + ResetDelay : process(aReset, BusClk) + begin + if aReset then + aRadioClkMmcmResetInternal <= '1'; + elsif rising_edge(BusClk) then + if bReset then + aRadioClkMmcmResetInternal <= '1'; + else + -- Delay by 1 to allow the BUFGs to turn off before the MMCM is reset. + aRadioClkMmcmResetInternal <= bRadioClkMmcmReset; + end if; + end if; + end process ResetDelay; + + + RadioClkMmcm: MMCME2_ADV + generic map( + COMPENSATION => "ZHOLD", + BANDWIDTH => "OPTIMIZED", + CLKFBOUT_MULT_F => 6.000, -- Feedback + CLKOUT0_DIVIDE_F => 6.000, -- Data Clock 1x, RadioClk1xPll + CLKOUT1_DIVIDE => 3, -- Data Clock 2x, RadioClk2xPll + CLKOUT2_DIVIDE => 2, -- Data Clock 3x, RadioClk3xPll + CLKOUT3_DIVIDE => 1, -- unused + CLKOUT4_DIVIDE => 1, -- unused + CLKOUT5_DIVIDE => 1, -- unused + CLKOUT6_DIVIDE => 1, -- unused + CLKFBOUT_PHASE => 0.000, -- Feedback + CLKOUT0_PHASE => 0.000, -- Data Clock 1x + CLKOUT1_PHASE => 0.000, -- Data Clock 2x + CLKOUT2_PHASE => 0.000, -- Data Clock 3x + CLKOUT3_PHASE => 0.000, -- unused + CLKOUT4_PHASE => 0.000, -- unused + CLKOUT5_PHASE => 0.000, -- unused + CLKOUT6_PHASE => 0.000, -- unused + CLKOUT0_DUTY_CYCLE => 0.500, + CLKOUT1_DUTY_CYCLE => 0.500, + CLKOUT2_DUTY_CYCLE => 0.500, + CLKOUT3_DUTY_CYCLE => 0.500, + CLKOUT4_DUTY_CYCLE => 0.500, + CLKOUT5_DUTY_CYCLE => 0.500, + CLKOUT6_DUTY_CYCLE => 0.500, + DIVCLK_DIVIDE => 1, + REF_JITTER1 => 0.010, + CLKIN1_PERIOD => 6.510, -- 153.6 MHz max + CLKFBOUT_USE_FINE_PS => true, + CLKOUT0_USE_FINE_PS => false, + CLKOUT1_USE_FINE_PS => false, + CLKOUT2_USE_FINE_PS => false, + CLKOUT3_USE_FINE_PS => false, + CLKOUT4_USE_FINE_PS => false, + CLKOUT5_USE_FINE_PS => false, + CLKOUT6_USE_FINE_PS => false, + STARTUP_WAIT => false, + CLKOUT4_CASCADE => false) + port map ( + CLKINSEL => '1', + CLKIN1 => FpgaClkSE, + CLKIN2 => '0', + CLKFBIN => RadioClkMmcmFeedbackIn, + RST => aRadioClkMmcmResetInternal, + PWRDWN => '0', + DADDR => (others => '0'), + DI => (others => '0'), + DWE => '0', + DEN => '0', + DCLK => '0', + DO => open, + DRDY => open, + PSINCDEC => pPsInc, + PSEN => pPsEn, + PSCLK => PsClk, + PSDONE => pPsDone, + CLKOUT0 => RadioClk1xPll, + CLKOUT0B => open, + CLKOUT1 => RadioClk2xPll, + CLKOUT1B => open, + CLKOUT2 => RadioClk3xPll, + CLKOUT2B => open, + CLKOUT3 => open, + CLKOUT3B => open, + CLKOUT4 => open, + CLKOUT5 => open, + CLKOUT6 => open, + CLKFBOUT => RadioClkMmcmFeedbackOut, + CLKFBOUTB => open, + LOCKED => aRadioClkMmcmLocked, + CLKINSTOPPED => open, + CLKFBSTOPPED => open); + + RadioClkMmcmFeedbackBufg: BUFG + port map ( + I => RadioClkMmcmFeedbackOut, + O => RadioClkMmcmFeedbackIn + ); + + + -- Only enable the WRAPBUFGs when the MMCM is locked. If the MMCM is ever placed in + -- reset, we turn off the clocks one cycle before the asynchronous version + -- (aRadioClkMmcmResetInternal) reaches the MMCM inputs in order to prevent + -- output glitches. + CombineEnablesForBuffers : process(aReset, BusClk) + begin + if aReset then + bRadioClkMmcmLocked_ms <= '0'; + bRadioClkMmcmLocked <= '0'; + bEnableRadioClk1xBufgOutput <= '0'; + bEnableRadioClk2xBufgOutput <= '0'; + bEnableRadioClk3xBufgOutput <= '0'; + bEnableRadioClkBufgOutputs <= '0'; + elsif rising_edge(BusClk) then + if bReset then + bRadioClkMmcmLocked_ms <= '0'; + bRadioClkMmcmLocked <= '0'; + bEnableRadioClk1xBufgOutput <= '0'; + bEnableRadioClk2xBufgOutput <= '0'; + bEnableRadioClk3xBufgOutput <= '0'; + bEnableRadioClkBufgOutputs <= '0'; + else + bRadioClkMmcmLocked_ms <= aRadioClkMmcmLocked; + bRadioClkMmcmLocked <= bRadioClkMmcmLocked_ms; + + bEnableRadioClkBufgOutputs <= bRadioClkMmcmLocked and + not bRadioClkMmcmReset; + bEnableRadioClk1xBufgOutput <= bRadioClk1xEnabled and bEnableRadioClkBufgOutputs; + bEnableRadioClk2xBufgOutput <= bRadioClk2xEnabled and bEnableRadioClkBufgOutputs; + bEnableRadioClk3xBufgOutput <= bRadioClk3xEnabled and bEnableRadioClkBufgOutputs; + end if; + end if; + end process CombineEnablesForBuffers; + + bRadioClksValid <= bEnableRadioClkBufgOutputs; + + --vhook_e WrapBufg RadioClk1xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk1xPll + --vhook_a aCe bEnableRadioClk1xBufgOutput + --vhook_a ClkOut RadioClk1xLcl + RadioClk1xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk1xPll, --in std_logic + aCe => bEnableRadioClk1xBufgOutput, --in std_logic + ClkOut => RadioClk1xLcl); --out std_logic + + --vhook_e WrapBufg RadioClk2xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk2xPll + --vhook_a aCe bEnableRadioClk2xBufgOutput + --vhook_a ClkOut RadioClk2xLcl + RadioClk2xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk2xPll, --in std_logic + aCe => bEnableRadioClk2xBufgOutput, --in std_logic + ClkOut => RadioClk2xLcl); --out std_logic + + --vhook_e WrapBufg RadioClk3xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk3xPll + --vhook_a aCe bEnableRadioClk3xBufgOutput + --vhook_a ClkOut RadioClk3xLcl + RadioClk3xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk3xPll, --in std_logic + aCe => bEnableRadioClk3xBufgOutput, --in std_logic + ClkOut => RadioClk3xLcl); --out std_logic + + + -- Assign outputs from locals. + RadioClk1x <= RadioClk1xLcl; + RadioClk2x <= RadioClk2xLcl; + RadioClk3x <= RadioClk3xLcl; + + + +end rtl; |