概述
Verilog语言是硬件描述语言而不是设计语言。在写Verilog代码时,大脑要先想好完成的具体功能应该用什么样的电路实现,然后再用Verilog描述出来。
1.数字电路和模拟电路
数字信号指信号无论从时间上还是大小上都是不连续的。
模拟信号指时间联系变化的信号
2.数制与编码
在Verilog中表示一个二进制,首先要给出长度,二进制的标识,最后是数值。例如8’b1000,表示8位二进制数1000。如果表示十进制数,将二进制标识换成十进制表示。
位数和标识可以省略,默认位数是32位,默认进制是十进制。
3.逻辑代数
在逻辑代数中有三种基本的逻辑运算,分别是与、或、非。这三种逻辑运算可以组合任意复杂逻辑运算。
根据逻辑功能的不同,可以将数字电路分为两类,组合逻辑电路、时序逻辑电路。
组合逻辑电路:电路的输出仅仅与当时的输入有关系,与之前的输入没有关系。
组合逻辑电路分析方法
常用的逻辑电路有编码器、译码器、数据选择器、数值比较器和加法器。
- 编码器
日常生活中电视机遥控器上的键盘输入和密码锁。编码器有互斥编码器和优先编码器之分。互斥编码器:任意时刻只允许一个输入信号有效,否则将产生错误输出。
优先编码器:允许多个输入信号同时有效,输出是对优先级别高的输入信号进行编码。
8-3互斥编码器
8-3编码器可以3位二进制代码对8个信号进行编码的电路。8个输入3个输出。
设计8-3编码器
第一步根据给出的逻辑功能写出真值表,8个互斥的输入信号,编成一个对应的3位二进制代码。将8个输入信号分别定义为I0,I1,I2一直到I7,将3个输出信号定义为A0、A1和A2。每一个互斥的输入信号为1时,输出一个对应的3位二进制码。
当I0输入为1时,对应的三个输出是111。当I1输入为1时,对应的三个输出为110。以此类推直到I7输入为1,对应输出为000。根据这个公式写出真值表。
根据真值表,写出逻辑表达式。将输入变量等于1 的情况相或起来,写出表达式。
通过表达式看出,每个输出变量的结果都由若干个输入变量通过相或之后得到的。根据这些函数式画出逻辑图。
对互斥编码器修改为优先编码器。允许某一时刻多个输入端为有效电平,但只对优先级最高的输入信号进行编码。在这里规定I7的优先级最高,I0的优先级最低,根据条件,列出真值表。
利用Verilog来描述编码器
module Digital_Encoder(
I,A
);
input [7:0]
I;
output [2:0]
A;
reg [2:0] A ;
always@(*)
begin
case(I)
8'b0000_0001 : A=3'b000;
8'b0000_0010 : A=3'b001;
8'b0000_0100 : A=3'b010;
8'b0000_1000 : A=3'b011;
8'b0001_0000 : A=3'b100;
8'b0010_0000 : A=3'b101;
8'b0100_0000 : A=3'b110;
8'b1000_0000 : A=3'b111;
default : A = 3'b000;
endcase
end
endmodule
开头是module关键字,紧接着是模块名Encoder(英文翻译为中文为编码器)。模块名之后是端口名I,A。编码器有8个输入和3个输出,按照常规的写法,可以分别把输入写为I0、I1、I2一直到I7和三个输出A0、A1、A2,如果有100个输入是不是要写100个?为了解决这种问题,所以写input [7:0] I,每一位代表一个输入。往下是数据类型的定义。在过程赋值语句always中左侧变量声明为reg。如果是连续赋值语句assign,需要用到的就是wire,可以省略声明,系统默认为wire型。接下来是always关键词,always@(*表示代码中的任何东西改变,都会触发里边的程序。begin end之间的代码顺序执行,被module和endmodule括起来的语句并行执行。如果在一个module中有两个always,这两个always没有先后顺序,同时执行。case是一种多分支选择语句,当输入I为8’b00000001,代表I7为0,代表I6为0,代表I5为0,代表I4为0,代表I3为0,代表I2为0,代表I1为0,代表I0为1,此时输出为3’b001,也就是A2为0,A1为0,A0为1。case和endcase成对出现。default关键字的意思:如果上述条件不符合,会执行default中的语句。
观察case里的几条语句,与编码器真值表很像,这段代码描述的就是编码器真值表。接下来是优先编码器。代码基本与上边的代码差不多。唯一不同的是使用了if关键字。如果输入I7等于0,那么便会执行A=3’b000,如果I7不等于0,那么就不会执行。
module Digital_Priority_Encoder
(
I,A
);
input [7:0] I;
output [2:0] A;
reg [2:0] A;
always@(*)
begin
if(I[7] == 1'b0)
A = 3'b000;
else if(I[6] == 1'b0)
A = 3'b001;
else if(I[5] == 1'b0)
A = 3'b010;
else if(I[4] == 1'b0)
A = 3'b011;
else if(I[3] == 1'b0)
A = 3'b100;
else if(I[2] == 1'b0)
A = 3'b101;
else if(I[1] == 1'b0)
A = 3'b110;
else if(I[0] == 1'b0)
A = 3'b111;
else A = 3'b000;
end
endmodule
- 译码器
在编码时,每一组代码都有特定的含义,表示一个确定的信息。而译码则是把代码含义翻译出来的过程。完成译码功能的逻辑电路被称为译码器。
设计3-8译码器
编码器有8个输入,3个输出。译码器刚好相反有3个输入,8个输出。在编码器里I0输入为高电平,对应的输出为111.在译码器里,输入为111,对应的输出I0为高电平。以此类推写出真值表。
由真值表写出逻辑函数表达式。
最后根据逻辑函数表达式画出电路图。
module Digital_Decoder
(
A,I
);
input [2:0] A;
output [7:0] I;
reg [7:0] I;
always@(*)
begin
case(A)
3'b000:I = 8'b01111111;
3'b001:I = 8'b10111111;
3'b010:I = 8'b11011111;
3'b011:I = 8'b11101111;
3'b100:I = 8'b11110111;
3'b101:I = 8'b11111011;
3'b110:I = 8'b11111101;
3'b111:I = 8'b11111110;
default : I = 8'b11111111;
endcase
end
endmodule
译码器的应用:七段显示译码器。
常说的数码管是由7个发光二极管,按照一定的方式排列起来,利用不同光端的组合,显示不同的十进制数。
驱动七段数码管显示的译码器成为BCD七段显示译码器,通过它将BCD码变换成十进制数并在数码管上显示出来。真值表如下所示
- 数据选择器
所谓数据选择就是从多个输入的逻辑信号中选择一个逻辑信号输出,实现数据选择功能的逻辑电路便成为数据选择器。也成为多路复用器,作用类似于多个输入的单刀多掷开关。
以下为8-1数据选择器为例。功能示意图如下
从图中看出,D0-D7为数据输入端,Y为输出端,A0,A1,A2为3-8译码器的输入端,A0、A1、A2地址码经过3-8译码器译码,产生有效信号。控制八个开关,最终选择一路数据输出。根据分析,写出真值表。
根据真值表,写出函数表达式。
从逻辑图中可以看出,他只是在3-8译码器基础上添加了8个数据输入端D0-D7和一个或门。
module Selector
(
A,D0,D1,D2,D3,D4,D5,D6,D7,Y
);
input D0,D1,D2,D3,D4,D5,D6,D7;
input [2:0] A;
output[7:0] Y;
reg [7:0] Y;
always@(*)
begin
case(A)
3'b000 :Y=D0;
3'b001 :Y=D1;
3'b010 :Y=D2;
3'b011 :Y=D3;
3'b100 :Y=D4;
3'b101 :Y=D5;
3'b110 :Y=D6;
3'b111 :Y=D7;
default: Y = 1'b0 ;
endcase
end
endmodule
数值比较器
数值比较器是对两个数A、B进行比较,以判断其大小的逻辑电路。比较结果有A>B、A=B、A<B三种情况,仅有一种值为真。
尝试设计一个1位数值比较器,1位数值比较器的功能是比较两个1为二进制数的大小。假设两个数为A、B。写出真值表。
写出逻辑函数表达式
画出电路图
module Digital_Comparator
(
A,B,F
);
input [3:0 ] A;
input [3:0]
B;
output [2:0] F;
reg [2:0] F;
always@(*)
begin
if(A>B)
F = 3'b001;
else if(A==B)
F = 3'b010;
else
F = 3'b100;
end
endmodule
加法器
加法器是算术运算的基本单元电路。
加法器可以分为半加器和全加器。如果仅仅考虑两个1位二进制数A和B相加,而不考虑低位的进位,则成为半加,实现半加运算的电路叫做半加器。半加器有两个有两个输入端A和B,两个输出端S和C,S为和,C为高位的进位。根据逻辑功能写出真值表。
由真值表写出逻辑函数表达式:
根据函数表达式给出电路图。
由于半加没有考虑低位的进位,所以不能解决加法问题,下面是全加的一个例子。
从图中可以看出,两个四位二进制数相加,被加数Ai和加数Bi,11110是低位向高位的进位Ci-1,在相加过程中,除
最低位以外,其余各位即要考虑本位的相加,又要考虑低位向本位的进位Ci。因此全加就是将Ai,Bi,Ci-1这三个变量进行相加,求出Si及本位向高位的进位Ci。真值表如下
由真值表写出逻辑函数表达式
根据表达式画出电路图
要进行多位数相加,最简单的方法是将多个全加器进行级联,成为串行进位加法器。
全加器的个数等于相加的位数。最低位全加器的Ci-1端接0.串位进位加法器的优点是电路比较简单,缺点是速度比较慢。因为进位信号是串行传递,最后一位的进位输出C3要经过四位全加器传递之后才能形成。
Verilog代码描述
module Digital_Adder
(
A,B,S
);
input [3:0] A;
input [3:0] B;
output [3:0] S;
reg [3:0] S;
always @(*)
begin
S = A + B;
end
endmodule
改代码没有考虑进位溢出情况。当相加结果超过最大值,最高位进位输出丢失。
时序逻辑电路
组合逻辑电路是没有记忆功能的,在任何时刻产生的输出信号都仅仅取决于该时刻电路的输入信号。与之前的输入信号无关。时序电路与组合电路相反,有记忆功能,任何时刻的输出,不仅与该时刻的输入信号有关,而且与该时刻以前的输入信号有关。
一个完整的时序电路,由组合逻辑电路,存储信息的存储电路组成。常用的存储电路有两类,一类是锁存器,另一类是触发器。它们两者采用的电路结构形式不同,信号的触发方式也不同。采用电平触发方式的叫锁存器,采用脉冲边沿触发方式的叫触发器。
锁存器
锁存器(latch)是数字电路中一种具有记忆功能的逻辑元件。锁存器对脉冲电平敏感的存储单元电路,只在输入脉冲的高低电平期间对输入信号敏感并改变状态。在数字电路中可以记录二进制数字信号0和1。
RS锁存器
RS锁存器是构成复杂锁存器和复杂触发器的基础。
从电路图中科院看出,由两个或非门组成。有两个输入端,Sd和Rd,S和R分别代表SET和RESET,翻译过来是置位和复位的意思,下标D代表的是DATA,就是数据。正常工作时,Q和-Q是互补的。锁存器的状态用输出端Q的值来命名,若Q=0,则称锁存器为0状态。
RS锁存器工作原理
首先看RS锁存器置位,这里所谓的置位,就是要求Sd这个置位端必须要有激励信号,而Rd复位端不能有激励信号。就是要Sd=1,Rd =0。Sd是连接到G1这个或非门上的,当Sd=1时,根据或非门的逻辑关系,只要输入有1,输出就为0,只有输入全部为0时,输出才为1。那么根据这个关系,G1门的输出就是0,-Q同样也是0.再将0反馈到G2门的输入端,,此时G2的输出端为1,Q也为1。让Sd输入端为1,电路状态为1。这是RS锁存器的置位。
再看RS锁存器复位,首先给Rd复位端一个激励信号,而Sd置位端不能有激励信号,也就是让Rd=1,Sd=0。当Rd=1时,只要输入有1,输出就为0。再分析G2、G1,最后输出Q为0,让电路状态保持在0的状态,也就是RS锁存器的复位。
RS锁存器,可以将电路的状态锁住,当下一刻锁存器的置位端或复位端的激励信号突然消失了,锁存器仍能保持之前的工作状态。
假设刚刚将RS锁存器复位,现在这个锁存器Q=0,突然插销了Rd这个复位端的激励信号,那么此时的输入信号Rd和Sd都为0了。时序电路中发生时间不同的信号之间也是可以互相影响的。也就是G1和G2所输出的信号,还是之前的输入信号通过或非门产生的。所以此时Q仍然是0的,激励信号消失后,电路扔维持原来的状态不变。
RS锁存器里禁止Sd和Rd同时为1。Sd是置位,Rd是复位。同时置位复位会错乱。此时电路Q和-Q同时为0,加入下一时刻,Sd和Rd激励信号全部消失,期望电路按照原状态继续运行,可事实却不是。两个信号首先不可能同时变为0,肯定有先后之分,假如Sd先为0,那么G1门的输入端都为0,G1输出1,最后输出Q为0,电路保持在0状态。假设Rd先为0,G2门输出将为1,Q也为1,电路保持在1状态运行。所以很难确定此时电路的状态,所以禁止SdRd同时等于1的情况出现。
接下来尝试用与非门组成一个RS锁存器。电路图如下
可以看出,与非门和或非门构成的RS锁存器有点不同。在与非门构成的RS锁存器中,两个输入信号写出了-Sd和-Rd的形式。表示低电平有效。为0表示有激励信号,为1表示无激励信号。两个输出信号的位置也发生了改变。
下面讲解时序电路中四种描述方法,分别是特性表、特性方程、状态图和波形图。
特性表
特性表是反应输入变量和原状态以及新状态之间的一种真值表,也称为状态转换真值表。原状态用Qn表示,新状态用Qn+1表示。
根据特性表很清楚的看出RS锁存器的逻辑功能,当Sd和Rd同时等于0时,也就是无激励信号,Qn和Qn+1是一样的。以此类推,很容易理解。
特性方程
特性方程是锁存器新状态的逻辑表达式。
状态图
RS锁存器的状态图如下所示。
两个圆圈中的0和1表示RS锁存器的两个状态,四个箭头表示四个转换过程。箭头末端表示原状态,指向新状态,箭头旁边是状态改变的条件,x表示任意值。
波形图
门控RS锁存器
在实际工作中,希望能有一个控制信号去控制锁存器状态的转换,所以在RS锁存器的基础上增加了一个控制端,只有控制端的信号变为有效电平后,RS锁存器才能按照输入的置1或置0信号改变相应的状态,这种锁存器成为门控RS锁存器。
从门控RS锁存器的电路图可以看出,该电路由两个部分组成,第一个部分由G1和G2两个或非门组成了RS锁存器,第二个部分是由G3、G4两个与门组成的输入控制门电路。C为控制信号,它被加到了G3、G4两个与门的输入端上,用来控制激励信号的输入。Rd=RC,Sd=SC。
通过特性表可以看出,当C=0时,根据与门的逻辑关系,无论R和S输入1,还是输入0,Rd和Sd都将等于0,锁存器将维持原状态不改变,如果C=1的话,R将会等于Rd,S也将等于Sd。此时电路等效为RS锁存器。
从门控RS锁存器的波形图可以看出,当C=0时,不管Rd和Sd怎么变化,Q不会改变。
D锁存器
D锁存器由RS锁存器演变而来。能够将输入端的单路数据D存入到锁存器中的电路。
从电路图中可以看出,电路由两个部分组成。第一个部分由G1、G2两个与非门组成RS锁存器,第二个部分由G3、G4两个与非门组成的控制门电路。C为控制信号,它被加到了G3、G4两个与非门的输入端上,用来控制激励信号的输入。
D锁存器的工作原理,当控制端C=0时,根据与非门的逻辑,无论D等于什么,-Rd和-Sd都同时等于1。根据由与非门组成的RS锁存器的逻辑规律,Q将维持原状态不变。当控制端C=1时,如果此时D=0,-Sd就等于1,-Rd就等于0,锁存器的结果为1状态,也就是说锁存器的状态由输入端D来确定。D等于什么,锁存器状态就是什么。
特性表
从D锁存器的特性表可以看出,D控制锁存器的状态。将输出等于1的项提出来后,组成一个与或式。最后结果为:
接下来画出状态图。
波形图
从D锁存器的波形图可以看出,D是锁存器的输入信号,C是控制信号,Q是锁存器的输出信号。当C为高电平时,输出信号Q将跟随输入信号D的变化而变化。当C从高电平变为低电平时,输入信号D的状态将会觉得锁存器将要锁存的状态。
空翻现象
锁存器中存在空翻问题,当控制信号有效时,输入信号若发生多次变化,输出状态也跟着发生多次变化,这一现象被称为锁存器的空翻。
从波形图可以看出,蓝色虚线内,由于C为高电平,D为1,那么可以得出Q为1。当D变为0,Q就为0。空翻是一种有害的现象,使得时序电路不能按照时钟节拍工作,造成系统的误工作。为了解决寄存器的空翻现象,在锁存器的基础上进行了修改,设计出了触发器。按照功能的不同分为RS触发器、D触发器、JK触发器、T触发器。FPGA设计中重点理由D触发器,下面详细讲解。
触发器
触发器也是数字电路在一种具体记忆功能的逻辑元件。在触发脉冲的上升沿或下降沿瞬间改变其状态。
D触发器的电路图如下:
从D触发器的电路图可以看出,该电路由两个相同的D锁存器以及两个非门连接而成。F1和F2是D锁存器的电路符号,F1为主锁存器,F2为从锁存器。由于主锁存器的输出信号Q1是从锁存器的输入信号,因而造成了两个锁存器的主从关系,两个锁存器的控制信号都由外部时钟信号CLK提供。
当CLk=0时,CLK经过非门后连接F1的控制信号,此时F1控制信号为1,F1被选通。处于工作状态,如果输入信号D为1,经过F1,输出Q1为1。Q1再输入给F2,此时F2控制信号为0,F2此时为锁存状态。输入信号D未能直接改变输出Q的状态。也就是说输入信号先存入主锁存器中,而不直接影响输出Q的状态。
当外部的控制信号由0变为1时,F1的控制信号为0,住锁存器保持当前的状态,现在D变化,主锁存器的输出不会变化。F2的控制信号CLK为1,F2处于工作状态,Q1会作为F2的输入信号,影响输出Q的状态。Q1为1,根据锁存器的逻辑规律,输出Q将为1。在后半拍才能实现整个电路状态的改变。在一个变化周期内,触发器的输出状态只可能变化以此,克服了空翻现象。
D锁存器和D触发器的逻辑功能是相同的,只是触发方式有所不同。比较二者的波形图,分析不同之处。
D触发器在控制信号CLK为0时,才会接受信号D的值,并将值锁存起来,当控制信号CLK为1时,输出信号Q才会被改变。那么D触发器就是在时钟信号由0变为1的这个边沿进行触发的,将这种触发方式成为边沿触发。通过这种边沿触发方式的D触发器称为D触发器。
学完触发器的原理,下面用Verilog来描述触发器。
module Digital_Data_Flip_Flop
(
CLK_50M,RST_N,D,Q
);
input CLK_50M;
input RST_N;
input D;
output reg Q;//可以分开写,也可以一起写
always@(posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
Q<=1'b0;
else
Q<=D;
end
endmodule
always模块敏感表可以为电平、上升沿posedge、下降沿negedge。
always@(*) //always@(A,B)也可以always@(AorB)
begin
//具体逻辑
end
always后若由上升沿、下降沿声明,则为多时序逻辑,其基本代码如下所示。
always@(posedge CLK_50M)
begin
end
always@(posedge CLK_50M or negedge RST_N)
begin
end
always@(A,B),@是事件等待语句,意思是一直等待A和B两个敏感变量变化,不管A和B从高变低,还是从低变高,都会执行always里的语句。如果A和B没有变化,那么always也将不往下执行,一直等待循环。always@(*)是为了防止合设计时考虑不周带来的操作失误,星号表示变量,只要有任何输入信号变化,其输出立即发生变化。
在时序电路中的赋值是<=,而组合逻辑电路中赋值是=。阻塞赋值操作符用=表示,非阻塞赋值操作符用<=表示。
举个最简单的例子,用Verilog将两个数A和B的值进行交换。
是a=b;b=a;?将b的值给了a,a这时候是b的值,下一步a的值给b,最后结果a和b的值都是b刚开始的值,并未交换。
如果是a<=b;b<=a;就不同了,b的值赋予a后,a并不会立刻改变,下一步将值赋予b,完成交换。
阻塞和非阻塞赋值简单理解就是这样,当赋值后,值并不会立刻发生改变。
上述代码中的if语句用来判断复位信号是否有效,RST_N是一个低电平有效的复位信号,当RST_N=0时,if为真,语句会执行。到这D触发器就说完了下面说寄存器。
寄存器
寄存器由多个触发器组成,能够存储多位二进制数码的时序电路。
下面的例子为由四位D触发器组成的寄存器电路图。
F0、F1、F2、F3是四个边沿D触发器的电路符号,绿色的小三角表示他们的触发方式是边沿触发。
如果给电路中CP端一个脉冲的话,此刻D0、D1、D2、D3的值将被储存在寄存器里,直到CP端下一个脉冲到来,储存之才有可能改变。特性表如下所示。
从特性表可以看出,寄存器由寄存和保持两种工作状态。当时钟信号的上升沿到来时,电路将会出发,D0、D1、D2、D3的值将被寄存,直到下一时钟的上升沿到来之前,输入信号改变,输出的值不会改变。下面介绍一个稍微复杂点的寄存器,移位寄存器。
寄存器的应用。
流水灯是一个典型的右移位寄存器,通过流水灯来了解右移位寄存器的工作原理。
由4盏灯,分别是1号灯,2号,3号,4号。规定灯泡为1时,灯被点亮,当灯泡为0时,灯熄灭。将四位二进制数1000中的1进行右移得到0100,0010,0001。对应的效果为四盏灯依次点亮。下面画出控制电路,由4个D触发器依次连接起来。
从电路图看出,如果需要点亮第一个灯,那么应该让D0为1,根据D触发器的性质,需要让F0这个D触发器的输入端为1,并且让F0的控制端CP产生一个上升沿,使F0触发。CP不仅仅是F0的控制端同时是另外三个触发器的控制端,当CP上升沿来临,4个触发器将同时触发。此时触发的话,由于其他三个触发器输入端没有激励信号值为0,所以结果Q0为1其余输出为0。此时将D0的值改为0,触发器为锁存状态,输出上一时刻的值,输出又与下一触发器的输入相连,下一触发器的输入此时为1,触发器开始工作。依次类推实现了右移。
特性表
下面利用Verilog来描述寄存器。
module Digital_shift_reg
(
clk,rst_n,data_en,data_in,data_out
);
input clk;
input rst_n;
input data_en;
input data_in;
output data_out;
reg [3:0] data_out;
reg [3:0] data_out_n;
//时序电路
always@(posedge clk re negedge rst_n)
begin
if(!rst_n)
data_out <= 4'b0;
else
data_out <= data_out_n;
end
//组合电路
always@(*)
begin
if(data_en)
data_out_n = {data_out [2:0] ,data_in};
else
data_out_n = data_out;
end
endmodule
第一个always块描述了一个四位的寄存器。第二个alwas中实现移位操作。{a,b}表示拼接运算符,a=01,b=11,{a,b};结果为0111。下面看是如何移位的。
初始化后data_out为0,当data_in为1时,运行下面的程序,去out的低3位000,再和in拼接,最后输出为0001。第二次运行将in置0,out第三位为001,拼接后为0010。以此类推,实现了移位操作。
计数器
计数器是在FPGA中常用的时序电路。计数器是可以统计输入脉冲个数的时序电路。可以用于计数、定时、分频等多种功能。
计数器的结构由F1、F2、F3和F4四个边沿D触发器,加上三个异或门,两个与门组成的。假设电路的初始状态为0000,也就是四个输出端口Q1Q2Q3Q4为0000。F1的输入信号D是由-Q反馈回来的,Q为0,-Q就为1,F1的输入信号为1。F2的输入信号由Q1和Q2经过一个异或门之后得到。异或门相同出0相异得1。这里异或门的输出为0,F2的输入信号为0。F3的输入信号,由Q1和Q2经过与门再与Q3的值相异或得到。得到F3的输入为0。F4的输入信号由Q1Q2Q3经过一个与门之后得到的输出值,再与Q4的值相异或得到。Q1Q2Q3都是0,得到F4的输入为0。
分析完后,给CLK端口一个上升沿,四个边沿D触发器将会同时触发,当CLK上升沿到来,D触发器的输入值将会锁存,根据逻辑规律,下一刻4个D触发器的输出值就为1000。把Q1当成二进制的最低位,Q4的值当成二进制的最高位。最后得出的数就是0001,也就是十进制的1。计数器接受到了第一个时钟信号的上升沿,输出0001,当收到第二个上升沿计数器会输出二进制数0010,每当电路来一个时钟上升沿,计算器就会做加1运算。每当计数器记到第16个脉冲时,电路状态由1111变回0000完成一个周期循环。所以该电路也成为模16同步加法计数器。所谓同步指该电路中四个D触发器共用一个CLK,可以同时触发,就叫同步。
计数器的应用
一个两位数的秒表可以从0一直累加到59,然后再返回0累加。也就是模60计数器。选择模6计数器加上模10计数器的方法实现,个位显示0到9这10个数,十位显示0到5,6个数,将十位和个位分开进行计数。它的个位数字每间隔1秒变化一次,变化到9的时候,下一刻将会归0,然后重新计数,而十位的数字每间隔10s变化一次,变化到5的时候,它的下一刻也归0。
先将个位数码管和十位数码管分别于模10和模6计数器对应,然后将两个计数器输出信号引出,连接到相应的译码器,通过译码器将数字显示在数码管上。图中两个计数器,时钟信号不是共用的,模10计数器的时钟端,信号的上升沿间隔1s来一次,模6计数器的时钟端,信号的上升沿间隔10s来一次,具体怎么产生需要的时钟信号,就不具体讲了。
利用Verilog来描述计数器
module Digital_counter
(
clk,rst_n
);
input clk;
input rst_n;
reg [3:0] time_cnt;
reg [3:0] time_cnt_n;
//时序电路
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
time_cnt <= 4'b0;
else
time_cnt <= time_cnt_n;
end
//组合电路
always@(*)
begin
if(time_cnt == 4'hf)
time_cnt_n = 4'b0;
else
time_cnt_n = time_cnt + 1'b1;
end
endmodule
时序逻辑电路的设计与分析
在存储电路中根据存储单元改变的特点,可以将时序电路分为同步时序电路和异步时序电路电路。在同步时序电路中,所有存储单元的状态改变在统一的时钟脉冲控制下发生。在异步时序电路中,各存储单元的状态改变不是同时发生的,时钟脉冲只控制存储电路中的部分存储单元,其他则考输入信号或时序电路内部信号来控制。同步设计可以有效的避免毛刺,使设计更可靠,还可以使设计出的同步时序电路更易于分析及实现。目前很多仿真工具都支持同步仿真,所以在设计中一般使用同步设计方法。
时序逻辑电路的分析方法
在讲解分析方法之前,需要先了解三个描述方程。以下面的电路为例。
通过框图可以写出如下方程组。输出方程Z和驱动方程W来描述组合逻辑关系,状态方程描述存储电路的新状态与原状态和驱动信号W之间的关系。三个描述方程可以充分反应时序电路逻辑功能的特点。
在时序电路中根据输出信号的特点可以分为摩尔和米里型两类电路。在摩尔型电路中,输出信号仅仅取决于存储电路的状态;在米里型电路中,输出信号不仅取决于存储电路的状态,也取决于外部输入信号。下面详细讲解。
摩尔型电路的分析方法
分析时序电路,就是研究在一系列输入信号的作用下,将会产生怎样的输出,进而说明逻辑功能。写出电路图的三个描述方程,根据描述方程画出特性表、状态图,总结出时序电路的功能。首先我们分析摩尔型时序逻辑电路。
通过结构图可以看出,该电路只有输出没有输入,为同步摩尔型时序电路,并且由3个D触发器和4个与非门组成。根据结构图写出驱动方程和输出方程。
驱动方程为
输出方程为
根据写出的驱动方程带入D触发器的特性方程可以得出
至此,驱动方程、输出方程和状态方程已全部求出,通过三个方程写出特性表首先将D2、D1、D0取000,那么Q2、Q2、Q0也就为000,,将得出来的值代入状态方程得出状态方程的值,状态方程的值再反回D2,D1,D0,此时D2,D1,D0变为001,再求出新的状态,以此类推列出特性表。
根据特性表来画出状态图。
通过状态图可以很直观的看出状态走向,最后总结出它的逻辑功能,随着CLK脉冲的到来,改电路在7个有效状态中循环变化,而输出Z也在0010111七个数中不断循环。可以看出该电路时一个序列信号发生器,能够输出一个周期的数字序列信号。下面分析米里型时序逻辑电路。
米里型电路的分析方法
米里型逻辑电路的输出信号不仅取决于存储电路的状态,还取决于外部输入信号,因此要将它的输入信号也考虑进去。
通过该电路图可以看出,有一个外部输入信号X,所以为同步米里型时序电路,并且由2个异或、2个与1个非门、一个或门组合而成。写出驱动方程和输出方程。
最后得出状态方程
特性表需要写出Q1的n+1、Q0的n+1和Z的特性表。
根据特性表画出状态图。
当外部输入X等于0时,状态转移按00、01、10、11、00循环变化,可以实现加法计数器功能,当外部输入X等于1时,状态转移按00、11、10、01、00循环变化可以实现模4减法计数器功。
时序逻辑电路的设计方法
时序逻辑电路的设计过程是分析的逆过程,先要给出具体的逻辑功能求出实现这一逻辑功能的逻辑电路。在下面会设计一个简易的自动售货机。
要求该自动售货机只能投入一元硬币,当连续投入三个硬币以后,售货机才会给出一瓶饮料。该电路由一个输入和一个输出,是米里型电路。假设X为一元硬币输入,投入1元为1,未投入为0,Z为饮料输出,送出饮料Z为1,未送出Z为0。假设S0为初态,S1为投入一元后的状态,S2为投入两元后的状态。
下面开始设计,建立状态图是进行成功设计的第一步。根据不同的设计要求找出其对应的逻辑关系并建立出状态图。首先设自动售货机处于S0状态,紧接着投入一个一元硬币,也就是X等于1,电路状态由S0转换到S1,表示已收到1枚硬币。收到一个硬币,饮料不会送出,也就是说Z为0。再投入一枚硬币,X为1,由S1转换到S2状态,收到两个硬币,Z还是为0,当再投入一枚硬币,电路状态由S2转移到S0,饮料送出,Z等于1.结合分析画出状态图。
根据状态图,进行状态编码,在这用到了三个状态,M等于3根据2 n-1<M< 2 n,可以确定触发器个数n=2。利用两个触发器实现三个不同的状态。
其中11为无效状态,根据特性表写出状态方程和输出方程。
根据得出的方程画出电路图。
第一步,通过时序电路写出激励方程、输出方程和状态方程
第二步,通过状态方程列出状态表、画出状态图。
第三步,根据状态表和状态图总结说明电路的逻辑功能。
可编程逻辑器件
可编程逻辑器件PLD(即programmable logic device),pld是专用集成电路的基础上发展出来的一种新型逻辑器件,用户通过软件进行配置和编程,从而完成特定的功能,并且可以反复擦写和修改。下图是PLD的发展历程。
存储器ROM是一种存放固定信息的半导体,存储的信息是制造时由生产商家一次写入的。在工作时只能独处信息,不能写入信息。ROM通常用来存储那些不经常改变的信息。
从电路结构架图可以看出ROM由存储矩阵,地址译码器和输出缓冲器三个组成部分。输出缓冲器能提高存储器的带负载能力,实现对输出状态的三态控制。
可编程只读存储器
为了满足用户根据自己的需要来确定ROM的存储内容,设计出了PROM,可编程只读存储器。写入一次后就不能修改。
EPROM可擦除、可重新编程的只读存储器。想改写需要专用的紫外线灯照射芯片的受光窗口。并且只能整体擦除,不能单独擦除某一存储单元的内容。因此又设计了EEPROM克服了EPROM的缺点,擦除和编程都用电完成,可正片擦除也可独立擦除。
随机存取存储器
随机存取存储器RAM,主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。RAM可以按照需要随意地读写其内部存储单元的内容。它与只读存储器最大的区别就是,随机存储器在断电时,将会丢失其存储内容,而只读存储器不会,所以随机存储器主要用来存储短时间使用的程序。
根据存储单元的工作原理,随机存储器又分为SRAM静态随机存储器和DRAM动态随机存储器。DRAM是用电容有无电荷表示信息0和1,需要周期给电容充电。SRAM利用触发器的两个稳态来表示信息0和1,不需要刷新。SRAM存取速度比DRAM快,价格比DRAM高,所以SRAM一般容量较小,一般用作高速缓冲存储器Cache。DRAM保留数据时间短,速度慢,但比任何ROM都快,一般用作计算器内存。
FPGA和CPLD
复杂可编程逻辑器件CPLD是用户根据各自需要而自行构造扩机功能的数字集成电路。现场可编程门阵列FPGA作为专用集成电路领域中一种半定制电路而出现的。
最后
以上就是个性电源为你收集整理的FPGA基础(数字电路)的全部内容,希望文章能够帮你解决FPGA基础(数字电路)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复