Verilog实现任意占空比任意分频的方法.docx
- 文档编号:26610660
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:14
- 大小:42.86KB
Verilog实现任意占空比任意分频的方法.docx
《Verilog实现任意占空比任意分频的方法.docx》由会员分享,可在线阅读,更多相关《Verilog实现任意占空比任意分频的方法.docx(14页珍藏版)》请在冰豆网上搜索。
Verilog实现任意占空比任意分频的方法
Verilog-实现任意占空比、任意分频的方法
分频程序虽然简单,但我觉得由简入难是学习的一个必然阶段,慢慢的我们自然会成长起来。
所以如果有时间的话,大家都可以将自己的这种“小程序”贴到论坛上来。
如果你的程序好,其他人也可以学习;如果你的程序有问题,大家可以一起帮你找问题,共同进步。
还有,我觉得在发贴的时候,最好能将原理说一下。
一来大家看你的贴能学到东西;二来也方便解答你的问题,不然还得解答者自己去找资料搞懂原理,然后再回答你,回答你问题的人自然也就不多了。
说了一些题外话,下面转入正文:
在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求这样的话,对于程序有一定的要求,现在我在前人经验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。
比如:
我们FPGA系统时钟是50MHz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。
我们很容易想到用计数的方式来分频:
50000000/880=56818
这个数字不是2的整幂次方,那么怎么办呢?
我们可以设定一个参数,让它到56818的时候重新计数不就完了吗?
呵呵,程序如下:
modulediv(clk,clk_div);
inputclk;
outputclk_div;
reg[15:
0]counter;
always@(posedgeclk)
if(counter==56817)counter<=0;
elsecounter<=counter+1;
assignclk_div=counter[15];
endmodule
//
modulediv(clk,rst,clk_div);
inputclk,rst;
outputregclk_div;
reg[15:
0]counter;s
always@(posedgeclk)
继续让我们来看如何实现任意占空比,比如还是由50M分频产生880Hz,而分频得到的信号的占空比为30%。
56818×30%=17045
modulediv(clk,reset,clk_div,counter);
inputclk,reset;
outputclk_div;
output[15:
0]counter;
reg[15:
0]counter;
regclk_div;
always@(posedgeclk)
if(!
reset)counter<=0;
elseif(counter==56817)counter<=0;
elsecounter<=counter+1;
always@(posedgeclk)
if(!
reset)clk_div<=0;
elseif(counter<17045)clk_div<=1;
elseclk_div<=0;
endmodule
三分频的Verilog实现
//很实用也是笔试面试时常考的,已经经过仿真
占空比要求50%和不要求占空比差别会很大,先看一个占空比50%的描述
modulediv3(CLKIN,CLKOUT,RESETn);
inputCLKIN,RESETn;
outputCLKOUT;
//internalcountersignals
reg[1:
0]count_a;
reg[1:
0]count_b;
reg CLKOUT;
always@(negedgeRESETnorposedgeCLKIN)
begin
if(RESETn==1'b0)
count_a<=2'b00;
else
if(count_a==2'b10)
count_a<=2'b00;
else
count_a<=count_a+1;
end
always@(negedgeRESETnornegedgeCLKIN)
begin
if(RESETn==1'b0)
count_b<=2'b0;
else
if(count_b==2'b10)
count_b<=2'b00;
else
count_b<=count_b+1;
end
always@(count_aorcount_borRESETn)
begin
if(RESETn==1'b0)
CLKOUT=1'b0;
elseif((count_a+count_b==4)||(count_a+count_b==1))
CLKOUT=~CLKOUT;
end
endmodule
0 1 2 0 1 2
\ / / \ \ / / \
0 1 2 0 1 2
下面是一个非50%的描述,只用了上升沿
modulediv3(CLKIN,CLKOUT,RESETn);
inputCLKIN,RESETn;
outputCLKOUT;
wired;
reg q1,q2;
wire CLKOUT;
always@(negedgeRESETnorposedgeCLKIN)
begin
if(RESETn==1'b0)
q1<=1'b0;
else
q1<=d;
end
always@(negedgeRESETnorposedgeCLKIN)
begin
if(RESETn==1'b0)
q2<=1'b0;
else
q2<=q1;
end
assignd=~q1&~q2;
assignCLKOUT=q2;
endmodule
占空比不是50%,只用了单沿触发器,寄存器输出。
至于其他奇数要求50%的或者不要求的占空比的,都可以参照上面两个例子做出。
占空比为50%的一个更好的实现。
modulediv3(CLKIN,CLKOUT,RESETn);
inputCLKIN,RESETn;
outputCLKOUT;
//internalcountersignals
reg[1:
0]count_a;
reg b,c;
//reg CLKOUT;
wireCLKOUT;
always@(negedgeRESETnorposedgeCLKIN)
begin
if(RESETn==1'b0)
count_a<=2'b00;
else
if(count_a==2'b10)
count_a<=2'b00;
else
count_a<=count_a+1;
end
always@(negedgeRESETnornegedgeCLKIN)
begin
if(RESETn==1'b0)
b<=1'b0;
else
if(count_a==2'b01)
b<=2'b0;
else
b<=1'b1;
end
always@(negedgeRESETnorposedgeCLKIN)
begin
if(RESETn==1'b0)
c<=1'b0;
else
if(count_a==2'b10)
c<=1'b1;
elseif(count_a==2'b01)
c<=1'b0;
end
assign CLKOUT=b&c;
endmodule
时钟选择器的Verilog写法!
CPRI有3种数据时钟,61.44M122.88M245.76M,需要模块能够根据外部的速率指示信号(一个2位的输入信号,由模块外部给定)选择其中的一种时钟作为模块的工作时钟
但由于所选用的FPGA工作频率关系,不能超过400M,无法通过寄存器方式实现时钟源的选择.
使用双边触发的方式将最高的频率进行分频,代码如下,已经通过ModelSim的仿真,可以实现。
moduleclk_div(
reset, //复位信号
data_rate, //数据速率指示
clk2, //245.76M的时钟输入
time1, //分频计数器
clk //选择后的时钟输出
);
input reset;
input[1:
0]data_rate;
input clk2;
output[1:
0]time1;
output clk;
reg[1:
0]time1;
reg clk;
always@(clk2orreset)
if(reset)
begin
time1=2'b00;
clk=1'b0;
end
else
begin
time1=time1+1'b1;
case(data_rate)
2'b00:
if(time1==2'b00)
clk=~clk;
else
clk=clk;
2'b01:
if(time1[0]==1'b1)
clk=~clk;
else
clk=clk;
2'b10:
clk=clk;
2'b11:
clk=~clk;
endcase
end
endmodule
verilog实现gray码计数器
//16位gray码计数器,gary码状态改变时候每次只改变一个bit
//,可以有效防止竞争和毛刺的产生。
modulegray_counter(clk,clr,start,stop,q,cout);
inputclk;
inputclr;
inputstart,stop;
outputreg[3:
0]q;
outputregcout;
regflag=1;
reg[3:
0]s,next_s;
//parameterS0=0,S1=1,S2=2,S3=3,S4=4,S5=5,S6=6,S7=7;
//parameterS8=8,S9=9,S10=10,S11=11,S12=12,S13=13,S14=14,S15=15;
parameters0=0000,s1=0001,s2=0011,s3=0010;
parameters4=0110,s5=0111,s6=0101,s7=0100;
parameters8=1100,s9=1101,s10=1111,s11=1110;
parameters12=1010,s13=1011,s14=1001,s15=1000;
always@(posedgeclk)
begin
if(clr)s<=s0;
else s<=next_s;
end
/*always@(posedgestartorposedgestop)
begin
if(start)flag=1;
elseif(stop)flag=0;
end*/
always@(sorflag) /*该进程实现状态的转换*/
begin
case(s)
s0:
begin
if(flag) next_s<=s1;
//else next_s<=s0;
end
s1:
begin
if(flag) next_s<=s2;
end
s2:
begin
if(flag) next_s<=s3;
////else next_s<=s0;
end
s3:
begin
if(flag) next_s<=s4;
//else next_s<=s3;
end
s4:
begin
if(flag) next_s<=s5;
end
s5:
begin
if(flag) next_s<=s6;
//else next_s<=s0;
end
s6:
begin
if(flag) next_s<=s7;
//else next_s<=s3;
end
s7:
begin
if(flag) next_s<=s8;
//else next_s<=s0;
end
s8:
begin
if(flag) next_s<=s9;
end
s9:
begin
if(flag) next_s<=s10;
////else next_s<=s0;
end
s10:
begin
if(flag) next_s<=s11;
//else next_s<=s3;
end
s11:
begin
if(flag) next_s<=s12;
end
s12:
begin
if(flag) next_s<=s13;
//else next_s<=s0;
end
s13:
begin
if(flag) next_s<=s14;
//else next_s<=s3;
end
s14:
begin
if(flag) next_s<=s15;
////else next_s<=s0;
end
s15:
begin
if(flag) next_s<=s0;
//else next_s<=s3;
end
default:
next_s<=s0; /*default语句*/
endcase
end
always@(s) /*该进程定义组合逻辑(FSM的输出)*/
begin
case(s)
s0:
q=0;
s1:
q=4;
s2:
q=2;
s3:
q=3;
s4:
q=4;
s5:
q=5;
s6:
q=6;
s7:
q=7;
s8:
q=8;
s9:
q=9;
s10:
q=10;
s11:
q=11;
s12:
q=12;
s13:
q=13;
s14:
q=14;
s15:
q=15;
default:
q=0; /*default语句,避免锁存器的产生*/
endcase
end
always@(s)
begin
if(s==s15)cout=1;//assigncout=q;
elsecout=0;
end
endmodule
如何解决FPGA电路设计中的毛刺问题
随着半导体技术的飞速发展,FPGA(FieldProgrammableGateArray)的计算能力、容量以及可靠性也有了很大的提高。
它正以高度灵活的用户现场编程功能、灵活的反复改写功能、高可靠性等优点,成为数字电路设计、数字信号处理等领域的新宠。
但和所有的数字电路一样,毛刺也是FPGA电路中的棘手问题。
它的出现会影响电路工作的稳定性、可靠性,严重时会导致整个数字系统的误动作和逻辑紊乱。
因此,如何有效正确的解决设计中出现的毛刺,就成为整个设计中的关键一环。
本文就FPGA设计中出现的毛刺问题,根据笔者自己的经验和体会,提出了几种简单可行的解决方法和思路,供同行供交流与参考。
1:
FPGA电路中毛刺的产生
我们知道,信号在FPGA器件中通过逻辑单元连线时,一定存在延时。
延时的大小不仅和连线的长短和逻辑单元的数目有关,而且也和器件的制造工艺、工作环境等有关。
因此,信号在器件中传输的时候,所需要的时间是不能精确估计的,当多路信号同时发生跳变的瞬间,就产生了“竞争冒险”。
这时,往往会出现一些不正确的尖峰信号,这些尖峰信号就是“毛刺”。
另外,由于FPGA以及其它的CPLD器件内部的分布电容和电感对电路中的毛刺基本没有什么过滤作用,因此这些毛刺信号就会被“保留”并传递到后一级,从而使得毛刺问题更加突出。
可见,即使是在最简单的逻辑运算中,如果出现多路信号同时跳变的情况,在通过内部走线之后,就一定会产生毛刺。
而现在使用在数字电路设计以及数字信号处理中的信号往往是由时钟控制的,多数据输入的复杂运算系统,甚至每个数据都由相当多的位数组成。
这时,每一级的毛刺都会对结果有严重的影响,如果是多级的设计,那么毛刺累加后甚至会影响整个设计的可靠性和精确性。
下面我们将以乘法运算电路来说明毛刺的产生以及去除,在实验中,我们使用的编程软件是QuartusII2.0,实验器件为CycloneEP1CF400I7。
需要说明一点,由于示波器无法显示该整数运算的结果,我们这里将只给出软件仿真的结果。
而具体的编程以及程序的下载我们在这里也不再详述,可以参考相关的文献书籍。
2:
毛刺的消除方法
首先,我们来设计一个简单的乘法运算电路。
运算电路如图1所示。
图1乘法运算运算电路及结果(略) 如图1(c)所示,如果在不加任何的去除毛刺的措施的时候,我们可以看到结果c中含有大量的毛刺。
产生的原因就是在时钟的上升沿,每个输入(a和b)的各个数据线上的数据都不可能保证同时到达,也就是说在时钟读取数据线上的数据的时候,有的数据线上读取的已经是新的数据,而有的数据线上读取的仍然是上一个数据,这样无疑会产生毛刺信号,而当数据完全稳定的时候,毛刺信号也就自然消失了。
a:
输出加D触发器 这是一种比较传统的去除毛刺的方法。
原理就是用一个D触发器去读带毛刺的信号,利用D触发器对输入信号的毛刺不敏感的特点,去除信号中的毛刺。
这种方法在简单的逻辑电路中是常见的一种方法,尤其是对信号中发生在非时钟跳变沿的毛刺信号去除效果非常的明显。
但是对于大多数的时序电路来说,毛刺信号往往发生在时钟信号的跳变沿,这样D触发器的效果就没有那么明显了(见图2,加D触发器以后的输出q,仍含有毛刺)。
另外,D触发器的使用还会给系统带来一定的延时,特别是在系统级数较多的情况下,延时也将变大,因此在使用D触发器去除毛刺的时候,一定要视情况而定,并不是所有的毛刺都可以用D触发器来消除。
图2加D触发器后的运算电路及结果(略)
b:
信号同步法 在很多文章中都提到,设计数字电路的时候采用同步电路可以大大减少毛刺。
另外,由于大多数毛刺都比较短(大概几个纳秒),只要毛刺不出现在时钟跳变沿,毛刺信号就不会对系统造成危害了。
因此很多人认为,只要在整个系统中使用同一个时钟就可以达到系统同步的目标了。
但是这里面有一个非常严重的问题,就是时钟信号和其他所有的信号一样,在FPGA器件中传递的时候是有延时的,这样根本就无法预知时钟跳变沿的精确位置。
也就是说我们无法保证在某个时钟的跳变沿读取的数据是一个稳定的数据,尤其是在多级设计中,这个问题就更加突出了。
因此,做到真正的"同步"就是去除毛刺信号的关键问题。
我认为这里同步的关键就是保证在时钟的跳变沿读取的数据是稳定的数据而不是毛刺数据。
以这个思想为出发点,提出了以下几种具体的信号同步方法。
c:
信号延时同步法 首先,我们给出了一个两级乘法(c=ab;q=dc)的运算结果(如图3所示,这里不再给出运算电路)。
可以看到,在没加任何处理过程的时候,两级结果c和q中都含有大量的毛刺信号。
其中毛刺信号产生的原因就是在计算时钟跳变时刻,数据信号同时发生了跳变。
另外,第一级信号c中含有大量的毛刺,在经过第二次乘法运算以后被明显放大了,从图3可以看出q中毛刺更加严重了。
但在很多实际工作中,我们最关心的往往是最后的输出结果(q),只要中间信号的毛刺对后面的输出没有什么影响我们就不需要对它们作任何处理了。
因此,这里所提出的信号同步的核心思想就是消除这些中间毛刺信号的影响。
图3两级乘法运算的结果仿真(略) 信号延时法,它的原理就是在两级信号传递的过程中加一个延时环节,从而保证在下一个模块中读取到的数据是稳定后的数据,即不包含毛刺信号。
这里所指的信号延时可以是数据信号的延时,也可以是时钟信号的延时。
由于篇幅的关系,这里我们主要以对时钟信号的延时来说明信号延时法的原理。
对上述计算过程加时钟信号延时的原理及结果如图4所示。
图4加了时钟延时的两级乘法运算及结果(略) 图4中的clkdelay就是时钟延时环节。
在加这个环节以前的时钟信号是直接连到模块b上的,这样两个模块使用同一时钟,好像已经做到了同步,但是如图3所示,结果中含有大量的毛刺,其原因就是产生毛刺的根本原因--“竞争冒险"现象没有得到根本性的消除。
加时钟延时环节的作用就是要从根本上消除“竞争冒险”,其过程是将控制模块b的时钟延时一段时间,使得模块b的控制时钟在上跳变化时
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Verilog 实现 任意 分频 方法