技术标签: fpga开发
FPGA分频器是一种常用于数字信号处理、通信系统、雷达系统等领域的电路,其作用是将信号时钟分成多个频频率。分频电路是数字电路中常见的逻辑电路类型。在时序逻辑电路中,时钟是必不可少的,但对于时钟要求不高的基本设计,自行设计的分频电路,也就是时钟分频器,有时候比采用外部PLL更为简单、有效、快速。本文将详细介绍FPGA分频器的设计方法,并附上Verilog代码示例,以供参考。
分频器一般可以分为:偶数分频、奇数分频、小数分频。
将主时钟以2为幂次进行分割可以得到同步偶数分频时钟,即21,22,23…分频。电路上可采用D触发器实现,n个触发器可以构成2n次偶数分频。如图1所示,为2分频、4分频电路设计及波形。
用D触发器级联搭建分频电路只能实现2,4,8,16等分频,对于一般的偶数分频,可以通过计数器实现:若要实现N分频(N为偶数),只需将计数器在待分频时钟上升沿触发下循环计数,从0计数到(N/2 -1)后将输出时钟翻转即可实现。代码见工程Even_clk_freq_div。仿真图和代码如下:
//N为偶数分频的值,实现50%占空比的偶数分频
parameter N = 6;
reg [2:0] cnt;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)begin
cnt <= 3'd0;
clk_out <= 1'b0;
end
else if (cnt == (N-1)/2)begin
cnt <= 3'd0;
clk_out <= ~clk_out;
end
else
cnt <= cnt + 1'b1;
以7分频为例,通过如图2所示Moore状态机即可实现输入时钟的7分频。
值得注意的是,上图实现的7分频的占空比并非50%。代码见工程Odd_clk_freq_div_Moore。仿真和代码截图如下:
parameter state_0 = 3'd0,
state_1 = 3'd1,
state_2 = 3'd2,
state_3 = 3'd3,
state_4 = 3'd4,
state_5 = 3'd5,
state_6 = 3'd6;
reg [2:0] State,next_state;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
State <= state_0;
else
State <= next_state;
always @(*)
if (!rst_n)
next_state <= state_0;
else begin
case (State)
state_0 : next_state = state_1;
state_1 : next_state = state_2;
state_2 : next_state = state_3;
state_3 : next_state = state_4;
state_4 : next_state = state_5;
state_5 : next_state = state_6;
state_6 : next_state = state_0;
default : next_state = state_0;
endcase
end
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
clk_out <= 1'b0;
else begin
case(next_state)
state_0 : clk_out <= 1'b0;
state_1 : clk_out <= 1'b0;
state_2 : clk_out <= 1'b0;
state_3 : clk_out <= 1'b0;
state_4 : clk_out <= 1'b1;
state_5 : clk_out <= 1'b1;
state_6 : clk_out <= 1'b1;
default : clk_out <= 1'b0;
endcase
end
其实用状态机实现占空比非50%的分频电路还是比较麻烦的,可以采用计数器的方法:若要实现N分频(N为奇数),只需将计数器在待分频时钟上升沿触发下循环计数,从0计数到(N-1)后计数器清零。当计数到(N-1)/2后将输出时钟翻转,计数到0后再次翻转即可实现。代码见工程Odd_clk_freq_div0。仿真和代码如下:
//N为奇数分频的值,实现非50%占空比的奇数分频
parameter N = 7;
reg [2:0] cnt;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
cnt <= 3'd0;
else if (cnt == (N-1))
cnt <= 3'd0;
else
cnt <= cnt + 1'b1;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
clk_out <=1'b0;
else if (cnt == (N-1)/2)
clk_out <= ~clk_out;
else if (cnt == 3'b0)
clk_out <= ~clk_out;
else
clk_out <= clk_out;
对于奇数分频,就是分别利用待分频时钟的上升沿触发生成一个时钟,然后用下降沿触发生成另一个时钟,然后将两个时钟信号进行或/与运算得到占空比为50%的奇数分频。上面一小节已经介绍了如何利用待分频时钟的上升沿触发生成占空比非50%的时钟,只需再类似地利用待分频时钟的下降沿触发生成占空比非50%的时钟。具体方法详述如下:
① 设计2个分别用上升、下降沿触发的计数器
定义2个计数器cnt_p和cnt_n,分别利用时钟的上升沿和下降进行触发计数
② 利用上升、下降沿计数器生成两个分频时钟clk_p和clk_n
定义2个时钟信号clk_p和clk_n, 对于上升沿计数器cnt_p,当计数到0或者(N-1)/2时,均翻转clk_p信号;对于下降沿计数器cnt_n,当计数到0或者(N-1)/2时,均翻转clk_n信号。
③ 利用clk_p和clk_n通过逻辑运算生成占空比为50%的分频时钟
若clk_p和clk_n初始复位为0,将2个时钟clk_p和clk_n通过或运算即可生成占空比为50%的分频时钟,且clk_out上升沿和原时钟上升沿对齐。代码见工程Odd_clk_freq_div1。仿真截图和代码如下:
//N为奇数分频的值,实现50%占空比的奇数分频
parameter N = 7;
reg [2:0] cnt_p, cnt_n;
reg clk_p;
reg clk_n;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
cnt_p <= 3'd0;
else if (cnt_p == (N-1))
cnt_p <= 3'd0;
else
cnt_p <= cnt_p + 1'b1;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
clk_p <=1'b0;
else if (cnt_p == (N-1)/2)
clk_p <= ~clk_p;
else if (cnt_p == 3'b0)
clk_p <= ~clk_p;
else
clk_p <= clk_p;
//将clk_p打半拍得到clk_n
always @(negedge clk_in or negedge rst_n)
if (!rst_n)
cnt_n <= 3'd0;
else if (cnt_n == (N-1))
cnt_n <= 3'd0;
else
cnt_n <= cnt_n + 1'b1;
always @(negedge clk_in or negedge rst_n)
if (!rst_n)
clk_n <=1'b0;
else if (cnt_n == (N-1)/2)
clk_n <= ~clk_n;
else if (cnt_n == 3'b0)
clk_n <= ~clk_n;
else
clk_n <= clk_n;
assign clk_out = clk_p | clk_n;
详细的波形图如图3所示:
还有一种更简便的方法只需要一个计数器cnt_p就可以,通过cnt_p产生clk_p时钟,然后直接用待分频时钟下降沿对时钟clk_p打半拍得到时钟clk_n,最后将clk_p和clk_n相或就可以得到占空比为50%的7分频时钟。代码见工程Odd_clk_freq_div,个人比较推荐这种写法,里面涉及到对信号打半拍,理解到了对学习FPGA大有帮助。下面是仿真结果图和代码截图。
//N为奇数分频的值,实现50%占空比的奇数分频
parameter N = 7;
reg [2:0] cnt;
reg clk_p;
reg clk_n;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
cnt <= 3'd0;
else if (cnt == (N-1))
cnt <= 3'd0;
else
cnt <= cnt + 1'b1;
always @(posedge clk_in or negedge rst_n)
if (!rst_n)
clk_p <=1'b0;
else if (cnt == (N-1)/2)
clk_p <= ~clk_p;
else if (cnt == 3'b0)
clk_p <= ~clk_p;
else
clk_p <= clk_p;
//将clk_p打半拍得到clk_n
always @(negedge clk_in or negedge rst_n)
if (!rst_n)
clk_n <=1'b0;
else
clk_n <= clk_p;
assign clk_out = clk_p | clk_n;
上面我们从波形生成方法及Verilog实现的角度思考了如何设计占空比为50%的奇数分频电路,这里我们直接从电路角度出发进行设计。首先思考如何用D触发器和组合逻辑实现占空比为50%的三分频电路?思路:先使用触发器构成序列生成器,输出001循环脉冲,实现占空比非50%的三分频,然后用负沿触发器打一拍,再相或。由于001循环共三个状态,故需2个D触发器。通过列状态表、画卡诺图,得到由两个D触发器及逻辑门构成的001序列生成器,后接负沿触发器打一拍并将其输出与序列生成器的输出相或,即得到占空比为50%的三分频电路。下面贴出三分频和五分频电路的简略设计思路及过程仅供参考,如图4、图5所示。
小数分频电路可以转化为特定分频比电路设计问题。如19/9分频,意味着在输入时钟clk_in的19个周期内,输出需产生9个脉冲。因为19/9 = 2.11…, 因此可以用2分频和3分频配合实现,设待分频时钟的19个周期内共有x个二分频时钟周期,y个三分频时钟周期,则有:
x + y = 9 x+y=9 x+y=9
2 x + 3 y = 19 2x+3y=19 2x+3y=19
解得 x = 8 , y = 1 x=8,y=1 x=8,y=1。即只要在待分频时钟的19个周期内控制输出8个二分频时钟周期和1个三分频时钟周期即可。具体代码思路:
1)首先一个总的计数器,在0-18循环;
2)其次设计两个分别生成2分频和3分频的计数器,根据总计数器的数值范围分别在0-1和0-2循环;
3)最后是波形生成逻辑,根据总计数器和2、3分频计数器的数值控制输出脉冲翻转生成期望分频比的时钟。
reg [5:0] cnt;
reg [3:0] cnt_a;
reg [3:0] cnt_b;
reg clk_out_reg;
assign clk_out = clk_out_reg;
// div_a和div_b分别为根据文档公式计算出来的基准分频系数
// change为2、3分频时钟的切换点
parameter M = 5'd19;
parameter change = 5'd16;
parameter div_a = 5'd2;
parameter div_b = 5'd3;
//总计数器
always @(posedge clk_in or negedge rst_n)
if(!rst_n)
cnt <= 6'b0;
else begin
if(cnt == M - 1'b1)
cnt <= 6'b0;
else
cnt <= cnt + 1'b1;
end
//产生2、3分频的计数器
always @(posedge clk_in or negedge rst_n)
if(!rst_n) begin
cnt_a <= 4'b0;
cnt_b <= 4'b0;
end
else if(cnt <= change - 1'b1) begin
cnt_b <= 4'd0;
if(cnt_a == div_a - 1'b1)
cnt_a <= 4'd0;
else
cnt_a <= cnt_a + 1'b1;
end
else if(cnt > change - 1'b1) begin
cnt_a <= 4'd0;
if(cnt_b == div_b - 1'b1)
cnt_b <= 4'd0;
else
cnt_b <= cnt_b + 1'b1;
end
//输出时钟产生逻辑
always @(posedge clk_in or negedge rst_n)
if(!rst_n)
clk_out_reg <= 1'b0;
else if(cnt < change) begin
if(cnt_a == 4'd0 || cnt_a == div_a/2)
clk_out_reg <= ~clk_out_reg;
else
clk_out_reg <= clk_out_reg;
end
else if(cnt >= change) begin
if(cnt_b == 4'd0 || cnt_b == (div_b - 1'b1)/2)
clk_out_reg <= ~clk_out_reg;
else
clk_out_reg <= clk_out_reg;
end
上面代码的后段3分频是占空比非50%的,若要实现占空比50%,我们同样可以采取打半拍的方式并通过逻辑运算获得。代码和仿真结果如下,为了更好提现,这里实现20/9分频,通过公式计算得出在20个待分频时钟周期内,应该产生7个二分频脉冲和2个三分频脉冲。工程为Dec_Freq_Div_M_N。
reg [5:0] cnt;
reg [3:0] cnt_a;
reg [3:0] cnt_b;
reg clk_out_p;
reg clk_out_n;
assign clk_out = (cnt <= change) ? clk_out_p : (clk_out_p | clk_out_n); //产生占空比为50%的时钟
// div_a和div_b分别为根据文档公式计算出来的基准分频系数
// change为2、3分频时钟的切换点
parameter M = 5'd20;
parameter change = 5'd14;
parameter div_a = 5'd2;
parameter div_b = 5'd3;
//总计数器
always @(posedge clk_in or negedge rst_n)
if(!rst_n)
cnt <= 6'b0;
else begin
if(cnt == M - 1'b1)
cnt <= 6'b0;
else
cnt <= cnt + 1'b1;
end
//产生2、3分频的计数器
always @(posedge clk_in or negedge rst_n)
if(!rst_n) begin
cnt_a <= 4'b0;
cnt_b <= 4'b0;
end
else if(cnt <= change - 1'b1) begin
cnt_b <= 4'd0;
if(cnt_a == div_a - 1'b1)
cnt_a <= 4'd0;
else
cnt_a <= cnt_a + 1'b1;
end
else if(cnt > change - 1'b1) begin
cnt_a <= 4'd0;
if(cnt_b == div_b - 1'b1)
cnt_b <= 4'd0;
else
cnt_b <= cnt_b + 1'b1;
end
//输出时钟产生逻辑
always @(posedge clk_in or negedge rst_n)
if(!rst_n)
clk_out_p <= 1'b0;
else if(cnt < change) begin
if(cnt_a == 4'd0 || cnt_a == div_a/2)
clk_out_p <= ~clk_out_p;
else
clk_out_p <= clk_out_p;
end
else if(cnt >= change) begin
if(cnt_b == 4'd0 || cnt_b == (div_b - 1'b1)/2)
clk_out_p <= ~clk_out_p;
else
clk_out_p <= clk_out_p;
end
//打半拍
always @(negedge clk_in or negedge rst_n)
if(!rst_n)
clk_out_n <= 1'b0;
else
clk_out_n <= clk_out_p;
下图是本文的文件截图,有需要的话点击下面的链接获取:
文章浏览阅读64次。1、生成补丁,修改前后的apk包都必须签名。2、AndFix 不支持修改布局文件。3、文件的路径必须正确。4、AndFix 不支持添加匿名内部类(就是点击事件)。5、AndFix 不支持添加新的类。6、AndFix 支持连续打补丁(注意补丁的名字要求不一样)。转载于:https://www.cnblogs.com/Jackie-zhang/p/10162430.html..._阿里andfix增加内部类
文章浏览阅读115次。婴幼儿配方奶粉是作为宝宝在无法母乳喂养时的无奈选择,也是除母乳以外最好的选择,宝妈在选择奶粉时也会格外认真,当看到奶粉中含有香精香料成分时,部分宝妈便不会购买,甚至认为此类成分是对宝宝身体有所危害的,所以坚决抵制购买,那么添加到奶粉中的香精香料到底怎么样,长期吃有没有坏处?我们来看看吧~不同人群,对香精香料有不同看法"宝妈们这样说:前段时间网上一位宝妈的评论吸引了笔者的注意:“我这奶粉买回家一开罐...
文章浏览阅读2.5k次。并不是苹果说的触点问题,而是软布导线被腐蚀断线问题。用铜箔胶带粘一下就好了。不过二手直接买一个咸鱼上也就三百多,也不贵。这个明显是苹果设计缺陷。直接丢了挺可惜的。拆的时候小心点。我的QQ: 13008312096,有空的话可以帮忙有偿代处理。参考链接如下:nullhttps://www.youtube.com/watch?v=buNYHzMZJdk修复好的样子,毫无违和感:..._ipad10.5键盘套没反应
文章浏览阅读1.3w次,点赞3次,收藏13次。网上下载的gif图很多都不透底,而且尺寸时间什么的都不合适,用ps简单修改一下就好了1.抽帧很多gif图帧数很多,抽帧可以大幅压缩gif大小1.导入gif到ps2.勾选动作和时间轴面板这时我们发现帧和图层的隐藏显示是相对应的这样的话我们操作图层就会打乱帧,我们要让所有的图层都显示,但又不干扰帧的显示3.这时我们就要把它转换为视频时间轴4.然后再转换帧>>转换为..._gif抽帧
文章浏览阅读235次。通过本文将了解到以下内容:优先队列的概念优先队列的实现优先队列的应用1.优先队列的概念优先队列是计算机科学中的一类抽象数据类型。优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;优先级相同的元素按照其在优先队列中的顺序得到服务。优先队列至少需要支持下述操作:a.插入带优先级的元素b.取出具有最高优先级的元素c.查看最高优先级的元素。综合考虑插入和删除的性能 优先队列一般采用堆来实..._优先队列 c++面试
文章浏览阅读281次。windows系统VMware安装Linux虚拟机、配置JDK环境、安装tomcat、安装mysql、安装redis第一部分VMware安装Linux—————————————————————————————————xshell、VMware工具链接:解压之后安装VMware工具xshell不需要安装解压可直接使用..._vm中linux下载安装mysql jdk
文章浏览阅读2w次。由于通讯协议中长度使用byte字节来表示,但在java中长度超过127的时候会变成负数,所以需要保证得到的长度是正数byte b & 0xFFhttp://www.blogjava.net/orangelizq/archive/2008/07/20/216228.html在剖析该问题前请看如下代码public static String bytes2HexString(
文章浏览阅读10w+次,点赞112次,收藏974次。Ubuntu18.04镜像_ubuntu系统18.04
文章浏览阅读6.7k次,点赞3次,收藏17次。一、Json字符串和Json对象定义:1、Json字符串:所谓字符串:单引号或者双引号引起来,是一个String类型的字符串:如下:var person='{"name":"shily","sex":"女","age":"23"}';//json字符串console.log(person)console.log(person.name)console.log(typeof person) 2、Json对象:最显著的特征:对象的值可以用 “对象.属性” 进行访问,_json字符串数组
文章浏览阅读718次。CentOS 7:ip link set interface_name up 或 ip link set interface_name down。Ubuntu:ifconfig interface_name up 或 ifconfig interface_name down。CentOS 7:编辑 /etc/sysconfig/network-scripts/ifcfg-eth0 文件。Ubuntu:编辑 /etc/network/interfaces 文件。_ubuntu 命令跟centos
文章浏览阅读652次。jpegsr9e windows vs2019生成方法,以及库下载_jpeg library error vs2019
文章浏览阅读647次。总的来说,华为Mate 60/Pro系列手机的高速网速表现引起了广泛的关注,这也是消费者对该系列手机购买热情高涨的一个重要因素。可以看出,华为Mate 60/Pro系列手机的网速表现非常出色,这也是消费者购买该系列手机的一个重要原因。此前,华为Mate 60 Pro的供应量已经增至1500万至1700万台,而最新消息称,华为Mate 60 Pro和Mate 60 Pro+的出货量甚至已上调至2000万台。目前,在中国市场上,手机竞争愈发激烈,不仅华为Mate 60系列,其他品牌的手机也都受到了高温的迎接。_华为mate60pro+核实网络