-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathclockworks.v
135 lines (113 loc) · 3.1 KB
/
clockworks.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
/*
* Clockworks includes
* - gearbox to divide clock frequency, used
* to let you observe how the design behaves
* one cycle at a time.
* - PLL to generate faster clock
* - reset mechanism that resets the design
* during the first microseconds because
* reading in Ice40 BRAM during the first
* few microseconds returns garbage !
* (made me bang my head against the wall).
*
* Parameters
* SLOW number of bits of gearbox. Clock divider
* is (1 << SLOW)
*
* Macros
* NEGATIVE_RESET if board's RESET pin goes low on reset
* ICE_STICK if board is an IceStick.
*/
`include "PLL/femtopll.v"
`ifndef BENCH
`ifdef ECP5_EVN
`define NEGATIVE_RESET
`endif
`ifdef ARTY
`define NEGATIVE_RESET
`endif
`endif
module Clockworks
(
input wire CLK, // clock pin of the board
input wire RESET, // reset pin of the board
output wire clk, // (optionally divided) clock for the design.
// divided if SLOW is different from zero.
output wire resetn // (optionally timed) negative reset for the design
);
parameter SLOW=0;
generate
/****************************************************
Slow speed mode.
- Create a clock divider to let observe what happens.
- Nothing special to do for reset
****************************************************/
if(SLOW != 0) begin
// Factor is 1 << slow_bit.
// Since simulation is approx. 16 times slower than
// actual device we use different factor for bosh.
`ifdef BENCH
localparam slow_bit=SLOW-4;
`else
localparam slow_bit=SLOW;
`endif
reg [slow_bit:0] slow_CLK = 0;
always @(posedge CLK) begin
slow_CLK <= slow_CLK + 1;
end
assign clk = slow_CLK[slow_bit];
`ifdef NEGATIVE_RESET
assign resetn = RESET;
`else
assign resetn = !RESET;
`endif
/****************************************************
High speed mode.
- Nothing special to do for the clock
- A timer that resets the design during the first
few microseconds, because reading in Ice40 BRAM
during the first few microseconds returns garbage !
(made me bang my head against the wall).
****************************************************/
end else begin
`ifdef CPU_FREQ
femtoPLL #(
.freq(`CPU_FREQ)
) pll(
.pclk(CLK),
.clk(clk)
);
`else
assign clk=CLK;
`endif
// Preserve resources on Ice40HX1K (IceStick) with
// carefully tuned counter (12 bits suffice).
// For other FPGAs, use larger counter.
`ifdef ICE_STICK
reg [11:0] reset_cnt = 0;
`else
reg [15:0] reset_cnt = 0;
`endif
assign resetn = &reset_cnt;
`ifdef NEGATIVE_RESET
always @(posedge clk,negedge RESET) begin
if(!RESET) begin
reset_cnt <= 0;
end else begin
reset_cnt <= reset_cnt + !resetn;
end
end
`else
always @(posedge clk,posedge RESET) begin
if(RESET) begin
reset_cnt <= 0;
end else begin
/* verilator lint_off WIDTH */
reset_cnt <= reset_cnt + !resetn;
/* verilator lint_on WIDTH */
end
end
`endif
end
endgenerate
endmodule