文章来源: FPGA入门到精通
FPGA分频器是一种常用于数字信号处理、通信系统、雷达系统等领域的电路,其作用是将信号分成多个频段。在FPGA设计中,分频器是不可或缺的组成部分之一,通过对信号进行分频,可以方便地对不同频段进行处理和传输。本文将详细介绍FPGA分频器的设计方法,并附上Verilog代码示例,以供参考。
一、分频器定义
分频器是通过控制时钟信号的周期来实现分频。在实际应用中,FPGA时钟信号的产生有两种方法:使用PLL(Phase Locked Loop,锁相环)或MMCM(Mixed-Mode Clock Manager)生成倍频、分频信号,或者是使用Verilog构建分频电路。其中常用的是直接调用“PLL或MMCM”IP生成时钟信号,本文暂不介绍IP类,有有待后续IP系列更新。
分频器通常由两个部分组成:计数器和比较器。计数器用于计数,每计数到一定的值就会触发比较器,比较器会向输出引脚发出0或1的信号。这样就实现了对时钟信号的分频。
分频器一般可以分为3类:偶数分频、奇数分频、小数分频。
二、偶数分频
1、设计方法
2分频时钟设计,只需要循环计数0~1,计数为0时输出低电平,计数为1时输出高电平。
4分频时钟设计,只需要循环计数0~3,计数为0和1时输出低电平,计数为2和3时输出高电平。
8分频时钟设计,只需要循环计数0~7,计数为0~3时输出低电平,计数为4~7时输出高电平。
下图分别画出了基准时钟、2分频时钟、4分频时钟、8分频时钟。
由此可以推导出,偶数分频设计的方法:设为2N分频,只需设计一个计数器在上升沿时循环计数0~N-1,每隔0~N-1时输出翻转一次。
2、verilog代码实现
任意偶数分频设计,可通过设置参数NUM,设定分频数,具体代码如下所示:
module clk_divider_even#( parameter NUM = 8 )( input clk, input rst, output reg clk_o ); //参数定义 localparam WIDTH = $clog2(NUM); localparam CNT_END = NUM/2 - 1; reg [WIDTH-1:0] cnt; //计数模块 always@(posedge clk or posedge rst)begin if(rst) cnt <= 'b0; else if(cnt == CNT_END) //计满则清零 cnt <= 'b0; else cnt <= cnt + 1'b1; end //分频时钟输出模块 always@(posedge clk or posedge rst)begin if(rst) clk_o <= 1'b0; else if(cnt == CNT_END) //计满则输出反转 clk_o <= ~clk_o; else clk_o<= clk_o; end endmodule
从图中看出,输出了8分频时钟信号,与预期一致。
三、奇数分频
1、设计方法
3分频时钟设计,只需要在上升沿时循环计数0~2,上升沿计数时钟信号和下降沿计数时钟信号,都是前1个周期为低电平,后2个周期为高电平;
5分频时钟设计,只需要在上升沿时循环计数0~4,上升沿计数时钟信号和下降沿计数时钟信号,都是前2个周期为低电平,后3个周期为高电平;
7分频时钟设计,只需要在上升沿时循环计数0~6,上升沿计数时钟信号和下降沿计数时钟信号,都是前3个周期为低电平,后4个周期为高电平;
下图分别画出了基准时钟、3分频时钟、5分频时钟、7分频时钟。
由此可以推导出,奇数分频设计的方法:设为2N+1分频,只需设计一个计数器在上升沿时循环计数0~2N,上升沿计数时钟信号和下降沿计数时钟信号,都是前N个周期为低电平,后N+1个周期为高电平;
2、verilog代码实现
任意偶数分频设计,可通过设置参数NUM,设定分频数,具体代码如下所示:
module clk_divider_odd#( parameter NUM = 7 )( input clk, input rst, output wire clk_o ); //参数定义 localparam WIDTH = $clog2(NUM); localparam CNT_END = NUM - 1; localparam CNT_END0 = NUM/2 - 1; reg [WIDTH-1:0] cnt; reg clk_pos, clk_neg; //计数模块 always@(posedge clk or posedge rst)begin if(rst) cnt <= 'b0; else if(cnt == CNT_END) //计满则清零 cnt <= 'b0; else cnt <= cnt + 1'b1; end //分频时钟输出模块,时钟上升沿 always@(posedge clk or posedge rst)begin if(rst) clk_pos <= 1'b0; else if(cnt == CNT_END0) clk_pos <= 1'b1; else if(cnt == CNT_END ) clk_pos <= 1'b0; else clk_pos <= clk_pos; end //分频时钟输出模块,时钟下降沿 always@(negedge clk or posedge rst)begin if(rst) clk_neg <= 1'b0; else if(cnt == CNT_END0) clk_neg <= 1'b1; else if(cnt == CNT_END) clk_neg <= 1'b0; else clk_neg <= clk_neg; end //输出时钟 assign clk_o = clk_pos && clk_neg; endmodule
仿真结果如下图:
从图中看出,输出了7分频时钟信号,与预期一致。
四、总结
本文分享了“偶数分频和奇数分频”的原理和实现方法,实际应用中一般使用PLL或MMCM IP来实现分频输出。