Interfacing an ADC to an FPGA through 3-wire SPI

Discussion in 'Embedded Systems and Microcontrollers' started by Obanion, Jan 22, 2010.

  1. Obanion

    Thread Starter New Member

    Nov 26, 2009
    24
    0
    Edit: solved. Count == 13 should be changed to count == 14 for proper operation. The guys at the Altera forum helped me out, so if you're curious the code can be found there.

    Hi guys,

    I'm writing some Verilog code to interface a simple 12-bit serial ADC to an FPGA and I have some questions about my methodology. The ADC that I'm using is the ADS7818 (http://focus.ti.com/lit/ds/symlink/ads7818.pdf)

    I think the code should be very simple, but I just want to get a second opinion so I don't end up in the wrong direction. Basically, here's what I think should be done.

    1. Since the ADC is going to be operating at its full 500 KSPS, my input clock needs to be 8 MHz. This is going to be fed into the ADC at all time. For this reason, I think I should be using the DSP Interface Timing style on page 12 of the datasheet.

    2. Make a simple counter than counts up to 16 and then resets after that. This counter is operating at 8 MHz. This will allow me to keep track of all the current clock cycle, so I can grab the data and know when to assert the CONV.

    3. CONV will be asserted 0 when the falling edge of the CLK = 15 is present. At the falling edge CLK = 16, the CONV is asserted 1.

    4. At the falling edge of CLK = 1, I will grab the data and place them into the register. I will stop at CLK = 13, and at CLK = 13, I will put them into a another register.

    5. I will assert a ready signal (RDY) at the rising edge of CLK = 14 and make it low at the rising edge of CLK = 1. This RDY signal will tell my other modules that the data is ready and valid. My other modules, however, will be operating at 200 MHz, but the clock should be synchronized

    6. Everything will now repeat.

    Does this seem like it would work? I've never worked with SPI or external devices, nor have I ever written code from a timing diagram.

    In case you're interested, my code can be seen below.

    Thanks!

    Code ( (Unknown Language)):
    1. //register declarations
    2.     reg conv;
    3.     reg rdy;
    4.     reg [3:0] count;
    5.     reg [11:0] data_temp;
    6.     reg [11:0] tmp;
    7.    
    8.     //The clock counter. Starts at 0, so clock is from 0-15 instead of 1-16.
    9.     always @ (posedge CLOCK_8)
    10.         begin
    11.             count <= count + 1;
    12.         end
    13.    
    14.     //Assert the CONV signal
    15.     always @ (negedge CLOCK_8)
    16.         begin
    17.             if ((count == 14) || (count == 15))
    18.                 conv = 1'b0;
    19.             else
    20.                 conv = 1'b1;
    21.         end                
    22.    
    23.     //Read the serial data into a 12-bit register. Afterwards, convert it to parallel if the count is 13 (end of data stream)
    24.     always @ (negedge CLOCK_8)
    25.         begin
    26.             if (count == 13)
    27.                 tmp <= data_temp;
    28.             case (count)
    29.                 1: data_temp[11] <= serial_data;
    30.                 2: data_temp[10] <= serial_data;
    31.                 3: data_temp[9] <= serial_data;
    32.                 4: data_temp[8] <= serial_data;
    33.                 5: data_temp[7] <= serial_data;
    34.                 6: data_temp[6] <= serial_data;
    35.                 7: data_temp[5] <= serial_data;
    36.                 8: data_temp[4] <= serial_data;
    37.                 9: data_temp[3] <= serial_data;
    38.                 10: data_temp[2] <= serial_data;
    39.                 11: data_temp[1] <= serial_data;
    40.                 12: data_temp[0] <= serial_data;
    41.             endcase
    42.            
    43.         end
     
    Last edited: Jan 28, 2010
Loading...