热度 25
2013-8-14 10:51
5634 次阅读|
5 个评论
1、半整数分频占空比不为50% //说明:设计的史上最好用的半整数分频占空比不为50%,包含设计思路 module div_5(clk,clk_div,cnt1,cnt2,temp1,temp2);//N+0.5 input clk; output clk_div; output reg cnt1,cnt2; output reg temp1,temp2; initial begin temp1=0;temp2=1;end //首先进行初始化,temp1=0;temp2=1 parameter N=5; //设定分频系数为N+0.5 always @(posedge clk) //temp1上升沿跳变 begin if(cnt1==2*N) //2*N begin cnt1 =32'd0;end else begin cnt1 =cnt1 +32'd1;end if(cnt1==32'd0) begin temp1=1;end //高电平时间为N+1; if(cnt1==N+1) begin temp1=0;end //低电平时间为N; end always@(negedge clk) //temp2下降沿跳变 begin if(cnt2==2*N) //2*N begin cnt2 =32'd0;end else begin cnt2 =cnt2 +32'd1;end if(cnt2==32'd0) begin temp2=0;end //低电平时间为N; if(cnt2==N) begin temp2=1;end //高电平时间为N+1; end assign clk_div=temp1temp2; //逻辑与 endmodule //如果要进行N+0.5分频 //思路:总的来说要进行N+1+N=2N+1次分频 //在时钟的上升沿和下降沿都进行跳变 //上升沿进行占空比为N+1比N的时钟temp1; //下降沿进行占空比为N比N+1的时钟temp2; //最后div=temp1temp2 即可得到所需要的半整数分频 分频5.5仿真结果 2、奇数分频占空比为50% //说明:奇数分频。 module div_5(clk,clk_div,cnt1,cnt2,temp1,temp2);// input clk; output clk_div; output reg cnt1,cnt2; output reg temp1,temp2; parameter N=5; //设定分频系数 always @(posedge clk) begin if(cnt1==N-1) //N-1进行N计数 begin cnt1 =32'd0;end else begin cnt1 =cnt1 +32'd1;end if(cnt1==32'd0) begin temp1=1;end // if(cnt1==(N-1)/2) begin temp1=0;end //当计数到(N-1)/2时翻转 end always@(negedge clk) begin if(cnt2==N-1) //N-1 begin cnt2 =32'd0;end else begin cnt2 =cnt2 +32'd1;end if(cnt2==32'd0) begin temp2=1;end //; if(cnt2==(N-1)/2) begin temp2=0;end //当计数到(N-1)/2时翻转; end assign clk_div=temp1||temp2; //逻辑或 endmodule 3任意小数分频 分数分频实现基本上都是靠吞脉冲方法实现,如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 numerator; input denominator; output pulse; reg pulse; //parameter HIGHTIME=16'd2; wire quotient; //shang wire remainder; //yushu reg ina; reg inb; reg upclk; reg counter_clkin; reg counter; reg divnum; reg sum; reg flag; reg counter_pulseh; wire hightime; assign quotient=(denominator)?numerator/denominator:16'h0; assign remainder=(denominator)?numerator%denominator:16'h0; assign hightime={1'b0,quotient }; //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(!inbina) 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