• Verilog分频器的设计


     大三都要结束了,才发现自己太多东西没深入学习。

     对于偶分频:(计数到分频数的一半就翻转)

    注:

      图中只用了一个计数器,当然也可以用多个;

      图中只计数到需要分频的一半,当然也可计数到更多;

      图中从第一个上升沿有效,当然也可延迟多个周期开始。

    例如:

     1 //任意偶分频设计
     2 module frequency_divider_6 (clk, rst, data_out);
     3     input clk, rst;
     4     output data_out;
     5     reg [1:0] counter;
     6     reg data_out;
     7     parameter N = 6;  //改变N的值变成任意偶分频,同时counter的范围需要相应修改
     8     
     9     always @ (posedge clk or negedge rst)
    10         begin
    11             if (!rst)  //复位置零
    12                 begin
    13                     counter <= 0;
    14                     data_out <= 0;
    15                 end
    16             else    //分频
    17                 begin
    18                     if (counter == N/2 - 1)  //偶分频数一半时反相
    19                         begin
    20                             data_out <= ~data_out;
    21                             counter <= 0;  //置0,从0计数
    22                         end
    23                     else
    24                         counter <= counter + 1;
    25                 end
    26         end
    27 endmodule
    View Code

        从仿真波形看出复位后并没有立刻达到分频效果,复位结束后的2.5个周期无效,之后才达到分频效果。

        如果想从第一个上升沿就开始分频,那么就可以像我画的图中那样计数。如下所示:

     1 /任意偶分频设计
     2 module frequency_divider_6 (clk, rst, data_out);
     3     input clk, rst;
     4     output data_out;
     5     reg [1:0] counter;
     6     reg data_out;
     7     parameter N = 6;  //改变N的值变成任意偶分频,同时counter的范围需要相应修改
     8     
     9     always @ (posedge clk or negedge rst)
    10         begin
    11             if (!rst)  //复位置零
    12                 begin
    13                     data_out <= 0;
    14                 end
    15             else    //分频,也可用底下注释部分
    16                 begin
    17                     if (counter == 0)  //偶分频数一半时反相
    18                         begin
    19                             data_out <= ~data_out;
    20                         end
    21                     else
    22                         data_out <= data_out;
    23                 end
    24         end
    25     always @ (posedge clk or negedge rst)
    26         begin
    27             if (!rst)
    28                 begin
    29                     counter <= 0;
    30                 end
    31             else
    32                 begin
    33                     if (counter == (N / 2 - 1))
    34                         begin
    35                             counter <= 0;
    36                         end
    37                     else
    38                         counter <= counter + 1;
    39                 end
    40         end
    41 endmodule
    View Code

        注意到此代码和上一个同样是6分频的,此处把计数部分和分频部分分离开来,可读性强一些吧。此处只计数到 2 就把计数器清零,计数到 0 输出的分频信号就翻转。

     

        从仿真波形可看出从第一个上升沿就计数了。

    计数到 N - 1 (注意计数器位宽)例如:

     1 //任意偶分频设计
     2 module frequency_divider_6 (clk, rst, data_out);
     3     input clk, rst;
     4     output data_out;
     5     reg [2:0] counter;
     6     reg data_out;
     7     parameter N = 6;  //改变N的值变成任意偶分频,同时counter的范围需要相应修改
     8             
     9     always @ (posedge clk or negedge rst)
    10         begin
    11             if (!rst)  //复位置零
    12                 begin
    13                     data_out <= 0;//此处为1也可,看需求
    14                 end
    15             else    //分频,也可用底下注释部分
    16                 begin
    17                     if (counter < (N >> 1))  //偶分频数一半时反相
    18                         begin
    19                             data_out <= 1;
    20                         end
    21                     else
    22                         data_out <= 0;
    23                 end
    24         end
    25     always @ (posedge clk or negedge rst)
    26         begin
    27             if (!rst)
    28                 begin
    29                     counter <= 0;
    30                 end
    31             else
    32                 begin
    33                     if (counter == (N - 1))
    34                         begin
    35                             counter <= 0;
    36                         end
    37                     else
    38                         counter <= counter + 1;
    39                 end
    40         end
    41 endmodule
    View Code

        

        写法多种多样,差别都不太大,不再一一举例,根据需求设计即可。

    对于奇分频:(用两个计数器分别计到上升沿和下降沿达到分频数 (N - 1) / 2 和 (N + 1) / 2 时翻转)

    注:

      图中用了两个计数器,当然也可以用多个(两个就够了);

      图中只计数到需要分频数的(N - 1) / 2 和 (N + 1) / 2,时翻转,得到的波形需要相或;

      图中从第一个上升沿有效,当然也可延迟多个周期开始。

    例如:

     1 //任意奇分频设计
     2 module frequency_divider_5 (clk, rst, clk_p, clk_n, data_out);
     3     input clk, rst;
     4     output clk_p, clk_n, data_out;
     5     reg clk_p, clk_n;
     6     reg [2:0] counter_p, counter_n;
     7     parameter N = 5;  //改变N的值实现任意奇分频,注意counter_p和counter_n的范围
     8     //分频
     9     always @ (posedge clk or negedge rst) //上升沿计数与反相
    10         begin
    11             if (!rst) //复位置0,从0计数
    12                 begin
    13                     counter_p <= 0;
    14                     clk_p <= 0;
    15                 end
    16             else
    17                 begin
    18                     if (counter_p == N - 1)
    19                         counter_p <= 0;
    20                     else
    21                          counter_p <= counter_p + 1;
    22                     if ((counter_p == (N - 1) / 2) || (counter_p == N - 1))
    23                         clk_p <= ~clk_p;
    24                 end
    25         end
    26     always @ (negedge clk or negedge rst) //下降沿计数与反相
    27         begin
    28             if (!rst)
    29                 begin
    30                     counter_n <= 0;
    31                     clk_n <= 0;
    32                 end
    33             else 
    34             begin
    35                 if (counter_n == N - 1)
    36                     counter_n <= 0;
    37                 else
    38                      counter_n <= counter_n + 1;
    39                 if ((counter_n == (N - 1) / 2) || (counter_n == N - 1))
    40                     clk_n <= ~clk_n;
    41             end
    42         end
    43     assign data_out = clk_p | clk_n;  //相或运算,得到50%占空比的分频输出信号
    44 endmodule
    45     
    View Code

        和偶分频同样的情况,复位后有多个无效周期。

        如果想从第一个上升沿就开始分频,那么就可以像我画的图中那样计数。如下所示:

     

         从仿真波形可看出从第一个上升沿就计数了。

        除此之外,还可以计数到这些就翻转:

      1 和 (N - 1) / 2

      (N - 1) / 2 和 N - 1

      等等,根据需求即可

     比如:

     1 //任意奇分频设计
     2 module frequency_divider_5 (clk, rst, clk_p, clk_n, data_out);
     3     input clk, rst;
     4     output clk_p, clk_n, data_out;
     5     reg clk_p, clk_n;
     6     reg [2:0] counter_p, counter_n;
     7     parameter N = 5;  //改变N的值实现任意奇分频,注意counter_p和counter_n的范围
     8     
     9     always @ (posedge clk or negedge rst)  //上升沿计数器
    10         begin
    11             if (!rst) 
    12                 counter_p <= 0;
    13             else 
    14                 if (counter_p == N - 1)
    15                     counter_p <= 0;
    16                 else
    17                      counter_p <= counter_p + 1;
    18         end
    19     always @ (posedge clk or negedge rst)  //上升沿反相
    20         begin
    21             if (!rst)
    22                 clk_p <= 0;
    23             else 
    24                 if (counter_p < (N >> 1))  //N整体向右移动一位,最高位补零,其实就是N/2,不过在计算奇数的时候有很明显的优越性
    25                     clk_p <= 1;
    26                 else
    27                     clk_p <= 0;
    28         end
    29 
    30     always @ (negedge clk or negedge rst)  //下降沿计数器
    31         begin
    32             if (!rst) 
    33                 counter_n <= 0;
    34             else 
    35                 if (counter_n == N - 1)
    36                     counter_n <= 0;
    37                 else
    38                      counter_n <= counter_n + 1;
    39         end
    40     always @ (negedge clk or negedge rst)  //下降沿反相
    41         begin
    42             if (!rst)
    43                 clk_n <= 0;
    44             else 
    45                 if ((counter_n < (N >> 1))
    46                     clk_n <= 1;
    47                 else
    48                     clk_n <= 0;
    49         end
    50     assign data_out = clk_p | clk_n;  //相或运算,得到50%占空比的分频输出信号
    51 endmodule
    View Code

    任意分频设计:

     1 //下面是任意正整数的分频/ 此时举例是6倍频 /
     2 module frequency_divider_all (clk, rst, data_out, clk_p, clk_n);
     3 
     4     input clk, rst;
     5     output data_out, clk_p, clk_n;
     6 
     7     parameter WIDTH = 3;  //计数器二进制位宽
     8     parameter N     = 6;  //分频数(任意正整数)
     9 
    10     reg [WIDTH-1:0] counter_p;// 上升沿计数单位
    11     reg [WIDTH-1:0] counter_n;// 下降沿计数单位
    12     reg             clk_p;// 上升沿时钟
    13     reg             clk_n;// 下降沿时钟
    14 
    15     assign data_out = (N == 1) ? clk : (N[0]) ? (clk_p | clk_n) : clk_p;//其中N==1是判断不分频,N[0]是判断是奇数还是偶数,若为1则是奇数分频,若是偶数则是偶数分频。
    16             
    17     always @ (posedge clk or negedge rst) 
    18         begin
    19             if (!rst)
    20                 counter_p <= 0;
    21             else 
    22                 if (counter_p == (N - 1))
    23                     counter_p <= 0;
    24                 else
    25                     counter_p <= counter_p + 1;
    26         end
    27 
    28     always @ (posedge clk or negedge rst) 
    29         begin
    30             if (!rst) 
    31                 clk_p <= 1;//此处设置为0也是可以的,这个没有硬性的要求,不管是取0还是取1结果都是正确的。
    32             else 
    33                 if (counter_p < (N >> 1))//N整体向右移动一位,最高位补零,其实就是N/2,不过在计算奇数的时候有很明显的优越性
    34                     clk_p <= 1;
    35                 else
    36                     clk_p <= 0;    
    37         end
    38 
    39     always @ (negedge clk or negedge rst) 
    40         begin
    41             if (!rst)
    42                 counter_n <= 0;
    43             else 
    44                 if (counter_n == (N - 1))
    45                     counter_n <= 0;
    46                 else
    47                     counter_n <= counter_n + 1;
    48         end
    49 
    50     always @ (negedge clk or negedge rst) 
    51         begin
    52             if (!rst)
    53                 clk_n <= 1;
    54             else 
    55                 if (counter_n < (N >> 1))
    56                     clk_n <= 1;
    57                 else
    58                     clk_n <= 0;
    59         end
    60 
    61 endmodule

     

    总结

         多思考总有新发现。

    如有错误还请指出,如有侵权还请告知,如需转载请注明出处!                                              

    本人博客:http://www.cnblogs.com/yllinux/

  • 相关阅读:
    C++ 函数返回数组指针的问题
    cmake 静态调用 c++ dll 的类的一个例子(Clion IDE)[更新1:增加1.模版的应用,2.ma 的算法]
    一月5日
    一月5日
    一月5日
    一月5日
    一月5日
    一月5日
    一月5日
    一月5日
  • 原文地址:https://www.cnblogs.com/yllinux/p/7063652.html
Copyright © 2020-2023  润新知