|
|
>我在 Vivado 2017.3 中使用 FFT IP 核时遇到了一个棘手的问题
>
> **一、问题现象**
> 1. FFT IP 核可以正常配置和生成(Transform Length = 1024,Pipelined Streaming I/O,Target Clock = 200MHz)
> 2. 仿真可以运行,无语法错误,无编译错误
> 3. **`output.txt` 文件已生成,但内容为空(0 字节)**
> 4. 波形中 `m_axis_data_tvalid` 始终为 0,FFT 核没有输出有效数据
> 5. `s_axis_data_tvalid` 和 `s_axis_data_tready` 均为 1,输入通道握手正常
> 6. 仿真在发送 2 个数据后报错:`Failure: ERROR:add_1 must be in range [-1,DEPTH-1]`
>
> **二、环境信息**
> - Vivado 版本:2017.3
> - 器件:Zynq-7000 (xc7z020clg484-1)
> - FFT IP 版本:9.0 (Rev. 13)
> - 操作系统:Windows 10(用户名含中文字符“黄家乐”)
>
> **三、已尝试的解决方法(均无效)**
> 1. ✅ 修改 FFT 架构(Pipelined Streaming I/O → Automatically Select → Radix-4)
> 2. ✅ Transform Length 改为 1024,Target Clock Frequency 改为 200MHz
> 3. ✅ 删除所有多余的 `$finish`,只保留一个总仿真时间控制
> 4. ✅ Testbench 中 `for` 循环改为 1024 次,`tlast` 在第 1024 个数据时拉高
> 5. ✅ `input.hex` 文件使用绝对路径读取,并确认有 1024 行数据
> 6. ✅ 使用 `wait(m_axis_data_tvalid)` 等待 FFT 输出
> 7. ✅ 将 `#200000` 改为 `#10000` 提前采样
> 8. ✅ IP 核状态显示 `Up-to-date`,无警告
> 9. ✅ `aresetn` 已按 IP 要求保持至少 2 个周期低电平
> 10. ✅ 修改 `Target Clock Frequency` 从 250MHz 改为 200MHz
> 11. ✅ 尝试在 Testbench 中直接生成数据,跳过 `$readmemh` 文件读取
> 12. ✅ 尝试打开 `Open IP Example Design`,但该选项为灰色不可用
>
> **四、核心报错信息(Tcl Console 输出)**
> ```
> mem0=0000
> mem1=000c
> mem1023=fff4
> SEND 0 DATA=0000 TLAST=0
> SEND 1 DATA=000c TLAST=0
> Failure: ERROR:add_1 must be in range [-1,DEPTH-1]
> Time: 127500 ps Iteration: 1
> $finish called at time : 127500 ps
> INFO: [USF-XSim-97] XSim simulation ran for 1000ns
> ```
>
> **五、波形现象**
> - `s_axis_data_tvalid = 1`(输入有效)
> - `s_axis_data_tready = 1`(FFT 准备好接收)
> - `m_axis_data_tvalid = 0`(FFT 无输出)
> - `event_frame_started = 0`(FFT 未检测到帧开始)
> - `i[31:0] = 2`(只发送了 2 个数据,循环提前终止)
> - `s_axis_data_tlast` 始终为 0
>
> **六、怀疑方向**
> 1. `add_1 must be in range [-1,DEPTH-1]` 错误表明 FFT 核内部地址计数器越界,这可能与 IP 核的 `NFFT` 配置或 `Transform Length` 内部计算方式有关。
> 2. `event_frame_started` 始终为 0,说明 FFT 核没有检测到有效的数据帧开始。
> 3. `for` 循环只执行了 2 次就停止,可能是 `mem` 在 `i=2` 时读取到无效数据(`x`),导致 FFT 输入异常。
> 4. 是否有可能是 IP 核的 `Configuration` 和 `Implementation` 标签页中的某些选项(如 `Optional Output Fields`、`Output Ordering`)配置不当,导致输出被禁用?
> 5. Vivado 2017.3 版本是否对 FFT IP 核有已知 Bug?
>
> **七、请求帮助**
> 1. 请问 `ERROR:add_1 must be in range [-1,DEPTH-1]` 这个错误的根本原因是什么?如何解决?
> 2. 是否有 FFT IP 核的官方例程(Example Design)可以分享给我?
> 3. 能否提供一个经过验证的、完整的 1024 点 FFT Testbench 示例代码?
> 4. 是否建议升级 Vivado 版本到 2020.x 或更高版本?
> 5. Windows 用户名包含中文字符是否会影响 IP 核的仿真?
>
> **八、附件**
> - FFT IP 核配置截图(Configuration 和 Implementation 标签页)
> - 仿真波形截图
> - 当前 Testbench 代码
`timescale 1ns/1ps
module tb_fft();
reg aclk = 0;
reg aresetn = 0;
// Input
reg [15:0] s_axis_data_tdata = 0;
reg s_axis_data_tvalid = 0;
wire s_axis_data_tready;
reg s_axis_data_tlast = 0;
// Output
wire [15:0] m_axis_data_tdata;
wire m_axis_data_tvalid;
reg m_axis_data_tready = 1;
wire m_axis_data_tlast;
// Events
wire event_frame_started;
wire event_tlast_unexpected;
wire event_tlast_missing;
wire event_fft_overflow;
// FFT instance
fft_top uut(
.aclk(aclk),
.aresetn(aresetn),
.s_axis_data_tdata(s_axis_data_tdata),
.s_axis_data_tvalid(s_axis_data_tvalid),
.s_axis_data_tready(s_axis_data_tready),
.s_axis_data_tlast(s_axis_data_tlast),
.m_axis_data_tdata(m_axis_data_tdata),
.m_axis_data_tvalid(m_axis_data_tvalid),
.m_axis_data_tready(m_axis_data_tready),
.m_axis_data_tlast(m_axis_data_tlast),
.event_frame_started(event_frame_started),
.event_tlast_unexpected(event_tlast_unexpected),
.event_tlast_missing(event_tlast_missing),
.event_fft_overflow(event_fft_overflow)
);
always #2.5 aclk = ~aclk;
integer i;
integer out_file;
integer count;
initial begin
// 复位
aresetn = 0;
#100;
aresetn = 1;
#20;
// 打开输出文件
out_file = $fopen("output.txt", "w");
$display("开始发送数据...");
// 发送 1024 个数据(直接生成正弦波,不读取文件)
for(i = 0; i < 1024; i = i + 1) begin
@(posedge aclk);
// 用递增数据代替实际正弦波
s_axis_data_tdata <= i[15:0];
s_axis_data_tvalid <= 1;
s_axis_data_tlast <= (i == 1023) ? 1 : 0;
while(!s_axis_data_tready) @(posedge aclk);
end
s_axis_data_tvalid <= 0;
s_axis_data_tlast <= 0;
$display("数据发送完成,等待 FFT 输出...");
// 等待并保存输出
count = 0;
while(count < 1024) begin
@(posedge aclk);
if(m_axis_data_tvalid) begin
$fdisplay(out_file, "%d", $signed(m_axis_data_tdata));
count = count + 1;
end
end
$fclose(out_file);
$display("输出完成!共保存 %d 个数据", count);
$finish;
end
endmodule
|
-
|