首页 > 编程知识 正文

Verilog分频器,fpga分频器程序

时间:2023-05-05 13:21:14 阅读:153116 作者:2118

1、什么是分频器

在数字系统的设计中,经常需要使用多个时钟。 用于产生时钟信号通常可以有两种方法,一种是可以使用锁相环(PLL )来产生倍频、分频信号; 另一种是使用硬件描述语言构建分频电路。

分频器的设计通常分为奇数分频器、偶数分频器和小数分频器三种。 接下来,将描述偶数分频器和奇数分频器的设计仿真。

2、偶数分频器2.1、设计方法

如图所示,分别绘制了基准时钟、2分频时钟、4分频时钟、8分频时钟。

通过观察波形,可以很容易地得到。

2分频只需重复使用基准时钟在第1时钟输出高电平(或低电平),在第2时钟输出逆电平即可。

同样,4分频设计:利用基准时钟在第1、2时钟输出高电平(或低电平),在第3、4时钟输出相反电平,如此重复即可。

类似地,8分频设计:利用基准时钟向第1、2、3、4个时钟输出高电平(或低电平),向第5、6、7、8个时钟输出相反电平,如此反复即可。

由此可以推导出偶数分频设计的一般方法:假设为N分频,只需设计一个计数器从0计数到 N/2-1(一共N/2个基准时钟),然后将输出分频时钟翻转、计数器清零,如此循环就可以得到 N分频。

2.2、8分频电路设计实例接下来设计8分频电路并进行仿真验证。

8分频电路框图如下。

输入:

sys_clk :基准时钟信号(在此为50MHz,设定为周期20ns ) ) ) ) ) ) )。

sys_rst_n :低电平有效复位信号

输出:

clk_8:基准时钟信号的8分频信号(50/8=6.25MHz,周期100ns ) )。

根据前述方法,设计过程如下。

设计并计数计数器(从0计数到3(8/2-1),清零后重复)计数器每次计数到最大值时,反转8分频信号的理论上8分频模块的各信号波形应如下图所示。

2.2、Verilog可根据上图将Verilog代码编写如下。

//8分频电路设计module divider_8 //模块名称(inputsys_clk,//时钟(设定为50MHz ) inputsys_rst_n,//复位信号) n为有效低电平reg [1:0]cnt; //reg定义//计数模块//0至3共4个时钟周期always @ (posedge sys _ clkornegedgesys _ rst _ n ) beginif (! sys_rst_n(CNT=2'D0; //因为从复位零elseif(CNT==2'd3 )//0开始计数,所以需要-1cnt=2'd0; //fkdss清除elsecnt=cnt 2'd1; //8分频时钟输出模块//满足计数条件而不进行完全计数,反转8分频时钟//8分频时钟每4个周期反转,因此8分频时钟周期为8个时钟周期always @ (posedge sys _ com //复位清零elseif(CNT==2'd3 )//4时钟周期clk_8=~clk_8; //fkdss时,输出反转else clk_8=clk_8; //不记很多保持原样endendmodule 2.3、Testbench Testbench文件的创建比较简单,不需要定义或者做其他事情,只需实例化我们刚设计的8分频模块

` timescale 1ns/1ns//小时:单位1ns,精度1nsmodule tb_divider_8(; //仿真模块//输入reg定义regsys_clk; reg sys_rst_n; //输出wire定义wire clk_8; //初始化条件initial beginsys_clk=1'b0; //初始时钟是0sys_rst_n=1'b0; //初始复位是在0#10//10小时单位后sys_rst_n=1'b1; //上拉复位(此时复位无效) end//always表示重复进行,#10表示每10小时单位//10小时单位使时钟反转,即时钟周期为20小时单位(20ns ) end//always //被测试模块divider _8divider _8_ inst (实例化. sy

s_clk (sys_clk ), .sys_rst_n (sys_rst_n ), .clk_8 (clk_8 ) );endmodule 2.4、仿真结果

使用ModelSim执行仿真,仿真出来的波形如所示:

从波形图可以看到

10ns后停止复位计数器cnt一直在从0计数到3每当cnt计数到3,8分频时钟输出就会翻转一次输出的8分频信号周期刚好为8个基准时钟周期3、奇数分频器 3.1、设计方法

如图所示,分别画出了基准时钟、3分频时钟、5分频时钟、7分频时钟。

不难想到3分频信号的周期为基准时钟信号周期的3倍,那么3分频时钟信号的边沿变化肯定发生在第1.5个时钟周期(第2个时钟周期的下降沿),同理5分频的边沿变化肯定发生在第2.5个时钟周期(第3个时钟周期的下降沿),同理7分频的边沿变化肯定发生在第3.5个时钟周期(第4个时钟周期的下降沿)。同时我们会发现既然边沿的变化都发生在0.5个时钟周期,那么肯定要利用到时钟的下降沿。

3.2、7分频电路设计实例

根据上图的7分频为例,可以得到以下结论:

L3到L7为7分频的1个完整的时钟周期,同时也是7个基准时钟周期,即7分频L3(红线3,其他红线命名类推)到L4为7分频的半个时钟周期(高电平),同时也是3.5个基准时钟周期L4到L7为7分频的半个时钟周期(低电平),同时也是3.5个基准时钟周期clk_pos为上升沿敏感信号,分为两段,前半段占3个基准时钟周期(0~2),后半段占4个基准时钟周期(3~6)clk_neg为下降沿敏感信号,分为两段,前半段占3个基准时钟周期(0~2),后半段占4个基准时钟周期(3~6)将 clk_pos 和 clk_neg 相与(&&)就可以得到7分频电路

从7分频电路可以推导出奇数分频设计的一般方法:

假设为 N分频,需从0计数到 N-1(一共N/2个基准时钟),一直循环设计一个对基准时钟上升沿敏感的信号,每当计数到(N-1)/2-1时,时钟翻转;计数到计数器最大值时再反转设计一个对基准时钟下降沿敏感的信号,每当计数到(N-1)/2-1时,时钟翻转;计数到计数器最大值时再反转将 上升沿敏感的信号和 下降沿敏感的信号相与(&&)即N分频电路

7分频电路模块框图如下:

输入:

        sys_clk:基准时钟信号(这里设定为50MHz,周期20ns)

        sys_rst_n:低电平有效的复位信号

输出:

        clk_7:基准时钟信号的7分频信号(50/7=7.14MHz,周期140ns)

3.3、Verilog

根据上文分析不难编写Verilog代码如下:

module divider_7 //模块名(inputsys_clk,//时钟(设定为 50MHz)inputsys_rst_n,//复位信号(n 表示低电平有效)outputclk_7//输出7分频信号);//reg 定义reg [2:0]cnt;//最大为6,所以需要3位位宽regcnt_pos;//上升沿敏感信号regcnt_neg;//下降沿敏感信号assign clk_7 = cnt_pos && cnt_neg;//组合逻辑 与 //计数模块,从0计数到6共计7个时钟周期always@(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)cnt <= 3'd0;//复位清零else if(cnt == 3'd6)//从0开始计数,所以需要 -1cnt <= 3'd0;//fkdss则清零elsecnt <= cnt + 3'd1; //没记满就一直计数end//cnt_pos:上升沿触发//低电平维持3个基准时钟周期,高电平维持4个时钟周期always@(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) cnt_pos <= 1'b0; //复位清零else if(cnt == 3'd2) //记满3个时钟周期cnt_pos <= 1'b1; //前3个时钟周期输出为0,满足条件则输出1else if(cnt == 3'd6) //记满7个时钟周期cnt_pos <= 1'b0; //后4个时钟周期输出为1,满足条件则输出0else cnt_pos <= cnt_pos; //不满足条件就保持原来状态end//cnt_neg:下降沿触发//低电平维持3个基准时钟周期,高电平维持4个时钟周期always@(negedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) cnt_neg <= 1'b0; //复位清零else if(cnt == 2'd2) //记满3个时钟周期cnt_neg <= 1'b1; //前3个时钟周期输出为0,满足条件则输出1else if(cnt == 3'd6) //记满7个时钟周期cnt_neg <= 1'b0; //后4个时钟周期输出为1,满足条件则输出0else cnt_neg <= cnt_neg; //不满足条件就保持原来状态endendmodule 3.4、Testbench

Testbench文件比较简单,只需要实例化一下我们刚刚设计好的7分频模块就好了。

`timescale 1ns/1ns//时间刻度:单位1ns,精度1nsmodule tb_divider_7();//仿真模块//输入reg 定义regsys_clk;reg sys_rst_n;//输出wire定义wire clk_7;//设置初始化条件initial beginsys_clk = 1'b0;//初始时钟为0sys_rst_n <= 1'b0;//初始复位#10//10个时间单位后sys_rst_n <= 1'b1; //拉高复位(此时复位无效)end//always代表重复进行,#10代表每10个时间单位//每10个时间单位反转时钟,即时钟周期为20个时间单位(20ns)always #10 sys_clk = ~sys_clk;//例化被测试模块divider_7 divider_7_inst(.sys_clk (sys_clk ), .sys_rst_n (sys_rst_n ), .clk_7 (clk_7 ) );endmodule 3.5、仿真结果

使用ModelSim执行仿真,仿真出来的波形如所示:

从波形图可以看到

10ns后停止复位计数器cnt一直在从0计数到6每当cnt计数到3的上升沿(L2),cnt_pos信号输出翻转,每当cnt计数清零(L4),cnt_pos信号输出翻转每当cnt计数到3的下降沿(L1),cnt_neg信号输出翻转,每当cnt计数清零(L3),cnt_neg信号输出翻转从L2到L3为7分频信号的半个时钟周期(高电平),从L2到L3为8分频信号的半个时钟周期(低电平)从L2到L6为7分频信号的1个完整的时钟周期,同时也是7个基准时钟周期4.其他 版本信息

        文件:V1.0

        编号:5

        Vivado:无

        Modelsim:Modelsim SE-64 10.4

        Quartus II:无

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。