FPGA时钟分频器设计与盘古1K开发板实践
1. 盘古1K开发板与时钟分频器设计概述盘古1K开发板作为国产FPGA学习平台凭借其高性价比和丰富的外设接口已成为众多电子工程师和FPGA初学者的首选。本次练习聚焦时钟分频器设计这一数字电路基础课题对于掌握FPGA时序控制至关重要。时钟信号如同数字系统的心跳但实际工程中我们往往需要多种频率的时钟信号。以盘古1K为例其板载晶振可能只提供50MHz单一频率时钟而实际应用中UART通信可能需要115200Hz的低速时钟PWM调光可能需要1KHz~1MHz的可调时钟传感器采样可能需要特定频率的时钟信号传统解决方案有两种硬件PLL锁相环和软件分频器。PLL虽然精度高但配置复杂而Verilog实现的数字分频器则具有以下优势灵活可编程分频系数可动态调整资源占用少仅需少量逻辑单元学习价值高深入理解时序逻辑设计关键提示在FPGA设计中直接使用分频信号作为全局时钟是危险的做法会导致时序问题。推荐使用时钟使能信号如后文介绍的clk_flag配合系统时钟工作。2. 偶数分频器的实现与优化2.1 基础6分频器设计我们先从最简单的6分频偶数分频开始。其核心原理是利用计数器对原时钟周期进行计数在特定计数值翻转输出信号。以下是Verilog实现的关键代码段module divider_six( input wire sys_clk, // 50MHz系统时钟 input wire sys_rst_n, // 低电平复位 output reg clk_out // 分频输出 ); reg [1:0] cnt; // 0-2计数器 always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 2b0; clk_out 1b0; end else if(cnt 2d2) begin cnt 2b0; clk_out ~clk_out; // 计满翻转 end else cnt cnt 1b1; end endmodule这段代码会产生8.33MHz50MHz/6的方波信号但存在两个典型问题时钟偏移分频信号未走全局时钟网络毛刺风险组合逻辑产生的时钟可能存在抖动2.2 安全降频方案设计更专业的做法是生成时钟使能脉冲而非直接分频时钟。改进后的方案如下module divider_six( input wire sys_clk, input wire sys_rst_n, output reg clk_flag // 时钟使能脉冲 ); reg [2:0] cnt; // 0-5计数器 always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 3b0; clk_flag 1b0; end else begin clk_flag (cnt 3d4); // 提前一个周期产生脉冲 cnt (cnt 3d5) ? 3b0 : cnt 1b1; end end endmodule使用时序逻辑生成的clk_flag信号具有以下特点保持与系统时钟同步每个使能脉冲宽度严格为一个时钟周期可安全用于后续模块的条件判断应用示例always(posedge sys_clk) begin if(clk_flag) begin // 每6个时钟周期执行一次 end end3. 奇数分频器的实现技巧3.1 5分频器的设计挑战奇数分频如5分频的难点在于要保持50%占空比。单纯使用上升沿计数无法实现对称波形需要结合双沿触发技术。以下是解决方案分别用上升沿和下降沿生成两个相位差180度的信号将两个信号进行逻辑与操作得到最终输出module divider_five( input wire sys_clk, input wire sys_rst_n, output wire clk_out ); reg [2:0] cnt; reg clk1, clk2; // 上升沿计数 always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 3b0; clk1 1b1; end else if(cnt 3d4) cnt 3b0; else cnt cnt 1b1; if(cnt 3d1) clk1 1b0; else if(cnt 3d3) clk1 1b1; end // 下降沿计数 always(negedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) clk2 1b1; else if(cnt 3d1) clk2 1b0; else if(cnt 3d3) clk2 1b1; end assign clk_out clk1 clk2; endmodule3.2 奇数分频的使能信号实现同样地我们可以为奇数分频设计安全的使能信号module divider_five( input wire sys_clk, input wire sys_rst_n, output reg clk_flag ); reg [2:0] cnt; always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 3b0; clk_flag 1b0; end else begin clk_flag (cnt 3d3); cnt (cnt 3d4) ? 3b0 : cnt 1b1; end end endmodule4. 盘古1K开发板上的实现与验证4.1 工程配置要点在盘古1K开发板上实现分频器时需注意引脚约束set_location_assignment PIN_E1 -to sys_clk set_location_assignment PIN_M15 -to sys_rst_n set_location_assignment PIN_F15 -to clk_out时钟约束create_clock -name sys_clk -period 20 [get_ports sys_clk]资源占用评估偶数分频约15个LE奇数分频约25个LE使能信号方案额外增加3-5个LE4.2 实测问题排查指南实际调试中常见问题及解决方案现象可能原因解决方法无输出信号引脚约束错误检查.pin文件配置分频频率不准计数器位宽不足确保计数器能覆盖最大计数值输出波形畸变时序违例添加适当的时钟约束随机复位按键消抖不足增加复位信号滤波电路4.3 示波器测量技巧使用示波器验证分频效果时建议使用10:1探头降低负载效应触发模式设为边沿触发触发电平1.65V3.3V系统测量参数包括频率应为50MHz/N占空比奇数分频需接近50%上升时间应5ns5. 高级应用与扩展练习5.1 参数化分频器设计通过parameter实现可配置分频系数module divider #( parameter DIV 6 )( input wire sys_clk, input wire sys_rst_n, output reg clk_flag ); localparam CNT_WIDTH $clog2(DIV); reg [CNT_WIDTH-1:0] cnt; always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 0; clk_flag 0; end else begin clk_flag (cnt DIV-2); cnt (cnt DIV-1) ? 0 : cnt 1; end end endmodule5.2 动态重配置分频系数添加配置接口实现运行时调整module dynamic_divider( input wire sys_clk, input wire sys_rst_n, input wire [7:0] div_ratio, // 分频系数 output reg clk_flag ); reg [7:0] cnt; always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 0; clk_flag 0; end else begin clk_flag (cnt div_ratio-2); cnt (cnt div_ratio-1) ? 0 : cnt 1; end end endmodule5.3 小数分频技术通过交替使用N和N1分频实现小数分频比module frac_divider #( parameter M 3, // 分子 parameter N 2 // 分母 )( input wire sys_clk, input wire sys_rst_n, output reg clk_out ); // 实现3.5分频即7/2 reg [2:0] cnt; reg phase; always(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin cnt 0; phase 0; clk_out 0; end else begin if(phase 0) begin if(cnt 3) begin // 4分频 cnt 0; phase 1; clk_out ~clk_out; end else cnt cnt 1; end else begin if(cnt 2) begin // 3分频 cnt 0; phase 0; clk_out ~clk_out; end else cnt cnt 1; end end end endmodule在盘古1K上完成基础分频器设计后建议尝试以下扩展练习设计一个可按键调节分频系数的系统实现UART波特率时钟生成模块结合PWM模块验证分频时钟精度测量不同分频方案下的系统功耗差异