-
Notifications
You must be signed in to change notification settings - Fork 1
/
clkdiv.v
316 lines (283 loc) · 6.7 KB
/
clkdiv.v
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
//
// A generic clock divider
// by Tomek Szczesny 2022
//
// clkdiv divides the frequency of input clock signal by "divider".
// The output signal duty cycle is as near 50% as possible (sometimes less).
// In and out posedges are in sync.
//
// +------------------+
// | |
// in --->| clkdiv |---> out
// | |
// +------------------+
//
// Parameters:
// divider - a clock divider.
//
// Ports:
// in - Input
// out - Output
//
`ifndef _clkdiv_v_
`define _clkdiv_v_
module clkdiv(
input wire in,
output reg out
);
parameter divider = 31;
reg [$clog2(divider)-1:0] clkdiv = 0;
always@(posedge in)
begin
if (clkdiv == 0) begin
clkdiv <= divider - 1;
end else begin
clkdiv <= clkdiv - 1;
end
out <= clkdiv < (divider/2);
end
endmodule
//
// A high performance clock divider, by 2 or 3
// by Tomek Szczesny 2024
//
// clkdiv_2_3 divides the frequency of input clock signal by either 2 or 3,
// depending on the polarity of input signal.
// Its primary application is early stages of frequency division.
//
// This divider transitions with no glitches.
// The output signal duty cycle is near 50% if the input duty cycle is also 50%.
// In and out posedges are in sync.
//
// +----------------+
// sel --->| |
// in --->| clkdiv_2_3 |---> out
// | |
// +----------------+
//
// Parameters:
// None.
//
// Ports:
// sel - Division select (2 when low, 3 when high)
// in - Input
// out - Output
//
module clkdiv_2_3(
input wire sel,
input wire in,
output wire out
);
reg [1:0] ne = 0;
reg pe = 0;
reg rsel = 0;
always@(negedge in)
begin
if (ne == 2'b00)
begin
rsel <= sel;
ne <= {sel, 1'b1};
end
if (ne == 2'b01) ne <= 2'b00;
if (ne == 2'b11) ne <= 2'b01;
if (ne == 2'b10) ne <= 2'b00;
end
always@(posedge in)
begin
pe <= ne[0];
end
assign out = pe && (ne[0] || ~rsel);
endmodule
//
// A high performance clock divider, by 2 or 5
// by Tomek Szczesny 2024
//
// clkdiv_2_5 divides the frequency of input clock signal by either 2 or 5,
// depending on the polarity of input signal.
// Its primary application is early stages of frequency division.
//
// This divider transitions with no glitches.
// The output signal duty cycle is near 50% if the input duty cycle is also 50%.
// In and out posedges are in sync.
//
// +----------------+
// sel --->| |
// in --->| clkdiv_2_5 |---> out
// | |
// +----------------+
//
// Parameters:
// None.
//
// Ports:
// sel - Division select (2 when low, 5 when high)
// in - Input
// out - Output
//
module clkdiv_2_5(
input wire sel,
input wire in,
output wire out
);
reg [2:0] ne = 0;
reg pe = 0;
always@(negedge in)
begin
if (ne == 3'b000) ne <= sel ? 3'b001 : 3'b100;
if (ne == 3'b001) ne <= sel ? 3'b110 : 3'b100;
if (ne == 3'b011) ne <= sel ? 3'b100 : 3'b100;
if (ne == 3'b010) ne <= sel ? 3'b100 : 3'b100;
if (ne == 3'b110) ne <= sel ? 3'b111 : 3'b000;
if (ne == 3'b111) ne <= sel ? 3'b100 : 3'b000;
if (ne == 3'b101) ne <= sel ? 3'b000 : 3'b000;
if (ne == 3'b100) ne <= sel ? 3'b000 : 3'b000;
end
always@(posedge in)
begin
pe <= ne[2];
end
assign out = pe && (ne[2] || ~sel);
endmodule
//
// A Programmable clock divider
// by Tomek Szczesny 2024
//
// clkdiv_prog divides the frequency of the input clock signal by a selected
// divider ratio.
//
// The divider ratio is selected with a binary number on div input.
// The divider ratio is updated on out posedge for glitchless transitions.
//
// The output signal duty cycle is as near 50% as possible (sometimes less).
// In and out posedges are in sync.
//
// div == 0 causes out <= 0, effectively disabling the output.
//
// The reset output can be used to inhibit clock consumer for the
// duration of the transition.
// For this reason, one full clock cycle with an old setting is propagated
// with reset output high.
//
// +------------------+
// | |---> reset
// in --->| clkdiv_prog |---> out
// div[n] --->| |
// +------------------+
//
// Parameters:
// n - div width in bits
//
// Ports:
// in - Input
// div[n-1:0] - Divider ratio selection vector
// out - Output
// reset - Asserted when div != latched div value
//
`include "clkgate.v"
module clkdiv_prog(
input wire in,
input wire [n-1:0] div,
output wire reset,
output wire out
);
parameter n = 4;
reg [n-1:0] clkdiv = 0; // Divider counter
reg [n-1:0] seldiv = 0; // Selected divider ratio
reg outb = 0; // Output buffer
wire ing; // Gated input
reg [1:0] state = 0; // State register
// Reset output
assign reset = |state;
always@(posedge in)
begin
if (clkdiv <= 1) begin // Advance clkdiv
case (state)
2'b00: begin
clkdiv <= seldiv;
if (div != seldiv) state <= 2'b01;
end
2'b01: begin
clkdiv <= div;
seldiv <= div;
state <= 2'b11;
end
2'b11: begin
clkdiv <= seldiv;
state <= 2'b10;
end
2'b10: begin
clkdiv <= seldiv;
state <= 2'b00;
end
endcase
end else begin
clkdiv <= clkdiv - 1;
end
// Produce output
outb <= (clkdiv > (seldiv >> 1));
end
// Handling a special case of div == 1
// A gated clock passthrough
clkgate clkgate (
.in(in),
.gate(seldiv == 1),
.out(ing)
);
assign out = (seldiv == 1) ? ing : outb;
endmodule
//
// A Programmable clock divider
// compact version, without div1 handling
// by Tomek Szczesny 2024
//
// clkdiv_prog divides the frequency of the input clock signal by a selected
// divider ratio.
//
// The divider ratio is selected with a binary number on div input.
// The divider ratio is being read on each out posedge.
// Glitches are avoided, but sometimes it may have to cycle through the full
// capacity of 'div' input.
//
// The output signal duty cycle is as near 50% as possible (sometimes more).
// In and out posedges are in sync.
//
// div == 0 causes out <= 1, effectively disabling the output.
// div == 1 causes the gates of hell to open with an echoing squeak.
//
//
// +-----------------+
// | |
// in --->| clkdiv_prog_l |---> out
// div[n] --->| |
// +-----------------+
//
// Parameters:
// n - div width in bits
//
// Ports:
// in - Input
// div[n-1:0] - Divider ratio selection vector
// out - Output
//
module clkdiv_prog_l(
input wire in,
input wire [n-1:0] div,
output reg out
);
parameter n = 11;
reg [n-1:0] clkdiv = 1; // Divider counter
wire [n-1:0] clkdivm1;
assign clkdivm1 = clkdiv - 1;
always@(posedge in)
begin
if (clkdiv == 1) begin
clkdiv <= div;
out <= 1;
end
else begin
clkdiv <= clkdivm1;
if (clkdivm1 == div[n-1:1]) out <= 0;
end
end
endmodule
`endif