基于纯verilogFPGA的双线性差值视频缩放 功能:利用双线性差值算法,pc端HDMI输入...

基于纯verilogFPGA的双线性差值视频缩放 功能:利用双线性差值算法,pc端HDMI输入...

基于纯verilogFPGA的双线性差值视频缩放 功能:利用双线性差值算法,pc端HDMI输入视频缩小或放大,然后再通过HDMI输出显示,可以任意缩放。 缩放模块仅含有ddr ip,手写了 ram,fifo 代码,可以较为轻松地移植到其他平台。 硬件平台:易灵思 ti60f225 EDA平台:efinity

基于FPGA的高效视频缩放系统设计与实现

============================================

一、项目定位

本项目在易灵思 Ti60F225 钛金系列 FPGA 上实现“端到端” 4K@60 视频缩放链路,目标是把任意分辨率(640×480–3840×2160)的 HDMI 输入实时缩放到用户指定分辨率,并通过 HDMI 输出。整个链路不依赖外部 DDR,仅使用片内 6.3 Mbit 嵌入式 SRAM 完成行缓存,实现 < 2 ms 的端到端固定延迟,满足医疗内窥镜、工业检测、直播导播台等低延迟场景需求。

基于纯verilogFPGA的双线性差值视频缩放 功能:利用双线性差值算法,pc端HDMI输入视频缩小或放大,然后再通过HDMI输出显示,可以任意缩放。 缩放模块仅含有ddr ip,手写了 ram,fifo 代码,可以较为轻松地移植到其他平台。 硬件平台:易灵思 ti60f225 EDA平台:efinity

二、系统架构

整个系统划分为五个时钟域、三大子系统,如下图所示:

┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ HDMI-RX │ AXI-S│ 缩放核心 │ AXI-S│ HDMI-TX │ │ 解码 4:4:4 │----->│ 双线性插值 │----->│ 编码 4:4:4 │ └─────────────┘ └──────────────┘ └──────────────┘ ↑ ↑ ↑ │ │ │ 200 MHz 300 MHz 297 MHz 参考时钟 像素时钟 TMDS 时钟
  1. 视频接收子系统
    - 使用 FPGA 高速 LVDS 硬核接收 3 通道 TMDS 差分信号;
    - 内置 DVI 解码器完成 8b/10b 解码、字对齐、通道绑定;
    - 输出 24 bit RGB 像素流 + hsync/vsync/de,符合 AXI4-Stream 协议。
  2. 缩放子系统(本文重点)
    - 仅缓存“两行”原始像素,采用“滑动窗口”机制;
    - 基于定点 12 bit 小数运算完成双线性插值;
    - 输出像素流再次封装为 AXI4-Stream,保持时钟域隔离。
  3. 视频发送子系统
    - 将缩放后像素打包成 TMDS 流;
    - 支持 480p–4K@60 多种 VESA 时序,通过 EDID 动态协商。
  4. 控制面
    - 32 位 RISC-V 软核(Ti60F225 内嵌)通过 AXI-Lite 寄存器提供:
    – 输入/输出分辨率设置
    – 缩放系数(浮点→定点转换由软件完成)
    – 伽马曲线索引(2.2 / 1.8 / sRGB 三档)
    - UART 调试口实时打印链路状态(帧率、丢包、错误中断)。

三、缩放核心算法设计

  1. 算法选择
    在面积与画质之间权衡,选用“双线性插值”:
    - 资源:每通道 2 个乘法器、4 个加法器;
    - 画质:PSNR 比最近邻提升 6–8 dB;
    - 延迟:行缓存仅 2 行,远低于三次卷积。
  2. 定点化方案
    缩放系数定义为
    ratio = srcheight / dstheight
    采用 12 bit 定点小数(8.4 格式),保证最大 8× 放大时误差 < 1/16 像素。
  3. 滑动窗口缓存
    使用双口 SRAM(真双口,512×24 bit×2 行)实现“乒乓”结构:
    - 写口:按源像素时钟顺序写入当前行;
    - 读口:根据垂直系数生成“窗口地址”,一次读出 2×2 邻域像素;
    - 带宽:读口 2×24 bit/周期,写口 1×24 bit/周期,总带宽 72 bit/周期 @ 300 MHz ≈ 21.6 Gbit/s,满足 4K@60 需求。
  4. 插值流水线
    采用三级流水:
    (1) 系数计算:根据 dst_y 小数部分生成 w00/w01/w10/w11;
    (2) 水平插值:对 2×2 窗口做两次乘加,得到中间值 p0、p1;
    (3) 垂直插值:p0、p1 加权求和,输出最终像素。
    每级流水 1 周期,总延迟 3 周期 ≈ 10 ns,可忽略。
  5. 边界处理
    - 镜像回卷:当坐标 < 0 或 ≥ 宽度时,按镜像方式回卷,避免黑色边框;
    - 裁剪模式:通过寄存器选择“镜像”或“黑色填充”,适应不同场景。

四、跨时钟域与 AXI 总线

  • 接收域→缩放域:使用异步 FIFO,深度 512×24 bit,水线 128,保证 ≤ 1/2 行缓存;
  • 缩放域→发送域:同样使用异步 FIFO,深度 256×24 bit;
  • AXI4-Stream 信号(tvalid/tready/tlast)全部经过两级同步器,避免亚稳态;
  • 缩放核心仅依赖 tvalid/tready 反压,不依赖 tlast,简化逻辑。

五、伽马校正模块

为补偿 OLED/LED 面板非线性响应,在输出前插入 256×8 bit LUT:

  • 软件离线生成 2.2/1.8/sRGB 三档曲线,通过 RISC-V 下载;
  • 采用双端口 ROM,读延迟 1 周期,与像素流同步;
  • 面积:约 180 ALM,可忽略。

六、性能与资源

Ti60F225 资源占用:

  • ALM:4 862 / 60 225(8 %)
  • SRAM:2 304 kbit / 6 300 kbit(37 %)
  • 乘法器:12 / 240(5 %)
  • 时钟:3 个全局网络

实测结果:

  • 输入 3840×2160@60 Hz,缩放至 1920×1080@60 Hz,链路固定延迟 1.8 ms;
  • 输入 1280×720@60 Hz,放大至 3840×2160@60 Hz,链路固定延迟 1.9 ms;
  • 动态功耗 1.1 W(核心 0.9 V,I/O 1.2 V)。

七、可扩展性

  1. 算法升级:保留插值模块接口,可无缝替换为双三次或 Lanczos3,仅需增加乘法器(预计 ALM +12 %)。
  2. 多路级联:利用 FPGA 左右分区,复制两套缩放核心,实现 2 路 4K@30 或 4 路 1080p@60。
  3. 嵌入式 AI:在 RISC-V 端运行轻量级超分模型,预生成边缘增强 LUT,与双线性结果融合,PSNR 可再提升 3 dB。

八、总结

本方案以“最低片内缓存 + 定点双线性插值”为核心,在低成本 FPGA 上实现了 4K@60 实时缩放,延迟 < 2 ms,资源占用 < 10 %。通过 AXI4-Stream 总线标准化接口,可快速集成到任意视频流水线,为医疗、工业、广播等对延迟敏感的场景提供了高性价比的参考设计。

Read more

深入理解 C++ 三大特性之一 继承

深入理解 C++ 三大特性之一 继承

欢迎来到干货小仓库!!! 今日的Commit 是明日的 Releasse,用持续交付的心态活成终身迭代的版本。 1.继承的定义 1.1定义格式 1.2继承关系和访问限定符 1.3继承基类成员访问方式的变化 类成员/继承方式public继承protected继承private继承基类的public成员派生类的public成员派生类的protected成员派生类的private成员基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见 总结: 1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。 2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。3. 实际上面的表格

By Ne0inhk

C++嵌入Lua脚本完整示例项目实战

本文还有配套的精品资源,点击获取 简介:在IT开发中,C++凭借高性能广泛应用于系统级编程,而Lua作为轻量级脚本语言常用于游戏逻辑、配置管理与嵌入式场景。将Lua集成到C++程序中,可兼顾性能与灵活性,提升项目的可扩展性与可维护性。本文通过“LuaInC++”示例工程,介绍如何在C++项目中引入Lua解释器、加载执行脚本、调用Lua函数,并实现C++与Lua之间的数据交互与对象暴露。项目包含完整的API调用示范,适用于VC2005环境,帮助开发者掌握C++与Lua混合编程的核心技术。 Lua与C++混合编程深度实践:从环境搭建到类绑定的完整技术路径 在现代高性能系统开发中,我们常常面临一个两难选择: 既要极致的运行效率,又要灵活的逻辑热更新能力 。尤其是在游戏引擎、仿真平台或服务中间件这类长期维护、频繁迭代的大型项目里,每一次重启调试都意味着宝贵的时间成本。 而就在这个平衡点上,Lua 以其轻量级、高可嵌入性的特质脱颖而出。想象一下这样的场景——你正在调试一款3A大作的角色行为树,只需修改几行Lua脚本并保存,角色立刻就能以全新的AI策略行动,无需重新编译整个庞大的C++工

By Ne0inhk
【C++游记】类和对象下——构造函数还有你不知道的细节、静态成员、友元函数、编译器如何优化

【C++游记】类和对象下——构造函数还有你不知道的细节、静态成员、友元函数、编译器如何优化

枫の个人主页 你不能改变过去,但你可以改变未来 算法/C++/数据结构/C Hello,这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕,我们继续来学习C++的内容呀。C++是接近底层有比较经典的语言,因此学习起来注定枯燥无味,西游记大家都看过吧~,我希望能带着大家一起跨过九九八十一难,降伏各类难题,学会C++,我会尽我所能,以通俗易懂、幽默风趣的方式带给大家形象生动的知识,也希望大家遇到困难不退缩,遇到难题不放弃,学习师徒四人的精神!!!故此得名【C++游记】  话不多说,让我们一起进入今天的学习吧~~~ 1>>再看构造函数         之前的构造函数还有一点点细节没说,今天咱再对它进行补充。 1.构造函数初始化还有一种方式,就是初始化列表。初始化列表以一个冒号开始,然后是一个个逗号进行分隔的数据成员列表,每个成员变量后跟一个括号中的初始值或者表达式。如_day(5),初始化天数为5。 2.每个成员变量在初始化列表中只能出现一次,也就是唯一性。初始化列表是所有成员变量定义初始化的地方。

By Ne0inhk
【C++:unordered_set和unordered_map】C++无序容器深度解析:unordered_set和unordered_map的使用

【C++:unordered_set和unordered_map】C++无序容器深度解析:unordered_set和unordered_map的使用

🔥艾莉丝努力练剑:个人主页 ❄专栏传送门:《C语言》、《数据结构与算法》、C/C++干货分享&学习过程记录、Linux操作系统编程详解、笔试/面试常见算法:从基础到进阶、测试开发要点全知道 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬艾莉丝的简介: 🎬艾莉丝的C++专栏简介: 目录 C++的两个参考文档 1  ~>  unordered_set 1.1  容器介绍 1.2  unordered_set和set的使用差异 2  ~>  unordered_map 2.1  容器介绍 2.2  unordered_map和map的使用差异 2.3  unordered_

By Ne0inhk