1. 奇数分频器的核心原理
第一次接触奇数分频器时,我也被那些上升沿、下降沿的组合绕晕了。后来发现,理解它的关键就像玩拼图——把两个不完美的半成品组合起来,就能得到完美的50%占空比。举个例子,三分频就像把两个错开半拍的1/3占空比信号拼在一起,通过"或运算"让它们的优势互补。
具体怎么操作呢?假设要做个三分频:
- 先用计数器在上升沿数1-2-3循环
- 当cnt=1时拉高clk_out1,cnt=3时拉低
- 同样的逻辑用在下降沿生成clk_out2
- 最后clk_out = clk_out1 | clk_out2
实测波形会显示:clk_out1的高电平在cnt=1期间,clk_out2的高电平在cnt=2.5-3.5期间(因为下降沿触发)。两者叠加后,每个周期正好拼出1.5个原时钟周期的高电平,完美实现50%占空比。
2. 从三分频到N分频的通用框架
掌握了三分频后,我总结出一个通用公式:对于(2N+1)分频:
- 上升沿模块:高电平保持N个原周期
- 下降沿模块:同样保持N个周期但相位滞后半个周期
- 组合方式:或运算用于50%占空比,与运算用于特定占空比
比如七分频的Verilog代码骨架:
always @(posedge clk) begin if(cnt == 3'd6) cnt <= 3'd0; else cnt <= cnt + 1; clk_out1 <= (cnt < 3'd3); //N=3 end always @(negedge clk) begin clk_out2 <= (cnt < 3'd3); //同阈值 end assign clk_out = clk_out1 | clk_out2;这里有个易错点:计数器的比较值应该用N而不是分频系数。比如七分频时N=3(因为2N+1=7),实际比较的是cnt<3而不是cnt<7。我在第一次实现时就栽在这个细节上,导致占空比偏差很大。
3. 非对称占空比的实现技巧
面试中最刺激的就是遇到像"3/10占空比的五分频"这种变态需求。但破解方法很巧妙——把或运算改成与运算,就像把拼图的正片和负片叠加。
具体步骤(以5/18占空比九分频为例):
- 计算基础占空比:5/18 ≈ 2.5/9 → 取整得上升沿模块用2/9
- 下降沿模块同样用2/9占空比
- 两者相与时,重叠区域=2/9 - 1/18=5/18(因为下降沿模块滞后0.5周期)
关键代码修改点:
// 原50%占空比 assign clk_out = clk_out1 | clk_out2; // 非对称占空比 assign clk_out = clk_out1 & clk_out2;实测发现个有趣现象:当需要占空比>50%时,应该用"或运算";当<50%时用"与运算"。这就像调节相机的曝光补偿,过曝就减光,欠曝就补光。
4. 面试实战中的高频考点
在多次模拟面试中,我发现考官最爱挖的三个坑:
计数器位宽设置:比如九分频需要计数到8,必须用4位宽reg [3:0]cnt,用3位会溢出。有次我没注意这个细节,调试了半小时才找到问题。
组合逻辑延迟:当分频系数较大时(如15分频),组合逻辑可能产生毛刺。稳妥的做法是给clk_out1/clk_out2打一拍:
always @(posedge clk) begin clk_out1_reg <= clk_out1; clk_out2_reg <= clk_out2; end assign clk_out = clk_out1_reg | clk_out2_reg;- 复位信号处理:很多同学会忽略negedge rstn的情况。完整的写法应该是:
always @(posedge clk or negedge rstn) begin if(!rstn) begin cnt <= 0; clk_out1 <= 0; end else begin // 正常逻辑 end end always @(negedge clk or negedge rstn) begin if(!rstn) clk_out2 <= 0; //... end最近一次面试中,考官让我现场写个7/24占空比的十二分频器。其实奇数分频器设计就像搭积木,只要掌握核心原理,万变不离其宗。最终我通过调整上升沿模块(4/12)和下降沿模块(4/12)相与,得到4/12-1/24=7/24的占空比,顺利通关。