Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

How to read data from a memory location where ADC conversion result is stored?

Hi,

I am trying to use my ADC to sample an analog voltage. I used Qsys to design ADC modular core and was able to see the conversion result using ADC Toolkit. Now, I want to use this ADC conversion result in one of my other VHDL file where i use this result to perform some task. How can I access this ADC result. Can you provide me an example code which i can follow? What command in VHDL should i write to get access to this result register?

Please reply to my question as my earlier post is still replied to.

Regards,

Misha Kumar

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I assume you're not using Nios. So, in Qsys configure your ADC core for 'ADC control core only'. You may well be doing this anyway. Then make sure you've exported the 'command' and 'response' Avalon Streaming interfaces. Then, when you generate your HDL, you'll end up with a set of command & response signals to connect into your design.

    Then refer to figure 2-6 on page 2-9 of the max 10 analog to digital converter user guide (https://www.altera.com/literature/hb/max-10/ug_m10_adc.pdf). This shows you the timing for the Avalon streaming interfaces - which you exported - that you need to connect into your logic. You'll find your samples on the 'response_data' bus, valid when 'response_valid' indicates so.

    Cheers,

    Alex
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Alex,

    Thanks a lot for your reply. I followed what you suggested and qsys generated following example code for me. I included this code in my VHDL file.I have attached my VHDL code (at the bottom) where i want to read the data. The code is able to compile but i am not able to read the data. I used logic tap II analyzer to confirm that i am not reading ADC data. Kindly help.

    component ADC is

    port (

    clk_clk : in std_logic := 'X'; -- clk

    modular_adc_0_command_valid : in std_logic := 'X'; -- valid

    modular_adc_0_command_channel : in std_logic_vector(4 downto 0) := (others => 'X'); -- channel

    modular_adc_0_command_startofpacket : in std_logic := 'X'; -- startofpacket

    modular_adc_0_command_endofpacket : in std_logic := 'X'; -- endofpacket

    modular_adc_0_command_ready : out std_logic; -- ready

    modular_adc_0_response_valid : out std_logic; -- valid

    modular_adc_0_response_startofpacket : out std_logic; -- startofpacket

    modular_adc_0_response_endofpacket : out std_logic; -- endofpacket

    modular_adc_0_response_empty : out std_logic; -- empty

    modular_adc_0_response_channel : out std_logic_vector(4 downto 0); -- channel

    modular_adc_0_response_data : out std_logic_vector(11 downto 0); -- data

    reset_reset_n : in std_logic := 'X' -- reset_n

    );

    VHDL Code that I made:

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;

    use IEEE.NUMERIC_STD.ALL;

    entity ADC_PWM is

    Port ( clk_clk : in STD_LOGIC;

    Su : out STD_LOGIC;

    Sb : out STD_LOGIC);

    end ADC_PWM;

    architecture Behavioral of ADC_PWM is

    component ADC is

    port (

    clk_clk : in std_logic := 'X'; -- clk

    modular_adc_0_command_valid : in std_logic := 'X'; -- valid

    modular_adc_0_command_channel : in std_logic_vector(4 downto 0) := (others => 'X'); -- channel

    modular_adc_0_command_startofpacket : in std_logic := 'X'; -- startofpacket

    modular_adc_0_command_endofpacket : in std_logic := 'X'; -- endofpacket

    modular_adc_0_command_ready : out std_logic; -- ready

    modular_adc_0_response_valid : out std_logic; -- valid

    modular_adc_0_response_startofpacket : out std_logic; -- startofpacket

    modular_adc_0_response_endofpacket : out std_logic; -- endofpacket

    modular_adc_0_response_empty : out std_logic; -- empty

    modular_adc_0_response_channel : out std_logic_vector(4 downto 0); -- channel

    modular_adc_0_response_data : out std_logic_vector(11 downto 0); -- data

    reset_reset_n : in std_logic := 'X' -- reset_n

    );

    end component ADC;

    signal count,shadowload,CMP : unsigned (11 downto 0) := to_unsigned(0,12);

    signal deadtime : time := 500 ns;

    signal PRD : unsigned (11 downto 0) := to_unsigned(4000,12);

    signal Y : std_logic := '1';

    signal N : std_logic := '0';

    signal channel,responsechannel : std_logic_vector(4 downto 0) :=(others => '0');

    signal data : std_logic_vector(11 downto 0) :=(others => '0');

    signal ready,valid,sof,eof,empty,reset : std_logic := '0';

    begin

    CMP <= to_unsigned(2000,12);

    deadtime <= 500 ns;

    ADC1 : ADC port map(clk_clk,Y ,channel ,Y ,N ,ready,valid,sof,eof,empty,responsechannel, data, reset);

    process(shadowload,count)

    begin

    if (shadowload > count) then

    Su <= '0' ;

    Sb <= '1' after deadtime;

    else

    Sb <= '0';

    Su <= '1' after deadtime;

    end if;

    end process;

    process(clk_clk)

    begin

    if(rising_edge(clk_clk)) then

    if(count = PRD) then

    count <= to_unsigned(1,12);

    --shadowload <= unsigned(data);

    shadowload <= CMP;

    else

    count <= count + 1;

    end if;

    end if;

    end process;

    end Behavioral;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I feel there's quite a bit lacking in your code... You mention logic tap - can I assume you're trying to put this onto some hardware?

    In your entity declaration - 'Su' & 'Sb', your hardware's only I/O, has nothing to do with the ADC. Is this intentional?

    entity ADC_PWM is
        Port (
            clk_clk : in STD_LOGIC;
                 Su : out STD_LOGIC;
                 Sb : out STD_LOGIC);
    end ADC_PWM;
    

    What are you hoping the following will do? It may simulate as you'd expect but it won't synthesize to anything you can put onto hardware.
            deadtime <= 500 ns;
    .....
            process(shadowload,count)
                begin
                if (shadowload > count) then
                    Su <= '0' ; 
                    Sb <= '1' after deadtime;
                    else
                    Sb <= '0';
                    Su <= '1' after deadtime;
                end if;
            end process;
    

    What relevance does the following code have to your ADC? Perhaps none, but that means there isn't any logic left!

        process(clk_clk)
        begin
            if(rising_edge(clk_clk)) then
                if(count = PRD) then
                    count <= to_unsigned(1,12);
                    shadowload <= CMP;
                else
                    count <= count + 1;
                end if;
            end if;
        end process;
    

            signal ready,valid,sof,eof,empty,reset : std_logic := '0';
    .....
            ADC1 : ADC port map(clk_clk,Y ,channel ,Y ,N ,ready,valid,sof,eof,empty,responsechannel, data, reset);
    

    All those signals (ready,valid,sof etc.) are output signals from the ADC. The ADC drives these signals. You shouldn't be assigning them to '0'.

    None of your output signals connect to anything, except possibly your signal tap module. Signals that don't drive anything will result in chunks of logic being removed. If the ADC output signals don't actually drive anything what's to stop Quartus getting rid of it? (Yes, possibly signal tap.)

    All your ADC input signals are static. When I've previously played around with the ADC I found that didn't work - I had to control something. Looking back at my code the minimum I seemed to be able to get away with was pulsing 'command_valid', but I still had to pulse it.

    Your clock frequency - see table 5-1 on page 5-2 of the ADC document. Is you clock at an appropriate frequency?

    Is this a University tutorial? I feel you need a chat with your tutor...

    Cheers,

    Alex
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Alex,

    Thanks for your reply. I solved the problem. I was using static signals and now when i pulsed the start of packet and kept the command valid high all the time, it worked.

    The following part of the code is for Pulse Width Modulation (PWM) generator.What i intended to do earlier, is to read ADC data and use it to change the duty-cycle(or ON Time) of my pulse. Since, I was not ale to read ADC data, it kept it fixed earlier. The bottom code generates a counter for PWM.

    As, now I can read the ADC data, I am able to change this duty-cycle.

    Also, this code is not for university tutorial. It is for the industry. I am very new to VHDL coding and using FPGAs but certainly with your help I was able to correctly configure my ADC.

    Thanks again for your help!

    Regards,

    Misha

    Code:

    .....

    process(shadowload,count)

    begin

    if (shadowload > count) then

    Su <= '0' ;

    Sb <= '1' after deadtime;

    else

    Sb <= '0';

    Su <= '1' after deadtime;

    end if;

    end process;

    What relevance does the following code have to your ADC? Perhaps none, but that means there isn't any logic left!

    Code:

    process(clk_clk)

    begin

    if(rising_edge(clk_clk)) then

    if(count = PRD) then

    count <= to_unsigned(1,12);

    shadowload <= CMP;

    else

    count <= count + 1;

    end if;

    end if;

    end process;

    Code: