一、行波时钟
任意分频电路,相信很多人都听说过这个专业名词,好多视频上都说不建议使用计数器产生的分频时钟。其实在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
最后
以上就是幽默篮球最近收集整理的关于Verilog实现之任意分频电路的全部内容,更多相关Verilog实现之任意分频电路内容请搜索靠谱客的其他文章。
发表评论 取消回复