原理如下圖(為了方便簡潔,去掉了rst_n)
波形是這樣的

代碼就是根據電路圖寫的
1 /////////////////////////////////////////////////////////////////////////////////////////// 2 // DATE : Wed Jun 6 23:31:57 CST 2012 3 /////////////////////////////////////////////////////////////////////////////////////////// 4 module clk_sw( 5 input wire clk_a 6 , input wire clk_b 7 , input wire rst_n 8 , input wire sel 9 , output wire clk_o 10 ); 11 /////////////////////////////////////////////////////////////////////////////////////////// 12 // variable declaration 13 reg clk_a_en ; 14 reg clk_b_en ; 15 /////////////////////////////////////////////////////////////////////////////////////////// 16 // logic 17 always @(posedge clk_a or negedge rst_n) begin 18 if(~rst_n) clk_a_en <= 1'b0 ; 19 else clk_a_en <= ~sel & ~clk_b_en ; 20 end 21 always @(posedge clk_b or negedge rst_n) begin 22 if(~rst_n) clk_b_en <= 1'b0 ; 23 else clk_b_en <= sel & ~clk_a_en ; 24 end 25 assign clk_o = (clk_a & clk_a_en) | (clk_b & clk_b_en) ; 26 /////////////////////////////////////////////////////////////////////////////////////////// 27 28 endmodule // CREATED by poiu_elab@1207 29 30 ///////////////////////////////////////////////////////////////////////////////////////////
testbench是這樣的
1 ///////////////////////////////////////////////////////////////////////////////////////////
2 // DATE : Wed Jun 6 23:42:58 CST 2012
3 ///////////////////////////////////////////////////////////////////////////////////////////
4 `define CLK_A_CYCLE 23
5 `define CLK_B_CYCLE 47
6 module tb();
7 ///////////////////////////////////////////////////////////////////////////////////////////
8 // variable declaration
9 reg clk_a ;
10 reg clk_b ;
11 reg rst_n ;
12 reg sel ;
13 wire clk_o ;
14 ///////////////////////////////////////////////////////////////////////////////////////////
15 // stimulation generation
16 initial forever #(`CLK_A_CYCLE/2) clk_a = ~clk_a;
17 initial forever #(`CLK_B_CYCLE/2) clk_b = ~clk_b;
18 initial begin
19 rst_n = 1'b0 ;
20 clk_a = 1'b1 ;
21 clk_b = 1'b1 ;
22 sel = 1'b0 ;
23 #500;
24 rst_n = 1'b1 ;
25 #500;
26 #({$random}%13+500);
27 sel = ~sel ;
28 #({$random}%23+500);
29 sel = ~sel ;
30 #({$random}%33+500);
31 sel = ~sel ;
32 #({$random}%43+500);
33 sel = ~sel ;
34 #({$random}%53+500);
35 sel = ~sel ;
36 #({$random}%63+500);
37 sel = ~sel ;
38 #({$random}%73+500);
39 sel = ~sel ;
40 #({$random}%83+500);
41 sel = ~sel ;
42 #({$random}%93+500);
43 sel = ~sel ;
44 #({$random}%13+500);
45 sel = ~sel ;
46 #({$random}%23+500);
47 sel = ~sel ;
48 #({$random}%33+500);
49 sel = ~sel ;
50 #({$random}%43+500);
51 sel = ~sel ;
52 #({$random}%53+500);
53 sel = ~sel ;
54 #({$random}%63+500);
55 sel = ~sel ;
56 #({$random}%73+500);
57 sel = ~sel ;
58 #({$random}%83+500);
59 sel = ~sel ;
60 #({$random}%93+500);
61 sel = ~sel ;
62 #5000;
63 $stop;
64 end
65 ///////////////////////////////////////////////////////////////////////////////////////////
66 // module instaniation
67 clk_sw u_clk_sw(
68 .clk_a ( clk_a )
69 , .clk_b ( clk_b )
70 , .rst_n ( rst_n )
71 , .sel ( sel )
72 , .clk_o ( clk_o )
73 );
74 ///////////////////////////////////////////////////////////////////////////////////////////
75
76 endmodule // CREATED by poiu_elab@1207
77
78 ///////////////////////////////////////////////////////////////////////////////////////////
這里的核心就是你的sel發生翻轉的時候,首先肯定是在本時鐘域內的clk_en會先變低(invalid),之后才會使得另外時鐘域內的clk_en變高(valid),這時另外一個時鐘域內的時鐘才能和clk_en相與輸出。
簡而言之,比如一開始是clk_a有效,clk_out為clk_a,sel翻轉后,clk_a_en在clk_a的時鐘域內先關斷(拉低),使得clk_out持續拉低,clk_a_en變低后,clk_b_en在clk_b的時鐘域內才能被拉高有效,這時同步的clk_b_en信號與clk_b相與就能使得clk_out成功切換到clk_b了。
原理就是這樣,其中clk_a_en和clk_b_en不會同時有效就避免了時鐘切換的時候窄脈沖及毛刺的生成,但是我覺得由于是組合邏輯輸出的時鐘總歸還是會有一些缺點和不足的。不知道有沒有什么更好的辦法。
編輯:hfy
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
時鐘
+關注
關注
11文章
1971瀏覽量
135000 -
波形
+關注
關注
3文章
407瀏覽量
33080
發布評論請先 登錄
相關推薦
熱點推薦
一個時鐘異步切換原理圖
評論