FPGA学习篇——Verilog学习之分频器的实现
PS:目前手上仍然没有板子,按照野火视频的讲解,目前我们只能做到前面六步(其实第一步设计规划也是需要看板子的硬件的,但是现在没有板子就完全与野火传授的板子一致来看)
1 设计规划及波形绘制
1.1 分频器的原理:
分频器就是把输入信号的频率成倍数的降低后再进行输出。
比如说4分频器,就是把输入信号频率降低4倍再输出,可以理解成输入4个周期对应输出1个周期:
同理,12分频器,把输入信号频率降低12倍再输出,即输入12个周期对应输出1个周期。
倍频器原理:与分频器对应的就是倍频器,它是把输入信号的频率成倍数的升高后再进行输出(即即可以理解成N倍频器就是输入1个周期对应输出N个周期)
1.2 分频器的分类:
以倍数的奇偶分成奇分频器(3,5,7,9...)+偶分频器(2,4,6,8...)
1.3 波形绘制
1.3.1偶分频器
以4分频器为例(偶数分频器),按照偶分频器的原理可以看到,输出一个周期等于输入四个周期(图中红色虚线框起来部分),如何实现呢?
还记得我们上一节实现的计数器吗?看计数器的波形图(图1),其实就是一个分频器!输入25000000个周期等于一个输出周期!因此,我们可以仿照这个思想,通过计数来实现分频!调节计数值就可形成对应的分频器!
图1
那么按照上述思想,我们使得计数器取0~3(对应输入四个周期),又因为刚好为偶数,实际计数器取0和1即可,每到1的上升沿翻转一次,得到输出信号,如下图2所示。
图2
1.3.2 奇分频器
同样,我们使用计数的原理来实现奇分频器,但这里有一个问题,以5分频器为例,计数器取0~4(对应输入五个周期),我们要使得输出在2.5周期处翻转一次(这样输出在0~4才能形成一个周期),但我们计数cnt无法记到小数,那该怎么办呢?
这里有两种实现方法:
由图3波形图可以看到,如果在2的上升沿和4的上升沿各翻转一次,得到Out1,输出的周期占空比就不是50%,同样,在2的下降沿和4的下降沿各翻转一次,得到Out2,输出的周期占空比也不是50%
(1)但是!若Out1或上Out2(即Out1 | Out2),就可以得到Out,满足输出占空比50%的周期
(2)或者,直接看Out,使得输出在2的下降沿和4的上升沿各翻转一次,也能得到输出波形
图3
2 代码编写
2.1 偶分频器
module Divider_4(input sys_clk,input sys_rst_n,output reg Out);reg cnt ;always @(posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 0)cnt <= 2'd0;else if(cnt == 2'd1)cnt <= 2'd0;else cnt <= cnt + 1;
endalways @(posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 0)Out <= 1'b0;else if(cnt == 2'd1)Out <= ~Out; else Out <= Out;
endendmodule
2.2 奇分频器
方法(1):
module Divider_5(input sys_clk ,input sys_rst_n ,output Out );
reg [2:0] cnt;
reg Out1;
reg Out2;always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)cnt <= 3'd0; else if(cnt == 3'd4)cnt <= 3'd0;elsecnt <= cnt + 1;
endalways @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)Out1 <= 1'd0;else if(cnt == 3'd2)Out1 <= ~Out1;else if(cnt == 3'd4)Out1 <= ~Out1;else Out1 <= Out1;
endalways @(negedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)Out2 <= 1'd0;else if(cnt == 3'd2)Out2 <= ~Out2;else if(cnt == 3'd4)Out2 <= ~Out2;else Out2 <= Out2; endassign Out = (Out1 | Out2);endmodule
方法(2):
module Divider_5(input sys_clk ,input sys_rst_n ,output reg Out );
reg [2:0] cnt;always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)cnt <= 3'd0; else if(cnt == 3'd4)cnt <= 3'd0;elsecnt <= cnt + 1;
endalways @(negedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)Out <= 1'b0;else if(cnt == 3'd2)Out <= 1'b1;else Out <= Out;
endalways @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)Out <= 1'b0;else if(cnt == 3'd4)Out <= 1'b0;else Out <= Out;
endendmodule
3 逻辑仿真及波形验证
之前我们说到tb文件相当于模拟模块的输入情况,由于这里的4分频(偶数)和5分频(奇数)的输入都只有两个信号,并且情况一样,所以代码完全一致,修改对应的名称即可。
以下代码以5分频的仿真为例:
module tb_Divider_5();reg tb_sys_clk ;
reg tb_sys_rst_n ;wire tb_Out ;initial begintb_sys_clk <= 1'b0;tb_sys_rst_n <= 1'b0;#10tb_sys_rst_n <= 1'b1;
endalways #20 tb_sys_clk <= ~tb_sys_clk;// output declaration of module Divider_5Divider_5 u_Divider_5(.sys_clk (tb_sys_clk ),.sys_rst_n (tb_sys_rst_n ),.Out (tb_Out )
);endmodule
由下列波形图可以看到,仿真验证通过。
(本贴仅是个人经验,参考哔哩哔野火视频:19-第十四讲分频器---偶分频_哔哩哔哩_bilibili20-第十五讲-分频器---奇分频_哔哩哔哩_bilibili如有侵权请联系我~)