I. Issues
Assume that such a clock control model exists:
CLK1, CLK2 and the system clock frequency and phase are not consistent, we want to clk_sel = 1, the output CLK1, and vice versa output CLK2, CLK_SEL can be driven by the system clock, can also be driven by the combinatorial logic. In this case, the following "burr" problem occurs:
It can be seen that at the junction of CLK_SEL, it is very easy to have a burr in the CLK_OUT clock, thus affecting the normal operation of the system.
II. Solutions
(The following method is from B station UP: Pitt Pie)
The specific ideas are: 1. Two clocks are mutually exclusive outputs, i.e., the two non-gates B4 and B5 are used as inputs to the final A2 and A4;
2. The S3 and S6 registers are synchronized to sel using a falling edge drive, so that the output of both clocks can be done without burrs with a delay of one beat.
The analysis is as follows: when sel is 0, the initial value of ali_2 is 0, ali_1 is 1, and A1 is selected, and then two beats of synchronization are made to the ai signal driven by CLKA, and then S3 samples the beat-synchronized signals at the falling edge of CLKA, so that CLK-OUT is always pulled low due to the fact that CLKA is 0 before the falling edge to the latter rising edge, and then CLKA is high, at which time CLKA is 1 and ai2_2 is 1 because ai2_2 has been synchronized on the previous falling edge, at which time CLK_OUT outputs CLKA.
Essentially trading delay for accuracy.
III. Codes
Based on the above RTL, the code is as follows:
-
RTL
// // =============================================================================
// File Name : clk_gating_module.v
// Module : clk_gating_module
// Function : Burr free clock switching
// Type : RTL
// Aythor : Dongyang
// -----------------------------------------------------------------------------
// Update History :
// -----------------------------------------------------------------------------
`timescale 1 ns/1 ns
module clk_gating_module(
input sys_clk ,
input sys_rst_n ,
input i_clka ,
input i_clkb ,
input i_clk_sel ,
output o_clk_out
);
//******************** siganl define ********************
wire a1i_1 ;
wire a1i_2 ;
wire a3i_1 ;
wire a1o ;
wire a3o ;
wire a3i_2 ;
wire a2o ;
wire a4o ;
reg a4i_2 = 'b0;
reg a2i_2 = 'b0;
reg [1:0] a1o_dly = 'b0;
reg [1:0] a3o_dly = 'b0;
//******************** assign *****************************
assign a1i_1 = ~i_clk_sel ;
assign a3i_1 = i_clk_sel ;
assign a1i_2 = ~a4i_2 ;
assign a3i_2 = ~a2i_2 ;
assign a1o = a1i_1 & a1i_2 ;
assign a3o = a3i_2 & a3i_1;
assign a2o = i_clka & a2i_2;
assign a4o = a4i_2 & i_clkb;
assign o_clk_out = a2o | a4o ;
//**********************always*********************************
// CLKA domain
always @(posedge i_clka) begin
if(~sys_rst_n) begin
a1o_dly <= 'b0;
end
else begin
a1o_dly<= {a1o_dly[0],a1o};
end
end
always @(negedge i_clka) begin
if(~sys_rst_n) begin
a2i_2 <= 'b0;
end
else begin
a2i_2 <= a1o_dly[1];
end
end
//CLK B domain
always @(posedge i_clkb) begin
if(~sys_rst_n) begin
a3o_dly <= 'b0;
end
else begin
a3o_dly<= {a3o_dly[0],a3o};
end
end
always @(negedge i_clkb) begin
if(~sys_rst_n) begin
a4i_2 <= 'b0;
end
else begin
a4i_2 <= a3o_dly[1];
end
end
endmodule
-
TestBench
`timescale 1 ns/1 ns
module tb_clk_gatting();
reg clka = 'b0;
reg clkb = 'b0;
reg sys_clk = 'b0;
reg sys_rst_n = 'b0;
reg clk_sel = 'b0 ;
initial begin
clka = 'b0;
clkb = 'b0;
sys_clk = 'b0;
sys_rst_n = 'b0;
clk_sel = 'b0 ;
#6
clkb = 'b1;
#100
sys_rst_n = 'b1;
#1000
clk_sel = 1'b1;
#756
clk_sel = 1'b1;
#1500
clk_sel = 1'b0;
end
always # 10 sys_clk = ~sys_clk; //sys_clk 50M
always # 50 clka = ~clka ; // CLKA 10M
always # 30 clkb = ~clkb ; // CLKB 16.6M
clk_gating_module U_clk_gating_module(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.i_clka (clka),
.i_clkb (clkb),
.i_clk_sel (clk_sel),
.o_clk_out ()
);
endmodule
IV. Simulation Waveforms