FPGA 多路分频器实验

news/2025/2/1 12:03:26/

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)beginif(!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)beginif(!rst_n_i)div_cnt1 <= 2'b00;elsediv_cnt1 <= div_cnt1+1'b1;
endreg div4_o_r;
reg div8_o_r;
always@(posedge clk_i)beginif(!rst_n_i)div4_o_r <= 1'b0;else if(div_cnt1==2'b00 || div_cnt1==2'b10)div4_o_r <= ~div4_o_r;elsediv4_o_r <= div4_o_r;
endalways@(posedge clk_i)beginif(!rst_n_i)div8_o_r <= 1'b0;else if(div_cnt1==2'b00)div8_o_r <= ~div8_o_r;elsediv8_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)beginif(!rst_n_i)pos_cnt <= 2'b00;else if(pos_cnt == 2'd2)pos_cnt <= 2'b00;elsepos_cnt <= pos_cnt + 1'b1;
endalways@(negedge clk_i)beginif(!rst_n_i)	neg_cnt <= 2'b00;else if(neg_cnt == 2'd2)neg_cnt <= 2'b00;elseneg_cnt <= neg_cnt + 1'b1;
endreg div3_o_r0;
reg div3_o_r1;
always@(posedge clk_i)beginif(!rst_n_i)div3_o_r0 <= 1'b0;else if(pos_cnt < 2'd1)div3_o_r0 <= 1'b1;elsediv3_o_r0 <= 1'b0;
endalways@(negedge clk_i)beginif(!rst_n_i)div3_o_r1 <= 1'b0;else if(neg_cnt < 2'd1)	div3_o_r1 <= 1'b1;elsediv3_o_r1 <= 1'b0;
endreg div2hz_o_r;
reg [25:0] div2hz_cnt;wire ms250_en = (div2hz_cnt == REF_CLK/4 - 1'b1);
always@(posedge clk_i)
beginif(!rst_n_i)div2hz_cnt <= 0;else if(div2hz_cnt < REF_CLK/4 - 1'b1)div2hz_cnt <= div2hz_cnt + 1'b1;elsediv2hz_cnt <= 0;
endalways@(posedge clk_i)
beginif(!rst_n_i)div2hz_o_r <= 0;else if(ms250_en)div2hz_o_r <= ~div2hz_o_r;elsediv2hz_o_r <= div2hz_o_r;
endassign 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
endgenerateendmodule	

代码解释:
        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 Inputs4clk_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.ppmy.cn/news/1324740.html

相关文章

Linux的权限(2)

目录 Linux的&#xff08;事物属性&#xff09;文件权限 文件权限值得表示方法 字符表示方法 8进制表示方法 文件访问权限得相关设置方法 chmod修改权限法1 chmod修改权限法2 文件的角色&#xff08;拥有者/所属者&#xff09;修改 chown拥有者 chgrp所属者 &…

rust获取本地ip地址的方法

大家好&#xff0c;我是get_local_info作者带剑书生&#xff0c;这里用一篇文章讲解get_local_info的使用。 get_local_info是什么&#xff1f; get_local_info是一个获取linux系统信息的rust三方库&#xff0c;并提供一些常用功能&#xff0c;目前版本0.2.4。详细介绍地址&a…

REVIT二次开发生成三维轴网

步骤1 确定轴网 步骤2 生成3D轴网 using System; using System.Collections.Generic; using System.Linq; using System.Text;

#vue3 实现前端下载excel文件模板功能

一、需求&#xff1a; 前端无需通过后端接口&#xff0c;即可实现模板下载功能。 通过构造一个 JSON 对象&#xff0c;使用前端常用的第三方库 xlsx&#xff0c;可以直接将该 JSON 对象转换成 Excel 文件&#xff0c;让用户下载模板 二、效果&#xff1a; 三、源码如下&…

自学(网络安全)黑客——高效学习2024

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

新数智空间:阿里云边缘云持续保持中国公有云市场第一

全球领先的 IT 市场研究和咨询公司 IDC 发布 《中国边缘云市场解读&#xff08;2023H1&#xff09;》报告 中国边缘公有云服务市场 阿里云持续第一 稳居市场第一&#xff0c;“边缘”逆势生长 近日&#xff0c;全球领先的 IT 市场研究和咨询公司 IDC 最新发布《中国边缘云市…

VirtualBox安装openSUSE-Leap-15.5虚拟机并配置网络

VirtualBox安装openSUSE-Leap-15.5虚拟机并配置网络 适用于在VirtualBox平台上安装openSUSE-Leap-15.5虚拟机。 1. 安装准备 1.1 安装平台 Windows 11 1.2. 软件信息 软件名称软件版本安装路径Oracle VM VirtualBoxVirtualBox-7.0.12-159484D:\softwareopenSUSE-Leapopen…

Java-初识正则表达式 以及 练习

目录 什么是正则表达式&#xff1f; 1. 正则表达式---字符类&#xff08;一个大括号匹配一个字符&#xff09;&#xff1a; 2. 正则表达式---预字符类&#xff08;也是匹配一个字符&#xff09;&#xff1a; 正则表达式---数量词 &#xff08;可以匹配多个字符&#xff09;…