真实面经题目 · 原创解析

Verilog 写一个 32 分频电路时,翻转条件和计数边界怎么确定?

这题考偶数分频的边界理解,32 分频且希望 50% 占空比时,输出应每 16 个输入周期翻转一次。

出现于:华为 · FPGA

60 秒回答模板

32 分频的意思是输出周期等于输入周期的 32 倍。如果要求接近 50% 占空比的方波,输出半周期就是 16 个输入时钟,所以计数器计 0 到 15,达到 15 时清零并翻转输出。这样两次翻转组成一个完整输出周期,共 32 个输入周期。写代码时用 4 位计数器即可表示 0 到 15,时序逻辑用非阻塞赋值,复位时计数器和输出都清零。容易错的是计到 16 再翻转,或者把每 32 拍翻转一次,那样得到的是 64 分频方波。

考点 半周期翻转
难度 真实面经题
回答目标 写出 32 分频 50% 占空比方波,解释每 16 拍翻转和计数 0 到 15 的原因。

深入解析

01

先定义分频输出

若输出是方波时钟,N 分频通常指输出完整周期是输入周期的 N 倍。方波有高低两个半周期,所以偶数 N 分频时,每 N/2 个输入周期翻转一次。

02

32 分频的翻转点

32 的一半是 16,因此输出每 16 个输入周期翻转。计数器可以从 0 计到 15,命中 15 时翻转输出并把计数器清零。两次翻转后完成 32 个输入周期。

03

边界和位宽

0 到 15 共有 16 个状态,4 位计数器足够。若写成 cnt == 16,至少需要 5 位,而且半周期会变成 17 拍,分频比错误。

04

派生时钟使用要谨慎

这种逻辑分频输出若要驱动大量时序逻辑,要考虑时钟网络和约束。很多工程更推荐使用 clock enable,或使用器件专用时钟资源产生真正的派生时钟。

verilog

32 分频方波

module div32 (
    input  wire clk,
    input  wire rst_n,
    output reg  clk_div32
);

reg [3:0] cnt;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt       <= 4'd0;
        clk_div32 <= 1'b0;
    end else if (cnt == 4'd15) begin
        cnt       <= 4'd0;
        clk_div32 <= ~clk_div32;
    end else begin
        cnt       <= cnt + 4'd1;
    end
end

endmodule
  • 输出每 16 个输入时钟翻转一次,两次翻转构成 32 分频。
  • 如果用于内部逻辑,很多场景应优先考虑 clock enable 或专用时钟资源。

易错点

  • 每 32 拍翻转一次,实际输出完整周期变成 64 拍。
  • 计数到 16 再翻转,半周期多一拍。
  • 位宽和终值不匹配,导致比较值永远达不到或分频异常。
  • 把逻辑分频信号直接当全局时钟大量使用,不考虑时钟网络和约束。

面试官追问

如果只需要每 32 拍一个使能脉冲怎么写?

那就不翻转输出,而是在计数到 31 时打一拍 pulse,并清零计数器。它是周期性使能,不是 50% 占空比分频方波。

奇数分频能做到 50% 占空比吗?

单边沿简单计数通常不能天然做到严格 50% 占空比,需要双边沿、PLL/MMCM 或更复杂结构,且要考虑可综合性和时钟资源。

实现后你会用哪些检查来避免硬件问题?

我会至少做仿真、lint、综合后资源检查、时序约束和 STA;涉及跨时钟域还要做 CDC 检查,涉及板级接口还要结合时序裕量和实测波形验证。