首页 > 编程知识 正文

fpga时钟分频方法,verilog实现九分频

时间:2023-05-06 17:19:44 阅读:153113 作者:1553

由于硬件描述时钟信号的处理是FPGA的一个特征,分频器也是FPGA设计中使用频率非常高的基本设计之一。 一般来说,在FPGA中,搭载了可以进行各种时钟的分频和倍频设计的综合锁相环,但是根据语言设计的时钟分频是基本的训练,即使在设计对时钟要求不高的情况下,也可以节约锁相环的资源。 本实验实现了任意整数的分频器,分频时钟维持50%占空比。

1、偶数分频:偶数倍分频比较简单易懂。 完全可以通过计数器计数实现。 如果将偶数分频乘以n,则通过时钟触发开始计数器计数,当计数器从0计数到N/2-1时,输出时钟反转,循环进行。

2、奇数分频:要实现占空比50%的奇数倍分频,与偶数分频一样,在计数器减半的时候输出时钟会反转,得不到占空比50%的时钟。 以分频时钟CLK为例,以偶数分频进行奇数分频时,在CLK的上升沿被触发,得到占空比不是50%的1时钟信号(正周期比负周期多1时钟或少1时钟)。 但是,如果在CLK下降沿也触发,得到占空比不为50%的其他时钟信号,则这两个时钟的相位正好相差CLK的时钟周期的一半。 通过用这两个时钟信号进行逻辑运算,可以巧妙地得到占空比50%的时钟。

总之,为了实现占空比50%的n倍奇数分频,首先进行上升沿触发,进行模式n计数,将计数数量选定为某个值,进行输出时钟的反转,然后,经过(N-1 )/2再次进行反转,进行占空比进而,同时进行下降触发模拟n计数,当成为与上升触发输出时钟反转选择值相同的值时,进行输出时钟的时钟反转,同样,当经过(N-1 )/2时,再次反转输出时钟,使占空比为50% 对占空比不为50%的2个n分频时钟进行逻辑运算(正周期多的相和负周期多的相或) ),得到占空比为50%的奇数n分频时钟。

Verilog代码moduledivide(clk,rst_n,clkout ); input clk,rst_n; //输入信号。 在此,clk与FPGA的C1引脚连接,频率为12MHz outputclkout; //输出信号是可连接到LED观察分频的时钟//parameter为verilog的常量语句parameterWIDTH=3; //计数器位数,计数最大值为2**WIDTH-1parameterN=5; //分频系数请确保N 2**WIDTH-1。 否则,确定计数是否满足reg [WIDTH-1:0]cnt_p,cnt_n; //cnt_p是上升触发时的计数器,cnt_n是下降触发时的计数器regclk_p、clk_n; //clk_p是上升触发时分周时钟,clk_n是下降触发时分周时钟//上升触发时计数器的控制always @ (posedgeclkornegedgerst _ n )//posedge ELSEif(CNT_p==(n-1 ) ) cnt_p=0; else cnt_p=cnt_p 1; //计数器始终计数,计数到N-1时清零。 这是以模拟n的计数器end //上升沿为触发的分频时钟输出,n为奇数时得到的时钟占空比不是50%。 如果n为偶数得到的时钟占空比为50 % always @ (posedgeclkornegedgerst _ n ) beginif (! rst_n ) clk_p=0; ELSEif(CNT_p(N1 ) )/N1表示向右移动一个数量级,相当于通过除以2消除馀数clk_p=0; else clk_p=1; //得到的分频时钟的正周期从负周期开始为clk时钟end //下降沿触发时的计数器的控制always @ (negedgeclkornegedgerst _ n ) beginif (! rst_n ) cnt_n=0; ELSEif(CNT_n==(n-1 ) ) cnt_n=0; else cnt_n=cnt_n 1; 在end //下降沿触发的分频时钟输出与clk_p相差半个时钟的always@(negedgeclk ) beginif (! rst_n ) clk_n=0; ELSEif(CNT_n ) N1 ) ) clk_n=0; else clk_n=1; //得到的分频时钟的正周期比负周期短clk时钟end assign clkout=(N==1)? CLK:(n[0]? (clk_pclk_n ) :clk_p; //条件判断式

//当N=1时,直接输出clk //当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p //当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&clk_n。正周期多所以是相与endmodule

测试文件,进行功能仿真时需要编写testbench测试文件。verilog里的testbench文件和源文件一样也是.v文件,仿真能让我们更直观的观察信号波形,可以先阅读Diamond的使用了解如何使用Diamond中集成的仿真工具。

  `timescale 1ns/100ps //仿真时间单位/时间精度,时间单位要大于或者等于时间精度  module divide_tb(); //测试文件也是一个module,因为用于仿真所以无需输入输出信号  reg clk,rst_n; //需要产生的激励信号定义,激励信号需要过程块产生所以定义为reg型变量 wire clkout; //需要观察的输出信号定义,定义为wire型变量  //初始化过程块 initial begin clk = 0; rst_n = 0; #25 //#表示延时25个时间单位 rst_n = 1; //产生了一个初始25ns低电平,然后变高电平的复位信号 end  always #10 clk = ~clk; //每隔10ns翻转一次clk信号,也就是产生一个时钟周期20ns的clk,频率为50MHz   //module调用例化格式 divide #(.WIDTH(4),.N(11)) u1 ( //#后面的()中为参数传递,如果不传递参数就是所调用模块中的参数默认值 //divide表示所要例化的module名称,u1是我们定义的例化名称,必须以字母开头.clk(clk), //输入输出信号连接。 .clk表示module本身定义的信号名称;(clk)表示我们在这里定义的激励信号.rst_n(rst_n), //在testbench里定义的信号名称可以与所要调用module的端口信号名称不同.clkout(clkout) ); endmodule 引脚分配

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

信号引脚clkC1rst_nL14clkoutN13


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

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