集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: lcytms

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

[复制链接]
 楼主| lcytms 发表于 2016-11-9 20:13:31 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 21:00 编辑

当然了,有经验的同学可能会发现上述代码中,out_clk_1、out_clk_2是从复位完成时开始同步的,长时间运行,可能会导致同步出错,两信号相或之后就会不是所要的结果。
那么,我们可以考虑改进上述代码。
 楼主| lcytms 发表于 2016-11-9 21:01:42 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-10 09:23 编辑

新建改进的任意分频模块divider2.v。
将改进的任意分频模块divider2.v设置为顶层模块。
将原有的显式建模方式改为隐式建模方式,原有生成out_clk_2时采用~clk作为时钟,现在改用negedge clk触发。
同步由原来的复位信号同步,改为cnt计数器同步。
这样避免了原有的长时间运行后同步出错可能性。
改进的任意分频模块divider2.v代码如下。
module divider2 (clk, rst_n, clk_out);

        input clk, rst_n;
       
        output clk_out;

        parameter WIDTH = 3;                        // WIDTH = 3

        wire [25:0] HW, LW;
       
        assign HW = WIDTH>>1;
        assign LW = (WIDTH+1)>>1;
       
        reg out_clk_1, out_clk_2;
                                       
        reg state1, state2;
       
        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;
                                        out_clk_1 <= 1;
                                        state1 <= s0;
                                end
                        else
                                begin
                                        case (state1)
                                        s0        :        begin                                        // HW part
                                                                if (cnt < HW - 1)
                                                                        begin
                                                                                cnt <= cnt + 26'b1;
                                                                                out_clk_1 <= 1;
                                                                                state1 <= s0;
                                                                        end
                                                                else
                                                                        begin
                                                                                cnt <= 0;
                                                                                out_clk_1 <= 1;
                                                                                state1 <= s1;
                                                                        end
                                                        end
                                       
                                        s1        :        begin                                        // LW part
                                                                if (cnt < LW - 1)
                                                                        begin
                                                                                cnt <= cnt + 26'b1;
                                                                                out_clk_1 <= 0;
                                                                                state1 <= s1;
                                                                        end
                                                                else
                                                                        begin
                                                                                cnt <= 0;
                                                                                out_clk_1 <= 0;
                                                                                state1 <= s0;
                                                                        end
                                                        end
                                       
                                        default        :        state1 <= s0;
                                       
                                        endcase
                                end
                end

        always @ (negedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        out_clk_2 <= 1;
                                        state2 <= s0;
                                end
                        else
                                begin
                                        case (state2)
                                        s0        :        begin                                        // HW part
                                                                if (cnt < HW - 1)
                                                                        begin
                                                                                out_clk_2 <= 1;
                                                                                state2 <= s0;
                                                                        end
                                                                else
                                                                        begin
                                                                                out_clk_2 <= 1;
                                                                                state2 <= s1;
                                                                        end
                                                        end
                                       
                                        s1        :        begin                                        // LW part
                                                                if (cnt < LW - 1)
                                                                        begin
                                                                                out_clk_2 <= 0;
                                                                                state2 <= s1;
                                                                        end
                                                                else
                                                                        begin
                                                                                out_clk_2 <= 0;
                                                                                state2 <= s0;
                                                                        end
                                                        end
                                       
                                        default        :        state2 <= s0;
                                       
                                        endcase
                                end
                end

        assign clk_out = (WIDTH & 1'b1) ? (out_clk_1 || out_clk_2) : out_clk_1;
               
endmodule

本帖子中包含更多资源

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

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

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

module divider2_tb;

        reg clk, rst_n;
       
        wire clk_out;

        divider2 #(.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 21:15:53 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-9 21:18 编辑

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

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-9 21:18:08 | 显示全部楼层
修改WIDTH=6,此时分频次数为偶数次。
查看仿真波形,与设计要求相符。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-9 21:20:25 | 显示全部楼层
好了,今天的课程就讲到这里。
通过今天的课程,我们学习了任意分频器的基本原理,并对任意分频器电路进行了建模和仿真检查。
希望大家建立对任意分频器的理解,并熟练运用Verilog语言编写驱动逻辑。
更复杂的知识和技巧我们将逐步通过后面的课程展现给大家。

课程到此结束,谢谢大家的关注!
zxopenljx 发表于 2022-11-25 11:25:21 | 显示全部楼层
FPGA初级课程第十讲 任意分频器
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

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

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

GMT+8, 2024-12-24 03:02 , Processed in 0.060589 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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