blob: 4abdae9b46785acfc3fa7fa809be57ba1d4affa3 [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;
Tim Edwards581068f2020-11-19 12:45:25 -050023 wire pll_clk_divided;
24 wire pll_clk90_divided;
25 wire core_ext_clk;
Tim Edwards3245e2f2020-10-10 14:02:11 -040026 reg use_pll_first;
27 reg use_pll_second;
28 reg ext_clk_syncd_pre;
29 reg ext_clk_syncd;
30
31 assign pll_clk_sel = ~ext_clk_sel;
32
33 // Note that this implementation does not guard against switching to
34 // the PLL clock if the PLL clock is not present.
35
36 always @(posedge pll_clk or negedge resetb) begin
37 if (resetb == 1'b0) begin
38 use_pll_first <= 1'b0;
39 use_pll_second <= 1'b0;
40 ext_clk_syncd <= 1'b0;
41 end else begin
42 use_pll_first <= pll_clk_sel;
43 use_pll_second <= use_pll_first;
44 ext_clk_syncd_pre <= ext_clk; // Sync ext_clk to pll_clk
45 ext_clk_syncd <= ext_clk_syncd_pre; // Do this twice (resolve metastability)
46 end
47 end
48
49 // Apply PLL clock divider
50
51 clock_div #(
52 .SIZE(3)
53 ) divider (
54 .in(pll_clk),
55 .out(pll_clk_divided),
56 .N(sel),
57 .resetb(resetb)
58 );
59
Tim Edwards7a8cbb12020-10-12 11:32:11 -040060 // Secondary PLL clock divider for user space access
61
62 clock_div #(
63 .SIZE(3)
64 ) divider2 (
65 .in(pll_clk90),
66 .out(pll_clk90_divided),
67 .N(sel2),
68 .resetb(resetb)
69 );
70
71
Tim Edwards3245e2f2020-10-10 14:02:11 -040072 // Multiplex the clock output
73
74 assign core_ext_clk = (use_pll_first) ? ext_clk_syncd : ext_clk;
75 assign core_clk = (use_pll_second) ? pll_clk_divided : core_ext_clk;
Tim Edwards7a8cbb12020-10-12 11:32:11 -040076 assign user_clk = (use_pll_second) ? pll_clk90_divided : core_ext_clk;
Tim Edwards3245e2f2020-10-10 14:02:11 -040077
78 // Reset assignment. "reset" comes from POR, while "ext_reset"
79 // comes from standalone SPI (and is normally zero unless
80 // activated from the SPI).
81
82 // Staged-delay reset
83 reg [2:0] reset_delay;
84
85 always @(posedge core_clk or negedge resetb) begin
86 if (resetb == 1'b0) begin
87 reset_delay <= 3'b111;
88 end else begin
89 reset_delay <= {1'b0, reset_delay[2:1]};
90 end
91 end
92
93 assign resetb_sync = ~(reset_delay[0] | ext_reset);
94
95endmodule
Tim Edwards581068f2020-11-19 12:45:25 -050096`default_nettype wire