数字倍频电路设计:原理、Verilog实现与编码器四倍频实战
简介数字倍频是频率合成与通信系统中常见且关键的信号处理技术。这份文档围绕锁相环集成电路、DDS技术、VHDL语言以及单片机实现展开系统梳理了数字倍频电路的研究与应用适合电子、通信、自动化等专业学生及工程技术人员阅读。内容从CD4046锁相环的内部结构、功能特点与高倍锁相倍频应用讲起详细给出了配合CD4518计数分频器实现×10、×100倍频的典型电路同时探讨了三极管倍频器、宽带倍频器以及基于DDS的数字倍频方案其中通过单片机测量输入频率、由倍频系数换算输出频率并利用DDS产生信号的方法具有较高的工程参考价值。针对VHDL与AT89C2051单片锁相倍频电路文档还分析了误差来源并用MaxplusⅡ进行了仿真验证有利于理解数字倍频的设计要点与排错思路。资源包为单个doc文档大小1.57MB共1个文件查阅方便已有165人浏览学习对需要快速掌握倍频电路原理与实现方法的读者具有一定帮助。 数字倍频电路这名字听着有点学院派但搞过嵌入式、写过FPGA、调过电机驱动的朋友肯定不陌生。编码器测速要四倍频提高分辨率信号发生器要稳定输出整数倍时钟测频系统要把低速脉冲拉到高速计数器的量程里这些场景绕来绕去都会撞上同一个需求给一个方波信号把它变成频率严格等于原来整数倍的方波。用模拟锁相环当然能办但环路参数、压控振荡器、相位噪声这些事一掺和进来板子面积和调试成本都上去了。数字方案就不一样一颗CPLD或者FPGA就能搞定甚至单片机配合定时器也能凑合跑。这篇文章我想把数字倍频电路这件事从原理到落地串一遍重点拆解那些容易踩坑的细节——比如看起来倍频和真正逐周期均匀倍频到底差在哪计数器倍频的分频系数应该怎么动态算编码器四倍频遇到的毛刺和抖动又该怎么处理。无论你是在做测量仪器、电机控制还是纯粹想给时钟做整数倍提升这篇应该都能帮你省不少试错时间。1. 数字倍频解决的痛点和它的适用边界先说清楚一个基本事实模拟PLL倍频在射频和高速SerDes领域依然是绝对的王者那种应用对相位噪声和抖动的要求数字方案目前根本够不着。但只要信号频率在几十兆赫兹以下、对相位噪声要求不是变态级别数字倍频就完全有资格上场而且优势非常明显。1.1 模拟锁相环做倍频的麻烦事模拟PLL倍频的经典结构是鉴相器比较输入参考和反馈分频信号的相位差输出经过环路滤波器变成控制电压再去调压控振荡器的频率。环路锁定后VCO输出频率就是参考频率的N倍。这套方案的问题在于环路是个模拟反馈系统参数一旦设计不好就容易出现锁定时间过长、捕获带不够、环路振荡这类问题。我调试过一款以NE564为核心的倍频电路LC振荡器的磁芯稍微受温度影响漂了环路就失锁重新锁定的过程肉眼可见地慢。而且模拟PLL的元件分散性大同一批板子调出来的环路带宽都不完全一样生产一致性很难保证。数字倍频则完全绕开了这些麻烦没有模拟环路没有压控振荡器所有逻辑都在数字域里完成温度漂移对它的影响小得多。1.2 数字倍频真正适合的场合数字倍频电路最适合的场景有个共同特征输入信号本身就是数字方波或者脉冲频率不高且系统里已经存在一个比输入频率高得多的参考时钟。典型场景我举几个旋转编码器输出正交脉冲信号通过四倍频把每圈脉冲数翻四倍提高速度测量的分辨率流量计、水表、电表的脉冲输出频率太低需要倍频后才能进入高频计数器的测量范围显示驱动或者时序控制电路需要一个与输入同步的2倍频或4倍频时钟但不希望引入模拟PLL的锁定时间。这些场景里输入频率通常不到几兆赫兹系统里有几十到几百兆赫兹的高频时钟用数字方案做倍频成本低、稳定、可移植性强。2. 逐周期均匀倍频和平均倍频的本质差异做数字倍频最容易犯的认知错误就是把输出频率的平均值等于输入的N倍当成倍频成功了。这两件事差着十万八千里理解这个区别才算真正搞懂了数字倍频的原理。2.1 看起来倍频和真正逐周期倍频的差别假设输入是1kHz方波周期1ms。你拿一个高频时钟数出输入周期然后输出一个500Hz信号再经过一个二倍频器比如上升沿下降沿都触发脉冲输出平均频率确实变成了2kHz。但输出脉冲的位置是乱的有的脉冲出现在输入周期的前半段有的出现在后半段脉冲间隔忽大忽小。这叫平均频率倍频很多简易实现都是这么干的。真正逐周期均匀倍频要求的是输入一个周期内均匀地输出N个脉冲第一个脉冲出现在周期的1/N处第二个在2/N处以此类推。每个脉冲的位置都是确定的脉冲间隔严格相等。这个差别在测速场景里特别致命。编码器四倍频如果只是平均频率对那么速度测量值会剧烈抖动因为计数器在固定闸门时间内数到的脉冲数一会儿多一会儿少。逐周期均匀倍频才能保证同样转速下计数器读数是平稳的。2.2 为什么逐周期均匀倍频比想象中难难点在于当输入上升沿到来那一刻你还不知道这个周期到底有多长。要在这个周期的1/4处放一个脉冲你得提前知道周期长度但下个周期还没结束你不知道精确值。所以逐周期均匀倍频有两条路可走。一条是用延迟线输入边沿到达后启动一串延迟单元每个延迟单元的时间是周期T/N依次触发输出脉冲。这就要求延迟线总延迟能自动跟踪输入周期本质是一个全数字延迟锁定环。另一条路是用上个周期估计下个周期高频时钟测出最近一个输入周期的长度T然后假设下个周期长度接近T在下个周期的T/N处触发脉冲。这是工程上最常用的做法代价是输入频率瞬变时输出会滞后几个周期。理解了这个本质你就能明白网上那些号称能任意倍频的简单代码为什么效果差——它们大多只做了平均倍频没有真正解决周期内的均匀分配问题。3. 用高频计数器实现任意整数倍频设计与Verilog实现如果手里有FPGA或CPLD最实用的数字倍频方案就是高频时钟计数法。它的核心思想我在上一节说了高频时钟测量输入周期输出信号在周期的N等分点处翻转。3.1 两倍频的最简设计边沿触发加占空比校正先从两倍频说起。用高频时钟检测输入信号的上升沿和下降沿每个边沿让输出翻转一次。输入一个周期内上升沿和下降沿各一次输出翻转两次正好完成一个周期频率翻倍。但这个基本方案有个问题输出高电平时间等于输入从上升沿到下降沿的时间输出低电平时间等于输入从下降沿到上升沿的时间。如果输入占空比是50%输出恰好是50%方波如果输入占空比是30%输出脉冲就宽窄不一频谱上杂散分量很重。工程上我一般要求输出也是50%占空比做法是先把输入整形成50%占空比再去做边沿翻转倍频。整形方法就是高频时钟计数测出输入周期T后让中间整形信号在前半周期高、后半周期低。这样整形信号本身就是完美的50%方波再倍频就顺理成章了。3.2 任意整数倍频的通用计数器实现下面这段Verilog代码实现的是四倍频核心逻辑是一个自由运行的周期计数器加上四个比较点。module freq_mult4 ( input wire clk_high, // 高频采样时钟例如 50MHz input wire rst_n, input wire sig_in, // 输入方波 output reg sig_out // 四倍频输出 ); // 两级触发器同步输入消除亚稳态 reg sig_in_d1, sig_in_d2; always (posedge clk_high or negedge rst_n) begin if (!rst_n) begin sig_in_d1 1b0; sig_in_d2 1b0; end else begin sig_in_d1 sig_in; sig_in_d2 sig_in_d1; end end wire sig_sync sig_in_d2; // 输入边沿检测 reg sig_sync_d; always (posedge clk_high or negedge rst_n) begin if (!rst_n) sig_sync_d 1b0; else sig_sync_d sig_sync; end wire rise_edge sig_sync ~sig_sync_d; wire fall_edge ~sig_sync sig_sync_d; // 测周期高频时钟对输入周期计数 reg [31:0] period_cnt; reg [31:0] period_val; always (posedge clk_high or negedge rst_n) begin if (!rst_n) begin period_cnt 32d0; period_val 32d0; end else begin if (rise_edge) begin period_val period_cnt; // 锁存上一周期长度 period_cnt 32d1; end else begin period_cnt period_cnt 1b1; end end end // 四倍频输出在 T/4、T/2、3T/4 处翻转 reg [31:0] out_cnt; always (posedge clk_high or negedge rst_n) begin if (!rst_n) begin out_cnt 32d0; sig_out 1b0; end else begin if (rise_edge) begin out_cnt 32d1; sig_out 1b0; end else begin out_cnt out_cnt 1b1; if (period_val 0) begin if (out_cnt period_val / 4 || out_cnt period_val / 2 || out_cnt period_val * 3 / 4) begin sig_out ~sig_out; end end if (out_cnt period_val) begin out_cnt 32d1; end end end end endmodule这个设计里有几个细节需要仔细说。周期测量的位宽采样时钟50MHz输入信号1kHz时一个周期大约50000个高频时钟周期计数器需要16位以上。我统一用32位省心资源也多花不了几个。比较点的计算period_val / 4这些除法在FPGA综合时会消耗一些逻辑资源。如果对时序要求高可以预先在上升沿把四个比较点算好存进寄存器这样每周期只需要做一次除法而不是每次计数都重新算。上面代码为了清晰用了简化写法实际部署我建议改造成预计算。输出初始相位上升沿到达时sig_out复位为低电平这样每个输入周期输出相位都是确定的不会累积漂移。整数除法的舍入误差如果period_val不能被4整除比较点会有一两个时钟的偏差。50MHz采样50000点的时候1000ppm级别的误差肉眼不可见但如果输入频率接近采样时钟误差占比会迅速扩大。经验法则高频采样时钟频率至少要达到输入频率的50倍以上才适合用计数法做多倍频。3.3 时序约束和防止误触发的细节这段代码跑在实际芯片上时序约束要做对。sig_in是异步输入必须先经过两级触发器同步否则同一个边沿在不同时钟周期被采样到会出现一拍的亚稳态。两级触发器能把这种概率压到极低但并不是绝对消除真正苛刻的应用需要三级甚至更多级外加芬威克校正逻辑。另外如果输入信号有抖动比如机械开关、编码器在低速时产生的抖动计数值会飘忽不定导致输出频率也跟着乱跳。这种情况下要先做数字滤波连续采样得到几个稳定相同的值后才认为边沿有效。这块我会在编码器实战那节具体展开。4. 编码器四倍频实战从原理图到实测问题数字倍频应用最广的场景之一就是增量式编码器信号的四倍频。这里的关键不是用计数器法而是利用正交信号本身的特性做一个纯粹的组合逻辑解码。4.1 正交信号四倍频的原理增量式光电编码器输出A和B两路正交方波相位差90度。电机正转时A超前B反转时B超前A。一个信号周期内A和B的组合状态会变化四次00、10、11、01每个状态对应90度机械角或电气角。所以四倍频解码的核心是每个边沿无论是A的上升沿、下降沿还是B的上升沿、下降沿都产生一个计数脉冲同时根据边沿发生时另一路信号的电平判断方向。这个方案的好处是不需要计数高频时钟直接从边沿提取脉冲频率自动提升四倍。市面上大部分运动控制卡和驱动器里都是用这个原理。4.2 一个实战中必须处理的抖动问题理论很丰满现实很骨感。编码器装到电机轴上之后低速运行时机械振动会让A、B信号边缘产生大量抖动毛刺。这种毛刺在示波器上看起来就是一串连续的小脉冲如果直接进入边沿检测逻辑倍频输出会多出数不清的假脉冲计数器直接爆表。处理方案有两级硬件上在编码器输出端加RC低通滤波或者施密特触发器整形软件逻辑上加数字消抖窗口。我的做法是采样时钟用1MHz连续采样到8个相同电平才认为信号状态稳定。8个时钟对应8微秒的消抖时间对大部分电机应用足够了。消抖太狠也不行编码器最高转速对应边沿间隔可能只有几个微秒消抖窗口太大直接把有效边沿滤掉了。这个窗口要根据实际最大转速算很关键。算个例子编码器每转1000脉冲四倍频后每转4000脉冲。电机最高转速3000转每分钟对应每秒200000个脉冲边沿间隔5微秒。消抖窗口取2微秒的话有效边沿能正常通过机械抖动毛刺的宽度通常不到0.5微秒也能被滤掉。如果转速更高窗口要相应调短。4.3 方向判断和单倍频计数边沿检测的同时判断方向逻辑是这样A上升沿时若B为高则正转否则反转A下降沿时若B为低则正转否则反转。这个判断要跟边沿检测放在同一个时钟沿上处理绝对不能分拍否则方向信息就错了。实际项目中我倾向于把四倍频解码做成独立模块方向信号和脉冲信号分两路输出。后面接一个可逆计数器正转加计数反转减计数。这样倍频和计数解耦便于调试和复用。4.4 仿真和实测的对照我用ModelSim做了功能仿真输入A和B相差90度的正交信号频率10kHz输出脉冲序列的频率确实稳定在40kHz方向信号正确。上板实测后发现有个有趣的问题编码器线缆比较长的时候A和B的边沿会有点歪斜导致某个状态的持续时间特别短可能只有几个采样时钟。如果采样率不够高这个状态会被漏掉四倍频输出就少了脉冲。解决方法是采样时钟频率尽量高或者用硬件比较器先把正弦信号整形成方波再进FPGA。我后来把采样时钟从1MHz提到了10MHz漏脉冲问题基本消失。5. 从有限倍频到全数字锁相环什么时候该换个思路计数器法做2倍、4倍、8倍频都很顺手但如果你要的是50倍、100倍甚至动态可变倍频计数器法的局限就暴露出来了。5.1 大倍频倍数时计数器法为什么不灵倍数一大均匀性问题就变得尖锐。输入50kHz你要100倍频到5MHz高频采样时钟起码要100MHz而一个输出脉冲只对应20个采样时钟。四舍五入的误差占整个周期的比例上升到5%输出抖动肉眼可见。更麻烦的是计数器法本质是用一个周期预测下一个周期频率快速变化时输出追不上。输入从50kHz瞬间跳到60kHz计数器还在按旧周期计算比较点输出的前几个周期仍然是50kHz的100倍频然后才逐步调整。很多测频、通信场景根本容忍不了这种滞后。这时候就该考虑数字锁相环的思路了。全数字PLL的基本结构是数字鉴相器比较输入边沿和本地输出时钟分频后的边沿误差信号经过数字环路滤波器去调整一个数控振荡器的分频系数或相位。环路锁定后输出时钟的长期频率严格等于输入频率的N倍而且会持续跟踪输入频率变化。5.2 一个最小可用的数字PLL结构最简单的数字PLL可以这样搭高频参考时钟驱动一个NCO数控振荡器NCO的输出经分频器得到反馈信号与输入比较。鉴相器输出超前/滞后信号环路滤波器通常是一个一阶数字低通累加误差控制NCO的相位增量。这种结构在FPGA里实现起来不算复杂但环路带宽、阻尼系数、跟踪速度这些参数依然需要认真设计。比较器的量化噪声和环路滤波器的字长直接决定最终输出的抖动大小。我的经验是需要大于16倍的整数倍频且频率范围较宽时直接上数字PLL只是编码器四倍频、某个固定倍频这种场景计数法或者正交解码更合适引入PLL反而带来锁定时间和稳定性的新问题。5.3 选型决策表给个可以直接抄的选型建议表倍频需求推荐方案原因编码器正交信号4倍频正交边沿解码简单可靠天然四倍频固定2/4/8倍频输入频率稳定高频计数器法易实现延迟小资源占用小倍数大于16频率范围宽全数字PLL动态跟踪能力远强于计数法频率很高100MHz相位噪声要求苛刻模拟PLL或集成倍频芯片数字方案抖动无法满足输入频率实时变化又需要均匀倍频延迟锁相环DLL真正逐周期均匀输出但实现复杂另外提醒一句如果倍频输出只是用来做显示或用做粗略时钟那计数器法完全够用如果输出要作为另一个闭环系统的参考时钟那一定要评估好抖动对这个闭环的影响别省了PLL的成本最后在系统调试上加倍赔回去。我之前在一个测速项目里只想着用计数器法做100倍频结果输出抖动导致测速值跳变换成小型数字PLL之后问题才解决。所以方案取舍不是越简单越好而是要看整个系统对抖动和滞后时间的容忍度。数字倍频技术发展到今天已经不是能不能做的问题而是针对具体系统怎么选型的问题。把原理吃透把边界搞清楚你就能在各种倍频需求面前从容选型不踩无谓的坑。本文还有配套的精品资源点击获取