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
Your waveforms do not show SPI CS#. Its important that your waveforms match the timing on page 24.
Cheers, Dave - Altera_Forum
Honored Contributor
SPI CS is permanently tied low which is valid according to the datasheet. The only change between reading and writing is the number of bits sent to the ADC. The ADC is able to decode the address I send it, otherwise I would not read the correct values back.
- Altera_Forum
Honored Contributor
--- Quote Start --- SPI CS is permanently tied low which is valid according to the datasheet. --- Quote End --- Ok. That fact was not mentioned in your post, so I wanted to check. --- Quote Start --- The only change between reading and writing is the number of bits sent to the ADC. The ADC is able to decode the address I send it, otherwise I would not read the correct values back. --- Quote End --- Are you sending the right values for the W1/W0 fields? Cheers, Dave - Altera_Forum
Honored Contributor
--- Quote Start --- Are you sending the right values for the W1/W0 fields? Cheers, Dave --- Quote End --- I think so. I want to write 1 byte of data, so W1/W0 is "00"
where ADC_DATA is declared as an 8-bit value.SIGNAL DATA_TO_ADC : STD_LOGIC_VECTOR(NUM-1 DOWNTO 0) := '0' & "00" & ADC_WRITE_REG & ADC_DATA; - Altera_Forum
Honored Contributor
--- Quote Start --- I think so. I want to write 1 byte of data, so W1/W0 is "00" --- Quote End --- I don't see anywhere that it says W[1:0] = 00b is for one byte. Perhaps it is in fact supposed to be W[1:0] = 01b, and the wrong setting happens to work for read, but not for write. Cheers, Dave - Altera_Forum
Honored Contributor
Sorry, I overlooked the fact that it's not in the datasheet. I found it in this application note (pg. 6, table 2). Strange why it's not mentioned in the datasheet.
http://www.analog.com/static/imported-files/application_notes/56755538964965031881813an_877.pdf - Altera_Forum
Honored Contributor
--- Quote Start --- Sorry, I overlooked the fact that it's not in the datasheet. I found it in this application note --- Quote End --- Ok, so that is not the problem. I didn't read the data sheet completely. Take a look and see if there is a requirement to write a specific number of bytes, eg., write access to 16-bit register X must use 2-bytes otherwise write transactions will be ignored. The other thing is that previous transactions may be screwing up the interface. Can you control the chip-select? If you can deassert it, then you can ensure you have reset the ADC internal logic. Also, do you have an ADC clock? Some devices I have used will not work correctly until you *also* have the ADC clock. Cheers, Dave - Altera_Forum
Honored Contributor
--- Quote Start --- I didn't read the data sheet completely. Take a look and see if there is a requirement to write a specific number of bytes, eg., write access to 16-bit register X must use 2-bytes otherwise write transactions will be ignored. --- Quote End --- All the registers in the memory map table (pg. 27) have 8-bit data. --- Quote Start --- The other thing is that previous transactions may be screwing up the interface. Can you control the chip-select? If you can deassert it, then you can ensure you have reset the ADC internal logic. --- Quote End --- For now I'm only trying to perform one transaction. I either do a read or a write. For a read, I send 16-bits to the ADC (1-bit R/W + W[1:0] + Addr[12:0]) and get 8-bits back. For a write I just add 8-bits of data after the address. --- Quote Start --- Also, do you have an ADC clock? Some devices I have used will not work correctly until you *also* have the ADC clock. --- Quote End --- Yes, the 48 MHz fpga clock is tied to the ADC clock. - Altera_Forum
Honored Contributor
--- Quote Start --- All the registers in the memory map table (pg. 27) have 8-bit data. --- Quote End --- Ok. --- Quote Start --- For now I'm only trying to perform one transaction. I either do a read or a write. For a read, I send 16-bits to the ADC (1-bit R/W + W[1:0] + Addr[12:0]) and get 8-bits back. For a write I just add 8-bits of data after the address. --- Quote End --- Right, but its not working. So as a debugging aid, can you control the chip select signal? When your board powers on, what is to stop a few glitches occurring on the clock signal and getting the device in a screwy state. 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. Just a thought ... Cheers, Dave - Altera_Forum
Honored Contributor
--- Quote Start --- Right, but its not working. So as a debugging aid, can you control the chip select signal? --- Quote End --- 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. What bothers me is I never fail to read the correct default value of a register. 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.