首页 Verilog 正文

Verilog分频器

yummy头像 yummy Verilog 2022-04-21 15:04:36 0 161
导读:分频器是时序电路的基本器件,它的功能是对系统时钟或其他时钟进行分频产生所需要的时钟信号。分频有两种方式:一是通过HDL语言建模产生所需要的时钟信号,二是利用开发工具的PLL进行分频...

分频器

是时序电路的基本器件,它的功能是对系统时钟或其他时钟进行分频产生所需要的时钟信号。分频有两种方式:一是通过HDL语言建模产生所需要的时钟信号,二是利用开发工具的PLL进行分频。前者分频灵活,需编写代码实现;后者使用场景受限,因为有的低端FPGA没有PLL,但PLL的分频效果更好,而且在进行小数分频时也比较容易实现。

偶分频器

若要实现二分频,则只需要在原时钟的上升沿进行输出时钟状态的翻转即可,若实现四分频,则需要一个计数器,每次在原时钟的上升沿计数,当计数器计到两个上升沿时输出时钟状态进行翻转。

设计实现四分频

实验代码

// Filename﹕ divider.v
// Author﹕YMY
// Description﹕分频器实现4分频
// Calledby﹕/
// RevisionHistory﹕22-04-21
// Revision1.0
// Email﹕
// Company﹕  
// Copyright(c) YMY, All right reserved
module  divider(
    input    wire    sys_clk   , //系统时钟,50MHZ
    input    wire    sys_rst_n , //系统复位信号

    output   reg     clk_out     //输出信号
);

reg  [1:0]  cnt ; //计数器

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            cnt <= 2'd0 ;  //如果复位信号有效,计数器清零
        end
    else if(cnt == 2'd1)
        begin
            cnt <= 2'd0 ; //如果计数到最大值,计数器清零
        end
    else
        begin
            cnt <= cnt + 1'b1  ; //其他情况继续计数
        end    
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            clk_out <= 1'b0; //如果复位信号有效,输出信号拉低
        end
    else if(cnt == 2'd1)
        begin
            clk_out <= ~clk_out ; //如果计数器计到最大,输出信号取反
        end    
    else
        begin
            clk_out <= clk_out ; //其他情况保持不变
        end    
end


endmodule

测试代码

// Filename﹕ tb_divider.v
// Author﹕YMY
// Description﹕分频器实现4分频测试
// Calledby﹕/
// RevisionHistory﹕22-04-21
// Revision1.0
// Email﹕
// Company﹕  
// Copyright(c) YMY, All right reserved
`timescale 1ns/1ns
module tb_divider();
reg   sys_clk ;
reg   sys_rst_n ;

wire  clk_out ;

//初始化
initial begin
    sys_clk = 1'b1 ;
    sys_rst_n <= 1'b0 ;
    #20
    sys_rst_n <= 1'b1 ;
end

//产生时钟信号
always #10 sys_clk =~sys_clk ;

//模块例化
divider         divider_inst
(
    . sys_clk            ( sys_clk   ), //系统时钟,50MHZ
    . sys_rst_n          ( sys_rst_n ), //系统复位信号

    . clk_out            ( clk_out   )  //输出信号
);
endmodule

波形图

image.png

现在对一般情况进行分析,对时钟进行N分频,N为偶数;则计数器每次在原时钟的上升沿计数,计数器的范围为0-(N-1),我们可以在0-(N-1)这N个数中分出两个范围选择输出时钟的状态,如当cnt在0-M范围时输出时钟为低电平,当cnt在(M+1)-(N-1)范围时输出时钟为高电平,则我们可以动态调整输出时钟的占空比,输出时钟的占空比为(N-M-1)/N;

但是我们通过这种方式分频得到的时钟,表面上是对系统时钟进行分频,产生了一个低频时钟,但实际上与真正的系统时钟还是有很大的区别。因为在FPGA中凡是时钟信号都要连接到全局时钟网络,全局时钟网络也叫全局时钟数,是FPGA厂商专门为FPGA设计的。它能够使时钟信号到达每个寄存器的时间尽可能相同,减少时序问题的产生,而我们这种分频方式产生的低频信号,并没有连接到全局时钟网络上。但是我们外部晶振传入的时钟信号通过管脚连接到了FPGA的时钟引脚上,自然就连到了全局时钟网络上,所以说在系统时钟工作下的信号,要比我们刚刚分频产生的时钟工作下的信号更容易在高速系统中保持稳定。我们用flag标志信号,每两个flag之间标志频率,就是对系统时钟的4分频。

设计如下

// Filename﹕ divider_flag.v
// Author﹕YMY
// Description﹕分频器实现4分频
// Calledby﹕/
// RevisionHistory﹕22-04-21
// Revision1.0
// Email﹕
// Company﹕  
// Copyright(c) YMY, All right reserved
module  divider_flag(
    input    wire    sys_clk   , //系统时钟,50MHZ
    input    wire    sys_rst_n , //系统复位信号

    output   reg     clk_flag    //标志
);

reg   [2:0] cnt ; //计数器

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            cnt <= 3'd0 ;  //如果复位信号有效,计数器清零
        end
    else if(cnt == 3'd3)
        begin
            cnt <= 3'd0 ; //如果计数到最大值,计数器清零
        end
    else
        begin
            cnt <= cnt + 1'b1  ; //其他情况继续计数
        end    
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            clk_flag <= 1'b0; //如果复位信号有效,输出信号拉低
        end
    else if(cnt == 3'd3)
        begin
            clk_flag <= 1'b1 ; //如果计数器计到最大,标志信号拉高
        end    
    else
        begin
            clk_out <= 1'b0 ; //其他情况拉低
        end    
end


endmodule

奇分频

分析奇数分频器的思想:整体思路是产生两路上升沿和下降沿触发信号,然后对这两路信号进行操作得到最终分频时钟。

当分频系数N为奇数时,使用一个计数器在0~(N-1)循环进行计数,控制输出(N-1)/2个高电平,(N+1)/2个低电平,称为clk_1;然后将此clk_1电平信号延迟半个周期称为clk_2,最后输出clk_out = clk_1 | clk_2,即为占空比为50%的奇数分频器;另一种思路是产生输出(N+1)/2个高电平,(N-1)/2个低电平的clk_1,输出的分频时钟为clk_out = clk_1 & clk_2。

设计实现7分频

设计代码

// Filename﹕ divider.v
// Author﹕YMY
// Description﹕分频器实现7分频
// Calledby﹕/
// RevisionHistory﹕22-04-21
// Revision1.0
// Email﹕
// Company﹕  
// Copyright(c) YMY, All right reserved
module  divider_7(
    input    wire    sys_clk   , //系统时钟,50MHZ
    input    wire    sys_rst_n , //系统复位信号

    output   wire    clk_out     //输出信号
);

reg   [2:0] cnt   ; //计数器
reg         clk_1 ; //时钟信号1
reg         clk_2 ; //时钟信号2

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            cnt <= 3'd0 ;  //如果复位信号有效,计数器清零
        end
    else if(cnt == 3'd6)
        begin
            cnt <= 3'd0 ; //如果计数到4,计数器清零
        end
    else
        begin
            cnt <= cnt + 1'b1  ; //其他情况继续计数
        end    
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            clk_1 <= 1'b0; //如果复位信号有效,输出信号拉低
        end
    else if(cnt == 3'd3)
        begin
            clk_1 <= 1'b1 ; //如果计数器计到2,时钟信号1拉高
        end  
    else if(cnt == 3'd6)
        begin
            clk_1 <= 1'b0 ; //如果计数器计到4,时钟信号1拉低
        end      
    else
        begin
            clk_1 <= clk_1 ; //其他情况保持不变
        end    
end

always @(negedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        begin
            clk_2 <= 1'b0; //如果复位信号有效,输出信号拉低
        end
    else if(cnt == 3'd3)
        begin
            clk_2 <= 1'b1 ; //如果计数器计到2,时钟信号2拉高
        end  
    else if(cnt == 3'd6)
        begin
            clk_2 <= 1'b0 ; //如果计数器计到4,时钟信号2拉低
        end      
    else
        begin
            clk_2 <= clk_2 ; //其他情况保持不变
        end    
end

assign clk_out = (clk_1 | clk_2 ) ; //输出信号等于时钟信号1或上时钟信号2

endmodule

仿真代码

// Filename﹕ tb_divider.v
// Author﹕YMY
// Description﹕分频器实现4分频测试
// Calledby﹕/
// RevisionHistory﹕22-04-21
// Revision1.0
// Email﹕
// Company﹕  
// Copyright(c) YMY, All right reserved
`timescale 1ns/1ns
module tb_divider_7();
reg   sys_clk ;
reg   sys_rst_n ;

wire    clk_out ;

//初始化
initial begin
    sys_clk = 1'b1 ;
    sys_rst_n <= 1'b0 ;
    #20
    sys_rst_n <= 1'b1 ;
end

//产生时钟信号
always #10 sys_clk =~sys_clk ;

//模块例化
divider_7         divider_7
(
    . sys_clk            ( sys_clk   ), //系统时钟,50MHZ
    . sys_rst_n          ( sys_rst_n ), //系统复位信号

    . clk_out            ( clk_out   )  //输出信号
);
endmodule


波形图

image.png





————————————————

原文链接:https://blog.csdn.net/qq_42334072/article/details/115513144


本文地址:https://xn--zqqs03dbu6a.cn/?id=38
若非特殊说明,文章均属本站原创,转载请注明原链接。

欢迎 发表评论:

标签列表

退出请按Esc键