agorararmard | 6c766a8 | 2020-12-10 18:13:12 +0200 | [diff] [blame] | 1 | // SPDX-FileCopyrightText: 2020 Efabless Corporation |
agorararmard | e5780bf | 2020-12-09 21:27:56 +0000 | [diff] [blame] | 2 | // |
| 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. |
agorararmard | afa96ea | 2020-12-09 23:37:31 +0200 | [diff] [blame] | 14 | // SPDX-License-Identifier: Apache-2.0 |
agorararmard | e5780bf | 2020-12-09 21:27:56 +0000 | [diff] [blame] | 15 | |
Matt Venn | 08cd6eb | 2020-11-16 12:01:14 +0100 | [diff] [blame] | 16 | `default_nettype none |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 17 | // This routine synchronizes the |
| 18 | |
| 19 | module caravel_clocking( |
Manar | 61dce92 | 2020-11-10 19:26:28 +0200 | [diff] [blame] | 20 | `ifdef USE_POWER_PINS |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 21 | 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 Edwards | 7a8cbb1 | 2020-10-12 11:32:11 -0400 | [diff] [blame] | 28 | input pll_clk90, // Internal PLL (fast) clock, 90 degree phase |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 29 | input [2:0] sel, // Select clock divider value (0=thru, 1=divide-by-2, etc.) |
Tim Edwards | 7a8cbb1 | 2020-10-12 11:32:11 -0400 | [diff] [blame] | 30 | input [2:0] sel2, // Select clock divider value for 90 degree phase divided clock |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 31 | input ext_reset, // Positive sense reset from housekeeping SPI. |
| 32 | output core_clk, // Output core clock |
Tim Edwards | 7a8cbb1 | 2020-10-12 11:32:11 -0400 | [diff] [blame] | 33 | output user_clk, // Output user (secondary) clock |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 34 | output resetb_sync // Output propagated and buffered reset |
| 35 | ); |
| 36 | |
| 37 | wire pll_clk_sel; |
Tim Edwards | 581068f | 2020-11-19 12:45:25 -0500 | [diff] [blame] | 38 | wire pll_clk_divided; |
| 39 | wire pll_clk90_divided; |
| 40 | wire core_ext_clk; |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 41 | 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 Edwards | 7a8cbb1 | 2020-10-12 11:32:11 -0400 | [diff] [blame] | 75 | // 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 Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 87 | // 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 Edwards | 7a8cbb1 | 2020-10-12 11:32:11 -0400 | [diff] [blame] | 91 | assign user_clk = (use_pll_second) ? pll_clk90_divided : core_ext_clk; |
Tim Edwards | 3245e2f | 2020-10-10 14:02:11 -0400 | [diff] [blame] | 92 | |
| 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 | |
| 110 | endmodule |
Tim Edwards | 581068f | 2020-11-19 12:45:25 -0500 | [diff] [blame] | 111 | `default_nettype wire |