Forum Discussion
Altera_Forum
Honored Contributor
14 years agoConfiguring ADC using FPGA
I am trying to configure an ADC using an FPGA. I can read the default values from the ADC register properly, but I'm unable to write to those registers.
The fpga clock is 48 MHz and serial clock for the ADC is 8 MHz. The VHDL code that I've written is given below.LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.all;
ENTITY SPI_MASTER IS
GENERIC
(
NUM : INTEGER := 24
);
PORT
(
CLK_IN : IN STD_LOGIC;
SPI_MASTER_SDIO : INOUT STD_LOGIC;
SPI_MASTER_CLK : OUT STD_LOGIC;
SPI_MASTER_CS : OUT STD_LOGIC;
ADC_DATA_IN : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END ENTITY;
ARCHITECTURE BEHAV OF SPI_MASTER IS
CONSTANT ADC_WRITE_REG : STD_LOGIC_VECTOR(12 DOWNTO 0) := '0' & x"008"; --WRITE REGISTER
CONSTANT ADC_DATA : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"10"; --DATA TO WRITE
CONSTANT ADC_READ_REG : STD_LOGIC_VECTOR(12 DOWNTO 0) := '0' & x"015"; --READ REGISTER
SIGNAL DATA_TO_ADC : STD_LOGIC_VECTOR(NUM-1 DOWNTO 0) := '0' & "00" & ADC_WRITE_REG & ADC_DATA;
SIGNAL DATA_FROM_ADC : STD_LOGIC_VECTOR(15 DOWNTO 0) := '1' & "00" & ADC_READ_REG;
SIGNAL OE : STD_LOGIC := '1'; --OUTPUT ENABLE FROM FPGA, WHEN HIGH: SEND DATA TO ADC, WHEN LOW: RECEIVE DATA FROM ADC
SIGNAL DATA_IN : STD_LOGIC_VECTOR(7 DOWNTO 0) := "11111111";
SIGNAL MASTER_RST : STD_LOGIC := '0';
SIGNAL SENT : INTEGER := 0; --NUM BITS SENT
SIGNAL RCVD : INTEGER := 0; --NUM BITS RECEIVED
SIGNAL ADC_CLK : STD_LOGIC := '0'; --SERIAL CLOCK FOR ADC
SIGNAL COUNT : INTEGER := 0;
BEGIN
PROCESS(CLK_IN)
BEGIN
IF(RISING_EDGE(CLK_IN)) THEN
IF(COUNT = 2) THEN
ADC_CLK <= NOT ADC_CLK;
COUNT <= 0;
ELSE
COUNT <= COUNT + 1;
END IF;
END IF;
END PROCESS;
PROCESS(ADC_CLK,MASTER_RST,OE)
BEGIN
IF(FALLING_EDGE(ADC_CLK) AND MASTER_RST = '0') THEN
IF(OE = '1') THEN
IF(SENT < 23) THEN
--DATA_FROM_ADC <= DATA_FROM_ADC(14 DOWNTO 0) & '1';
DATA_TO_ADC <= DATA_TO_ADC(22 DOWNTO 0) & '1';
SENT <= SENT + 1;
ELSE
OE <= '0';
END IF;
END IF;
ELSIF(RISING_EDGE(ADC_CLK) AND MASTER_RST = '0') THEN
IF(OE = '0') THEN
DATA_IN <= DATA_IN(6 DOWNTO 0) & SPI_MASTER_SDIO;
RCVD <= RCVD + 1;
IF(RCVD > 6) THEN
MASTER_RST <= '1';
END IF;
END IF;
END IF;
END PROCESS;
--SPI_MASTER_SDIO <= DATA_FROM_ADC(15) WHEN OE = '1' ELSE 'Z';
SPI_MASTER_CS <= '0';
SPI_MASTER_CLK <= ADC_CLK;
ADC_DATA_IN <= DATA_IN;
SPI_MASTER_SDIO <= DATA_TO_ADC(23) WHEN OE = '1' ELSE 'Z';
END BEHAV; The parts that are commented are used for reading from the ADC registers. Also when reading the "IF (sent < 23)" is changed to "IF (sent < 15)". I used logic probes to see the output of the SCLK and SDIO pins (attached) and I don't see a problem. I am not sure why writing to the registers does not work. Here is the datasheet of the ADC since I couldn't upload the file: http://www.analog.com/static/imported-files/data_sheets/ad9649.pdf (http://www.analog.com/static/imported-files/data_sheets/ad9649.pdf) Any help/insight will be appreciated! Thanks.14 Replies
- Altera_Forum
Honored Contributor
--- Quote Start --- Yes I can control the chip select. I'll certainly give that a try, set CS high during power up and then set it low after a few clock cycles. --- Quote End --- Sounds like a good debug plan. --- Quote Start --- What bothers me is I never fail to read the correct default value of a register. --- Quote End --- Never try to interpret patterns, you'll never figure them out. --- Quote Start --- For now I have to change the address value in my VHDL code, re-compile the code, and re-program the FPGA. I would think a read would be more difficult to accomplish since the SDIO line has to change from an input to an output whereas for a write, it stays as an input line. --- Quote End --- You need to write an ADC interface controller, wrap it with a Avalon-MM registers interface, drop it into an SOPC or Qsys system, and then debug. That way you can generate reads or writes to whatever addresses you like. It may seem like a lot of extra work up front, but you'll benefit from it in the long run. Go through this tutorial: http://www.alterawiki.com/wiki/using_the_usb-blaster_as_an_sopc/qsys_avalon-mm_master_tutorial Cheers, Dave - Altera_Forum
Honored Contributor
--- Quote Start --- Even though the ADC has a mode where chip-select can be asserted low all the time, it might need it to be deasserted while being powered up. --- Quote End --- Yes, the chip misses a means to reset the SPI protocol without deasserting CS. I don't see a reliable way to operate the device without connecting CS. - Altera_Forum
Honored Contributor
It turns out that writing to certain address requires an additional step (from the datasheet):
transfer register mapaddress 0x08 to address 0x18 are shadowed. writes to these addresses do not affect part operation until a transfer command is issued by writing 0x01 to address 0xff, setting the transfer bit. this allows these registers to be updated internally and simulta-neously when the transfer bit is set. the internal update takes place when the transfer bit is set, and then the bit autoclears. So now the write is working properly. Thanks for taking the time to look through this.
- Altera_Forum
Honored Contributor
--- Quote Start --- So now the write is working properly. --- Quote End --- Great! However, make sure you follow Frank's and my advice; keep chip-select deasserted until your board powers up, to ensure the SPI device is initialized correctly. If you are developing a robust product, then you want to make sure that there are no 'hidden' issues that will show up in the future. Cheers, Dave