zoukankan      html  css  js  c++  java
  • verilog实现奇数倍分频

    在学习FPGA的过程中,最简单最基本的实验应该就是分频器了,
    同时分频器也是FPGA设计中使用频率非常高的基本设计之一,
    尽管在芯片厂家提供的IDE中集成了锁相环IP
    altera 的PLLXilinx ISE的DLL或者vivado中的clock来进行时钟的分频,倍频以及相移。
    但是对于时钟要求不高的逻辑,通过语言进行时钟的分频相移显得十分方便,
    这种方法可以节省芯片内部的锁相环资源,再者,通过语言设计进行时钟分频,可以锻炼我们对verilog的熟练和理解程度。

    • 偶数倍分频:实现起来比较简单,这里略过;

    • 奇数倍分频

      如果不要求占空比为50%的话,也比较容易实现,
      如进行三分频,通过待分频时钟上升沿触发计数器进行模三计数,
      当计数器计数到邻近值进行两次翻转,比如可以在计数器计数到1时,
      输出时钟进行翻转,计数到2时再次进行翻转。
      即在计数值在邻近的1和2进行了两次翻转。
      这样实现的三分频占空比为1/3或者2/3。

      对于实现占空比为50%的N倍奇数分频,我们可以分解为两个通道:

      • 上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,
        然后经过(N-1)/2再次进行翻转得到一个占空比为非50%奇数N分频时钟
      • 下降沿触发进行模N计数,到和上升沿触发输出时钟翻转选定值相同值时,
        进行输出时钟时钟翻转,同样经过(N-1)/2时,
        输出时钟再次翻转生成占空比非50%的奇数N分频时钟

      将这两个占空比非50%的N分频时钟或运算,得到占空比为50%的奇数n分频时钟

      具体例子:5分频等占空比,可以通过待分频时钟下降沿和上升沿触发0~4计数,

      • 对于待分频时钟的上升沿,当计数器cnt1计数到1时,
        clk_p翻转;当计数器计数到3(1 + (5 - 1) / 2 = 3)时,clk_p再次反转;
      • 对于待分频时钟的下降沿,当计数器cnt2计数到1时,
        clk_n翻转;当计数器计数到3(1 + (5 - 1) / 2 = 3)时,clk_n再次反转;
      • 然后下降沿产生的5分频时钟和上升沿产生的5分频时钟进行运算,
        即可得到占空比为50%的N分频时钟。

      这种方法可以实现任意的奇数分频。

    下面给出5分频的具体代码:

    `timescale 1ns/1ps 
    
    module CLK_DIV5(
        input   clk_i,
        input   rst_n,
        output  clk_o
        );
     
        reg [2:0] cnt1,cnt2;
        reg clk_p,clk_n;
               
    //*********************
    //MAIN CORE
    //*********************        
    always @(posedge clk_i,negedge rst_n)
        if(!rst_n) begin
            cnt1 <= 3'b0;
            clk_p <= 1'b0;
        end 
        else begin
            if(cnt1 == 3'b100) begin
                cnt1 <= 3'b0;
                clk_p <= clk_p;
            end
            else begin
                cnt1 <= cnt1 + 1'b1;
                if(cnt1 == 3'b1 || cnt1 == 3'b11)
                    clk_p <= ~clk_p;
            end
        end
    
    always @(negedge clk_i,negedge rst_n)
        if(!rst_n) begin
            cnt2 <= 3'b0;
            clk_n <= 1'b0;
        end 
        else begin
            if(cnt2 == 3'b100) begin
                cnt2 <= 3'b0;
                clk_n <= clk_n;
            end
            else begin
                cnt2 <= cnt2 + 1'b1;
                if(cnt2 == 3'b1 || cnt2 == 3'b11)
                    clk_n <= ~clk_n;
            end
        end
        
        assign clk_o = clk_p | clk_n;
    endmodule
    

    测试激励模块:

    `timescale 1ns/1ps 
    
    module TB_TOP;
    
        reg   rst_n  ;
        reg   clk    ;
    
       CLK_DIV5 U_CLK_DIV5(
            .clk_i(clk),
            .rst_n(rst_n),
            .clk_o(clk_o)
        );
        
    //*********************
    //MAIN CORE
    //*********************        
        initial begin 
            rst_n  =1'b1;
            clk    =1'b0;
            
            #5
            rst_n  = 1'b0;
            #5
            rst_n  = 1'b1;
     
            #500
            $finish;     
        end 
        
        always #1 clk = ~clk;
      
    endmodule
    

    modelsim仿真图:

  • 相关阅读:
    D. Constructing the Array
    B. Navigation System
    B. Dreamoon Likes Sequences
    A. Linova and Kingdom
    G. Special Permutation
    B. Xenia and Colorful Gems
    Firetrucks Are Red
    java getInstance()的使用
    java 静态代理和动态代理
    java 类加载机制和反射机制
  • 原文地址:https://www.cnblogs.com/christsong/p/5505545.html
Copyright © 2011-2022 走看看