爱板网论坛

查看: 287|回复: 0

[技术讨论] STEP BY STEP! 带你快速上手小脚丫FPGA开发板——4.时钟分频

[复制链接]

6

主题

0

好友

142

积分

版主

Rank: 7Rank: 7Rank: 7

  • TA的每日心情
    奋斗
    2017-8-8 12:52
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2017-8-14 10:34:19 |显示全部楼层
    本帖最后由 _张泽_ 于 2017-8-14 10:36 编辑

    时钟分频

    在之前的实验中我们已经熟悉了小脚丫的各种外设,掌握了verilog的组合逻辑设计,接下来我们将学习时序逻辑的设计。

    硬件说明

    时钟信号的处理是FPGA的特色之一,因此分频器也是FPGA设计中使用频率非常高的基本设计之一。一般在FPGA中都有集成的锁相环可以实现各种时钟的分频和倍频设计,但是通过语言设计进行时钟分频是最基本的训练,在对时钟要求不高的设计时也能节省锁相环资源。在本实验中我们将实现任意整数的分频器,分频的时钟保持50%占空比。

    1,偶数分频:偶数倍分频相对简单,比较容易理解。通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么通过时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,以此循环下去。

    2,奇数分频: 如果要实现占空比为50%的奇数倍分频,不能同偶数分频一样计数器记到一半的时候输出时钟翻转,那样得不到占空比50%的时钟。以待分频时钟CLK为例,如果以偶数分频的方法来做奇数分频,在CLK上升沿触发,将得到不是50%占空比的一个时钟信号(正周期比负周期多一个时钟或者少一个时钟);但是如果在CLK下降沿也触发,又得到另外一个不是50%占空比的时钟信号,这两个时钟相位正好相差半个CLK时钟周期。通过这两个时钟信号进行逻辑运算我们可以巧妙的得到50%占空比的时钟。

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

    2.png


    Verilog代码
    1. // ********************************************************************
    2. // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    3. // ********************************************************************
    4. // File name    : divide.v
    5. // Module name  : divide
    6. // Author       : STEP
    7. // Description  : clock divider
    8. // Web          : www.stepfpga.com
    9. //
    10. // --------------------------------------------------------------------
    11. // Code Revision History :
    12. // --------------------------------------------------------------------
    13. // Version: |Mod. Date:   |Changes Made:
    14. // V1.0     |2017/03/02   |Initial ver
    15. // --------------------------------------------------------------------
    16. // Module Function:任意整数时钟分频

    17. module divide (        clk,rst_n,clkout);

    18.         input         clk,rst_n;                       //输入信号,其中clk连接到FPGA的C1脚,频率为12MHz
    19.         output        clkout;                          //输出信号,可以连接到LED观察分频的时钟
    20.         
    21.         //parameter是verilog里常数语句
    22.         parameter        WIDTH        = 3;             //计数器的位数,计数的最大值为 2**WIDTH-1
    23.         parameter        N        = 5;             //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出
    24.         
    25.         reg         [WIDTH-1:0]        cnt_p,cnt_n;     //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器
    26.         reg                        clk_p,clk_n;     //clk_p为上升沿触发时分频时钟,clk_n为下降沿触发时分频时钟
    27.         
    28.         //上升沿触发时计数器的控制
    29.         always @ (posedge clk or negedge rst_n )         //posedge和negedge是verilog表示信号上升沿和下降沿
    30.                                                          //当clk上升沿来临或者rst_n变低的时候执行一次always里的语句
    31.                 begin
    32.                         if(!rst_n)
    33.                                 cnt_p<=0;
    34.                         else if (cnt_p==(N-1))
    35.                                 cnt_p<=0;
    36.                         else cnt_p<=cnt_p+1;             //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器
    37.                 end
    38.         
    39.          //上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%
    40.          always @ (posedge clk or negedge rst_n)
    41.                 begin
    42.                         if(!rst_n)
    43.                                 clk_p<=0;
    44.                         else if (cnt_p<(N>>1))          //N>>1表示右移一位,相当于除以2去掉余数
    45.                                 clk_p<=0;
    46.                         else
    47.                                 clk_p<=1;               //得到的分频时钟正周期比负周期多一个clk时钟
    48.                 end

    49.         //下降沿触发时计数器的控制               
    50.         always @ (negedge clk or negedge rst_n)
    51.                 begin
    52.                         if(!rst_n)
    53.                                 cnt_n<=0;
    54.                         else if (cnt_n==(N-1))
    55.                                 cnt_n<=0;
    56.                         else cnt_n<=cnt_n+1;
    57.                 end
    58.                
    59.         //下降沿触发的分频时钟输出,和clk_p相差半个时钟
    60.         always @ (negedge clk)
    61.                 begin
    62.                         if(!rst_n)
    63.                                 clk_n<=0;
    64.                         else if (cnt_n<(N>>1))  
    65.                                 clk_n<=0;
    66.                         else
    67.                                 clk_n<=1;                //得到的分频时钟正周期比负周期多一个clk时钟
    68.                 end

    69.         assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;      //条件判断表达式
    70.                                                                     //当N=1时,直接输出clk
    71.                                                                     //当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p
    72.                                                                     //当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&clk_n。正周期多所以是相与
    73. endmodule     
    复制代码
    测试文件,进行功能仿真时需要编写testbench测试文件。verilog里的testbench文件和源文件一样也是.v文件,仿真能让我们更直观的观察信号波形,可以先阅读[[lattice_diamond的使用|Diamond的使用]]了解如何使用Diamond中集成的仿真工具。

    1. // ********************************************************************
    2. // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    3. // ********************************************************************
    4. // File name    : divide_tb.v
    5. // Module name  : divide_tb
    6. // Author       : STEP
    7. // Description  : clock divider
    8. // Web          : www.stepfpga.com
    9. //
    10. // --------------------------------------------------------------------
    11. // Code Revision History :
    12. // --------------------------------------------------------------------
    13. // Version: |Mod. Date:   |Changes Made:
    14. // V1.0     |2017/03/02   |Initial ver
    15. // --------------------------------------------------------------------
    16. // Module Function:divide.v时钟分频器的测试文件

    17.           `timescale 1ns/100ps                             //仿真时间单位/时间精度,时间单位要大于或者等于时间精度
    18.          
    19.           module divide_tb();                              //测试文件也是一个module,因为用于仿真所以无需输入输出信号

    20.           reg    clk,rst_n;                                //需要产生的激励信号定义,激励信号需要过程块产生所以定义为reg型变量
    21.           wire   clkout;                                   //需要观察的输出信号定义,定义为wire型变量

    22.           //初始化过程块
    23.           initial
    24.           begin
    25.                  clk = 0;
    26.                  rst_n = 0;
    27.                  #25                                      //#表示延时25个时间单位
    28.                  rst_n = 1;                               //产生了一个初始25ns低电平,然后变高电平的复位信号
    29.           end
    30.         
    31.           always #10 clk = ~clk;                          //每隔10ns翻转一次clk信号,也就是产生一个时钟周期20ns的clk,频率为50MHz  

    32.           //module调用例化格式
    33.           divide  #(.WIDTH(4),.N(11))  u1 (                         //#后面的()中为参数传递,如果不传递参数就是所调用模块中的参数默认值
    34.                                                                    //divide表示所要例化的module名称,u1是我们定义的例化名称,必须以字母开头
    35.                                                 .clk        (clk),     //输入输出信号连接。 .clk表示module本身定义的信号名称;(clk)表示我们在这里定义的激励信号
    36.                                                 .rst_n        (rst_n),   //在testbench里定义的信号名称可以与所要调用module的端口信号名称不同
    37.                                                 .clkout        (clkout)   
    38.                                           );
    39.          endmodule
    复制代码
    引脚分配

    小脚丫上的系统时钟连接到FPGA的C1脚,时钟为12MHz。你可以通过仿真波形观察分频时钟(注意仿真的时间是有限的,所以分频时钟频率需要较高)。如果我们想通过眼睛观察LED的闪烁,那么需要设置参数N和WIDTH得到一个频率较低的时钟(例如N=12000000,WIDTH=24,分频时钟周期为1秒)。

    信号 引脚
    clk C1
    rst_n L14
    clkout N13

    修改程序中的分频系数和计数器位数就能够调整LED闪烁速度(注意计数的最大值一定要保证超过分频系数N)。

    小结
    在本实验学习了如何进行任意整数的分频设计,我们产生各种时钟,通过修改程序还能实验调整输出时钟的频率、相位以及占空比,非常灵活。同时学习了如何编写testbench文件,了解verilog中如何例化module,在后面的学习中将会经常用到。在下个实验我们将进一步了解时序逻辑,如何利用时钟来进一步设计,请关注我们下一篇的文章——流水灯。

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

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

    手机版|爱板网 |网站地图  

    GMT+8, 2017-12-16 03:55 , Processed in 0.153781 second(s), 11 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部