diff --git a/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249Deserializer.vhd b/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249Deserializer.vhd index d0d9f3feec..d8b08f5f12 100644 --- a/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249Deserializer.vhd +++ b/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249Deserializer.vhd @@ -32,30 +32,30 @@ use surf.Ad9249Pkg.all; entity Ad9249Deserializer is generic ( - TPD_G : time := 1 ns; - SIM_DEVICE_G : string := "ULTRASCALE"; - IODELAY_GROUP_G : string := "DEFAULT_GROUP"; - IDELAY_CASCADE_G : boolean := false; - IDELAYCTRL_FREQ_G : real := 300.0; - DEFAULT_DELAY_G : slv(8 downto 0) := (others => '0'); - ADC_INVERT_CH_G : sl := '0'; - BIT_REV_G : sl := '0'); + TPD_G : time := 1 ns; + SIM_DEVICE_G : string := "ULTRASCALE"; + IODELAY_GROUP_G : string := "DEFAULT_GROUP"; + IDELAY_CASCADE_G : boolean := false; + IDELAYCTRL_FREQ_G : real := 300.0; + DEFAULT_DELAY_G : slv(8 downto 0) := (others => '0'); + ADC_INVERT_CH_G : sl := '0'; + BIT_REV_G : sl := '0'); port ( -- Serial Data from ADC - dClk : in sl; -- Data clock - dRst : in sl; -- Data reset + dClk : in sl; -- Data clock + dRst : in sl; -- Data reset dClkDiv4 : in sl; dRstDiv4 : in sl; - sDataP : in sl; -- Frame clock + sDataP : in sl; -- Frame clock sDataN : in sl; -- Signal to control data gearboxes loadDelay : in sl; delay : in slv(8 downto 0) := "000000000"; delayValueOut : out slv(8 downto 0); - bitSlip : in sl; -- dClkDiv4 domain - adcData : out slv(13 downto 0); -- dClkDiv4 domain - adcValid : out sl -- dClkDiv4 domain - ); + bitSlip : in sl; -- dClkDiv4 domain + adcData : out slv(13 downto 0); -- dClkDiv4 domain + adcValid : out sl -- dClkDiv4 domain + ); end Ad9249Deserializer; -- Define architecture @@ -70,21 +70,21 @@ architecture rtl of Ad9249Deserializer is -- Local signals - signal sDataPadP : sl; - signal sDataPadN : sl; - signal sData_i : sl; - signal sData_d : sl; + signal sDataPadP : sl; + signal sDataPadN : sl; + signal sData_i : sl; + signal sData_d : sl; -- idelay signals signal masterCntValue1 : slv(8 downto 0); signal masterCntValue2 : slv(8 downto 0); - signal cascOut : sl; - signal cascRet : sl; + signal cascOut : sl; + signal cascRet : sl; -- iserdes signal - signal masterData : slv(7 downto 0); - signal iAdcData : slv(13 downto 0); + signal masterData : slv(7 downto 0); + signal iAdcData : slv(13 downto 0); - attribute keep of sData_i : signal is "true"; + attribute keep of sData_i : signal is "true"; begin @@ -97,13 +97,13 @@ begin U_IBUFDS_sData : IBUFDS_DIFF_OUT generic map ( DQS_BIAS => "FALSE" -- (FALSE, TRUE) - ) + ) port map ( O => sDataPadP, -- 1-bit output: Buffer output OB => sDataPadN, I => sDataP, -- 1-bit input: Diff_p buffer input (connect directly to top-level port) IB => sDataN -- 1-bit input: Diff_n buffer input (connect directly to top-level port) - ); + ); -- Optionally invert the pad input sData_i <= sDataPadP when ADC_INVERT_CH_G = '0' else sDataPadN; ---------------------------------------------------------------------------- @@ -111,7 +111,7 @@ begin ---------------------------------------------------------------------------- U_IDELAYE3_0 : entity surf.Idelaye3Wrapper generic map ( - CASCADE => CASCADE_C, -- Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE) + CASCADE => CASCADE_C, -- Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE) DELAY_FORMAT => "COUNT", -- Units of the DELAY_VALUE (COUNT, TIME) DELAY_SRC => "IDATAIN", -- Delay input (DATAIN, IDATAIN) DELAY_TYPE => "VAR_LOAD", -- Set the type of tap delay line (FIXED, VARIABLE, VAR_LOAD) @@ -125,59 +125,60 @@ begin -- SYNC) ) port map ( - CASC_IN => '0', -- 1-bit input: Cascade delay input from slave ODELAY CASCADE_OUT - CASC_OUT => cascOut, -- 1-bit output: Cascade delay output to ODELAY input cascade + CASC_IN => '0', -- 1-bit input: Cascade delay input from slave ODELAY CASCADE_OUT + CASC_OUT => cascOut, -- 1-bit output: Cascade delay output to ODELAY input cascade CASC_RETURN => cascRet, -- 1-bit input: Cascade delay returning from slave ODELAY DATAOUT - CNTVALUEOUT => masterCntValue1, -- 9-bit output: Counter value output + CNTVALUEOUT => masterCntValue1, -- 9-bit output: Counter value output DATAOUT => sData_d, -- 1-bit output: Delayed data output - CE => '0', -- 1-bit input: Active high enable increment/decrement input + CE => '0', -- 1-bit input: Active high enable increment/decrement input CLK => dClkDiv4, -- 1-bit input: Clock input - CNTVALUEIN => delay, -- 9-bit input: Counter value input + CNTVALUEIN => delay, -- 9-bit input: Counter value input DATAIN => '1', -- 1-bit input: Data input from the logic - EN_VTC => '0', -- 1-bit input: Keep delay constant over VT + EN_VTC => '0', -- 1-bit input: Keep delay constant over VT IDATAIN => sData_i, -- 1-bit input: Data input from the IOBUF INC => '0', -- 1-bit input: Increment / Decrement tap delay input - LOAD => loadDelay, -- 1-bit input: Load DELAY_VALUE input - RST => dRstDiv4 -- 1-bit input: Asynchronous Reset to the DELAY_VALUE + LOAD => loadDelay, -- 1-bit input: Load DELAY_VALUE input + RST => dRstDiv4 -- 1-bit input: Asynchronous Reset to the DELAY_VALUE ); - G_IdelayCascade: if IDELAY_CASCADE_G = true generate - signal masterCntValue : slv(9 downto 0); + G_IdelayCascade : if IDELAY_CASCADE_G = true generate + signal masterCntValue : slv(9 downto 0); begin U_ODELAYE3_0 : entity surf.Odelaye3Wrapper generic map ( - CASCADE => "SLAVE_END", -- Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE) - DELAY_FORMAT => "COUNT", -- Units of the DELAY_VALUE (COUNT, TIME) - DELAY_TYPE => "VAR_LOAD", -- Set the type of tap delay line (FIXED, VARIABLE, VAR_LOAD) - DELAY_VALUE => conv_integer(DEFAULT_DELAY_G), -- Input delay value setting - IS_CLK_INVERTED => '0', -- Optional inversion for CLK - IS_RST_INVERTED => '0', -- Optional inversion for RST - REFCLK_FREQUENCY => IDELAYCTRL_FREQ_G, -- IDELAYCTRL clock input frequency in MHz (200.0-2400.0) - UPDATE_MODE => "ASYNC") -- Determines when updates to the delay will take effect (ASYNC, MANUAL, SYNC) + CASCADE => "SLAVE_END", -- Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE) + DELAY_FORMAT => "COUNT", -- Units of the DELAY_VALUE (COUNT, TIME) + DELAY_TYPE => "VAR_LOAD", -- Set the type of tap delay line (FIXED, VARIABLE, VAR_LOAD) + DELAY_VALUE => conv_integer(DEFAULT_DELAY_G), -- Input delay value setting + IS_CLK_INVERTED => '0', -- Optional inversion for CLK + IS_RST_INVERTED => '0', -- Optional inversion for RST + REFCLK_FREQUENCY => IDELAYCTRL_FREQ_G, -- IDELAYCTRL clock input frequency in MHz (200.0-2400.0) + SIM_DEVICE => SIM_DEVICE_G, + UPDATE_MODE => "ASYNC") -- Determines when updates to the delay will take effect (ASYNC, MANUAL, SYNC) port map ( - CASC_IN => cascOut, -- 1-bit input: Cascade delay input from slave IDELAY CASCADE_OUT - CASC_OUT => open, -- 1-bit output: Cascade delay output to IDELAY input cascade - CASC_RETURN => '0', -- 1-bit input: Cascade delay returning from slave IDELAY DATAOUT - ODATAIN => '0', -- 1-bit input: Data input - DATAOUT => cascRet, -- 1-bit output: Delayed data from ODATAIN input port - CLK => dClkDiv4, -- 1-bit input: Clock input - EN_VTC => '0', -- 1-bit input: Keep delay constant over VT - INC => '0', -- 1-bit input: Increment / Decrement tap delay input - CE => '0', -- 1-bit input: Active high enable increment/decrement input + CASC_IN => cascOut, -- 1-bit input: Cascade delay input from slave IDELAY CASCADE_OUT + CASC_OUT => open, -- 1-bit output: Cascade delay output to IDELAY input cascade + CASC_RETURN => '0', -- 1-bit input: Cascade delay returning from slave IDELAY DATAOUT + ODATAIN => '0', -- 1-bit input: Data input + DATAOUT => cascRet, -- 1-bit output: Delayed data from ODATAIN input port + CLK => dClkDiv4, -- 1-bit input: Clock input + EN_VTC => '0', -- 1-bit input: Keep delay constant over VT + INC => '0', -- 1-bit input: Increment / Decrement tap delay input + CE => '0', -- 1-bit input: Active high enable increment/decrement input LOAD => loadDelay, -- 1-bit input: Load DELAY_VALUE input - RST => dRstDiv4, -- 1-bit input: Asynchronous Reset to the DELAY_VALUE - CNTVALUEIN => delay, -- 9-bit input: Counter value input - CNTVALUEOUT => masterCntValue2); -- 9-bit output: Counter value output + RST => dRstDiv4, -- 1-bit input: Asynchronous Reset to the DELAY_VALUE + CNTVALUEIN => delay, -- 9-bit input: Counter value input + CNTVALUEOUT => masterCntValue2); -- 9-bit output: Counter value output masterCntValue <= resize(masterCntValue1, 10, '0') + masterCntValue2; - delayValueOut <= masterCntValue(9 downto 1); + delayValueOut <= masterCntValue(9 downto 1); end generate; - G_IdelayNoCascade: if IDELAY_CASCADE_G = false generate - delayValueOut <= masterCntValue1; - masterCntValue2 <= (others=>'0'); - cascRet <= '0'; + G_IdelayNoCascade : if IDELAY_CASCADE_G = false generate + delayValueOut <= masterCntValue1; + masterCntValue2 <= (others => '0'); + cascRet <= '0'; end generate; ---------------------------------------------------------------------------- @@ -192,42 +193,38 @@ begin IS_CLK_INVERTED => '0', -- Optional inversion for CLK IS_RST_INVERTED => '0', -- Optional inversion for RST SIM_DEVICE => SIM_DEVICE_G -- Set the device version (ULTRASCALE, ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1, - ) + ) port map ( FIFO_EMPTY => open, -- 1-bit output: FIFO empty flag INTERNAL_DIVCLK => open, -- 1-bit output: Internally divided down clock used when FIFO is - Q => masterData, -- bit registered output - CLK => dClk, -- 1-bit input: High-speed clock - CLKDIV => dClkDiv4, -- 1-bit input: Divided Clock - CLK_B => dClk, -- 1-bit input: Inversion of High-speed clock CLK - D => sData_d, -- 1-bit input: Serial Data Input - FIFO_RD_CLK => '1', -- 1-bit input: FIFO read clock - FIFO_RD_EN => '1', -- 1-bit input: Enables reading the FIFO when asserted - RST => dRstDiv4 -- 1-bit input: Asynchronous Reset - ); - - + Q => masterData, -- bit registered output + CLK => dClk, -- 1-bit input: High-speed clock + CLKDIV => dClkDiv4, -- 1-bit input: Divided Clock + CLK_B => dClk, -- 1-bit input: Inversion of High-speed clock CLK + D => sData_d, -- 1-bit input: Serial Data Input + FIFO_RD_CLK => '1', -- 1-bit input: FIFO read clock + FIFO_RD_EN => '1', -- 1-bit input: Enables reading the FIFO when asserted + RST => dRstDiv4 -- 1-bit input: Asynchronous Reset + ); U_Gearbox : entity surf.Gearbox generic map ( - TPD_G => TPD_G, - SLAVE_WIDTH_G => 8, - MASTER_WIDTH_G => 14 - ) + TPD_G => TPD_G, + SLAVE_WIDTH_G => 8, + MASTER_WIDTH_G => 14, + MASTER_BIT_REVERSE_G => toBoolean(BIT_REV_G) + ) port map ( clk => dClkDiv4, rst => dRstDiv4, - slip => bitSlip, -- bitslip by the Microblaze alignment code + slip => bitSlip, -- bitslip by the Microblaze alignment code -- Slave Interface slaveValid => '1', slaveData => masterData, -- Master Interface masterValid => adcValid, - masterData => iAdcData, - masterReady => '1' - ); - - adcData <= iAdcData when BIT_REV_G = '0' else bitReverse(iAdcData(6 downto 0)) & bitReverse(iAdcData(13 downto 7)); + masterData => adcData, + masterReady => '1'); end rtl; diff --git a/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup.vhd b/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup.vhd index 0b4c58c91c..e610af0cab 100644 --- a/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup.vhd +++ b/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup.vhd @@ -45,36 +45,36 @@ entity Ad9249ReadoutGroup is SIM_SPEEDUP_G : boolean := false); port ( -- Master system clock, 125Mhz - axilClk : in sl; - axilRst : in sl; + axilClk : in sl; + axilRst : in sl; -- Axi Interface - axilWriteMaster : in AxiLiteWriteMasterType; - axilWriteSlave : out AxiLiteWriteSlaveType; - axilReadMaster : in AxiLiteReadMasterType; - axilReadSlave : out AxiLiteReadSlaveType; + axilWriteMaster : in AxiLiteWriteMasterType; + axilWriteSlave : out AxiLiteWriteSlaveType; + axilReadMaster : in AxiLiteReadMasterType; + axilReadSlave : out AxiLiteReadSlaveType; -- Reset for adc deserializer (axilClk domain) - adcClkRst : in sl; + adcClkRst : in sl; -- clocks must be provided with USE_MMCME_G = false -- this option is necessary if there is many ADCs -- one external MMCM should be instantiated to be used with all Ad9249ReadoutGroups - adcBitClkIn : in sl; -- 350.0 MHz - adcBitClkDiv4In : in sl; -- 87.5 MHz - adcBitRstIn : in sl; - adcBitRstDiv4In : in sl; + adcBitClkIn : in sl; -- 350.0 MHz + adcBitClkDiv4In : in sl; -- 87.5 MHz + adcBitRstIn : in sl; + adcBitRstDiv4In : in sl; -- Serial Data from ADC - adcSerial : in Ad9249SerialGroupType; + adcSerial : in Ad9249SerialGroupType; -- Deserialized ADC Data - adcStreamClk : in sl; - adcStreams : out AxiStreamMasterArray(NUM_CHANNELS_G-1 downto 0) := - (others => axiStreamMasterInit((false, 2, 8, 0, TKEEP_NORMAL_C, 0, TUSER_NORMAL_C))); + adcStreamClk : in sl; + adcStreams : out AxiStreamMasterArray(NUM_CHANNELS_G-1 downto 0) := + (others => axiStreamMasterInit((false, 2, 8, 0, TKEEP_NORMAL_C, 0, TUSER_NORMAL_C))); -- optional ready to allow evenout samples readout in adcStreamClk - adcReady : in slv(NUM_CHANNELS_G-1 downto 0) := (others => '1') - ); + adcReady : in slv(NUM_CHANNELS_G-1 downto 0) := (others => '1') + ); end Ad9249ReadoutGroup; -- Define architecture @@ -111,7 +111,7 @@ architecture rtl of Ad9249ReadoutGroup is readoutDebug1 => (others => (others => '0')), lockedCountRst => '0', invert => '0' - ); + ); signal lockedSync : sl; signal lockedFallCount : slv(15 downto 0); @@ -123,24 +123,24 @@ architecture rtl of Ad9249ReadoutGroup is -- ADC Readout Clocked Registers ------------------------------------------------------------------------------------------------- type AdcRegType is record - slip : sl; - count : slv(5 downto 0); + slip : sl; + count : slv(5 downto 0); --loadDelay : sl; --delayValue : slv(8 downto 0); - locked : sl; - fifoWrData : Slv16Array(NUM_CHANNELS_G-1 downto 0); - fifoWrDataEn : slv(NUM_CHANNELS_G-1 downto 0); + locked : sl; + fifoWrData : Slv16Array(NUM_CHANNELS_G-1 downto 0); + fifoWrDataEn : slv(NUM_CHANNELS_G-1 downto 0); end record; constant ADC_REG_INIT_C : AdcRegType := ( - slip => '0', - count => (others => '0'), + slip => '0', + count => (others => '0'), --loadDelay => '0', --delayValue => (others => '0'), - locked => '0', - fifoWrData => (others => (others => '0')), - fifoWrDataEn => (others => '0') - ); + locked => '0', + fifoWrData => (others => (others => '0')), + fifoWrDataEn => (others => '0') + ); signal adcR : AdcRegType := ADC_REG_INIT_C; signal adcRin : AdcRegType; @@ -157,9 +157,9 @@ architecture rtl of Ad9249ReadoutGroup is signal adcBitRst : sl; signal adcClkRstSync : sl; - signal adcFrame : slv(13 downto 0); - signal adcFrameSync : slv(13 downto 0); - signal adcData : Slv14Array(NUM_CHANNELS_G-1 downto 0); + signal adcFrame : slv(13 downto 0); + signal adcFrameSync : slv(13 downto 0); + signal adcData : Slv14Array(NUM_CHANNELS_G-1 downto 0); signal curDelayFrame : slv(8 downto 0); signal curDelayData : slv9Array(NUM_CHANNELS_G-1 downto 0); @@ -173,7 +173,7 @@ architecture rtl of Ad9249ReadoutGroup is signal frameDelay : slv(8 downto 0); signal frameDelaySet : sl; - signal invertSync : sl; + signal invertSync : sl; begin ------------------------------------------------------------------------------------------------- @@ -198,7 +198,7 @@ begin rdClk => axilClk, rdRst => axilRst, cntRst => axilR.lockedCountRst - ); + ); Synchronizer_1 : entity surf.Synchronizer generic map ( @@ -240,9 +240,9 @@ begin begin v := axilR; - v.dataDelaySet := (others => '0'); - v.frameDelaySet := '0'; - v.lockedCountRst := '0'; + v.dataDelaySet := (others => '0'); + v.frameDelaySet := '0'; + v.lockedCountRst := '0'; -- Store last two samples read from ADC for i in 0 to NUM_CHANNELS_G-1 loop @@ -318,14 +318,14 @@ begin G_MMCM : if USE_MMCME_G = true generate AdcClk_I_Ibufds : IBUFDS - generic map ( - DQS_BIAS => "FALSE" - ) - port map ( - I => adcSerial.dClkP, - IB => adcSerial.dClkN, - O => adcDclk - ); + generic map ( + DQS_BIAS => "FALSE" + ) + port map ( + I => adcSerial.dClkP, + IB => adcSerial.dClkN, + O => adcDclk + ); ------------------------------------------ -- Generate clocks from ADC incoming clock @@ -335,22 +335,22 @@ begin -- clkOut(1) : 87.50 MHz adcBitClkDiv4 clock U_iserdesClockGen : entity surf.ClockManagerUltraScale generic map( - TPD_G => 1 ns, - TYPE_G => "MMCM", -- or "PLL" - INPUT_BUFG_G => true, - FB_BUFG_G => true, - RST_IN_POLARITY_G => '1', -- '0' for active low - NUM_CLOCKS_G => 2, + TPD_G => 1 ns, + TYPE_G => "MMCM", -- or "PLL" + INPUT_BUFG_G => true, + FB_BUFG_G => true, + RST_IN_POLARITY_G => '1', -- '0' for active low + NUM_CLOCKS_G => 2, -- MMCM attributes - BANDWIDTH_G => "OPTIMIZED", - CLKIN_PERIOD_G => 2.85, -- Input period in ns ); - DIVCLK_DIVIDE_G => 10, - CLKFBOUT_MULT_F_G => 20.0, - CLKFBOUT_MULT_G => 5, - CLKOUT0_DIVIDE_F_G => 1.0, - CLKOUT0_DIVIDE_G => 2, - CLKOUT1_DIVIDE_G => 8 - ) + BANDWIDTH_G => "OPTIMIZED", + CLKIN_PERIOD_G => 2.85, -- Input period in ns ); + DIVCLK_DIVIDE_G => 10, + CLKFBOUT_MULT_F_G => 20.0, + CLKFBOUT_MULT_G => 5, + CLKOUT0_DIVIDE_F_G => 1.0, + CLKOUT0_DIVIDE_G => 2, + CLKOUT1_DIVIDE_G => 8 + ) port map( clkIn => adcDclk, rstIn => '0', @@ -359,16 +359,16 @@ begin rstOut(0) => adcBitRst, rstOut(1) => adcBitRstDiv4, locked => open - ); + ); end generate G_MMCM; G_NO_MMCM : if USE_MMCME_G = false generate - adcBitClk <= adcBitClkIn; - adcBitClkDiv4 <= adcBitClkDiv4In; - adcBitRst <= adcBitRstIn; - adcBitRstDiv4 <= adcBitRstDiv4In; + adcBitClk <= adcBitClkIn; + adcBitClkDiv4 <= adcBitClkDiv4In; + adcBitRst <= adcBitRstIn; + adcBitRstDiv4 <= adcBitRstDiv4In; end generate G_NO_MMCM; @@ -386,7 +386,7 @@ begin ADC_INVERT_CH_G => '1', BIT_REV_G => '0') port map ( - dClk => adcBitClk, -- Data clock + dClk => adcBitClk, -- Data clock dRst => adcBitRst, dClkDiv4 => adcBitClkDiv4, dRstDiv4 => adcBitRstDiv4, @@ -398,7 +398,7 @@ begin bitSlip => adcR.slip, adcData => adcFrame, adcValid => adcFrameValid - ); + ); U_FrmDlyFifo : entity surf.SynchronizerFifo generic map ( @@ -436,7 +436,7 @@ begin ADC_INVERT_CH_G => ADC_INVERT_CH_G(i), BIT_REV_G => '1') port map ( - dClk => adcBitClk, -- Data clock + dClk => adcBitClk, -- Data clock dRst => adcBitRst, dClkDiv4 => adcBitClkDiv4, dRstDiv4 => adcBitRstDiv4, @@ -481,7 +481,7 @@ begin ---------------------------------------------------------------------------------------------- -- Slip bits until correct alignment seen ---------------------------------------------------------------------------------------------- - v.slip := '0'; + v.slip := '0'; if (adcR.count = 0) then if adcFrameValid = '1' then if (adcFrame = FRAME_PATTERN_C) then @@ -537,14 +537,14 @@ begin end process adcSeq; RstSync_1 : entity surf.RstSync - generic map ( - TPD_G => TPD_G - ) - port map ( - clk => adcBitClkDiv4, - asyncRst => adcClkRst, - syncRst => adcClkRstSync - ); + generic map ( + TPD_G => TPD_G + ) + port map ( + clk => adcBitClkDiv4, + asyncRst => adcClkRst, + syncRst => adcClkRstSync + ); -- synchronize data cross-clocks G_FIFO_SYNC : for i in NUM_CHANNELS_G-1 downto 0 generate @@ -552,9 +552,9 @@ begin U_DataFifo : entity surf.SynchronizerFifo generic map ( - TPD_G => TPD_G, - DATA_WIDTH_G => 16, - ADDR_WIDTH_G => 4) + TPD_G => TPD_G, + DATA_WIDTH_G => 16, + ADDR_WIDTH_G => 4) port map ( rst => adcBitRstDiv4, wr_clk => adcBitClkDiv4, @@ -564,7 +564,7 @@ begin rd_en => fifoDataRdEn(i), valid => fifoDataValid(i), dout => adcStreams(i).tdata(15 downto 0) - ); + ); fifoDataRdEn(i) <= adcReady(i) and fifoDataValid(i); adcStreams(i).tDest <= toSlv(i, 8); @@ -572,9 +572,9 @@ begin U_DataFifoDebug : entity surf.SynchronizerFifo generic map ( - TPD_G => TPD_G, - DATA_WIDTH_G => 16, - ADDR_WIDTH_G => 4) + TPD_G => TPD_G, + DATA_WIDTH_G => 16, + ADDR_WIDTH_G => 4) port map ( rst => adcBitRstDiv4, wr_clk => adcBitClkDiv4, @@ -584,7 +584,7 @@ begin rd_en => debugDataValid(i), valid => debugDataValid(i), dout => debugData(i) - ); + ); end generate; diff --git a/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup2.vhd b/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup2.vhd new file mode 100644 index 0000000000..4a86948b48 --- /dev/null +++ b/devices/AnalogDevices/ad9249/UltraScale/rtl/Ad9249ReadoutGroup2.vhd @@ -0,0 +1,582 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: +-- ADC Readout Controller +-- Receives ADC Data from an AD9592 chip. +-- Designed specifically for Xilinx 7 series FPGAs +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library UNISIM; +use UNISIM.vcomponents.all; + + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiLitePkg.all; +use surf.AxiStreamPkg.all; +use surf.Ad9249Pkg.all; + +entity Ad9249ReadoutGroup2 is + generic ( + TPD_G : time := 1 ns; + SIM_DEVICE_G : string := "ULTRASCALE"; + NUM_CHANNELS_G : natural := 8; + SIMULATION_G : boolean := false; + DEFAULT_DELAY_G : slv(8 downto 0) := "000000000"; + ADC_INVERT_CH_G : slv(7 downto 0) := "00000000"); + port ( + -- AXI-Lite clock + axilClk : in sl; + axilRst : in sl; + + -- Axi Interface + axilWriteMaster : in AxiLiteWriteMasterType; + axilWriteSlave : out AxiLiteWriteSlaveType := AXI_LITE_WRITE_SLAVE_EMPTY_DECERR_C; + axilReadMaster : in AxiLiteReadMasterType; + axilReadSlave : out AxiLiteReadSlaveType := AXI_LITE_READ_SLAVE_EMPTY_DECERR_C; + + -- Asynchronous reset for adc deserializer + adcClkRst : in sl; + + -- DDR Serial Data from ADC + adcSerial : in Ad9249SerialGroupType; + + -- Deserialized ADC Data + adcStreamClk : in sl; + adcStreams : out AxiStreamMasterArray(NUM_CHANNELS_G-1 downto 0) := (others => axiStreamMasterInit(AD9249_AXIS_CFG_G))); + +end Ad9249ReadoutGroup2; + +-- Define architecture +architecture rtl of Ad9249ReadoutGroup2 is + + + ------------------------------------------------------------------------------------------------- + -- AXIL Registers + ------------------------------------------------------------------------------------------------- + type AxilRegType is record + axilWriteSlave : AxiLiteWriteSlaveType; + axilReadSlave : AxiLiteReadSlaveType; + delay : slv(8 downto 0); + delaySet : sl; + freezeDebug : sl; + readoutDebug0 : slv16Array(7 downto 0); + readoutDebug1 : slv16Array(7 downto 0); + lockedCountRst : sl; + invert : sl; + realign : sl; + minEyeWidth : slv(7 downto 0); + end record; + + constant AXIL_REG_INIT_C : AxilRegType := ( + axilWriteSlave => AXI_LITE_WRITE_SLAVE_INIT_C, + axilReadSlave => AXI_LITE_READ_SLAVE_INIT_C, + delay => DEFAULT_DELAY_G, + delaySet => '0', + freezeDebug => '0', + readoutDebug0 => (others => (others => '0')), + readoutDebug1 => (others => (others => '0')), + lockedCountRst => '0', + invert => '0', + realign => '1', + minEyeWidth => X"50"); + + signal lockedSync : sl; + signal lockedFallCount : slv(15 downto 0); + + signal axilR : AxilRegType := AXIL_REG_INIT_C; + signal axilRin : AxilRegType; + + ------------------------------------------------------------------------------------------------- + -- ADC Readout Clocked Registers + ------------------------------------------------------------------------------------------------- + type AdcRegType is record + errorDet : sl; + end record; + + constant ADC_REG_INIT_C : AdcRegType := ( + errorDet => '1'); + + + signal adcR : AdcRegType := ADC_REG_INIT_C; + signal adcRin : AdcRegType; + + + -- Local Signals + signal adcBitClk : sl; + signal adcBitRst : sl; + signal adcBitClkDiv4 : sl; + signal adcBitRstDiv4 : sl; + + signal adcFrame : slv(13 downto 0); + signal adcFrameValid : sl; + signal adcFrameSync : slv(13 downto 0); + signal adcFrameSyncValid : sl; + signal adcData : slv14Array(NUM_CHANNELS_G-1 downto 0); + signal adcDataValid : slv(NUM_CHANNELS_G-1 downto 0); + + signal fifoWrData : slv16Array(NUM_CHANNELS_G-1 downto 0); + signal fifoDataValid : sl; + signal fifoDataOut : slv(NUM_CHANNELS_G*16-1 downto 0); + signal fifoDataIn : slv(NUM_CHANNELS_G*16-1 downto 0); + signal fifoDataTmp : slv16Array(NUM_CHANNELS_G-1 downto 0); + + signal debugDataValid : sl; + signal debugDataOut : slv(NUM_CHANNELS_G*16-1 downto 0); + signal debugDataTmp : slv16Array(7 downto 0); + + signal invertSync : sl; + signal bitSlip : sl; + signal dlyLoad : sl; + signal dlyCfg : slv(8 downto 0); + signal enUsrDlyCfg : sl; + signal usrDlyCfg : slv(8 downto 0) := (others => '0'); + signal minEyeWidthSync : slv(7 downto 0); + signal lockingCntCfg : slv(23 downto 0) := ite(SIMULATION_G, X"000008", X"00FFFF"); + signal locked : sl; + signal realignSync : sl; + signal curDelay : slv(8 downto 0); + signal errorDetCount : slv(15 downto 0); + signal errorDet : sl; + + +begin + ------------------------------------------------------------------------------------------------- + -- Synchronize adcR.locked across to axil clock domain and count falling edges on it + ------------------------------------------------------------------------------------------------- + Synchronizer_locked : entity surf.Synchronizer + generic map ( + TPD_G => TPD_G, + STAGES_G => 2) + port map ( + clk => axilClk, + rst => axilRst, + dataIn => locked, + dataOut => lockedSync); + + SynchronizerOneShotCnt_locked_fall : entity surf.SynchronizerOneShotCnt + generic map ( + TPD_G => TPD_G, + IN_POLARITY_G => '0', + OUT_POLARITY_G => '0', + CNT_RST_EDGE_G => true, + CNT_WIDTH_G => 16) + port map ( + dataIn => locked, + rollOverEn => '0', + cntRst => axilR.lockedCountRst, + dataOut => open, + cntOut => lockedFallCount, + wrClk => adcBitClkDiv4, + wrRst => '0', + rdClk => axilClk, + rdRst => axilRst); + + SynchronizerOneShotCnt_2 : entity surf.SynchronizerOneShotCnt + generic map ( + TPD_G => TPD_G, + IN_POLARITY_G => '1', + OUT_POLARITY_G => '1', + CNT_RST_EDGE_G => false, + CNT_WIDTH_G => 16) + port map ( + dataIn => errorDet, + rollOverEn => '0', + cntRst => axilR.lockedCountRst, + dataOut => open, + cntOut => errorDetCount, + wrClk => adcBitClkDiv4, + wrRst => '0', + rdClk => axilClk, + rdRst => axilRst); + + + SynchronizerVector_FRAME : entity surf.SynchronizerFifo + generic map ( + TPD_G => TPD_G, + MEMORY_TYPE_G => "distributed", + DATA_WIDTH_G => 14, + ADDR_WIDTH_G => 4) + port map ( + rst => axilRst, + wr_clk => adcBitClkDiv4, + wr_en => adcFrameValid, + din => adcFrame, + rd_clk => axilClk, + rd_en => adcFrameSyncValid, + valid => adcFrameSyncValid, + dout => adcFrameSync); + + U_SynchronizerVector_CUR_DELAY : entity surf.SynchronizerVector + generic map ( + TPD_G => TPD_G, + STAGES_G => 2, + WIDTH_G => 9) + port map ( + clk => axilClk, -- [in] + rst => axilRst, -- [in] + dataIn => dlyCfg, -- [in] + dataOut => curDelay); -- [out] + + + -- AXIL to ADC clock + Synchronizer_INVERT : entity surf.Synchronizer + generic map ( + TPD_G => TPD_G, + STAGES_G => 2) + port map ( + clk => adcBitClkDiv4, + dataIn => axilR.invert, + dataOut => invertSync); + + Synchronizer_REALIGN : entity surf.RstSync + generic map ( + TPD_G => TPD_G, + RELEASE_DELAY_G => 3) + port map ( + clk => adcBitClkDiv4, + asyncRst => axilR.realign, + syncRst => realignSync); + + Synchronizer_USR_DELAY_SET : entity surf.Synchronizer + generic map ( + TPD_G => TPD_G, + STAGES_G => 3) + port map ( + clk => adcBitClkDiv4, + rst => adcBitRstDiv4, + dataIn => axilR.delaySet, + dataOut => enUsrDlyCfg); + + U_SynchronizerVector_USR_DELAY : entity surf.SynchronizerVector + generic map ( + TPD_G => TPD_G, + STAGES_G => 2, + WIDTH_G => 9) + port map ( + clk => adcBitClkDiv4, -- [in] + rst => adcBitRstDiv4, -- [in] + dataIn => axilR.delay, -- [in] + dataOut => usrDlyCfg); -- [out] + + U_SynchronizerVector_EYE_WIDTH : entity surf.SynchronizerVector + generic map ( + TPD_G => TPD_G, + STAGES_G => 2, + WIDTH_G => 8) + port map ( + clk => adcBitClkDiv4, -- [in] + rst => adcBitRstDiv4, -- [in] + dataIn => axilR.minEyeWidth, -- [in] + dataOut => minEyeWidthSync); -- [out] + + + +------------------------------------------------------------------------------------------------- +-- AXIL Interface +------------------------------------------------------------------------------------------------- + axilComb : process (adcFrameSync, axilR, axilReadMaster, axilRst, axilWriteMaster, curDelay, + debugDataTmp, debugDataValid, errorDetCount, lockedFallCount, lockedSync) is + variable v : AxilRegType; + variable axilEp : AxiLiteEndpointType; + begin + v := axilR; + + v.delaySet := '0'; + + -- Store last two samples read from ADC + if (debugDataValid = '1' and axilR.freezeDebug = '0') then + v.readoutDebug0 := debugDataTmp; + v.readoutDebug1 := axilR.readoutDebug0; + end if; + + axiSlaveWaitTxn(axilEp, axilWriteMaster, axilReadMaster, v.axilWriteSlave, v.axilReadSlave); + + -- Write delay values to IDELAY primatives + -- Overriding gearbox aligner + -- All writes go to same r.delay register, + axiSlaveRegister(axilEp, X"00", 0, v.delay); + axiWrDetect(axilEp, X"00", v.delaySet); + axiSlaveRegisterR(axilEp, X"00", 0, curDelay); + + v.realign := '0'; + axiSlaveRegister(axilEp, X"20", 0, v.realign); + axiSlaveRegisterR(axilEp, X"30", 0, errorDetCount); + + -- Debug output to see how many times the shift has needed a relock + axiSlaveRegisterR(axilEp, X"50", 0, lockedFallCount); + axiSlaveRegisterR(axilEp, X"50", 16, lockedSync); + + axiSlaveRegisterR(axilEp, X"58", 0, adcFrameSync); + + axiSlaveRegister(axilEp, X"5C", 0, v.lockedCountRst); + + axiSlaveRegister(axilEp, X"60", 0, v.invert); + + -- Debug registers. Output the last 2 words received + for ch in 0 to 7 loop + axiSlaveRegisterR(axilEp, X"80"+toSlv((ch*4), 8), 0, axilR.readoutDebug0(ch)); + axiSlaveRegisterR(axilEp, X"80"+toSlv((ch*4), 8), 16, axilR.readoutDebug1(ch)); + end loop; + + axiSlaveRegister(axilEp, X"A0", 0, v.freezeDebug); + + axiSlaveDefault(axilEp, v.axilWriteSlave, v.axilReadSlave, AXI_RESP_DECERR_C); + + if (axilRst = '1') then + v := AXIL_REG_INIT_C; + end if; + + axilRin <= v; + axilWriteSlave <= axilR.axilWriteSlave; + axilReadSlave <= axilR.axilReadSlave; + + end process; + + axilSeq : process (axilClk) is + begin + if (rising_edge(axilClk)) then + axilR <= axilRin after TPD_G; + end if; + end process axilSeq; + + +------------------------------------------------------------------------------------------------- +-- Create Clocks +------------------------------------------------------------------------------------------------- + + AdcClk_I_Ibufds : IBUFGDS + port map ( + I => adcSerial.dClkP, + IB => adcSerial.dClkN, + O => adcBitClk); + + + ADC_BITCLK_RST_SYNC : entity surf.RstSync + generic map ( + TPD_G => TPD_G, + RELEASE_DELAY_G => 5) + port map ( + clk => adcBitClk, + asyncRst => adcClkRst, + syncRst => adcBitRst); + + + U_AdcBitClkRD4 : BUFGCE_DIV + generic map ( + BUFGCE_DIVIDE => 4, -- 1-8 + -- Programmable Inversion Attributes: Specifies built-in programmable inversion on specific pins + IS_CE_INVERTED => '0', -- Optional inversion for CE + IS_CLR_INVERTED => '0', -- Optional inversion for CLR + IS_I_INVERTED => '0') -- Optional inversion for I + port map ( + I => adcBitClk, + O => adcBitClkDiv4, + CE => '1', + CLR => '0'); + + + ADC_BITCLK_DIV4_RST_SYNC : entity surf.RstSync + generic map ( + TPD_G => TPD_G, + RELEASE_DELAY_G => 5) + port map ( + clk => adcBitClkDiv4, + asyncRst => adcClkRst, + syncRst => adcBitRstDiv4); + + +------------------------------------------------------------------------------------------------- +-- Deserializers +------------------------------------------------------------------------------------------------- + + U_FRAME_DESERIALIZER : entity surf.Ad9249Deserializer + generic map ( + TPD_G => TPD_G, + SIM_DEVICE_G => SIM_DEVICE_G, + DEFAULT_DELAY_G => DEFAULT_DELAY_G, + IDELAYCTRL_FREQ_G => 350.0, -- Check this + ADC_INVERT_CH_G => '0', + BIT_REV_G => '1') + port map ( + dClk => adcBitClk, + dRst => adcBitRst, + dClkDiv4 => adcBitClkDiv4, + dRstDiv4 => realignSync, + sDataP => adcSerial.fClkP, + sDataN => adcSerial.fClkN, + loadDelay => dlyLoad, + delay => dlyCfg, + bitSlip => bitSlip, + delayValueOut => open, + adcData => adcFrame, + adcValid => adcFrameValid); + + +-------------------------------- +-- Data Input, 8 channels +-------------------------------- + GenData : for ch in NUM_CHANNELS_G-1 downto 0 generate + U_DATA_DESERIALIZER : entity surf.Ad9249Deserializer + generic map ( + TPD_G => TPD_G, + SIM_DEVICE_G => SIM_DEVICE_G, + DEFAULT_DELAY_G => DEFAULT_DELAY_G, + IDELAYCTRL_FREQ_G => 350.0, -- Check this + ADC_INVERT_CH_G => ADC_INVERT_CH_G(ch), + BIT_REV_G => '1') -- Should maybe be '1' + port map ( + dClk => adcBitClk, + dRst => adcBitRst, + dClkDiv4 => adcBitClkDiv4, + dRstDiv4 => realignSync, + sDataP => adcSerial.chP(ch), + sDataN => adcSerial.chN(ch), + loadDelay => dlyLoad, + delay => dlyCfg, + bitSlip => bitSlip, + delayValueOut => open, + adcData => adcData(ch), + adcValid => adcDataValid(ch)); + end generate; + + + ---------------------------------------------------------------------------------------------- + -- Aligner + ---------------------------------------------------------------------------------------------- + U_SelectIoRxGearboxAligner_1 : entity surf.SelectIoRxGearboxAligner + generic map ( + TPD_G => TPD_G, + SIMULATION_G => SIMULATION_G, + CODE_TYPE_G => "LINE_CODE", + DLY_STEP_SIZE_G => ite(SIMULATION_G, 16, 1)) + port map ( + clk => adcBitClkDiv4, -- [in] + rst => adcBitRstDiv4, -- [in] + lineCodeValid => '1', -- [in] + lineCodeErr => adcR.errorDet, -- [in] + lineCodeDispErr => realignSync, -- [in] + linkOutOfSync => '0', -- [in] + rxHeaderValid => '0', -- [in] + rxHeader => (others => '0'), -- [in] + bitSlip => bitSlip, -- [out] + dlyLoad => dlyLoad, -- [out] + dlyCfg => dlyCfg, -- [out] + enUsrDlyCfg => enUsrDlyCfg, -- [in] + usrDlyCfg => usrDlyCfg, -- [in] + bypFirstBerDet => '1', -- [in] + minEyeWidth => minEyeWidthSync, -- [in] + lockingCntCfg => lockingCntCfg, -- [in] + errorDet => errorDet, -- [out] + locked => locked); -- [out] + + + ------------------------------------------------------------------------------------------------- + -- ADC Bit Clocked Logic + ------------------------------------------------------------------------------------------------- + adcComb : process (adcFrame, adcFrameValid, adcR) is + variable v : AdcRegType; + begin + v := adcR; + + if (adcFrameValid = '1') then + v.errorDet := toSl(adcFrame /= "11111110000000"); + end if; + + adcRin <= v; + + end process adcComb; + + adcSeq : process (adcBitClkDiv4, adcBitRstDiv4) is + begin + if (adcBitRstDiv4 = '1') then + adcR <= ADC_REG_INIT_C after TPD_G; + elsif (rising_edge(adcBitClkDiv4)) then + adcR <= adcRin after TPD_G; + end if; + end process adcSeq; + + + GLUE_COMB : process (adcData, invertSync, locked) is + begin + for ch in NUM_CHANNELS_G-1 downto 0 loop + if (locked = '1') then + -- Locked, output adc data + if invertSync = '1' then + -- Invert all bits but keep 2 LSBs clear + fifoWrData(ch) <= "00" & ("11111111111111" - adcData(ch)); + else + fifoWrData(ch) <= "00" & adcData(ch); + end if; + else + -- Not locked + fifoWrData(ch) <= (others => '1'); --"10" & "00000000000000"; + end if; + end loop; + end process GLUE_COMB; + + +-- Flatten fifoWrData onto fifoDataIn for FIFO +-- Regroup fifoDataOut by channel into fifoDataTmp +-- Format fifoDataTmp into AxiStream channels + glue : for i in NUM_CHANNELS_G-1 downto 0 generate + fifoDataIn(i*16+15 downto i*16) <= fifoWrData(i); + fifoDataTmp(i) <= fifoDataOut(i*16+15 downto i*16); + debugDataTmp(i) <= debugDataOut(i*16+15 downto i*16); + adcStreams(i).tdata(15 downto 0) <= fifoDataTmp(i); + adcStreams(i).tDest <= toSlv(i, 8); + adcStreams(i).tValid <= fifoDataValid; + end generate; + + -- Single fifo to synchronize adc data to the Stream clock + U_DataFifo : entity surf.SynchronizerFifo + generic map ( + TPD_G => TPD_G, + MEMORY_TYPE_G => "distributed", + DATA_WIDTH_G => NUM_CHANNELS_G*16, + ADDR_WIDTH_G => 4, + INIT_G => "0") + port map ( + rst => adcBitRstDiv4, + wr_clk => adcBitClkDiv4, + wr_en => adcFrameValid, --Always write data + din => fifoDataIn, + rd_clk => adcStreamClk, + rd_en => fifoDataValid, + valid => fifoDataValid, + dout => fifoDataOut); + + U_DataFifoDebug : entity surf.SynchronizerFifo + generic map ( + TPD_G => TPD_G, + MEMORY_TYPE_G => "distributed", + DATA_WIDTH_G => NUM_CHANNELS_G*16, + ADDR_WIDTH_G => 4, + INIT_G => "0") + port map ( + rst => adcBitRstDiv4, + wr_clk => adcBitClkDiv4, + wr_en => adcFrameValid, --Always write data + din => fifoDataIn, + rd_clk => axilClk, + rd_en => debugDataValid, + valid => debugDataValid, + dout => debugDataOut); + + +end rtl; + diff --git a/devices/AnalogDevices/ad9249/tb/Ad9249Group.vhd b/devices/AnalogDevices/ad9249/tb/Ad9249Group.vhd index 694c68637f..02db1c9676 100644 --- a/devices/AnalogDevices/ad9249/tb/Ad9249Group.vhd +++ b/devices/AnalogDevices/ad9249/tb/Ad9249Group.vhd @@ -32,8 +32,8 @@ entity Ad9249Group is CLK_PERIOD_G : time := 24 ns; DIVCLK_DIVIDE_G : integer := 1; CLKFBOUT_MULT_G : integer := 49; - CLK_DCO_DIVIDE_G : integer := 49; - CLK_FCO_DIVIDE_G : integer := 7); + CLK_DCO_DIVIDE_G : integer := 7; + CLK_FCO_DIVIDE_G : integer := 49); port ( clk : in sl; @@ -230,31 +230,32 @@ begin -- Use a clock manager to create the serial clock -- There's probably a better way but this works. ------------------------------------------------------------------------------------------------- - U_CtrlClockManager7 : entity surf.ClockManager7 - generic map ( - TPD_G => TPD_G, - TYPE_G => "MMCM", - INPUT_BUFG_G => false, - FB_BUFG_G => true, - NUM_CLOCKS_G => 4, - BANDWIDTH_G => "HIGH", - CLKIN_PERIOD_G => CLK_PERIOD_C, - DIVCLK_DIVIDE_G => DIVCLK_DIVIDE_G, - CLKFBOUT_MULT_G => CLKFBOUT_MULT_G, - CLKOUT0_DIVIDE_G => CLK_FCO_DIVIDE_G, - CLKOUT1_DIVIDE_G => CLK_DCO_DIVIDE_G, - CLKOUT2_DIVIDE_G => CLK_DCO_DIVIDE_G, - CLKOUT2_PHASE_G => 90.0, - CLKOUT3_DIVIDE_G => CLK_FCO_DIVIDE_G, - CLKOUT3_PHASE_G => 257.143) - port map ( - clkIn => clk, - rstIn => pllRst, - clkOut(0) => fClk, - clkOut(1) => dClk, - clkOut(2) => dco, - clkOut(3) => fco, - locked => locked); + U_CtrlClockManager7 : entity surf.ClockManager7 + generic map ( + TPD_G => TPD_G, + TYPE_G => "PLL", + INPUT_BUFG_G => false, + FB_BUFG_G => true, + NUM_CLOCKS_G => 4, + BANDWIDTH_G => "HIGH", + CLKIN_PERIOD_G => CLK_PERIOD_C, + DIVCLK_DIVIDE_G => DIVCLK_DIVIDE_G, + CLKFBOUT_MULT_G => CLKFBOUT_MULT_G, + CLKOUT0_DIVIDE_G => CLK_FCO_DIVIDE_G, + CLKOUT1_DIVIDE_G => CLK_DCO_DIVIDE_G, + CLKOUT2_DIVIDE_G => CLK_DCO_DIVIDE_G, + CLKOUT2_PHASE_G => 90.0, + CLKOUT3_DIVIDE_G => CLK_FCO_DIVIDE_G, + CLKOUT3_PHASE_G => 257.143) + port map ( + clkIn => clk, + rstIn => pllRst, + clkOut(0) => fClk, + clkOut(1) => dClk, + clkOut(2) => dco, + clkOut(3) => fco, + locked => locked); + RstSync_1 : entity surf.RstSync diff --git a/devices/AnalogDevices/ruckus.tcl b/devices/AnalogDevices/ruckus.tcl index 0d3997bbe6..0e92b6ce04 100644 --- a/devices/AnalogDevices/ruckus.tcl +++ b/devices/AnalogDevices/ruckus.tcl @@ -10,4 +10,8 @@ if { $::env(VIVADO_VERSION) > 0.0} { loadRuckusTcl "$::DIR_PATH/ad9467" loadRuckusTcl "$::DIR_PATH/ad9249" loadRuckusTcl "$::DIR_PATH/ad9681" -} \ No newline at end of file + + # AD9249 sim model requires ClockManager7 + loadSource -lib surf -path "$::DIR_PATH/../../xilinx/7Series/general/rtl/ClockManager7.vhd" + loadSource -lib surf -path "$::DIR_PATH/../../xilinx/7Series/general/rtl/ClockManager7Pkg.vhd" +} diff --git a/python/surf/devices/analog_devices/_Ad9249.py b/python/surf/devices/analog_devices/_Ad9249.py index f497266b13..a25c07934c 100644 --- a/python/surf/devices/analog_devices/_Ad9249.py +++ b/python/surf/devices/analog_devices/_Ad9249.py @@ -421,6 +421,158 @@ def readBlocks(self, *, recurse=True, variable=None, checkEach=False, index=-1, for key,value in self.devices.items(): value.readBlocks(recurse=True, checkEach=checkEach, **kwargs) + +class Ad9249ReadoutGroup2(pr.Device): + def __init__(self, + name = 'Ad9249Readout', + description = 'Configure readout of 1 bank of an AD9249', + fpga = '7series', + channels = 8, + **kwargs): + + assert (channels > 0 and channels <= 8), f'channels ({channels}) must be between 0 and 8' + super().__init__(name=name, description=description, **kwargs) + + if fpga == '7series': + delayBits = 6 + elif fpga == 'ultrascale': + delayBits = 9 + else: + delayBits = 6 + + + self.add(pr.RemoteVariable( + name = 'Delay', + description = 'IDELAY value', + offset = 0x00, + bitSize = delayBits, + bitOffset = 0, + base = pr.UInt, + mode = 'RW', + verify = False, + groups = 'NoConfig', + )) + + self.add(pr.RemoteCommand( + name='Relock', + hidden=False, + offset=0x20, + bitSize=1, + bitOffset=0, + base=pr.UInt, + function=pr.RemoteCommand.toggle)) + + self.add(pr.RemoteVariable( + name = 'ErrorDetCount', + description = 'Number of times that frame lock has been lost since reset', + offset = 0x30, + disp = '{:d}', + bitSize = 16, + bitOffset = 0, + base = pr.UInt, + mode = 'RO', + )) + + self.add(pr.RemoteVariable( + name = 'LostLockCount', + description = 'Number of times that frame lock has been lost since reset', + offset = 0x50, + bitSize = 16, + bitOffset = 0, + base = pr.UInt, + mode = 'RO', + )) + + self.add(pr.RemoteVariable( + name = 'Locked', + description = 'Readout has locked on to the frame boundary', + offset = 0x50, + bitSize = 1, + bitOffset = 16, + base = pr.Bool, + mode = 'RO', + )) + + self.add(pr.RemoteVariable( + name = 'AdcFrameSync', + description = 'Last deserialized FCO value for debug', + offset = 0x58, + bitSize = 14, + base = pr.UInt, + mode = 'RO', + )) + + self.add(pr.RemoteVariable( + name = 'Invert', + description = 'Optional ADC data inversion (offset binary only)', + offset = 0x60, + bitSize = 1, + bitOffset = 0, + base = pr.Bool, + mode = 'RW', + )) + + for i in range(channels): + self.add(pr.RemoteVariable( + name = f'AdcChannel[{i:d}]', + description = f'Last deserialized channel {i:d} ADC value for debug', + offset = 0x80 + (i*4), + bitSize = 32, + bitOffset = 0, + base = pr.UInt, + disp = '{:09_x}', + mode = 'RO', + )) + + for i in range(channels): + self.add(pr.LinkVariable( + name = f'AdcVoltage[{i}]', + mode = 'RO', + disp = '{:1.9f}', + variable = self.AdcChannel[i], + linkedGet = lambda read, check, r=self.AdcChannel[i]: 2*pr.twosComplement(r.get(read=read, check=check)>>18, 14)/2**14, + units = 'V')) + + self.add(pr.RemoteCommand( + name = 'LostLockCountReset', + description = 'Reset LostLockCount', + function = pr.BaseCommand.toggle, + offset = 0x5C, + bitSize = 1, + bitOffset = 0, + )) + + self.add(pr.RemoteCommand( + name='FreezeDebug', + description='Freeze all of the AdcChannel registers', + hidden=True, + offset=0xA0, + bitSize=1, + bitOffset=0, + base=pr.UInt, + function=pr.RemoteCommand.touch)) + + def readBlocks(self, *, recurse=True, variable=None, checkEach=False, index=-1, **kwargs): + """ + Perform background reads + """ + checkEach = checkEach or self.forceCheckEach + + if variable is not None: + pr.startTransaction(variable._block, type=rim.Read, checkEach=checkEach, variable=variable, index=index, **kwargs) + + else: + self.FreezeDebug(1) + for block in self._blocks: + if block.bulkOpEn: + pr.startTransaction(block, type=rim.Read, checkEach=checkEach, **kwargs) + self.FreezeDebug(0) + + if recurse: + for key,value in self.devices.items(): + value.readBlocks(recurse=True, checkEach=checkEach, **kwargs) + + class AdcTester(pr.Device): def __init__(self, **kwargs): """Create AdcTester"""