分频器是用的最广的一种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. python刷LeetCode:1.两数之和

    难度等级:简单 题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不 ...

  2. Windows下C extension not loaded for Word2Vec, training will be slow.解决方法

    在网上看了好多个博客,都没有很好解决,最后google.. 大概问题就是gensim库在安装时没有和其他一些包关联起来(可能是由于用pip安装的gensim导致这个问题),所以在用Word2Vec时没 ...

  3. 微信H5支付,成功样例

    <?php/** * Created by PhpStorm. * User: Administrator * Date: 2019/6/3 * Time: 12:00 */ if( !defi ...

  4. C语言-再论指针与数组

    指针与数组的天生姻缘1.以指针方式来访问数组元素(1).数组元素使用时不能整体访问,只能是单个访问.访问形式有两种:数组形式和指针形式.(2).数组形式访问数组元素:数组名[下标]:(下标从0开始(3 ...

  5. 一图解明Android Studio项目文件结构各部分作用

    初学Android在阅读<第一行代码>的时候整理出来的,如果差错恳请指出,不胜感激. 制图不易,转载请标注出处,谢谢.

  6. FPGA的基本组成单元LUT,以及三种核的概念

    .查找表 LUT就是查找表,对于4输入的LUT而言,实际上就是4位地址位,一位数据位的存储器,能够存储16位数据,所以我们在FPGA设计中可以用LUT组建分布式的RAM. 这样也可以解释我们在设计中为 ...

  7. dotnet core 链接mongodb

    导入命名空间 using MongoDB.Bson; using MongoDB.Driver; 测试示例: var client = new MongoClient("mongodb:// ...

  8. pandas在指定列插入数据

    import pandas as pd import numpy as np df = pd.DataFrame(np.arange(15).reshape(5, 3), columns=['a', ...

  9. Java连接MySQL Warning: Establishing SSL connection without server's identity verification is not recommended

    1. 数据库 1.1 创建表 在当前数据库students中,创建数据表student: mysql> create table student( ),#学生ID ),#学生姓名 -> a ...

  10. ZJNU 1542 - 三角形(续)--中高级

    从小到大排序后 先固定一遍,另外两边递增查找 即固定 i,j=i+1,k=j+1 然后让k递增到 a[i]+a[j]<=a[k] 时 此时不能凑成一个三角形 答案增加 k-1-j 组 此时不需要 ...