[笔记] Frequncy Divider

Abstract

  本文讨论FPGA设计中最常用的分频器的设计,奇数分频,偶数分频,小数分频;

Introduction

  偶数分频:如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。

  clkdiv_even.v

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
//clkdiv_24,n=12
module clkdiv_even(
//  input
input clk_50,
input rst_n,
//  output
output reg clkdiv_even
);
 
parameter   PERIOD = 24,
            PULSEWIDTH = 12,
            SIZE =5;    //24=11000,共5位;
 
reg[SIZE-1:0] cnt;
             
always@(posedge clk_50 or negedge rst_n)
    if(!rst_n)
        cnt <= 0;
    else if(cnt < PERIOD-1)
        cnt <= cnt+1;
    else
        cnt <= 0;
         
always@(posedge clk_50 or negedge rst_n)
    if(!rst_n)
        clkdiv_even <= 0;
    else if(cnt < PULSEWIDTH)    //  由此得到占空比为50%
        clkdiv_even <= 1;
    else
        clkdiv_even <= 0;
     
endmodule

  clkdiv_even.vt

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
`timescale 1 ns/ 1 ns
module clkdiv_even_vlg_tst();
// constants                                          
// general purpose registers
 
reg clk_50;
reg rst_n;
// wires                                              
wire clkdiv_even;
 
// assign statements (if any)                         
clkdiv_even i1 (
// port map - connection between master ports and signals/registers  
    .clk_50(clk_50),
    .clkdiv_even(clkdiv_even),
    .rst_n(rst_n)
);
 
parameter PERIOD = 20;
 
initial                                               
begin                                                 
    clk_50 = 0;
    #1000 rst_n = 0;
    #10000 rst_n = 1;
    forever
    #(PERIOD/2) clk_50 = ~clk_50;
end                                                   
                                              
endmodule

  simulation wave

 

   奇数分频:用两个计数器,一个由输入时钟上升沿触发,一个由输入时钟下降沿触发,最后两个计数器输出相或。

  clkdiv_odd.v

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
53
54
55
//clkdiv13,n=7;
module clkdiv_odd(
//  input
input clk_50,
input rst_n,
//  output
output clkdiv13
);
 
parameter   PERIOD = 13,
            PULSEWIDTH = 6.5,
            SIZE = 4;   //13=1101;
             
reg[4:0] cnt1,cnt2;
reg clkout1,clkout2;
 
always@(posedge clk_50 or negedge rst_n)
    if(!rst_n)
        begin
            clkout1 <= 0;
            cnt1 <= 0;
        end
    else
        begin
            if(cnt1 == PERIOD-1)
                cnt1 <= 0;
            else
                cnt1 <= cnt1+1;
            if(cnt1<(PERIOD-1)/2)
                clkout1 <= 1;
            else
                clkout1 <= 0;
        end
         
always@(negedge clk_50 or negedge rst_n)    //clk_50下降沿触发
    if(!rst_n)
        begin
            clkout2 <= 0;
            cnt2 <= 0;
        end
    else
        begin
            if(cnt2 == PERIOD-1)
                cnt2 <= 0;
            else
                cnt2 <= cnt2+1;
            if(cnt2<(PERIOD-1)/2)
                clkout2 <= 1;
            else
                clkout2 <= 0;
        end
         
assign clkdiv13 = clkout1|clkout2;
 
endmodule

   simulation wave

  奇数分频两种方法总结:(Refer to http://blog.sina.com.cn/s/blog_4b03202d0100at7i.html)

  、对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%奇数n分频时钟。再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟相或运算,得到占空比为50%的奇数n分频时钟。

  、对进行奇数倍n分频时钟,首先进行n/2分频(带小数,即等于(n-1)/2+0.5),然后再进行二分频得到。得到占空比为50%的奇数倍分频。

 

  半整数分频:

  clkdiv_npn.v

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
//  clkdiv_5.5
module clkdiv_npn(
//  input
input clk_50,
input rst_n,
//  output
output reg clkdiv_out
);
reg clk1;
wire clk2; 
integer count;  //Count为N的值
xor xor1(clk2,clk_50,clk1); //clk2:output,
 
always@(posedge clkdiv_out or negedge rst_n)    //clkdiv_out 2分频
    if(!rst_n)
        clk1 <= 1'b0;
    else
        clk1 = ~clk1;
         
always@(posedge clk2 or negedge rst_n)
    if(!rst_n)
        begin
            count <= 0;
            clkdiv_out <= 1'b0;
        end
    else if(count == 5) //计数到5时clkdiv_out输出1
        begin
            count <= 0;
            clkdiv_out <= 1'b1;
        end
    else
        begin
            count <= count+1;
            clkdiv_out <= 1'b0;
        end
         
endmodule

   simulation wave

posted on   LiangXuan  阅读(584)  评论(0编辑  收藏  举报

编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
< 2011年12月 >
27 28 29 30 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
1 2 3 4 5 6 7

导航

统计

点击右上角即可分享
微信分享提示