VHDL手写FFT:参数化定点RTL实现,摆脱IP核依赖

FFT的VHDL手写实现,我在项目里折腾过好几版,从最简单的16点验证到1024点应用,踩了不少坑也积累了一些经验。这次分享的这套代码,核心特点是完全绕开厂商IP核,N点长度通过顶层参数配置,输入16位有符号定点数,输出对齐到32位。如果你正在做FPGA信号处理,又受制于IP核的许可证和时间控制问题,这篇文章应该能帮你省下不少弯路。

先交代一下设计背景。我手头那个项目需要把时域信号做频谱分析,数据来自16位ADC,点数随时可能调整。用芯片原厂的FFT IP核虽然方便,但有两个痛点:一是IP核生成后不好跨平台移植,换一颗芯片就得重新生成;二是黑盒封装导致定点格式和中间缩放策略完全不可控,调试时出了问题很难定位。于是决定自己用VHDL写一套纯RTL的FFT,把参数化、定点位宽、资源开销都握在自己手里。这套代码后续又重构过两次,现在共享出来的是最稳定的一版。

1. 设计目标与整体方案:手写FFT到底比IP核香在哪

1.1 为什么坚持不用IP核

很多人觉得FFT IP核是免费的,性能又好,自己写纯属浪费时间。这话放在芯片型号固定的量产项目里有一定道理,但如果你需要经常更换FPGA平台,或者想在综合工具之外做更细粒度的时序和位宽控制,手写RTL的价值就出来了。另一个实际原因是,某些场景下FFT点数不是固定值,IP核在综合时就确定死了,每次改点数都要重新生成、重新配置时序约束,而参数化RTL只需要改一个generic重新综合,整个流程顺畅很多。再加上阅读代码就能准确知道每一级蝶形运算的延迟周期,这对设计数据通路握手逻辑非常关键。

当然,手写FFT也有代价。最明显的是旋转因子的生成、存储还有地址调度都得自己写,稍微疏忽就容易出bug。其次,IP核在架构优化上做了很多工作,比如并行蝶形单元、多bank存取,而手写基础版本通常只能做到单蝶形单元复用,吞吐率会低一些。我的建议是:对性能要求不极端、更注重可控性和可移植性的项目,手写是优选;对超高吞吐率应用,还是评估一下IP核或者流水线架构再说。

1.2 基2-DIT架构与“任意长度”的真实含义

FFT算法选型上,我采用的是最经典的基2按时间抽取(DIT)结构。选择DIT的理由很现实:输入按bit反转顺序写入RAM,输出自然顺序,方便后续模块直接读取频谱结果。如果选按频率抽取(DIF),输出是乱序的,还得配一个bit反转模块把顺序纠正回来,多一重麻烦。基4虽然能减少复数乘法次数,但控制逻辑和地址生成复杂度上升一个台阶,对参数化设计不够友好,所以最终定基2。

这里需要把“计算长度可以任意设置”讲清楚,避免误会。标准基2FFT的点数N必须满足2的整数次幂,你不能指望设置一个N=1000还能直接用基2结构跑。代码里N是顶层generic参数,综合前任意指定2的幂次值,比如64、256、1024、65536都行,不需要改内部逻辑。如果项目确实需要非2幂次长度,常规做法是补零到下一个2的幂次,或者改用混合基架构,那是另一套更复杂的方案了,后续可以单独讨论。

1.3 乒乓RAM加单蝶形单元的性价比方案

架构设计上我走过弯路。最初尝试全流水线结构,每个蝶形级分配独立运算单元,数据流式处理,吞吐率确实高,但资源占用感人,N稍微大一点就把BRAM和DSP吃光了。后来改成最简单的“乒乓RAM+单蝶形单元”结构,也就是一个蝶形运算单元配两块数据RAM,交替读写完成各级计算。

这种结构的好处是资源占用非常低,而且控制逻辑清晰。代价是计算时间变成(M×N/2)个蝶形周期,M等于log2(N)。对大多数非实时流处理的频谱分析场景来说,几十微秒的计算延迟完全够用。如果后面项目升级需要更高吞吐率,可以在这个基础上把单蝶形扩展到多个并行蝶形单元,也可以通过加深流水线减少单蝶形延迟周期,这些都是相对独立的优化点,不会推翻整体架构。

2. 定点数规划:16位进、32位出的位宽账怎么算

2.1 输入与旋转因子的定点格式约定

输入是16位有符号数,这一点好处理,但具体定点格式必须提前约定清楚。我按常见ADC数据格式把输入看作Q1.14,也就是1位符号、1位整数、14位小数,数值范围在[-2, 2)之间。12位或14位ADC的数据左对齐到16位之后,格式同样是Q1.14,比较通用。

旋转因子W_N^k = cos(2πk/N) - j·sin(2πk/N),幅度永远不超过1。我用16位有符号数表示,同样采用Q1.14格式。需要注意Q1.14表示不了精确的1.0,最大值是32767/16384≈0.99994,这个量化误差大约3e-5,对大多数信号处理应用来说完全够用。旋转因子的实部和虚部在综合时通过函数预计算并量化,后续所有运算都用这个量化后的值。

2.2 蝶形运算的位宽增长规律与饱和策略

很多人写FFT最容易在这里出问题。蝶形运算包含了复数乘法和加减法,位宽增长是有规律的。每一级蝶形里,两个数据相加,结果最多比输入多1位。所以经过M级蝶形之后,整体位宽最多增长M位。输入16位,如果N最大取65536,M就是16,16加16正好等于32。这也是标题里“输出32位”的真正底气:它保证了最极端N值下也不至于溢出内部数据通路。

我采用的32位数据通路设计是:输入数据符号扩展到32位,旋转因子保持16位Q1.14,复数乘法用32位乘以16位得到48位乘积,再右移14位消除旋转因子的定标,得到32位结果。蝶形加法运算在32位精度下完成,理论上加法结果需要33位表示,我的处理方式是使用一个内部33位累加器,然后做饱和截断。也就是检测结果是否超出32位有符号数范围,超出就钳位到最大值或最小值,没超出就取低32位。饱和处理虽然会引入少量非线性失真,但相比直接截断最高位导致符号翻转,安全性高得多。

2.3 32位输出的定标与工程解释

输出32位定点数之后,使用方需要知道这个数的实际物理含义。我这里约定整个数据通路没有做任何归一化缩放,每一级都保留最大精度,输出32位就是FFT结果的整数定标表示。输入是16位整数格式,旋转因子被去掉14位小数后,输出数值约等于标准FFT结果的2^14倍,这个倍率会在交付文档里写明,由软件端按需缩放。

实际测量下来,N=1024时输入满幅正弦信号,输出频谱主峰和理论值能对上,旁瓣电平也符合预期。如果用户需要浮点结果,在软件端把输出32位整数乘以一个换算系数即可,不需要改FPGA代码。后续如果想在FPGA侧直接输出特定定标格式,比如Q1.30或者Q7.24,可以加一个移位寄存器做位对齐,改动成本不大。

3. 旋转因子ROM与蝶形单元的实现细节

3.1 旋转因子生成的两条路线

旋转因子在FFT里占据核心位置,它的精度直接影响整体频谱质量。我试过两种生成方式:一种是在VHDL里用math_real库的cos和sin函数做初始化,通过一个函数在综合时展开生成ROM内容;另一种是Python脚本离线计算生成.coe或.mif文件,用IP核加载或者用文件读取方式初始化。两种方式我都跑通过,各有优劣。

VHDL函数初始化的优势是参数化方便,改N之后重新综合自动生成新旋转因子表,不需要额外脚本流程。缺点是某些综合工具对VHDL-2008的纯函数生成大数组支持不够好,尤其是在覆盖率分析和跨平台移植时容易出幺蛾子。Python脚本方式则更可控,你可以先在电脑上对比量化前后的频谱差异,确认无误后再生成表文件,但缺点是流程多了一步,改N要重新跑脚本。我的代码最终采用VHDL函数初始化,主要是因为项目需要频繁切换N值,综合流程干净最重要。

旋转因子存储结构上,我没有做象限对称压缩,直接完整存储了N/2个点的cos和sin值,地址范围0到N/2-1。N点FFT中实际出现的旋转因子只有N/2个不同的复数,再往后的值会因为周期性和对称性重复或取反。完整存储换来了最简单的地址映射逻辑,N最大65536时存储量是32768×32位约1Mbit,现代FPGA的BRAM完全可以承受。资源控得极紧的场景可以改成只存N/4个象限利用对称性恢复,这个优化建议放在文章后面详细说明。

3.2 复数乘法的资源优化与最简写法

蝶形运算中的复数乘法(a+jb)(c+jd) = (ac-bd) + j(ad+bc),最直观写法需要4个实数乘法器、2个加法器和2个减法器。我最初就是这样实现的,代码清晰,但每个蝶形消耗4个DSP48。后来意识到,在许多设计中c和d中有一个是1或0的特殊情况可以省略,但FFT通用蝶形的旋转因子大部分不是特殊值,所以没有省头。

还有一种降低乘法次数的高斯优化法:把复数乘法改成3次实数乘法和5次加减法,理论上能减少DSP占用。不过FPGA的DSP块通常是24位或27位乘法器,16位乘法根本用不满一个DSP,省下一个乘法器对资源总量帮助不大,反而让代码可读性变差。所以我的代码里保留4乘法器方案,配合状态机复用,整个FFT核心只用一个复数乘法器,资源占用情况非常理想。N=1024时,全套代码加两块数据RAM加旋转因子ROM,在主流中端FPGA上占用不到20%的BRAM和几个DSP块,留了大量余地给其他信号处理逻辑。

3.3 蝶形加法器的饱和判断逻辑

蝶形加法是p_new = p + W·q和q_new = p - W·q,这里的W·q是经过右移14位后的32位定点数。加法器用33位中间变量做运算,饱和截断逻辑要同时判断正方向和负方向溢出。VHDL里最直接的做法是:先把两个32位操作数符号扩展成33位,做加减法后判断结果是否超出32位有符号范围。如果结果大于最大正数或小于最小负数,输出饱和值,否则输出低32位。

饱和判断组合逻辑会出现在关键路径上,但因为我们用的是低时钟频率加状态机复用架构,时序很宽裕。如果以后改成流水线结构,这里需要注意把饱和判断拆成两级流水,避免成为频率瓶颈。另外,饱和处理的触发概率理论上极低,因为16位输入到32位输出之间留有16位的增长余量,只有N接近65536并且输入信号出现最坏同相叠加时才会触发。实测N=1024时,即使输入满幅方波,频谱结果也完全不会触碰到饱和边界。

4. 状态机、地址生成与完整代码骨架

4.1 顶层实体与参数定义

代码顶层实体把参数全部暴露出来,方便集成时修改。下面是精简后的接口,省略了部分信号:

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity fft_top is generic ( N : integer := 1024; -- FFT点数,必须是2的幂 DATA_WIDTH : integer := 16; -- 输入数据位宽 TW_WIDTH : integer := 16; -- 旋转因子位宽 OUT_WIDTH : integer := 32 -- 输出数据位宽 ); port ( clk : in std_logic; rst_n : in std_logic; start : in std_logic; -- 开始FFT运算 din : in std_logic_vector(DATA_WIDTH-1 downto 0); din_valid : in std_logic; -- 输入数据有效,用于加载RAM dout : out std_logic_vector(OUT_WIDTH-1 downto 0); dout_valid : out std_logic; -- 输出数据有效 done : out std_logic -- FFT运算完成 ); end entity;

内部复用蝶形运算单元,计算流程通过状态机控制。N是generic参数,综合时通过函数计算出级数M和bit反转位数,内部地址生成都基于这两个常量。有一处需要注意:N必须硬性保证为2的幂,我通常会在代码里加一个综合断言(VHDL-2008的assert语句),如果N不是2的幂直接报错,省得综合出一堆错误逻辑后再排查。

4.2 蝶形运算状态机的工作流程

状态机是整个设计的控制核心,我划分成IDLE、LOAD、RUN和DONE四个状态。IDLE状态等待外部start信号;LOAD状态把输入的N个数据按bit反转顺序写入RAM_A,同时RAM_B保持空闲;RUN状态执行M级蝶形运算,每级内循环N/2个蝶形,全部完成后源RAM和目标RAM互换再进入下一级;DONE状态拉高done信号,并输出结果。

RUN状态内部又分成几个子状态,包括发出读地址、等待RAM读数据、执行复数乘法、执行加减法与饱和截断、写回目标RAM。这套流程如果完全串行,每个蝶形大约需要3到4个时钟周期。实际上我在读数据阶段做了一个小流水:把旋转因子ROM的读地址提前一拍送出,这样等到数据从RAM返回时旋转因子也从ROM返回了,省掉了等待时间。这个细节虽然不起眼,但对整体计算时间影响不小,N=1024时能让总周期数减少近30%。

4.3 地址和旋转因子索引的递推计算

地址生成是手写FFT最容易写错的地方。标准DIT算法里,第l级(从0开始计数)的蝶形跨度span等于2的l次方,块大小block等于span乘以2。组内第j个蝶形的两个输入地址分别是group_base加j和group_base加j再加span,旋转因子的索引是j乘以N除以block。

直接用上面的公式做整数除法在综合时会消耗不少逻辑,但如果N是2的幂,除法和乘法都可以转换成移位。我实际写地址生成逻辑时,在状态机里维护一个蝶形计数器,用这个计数器同时算出组号、组内蝶形序号和旋转因子索引。最关键的一点是:旋转因子索引要先把最后一个蝶形的序号右移,再乘以对应的2的幂次,这样不会出现索引越界。曾经有一版代码在这个地方把索引算错,结果高频段的频谱幅度整体错位,排查了好久才定位到是这个移位方向反了。

旋转因子索引算出来后,ROM地址直接等于索引,不需要象限纠正,这也是完整存储N/2个旋转因子带来的便利。如果采用象限压缩存储,这个地方要额外处理实部虚部的符号翻转,逻辑复杂度会上升不少,但能节省约一半ROM容量。

5. 仿真验证与实测排坑

5.1 测试向量生成与误差评估方法

写完代码之后,验证环节必须严格。我的做法是写一个Python脚本生成测试激励:先构造已知频率和幅度的正弦叠加信号,量化成16位定点数据写入文本文件;然后testbench读取这个文件,驱动din端口加载到FFT模块;运算完成后把dout按顺序打印到另一个文本文件;最后用Python脚本读回结果,与NumPy的浮点FFT结果做对比。

对比指标我常用三个:幅度谱的最大相对误差、指定频率点的主峰幅度误差、以及全频带的信噪比SNR。N=1024、输入满幅单频正弦时,实测主峰幅度误差小于0.1%,全频带SNR可以达到65dB以上。这个精度对绝大多数工业信号处理应用绰绰有余。如果项目对精度要求更高,可以考虑增大旋转因子量化位宽到24位,但乘法器资源会翻倍,需要权衡。

5.2 定点误差来源分析与优化

固定点FFT的误差来源主要有三个:输入量化误差、旋转因子量化误差、以及蝶形运算中的乘法截断误差。输入量化误差来自ADC,属于源头噪声,FPGA侧无能为力。旋转因子量化误差在16位下大约是10^-5量级,它的影响会随着级数累积,N越大越明显。乘法截断误差则是每次都把中间乘积右移14位丢弃低位造成的,这个误差是随机的,不会累积放大,但会抬高噪声底。

如果想进一步提升精度,最有效的优化点是把乘法后的右移操作改成舍入而不是直接截断,也就是经典的四舍五入。VHDL里实现舍入很简单:右移之前先加上最高被丢弃位的值,即加(1 << (SHIFT-1)),然后再右移。我做过对比,这个改动让SNR提升了大约3dB,代价只是一点点组合逻辑。更激进的做法是块浮点结构,在每一级检测数据整体增长,有溢出风险时统一右移,但那个控制逻辑就复杂多了。

5.3 常见问题速查表

问题现象可能原因解决方法
输出频谱频率轴镜像输入bit反转地址写错或漏做检查LOAD状态地址生成,确认bit反转函数正确
高频段幅度整体偏低旋转因子ROM地址索引算错在testbench中打印ROM地址和期望值对比,重点检查移位方向
噪声底过高乘法右移采用直接截断改成加半舍入后再右移
综合后时序不收敛蝶形加法饱和判断路径过长把饱和判断拆流水级,或放宽时钟约束
改N后结果仍像旧点数生成ROM的初始化函数没有重新综合确认综合工具正确重新展开函数,必要时强制重建工程
输出数据顺序不对DIT输入bit反转与输出顺序不匹配确认输入是bit反转序、输出自然序,或反过来

这些坑我基本都踩过一遍,尤其是旋转因子索引和输入bit反转这两类问题,纯看代码很难发现波形错在哪。建议从一开始就在testbench里做完整的输入输出顺序核对,不要只盯频谱幅度。频谱幅度看起来很正常但顺序错位的情况是完全可能发生的,毕竟FFT结果的能量分布对顺序错误不敏感。

最后一件事想强调一下。手写FFT最怕“看起来能跑就算完成”的心态,定点格式和状态机时序的验证一定要做到位。我的习惯是每次改完N参数,都会用Python脚本重新生成测试向量,跑完对比信噪比,再把频谱图拉出来看一遍,宁可多花10分钟确认,也不把隐患留给后续集成。这套代码后续还可以往两个方向扩展:一个是对旋转因子ROM做象限压缩,把存储资源砍掉一半;另一个是把单蝶形单元包装成流水线结构,配合多块RAM换取更高吞吐率。不管往哪个方向走,基础的地址生成和位宽规划都不用推翻,这也是当初把参数化设计放在第一位的原因。

相关新闻

Claude Skill 下载安装完全指南:三种方法与排错思路

Claude Skill 下载安装完全指南:三种方法与排错思路

我估摸着不少人和我一样&#xff0c;第一次听到"Claude Skill"这四个字的时候&#xff0c;脑子里冒出来的问题就一个&#xff1a;这到底是个插件、一套配置&#xff0c;还是一个能自动干活的小助手&#xff1f;等你真正打开搜索框开始找下载安装教程&#xff0c;又会…

2026/10/20 18:58:59 阅读更多 →
浏览器驱动Agent实战:从感知到执行,效率重构的完整打法

浏览器驱动Agent实战:从感知到执行,效率重构的完整打法

2026年9月15日&#xff0c;下午两点多&#xff0c;运营同事拿着一张截图找到我&#xff0c;说竞品官网改版了&#xff0c;他们手工维护了半年的价格表全部要重来。我一边听一边打开终端&#xff0c;把浏览器驱动Agent的任务描述从"按SKU抓取描述和价格"改成了"打…

2026/10/20 18:58:59 阅读更多 →
C#调用FFmpeg实现文案自动转视频:语音合成与图片合成全流程解析

C#调用FFmpeg实现文案自动转视频:语音合成与图片合成全流程解析

简介&#xff1a;一份C#实现文案转语音并与图片合成视频的完整VS2013工程&#xff0c;面向需要批量生成配音短视频、图文卡点视频的.NET开发者、自媒体运营及课件制作者。项目调用百度API将首行文案合成为配音文件&#xff0c;再依据语音时长计算出所需图片帧数&#xff0c;最后…

2026/10/20 18:58:59 阅读更多 →

最新新闻

模型量化如何影响推理性能?实战解析原理、选型与问题排查

模型量化如何影响推理性能?实战解析原理、选型与问题排查

在AI推理优化这条路上&#xff0c;量化是我见过投入产出比最高的手段。很多人以为量化就是把模型从FP32变成INT8&#xff0c;体积缩小、推理变快&#xff0c;但实操后才发现&#xff0c;AI模型量化对推理性能的影响并不只有正向&#xff1a;有时速度反而下降&#xff0c;精度却…

2026/10/20 20:20:51 阅读更多 →
基于Simulink的23自由度分布式电驱动整车动力学模型搭建与仿真

基于Simulink的23自由度分布式电驱动整车动力学模型搭建与仿真

做分布式电驱动车辆的控制&#xff0c;最头疼的问题就是你手上的整车模型到底该建多细。我这次在Matlab Simulink里完整搭了一套23自由度整车动力学模型&#xff0c;把车身六个方向的运动、四个车轮的垂向跳动、车轮旋转、转向系统、以及分布式驱动链条的扭转自由度全部拉进来了…

2026/10/20 20:20:51 阅读更多 →
用JSON和Python命令行构建个人技能管理工具:从数据建模到实践

用JSON和Python命令行构建个人技能管理工具:从数据建模到实践

1. 为什么需要技能管理工具&#xff1a;需求拆解与设计取舍上周末想更新简历&#xff0c;结果发现我根本说不清“现在到底会什么”。十几项技能分散在旧简历、脑图、收藏夹和一摞笔记本里&#xff0c;有的早已过期&#xff0c;有的只停留在“看过教程”的阶段&#xff0c;还有的…

2026/10/20 20:20:51 阅读更多 →
企业微信回调验证与AES加解密:.NET开发者接入指南

企业微信回调验证与AES加解密:.NET开发者接入指南

接手过几个企业微信自建应用的项目&#xff0c;每次新人对接时几乎都会卡在同一个地方&#xff1a;管理后台保存“接收消息服务器”配置时提示URL验证失败&#xff0c;或者明明验证过了&#xff0c;消息却一直推送不进来。这个环节看着只是填几个参数&#xff0c;背后实际上是一…

2026/10/20 20:20:51 阅读更多 →
vLLM Prefix Caching 原理:如何用 Paged KV 消除重复计算

vLLM Prefix Caching 原理:如何用 Paged KV 消除重复计算

先说一个我遇到过的情况。某个线上推理服务&#xff0c;所有请求都带着同一段两千多字的 system prompt&#xff0c;并发一上来&#xff0c;GPU 利用率看着很高&#xff0c;但真正对用户有用的计算没多少——大部分算力在一遍遍重复计算同一段内容的 K 和 V。很长一段时间里&am…

2026/10/20 20:20:51 阅读更多 →
用Design.md构建符合产品风格的原型设计:设计令牌实战指南

用Design.md构建符合产品风格的原型设计:设计令牌实战指南

上周跟某团队聊原型评审&#xff0c;对方把三个页面的设计稿拍在我面前&#xff0c;主色蓝就出现了五种&#xff0c;没有两个颜色值相同。评审会开了一个小时&#xff0c;快一半时间在争论“这个蓝到底是不是我们品牌那个蓝”。原型阶段最让人心累的从来不是画得快不快&#xf…

2026/10/20 20:19:47 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →