本节讲述部分的verilog语法
主要包括
位拼接“{}”的用法
Parameter用法
Beginend语句块
同步与异步
条件语句ca,if等
阻塞赋值与非阻塞赋值
边沿检测电路(双边沿触发的计数器)
按键去抖动电路设计
{}用法
在C语言中,{}是复合语句,但是在verilog中,有着不同的含义-位拼接运算符。即,
将几个1位或者是多位的变量拼接成位更宽的量。
假设a=1’b0;
b=3’b101;
c=2’b11
那么{c,b,a}=6’b11_101_0。下划线可以使结果看起来更加清晰,别无他意。
又如{c[0],b[2:1],c[1]}=4’b1_10_1;
实例:使用{}一位全加器的设计。
全加器和半加器类似,只是在输入端还有一个进位输入端Ci,电路符号如下:
回顾前面的讲述,半加器中我们使用了2位的变量temp来保存运算结果,而实际上这个
temp就是Co和S的拼接,即{Co,S}=temp。这里三个1位的数相加结果最大仍然是
2位,使用{Co,S}代替半加器中temp的代码如下:
代码注释:
(1)A+B+Ci的和存入{Co,S}拼接符中,Co为高位,S为低位。
moduleFullAdder(A,B,Ci,Co,S);
inputA,B,Ci;wireA,B,Ci;
outputCo,S;wireCo,S;
assign{Co,S}=A+B+Ci;//---------(1)
endmodule
FullAdder1bit
S
A
B
Co
Ci
{}有时候还用作复制运算符,例如:
A=1’b1;
B=2{A};则,B的值为A复制2次,即二进制的11(2’b11)。
注释:部分EDA工具可能不支持此复制运算符功能。
Parameter关键字
Verilog中使用parameter关键字来定义常量。
例如:parameterW=5
那么在任何时候W就代表5。通常在可变宽度的设计中很有用。为可变宽度变量的设计提供
了方便。接下来以4位全加器的设计演示parameter关键字的使用。
例:4位全加器的设计
根据要求,全加器要有两个4位的输入端,一个进位输入端Ci,一个4位的和输出端S和
一个进位输出端Co。模块图如下:
这里使用parameter关键字定义一个常量WIDTH为4,即parameterWIDTH=4;
然后在位宽设计的时候采用这个符号WIDTH来定义,如:wire[WIDTH-1:0]A;则A
为4位宽的连线。完整代码如下:
代码注释:
可以在module和endmodule之间的任何位置使用parameter关键字定义常量。
综合后的RTL视图如下,可以看出全加器的输入都是4位的。
moduleFullAdderNbit(A,B,Ci,Co,S);
parameterWIDTH=4;//---------(1)
input[WIDTH-1:0]A,B;
wire[WIDTH-1:0]A,B;
inputCi;
wireCi;
output[WIDTH-1:0]S;
wire[WIDTH-1:0]S;
outputCo;
wireCo;
assign{Co,S}=A+B+Ci;
endmodule
FullAdder4bit
S[3..0]
A[3..0]
B[3..0]
Co
Ci
出几道简单的
小作业题目
+A[4..0]
B[4..0]
ADDER
+A[4..0]
B[4..0]
ADDER
Ci
Co
B[3..0]S[3..0]
Add1
4'h0--
Add0
1'h0--
1'h0--
A[3..0]
使用parameter的关键字的好处之一是,当我们需要另外一个8位的全加器的时候,我们
不需要修改很多代码,只需要将parameterWIDTH=4;中的4换成8即可。然后重新综
合,查看一下是否变为了8位全加器。
beginend块语句
beginend的功能相当于c语言中的复合语句“{}”的功能,即把好几条语句组合在一
起作为一条语句执行。此处以模N计数器做实例讲解beginend的用法。
模N计数器,即计数器的技术个数为N个,如果计数器从0开始计数,当记到N-1时
候就开始下一轮的计数,即计数范围从0~N-1。
实例:模10计数器设计。
假设该计数器有两个端口,时钟输入端clk,计数器输出端cntr,技术范围从0~9。
代码如下:
代码注释:
(1)VerilogHDL中允许将端口和类型放在一起声明。outputreg[3:0]cntr;相
当于
output[3:0]cntr;
outputreg[3:0]cntr;
两条语句的功能。输入的类型如果不声明,则默认为wire型。如:inputclk;没有声明
clk类型,则表示clk为wire型。cntr宽度为4位,因为9变为二进制是1001,占4
位。
modulecounter10(clk,cntr);
inputclk;
outputreg[3:0]cntr;//---------(1)
always@(podgeclk)
begin//---------(4)
if(cntr==4'b1001)//---------(2)
cntr=0;
el
cntr=cntr+1;//---------(3)
end//---------(4)
endmodule
(2)和(3)这里判断的是cntr是否为9(二进制1001),而不是10。要特别注意!这里
分析一下电路的动作,每个加1动作的进行都需要podgeclk才能进行,计数器是从0
开始计数的,当cntr变到9时就已经用了10个podgeclk了。如果让电路再次动作,
就需要第11个podgeclk,而这时的计数值应该为0(模10已经完成了,下一个周
期开始)。所以在第11个podgeclk到来之前计数值为9。这和C语言中的运行方式
完全不同,不是顺序执行的,切记!另外,有的同学会问,为什么不这样写
begin
cntr=cntr+1;
if(cntr==4'b1001)
cntr=0;
end
这种写法里面,begin和end之间有2条语句,原代码中是一条if语句。一定要记住硬
件描述语言生成的硬件电路,这两条语句都同时对cntr进行赋值操作(只看语句本身,不
要带入语句的含义去看),这在电路上是不允许的,也就是说不可能有个电路的输出有两种
同时给的驱动!尽管有些EDA软件工具会智能化的理解并生成正确的电路,但在学习中一
定要避免这种方式的使用,切记!
(4)这两个(4)一定要成对使用。这个块还可以给起个名字,叫做块名。没有什么电气意
义,只是使代码看起来更清晰明了。用法如下:
begin:aaaa
if(cntr==4'b1001)
cntr=0;
el
cntr=cntr+1;
end
:aaaa就是beginend块的块名
同步电路与异步电路
从上一节的D触发器设计的RTL视图中我们可以看出,D触发器本身的功能引脚较多,
而我们使用的就CP和D、Q三个。下面我们尝试着使用其他的引脚。
D触发器设计实例2:具有同步复位功能的D触发器设计。
在最简单的D触发器基础上设计带复位端输入的D触发器。即使用RTL图中的CLR引
脚。电路图如下。
复位功能在数字电路中有同步复位和异步复位两类。所谓同步,指的是与时钟同步,也
就是D触发器的任何输出都需要有时钟的上升沿才能产生输出。所谓异步是指即使没有时
钟的上升沿也能够产生输出行为。这两种方式在VerilogHDL中都给予了支持。
同步复位D触发器指当复位引脚端有效时(通常约定为高电平,也可以根据需要设计成
低电平),在时钟上升沿出现时,D触发器会输出(Q端)复位(即为0),否则,在时钟上
升沿出现时,将D端的值传递至Q端。
MyDff2
CP
Q
D
CLR
同步复位D触发器设计:
代码注释:
(1)如果条件成立,即clr为高电平时,进行(2)
(2)q端口输出低电平,即复位
(3)否则,如果clr端口不为高电平,则进行d触发器的正常工作行为。
(4)语法,可以将相同类型的端口或者端口类型写在一个关键字的后面,中间用逗号隔
开,最后放一个分号。类似c语言中的一次定义多个相同类型的变量方式。
查看一下生成的RTL视图
0
1
D
ENA
Q
PRE
CLR
0
cp
q
q~reg0
d
q~0
clr
此时RTL图发生了变化,图中多了一个2选1的模块。根据此图分析,当clr为高电平
时,二选一的数据选择器会选择0至D触发器的输入端,故,当D触发器的时钟上升沿出
现时,会将0送至输出q端;如果clr为低电平,则将d送至输出q端。这里,RTL视图中
没有使用D触发器本身的CLR引脚,因此也可以推测D触发器本身的CLR引脚不是同步
复位功能引脚,而是异步复位功能。可以在接下来的D触发器设计实例3中得到验证。
这里使用了ifel语句对clr的电平值进行判断,如果为高,就执行功能1,否则的话
执行功能2。此if-el语句的功能和c语言中的if-el语句功能完全一致,不再详细论述。
D触发器设计实例3:具有异步复位功能的D触发器设计。
异步复位D触发器指当复位引脚端有效时(通常约定为高电平,也可以根据需要设计
成低电平),D触发器就会立刻输出(Q端)复位(即为0),否则,将D端的值传递至Q
端。这个动作的过程没有时钟的参与!
异步复位D触发器设计:
moduleMyDff2_sync(cp,d,q,clr);
inputcp;inputd;inputclr;
outputq;
wirecp;regq;
wired,clr;//------(4)
always@(podgecp)
if(clr==1'b1)//------(1)
q=1'b0;//------(2)
el//------(3)
q=d;
endmodule
代码注释:
(1)和同步复位D触发器的区别在于always@后面的括号中多了一个条件podgeclr。
也就是说,这个always模块的动作可以在时钟cp的上升沿来触发,也可以由clr的上升沿
来触发。两个条件之间用逗号“,”隔开,表示或的关系,也可以用关键字or代替。也就是
说,或者podgecp来触发电路动作,或者podgeclr来触发电路动作。这样,即使没有
cp的上升沿,也可以产生动作,这就是异步的由来。
生成的RTL视图如下
D
ENA
Q
PRE
CLR
q
clr
cp
q~reg0
d
这是大家看到,clr的端口直接连接到了D触发器的CLR端上,也充分说名了这个端是
异步端口,也可以从仿真的图上来说明。
在25ns时刻,clr为低电平,这时候d触发器正常工作,将d端输出至q端,因d为高
电平,故q端这时候变高。在60ns时刻,这个时刻,没有出现cp的上升沿,但是输出端发
生了变化,很显然是由于clr的变化导致的q端输出。因此,这个D触发器是异步复位的D
触发器。
特别注意,在always块的@(触发信号)中,有2个信号,为什么在生成电路的时候
将cp连接到了D触发器的时钟端,而将clr端口连接到了D触发器的CLR端呢?为什么不
将cp连接到CLR端,clr连接到时钟输入上呢?难道是因为名称的缘故?答案是否定的。
这里注意到,尽管@(触发信号)中有两个信号,但是其中一个信号clr在always块的内部
moduleMyDff3_async(cp,d,q,clr);
inputcp;inputd;inputclr;
outputq;
wirecp;regq;
always@(podgecp,podgeclr)//------(1)
if(clr==1'b1)
q=1'b0;
el
q=d;
endmodule
做了判断if(clr==1’b1),而另一个没有判断。VerilogHDL综合器规定,在always块语
句中被判断的量一定是复位或者是置位端口,always块中没有判断的量一定是时钟。换句话
说,时序电路的时钟在always块中是不允许进行电平高低的判定和读取等操作的。
小测试,将上述代码修改成以下代码并综合
代码注释:
(1)这里将if语句后面的clr换成了cp,编译后查看RTL视图如下:
D
ENA
Q
PRE
CLR
cp
q
clr
d
q~reg0
图中将cp连接到了CLR端,而将clr连接到了D触发器的时钟端,充分证明了上述观
点。
D触发器设计实例4:具有复位和置位功能的D触发器设计。
此处为了节约篇幅,只进行异步置位、异步复位(复位优先)的方式进行设计,其余方
式的D触发器请自行设计。
moduleMyDff3_async(cp,d,q,clr);
inputcp;inputd;inputclr;
outputq;
wirecp;regq;
always@(podgecp,podgeclr)
if(cp==1'b1)//------(1)
q=1'b0;
el
q=d;
endmodule
生成RTL视图如下:
D
ENA
Q
PRE
CLR
q~reg0
q
clr
cp
d
q~0
pre
条件语句ca,if等
If语句和ca语句是VerilogHDL的典型条件语句,其中if语句的用法和c语言中
的用法完全一致,在此处,不在详细叙述。但注意,如果有多个ifel语句同时使用的
话,el总是和最近的if配对。
以下以带有同步加载、同步清零的8位计数器为例示范if语句的使用。根据设计的要求,
此模块图应该具有以下端口
该计数器有5个端口,其中,clk为计数时钟,din为8为的数据置入端,dout为8位的
计数数据输出端,load为初值置入使能端,假设高电平有效,clr为计数清零端,假设高
电平有效。当load和clr均为低电平时,计数器正常计数。
moduleMyDff4(cp,d,q,clr,pre);
inputcp;inputd;inputclr;inputpre;
outputq;
wirecp;regq;
wired,clr,pre;
always@(podgecp,podgeclr,podgepre)
if(clr==1'b1)
q=1'b0;
elif(pre==1'b1)
q=1'b1;
el
q=d;
endmodule
Counter8bit
dout[7..0]
din[7..0]
load
clk
clr
在功能部分的语句中,先判断clr是否有效(高电平),如果有效则给计数器清0;否则检
查load是否有效,如果有效(高电平),则把初值din赋给计数器输出,如果load无效,
则正常加1计数。
读者试着使用if语句对该计数器进行增加功能,变为模60的计数器。
If语句示例2:带有方向控制的加减法计数器设计。
为了研究问题简便,这里不再采用清零端和初值加载功能,只有clk时钟端、updown方
向控制端和计数输出端dout。模块图如下:
功能定义如下:当updown为高电平时,dout对clk的上升沿进行加1计数,否则进行
减1计数。
代码如下:
updownCounter
dout[7..0]
updown
clk
modulecounter8bit(clk,din,load,clr,dout);
inputclk;
input[7:0]din;
inputload;
inputclr;
outputreg[7:0]dout;
always@(podgeclk)
begin
if(clr==1)
dout=0;
elif(load==1)
dout=din;
el
dout=dout+1;
end
endmodule
功能比较简单,这里不在注释。功能的正确性可以从仿真图上进行验证出来
从图中可以看出,当updown为高电平时,计数器的结果从0~23进行了加1计数,当
updown变为低电平时,从23往下减计数,等等。
VerilogHDL中的另一条件语句是ca,它的语法格式如下:
其中ca和endca为ca语句的关键字。如果敏感信号表达式(通常是变量)和值
n(分支值)相等,那么该分支值后面的语句就会执行,执行结束立刻退出ca语句。它
的语法非常类似于c语言中的switch-ca语句,但是注意每个分支值后面没有break!
下面用示例进行说明ca语句的用法。
七(八)段数码管是电路系统中常见的外设,通常用于模拟显示数字和个别字符。它的
外形如下:
ca(敏感信号表达式)
值1:语句1;//ca分支
值2:语句2;
……
值n:语句n;
default:语句n+1;
endca
moduleupdownCounter(clk,updown,dout);
inputclk;
inputupdown;
outputreg[7:0]dout;
always@(podgeclk)
begin
if(updown==1)
dout=dout+1;
el
dout=dout-1;
end
endmodule
标有abcd~h的就是8个发光二极管,这8个二极管又有两种形式的电路连接方法,分别
称共阴极接法和共阳极接法。共阴极的数码管内部电路如下图:
将所有的二极管的阴极接到一起,通常连接到电路的GND上。共阳极的接法恰好相反,把
所有二极管的阳极连接在一起,如下图
以,共阴极为例,通常电路设计的连接如下图(图中串联了限流电阻,通常270R左右)
若要显示如下字符0、1、2、3、4、5、6、7、8、9见下图
FPGA/CPLD
GND
A
B
C
D
E
F
G
H
gnd
只需要将a、b、c、d、e、f、g、h等端口输出相应的高低电平即可。
代码示例:设计一个八段数码管显示译码电路,将4为输入的二进制数在数码管上显示出
来。模块图如下:
din为二进制的输入,a、b、c、d、e、f、g、h为8个输出端口,分别通过限流电阻连
接到八段数码管相应的段上。
代码如下:
bcd2Seg
a
din[3..0]
b
c
d
e
f
g
h
代码注释:
(1)always@(din)表示当din发生值得变化的时候,always块(从begin到end之
间的代码)动作一次。always@(din)也可以写成always@(*),凡是括号中不是边沿信
号的都可以写成*号,意义不变。
(2)和(5),ca语句的格式,必须成对使用。
(3)分支值中的4'd0也可以写成0(缺省为10进制)或者4'b0000,在硬件上的含义的
相同的。只是表现形式不同而已(十进制的和二进制的)。后面的分支同样适用。
(4)default是ca语句的缺省选项(和c语言中的swich-ca一样),当输入的二
进制值不在0~9范围内的时候,数码管不显示。
这是一个很实用的例程,在很多数码管显示的系统中,可以直接使用。有兴趣的同学可以下
载到带有数码管的FPGA/CPLD硬件系统上尝试一下。还可以对此程序进行扩展,让它能够
显示十六进制的AbCdE和F等,这里不再在赘述。
小作业:设计一个加减法电路,2个4位数的加减法,结果用八段数码管显示出来
阻塞赋值与非阻塞赋值
在以往的设计中,都是用了“=”这个赋值符号。通常称作阻塞赋值符号。那么它的意
义和作用是什么呢?这里通过一个实例设计来进行“=”含义的诠释。
欲设计一2个D触发器级联的电路,如下图:
modulebcd2g(din,a,b,c,d,e,f,g,h);
outputrega,b,c,d,e,f,g,h;
input[3:0]din;
always@(din)//------(1)
begin
ca(din)//------(2)
4'd0:{a,b,c,d,e,f,g,h}=8'b11111100;//------(3)
4'd1:{a,b,c,d,e,f,g,h}=8'b01100000;
4'd2:{a,b,c,d,e,f,g,h}=8'b11011010;
4'd3:{a,b,c,d,e,f,g,h}=8'b11110010;
4'd4:{a,b,c,d,e,f,g,h}=8'b01100110;
4'd5:{a,b,c,d,e,f,g,h}=8'b10110110;
4'd6:{a,b,c,d,e,f,g,h}=8'b10111110;
4'd7:{a,b,c,d,e,f,g,h}=8'b11100000;
4'd8:{a,b,c,d,e,f,g,h}=8'b11111110;
4'd9:{a,b,c,d,e,f,g,h}=8'b11110110;
default:{a,b,c,d,e,f,g,h}=8'b0000_0000;//------(4)
endca//------(5)
end
endmodule
根据电路的构成,使用非阻塞赋值符号“=”的代码如下:
使用QuartusII综合后,发现生成的电路如下图:
D
ENA
Q
PRE
CLR
D
ENA
Q
PRE
CLR
q1
q1~reg0
q0
q0~reg0
clk
d
也就是说,实际上两个Dff根本没有级联起来?这是为什么呢?在Verilog中,“=”
为非阻塞赋值,从语义上讲,begin和end之间使用了阻塞赋值语句,那么这些语句的赋
值是有先后顺序的(注意这里的说法,是语义上的先后顺序,实际硬件电路的动作都是在
clk的上升沿处进行的)。也就是说,后一条语句的执行(q1=q0;)是在前一条语句q0=d;
赋值结束才进行,而第一条语句中已经将q0的值变成了d,所以下一条语句中将q0的值
付给q1就是将d的值赋给q1,所以综合后电路中出现的两个d触发器输入端都是d。
要想使生成的电路符合要求,必须在(q1=q0;)这条语句执行的时候,d的值还没有
来得及赋给q0才可以。也就是说,让两条赋值语句同时执行就可以。这里就用到非阻塞赋
值“<=”符号,非阻塞赋值的含义就是指begin和end之间的各个语句执行时同时进行的,
不必等上一条语句执行结束就立刻执行。在上面的实例中,将阻塞赋值符号变为非阻塞符号,
代码如下:
moduleMy2Dffs(clk,d,q0,q1);
inputclk,d;
outputregq0,q1;
always@(podgeclk)
begin
q0=d;
q1=q0;
end
endmodule
My2Dffs
q1
d
clk
q0
重新编译代码,查看RTL电路图如下:
D
ENA
Q
PRE
CLR
D
ENA
Q
PRE
CLR
q1~reg0
clk
q0
q1d
q0~reg0
这时候生成的电路就是最开始要设计的电路了。
注意事项:阻塞非阻塞赋值只有在时序电路中才会出现,所以只能在always语句中
使用,换句话说,不可以在assign语句使用“<=”符号,因为assign电路生成的都是
组合电路。
非阻塞赋值符号“<=”和比较小于等于“<=”是相同的,在VerilogHDL靠语句来
识别,如果出现在条件语句if等后面,则是“小于等于”,如果出现在赋值语句中就是赋
值符号,要注意识别。
多数情况下,为了得到更为精确的逻辑,往往使用“<=”的场合比较多,“=”一般会
在算法中出现。
接着上例,如果说我就想使用“=”符号来实现两个D触发器的级联电路,可以吗?答
案是肯定的,只需要将begin和end之间的两条语句调换一下顺序就可以了,读者可以自
己去验证并体会其中的含义。当然也可写2个always块,每个always块中各使用一条
赋值语句,因为多个always是并行执行的,所以没有语句执行先后之说。
边沿检测电路
两个相互级联的D触发器在实际的应用中有着很巧妙的应用。
有如下电路
moduleMy2Dffs(clk,d,q0,q1);
inputclk,d;
outputregq0,q1;
always@(podgeclk)
begin
q0<=d;
q1<=q0;
end
endmodule
在级联的2个d触发器后面分别接入了非门和与门或者是异或门,那么这些门的输出
端a、b、c会出现什么样的特点呢?
首先分析一下a输出,因为两个d触发器是记忆电路,故假设q0和q1端都为低电平,
d也是低电平,则a端当前t0时刻输出为低(即0),t1时刻,d变为高电平,t2时刻,
时钟上升沿到来。q0端变为高电平,但q1端仍然为低电平,q1的非则为高电平,所以a
端输出高电平。t3时刻,又一个clk时钟沿来到,这是q1输出也变为了高电平,故a端
又变为低电平。t3时刻以后,例如t4,q0和q1的输出一直为高,a端一直为低电平。
由此图得出,当d输入端出现一个上升沿的时候,在clk的作用下,系统的a端会出
现一个clk周期宽度的正脉中,这个特性可以在很多的应用中发挥关键的作用,这个电路
也叫做上升沿检测电路,或者叫上升沿微分电路(卢毅赖杰编著的VHDL与数字电路设计)。
同理可以得出,当d端出现下降沿的时候,b端会输出一个clk周期宽度的正脉中(下降
沿检测电路或下降沿微分电路);不论d端产生的是上升沿还是下降沿,c端都会输出一个
clk周期宽度的正脉冲(双边沿检测电路或双边沿微分电路)。
该电路的完整描述与如下:
EdgeDetect
q1
d
clk
q0
b
c
a
clk
d
t0t1t2
q0
q1
t3
a
t4
注释:(1)”^”为异或运算符,和c语言中的异或运算一样
仿真波形如下图:
由上图仿真结果来看,和分析的结果一样。在215ns时刻,d出现了上升沿,随后a端和
c端均出现了一个周期的正脉冲,在301ns时刻,d端变低,随后b端和c端口均出现了
一个周期的正脉冲。
利用边沿检测电路可以实现一个电路看起来是由多个边沿触发的。而实际上多个时钟的
电路时不存在的,因为在数字电路里面,任何触发器都只有一个时钟边沿触发。接下来以双
边沿触发的计数器为例,查看电路设计的巧妙之处。
两路边沿触发的计数器设计实例
up
down
clk
cntr
8
TwoCPCounter
Up和down是两个输入端,当up端由低到高变化一次时,cntr进行加1动作(向上
计数),当down端由低到高变化一次时cntr进行减加1动作(向下计数),clk为系统的
moduleEdgeDetect(clk,d,a,b,c);
inputclk,d;
outputa,b,c;
regq0,q1;
always@(podgeclk)
begin
q0<=d;
q1<=q0;
end
assigna=q0&(!q1);
assignb=(!q0)&q1;
assignc=q0^q1;//-----(1)
endmodule
时钟端,用来检测up和down的上升沿(微分电路)。
根据要求,使用clk分别对up和down进行边沿检测,即设计两个微分电路。然后根
据微分电路的特征(只有一个周期的脉宽,即在这个周期内只有一个上升沿(下降沿)),然
后在计数电路中判读出现了哪一个脉冲即可进行相应的加或减1操作了。
完整代码如下:
这里的加减计数器和之前讲过的用一个端口控制加减方向的计数器有着本质的不同,注
意区分,体会其中的硬件含义。
注意:千万不要用podgeup,podgedown作为always的触发条件实现该实
例
按键去抖动电路设计
moduletwocpcounter(clk,up,down,cntr);
inputclk,up,down;
outputreg[7:0]cntr;
regq0,q1;
wireup_pul;
always@(podgeclk)
begin
q0<=up;
q1<=q0;
end
assignup_pul=q0&(!q1);
regp0,p1;
wiredown_pul;
always@(podgeclk)
begin
p0<=down;
p1<=p0;
end
assigndown_pul=p0&(!p1);
always@(podgeclk)
begin
if(up_pul)
cntr<=cntr+1;
elif(down_pul)
cntr<=cntr-1;
end
endmodule
产生up上升沿微分up_pul
产生down上升沿微分
down_pul
由于up_pul和down_pul宽
度为1个clk周期,故当up端出现
上升沿时候,计数器只会进行1次加
操作,同理,down端出现上升沿时
候,计数器只会进行1次减操作
继续研究两个D触发器级联的作用。在实际应用中,经常用到按键,常见的电路连接
如下图:
本文发布于:2022-11-12 17:58:40,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/88/5813.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |