FPGA 多路分频器实验

news2024/12/23 9:30:02

1 概述
        在 FPGA 中,时钟分频是经常用到的。本节课讲解 2 分频、3 分频、4 分频和 8 分频的 Verilog 实现并且学习 generate 语法功能的应。

2 程序设计思路
        1)整数倍分频,为 2、4、8,这种 2^n 次方倍数倍数关系的分频最容易实现,所以我们可以把这 3 种分频方式归为一类。
        2)3 分频是奇数倍分频,这种分频比较麻烦,对于初学者肯定得思考一番。
        3)2HZ 和前文中流水灯的延迟控制方法有一样,只要实现每过 500ms 对寄存器取反操作。
        对于这类基础简单的方案,笔者认为,大家学习主要缺少的是思路,所以我们直接拿程序来分析。
Clk_Divider.v

`timescale 1ns / 1ps
module Clk_Divider# 
(
parameter DEBUG_ENABLE = 1'b1,
parameter REF_CLK      = 32'd100000000
)
(
input clk_i,
input  rst_n_i,
output div2_o,
//output div3_o,
output div4_o,
output div8_o,
output div2hz_o
    );


//2分频代码:只要基于源时钟每个时钟的上升沿对div2_o_r寄存器取反    
reg div2_o_r;
always@(posedge clk_i)begin
	if(!rst_n_i)
		div2_o_r <= 1'b0;
	else 
		div2_o_r <= ~div2_o_r;
end

//4分频和8分频代码:共同使用了div_cnt1计数器
//4分频就是对计数器在div_cnt1==2'b00或者div_cnt1==2'b10的时候对div4_o_r寄存器取反;
//而8分频是对div_cnt1==2'b00的时候对div8_o_r取反
reg [1:0] div_cnt1;
always@(posedge clk_i)begin
	if(!rst_n_i)
		div_cnt1 <= 2'b00;
	else
		div_cnt1 <= div_cnt1+1'b1;
end

reg div4_o_r;
reg div8_o_r;
always@(posedge clk_i)begin
	if(!rst_n_i)
		div4_o_r <= 1'b0;
	else if(div_cnt1==2'b00 || div_cnt1==2'b10)
		div4_o_r <= ~div4_o_r;
	else
		div4_o_r <= div4_o_r;
end

always@(posedge clk_i)begin
	if(!rst_n_i)
		div8_o_r <= 1'b0;
	else if(div_cnt1==2'b00)
		div8_o_r <= ~div8_o_r;
	else
		div8_o_r <= div8_o_r;
end
/*
3分频的本质是我们需要在每次1.5倍的时钟周期的时候实现3分频寄存器的翻转,但是我们无法直接实现1.5倍的分频。
因此采取分别采取2个计数器pos_cnt和neg_cnt,分别对上升沿和下降沿计数。计数周期是0-1-2,共计3个时钟周期。
我们取pos_cnt == 2'd1的时候div3_o_r0输出高电平,neg_cnt == 2'd1的时候div3_o_r1输出高电平。
由于div3_o_r0和div3_o_r1输出1个时钟的高电平,但是相位相差180°,因此只要执行div3_o = div3_o_r0 | div3_o_r1运算,
就能实现1.5倍周期的输出高电平,那么剩余的1.5倍源时钟周期就是输出低电平了。
*/
reg [1:0] pos_cnt;
reg [1:0] neg_cnt;
always@(posedge clk_i)begin
	if(!rst_n_i)
		pos_cnt <= 2'b00;
	else if(pos_cnt == 2'd2)
		pos_cnt <= 2'b00;
	else
		pos_cnt <= pos_cnt + 1'b1;
end

always@(negedge clk_i)begin
	if(!rst_n_i)	
		neg_cnt <= 2'b00;
	else if(neg_cnt == 2'd2)
		neg_cnt <= 2'b00;
	else
		neg_cnt <= neg_cnt + 1'b1;
end

reg div3_o_r0;
reg div3_o_r1;
always@(posedge clk_i)begin
	if(!rst_n_i)
		div3_o_r0 <= 1'b0;
	else if(pos_cnt < 2'd1)
		div3_o_r0 <= 1'b1;
	else
		div3_o_r0 <= 1'b0;
end

always@(negedge clk_i)begin
	if(!rst_n_i)
		div3_o_r1 <= 1'b0;
	else if(neg_cnt < 2'd1)	
		div3_o_r1 <= 1'b1;
	else
		div3_o_r1 <= 1'b0;
end

reg div2hz_o_r;
reg [25:0] div2hz_cnt;

wire ms250_en = (div2hz_cnt == REF_CLK/4 - 1'b1);
always@(posedge clk_i)
begin
	if(!rst_n_i)
		div2hz_cnt <= 0;
	else if(div2hz_cnt < REF_CLK/4 - 1'b1)
		div2hz_cnt <= div2hz_cnt + 1'b1;
	else
		div2hz_cnt <= 0;
end

always@(posedge clk_i)
begin
	if(!rst_n_i)
		div2hz_o_r <= 0;
	else if(ms250_en)
		div2hz_o_r <= ~div2hz_o_r;
	else
		div2hz_o_r <= div2hz_o_r;
end

assign div2_o = div2_o_r;
assign div3_o = div3_o_r0 | div3_o_r1;
assign div4_o = div4_o_r;
assign div8_o = div8_o_r;
assign div2hz_o = div2hz_o_r;

generate  if(DEBUG_ENABLE == 1'b1) begin : debugcore
//添加ila IP ,Chipscope观察信号
ila_0 ila_0_0 (
	.clk(clk_i), // input wire clk
	.probe0(div2hz_o), // input wire [0:0]  probe0  
	.probe1({div2_o,div4_o,div8_o}) // input wire [3:0]  probe1
);
end
endgenerate

endmodule	

代码解释:
        2 分频代码:只要基于源时钟每个时钟的上升沿对 div2_o_r 寄存器取反
        4 分频和 8 分频代码:共同使用了 div_cnt1 计数器,4 分频就是对计数器在 div_cnt12’b00 或者 div_cnt12’b10 的时候对 div4_o_r 寄存器取反;而 8 分频是对 div_cnt1==2’b00 的时候对 div8_o_r 取反
        3 分频代码:3 分频的本质是我们需要在每次 1.5 倍的时钟周期的时候实现 3 分频寄存器的翻转,但是我们无法直接实现 1.5倍的分频。因此采取分别采取 2 个计数器 pos_cnt 和 neg_cnt,分别对上升沿和下降沿计数。计数周期是 0-1-2,共计 3 个时钟周期。我们取 pos_cnt == 2’d1 的时候 div3_o_r0 输出高电平,neg_cnt == 2’d1 的时候 div3_o_r1 输出高电平。由于 div3_o_r0 和 div3_o_r1 输出 1 个时钟的高电平,但是相位相差 180°,因此只要执行 div3_o = div3_o_r0 | div3_o_r1 运算,就能实现 1.5 倍周期的输出高电平,那么剩余的 1.5 倍源时钟周期就是输出低电平了。

3 RTL 仿真
Clk_Divider_Tb.v

module Clk_Divider_Tb();
// Inputs
reg clk_i;
reg rst_n_i;
// Outputs
wire div2_o;
//wire div3_o;
wire div4_o;
wire div8_o;
wire div2hz_o;

// Instantiate the Unit Under Test (UUT)
Clk_Divider#(
.DEBUG_ENABLE(1'b0),
.REF_CLK(100000000)
) 
Clk_Divider_inst
(
.clk_i(clk_i),
.rst_n_i(rst_n_i), 
.div2_o(div2_o),
.div4_o(div4_o),
.div8_o(div8_o),
.div2hz_o(div2hz_o)
);

initial begin
// Initialize Inputs4
    clk_i= 0;
    rst_n_i = 0;
// Wait 100 ns for global reset to finish
    #100;
    rst_n_i=1;
end
always #5 clk_i =~clk_i;
endmodule

2 分频、3 分频、8 分频

2HZ 分频

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1394382.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Security 中 Authentication和Authorization的区别

Authentication Spring Security提供了全面的认证支持。认证是用来验证试图访问特定资源的用户身份的方式。验证用户的常见方式是要求用户输入用户名和密码。一旦认证完成&#xff0c;我们就知道了用户的身份并且可以进行授权。 Spring Security内置支持对用户进行认证。 简…

el-date-picker如果超过限制跨度则提示

需求&#xff1a;实现日期时间选择组件跨度如果超过限制天数&#xff0c;点击查询则提示超过限制时间 封装一个方法&#xff0c;传入开始和结束时间以及限制天数&#xff0c;如果超过则返回false //计算时间跨度是否超过限制天数isTimeSpanWithinLimit(startTime, endTime, li…

Android Text View 去掉默认的padding的实现方法

先看下最终实现效果&#xff0c;满意您在往下看&#xff1a; TextView 绘制的时候自带一定的Padding值&#xff0c;要想实现去掉默认的padding值&#xff0c;xml文件可以设置一个属性值 &#xff1a; android:includeFontPadding"false" 然后运行起来就会发现&…

【C++干货铺】红黑树 (Red Black Tree)

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 前言 红黑树的概念 红黑树的性质 红黑树结点的定义 红黑树的插入操作 插入新的结点 检查规则进行改色 情况一 情况二 情况三 插入完整代码 红黑树的验…

ArcGIS Pro 如何新建布局

你是否已经习惯了在ArcGIS中数据视图和布局视图之间来回切换&#xff0c;到了ArcGIS Pro中却找不到二者之间切换的按钮&#xff0c;即使新建布局后却发现地图怎么却是一片空白。 这一切的一切都是因为ArcGIS Pro的功能框架完全不同&#xff0c;这里为大家介绍一下在ArcGIS Pro…

纸黄金实战投资技巧:避免亏损的有效策略

在纸黄金交易的实战中&#xff0c;避免亏损是每位投资者都追求的目标。虽然任何投资都存在一定的风险&#xff0c;但采取一些有效的策略可以帮助投资者最大限度地减少亏损的可能性。以下是一些在纸黄金交易中避免亏损的实战技巧&#xff1a; 一、设定止损点是避免亏损的关键 止…

【Android】自定义View onDraw()方法会调用两次

问题 自定义了View后&#xff0c;在构造函数中设置画笔颜色&#xff0c;发现它没起效&#xff0c;但是在onDraw()里设置颜色就会起效&#xff0c;出问题的代码如下&#xff1a; public RoundSeekbarView(Context context, Nullable AttributeSet attrs) {super(context, attrs…

dubbo入门案例!!!

入门案例之前我们先介绍一下&#xff1a;zookeeper。 Zookeeper是Apacahe Hadoop的子项目&#xff0c;可以为分布式应用程序协调服务&#xff0c;适合作为Dubbo服务的注册中心&#xff0c;负责服务地址的注册与查找&#xff0c;相当于目录服务&#xff0c;服务提供者和消费者只…

考下初级会计证书,好处竟有这么多!柯桥学会计去哪里?零基础入门手把手教学

初级会计证书有什么用&#xff1f; 初级会计证书有什么用&#xff1f;往下看&#xff0c;看完还没报名的建议大家赶紧报名&#xff0c;今年拿下&#xff01;因为初级会计证书真的很有用&#xff01; 01 求职刚需 初级会计是会计职业的起点&#xff0c;很多会计基础岗位&#x…

rust跟我学六:虚拟机检测

图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎么检测是否在虚拟机里运行的。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:…

关于Jenkins安装后,插件管理中插件版本依赖报错问题的解决方法

我们在初次安装完Jenkins后&#xff0c;通常会去下载要使用的插件&#xff0c;但是在插件管理中通常会出现插件版本问题的提示&#xff0c;例如&#xff1a; 此类问题一般可通过升级Jenkins到最新版本来解决问题。但是Jenkins从旧版本升级到最新版本&#xff0c;望望可能会连…

redis安装-Linux为例

可以下载一个Shell或者MobaXterm工具&#xff0c;便于操作 在redis官网下载压缩包 开始安装 安装依赖 yum install -y gcc tcl切换目录 切换目录后直接把redis安装包拖到/user/local/src/下 cd /user/local/src/解压然后安装 #解压 tar -zxvf redis-7.2.4.tar.gz #安装 …

并发编程之MESI缓存一致性协议

目录 CPU缓存架构 CPU多核缓存架构 CPU缓存架构缓存一致性的解决方案 缓存一致性协议实现原理 总线窥探 工作原理 窥探协议类型 缓存一致性协议 MESI协议 伪共享问题 CPU缓存架构 CPU缓存即高速缓冲存储器&#xff0c;是位于CPU与主内存间的一种容量较小但速度很高的…

如何在MinIO存储服务中通过Buckets实现远程访问管理界面上传文件

文章目录 前言1. 创建Buckets和Access Keys2. Linux 安装Cpolar3. 创建连接MinIO服务公网地址4. 远程调用MinIO服务小结5. 固定连接TCP公网地址6. 固定地址连接测试 前言 MinIO是一款高性能、分布式的对象存储系统&#xff0c;它可以100%的运行在标准硬件上&#xff0c;即X86等…

Halcon基于相关性的模板匹配

Halcon基于相关性的模板匹配 基于相关性的模板匹配其实是另一种基于灰度值的匹配&#xff0c;不过它的特点是使用一种归一化的互相关匹配&#xff08;Normalized Cross Correlation&#xff0c;NCC&#xff09;来衡量模板图像和检测图像之间的关系&#xff0c;因此&#xff0c…

前端实现轮训和长连接

简介 轮训和长连接相关内容可以参考之前的文章消息推送系统。消息推送系统-CSDN博客文章浏览阅读106次。在餐饮行业中&#xff0c;店内应用有pos、厨显屏等&#xff0c;云端应用为对应数据中心。为了实现云端数据和操作指令下发到店内应用&#xff0c;需要有一个系统实现这个功…

“重大利好”!以太坊坎昆升级临近!Layer2新玩家Blast不断蚕食市场份额,令竞品汗流浃背?

1月17日&#xff0c;坎昆升级&#xff08;Dencun&#xff09;率先在以太坊Goerli测试网启动&#xff0c;由于Goerli是参与者数量以及网络负载程度最高的测试网&#xff0c;仅次于以太坊主网&#xff0c;因此如果没什么问题&#xff0c;预示着主网升级已经不远。 而现在&#xf…

「alias」Linux 给命令起别名,自定义bash命令

0. 背景 Arch 系统没有 ll命令,在其他发行版用惯了一时间没有真不习惯,来配置一下吧! 1. 全局配置 我希望 ll 命令可以被所有人使用,所以应该配置在全局的bash配置文件中,一般这个全局bash配置文件在: /etc/bash.bashrc 切好管理员权限后,命令如下 echo “alias ll‘ls -l -…

QuestDB时序数据库快速入门

简介 QuestDB是一个开源的高性能时序数据库&#xff0c;专门用于处理时间序列相关的数据存储与查询&#xff1b; QuestDB使用列式存储模型。数据存储在表中&#xff0c;每列存储在其自己的文件和其自己的本机格式中。新数据被附加到每列的底部&#xff0c;以便能够按照与摄取…

【音视频】基于NGINX如何播放rtmp视频流

背景 现阶段直播越来越流行&#xff0c;直播技术发展也越来越快。Webrtc、rtmp、rtsp是比较火热的技术&#xff0c;而且应用也比较广泛。本文通过实践来展开介绍关于rtmp如何播放。 概要 本文重点介绍基于NGINX如何播放rtmp视频流 正文 1、构造rtsp视频流 可以参考上一篇…