前言
学习说明此文档为本人的学习笔记,注重实践,关于理论部分会给出相应的学习链接。
学习视频:是根据野火FPGA视频教程——第十四讲
https://www.bilibili.com/video/BV1nQ4y1Z7zN?p=3
理论学习
时钟是数字电路中的基本单元,通常一个板子上只有一个经侦,即只有一种频率的时钟。因此在用到不同时钟时就需要进行分频(时钟频率更慢),倍频(时钟频率更快)。
有两种方式可以选择:一种时锁相环(PLL);另一种时自己动手Verilog代码描述
在Verilog代码描述形成的分频电路,即分频器。所谓“分频”,就是把输入信号的频率变成倍数地低于输入频率的输出信号。分频可以通过计数器来实现,如十进制计数器就是十分频。
实战演练一 偶分频
一、设计规划
1.1 实验目标
设计对系统时钟进行6分频
1.2 硬件资源
这里使用的是野火升腾mini开发板 A7 35T,拓展IO口K21进行时钟输出。
二、程序设计
2.1 模块框图及波形图
以上虽然产生了占空比50%的6分频的时钟,但是在高速电路中会有问题:
为解决以上问题:标志位1/6占空比的6分频器
这里使用flge标志信号,用于标记6分频的clk_flge标志信号,每两个clk_flge脉冲之间的频率就是对sys_clk时钟信号的6分频,相应的技术器也应增加。
2.2 代码编写
//50%占空比分频方式
//使用方式:遇到clk_out的上升沿a+1;
//问题:由于clk_out的上升沿并不是系统时钟,并未链接到时钟树上,导致高速电路中有问题
//解决:不使用上升沿作为时钟变化的判断,通过电平方式
module divider_six(
input wire sys_clk,
input wire sys_rst_n,
output reg clk_flag
);
parameter COUNT_MAX = 3'd4;
reg [1:0] count; //计数寄存器变量
reg a;
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
count <= 0;
else if(count == COUNT_MAX)
count <= 1'b0;
else
count <= count + 1;
/* //分频方法实现——50%占空比, COUNT_MAX = 2'd2;进行一次翻转
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
clk_out <= 1'b0;
else if(count == COUNT_MAX)
clk_out <= ~clk_out;
else
clk_out <= clk_out;
//使用方式:遇到clk_out的上升沿a+1;
//问题:由于clk_out的上升沿并不是系统时钟,并未链接到时钟树上,导致高速电路中有问题
//解决:不使用上升沿作为时钟变化的判断,通过电平方式
always @(posedge clk_out or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
a <= 1'b0;
else
a <= a + 1'b1; */
//降频方法实现——1/6占空比, COUNT_MAX = 3'd4;在4-5期间保持一时钟周期的高电平
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
clk_flag <= 0;
else if(count == COUNT_MAX)
clk_flag <= 1'b1;
else
clk_flag <= 1'b0;
/* //使用方式:遇到clk_flag的高电平;
//将clk_flag的电平作为触发条件,clk_flag具有系统时钟相同的性质,电平变化条件依然是sys_clk
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
a <= 1'b0;
else if(clk_flag)
a <= a+1'b0; */
endmodule
RTL视图:与计数器相同
降频方式
三、逻辑仿真
3.1 仿真文件的编写
`timescale 1ns / 1ns
///
// Company: 追逐者——桥的小作坊
// Create Date: 2022/05/08 10:02:20
// Design Name: 分频器——偶分频(6分频)
// Module Name: tb_divider_six
/
module tb_divider_six();
reg SYS_CLK ;
reg SYS_RST_N;
wire CLK_OUT ;
//变量初始化
initial begin
SYS_CLK = 1'b0;
SYS_RST_N <= 1'b0;
#20
SYS_RST_N <= 1'b1;
end
always #10 SYS_CLK = ~SYS_CLK;
//模块实例化
divider_six divider_six_inst(
.sys_clk (SYS_CLK ),
.sys_rst_n(SYS_RST_N),
.clk_out (CLK_OUT )
);
endmodule
3.2 仿真波形图对比
由上图可以看出在,达到了6分频的效果,和绘制的波形图相同。
实战演练二 奇分频
一、设计规划
1.1 实验目标
设计对系统时钟进行5分频的奇分频。
1.2 硬件资源
这里使用的是野火升腾mini开发板 A7 35T,拓展IO口K21进行时钟输出。
二、程序设计
2.1 模块框图及波形图
2.2 代码编写
module divider_five(
input wire sys_clk ,
input wire sys_rst_n ,
output wire clk_out
);
reg [2:0] cnt;
reg clk1, clk2;
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_clk == 1'b0)
cnt <= 3'd0;
else if(cnt == 3'd4)
cnt <= 3'd0;
else
cnt <= cnt + 3'd1;
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
clk1 <= 1'b0;
else if(cnt == 3'd2)
clk1 <= 1'b1;
else if(cnt == 3'd4)
clk1 <= 1'b0;
else
clk1 <= clk1;
always @(negedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
clk2 <= 1'b0;
else if(cnt == 3'd2)
clk2 <= 1'b1;
else if(cnt == 3'd4)
clk2 <= 1'b0;
else
clk2 <= clk2;
//使用组合逻辑电路进行赋值,这样时钟就不会延长一个周期
assign clk_out = (clk1 | clk2);
endmodule
RTL视图
三、逻辑仿真
3.1 仿真文件的编写
`timescale 1ns / 1ns
///
// Company: 追逐者——桥的小作坊
// Create Date: 2022/05/08 10:02:20
// Design Name: 分频器——奇分频(5分频)
// Module Name: tb_divider_five
/
module tb_divider_five();
reg SYS_CLK ;
reg SYS_RST_N;
wire CLK_OUT ;
//变量初始化
initial begin
SYS_CLK = 1'b0;
SYS_RST_N <= 1'b0;
#20
SYS_RST_N <= 1'b1;
end
always #10 SYS_CLK = ~SYS_CLK;
//模块实例化
divider_five divider_five_inst(
.sys_clk (SYS_CLK ),
.sys_rst_n(SYS_RST_N),
.clk_out (CLK_OUT )
);
endmodule
3.2 仿真波形图对比
四、上板验证
4.1 管脚绑定