当前位置:   article > 正文

Verilog奇数分频(个人总结)

verilog奇数分频

Verilog奇数分频(个人总结)

 奇数分频器跟偶数分频器一样,当计数器的值等于分频系数(加1或者减1)的一半或等于分频系数时,时钟信号翻转。奇数分频器分频原理如下图:
在这里插入图片描述
 上图的分频系数是3,用一个计数器在上升沿计数,每次计数到1翻转一次,每次计数到3再翻转一次,然后周期重复得到信号clkp1,它的周期就是clk的3倍,但是它的占空比不是50%(占空比就是clk为高的时间占整个时钟周期的百分比)。奇数分频想通过计数器直接分频出占空比是50%的时钟是不可能的,必须要通过中间的临时波形,做一些逻辑“与”“或”的动作才能得到占空比50%的分频时钟。

方法一作逻辑“与”操作

以下代码是个人的一个总结,实现了7分频,要想实现其他奇数分频,改变div数值即可(相比其他的,还是比较容易看懂理解的)。

module frequency_div
#(parameter div = 6)
(
    input   clk,
    input   rst_n,
    output  clk_div
);

//奇数分频情况
reg [3:0]cnt;
reg clk_test;
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 4'b0;
    end
    else if(cnt == div)
        cnt <= 4'b0;    
    else begin
        cnt <= cnt + 1;
    end
end

reg clk_1;
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        clk_1 <= 1'b0;
    end
    else if(cnt == div/2 +2)//注意个人写法,下文有分析
        clk_1 <= 1'b0;
    else if(cnt == 4'd1)
        clk_1 <= 1'b1;
end

reg clk_2;
always@(negedge clk or negedge rst_n)begin
    if(!rst_n)begin
        clk_2 <= 1'b0;
    end
    else if(cnt == div/2 +2)
        clk_2 <= 1'b0;
    else if(cnt == 4'd1)
        clk_2 <= 1'b1;
end
    
assign  clk_div = clk_1 & clk_2;     
    
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

代码中只需要定义clk_1和clk_2就行(注意上升沿触发和下降沿触发的区别),若要修改分频系数,改变div数值即可。

上述文中cnt == div/2 +2和cnt == 4’d1是对“奇数分频器跟偶数分频器一样,当计数器的值等于分频系数(加1或者减1)的一半或等于分频系数时,时钟信号翻转”的解释。至于为什么不选择cnt == div/2 +1和cnt == 4’d0,下文仿真会有解释。

先贴出tb文件代码:

`timescale 1ns / 1ps
module tb_frequency_div(
    );
reg clk;
reg rst_n;
wire clk_div;

initial begin
    clk = 1'b0;
    rst_n = 1'b0;
    #9 
    rst_n = 1'b1;
end

always #10 clk = ~clk;
   
frequency_div u_frequency_div(
    .clk        (clk),
    .rst_n      (rst_n),
    .clk_div    (clk_div)    
);       
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

选择cnt == div/2 +1和cnt == 4’d0的仿真:
在这里插入图片描述

选择cnt == div/2 +2和cnt == 4’d1的仿真:
在这里插入图片描述
可以发现复位之后,第一种有一段缺失,效果较差,第二种更完整一些,故选择第二种。这边对于这段代码做出解释,防止阅读难以理解。

方法二做逻辑“或”操作

相比逻辑与操作更加容易理解与实现一些

实现5分频代码:

module fre_div (
    input   clk,
    input   rst_n,
    output  clk_div
);

reg     clk_div1;
reg     clk_div2;
reg     [2:0]cnt;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt <= 3'd0;
    end
    else if(cnt != 3'd4)begin
        cnt <= cnt + 1'b1;
    end
    else begin
        cnt <= 3'd0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        clk_div1 <= 1'b0;
    end
    else if (cnt == 3'd0) begin
        clk_div1 <= ~clk_div1;
    end
    else if (cnt == 3'd2) begin
        clk_div1 <= ~clk_div1;
    end
    else begin
        clk_div1 <= clk_div1;
    end
end

always @(negedge clk or negedge rst_n) begin
    if (!rst_n) begin
        clk_div2 <= 1'b0;
    end
    else begin
        clk_div2 <= clk_div1;
    end
end

assign clk_div = clk_div1 | clk_div2;
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

tb文件

`timescale 1ns/100ps

module tb_fre_div ();
reg clk;
reg rst_n;
wire clk_div;
initial begin
    clk = 0;
    rst_n = 0;
    
    #10 
    rst_n = 1;
end

always #10 clk = ~clk;

fre_div u_fre_div(
    .clk        (clk),
    .rst_n      (rst_n),
    .clk_div    (clk_div)

);

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

仿真结果
在这里插入图片描述
  可以观察到逻辑或的规律是:计数cnt计到想要分频的n-1次(从0开始),clk_div1在cnt为0时候翻转一次,然后在(n-1)/2的时候再翻转一次,然后clk_div2在下降沿采样clk_div1,最后将两个信号取或操作即可。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/519140
推荐阅读
相关标签
  

闽ICP备14008679号