集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 7135|回复: 11

FPGA初级课程第九讲 分频器

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

FPGA初级课程
第九讲 分频器

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


本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-9 19:11:03 | 显示全部楼层
分频器这个名词或许大家都很熟悉了,运用计数器我们就能轻松地实现分频器设计。

我们打开《23至芯科技奋斗的小孩之altera 系列 第二十三篇 分频器.pdf》文件。


对于每一个的小实验,我们都可以把它看作是一个小项目,逐步的去分析,设计,调试,最后完成功能。
下面我们就开始我们的“小项目”。
项目名称:分频器
具体要求:将本地晶振分频成一定的频率。
架构图如下:

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-9 19:12:10 | 显示全部楼层
系统设计:
1. 工程的名称:div_freq。


我们首先来写一个计数器,实现10分频,将至芯科技ZX_1开发板上的50MHz系统时钟变成5MHz时钟输出。

很简单,我就让每隔5个时钟取反一次就行了。这种分频实现起来非常简单,它的特点是占空比为50%,而且是偶数次分频。
 楼主| lcytms 发表于 2016-11-9 19:13:02 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 19:15 编辑

新建工程文件夹div_freq。
新建分频模块div_freq2n.v,后面加上2n表示偶数次分频,以区别于我们后面要实现的通用分频模块div_freq.v。通用分频模块div_freq.v不局限于偶数次分频,而且占空比可调。
将分频模块div_freq2n.v设置为顶层模块。
module div_freq2n (clk, rst_n, clk_out);

        input clk, rst_n;
       
        output reg clk_out;
       
        parameter CNT_NUM = 5;  // half of 10
       
        reg [25:0] cnt;

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        cnt <= 0;
                                        clk_out <= 1;
                                end
                        else
                                begin
                                        if (cnt < CNT_NUM - 1)
                                                begin
                                                        cnt <= cnt + 26'b1;
                                                end
                                        else
                                                begin
                                                        cnt <= 0;
                                                        clk_out <= ~clk_out;
                                                end
                                end
                end

endmodule

本帖子中包含更多资源

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

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

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

module div_freq2n_tb;

        reg clk, rst_n;
       
        wire clk_out;

        div_freq2n #(.CNT_NUM(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 19:19:26 | 显示全部楼层
设置好仿真。
查看仿真波形。与设计要求相符。
通过修改参数CNT_NUM可以实现分频次数的调整。

本帖子中包含更多资源

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

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

下面我们要实现的通用分频模块div_freq.v不局限于偶数次分频,而且占空比可调。

我们回到《23至芯科技奋斗的小孩之altera 系列 第二十三篇 分频器.pdf》文件。


2. 状态转移图如下图所示。
HW:高电平所占的周期数
LW:低电平所占的周期数

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-9 19:23:28 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 19:29 编辑

新建通用分频模块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 19:30:41 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 19:32 编辑

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

module div_freq_tb;

        reg clk, rst_n;
       
        wire clk_out;

        div_freq #(.HW(3), .LW(2)) 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 19:34:27 | 显示全部楼层
设置好仿真。
查看仿真波形。与设计要求相符。
通过修改参数HW、LW可以实现分频次数的调整。
高电平为3个周期,低电平为2个周期。本地晶振是50MHz,我们分频出来的时钟为10MHz,并且占空比为60%。

如果本地晶振或者输出的时钟和笔者的设计不同,请自行更改设计,以保证设计的正确性。

本帖子中包含更多资源

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

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

本版积分规则

关闭

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

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

GMT+8, 2024-11-23 11:50 , Processed in 0.067663 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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