blob: aa49d6f4a892751ab1ea388f988183edc6884d0a [file] [log] [blame]
Matt Venn08cd6eb2020-11-16 12:01:14 +01001`default_nettype none
Tim Edwards3245e2f2020-10-10 14:02:11 -04002// This routine synchronizes the
3
4module caravel_clocking(
Manar61dce922020-11-10 19:26:28 +02005`ifdef USE_POWER_PINS
Tim Edwards3245e2f2020-10-10 14:02:11 -04006 input vdd1v8,
7 input vss,
8`endif
9 input resetb, // Master (negative sense) reset
10 input ext_clk_sel, // 0=use PLL clock, 1=use external (pad) clock
11 input ext_clk, // External pad (slow) clock
12 input pll_clk, // Internal PLL (fast) clock
Tim Edwards7a8cbb12020-10-12 11:32:11 -040013 input pll_clk90, // Internal PLL (fast) clock, 90 degree phase
Tim Edwards3245e2f2020-10-10 14:02:11 -040014 input [2:0] sel, // Select clock divider value (0=thru, 1=divide-by-2, etc.)
Tim Edwards7a8cbb12020-10-12 11:32:11 -040015 input [2:0] sel2, // Select clock divider value for 90 degree phase divided clock
Tim Edwards3245e2f2020-10-10 14:02:11 -040016 input ext_reset, // Positive sense reset from housekeeping SPI.
17 output core_clk, // Output core clock
Tim Edwards7a8cbb12020-10-12 11:32:11 -040018 output user_clk, // Output user (secondary) clock
Tim Edwards3245e2f2020-10-10 14:02:11 -040019 output resetb_sync // Output propagated and buffered reset
20);
21
22 wire pll_clk_sel;
23 reg use_pll_first;
24 reg use_pll_second;
25 reg ext_clk_syncd_pre;
26 reg ext_clk_syncd;
27
28 assign pll_clk_sel = ~ext_clk_sel;
29
30 // Note that this implementation does not guard against switching to
31 // the PLL clock if the PLL clock is not present.
32
33 always @(posedge pll_clk or negedge resetb) begin
34 if (resetb == 1'b0) begin
35 use_pll_first <= 1'b0;
36 use_pll_second <= 1'b0;
37 ext_clk_syncd <= 1'b0;
38 end else begin
39 use_pll_first <= pll_clk_sel;
40 use_pll_second <= use_pll_first;
41 ext_clk_syncd_pre <= ext_clk; // Sync ext_clk to pll_clk
42 ext_clk_syncd <= ext_clk_syncd_pre; // Do this twice (resolve metastability)
43 end
44 end
45
46 // Apply PLL clock divider
47
48 clock_div #(
49 .SIZE(3)
50 ) divider (
51 .in(pll_clk),
52 .out(pll_clk_divided),
53 .N(sel),
54 .resetb(resetb)
55 );
56
Tim Edwards7a8cbb12020-10-12 11:32:11 -040057 // Secondary PLL clock divider for user space access
58
59 clock_div #(
60 .SIZE(3)
61 ) divider2 (
62 .in(pll_clk90),
63 .out(pll_clk90_divided),
64 .N(sel2),
65 .resetb(resetb)
66 );
67
68
Tim Edwards3245e2f2020-10-10 14:02:11 -040069 // Multiplex the clock output
70
71 assign core_ext_clk = (use_pll_first) ? ext_clk_syncd : ext_clk;
72 assign core_clk = (use_pll_second) ? pll_clk_divided : core_ext_clk;
Tim Edwards7a8cbb12020-10-12 11:32:11 -040073 assign user_clk = (use_pll_second) ? pll_clk90_divided : core_ext_clk;
Tim Edwards3245e2f2020-10-10 14:02:11 -040074
75 // Reset assignment. "reset" comes from POR, while "ext_reset"
76 // comes from standalone SPI (and is normally zero unless
77 // activated from the SPI).
78
79 // Staged-delay reset
80 reg [2:0] reset_delay;
81
82 always @(posedge core_clk or negedge resetb) begin
83 if (resetb == 1'b0) begin
84 reset_delay <= 3'b111;
85 end else begin
86 reset_delay <= {1'b0, reset_delay[2:1]};
87 end
88 end
89
90 assign resetb_sync = ~(reset_delay[0] | ext_reset);
91
92endmodule