原创 任意分数分频Verilog实现

2010-10-9 08:13 5427 0 5 分类: FPGA/CPLD

任意分数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)


        begin


        ina<=0;


        inb<=0;


        end


    else


        begin


        ina<=clkin;


        inb<=ina;


        end


    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


        else


            begin


            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


 


在此附上仿真波形


文章评论5条评论)

登录后参与讨论

billzhu_345737527 2013-1-9 17:56

您好,我用你这个程序没有输出波形,能麻烦你把你的程序发给我么,我的邮箱是hrbs@qq.com,谢谢!

firewithin 2010-10-20 21:58

做这个之间看过《基于FPGA的小数分频器的实现》

xkun 2010-10-20 17:41

不知道你是参考那篇论文做的? 《基于FPGA的小数分频器的实现》?

firewithin 2010-10-19 21:46

对不起,一不小心点错了,点成删除评论了。程序里clk是fpga的工作频率,clkin为输入频率。clk应该可以根据需要删去。本人在编此程序时,主要是项目所需,前级有QEP解码输出一个脉冲clkin,要将此脉冲分频。为了只有一个时钟域,工程里全以clk为基准。

lizhenjian163_783085159 2010-10-19 16:32

您好: clk,clkin有什么联系?? 为什么要用2个输入时钟?? 一般工程时一个输入时钟。 我的邮箱是wxkhappy@163.com
相关推荐阅读
firewithin 2011-01-19 17:05
stm32使用fsmc时地址移位问题
stm32平台使用fsmc时,当操作数据宽度为8位时,HADDR【25:0】与FSMC【25:0】对齐,当操作的数据为16位时,HADDR【25:1】与FSMC【24:0】对齐,HADDR【0】未接。...
firewithin 2011-01-05 19:42
verilog分频
fpga程序里经常会遇见给一个50 MHZ的clk,然后产生一个可变频率的clk‘。尤其是在电机控制中,加减速需要便频率,而fpga中除法又比较耗资源。今天看到一个程序,觉得思想不错,整理如下。   ...
firewithin 2011-01-01 23:47
2011,回顾从前
毕业第一年。    2010很快过去了,大学生活也已经成了历史,貌似很近,又貌似很远。    2011已经来临,是时候该回顾回顾自己大学至今都在做什么了。俗话说,男的把电脑当游戏机,女的把电脑当影碟机...
firewithin 2010-12-24 11:33
sdram verilog程序
sdram芯片用的是hy57v641620hgt-7,fpga用的是EP1C6Q240C8,晶振是50M,经过PLL倍频至125M,系统clk时钟是125M,sdram时钟相移-3ns程序是根据特权的...
firewithin 2010-12-24 11:26
串口verilog程序
发一个自己写的串口程序,波特率115200,一位起始位,8个数据位,一个停止位接收采用8倍过采样。下面有4个module,uart是顶层模块,uart_rx是接收模块,uart_tx是发送模块,uar...
firewithin 2010-11-27 18:58
tft verilog驱动
       使用的TFT为群创7寸液晶屏AT070TN83,分辨率为800*480FPGA为ep1c6q240c8,晶振为50M       首先介绍一下TFT接口       1和2脚VLED,4...
广告
我要评论
5
0
广告
关闭 热点推荐上一条 /3 下一条