logo资料库

FPGA分数分频程序.doc

第1页 / 共7页
第2页 / 共7页
第3页 / 共7页
第4页 / 共7页
第5页 / 共7页
第6页 / 共7页
第7页 / 共7页
资料共7页,全文预览结束
任意分数 Verilog 实现 网上常见的多为小数分频,分数分频也为有规律的分频,如 N/2、 M-1/N 等。而像 M/N 型分数分频却很少。现介绍一下本人的分数分频实现方法, 如果不当之处敬请指教。 分数分频实现基本上都是靠吞脉冲方法实现,如 5/2 分频,就可 以分成一个 2 分频,一个 3 分频接替出现,这样(2+3)/2 就是 5/2 分频。 下面以 68/9 为例介绍下怎么计算。 68=9*7+5,即商为 7,余数为 5。可以推出 68/9 分频,可以看成 5 个 8 分频和 4 个 7 分频,即(5*8+4*7)/9=68/9。这个 7 分频和 8 分频中的数 字 7 和 8 就是从商中得出来的。那 5 个 8 分频和 4 个 7 分频中的数字 5 和 4 就是 从余数中的出来的,5 是余数,4 是(9-5)。 分 子 : numerator 。 分 母 denominator 。 商 quotient 。 余 数 remainder。(翻译不是很准确,表达下意思就行了,呵呵)。 numerator=quotient*denominator+remainder.那么 numerator/ denominator 分频就可以通过 remainder 个(quotient+1)分频和(denominator -remainder)个 quotient 分频组成。 还是以 68/9 为例。我们得出了 5 个 8 分频和 4 个 7 分频可以实现 这个分数分频,但这 5 个 8 分频和 4 个 7 分频怎么放置呢? 先放 5 个 8 分频,再放 4 个 7 分频,这样绝对是不行的。为了均 匀的放置这两种频率,我从小数分频中学到一种方法。找个临时变量 temp(程 序中用的是 sum)。初始化为 0。每次分频完让它加上余数,判断是否大于分母, 如果小于分母,择输出 7 分频,否则输出 8 分频,并且将这个值减去分母(让它 小于分母)。这样 temp 值就变成了 5 1 6 2 7 3 8 4 0 5…… 分频值就成了 7 8 7 8 7 8 7 8 8 7 8 7 8 7 8 7 8 8……可以统计一下 7 分频 和 8 分频的比例就正好是 4:5,这样就实现了分数分频。 程序如下所示: 输入信号:clk,rst,clkin(要分频的时钟信号),numerator(分子), denominator, (分母) 输出信号:pulse 中间信号:quotient(商),remainder(余数)等 hightime 为输出信号 pulse 输出高电平时间,可控制占空比
/************************************************* //module name:fredivAB //designer:kang //date:2010-10-08 //version:1.00 *************************************************/ module fredivAB( //input signals clk, rst, clkin, numerator, //fenzi denominator, //fenmu //output signals pulse ); input clk; input rst; input clkin;
input [15:0] numerator; input [15:0] denominator; output pulse; reg pulse; //parameter HIGHTIME=16'd2; wire [15:0] quotient; //shang wire [15:0] remainder; //yushu reg ina; reg inb; reg upclk; reg counter_clkin; reg [15:0] counter; reg [15:0] divnum; reg [15:0] sum; reg flag; reg [15:0] counter_pulseh; wire [15:0] hightime; assign quotient=(denominator)?numerator/denominator:16'h0; assign remainder=(denominator)?numerator%denominator:16'h0; assign hightime={1'b0,quotient[15:1]};
//assign hightime=16'h1; //save the prior and current state of clkin always @(posedge clk or negedge rst) begin if(!rst) else end begin ina<=0; inb<=0; end begin ina<=clkin; inb<=ina; end //check posedge pf clkin always @(posedge clk or negedge rst) begin if(!rst) upclk<=0; else if(!inb&ina) upclk<=1'b1; else upclk<=0; end
//fre div counter always @(posedge clk or negedge rst) begin if(!rst) begin counter<=0; end else if(counter==divnum) counter<=16'h0; else if(upclk) counter<=counter+1'b1; else counter<=counter; end always @(posedge clk or negedge rst) begin if(!rst) begin sum<=0; flag<=0; end else if(counter==divnum) begin if((sum+remainder)>=denominator) //fenmu begin
sum<=sum+remainder-denominator; flag<=1; end begin else sum<=sum+remainder; flag<=0; end end end always @(posedge clk or negedge rst) if(!rst) divnum<=0; else if(flag) divnum<=quotient+1'b1; else divnum<=quotient; //counter_plush always @(posedge clk or negedge rst) begin if(!rst) counter_pulseh<=hightime+16'h1; else if((counter==divnum)&&divnum) counter_pulseh<=0; else if(upclk) counter_pulseh<=counter_pulseh+1'b1; end
//pulse produce always @(posedge clk or negedge rst) if(!rst) pulse<=1'b0; else if(counter_pulseh<=(hightime-1)) pulse<=1'b1; else pulse<=1'b0; endmodule 在此附上仿真波形
分享到:
收藏