搜档网
当前位置:搜档网 › 任意分频的verilog语言实现

任意分频的verilog语言实现

任意分频的verilog语言实现

网上看到的,很有帮助,zz与此

现来说说分频原理吧,原理通了,什么都好办了。

1. 偶数倍(2N)分频

使用一模N计数器模块即可实现,即每当模N计数器上升沿从0开始计数至N时,输出时钟进行翻转,同时给计数器一复位信号使之从0开始重新计数,以此循环即可。偶数倍分频原理示意图见图1。

2. 奇数倍(2N+1)分频

(1)占空比为X/(2N+1)或(2N+1-X)/(2N+1)分频,用模(2N+1)计数器模块可以实现。取0至2N之间一数值X(0
(2)占空比为50%的分频,设计思想如下:基于(1)中占空比为非50%的输出时钟在输入时钟的上升沿触发翻转;若在同一个输入时钟周期内,此计数器的两次输出时钟翻转分别在与(1)中对应的下降沿触发翻转,输出的时钟与(1)中输出的时钟进行逻辑或,即可得到占空比为50%的奇数倍分频时钟。当然其输出端再与偶数倍分频器串接则可以实现偶数倍分频。奇数倍分频原理示意图见图2。(这也是许多公司常出的面试题,^_^,是不是很简单?)

3. N-0.5倍分频

采用模N计数器可以实现。具体如下:计数器从0开始上升沿计数,计数达到N-1上升沿时,输出时钟需翻转,由于分频值为N-0.5,所以在时钟翻转后经历0.5个周期时,计数器输出时钟必须进行再次翻转,即当CLK为下降沿时计数器的输入端应为上升沿脉冲,使计数器计数达到N而复位为0重新开始计数同时输出时钟翻转。这个过程所要做的就是对CLK进行适当的变换,使之送给计数器的触发时钟每经历N-0.5个周期就翻转一次。N-0.5倍:取N=3,分频原理示意图见图3。



对于任意的N+A/B倍分频(N、A、B∈Z,A≦B)



分别设计一个分频值为N和分频值N+1的整数分频器,采用脉冲计数来控制单位时间内两个分频器出现的次数,从而获得所需要的小数分频值。可以采取如下方法来计算个子出现的频率:



设N出现的频率为a,则N×a+(N+1)×(B-a)=N×B+A 求解a=B-A; 所以N+1出现的频率为A.例如实现7+2/5分频,取a为3,即7×3+8×2就可以实现。但是由于这种小数分频输出的时钟脉冲抖动很大,现实中很少使用。





//很实用也是笔试面试时常考的,已经经过仿真

占空比要求50%和不要求占空比差别会很大,先看一个占空比50%的描述
module div3(CLKIN,CLKOUT,RESETn);
input CLKIN,RESETn;
output CLKOUT;

//internal counter signals
reg[1:0] count_a;
reg[1:0] count_b;

reg CLKOUT;

always @(negedge RESETn or posedge CLKIN)
begin
if (RESETn==1'b0)
count_a<=2'b00;
else
if (count_a==2'b10)
count_a<=2'b00;
else
count_a<=count_a+1;
end

always @(negedge RESETn or negedge CLKIN)
begin
if (RESETn==1'b0)
count_b<=2'b0;
else
if (count_b==2'b10)
count_b<=2'b00;
else
count_b<=count_b+1;
end

always @(count_a or count_b or RESETn)
begin
if (RESETn==1'b0)
CLKOUT=1'b0;
else if((count_a+count_b==4)||(count_a+ count_b==1))
CLKOUT=~CLKOUT;
end


endmodule

0 1 2 0 1 2
\ / / \ \ / / \
0 1 2 0 1 2

下面是一个非50%的描述,只用了上升沿

module div3(CLKIN,CLKOUT,RESETn);
input CLKIN,RESETn;
output CLKOUT;


wire d;
reg q1,q2;
wire CLKOUT;

always @(negedge RESETn or posedge CLKIN)
begin
if (RESETn==1'b0)
q1<=1'b0;
else
q1<=d;
end

always @(negedge RESETn or posedge CLKIN)
begin
if (RESETn==1'b0)
q2<=1'b0;
else
q2<=q1;
end

assign d=~q1 & ~q2;

assign CLKOUT=q2;

endmodule


占空比不是50%,只用了单沿触发器,寄存器输出。

至于其他奇数要求50%的或者不要求的占空比的,都可以参照上面两个例子做出。
占空比为50%的一个更好的实现。
module div3(CLKIN,CLKOUT,RESETn);
input CLKIN,RESETn;
output CLKOUT;
//internal counter signals
reg[1:0] count_a;
reg b,c;
//reg CLKOUT;
wire CLKOUT;
always @(negedge RESETn or posedge CLKIN)
begin
if (RESETn==1'b0)
count_a<=2'b00;
else
if (count_a==2'b10)
count_a<=2'b00;
else
count_a<=count_a+1;
end
always @(negedge RESETn or negedge CLKIN)
begin
if (RESETn==1'b0)
b<=1'b0;
else
if (count_a==2'b01)
b<=2'b0;
else
b<=1'b1;
end
always @(negedge RESETn or posedge CLKIN)
begin
if (RESETn==1'b0)
c<=1'b0;
else
if (count_a==2'b10)
c<=1'b1;
else if (count_a==2'b01)
c<=1'b0;
end
assign CLKOUT=b & c;

endmodule





任意奇数分频

//改变FRE_COF即可改变分频系数,这里为7分频

module div7(
clk,
rst_n,
clkout,
clkout1,
clkout2);

input clk,rst_n;
output clkout,clkout1,clkout2;

reg clkout1,clkout2;
reg[2:0] cnt1,cnt2;

parameter FRE_COF=3'b111; //更改分频比,偶数不成立
parameter STOP=FRE_COF-1;
parameter THRESHOLD=FRE_COF-1>>1; //除2操作

assign clkout=clkout1|clkout2; //相或

always @(posedge clk or negedge rst_n)

begin //正沿触发
if(!rst_n)
begin
cnt1<=0;
clkout1<=0;
end
else begin
if(cnt1==STOP)
begin
cnt1<=0;
clkout1<=~clkout1;
end
else begin
cnt1<=cnt1+1;
if(cnt1==THRESHOLD)
clkout1<=~clkout1;
else
clkout1<=clkout1;
end
end
end

always@(negedge clk or negedge rst_n)begin //负沿触发
if(!rst_n)begin
cnt2<=0;
clkout2<=0;
end
else begin
if(cnt2==STOP)
begin
cnt2<=0;
clkout2<=~clkout2;
end
else begin
cnt2<=cnt2+1;
if(cnt2==THRESHOLD)
clkout2<=~clkout2;
else
clkout2<=clkout2;
end
end
end

endmodule

相关主题