verilog分頻器設計及cnt計數器相關注意事項


 特別注意:在PFGA中能用全局時鍾資源clk就用全局時鍾資源,盡量避免用這種分頻出來的時鍾作為時鍾源,因為這種分頻出來的時鍾走的不是快速通道,信號到別的寄存器這一段路程會產生相對較大的延遲。

//這部分代碼有錯,僅用於分析,不可用於仿真
module
division( input clk, input rst_n, output sclk //分頻后的時鍾 ); paramater N = SYS_CLK/SCLK ; //N表示幾分頻系數,當前系統時鍾頻率/所需模塊時鍾頻率 //reg define reg [7:0] cnt //僅支持2 ~ 128 的偶數分頻 //cnt計數模塊 always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt <= 1'd0; esle if(cnt < N - 1) //注意這里是個小於符號,計數器cnt進行0--N-1循環計數 cnt <= cnt + 1'b1; else cnt <= 1'd0; end //分頻模塊 always@(posedge clk or negedge rst_n)begin if(!rst_n) sclk <= 1'd1; else if(cnt == N >> 1) //注意N>>1代表M向右平移一位,即N/2; N >> 2代表M向右平移兩位,即N/4;......... sclk <= 1'b0; else if(cnt == 1'b0)     sclk <= 1'b1; else sclk <= sclk ; end //假如用產生的sclk信號作為觸發信號去驅動別的模塊,則會產生一定的延遲。避免用這種分頻出來的時鍾作為時鍾源,因為這種分頻出來的時鍾走的不是快速通道,信號到別的寄存器這一段路程會產生相對較大的延遲。 always@(posedge sclk or negedge rst_n)begin if(!rst_n) sclk <= 1'd1; else if(cnt == ......) ....; else if(cnt == ......)     ....; else ....; end //上面的always塊程序會產生延遲,應該用以下的形式 always@(posedge clk )begin case(cnt) 0 : sclk <= 1'b0 ; 1 : .... 2 : sclk <= 1'b1; ... ... //根據cnt計數器來變換sclk和執行其它條件 ... end endmodule
 

 

分頻器設計:

  

   

   以下為分頻器設計代碼:

    當分頻系數N = sys_clk/scl_clk(系統系統時鍾頻率/模塊所需時鍾頻率)為偶數時:(只能實現2,4,6,8......128分頻)

/**********************.v文件************************/
module Division(
       input     clk,
       input     rst_n,
       
       output reg  sclk        //分頻后的時鍾
);
parameter    SYS_CLK  = 25_000_000;
parameter    SCLK  =  12500_000;
parameter    N = SYS_CLK/SCLK;    //N表示幾分頻系數,當前系統時鍾頻率/所需模塊時鍾頻率
//reg define
reg  [7:0]  cnt;        //僅支持2 ~ 128 的偶數分頻

//cnt計數模塊
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
       cnt <= 8'd0;
    else if(cnt < N - 1)         //注意這里是個小於符號,計數器cnt進行0--N-1循環計數
       cnt <= cnt + 1'b1;
    else 
       cnt <= 8'd0;
end

//分頻模塊
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
      sclk <= 1'b1;
    else if(cnt == (N >> 1))    //注意N>>1代表N向右平移一位,即N/2; N >> 2代表N向右平移兩位,即N/4;.........
         sclk <= 1'b0;
    else if(cnt == 8'd0)
         sclk <= 1'b1;
    else
         sclk <= sclk;
end
endmodule

/*************************tb文件***********************/

`timescale   1ns/1ps
`define   period_clk  20
module  tb;
    reg                sys_clk;
    reg                sys_rst_n;
    wire               sclk;

/*---------------例化DDS模塊------------------*/  
Division  #(.N(2)//,
//       .SYS_CLK(25_000_000)
       ) 
       Division(
         .clk(sys_clk),    
         .rst_n(sys_rst_n),
         .sclk(sclk) 
        ); 
        
initial   sys_clk = 1'b1;
always   #(`period_clk/2)   sys_clk = ~sys_clk;
initial begin
    sys_rst_n = 1'b0;
    #10;
    sys_rst_n = 1'b1;
    #1_000;
    $stop;
end 
endmodule

 

當N=2,分頻系數為2時下的仿真波形:

 

 

 

 

 

 

計數器設計:

    

 

      上圖為cnt計數器計數N = 5個數的波形;即  cnt < N - 1 ;

 

     計數器設計時應該注意的事情:假如要計數N個數:

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
       cnt <= 1'd0;
    esle if(cnt < N - 1)         //注意這里是個小於符號
       cnt <= cnt + 1'b1;
    else 
       cnt <= 1'd0;
end

        假如在計數滿N個數時,需要執行別的事情:

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
       cnt <= 1'd0;
    esle if(cnt < N - 1)         //注意這里是個小於符號
       cnt <= cnt + 1'b1;
    else 
       cnt <= 1'd0;
end

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
       .....
    esle if(cnt == N - 1)        
       .....
    else 
       .....
end

 

當分頻系數N = sys_clk/scl_clk(系統系統時鍾頻率/模塊所需時鍾頻率)為奇數時:

 

 

 

 


免責聲明!

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



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