搜索
bottom↓
回复: 37

Verilog 实现任意分频 【转】

[复制链接]

出0入0汤圆

发表于 2010-12-13 16:18:34 | 显示全部楼层 |阅读模式
这是我网上转来的哈

分频程序虽然简单,但我觉得由简入难是学习的一个必然阶段,慢慢的我们自然会成长起来。所以如果有时间的话,大家都可以将自己的这种“小程序”贴到论坛上来。如果你的程序好,其他人也可以学习;如果你的程序有问题,大家可以一起帮你找问题,共同进步。还有,我觉得在 发贴的时候,最好能将原理说一下。一来大家看你的贴能学到东西;二来也方便解答你的问题,不然还得解答者自己去找资料搞懂原理,然后再回答你,回答你问题 的人自然也就不多了。

在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求这样的话,对于程序有一定的要求,现在我在前人经验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。

比如:我们FPGA系统时钟是50M Hz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。我们很容易想到用计数的方式来分频:

50000000/880 = 56818

这个数字不是2的整幂次方,那么怎么办呢?我们可以设定一个参数,让它到56818的时候重新计数不就完了吗?呵呵,程序如下:

module div(clk, clk_div);

input clk;

output clk_div;

reg [15:0] counter;

always @(posedge clk)

if(counter==56817) counter <= 0;

else counter <= counter+1;

assign clk_div = counter[15];

endmodule

在我们日常的设计中很多情形下会用到需要分频的情形,好多人的做法是先用高频时钟计数,然后使用计数器的某一位输出作为工作时钟进行其他的逻辑设计,上面的程序就是一个体现。

下面我们来算一下它的占空比:我们清楚地知道,这个输出波形在counter为0到32767的时候为低,在32768到56817的时候为高,占空比为40%多一些,如果我们需要占空比为50%,那么怎么办呢?

我们再设定一个参数,使它为56817的一半,使达到它的时候波形翻转,那不就完了吗?呵呵,再看看:

module div(clk, clk_div);

input clk;

output clk_div;

reg [14:0] counter;

always @(posedge clk)

if(counter==28408) counter <= 0;

else counter <= counter+1;

reg clk_div;

always @(posedge clk)

  if(counter==28408) clk_div <= ~clk_div;

endmodule

占空比是不是神奇地变成50%了呢?呵呵。

继续让我们来看如何实现任意占空比,比如还是由50 M 分频产生880 Hz,而分频得到的信号的占空比为30%。

56818×30%=17045

module div(clk,reset,clk_div,counter);

input clk,reset;

output clk_div;

output [15:0] counter;

reg [15:0] counter;

reg clk_div;

always @(posedge clk)

if(!reset) counter <= 0;

else if(counter==56817) counter <= 0;

else counter <= counter+1;

always @(posedge clk)

if(!reset) clk_div <= 0;

else if(counter<17045) clk_div <= 1;

else clk_div <= 0;

endmodule

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入300汤圆

发表于 2010-12-13 20:48:23 | 显示全部楼层
这种帖子是教学帖,必须顶起

出0入0汤圆

发表于 2010-12-13 21:10:43 | 显示全部楼层
学习下,先顶后看。

出0入0汤圆

发表于 2010-12-13 21:16:14 | 显示全部楼层
mark!~

出0入0汤圆

发表于 2010-12-13 21:33:26 | 显示全部楼层
很基础,mark~~

出0入0汤圆

发表于 2010-12-13 21:39:17 | 显示全部楼层
基础,mark

出0入0汤圆

发表于 2010-12-14 08:29:35 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-12-14 09:30:21 | 显示全部楼层
不懂fpga 好像mcu不能这么干

出0入0汤圆

发表于 2010-12-14 10:14:36 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-12-14 11:56:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-14 12:18:03 | 显示全部楼层
好像不能实现任意分频,只能实现N*2分频,N为计数值

出0入0汤圆

发表于 2010-12-15 16:39:00 | 显示全部楼层
强贴MARK~~~

出0入0汤圆

发表于 2010-12-15 20:19:41 | 显示全部楼层
只是整数分频

出0入0汤圆

发表于 2010-12-17 11:37:37 | 显示全部楼层
有个免费的小软件,可以设置分频比和占空比后,自动生成verilog/VHDL代码。

奇数分频的原理也就是分别写个上升沿触发和下降沿出发的代码,再用组合逻辑并起来,就实现了。

这台电脑上没有这个软件,下次找到了发上来。

出0入0汤圆

发表于 2010-12-17 11:41:06 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-1-10 10:30:41 | 显示全部楼层
学习,我一直不注重这个,原理不懂

出0入0汤圆

发表于 2011-1-10 12:41:26 | 显示全部楼层
回复【楼主位】liu116feng
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2011-1-10 13:05:10 | 显示全部楼层
不错,但“任意”二字太可怕了。

出0入0汤圆

发表于 2011-1-19 18:31:40 | 显示全部楼层
不错 学习了

出0入0汤圆

发表于 2011-1-19 19:52:50 | 显示全部楼层
任意整数倍分频,任意占空比我也自己想出来了,怎么你这个代码量这么大啊。。

always@(posedge c0)
begin
clk_c<=clk_c+1;
if(clk_c==13)
begin
clk_c<=0;
c1<=~c1;
end
end

出0入0汤圆

发表于 2011-1-20 06:31:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-24 15:30:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-29 13:07:52 | 显示全部楼层
学习下,先顶后看。

出0入0汤圆

发表于 2011-1-30 13:16:01 | 显示全部楼层
ding

出0入0汤圆

发表于 2011-2-18 21:02:08 | 显示全部楼层
回复【楼主位】liu116feng
-----------------------------------------------------------------------

学习啦

出0入0汤圆

发表于 2011-2-20 14:18:15 | 显示全部楼层
好帖子

出0入0汤圆

发表于 2011-2-20 16:59:03 | 显示全部楼层
很是不错的!!  学习了!!

出0入0汤圆

发表于 2011-2-20 18:09:28 | 显示全部楼层
mark

出55入66汤圆

发表于 2011-2-20 18:20:18 | 显示全部楼层
能倍频就好了

出0入0汤圆

发表于 2011-2-21 02:01:25 | 显示全部楼层
回复【19楼】wwuchang
任意整数倍分频,任意占空比我也自己想出来了,怎么你这个代码量这么大啊。。
always@(posedge c0)
begin
clk_c&lt;=clk_c+1;
if(clk_c==13)
begin
clk_c&lt;=0;
c1&lt;=~c1;
end
end

-----------------------------------------------------------------------
非阻塞赋值竟然立即进行比较! 服了U

出0入0汤圆

发表于 2011-2-22 16:50:16 | 显示全部楼层
module div(clk, clk_div);
input clk;
output clk_div;
reg [14:0] counter;
reg clk_div;
always @(posedge clk)
if(counter==28408)
begin
counter <= 0;
clk_div <= ~clk_div;
end
else
  begin
counter <= counter+1;
clk_div <= clk_div;
  end
/*always @(posedge clk)
  if(counter==28408)
   clk_div <= ~clk_div;*/
endmodule

出0入0汤圆

发表于 2011-2-24 16:06:56 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-6-2 23:08:48 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-2 23:15:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-23 14:50:43 | 显示全部楼层
不错,收藏了。

出0入0汤圆

发表于 2011-10-25 16:58:51 | 显示全部楼层
mark分频器
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 11:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表