基礎項目(5)任意時鍾分頻程序設計講解


寫在前面的話

在數字邏輯電路設計中,分頻器是一種基本的電路單元。通常用來對某個給定頻率進行分頻,以得到所需的頻率。分頻在FPGA的設計中一直都擔任着很重要的角色,而說到分頻,我相信很多人都已經想到了利用計數器計數來得到想要的時鍾頻率,但問題是僅僅利用計數器來分頻,只可以實現偶數分頻,而如果需要三分頻、五分頻、七分頻等等奇數類分頻,那應該怎么辦呢?在這里,夢翼師兄為大家介紹一種可以實現任意整數分頻的方法。

實現原理

這種方法同樣也是利用了計數器來實現,當然我們是使用狀態機來實現的。我們首先定義分頻時鍾高電平的個數和低電平的個數,在第一個狀態,當計數器計數值小於分頻時鍾低電平個數的時候,輸出電平為低電平,等於低電平的個數的時候,輸出取反同時計數器清零,跳轉到下一個狀態。在這個狀態當計數器計數小於分頻時鍾高電平個數的時候,輸出電平不變,當計數器數值等於高電平個數的時候,輸出取反同時計數器清零,跳轉到上一個狀態,這樣就可以實現任意分頻。

系統框架

頂層模塊端口描述

端口名

端口說明

clk

系統時鍾50Mhz

rst_n

系統低電平復位信號

clk_out

輸出分頻時鍾

代碼分析

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function : 任意分頻模塊 *****************************************************/

01  module divide(

02              clk,    //系統時鍾輸入

03              rst_n,  //系統低電平復位

04              clk_out //分頻時鍾輸出

05              );

06

07      parameter HW = 3;   //輸出時鍾高電平寬度

08      parameter LW = 2;   //輸出時鍾低電平寬度

09      

10      input clk;     //系統時鍾輸入

11      input rst_n;   //系統低電平復位

12      output clk_out; //分頻時鍾輸出

13      

14      reg clk_out;

15      reg [31:0] count; //計數器

16      reg state;  //狀態寄存器

17      

18      always @ (posedge clk or negedge rst_n) 

19      begin

20          if (!rst_n)         //異步復位

21              begin

22                  clk_out <= 1'b0; //賦初值

23                  count <= 0;

24                  state <= 0;

25              end

26          else

27              case (state)

28                  0 : if (count < LW-1) //輸出低電平個數比較器

29                          begin

30                              count <= count + 1;

31                              state <= 0;

32                          end

33                      else //輸出低電平個數等於設定的低電平個數

34                          begin

35                              count <= 0; //計數器清零

36                              clk_out <= 1'b1; //輸出變為1

37                              state <= 1;

38                          end

39                                  

40                  1 : if (count < HW-1) //輸出高電平個數比較器

41                          begin

42                              count <= count + 1;

43                              state <= 1;

44                          end

45                      else //輸出高電平個數等於設定的高電平個數

46                          begin

47                              count <= 0; //計數器清零

48                              clk_out <= 1'b0; //輸出變為0

49                              state <= 0;

50                          end

51                  default : state <= 0;

52                  endcase

53      end

54

55  endmodule

7~8行定義了2個參數,一個是輸出高電平的個數,一個是低電平的個數,比如HW=3,LW=2輸出就是一個5分頻的時鍾,

比如HW=3,LW=3輸出就是一個6分頻的時鍾,可見只要改變HW和LW的值就可以實現任意分頻。第18~53行就是利用狀態機來實現分頻的過程,用2個狀態來計數輸出高電平個數和低電平個數。

編寫測試代碼如下:

/****************************************************          

 *   Engineer      :   夢翼師兄

 *   QQ             :   761664056

 *   The module function : 任意分頻測試模塊 *****************************************************/

01  `timescale 1ns/1ps  //仿真時間單位是ns,仿真時間精度是ps         

02  module tb;

03

04  reg clk, rst_n; //仿真激勵時鍾,復位信號

05

06  wire clk_out;     //仿真輸出分頻信號

07

08  initial begin

09      clk = 0;                //clk時鍾信號初始化

10      rst_n = 0;          //rst_n復位信號初始化

11      #200.1 

12      rst_n = 1;          //200.1ns之后,復位結束

13  end

14

15  always #10 clk = ~clk;  //產生50Mhz時鍾信號

16

17  divide divide(   //把激勵信號送進diveder模塊       

18                  .clk(clk),                                  

19                  .rst_n(rst_n),

20                  .clk_out(clk_out)

21                   );

22              

23  endmodule

仿真分析

我們輸入的時鍾是50Mhz,一個周期是20ns,輸出5分頻的時鍾,周期是100ns,可見我們的設計是正確的。

我們修改分頻模塊的參數將HW改為3,LW改為3,仿真波形如下:

同樣輸入的時鍾是50Mhz,一個周期是20ns,輸出6分頻的時鍾,周期是120ns,可見我們的設計是正確的。

 

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM