Tool/software:
Hi.
I am looking for an HDL behavioral model for FPGA simulation of ADS79xx ( ADS7952 ).
Thank you.
David.
Hi David,
Unfortunately we don't have a Verilog/VHDL behavioral model for the digital communications for this device. I will take this inquiry as a request in case this development occurs in the future.
Regards,
Joel
Gemini wrote this:
// Behavioral model for the Texas Instruments ADS7952 ADC // Not a cycle-accurate model, but provides basic functionality for simulation. `timescale 1ns / 1ps module ADS7952_model ( inout SDO, input CS, input SCLK, input SDI, inout [3:0] GPIO ); // Internal state reg [15:0] shift_reg; reg [ 3:0] bit_count; reg sdo_oe; reg [11:0] adc_mem [11:0]; // Memory for 12 channels reg [ 3:0] current_channel; reg auto_mode; // GPIO registers reg [ 3:0] gpio_dir; // 0 = input, 1 = output reg [ 3:0] gpio_out; // GPIO output enables assign GPIO[0] = gpio_dir[0] ? gpio_out[0] : 1'bz; assign GPIO[1] = gpio_dir[1] ? gpio_out[1] : 1'bz; assign GPIO[2] = gpio_dir[2] ? gpio_out[2] : 1'bz; assign GPIO[3] = gpio_dir[3] ? gpio_out[3] : 1'bz; // Initialize memory and registers integer i; initial begin for ( i = 0; i < 12; i = i + 1 ) begin adc_mem[i] <= i * 256; end current_channel <= 0; auto_mode <= 0; sdo_oe <= 1'b0; bit_count <= 0; // Default GPIO to input gpio_dir <= 4'b0000; gpio_out <= 4'b0000; end assign SDO = sdo_oe ? shift_reg[15] : 1'bz; always @(negedge CS) begin // Start of a new transaction bit_count <= 0; sdo_oe <= 1'b1; // Load the shift register with the result of the previous conversion shift_reg <= { adc_mem[current_channel], 4'b0000 }; end always @(posedge CS) begin // End of transaction sdo_oe <= 1'b0; // Decode the command received on SDI case (shift_reg[15:12]) 4'b1000: begin // Manual mode channel select auto_mode <= 0; current_channel <= shift_reg[11:8]; end 4'b1010: begin // Auto-1 mode auto_mode <= 1; end 4'b0100: begin // GPIO programming gpio_dir <= shift_reg[9:6]; gpio_out <= shift_reg[5:2]; end // Other modes are not implemented in this simple model endcase // In auto mode, increment channel after each conversion if (auto_mode) begin current_channel <= (current_channel == 11) ? 0 : current_channel + 1; end end always @(posedge SCLK) begin if (!CS) begin // Shift data in on SDI and out on SDO shift_reg <= { shift_reg[14:0], SDI }; bit_count <= bit_count + 1; end end endmodule
That doesn't look like a bad place to start. I'm sure there are some improvements to be made, but if you are able to use it for preliminary simulations before hardware gets in, I can help by sharing the expected output of the ADC.
Regards,
Joel
I will say, creating a full, accurate behavioral model will undoubtedly be a more advanced state machine. As far as I know, we haven't released any behavioral models of our devices' digital interface to date. Are you able to test with actual hardware? I'd like to understand how the behavioral model would be expected to be used a little more, and what benefits it brings to your development.
Regards,
Joel
As I see it - HDL behavioral model for helping customers integrate TI's products into products - is a very important selling tool.
It is fairly easy to do - with the current AI tools - just open a git project for doing so - and let AI fill it...
Once you find an error - fix it :-)
The Idea is very simple - The task is to write the FPGA code that glue the CPU to the ADC.
So I write a Test Bench to test my implementation and to give the software guys instructions on how the hardware works.
In this test bench I connect my FPGA design ( the CPU interface to an SPI ) to a "behavioral model of the hardware" that include a behavioral model of the ADC.
This test bench then runs in an HDL simulator and show a "success" if the test passed.
Then the software can do the same steps as the test bench and have a good chance of actually working in production...
Now I have a real problem from real hardware:
In the 1 transaction 0001 | 1 | 0001 | 0 | 0 | 0 | 0000 : channel requested is 1
In the 2 transaction 0001 | 1 | 0010 | 0 | 0 | 0 | 0000 : channel requested is 2
In the 3 transaction 0001 | 1 | 0011 | 0 | 0 | 0 | 0000 : channel requested is 3
Expected channel result is 1 but the channel returned is 0
What did I miss?
Thank you
David
Hi David,
Input data format for manual mode looks correct, but I would try configuring the SPI peripheral as SPI Mode 0 (CPHA = 0, CPOL = 0). Given that, the device might only be seeing 15 clocks.
Regards,
Joel
Thank you for your reply - I did what you suggested and now it works better.
This is my current version for a behavioral model for the ADS7952 - hope it make sense ....
// ADS7952_model.sv // Behavioral model for the Texas Instruments ADS7952 ADC // Modified to better reflect the one-frame delay for manual mode programming as per the datasheet. `timescale 1ns / 1ps module ADS7952_model ( output SDO, input CS, input SCLK, input SDI, inout [ 3:0] GPIO, input [11:0] adc_in[11:0] ); // Internal state reg [15:0] shift_reg; reg [ 3:0] bit_count; reg SDO_out; reg sdo_oe; reg [ 3:0] adc_channl_requested; // in the end of first transaction we know what channel to sample reg [11:0] adc_mem_sampled; // after 2ed CS neg edg -> we sample the adc of adc_channl_requested in the previos transaction reg [ 3:0] adc_channl_in_convertion; // after 2ed CS neg edg -> move the adc_channl_requested here reg [11:0] adc_mem_ready2send; // after 2ed CS pos edg -> move the adc_mem_sampled to ready for sending in the 3ed transaction reg [ 3:0] adc_channl_ready2send; // after 2ed CS pos edg -> move the adc_channl_in_convertion here reg auto_mode; // GPIO registers reg [ 3:0] gpio_dir; // 0 = input, 1 = output reg [ 3:0] gpio_out; // GPIO output enables assign GPIO[0] = gpio_dir[0] ? gpio_out[0] : 1'bz; assign GPIO[1] = gpio_dir[1] ? gpio_out[1] : 1'bz; assign GPIO[2] = gpio_dir[2] ? gpio_out[2] : 1'bz; assign GPIO[3] = gpio_dir[3] ? gpio_out[3] : 1'bz; assign SDO = sdo_oe ? SDO_out : 1'bz; // Initialize memory and registers integer i; initial begin auto_mode <= 0; sdo_oe <= 1'b0; shift_reg <= 16'd0; bit_count <= 0; // Default GPIO to input gpio_dir <= 4'b0000; // All inputs gpio_out <= 4'b0000; #1; adc_channl_requested <= 4'hB; adc_mem_sampled <= 12'hDED; adc_channl_in_convertion <= 4'hB; adc_mem_ready2send <= 12'hDED; adc_channl_ready2send <= 4'hB; end // At the start of a transaction, load the shift register with the result // of the *previous* conversion cycle (for the current_channel). always @(negedge CS) begin // Start of a new transaction bit_count <= 0; sdo_oe <= 1'b1; // Load the shift register with the result of the previous conversion shift_reg <= { adc_channl_ready2send, adc_mem_ready2send }; SDO_out <= adc_channl_ready2send[3]; // The input signal is sampled with the falling edge of CS: adc_mem_sampled <= adc_in[ adc_channl_requested ]; // requested -> convertion adc_channl_in_convertion <= adc_channl_requested; end // At the end of a transaction, decode the command that was just received // and set up the state for the *next* transaction. always @(posedge CS) begin // End of transaction sdo_oe <= 1'b0; SDO_out <= 1'b1; // next ADC step // convertion -> ready adc_channl_ready2send <= adc_channl_in_convertion; adc_mem_ready2send <= adc_mem_sampled; // Decode the command received on SDI case (shift_reg[15:12]) 4'b0001: begin // Manual Mode (DI15-12 = 0001) auto_mode <= 0; // DI11 = 1 enables programming of ‘range and GPIO’ if ( 1'b1 == shift_reg[11 ] ) begin adc_channl_requested <= shift_reg[10:7]; // DI10-7 = binary address of channel // shift_reg[ 6 ]; // 0 = Vref 1 = 2*Vref // shift_reg[ 5 ]; // 1 = power down // shift_reg[ 4 ]; // in next transaction 0 = output samples channel 1 = output GPIO gpio_out <= shift_reg[ 3:0]; end end // Other modes (like Auto-1) would need to be defined based on their DI15-12 patterns // If no other patterns are defined, they would fall into a default case. default: begin // Handle unimplemented or reserved commands end endcase // After decoding, update the current_channel for the next conversion cycle. // if (auto_mode) begin // In auto mode, channel increments after each conversion. // The programmed_channel is ignored. // current_channel <= (current_channel == 11) ? 0 : current_channel + 1; // end else begin // In manual mode, the next channel to be converted is the one we just programmed. // current_channel <= programmed_channel; // end end always @(posedge SCLK) begin if (!CS) begin // Shift data in on SDI and out on SDO shift_reg <= { shift_reg[14:0], SDI }; bit_count <= bit_count + 1; end end always @(negedge SCLK) begin if (!CS) begin if ( sdo_oe ) begin SDO_out <= shift_reg[15]; end else begin SDO_out <= 1'b1; end; end end endmodule
It seems my understanding of the datasheet is not correct.
In manual mode, If I sample the same channel number 8 in all SPI transactions -
the sampling and conversion and sending is happening on the same transaction.
and not as I understood from the datasheet - that sending should happen on the next transaction - but apparently I was wrong.
In the picture you can see the logic analyzer's pickup.
I have an analog MUX connected to channel 8 of the ADC.
Only MUX input number 4 is connect to VCC to get FFF reading. All other external MUX inputs are connected to GND to give 000.
I sample channel 8 of the ADC while MUX is on 3 to get 000 -> then I sample channel 8 another 2 times on MUX on channel 4 & get FFF twice ->
Then other MUX inputs...
There is NO delay of one SPI transaction - the voltage is converted and sent in the same transaction - NOT as could be understood from the datasheet.
What do I miss?
Thank you.
David.
Hi David,
Where are you gathering what channel the output data corresponds to? Are you able to mark up the image to clarify what you are referring to? The first 4 bits of the output word should also contain the channel address for the corresponding data if DI04 is set to 0.
In manual mode, there should actually be a 2 SPI frame delay between when the channel is selected, and when the corresponding conversion is output.
Regards,
Joel
As explained - and you can see in the timing diagram - the channel selected is 8 - and channel received is 8 - in all transactions!
My external MUX has its 3 select bits in the diagram and all inputs connected to GND except 4 which is connected to VCC.
As you can see - there is no delay - the result of the conversion is sent immediately at the same transaction as the sampled.
I get FFF on selecting external MUX to 4 in the two middle transactions... and 000 in all other channels.
Hi David,
Apologies. I misunderstood the setup. I've read more carefully this time.
The internal ADC MUX is set to channel 8. You also have an external MUX connected to channel 8. On the external MUX, input 4 is is connected to VCC (full-scale), while the other inputs are grounded.
The behavior you are seeing is expected. The input is sampled and held on the falling edge of ~CS. See the timing diagram below (Figure 1), specifically the acquisition and conversion plots.
The paragraph below also clarifies the timing. The device outputs data while the conversion is in progress.
The delay I was referring to is the internal channel switching delay.
Regards,
Joel