blob: cc0af252b75c417c8087aadd8ba4de925690aa88 [file] [log] [blame]
agorararmard6c766a82020-12-10 18:13:12 +02001// SPDX-FileCopyrightText: 2020 Efabless Corporation
agorararmarde5780bf2020-12-09 21:27:56 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
agorararmardafa96ea2020-12-09 23:37:31 +020014// SPDX-License-Identifier: Apache-2.0
agorararmarde5780bf2020-12-09 21:27:56 +000015
Matt Venn08cd6eb2020-11-16 12:01:14 +010016`default_nettype none
Tim Edwards3245e2f2020-10-10 14:02:11 -040017// This routine synchronizes the
18
19module caravel_clocking(
Manar61dce922020-11-10 19:26:28 +020020`ifdef USE_POWER_PINS
Tim Edwards3245e2f2020-10-10 14:02:11 -040021 input vdd1v8,
22 input vss,
23`endif
24 input resetb, // Master (negative sense) reset
25 input ext_clk_sel, // 0=use PLL clock, 1=use external (pad) clock
26 input ext_clk, // External pad (slow) clock
27 input pll_clk, // Internal PLL (fast) clock
Tim Edwards7a8cbb12020-10-12 11:32:11 -040028 input pll_clk90, // Internal PLL (fast) clock, 90 degree phase
Tim Edwards3245e2f2020-10-10 14:02:11 -040029 input [2:0] sel, // Select clock divider value (0=thru, 1=divide-by-2, etc.)
Tim Edwards7a8cbb12020-10-12 11:32:11 -040030 input [2:0] sel2, // Select clock divider value for 90 degree phase divided clock
Tim Edwards3245e2f2020-10-10 14:02:11 -040031 input ext_reset, // Positive sense reset from housekeeping SPI.
32 output core_clk, // Output core clock
Tim Edwards7a8cbb12020-10-12 11:32:11 -040033 output user_clk, // Output user (secondary) clock
Tim Edwards3245e2f2020-10-10 14:02:11 -040034 output resetb_sync // Output propagated and buffered reset
35);
36
37 wire pll_clk_sel;
Tim Edwards581068f2020-11-19 12:45:25 -050038 wire pll_clk_divided;
39 wire pll_clk90_divided;
40 wire core_ext_clk;
Tim Edwards3245e2f2020-10-10 14:02:11 -040041 reg use_pll_first;
42 reg use_pll_second;
43 reg ext_clk_syncd_pre;
44 reg ext_clk_syncd;
45
46 assign pll_clk_sel = ~ext_clk_sel;
47
48 // Note that this implementation does not guard against switching to
49 // the PLL clock if the PLL clock is not present.
50
51 always @(posedge pll_clk or negedge resetb) begin
52 if (resetb == 1'b0) begin
53 use_pll_first <= 1'b0;
54 use_pll_second <= 1'b0;
55 ext_clk_syncd <= 1'b0;
56 end else begin
57 use_pll_first <= pll_clk_sel;
58 use_pll_second <= use_pll_first;
59 ext_clk_syncd_pre <= ext_clk; // Sync ext_clk to pll_clk
60 ext_clk_syncd <= ext_clk_syncd_pre; // Do this twice (resolve metastability)
61 end
62 end
63
64 // Apply PLL clock divider
65
66 clock_div #(
67 .SIZE(3)
68 ) divider (
69 .in(pll_clk),
70 .out(pll_clk_divided),
71 .N(sel),
72 .resetb(resetb)
73 );
74
Tim Edwards7a8cbb12020-10-12 11:32:11 -040075 // Secondary PLL clock divider for user space access
76
77 clock_div #(
78 .SIZE(3)
79 ) divider2 (
80 .in(pll_clk90),
81 .out(pll_clk90_divided),
82 .N(sel2),
83 .resetb(resetb)
84 );
85
86
Tim Edwards3245e2f2020-10-10 14:02:11 -040087 // Multiplex the clock output
88
89 assign core_ext_clk = (use_pll_first) ? ext_clk_syncd : ext_clk;
90 assign core_clk = (use_pll_second) ? pll_clk_divided : core_ext_clk;
Tim Edwards7a8cbb12020-10-12 11:32:11 -040091 assign user_clk = (use_pll_second) ? pll_clk90_divided : core_ext_clk;
Tim Edwards3245e2f2020-10-10 14:02:11 -040092
93 // Reset assignment. "reset" comes from POR, while "ext_reset"
94 // comes from standalone SPI (and is normally zero unless
95 // activated from the SPI).
96
97 // Staged-delay reset
98 reg [2:0] reset_delay;
99
100 always @(posedge core_clk or negedge resetb) begin
101 if (resetb == 1'b0) begin
102 reset_delay <= 3'b111;
103 end else begin
104 reset_delay <= {1'b0, reset_delay[2:1]};
105 end
106 end
107
108 assign resetb_sync = ~(reset_delay[0] | ext_reset);
109
110endmodule
Tim Edwards581068f2020-11-19 12:45:25 -0500111`default_nettype wire