2026年FPGA校招,手撕Verilog实现AXI4-Stream实时中值滤波,3x3窗口排序网络怎么设计流水线才能不丢帧?

开放9 回答 28 浏览

最近在准备2026年FPGA校招,看到很多面经提到手撕Verilog实现实时图像处理模块。我遇到一个题:用AXI4-Stream接口实现3×3中值滤波,要求流水线设计不能丢帧。排序网络到底用冒泡排序还是奇偶排序?行缓冲怎么搭才能不浪费BRAM?求大佬指点具体流水线划分和时序控制细节。

分享:
  • FPGA萌新上路

    说实话,校招手撕题里让你写完整AXI4-Stream中值滤波的很少见,更多是考你对流水线握手逻辑的理解。排序网络这块,你提的冒泡和奇偶排序其实都不是最优选——冒泡排序在3×3窗口里延迟确实大,每个时钟只能冒一个值,9个数据要9个周期才能排好,后续流水线根本跑不满。奇偶排序虽然并行度好一点,但实际综合出来资源比双调排序高,因为比较器对之间的连接更乱。个人建议你直接上双调排序网络,3×3窗口只需要4级比较器(第1级排4对,第2级排4对,第3级排2对,第4级排1对),9个数据7个周期就能出中值,关键是流水线深度固定,时序很好收敛。行缓冲这块有个坑:很多人习惯用移位寄存器链搭3行,但这样每行宽度是图像宽度,BRAM使用量会翻倍。正确做法是用双端口BRAM做环形缓冲,只存两行半的数据,写地址每来一个valid就加1,读地址比写地址提前一个窗口宽度,这样BRAM深度只需要图像宽度的1.5倍左右,省一半资源。流水线分级我倾向于分成四级:第一级收当前行数据并更新BRAM,第二级从BRAM读出9个窗口像素并寄存,第三级跑双调排序网络,第四级输出中值并生成valid。反压处理有个常见误区:很多人只在输出端做ready/valid握手,但中间级如果被反压,BRAM读地址会乱套。正确做法是每级都加一个深度为2的FIFO做弹性缓冲,这样反压只影响本级,不会往上追。你准备的时候可以画一个详细的时序图,标清楚每级valid和ready的依赖关系,面试官很吃这套。你们学校实验室有提供标准AXI4-Stream VIP吗?如果没有的话建议你自己写一个简单的driver,调试起来会快很多。

  • 单片机初学者

    排序网络别纠结,3×3窗口用双调排序比奇偶排序省逻辑,行缓冲用BRAM双端口做成环形缓冲就够了,别用移位寄存器链。流水线分三级:填充、排序、输出,每级加个深度1的reg做握手中转,反压不会丢帧。

  • Verilog小白学编程

    中值滤波的流水线设计,核心在于排序网络的行缓冲与握手逻辑不能割裂开想。我建议你把行缓冲和排序网络合并成两级流水:第一级用双端口BRAM做环形缓冲,在写入当前像素的同时,从BRAM读出前两行对应列的三个像素,拼成3×3窗口的三列数据并寄存;第二级把这三列数据通过一个三级流水线的双调排序网络排序,输出中值。这样不需要额外的行缓冲填充阶段,每来一个valid就能处理一帧,反压时只要在输出端加一个深度为2的FIFO,BRAM的读地址只受写地址影响,不会因为反压而错乱。你面试的时候可以强调这种设计减少了总流水线级数,但需要提前算好BRAM读地址的偏移量,不然会读到旧数据。另外,AXI4-Stream的tready信号一定要在排序网络处理完当前数据后再拉高,否则tvalid和tready同时有效时窗口数据还没准备好。你目前准备的仿真环境是Vivado还是Modelsim?如果是Vivado的话可以用自带的AXI Verification IP来测握手时序。

  • 电路板玩家小王

    行缓冲这块,很多人一上来就想着用移位寄存器链去存三行数据,但那样每行宽度一上来,BRAM资源直接翻倍,不划算。你可以用双端口BRAM做环形缓冲,只存两行半的数据,写地址每来一个valid就加1,读地址用写地址减去图像宽度再减去当前列偏移,这样每拍都能读到对应窗口的三列。排序网络别纠结冒泡排序了,3×3窗口下9个数据用双调排序,4级比较器7个周期就出中值,流水线深度固定,时序好收敛。反压处理有个小技巧:在排序网络输出端加一个深度为2的FIFO,tready信号等排序网络处理完当前数据再拉高,这样tvalid和tready同时有效时窗口数据不会乱。你面试时可以提一下,这种设计把行缓冲和排序网络合并成两级流水,减少了总级数,但BRAM读地址的偏移量要提前算好,不然会读到旧数据。另外,你目前是准备用Xilinx的器件还是Intel的?不同厂家的BRAM读写时序稍有差异,读延迟会影响地址计算。

  • Debug小白

    说实话,校招手撕题里让你写完整AXI4-Stream中值滤波的并不多见,更多是考你对流水线握手逻辑的理解。排序网络这块,你提的冒泡和奇偶排序其实都不是最优选——冒泡排序在3×3窗口里延迟确实大,每个时钟只能冒一个值,9个数据要9个周期才能排好,后续流水线根本跑不满。奇偶排序虽然并行度好一点,但实际综合出来资源比双调排序高,因为比较器对之间的连接更乱。个人建议你直接上双调排序网络,3×3窗口只需要4级比较器(第1级排4对,第2级排4对,第3级排2对,第4级排1对),9个数据7个周期就能出中值,关键是流水线深度固定,时序很好收敛。行缓冲这块有个坑:很多人习惯用移位寄存器链搭3行,但这样每行宽度是图像宽度,BRAM使用量会翻倍。正确做法是用双端口BRAM做环形缓冲,只存两行半的数据,写地址每来一个valid就加1,读地址用写地址减去图像宽度再减去列偏移,这样每拍都能读到对应窗口的三列数据。流水线建议分三级:第一级做行缓冲填充和窗口数据拼凑,第二级做排序网络计算,第三级输出中值并处理AXI4-Stream握手。反压时注意,tready信号必须在排序网络处理完当前数据后再拉高,否则tvalid和tready同时有效时窗口数据还没准备好。你可以在输出端加一个深度为2的FIFO,这样反压不会丢帧,而且BRAM的读地址只受写地址影响,不会因为反压而错乱。面试官一般会追问:如果图像宽度不是2的幂次,BRAM地址该怎么算?你可以回答用模运算器或者预先算好行末尾的地址跳变点。你目前是准备手撕代码还是面试官会问你原理?

  • 电子入门生

    双调排序网络4级比较器搞定3×3,比冒泡省周期。行缓冲用BRAM双端口做环形缓冲,写地址自增,读地址用写地址减图像宽度再减列偏移,别用移位寄存器链浪费资源。反压加个深度2的FIFO就行。

  • 电子工程学生

    冒泡排序在3×3窗口下确实延迟大,9个数据串行排完要9个周期,流水线根本跑不满。校招手撕题一般不会让你写完整AXI4-Stream中值滤波,更多是考你握手信号怎么处理——tvalid和tready的时序关系是重点。排序网络直接上双调排序,4级比较器7个周期出结果,流水线深度固定。行缓冲用双端口BRAM做环形缓冲,只存两行半数据,写地址每拍加1,读地址用写地址减图像宽度再减列偏移,这样每拍都能读到三列数据。反压处理加个深度2的FIFO就行。你目前是在准备哪个方向的岗位?图像还是通信?

  • 编程小菜

    讲真,校招面试官很少指望你能当场写出完整的中值滤波模块,他们更想看你对流水线握手和资源取舍的理解。排序网络这块,冒泡排序在3×3窗口里确实不实用——每个时钟只能冒一个值,9个数据排完要9个周期,后续流水线空等,帧率一高就丢帧。奇偶排序并行度好一点,但综合后比较器对之间的连接很乱,时序难收敛。个人建议你直接上双调排序网络,3×3窗口只需要4级比较器(第1级排4对,第2级排4对,第3级排2对,第4级排1对),9个数据7个周期出中值,流水线深度固定,时序很好收敛。行缓冲这块有个常见坑:很多人用移位寄存器链搭3行,每行宽度是图像宽度,BRAM使用量直接翻倍。正确做法是用双端口BRAM做环形缓冲,只存两行半的数据,写地址每来一个valid就加1,读地址用写地址减图像宽度再减当前列偏移,这样每拍都能读到对应窗口的三列。流水线可以分三级:第一级行缓冲填充,第二级排序网络计算,第三级结果输出。每级之间加个深度1的reg做握手中转,tready信号等排序网络处理完当前数据再拉高,这样tvalid和tready同时有效时窗口数据不会乱。反压处理有个小技巧:在排序网络输出端加一个深度为2的FIFO,当反压来时,FIFO能缓存两拍数据,给流水线足够时间排空。你面试时可以提一下,这种设计把行缓冲和排序网络合并成两级流水,减少了总级数,但BRAM读地址的偏移量要提前算好,不然会读到旧数据。另外,你目前是准备用Xilinx的器件还是Intel的?两家BRAM的读写时序略有差异,影响读地址计算。

  • EE学生一枚

    排序网络这块,除了双调排序,其实奇偶排序在3×3窗口下也有用武之地——如果你对资源不敏感但对延迟敏感,奇偶排序3级比较器就能出结果,比双调排序少1级。不过奇偶排序的缺点是比较器对之间的连接更乱,综合后时序容易出问题,而且对非2的幂次数据量适配性差。行缓冲用移位寄存器链也不是完全不能用,如果你图像宽度很小(比如128以内),用寄存器搭三行反而比BRAM省资源,因为BRAM有最小容量限制,小宽度下利用率很低。流水线划分上,我建议你把行缓冲填充和排序网络计算合并成两级流水:第一级用双端口BRAM做环形缓冲,在写入当前像素的同时,从BRAM读出前两行对应列的三个像素,拼成3×3窗口的三列数据并寄存;第二级把这三列数据通过一个三级流水线的排序网络排序,输出中值。这样不需要额外的行缓冲填充阶段,每来一个valid就能处理一帧,反压时只要在输出端加一个深度为2的FIFO,BRAM的读地址只受写地址影响,不会因为反压而错乱。不过有个风险点:如果你的图像尺寸是动态变化的(比如来自不同分辨率的摄像头),环形缓冲的地址计算就需要额外配置寄存器,否则读地址会算错。你目前的图像分辨率是固定的还是可变的?这个会影响你的设计选择。

登录后可在本页底部提交回答

提问者

极简码农查看主页

描述场景与已尝试方案,更容易获得有效解答

浏览「其他」

相关问题

同分类问答

提问建议

  • 标题写清核心疑问,避免「求助」「请问」等空泛用语
  • 正文补充环境、版本、报错信息或截图
  • 先搜索本站是否已有相近问题,减少重复提问
  • 若与课程相关,请标明课时或章节便于讲师定位

技术问答

问完之后的闭环

  • 关联课程精学高频问题往往对应章节,建议回到课程补基础。
  • 产出与互助解决过程可写成笔记,帮助后续同学。

探索全站