Files
b210-k7-fpga/top/x400/rf/common/rf_nco_reset.vhd
T
adf6f576c6 mpm/fpga: x4xx: Major updates in preparation for future devices
FPGA:
- Split up MB registers that control daughterboard specific settings so
  that daughterboards 0 and 1 could have different setings, in
  preparation for future devices that require different settings.
  This requires a compat number bump to 8.0.
- Add registers for additional RFDC information, including the
  block/tile mapping of the individual channels, and information about
  resampling capabilities
- Identify sections of code that would be specific to X410/ZBX and move
  them to their own headers, so it's trivial to add device-specific
  sections of code instead for other devices in the future.
  - This includes constraints for clocks and I/O pins.
- Remove ability to do timed ctrlport transactions to the MB CPLD, this
  was unused and possibly broken.
- Move daughterboard-specific code into its own code location
  (dboards/zbx)
- Move X410-specific register documentation to its own location
  (doc/X410)
- Refactor Makefiles to split out X410/ZBX specific components and allow
  switching between device types
- Add 512-bit AXI interconnects
- Make number of timekeepers configurable (X410 keeps the single
  timekeeper)

MPM:
- Required compat is bumped to 8.0
- Now supports new registers for detecting DSP capabilities and
  multi-rate settings for the daughterboards
- Adds MMCM controls (currently unused)

Co-authored-by: Wade Fife <wade.fife@ni.com>
Co-authored-by: Ryan Marlow <ryan@lmarlow.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>


Original-commit: c1d268917ea65dd9c5a42366014cb96d3c025223
2023-05-23 09:06:17 +02:00

248 lines
9.3 KiB
VHDL

--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: rf_nco_reset
--
-- Description:
--
-- This entity has the logic needed to synchronously reset the NCO inside the
-- RF section.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity rf_nco_reset is
port(
-- AXI-lite clock used for RFDC configuration.
ConfigClk : in std_logic;
-- Radio clock used in the converter data path.
DataClk : in std_logic;
-- PL SYSREF
dSysref : in std_logic;
--Strobe dNcoResetEn for one DataClk cycle to initiate NCO reset.
dStartNcoReset : in std_logic;
---------------------------------------------------------------------------
-- NCO reset controls and status
---------------------------------------------------------------------------
-- Port naming convention:
-- cDac<Tile Number><Converter Number><signal name>
-- cAdc<Tile Number><Converter Number><signal name>
-----------------------------------
-- DAC Tile 228
-----------------------------------
-- DAC common NCO update controls and status.
cDac0xNcoUpdateBusy : in std_logic_vector(1 downto 0);
cDac0xNcoUpdateReq : out std_logic := '0';
cDac0xSysrefIntGating : out std_logic := '0';
cDac0xSysrefIntReenable : out std_logic := '0';
-----------------------------------
-- DAC Tile 229
-----------------------------------
-- DAC common NCO update controls and status.
cDac1xNcoUpdateBusy : in std_logic;
cDac1xNcoUpdateReq : out std_logic := '0';
-----------------------------------
--ADC Tile 224
-----------------------------------
-- ADC common NCO update controls and status.
cAdc0xNcoUpdateBusy : in std_logic;
cAdc0xNcoUpdateReq : out std_logic := '0';
-----------------------------------
--ADC Tile 225
-----------------------------------
-- ADC common NCO update controls and status.
cAdc1xNcoUpdateBusy : in std_logic;
cAdc1xNcoUpdateReq : out std_logic := '0';
-----------------------------------
--ADC Tile 226
-----------------------------------
-- ADC common NCO update controls and status.
cAdc2xNcoUpdateBusy : in std_logic;
cAdc2xNcoUpdateReq : out std_logic := '0';
-----------------------------------
--ADC Tile 227
-----------------------------------
-- ADC common NCO update controls and status.
cAdc3xNcoUpdateBusy : in std_logic;
cAdc3xNcoUpdateReq : out std_logic := '0';
-- NCO reset can be initiated only when cNcoPhaseRst is set to '1' and
-- cNcoUpdateEn = 0x20. The FSM in this entity will set these values when
-- an NCO reset is initiated during synchronization. These ports are common
-- for all the converters. So, we will fan these signals out to each
-- converter outside this entity.
cNcoPhaseRst : out std_logic := '1';
cNcoUpdateEn : out std_logic_vector(5 downto 0) := "100000";
-- NCO reset status back to the user.
dNcoResetDone : out std_logic := '0'
);
end rf_nco_reset;
architecture RTL of rf_nco_reset is
-- State machine to sequence NCO reset across different RFDC tiles.
type ResetState_t is (Idle, ReqGating, CheckGating, CheckUpdateDone,
CheckResetDone, ResetDone);
signal cResetState : ResetState_t := Idle;
signal dNcoResetDone_ms, cNcoResetDone : std_logic := '0';
signal dStartNcoResetReg, cStartNcoReset_ms, cStartNcoReset : std_logic := '0';
signal cSysref_ms, cSysref, cSysrefDlyd : std_logic := '0';
signal cSysrefIntGating, dSysrefIntGating_ms,
dSysrefIntGating : std_logic := '0';
begin
-- NCO start signal from the user is a one DataClk cycle strobe. In this
-- process, we register the NCO start request from the user. This NCO start
-- request register is cleared after the NCO reset sequence is initiated. We
-- used the signal used to gate SYSREF to clear this register.
RegNcoStart: process(DataClk)
begin
if rising_edge(DataClk) then
dSysrefIntGating_ms <= cSysrefIntGating;
dSysrefIntGating <= dSysrefIntGating_ms;
if dSysrefIntGating = '1' then
dStartNcoResetReg <= '0';
elsif dStartNcoReset = '1' then
dStartNcoResetReg <= '1';
end if;
end if;
end process RegNcoStart;
-- Irrespective of when NCO reset strobe is issued by the user, we need to
-- initiate NCO reset only on the rising edge of SYSREF. This is because, we
-- have to complete the reset within a SYSREF period.
ConfigClkCross: process(ConfigClk)
begin
if rising_edge(ConfigClk) then
cSysref_ms <= dSysref;
cSysref <= cSysref_ms;
cSysrefDlyd <= cSysref;
cStartNcoReset_ms <= dStartNcoResetReg;
cStartNcoReset <= cStartNcoReset_ms;
end if;
end process ConfigClkCross;
-- These signals can be set to a constant value as NCO phase reset is only
-- initiated by *NcoUpdateReq signal.
cNcoPhaseRst <= '1';
cNcoUpdateEn <= "100000";
-- ! STATE MACHINE STARTUP !
-- The state machine starts in Idle state and does not change state until
-- cStartNcoReset is set to '1'. cStartNcoReset signal and cSysref are based
-- of ConfigClock so changing state from Idle cannot go metastable. State
-- machine to initiate NCO reset on all enabled RFDC tiles. This state
-- machine was written based of the information provided in "NCO frequency
-- hopping" section in PG269 (v2.2). We use multi-mode for NCO reset.
ResetFsm: process(ConfigClk)
begin
if rising_edge(ConfigClk) then
cResetState <= Idle;
cNcoResetDone <= '0';
cDac0xNcoUpdateReq <= '0';
cSysrefIntGating <= '0';
cDac0xSysrefIntReenable <= '0';
cDac1xNcoUpdateReq <= '0';
cAdc0xNcoUpdateReq <= '0';
cAdc1xNcoUpdateReq <= '0';
cAdc2xNcoUpdateReq <= '0';
cAdc3xNcoUpdateReq <= '0';
case cResetState is
-- Stay in this state until NCO reset sequence is initiated. NCO reset
-- is initiated only on the rising edge of SYSREF.
when Idle =>
if cSysref = '1' and cSysrefDlyd = '0' and cStartNcoReset = '1' then
cResetState <= ReqGating;
cSysrefIntGating <= '1';
end if;
-- When NCO reset is initiated, gate the RFDC internal SYSREF. To gate
-- internal SYSREF set cSysrefIntGating to '1'. To request NCO reset
-- strobe cDac0xNcoUpdateReq for one ConfigClk period. At this point,
-- we can only request NCO reset for RF-DAC tile 228.
when ReqGating =>
cResetState <= CheckGating;
cDac0xNcoUpdateReq <= '1';
cSysrefIntGating <= '1';
-- Since we are gating SYSREF inside RFDC, we need to wait until SYSREF
-- is gated internally. RFDC sets cDac0xNcoUpdateBusy[0] to '1' when
-- SYSREF is gated. cDac0xNcoUpdateBusy[1] is also set to '1' to
-- indicate that NCO reset is still in progress. After the SYSREF is
-- gated request NCO reset on all other converter tiles.
when CheckGating =>
cSysrefIntGating <= '1';
cResetState <= CheckGating;
if cDac0xNcoUpdateBusy = "11" then
cResetState <= CheckUpdateDone;
cDac1xNcoUpdateReq <= '1';
cAdc0xNcoUpdateReq <= '1';
cAdc1xNcoUpdateReq <= '1';
cAdc2xNcoUpdateReq <= '1';
cAdc3xNcoUpdateReq <= '1';
end if;
-- In this state, we check if the RFDC block is ready for NCO reset.
-- This check is done using the *Busy signal from RFDC. Once RFDC is
-- ready for NCO reset, disable internal SYSREF gating.
when CheckUpdateDone =>
cSysrefIntGating <= '1';
cResetState <= CheckUpdateDone;
if cDac0xNcoUpdateBusy = "10" and cAdc0xNcoUpdateBusy = '0' and
cAdc1xNcoUpdateBusy = '0' and cAdc2xNcoUpdateBusy = '0' and
cAdc3xNcoUpdateBusy = '0' and cDac1xNcoUpdateBusy = '0' and
cSysref = '1' and cSysrefDlyd = '0' then
cDac0xSysrefIntReenable <= '1';
cResetState <= CheckResetDone;
end if;
-- NCO reset is done when cDac0xNcoUpdateBusy[1] is set to '0'. RFDC is
-- programmed from software to reset the NCO on a SYSREF rising edge.
when CheckResetDone =>
cSysrefIntGating <= '1';
cResetState <= CheckResetDone;
if cDac0xNcoUpdateBusy = "00" then
cResetState <= ResetDone;
end if;
-- Wait in this state until another NCO reset request is issued.
when ResetDone =>
cNcoResetDone <= '1';
cResetState <= ResetDone;
if cSysref = '1' and cSysrefDlyd = '0' and cStartNcoReset = '1' then
cResetState <= ReqGating;
cSysrefIntGating <= '1';
end if;
end case;
end if;
end process ResetFsm;
cDac0xSysrefIntGating <= cSysrefIntGating;
-- Move the NCO reset done status to DataClk domain.
DataClkCrossing: process(DataClk)
begin
if rising_edge(DataClk) then
dNcoResetDone_ms <= cNcoResetDone;
dNcoResetDone <= dNcoResetDone_ms;
end if;
end process DataClkCrossing;
end RTL;