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