基于50MHz时钟的Verilog计数器适配1Hz/2Hz时钟的技术问询
嘿,我来帮你搞定这个Verilog时钟分频和计数的问题!针对你的50MHz FPGA,要生成1Hz/2Hz时钟同时保留计数功能,我给你整理了一套适配方案,完全贴合你提到的freerun和Maxval控制逻辑~
适配50MHz时钟的1Hz/2Hz生成+计数方案
首先得明确核心的分频逻辑:50MHz时钟周期是20ns,要得到1Hz信号需要计数5000万次,2Hz则是2500万次——这意味着原来的8位计数器肯定不够用,得先扩展位宽,不然根本装不下这么大的数。
1. 核心逻辑说明
我们需要一个计数器,跟着50MHz时钟脉冲递增,同时实现两种复位模式:
- 当
freerun为高电平时:计数器一直数到26位的最大值(67108863)后自动复位循环 - 当
freerun为低电平时:计数器数到你设定的Maxval就复位重新开始
同时,在计数过程中触发1Hz和2Hz的时钟翻转,保证输出的时钟占空比是50%。
2. 修改后的完整Verilog代码
module clocktime( input clk_50mhz, // FPGA的50MHz输入时钟 input freerun, // 模式切换:1=自由计数到最大值复位,0=到Maxval复位 input Reset, // 全局复位信号 output reg clk_1hz, // 输出1Hz时钟 output reg clk_2hz, // 输出2Hz时钟 input [25:0] Maxval, // 把输入扩展到26位,支持最大67M的计数上限 output reg [25:0] count_out // 实时输出当前计数值,保留计数功能 ); // 预定义分频常数,直接对应50MHz到目标时钟的计数阈值 localparam DIV_1HZ = 26'd49_999_999; // 数到这个值翻转1Hz时钟 localparam DIV_2HZ = 26'd24_999_999; // 数到这个值翻转2Hz时钟 localparam MAX_COUNT = 26'd67_108_863; // 2^26-1,自由运行模式的最大计数值 always @(posedge clk_50mhz or posedge Reset) begin if(Reset) begin // 复位时把所有寄存器拉回初始状态 count_out <= 26'd0; clk_1hz <= 1'b0; clk_2hz <= 1'b0; end else begin // 先处理计数逻辑 if(freerun) begin // 自由运行模式:到最大值就清零 count_out <= (count_out == MAX_COUNT) ? 26'd0 : count_out + 26'd1; end else begin // 自定义模式:到设定的Maxval就清零 count_out <= (count_out == Maxval) ? 26'd0 : count_out + 26'd1; end // 生成1Hz时钟:每数到DIV_1HZ就翻转一次电平 if(count_out == DIV_1HZ) begin clk_1hz <= ~clk_1hz; end // 生成2Hz时钟:每数到DIV_2HZ就翻转一次电平 if(count_out == DIV_2HZ) begin clk_2hz <= ~clk_2hz; end end end endmodule
3. 关键适配细节
- 位宽扩展:原来的8位
Maxval和计数器完全装不下5000万的计数需求,所以我把计数器和Maxval都改成了26位,这样最大能支持6700万次计数,完全覆盖1Hz/2Hz的需求。如果你的项目必须保留8位输入,也可以加个简单的映射逻辑,把8位值对应到预设的分频阈值,但灵活性会差一些。 - 时钟占空比:用电平翻转的方式生成时钟,能保证输出的1Hz/2Hz信号是50%占空比的标准时钟,比单纯的脉冲触发更实用。
- 模式兼容:
freerun信号完美切换两种计数模式,不管哪种模式,时钟生成逻辑都不受影响,计数功能也完整保留。 - 复位可靠性:全局复位
Reset会同步把计数器和时钟输出拉回初始状态,避免启动时的异常。
4. 额外优化小建议
- 如果只需要脉冲形式的触发信号(比如每秒触发一次动作),可以把时钟输出改成脉冲:当计数器到阈值时输出一个周期的高电平,然后直接复位计数器,逻辑会更简单。
- 把分频常数改成可配置的参数,比如
parameter CLK_IN_FREQ = 50_000_000;,后续换不同频率的输入时钟时,只需要改这个参数就行,不用手动算阈值。 - 要是你的FPGA更适合同步复位,可以把
Reset改成同步触发(去掉posedge Reset,放到时钟沿里判断),能减少时序风险。
内容的提问来源于stack exchange,提问作者user8588899




