1 ------------------------------------------------------------------------------- 2 -- File : Ad9249ReadoutGroup.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2016-05-26 5 -- Last update: 2017-03-07 6 ------------------------------------------------------------------------------- 8 -- ADC Readout Controller 9 -- Receives ADC Data from an AD9592 chip. 10 -- Designed specifically for Xilinx 7 series FPGAs 11 ------------------------------------------------------------------------------- 12 -- This file is part of 'SLAC Firmware Standard Library'. 13 -- It is subject to the license terms in the LICENSE.txt file found in the 14 -- top-level directory of this distribution and at: 15 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 16 -- No part of 'SLAC Firmware Standard Library', including this file, 17 -- may be copied, modified, propagated, or distributed except according to 18 -- the terms contained in the LICENSE.txt file. 19 ------------------------------------------------------------------------------- 22 use ieee.std_logic_1164.
all;
23 use ieee.std_logic_arith.
all;
24 use ieee.std_logic_unsigned.
all;
27 use UNISIM.vcomponents.
all;
35 --! @ingroup devices_AnalogDevices_ad9249 45 -- Master system clock, 125Mhz 55 -- Reset for adc deserializer 58 -- Serial Data from ADC 61 -- Deserialized ADC Data 64 (others => axiStreamMasterInit((false, 2, 8, 0, TKEEP_NORMAL_C, 0, TUSER_NORMAL_C))));
65 end Ad9249ReadoutGroup;
67 -- Define architecture 70 ------------------------------------------------------------------------------------------------- 72 ------------------------------------------------------------------------------------------------- 73 type AxilRegType is record 76 delay : slv(4 downto 0);
84 constant AXIL_REG_INIT_C : AxilRegType := ( 88 dataDelaySet => (others => '1'), 90 readoutDebug0 => (others => (others => '0')), 91 readoutDebug1 => (others => (others => '0')), 92 lockedCountRst => '0');
94 signal lockedSync : sl;
95 signal lockedFallCount : slv(15 downto 0);
97 signal axilR : AxilRegType := AXIL_REG_INIT_C;
98 signal axilRin : AxilRegType;
100 ------------------------------------------------------------------------------------------------- 101 -- ADC Readout Clocked Registers 102 ------------------------------------------------------------------------------------------------- 103 type AdcRegType is record 105 count : slv(5 downto 0);
110 constant ADC_REG_INIT_C : AdcRegType := ( 112 count => (others => '0'), 114 fifoWrData => (others => (others => '0')));
116 signal adcR : AdcRegType := ADC_REG_INIT_C;
117 signal adcRin : AdcRegType;
121 signal tmpAdcClk : sl;
122 signal adcBitClkIo : sl;
123 signal adcBitClkIoInv : sl;
124 signal adcBitClkR : sl;
125 signal adcBitRst : sl;
127 signal adcFramePad : sl;
128 signal adcFrame : slv(13 downto 0);
129 signal adcFrameSync : slv(13 downto 0);
134 signal curDelayFrame : slv(4 downto 0);
137 signal fifoDataValid : sl;
142 signal debugDataValid : sl;
147 ------------------------------------------------------------------------------------------------- 148 -- Synchronize adcR.locked across to axil clock domain and count falling edges on it 149 ------------------------------------------------------------------------------------------------- 161 cntRst => axilR.lockedCountRst,
163 cntOut => lockedFallCount,
190 ------------------------------------------------------------------------------------------------- 192 ------------------------------------------------------------------------------------------------- 194 curDelayFrame, debugDataTmp, debugDataValid, lockedFallCount, lockedSync)
is 195 variable v : AxilRegType;
200 v.dataDelaySet := (others => '0');
201 v.frameDelaySet := '0';
204 -- Store last two samples read from ADC 205 if (debugDataValid = '1') then 206 v.readoutDebug0 := debugDataTmp;
207 v.readoutDebug1 := axilR.readoutDebug0;
212 -- Up to 8 delay registers 213 -- Write delay values to IDELAY primatives 214 -- All writes go to same r.delay register, 215 -- dataDelaySet(i) or frameDelaySet enables the primative write 217 axiSlaveRegister(axilEp, X"00"+toSlv((i*4), 8), 0, v.delay);
218 axiSlaveRegister(axilEp, X"00"+toSlv((i*4), 8), 5, v.dataDelaySet(i), '1');
220 axiSlaveRegister(axilEp, X"20", 0, v.delay);
221 axiSlaveRegister(axilEp, X"20", 5, v.frameDelaySet, '1');
223 -- Override read from r.delay and use curDealy output from delay primative instead 225 axiSlaveRegisterR(axilEp, X"00"+toSlv((i*4), 8), 0, curDelayData(i));
227 axiSlaveRegisterR(axilEp, X"20", 0, curDelayFrame);
230 -- Debug output to see how many times the shift has needed a relock 231 axiSlaveRegisterR(axilEp, X"30", 0, lockedFallCount);
232 axiSlaveRegisterR(axilEp, X"30", 16, lockedSync);
233 axiSlaveRegisterR(axilEp, X"34", 0, adcFrameSync);
234 axiSlaveRegister(axilEp, X"38", 0, v.lockedCountRst);
236 -- Debug registers. Output the last 2 words received 238 axiSlaveRegisterR(axilEp, X"80"+toSlv((i*4), 8), 0, axilR.readoutDebug0(i));
239 axiSlaveRegisterR(axilEp, X"80"+toSlv((i*4), 8), 16, axilR.readoutDebug1(i));
245 v := AXIL_REG_INIT_C;
257 axilR <= axilRin after TPD_G;
263 ------------------------------------------------------------------------------------------------- 265 ------------------------------------------------------------------------------------------------- 267 AdcClk_I_Ibufds : IBUFDS
270 IOSTANDARD =>
"LVDS_25") 272 I => adcSerial.dClkP,
273 IB => adcSerial.dClkN,
282 adcBitClkIoInv <= not adcBitClkIo;
287 SIM_DEVICE =>
"7SERIES",
295 -- Regional clock reset 296 ADC_BITCLK_RST_SYNC :
entity work.
RstSync 306 ------------------------------------------------------------------------------------------------- 308 ------------------------------------------------------------------------------------------------- 310 -- Frame signal input 315 I => adcSerial.fClkP,
316 IB => adcSerial.fClkN,
325 clkIo => adcBitClkIo,
334 iData => adcFramePad,
337 -------------------------------- 338 -- Data Input, 8 channels 339 -------------------------------- 342 -- Frame signal input 347 I => adcSerial.chP
(i
),
348 IB => adcSerial.chN
(i
),
349 O => adcDataPadOut
(i
));
351 -- Optionally invert the pad input 352 adcDataPad(i) <= adcDataPadOut(i) when ADC_INVERT_CH_G(i) = '0' else not adcDataPadOut(i);
360 clkIo => adcBitClkIo,
369 iData => adcDataPad
(i
),
370 oData => adcData
(i
));
373 ------------------------------------------------------------------------------------------------- 374 -- ADC Bit Clocked Logic 375 ------------------------------------------------------------------------------------------------- 376 adcComb :
process (adcData, adcFrame, adcR)
is 377 variable v : AdcRegType;
381 ---------------------------------------------------------------------------------------------- 382 -- Slip bits until correct alignment seen 383 ---------------------------------------------------------------------------------------------- 386 if (adcR.count = 0) then 387 if (adcFrame = "11111110000000") then 392 v.count := adcR.count + 1;
396 if (adcR.count /= 0) then 397 v.count := adcR.count + 1;
400 ---------------------------------------------------------------------------------------------- 401 -- Look for Frame rising edges and write data to fifos 402 ---------------------------------------------------------------------------------------------- 404 if (adcR.locked = '1' and adcFrame = "11111110000000") then 405 -- Locked, output adc data 406 v.fifoWrData(i) := "00" & adcData(i);
409 v.fifoWrData(i) := (others => '1');
--"10" & "00000000000000"; 417 adcSeq :
process (adcBitClkR, adcBitRst)
is 419 if (adcBitRst = '1') then 420 adcR <= ADC_REG_INIT_C after TPD_G;
421 elsif (rising_edge(adcBitClkR)) then 422 adcR <= adcRin after TPD_G;
426 -- Flatten fifoWrData onto fifoDataIn for FIFO 427 -- Regroup fifoDataOut by channel into fifoDataTmp 428 -- Format fifoDataTmp into AxiStream channels 430 fifoDataIn(i*16+15 downto i*16) <= adcR.fifoWrData(i);
431 fifoDataTmp(i) <= fifoDataOut(i*16+15 downto i*16);
432 debugDataTmp(i) <= debugDataOut(i*16+15 downto i*16);
433 adcStreams(i).tdata(15 downto 0) <= fifoDataTmp(i);
438 -- Single fifo to synchronize adc data to the Stream clock 449 wr_en => '1',
--Always write data 452 rd_en => fifoDataValid,
453 valid => fifoDataValid,
454 dout => fifoDataOut
);
466 wr_en => '1',
--Always write data 469 rd_en => debugDataValid,
470 valid => debugDataValid,
471 dout => debugDataOut
);
in rstsl :=not RST_POLARITY_G
in dinslv( DATA_WIDTH_G- 1 downto 0)
IDELAYCTRL_FREQ_Greal := 200.0
IDELAYCTRL_FREQ_Greal := 200.0
ADDR_WIDTH_Ginteger range 2 to 48:= 4
in adcSerialAd9249SerialGroupType
NUM_CHANNELS_Gnatural range 1 to 8:= 8
BRAM_EN_Gboolean := false
in dataInslv( WIDTH_G- 1 downto 0)
IODELAY_GROUP_Gstring := "DEFAULT_GROUP"
out doutslv( DATA_WIDTH_G- 1 downto 0)
CNT_RST_EDGE_Gboolean := true
out cntOutslv( CNT_WIDTH_G- 1 downto 0)
array(natural range <> ) of slv( 13 downto 0) Slv14Array
in axilReadMasterAxiLiteReadMasterType
RELEASE_DELAY_Ginteger range 3 to positive'high:= 3
slv( 1 downto 0) := "11" AXI_RESP_DECERR_C
ADC_INVERT_CH_Gslv( 7 downto 0) := "00000000"
in axilWriteMasterAxiLiteWriteMasterType
CNT_WIDTH_Gpositive := 16
out axilWriteSlaveAxiLiteWriteSlaveType
out axilReadSlaveAxiLiteReadSlaveType
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
out dataOutslv( WIDTH_G- 1 downto 0)
array(natural range <> ) of AxiStreamMasterType AxiStreamMasterArray
DEFAULT_DELAY_Gslv( 4 downto 0) :=( others => '0')
in wrRstsl :=not RST_POLARITY_G
array(natural range <> ) of slv( 15 downto 0) Slv16Array
out curDelayslv( 4 downto 0)
in cntRstsl :=not RST_POLARITY_G
out adcStreamsAxiStreamMasterArray( NUM_CHANNELS_G- 1 downto 0) :=( others => axiStreamMasterInit(( false, 2, 8, 0, TKEEP_NORMAL_C, 0, TUSER_NORMAL_C)))
in rstsl :=not RST_POLARITY_G
out oDataslv( 13 downto 0)
in setDelayslv( 4 downto 0)
in rdRstsl :=not RST_POLARITY_G
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16