OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [mp3/] [lib/] [xilinx/] [unisims/] [CLKDLL.v] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 266 lampret
// $Header: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/mp3/lib/xilinx/unisims/CLKDLL.v,v 1.1.1.1 2001-11-04 18:59:46 lampret Exp $
2
 
3
/*
4
 
5
FUNCTION        : Clock Delay Locked Loop
6
 
7
*/
8
 
9
`timescale  1 ps / 1 ps
10
 
11
module CLKDLL (CLK0, CLK90, CLK180, CLK270, CLK2X, CLKDV, LOCKED,
12
               CLKIN, CLKFB, RST);
13
 
14
parameter CLKDV_DIVIDE = 2.0;
15
parameter DUTY_CYCLE_CORRECTION = "TRUE";
16
parameter MAXPERCLKIN = 100000;
17
 
18
input  CLKIN, CLKFB, RST;
19
output CLK0, CLK90, CLK180, CLK270, CLK2X, CLKDV, LOCKED;
20
reg    CLK0, CLK90, CLK180, CLK270, CLK2X, CLKDV;
21
 
22
reg    lock_period, lock_delay, lock_clkin, lock_clkfb;
23
reg    delay_found;
24
time   clkin_edge[0:1];
25
time   delay_edge[0:1];
26
time   period, delay, delay_fb;
27
 
28
wire   clkin_in, clkfb_in, rst_in;
29
reg    locked_out;
30
wire   clk0_int, clk2x_int, clk4x_int, clkdv_int;
31
wire   clk2x_2575, clk2x_5050;
32
 
33
reg    clkin_window, clkfb_window;
34
reg    clk1x, clkin_5050, clk1x_5050;
35
reg    clk1x_shift125, clk1x_shift250;
36
reg    clk2x_shift;
37
 
38
reg    [7:0] count3, count4, count5;
39
reg    [32:1] divider;
40
reg    [7:0] divide_type;
41
reg    clk1x_type;
42
reg    rst_1, rst_2;
43
reg    notifier;
44
 
45
initial begin
46
  clk1x          <= 0;
47
  clk1x_5050     <= 0;
48
  clk1x_shift125 <= 0;
49
  clk1x_shift250 <= 0;
50
  clk2x_shift    <= 0;
51
  clkfb_window   <= 0;
52
  clkin_5050     <= 0;
53
  clkin_edge[0]  <= 1'bx;
54
  clkin_edge[1]  <= 1'bx;
55
  clkin_window   <= 0;
56
  count3         <= 0;
57
  count4         <= 0;
58
  count5         <= 0;
59
  delay          <= 0;
60
  delay_fb       <= 0;
61
  delay_found    <= 0;
62
  divider        <= 0;
63
  lock_delay     <= 0;
64
  lock_period    <= 0;
65
  period         <= 0;
66
 
67
  case (DUTY_CYCLE_CORRECTION)
68
    "false" : clk1x_type <= 0;
69
    "FALSE" : clk1x_type <= 0;
70
    "true"  : clk1x_type <= 1;
71
    "TRUE"  : clk1x_type <= 1;
72
    default : begin
73
                $display("Error : DUTY_CYCLE_CORRECTION = %s is neither TRUE nor FALSE.", DUTY_CYCLE_CORRECTION);
74
                $finish;
75
              end
76
  endcase
77
 
78
  case (CLKDV_DIVIDE)
79
    1.5   : divide_type <= 'd3;
80
    2.0   : divide_type <= 'd4;
81
    2.5   : divide_type <= 'd5;
82
    3.0   : divide_type <= 'd6;
83
    4.0   : divide_type <= 'd8;
84
    5.0   : divide_type <= 'd10;
85
    8.0   : divide_type <= 'd16;
86
    16.0  : divide_type <= 'd32;
87
    default : begin
88
                $display("Error : CLKDV_DIVIDE = %f is not 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 8.0 or 16.0.", CLKDV_DIVIDE);
89
                $finish;
90
              end
91
  endcase
92
end
93
 
94
//
95
// input wire delays
96
//
97
buf b_clkin (clkin_in, CLKIN);
98
buf b_clkfb (clkfb_in, CLKFB);
99
buf b_rst (rst_in, RST);
100
buf b_locked (LOCKED, locked_out);
101
 
102
//
103
// determine clock period
104
//
105
always @(posedge clkin_in) begin
106
  clkin_edge[0] <= $time;
107
  clkin_edge[1] <= clkin_edge[0];
108
  if (rst_2)
109
    period <= 0;
110
  else if (period < clkin_edge[0] - clkin_edge[1] - 100)
111
    period <= clkin_edge[0] - clkin_edge[1];
112
  else if (period > clkin_edge[0] - clkin_edge[1] + 100)
113
    period <= clkin_edge[0] - clkin_edge[1];
114
end
115
 
116
always @(period) begin // period changed reset everything
117
  clk1x          <= 0;
118
  clk1x_5050     <= 0;
119
  clk1x_shift125 <= 0;
120
  clk1x_shift250 <= 0;
121
  clk2x_shift    <= 0;
122
  clkin_5050     <= 0;
123
  delay          <= 0;
124
  delay_fb       <= 0;
125
  delay_found    <= 0;
126
  lock_delay     <= 0;
127
  lock_period    <= 0;
128
  if (period < clkin_edge[0] - clkin_edge[1] - 100)
129
    lock_period <= 0;
130
  else if (period > clkin_edge[0] - clkin_edge[1] + 100)
131
    lock_period <= 0;
132
  else if ((clkin_edge[0] != 1'bx) && (clkin_edge[1] != 1'bx))
133
    lock_period <= 1;
134
end
135
 
136
always @(posedge lock_period) begin
137
  if (period > MAXPERCLKIN) begin
138
    $display("    \$maxperiod( posedge CLKIN:%0.3f", $time/1000, "ns,  %0d", MAXPERCLKIN, " : %0.3f", period/1000, "ns );");
139
  end
140
end
141
 
142
//
143
// determine clock delay
144
//
145
always @ (lock_period or delay_found) begin
146
  if (lock_period && !delay_found) begin
147
    assign CLK0 = 0; assign CLK2X = 0;
148
    #period
149
    assign CLK0 = 1; assign CLK2X = 1;
150
    delay_edge[1] = $time;
151
    @(posedge clkfb_in)
152
    delay_edge[0] = $time;
153
    #period
154
    assign CLK0 = 0; assign CLK2X = 0;
155
    deassign CLK0; deassign CLK2X;
156
    delay = (10 * period - (delay_edge[0] - delay_edge[1])) % period;
157
    delay_found = 1;
158
  end
159
end
160
 
161
always @ (lock_period or delay_found) begin
162
  if (lock_period && delay_found) begin
163
    for (delay_fb = 0; delay_fb < delay; delay_fb = delay_fb + 1000)
164
      @(posedge clkin_in);
165
    delay_fb <= delay;
166
  end
167
end
168
 
169
always @ (posedge clkin_in) begin
170
  if (rst_2) begin
171
    clk1x          <= 0;
172
    clk1x_5050     <= 0;
173
    clk1x_shift125 <= 0;
174
    clk1x_shift250 <= 0;
175
    clk2x_shift    <= 0;
176
    clkin_5050     <= 0;
177
    delay          <= 0;
178
    delay_fb       <= 0;
179
    delay_found    <= 0;
180
    lock_delay     <= 0;
181
    lock_period    <= 0;
182
    period         <= 0;
183
  end
184
end
185
 
186
always @ (posedge clkfb_in) begin
187
  #0   clkfb_window = 1;
188
  #100 clkfb_window = 0;
189
end
190
 
191
always @ (posedge clkin_in) begin
192
  #0   clkin_window = 1;
193
  #100 clkin_window = 0;
194
end
195
 
196
always @ (posedge clkin_in) begin
197
  #1
198
  if (clkfb_window && delay_found)
199
    lock_clkin <= 1;
200
  else
201
    lock_clkin <= 0;
202
end
203
 
204
always @ (posedge clkfb_in) begin
205
  #1
206
  if (clkin_window && delay_found)
207
    lock_clkfb <= 1;
208
  else
209
    lock_clkfb <= 0;
210
  @ (posedge clkfb_in);
211
end
212
 
213
always @ (lock_clkin or lock_clkfb) begin
214
  if (lock_clkin || lock_clkfb)
215
    lock_delay <= 1;
216
  else
217
    lock_delay <= 0;
218
end
219
 
220
//
221
// generate master reset signal
222
//
223
always @ (posedge clkin_in) begin
224
   {rst_2,rst_1} <= {rst_1,rst_in};
225
end
226
 
227
//
228
// generate lock signal
229
//
230
always @ (posedge clkin_in) begin
231
  locked_out <= lock_delay & lock_period & ~rst_2;
232
end
233
 
234
//
235
// generate the clk0_int
236
//
237
always @ (clkin_in) begin
238
  if (delay_found)
239
    clk1x <= #delay_fb clkin_in;
240
end
241
 
242
always @ (posedge clkin_in) begin
243
  clkin_5050 <= 1;
244
  #(period/2)
245
  clkin_5050 <= 0;
246
end
247
 
248
always @ (clkin_5050) begin
249
  if (delay_found)
250
    clk1x_5050 <= #delay_fb clkin_5050;
251
end
252
 
253
assign clk0_int = (clk1x_type) ? clk1x_5050 : clk1x;
254
 
255
//
256
// generate the clk2x_int
257
//
258
always @(clk1x_5050) begin
259
  clk1x_shift125 <= #(period/8) clk1x_5050;
260
  clk1x_shift250 <= #(period/4) clk1x_5050;
261
end
262
 
263
assign clk2x_2575 = clk1x_5050 & ~clk1x_shift250;
264
assign clk2x_5050 = clk1x_5050 ^ clk1x_shift250;
265
assign clk2x_int = (locked_out) ? clk2x_5050 : clk2x_2575;
266
 
267
//
268
// generate the clk4x_int
269
//
270
always @(clk2x_5050) begin
271
  clk2x_shift <= #(period/8) clk2x_5050;
272
end
273
 
274
assign clk4x_int = locked_out & (clk2x_5050 ^ clk2x_shift);
275
 
276
//
277
// generate the clkdv_int
278
//
279
always @ (negedge rst_2) begin
280
  count3  <= 0;
281
  count4  <= 0;
282
  count5  <= 0;
283
  divider <= 0;
284
end
285
 
286
always @(posedge clk4x_int) begin
287
  if (count3 == 0)
288
    divider[3] <= divider[3] + 1;
289
  count3 <= (count3 + 1) % 3;
290
end
291
 
292
always @(posedge clk4x_int) begin
293
  if (count4 == 0)
294
    divider[4] <= divider[4] + 1;
295
  count4 <= (count4 + 1) % 4;
296
end
297
 
298
always @(posedge clk4x_int) begin
299
  if (count5 == 0)
300
    divider[5] <= divider[5] + 1;
301
  count5 <= (count5 + 1) % 5;
302
end
303
 
304
always @(posedge divider[3]) begin
305
  divider[6] <= divider[6] + 1;
306
end
307
 
308
always @(posedge divider[4]) begin
309
  divider[8] <= divider[8] + 1;
310
end
311
 
312
always @(posedge divider[5]) begin
313
  divider[10] <= divider[10] + 1;
314
end
315
 
316
always @(posedge divider[8]) begin
317
  divider[16] <= divider[16] + 1;
318
end
319
 
320
always @(posedge divider[16]) begin
321
  divider[32] <= divider[32] + 1;
322
end
323
 
324
assign clkdv_int = divider[divide_type];
325
 
326
//
327
// generate all output signal
328
//
329
always @ (clk0_int) begin
330
    CLK0 <= clk0_int;
331
end
332
 
333
always @ (clk0_int) begin
334
    CLK90 <= #(period/4) clk0_int;
335
end
336
 
337
always @ (clk0_int) begin
338
    CLK180 <= #(period/2) clk0_int;
339
end
340
 
341
always @ (clk0_int) begin
342
    CLK270 <= #(3*period/4) clk0_int;
343
end
344
 
345
always @ (clk2x_int) begin
346
    CLK2X <= clk2x_int;
347
end
348
 
349
always @ (clkdv_int) begin
350
    CLKDV <= clkdv_int;
351
end
352
 
353
specify
354
        specparam CLKFBDLYLH = 0:0:0, CLKFBDLYHL = 0:0:0;
355
        specparam CLKINDLYLH = 0:0:0, CLKINDLYHL = 0:0:0;
356
        specparam RSTDLYLH = 0:0:0, RSTDLYHL = 0:0:0;
357
        specparam LOCKEDDLYLH = 0:0:0, LOCKEDDLYHL = 0:0:0;
358
        specparam PWCLKINHI = 0:0:0, PWCLKINLO = 0:0:0;
359
        specparam PWRSTHI = 0:0:0;
360
        specparam MINPERCLKIN = 10:10:10;
361
 
362
        (CLKIN => LOCKED) = (CLKINDLYLH + LOCKEDDLYLH, CLKINDLYHL + LOCKEDDLYHL);
363
        $width (posedge CLKIN, PWCLKINHI, 0, notifier);
364
        $width (negedge CLKIN, PWCLKINLO, 0, notifier);
365
        $width (posedge RST, PWRSTHI, 0, notifier);
366
        $period (posedge CLKIN, MINPERCLKIN, notifier);
367
endspecify
368
 
369
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.