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) 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如有侵权请联系我~)

相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
ZPC82103 天前
docker 镜像备份
人工智能·算法·fpga开发·机器人
ZPC82103 天前
docker 使用GUI ROS2
人工智能·算法·fpga开发·机器人
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛3 天前
计算机系统概论——校验码
学习
babe小鑫3 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms3 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下3 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。3 天前
2026.2.25监控学习
学习