• Verilog实现之任意分频电路


    一、行波时钟

      任意分频电路,相信很多人都听说过这个专业名词,好多视频上都说不建议使用计数器产生的分频时钟。其实在FPGA领域当中,由寄存器分频产生的时钟还有一个学名叫做,行波时钟。是由时序逻辑产生比如A寄存器的输出作为B寄存的时钟输入(一般不建议使用),如下图所示;驱动右边那个触发器的时钟即为行波时钟。之所以不建议使用在FPGA中使用行波时钟,因为这样会在FPGA设计中引入新的时钟域,,增加时序分析的难度,并且由于行波时钟的相位通常会滞后于原始时钟,会导致后续触发器的保持时间不一定能满足。

      事实上,采用行波时钟的目的无非是为后续时序电路的处理速度进行降频,而要实现降频的功能,除了通过降低时钟信号的频率外,仍然可以通过控制后续时序电路存储单元的使能端来实现,因此,上例中的电路完全可以修改如下:这样一来,整个时序逻辑将只被一个时钟信号所驱动。

    二、任意分频电路

      虽然说比建议使用分屏电路。但是在一些对时序要求不高的情况下是完全可以用的。而且还可以节省PLL和DCM等资源。那么设计一个任意分频的电路。这里的关键是偶数分频和奇数分频两大块。占空比一般都是50%。分频电路的整体架构如下:

       1、偶数分频:可以不用介绍,计数到N/2翻转就可以。

       2、奇数分频    第一步:上升沿触发进行模N计数,从0开始计数,计数到0+(n-1)/2,进行翻转,即为clk_odd= ~clk_odd

                第二步:还是在上升沿的条件下,从接着第一步计数,在其基础上再计数(n-1)/2,再次翻转;clk_odd= ~clk_odd

                                    第三步:在下降沿的条件下,采集clk_odd,即:clk_odd_r = clk_odd

             第四步;输出clk_odd_out = clk_odd_r |clk_odd;即为所求‘。

    三、实现  

      1 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      2 // Project Name : 
      3 // Website      : https://home.cnblogs.com/lgy-gdeu/
      4 // Author         : LGY GUET Uiversity
      5 // Weixin         : li15226499835
      6 // Email          : 15277385992@163.com
      7 // File           : 
      8 // Create         : 2020-07-01
      9 // Revise         : 
     10 // Editor         : sublime text{SUBLIME_VERSION}, tab size ({TABS})
     11 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     12 // Modification History:
     13 // Date             By              Version                 Change Description
     14 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     15 // {DATE} {TIME}    LGY           1.0                        ++++++++++++++++ 
     16 // *********************************************************************************
     17 `timescale      1ns/1ns
     18 module mux_cnt(
     19 input            wire                     sclk     ,
     20 input            wire                    s_rst_n  ,
     21 input             wire[3:0]               div      ,
     22 output          wire                    clk_out 
     23     );
     24 
     25 //========================================================================
     26 // ################ Define Parameter and Internal signals ################ 
     27 //========================================================================/
     28 localparam             DIV1 = 1                ;
     29 localparam            DIV2 = 2                ;
     30 localparam          DIV3 = 3                ;
     31 localparam          DIV4 = 4                ;
     32 localparam          DIV5 = 5                ;
     33 localparam          DIV6 = 6                ;
     34 localparam            DIV7 = 7                ;
     35 localparam          DIV8 = 8                ;
     36 reg        [7:0]            fre_en          ;
     37 //=============================================================================
     38 //+++++++++++++++++++++++++     Main Code    +++++++++++++++++++++++++++++++
     39 //=============================================================================
     40 //分频模式的使能,一共是8种模式
     41 always @(posedge sclk or negedge s_rst_n)begin
     42         if(!s_rst_n)begin
     43             fre_en    <=   0;
     44         end    
     45         else begin
     46             case(div )
     47                 DIV1 :   fre_en   <=  8'b0000_0001 ;
     48                 DIV2 :   fre_en   <=  8'b0000_0010 ;
     49                 DIV3 :   fre_en   <=  8'b0000_0100 ;
     50                 DIV4 :   fre_en   <=  8'b0000_1000 ;
     51                 DIV5 :   fre_en   <=  8'b0001_0000 ;
     52                 DIV6 :   fre_en   <=  8'b0010_0000 ;
     53                 DIV7 :   fre_en   <=  8'b0100_0000 ;
     54                 DIV8 :   fre_en   <=  8'b1000_0000 ;                
     55             endcase
     56         end
     57 end
     58 
     59 //计数模块
     60 reg                [3:0]            fre_cnt       ;
     61 always @(posedge sclk or negedge s_rst_n)begin
     62     if(!s_rst_n)begin
     63         fre_cnt   <=    0 ;
     64     end
     65     else begin
     66         case (1'b1)
     67             fre_en[0]  :  begin
     68                 ;
     69             end
     70             fre_en[1]  :  begin
     71                 ;
     72             end
     73             fre_en[2]  : begin
     74                 if(fre_cnt < 2)
     75                     fre_cnt  <= fre_cnt + 1'b1 ;
     76                 else 
     77                     fre_cnt  <= 0 ;    
     78             end
     79             fre_en[3]  : begin
     80                 if(fre_cnt<3)
     81                     fre_cnt   <= fre_cnt + 1'b1 ;
     82                 else 
     83                     fre_cnt   <= 0;    
     84             end
     85             fre_en[4]  : begin
     86                 if(fre_cnt<4)
     87                     fre_cnt   <= fre_cnt +  1'b1 ;
     88                 else 
     89                     fre_cnt   <= 0;
     90             end
     91             fre_en[5]  : begin
     92                 if(fre_cnt<5)
     93                     fre_cnt   <= fre_cnt +  1'b1 ;
     94                 else 
     95                     fre_cnt   <= 0;    
     96             end
     97             fre_en[6]  : begin
     98                 if(fre_cnt<6)
     99                     fre_cnt   <= fre_cnt + 1'b1 ;
    100                 else 
    101                     fre_cnt   <= 0;    
    102             end
    103             fre_en[7]  : begin
    104                 if(fre_cnt<7)
    105                     fre_cnt   <= fre_cnt + 1'b1  ;
    106                 else 
    107                     fre_cnt   <= 0;    
    108             end
    109 
    110         endcase
    111     end
    112 end
    113 //分频模块
    114 reg          clk_out_odd_r    ;   //奇数分频,中间变量
    115 reg          clk_out_even     ;   //偶数分频,直接输出 
    116 always @ (posedge sclk or negedge s_rst_n) begin
    117     if(s_rst_n == 1'b0)begin
    118         clk_out_even  <= 0;
    119         clk_out_odd_r <= 0; 
    120     end    
    121     else begin
    122         case  (1'b1)
    123             fre_en[0] :  begin
    124                 ;
    125             end
    126             fre_en[1] :  begin
    127                 clk_out_even <= ~clk_out_even ;
    128             end
    129             fre_en[2] :  begin// 3 div
    130                 if (fre_cnt==1)
    131                     clk_out_odd_r   <=  ~clk_out_odd_r;
    132                 else if(fre_cnt==2)
    133                     clk_out_odd_r   <=  ~clk_out_odd_r;    
    134                 else
    135                     clk_out_odd_r   <= clk_out_odd_r;    
    136             end
    137             fre_en[3] :  begin//4 div
    138                 if(fre_cnt == 1)
    139                     clk_out_even    <= ~clk_out_even  ;
    140                 else if(fre_cnt ==3)
    141                     clk_out_even    <= ~clk_out_even   ;
    142                 else
    143                     clk_out_even    <=  clk_out_even   ;                  
    144             end
    145             fre_en[4] :  begin//5 div
    146                 if(fre_cnt == 2)
    147                     clk_out_odd_r   <=  ~clk_out_odd_r;
    148                 else if(fre_cnt == 4)
    149                     clk_out_odd_r   <=  ~clk_out_odd_r;
    150                 else 
    151                     clk_out_odd_r   <=  clk_out_odd_r ;    
    152                             
    153             end
    154             fre_en[5] : begin// 6 div
    155                 if (fre_cnt == 2)
    156                     clk_out_even    <=  ~clk_out_even  ;
    157                 else if(fre_cnt == 5)
    158                     clk_out_even    <=  ~clk_out_even  ;
    159                 else
    160                     clk_out_even    <=  clk_out_even;                
    161             end
    162             fre_en[6] :  begin //7div
    163                 if(fre_cnt == 3)
    164                     clk_out_odd_r    <=  ~clk_out_odd_r ;
    165                 else if(fre_cnt ==6)
    166                     clk_out_odd_r    <=  ~clk_out_odd_r ;
    167                 else
    168                     clk_out_odd_r    <=  clk_out_odd_r ;        
    169             end 
    170             fre_en[7] : begin // 8 div
    171                 if(fre_cnt == 3)
    172                     clk_out_even     <=  ~clk_out_even  ;
    173                 else if(fre_cnt ==7)
    174                     clk_out_even     <=  ~clk_out_even  ;
    175                 else 
    176                     clk_out_even     <=  clk_out_even ;            
    177             end
    178 
    179         endcase
    180     end    
    181         
    182 end
    183 
    184 //中间输出模块
    185 reg             clk_out_odd_r1 ;//用来存放下降沿采集的数据
    186 always @(negedge  sclk or negedge s_rst_n)begin
    187     if(!s_rst_n)
    188         clk_out_odd_r1   <=   0;
    189     else begin
    190         case (1'b1 )
    191             fre_en[0] : begin
    192                 ;
    193             end
    194             fre_en[1] : begin
    195                 ;
    196             end
    197             fre_en[2] : begin
    198                 clk_out_odd_r1   <=  clk_out_odd_r ;
    199             end
    200             fre_en[3] : begin
    201                 ;
    202             end
    203             fre_en[4] : begin
    204                 clk_out_odd_r1   <=  clk_out_odd_r ;
    205             end
    206             fre_en[5] : begin
    207                 ;
    208             end
    209             fre_en[6] : begin
    210                 clk_out_odd_r1   <=  clk_out_odd_r ;
    211             end
    212             fre_en[7] : begin
    213                 ;
    214             end
    215         endcase 
    216     end    
    217 end
    218 
    219 //最后的输出
    220 //assign     clk_out   =  ( fre_en[0] | fre_en[1] | fre_en[3] | fre_en[5] | fre_en[7] )?clk_out_even:clk_out_odd_r|clk_out_odd_r1;
    221 assign    clk_out   =  fre_en[0]? sclk :(( fre_en[1] | fre_en[3] | fre_en[5] | fre_en[7])?clk_out_even:clk_out_odd_r|clk_out_odd_r1);
    222 
    223 endmodule

    激励文件

     

     1 `timescale 1ns / 1ps
     2 //////////////////////////////////////////////////////////////////////////////////
     3 // Company: 
     4 // Engineer: 
     5 // 
     6 // Create Date: 2020/07/01 14:59:38
     7 // Design Name: 
     8 // Module Name: mux_cnt_tb
     9 // Project Name: 
    10 // Target Devices: 
    11 // Tool Versions: 
    12 // Description: 
    13 // 
    14 // Dependencies: 
    15 // 
    16 // Revision:
    17 // Revision 0.01 - File Created
    18 // Additional Comments:
    19 // 
    20 //////////////////////////////////////////////////////////////////////////////////
    21 
    22 
    23 module mux_cnt_tb();
    24 reg            sclk     ;
    25 reg            s_rst_n  ;
    26 reg  [3:0]     div      ;
    27 wire           clk_out  ;
    28 
    29 //=============================================================================
    30 //+++++++++++++++++++++++++     Main Code    +++++++++++++++++++++++++++++++里
    31 //=============================================================================
    32 
    33 //initial begin
    34 //    sclk   =  0 ;
    35 //    forever  begin
    36 //        #2  sclk = ~sclk ;
    37 //    end
    38 //end
    39 
    40 
    41 
    42 
    43 initial begin
    44     sclk  = 0;
    45     s_rst_n = 0;
    46     div = 3 ;
    47     #20
    48     s_rst_n = 1;
    49     #400
    50     div = 1; 
    51     #600
    52     s_rst_n = 1;
    53     div = 5;
    54     #1200
    55     div = 2;
    56     #600
    57 
    58     $finish;
    59     
    60 end
    61 always #10 sclk = ~sclk ;
    62 
    63 
    64 mux_cnt inst_mux_cnt (.sclk(sclk), .s_rst_n(s_rst_n), .div(div), .clk_out(clk_out));
    65 
    66 
    67 endmodule

    四、仿真时序图

       

      

     

  • 相关阅读:
    join
    PS1-4
    tftp + bras
    awk调用shell
    curl
    ssh
    查看cp进度,使用watch
    tftp
    scp 链接文件的问题 + tar
    mysql必知必会(三、使用mysql)
  • 原文地址:https://www.cnblogs.com/lgy-gdeu/p/13221754.html
Copyright © 2020-2023  润新知