一、行波时钟

  任意分频电路,相信很多人都听说过这个专业名词,好多视频上都说不建议使用计数器产生的分频时钟。其实在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

 

四、仿真时序图