Vivado HLS读取FIFO时读使能信号异常问题咨询
FPGA HLS实现FIFO读逻辑问题排查
问题背景
- 基于FPGA开发盖革脉冲积分器(当前调试阶段用Arduino模拟设备)数据读取系统,采集数据存入Vivado FIFO Generator IP生成的FIFO缓冲区,现有RTL模块已实现Arduino数据到FIFO的写入功能
- 需在Vivado HLS中实现FIFO读逻辑,对外提供对接微处理器的AXI接口:读操作流程为拉高读使能
fifo_rd_en,等待N个时钟周期,期间将FIFO输出端口数据存入数组,完成后拉低读使能
原有问题代码
#include "ap_cint.h" #define N 10 int readfifo(int fifo_dout, int1* fifo_rd_en, int data[N]) { #pragma HLS INTERFACE s_axilite port=data #pragma HLS INTERFACE ap_none register port=fifo_rd_en #pragma HLS INTERFACE ap_none port=fifo_dout #pragma HLS INTERFACE s_axilite port=return *fifo_rd_en=1; for(int i=0; i<10; i++) { #pragma HLS PIPELINE off data[i] = fifo_dout; } *fifo_rd_en=0; return 1; }
异常表现
测试时出现两类异常:
fifo_rd_en拉高后可正常读取数据,但始终无法拉低fifo_rd_en始终无法拉高
错误根因
原有实现存在3个核心问题,直接导致时序不符合预期:
- 端口声明方式错误:顶层输出端口使用
int1*指针类型,HLS会默认将指针推断为存储访问类接口,而非普通电平输出端口,综合出的fifo_rd_en信号握手逻辑和预期完全不符,这是电平异常的核心原因 - 无显式时序约束:循环关闭PIPELINE后,HLS不会保证每次循环迭代占用1个时钟周期,循环执行时长不受控,且没有匹配FIFO的读延迟时序(标准非FWFT模式FIFO,读使能拉高1个周期后,输出端口才会送出有效数据)
- 数组接口配置缺失:
data数组仅配置了s_axilite端口,未做数组拆分,HLS可能将数组综合为内部BRAM,导致微处理器无法通过AXI接口正确读取存储的采集数据
修正后实现
#include "ap_cint.h" #define N 10 int readfifo(int fifo_dout, int1 &fifo_rd_en, int data[N]) { #pragma HLS INTERFACE s_axilite port=return bundle=CTRL #pragma HLS INTERFACE s_axilite port=data bundle=CTRL #pragma HLS INTERFACE ap_none register port=fifo_rd_en #pragma HLS INTERFACE ap_none port=fifo_dout #pragma HLS ARRAY_PARTITION variable=data complete int i; // 初始化读使能为低电平,等待信号稳定 fifo_rd_en = 0; wait(); // 拉高读使能,连续读取N个数据 fifo_rd_en = 1; read_loop: for(i = 0; i < N; i++){ #pragma HLS PIPELINE II=1 // 匹配非FWFT模式FIFO的1周期读延迟,打拍后采集有效数据 wait(); data[i] = fifo_dout; } // 读取完成拉低读使能 fifo_rd_en = 0; wait(); return 1; }
修正说明
- 将
fifo_rd_en改为引用类型传参,避免HLS误推断接口类型,保证端口为普通寄存器输出的电平信号 - 所有s_axilite接口添加
bundle=CTRL约束,统一绑定到同一个AXI Lite总线,避免生成多个独立总线导致微处理器访问异常 - 添加
ARRAY_PARTITION约束将data数组完全拆分,综合为寄存器组,保证AXI接口可正常访问所有存储的数据 - 循环添加
PIPELINE II=1约束,保证每次循环迭代间隔为1个时钟周期,读速率和FIFO输出速率匹配 - 显式添加
wait()做周期对齐,匹配FIFO读延迟,保证采集到的是有效输出数据
适配说明
如果使用的FIFO配置为首字下落(FWFT)模式,读使能拉高当周期输出数据即为有效值,可将循环内的wait()移动到data[i] = fifo_dout;语句之后,调整采样时序即可。
内容的提问来源于stack exchange,提问作者gudise
相关产品推荐
相关产品推荐

