Altera_Forum
Honored Contributor
16 years agoADC interfacing code for 3-wire SPI using Verilog
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 from Texas Instruments.. 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've done so far, but I seem to be having some trouble getting it works. In actual fact, I'm not sure if I'm asserting and reading the data correctly. Anyway, this is what I have so far: 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. I'd appreciate any input you have for modification to get this thing going.//register declarations
reg conv;
reg rdy;
reg count;
reg data_temp;
reg tmp;
//The clock counter. Starts at 0, so clock is from 0-15 instead of 1-16.
always @ (posedge CLOCK_8)
begin
count <= count + 1;
end
//Assert the CONV signal
always @ (negedge CLOCK_8)
begin
if ((count == 14) || (count == 15))
conv = 1'b0;
else
conv = 1'b1;
end
//Read the serial data into a 12-bit register. Afterwards, convert it to parallel if the count is 13 (end of data stream)
always @ (negedge CLOCK_8)
begin
if (count == 13)
tmp <= data_temp;
case (count)
1: data_temp <= serial_data;
2: data_temp <= serial_data;
3: data_temp <= serial_data;
4: data_temp <= serial_data;
5: data_temp <= serial_data;
6: data_temp <= serial_data;
7: data_temp <= serial_data;
8: data_temp <= serial_data;
9: data_temp <= serial_data;
10: data_temp <= serial_data;
11: data_temp <= serial_data;
12: data_temp <= serial_data;
endcase
endThis is also a cross-post to the same thread on the allaboutcircuits embedded systems forum. I have posted here because I haven't been able to get a reply.