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>


Original-commit: bafa9d95453387814ef25e6b6256ba8db2df612f
This commit is contained in:
Martin Braun
2020-01-28 09:35:36 -08:00
co-authored by Alex Williams Andrej Rode Ashish Chaudhari Ben Hilburn Ciro Nishiguchi Daniel Jepson Derek Kozel EJ Kreinar Humberto Jimenez Ian Buckley Jörg Hofrichter Jon Kiser Josh Blum Jonathon Pendlum Matt Ettus Michael West Moritz Fischer Nick Foster Nicolas Cuervo Paul Butler Paul David Ryan Marlow Sugandha Gupta Sylvain Munaut Trung Tran Vidush Vishwanath Wade Fife
parent 74893643ca
commit 6b67702ad7
2157 changed files with 1282567 additions and 0 deletions
+345
View File
@@ -0,0 +1,345 @@
-------------------------------------------------------------------------------
--
-- File: ClockingRegs.vhd
-- Author: Daniel Jepson; mods by Humberto Jimenez
-- Original Project: N310; N32x
-- 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
@@ -0,0 +1,116 @@
-------------------------------------------------------------------------------
--
-- File: DaughterboardRegs.vhd
-- Author: Daniel Jepson; mods by Humberto Jimenez
-- Original Project: N310; N32x
-- 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
+563
View File
@@ -0,0 +1,563 @@
-------------------------------------------------------------------------------
--
-- File: DbCore.vhd
-- Author: Daniel Jepson; mods by Humberto Jimenez
-- Original Project: N310; N320
-- 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.PkgRhPersonality.all;
use work.PkgRegs.all;
use work.PkgJesdConfig.all;
use work.PkgAdcDacInterfaceTypes.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 two samples 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.
-- Supporting 2 samples per clk cycle.
sAdcDataValid : out std_logic;
sAdcDataSample0I : out std_logic_vector(15 downto 0);
sAdcDataSample0Q : out std_logic_vector(15 downto 0);
sAdcDataSample1I : out std_logic_vector(15 downto 0);
sAdcDataSample1Q : out std_logic_vector(15 downto 0);
--
sDacReadyForInput : out std_logic;
sDacDataSample0I : in std_logic_vector(15 downto 0);
sDacDataSample0Q : in std_logic_vector(15 downto 0);
sDacDataSample1I : in std_logic_vector(15 downto 0);
sDacDataSample1Q : 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;
JesdRefClk_p : in STD_LOGIC;
JesdRefClk_n : in STD_LOGIC;
bJesdRefClkPresent : out STD_LOGIC;
aLmkSync : out STD_LOGIC;
bRegPortInFlat : in STD_LOGIC_VECTOR(49 downto 0);
bRegPortOutFlat : out STD_LOGIC_VECTOR(33 downto 0);
CaptureSysRefClk : in STD_LOGIC;
cSysRefFpgaLvds_p : in STD_LOGIC;
cSysRefFpgaLvds_n : in STD_LOGIC;
fSysRef : 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;
fAdcDataFlatter : out STD_LOGIC_VECTOR(63 downto 0);
fDacDataFlatter : in STD_LOGIC_VECTOR(63 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 sAdcDataFlatter: STD_LOGIC_VECTOR(63 downto 0);
signal SampleClk1xOutLcl: std_logic;
signal sDacDataFlatter: STD_LOGIC_VECTOR(63 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 sAdcDataAry : AdcDataAry_t;
signal sDacDataAry : DacDataAry_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
JesdRefClk_p => JesdRefClk_p, --in STD_LOGIC
JesdRefClk_n => JesdRefClk_n, --in STD_LOGIC
bJesdRefClkPresent => bJesdRefClkPresent, --out STD_LOGIC
aLmkSync => aLmkSync, --out STD_LOGIC
bRegPortInFlat => bJesdCoreRegPortInFlat, --in STD_LOGIC_VECTOR(49:0)
bRegPortOutFlat => bJesdCoreRegPortOutFlat, --out STD_LOGIC_VECTOR(33:0)
CaptureSysRefClk => SampleClk1xOutLcl, --in STD_LOGIC
cSysRefFpgaLvds_p => sSysRefFpgaLvds_p, --in STD_LOGIC
cSysRefFpgaLvds_n => sSysRefFpgaLvds_n, --in STD_LOGIC
fSysRef => sSysRefAsyncReset, --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
fAdcDataFlatter => sAdcDataFlatter, --out STD_LOGIC_VECTOR(63:0)
fDacDataFlatter => sDacDataFlatter, --in STD_LOGIC_VECTOR(63: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.
sAdcDataAry <= Unflatten(sAdcDataFlatter);
sDacDataFlatter <= Flatten(sDacDataAry);
-- Data mapping using the array types.
sAdcDataSample0I <= (sAdcDataAry(0).Data.I & sAdcDataAry(0).Over.I & sAdcDataAry(0).CBit1.I);
sAdcDataSample0Q <= (sAdcDataAry(0).Data.Q & sAdcDataAry(0).Over.Q & sAdcDataAry(0).CBit1.Q);
sAdcDataSample1I <= (sAdcDataAry(1).Data.I & sAdcDataAry(1).Over.I & sAdcDataAry(1).CBit1.I);
sAdcDataSample1Q <= (sAdcDataAry(1).Data.Q & sAdcDataAry(1).Over.Q & sAdcDataAry(1).CBit1.Q);
--
sDacDataAry(0).Data.I <= sDacDataSample0I;
sDacDataAry(0).Data.Q <= sDacDataSample0Q;
sDacDataAry(1).Data.I <= sDacDataSample1I;
sDacDataAry(1).Data.Q <= sDacDataSample1Q;
-- 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(kDbId,kDbIdSize))
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(kDbId,kDbIdSize)), --in std_logic_vector(15:0)
kSlotId => kSlotId); --in std_logic
end RTL;
Binary file not shown.
@@ -0,0 +1,54 @@
-- Copyright 1986-2017 Xilinx, Inc. All Rights Reserved.
-- --------------------------------------------------------------------------------
-- Tool Version: Vivado v.2017.4 (win64) Build 2086221 Fri Dec 15 20:55:39 MST 2017
-- Date : Fri Nov 9 16:19:51 2018
-- Host : hjimenez 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;
JesdRefClk_p : in STD_LOGIC;
JesdRefClk_n : in STD_LOGIC;
bJesdRefClkPresent : out STD_LOGIC;
aLmkSync : out STD_LOGIC;
bRegPortInFlat : in STD_LOGIC_VECTOR ( 49 downto 0 );
bRegPortOutFlat : out STD_LOGIC_VECTOR ( 33 downto 0 );
CaptureSysRefClk : in STD_LOGIC;
cSysRefFpgaLvds_p : in STD_LOGIC;
cSysRefFpgaLvds_n : in STD_LOGIC;
fSysRef : 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;
fAdcDataFlatter : out STD_LOGIC_VECTOR ( 63 downto 0 );
fDacDataFlatter : in STD_LOGIC_VECTOR ( 63 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,JesdRefClk_p,JesdRefClk_n,bJesdRefClkPresent,aLmkSync,bRegPortInFlat[49:0],bRegPortOutFlat[33:0],CaptureSysRefClk,cSysRefFpgaLvds_p,cSysRefFpgaLvds_n,fSysRef,aAdcRx_p[3:0],aAdcRx_n[3:0],aSyncAdcOut_n,aDacTx_p[3:0],aDacTx_n[3:0],aSyncDacIn_n,fAdcDataFlatter[63:0],fDacDataFlatter[63:0],fAdcDataValid,fDacReadyForInput,aDacSync,aAdcSync";
begin
end;
@@ -0,0 +1,302 @@
-------------------------------------------------------------------------------
--
-- File: PkgAdcDacInterfaceTypes.vhd
-- Author: National Instruments
-- Original Project: USRP N32x
-- Date: 15 Dec 2017
--
-------------------------------------------------------------------------------
-- (c) 2018 Copyright National Instruments Corporation
-- All Rights Reserved
-- National Instruments Internal Information
-------------------------------------------------------------------------------
--
-- Purpose: Contains types for ADC and DAC data so they can more easily be
-- passed through the design.
--
-- vreview_group JesdCoreN32x
-- vreview_reviewers djepson wfife
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.PkgJesdConfig.all;
package PkgAdcDacInterfaceTypes is
-- Data type for the DACs.
type DacData_t is record
I : std_logic_vector(kDacDataWidth - 1 downto 0);
Q : std_logic_vector(kDacDataWidth - 1 downto 0);
end record;
-- Data type for the ADCs.
type AdcData_t is record
I : std_logic_vector(kAdcDataWidth - 1 downto 0);
Q : std_logic_vector(kAdcDataWidth - 1 downto 0);
end record;
-- Type has two bits that correspond to I and Q; example usage: overrange flags.
type IQFlags_t is record
I : std_logic;
Q : std_logic;
end record;
-- Single data type for all information from the ADCs.
type AdcSamples_t is record
Data : AdcData_t;
Over : IQFlags_t;
CBit1 : IQFlags_t;
end record;
-- Single data type for all information to the DACs.
type DacSamples_t is record
Data : DacData_t;
end record;
-- To support multiple data values per clock cycle, these types
-- are arrays of the ADC and DAC data types where the size of the array
-- corresponds to the number of samples per cycle.
type AdcDataAry_t is array (kSamplesPerCycle - 1 downto 0) of AdcSamples_t;
type DacDataAry_t is array (kSamplesPerCycle - 1 downto 0) of DacSamples_t;
-- Zero/default constant
constant kAdcDataAryZero : AdcDataAry_t :=
(others => (Data => (others => (others => '0')),
Over => (others => '0'),
CBit1 => (others => '0'))
);
-- Zero/default constant
constant kDacDataAryZero : DacDataAry_t :=
(others => (Data => (others => (others => '0')))
);
-- Flattened type that converts the ADC data into std_logic_vector types. This type is
-- not suitable for use in the port maps of components that are presynthesized (into EDF
-- or NGC files) but is useful for passing data to the top level.
type AdcDataAryFlat_t is record
DataI : std_logic_vector(kSamplesPerCycle*kAdcDataWidth - 1 downto 0);
DataQ : std_logic_vector(kSamplesPerCycle*kAdcDataWidth - 1 downto 0);
OverI : std_logic_vector(kSamplesPerCycle - 1 downto 0);
OverQ : std_logic_vector(kSamplesPerCycle - 1 downto 0);
CBit1I : std_logic_vector(kSamplesPerCycle - 1 downto 0);
CBit1Q : std_logic_vector(kSamplesPerCycle - 1 downto 0);
end record;
-- Fully flattened ADC data for passing into and out of presynthesized components.
subtype AdcDataAryFlatter_t is std_logic_vector(2*(kSamplesPerCycle*(kAdcDataWidth + 2)) - 1 downto 0);
-- Flattened type that converts the DAC data into std_logic_vector types. This type is
-- not suitable for use in the port maps of components that are presynthesized (into EDF
-- or NGC files) but is useful for passing data from the top level.
type DacDataAryFlat_t is record
DataI : std_logic_vector(kSamplesPerCycle*kDacDataWidth - 1 downto 0);
DataQ : std_logic_vector(kSamplesPerCycle*kDacDataWidth - 1 downto 0);
end record;
-- Fully flattened DAC data for passing into and out of presynthesized components.
subtype DacDataAryFlatter_t is std_logic_vector(2*(kSamplesPerCycle*kDacDataWidth) - 1 downto 0);
-- Function to convert types defined above for the ADC data
function Flatten (AdcData : AdcDataAry_t) return AdcDataAryFlat_t;
function Flatten (AdcData : AdcDataAryFlat_t) return AdcDataAryFlatter_t;
function Flatten (AdcData : AdcDataAry_t) return AdcDataAryFlatter_t;
function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAryFlat_t;
function Unflatten(AdcData : AdcDataAryFlat_t) return AdcDataAry_t;
function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAry_t;
-- Function to convert types defined above for the DAC data
function Flatten (DacData : DacDataAry_t) return DacDataAryFlat_t;
function Flatten (DacData : DacDataAryFlat_t) return DacDataAryFlatter_t;
function Flatten (DacData : DacDataAry_t) return DacDataAryFlatter_t;
function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAryFlat_t;
function UnFlatten(DacData : DacDataAryFlat_t) return DacDataAry_t;
function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAry_t;
end package PkgAdcDacInterfaceTypes;
package body PkgAdcDacInterfaceTypes is
-- Flattens AdcDataAry_t to AdcDataAryFlat_t
function Flatten(AdcData : AdcDataAry_t) return AdcDataAryFlat_t
is
variable ReturnVar : AdcDataAryFlat_t;
begin
ReturnVar := (DataI => (others => '0'), -- Note (others => (others => '0')) does not work here
DataQ => (others => '0'), -- since DataX and OverX/CBit1X are of different lengths (ModelSim error)
OverI => (others => '0'),
OverQ => (others => '0'),
CBit1I => (others => '0'),
CBit1Q => (others => '0'));
-- The upstream logic puts the 0th element of an array in the MSBs of its data word
for i in 0 to kSamplesPerCycle - 1 loop
ReturnVar.DataI((kSamplesPerCycle - i)*kAdcDataWidth - 1 downto (kSamplesPerCycle - 1 - i)*kAdcDataWidth) := AdcData(i).Data.I; -- Input Data 0 to MSB
ReturnVar.DataQ((kSamplesPerCycle - i)*kAdcDataWidth - 1 downto (kSamplesPerCycle - 1 - i)*kAdcDataWidth) := AdcData(i).Data.Q;
ReturnVar.OverI (kSamplesPerCycle - 1 - i) := AdcData(i).Over.I; -- Input Data 0 to MSB
ReturnVar.OverQ (kSamplesPerCycle - 1 - i) := AdcData(i).Over.Q;
ReturnVar.CBit1I(kSamplesPerCycle - 1 - i) := AdcData(i).CBit1.I;
ReturnVar.CBit1Q(kSamplesPerCycle - 1 - i) := AdcData(i).CBit1.Q;
end loop;
return ReturnVar;
end function Flatten;
-- UnFlattens AdcDataAryFlat_t to AdcDataAry_t
function Unflatten(AdcData : AdcDataAryFlat_t) return AdcDataAry_t
is
variable ReturnVar : AdcDataAry_t;
begin
ReturnVar := (others => (Data => (others => (others => '0')), Over => (others => '0'), CBit1 => (others => '0')));
for i in 0 to kSamplesPerCycle - 1 loop
-- MSB of flattened word = 0th element of ADC data array - this corresponds to how TheWindow
-- expects data arrays to be transferred.
ReturnVar(kSamplesPerCycle - 1 - i).Data.I := AdcData.DataI((i+1)*kAdcDataWidth - 1 downto i*kAdcDataWidth);
ReturnVar(kSamplesPerCycle - 1 - i).Data.Q := AdcData.DataQ((i+1)*kAdcDataWidth - 1 downto i*kAdcDataWidth);
ReturnVar(kSamplesPerCycle - 1 - i).Over.I := AdcData.OverI(i);
ReturnVar(kSamplesPerCycle - 1 - i).Over.Q := AdcData.OverQ(i);
ReturnVar(kSamplesPerCycle - 1 - i).CBit1.I := AdcData.CBit1I(i);
ReturnVar(kSamplesPerCycle - 1 - i).CBit1.Q := AdcData.CBit1Q(i);
end loop;
return ReturnVar;
end function Unflatten;
-- Flattens AdcDataAryFlat_t to AdcDataAryFlatter_t
function Flatten(AdcData : AdcDataAryFlat_t) return AdcDataAryFlatter_t
is
variable ReturnVar : AdcDataAryFlatter_t;
begin
ReturnVar := AdcData.OverQ & AdcData.CBit1Q & AdcData.OverI & AdcData.CBit1I & AdcData.DataQ & AdcData.DataI;
return ReturnVar;
end function Flatten;
-- UnFlattens AdcDataAryFlatter_t to AdcDataAryFlat_t
function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAryFlat_t
is
variable ReturnVar : AdcDataAryFlat_t;
begin
ReturnVar.DataI := AdcData(1*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle - 1 downto 0*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle);
ReturnVar.DataQ := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle - 1 downto 1*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle);
ReturnVar.CBit1I := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 1*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle);
ReturnVar.OverI := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 2*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 1*kSamplesPerCycle);
ReturnVar.CBit1Q := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 3*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 2*kSamplesPerCycle);
ReturnVar.OverQ := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 4*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 3*kSamplesPerCycle);
return ReturnVar;
end function Unflatten;
-- Flattens AdcDataAry_t to AdcDataAryFlatter_t
function Flatten(AdcData : AdcDataAry_t) return AdcDataAryFlatter_t
is
variable TempVar : AdcDataAryFlat_t;
variable ReturnVar : AdcDataAryFlatter_t;
begin
TempVar := Flatten(AdcData);
ReturnVar := Flatten(TempVar);
return ReturnVar;
end function Flatten;
-- UnFlattens AdcDataAryFlatter_t to AdcDataAry_t
function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAry_t
is
variable TempVar : AdcDataAryFlat_t;
variable ReturnVar : AdcDataAry_t;
begin
TempVar := Unflatten(AdcData);
ReturnVar := Unflatten(TempVar);
return ReturnVar;
end function Unflatten;
-- Flattens DacDataAry_t to DacDataAryFlat_t
function Flatten(DacData : DacDataAry_t) return DacDataAryFlat_t
is
variable ReturnVar : DacDataAryFlat_t;
begin
ReturnVar := (others => (others => '0'));
for i in 0 to kSamplesPerCycle - 1 loop
-- MSB of flattened word = 0th element of ADC data array - this corresponds to how TheWindow
-- expects data arrays to be transferred.
ReturnVar.DataI((i+1)*kDacDataWidth - 1 downto i*kDacDataWidth) := DacData(kSamplesPerCycle - 1 - i).Data.I;
ReturnVar.DataQ((i+1)*kDacDataWidth - 1 downto i*kDacDataWidth) := DacData(kSamplesPerCycle - 1 - i).Data.Q;
end loop;
return ReturnVar;
end function Flatten;
-- UnFlattens DacDataAryFlat_t to DacDataAry_t
function UnFlatten(DacData : DacDataAryFlat_t) return DacDataAry_t
is
variable ReturnVar : DacDataAry_t;
begin
ReturnVar := (others => (Data => (others => (others => '0'))));
-- The upstream logic puts the 0th element of an array in the MSBs of its data word
for i in 0 to kSamplesPerCycle - 1 loop
ReturnVar(kSamplesPerCycle - 1 - i).Data.I := DacData.DataI(kDacDataWidth*(i+1) - 1 downto kDacDataWidth*i);
ReturnVar(kSamplesPerCycle - 1 - i).Data.Q := DacData.DataQ(kDacDataWidth*(i+1) - 1 downto kDacDataWidth*i);
end loop;
return ReturnVar;
end function UnFlatten;
-- Flattens DacDataAryFlat_t to DacDataAryFlatter_t
function Flatten(DacData : DacDataAryFlat_t) return DacDataAryFlatter_t
is
variable ReturnVar : DacDataAryFlatter_t;
begin
ReturnVar := DacData.DataQ & DacData.DataI;
return ReturnVar;
end function Flatten;
-- UnFlattens DacDataAryFlatter_t to DacDataAryFlat_t
function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAryFlat_t
is
variable ReturnVar : DacDataAryFlat_t;
begin
ReturnVar.DataI := DacData(1*kSamplesPerCycle*kDacDataWidth - 1 downto 0*kSamplesPerCycle*kDacDataWidth);
ReturnVar.DataQ := DacData(2*kSamplesPerCycle*kDacDataWidth - 1 downto 1*kSamplesPerCycle*kDacDataWidth);
return ReturnVar;
end function Unflatten;
-- Flattens DacDataAry_t to DacDataAryFlatter_t
function Flatten(DacData : DacDataAry_t) return DacDataAryFlatter_t
is
variable TempVar : DacDataAryFlat_t;
variable ReturnVar : DacDataAryFlatter_t;
begin
TempVar := Flatten(DacData);
ReturnVar := Flatten(TempVar);
return ReturnVar;
end function Flatten;
-- UnFlattens DacDataAryFlatter_t to DacDataAry_t
function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAry_t
is
variable TempVar : DacDataAryFlat_t;
variable ReturnVar : DacDataAry_t;
begin
TempVar := Unflatten(DacData);
ReturnVar := Unflatten(TempVar);
return ReturnVar;
end function Unflatten;
end package body;
@@ -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;
@@ -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;
@@ -0,0 +1,165 @@
-------------------------------------------------------------------------------
--
-- File: PkgJesdConfig.vhd
-- Author: National Instruments
-- Original Project: N32x
-- Date: 15 Dec 2017
--
-------------------------------------------------------------------------------
-- 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.
--
-- vreview_group JesdCoreN32x
-- vreview_reviewers djepson wfife
-------------------------------------------------------------------------------
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 N32x, all lanes are in one quad and we use the QPLL.
constant kJesdUseQpll : boolean := true;
constant kAdcDataWidth : integer := 14; -- ADC data width in bits
constant kDacDataWidth : integer := 16; -- DAC data width in bits
constant kSamplesPerCycle : integer := 2; -- Number of samples per SampleClk1x
constant kGtxDrpAddrWidth : natural := 9;
constant kGtxAddrLsbPosition : natural := 2;
constant kQpllDrpAddrWidth : natural := 8;
constant kGtxDrpDataWidth : natural := 16;
-- 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;
-- Rhodium:
-- JESD shared setup - LMFS = 4211, HD = 1 (Samples are split across multiple lanes).
constant kNumLanes : natural := 4; -- L
constant kNumConvs : positive := 2; -- M
constant kOctetsPerFrame : natural := 1; -- 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 := true; -- HD
constant kConvResBits : positive := kDacDataWidth; -- Converter resolution in bits
constant kConvSampleBits : positive := 16; -- Sample Length in bits
constant kInitLaneAlignCnt : positive := 4;
constant kFramesPerMulti : natural := 24; -- K
-- Rhodium:
-- The converters are running at 400/491.52/500 MSPS (DeviceClk), and the sampling
-- clock at the FPGA (UserClk) is 200/245.76/250 MHz; so UsrClk = (DeviceClk / 2).
-- The frame rate = DeviceClk, and the Multiframe rate = (frame rate / kFramesPerMulti)
-- Thus, kUserClksPerMulti = (UsrClk / Multiframe rate)
-- = (UsrClk / (DeviceClk / kFramesPerMulti))
-- since UsrClk = DeviceClk / 2 then,
-- kUserClksPerMulti = ((DeviceClk / 2) / (DeviceClk / kFramesPerMulti))
-- therefore,
-- kUserClksPerMulti = kFramesPerMulti / 2
constant kUserClksPerMulti : integer := kFramesPerMulti / 2;
type NaturalVector is array ( natural range <>) of natural;
-- The PCB connections are are passed trough, any swapping is handled somewhere else.
--
-- 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
);
-- User Rx Data
-- ADC Word data width: 14 sample bits + 2 tails bits
constant kAdcWordWidth : integer := 16;
subtype AdcWord_t is std_logic_vector(kAdcWordWidth - 1 downto 0);
type AdcWordArray_t is array(kSamplesPerCycle*2 - 1 downto 0) of AdcWord_t; -- The *2 is because there are two samples (I and Q) per "sample"
-- Constants to specify the contents of the AdcWord_t vector.
constant kAdcWordDataMsb : integer := 15;
constant kAdcWordDataLsb : integer := 2;
constant kAdcWordOver : integer := 1;
constant kAdcWordCBit1 : integer := 0;
-- Option to pipeline stages to improve timing, if needed
constant kPipelineDetectCharsStage : boolean := false;
constant kPipelineCharReplStage : boolean := false;
end package;
@@ -0,0 +1,62 @@
-------------------------------------------------------------------------------
--
-- File: PkgRhPersonality.vhd
-- Author: National Instruments
-- Original Project: N32x
-- Date: 15 Dec 2017
--
-------------------------------------------------------------------------------
-- Copyright 2017 Ettus Research, A National Instruments Company
-- SPDX-License-Identifier: GPL-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 PkgRhPersonality is
-- Rhodium daughterboard ID definition.
constant kDbId : integer := 16#152#;
constant kDbIdSize : integer := 16;
-- 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 PkgRhPersonality;
@@ -0,0 +1,305 @@
-------------------------------------------------------------------------------
--
-- 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 => 4.000, -- Feedback
CLKOUT0_DIVIDE_F => 4.000, -- Data Clock 1x, RadioClk1xPll
CLKOUT1_DIVIDE => 2, -- 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 => 4.069, -- 245.76 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;