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