Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20687 Discussions

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

Altera_Forum
Honored Contributor II
1,836 Views

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
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
715 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
715 Views

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;
0 Kudos
Altera_Forum
Honored Contributor II
715 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
715 Views

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:
0 Kudos
Reply