工具/软件:
你(们)好
我正在寻找 ADS79xx ( ADS7952 ) FPGA 仿真的 HDL 行为模型。
谢谢你。
David。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Gemini 写道:
// 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
我认为、用于帮助客户将 TI 产品集成到产品中的 HDL 行为模型是一种非常重要的销售工具。
这是相当容易的 — 使用当前的 AI 工具 — 只需打开一个 git 项目这样做 — 让 AI 填充它...
一旦你发现错误 — 修复它:-)
目的非常简单、 任务是编写将 CPU 胶合到 ADC 的 FPGA 代码。
所以我写了一个测试台来测试我的实施并向软件人员提供硬件工作原理的说明。
在这个测试台 ,我将我的 FPGA 设计 ( CPU 接口到 SPI ) 连接到“硬件的行为模型“,其中包括 ADC 的行为模型。
然后、该测试台在 HDL 模拟器中运行、如果测试通过、则显示“成功“。
然后、该软件可以执行与测试台相同的步骤、并且很有可能实际在生产中工作...
现在、我在实际硬件方面遇到了一个真正的问题:

在 1 个事务中 0001 | 1 | 0001 | 0 | 0 | 0 | 0000:请求的通道为 1
在 2 个事务中 0001 | 1 | 0010 | 0 | 0 | 0 | 0000:请求的通道是 2
在 3 个事务中 0001 | 1 | 0011 | 0 | 0 | 0000:请求的通道为 3
预期的通道结果为 1、但返回的通道为 0
我想念什么?
谢谢你
David
感谢您的答复 — 我做了您的建议,现在它更好地工作.
这是我目前针对 ADS7952 行为模型的版本 — 希望它有意义 ...
// 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,
input [ 3:0] GPIO, // inout
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] mux_channl_requested; // in the end of transaction we know what channel to sample after delay
reg [ 3:0] mux_channl_delay; // save the requested channel
reg [ 3:0] mux_channl_ready2send; // CS pos edg -> move the mux_channl_delay 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;
mux_channl_requested <= 4'hB;
mux_channl_delay <= 4'hB;
mux_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 <= { mux_channl_ready2send, adc_in[ mux_channl_ready2send ] };
SDO_out <= mux_channl_ready2send[3]; // put shift_reg's msb on the output line
// requested -> mux delay
mux_channl_delay <= mux_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
// mux delay -> ready
mux_channl_ready2send <= mux_channl_delay;
// 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
mux_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
我对数据表的理解似乎并不正确。
在手动模式下、如果我在所有 SPI 事务中对相同的通道编号 8 进行采样:
采样和转换与发送在同一个事务上进行。
并不像我从数据表中所理解的那样 — 发送应该在下一次交易中发生-但显然我是错的。

在图中、您可以看到逻辑分析仪的拾取过程。
我有一个模拟多路复用器连接到 ADC 的通道 8。
只有编号为 4 的多路复用器输入连接到 VCC 以获得 FFF 读数。 所有其他外部多路复用器输入都连接到 GND 以提供 000。
当 MUX 开启 3 时、我对 ADC 的通道 8 进行采样以获得 000 ->然后、我在通道 4 的 MUX 上再对通道 8 进行 2 次采样、并获得 FFF 两次->
然后是其他多路复用器输入...
一个 SPI 事务没有延迟(电压在同一事务中转换和发送)、数据表中并未理解。
我错过了什么?
谢谢你。
David。
您好、David:
道歉。 我误解了设置。 我已经阅读了更仔细的这一次。
内部 ADC 多路复用器设置为通道 8。 您还有一个连接到通道 8 的外部多路复用器。 在外部多路复用器上、 输入 4 连接到 VCC(满量程)、而其他输入接地。
您看到的行为是预期行为。 ~在 Δ V CS 的下降沿进行采样和保持。 请参阅下面的时序图(图 1)、特别是采集图和转换图。

以下段落还澄清了时间安排。 转换过程中、器件会输出数据。

我指的延迟是内部信道开关延迟。
此致、
Joel
Joel
我在 图 1 中没有看到。 您 可以看到发送的数据位于 n'CS th 事务中来自同一 n 的 CS 下降沿。
如果您查看 Acquisition 线 — 您可以看到样本从 n-1 的时钟 13 开始、到 n CS 的下降沿结束。
它没有在 SDO 线路上说明 12 位转换结果属于什么 — n 或 (n-1)?
我看了图 51:

在这里您可以清楚地看到一个样本从转换 i2c 事务到发送 i2c 事务的延迟 — 这在实际 IC 中没有发生
如果我有“非假冒“的设备:-) 在我的板...
您的开发板是否具备对此进行测试的能力?
谢谢你。
David。
您好、David:
图 1 和文本的组合(采集和转换)提供了详细信息。
根据数据表、SDO 上的数据属于在转换周期前立即采集的样本。
在本例中、您不会在 SDI 上发送命令来更改器件内部的通道、因此没有内部多路复用器开关延迟、图 51 不适用。
~、输入信号的采集从帧 n 的 SCLK 的第 14 个上升沿开始、在 Δ V CS 下降时结束、以指示帧 n+1 的开始。 采样的转换在 SDO 上的数据移出的同时发生。
如果这有助于更清楚地解释操作、请告诉我。
此致、
Joel
“谢谢你!
芯片如何知道采样和转换后要做什么? 在一种情况下、它会在同一 SPI 采样事务中发送数据 — 在另一种情况下,它会在下一个事务中发送采样数据...? (在当前事务 CS 下降沿开始时正在进行采样...)
这是非常意外的行为... 因为它会发现它是在什么情况下“ 过去“-通道选择在位 10 到位 7 和数据从位 11 发送到 0 :-)
您能在上面修复我的行为模式吗... 只是要清楚你的意思...
谢谢你!
David。
您好、David:
~需要澄清的是、该器件始终在 Δ I CS 的下降沿对多路复用器上选择的电流输入进行采样。 采样、转换和数据输出将在同一 SPI 帧内进行。
但是、 内部多路复用器开关本身会延迟、因此 ADC 将在开关之前对同一通道进行更多采样。
我在下面链接了我同事的一个帖子、这可能有助于进一步澄清、我希望我能在之前就这样说。 我认为重要的一点是区分采样输入信号的实例、以及多路复用器切换以允许对输入信号进行采样的时间。
此致、
Joel
Joel,
很明显的是数据表不清楚:-)
Keith 的解释无助于:
“下面是图 50 中所示的流程:
(a) 帧 n:* SDI:‘frame n +1’的编程、DI10..7 =通道的二进制地址“
(B) Frame n+1:* Mux:选择在‘frame n'(手动模式)中编程的信道此信道将在此获取
并在‘frame n+2’开头采样的帧
本例中未使用、因为我始终使用通道 8 — 内部多路复用器通道无变化。
“(c) Frame n+2:* Sample:对在‘frame n+1’中选择的通道进行采样和转换
我猜在这个事务中发送的数据是同一个事务的采样... -没有明确的写。
数据表并未 说明同一事务上会发生“采样转换和发送“。
很容易将内部多路复用器延迟误认为是采样转换还是发送延迟。
谢谢你。
P.S.我修正了上面的行为模型、以反映我对数据表的新理解...
David。