You'll have to supply a pulse to CONVST_A, CONVST_B, CONVST_C and CONVST_D for all three ADCs to start their conversions. Use an external clock (XCLK) to synchronize the conversions. Check the BUSY/INT output for end-of-conversion:
When bit C27 = 1 (BUSY/INT in CONFIG), this pin is an interrupt output. This pin transitions high after a conversion
has been completed and remains high until the next read access. This mode can only be used if all eight channels
are sampled simultaneously (all CONVST_x tied together). The polarity of the BUSY/INT output can be changed
using bit C26 (BUSY L/H) in the Configuration Register. (page 16)
You then can read the data of the different ADCs into several registers. At that moment timing is no longer relevant to the synchronicity of the conversion.
Normally, FIFOs are self controlled to prevent overflows and underflows. This is done by implementing a forward and backward flow control. Forward flow control means that data words are marked valid in the FIFO so that the read side can distinguish valid from invalid words. Backward flow control is achieved by exporting fill state of a FIFO to the write side. If the FIFO is full it creates a 'full' signal signaling the writer that it can handle more data.
In your case the ADC is transmitting data at a constant rate, so you have to dimension the FIFO correct to prevent an overflow.
\$Write\,speed = 20\,MHz \cdot \frac{1\ ADC\,Words}{16\ Cycles} = 1.25\,M\frac{Words}{sec}\$
\$Read\,speed = 100\,MHz \cdot \frac{1\,Word}{1\,Cycle} = 100\,M\frac{Words}{sec}\$
Because read speed is faster then write speed and write burst length is one, you don't need to worry about FIFO depth or burst length and overflows. Note cross clock FIFOs have a minimum dephs, e.g. 3 words.
Lets have a look to a common FIFO interface:
entity fifo_ic_got is
generic (
D_BITS : positive; -- Data Width
MIN_DEPTH : positive -- Minimum FIFO Depth
);
port (
-- Write Interface
clk_wr : in std_logic;
rst_wr : in std_logic;
put : in std_logic;
din : in std_logic_vector(D_BITS-1 downto 0);
full : out std_logic;
-- Read Interface
clk_rd : in std_logic;
rst_rd : in std_logic;
got : in std_logic;
valid : out std_logic;
dout : out std_logic_vector(D_BITS-1 downto 0)
);
end;
This FIFO has 2 clock inputs, one for each clock domain (read (rd) and write (wr)) as well as one resets for each side.
The data path din to dout is surrounded by 4 signals:
- put - din is valid -> store word in the FIFO
- full - the FIFO is full -> no more data can be stored, put has no effect
- valid - the FIFO has at least one data word, which can be seen at dout
- got - the current word on dout was read and the circuit is ready for the next word
Writing at every 16th clock cycle means to assign put every 16 cycles to 1. She signal full can be ignored, because the read side is always faster then the write side.
Here is a waveform for the FIFO:
Wavedrome online waveform editor
Best Answer
I think you need to go a little further than your proposed solution. I would suggest that you have the data read from the ADC into a register using the ADC clock. The register should be long enough to hold the entire integer value from the ADC. Once that register is full with a reading the associated state machine logic would generate a signal to indicate that the value was valid and not going to change and can be read by the main FPGA logic.
From the point of view of the logic driven from the main FPGA system clock the register complete signal would be asynchronous, however you could use it as an enable signal to copy the data in one system clock cycle to another register on the next system clock edge. Thus you would now have the data available synchronous to the FPGA system clock.
The only restriction with this scheme that I can forsee is that the FPGA clock would need to be at a higher rate than the ADC clock to ensure that the data was available for sufficiently long.