奇数偶数分频
占空比为50%的分频
偶数分频比较简单
比如N分频,那么计数到N/2-1,然后时钟翻转,代码如下:
module even(clk_in,clk_out,rst_n); input clk_in; input rst_n; output clk_out; parameter N=6; reg [3:0] cnt; reg clk_out; always @(posedge clk_in or negedge rst_n) begin if(!rst_n) begin cnt<=4'b0000; clk_out<=0; end else if(cnt==(N/2-1)) begin clk_out<=~clk_out; cnt<=4'b0000; end else cnt<=cnt+1; end endmodule
实现奇数分频,分别用上升沿计数到(N-1)/2-1,再计数到N-1,再用下降沿计数到(N-1)/2-1,再计数到N-1,,得到两个波形,然后相或即可 代码如下:
module div3(clk,clk_out,rst_n); input clk,rst_n; output clk_out; reg [3:0] cnt_p,cnt_n; reg clk_p,clk_n; parameter N=5; always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt_p<=4'h0; else if(cnt_p==N-1) cnt_p<=0; else cnt_p<=cnt_p+1; end always @(negedge clk or negedge rst_n) begin if(!rst_n) cnt_n<=4'h0; else if(cnt_n==N-1) cnt_n<=0; else cnt_n<=cnt_n+1; end always @(posedge clk or negedge rst_n) begin if(!rst_n) clk_p<=1; else if(cnt_p==(N-1)/2-1) clk_p<=~clk_p; else if(cnt_p==(N-1)) clk_p<=~clk_p; end always @(negedge clk or negedge rst_n) begin if(!rst_n) clk_n<=1; else if(cnt_n==(N-1)/2-1) clk_n<=~clk_n; else if(cnt_n==(N-1)) clk_n<=~clk_n; end assign clk_out=clk_n|clk_p; endmodule
一、为啥要说任意分频
也许FPGA中的第一个实验应该是分频实验,而不是流水灯,或者LCD1602的"Hello World"显示,因为分频的思想在FPGA中极为重要。当初安排流水灯,只是为了能让大家看到效果,来激发您的兴趣(MCU的学习也是如此)。
在大部分的教科书中,都会提到如何分频,包括奇数分频,偶数分频,小数分频等。有些教科书中也会讲到任意分频(半分频,任意分数分频)原理,用的是相位与的电路,并不能办到50%的占空比,也不是很灵活。
但没有一本教科书会讲到精准,浅显易懂的高精度任意分频原理(至少Bingo没看到过),同时也没有一种设计能用同一个电路实现任意频率的控制。Bingo对于当年做的任意波形发生器时候的相位累加器原理,从中受到启发,总结出高精度任意频率合成的重要思维,在此贡献给大家,希望对大家有用。
二、任意分频原理以及性能
1. DDS相位累加器
(1)DDS合成流程
首先讲诉DSS(直接频率合成法)的原理。
DDS是重要的频率合成方法,在波形发生器中有极其重要的应用。DDS主要由以下几部分组成:
a) 相位累加器
b) RAM数据读取
c) D/A转换器
d) 低通滤波器
见如下流程图:直接频率合成法的流程图,有固定模块,输入频率控制器,输出固定频率的波形。
此电路最主要模块是相位累加器,通过相位累加器循环计数,循环读取RAM的数据,从而得到固定频率的波形数据。
(2)相位累加器原理
相位累加原理流程如上所示:
输入频率控制字,根据算法,来实现相位的变化,分析如下所示:
假定FPGA基准频率为50MHz,即基准频率:
K为频率控制字,则相位输出的频率为:
即
根据相位累加原理,以及RAM缓存读取数据,每一次的循环,RAM数据间隔K读取一次。
当K=1的时候,公式能输出最小频率,根据公式(1):
所以,最小波形频率步进为0.011655Hz。
当fo=1Hz的时候,根据公式(2)
所以,每Hz的增减,K的步进为85.90。
当K=N/2的时候,公式能输出最大频率(因为每个CLK跳变一次),此时,根据公式(1),得到:
因此,根据频率控制字K的变化,能输出及固定频率的波形。
2. 任意频率分频原理
在FPGA中某些应用场合,对频率要求比较高的情况下,用相位累加器原理来生成固定频率的方法,未尝不可。
我们规定,对Cnt进行对半50%拆分,具体如下:
同上:
在FPGA中应用,Verilog代码如下所示:
/*************************************************** * Module Name : clk_generator * Engineer : Crazy Bingo * Target Device : EP2C8Q208C8 * Tool versions : Quartus II 9.1SP1 * Create Date : 2011-6-25 * Revision : v1.0 * Description : **************************************************/ /************************************************* fc = 50MHz 50*10^6 fo = fc*K/(2^32) K = fo*(2^32)/fc = fo*(2^32)/(50*10^6) **************************************************/ module clk_generator # ( parameter FREQ_WORD = 32'd8590 //1KHz ) ( input clk, //50MHz input rst_n, //clock reset output reg clk_out ); //-------------------------------------- reg [31:0] max_value; always@(posedge clk or negedge rst_n) begin if(!rst_n) max_value <= 1'b0; else max_value <= max_value + FREQ_WORD; end //-------------------------------------- always@(posedge clk or negedge rst_n) begin if(!rst_n) clk_out <= 1'b0; else begin if(max_value < 32'h7FFF_FFFF) clk_out <= 1'b0; else clk_out <= 1'b1; end end endmodule
本代码由Bingo从DDS相位累加器中,相应移植总结出来的任意频率分频原理,本模块应用在多个对频率精准度要求比较高的工程中(如UART中,要得到115200Hz的bps,用这种任意分频的原理来得到精准的方法,一定程度上能够提高数据传输的准确率)。
在DDS中的相位累加器的任意分频原理,在一般工程中同样可以应用。在某些应用场合,还是值得考虑的。本应用纯属Bingo个人主观应用,如有异议,请联系本人。