Verilog设计分频器(面试必看)
分频器是指使输出信号频率为输入信号频率整数分之一的电子电路。在许多电子设备中如电子钟、频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是一种主要变换手段。
早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代了正弦分频器。
下面以Verilog HDL 语言为基础介绍占空比为50%的分频器。
1、偶分频
偶分频电路指的是分频系数为 2、4、6、8 ... 等偶数整数的分频电路,我们可以直接进行分频。
例如下面 divider.v 中,对输入时钟进行6分频,即假设clk 为 50MHz ,分频后的时钟频率为 (50/6) MHz。程序如下:
设计代码:
- //rtl
- module divider(
- clk,
- rst_n,
- clk_div
- );
- input clk;
- input rst_n;
- output clk_div;
- reg clk_div;
- parameter NUM_DIV = ;
- reg [:] cnt;
- always @(posedge clk or negedge rst_n)
- if(!rst_n) begin
- cnt <= 'd0;
- clk_div <= 'b0;
- end
- else if(cnt < NUM_DIV / - ) begin
- cnt <= cnt + 'b1;
- clk_div <= clk_div;
- end
- else begin
- cnt <= 'd0;
- clk_div <= ~clk_div;
- end
- endmodule
仿真程序:
- //tb
- module divider_tb();
- reg clk;
- reg rst_n;
- wire clk_div;
- parameter DELY=;
- divider U_divider(
- .clk (clk ),
- .rst_n (rst_n ),
- .clk_div(clk_div)
- );
- always #(DELY/) clk=~clk;//产生时钟波形
- initial begin
- $fsdbDumpfile("divider_even.fsdb");
- $fsdbDumpvars(,U_divider);
- end
- initial begin
- clk=;rst_n=;
- #DELY rst_n=;
- #((DELY*)) $finish;
- end
- endmodule
可以看到,clk的上升沿,采样到cnt=2的时候,就翻转,采样到0和1的时候,保持。这样就可以做到一半高电平,一半低电平。
由于奇分频需要保持分频后的时钟占空比为 50% ,所以不能像偶分频那样直接在分频系数的一半时使时钟信号翻转(高电平一半,低电平一半)。
在此我们需要利用输入时钟上升沿和下降沿来进行设计。
clk_div1 和clk_div2 的上升沿到来时间相差半个输入周期,所以将这两个信号进行或操作,即可得到占空比为 50% 的5分频时钟。程序如下:
- //rtl
- module divider(
- clk,
- rst_n,
- clk_div
- );
- input clk;
- input rst_n;
- output clk_div;
- reg clk_div;
- parameter NUM_DIV = ;
- reg[:] cnt1;
- reg[:] cnt2;
- reg clk_div1, clk_div2;
- always @(posedge clk or negedge rst_n)
- if(!rst_n)
- cnt1 <= ;
- else if(cnt1 < NUM_DIV - )
- cnt1 <= cnt1 + 'b1;
- else
- cnt1 <= ;
- always @(posedge clk or negedge rst_n)
- if(!rst_n)
- clk_div1 <= 'b1;
- else if(cnt1 < NUM_DIV / )
- clk_div1 <= 'b1;
- else
- clk_div1 <= 'b0;
- always @(negedge clk or negedge rst_n)
- if(!rst_n)
- cnt2 <= ;
- else if(cnt2 < NUM_DIV - )
- cnt2 <= cnt2 + 'b1;
- else
- cnt2 <= ;
- always @(negedge clk or negedge rst_n)
- if(!rst_n)
- clk_div2 <= 'b1;
- else if(cnt2 < NUM_DIV / )
- clk_div2 <= 'b1;
- else
- clk_div2 <= 'b0;
- assign clk_div = clk_div1 | clk_div2;
- endmodule
仿真代码:
- //tb
- module divider_tb();
- reg clk;
- reg rst_n;
- wire clk_div;
- parameter DELY=;
- divider U_divider(
- .clk (clk ),
- .rst_n (rst_n ),
- .clk_div(clk_div)
- );
- always #(DELY/) clk=~clk;//产生时钟波形
- initial begin
- $fsdbDumpfile("divider_odd.fsdb");
- $fsdbDumpvars(,U_divider);
- end
- initial begin
- clk=;rst_n=;
- #DELY rst_n=;
- #((DELY*)) $finish;
- end
- endmodule
对其进行测试和验证(此仿真波形是三分频,占空比50%),即上述程序吧NUM_DIV改成3即可,得到如下波形:
3.任意占空比的任意分频
在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求这样的话,对于程序有一定的要求。
现在在前面两个实验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。
比如: FPGA系统时钟是50M Hz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。很容易想到用计数的方式来分频:50000000/880 = 56818。
显然这个数字不是2的整幂次方,那么我们可以设定一个参数,让它到56818的时候重新计数就可以实现了。程序如下:
设计代码:
- //rtl
- module div(
- clk,
- rst_n,
- clk_div
- );
- input clk,rst_n;
- output clk_div;
- reg clk_div;
- reg [:] counter;
- always @(posedge clk or negedge rst_n)
- if(!rst_n)
- counter <= ;
- else if(counter==)
- counter <= ;
- else
- counter <= counter+;
- assign clk_div = counter[];
- endmodule
仿真代码:
- //tb
- module div_tb();
- reg clk;
- reg rst_n;
- wire clk_div;
- parameter DELY=;
- div U_div(
- .clk (clk ),
- .rst_n (rst_n),
- .clk_div(clk_div)
- );
- always #(DELY/) clk=~clk;//产生时钟波形
- initial begin
- $fsdbDumpfile("div_any.fsdb");
- $fsdbDumpvars(,U_div);
- end
- initial begin
- clk=;rst_n=;
- #DELY rst_n=;
- #((DELY*)) $finish;
- end
- endmodule
分频的应用很广泛,一般的做法是先用高频时钟计数,然后使用计数器的某一位输出作为工作时钟进行其他的逻辑设计,上面的程序就是一个体现。
下面我们来算一下它的占空比:
我们清楚地知道,这个输出波形在counter为0到32767(2的14次方)的时候为低,在32768到56817的时候为高,占空比为40%多一些,
如果我们需要占空比为50%,那么我们需要再设定一个参数,使它为56817的一半,使达到它的时候波形翻转,就可以实现结果了。
程序如下:28408=56818/2-1,计数到28408就清零,翻转,其余的计数期间,保持不变。
设计代码:
- //rtl
- module div(
- clk,
- rst_n,
- clk_div
- );
- input clk,rst_n;
- output clk_div;
- reg clk_div;
- reg [:] counter;
- always @(posedge clk or negedge rst_n)
- if(!rst_n)
- counter <= ;
- else if(counter==)
- counter <= ;
- else
- counter <= counter+;
- always @(posedge clk or negedge rst_n)
- if(!rst_n)
- clk_div <= ;
- else if(counter==)
- clk_div <= ~clk_div;
- endmodule
仿真代码:
- //tb
- module div_tb();
- reg clk;
- reg rst_n=;
- wire clk_div;
- parameter DELY=;
- div U_div(
- .clk (clk ),
- .rst_n (rst_n),
- .clk_div(clk_div)
- );
- always #(DELY/) clk=~clk;//产生时钟波形
- initial begin
- $fsdbDumpfile("div_any.fsdb");
- $fsdbDumpvars(,U_div);
- end
- initial begin
- clk=;rst_n=;
- #DELY rst_n=;
- #((DELY*)) $finish;
- end
- endmodule
- //rtl
- module div(
- clk,
- rst_n,
- clk_div,
- counter
- );
- input clk,rst_n;
- output clk_div;
- reg clk_div;
- output [:] counter;
- reg [:] counter;
- always @(posedge clk)
- if(!rst_n)
- counter <= ;
- else if(counter==)
- counter <= ;
- else counter <= counter+;
- always @(posedge clk)
- if(!rst_n)
- clk_div <= ;
- else if(counter<)
- clk_div <= ;
- else
- clk_div <= ;
- endmodule
仿真代码:
- //tb
- module div_tb();
- reg clk;
- reg rst_n;
- wire clk_div;
- wire [:] counter;
- parameter DELY=;
- div U_div(
- .clk (clk ),
- .rst_n (rst_n ),
- .counter(counter),
- .clk_div(clk_div)
- );
- always #(DELY/) clk=~clk;//产生时钟波形
- initial begin
- $fsdbDumpfile("div_any.fsdb");
- $fsdbDumpvars(,U_div);
- end
- initial begin
- clk=;rst_n=;
- #DELY rst_n=;
- #((DELY*)) $finish;
- end
- endmodule
通过以上的学习,对分频器有了比较深刻的认识,将在以后的学习中会有广泛的应用。
原出处:https://www.chipist.cn/article/166 如有什么疑问,欢迎讨论:QQ:447574829
Verilog设计分频器(面试必看)的更多相关文章
- 面试必看!靠着这份字节和腾讯的面经,我成功拿下了offer!
准备 敲定了方向和目标后就开始系统准备,主要分为以下几个方面来准备. 算法题 事先已经看过别人的社招面经知道头条每轮技术面都有算法题,而这一块平时练习的比较少,校招时刷的题也忘记了很多.因此系统复习的 ...
- linux c++ 服务器端开发面试必看书籍
摘自别人博客,地址:http://blog.csdn.net/qianggezhishen/article/details/45951095 打算从这开始一本一本开始看 题外话: 推荐一个 githu ...
- 面试必看!凭借着这份 MySQL 高频面试题,我拿到了京东,字节的offer!
前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水. 前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面 ...
- iOS面试必看
转载:http://www.jianshu.com/p/5d2163640e26 序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形 ...
- iOS面试必看,最全梳理
序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,加之,培训机构一火车地向用人单位输送iOS开发人员,打破了生态圈的动态 ...
- iOS,面试必看,最全梳理
序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,加之,培训机构一火车地向用人单位输送iOS开发人员,打破了生态圈的动态 ...
- iOS面试必看经典试题分析
> **不用临时变量怎么实现两个数据的交换?** 方式一:加减法的运算方式求解new_b = a - b + b = a;new_a = a + b - a = b;一个简单的运算方式,最重要的 ...
- 百度搜索 “Java面试题” 前200页(面试必看)
前言 本文中的题目来源于网上的一篇文章<百度搜索 "Java面试题" 前200页>,但该文章里面只有题目,没有答案.因此,我整理了一些答案发布于本文.本文整理答案的原则 ...
- iOS - 基础知识总结(OC版) 面试必看 再不看就要用swift了
OC的理解与特性 OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装.继承.多态.它既具有静态语言的特性(如C++),又有动态语言的效率(动态绑定.动态加载等).总体来讲,OC确实是一门不错 ...
随机推荐
- hdu1698(线段树区间替换模板)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1698 题意: 第一行输入 t 表 t 组测试数据, 对于每组测试数据, 第一行输入一个 n , 表示 ...
- codeforces1009G Allowed Letters【贪心+hall定理】
因为是字典序所以贪心选当前能选的最小的,所以问题就在于怎么快速计算当前这个位置能不能选枚举的字母 重排之后的序列是可以和原序列完美匹配的,而完美匹配需要满足hall定理,也就是左边任意k个集合一定和右 ...
- 坑爹的 Java 可变参数,把我整得够惨。。
最近在写一个功能点,用了 Java 中的可变参数,真是把我搞得够惨.. 什么是可变参数? 就是方法参数用 Object... args 三个点形式,一个参数可以接收多个参数. 实际的代码就不帖了,来看 ...
- ps 命令参数解释
转自:https://www.cnblogs.com/fps2tao/p/7692482.html A 显示所有进程(等价于-e)(utility)-a 显示一个终端的所有进程,除了会话引线-N 忽略 ...
- python——基本数据类型1——简介
列表 列表是可变数据类型.是序列类型; 列表的内容可以是数字,字符串和其它列表: 0第一个元素,-1最后一个元素, 定义连续列表 li = list(range(1,10,2)) 列表取值: 取 b: ...
- Codeforces Round #431 (Div. 2) C
From beginning till end, this message has been waiting to be conveyed. For a given unordered multise ...
- FusionCharts的类 - 实例功能
一.FusionCharts的类 - 实例功能 1.configure(name:string , value:string) or configure(configurations: Objec ...
- Hadoop数据管理
本节主要从三方面介绍Hadoop数据管理:分布式文件系统HDFS.分部式数据库HBase和数据仓库工具Hive. 1. HDFS的数据管理 HDFS是分布式计算的存储基石,Hadoop分布式文件系统和 ...
- redis启动内存不足
redis-server.exe redis.windows.conf --maxheap 2gb
- Column 'xxx' in field list is ambiguous
一 其实看一下ambiguous的翻译就好了 一开始我觉得是含糊什么的,后来找了下才知道应该是双关... 二 所以翻译过来就是 : 列'XX'在字段列表中双关 其实就是两张表有相同的字段,但是使用时, ...