• 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仿真图:

  • 相关阅读:
    gradle平级项目引用
    java使用ssh访问Linux的项目jscraft
    debian更新源时找不到公钥的解决办法
    debian系在线安装软件apt-get命令族
    vim打造开发IDE
    Mysql主从同步配置
    byte[] 转Hex String
    记录一次条件比较多的SQL查询语句
    LruCache的缓存策略
    LinkedHashMap的实现原理
  • 原文地址:https://www.cnblogs.com/christsong/p/5505545.html
Copyright © 2020-2023  润新知