
结论:基础功能已100%闭环,零错误验证通过
从串口日志和现象可以完全确认:
- PS驱动完全正确:DMA初始化、分段传输、Cache操作、结果比对全部正常,双通道无超时无错误
- PL核心逻辑无误:Sobel卷积、行缓存窗口、输出使能时序完全正确,ForceZeroTest模式下 0/15876 像素错误,软硬件结果完全匹配
- 根因彻底明确:之前反复出现的DMA Halted、传输超时,和PS端、DMA IP本身无关,是新版PL代码(新增TLAST延迟链、输入总计数逻辑)引入的硬件状态机异常,换回经过验证的旧版逻辑后问题自动消失
问题复盘:为什么新版PL会导致DMA锁死
之前的方案一次性引入了「输入总计数、TLAST延迟链、输出使能改判据」多个变量,属于典型的过度修改引入新故障:
- 分段传输会产生2个输入TLAST,延迟链逻辑无法正确区分「分段TLAST」和「帧尾TLAST」,导致内部状态机跑飞
- 输出端异常的总线状态反向传导,干扰了DMA的流控甚至AXI-Lite配置通路,最终表现为通道异常锁死在Halted态
- 纯自回环没有算法逻辑、没有状态机,所以永远正常;一接复杂算法就出问题,本质是PL逻辑的健壮性不足
后续优化路线(最小增量迭代,每步可回退)
建议先将当前版本存档为 V1.0稳定基线,后续所有优化都基于此版本做单点修改,每改一个点验证一次,不再一次性引入大量变量。
阶段1:添加TLAST帧结束信号(仅改1处,其余全不动)
在当前稳定代码基础上,仅用输出像素计数生成TLAST,正好输出15876个有效像素时拉高1拍,逻辑最简、最可控,完全不触碰行缓存和计算逻辑。
核心修改点(直接替换输出逻辑部分即可):
// 新增:输出像素计数器,位宽刚好覆盖15876
reg [14:0] out_pix_cnt;
always @(posedge aclk or negedge aresetn) begin
if (!aresetn) begin
out_pix_cnt <= 15'd0;
m_axis_tvalid <= 1'b0;
m_axis_tdata <= 8'h00;
m_axis_tlast <= 1'b0;
end else if (m_axis_tready) begin
if(s_axis_tvalid && out_en) begin
m_axis_tvalid <= 1'b1;
m_axis_tdata <= sobel_result;
// 计数到最后一个像素时拉高TLAST,同时清零计数器
if(out_pix_cnt == OUT_PIX_TOTAL - 1) begin
out_pix_cnt <= 15'd0;
m_axis_tlast <= 1'b1;
end else begin
out_pix_cnt <= out_pix_cnt + 1'b1;
m_axis_tlast <= 1'b0;
end
end else begin
m_axis_tvalid <= 1'b0;
m_axis_tdata <= 8'h00;
m_axis_tlast <= 1'b0;
end
end
end
验证标准:
- DMA传输仍无超时、无错误
- 像素匹配仍保持0错误
- ILA抓取TLAST与最后一个有效像素严格同拍
阶段2:升级16位长度寄存器,去掉分段传输
TLAST功能稳定后,再做第二步优化:
- Vivado中修改DMA IP,将
Width of Buffer Length Register改为16 - PS端删除分段逻辑,改为单次16384字节整帧传输
- 验证单次传输稳定性,简化代码逻辑
阶段3:进阶优化(按需进行)
- 行缓存改用Block RAM实现,减少寄存器资源占用
- 增加帧间自动复位逻辑,支持连续多帧传输
- 新增错误检测与上报,符合医疗影像可靠性设计要求
补充建议
当前版本已经具备完整的功能闭环,完全可以作为第一阶段成果输出CSDN博客。TLAST、单帧传输属于优化项,不影响核心功能的演示与总结,可以先沉淀成果,再逐步迭代优化,避免陷入「越改越出问题」的死循环。

239

被折叠的 条评论
为什么被折叠?



