集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 8647|回复: 16

FPGA初级课程第十讲 任意分频器

[复制链接]
lcytms 发表于 2016-11-9 19:49:44 | 显示全部楼层 |阅读模式
本帖最后由 lcytms 于 2016-11-9 21:00 编辑

FPGA初级课程
第十讲 任意分频器

Hi,大家好!我是至芯科技的李老师。
今天讲课的题目是:任意分频器。
本节课我先简要地介绍一下任意分频器的物理原理,然后实际演示一下任意分频器驱动逻辑电路的建模与仿真,并通过仿真查看效果。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 19:51:59 | 显示全部楼层
在第九讲 分频器中大家学习了运用计数器实现分频器设计。
我们来回顾一下。
打开第九讲的工程文件。
第九讲先后介绍了两种分频器设计。
第一种是偶数次分频,占空比为50%。
第二种是通用分频,占空比可调。分频次数不局限于偶数次。

貌似第二种分频可以实现任意次分频,但是它有一个局限性,就是奇数次分频时,不能实现50%占空比。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 19:52:36 | 显示全部楼层
而很多情况下,需要不仅能做到奇数次分频,而且要求为50%占空比,这更接近于晶振的方波信号。

当然了,可以通过锁相环将系统时钟信号先进行二倍频,再做偶数次分频。
我们这里介绍的是不使用锁相环,还是使用计数器的方式,来实现这种奇数次分频,这里我们称之为任意分频器。
 楼主| lcytms 发表于 2016-11-9 19:58:23 | 显示全部楼层
我们打开至芯科技编写的《27.炼狱传奇-任意分频之战.pdf》文档。


分频在fpga的设计中一直都担任着很重要的角色,而说到分频,我相信很多人都已经想到了利用计算器来计算达到想要的时钟频率,但问题是仅仅利用计数器来分频,只可以实现偶数分频,而如果我需要三分频,五分频,七分频等等奇数类分频,那究竟怎么办呢?
在这里,让我介绍一个可以实现任意整数分频的方法,这个办法也是同样利用了计数器来计算,当是跟偶数分频不一样的地方是任意整数分频利用了两个计数器来实现。

下面我们来看看三分频实现的时序图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 19:58:54 | 显示全部楼层
三分频设计中,由out_clk_1和out_clk_2相或得到最终输出。
out_clk_1可以理解成HW=1、LW=2的通用分频输出。
out_clk_2可以理解成反时钟条件下out_clk_1的输出。
 楼主| lcytms 发表于 2016-11-9 19:59:30 | 显示全部楼层
既然原理已经明白,编写代码如下。
先打开第九讲中编写的通用分频模块div_freq.v。
复习div_freq.v代码部分。
module div_freq (clk, rst_n, clk_out);

        input clk, rst_n;
       
        output reg clk_out;
       
        parameter        HW = 50,
                                        LW = 50;                // HW + LW = 100 times

        reg state;

        localparam        s0 = 1'b0,
                                        s1 = 1'b1;
       
        reg [25:0] cnt;

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        cnt <= 0;
                                        clk_out <= 1;
                                        state <= s0;
                                end
                        else
                                begin
                                        case (state)
                                        s0        :        begin                                                                // HW part
                                                                if (cnt < HW - 1)
                                                                        begin
                                                                                cnt <= cnt + 26'b1;
                                                                                clk_out <= 1;
                                                                                state <= s0;
                                                                        end
                                                                else
                                                                        begin
                                                                                cnt <= 0;
                                                                                clk_out <= 1;
                                                                                state <= s1;
                                                                        end
                                                        end
                                       
                                        s1        :        begin                                                                // LW part
                                                                if (cnt < LW - 1)
                                                                        begin
                                                                                cnt <= cnt + 26'b1;
                                                                                clk_out <= 0;
                                                                                state <= s1;
                                                                        end
                                                                else
                                                                        begin
                                                                                cnt <= 0;
                                                                                clk_out <= 0;
                                                                                state <= s0;
                                                                        end
                                                        end
                                       
                                        default        :        state <= s0;
                                       
                                        endcase
                                end
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 20:01:12 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 20:03 编辑

新建任意分频模块divider.v
将任意分频模块divider.v设置为顶层模块。
module divider (clk, rst_n, clk_out);

        input clk, rst_n;
       
        output clk_out;

        parameter        WIDTH = 3;                // WIDTH = 3
       
        wire out_clk_1, out_clk_2;
       
        div_freq #(.HW(WIDTH>>1), .LW((WIDTH+1)>>1))
                d1 (.clk(clk), .rst_n(rst_n), .clk_out(out_clk_1));
       
        div_freq #(.HW(WIDTH>>1), .LW((WIDTH+1)>>1))
                d2 (.clk(~clk), .rst_n(rst_n), .clk_out(out_clk_2));
               
        assign clk_out = (WIDTH & 1'b1) ? (out_clk_1 || out_clk_2) : out_clk_1;

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 20:03:59 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 20:05 编辑

新建Testbench。编写divider_tb.v模块代码。
`timescale 1ns/1ps

module divider_tb;

        reg clk, rst_n;
       
        wire clk_out;

        divider #(.WIDTH(5)) dut (.clk(clk), .rst_n(rst_n), .clk_out(clk_out));

        initial
                begin
                        clk = 1;
                        rst_n = 0;
                        #200.1
                        rst_n = 1;
                       
                        #2000 $stop;
                end
               
        always #10 clk = ~clk;

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 20:07:18 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 21:19 编辑

设置好仿真。
查看仿真波形。
WIDTH=5,此时分频次数为奇数次,仿真波形与设计要求相符。
通过修改参数WIDTH可以实现分频次数的调整。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-9 20:12:49 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 21:19 编辑

修改WIDTH=6,此时分频次数为偶数次。
查看仿真波形,与设计要求相符。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-12-24 03:26 , Processed in 0.071159 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表