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) begin
if(sys_rst_n == 0)
cnt <= 2'd0;
else if(cnt == 2'd1)
cnt <= 2'd0;
else
cnt <= cnt + 1;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 0)
Out <= 1'b0;
else if(cnt == 2'd1)
Out <= ~Out;
else
Out <= Out;
end
endmodule
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) begin
if(!sys_rst_n)
cnt <= 3'd0;
else if(cnt == 3'd4)
cnt <= 3'd0;
else
cnt <= cnt + 1;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
Out1 <= 1'd0;
else if(cnt == 3'd2)
Out1 <= ~Out1;
else if(cnt == 3'd4)
Out1 <= ~Out1;
else
Out1 <= Out1;
end
always @(negedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
Out2 <= 1'd0;
else if(cnt == 3'd2)
Out2 <= ~Out2;
else if(cnt == 3'd4)
Out2 <= ~Out2;
else
Out2 <= Out2;
end
assign 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) begin
if(!sys_rst_n)
cnt <= 3'd0;
else if(cnt == 3'd4)
cnt <= 3'd0;
else
cnt <= cnt + 1;
end
always @(negedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
Out <= 1'b0;
else if(cnt == 3'd2)
Out <= 1'b1;
else
Out <= Out;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
Out <= 1'b0;
else if(cnt == 3'd4)
Out <= 1'b0;
else
Out <= Out;
end
endmodule
3 逻辑仿真及波形验证
之前我们说到tb文件相当于模拟模块的输入情况,**由于这里的4分频(偶数)和5分频(奇数)的输入都只有两个信号,并且情况一样,所以代码完全一致,**修改对应的名称即可。
以下代码以5分频的仿真为例:
module tb_Divider_5();
reg tb_sys_clk ;
reg tb_sys_rst_n ;
wire tb_Out ;
initial begin
tb_sys_clk <= 1'b0;
tb_sys_rst_n <= 1'b0;
#10
tb_sys_rst_n <= 1'b1;
end
always #20 tb_sys_clk <= ~tb_sys_clk;
// output declaration of module Divider_5
Divider_5 u_Divider_5(
.sys_clk (tb_sys_clk ),
.sys_rst_n (tb_sys_rst_n ),
.Out (tb_Out )
);
endmodule
由下列波形图可以看到,仿真验证通过。

(本贴仅是个人经验,参考哔哩哔野火视频: 19-第十四讲分频器---偶分频_哔哩哔哩_bilibili20-第十五讲-分频器---奇分频_哔哩哔哩_bilibili如有侵权请联系我~)