在通常的学习中,或者一些网络课程当中,总会强调使用PLLIP核出来的时钟。但是在实际中并非所有的逻辑都是有那么高的逻辑要求。通过语言进行时钟的分频相移显得十分方便,这种方法可以节省芯片内部的锁相环资源,再者,通过语言设计进行时钟分频,可以锻炼我们对verilog的熟练和理解程度。这里主要讲解奇数倍分频。
奇数倍分频:
如果不要求占空比为50%的话,也比较容易实现,如进行三分频,通过待分频时钟上升沿触发计数器进行模三计数,当计数器计数到邻近值进行两次翻转,比如可以在计数器计数到1时,输出时钟进行翻转,计数到2时再次进行翻转。即在计数值在邻近的1和2进行了两次翻转。这样实现的三分频占空比为1/3或者2/3。
奇数倍分频操作步骤:
对于实现占空比为50%的N倍奇数分频,我们可以分解为两个通道:
第一个通道:
第一步:上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,
第二步:然后经过(N-1)/2再次进行翻转得到一个占空比为非50%奇数N分频时钟;
第一个通道:
第一步:下降沿触发进行模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟时钟翻转。
第一步:同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数N分频时钟。
最后输出:将这两个占空比非50%的N分频时钟或运算,得到占空比为50%的奇数n分频时钟。
具体例子:5分频等占空比,可以通过待分频时钟下降沿和上升沿触发0~4计数,
①对于待分频时钟的上升沿,当计数器cnt1计数到1时,
clk_p翻转;当计数器计数到3(1 + (5 - 1) / 2 = 3)时,clk_p再次反转;
②对于待分频时钟的下降沿,当计数器cnt2计数到1时,
clk_n翻转;当计数器计数到3(1 + (5 - 1) / 2 = 3)时,clk_n再次反转;
③然后下降沿产生的5分频时钟和上升沿产生的5分频时钟进行或运算,
即可得到占空比为50%的N分频时钟。
例程:实现三分频,占空比50%
1 // ********************************************************************************* 2 // Project Name : 3 // weixin : li15226499835 4 // Website : https://www.cnblogs.com/lgy-gdeu/ 5 // Create Time : 2020// 6 // File Name : .v 7 // Module Name : 8 // Abstract : 9 // editor : sublime text 3 10 // ********************************************************************************* 11 // Modification History: 12 // Date By Version Change Description 13 // ----------------------------------------------------------------------- 14 // 2020// Liguoyong 1.0 Original 15 // 16 // ********************************************************************************* 17 `timescale 1ns/1ns 18 module three_clock_divide ( 19 //system signals 20 input wire sclk , 21 input wire s_rst_n , 22 //out div_three_clock 23 output wire div_three_clock 24 25 ); 26 27 //========================================================================\ 28 // =========== Define Parameter and Internal signals =========== 29 //========================================================================/ 30 reg [1:0] cnt_1 ; 31 reg [1:0] cnt_2 ; 32 reg clk_p ; 33 reg clk_n ; 34 35 //============================================================================= 36 //**************************** Main Code ******************************* 37 //============================================================================= 38 39 //cnt_1 40 always @(posedge sclk or negedge s_rst_n)begin 41 if(!s_rst_n) 42 cnt_1 <= 0; 43 else if(cnt_1 == 2'b10) 44 cnt_1 <= 0; 45 else 46 cnt_1 <= cnt_1 + 1'b1 ; 47 48 end 49 50 //cnt_2 51 always @(negedge sclk or negedge s_rst_n)begin 52 if(!s_rst_n) 53 cnt_2 <= 0 ; 54 else if(cnt_2 == 2'b10) 55 cnt_2 <= 0 ; 56 else 57 cnt_2 <= cnt_2 + 1'b1 ; 58 end 59 60 //clk_p 61 always @(posedge sclk or negedge s_rst_n)begin 62 if(!s_rst_n) 63 clk_p <= 1'b0; 64 else if(cnt_1== 2'b01) 65 clk_p <= ~clk_p; 66 else if(cnt_1==2'b10) 67 clk_p <= ~clk_p; 68 else 69 clk_p <= clk_p; 70 71 end 72 73 //clk_n 74 always @(negedge sclk or negedge s_rst_n)begin 75 if(!s_rst_n) 76 clk_n <= 0 ; 77 else if(cnt_2 == 2'b01) 78 clk_n <= ~clk_n ; 79 else if(cnt_2 == 2'b10) 80 clk_n <= ~clk_n ; 81 else 82 clk_n <= clk_n; 83 84 end 85 assign div_three_clock = clk_p | clk_n; 86 87 endmodule
测试激励:
1 // ********************************************************************************* 2 // Project Name : 3 // weixin : li15226499835 4 // Website : https://www.cnblogs.com/lgy-gdeu/ 5 // Create Time : 2020// 6 // File Name : .v 7 // Module Name : 8 // Abstract : 9 // editor : sublime text 3 10 // ********************************************************************************* 11 // Modification History: 12 // Date By Version Change Description 13 // ----------------------------------------------------------------------- 14 // 2020// Liguoyong 1.0 Original 15 // 16 // ********************************************************************************* 17 `timescale 1ns/1ns 18 19 module tb_three_clock_div (); 20 21 reg tb_sclk ; 22 reg tb_s_rst_n ; 23 wire o_clk ; 24 25 initial begin 26 tb_sclk = 1'b1 ; 27 tb_s_rst_n<= 1'b0 ; 28 #100 29 tb_s_rst_n<= 1'b1 ; 30 #10000 31 $finish; 32 end 33 always #20 tb_sclk = ~tb_sclk ; 34 35 36 //例化 37 three_clock_divide three_clock_divide_inst( 38 //system signals 39 .sclk (tb_sclk), 40 .s_rst_n (tb_s_rst_n), 41 //out div_three_clock 42 .div_three_clock (o_clk) 43 44 ); 45 46 endmodule
仿真: