FPGA 多路分频器实验

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 分频

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

记一次DateTimeFormat注解的坑

记一次DateTimeFormat注解的坑 背景&#xff1a;在用Echarts做图表时&#xff0c;前端传两个日期参数&#xff0c;获取日期区间的图表数据。想遵循RESTful风格&#xff0c;所以使用get请求获取date参数。前端读取当前日期&#xff0c;将七天前日期和当前日期作为参数传给后端&…

享元模式介绍

目录 一、享元模式介绍 1.1 享元模式定义 1.2 享元模式原理 1.2.1 享元模式类图 1.2.2 模式角色说明 1.2.3 示例代码 二、享元模式的应用 2.1 需求说明 2.2 需求实现 2.2.1 类图 2.2.2 具体实现 2.2.2.1 抽象享元类 2.2.2.2 共享享元类-白色棋子 2.2.2.3 共享享元…

JAVA SECS发送Report C#处理SECS Report SECS发送事件资料大全 S6F11 建立通讯S1F13

发送S6F11非常简单&#xff0c;只需5~6行代码&#xff0c;最核心是代码清晰易懂。 任何人都可以一看就能上手&#xff0c;如果说用代码可读性作为不可替代性的壁垒就无话可说了。 private void buttonS6F11_Click(object sender, EventArgs e) {int nTransaction 0;// 数据部…

Rust之旅 - Rust概念、Windows安装、环境配置

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 系列专栏目录 [Java项目…

【SpringBoot】SpringBoot 项目初始化方法

github 搜索 springboot 模板 github 搜索 springboot 模板&#xff0c;拉取现成代码。 SpringBoot 官方的模板生成器 SpringBoot 官方的模板生成器&#xff08;https://start.spring.io/&#xff09; 在 IDEA 开发工具中生成 这里我修改成阿里的镜像主要是要使用 Java8。 …

制作一个Python聊天机器人

我们学习一下如何使用 ChatterBot 库在 Python 中创建聊天机器人&#xff0c;该库实现了各种机器学习算法来生成响应对话&#xff0c;还是挺不错的 什么是聊天机器人 聊天机器人也称为聊天机器人、机器人、人工代理等&#xff0c;基本上是由人工智能驱动的软件程序&#xff0…

最多购买宝石数目 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 橱窗里有一排宝石&#xff0c;不同的宝石对应不同的价格&#xff0c;宝石的价格标记为 gems[i],0<i<n, n gems.length 宝石可同时出售0个或多个&#xff…

test2测试

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 磁盘满的本质分析 专栏&#xff1a;《Linux从小白到大神》 | 系统学习Linux开发、VIM/GCC/GDB/Make工具…

如何发挥 Sketch在UI和UX设计中的作用

Sketch是一款专业的矢量图形设计软件&#xff0c;主要应用于UI设计、移动应用设计、Web设计等领域。假如你是一个交互设计师或UI设计师&#xff0c;那么你一定知道Sketch这一强大的矢量设计软件&#xff1b;如果你使用了Photoshop&#xff0c;那么在你接触到Sketch之后&#xf…

物联网协议Coap之C#基于Mozi的CoapServer实现解析

目录 前言 一、C#的Coap Server实现 1、CoapServer相关类 2、主要类解析 3、资源控制器定义 4、ResourceManager管理器 二、CoapServer生命周期 1、Server创建代码 2、服务端创建 3、绑定endpoint 4、准备接收请求 总结 前言 在之前的关于物联网协议的介绍中&#…

汽车连接器接线端子和多芯线束连接界面

冷压接的开式压接和闭式压接以及热压接的超声波焊接对汽车连接器接线端子和多芯线束连接界面 连接器接线端子和多芯线束的连接是电子线束行业&#xff0c;特别是汽车行业常用的导线连接方式。汽车整车线束又由许多分支线束组成&#xff0c;而分支线束必须通过连接器实现连接&am…

HBase学习六:LSM树算法

1、简介 HBase是基于LSM树架构实现的,天生适合写多读少的应用场景。 LSM树本质上和B+树一样,是一种磁盘数据的索引结构。但和B+树不同的是,LSM树的索引对写入请求更友好。因为无论是何种写入请求,LSM树都会将写入操作处理为一次顺序写,而HDFS擅长的正是顺序写(且HDFS不…

IMDB电影评论的情感分析——paddle

项目地址&#xff1a;IMDB电影评论的情感分析 - 飞桨AI Studio星河社区 (baidu.com) 1. 实验介绍 1.1 实验目的 理解并掌握循环神经网络的基础知识点&#xff0c;包括模型的时序结构、模型的前向传播、反向传播等掌握长短时记忆网络LSTM和门控循环单元网络GRU的设计原理熟悉如…

移动云助力智慧交通数智化升级

智慧交通是在整个交通运输领域充分利用物联网、空间感知、云计算、移动互联网等新一代信息技术&#xff0c;综合运用交通科学、系统方法、人工智能、知识挖掘等理论与工具&#xff0c;以全面感知、深度融合、主动服务、科学决策为目标&#xff0c;推动交通运输更安全、更高效、…

O(1)插入、删除和随机元素[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 实现RandomizedSet类&#xff1a; 【1】RandomizedSet()初始化RandomizedSet对象。 【2】bool insert(int val)当元素val不存在时&#xff0c;向集合中插入该项&#xff0c;并返回true&#xff1b;否则&#xff0c;返回false。 【3】…

java基本算法

1.链表 链表用来存储数据&#xff0c;由一系列的结点组成。这些结点的物理地址不一定是连续的&#xff0c;即可能连续&#xff0c;也可能不连续&#xff0c;但链表里的结点是有序的。一个结点由数据的值和下一个数据的地址组成。一个链表内的数据类型可以是多种多样的。数组也是…

Debian系统写Mysql时中文出现乱码无法定入的问题解决方案

原因是操作系统可能精简安装&#xff0c;没有GBK字符集&#xff0c;只有UTF8在转换或使用的时候有问题。 使用locale -a查看系统支持的字符集。正常的比较全的字符集的操作系统如下&#xff1a; 有问题的操作系统字符集如下&#xff1a; 解决方案&#xff1a; 步骤1&#…

protobuf学习日记 | 认识protobuf中的类型

目录 前言 一、标量数据类型 二、protobuf中的 “数组” 三、特殊类型 1、枚举类型 &#xff08;1&#xff09;类型讲解 &#xff08;2&#xff09;升级通讯录 2、Any类型 &#xff08;1&#xff09;类型讲解 &#xff08;2&#xff09;升级通讯录 3、oneof类型 …

【动态规划】【二分查找】【C++算法】730. 统计不同回文子序列

作者推荐 【动态规划】【数学】【C算法】18赛车 涉及知识点 动态规划 二分查找 LeetCode730. 统计不同回文子序列 给你一个字符串 s &#xff0c;返回 s 中不同的非空回文子序列个数 。由于答案可能很大&#xff0c;请返回对 109 7 取余 的结果。 字符串的子序列可以经由…

ubuntu源码安装MySQL

mysql下载路径 创建新数组 mysql sudo groupadd mysql# 创建用户 mysql ,指定属组为 mysql&#xff0c;禁止其登录 # --no-create-home选项&#xff0c;创建用户时不会自动创建主目录 sudo adduser --system --no-create-home --ingroup mysql --shell /sbin/nologin mysql创…