Verilog实现---1/x任意整数分频器通用代码

本文详细介绍了FPGA中偶数和奇数分频的设计原理,包括50%占空比的实现方法,并提供了对应的Verilog代码实现。通过模块化设计,实现了根据分频数自动选择奇偶分频器的功能。测试与波形验证了四分频的正确性,同时也指出调整参数即可适应不同分频需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.偶数分频

对于占空比为50%,分频系数为N的偶数分频,其核心思想是使用计数范围为[0, (N/2)-1]的计数器,每当计数器计到最大值时输出时钟翻转一次,其余时间保持不变。

八分频示意图

在这里插入图片描述

2.奇数分频

奇数分频比偶数稍微复杂一些,为了实现50%的占空比,需要分别设置上升沿和下降沿触发的计数器,其核心思想是使用计数范围为[0, (N-1)/2]和[0, (N-1)]的计数器,各自输出当前有效沿下的时钟,最后将二者或起来,得到最终输出的时钟信号。

五分频示意图

五分频

3.代码文件说明

分频器的代码并不难,网上多数是奇偶分频分开写的代码,按照电路结构去理解,分频器分为奇偶数两个module是比较理想的。如果把奇偶两个模块写到一个module中,则会导致输出经过较多的逻辑电路,而且每次调用都会用上奇偶分频的全部模块,会浪费很多资源。调用本次代码时,只需例化Div.v,本次代码得到的都是 占空比为50% 的时钟。

名字说明
div_even.v偶数分频module
div_odd.v奇数分频module
Div.v例化奇偶分频module的顶层

4.端口说明

仅以Div.v这个module来说明:

名字类型说明
fre_divparameter分频数
clkinput输入时钟
rst_ninput复位
clk_outoutput输出时钟

5.测试&波形

为了进行测试,写了一个TOP文件:

//-----------------------------------------------------------------------------------------------
//  Copyright    : 
//  File Name    : TOP
//  Author       : Luk.wj
//  Data         : 2021.10.14
//  Description  : TOP file for test
//-----------------------------------------------------------------------------------------------

module TOP #(
    parameter    fre_div = 4    //frequency division
) (
    input        clk,
    input        rst_n,
    output       clk_out
);

Div#(
    .fre_div   ( fre_div   )
)u1_Div(
    .clk       ( clk       ),
    .rst_n     ( rst_n     ),
    .clk_out   ( clk_out   )
);
    
endmodule

测试中是四分频,波形如下图:
在这里插入图片描述
如果需要其他分频数,只需修改传递的参数即可。

6.代码

div_even.v代码:

//-----------------------------------------------------------------------------------------------
//  Copyright    : 
//  File Name    : div_even
//  Author       : Luk.wj
//  Data         : 2021.10.13
//  Description  : Even frequency division
//-----------------------------------------------------------------------------------------------

module div_even #(
    parameter    fre_div = 4    //frequency division
) (
    input            clk,
    input            rst_n,
    output reg       clk_out
);

reg  [fre_div/2-1:0]    cnt;  

always @(posedge clk or negedge rst_n) begin
   if (!rst_n) begin
       cnt     <= 0;
       clk_out <= 1'b0;
   end
   else if (cnt == (fre_div/2-1)) begin
       cnt     <= 0;
       clk_out <= ~clk_out;
   end
   else
       cnt <= cnt + 1;
end

endmodule

div_odd.v代码:

//-----------------------------------------------------------------------------------------------
//  Copyright    : 
//  File Name    : div_odd
//  Author       : Luk.wj
//  Data         : 2021.10.13
//  Description  : Odd numkber frequency division
//-----------------------------------------------------------------------------------------------

module div_odd #(
    parameter    fre_div = 5    //frequency division
) (
    input            clk,
    input            rst_n,
    output           clk_out
);

reg  [(fre_div-1)/2:0]    cnt_p, cnt_n;  //posedge, negedge count
reg  clk_p, clk_n;                       //posedge, negedge generate clock

//====================================================  clk_p unit
always @(posedge clk or negedge rst_n) begin
   if (!rst_n) begin
       cnt_p  <= 0;
       clk_p  <= 1'b0;
   end
   else if (cnt_p == (fre_div-1)/2) begin
       clk_p  <= ~clk_p;
       cnt_p  <= cnt_p + 1;
   end
   else if (cnt_p == (fre_div-1)) begin
       cnt_p  <= 0;
       clk_p  <= ~clk_p;
   end
   else
       cnt_p  <= cnt_p + 1;
end

//====================================================  clk_n unit
always @(negedge clk or negedge rst_n) begin
   if (!rst_n) begin
       cnt_n  <= 0;
       clk_n  <= 1'b0;
   end
   else if (cnt_n == (fre_div-1)/2) begin
       clk_n  <= ~clk_n;
       cnt_n  <= cnt_n + 1;
   end  
   else if (cnt_n == (fre_div-1)) begin
       cnt_n  <= 0;
       clk_n  <= ~clk_n;
   end
   else
       cnt_n  <= cnt_n + 1;   
end

assign clk_out = clk_p | clk_n;

endmodule

Div.v代码:

//-----------------------------------------------------------------------------------------------
//  Copyright    : 
//  File Name    : Div
//  Author       : Luk.wj
//  Data         : 2021.10.14
//  Description  : Any integer frequency division module
//-----------------------------------------------------------------------------------------------

module Div #(
    parameter    fre_div = 4    //frequency division
) (
    input        rst_n,
    input        clk,
    output       clk_out
);

generate
    // Even
    if (fre_div[0] == 1'b0) begin: div
        div_even#(
            .fre_div   ( fre_div   )
        ) u1_div_even(
            .clk       ( clk       ),
            .rst_n     ( rst_n     ),
            .clk_out   ( clk_out   )
        );
    end
    // Odd
    else begin: div
        div_odd#(
            .fre_div   ( fre_div   )
        ) u1_div_odd(
            .clk       ( clk       ),
            .rst_n     ( rst_n     ),
            .clk_out   ( clk_out   )
        );
    end
endgenerate

endmodule

7.Reference

https://blog.youkuaiyun.com/qq_36550892/article/details/126278909

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值