ID 683082
Date 9/26/2022
Public

## 1.6.2. Clock Multiplexing

Clock multiplexing is sometimes used to operate the same logic function with different clock sources. This type of logic can introduce glitches that create functional problems. The delay inherent in the combinational logic can also lead to timing problems. Clock multiplexers trigger warnings from a wide range of design rule check and timing analysis tools.

Use dedicated hardware to perform clock multiplexing when it is available, instead of using multiplexing logic. For example, you can use the Clock Switchover feature or the Clock Control Block available in certain Intel FPGA devices. These dedicated hardware blocks avoid glitches, ensure that you use global low-skew routing lines, and avoid any possible hold time problems on the device due to logic delay on the clock line. Intel FPGA devices also support dynamic PLL reconfiguration, which is the safest and most robust method of changing clock rates during device operation.

If your design has too many clocks to use the clock control block, or if dynamic reconfiguration is too complex for your design, you can implement a clock multiplexer in logic cells. However, if you use this implementation, consider simultaneous toggling inputs and ensure glitch-free transitions.

Figure 3. Simple Clock Multiplexer in a 6-Input LUT

Each device datasheet describes how LUT outputs can glitch during a simultaneous toggle of input signals, independent of the LUT function. Even though the 4:1 MUX function does not generate detectable glitches during simultaneous data input toggles, some cell implementations of multiplexing logic exhibit significant glitches, so this clock mux structure is not recommended. An additional problem with this implementation is that the output behaves erratically during a change in the clk_select signals. This behavior could create timing violations on all registers fed by the system clock and result in possible metastability.

A more sophisticated clock select structure can eliminate the simultaneous toggle and switching problems.

Figure 4. Glitch-Free Clock Multiplexer Structure

You can generalize this structure for any number of clock channels. The design ensures that no clock activates until all others are inactive for at least a few cycles, and that activation occurs while the clock is low. The design applies a synthesis_keep directive to the AND gates on the right side, which ensures there are no simultaneous toggles on the input of the clk_out OR gate.

Note: 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. The select signals are implemented as a “one-hot” control in this example, but you can use other encoding if you prefer. The input side logic is asynchronous and is not critical. This design can tolerate extreme glitching during the switch process.

### Verilog HDL Clock Multiplexing Design to Avoid Glitches

This example works with Verilog-2001.

module clock_mux (clk,clk_select,clk_out);

parameter num_clocks = 4;

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
assign tmp_mask = {num_clocks{1'b1}} ^ (1 << 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
endgenerate

// These will not exhibit simultaneous toggle by construction
assign clk_out = |gated_clks;

endmodule