分频器是用的最广的一种FPGA电路了,我最初使用的是crazybingo的一个任意分频器,可以实现高精度任意分频的一个通用模块,他的思想在于首先指定计数器的位宽比如32位,那么这个计数器的最大值就是2^32=4294967296,

假设系统时钟为50MHz,那么假如要想实现输出频率为fout,那么可以使用的频率控制字为:

K满足关系:

,那么设计计数器在每个时钟上升沿累加的值为K,当计数值为2^31时,clkout=1;否则clkout=0.最终即可以实现任意频率的输出,精度的计算方法为当K=1时,可以得到clkout=0.0116415321826934814453125Hz,也即是说可以输出的最小频率为0.011Hz

此外我们最为常见的分频器分为以下4种分析:

1.偶数分频

最简单,要想得到分频系数为N的频率输出,设定一个计数器,这个计数器从零开始加1,当加到N/2-1时计数器清零,或者clkout翻转,以此循环,即可实现偶数倍分频。

2.奇数分频(分占空比不确定以及占空比50%)

方法一:分频系数为N,占总比不确定:以三(N)分频为例,上升沿触发计数,计数器计数到1(N-1)/2时输出时钟翻转,计数到2(N-1)时再次翻转.代码为产生1/11占空比为十一分频时钟:在计数值为9和10时均反转时钟,是产生抽样脉冲的有效方法:

always @(posedge clk or posedge rst) begin
if(rst)begin //复位
cnt<=;
clk_div11<=;
end
elseif(cnt==) begin
clk_div11<=~clk_div11; //时钟翻转
cnt<=cnt+; //继续计数
end
elseif(cnt==) begin
clk_div11<=~clk_div11; //时钟翻转
cnt<=; //计数清零
end
else
cnt<=cnt+;
end

占空比50% ,则可以在上面的基础上,加上一个下降沿触发计数,然后将上升沿和下降沿产生的时钟进行相或运算,即可得到奇数分频输出。

reg clk1;
reg[:]cnt1;
always@(posedge clk or posedge rst) begin
if(rst)begin //复位
cnt1<=;
clk1<=;
end
elseif(cnt1==) begin
clk1<=~clk1; //时钟翻转
cnt1<=cnt1+; //继续计数
end
elseif(cnt1==) begin
clk1<=~clk1; //时钟翻转
cnt1<=; //计数清零
end
else
cnt1<=cnt1+;
end reg clk2;
reg[:]cnt2;
always@(negedge clk or posedge rst) begin
if(rst)begin //复位
cnt2<=;
clk2<=;
end
elseif(cnt2==) begin
clk2<=~clk2; //时钟翻转
cnt2<=cnt2+; //继续计数
end
elseif(cnt2==) begin
clk2<=~clk2; //时钟翻转
cnt2<=; //计数清零
end
else
cnt2<=cnt2+;
end assign clk_div3=clk1 | clk2; //或运算
 
图1 50%占空比的三分频电路原理图

方法二:对进行奇数倍n分频时钟,先进行n/2分频,然后在二分频得到(这部分先讲半整数分频)

亲测有效代码:
module ModuloN_Cntr(input clk,rst,output clk_out);
reg [1:0]cnt1;
reg [1:0]cnt2;
reg temp1,temp2;
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
cnt1<=0;
temp1<=0;
end
else
begin
if(cnt1==2)
begin
temp1<=1;
cnt1<=0;
end
else
begin
cnt1<=cnt1+1;
temp1<=0;
end
end
end
always@(negedge clk or negedge rst)
begin
if(~rst)
begin
cnt2<=0;
temp2<=0;
end
else
begin
if(cnt2==2)
begin
temp2<=1;
cnt2<=0;
end
else
begin
cnt2<=cnt2+1;
temp2<=0;
end
end
end
assign clk_out=temp1|temp2;
endmodule

仿真波形:

3.半整数分频

半整数指的是N+0.5分频器设计:先进行模N+1计数,计数到N时输出时钟赋值为1,然后当计数到0时,输出时钟赋值为0,因此保持计数值为N的时间为半个时钟周期即为设计的关键,从中可以发现,计数器是在时钟的上升沿计数,那么我们可以让时钟在计数值为N时,将计数触发时钟翻转,时钟的下降沿变为上升沿,因此计数值为0,所以每产生一个N+0.5分频时钟周期,触发时钟都要翻转一次,以2.5分频为例程序如下:

 //异或运算
       assignclk_in=clk^clk_div2;
       //模3计数器
       reg clk_out;
       reg [1:0]cnt;
       always@(posedge clk_in or posedge rst) begin
              if(rst)begin   //复位
                     cnt<=0;
                     clk_out<=0;
              end
              elseif(cnt==1) begin
                     clk_out<=~clk_out;   //时钟翻转
                     cnt<=cnt+1;    //继续计数
              end
              elseif(cnt==2) begin
                     clk_out<=~clk_out;   //时钟翻转
                     cnt<=0;    //计数清零
              end
              else
                     cnt<=cnt+1;
       end
       //2分频
       reg clk_div2;
       always@(posedge clk_out or posedge rst) begin
              if(rst)  clk_div2<=0;  //复位
              else  clk_div2=~clk_div2;
       end
 
图3 通用半整数分频器的电路原理图
 
图4  2.5倍分频器时序仿真图

那么5.5分频呢:

代码:通用的这里N=5;

module ModuloN_Cntr(clk,clk_div,temp1,temp2);//N+0.5
input clk;
output clk_div;
reg[:]cnt1=;
reg[:]cnt2=;
output reg temp1,temp2;
initial begin temp1=;temp2=;end //首先进行初始化,temp1=0;temp2=1
parameter N=; //设定分频系数为N+0.5
always @(posedge clk) //temp1上升沿跳变
begin
if(cnt1==*N) //2*N
begin cnt1[:]<='d0;end
else begin cnt1[:]<=cnt1[:]+'d1;end
if(cnt1=='d0) begin temp1<=1;end //高电平时间为N+1;
if(cnt1==N+) begin temp1<=;end //低电平时间为N;
end
always@(negedge clk) //temp2下降沿跳变
begin
if(cnt2==*N) //2*N
begin cnt2[:]<='d0;end
else begin cnt2[:]<=cnt2[:]+'d1;end
if(cnt2=='d0) begin temp2<=0;end //低电平时间为N;
if(cnt2==N) begin temp2<=;end //高电平时间为N+1;
end
assign clk_div=temp1&&temp2; //逻辑与
endmodule
//如果要进行N+0.5分频
//思路:总的来说要进行N+1+N=2N+1次分频
//在时钟的上升沿和下降沿都进行跳变
//上升沿进行占空比为N+1比N的时钟temp1;
//下降沿进行占空比为N比N+1的时钟temp2;
//最后div=temp1&&temp2 即可得到所需要的半整数分频

仿真波形:

4.任意小数分频

小数分频器的实现方法有很多中,但其基本原理都一样的,即在若干个分频周期中采取某种方法使某几个周期多计或少计一个数,从而在整个计数周期的总体平均意义上获得一个小数分频比。一般而言,这种分频由于分频输出的时钟脉冲抖动很大,故在设计中的使用已经非常少。但是,这也是可以实现的。以8.7倍分频为例,本文仅仅给出双模前置小数分频原理的verilog代码及其仿真图(如图6),具体原理可以参考刘亚海的《基于FPGA的小数分频器的实现》以及毛为勇的《基于FPGA的任意小数分频器的设计》。

还是放下代码吧:

//8分频
reg clk_div8;
reg[:]cnt_div8;
always@(posedge clk or posedge rst) begin
if(rst)begin //复位
clk_div8<=;
cnt_div8<=;
end
elseif(cnt_div8=='d7) begin
clk_div8<=; //置1
cnt_div8<=;
end
elseif(cnt_div8=='d0) begin
clk_div8<=; //置0
cnt_div8<=cnt_div8+;
end
else
cnt_div8<=cnt_div8+;
end //9分频
reg clk_div9;
reg[:]cnt_div9;
always@(posedge clk or posedge rst) begin
if(rst)begin //复位
clk_div9<=;
cnt_div9<=;
end
elseif(cnt_div9=='d8) begin
clk_div9<=; //置1
cnt_div9<=;
end
elseif(cnt_div9=='d0) begin
clk_div9<=; //置0
cnt_div9<=cnt_div9+;
end
else
cnt_div9<=cnt_div9+;
end
//控制信号
parameterDiv8Num=;
reg ctrl;
reg[:]AddValue;
always@(posedge clk or posedge rst) begin
if(rst)begin //复位
ctrl<=;
AddValue<=-;
end
elseif(AddValue<) begin
ctrl<=;
AddValue<=AddValue+Div8Num;
end
else begin
ctrl<=;
AddValue<=AddValue-;
end
end //选择输出
reg clk_out;
always @(ctrlor posedge clk or posedge rst) begin
if(rst) clk_out<=; //复位
elseif(ctrl) clk_out<=clk_div8;
elseclk_out<=clk_div9;
end
 
图6  8.7分频器的时序仿真图
 
4、总结分频器是FPGA的基础,而且在FPGA逻辑电路设计的时候是经常使用的,希望大家对以上的整数倍分频和半整数倍分频能熟练掌握

关于分频器的FPGA实现整理思路的更多相关文章

  1. FPGA浮点数定点数的处理

    http://blog.chinaaet.com/justlxy/p/5100053166大佬博客,讲的非常有条理的 1,基础知识 (1)定点数的基础认知: 首先例如一个16位的数表示的定点数的范围是 ...

  2. mac下常用软件整理

    1.非常好用的压缩管理软件(免费版):RAR Extrator Free  解压的中文不会产生乱码: 2.记笔记用的:有道笔记.Evernote 3.SVN管理软件:ConerStone 4.非常给力 ...

  3. 【加解密专辑】对接触到的PGP、RSA、AES加解密算法整理

    先贴代码,有空再整理思路 PGP加密 using System; using System.IO; using Org.BouncyCastle.Bcpg; using Org.BouncyCastl ...

  4. 【小梅哥FPGA进阶教程】第十一章 四通道幅频相可调DDS信号发生器

    十一.四通道幅频相可调DDS信号发生器 本文由山东大学研友袁卓贡献,特此感谢 实验目标 实现多通道可调信号发生器 实验平台 芯航线FPGA核心板.ADDA模块 实验现象 实现基于FPGA的多通道可调信 ...

  5. 发现程序bug思路

    大家有没有遇到过项目,程序出现个bug,但花了好久(真的是a long long time啊)才发现引发这个问题的原因,心想原来就这个原因导致的啊,要是早想到就好了! 其实我们确实的是方法,希望我的抛 ...

  6. Microsoft Azure 资料整理

    鉴于Microsoft Azure的技术迭代更新相当快,所以推荐大家还是以官方文档为准. 以Global Azure 的为主,Mooncake版本自行删减 首先推荐Azure for MSDN htt ...

  7. 对cpu与load的理解及线上问题处理思路解读

    前言 2019双11还有不到2个月就要到来了,大家也都知道服务器在大促期间由于流量的增加势必导致机器的cpu与load变高.因此趁着这个时机正好再好好学习.巩固一下cpu和load的概念,为双11做准 ...

  8. Hazel,自动整理文件,让你的 Mac 井井有条

    原文地址 https://sspai.com/post/35225 让我们从实际需求出发,看看问题出在哪里,并在此基础上认识和学习使用 Hazel. 电脑随着使用时间的增长,其中的文件也在疯狂的增长, ...

  9. C语言整理复习——指针

    指针是C的精华,不会指针就等于没学C.但指针又是C里最难理解的部分,所以特意写下这篇博客整理思路. 一.指针类型的声明 C的数据类型由整型.浮点型.字符型.布尔型.指针这几部分构成.前四种类型比较好理 ...

随机推荐

  1. ZJNU 2342 - 夏华献要回家

    (夏华献在学校也要做一次梦!) 把5的答案手动算出 会发现从学校开始,兔子的数量呈斐波那契数列(第2项开始)增长 假如现在有n盏路灯 那么睡觉的时间可以得到为 但是n有1e18大,明显使用标准数学公式 ...

  2. D10 基本数据类型(各种职业的技能分析) 主要为 int 和 str

    在python中具有魔法的  职业  类型 召唤每种职业  在pychar 中 打出该职业的名称 按住Ctrl 光标在该职业名称上 点击就能看该职业的技能 1   数字   int a = " ...

  3. SWIG 3 中文手册——9. SWIG 库

    目录 9 SWIG 库 9.1 %include 指令与库搜索路径 9.2 C 数组与指针 9.2.1 cpointer.i 9.2.2 carrays.i 9.2.3 cmalloc.i 9.2.4 ...

  4. 《Docekr入门学习篇》——Docker实战

    基础环境 root@docker~]# cat /etc/redhat-release #查看版本号 CentOS Linux release (Core) [root@docker ~]# unam ...

  5. UML类图说明

    1:示例 这是一个使用UML表示的类图的结构,通过箭头,菱形,实线以及虚线来代表一些类之间的关系,后面将按照上面的例子一一介绍说明. 上图中,abstract 车是一个抽象类.小汽车和自行车是继承了车 ...

  6. PAT Advanced 1015 Reversible Primes (20) [素数]

    题目 A reversible prime in any number system is a prime whose "reverse" in that number syste ...

  7. ubuntu下Django的搭建

    工具:Window下的pycharm .VirtualBox下的Ubuntu系统.非必需的Xshell(远程连接工具) 现在针对各种包或python版本不能共存或包不能很好下载的问题,开始流行使用虚拟 ...

  8. cf1172E Nauuo and ODT(LCT)

    首先可以转化问题,变为对每种颜色分别考虑不含该颜色的简单路径条数.然后把不是当前颜色的点视为白色,是当前颜色的点视为黑色,显然路径数量是每个白色连通块大小的平方和,然后题目变为:黑白两色的树,单点翻转 ...

  9. 了解Kafka生产者

    了解Kafka生产者 ​ 之前对kafka的整体架构有浅显的了解,这次正好有时间,准备深入了解一下kafka,首先先从数据的生产者开始吧. 生产者的整体架构 ​ 可以看到整个生产者进程主要由两个线程进 ...

  10. Python笔记_第四篇_高阶编程_GUI编程之Tkinter_2.控件类

    1. Label控件: 说明:标签控件,可显示文本 图示1: 实例1: import tkinter # 创建主窗口__编程头部 win = tkinter.Tk() # 设置标题 win.title ...