任意倍数占空比为50%的偶数分频
以四分频为例,分频后的一个周期是分频前的四个周期,并且分频后的一个周期中,一半是高电平,一半是低电平,这就是占空比为50%的四分频。
要实现该功能,使用一个计数器在0~3之间计数,clk_out在0和2时翻转即可。
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
| module even_divider #( parameter DIVIDE_FACTOR = 4 ) ( input clk_in , input rst_n , output reg clk_out ); parameter CNT_WIDTH = $clog2(DIVIDE_FACTOR) ; reg [CNT_WIDTH : 0] cnt ; always@(posedge clk_in or negedge rst_n) begin if( ~rst_n ) begin cnt <= 'b0; end else if( cnt == DIVIDE_FACTOR - 1 ) begin cnt <= 'b0; end else begin cnt <= cnt + 1'b1; end end always@(posedge clk_in or negedge rst_n) begin if(~rst_n) begin clk_out <= 1'b0; end else if( cnt == 0 ) begin clk_out <= 1'b1; end else if( cnt == DIVIDE_FACTOR >> 1 ) begin clk_out <= 1'b0; end else begin clk_out <= clk_out; end end endmodule
|
任意倍数占空比为50%的奇数分频
以5分频为例,分频后的一个周期是分频前的五个周期,并且分频后的一个周期中,一半是高电平,一半是低电平,这就是占空比为50%的五分频。
我们先不考虑占空比,那么可以让2个周期为高,3个周期为低,或者1个周期为高,4个周期为低,这样来实现5分频。
如果占空比要求为50%,那么就必须2.5个周期为高,2.5个周期为低,该怎么办?
可以令clk1和clk2都是先2个周期为高,再3个周期为低,然后让他们的相位相差半个周期,然后令clk1和clk2进行或运算,得到最终生成的clk_out。
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
|
module odd_divider #( parameter dividor = 3 ) ( input clk_in, input rst_n, output clk_out );
parameter CNT_WIDTH = $clog2(dividor-1);
reg flag_1; reg flag_2; reg [CNT_WIDTH :0] cnt;
always @(posedge clk_in or negedge rst_n) begin if (!rst_n) cnt <= 0; else if(cnt == dividor - 1) cnt <= 0; else cnt <= cnt + 1'd1; end always @(posedge clk_in or negedge rst_n) begin if (!rst_n) flag_1 <= 0; else if( cnt == 0 ) flag_1 <= ~flag_1; else if( cnt == dividor >> 1 ) flag_1 <= ~flag_1; else flag_1 <= flag_1; end
always @(negedge clk_in or negedge rst_n) begin if (!rst_n) flag_2 <= 0; else if(cnt == 0 ) flag_2 <= ~flag_2; else if(cnt == dividor >> 1) flag_2 <= ~flag_2; else flag_2 <= flag_2; end
assign clk_out = flag_1 || flag_2; endmodule
|
Testbench
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
| `timescale 1ns / 1ps
module tb_divider(); reg clk_in,rst_n; wire odd_clk_out; wire even_clk_out; initial begin clk_in = 1; rst_n = 0; #25 rst_n = 1; #305; $finish; end always #10 clk_in = ~ clk_in; odd_divider odd_divider_u0 ( .clk_in ( clk_in ) , .rst_n ( rst_n ) , .clk_out ( odd_clk_out ) ); defparam odd_divider_u0.dividor = 5; even_divider even_divider_u0 ( .clk_in ( clk_in ) , .rst_n ( rst_n ) , .clk_out ( even_clk_out ) ); defparam even_divider_u0.DIVIDE_FACTOR = 4; endmodule
|