Reputation: 121
I need to control sampling frequency of ADCs interfaced with my FPGA.
I can use a 50MSPS, 14 bit resolution ADC. and then using DCM divide the FPGA source 50MHz clock to 1MHz, 2MHz and 5MHz and use these frequencies each time as the clock of my ADCs. or I can use a 20MSPS, 16 bit resolution ADC and choose a smaller subsampling ratio in DCM. which one is preferred? Is this a correct way of thinking?
I can think of something like:
if ((data_rate=1MSPS and rising_edge(clk_1M)) or (data_rate=2MSPS and rising_edge(clk_2M)) or
(data_rate=5MSPS and rising_edge(clk_5M)) ) then
//save sub sampled adc data samples
ADCDATA1(13 downto 0)<= Data_in(13 downto 0);
is this bad coding?! or completely wrong and won't work?
Upvotes: 0
Views: 362
Reputation: 21
You didn't say what family or P/N of FPGA you are using, but based on experience there is a lower limit on the frequency of most DCMs. You will want to consult the data sheet for your device to find the minimum output frequency. That may be as low as perhaps 5 or 6MHz so reaching 1MHz or 2MHz might be a problem. What I have done in the past for low frequency ADC interfaces (or any low rate parallel/serial interface) is to run my FPGA vhdl processes off of say a convenient integer multiple of the ADC sample rate, like you suggest (say 20MHz) and then create a counter also running at 20MHz which output's an enable signal once per ADC sample period. For a 1MHz sample rate that means the counter would count from 0 to 19 then reset back to zero and repeat the count sequence. When your count value reaches 19, output a pulse and call it 'clock_enable'. Then in your ADC sample process, make your process sensitivity list only senstive to clk_20M and use only rising_edge(clk_20M) in the body of your process like this:
MY_CLK_ENABLER : process(clk_20M)
begin
if rising_edge(clk_20M) then
if (clk_en_count = "10011") then -- count to 19 the reset
clk_en_count <= "00000";
clk_enable <= '1';
else
clk_en_count <= clk_en_count + '1';
clk_enable <= '0';
end if;
end if;
end process;
MY_SUB_SMPL : process(clk_20M)
begin
if rising_edge(clk_20M) then
if (clk_enable = '1') then
ADCDATA1(13 downto 0)<= Data_in(13 downto 0);
end if;
end if;
end process;
Also, if you are using a 16 bit ADC I would want to use all the bits, but it sounds like you are somehow limited to using only 14 of the 16 bits. If this is true, and your signal presented to the input of the ADC occupies the full scale input voltage range of the device, you will probably want to take bits 15 downto 2 rather than 13 downto 0 because taking the lower bits only with a full scale input will result in a clipped digital waveform.
Upvotes: 2