You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于50MHz时钟的Verilog计数器适配1Hz/2Hz时钟的技术问询

嘿,我来帮你搞定这个Verilog时钟分频和计数的问题!针对你的50MHz FPGA,要生成1Hz/2Hz时钟同时保留计数功能,我给你整理了一套适配方案,完全贴合你提到的freerunMaxval控制逻辑~

适配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

火山引擎 最新活动