-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclock_mux.v
59 lines (43 loc) · 1.48 KB
/
clock_mux.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// From: https://www.intel.com/content/www/us/en/docs/programmable/683082/22-1/clock-multiplexing.html
/*
Switching from clock A to clock B requires that clock A continue to operate
for at least a few cycles. If clock A stops immediately, the design sticks.
*/
module clock_mux (clk, clk_select, clk_out);
parameter num_clocks = 3;
input [num_clocks-1:0] clk;
input [num_clocks-1:0] clk_select; // one hot
output clk_out;
genvar i;
reg [num_clocks-1:0] ena_r0;
reg [num_clocks-1:0] ena_r1;
reg [num_clocks-1:0] ena_r2;
wire [num_clocks-1:0] qualified_sel;
// A look-up-table (LUT) can glitch when multiple inputs
// change simultaneously. Use the keep attribute to
// insert a hard logic cell buffer and prevent
// the unrelated clocks from appearing on the same LUT.
wire [num_clocks-1:0] gated_clks /* synthesis keep */;
initial begin
ena_r0 = 0;
ena_r1 = 0;
ena_r2 = 0;
end
generate
for (i=0; i<num_clocks; i=i+1) begin: lp0
wire [num_clocks-1:0] tmp_mask;
assign tmp_mask = {num_clocks{1'b1}} ^ ({{(num_clocks-1){1'b0}}, 1'b1} << i);
assign qualified_sel[i] = clk_select[i] & (~|(ena_r2 & tmp_mask));
always @(posedge clk[i]) begin
ena_r0[i] <= qualified_sel[i];
ena_r1[i] <= ena_r0[i];
end
always @(negedge clk[i]) begin
ena_r2[i] <= ena_r1[i];
end
assign gated_clks[i] = clk[i] & ena_r2[i];
end: lp0
endgenerate
// These will not exhibit simultaneous toggle by construction
assign clk_out = |gated_clks;
endmodule