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!
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!
Rich (BB code):
//register declarations
reg conv;
reg rdy;
reg [3:0] count;
reg [11:0] data_temp;
reg [11:0] 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[11] <= serial_data;
2: data_temp[10] <= serial_data;
3: data_temp[9] <= serial_data;
4: data_temp[8] <= serial_data;
5: data_temp[7] <= serial_data;
6: data_temp[6] <= serial_data;
7: data_temp[5] <= serial_data;
8: data_temp[4] <= serial_data;
9: data_temp[3] <= serial_data;
10: data_temp[2] <= serial_data;
11: data_temp[1] <= serial_data;
12: data_temp[0] <= serial_data;
endcase
end
Last edited: