任意分频 奇数偶数分频
任意分频的方法从网上看了有不少东西,主要有奇数分频,偶数分频,再就是任意分频。
1、先说一下任意分频,任意分频的方法类似于DDS的产生方法,Fo/Fclk = fword / 2^N; N为计数器位宽,位宽越大,计数器越精确,
如果产生1_000_010Hz频率的信号,假设位宽是32位,时钟是50M,fword = 1_000_010 * 2^32 /50_000_000 = 85900204.913 四舍五入
fword为85900205;以2^31当作门限电压,当计数器小于2^32一半的时候,div_clk输出低电平,否则输出高电平,不过存在相位抖动的
情况,一般情况采用这种方法分频是ok的。
/*----------------------------------------------------------------------- Date : 2017--XX Description : Design for LCD1602 Display. -----------------------------------------------------------------------*/ module pro_clk ( //global clock input clk, //system clock input rst_n, //sync reset //XXX interface output reg div_clk // ); //-------------------------------- //Funtion : pinlv控制字 parameter fword = 32'd85900205; reg [31:0] cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt <= 32'd0; else cnt <= cnt + fword; end //-------------------------------- //Funtion : 方波合成 always @(posedge clk or negedge rst_n) begin if(!rst_n) div_clk <= 1'd0; else if(cnt < 32'h7fff_ffff) div_clk <= 1'd0; else div_clk <= 1'd1; end //-------------------------------- //Funtion : 检测上升沿 reg div_clk_r; always @(posedge clk or negedge rst_n) begin if(!rst_n) div_clk_r <= 1'd0; else div_clk_r <= div_clk; end wire div_value; assign div_value = (div_clk == 1'b1 && div_clk_r == 1'b0) ? 1'b1 : 1'b0; endmodule
2、偶数分频就是平常大家最常用的一种方法,比如进行N分频,N为偶数,那么通过计数器从0计数到N/2 - 1,输出时钟进行反转,这样最终输出的信号就是
N倍偶数分频了。
/*-----------------------------------------------------------------------
Date : 2017-07-29
Description : Design for 奇数分频.
-----------------------------------------------------------------------*/
module pro_clk
(
//global clock
input clk, //system clock
input rst_n, //sync reset
//div_clk interface
output div_clk //
);
//--------------------------------
//Funtion : counter1
parameter N = 32'd11;
reg [31:0] cnt;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 32'd0;
else if(cnt == N - 1'b1)
cnt <= 32'd0;
else
cnt <= cnt + 1'd1;
end
//--------------------------------
//Funtion : counter2
parameter N1 = 32'd11;
reg [31:0] cnt1;
always @(negedge clk or negedge rst_n)
begin
if(!rst_n)
cnt1 <= 32'd0;
else if(cnt1 == N1 - 1'b1)
cnt1 <= 32'd0;
else
cnt1<= cnt1 + 1'd1;
end
//--------------------------------
//Funtion : 方波合成
reg div_clk1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
div_clk1 <= 1'd0;
else if(cnt == ((N >> 1'b1) - 1'b1))
div_clk1 <= 1'b0;
else if(cnt == N - 1'b1)
div_clk1 <= 1'b1;
end
//--------------------------------
//Funtion : 方波合成
reg div_clk2;
always @(negedge clk or negedge rst_n)
begin
if(!rst_n)
div_clk2 <= 1'd0;
else if(cnt1 == ((N1 >> 1'b1) - 1'b1))
div_clk2 <= 1'b0;
else if(cnt1 == N1 - 1'b1)
div_clk2 <= 1'b1;
end
//--------------------------------
//Funtion : 方波合成
assign div_clk = div_clk1 | div_clk2;
//--------------------------------
//Funtion : 检测上升沿
reg div_clk_r;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
div_clk_r <= 1'd0;
else
div_clk_r <= div_clk;
end
wire div_value;
assign div_value = (div_clk == 1'b1 && div_clk_r == 1'b0) ? 1'b1 : 1'b0;
endmodule