基于DDS原理的高精度任意分频器(使用Verilog)

在FPGA设计中,每个模块常常要用不同频率的时钟信号作为时钟输入端,但往往使用计数器设计的时钟精度不够,所产生的的误差在一次次的累加下会变得越来越大。使用锁相环IP核当然可以实现,但所需要的分频时钟多起来了,这时候的锁相环就不那么容易使用;并且针对某些时钟频率,锁相环也达不到那个要求。所以,分享一种原理方便,操作简单,并且精度还可以达到很高的一种分频方法。

原理

DDS原理我们在此不过多赘述,只需要了解DDS的一个核心公式即可。

         eq?f_%7B0%7D%3D%20%5Cfrac%7Bf_%7Bc%7D*k%7D%7B2%5E%7BN%7D%7D        ——(1)                                                              

eq?f_%7B0%7D是所需要的时钟频率;eq?f_%7Bc%7D是开发板时钟或者叫系统时钟;eq?k是频率控制字;eq?N是所定义的计数器位宽。

知道了原理,那这个公式究竟是怎么用呢?

第一步:稍稍对公式做个变形:

         eq?k%3D%5Cfrac%7Bf_%7B0%7D*2%5E%7BN%7D%7D%7Bf_%7Bc%7D%7D        ——(2)

第二步:确定eq?f_%7B0%7Deq?Neq?f_%7Bc%7D等参数;

第三步:依据公式计算频率控制字。

现在我们来演示一下:例如我们的板载晶振为50MHz,所需要的分频时钟为8.35MHz,计数器位宽我们选择48位(计数器位宽越大,精度越好;综合考虑来说,当计数器位宽为48位时,精度完全满足要求并且也不会占用特别大的资源)。

d77492f696db488c92d934a74d8303e7.png

代入(2)式计算可得:eq?k = 47006321110680("小数部分大于5需要进位,由FPGA的特性决定")

此时将eq?k的值再代入(1)式中,可得eq?f_%7B0%7D=8.3500000000000795807864051312208

可以看到精度逼近于小数点后13位,由此可见,理论上完全满足要求。8c147b0d00b549b1b5aaae47a752d21a.png

看到这里,有人会说,你这只是验证了时钟周期的精度,我最终的目的就是为了输出时钟频率那怎么办呢?简单的分两种情况,由特殊到一般性。

一、特殊情况,即50%的占空比:

        ①简单写法:取计数器的最高位直接输出;

       ② 通用写法:当计数器小于eq?%5Ctfrac%7B2%5E%7BN%7D%7D%7B2%7D时,时钟输出端为0,否则为1。

二、一般情况,即任意占空比:

        计数器大小eq?2%5E%7BN%7D,可以理解为周期;那么任意占空比就是给eq?2%5E%7BN%20%7D乘以你要的占空比,小于时时钟输出为0,大于时时钟输出为1。

//**************************************** Message ***********************************//
//技术交流:folkore0118@163.com
//关注CSDN博主:“彼稷”
//Author: 彼稷 
//All rights reserved	                               
//----------------------------------------------------------------------------------------
// Target Devices: 		DELL-G15
// Tool Versions:       vivado2021.2
// File name:           
// Last modified Date:  2023年12月12日
// Last Version:        
// Descriptions:        基于DDS原理的时钟分频 
//----------------------------------------------------------------------------------------
//****************************************************************************************//
`timescale 1ns / 1ps

module CLK(
		i_sys_clk		,	
		i_rst_n         ,
		o_clk
    );
	input		i_sys_clk		;
	input		i_rst_n         ;
	output		o_clk           ;
	
	localparam	FRE_WROD	=	48'd47006321110680;
	
	reg	[47:0]	cnt_clk;
	always@(posedge i_sys_clk or negedge i_rst_n)begin
		if(!i_rst_n)
			cnt_clk	<=	48'd0;
		else
			cnt_clk	<=	cnt_clk	+	FRE_WROD;
	end 
	
	assign	o_clk	=	cnt_clk[47];
	
endmodule

0158f5f58be94a5bb4c131da368a8d78.png

4e377b64725f4f15b8a751cd2c10144c.png

由于计数器只在时钟上升沿有效,故会出现些许偏差,系统时钟频率越高,分频效果越好。

注意!!!

频率控制字一定要声明位宽,vivado中数据位宽默认是32位,若频率控制字位宽大于32位,则会出错。

 

 

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彼稷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值