IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于verilog的时钟管理电路设计(奇数/偶数分频、门控时钟等) -> 正文阅读

[嵌入式]基于verilog的时钟管理电路设计(奇数/偶数分频、门控时钟等)


前言

??在许多设计中,常常伴随着对时钟的各种需求,如需要进行偶数倍分频,奇数倍分频;对于时钟的处理也很重要,如何防止时钟截断,时钟毛刺,减少累计时钟偏移;在低功耗设计中,如何降低时钟网络和其中寄存器的功耗;
??进而衍生出各种技术,如行波计数器、计数分频器、门控时钟、锁存器门控时钟等待。
??在数字设计中,产生时钟信号的方法主要有两种,一种是通过PLL锁相环对时钟源进行分频或倍频,另一种是在设计的模块中用硬件描述语言描述分频逻辑。
??在本文中将对这些技术进行简要的介绍,并给出若干设计实例。


一、开源资料下载链接

??https://hihii11.github.io/verilog_clockmanager.html

二、行波计数器

2.1 行波计数器介绍

??图2.1给出了一个三级行波计数器,每个D触发器的反相输出端~Q与输入端D相连。正向输出端作为下一级触发器的时钟信号。
在这里插入图片描述????????????????图2.1 三级行波计数器

这样设计的行波计数器相对于其他分频器来说,其具有以下特点。
1.每级D触发器可对源时钟进行2n分频。
??如上图2.1中,
????clk1 = clk_source / 2;
???? clk2 = clk_source / 4;
???? clk3 = clk_source / 8;
?? 其各级时钟波形如图2.2所示。
在这里插入图片描述
????????????????图2.2 各级时钟波形
2.资源消耗少
??由于行波计数器仅通过若干个触发器级联产生时钟,所以其没有附加的组合逻辑,故消耗资源较少。
3.功耗低
??由于行波计数器消耗资源少,故在CLK发生反转时,所带动的处于活跃的组合逻辑部分也较少,因此由这部分逻辑产生的峰值功耗大大降低。
??在低功耗设计中常用行波计数器。

行波计数器也存在以下缺点:
1.行波计数器有较严重的级联效应
??由于行波计数器的级联结构,其每一级时钟都会产生一定的滞后。
如:
??clk1 相较于 clk_source 会产生由U1A所引入的触发器延时及布线延时(tU1A)。
??clk2 相较于 clk1 会产生由U2A所引入的触发器延时(tU2A)。
??clk3 同理。
??由此一来,延迟会不断积累,如图2.3所示。
在这里插入图片描述
????????????????图2.3 行波计数器的级联效应
??一方面这种延迟可能会引入毛刺,另一方面在同步电路设计中,有可能会违背数据的建立保持时间。
??因为行波计数器产生的时钟本质上是异步的,依赖其产生的时钟的模块,在进行数据交互时,属于跨时钟域。
2.会对STA工具和综合工具带来麻烦
??行波计数器在各阶段创建时钟所引入的级联效应导致的问题,会增加STA工具和综合工具的工作量。

2.2 设计实例

1.模块代码

module travel_wave_counter#(
       parameter integer LEVELs = 3
)
(
       input  wire                  CLK_IN,
       input  wire                    nRST,
       output wire [LEVELs-1:0]    CLK_OUT
    );
    
    genvar i;
    generate
        for(i = 0;i < LEVELs;i = i+1)
        begin
            if(i == 0)
            begin
                travel_wave_level travel_wave_level_inist0(
                   .CLK_IN(CLK_IN),.nRST(nRST),.DOUT(CLK_OUT[i]));
            end
            else
            begin
                travel_wave_level travel_wave_level_inist0(
                   .CLK_IN(CLK_OUT[i-1]),.nRST(nRST),.DOUT(CLK_OUT[i]));
            end
        end
    endgenerate    
endmodule

module travel_wave_level(
       input  wire  CLK_IN,
       input  wire    nRST,
       output wire    DOUT
);
    reg dout;
    assign DOUT = dout;
    always@(posedge CLK_IN,negedge nRST)
    begin
        if(~nRST)
        begin
            dout <= 1'b0;
        end
        else
        begin
            dout <= ~dout;
        end
    end
endmodule

2.综合电路框图
在这里插入图片描述

2.3 总结

??行波计数器产生时钟属于异步,同步应当避免。
??在低功耗设计等情况下,可以尝试使用行波计数器,但需要严格控制。


三、计数分频器

3.1 计数分频器介绍

??针对上述行波计数器的缺点,在同步电路设计中,可以采用计数器或状态机来产生分频时钟。
??利用计数器产生分频器需要注意:
??1.应由寄存器直接产生时钟信号,永远不要对计数器或状态机输出进行译码。
??原因是状态改变时信号会产生竞争冒险,从而导致逻辑错误,产生的时钟信号出现毛刺,会导致电路逻辑错误。
??2.对主频进行分频时,应使用同步计数器或状态机。

3.2 设计实例

??典型的计数分频器设计:(注意本小节计数器均为偶数分频)
1.使用两个同步always逻辑块

module div_counter#(
        parameter integer DIV_NUM = 2
)(
        input  wire  CLK_IN,
        input  wire    nRST,
        output wire CLK_OUT
    );
    
    reg [15:0] clk_cnt;
    reg clk_out;
    assign CLK_OUT = clk_out;
    always@(posedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_cnt <= 16'd0;
        end
        else
        begin
            if(clk_cnt != DIV_NUM - 1)
                clk_cnt <= clk_cnt + 16'd1;
            else
                clk_cnt <= 16'd0;
        end
    end
    
    always@(posedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_out <= 1'b0;
        end
        else
        begin
            if(clk_cnt < DIV_NUM/2)
                clk_out <= 1'b1;
            else
                clk_out <= 1'b0;
        end
    end
endmodule

综合后电路:
在这里插入图片描述2.一个always逻辑块,一个组合逻辑

module div_counter#(
        parameter integer DIV_NUM = 2
)(
        input  wire  CLK_IN,
        input  wire    nRST,
        output wire CLK_OUT
    );
    
    reg [15:0] clk_cnt;
    reg clk_out;
    assign CLK_OUT = (clk_cnt < DIV_NUM/2)?1'b1:1'b0;
    always@(posedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_cnt <= 16'd0;
        end
        else
        begin
            if(clk_cnt != DIV_NUM - 1)
                clk_cnt <= clk_cnt + 16'd1;
            else
                clk_cnt <= 16'd0;
        end
    end
endmodule

综合后电路:
在这里插入图片描述??两种设计方式的区别在于,第一种设计时钟信号是通过时序逻辑驱动产生的,而第二种是直接通过组合逻辑产生。
??第二种设计对于信号毛刺的抗干扰性较差,第一种可以很好地滤除毛刺。

3.3 总结

??对于行波计数器的缺点,可采取计数器的方法进行时钟分频。
??完全同步的设计,时钟偏移现象相对行波计数器较轻。
??消耗的资源较行波计数器较多,且功耗较大。


四、门控时钟设计

4.1 门控时钟介绍

??门控时钟是减少功耗的有力手段,在时钟被门控关闭后,该时钟网络和其中的寄存器都会停止翻转,因此功耗会显著减低。
??但门控时钟也会带来一些问题:
??1.门控时钟属于非同步设计,会增加设计时间和验证工作量。
??2.门控时钟会在时钟链路上增加额外的时钟偏移。
??3.门控时钟对毛刺敏感,可能导致设计失败。

传统的门控时钟设计如图3.1所示:
在这里插入图片描述
????????????????图4.1 典型门控时钟电路
??对于时钟源clk_source经过一个额外的与门U2A,当clk_en为高时,clk_source能过通过到达U1A触发器,当clk_en为低时clk_source无法到达触发器。
??当clk_en为低时,触发器及其时钟网络中的所有组合逻辑停止翻转,out端保持不变。
??由于clk_source经过了U2A与门,所有会产生一定的时钟偏移。

4.2伪门控时钟

??上述问题可以通过同步设计来解决。
??使用MUX的同步设计方案:
在这里插入图片描述
????????????????图4.2 伪门控时钟电路
??可以通过clk_en来控制触发器输入端口D的数据,若此时选择的数据为out端口,则触发器输出将保持不变。
??但由于并未切断时钟树,所以触发器内部包括组合逻辑都处于活跃状态,功耗并未得到实质性降低。

4.3 基于锁存器的门控时钟

传统的门控时钟仅有一级与门进行门控控制,其会产生时钟截断情况:
在这里插入图片描述
????????????????图4.3 传统门控时钟的时钟截断现象
??在6时刻,因为clk_en由高变低,所以其输出clk_out被截断,同理在8时刻,由于clk_en变高,clk_out同样被截断。
??这样的截断会产生以下一些问题:
??1.时钟占空比不平衡。
??2.产生的脉冲尖峰(干扰)会引起保持建立时间的问题。

??故在设计中可采用锁存器来避免时钟截断。

4.3 基于锁存器的门控时钟设计实例

基于锁存器门控时钟的verilog描述:

module gata_clock(
        input  wire     CLK_IN,
        input  wire    CLK_ENI,
        output wire    CLK_OUT
    );
    reg clk_eno;
    
    assign CLK_OUT = clk_eno & CLK_IN;
    
    always@(~CLK_IN)
    begin
        clk_eno <= CLK_ENI;
    end    
endmodule

时钟截断仿真:
在这里插入图片描述
由于在FPGA设计中,板上资源有时没有锁存器;
此时可以将锁存器换为触发器;

module gata_clock(
        input  wire     CLK_IN,
        input  wire    CLK_ENI,
        output wire    CLK_OUT
    );
    (*KEEP="true"*)reg clk_eno;
    
    assign CLK_OUT = clk_eno & CLK_IN;
    
    always@(posedge CLK_IN)
    begin
        clk_eno <= CLK_ENI;
    end    
endmodule

综合后电路:
在这里插入图片描述

4.4 总结

??合理使用门控时钟可以降低模块功耗。
??在FPGA设计中,可以使用带触发器的门控时钟来消除时钟截断现象。


五、奇数分频器

5.1 奇数分频器简介

??对于偶数倍的分频,可以使用行波计数器或计数器等方式实现;
??但对于占空比要求为百分之50的奇数分频,上述几种设计就难以实现了;
??对于奇数倍的分频,可以采取以下设计方法:
??1.创建一个模N计数器,计数值为0-(N-1)
??2.创建两个T触发器,用于产生时钟产生逻辑LOGIC0,LOGIC1
?? ??需要注意产生LOGIC0的T触发器需在输入时钟的上升沿采样
???? 产生LOGIC1的T触发器在输入时钟的下降沿采样
??3.创建两个T触发器使能信号TFF_EN0,TFF_EN1
????TFF_EN0在第1步中,计数值为1的时候置位
????TFF_EN1在第1步中,计数值为(N+1)/2时置位
??4.创建产生时钟逻辑,CLK_OUT = LOGIC0 ^ LOGIC1

5.2 设计实例

奇数分频器设计代码:

module odd_clk_div#(
        parameter integer DIV_NUM = 3
)(
       input  wire  CLK_IN,
       input  wire    nRST,
       output wire  TFF_EN0,
       output wire  TFF_EN1,
       output wire   LOGIC0,
       output wire   LOGIC1,
       output wire   [15:0] CLK_CNT,
       output wire CLK_OUT
    );
    
    reg [15:0] clk_cnt;//clock counter
    wire tff_en0,tff_en1;
    assign CLK_CNT = clk_cnt;
    assign tff_en0 = (clk_cnt == 'd0)?1'b1:1'b0;
    assign tff_en1 = (clk_cnt == (DIV_NUM+1)/2)?1'b1:1'b0;
    assign TFF_EN0 = tff_en0;
    assign TFF_EN1 = tff_en1;
    //counter
    always@(posedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_cnt <= 16'd0;
        end
        else
        begin
            if(clk_cnt != DIV_NUM - 1)
            begin
                clk_cnt <= clk_cnt + 16'd1;
            end 
            else clk_cnt <= 16'd0;
        end
    end
    
    //clock bulid logic
    reg clk_div0_lgic;//sample tff_en0 at clk posegde
    reg clk_div1_lgic;//sample tff_en1 at clk negedge
    assign CLK_OUT = clk_div0_lgic ^ clk_div1_lgic;
    assign LOGIC0 = clk_div0_lgic;
    assign LOGIC1 = clk_div1_lgic;
    //TFF 0
    always@(posedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_div0_lgic <= 1'b0;
        end
        else
        begin
            if(tff_en0)
                clk_div0_lgic <= ~clk_div0_lgic;
            else
                clk_div0_lgic <= clk_div0_lgic;
        end
    end
    //TFF 1
    always@(negedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_div1_lgic <= 1'b0;
        end
        else
        begin
             if(tff_en1)
                clk_div1_lgic <= ~clk_div1_lgic;
            else
                clk_div1_lgic <= clk_div1_lgic;
        end
    end

当DIV_NUM = 7时,仿真波形如下:
在这里插入图片描述上述设计综合:
在这里插入图片描述

5.3 另一种设计思路

??本质上来说,这种奇数倍分频产生了两个2N倍的偶数分频信号,只不过利用两个分频信号的相位差进行逻辑异或得到N分频的信号;
??因此也可以采用以下的设计思路:
??1.首先创建两个模2N的计数器
????第一个计数器在clk上升沿采样,初值为0
????第二个计数器在clk下降沿采样,初值为(DIV_NUM+1)/2 - 1
??2.根据两个计数器的值产生两个2N倍偶数分频信号
??3.将产生的偶数分频信号进行异或产生时钟

module odd_clk_div#(
        parameter integer DIV_NUM = 3
)(
       input  wire  CLK_IN,
       input  wire    nRST,
       output wire   LOGIC0,
       output wire   LOGIC1,
       output wire   [15:0] CLK_CNT0,
       output wire   [15:0] CLK_CNT1,
       output wire CLK_OUT
    );
    
    reg [15:0] clk_cnt0;//clock counter
    reg [15:0] clk_cnt1;//clock counter
    wire logic0,logic1;
    assign LOGIC0 = logic0;    
    assign LOGIC1 = logic1;    
    assign CLK_CNT0 = clk_cnt0;
    assign CLK_CNT1 = clk_cnt1;
    
    
    
    assign CLK_OUT = logic0 ^ logic1;
    assign logic0 = (clk_cnt0 < DIV_NUM ) ? 1'b1:1'b0;
    assign logic1 = (clk_cnt1 < DIV_NUM ) ? 1'b1:1'b0;
    //counter
    always@(posedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_cnt0 <= 16'd0;
        end
        else
        begin
            if(clk_cnt0 != 2*DIV_NUM - 1)
            begin
                clk_cnt0 <= clk_cnt0 + 16'd1;
            end 
            else clk_cnt0 <= 16'd0;
        end
    end
    always@(negedge CLK_IN)
    begin
        if(~nRST)
        begin
            clk_cnt1 <= (DIV_NUM+1)/2 - 1;
        end
        else
        begin
            if(clk_cnt1 != 2*DIV_NUM - 1)
            begin
                clk_cnt1 <= clk_cnt1 + 16'd1;
            end 
            else clk_cnt1 <= 16'd0;
        end
    end
   
endmodule

仿真:
在这里插入图片描述
设计综合:
在这里插入图片描述

5.4 总结

??奇数分频可通过产生两个相位不同的2N倍分频,异或产生


文献参考

1.《硬件架构的艺术-数字电路的设计方法与技术》
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:07:47  更:2022-07-04 23:09:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 8:01:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计