时钟分频器

参考书本:《硬件架构的艺术》

补充:

同步整数分频可以用moore状态机很容易实现。但是这样简单的逻辑无法产生50%占空比的输出。

七分频Moore状态机 

1. 偶数分频

2. 奇数整数分频(50%占空比)

概念上:以期望输出频率的一半生成两个正交相位时钟(两个时钟之间有90°相位差),然后通过两个波形异或得到输出频率。由于存在固定90°相位差,每次异或输入只有一端会变化,这样有效消除了输出波形上的毛刺。

实现步骤:

(1)计数器:clk上升沿,0~(N-1),N是奇数

(2)使用两个开关触发器(TFF),产生使能信号

tff1_en:计数为0时使能;tff2_en:计数为(N+1)/2时使能。

(3)div1: tff1 clk上升沿 信号翻转;div2:tff2 clk下降沿 信号翻转

(4)clkout:div1和div2异或

用T触发器进行50%占空比3分频 

也可以使用D触发器实现。

比如实现5分频(50%占空比)

(1)计数器cnt:clk上升沿触发,计数0~(N-1),N是奇数;

(2)div1信号产生:clk上升沿触发, cnt计数到0,信号翻转div1<=~div1;

         div2信号产生:clk下降沿触发,cnt计数到(N+1)/2,信号翻转div2<=div2;

(3)clkout信号:div1信号与div2信号进行异或。

设计代码:

//5分频
`timescale 1ns/1ns

module div_5 (
    input clk,
    input rst_n,
    output clk_div5 
);

reg [2:0] cnt;
reg div1;
reg div2;

//计数5:0~4     0~(N-1)
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt<=0;
    end else if(cnt==3'd4) begin
        cnt<=0;
    end else begin
        cnt<=cnt+1'b1;
    end
end

//div1:时钟上升沿,计数到0翻转
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        div1<=0;
    end else if (cnt==0) begin
        div1<=~div1;
    end else begin
        div1<=div1;
    end
end

//div2:时钟下降沿,计数到3翻转 (N+1)/2
always @(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        div2<=0;
    end else if(cnt==3'd3) begin
        div2<=~div2;
    end else begin
        div2<=div2;
    end
end

//div1和div2异或得到输出时钟
assign clk_div5=div1^div2;

endmodule

测试代码:

//5分频测试

`timescale 1ns/1ns

module div_5_tb ();

reg clk;
reg rst_n;
wire clk_div5;

initial begin
    clk=0;
    rst_n=0;
    #20;
    rst_n=1;
end

always #10 clk=~clk;

div_5 u1 (.clk(clk),.rst_n(rst_n),.clk_div5(clk_div5));


endmodule

仿真波形:

RTL分析结构图:

注意:后面两个D触发器的时钟应该一个是clk,一个是clk经过反相器之后,一个是上升沿触发,一个是下降沿触发。发现它是直接电路实现上,右下角触发器的C端前面有个小圆圈代表非,也就是下降沿触发。

综合之后的结构图:

3.非整数分频(1.5倍分频,4.5倍分频类似,非50%占空比,占空比还是有一定限制的)

设计思想:

4.5分频(非50%占空比),也就是每9个输入时钟包含2个对称脉冲,这种通过移位的方法可以保证输出波形不包含毛刺

设计步骤:

步骤一:使用复位值为0_0000_0001的9位移位寄存器,每个clk上升沿循环左移一位

步骤二:产生第1个脉冲,需要在半周期时移动第1位,再与第1位与第2位进行或操作(如何实现半周期,clk下降沿触发,前提输入时钟clk是50%占空比)

步骤三:产生第2个脉冲,需要第5位和第6位必须在半周期时移动,并与原始第6位进行或操作  

注意事项:

(1)shift_cnt<={shift_cnt[7:0],shift_cnt[8]};  //实现循环移位

(2)为什么产生第一个脉冲,还要跟半周期移动第1位得到的ps_count0相或呢,shift_cnt[0]与shift_cnt[1]相或不就行了嘛?还有产生第二个脉冲的时候,为什么还要与原始第6位相或呢?

我的理解:实际电路,考虑时延等,为了补齐中间的时间空白,保证输出小数倍频时钟周期的完整性和正确性。

(3)用的[8:0]代表9位,后面的位数别搞混了

(4)其实可以修改占空比,不一定非要两个clk时长的高电平。9位移位寄存器是确定总的时长;和至少一个半周期移动一起确定*.5倍频,参与相或是几位确定了占空比。比如本设计占空比是4/9,也可以改为2/9。改法:

assign clk_div4_5=shift_cnt[0]|ps_count4;

(5)为什么用这种方法?用移位的方法可以保证输出的波形不含毛刺。是对比另一种方法(不提倡,在本小节后面会提到)

4.5倍分频设计代码:

//4.5分频(非50%占空比)
//每9个输入时钟包含2个对称脉冲,这种通过移位的方法可以保证输出波形不包含毛刺
//!!!注意:[8:0] 位数别弄混了
`timescale 1ns/1ns

module div4_5 (
    input clk,
    input rst_n,
    output clk_div4_5   
);

reg [8:0] shift_cnt;
reg ps_count0;
reg ps_count4;
reg ps_count5;

//使用复位值为0_0000_0001的9位移位寄存器,每个clk上升沿循环左移一位
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        shift_cnt<=9'b0_0000_0001;
    end else begin
        shift_cnt<={shift_cnt[7:0],shift_cnt[8]};  //循环移位
    end
end

//产生第1个脉冲,需要在半周期时移动第1位,再与第1位与第2位进行或操作
//产生第2个脉冲,需要第5位和第6位必须在半周期时移动,并与原始第6位进行或操作    ??为什么还要原始第6位?我的理解:实际电路,考虑时延等,为了补齐中间的时间空白,保证周期性完整,正确
always @(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        ps_count0<=1'b0;
        ps_count4<=1'b0;
        ps_count5<=1'b0;
    end else begin
        ps_count0<=shift_cnt[0];
        ps_count4<=shift_cnt[4];
        ps_count5<=shift_cnt[5];
    end
end

assign clk_div4_5=(shift_cnt[0]|shift_cnt[1]|ps_count0)|(shift_cnt[5]|ps_count4|ps_count5);

endmodule

4.5倍分频测试代码:

//检测4.5倍分频
`timescale  1ns/1ns
module div4_5_tb();

reg clk;
reg rst_n;
wire clk_div4_5;



initial begin
    clk=0;
    rst_n=0;
    #10;
    rst_n=1;
end

always #10 clk=~clk;

div4_5 u2(
 .clk (clk),
  .rst_n(rst_n),
  . clk_div4_5 (clk_div4_5 ) 
);

endmodule

4.5倍分频仿真波形 (占空比4/9)

1.5倍分频代码设计思路:

每3个输入时钟包含2个对称脉冲,使用复位值为001的3位移位寄存器,每个clk上升沿循环左移一位,产生第1个脉冲,shift_cnt[0]即可,产生第2个脉冲,需要第2位在半周期时移动

设计代码:

//1.5分频(非50%占空比)
//每3个输入时钟包含2个对称脉冲,这种通过移位的方法可以保证输出波形不包含毛刺
`timescale 1ns/1ns

module div4_5 (
    input clk,
    input rst_n,
    output clk_div1_5   
);

reg [2:0] shift_cnt;
reg ps_count1;

//使用复位值为001的3位移位寄存器,每个clk上升沿循环左移一位
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        shift_cnt<=3'b001;
    end else begin
        shift_cnt<={shift_cnt[1:0],shift_cnt[2]};  //循环移位
    end
end

//产生第1个脉冲,shift_cnt[0]即可
//产生第2个脉冲,需要第2位在半周期时移动
always @(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        ps_count1<=1'b0;
    end else begin
        ps_count1<=shift_cnt[1];
    end
end

assign clk_div1_5=shift_cnt[0]|ps_count1;

endmodule

1.5倍数分频(占空比2/3)

另一种方法,不推荐,产生毛刺

4.任意小数分频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值