尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FPGA核脉冲梯形成型:从MATLAB仿真到Verilog实现的工程实践

FPGA核脉冲梯形成型:从MATLAB仿真到Verilog实现的工程实践 做核脉冲数字处理这大半年我前前后后推倒过三版梯形成型的 Verilog 代码。算法本身不算难难的是从 MATLAB 浮点模型落地到定点 RTL 之后一个个歪斜的平顶、莫名的毛刺、飘来飘去的基线会反复教你做人。这篇博客就围绕FPGA 核脉冲梯形成型这条主线把从 MATLAB 浮点验证到 50MHz 采样率部署的完整链路写下来包括算法推导、定点化策略、Verilog 模块划分、资源约束和调试踩坑记录给正在做核信号采集、能谱测量或者数字多道处理的同行一个可以直接参考的工程样本。先说清楚适用范围。这里的输入信号是探测器经过电荷灵敏前置放大器之后出来的指数衰减脉冲时间常数从几百纳秒到几十微秒不等。硬件平台是 50MSPS 的 ADC 加一块 Artix-7 级别的 FPGAVerilog 实现的核心模块包括极零相消、双积分器、延迟差分成形、触发与复位控制。整个系统做完之后从探测器信号进来到 FPGA 输出梯形平顶的幅度值延迟只占几个时钟周期对后续多道脉冲幅度分析来说完全够用。1. 核脉冲为什么非要成形指数尾巴带来的三个痛1.1 原始信号看着干净实际上全是麻烦探测器和前置放大器出来的信号理想情况下长这样x(t) A · exp(-t / τ)其中 A 和入射粒子的能量成正比τ 是前端电路和探测器共同决定的指数衰减时间常数。MATLAB 里画出来是一条干净平滑的指数曲线看起来人畜无害但真放到实际测量里这条尾巴带来的麻烦一个比一个头疼。第一个麻烦是尾堆积。指数衰减在数学上永远到不了零前一个脉冲的尾巴会一直叠到后面的脉冲上。高计数率场景下两个事件间隔很短时后一个脉冲的起点就踩在前一个脉冲的尾巴上梯形平顶被抬高测出来的能量系统性偏高。这个误差不是固定的和事件间隔有关很难用软件后处理完全扣除。第二个麻烦是基线波动。闪烁体探测器的脉冲本来就符合泊松统计事件间隔随机分布叠加在探测器前置放大输出上的残留尾巴不断变化相当于基线在慢慢漂。如果你不做成形直接做峰值提取基线的慢漂移就会变成能量谱的峰位漂移和峰展宽。第三个麻烦是信噪比和分辨率的矛盾。原始指数脉冲的上升沿非常陡直接采峰值对噪声和触发时刻极其敏感。想要降噪就得把信号拉宽但拉得越宽堆积越严重死时间越大。这个矛盾在模拟成形时代只能靠一堆电阻电容调出一个折中值到了数字域我们有了更自由的选择。1.2 梯形为什么比高斯和 CR-RC 成形更顶用模拟电路时代最常见的是 CR-RC、CR-(RC)ⁿ 以及高斯成形本质是用无源或有源滤波网络把指数尾巴整形成近似高斯或准高斯脉冲。它们也能降噪但有几个天然短板成形时间由硬件电阻电容决定想换参数得改电路输出脉冲形状对探测器电荷收集时间的起伏敏感容易产生弹道亏损温漂和元件公差也会导致成形参数随时间变化。梯形成型的输出是一个两边对称的梯形分为上升段、平顶段、下降段。和传统成形相比它有几个很实际的优势。第一平顶段天然抗弹道亏损。不同粒子在探测器内的径迹位置不同电荷收集时间会有几十纳秒到几微秒的扩展。如果做成高斯或尖峰形状这个扩展会直接反映成峰高的损失而梯形有一段足够宽的平顶只要平顶时间大于收集时间的扩展范围幅度基本不变。第二成形参数可以随时改。上升时间和平顶时间在数字域里就是两个寄存器换探测器、换计数率环境、换能量范围改寄存器值就行不用重新改硬件。第三数字实现没有温漂和老化问题。这也是为什么现在越来越多的核电子学系统甚至很多便携式γ谱仪都开始走数字化多道 数字成形路线。1.3 三个关键参数到底怎么选梯形成型有三个绕不开的参数上升时间 l、平顶时间 m以及总成形时间 2lm。这里 l 和 m 都不是时间而是采样点数。在 50MHz 采样率下1μs 正好对应 50 个采样点算起来非常直观。上升时间 l 决定了系统的降噪能力。梯形本质上等效于一个时域滤波窗口l 越长窗口内平均的采样点越多高频白噪声被压得越狠。代价是脉冲总宽度变长堆积处理能力下降。平顶时间 m 的选取主要看探测器的电荷收集时间。对闪烁体探测器发光衰减和光电子收集的时间晃动通常在几百纳秒量级m 取 0.5~2μs 比较稳妥。对半导体探测器载流子收集时间可能达到几微秒甚至更长m 要相应加大。总成形时间 2lm 决定了系统能支持的最大计数率。打个比方Nai(Tl) 探测器配 1.5μs 上升、1μs 平顶总成形时间 4μs理论上能处理的脉冲间隔约 4μs对应计数率上限在 100k~200k cps 量级。这个估计比较粗暴实际还要考虑触发判定时间和后处理时间但作为初步设计参考已经够用。2. MATLAB 浮点仿真先把算法拆通透再动 RTL2.1 极零相消把指数尾巴变成一根针梯形成型的第一步是要把指数衰减脉冲变成一个很窄的近似冲激。这个事情在模拟电路里叫极零相消核心思想是输入信号在 z 域里有一个极点 zp那我们就构造一个数字滤波器在相同位置放一个零点去抵消它。假设输入是理想指数脉冲x[n] A · a^n其中 a exp(-T/τ)T 1/fsn ≥ 0注意第一个采样点 n0 时 x[0]A之前 x[-1]0。定义 p exp(-T/τ)和输入信号的时间常数完全匹配。做一步差分d[n] x[n] - p · x[n-1]把表达式代进去d[0] A d[n] A·a^n - p·A·a^(n-1) A·a^n - A·a^n 0 (n ≥ 1)也就是说只要 p 匹配准确指数尾巴会被完全消掉d[n] 只剩第一个采样点的一根冲激。这一步的物理含义很直观指数尾巴不是我们想要的信息载体反而是堆叠和基线的来源提前把它滤干净后面几个模块才能安心工作。2.2 双累积加窗口差分冲激就变成了梯形有了冲激 d[n]制造梯形就非常机械了。梯形在连续时间上可以看作两个斜坡的叠加而在离散域只需要对冲激做两次累积得到一个斜坡再做一次带延迟的差分。第一次累积得到阶跃u[n] u[n-1] d[n]第二次累积得到斜坡v[n] v[n-1] u[n]如果 d[n] A·δ[n]那么 u[n] An≥0v[n] ≈ A·(n1)这是一个线性斜坡。然后用一个四端窗口差分把斜坡切成梯形y[n] v[n] - v[n-l] - v[n-(lm)] v[n-(2lm)]分段展开n 的范围y[n] 的值形状0 ≤ n ln · A上升斜线l ≤ n lml · A平顶lm ≤ n 2lm(2lm-n) · A下降斜线n ≥ 2lm0归零注意一个细节梯形平顶的高度是 A·l正好和上升采样点数成正比。这个 l 相当于一个固定增益在做能谱刻度时统一标定一次就行不需要在算法里除回去。如果图省事直接用平顶高度做能量道址谱形状的线性度依然很好。2.3 MATLAB 仿真代码与结果判读下面是完整可跑的 MATLAB 浮点仿真建议入手时先在自己电脑上跑一遍把每个中间变量都 plot 出来看一眼。% trapezoid_shaping_demo.m % 核脉冲梯形成型浮点仿真输入为指数衰减脉冲 fs 50e6; % 采样率 50MHz tau 5e-6; % 输入指数衰减时间常数 rise_us 1.5; % 上升时间单位 us flat_us 1.0; % 平顶时间单位 us l round(rise_us * 1e-6 * fs); % 上升采样点数 m round(flat_us * 1e-6 * fs); % 平顶采样点数 N 800; t (0:N-1) / fs; A 1.0; x A * exp(-t / tau); rng(42); x x 0.005 * randn(1, N); % 加一点白噪声模拟真实采集 % 算法主体PZC 双累积 窗口差分 p exp(-1 / (fs * tau)); x_d1 [0, x(1:end-1)]; % x[n-1] d x - p * x_d1; % 极零相消 u zeros(1, N); v zeros(1, N); for n 2:N u(n) u(n-1) d(n); % 一次累积 v(n) v(n-1) u(n); % 二次累积 end y zeros(1, N); for n 1:N n1 n - l; n2 n - l - m; n3 n - 2*l - m; v1 0; v2 0; v3 0; if n1 1, v1 v(n1); end if n2 1, v2 v(n2); end if n3 1, v3 v(n3); end y(n) v(n) - v1 - v2 v3; end y y / l; % 归一化回 A figure; subplot(3,1,1); plot(t*1e6, x); title(输入指数衰减脉冲); xlabel(us); ylabel(幅度); subplot(3,1,2); plot(t*1e6, d); title(极零相消输出); xlabel(us); ylabel(幅度); subplot(3,1,3); plot(t*1e6, y); title(梯形输出); xlabel(us); ylabel(幅度);跑完这段代码你会看到 d[n] 在第一个采样点处有一个尖峰后面几乎就是一条贴着零的线y[n] 则是一个标准的梯形。如果 p 匹配不准确即实际时间常数 τ 和 p 对应的 τ 不一致d[n] 不会完全归零会残留一个小指数尾巴体现在最终梯形上就是平顶带斜率。失配方向有个规律实际时间常数变长p 变小平顶会向下斜实际时间常数变短p 变大平顶会向上斜。2.4 仿真时最容易被忽视的三个点第一个是噪声的整形走向。PZC 做了一次差分本质上会对高频噪声做一次加重让白噪声变成类似微分噪声的形态。但紧接着的双累积又是两次强低通把高频压得非常狠。所以不要看中间变量 d[n] 的噪声大就心慌最终梯形输出的噪声性能才是真正的判据。第二个是平顶区间的选取。仿真时取平顶段的平均值作为幅度能明显降低噪声对结果的影响。平顶中间的采样点更稳靠近上升沿和下降沿的过渡区会有轻微的边沿效应。第三个是防止循环索引越界。上面代码里窗口差分那一段用 if n11 做了边界保护实际写产品代码时更推荐把 v 数组加 padding或者用仿真专用的 sink 逻辑方便维护。MATLAB 不是越界了会静默给 0容易让人误判边界行为。3. Verilog 定点化与模块设计从浮点模型到可综合 RTL3.1 位宽计算这不是拍脑袋是有账可算的浮点转定点最重要的就是位宽。给少了直接溢出梯形平顶被削掉给多了浪费资源。下面这套计算思路在 50MHz 采样率、14 位 ADC 的设定下已经足够严谨换其他参数也能照葫芦画瓢。先看 PZC。设 ADC 数据位宽 AW14做有符号处理输入先减基线见第 5 节幅度范围 ±8192。p 是小于 1 的正数用 Q0.14 格式表示p ∈ [0, 0.9999]实际使用时留一点余量别让它取到 1。乘法 x·p 的结果位宽是 AWPW28 位但 p1 意味着乘积不会超过 x 的绝对大小所以取乘积的高AW1位就足够了。一次减法的结果d 的最大动态范围差不多是输入幅度的两倍因此 d 取 AW418 位比较稳就算 PZC 把上升沿的寄生尖峰也包进来也不怕。接着是双积分器。u 是 d 的累积v 是 u 的累积。最坏情况是连续来大脉冲u 在一段时间内不断累加。但好在我们的触发窗口方案里u 和 v 在事件结束时都会复位。只要保证单次事件窗口内不溢出即可。上面推导过梯形平顶高度约等于 A·lv 的最大值也是这个量级。所以 v 需要的位宽是v_bit AW ceil(log2(l_max))l_max 按最大上升采样点数 1023约 20μs 50MHz算ceil(log2(1023))10总位宽 141024 位再加一位符号位取 26 位绰绰有余。如果 l 上限更大比如到 4095那就是 28 位算法上完全不受影响。3.2 顶层架构触发、PZC、双积分、延迟线、组合输出这版 Verilog 设计采用事件窗口模式整体数据流是adc_data → 基线扣除 → 过阈值触发 → PZC → 双积分器 → 延迟抽头 → 梯形组合 → 平顶提取完整模块清单大致这些模块功能关键参数baseline_sub扣除 ADC 直流偏置转有符号数常数或者慢速基线估计trigger_ctrl检测脉冲前沿产生窗口计时和 clr阈值、滞回、窗口长度pzc极零相消p 寄存器Q0.14double_integratoru/v 双累积26 位有符号delay_line延迟 v 信号 2lm 个时钟BRAM 或移位寄存器trap_comb四端窗口差分两级流水触发控制是这个架构的中枢。它的做法是原始信号减掉基线后如果超过阈值启动一个窗口计数器窗口长度取 2lm 再加一点裕量比如加 16 个时钟。触发之后复合逻辑进入成型阶段窗口结束拉出一拍 clr把 PZC 的 x_d1、双积分器的 u/v、延迟线的内容全部清零等待下一个事件。这里要注意的一个细节是窗口的起点应该尽可能接近脉冲的真实前沿。如果触发慢了梯形的前几段会缺损。一个省事的做法是用比较器检测上升沿同时给触发信号加一小段可编程的预触发延迟依靠 FPGA 内部的 FIFO 补偿掉触发判定的时间。3.3 PZC 和双积分器的 RTL 参考PZC 的核心代码不长但要注意乘法器在 DSP48 里的资源分配和结果截断方式。module pzc #( parameter AW 14, // adc 有符号位宽 parameter PW 16 // p 定点位宽Q0.15 )( input wire clk, input wire rst_n, input wire clr, input wire signed [AW-1:0] x, input wire signed [PW-1:0] p, output reg signed [AW3:0] d ); reg signed [AW-1:0] x_d1; wire signed [AWPW-1:0] mult $signed(x_d1) * $signed(p); always (posedge clk or negedge rst_n) begin if (!rst_n) begin x_d1 {AW{1b0}}; d {AW4{1b0}}; end else if (clr) begin x_d1 {AW{1b0}}; d {AW4{1b0}}; end else begin x_d1 x; // 截断乘积高位等效乘以 p结果转入有符号 d $signed(x) - $signed(mult[AWPW-2:PW-1]); end end endmodule双积分器是这个链路里唯一带反馈回路的模块加法不能随便插流水线因为它要求当前时钟周期读到上一拍刚算出来的结果。好在 26 位加法器在 50MHz 下延时就几个纳秒时序压力很小。module double_integrator #( parameter DW 18, parameter OW 26 )( input wire clk, input wire rst_n, input wire clr, input wire signed [DW-1:0] d, output reg signed [OW-1:0] u, output reg signed [OW-1:0] v ); always (posedge clk or negedge rst_n) begin if (!rst_n) begin u {OW{1b0}}; v {OW{1b0}}; end else if (clr) begin u {OW{1b0}}; v {OW{1b0}}; end else begin u $signed(u) $signed(d); v $signed(v) $signed(u); end end endmodule3.4 延迟线实现BRAM 环形缓冲还是移位寄存器延迟线需要把 v 信号延迟到三个不同的时间点上v[n-l]、v[n-l-m]、v[n-2l-m]。从实现难度来看最好让一个深度为 2lm 的延迟链统一提供三个抽头这样不管参数怎么改只需要改端口位置。当总深度在几十到两三百的范围时两种方案都可以移位寄存器SRL用 FPGA 里的分布式资源LVDS 级联实现简单但深度大了占 LUT 特别多。深度 200 的话大约消耗 200 个 FF/bit对 26 位信号就是 5200 个 FF在 35T 这种小芯片上已经占掉不少。小规模验证无所谓通道多了肯定不行。BRAM 环形缓冲把 v 写进一块深度为 256 的简单双口 RAM用四个读地址同时读出三个抽头和一个当前值。BRAM 在大多数 FPGA 里是按块分配的一块 18Kb 的 BRAM 存 512×26bit 完全够用逻辑资源只消耗几个计数器。这是更工程化的选择。我实际项目里用的是 BRAM 方案做法是维护一个写指针 wptr三个读指针分别等于 wptr - l、wptr - l - m、wptr - 2l - m出现负数时加上缓冲深度。需要注意指针减法的仿真细节很多第一次写这个逻辑的人容易在边界处拿到旧数据导致梯形首尾出现毛刺。3.5 为什么窗口结束必须清累积器如果不加窗口复位系统变为自由运行模式PZC 连续工作双积分器不停累积窗口差分输出依然能形成一个个分离的梯形。这个方案并没有本质错误商用数字多道里也有这么干的但它有一个绕不开的问题v 是 v[n-1]u[n] 的无限积分只要有残余直流或低频率扰动v 就会慢慢漂向饱和。为了长时间连续运行v 的位宽可能要扩到 40 甚至 48 位白白浪费资源还要处理饱和回绕的边界情况。事件窗口方案用复位把这些麻烦都挡在门外每个事件独立进行累积器只积累窗口内的量位宽可控基线上漂的影响也被压到最低。代价是触发逻辑要做对包括阈值、滞回、窗口长度和复位时序但这些都是可控的工程问题比解决饱和漂移容易得多。4. 50MHz 采样率的落地资源、约束与实测对账4.1 平台选型与时钟架构我在项目里用的是 Xilinx Artix-7 XC7A35T配一块 14 位、50MSPS 的 ADC 子板。FPGA 板卡提供 50MHz 晶振ADC 给一个随路时钟或者由 FPGA 生成采样时钟都可以。如果走ADC 主时钟FPGA 随路接收的架构需要把 ADC 输出的 PCLK 接到全局时钟引脚并且用 MMCM 做一些微小的相位补偿保证 adc_data 在建立/保持窗口内稳定。这种平台对 50MHz 来说非常宽松绝大多数逻辑都是组合路径几百皮秒、寄存器路径十几纳秒换句话说是闭着眼睛综合也能过时序的状态。但宽松不意味着可以不约束后面会说。4.2 资源占用到底有多少把模块按上面方案实现后实际上板后的资源占用大致如下资源用量说明LUT约 350大部分消耗在触发判断和地址计算FF约 260流水线和状态机DSP48E11PZC 里的乘法BRAM 18Kb1~2延迟线深度 256×26bit时钟管理器1如果需要产生 ADC 采样时钟对 35T 这种 20800 LUT 的小芯片来说整个梯形成型模块占 LUT 不到 2%BRAM 也就半块。也就是说这个算法本身非常轻量真正吃资源的往往是外围的以太网上传、USB 接口、能谱直方图累加这些部分。这也是梯形成型在 FPGA 上特别有优势的一个原因即使做 32 通道并行处理每通道一套这样的逻辑也只需要 32 个 DSP48 和 32~64 块 BRAM35T 刚好能塞下。如果以后想扩展多通道架构上完全不用大改。4.3 时序约束哪怕 50MHz 也要把四类约束写全很多人觉得低速率设计不需要时序约束这是大坑。不写约束综合工具会默认所有路径理想但上板后数据的建立保持时间对不对全靠运气和 PCB 质量。至少要把这几类约束写清楚create_clock -name sys_clk -period 20.0 [get_ports clk] # ADC 数据的输入延迟具体值查 ADC 数据手册 set_input_delay -clock sys_clk -max 6.0 [get_ports {adc_data[*]}] set_input_delay -clock sys_clk -min 2.0 [get_ports {adc_data[*]}]如果 ADC 数据和 PCLK 是中心对齐还是边沿对齐搞不清楚可以在硬件上把 PCLK 反相试一下用 ILA 抓纯直流输入时的波形看到稳定的固定码元就说明对齐没问题。另外注意复位信号的处理。尽量做异步复位同步释放保证所有模块同一拍退出复位不然 PZC 和双积分器的初始状态可能差一个周期梯形起点会出现一一拍的缺口。4.4 上板实测MATLAB 模型和 RTL 对账验证流程分三步走。第一步用信号发生器产生一串已知幅度、已知时间常数的指数衰减脉冲接进 FPGA。ILA 里抓 adc_data、d、u、v、trap_out 五个信号。把数据导出来和 MATLAB 的仿真波形做逐点对比。理论上应该几乎完全重合除了定点量化引入的微小误差。第二步把 FPGA 的梯形平顶幅度值通过串口或以太网上传在 PC 上画能谱直方图。输入一个已知能量的 γ 源比如 Cs-137 的 662keV 峰看峰位和峰形。用梯形成型后的能量分辨率应该比直接做峰值检测有明显改善峰位也更稳定。第三步做计数率扫描。往探测器前面放不同活度的放射源或者用信号发生器提高脉冲重复率观察堆积情况。在这一步触发窗口和复位逻辑最容易出问题因为你开始遇到两个脉冲间隔小于 2lm 的场景了。4.5 实测中常见现象速查现象原因处理方向梯形平顶带斜坡p 失配或基线未扣净调整 p或补实时基线估计平顶塌陷有凹坑m 太短增大平顶时间输出叠加两个梯形窗口内来了第二个事件增加堆积拒绝逻辑梯形顶部有毛刺延迟线抽头边界处理错误检查读指针回绕逻辑第一个梯形不正确复位后 x_d1 和延迟线没清干净复盘 clr 的覆盖范围5. 调试中踩过的坑这些细节文档里通常不会写5.1 基线扣除最容易忽略的隐形杀手第一次上板时我把 ADC 原始码直接送进 PZC结果梯形输出完全没有平顶整条基线都在向上飘。查了两天才意识到问题ADC 的模拟输入端有 1.5V 直流偏置14 位无符号输出在无信号时不是 0而是 8192 左右。PZC 对这种直流输入并不是完全透明的残差被双积分器不断累积最终变成一个持续增长的斜坡。解决方法是先做一个 baseline_sub 模块把 ADC 原始码减掉一个基线值转成有符号数再进 PZC。基线值可以是上电后无源本底时的采样均值更工程化的做法是做一个慢速移动平均或一阶低通估计实时跟踪基线漂移。5.2 复位时序的后手延迟线不清第二个脉冲准歪事件窗口结束后的 clr 信号刚写出来时我只清了双积分器的 u 和 v结果在相邻短间隔脉冲测试中第二个脉冲的梯形平顶总比第一个偏低。后来用 ILA 抓信号发现PZC 的 x_d1 里还残留着上一个脉冲最后时刻的采样值clr 之后第一个新采样进来PZC 会错估一个差分项直接污染了第二个脉冲的成形。解决方式很粗暴但有效clr 时把所有状态变量统一清零包括 PZC 的 x_d1、双积分器的 u/v、延迟线的写读指针甚至 BRAM 里的残留数据。如果 BRAM 不支持全局清零就在延迟线读端加一个基于 clr 的掩码让 clr 之后的输出强制归零直到新的有效数据写完整个延迟环。5.3 p 值的定点精度和乘法截断PZC 的 p 接近 1比如 τ5μs、fs50MHz 时pexp(-0.004)≈0.996。如果 p 的定点格式只有 8 位小数量化误差就相当于时间常数失配百分之几最终表现在平顶斜率上就会比理论预期明显很多。我最终把 p 存在 Q0.15 格式的寄存器里这样最小的量化步进约为 3e-5对应等效 τ 失配在千分之一以内平顶的斜度基本看不出来。乘法结果的截断也要留意。直接截掉低位相当于向下取整会给 d 引入一个固定的负偏置累积到积分器里就是基线偏移。推荐在截断前加上半字rounding或者用 DSP48 的 ALUMODE 配合做四舍五入成本几乎为零。5.4 触发阈值过高丢小信号过低连续误触发触发模块的阈值设置比想象中更影响整体性能。阈值太高小能量的事件直接丢了阈值太低噪声峰值不停越过阈值触发逻辑把窗口开了一次又一次复位信号频繁拉高正常脉冲反而被切成碎片。我的做法是用原始信号减基线后做阈值判断而不是用 PZC 后的 d 信号因为 d 噪声被差分放大了触发不稳定。阈值设为基线噪声峰值的 5~7 倍并加入滞回——一旦触发阈值降到原有的一半直到脉冲幅度回落。这个滞回可以有效避免同一个梯形被重复触发。5.5 双肩现象和解法有段时间梯形输出在平顶两侧出现明显的凹陷看起来像长了两个肩膀。排查到最后原因是平顶时间 m 太小小于探测器电荷收集时间在模拟前端的展宽导致梯形还没有完全成形就进入了下降段平顶中段反而被拉低。这个问题的本质是参数匹配问题而不是 RTL bug。把 m 加长比如从 25 个采样点加到 50 个采样点双肩肉眼可见地消失了。这个案例也提醒我参数调优阶段不要只看整体形状像不像梯形要把平顶局部放大后逐段检查。最后说句实在话梯形成型的 RTL 本身不复杂难的是把参数、位宽、复位时序这些真正决定成败的细节都收干净。我自己这套方案在 50MHz 采样率、14 位 ADC 上加 Artix-7跑得很稳占用资源少实时性也完全够。后续如果要换更高采样率流水线深度要相应调整要做多通道直接实例化多份模块即可。核心的设计思路和踩坑经验放到任何档次的硬件上方向都是一样的。
返回列表