首页资源分类FPGA/CPLDAltera > 2《HELLO FPGA》- 数字电路篇

2《HELLO FPGA》- 数字电路篇

已有 447940个资源

下载专区

FPGA/CPLD热门资源

本周本月全部

文档信息举报收藏

标    签:《HELLOFPGA》

分    享:

文档简介

2《HELLO FPGA》- 数字电路篇

文档预览

封面 前言 为什么要学数字电路篇:数字电路是 FPGA 的敲门砖、垫脚石,为什么这样说呢,因为数 字电路主要的内容就是逻辑和时序,而逻辑与时序就是 FPGA 设计的核心。逻辑无非就是与门、 或门、非门……,时序无非就是锁存器、触发器、寄存器等等,再复杂的设计也就是用这些基本 电路搭起来的,那么我们只有知道了这些基本电路的功能才能搭建出想要的电路。 数字电路篇包含了哪些内容:该篇是从数字逻辑最基础的 0 和 1 入手,以逻辑代数为基础详 细来讲解与门、或门、非门等基本门电路的功能,又以基本的门电路为基础,进一步学习了组合 逻辑电路,其中不同的与或非门组合,可构造出不同的组合逻辑电路,例如编码器、译码器、数 据选择器等。接下来在组合逻辑电路的基础上,我们又进一步了解学习时序逻辑电路,时序逻辑 电路不同于组合逻辑电路,时序逻辑电路能做到组合电路做不到的事情,那就是让电路具有“记 忆”功能,如寄存器、计数器等。最后,我们深入探讨读者最为关心的可编程器件的内部结构和 原理,为进一步学习 FPGA 原理打下了基础。 目录 第一章 数字电路的基础知识 ......................................................................................................... 1 §1.1 数字电路和模拟电路 ......................................................................................................3 §1.2 数制与编码 .....................................................................................................................3 §1.3 逻辑代数.........................................................................................................................4 §1.4 硬件描述语言 .................................................................................................................5 第二章 组合逻辑电路的分析与设计............................................................................................ 11 §2.1 组合逻辑电路的分析方法 ............................................................................................ 13 §2.2 公式化简和卡诺图化简................................................................................................14 2.2.1 公式化简法............................................................................................................15 2.2.2 卡诺图化简法 ....................................................................................................... 16 2.2.3 格雷码...................................................................................................................19 §2.3 组合逻辑电路的设计方法 ........................................................................................... 20 §2.4 竞争与冒险................................................................................................................... 21 2.4.1 冒险现象的产生 .................................................................................................... 21 2.4.2 逻辑冒险的识别与消除 ....................................................................................... 24 2.4.3 功能冒险的识别与消除 ....................................................................................... 26 第三章 组合逻辑电路的应用 .......................................................................................................29 §3.1 编码器...........................................................................................................................31 3.1.1 编码器的原理 ........................................................................................................ 31 3.1.2 编码器的使用方法 ............................................................................................... 33 3.1.3 利用 Verilog 来描述编码器.................................................................................. 35 §3.2 译码器 ......................................................................................................................... 37 3.2.1 译码器的原理 ....................................................................................................... 37 3.2.2 译码器的使用方法 ............................................................................................... 38 3.2.3 利用 Verilog 来描述译码器 ................................................................................. 39 3.2.4 译码器的应用 ...................................................................................................... 40 §3.3 数据选择器................................................................................................................... 41 3.3.1 数据选择的原理 .................................................................................................... 41 3.3.2 数据选择器的使用方法 ....................................................................................... 43 3.3.3 利用 Verilog 来描述数据选择器.......................................................................... 44 §3.4 数值比较器.................................................................................................................. 44 3.4.1 数值比较器的原理 ............................................................................................... 45 3.4.2 数值比较器的使用方法 ....................................................................................... 45 3.4.3 利用 Verilog 来描述数值比较器.......................................................................... 46 §3.5 加法器 ......................................................................................................................... 47 3.5.1 加法器的原理 ....................................................................................................... 47 3.5.2 加法器的使用方法 ............................................................................................... 49 3.5.3 利用 Verilog 来描述加法器 ................................................................................. 49 第四章 时序逻辑电路的基础知识................................................................................................ 51 §4.1 锁存器.......................................................................................................................... 53 4.1.1 RS 锁存器 ............................................................................................................. 53 4.1.2 门控 RS 锁存器 ................................................................................................... 58 4.1.3 D 锁存器 ............................................................................................................... 59 4.1.4 空翻现象 ............................................................................................................... 61 §4.2 触发器 ......................................................................................................................... 62 4.2.1 触发器的原理 ....................................................................................................... 62 4.2.2 利用 Verilog 来描述触发器 ................................................................................. 64 §4.3 寄存器 ......................................................................................................................... 66 4.3.1 寄存器的原理 ....................................................................................................... 66 4.3.2 寄存器的应用 ...................................................................................................... 67 4.3.3 利用 Verilog 来描述寄存器 ................................................................................. 69 §4.4 计数器 ......................................................................................................................... 70 4.4.1 计数器的原理 ....................................................................................................... 70 4.4.2 计数器的应用 ...................................................................................................... 72 4.4.3 计利用 Verilog 来描述计数器 ............................................................................. 73 第五章 时序逻辑电路的设计与分析............................................................................................75 §5.1 时序逻辑电路的分析方法 ........................................................................................... 77 5.1.1 摩尔型电路的分析方法 ........................................................................................ 78 5.1.2 米里型电路的分析方法........................................................................................ 80 §5.2 时序逻辑电路的设计方法 ........................................................................................... 82 第六章 可编程逻辑器件.............................................................................................................. 85 §6.1 第一阶段:存储器....................................................................................................... 87 6.1.1 只读存储器 ........................................................................................................... 87 6.1.2 可编程只读存储器 ............................................................................................... 89 6.1.3 随机存取存储器 ................................................................................................... 90 §6.2 第二阶段:可编程逻辑阵列和可编程阵列逻辑......................................................... 90 6.2.1 可编程逻辑阵列 ................................................................................................... 90 6.2.2 可编程阵列逻辑....................................................................................................91 §6.3 第三阶段:FPGA 和 CPLD ....................................................................................... 92 6.3.1 复杂可编程逻辑器件 ........................................................................................... 92 6.3.2 现场可编程门阵列 ............................................................................................... 94 版权声明 ........................................................................................................................................ 99 数字电路的基础知识 第一章 数字电路的基础知识 §1.1 数字电路和模拟电路 在学习数字电路之前,首先我们要了解什么是数字电路,想要弄明白什么是数字电路,那不 得不提及一下数字信号和模拟信号这两个概念。如图 1.1 所示。所谓模拟信号,就是指随时间连 续变化的信号。比如温度、压力、速度等信号。所谓数字信号,就是指该信号无论从时间上还是 从大小上看其变化都是不连续的,比如人数、产品数等信号。 模拟信号 数字信号 v v O t O t 图 1.1 模拟信号和数字信号 当我们知道了数字信号和模拟信号,我们对数字电路和模拟电路就比较容易理解拉,所谓数 字电路就是处理数字信号的电路,所谓模拟电路也就是处理模拟信号的电路。由于 FPGA 只能 处理数字信号,所以我们这里只需要学习数字电路就可以了,对模拟电路感兴趣的读者可以自己 查找资料进行学习。 §1.2 数制与编码 我们知道了什么是数字电路之后,接下来我们再来说一说数字电路中的数制与编码。首先我 们介绍的是数制。所谓数制,指的是进位计数制,也就是我们通常说的二进制、十进制、十六进 制等常用进制,对于这些常用进制,我相信大家还是能够理解的,我们就不在进一步剖开去讲了。 我们在这里讲一讲它们在 FPGA 中是如何表示的,这里我们就以 Verilog 语言为例。 在 Verilog 中,我们想要表示一个二进制,首先我们要给出二进制数的长度,其次我们还要 给出二进数的标识,最后我们才能给出二进制数值,比如(8’b1000,这里我们表示的是 8 位的 二进制数 1000)。如果我们想要表示一个十进制数,那么我们只需要将二进制数的标识换成十进 制数即可,比如(8’d8),十六进制也是如此,比如(8’h8)。这里读者有两点要注意的,第一点 就是位数和标识是可以省略的,默认的位数是 32 位,默认的进制是十进制;第二点就是数值决 定位数的长度,我们知道数字电路的眼里只有二进制,尽管我们表示的是十进制,十六进制,但 是存入到数字电路里的仍是二进制。 我们知道了二进制,知道了十进制,也知道了十六进制,但是我们不知道十进制是如何变成 二进制的,也不知道十六进制是如何变成十进制的,没关系,不要怕,接下来我们就来解决这个 4 数字电路篇 §1 问题。由于我们这里学习数字电路不是为了应付学校考试,而是为了能够更好、更快的解决实际 问题,所以我们就不需要闭卷、闷头写公式了,我们可以查找资料,也可以借助工具,什么方法 效率高,我们就用什么方法呗。在这里,我们就不介绍书本上的转换方法拉,比如按权展开法, 就不在介绍了,我们这里介绍的是 Windows 自带的程序员计算器,没错,就是它,我们的好朋 友:程序员计算器。我们打开程序员计算器,只需要轻轻敲打几下键盘,点几下鼠标,就可以从 容不迫的进行转换拉。 说完了进制,下面我们再来说一说编码,所谓编码就是以若干二进制数表示一个十进制,这 种二进制编码称为二进制编码的十进制数,简称二-十进制编码,也可以称为 BCD 码(Binary Coded Decimal)。常见的几种编码如表 1.1 所示。 十进制 0 1 2 3 4 5 6 7 8 9 8421 码 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 表 1.1 常见编码 5421 码 2421 码 0000 0000 0001 0001 0010 0010 0011 0011 0100 0100 1000 1011 1001 1100 1010 1101 1011 1110 1100 1111 余3码 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 余 3 循环码 0010 0110 0111 0101 0100 1100 1101 1111 1110 1010 上述的编码规则各不相同,最常用的就属 8421 码,它的编码规则其实就是将二进制数转换 成十进制数,在这里,大家并不需要刻意的去背它,在后面我们用的多了,就自然而然的记住了。 其余的编码这里大家混个脸熟,留下点印象即可,在后面的学习中我们会对用到的编码进行详细 说明。 §1.3 逻辑代数 接下来我们将要学习的逻辑代数是数字电路中的核心重点知识,听到核心重点也许大家会 感到害怕,一般核心重点知识就是比较难的知识,不过这里的逻辑代数知识同前面的基础知识一 样,都是比较简单的基础知识。在逻辑代数中有三种基本的逻辑运算,它们分别是:与、或、非。 这三种基本的逻辑运算可以组合成任意的复杂逻辑运算。 我们在实际应用中为了减少逻辑运算的数目,使数字电路的设计方便,我们通常还使用其他 四种组合运算,它们分别是:与非、或非、异或、同或。下面我们就对这些逻辑运算进行介绍。 为了能让大家更好的对比学习这些逻辑运算,我将它们制作成了表格,如表 1.2 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §1 与 输出 (AND) 输入 00 0 01 0 10 0 11 1 数字电路的基础知识 表 1.2 常见的门电路几种表示方法 或 (OR) 非 与非 (NOT) (NAND) 或非 (NOR) 0 1 1 1 1 1 1 0 1 0 1 0 1 0 0 0 异或 (XOR) 0 1 1 0 国内 & ≥1 =1 & ≥1 =1 电 路 符 号 国外 5 同或 (XNOR) 1 0 0 1 = 通过表格我们可以知道这些逻辑运算的逻辑符号、逻辑表达式和真值表。由于国外的电路符 合和我们国内的电路符号稍微有点不同,所以这里我们将这两种符号都列了出来,方便读者对比 学习。看完了这个表格,相信大家对这些逻辑运算都有了一定的了解。下面我们来看一下它们在 FPGA 中是如何实现和使用的,在介绍它们是如何实现和使用之前,这里我们就先来了解一下硬 件描述语言。 §1.4 硬件描述语言 在 FPGA 的设计中,我们有多种设计方式,如绘制原理图、编写描述语言代码等。早期的 工程师对原理图的设计方式情有独钟,这种输入方式能够很直观的看出电路的结构并快速理解 电路。随着逻辑规模的不断攀升,逻辑电路也越来越复杂,这种输入方式就会显得力不从心,应 付简单的逻辑电路还算实用,应付起复杂的逻辑电路就不行了。因此取而代之的便是编写描述语 言代码的方式,现今的绝大多数设计都是采用代码来完成的。目前主流的硬件描述语言有两种: 一种是 VHDL,另一种是 Verilog。VHDL 发展较早,语法严谨;Verilog 类似 C 语言,语法风格 比较自由。对于初入 FPGA 的新手而言,掌握一种硬件描述语言是必要的。 如果有困难选择症的读者,这里就要开始犹豫了,到底选择哪一种硬件描述语言呢?那么这 里我们就给出一些参考意见,若之前你有一定的 C 语言基础,那么不妨先学 Verilog 硬件描述语 言,这有助于加快对语法本身的理解。在将其中一门语言学精、用熟之后,最好也能够着手掌握 另一门语言。如果没有 C 语言基础但是你想快速入门,那么这里我们仍推荐学习 Verilog,因为 VHDL 硬件描述语言比较难,不容易学习,而 Verilog 硬件描述语言则相对比较容易学习,能够 快速入门。至于到底先学哪一门,还需要读者根据自身的情况做考量。 本书主要以 Verilog 硬件描述语言为主,模块是 Verilog HDL 的基本描述单位,用于描述每 个设计的功能或结构,以及与其他模块通信的外部接口。一个模块可以包括整个设计模块或者设 计模型的一部分,模块的定义总是以关键词 module 开始,以关键词 endmodule 结尾,它的一 般语法结构如代码 1.1 所示。 http://www.fpga.gs/ 6 数字电路篇 §1 代码 1.1 一般的 Verilog 语法结构 1 module 模块名 2( 3 端口名 1,端口名 2,端口名 3,… 4 ); 5 端口类型说明(input,output,inout); 6 参数定义(可选); 7 数据类型定义(wire,reg 等); 8 9 //----------以上为描述接口说明部分----------// 10 //----------以下为描述逻辑功能部分----------// 11 12 实例引用低层次模块和基本门级元件; 13 连续赋值语句(assign); 14 过程赋值语句(initial 和 always) 15 功能描述语句; 16 任务和函数; 17 18 endmodule 看到这里,有的读者也许会皱起眉头接受不了,因为上面给出的这个语法结构不简单呀,可 以说的上是非常复杂的结构了。大家不要着急。这个语法结构看似复杂,其实它并不复杂,我们 只要理解了它,自然而然也就觉得不复杂了。下面我们就来详细的介绍一下上面的语法结构: (1) “模块名”是模块唯一的标示符,括号中以逗号分隔列出的端口名是该模块的输入、输 出端口。 (2) “端口类型说明”为 input(输入)、output(输出)、inout(双向端口)三种类型,凡是在模块 名后面圆括号中出现的端口名都必须明确地说明其端口类型。 (3) “参数定义”是将常量用符号常量代替,以增加程序的可读性和可修改性,它是一个可 选择的语句,用不到可以省略。 (4) “数据类型定义”部分用来指定模块内所用的数据对象是寄存器类型(reg 等)还是连线类 型(wire 等)。 剩下的三个语法:实例引用低层次模块和基本门级元件、连续赋值语句和过程块描述,如果 我们再去讲解它们,那么我相信大家一定会飞上了天,云里雾里的不知所措。下面我们就不在给 出概念了,直接以门电路为例,来看下我们是如何利用 Verilog 描述出一个门电路的。 在数字逻辑中,我们想要表示一个与门,只需要 Y=A·B,或 Y=AB 就可以了。在 Verilog 中,如果我们想要表示一个与门,那么我们只需要利用&&符号便可实现,如果我们想要将结果 输出给 Y,那么我们只需要输入 Y=A&&B 便可实现,下面我们给出与门电路的 Verilog 完整代 码,如代码 1.2 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §1 数字电路的基础知识 7 1 module yumen 2( 3 A,B,Y 4 ); 5 6 input A; 7 input B; 8 output Y; 9 10 assign Y = A && B; 11 12 endmodule 代码 1.2 与门电路的 Verilog 完整代码 下面我们就来简单的介绍一下这段代码,我们从代码中可以看出,这个模块是以关键字 module 开始,以关键字 endmodule 结尾,module 后面的模块名是 yumen,这个模块名的命名 是没有限制的,不过我们这里建议大家,尽量用能够描述整个模块功能的名字去命名它。接下来 我们再来看一下端口,从代码中我们可以看出这里有三个端口,分别是 A,B,Y。尽管我们知 道了有三个端口,但是我们现在并不知道这三个端口是什么类型的,接着往下看,我们便能看到 端口类型说明,这时,我们便知道了 A 和 B 端口为输入端口,Y 端口为输出端口。按照上面的 语法结构,下面就到了数据类型定义,我们再次查看代码会发现,我们代码中没有数据类型定义, 这是怎么回事?在这里,是因为 input 或者 output 默认的数据类型是 wire 型,所以我们将数据 类型定义给省去了,当然,我们也可以给它们再一次定义。比如:wire A,wire B,wire Y;这 里大家要注意了,input 类型只能是 wire,我们一般对 input 类型不做任何数据类型定义。接下 来我们接着看参数定义,由于我们这个 yumen 模块代码比较简单,在这里我们就同样也将参数 定义给省去了。以上我们就将代码中的接口说明部分给介绍完了,接下来我们接着介绍逻辑功能 部分。在逻辑功能部分相信大家看看之前的语法结构,在看看下面的与门代码,相信大家已经猜 个八九不离十了,下面代码中用的就是连续赋值语句 assign,赋值语句 assign 是针对 wire 型变 量的一种赋值语句,wire 型变量一般对应到 FPGA 中的一根线,由于 wire 型的值是会随着驱动 源的变化而变化的,所以我们也将 assign 称为“连续”赋值语句。 小提示:如果大家想要实现其他运算,那么我们只需要利用或(||)符号和非(!)符号就可 以了,那如果我们想要实现一个与非运算,是不是也只需要一个符号就可以实现与非了呢,答案 是不行的,Verilog 中是没有与非、或非、异或和同或这些组合逻辑运算符号的,既然它们是组 合逻辑运算,我们只需要利用与、或、非运算将它们组合出来就可以了,比如这里我们想要实现 一个与非,那么我们就可以这样 Y=!(A&&B)就可以实现与非运算,其他组合逻辑运算也都可以 一一实现。为了让大家能够更好的理解,我们也将其他的两种描述方法给出,让大家能够对比学 习。首先我们给出的是引用低层次模块的基本门级元件。如代码 1.3 所示。 http://www.fpga.gs/ 8 数字电路篇 §1 1 module yumen 2( 3 A,B,Y 4 ); 5 6 input A; 7 input B; 8 output Y; 9 10 and (Y,A,B); 11 12 endmodule 代码 1.3 引用低层次模块的描述方法实现与门电路 小提示:Verilog HDL 内置 26 个基本元件,其中 14 个是门级元件,12 个为开关级元件,这 里只介绍 7 个基本门,and(与)、nand(与非)、or(或)、nor(或非)、not(非)、xor(异或)、 nxor(同或)。 接下来我们给出的是过程块描述方法,如代码 1.4 所示。 代码 1.4 利用过程赋值语句来描述与门电路 1 module yumen 2( 3 A,B,Y 4 ); 5 6 input A; 7 input B; 8 output Y; 9 10 reg Y; 11 12 always @ (A,B) //always @ (*) 13 Y = A && B; 14 15 endmodule 小提示:Verilog 中让人困惑的地方就是 reg 和 wire 的使用,虽然声明 reg 和 wire 的规则 很简单,但是很多新手总是难以理解,不知道什么时候用 reg 类型、什么时候用 wire 类型。其 实它们的使用规则很简单。在 Verilog 中,任何过程赋值的左侧变量必须声明为 reg,除此之外 使用的变量必须声明为 wire,没有其他例外的情况。Verilog 为什么要区分 reg 和 wire 类型呢? 这个问题的答案和数据类型检查有关。如果有人尝试对同一个变量既做连续赋值,又做过程赋值, 那么连续赋值要求用 net 声明,过程赋值,要求用 reg 赋值。但是把同一个变量同时声明为两种 类型,就是语法错误,所以这就保证了设计者不能同一变量使用两种不同类型赋值。 always 和 assign 相对来说,还是 assign 比较容易理解,这里我将 always @ (A,B)详细讲 Zircon Opto-Electronic Technology CO.,Ltd. §1 数字电路的基础知识 9 解一下,@是事件等待语句,意思是 always 不断循环等待 A 和 B 两个敏感变量变化,不管 A 和 B 是从高变低,还是从低变高,都将会执行 always 下面的 Y=A&&B 语句。如果 A 和 B 都没 有变化,那么 always 也将不往下执行,将一直循环等待。新标准可以这样书写 always @ (*), 其解释如下:always @ (*)是个组合逻辑电路的描述方式;是为了防止你在设计时考虑不周全带 来一些操作失误,所以敏感表用*(表示全部的敏感变量),只要有任何输入信号变化,其输出立 即发送变化。 看到这里,我们问大家,上面的代码你们理解了吗?大家会说,理解了,这么简单,不就是 描述一个与门嘛。如果我们这么问:上面的代码你们会了吗?也许大家会说,不会。原因大概有 这么两条,1 是关键字记不住,2 是不知道关键字的语法结构,很可能写出来的代码不符合编译 器的要求。这是正常现象,因为我们没有学习过 Verilog 语言嘛。也许会有的读者问,我们是不 是要将这些关键字背下来才能学会 Verilog 语言。这是没有必要的,我们还是那句话,用多了自 然而然就会了,不管是 Verilog 语言还是 C 语言,或者是 JAVA 语言,它们的语法是死的。单从 语法本身来说,学习 Verilog 并不困难,常用的语法屈指可数(input、output、wire、reg、assign、 always、if、else、case、begin、end),上面的这些关键字相信大家都有见过,它们在我们的后 面的例程中也会反反复复出现。因此,我们在学习 Verilog 语法的时候并不需要花费太多功夫, 只要跟随着我们的例程一步步走,我们给出的代码例程都看懂、理解了,那么在语法方面就已经 足够了,无论多么牛逼的工程师,在他的代码里无非也就是上面一些语法而已。 不过我们在这里要重点强调的是:Verilog 硬件描述语言和我们的 C 语言是大大的不同滴, 我们写 C 语言代码是编程,我们写 Verilog 代码是描述。事实上,我们也可以从硬件描述语言的 名称中也是可以看出的,大家注意硬件描述语言名称中的“描述”两个字,它为什么是描述而不 是设计呢?其主要原因就是硬件描述语言确实不是用来设计电路的,而仅仅是用来描述电路的。 描述这个词精确地反映了硬件描述语言的本质。我们在写 Verilog 代码的时候,大脑里要先想好 完成的具体功能应该用什么样的物理电路去实现,然后再用 Verilog 语言将该电路描述出来,而 不能凭空地去写代码,只有存在的电路才是可物理实现的,Verilog 语言只不过是将这种设计转 化为文字表达形式而已。 还记得我们之前说过的在出现硬件描述语言之前,电路设计一般通过原理图输入的方式实 现,这种设计过程就是我们心中先有了电路,然后再用一种计算机能够识别的方式进行描述,现 在的 Verilog 语言只是相当于我们有了更先进的描述方法,可以从更高的抽象层次对电路进行描 述,不需要用传统的设计方法从门级电路搭起,但是其过程原理还是依然不变的,心中先有电路, 再将它描述成 Verilog 代码。我们只有这样,才能真正的做到代码在屏中,电路在心中。那么接 下来问题来了,我们怎么样才能做到心中先有电路呢?我们现在学习的数字电路便能够很好的 解答这个问题。我们只有把数字电路基础知识学好才能做到心中先有电路。这里我们再一次提醒 大家,本书中的 Verilog 只求理解不求死磕,如果有的读者在学习本书时卡在了 Verilog 代码处, 那么你可以跳过该小节,它不会影响到你后续的学习。 http://www.fpga.gs/ 组合逻辑电路的分析与设计 http://www.fpga.gs/ 第二章 组合逻辑电路的分析与设计 在数字电路中,根据逻辑功能的不同,我们可以将数字电路分成两大类,一类叫做组合逻辑 电路、另一类叫做时序逻辑电路。我们学习数字电路,其实就是学习组合逻辑电路和时序逻辑电 路。接下来我们就来看一看什么是组合逻辑电路,如图 2.1 所示。 X1 Y1 X2 组合逻辑电路 Y2 X3 Y3 图 2.1 组合逻辑电路的示意图 我们从图中可以看出,左侧的 X1 到 X n 是表示它的输入变量,右侧的 Z1 到 Zn 是表示它的 输出变量,对于这种电路,它的输出 Z1 到 Zn 仅仅与当时的输入 X1 到 X n 有关系,而与之前的 输入 X1 到 X n 是没有关系的,像这种电路,我们就称它为组合逻辑电路。 §2.1 组合逻辑电路的分析方法 我们知道了组合逻辑电路之后,接下来我们学习的是如何分析一个组合逻辑电路,这里我们 先不给出分析方法,我们直接给出一个电路图来进行现场分析,大家可以跟着我们的思路一步步 学习,当我们分析完了整个电路,大家也就自然而然的明白了整个分析过程,在这时,我们给出 组合逻辑电路的分析方法,大家也就能够理解,并且融会贯通。下面我们给出组合逻辑电路图, 如图 2.2 所示。 & P2 A B P1 & P3 & ≥1 L C & P4 图 2.2 组合逻辑电路图 首先,我们先将逻辑电路图转换成我们比较容易计算的逻辑表达式,如何转换呢,我们可以 先写出逻辑电路 P1 的逻辑表达式,然后依次再写出 P2 、 P3 、 P4 的逻辑表达式,它们的表达式 分别如下: P1  ABC P3  BP1  B ABC P2  AP1  AABC P4  CP1  C ABC 14 数字电路篇 §2 最终我们便可以得出: L  P2  P3  P4  AABC  B ABC  C ABC  ABC  ABC 从逻辑图一直到逻辑表达式相信读者还都能够理解,但是到了逻辑表达式化简相信读者就 有点摸不着头脑了,这里读者不用担心,我们分析完电路图之后,将会详细说明如何化简。在这 里读者还是先将注意力放在分析电路上。写出了逻辑表达式经过化简后,接下来我们就需要根据 逻辑表达式画出真值表,下面我们给出已经画好的真值表,如表 2.1 所示。 表 2.1 真值表 A B C L 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 从表中我们可以看出三个变量 A,B,C 它们总共有 8 种情况,然后我们只需要将这 8 种情况 依次代入化简后的表达式中,便可得出结果 L。接下来就是最后一步,也是最难的一步,我们需 要从真值表中分析出电路的功能。此电路当三个输入变量 A、B、C 全为 0 或者全为 1 的时候 L 才为 1,因此我们就可以根据真值表总结出电路功能,只有当三个变量一致时,输出才为 1,当 三个变量不一致时,输出就为 0,故称此电路为“一致电路”。 经过前面的电路分析,即使我不给出分析方法,相信读者们也都已经知道了分析方法是什么, 下面我们给出组合逻辑电路的分析方法流程图,如图 2.3 所示。 组合逻辑 电路 逻辑表达式 化简 变换 最简表达式 真值表 逻辑功能 图 2.3 组合逻辑电路的分析方法 接下来我们就来说一说化简,在逻辑电路的分析和设计中,我们经常会遇到逻辑函数化简问 题,化简这一过程本身并不是很难,难点在于除了需要掌握大量的基本公式以外,还需要能够灵 活、交替地运用各种方法,方可求得最简结果。这里我们需要说明的是,新手在入门学习 FPGA 的时候,基本上是用不到化简的,如果有看到公式就会感到头疼的读者可以跳过化简这一小节直 接进入下一小节的学习,当然,你也可以快速大致浏览一遍,在以后的 FPGA 设计中,如果我 们碰到需要化简的时候,我们还可以回过头来再来学习一下化简。 §2.2 公式化简和卡诺图化简 在学习化简之前,也许有的读者会有这么一个疑问,为什么要化简,我们知道同样功能的逻 Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 15 辑函数可以有繁有简不同的表示形式,当表达式复杂时,其对应的数字电路所使用的元器件就会 相应地多一些。当表达形式简单时,其对应的数字电路所使用的元器件就会相应地少一些;因此, 一个简洁的数字电路既有利于节省元器件、降低成本、也有利于减少元器件的故障率、提高电路 的可靠性,给制作带来了方便。为了得到更加简洁的数字电路,我们很有必要对待实现的逻辑函 数首先进行一下化简操作。 2.2.1 公式化简法 想要确保化简的结果是正确的,那么我们在化简中应该遵循化简的基本定律和逻辑代数的 三条规则。下面我们就进一步详细讲解基本定律和三条规则。为了方便大家学习,我将九条基本 定律做成了表格,如表 2.2 所示。 表 2.2 九条基本定律 ①0-1定律 ②自等律 ③重叠律 ④互补律 ⑤交换律 ⑥结合律 ⑦分配律 ⑧反演律 ⑨还原律 这些逻辑代数中的基本定律和我们数学中学过的代数很相似,这些定律都很简单,也是比较 容易理解的。下面我们就来看一看逻辑代数中的三条规则,逻辑代数有三条重要的规则,它们分 别是代入规则、反演规则和对偶规则,下面我们分别进行介绍。 首先我们介绍的是代入规则,这里同样我们不在给出另人抓狂的且还看不懂的官方定义,我 们直接举例进行说明,已知等式 A  B  A B ,有函数 F  B  C ,若 F 代入此等式中的 B , 则有 A  (B  C)  A B  C ,这就是我们所说的代入规则。 接下来我们介绍的是反演规则,同代入规则一样,我们直接上例子, F1  A  (B  C) ,如 果我们 F1 中的所有的运算符、常量及变量作如下变换    、    、 0 1、1  0 、原变 量  反变量、反变量  原变量,那么 F 2  A (B C) , F1 与 F 2 互为反函数,这个就是我们 所说的反演规则。 最后要介绍的就是对偶规则了,下面我们给出对偶的例子,F1  A B  C ,如果我们 F1 中 的所有的运算符、常量及变量作如下变换    、   、0 1、1  0 这里注意了变量是不 变,那么 F 2  A  B C , F1 与 F 2 互为对偶式,这个就是我们所说的对偶规则,这时我们在 返回去看九条定律,你会发现每一条定律的两个式子都是互为对偶式的,所以,有了对偶规则, 使得我们需要记忆的公式数目就减少了一版。 这里我们要注意一点,一般情况下, F '  F ,其中 F ' 是 F 的对偶式, F 是 F 的反函数, http://www.fpga.gs/ 16 数字电路篇 §2 只有在某些特殊情况下,F '  F ,例如异或表达式 F  AB  AB ,F '  (A  B)(A  B) ,而 F  (A  B)(A  B) ,所以 F '  F 。 看完了基本定律和三条规则,我们仍然不能进行化简,因为我们还要学习一些公式化简的方 法,公式化简中常用的几种方法总结如下。 (1) 并项法:利用公式 AB  AB  A ,将两项合并为一项,并消去因子 B 和 B 。 (2) 吸收法:利用公式 A  AB  A,消去多余项。 (3) 消项法:利用公式 AB  AC  BC  AB  AC ,消去多余项。 (4) 消因子法:利用公式 A  AB  A  B ,消去多余的变量因子 A 。 (5) 配项法:利用 A1  A和 A  A  1,为某项配上一个变量,以便用其它方法进行化简。 至此,公式化简法就已经讲完拉,在实际应用中可能遇到比较复杂的函数式,只要熟练掌握 逻辑代数的定律和规则,并且灵活运用上述方法,总能把函数化简成最简。下面我们就以分析电 路的逻辑表达式为例进行练手,看一看是如何化简的: L  AABC  B ABC  C ABC (利用分配律)  ABC(A  B  C) (利用反演律)  ABC  ABC 看到这里,相信读者能够理解最后一步是如何得到的,并且已经知道了上述定律规则和方法 的重要性,不理解的也不要灰心,公式化简法可不是看一遍就能够学会的,它需要大量的实战练 习才能融会贯通、收放自如。 2.2.2 卡诺图化简法 通过上面的公式化简学习,我们可以看出公式化简法使用不方便、不易判断是否已简化到最 简形式,技巧性较高,对使用者的要求较高,并且它还只能用于一些逻辑表达式比较简单的函数。 接下来我们介绍的卡诺图化简法可以更简单、直接的得到逻辑函数的最简表达式,因此逻辑函数 的卡诺图化简法在实际分析、设计电路时有很广泛的应用。在讲解卡诺图之前,我们需要了解一 下最小项。 所谓最小项,就是该乘积项在输入随机的情况下,结果为 1 的可能性最小,下面我们举例进 行说明,有两个变量 A 、 B ,它们可以构成许多乘积项,在它们构成的乘积项中有四个乘积项 需要我们特别注意,它们分别是 AB 、AB 、AB 、AB ,这四个乘积项就是我们所说得最小项, 对于上述的四个乘积项来说,输入的组合情况有 4 种,但是对于每一个最小项来说,仅有 1 种输 入情况能够使其为 1。通过上面的例子我们可以总结出以下 3 条规律: (1) n 个变量最多可构成 2n 个最小项。 (2) n 个变量构成的每个最小项,一定是包含 n 个因子的乘积项。 (3) 在各个最小项中,每个变量必须以原变量或反变量形式作为因子仅出现一次。 根据上面的规律我们很容易的就能写出三个变量 A 、B 、C 的所有最小项。下面我们给出 三变量全部最小项,如表 2.3 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 17 编号 表 2.3 三变量最小项的真值表 000 001 010 011 100 101 110 111 10000000 01000000 00100000 00010000 00001000 00000100 00000010 00000001 为了便于书写和识别,我们对最小项进行了如上编号,通过上表我们可以看出以下 4 条性 质: (1) 每个最小项只有对应的一组变量取值能使其值为 1。 (2) n 个变量的全体最小项之和恒为 1。 (3) n 个变量的任意两个不同的最小项之积恒为 0。 (4) 相邻的两个最小项之和,可以合并成一项,并消去一个因子。 对于第(4)条性质,这里我们需要重点说明一下,因为在卡诺图化简中我们会用的到,这 里的相邻不是几何位置的相邻,而是指逻辑上相邻。这里我们举例进行说明, 三变量最小项 ABC 和 ABC 它们的几何位置上是不相邻的,但是它们的逻辑上是相邻的,因为它们之中只有 一个因子不同,前项中有 A ,后项中有 A ,其余因子完全相同,于是这两项相加可以合并成一 项,并消去那个不同的因子, ABC  ABC  BC 。 至此,最小项的概念已经讲完了,不过有一点我们要在这里提一下,有最小项,同样就会有 最大项,由于最大项在我们这里并不实用,这里我们就不在进行讲解。下面我们就要进行卡诺图 的讲解,所谓卡诺图,就是把真值表中的最小项重新排列,把它们排列成矩阵形式,并且矩阵的 横方向和纵方向上的布尔变量需要按照格雷码的顺序进行排列,这样构成的图形就是卡诺图,对 于格雷码我们将会在讲解完卡诺图之后进行详细说明。下面我们分别给出了二变量、三变量和四 变量的卡诺图,如图 2.4 所示。 B A 01 BC C CD A 00 01 11 10 AB 0 1 AB 00 01 11 10 0 0 00 00 1 1 01 01 11 11 10 10 图 2.4 二变量、三变量和四变量卡诺图 http://www.fpga.gs/ 18 数字电路篇 §2 老样子,我们还是先举例子然后在分析,这里我们就以 F  m3  m4  m5  m6  m7 。首先 我们根据逻辑表达式 F 画出其对应的卡诺图,如图 2.5(a)所示。 C AB 0 1 00 C AB 0 1 00 01 1 01 1 11 1 1 10 1 1 11 1 1 10 1 1 (a) 图 2.5 (a)没有化简的卡诺图 (b) (b)化简后的卡诺图 得到卡诺图以后,我们便可以在卡诺图中画出其相邻变量,具体操作如图 2.5(b)所示,画 出了相邻变量后,我们便可以进行逻辑化简了,首先我们先来看一看图中的大圈,从图中我们便 可以看出大圈中的 4 个最小项最终合并成 A ,不知道技巧的读者想要看出 A 来还是有难度的, 下面我们就来简单说明一下这个小技巧,由于这个大圈只覆盖了 AB 变量的 11 和 10 取值, C 变量的 0 和 1 取值,那么其他地方的取值我们就不需要观察了,又由于 AB 变量中 11 和 10 取值 是相邻变量,那么只有相同的才会保留,相反的将会合并掉,所以 AB 变量将保留 A 变量,消 去 B 变量。而 C 变量同 AB 变量方法相同,因此只留下了 A 变量。 如果小技巧不太容易理解,那么我们还可以利用下面的方法进行合并相邻项。从大圈中我们 可以得到 4 个最小项,它们分别是 m6  m7  m4  m5 ,即 ABC  ABC  ABC  ABC ,我们 将相邻变量进行合并可以得出: AB(C  C)  AB(C  C)  AB  AB  A(B  B)  A 。 接着我们利用同样的方法将小圈中的相邻项进行化简,由于小圈只覆盖了 AB 变量的 01 和 11 取值,C 变量的 1 取值,那么在 AB 变量中合并最小项可得出 B ,而 C 变量只有 1 取值,所 以最终结果便为 BC ,最后将大圈得出的结果或上小圈得出的结果就是逻辑表达式的最简结果, 即 F  A  BC 。 通过前面的学习我们可以知道,卡诺图化简法其难度主要在如何圈出相邻项,那么下面我们 便给出如何圈出相邻项的口诀,只要遵循这个口诀就能得出最简逻辑表达式,其口诀就是“圈子 要少,圈子要大”,所谓“圈子要少、圈子要大”就是利用最少、最大的圆圈来覆盖掉所有为 1 的 最小项。 除了遵循上面所讲的化简口诀和化简步骤以外,我们还需要注意一下几个问题: (1) 所有的圈必须覆盖全部标 1 方格。 (2) 每个圈中包含的相邻小方格数,必须为 2 的整数次幂。 (3) 为了得到尽可能大的圈,圈与圈之间可以重叠一个或 n 个标 1 方格。 (4) 每个圈中至少有一个标 1 方格未被其它圈所覆盖。 下面我们给出了几个典型的卡诺图画圈参考图,在碰到不知道如何画圈的时候可以参考这 Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 19 几个图来进行画圈。如图 2.6 所示。 CD CD CD CD AB 00 01 11 10 AB 00 01 11 10 AB 00 01 11 10 AB 00 01 11 10 00 1 0 0 1 00 0 1 0 0 00 0 1 1 0 00 1 1 1 0 01 0 1 1 0 01 1 1 1 1 01 1 0 0 1 01 0 0 1 0 11 0 1 1 0 11 0 1 0 0 11 1 0 0 1 11 0 1 0 0 10 1 0 0 1 10 0 1 0 0 10 0 1 1 0 10 1 0 0 1 图 2.6 卡诺图画圈参考图 至此,卡诺图化简法就已经告一段落了,下面我们就来说一说格雷码。 2.2.3 格雷码 格雷码又叫循环二进制码或反射二进制码,它的基本特点就是任意两个相邻的代码只有一 位二进制数不同, 举个例子来说吧,如果用一个 8 位的二进制数来表示温度,温度是不断连续 变化的,36℃、37℃、38℃,那么温度每升高一度,二进制数就加 1。这时候,二进制数有可能 是多个位同时变化的,比如当温度由 39℃变成 40℃时,那么二进制数就会由 100111(39℃)变 化成 101000(40℃),有四个位发生变化;当温度越高,数字变化的位数也就越多,每个位变化 的频率也是较高的,这在特定的情况下,是十分不利的,有可能会导致电路状态错误或输出错误 的结果,而使用格雷码可以避免这种错误,由于格雷码具有循环特性和单步特性,当用它表示一 个连续变化的数值时,仅有一个位会翻转,大大的降低了位变化的频率,因而可以保证传输的稳 定性,较少传输误码率。 格雷码的单步特性就是是指,当格雷码表示的一个数值连续变化时,格雷码只有一个位会变 化,如表 2.4 所示,1000 变到 0000,格雷码只有一位翻转,这就是刚才我们说的它最基本的特 点。 十进制 0 1 2 3 4 5 6 7 二进制 0000 0001 0010 0011 0100 0101 0110 0111 表 2.4 格雷码 格雷码 十进制 0000 8 0001 9 0011 10 0010 11 0110 12 0111 13 0101 14 0100 15 二进制 1000 1001 1010 1011 1100 1101 1110 1111 格雷码 1100 1101 1111 1110 1010 1011 1001 1000 大家看一下这个表,有没有发现二进制转为格雷码的规律,看上去,格雷码似乎很乱,其实 它有着独特的规律的,只是我们不易发现。现在我们先来看二进制转换为格雷码的过程,也就是 编码,这里我们就以二进制 0111 转换为格雷码 0100 为例: http://www.fpga.gs/ 20 数字电路篇 §2 (1) 二进制第一位的 1 和第二位 1 异或得到 0,得到的结果就是格雷码的第一位。 (2) 二进制第二位的 1 与第三位 1 异或得到 0,得到的结果就是格雷码的第二位。 (3) 二进制第三位的 1 与第四位 0 异或得到 1,得到的结果就是格雷码的第三位。 (4) 二进制第四位的 0 将保持不变,作为格雷码的第四位。 最后,我们完成了转换,得到了格雷码 0100。下面我们来看下如何将格雷码转换成二进制: 这里我们就以格雷码 0101 转换为二进制 0110 为例: (1) 格雷码第四位 0 将保持不变,作为二进制的第四位。 (2) 格雷码第三位 1 和第(1)步骤中的结果 0 异或得 1,得到的结果就是二进制的第三位。 (3) 格雷码第二位 0 与第(2)步骤中的结果 1 异或得 1,得到的结果就是二进制的第二位。 (4) 格雷码第一位 1 与第(3)步骤中的结果 1 异或得 0,得到的结果就是二进制的第一位。 至此,我们的支线任务就已经做完拉,接下来我们要回到我们的主线任务组合逻辑电路的设 计方法上。 §2.3 组合逻辑电路的设计方法 下面我们将要学习的是如何设计一个组合逻辑电路,通过前面的学习我们知道,分析组合逻 辑电路是根据给定的组合电路逻辑图,分析出其逻辑功能。那么设计组合逻辑电路就是分析组合 逻辑电路的逆过程,我们要根据给定的逻辑功能要求,设计出一个能实现这种功能的最简逻辑电 路。同分析组合逻辑电路一样,我们举例进行说明,这里我们以三人表决器为例进行详细说明。 首先我们要根据设计要求建立该逻辑函数的真值表,这里我们设 A、B、C 分别代表参加表 决的三个输入变量,L 为表决结果。规定变量 A=1、B=1、C=1 表示赞成,反之表示不赞成;L=1 表示多数赞成,即通过,反之表示不通过。故可列出真值表,如表 2.5 所示。 表 2.5 三人表决器真值表 A B C L 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 1 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 接下来我们便可以通过真值表写出函数表达式,我们将 L=1 的结果分别取出并相或即可组 成函数表达式,L  ABC  ABC  ABC  ABC ,得出了函数表达式我们需要将函数表达式进 行化简,我们可以用公式法化简也可以用卡诺图法化简,由于的函数表达式比较简单,这里我们 就利用公式化进行化简,我们利用并项法 A A1 将上述函数表达式进行化简, L  (A  A)BC  A(B  B)C  AB(C  C) ,最后化简得出 L  BC  AC  AB 。 Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 21 根据最后化简的函数表达式,我们画出三人表决器的逻辑图,逻辑图如图 2.7 所示。 A B & C & ≥1 L & 图 2.7 三人表决器的逻辑图 经过前面的学习,我们自己想要设计出一个电路还是很简单的,看到这里相信大家也都能理 解,下面我们给出组合逻辑电路的设计方法流程图,如图 2.8 所示。 实际逻辑 问题 真值表 逻辑表达式 化简 变换 最简(或者最 合理)表达式 逻辑图 图 2.8 组合逻辑电路的设计方法 至此,组合逻辑电路的分析和设计就已经讲完了,下面我们就来看一看组合逻辑电路中的竞 争与冒险。 §2.4 竞争与冒险 我们在分析和设计组合逻辑电路时,竞争与冒险是我们所遇到的一大问题,根据其产生的原 因不同,我们又可分为逻辑竞争、逻辑冒险和功能竞争、功能冒险。接下来我们就来看一看什么 是竞争,什么是冒险,逻辑竞争、逻辑冒险和功能竞争、功能冒险又有什么区别,它们是如何产 生的,我们又是怎么消除它们,下面我们将会一一进行详细的讲解说明。 2.4.1 冒险现象的产生 在我们讲解竞争和冒险之前,我们要先了解一个简单的概念,一般来说像我们前面所分析和 设计的门电路,都是把门电路看做成理想门电路,也就是说,这个电路它本身是没有延迟时间, 但是在实际电路中,输入信号通过每一个门电路然后输出,它总是要有传输时间的,那么这个就 叫做门电路的传输时间或是延迟时间。 接下来我们就要进入正题,讲解什么是竞争,所谓竞争就是在一个组合电路当中,当某一个 变量经过两条以上的路径到达输出端的时候,由于每条路径上的延迟时间的不同,不一样,到达 终点的时间就会有先有后,那么这一现象我们就称作竞争,这里的竞争我们也可以称为逻辑竞争。 下面我们通过更直观的电路图,来详细说明什么是逻辑竞争,如图 2.9 所示。 http://www.fpga.gs/ 22 数字电路篇 §2 G1 A 1 G2 & L 图 2.9 电路图 通过这个逻辑电路图我们可以看出,输入变量 A 一端是连接到了 G1门上,延迟了一个时间 以后,才能到达 G2 门的输入端,而输入变量 A 的另一端则是直接连接到了 G2 门的输入端,因 此,我们可以说同一个信号 A ,它是经过两个路径分别到达 G2 门,它由于经过两个路径,而且 每条路径上的延迟时间是不一样的,那就说明,这两个信号到达 G2 门输入端是有先有后的,所 以说这么一个现象就称作逻辑竞争。 那什么又是冒险呢,所谓冒险就是在具有竞争现象的组合电路中,当某个变量发生变化的时 候,比如说从 1 跳到 0,或者说从 0 跳到 1,如果真值表所描述的逻辑关系或者功能遭受到短暂 的破坏,在输出端它就会出现一个不应有的这么一个尖脉冲,这个尖脉冲也称作毛刺,那么这么 一种现象就叫冒险,这里的冒险我们也可以称为逻辑冒险,逻辑冒险是一个错误的输出,那么下 面我们依旧是通过上面的电路图来分析这个逻辑冒险是怎么产生的。 首先,我们根据上面的电路图写出表达式, L  A A ,然后我们再根据这个表达式写出真 值表,如表 2.6 所示。 表 2.6 真值表 AA L 0 1 0 1 0 0 从真值表中我们可以看到这个输出变量是恒等于 0 的,我们根据真值表画出它的波形图,如 图 2.10(a)所示。 A A A A L L tp (a) (b) 图 2.10(a)理想状态的波形图 (b)实际状态的波形图 从图 2.10(a)中我们可以更直观的观察到 L 恒等于 0,这个波形就是一个理想状态的波形 图,前面我们也说过实际电路中每一个门电路它都是有延迟时间的,那么我们就将这个延迟时间 记作 tp,然后根据延迟时间 tp,我们画出实际状态的波形图,如图 2.10(b)所示。 Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 23 从图 2.10(b)中我们可以看出, A 信号经过了一个 G1非门,由于 G1非门它有一个延迟 时间 tp,所以 A 并不是立刻变为 0,而是经过一个延迟时间 tp 以后,它才能变为 0,按照与的 逻辑功能,当 A 等于 1, A 等于 1 时,那么 L 就会等于 1,但是这个 L 并不会立刻输出 1,因为 A 和 A 还要经过一个 G2 与门的延迟以后才会输出 1。因此,这个电路的输出端 L 也经过了一 个延迟 tp 以后才输出 1。 在实际状态波形图中,出现这种 L 等于 1 的波形,相当于在电路中产生了一个尖脉冲,是不 符合我们逻辑表达式的要求,是一个错误的波形,因此,我们把这种出现错误波形的现象称为逻 辑冒险,又因为产生的是一个正的尖脉冲,所以我们通常称这种逻辑冒险为“1 型冒险”。 接下来我们继续回到图 2.10(b)的分析之中,我们刚刚分析了前半段波形,现在我们就来 分析后半段波形,同样当 A 变为 0 以后, A 也不是立刻变为 1,它也要经过一个延迟 tp 以后才 会变成 1, A 和 A 总是要滞后一个延迟时间,但是在后面三条虚线内的波形中,尽管也出现了 逻辑竞争,但是并没有出现错误输出,由此可以说明,有逻辑竞争的地方不一定有逻辑冒险。 既然有 1 型冒险,那么想必不用说我们也会知道肯定也会有 0 型冒险,同上面的 1 型冒险分 析方法一样,这里我们就不在进行分析,直接给出 0 型冒险的电路图,如图 2.11 所示。 G1 A 1 G2 ≥1 L 图 2.11 0 型冒险的电路图 根据电路图我们写出 0 型冒险的逻辑表达式 L  A  A ,根据表达式在画出它的真值表, 如表 2.7 所示。 表 2.7 0 型冒险真值表 AA L 0 1 1 1 0 1 我们通过真值表画出带有延迟 tp 的波形图,如图 2.12 所示。 A A L 图 2.12 0 型冒险的波形图 在图 2.12 中,出现这种 L 等于 0 的波形,是不符合我们逻辑表达式的要求,是一个错误的 波形,因此,我们把这种出现错误波形的现象称为逻辑冒险,又因为产生的是一个负的尖脉冲, 所以我们通常称这种逻辑冒险为“0 型冒险”。通过了前面的学习,相信读者对逻辑竞争和逻辑 http://www.fpga.gs/ 24 数字电路篇 §2 冒险都有了一个全新的认识,那么下面我们就来揭开功能竞争和功能冒险的神秘面纱。 在逻辑竞争和逻辑冒险的学习中,大家有没有注意到一个问题,在我们所讲的情况中,不管 是 0 型冒险,还是 1 型冒险,它们的输入变量只有一个,说到这里机智的读者是不是明白了点什 么,在这里我们还要对功能竞争和功能冒险特别说明一下,由于功能冒险是由电路的逻辑功能决 定的,因此 所谓功能竞争,就是当多个变量经过两条以上的路径到达输出端时,同样的也会产生竞争, 那么我们就把这种竞争称为功能竞争,在具有功能竞争的组合电路中,也同样会产生冒险,那么 我们则把这种冒险称为功能冒险。下面我们举例进行详细说明,如图 2.13 所示。 A B L A L B A B L tp (a) 图 2.13(a)1 型冒险 A B L tp (b) (b)0 型冒险 从图 2.13(a)中我们可以看出,对于与门,若稳态时 A  1 , B  0 或 A  0 , B  1 时, 输出恒为 L  0 。但是在信号的传输过程中,由于传输时间不同,造成在时间 tp 内,出现了一 个错误的波形,出现这种 L 等于 1 的波形,是不符合我们逻辑表达式的要求,是一个错误的波形, 因此,我们把这种出现错误波形的现象称为功能冒险,又因为产生的是一个正的尖脉冲,所以我 们通常称这种功能冒险为“1 型冒险”。 从图 2.13(b)中我们同样也可以看出,对于或门也会出现同与门一样的情况,只不过这里 出现的是负的尖脉冲,因此我们也可以称它为“0 型冒险”。 2.4.2 逻辑冒险的识别与消除 1. 逻辑冒险的识别 通过前面的学习,我们知道了竞争与冒险的概念,并且还知道了它们是如何产生的,接下来 我们学习的就是如何从我们设计的电路中找出竞争与冒险,只有找出它们,我们才能对症下药。 首先我们讲解的是逻辑冒险的识别与消除,我们想要识别一个组合电路是否存在逻辑冒险,通常 有两种方法来判别,一种为代数法,另一种为卡诺图法。接下来我们就对它们分别进行讲解。 首先我们要说的是代数法,所谓代数法就是根据电路图写出其逻辑表达式,在该逻辑表达式 中当某些逻辑变量取特定值 0 或 1 时,如果逻辑表达式能转换为 A A ,则该电路存在 1 型冒险, 若逻辑表达式能转换为 A  A ,则该电路存在 0 型冒险。下面我们举例进行说明,如图 2.14 所 Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 25 示。 B & C & ≥1 L A & 图 2.14 存在 0 型冒险的电路图 从图 2.14 中我们可以写出该电路图的逻辑表达式为 L  AC  BC ,在该逻辑表达式中,若 输入变量 A  B  1,则有 L  C  C ,因此我们便可以断定该电路存在 0 型冒险。 接下来我们再来看一看卡诺图法,所谓卡诺图法就是根据逻辑表达式画出其卡诺图,在该卡 诺图中,若输入变量在卡诺圈内改变时,则输出不会有冒险现象,若输入变量是在相邻卡诺圈的 相邻处发生变化,并且是从一个卡诺圈进入另一个卡诺圈,则有可能产生逻辑冒险现象。下面我 们同样以 L  AC  BC 为例进行说明,我们这里就直接给出该电路所对应的卡诺图,如图 2.15 所示。 C AB 0 1 00 01 1 11 1 1 10 1 0 图 2.15 卡诺图识别逻辑冒险 从卡诺图中我们可以看出,当 A  1 、C  0 , B 由 0 1时,此时的变化是在卡诺圈内变 化,所以不会出现冒险,同理,当 B  C  1, A 由 0 1时,也是在卡诺圈内变化,故也不会 出现冒险。但是当 A  B  1,C 从 0 1时,相当于输入变量 A 、B 、C 从 110 变化到 111, 此时的变化是从一个卡诺圈变化进入另一个卡诺圈,故如前所述,该电路输出存在冒险现象。 2. 逻辑冒险的消除 逻辑冒险可以通过电路的重新设计来消除,若在函数表达式中增加冗余项(相当于在卡诺图 中增加多余的卡诺圈),则其既不改变函数的逻辑功能,又可消除逻辑冒险,缺点是增加了电路 结构的复杂性。下面我们举例进行说明,在之前的学习中我们知道 L  AC  BC ,存在冒险现 象,根据公式我们可以在其逻辑表达式中增加一个乘积项 AB ,使其变为 L  AC  BC  AB , 因此在原来产生冒险的条件 A  B  1 时, L  1将不会产生冒险。这函数增加了乘积项后,已 不在是最简函数表达式,故这种乘积项我们也可以称为冗余项。下面我们就来看一下卡诺图如何 http://www.fpga.gs/ 26 数字电路篇 §2 消除逻辑冒险,如图 2.16 所示。通过卡诺图我们可以看出,我们通过增加了多余的卡诺圈以消 除冒险现象。 C AB 0 1 00 01 1 11 1 1 10 1 0 图 2.16 卡诺图消除逻辑冒险 这里值得注意的是,消除逻辑冒险的方法不仅仅只有这一种方法,我们还可以通过增加选通 信号或增加输出滤波电容来消除逻辑冒险,这里我们就不在进一步对它们进行讲解。下面我们就 来看一看功能冒险是如何识别并消除的。 2.4.3 功能冒险的识别与消除 1. 功能冒险的识别 对于功能冒险的识别我们通常采用卡诺图来进行判别,下面我们同样举例进行说明,如图 2.17 所示的卡诺图。 CD AB 00 01 11 10 00 0 1 0 0 01 1 1 1 1 11 1 0 1 1 10 0 0 0 0 图 2.17 卡诺图识别功能冒险 从卡诺图中我们可以看出, ABCD  0001时, F  1;若 ABCD 由 0001 变化到 0111 , 即 B 由 0 1,C 也由 0 1,则变化后函数 F 的稳定值也为 1,由于输入变量 B 、C 实际上 不可能绝对同时变化,它们的变化总是有先有后的,若 B 先变,则变化途径为 0001  0101  0111,相对应的输出 F 变化为1 1 1,此时没有冒险现象,但若 C 先变, 则变化途径为 0001  0011  0111,相对应的输出 F 变化为1  0 1,因此出现了 0 型冒 险。再有,如 ABCD由 1111 变化到 0110 时,其变化途径为 1111 1110  0110 或者 1111 0111 011,0 这时, F 的变化均为1 1 1,可见此时不产生冒险。 经过上面的分析我们可以知道,若电路具有下列三点,则其输出可能产生功能冒险: Zircon Opto-Electronic Technology CO.,Ltd. §2 组合逻辑电路的分析与设计 27 (1) 有两个以上变量同时发生变化(如果仅有一个输入变量发生变化,则无功能冒险); (2) 变化前后,输出稳态值保持不变; (3) 在由 n ( n  2 )个变量发送变化的 2n 个方格中,既要有 0,又要有 1;(如果对应 2n 个变量取值组合的输出值全为 1 或全为 0,电路是不会产生功能冒险的)。 2. 功能冒险的消除 功能冒险是由于在输入 n 个变量同时变化时,它们的实际变化在时间上有先有后引起的,因 此改变电路的逻辑设计并不能消除功能冒险。对待功能冒险常用的方法是增加选通信号或者增 加输出滤波电容方法。至此,第 2 章组合逻辑电路的分析与设计我们就已经讲完了。 http://www.fpga.gs/ 组合逻辑电路的应用 第三章 组合逻辑电路的应用 由于我们在生活中会遇到各种各样的逻辑问题,所以我们会设计各种各样的逻辑电路来解 决我们所遇到的逻辑问题,然而我们发现,其中有些逻辑电路反复、大量地出现在我们设计的组 合逻辑电路中。这些逻辑电路主要有编码器、译码器、数据选择器、数值比较器和加法器等。为 了使用方便,我们便将这些逻辑电路制成了中规模集成电路模块,当我们设计功能较为复杂的逻 辑电路时,我们便可以调用这些中规模集成电路模块,来作为我们设计电路的组成部分,因此可 以帮助我们简化设计、提高效率。下面我们就分别来介绍一下这些电路的工作原理和使用方法, 以便我们能够直接使用。 §3.1 编码器 首先我们讲解的是编码器,编码器其实就是人与电子设备之间一座沟通的桥梁,为什么这样 说呢,下面我们举例说明,比如计算机的键盘,它上面有很多的符号,我们常用的 26 个字母 (ABCD……)、我们常用的数字键(0123456789),还有标点符号等等,这些都是一些特定的 信息,但是对于计算机来说,它并不认识什么是 A、什么是 B、什么是 5678,而计算机它只认 识 0 和 1,为此我们便利用 0 和 1 组成的代码来表示这些特定的字母和数字,例如,用 01000001 来表示字母 A。建立这种代码与信息一一对应关系的过程称为编码,那么完成这种编码的电路便 叫做编码器。 3.1.1 编码器的原理 编码器在我们日常生活中是经过遇到的,比如电视机遥控器上的键盘输入、密码锁和银行出 纳台上密码输入都属于编码器。编码器有互斥编码器和优先编码器之分。所谓互斥编码器就是任 何时刻只允许一个输入信号有效,否则将产生错误输出。所谓优先编码器就是允许多个输入信号 同时有效,输出是对优先级别高的输入信号进行编码。 下面我们先来看看互斥编码器,我们这里就以 8-3 互斥编码器为例进行讲解,所谓 8-3 编 码器就是可以实现 3 位二进制代码对 8 个信号进行编码的电路,那么这个电路应该有 8 个输入 和 3 个输出,这里我们就根据 8-3 编码器的性质,设计一个 8-3 编码器的电路该怎么做呢?通 过上一章的学习,我们知道如何设计一个 8-3 编码器,第一步我们应该先根据给出的逻辑功能 写出真值表,8-3 编码器的逻辑功能就是分别把 8 个互斥的输入信号,编成一个对应的 3 位二 进制代码。那么,我们就可以对这 8 个输入信号和 3 个输出信号进行定义,我们可以将 8 个输 入信号分别定义为 I0 、 I1 、 I2 、 I3 、一直到 I7 ,将 3 个输出信号定义为 A0 、 A1 和 A2 ,又由 于每一个互斥的输入信号为 1 时,将输出一个对应的 3 位二进制码,且这个 3 位的二进制码不 能重复,所以我们可以进行如下的定义,当 I0 输入为 1 时, 或者说 I0 为高电平时,那么它对应 的 3 个输出就是 111,这里的 111 看成是一个三位的二进制数,当 I1 输入为 1 时,对应的 3 个输 出为 110,当 I2 输入为 1 时,对应的 3 个输出为 101,以此类推直至到 I7 的输入为 1 的时候。 对应的三个输出为 000。根据这个规律我们就可以写出这样的一个真值表了,如表 3.1 所示。 32 数字电路篇 §3 表 3.1 8-3 互斥编码器的真值表 输入 输出 I0 I1 I2 I3 I4 I5 I6 I7 A2 A1 A0 00000001000 00000010001 00000100010 00001000011 00010000100 00100000101 01000000110 10000000111 那么有了真值表以后,我们就可以根据真值表,写出其逻辑表达式,在之前的章节中我们学 习过将含有一个输出变量的真值表如何写出表达式,那就是将这个输出变量所有可能等于 1 的 情况相或起来,就可以写出它的表达式了,那么现在我们碰到了有三个输出的真值表,这里我们 只需要照葫芦画瓢,利用同样的方法将这三个输出变量的表达式写出即可,它们的表达式如下: A0  I0  I2  I 4 I6 A1  I0  I1  I4  I5 A2  I0  I1  I2  I3 通过表达式我们可以看出,每个输出变量的结果都是由若干个输入变量通过相或之后得到 的。那么如果要根据这些函数式画出逻辑图的话,我们就可以先画出三个或门符号,再根据函数 式的逻辑规律,将这些输入变量通过连线,经过对应的或门之后与其对应输出变量相连,这样就 画出最终的电路图了,如图 3.1 所示。 A2 A1 A0 ≥1 ≥1 ≥1 I7 I6 I5 I4 I3 I2 I1 I0 图 3.1 互斥编码器的电路图 这个电路图看起来复杂,其实功能并不复杂,只是输入端口和输出端口比较多而已。通过对 8-3 互斥编码器的设计,我们对具有互相排斥输入的编码器已经有了一个了解,那么下面我们对 上面已经得到的 8-3 编码器进行修改,使之成为一个 8-3 优先编码器。 Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 33 3.1.2 编码器的使用方法 前面我们提到过,优先编码器是去除了输入互相排斥这一特殊的约束条件,它允许在某一时 刻多个输入端为有效电平,但只对优先级最高的输入信号进行编码。那么首先我们可以去除上例 中的约束条件,即允许多个输入端同时为有效电平,并规定输入信号优先级的高低次序为 I7 、 I6 、 I5 、 I4 、 I3 、 I2 、I1 、 I0 ,其中 I7 的优先级最高, I0 的优先级最低。根据这样的条件, 我们就可以列出这个 8-3 优先编码器的真值表了。如表 3.2 所示。 表 3.2 8-3 优先编码器的真值表 输入 输出 I0 I1 I2 I3 I4 I5 I6 I7 A2 A1 A0 XXXXXXX1000 XXXXXX10001 XXXXX100010 XXXX1000011 XXX10000100 XX100000101 X1000000110 10000000111 其实在实际的工作中,8-3 优先编码器的功能都是由现成的中规模集成电路模块来完成的, 很少会需要我们自己用门电路搭出来,其中 74148(SN74LS148)芯片就是一种常用的 8-3 优 先编码器,我们根据这个芯片厂家(德州仪器 TI)提供的芯片手册(datasheet)就可以知道它 的管脚说明、真值表、电路图、等等信息了,如图 3.2 所示。 http://www.fpga.gs/ 34 数字电路篇 §3 图 3.2 德州仪器 TI 的 SN74LS148 芯片手册 由于内容过多,并且 datasheet 在网上是公开的可以随时下载(www.alldatasheet.com), 这里我们就不给出太多内容,只给出部分截图。这里需要注意的是,由于国内的 IC 行业被老外 甩得比较远,所以我们看到的芯片手册基本上都是英文文档的,想要找到一本中文的文档是非常 困难的,即使找到了中文的文档,细细研究后你会发现里面是漏洞百出,有时和原文意思相去甚 远。如果英语不太好的人刚开始看英文文档那是很痛苦的,但是我们要坚持,当我们看的越多时, 你会慢慢发现,datasheet 里的英文词汇也就那么些,翻来覆去地用,当你看习惯了后仔细想想 也就那么回事,所以,我们推荐大家一定要看原版的 datasheet。下面我们在 74148 的 datasheet 中找到它的真值表,为了方便大家和之前设计的 8-3 优先编码器的真值表对比学习,这里我们 将 74148 的 datasheet 中的真值表稍作修改,如表 3.3 所示。 表 3.3 74148 的真值表 输入 I0 I1 I2 I3 I4 I5 I6 I7 1XXXXXXXX1 0111111111 0XXXXXXX00 0XXXXXX010 0XXXXX0110 0XXXX01110 0XXX011111 0XX0111111 0X01111111 0011111111 输出 EO 1111 1110 0001 0101 1001 1101 0001 0101 1001 1101 Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 35 这个真值表看起来和我们刚刚得到的 8-3 优先编码器的真值表有些不一样,其实它完成的 也是 8-3 优先编码器的功能。只不过之前的真值表表示的是输入为高电平有效,而这里的真值 表表示的是输入低电平有效。在 74148 里,输入信号为 I0 ~ I7 ,输出信号为 A0 ~ A2 ,并且 它们均是以低电平为有效。在输入信号中 I7 的优先级最高,然后依次是 I6 、 I5 … I0 。74148 这个芯片的输入管脚还增加了一个 EI ,而输出管脚增加了 EO 、及 GS 。那么这多出的三个管 脚,是干什么用的呢,其中, EI 做为使能输入端使用,也就是说这个管脚可以控制芯片工作状 态,低电平为工作,高电平为不工作,EO 为扩展输出端,高电平有效,用于多个芯片连接扩展, 这个的用法我们后面会详细讲。 GS 为编码器的工作标志,低电平表示这个编码器在正常工作, 高电平表示这个编码器没有正常工作。 3.1.3 利用 Verilog 来描述编码器 学完了编码器的原理,知道了编码器的使用方法,接下来我们就来看看如何利用 Verilog 来 描述我们的编码器。下面我们废话不多说,直接上代码,如代码 3.1 所示。 代码 3.1 编码器的 Verillog 代码 1 module Digital_Encoder 2( 3 I,A 4 ); 5 6 input [7:0] I; 7 output [2:0] A; 8 9 reg [2:0] A; 10 11 always @ (*) 12 begin 13 case(I) 14 8'b0000_0001 : A = 3'b000; 15 8'b0000_0010 : A = 3'b001; 16 8'b0000_0100 : A = 3'b010; 17 8'b0000_1000 : A = 3'b011; 18 8'b0001_0000 : A = 3'b100; 19 8'b0010_0000 : A = 3'b101; 20 8'b0100_0000 : A = 3'b110; 21 8'b1000_0000 : A = 3'b111; 22 default: A = 3'b000; 23 endcase 24 end 25 26 endmodule 在上面这个代码中,除了我们不认识的关键字,剩下的关键字我们都认识,如果之前你看过 http://www.fpga.gs/ 36 数字电路篇 §3 与门的代码,那么你就会认识以下关键字:module、input、output、reg、wire、always、还有 endmodule。剩下的 begin、case、default、endcase、end 是新增加的,我们没有见过的。接 下来我们就来带大家过一遍代码。 老规矩 module 关键字打头阵,紧接着是我们的模块名,由于我们描述的是编码器,所以我 们给模块起了一个 Encoder(Encoder 翻译过来就是编码器,我就是找度娘翻译的)。模块名之 后就是我们的端口名,我们可以看到有两个端口名,一个是 I,一个是 A(为什么要叫 I 和 A 呢? 我们参考的编码器真值表中的输入和输出),到这里都是一帆风顺,没有不理解的地方,然后我 们继续往下走,接下来我们来看端口类型说明,看到这里,我们发现了新花样,有的读者就会蒙 了,不知道这是几个意思了,镇定镇定,我们知道编码器,它是有 8 个输入和 3 个输出,按照常 规的写法,我们可以写八个输入分别是 I0、I1、I2、I3、I4、I5、I6、I7 和三个输出 A0、A1、A2, 这种写法是不是感觉很累,如果有 100 个输入,我们是不是要敲 100 个!为了解决这种问题, 我们还有另外一种写法,就是我们这种 input [7:0] I,它代表的意思就是 I0、I1、I2、I3、I4、I5、 I6、I7。知道了这是什么意思之后,我们继续往下看,接下来我们看的就是数据类型定义,也就 是代码中的第 9 行,在这里大家有没有明白这里为什么要用 reg 类型?如果不明白,那么这次 就要记住了,因为我们用的是过程赋值语句 always。如果是连续赋值语句 assign,那么我们用 到的就是 wire 型,当然我们还可以省略掉,因为变量默认类型的就是 wire 类型。说完了数据类 型定义,我们接下来就进入 always 关键字,这里的 always @ (*)相信大家都能够理解了,我们 在与门代码的时候专门提到过,这里我们来看看 begin 关键字。begin 关键字和 end 这两个关键 字是成对出现的,比如大括号“(”可以看做是 begin,大括号“)”可以看做是 end。只要被 begin 和 end 也就是这个括号括起来的语句,它们都是顺序执行的。被 module 和 endmodule 这个括号括起来的语句,它们都是并行执行的。我们举个例子:如果一个 begin 和 end 中有两 条语句,那么这两条语句在前面的先会被执行,前面的这个语句执行完毕之后再去执行后面的这 条语句。如果一个 module 和 endmodule 中有两个 always 模块,这两个 always 模块是没有先 后顺序的,它们是同时执行的。接下来我们再来看看 case 关键字,case 是一种多分支选择语 句,比如我们的输入 I7=0、I6=0、I5=0、I4=0、I3=0、I2=0、I1=0、I0=1(也就是 I=8’b00000001) 时,我们的输出便会输出 A2=0、A1=0、A0=1(也就是 A=3’b000)。case 和 endcase 也是成 对出现的。default 的关键字的意思是:如果上述条件都不符合,那么就会执行 default 中的 A=3’b000 这条语句,也就是说,如果我们的输入出现了 I=8’b00000011 或 I=8’b10000001 等情况,那么都会执行 defalut 中的语句。到这里,相信大家对上面的关键字都有所了解了吧, 看完了关键字,接下来我们再来看看这个模块的功能(尽管我们已经知道了这个模块的功能是编 码器),我仔细观察 case 里的那几条语句,我们会发现,这和编码器真值表很像,没错,我们这 段代码描述的就是编码器真值表。当然,我们还可以描述编码器的逻辑表达式和逻辑电路图来实 现编码器,由于篇幅有限,我们这里就不在给出,读者可以自行尝试。 知道了编码器的代码,接下来我们再来看看优先编码器,如代码 3.2 所示。优先编码器同编 码器的代码基本上差不多,唯一不同的是,我们这里使用的是 if 关键字,接下来我们就对 if 这部 分内容进行一个详细介绍,我们直接来看代码的第 11 行,这行语句的意思是如果输入 I7 等于 0, 那么便会执行 A=3’b000,如果 I7 不等于 0,那么就不会执行 A=3’b000,而会执行下面的第 11 行中的 else if 语句。如果 I6 同样也不等于 0,那么将会依次往下执行直至判断 I0 等不等于 0, Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 37 如果 I0 也不等于 0,那么将会执行 else 中的 A = 3’b000 这条语句。我们从这个过程中可以看 出,I7 的优先级最高,我们先判断的 I7,依次 I6,直至 I0。 代码 3.2 优先编码器的 Verilog 代码 1 module Digital_Priority_Encoder 2( 3 I,A 4 ); 5 input [7:0] I; 6 output [2:0] A; 7 reg [2:0] A; 8 9 always @ (*) 10 begin 11 if(I[7] == 1'b0) A = 3'b000; 12 else if(I[6] == 1'b0) A = 3'b001; 13 else if(I[5] == 1'b0) A = 3'b010; 14 else if(I[4] == 1'b0) A = 3'b011; 15 else if(I[3] == 1'b0) A = 3'b100; 16 else if(I[2] == 1'b0) A = 3'b101; 17 else if(I[1] == 1'b0) A = 3'b110; 18 else if(I[0] == 1'b0) A = 3'b111; 19 else A = 3'b000; 20 end 21 22 endmodule 通过上述的这些讲解,相信大家对编码器有了一定的了解,那么编码器的讲解就告一段落了, 下面我们开始介绍另一种组合逻辑模块,译码器。 §3.2 译码器 通过前面的学习,我们知道了在编码时,每一组代码都具有了特定的含意,即表示一个确定 的信息,而译码则是编码的逆过程,是把每一组代码的含意翻译出来的过程,完成译码功能的逻 辑电路就被称为译码器,译码器通常用于计算机中对存储单元的地址的译码。 3.2.1 译码器的原理 这里我们同编码器一样,首先尝试设计一个 3-8 译码器。译码器的设计过程同编码器一样, 编码器有 8 个输入,3 个输出,而译码器与之恰恰相反有 3 个输入,8 个输出,在编码器里 I0 输入为高电平,其对应的是输出就是 111,而在译码器里,输入为 111,其对应的输出 I0 就为高 电平,依次类推,我们就可以写出 3-8 译码器的真值表,如表 3.4 所示。 http://www.fpga.gs/ 38 数字电路篇 §3 表 3.4 3-8 译码器的真值表 输入 输出 A2 A1 A0 I0 I1 I2 I3 I4 I5 I6 I7 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 从真值表中我们可以看出,编码器和译码器的逻辑功能正如我们先前所说正好相反。接下来 我们便根据真值表来写出它的逻辑函数表达式,由于这里的方法同编码器一样,我们就不在详细 说明,直接给出它的逻辑函数表达式: I0  A2 A1 A0 I4  A2 A1 A0 I1  A2 A1 A0 I2  A2 A1 A0 I3  A2 A1 A0 I5  A2 A1 A0 I6  A2 A1 A0 I7  A2 A1 A0 最后我们便能根据逻辑函数表达式画出 3-8 译码器的电路图,如图 3.3 所示。 I0 I1 I2 I3 I4 I5 I6 I7 & & & & & & & & 1 1 1 1 1 1 A0 A1 A2 图 3.3 3-8 译码器的电路图 这个电路图也同编码器一样看起来很复杂,其实功能并不复杂,只是输入端口和输出端口比 较多而已。接下来我们就来看一看译码器的集成电路模块 74138。 3.2.2 译码器的使用方法 Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 39 同编码器 74148 一样,译码器也有着相对应的集成电路模块 74138,74138 是一种应用广 泛的典型译码器,这里我们不在给出 74138 的 datasheet 截图,想要进一步学习的读者可以自 行下载。下面我们直接给出 74138 的真值表,如表 3.5 所示。 表 3.5 74138 的真值表 G1 X1 XX 0X 10 10 10 10 10 10 10 10 输入 A2 A1 A0 XXXX1 1XXX1 XXXX1 00000 00011 00101 00111 01001 01011 01101 01111 输出 1 2 3 4 5 6 7 1111111 1111111 1111111 1111111 0111111 1011111 1101111 1110111 1111011 1111101 1111110 从真值表中我们可以看到 A2 、A1 、A0 为 3 位二进制代码输入端,因此会有 8 种( 23  8 ) 组合输出,即可译出 8 个输出信号 Y0 ~ Y7 ,输出为低电平有效,对应每一组二进制输入代码, 只有其中一个输出为低电平,其余输出均为高电平。此外,我们还可以看到真值表中还多出了 G1 、 G2A 、 G2B 三个使能输入端,只有当 G1  1、 G2A  0 、 G2B  0 时,74138 译码器才能正常 工作。 3.2.3 利用 Verilog 来描述译码器 学完了译码器的原理,知道了译码器的使用方法,接下来我们同编码器一样,也来看看如何 利用 Verilog 来描述我们的译码器。废话不多说,直接上译码器的代码,如代码 3.3 所示。 代码 3.3 译码器的 Verilog 代码 1 module Digital_Decoder 2( 3 A,I 4 ); 5 6 input [2:0] A; 7 output [7:0] I; 8 9 reg [7:0] I; 10 11 always @ (*) 12 begin 13 case(A) http://www.fpga.gs/ 40 数字电路篇 §3 14 3'b000 : I = 8'b01111111; 15 3'b001 : I = 8'b10111111; 16 3'b010 : I = 8'b11011111; 17 3'b011 : I = 8'b11101111; 18 3'b100 : I = 8'b11110111; 19 3'b101 : I = 8'b11111011; 20 3'b110 : I = 8'b11111101; 21 3'b111 : I = 8'b11111110; 22 default: I = 8'b11111111; 23 endcase 24 end 25 26 endmodule 我们刚开始看到这些代码,那是既陌生又害怕,而现在我们再看到这些代码,是不是感觉有 点既熟悉又亲切了,相信用不了几次,大家对这些老面孔,忘都忘不掉了。由于这些代码都比较 简单,并且我们也知道了这个代码模块所要表达的功能思想,所以我们在这里就不一一进行讲解 了,大家要自行揣摩和领悟(别走火入魔了)。在这里我们提醒大家,对照着真值表去看代码会 有其他功效呦,还有一点就是,大家不要仅限于看,在看懂的前提下,我们还要去动手实践一下, 你可以模仿我们的这个代码,你也可以自己描述一个 4-16 译码器,你在模仿或者是描述新的译 码器的过程中,一定要注意代码风格,一定要注意代码风格,一定要注意代码风格,重要的事情 说三遍。通过上述的这些讲解,相信大家对译码器有了一定的了解,下面我们再来介绍一下译码 器的应用。 3.2.4 译码器的应用 下面我们来介绍一个译码器的经典应用,七段显示译码器。我们常说的数码管,它就是将七 个发光二极管,按一定的方式排列起来,利用不同发光段的组合,显示出 0~9 十个十进制数, 如图 3.4 所示。 g f COM a b a f g b e c d DP e d COM c DP 图 3.4 七段发光二极管示意图 下面重点来了,驱动七段数码管显示的译码器称为 BCD 七段显示译码器,通过它将 BCD 码变换成十进制数并在数码管上显示出来。该译码器有四个输入端七个输出端。前者输入待显示 的 BCD 码,后者分别接到七段数码管的对应接线端,每输入一组 BCD 码,译码器便会有确定 Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 41 信号从输出端输出,它的真值表如表 3.6 所示。 表 3.6 七段显示译码器的真值表 输入 输出 显示 A3 A2 A1 A0 a b c d e f g 00001111110 0 00010110000 1 00101101101 2 00111111001 3 01000110011 4 01011011011 5 01100011111 6 01111110000 7 10001111111 8 10011110011 9 10101110111 A 10111111111 B 11001001110 C 11010111101 D 11101001111 E 11111000111 F 我 们 根 据 其 真 值 表 可 以 看 出 , 当 输 入 信 号 A3 A2 A1A0  0000 , 其 输 出 信 号 abcdefg 1111110 ,将点亮的 abcdefg 对应到实际的数码管上,刚好显示为 0 ,这就是数码 管能显示数字的原因。那么在后面我们正式开始进行 FPGA 设计的时候,如果要用 FPGA 控制 数码管的话,也是利用了这里七段显示译码器的思想。 §3.3 数据选择器 说完了译码器,下面我们再来介绍数据选择器,在介绍数据选择器之前我们要先知道什么是 数据选择,所谓数据选择就是从多个输入的逻辑信号中选择一个逻辑信号输出,实现数据选择功 能的逻辑电路便成为数据选择器。数据选择器也称为多路复用器,它的作用相当于多个输入的单 刀多掷开关。 3.3.1 数据选择的原理 老规矩,我们还是从设计开始,只有经过了思考,并设计出数据选择器,我们才能真正的了 解数据选择器的原理。这里我们以 8-1 数据选择器为例,下面我们给出 8-1 数据选择器的功能 示意图,如图 3.5 所示。 http://www.fpga.gs/ 42 数字电路篇 §3 3-8译码器 A0 A1 A2 DDDDDDDD01234567 Y 图 3.5 8-1 数据选择器示意图 从图中我们看出, D0 ~ D7 为数据输入端,Y 为输出端, A0 、 A1 、 A2 为 3-8 译码器的输 入端, A0 、 A1 、 A2 地址码经过 3-8 译码器译码,产生有效信号,来控制八个开关,最终选择 一路数据输出。我们根据以上分析,可以轻易的写出 8-1 数据选择器的真值表,如表 3.7 所示。 表 3.7 8-1 数据选择器的真值表 译码器输入 译码器输出 Y输出 A2 A1 A0 I0 I1 I2 I3 I4 I5 I6 I7 0 1 0 0 0 1 0 0 0 0 0 0 0 D0 D0 0 0 1 0 1 0 0 0 0 0 0 D1 D1 0 1 0 0 0 1 0 0 0 0 0 D2 D2 0 1 1 0 0 0 1 0 0 0 0 D3 D3 1 0 0 0 0 0 0 1 0 0 0 D4 D4 1 0 1 0 0 0 0 0 1 0 0 D5 D5 1 1 0 0 0 0 0 0 0 1 0 D6 D6 1 1 1 0 0 0 0 0 0 0 1 D7 D7 我们从真值表中可以看出,当 A0 A1A2  000 时,输出 I0 为高电平,其余为低电平,对应高 电平的开关闭合,而对应低电平的开关则仍保持断开,因此, Y 的输出为 D0 ,当 D0  0 时, Y  0 ,当 D0  1时, Y  1。下面我们可以根据真值表来写出它的函数表达式: Y  D0 A2 A1 A0  D1 A2 A1A0  D2 A2 A1 A0 D3 A2 A1A0  D4 A2 A1 A0  D5 A2 A1A0 D6 A2 A1 A0  D7 A2 A1A0 下面我们就可以画出它的电路图,如图 3.6 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 43 D0 D1 D2 D3 D4 D5 D6 D7 A0 1 1 A1 1 1 & & & & ≥1 Y & & & & A2 1 1 图 3.6 8-1 数据选择器电路图 从逻辑图中我们可以看出,它只是在 3-8 译码器的基础上添加了 8 个数据输入端 D0 ~ D7 和一个或门。 3.3.2 数据选择器的使用方法 接下来我们介绍集成数据选择器,74151 是一种典型集成 8 选 1 数据选择器,我们给出其对 应的真值表,如表 3.8 所示。 表 3.8 74151 数据选择器的真值表 输入 数据选择 A2 A1 A0 X X X 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 使能 1 0 0 0 0 0 0 0 0 输出 Y Y 0 1 D0 D0 D1 D1 D2 D2 D3 D3 D4 D4 D5 D5 D6 D6 D7 D7 从真值表我们可以看出,它多出了一个使能输入端 G ,当 G 为 1 时,数据选择器不能正常 工作,当 G 为 0 时,数据选择器可以正常工作。其余功能和我们自己设计的八选一数据选择器 http://www.fpga.gs/ 44 数字电路篇 §3 一致,这里我们就不啰嗦拉。 3.3.3 利用 Verilog 来描述数据选择器 学完了数据选择器的原理,知道了数据选择器的使用方法,接下来我们就来看看如何利用 Verilog 来描述我们的数据选择器。下面我们废话不多说,直接上代码,如代码 3.4 所示。 代码 3.4 数据选择器的 Verilog 代码 1 module Selector 2( 3 A,D0,D1,D2,D3, 4 D4,D5,D6,D7,Y 5 ); 6 input D0,D1,D2,D3,D4,D5,D6,D7; 7 input [2:0] A; 8 output [7:0] Y; 9 10 reg [7:0] Y; 11 12 always @ (*) 13 begin 14 case(A) 15 3'b000 : Y = D0; 16 3'b001 : Y = D1; 17 3'b010 : Y = D2; 18 3'b011 : Y = D3; 19 3'b100 : Y = D4; 20 3'b101 : Y = D5; 21 3'b110 : Y = D6; 22 3'b111 : Y = D7; 23 default: Y = 1'b0; 24 endcase 25 end 26 27 endmodule 从代码中我们可以看出,该代码和我们的译码器代码基本是一致的,唯一不同的在于输出的 值,译码器中我们输出的是八位二进制数,而数据选择器中我们输出的是 D0、D1、D2、D3、 D4、D5、D6、D7。通过上述的这些讲解,相信大家对数据选择器有了一定的了解,那么数据选 择器的讲解就告一段落了,下面我们开始介绍另一种组合逻辑模块,数值比较器。 §3.4 数值比较器 讲完了数据选择器,下面我们再来介绍一下数值比较器,所谓数值比较器就是对两个数 A、 B 进行比较,以判断其大小的逻辑电路。比较结果有 A>B、A=B、AB 0 0 1 0 输出 FA B3 A3 < B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 A3 = B3 输 A2 B2 × × A2 > B2 A2 < B2 A2 = B2 A2 = B2 A2 = B2 A2 = B2 A2 = B2 A2 = B2 A2 = B2 A2 = B2 A2 = B2 A1 B1 × × × × A1 > B1 A1 < B1 A1 = B1 A1 = B1 A1 = B1 A1 = B1 A1 = B1 A1 = B1 A1 = B1 入 输出 A0 B0 × IA>B IAB FA B0 × × × 1 0 0 A0 < B0 × × × 0 1 0 A0 = B0 1 0 0 1 0 0 A0 = B0 0 1 0 0 1 0 A0 = B0 × × 1 0 0 1 A0 = B0 1 1 0 0 0 0 A0 = B0 0 0 0 1 1 0 我们从真值表中可以看出,输出变量 FAB 、 FAB 、 FAB 是总的比较结果,输入变量 A3 、 A2 、 A1 、 A0 和 B3 、 B2 、 B1 、 B0 是两个相比较的四位二进制数, I AB 、 I AB 、 I AB 是另外 两个低位数比较结果。该低位数比较结果输入端是为了与其他数值比较器连接,以便扩展成更多 位数值比较器。如果只比较两个四位数,应将 I AB 和 I AB 接低电平, I AB 接高电平。 接下来我们分析一下真值表,两个相比较的四位二进制数 A3 A2 A1A0 和 B3B2B1B0 ,应从最 高位开始,若 A3  B3 或者 A3  B3 ,则不管低位数值如何,必有 A  B (或者 A  B );若 A3  B3 ,则需要比较次高位,依次类推逐位进行比较,最终,我们就可以完成比较了。 3.4.3 利用 Verilog 来描述数值比较器 学完了数值比较器的原理,知道了数值比较器的使用方法,接下来我们就来看看如何利用 Verilog 来描述我们的数值比较器。下面我们废话不多说,直接上代码,如代码 3.5 所示。 代码 3.5 数值比较器的 Verilog 代码 1 module Digital_Comparator 2( 3 A,B,F 4 ); 5 input [3:0] A; 6 input [3:0] B; 7 output [2:0] F; 8 reg [2:0] F; 9 10 always @ (*) 11 begin 12 if(A > B) 13 F = 3'b001; 14 else if(A == B) Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 47 15 F = 3'b010; 16 else 17 F = 3'b100; 18 end 19 20 endmodule 通过上述的这些讲解,相信大家对数值比较器有了一定的了解,那么数值比较器的讲解就告 一段落了,下面我们开始介绍另一种组合逻辑模块,加法器。 §3.5 加法器 数字信号的算术运算主要是加、减、乘、除四个类型,而加运算为最基础,因为其他的几种 运算都可以分解成若干步加法运算进行。所以加法器是算术运算的基本单元电路。 3.5.1 加法器的原理 加法器可以分为半加器和全加器。那什么是半加器呢,如果仅仅考虑两个一位二进制数 A 和 B 相加,而不考虑低位的进位,则称为半加,实现半加运算的电路叫做半加器。半加器有两个输 入端 A 和 B,两个输出端 S 和 C,其中 S 为和,C 为向高位的进位。我们根据逻辑功能写出其 对应的真值表,如表 3.11 所示。 表 3.11 半加器的真值表 输入 输出 A B S C 0 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1 由真值表我们写出它的逻辑函数表达式: S  AB  AB  A B C  AB 我们再根据逻辑函数表达式给出它的电路图,如图 3.8 所示。 A =1 S B & C http://www.fpga.gs/ 48 数字电路篇 §3 图 3.8 半加器的电路图 由于半加没有考虑低位的进位,所以仅半加是不能解决加法问题的,那么我们就需要了解全 加器。下面我们通过一个例子来分析什么是全加。大家看图 3.9 所示的式子。 1101 1111 + 11110 被加数Ai 加数Bi 低位向高位的进位Ci-1 + 11100 和值Si 图 3.9 全加器原理示意图 从图中我们可以看出,两个四位二进制数相加,其中 1101 为被加数 Ai ,1111 为加数 Bi ,而 11110 则是低位向高位的进位 Ci1 ,在相加过程中,除最低位以外,其余各位既要考虑本位的相 加,又要考虑低位向本位的进位 Ci1 。因此,所谓全加就是将 Ai 、 Bi 、 Ci1 、这三个变量进行 相加,求出 Si 及本位向高位的进位 Ci 。这样能够实现全加运算的逻辑电路叫做全加器,因此, 我们便可以写出全加器的真值表,如表 3.12 所示。 表 3.12 全加器的真值表 输入 Ai Bi Ci-1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 输出 Si Ci 0 0 1 0 1 0 0 1 1 0 0 1 0 1 1 1 由真值表我们写出它的逻辑函数表达式: Si  Ai BiCi1  Ai Bi Ci1  Ai Bi Ci1  Ai BiCi1  ( Ai Bi  Ai Bi )C i1( Ai Bi  Ai Bi )Ci1 Ci  Ai BiCi1  Ai BiCi1  Ai Bi Ci1  Ai BiCi1  Ai Bi  ( Ai B i  Ai Bi )Ci-1 我们再根据逻辑函数表达式给出它的电路图,如图 3.10 所示。 Ai Bi =1 =1 Si C i-1 & ≥1 Ci & 图 3.10 全加器的电路图 Zircon Opto-Electronic Technology CO.,Ltd. §3 组合逻辑电路的应用 49 要进行多位数相加,最简单的方法是将多个全加器进行级联,称为串行进位加法器,如图 3.11 所示。 C3 S3 S2 S1 S0 Ci Si ∑ Ai Bi Ci-1 Ci Si ∑ Ai Bi Ci-1 Ci Si ∑ Ai Bi Ci-1 Ci Si ∑ Ai Bi Ci-1 A3 B3 C2 A2 B2 C1 A1 B1 C0 图 3.11 串行进位加法器的电路图 A0 B0 C-1 两个 4 位相加数 A3、A2、A1、A0 和 B3、B2、B1、B0 的各位同时送到相应全加器的输入端, 进位数串行传送。全加器的个数等于相加数的位数。最低位全加器的 Ci-1 端应接 0。 串行进位加 法器的优点是电路比较简单,缺点是速度比较慢。因为进位信号是串行传递,最后一位的进位输 出 C3 要经过四位全加器传递之后才能形成。如果位数增加,传输延迟时间将更长,工作速度更 慢。 为了提高速度,我们又设计了一种多位数快速进位(又称超前进位)的加法器。所谓快速 进位,是对普通的全加器进行改良而设计成的并行加法器,主要是针对普通全加器串联时互相进 位产生的延迟进行了改良,各级进位信号可以同时送到各位全加器的进位输入端。现在的集成加 法器,大多采用这种方法。下面我们就来介绍一下采用多位数快速进位的 74F283 集成加法器。 3.5.2 加法器的使用方法 74F283 是运用超前进位的 4 位二进制全加器,由于 74F283 的真值表过于庞大,这里我们 列举出两个进行讲解,从真值表中我们可以看出,A3、A2、A1、A0 是一组加数,B3、B2、B1、B0 为另一组加数,S3、S2、S1、S0 为和,C0 为低位进位信号,C4 为高位的进位信号。从真值表的第 一行表格中我们可以看出,C0=0,A3A2A1A0 为 1010,对应十进制的 10。B3B2B1B0 为 1001,对应 十进制的 9,则 S3S2S1S0 变为 0011,对应十进制的 3,C4 为 1,因此 A+B 等于 9+10=19,S+C4 等于 3+16=19。从真值表第二行表格中我们可以看到 C0=1,A3A2A1A0 为 0101,对应十进制的 5。 B3B2B1B0 为 0110,对应十进制的 6,则 S3S2S1S0 变为 1100,对应十进制的 12,C4=0,因此 C0+A+B 等于 1+5+6=12,S+C4 等于 12+0=12。 表 3.13 74F283 加法器的真值表 输入 输出 C0 A3 A2 A1 A0 B3 B2 B1 B0 S3 S2 S1 S0 C4 01010100100111 10101011011000 3.5.3 利用 Verilog 来描述加法器 学完了加法器的原理,知道了加法器的使用方法,接下来我们就来看看如何利用 Verilog 来 http://www.fpga.gs/ 50 数字电路篇 §3 描述我们的加法器。下面我们废话不多说,直接上代码,如代码 3.6 所示。 1 module Digital_Adder 2( 3 A,B,S 4 ); 5 6 input [3:0] A; 7 input [3:0] B; 8 output [3:0] S; 9 10 reg [3:0] S; 11 12 always @ (*) 13 begin 14 S = A + B; 15 end 16 17 endmodule 代码 3.6 加法器的 Verilog 代码 从上面的代码中我们可以看出,该代码是没有考虑进位及溢出情况的。当相加结果超过 4’hF 时,最高位(进位输出)丢失。小提示:Verilog HDL 中绝大多数运算操作符都是可以直 接使用的,比如:+(加)、-(减)、*(乘)、/(除)、!(逻辑非)、~(取反)、&(与)、~&(与 非)、|(或)、~|(或非)、^(异或)、~^(同或)、%(取模)、<<(逻辑左移)、>>(逻辑右移)、 <(小于)、<=(小等于)、>(大于)、>=(大等于)、==(等于)、!(逻辑不等于)、&&(逻辑与)、 ||(逻辑或)。 以上我们主要讲解了组合逻辑电路中编码器、译码器等功能模块,这里大家需要理解它们的 设计思路,在将来我们进行 FPGA 设计时会用得到。下面我们将会介绍的是时序逻辑电路。 Zircon Opto-Electronic Technology CO.,Ltd. 时序逻辑电路的基础知识 第四章 时序逻辑电路的基础知识 通过前面的学习,我们知道了组合逻辑电路是没有记忆功能的,也就是说在任何时刻产生的 输出信号都仅仅取决于该时刻电路的输入信号。而与它以前的输入信号是无关的。恰恰时序电路 与组合电路相反,时序电路是有记忆功能的,它在任何时刻的输出,不仅与该时刻的输入信号有 关,而且还与该时刻以前的输入信号有关。这样说,听起来可能有点绕,那么下面我们举一个实 际的例子,来说明一下。有一台自动售货机,它有一个投币口,并且它规定只允许投入一元面值 的硬币。如果一罐饮料的价格为三元,那么当顾客连续投入三个一元的硬币后,机器将输出一罐 饮料。机器之所以能在第三枚硬币投入后输出一罐饮料,是因为当我们每次投入一枚硬币时,机 器都能将这些投币信息记录下来,那么这样的记忆功能,就是由机器内部的时序电路来实现的。 下面我给大家看一张时序电路的示意图,如图 4.1 所示。 X1 Z1 Xi 组合电路 ZJ … … … … Q1 W1 存储电路 Qm Wn 图 4.1 时序逻辑电路的示意图 从图 4.1 中我们可以看出,一个完整的时序电路,是由这两个部分组成的,一部分是我们之 前讲的组合逻辑电路,另外一部分就是用来保存输入信息的存储电路。关于组合逻辑电路相信大 家都已经很熟了,我们这里就不在多提了,如果不熟悉的读者可以返回组合逻辑电路部分进一步 学习。那么下面我们就重点来讲一讲存储电路。常用的存储电路有两类,一类是锁存器,而另一 类是触发器。它们两者所采用的电路结构形式不同,信号的触发方式也不同,其中,采用电平触 发方式的叫做锁存器,而采用脉冲边沿触发方式的叫做触发器。 §4.1 锁存器 锁存器(Latch)是数字电路中的一种具有记忆功能的逻辑元件。锁存器对脉冲电平敏感的 存储单元电路,它只在输入脉冲的高电平(或低电平)期间对输入信号敏感并改变状态。在数字 电路中可以记录二进制数字信号“0”和“1”。 4.1.1 RS 锁存器 下面我们先来介绍一种最基本的锁存器,就是 RS 锁存器。RS 锁存器是构成所有复杂的锁 存器和复杂的触发器的基础。大家看图 4.2 所示。 54 数字电路篇 §4 SD ≥1 Q ≥1 Q RD 图 4.2 或非门组成的 RS 锁存器的电路图 从 RS 锁存器的电路图中我们可以看出,它是由两个或非门组成的,之前我们在讲组合逻辑 的时候,也接触过或非门,只不过那个时候,没有出现过现在这种输出信号交叉反馈的情况,那 么这种交叉反馈的结构其实也就是时序电路最主要的特征了。它有两个输入端, SD 和 RD ,这 里的 S 和 R 分别代表的是英语 SET 和 RESET,也就是置位和复位的意思,下标 D 代表的是 DATA,就是数据。如果 SD 和 RD 端为 1 时表示有激励信号,为 0 时表示无激励信号,电路中 还有两个输出端 Q 和 Q ,在正常工作时,Q 和 Q 的逻辑值是互补的,若 Q  0 ,则 Q  1,若 Q  1,则 Q  0 。锁存器的状态,就是用输出端 Q 的值来命名的,若 Q  0 ,则称锁存器为 0 状态,若 Q  1,则称锁存器为 1 状态。 通过前面的介绍我们了解了 RS 锁存器的输入管脚和输出管脚的功能及意义,那么接下来我 们就来看一看 RS 锁存器是如何工作的。首先我们来看如何给 RS 锁存器置位,这里所谓的置 位,就是要求 SD 这个置位端必须要有激励信号,而 RD 这个复位端不能有激励信号,也就是要 让 SD  1, RD  0 ,那么我们看, SD 是连接到 G1 这个或非门上的,当 SD  1 时,根据或非 门的逻辑关系,只要输入有 1,输出就为 0,只有在输入全部为 0 时,输出才为 1。那么根据这 个关系,G1 门的输出就是 0,Q 同样也就是 0。那么,下面我们再将这里的 0 反馈到 G2 门的输 入端, G2 门一共只有两个输入端,一个是 G1 输出端反馈回来的,另外一个就是 RD ,那么此时 这两个输入端都是 0 了,所以根据或非门的逻辑关系,我们可以知道, G2 的输出端此时为 1, 那么 Q 也就为 1。这里的 Q 代表的就是这个电路的此时的状态, Q 等于 1,也就代表这个电路 此时的状态为 1。我让 SD 这个输入端为 1,其实也就是希望让这个电路的状态为 1。这就是 RS 锁存器的置位。 说完了置位,我们再来看复位,所谓的给 RS 锁存器复位,首先就要给 RD 这个复位端一个 激励信号,而 SD 这个置位端不能有激励信号,也就是要让 RD  1 ,SD  0 ,那么我们看,RD 是连接到 G2 这个或非门上的,当 RD  1 时,根据或非门的逻辑关系,只要输入有 1,输出就为 0,那么我们就可以知道, G2 门的这个输出呢,就肯定是 0 了,那么 Q 也肯定是 0 了,我们再 将这个 0,反馈到 G1 门的输入端后,由于 G1 门此时的两个输入端都是 0,所以,根据或非门的 逻辑关系,我们可以知道,此时 G1 的输出端,一定是 1,Q 也一定是 1 了,电路中的 Q 和 Q , 也就正好是相反的状态,此时电路的状态也就保持在 0 的状态了。那么我们使 RD 这个复位端为 1,其实就是让电路的状态保持在 0 的状态,这就是 RS 锁存器的复位。 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 55 讲到这里大家应该已经了解了 RS 锁存器的置位和复位了,那么 RS 锁存器,之所以被称为 锁存器,其实就是它能够将电路的状态锁住,通俗的说,也就是当下一刻,锁存器的置位端或者 复位端的激励信号突然消失了,锁存器仍然能够保持之前的状态工作。这样说,大家可能还是不 太理解,下面我们还是根据实际电路来讲解一下。假设我刚刚将这个 RS 锁存器复位了,现在这 个锁存器的 Q  0 , Q  1,突然我们撤销了 RD 这个复位端的激励信号,那么此时的输入信号 RD 和 SD 就都为 0 了。讲到这里,大家可能会有疑问了,如果两个输入端都是 0,那么不好判 断 G1 和 G2 两个或非门的输出值了呀,这里呢,我要和大家解释一下了,时序电路之所以被称为 时序电路,就是因为这个电路中发生时间不同的信号,它们之间是可以相互影响的,就比如这个 电路,虽然我们现在两个输入端都是 0,但是将要分别与这两个 0 相或非的信号,也就是现在这 一刻 G1 门或者 G2 所输出的信号,一定是之前的输入信号通过或非门产生的,所以这里我们应该 将之前 G1 的输出值 1 以及 G2 的输出值 0 反馈回 G1 和 G2 的输入端,根据或非门的逻辑关系,我 们很容易看出,此时的 Q 仍然是等于 0 的, Q 也仍然是等于 1 的,RS 锁存器的输入端激励信 号消失后,电路仍然维持在原来的状态不变。 看到这里不知道你有没有被绕进去,如果你现在头脑已经混乱了,那么我们这里建议你拿出 一支笔和一张纸,把上面的 RS 锁存器电路图画下来,然后跟着我们的分析过程,走一步,就在 纸上画一步,一步步来理解直至你能够真正理解这个电路为止,因为 RS 锁存器是最最基础的一 种锁存器,这个电路是我们后面讲的所有知识的基础,如果这里没有搞明白、弄清楚,那么接下 来你将越学越乱。 如果你看完上面头脑思路都很清晰,那么接下来我们就要开始讲解 RS 锁存器的另外一种情 况,也是 RS 锁存器里禁止出现的一种情况,就是 SD 和 RD 同时为 1,也就是 SD 和 RD 同时有 激励信号,这种情况在 RS 锁存器里是不允许出现的,大家想一想, SD 是置位, RD 是复位, 你同时又想置位又想复位,那么锁存器肯定要错乱了。根据电路,我们也可以看出,如果 SD 和 RD 同时为 1,那么 Q 和 Q 就会同时等于 0,但是假如下一时刻, SD 和 RD 的激励信号全部消 失了,那么我们希望的是电路能够按照原状态继续运行,可是事实上却会进入一种错乱的状态, 比如此时 SD 和 RD 突然全为 0 了,但是它们两个变 0 的过程肯定是有先有后的,不可能完全同 时变 0,这里我们先假设 SD 先变 0 了,那么 G1 门的两个输入端此时就应该都为 0 了,根据或 非门的逻辑规律,此时 G1 门的输出就应该是 1 了, Q 就为 1 了,我们再将这个 1 反馈到 G2 门 的输入端的话,那么此时 G2 门的输出将是 0,电路将在保持在 0 状态。这是第一种情况,还有 一种情况就是 RD 先变 0 了,那么 G2 门的输出将是 1, Q 也将是 1,电路将会保持在 1 状态运 行。由此我们可以看出,我们将很难保证此时电路的状态,它有可能是 1 也有可能是 0。所以正 常情况下,我们要禁止 SD 和 RD 同时等于 1 的情况出现。 讲到这里,大家应该已经明白如何用或非门组成一个 RS 锁存器了,然而在构造 RS 锁存器 时,不仅能用或非门组成,还能用与非门组成。那么下面我们再来尝试用与非门组成一个 RS 锁 存器,现在我们给出与非门构成的 RS 锁存器的电路图,如图 4.3 所示。 http://www.fpga.gs/ 56 数字电路篇 §4 SD & Q & Q RD 图 4.3 与非门组成的 RS 锁存器的电路图 大家可以看出,这里与非门构成的 RS 锁存器和或非门构成的 RS 锁存器还是稍微有点不同 的,在与非门构成的 RS 锁存器中,两个输入信号写成了 SD 和 RD 形式,变量带非的这种形式 是指输入低电平有效,也就是说, SD 或者 RD 为 0 时,表示有激励信号,为 1 时则表示无激励 信号。两个输出信号的位置也发生了改变,对这个逻辑图的分析,基本上和我们之前讲的过程是 一样的,这里我们就不在重复讲解了。下面我们就来讲解一下时序电路中的四种描述方法,它们 分别是特性表、特性方程、状态图和波形图。接下来我们将对它们逐一进行介绍。 3. 特性表 首先我们介绍的是特性表,什么是特性表,特性表就是反应输入变量和原状态以及新状态之 间关系的一种真值表,也被称为状态转换真值表,这里的原状态,我们用 Qn 来表示,新状态用 Qn1 来表示。下面我们就趁热打铁以 RS 锁存器的特性表为例进行讲解,我们这里给出它的特性 表,如表 4.1 所示。 表 4.1 RS 锁存器的特性表 输入 SD RD 0 0 0 0 0 1 0 1 1 0 1 0 1 1 1 1 原状态 Qn 0 1 0 1 0 1 0 1 新状态 Qn+1 0 1 0 0 1 1 不定 不定 根据特性表我们就能很清楚的看出 RS 锁存器的逻辑功能,比如,当 SD 和 RD 同时等于 0 时,也就是说,两个输入端均无激励信号时 , Qn 和 Qn1 是相等的,也就是锁存器的原状态 Qn 和新状态 Qn1 保持不变。以此类推,大家应该可以很轻松的理解,如何利用特性表来描述锁存器 的逻辑功能了。 4. 特性方程 了解完了特性表,接下来我们再来介绍特性方程,什么是特性方程呢,特性方程就是锁存器 新状态的逻辑函数表达式,同样我们也是举例说明,我们通过 RS 锁存器的特性表写出它的特性 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 57 方程,这里也是利用我们之前讲过的方式,将输出等于 1 的项提出来后,组成一个与或式,那么 这里我们将 Qn1 等于 1 的项提取出来以后得到的函数式: Qn1  SD RDQn  SD RD Qn  SD RDQn SDRD  0 (约束条件) 利用约束条件将上式化简得出: Qn1  SD  RDQn 我们把化简后的公式称为 RS 锁存器的特性方程。看到这里,有的的朋友会有这么一个疑 问,在组合电路中我们能通过函数表达式直接画出它的电路图,那在时序电路中,也可以根据特 性方程直接画出电路图吗,这里很遗憾的告诉大家,不能,那么至于为什么不能,我们会在后面 给大家进行讲解。 5. 状态图 下面我们先接着来看 RS 锁存器的状态图,如图 4.4 所示。 S=1 R=0 S=0 R=X 0 1 S=X R=0 S=0 R=1 图 4.4 RS 锁存器的状态图 从 RS 锁存器的状态图中我们可以看出,该状态图是由两个圆圈和四个箭头组成,两个圆圈 中的 0 和 1 表示的是 RS 锁存器的两个状态,而四个箭头表示的是四个转换过程,箭头的末端是 原状态 Qn ,箭头的前端是新状态 Qn1 ,在箭头旁边的 SD 和 RD 是状态改变的条件, X 代表任 意状态。由此,我们就可以根据 RS 锁存器的状态图来看出 RS 锁存器的状态是如何变化的。 6. 波形图 讲完了状态图,我们再来看波形图,对于波形图我相信大家并不陌生,用过示波器或者逻辑 分析仪的朋友看上一眼波形图应该就能够明白了,大家看这个波形图,如图 4.5 所示。 http://www.fpga.gs/ 58 数字电路篇 §4 1 0 1 0 0 01 0 0 1 0 1 00 0 0 0 X 1 10 1 1 0 X 0 01 图 4.5 RS 锁存器的波形图 从波形图中我们可以看出, SD 和 RD 这两条波形不是唯一的,大家可以随意画出这两条波 形,但是 Q 和 Q 就不能随意画了,它们两个输出都要遵循 RS 锁存器的逻辑功能,比如,第一 个虚线内,当 SD  1, RD  0 时,根据我们前面的分析可以得出,不管前面的 Q 和 Q 的波形 是什么状态,在这个虚线内的 Q  1, Q  0 。以下也都是同理的,我们可以根据逻辑关系画出 Q 和 Q 两条波形,通过整个波形图我们能够更形象化地理解 RS 锁存器的工作特性。在实际应 用中,我们也会经常分析波形图,所以大家要能够掌握并且看懂波形图。 至此,我们时序电路的 4 种描述方法已经介绍完了,在我们介绍这 4 种描述方法时,相信 大家对 RS 锁存器的理解又更进一步,那么接下来,我们就来看一个比 RS 锁存器稍微复杂一点 的门控 RS 锁存器。 4.1.2 门控 RS 锁存器 在实际工作中,我们更多的情况下是希望能有一个控制信号去控制锁存器状态的转换,所以 我们在 RS 锁存器的基础上增加了一个控制端,只有控制端的信号变为有效电平后,RS 锁存器 才能按照输入的置 1 或置 0 信号改变相应的状态,这里我们将这种改变后 RS 锁存器,称为门控 RS 锁存器。并且我们将这种触发方式称为电平触发。下面我给出门控 RS 锁存器的电路结构图, & ≥1 ≥1 & 图 4.6 门控 RS 锁存器的电路图 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 59 从门控 RS 锁存器的电路图中我们可以看出,该电路主要是由两个部分组成,第一个部分是 由 G1 、G2 两个或非门组成了 RS 锁存器,第二个部分是由 G3 、G4 两个与门组成的输入控制门 电路。 C 为控制信号,它被加到了 G3 、 G4 两个与门的输入端上,用来控制激励信号的输入, 因此, RD  RC ,SD  SC 。由此我们便可以根据电路图来写出它的特性表,下面我们给出门 控 RS 锁存器的特性表,如表 4.2 所示。 表 4.2 门控 RS 锁存器的特性表 C S R Qn Qn+1 0 X X 0 0 0 X X 1 1 1 0 0 0 0 1 0 0 1 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 1 0 1 1 1 1 1 0 不定 1 1 1 1 不定 通过特性表我们可以看出,当 C  0 时,根据与门的逻辑关系,无论 R 和 S 输入 1,还是输 入 0,RD 和 SD 都将等于 0,那么锁存器也将维持原状态不改变,如果 C  1的话, R 将会等于 RD , S 也将会等于 SD ,此时的电路将等效为 RS 锁存器。由此我们可以看出,门控 RS 锁存 器状态的改变是由输入端 C 来控制的。下面我们给出门控 RS 锁存器的波形图,如图 4.7 所示。 图 4.7 门控 RS 锁存器的波形图 从门控 RS 锁存器的波形图中我们可以看出,当 C  0 时,不管 RD 和 SD 怎么变化, Q 仍 然是纹丝不动,当 C  1时, Q 则根据 R 和 S 的状态来改变状态。这就是门控 RS 锁存器的逻 辑规律。 4.1.3 D 锁存器 http://www.fpga.gs/ 60 数字电路篇 §4 讲到这,大家应该已经对门控这个概念有所了解了,接下来,我们再来讲一种锁存器,是在 门控 RS 锁存器的基础上演变而来的,叫做 D 锁存器。所谓的 D 锁存器,就是能够将输入端的 单路数据 D 存入到锁存器中的电路,下面我们给出 D 锁存器的电路图,如图 4.8 所示。 C RD & & Q & Q & D SD 控制门电路 RS锁存器 图 4.8 D 锁存器的电路图 从 D 锁存器的电路图中我们可以看出,该电路主要是由两个部分组成,第一个部分是由 G1 、 G2 两个与非门组成的 RS 锁存器,第二个部分是由 G3 、G4 两个与非门组成的控制门电路。C 为控制信号,它被加到了 G3 、 G4 两个与非门的输入端上,用来控制激励信号的输入。 下面我们来分析一下 D 锁存器的工作原理,当控制端 C  0 时,根据与非门的逻辑规律, 无论此时 D 等于什么, RD 和 SD 都同时等于 1,根据由与非门组成的 RS 锁存器的逻辑规律, RD 和 SD 都同时等于 1 的话,锁存器的输出端 Q 将维持原状态不变。那么,当控制端 C  1时, 如果此时 D  0 , SD 就等于 1, RD 就等于 0,根据 RS 锁存器的逻辑规律,电路的结果就为 0 状态;如果 D  1,那么 RD 就等于 1, SD 也就等于 0,锁存器的结果就为 1 状态,也就是说, 此时锁存器的状态是由激励输入端 D 来确定的,并且 D 等于什么,锁存器的状态就是什么,这 就是我们前面所说的,将单路数据 D 存入到锁存器之中。 根据上面的讲解,我们已经知道了 D 锁存器的逻辑功能了。下面我们就根据逻辑功能,来 写出它的特性表,如表 4.3 所示。 表 4.3 D 锁存器的特性表 0 X 0 0 0 X 1 1 1 0 0 0 1 0 1 0 1 1 0 1 1 1 1 1 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 61 从 D 锁存器的特性表中我们可以看出,如果 D  0 ,那么 Qn1 就等于 0,如果 D  1,那 么 Qn1 就等于 1。我们根据这里的特性表便可以写出它的特性方程,还是按照老方法,将输出等 于 1 的项提出来后,组成一个与或式,那么这里我们就不一步步的化简了,直接给出化简后的特 性方程: Qn1  D 接下来我们再来画出它的状态图,如图 4.9 所示。 D=1 D=0 0 1 D=1 D=0 图 4.9 D 锁存器的状态图 从状态图中我们可以看出,当 D 在 0 状态时,也就是输入 D  0 时,输出 Qn1 将保持 0 状 态,当输入 D  1时,那么输出 Qn1 将从 0 变为 1。 下面我们画出它的波形图,如图 4.10 所示。 锁存 Q跟随D 锁存 Q跟随D 图 4.10 D 锁存器的波形图 锁存 从 D 锁存器的波形图图中我们可以看出, D 是锁存器的输入信号, C 是锁存器的控制信 号, Q 是锁存器的输出信号,当控制信号 C 为高电平时,输出信号 Q 将跟随输入信号 D 的变 化而变化,大家看虚线内,Q 的波形等于 D 的波形。当控制信号 C 从高电平变为低电平时,输 入信号 D 的状态将会决定锁存器将要锁存的状态。大家可以看, C 由高变低的那两条虚线内, 所对应的输入信号 D 为低电平,那么输出信号 Q 也将会锁存低电平。最后面的那两条虚线也同 理, D 为高电平, Q 锁存高电平,至此关于 D 锁存器波形图就已经讲完啦。 4.1.4 空翻现象 下面我们来看下锁存器中的存在的空翻问题。什么是空翻。当控制信号有效时,输入信号若 http://www.fpga.gs/ 62 数字电路篇 §4 发生多次变化,输出状态也跟着发生多次变化,这一现象就被称为锁存器的空翻。下面我们给出 带有空翻现象的波形图,这里我们就以 D 锁存器为例,如图 4.11 所示。 有效 翻转 空翻 空翻 图 4.11 带有空翻现象的波形图 从波形图中我们可以看出,蓝色虚线内,由于控制信号 C 为高电平,D  1,那么我们可以 得出 Q  1。接下来看蓝色和黄色虚线内,由于 D  0 ,那么 Q  0 ,同理,最后面的两条黄色 虚线内,D 为 1,Q 就为 1。我们就把后面这四条虚线内的翻转称为空翻。空翻是一种有害的现 象,它使得时序电路不能按时钟节拍工作,造成系统的误动作。我们前面学习的锁存器都存在空 翻现象,而引起空翻现象是由锁存器的结构导致的,为了能够解决锁存器的空翻现象,人们便在 锁存器的基础上进行了修改,因此人们便设计出了触发器,触发器按照逻辑功能的不同可分为 RS 触发器、D 触发器、JK 触发器、T 触发器。由于在 FPGA 设计中我们更多的是利用 D 触发 器来设计电路,基本上每一个时序电路模块都能看到 D 触发器的身影,所以下面我们将重点放 在 D 触发器上,其他的触发器我们这里就不在进行讲解了,想要进一步学习的读者可以自行查 找资料,这里需要注意的是,我们只要学会 D 触发器,其他的触发器也是分分钟就能够掌握, 所以大家在学习这一部分时一定要格外的用心才行。 §4.2 触发器 触发器(Flip-Flop)也是数字电路中的一种具有记忆功能的逻辑元件。触发器对脉冲边沿敏 感的存储单元电路,它只在触发脉冲的上升沿(或下降沿)瞬间改变其状态。在数字电路中可以 记录二进制数字信号“0”和“1”。 4.2.1 触发器的原理 那么下面我们就以 D 触发器为例,先讲解 D 触发器是如何构造的,然后在分析 D 触发器是 如何解决空翻的。在给出 D 触发器的电路图之前,我们先来看下 D 锁存器的逻辑符号,如图 4.12 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 63 C RD & & Q 1 & Q & D SD 图 4.12 D 锁存器的电路图和逻辑符号 从 D 锁存器的电路图中我们可以看出,由于 D 锁存器的电路图还是稍微有点复杂的,想要 画出一个 D 锁存器的电路图并不是那么容易的,因此人们使用左边的逻辑符号来代替 D 锁存器 的电路图。接下来我们给出 D 触发器的电路图,如图 4.13 所示。 F1 F2 D Q1 Q2 Q CLK 1 1 CLK 2 1 Q CLK 1 1 图 4.13 D 触发器的电路图 从 D 触发器的电路图中我们可以看出,该电路是由两个相同的 D 锁存器以及两个非门连接 而成的,图中的 F1 和 F 2 就是 D 锁存器的电路符号, F1 为主锁存器, F 2 为从锁存器,由于 主锁存器的输出信号 Q1 就是从锁存器的输入信号,因而造成了两个锁存器的主从关系,这两个 锁存器的控制信号都由外部时钟信号 CLK 提供。 下面我们来分析 D 触发器是如何工作的,并且看看它是否能够解决空翻的现象。当 CLK  0 时, CLK 经过非门后直接 F1 的控制信号,那么此时 F1 的控制信号为 1, F1 被选通,处于工 作状态,如果现在输入信号 D 为 1 的话,它经过 F1 , F1 的输出 Q1 将为 1,这里的 Q1 ,不仅 是 F1 的输出信号,也同时是 F 2 的输入信号,不过现在 F 2 的控制信号为 0, F 2 被封锁了,处 于保持状态,输入信号 D 没有办法直接改变输出 Q 的状态,这是前半拍的工作情况,也就是说, 输入信号先存入主锁存器中,而不直接影响输出 Q 的状态。下面我们再来看后半拍,外部的控 制信号 CLK 由 0 变为 1 了,这个 1,经过非门后直接作为 F1 的控制信号,那么此时 F1 的控制 信号为 0,主锁存器 F1 就被封锁了,它的输出 Q1 将保持在当前的状态,即使现在输入信号 D 再发生改变, Q1 的值也不再受影响了。而 F 2 的控制信号 CLK 此时为 1, F 2 处于工作状态, Q1 将会作为 F 2 这个从锁存器的输入信号,直接影响到输出信号 Q 的状态。 Q1 为 1,那么根据 D 锁存器的逻辑规律,输出的 Q 将为 1, Q 非将为 0。这就是后半拍的工作情况,在后半拍里 我们才能实现整个电路状态的改变,因此从上面的分析中我们就可以看出,在 CLK 信号由 0 变 为 1,这样的一个变化周期内,触发器的输出状态只可能改变一次,这样就克服了锁存器中存在 http://www.fpga.gs/ 64 数字电路篇 §4 的空翻现象。 通过 D 锁存器和 D 触发器的学习,细心的读者应该已经发现了,D 锁存器与 D 触发器的逻 辑功能其实是相同的,只不过它们的触发方式有所不同。接下来我们通过将 D 触发器的波形图 与前面 D 锁存器的波形图进行比较,来看一看,它们的触发方式不同在哪里,如图 4.14 所示。 电平触发 边沿触发 主 选通 从 保持 保持 选通 选通 保持 有效 翻转 空翻 空翻 图 4.14 D 锁存器和 D 触发器的波形对比图 大家先看 D 触发器的波形图,D 触发器是在控制信号 CLK 为 0 时,才会接收输入信号 D 的值,并将这个值锁存起来,当控制信号 CLK 变为 1 时,输出信号 Q 才会被改变。那么 D 触 发器,其实就是在 CLK 这个时钟信号由 0 变为 1 的这个边沿进行触发的,通常我们就将这种触 发方式称为边沿触发,通过这种边沿触发方式的 D 触发器我们也将它称为边沿 D 触发器。 D 锁存器的触发方式是电平触发,和我们刚刚讲的边沿触发是有所不同的。这种不同是由于 锁存器和触发器的电路结构不同,而造成的。这里需要注意的是,由于 D 锁存器的功能和 D 触 发器的功能是一样的,所以在编写代码时很容易把 D 锁存器当成 D 触发器来使用,这种情况我 们是应该要极力避免的,关于这部分的内容我们会有详细的介绍的,这里大家混个脸熟就行。 至此关于触发器的基础知识内容就已经讲完啦,我们前面讲的所有内容其实都是为边沿触 发器做铺垫。在组合电路中我们知道,与或非门是组合电路的核心知识,不懂与或非,就看不懂 组合逻辑电路,在时序电路中,边沿触发器就是时序电路的核心知识,如果不懂边沿触发器,那 么也就看不懂时序电路,后续讲解的寄存器和计数器都是用这些边沿触发器组合而成的。 4.2.2 利用 Verilog 来描述触发器 学完了触发器的原理,接下来我们就来看看如何利用 Verilog 来描述我们的触发器。下面我 们废话不多说,直接上代码,如代码 4.1 所示。 代码 4.1 D 触发器的 Verilog 代码 1 module Digital_Data_Flip_Flop 2( 3 CLK_50M,RST_N,D,Q 4 ); 5 6 input CLK_50M; 7 input RST_N; Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 65 8 input D; 9 output reg Q; //可以分开写 output Q;reg Q;也可以合并在一起 10 11 always @ (posedge CLK_50M or negedge RST_N) 12 begin 13 if(!RST_N) 14 Q <= 1'b0; 15 else 16 Q <= D; 17 end 18 19 endmodule 通过上面的代码,我们可以从模块名中大致猜出,这个 Verilog 代码描述的是一个 D 触发 器,虽然代码只有寥寥几行,关键字也都比较熟悉,但是该代码所描述的功能和我们之前代码所 描述的功能是有很大区别的,之前我们所描述的功能是没有时钟信号的,换句话说我们之前描述 的都是组合逻辑电路,而现在我们描述的是一个货真价实的时序电路,接下来我们就来带大家分 析一下该代码。 该代码的第 11 行至第 17 行,就是本程序中最核心的,也是用法相对比较多的 always 模块。 always 模块敏感表可以为电平、沿信号(上升沿)posedge、(下降沿)negedge;前面我们都把 always 模块用在组合逻辑电路中,其基本代码结构如代码 4.2 所示。 1 always @ (*) 2 begin 3 //具体逻辑 4 end 代码 4.2 always 模块用于组合逻辑电路中 //always @ (A,B) 也可以 always @ (A or B) always 后若有沿信号(上升沿 posedge,下降沿 negedge)声明,则多为时序逻辑,其基本代 码结构如代码 4.3 所示。 代码 4.3 always 模块用于时序逻辑电路中 1 always @ (posedge CLK_50M) //单个沿触发的时序逻辑 2 begin 3 //具体逻辑 4 end 5 6 always @ (posedge CLK_50M or negedge RST_N) //多个沿触发的时序逻辑 7 begin 8 //具体逻辑 9 end 下面我对这两个组合和时序代码结构用语言进行描述一下:组合逻辑电路中 always 前面已 经介绍过了,不过这里为了方便读者对比,我们再回顾一下。always @ (A,B)详细讲解一下,@ 是事件等待语句,意思是一直等待 A 和 B 二个敏感变量变化,不管 A 和 B 是从高变低,还是从 http://www.fpga.gs/ 66 数字电路篇 §4 低变高,都将会执行 always 下面的 begin……end 中的语句。如果 A 和 B 都没有变化,那么 always 也将不往下执行,将一直循环等待。新标准可以这样书写 always @ (*),其解释如下: always @ (*)是个组合逻辑电路的描述方式;是为了防止你在设计时考虑不周全带来一些操作失 误,所以敏感表用*(表示全部的敏感变量,这里表示 A 和 B),只要有任何输入信号变化,其输 出立即发送变化。 时序逻辑电路中 always @ (posedge CLK_50M or negedge RST_N):@也同样是时间等 待语句,只是这里一直等待的是 CLK_50M 和 RST_N 二个敏感变量的上升沿和下降沿的变化, 如果有一个 CLK_50M 的上升沿到来,那么便会执行 always 下面的 begin……end 中的语句。 同样的如果有一个 RST_N 的下降沿到来,也同样会执行 always 下面的 begin……end 中的语 句。如果两个信号都没有到来,那么将不会执行 begin……end 中的语句,一直等待信号的到来。 细心的读者一定会发现时序电路中的赋值是<=,而组合逻辑电路中的赋值是=,是不是我在 编写代码的时候小手一抖,多打了一个符号呢,不是这样的,在 Verilog 中有这么两个概念。阻 塞赋值操作符用等号(即= )表示,非阻塞赋值操作符用小于等于号 (即 <= )表示。阻塞和非阻塞 赋值的语言结构,在 Verilog 语言中相对来说还是比较最难理解的。在很多时候,用"="或者是 "<="实际上对应的是不同的硬件电路,在这里我就不多做解释,1、是一句两句是解释不清楚它 们之间的关系,2、是有可能越解释读者反而越凌乱。想要进一步了解什么是阻塞和非阻塞可以 参考《Verilog 语法篇》。 在这里,大家只要记住:按照我们的代码风格来写,是很轻松就能够知道什么时候用阻塞什 么时候用非阻塞,因为我们的代码风格是组合和时序电路分开写的,这样写有什么好处呢,1、 是时序电路用非阻塞赋值(<=),组合电路用阻塞赋值(=),是不是一下就能分清楚了。2、是 当工程很大时,分析起来很有优势,因为时序逻辑部分的写法几乎是完全一样的,这时就可以将 主要精力放在分析组合逻辑上面。3、就是代码容易解读,别人读你写的代码更容易理解。4、5、 6、……,当然好处还有很多,剩下的就需要大家慢慢去挖掘体会了。 通过上面的介绍,相信大家已经知道了时序电路是如何描述的,接下来我们再来看下 always 模块中的代码,首先我们看到的是第 13 行的 if 语句,该语句判断复位信号是否有效,从我们的 变量命名规则中我们可以看出 RST_N 是一个低电平有效的复位信号,也就是说,当 RST_N=0 时,if 为真,Q<=1’b0 会被执行,D 触发器将会被复位输出 0,当 RST_N=1 时,if 为假,我们 就要执行 else 中的 Q<=D 这条语句,D 触发器将会正常工作。至此,我们的 D 触发器代码就已 经说完了,接下来我们再来看一看寄存器。 §4.3 寄存器 通过前面的学习,我们对触发器都有了一定的了解,只要我们搞明白、弄清楚触发器,寄存 器也是分分钟就能够学会的。为什么会这样说呢,因为寄存器就是由多个触发器组成的,我们知 道能够存储一位二进制码的时序电路叫做触发器,其实寄存器就是能够存储多位二进制数码的 时序电路。 4.3.1 寄存器的原理 为了让大家能够进一步了解和明白寄存器,下面我们举例进行说明,我们给出由四位 D 触 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 发器组成的寄存器电路图,如图 4.15 所示。 Q0 Q0 F0 Q 1D C1 Q1 Q1 F1 Q 1D C1 Q2 Q2 F2 Q 1D C1 67 Q3 Q3 F3 Q 1D C1 1 D0 CP D1 D2 D3 图 4.15 由四位 D 触发器组成的寄存器电路图 通过电路图我们可以看出, F0 、 F1 、 F2 、 F3 是 4 个边沿 D 触发器的电路符号,图中绿色 的小三角则表示它们的触发方式是边沿触发,这个就是寄存器的基本结构,下面我们就来看一看 寄存器的工作原理。 如果此时我们给电路中的 CP 端一个脉冲的话,那么此刻 D0 、 D1 、 D2 、 D3 的值就将被 储存在寄存器里了。直到 CP 端下一个脉冲的上升沿到来时,储存的值才有可能被改变。根据这 个特性我们可以列出该电路的特性表。如表 4.4 所示。 表 4.4 由四位 D 触发器组成的寄存器特性表 时钟 输入 输出 工作模式 CP D0、D1、D2、D3 Q0、Q1、Q2、Q3 ↑ D0、D1、D2、D3 D0、D1、D2、D3 数码寄存 1 X、X、X、X 保持 数据保持 0 X、X、X、X 保持 数据保持 从特性表中我们可以看出,这种寄存器有两种工作状态,分别是寄存和保持。当时钟信号的 上升沿到来时,电路将会触发,D0、D1、D2、D3 的值将被寄存,直到下一个时钟信号的上升 沿到来之前,无论我们怎么改变输入信号的值,输出信号的值也不会改变。这就是基本寄存器的 逻辑规律,非常的容易理解。下面我们就再来介绍一个稍微复杂一点的寄存器,它不但可以寄存 数码,而且还能在时钟信号控制下,将所寄存的数据能够向左或向右进行移位,我们通常把这种 寄存器称为移位寄存器。 4.3.2 寄存器的应用 移位寄存器有可以分为单向移位寄存器和双向移位寄存器,单向移位寄存器指的就是右移 位寄存器和左移位寄存器,而双向移位寄存器就是既能向左也能向右移位。这里我们就以右移位 http://www.fpga.gs/ 68 数字电路篇 §4 寄存器为例,进行详细讲解。 相信大家都见过流水灯,流水灯就是一个典型的右移位寄存器,接下来我们通过流水灯来了 解右移位寄存器的工作原理,下面我们给出示意图,如图 4.16 所示。 1号灯 2号灯 3号灯 图 4.16 流水灯工作原理示意图 4号灯 大家看,这里有 4 盏灯,分别是 1 号灯,2 号灯,3 号灯和 4 号灯。这里我们规定当灯泡为 1 时,灯就会点亮,当灯泡为 0 时,灯就会熄灭。首先,当 1 号灯为 1,其余灯为 0 时,那么 1 号灯将会点亮,其余灯将熄灭。其次,当 2 号灯将为 1,其余灯为 0 时,那么 2 号灯将会点亮, 其余灯将熄灭。同理,我们这样依次将灯点亮就可以形成流水灯的效果了,整个过程就相当于将 四位二进制 1000 中的 1 进行右移,得到 0100,0010,0001。那么下面我们画出这个流水灯的 控制电路,也就是右移位寄存器,它是由 4 个 D 触发器依次连接起来的,如图 4.17 所示。 Q0 Q1 Q2 Q3 F0 F1 F2 F3 Di D0 1D Q D1 1D Q D2 1D Q D3 1D Q C1 C1 C1 C1 CP 图 4.17 由四位 D 触发器组成的右移寄存器电路图 从右移寄存器的电路图中我们可以看出,如果我们需要点亮第一个灯的话,那么我们应该让 D0 为 1,那么根据 D 触发器的性质,我们需要让 F0 这个 D 触发器的输入端 Di 为 1,并且让 F0 的控制端 CP 产生一个上升沿,促使 F0 触发。注意,电路中的 CP 不仅仅是 F0 这个 D 触发器的 控制端,还同时是 F1 、 F2 、 F3 的控制端,这也就表示,当 CP 端的上升沿来临时,这四个触发 器将同时触发,大家看,此刻 F0 它的输入信号是 1,而与此同时, F1 、 F2 、 F3 输入端口没有 激励信号,那么如果此时它们四个同时触发的话, Q0 将等于 1, Q1 、 Q2 、 Q3 将会等于 0。此 时这四个触发器的输出值也被锁存了,直到下一个上升沿到来时,才有可能被改变。下一步,我 们需要做的是移位,让触发器的状态 1 向右移,怎么做呢,我们先让 Di 这个输入端口变为 0, 那么此时 D0 就是 0 了, D1 是 1,这个 D1 就是之前 F0 被锁存的输出值,再看 D2 和 D3 也都是 0,此时我们让 CP 端产生一个上升沿,4 个触发器就都被触发了,Q0 等于 0,Q1 等于 1,Q2 和 Q3 都等于 0。看到这里,大家应该已经发现,F0 触发器的状态 1,现在已经右移到 F1 触发器上, 这就是移位寄存器的作用,依次类推,我们如果保持 Di 端口的输入 0 不变,并且再次让 CP 端 口产生一个上升沿, F1 的状态 1,将会右移到 F2 触发器上。 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 69 现在大家应该已经明白了右移位寄存器的工作原理了吧。那么我们根据前面的分析,写出一 张特性表。这张特性表表示的也是刚才右移位寄存器实现流水灯的逻辑规律。如表 4.5 所示。 表 4.5 由四位 D 触发器组成的右移寄存器特性表 移位脉冲 输入信号 输出 CP Di Q0 Q1 Q2 Q3 0 X 0 0 0 0 1 1 1 0 0 0 2 0 0 1 0 0 3 0 0 0 1 0 4 0 0 0 0 1 4.3.3 利用 Verilog 来描述寄存器 学完了寄存器的原理,我相信大家都明白了什么是寄存器,由于寄存器代码比较简单,没有 什么难度,所以我们就不再给出寄存器的 Verilog 代码了,我们这里决定给出一个更具有挑战性 的代码,那就是移位寄存器。接下来我们就来看看如何利用 Verilog 来描述我们的移位寄存器。 下面我们废话不多说,直接上代码,如代码 4.4 所示。 代码 4.4 移位寄存器的 Verilog 代码 1 module Digital_Shift_Reg 2( 3 CLK_50M,RST_N,DATA_EN,DATA_IN,DATA_OUT 4 ); 5 6 input CLK_50M; 7 input RST_N; 8 input DATA_EN; 9 input DATA_IN; 10 output DATA_OUT; 11 12 reg [3:0] DATA_OUT; 13 reg [3:0] DATA_OUT_N; 14 15 //时序电路 16 always @ (posedge CLK_50M or negedge RST_N) 17 begin 18 if(!RST_N) 19 DATA_OUT <= 4'b0; 20 else 21 DATA_OUT <= DATA_OUT_N; 22 end 23 24 //组合电路 http://www.fpga.gs/ 70 数字电路篇 §4 25 always @ (*) 26 begin 27 if(DATA_EN) 28 DATA_OUT_N = {DATA_OUT[2:0] , DATA_IN}; 29 else 30 DATA_OUT_N = DATA_OUT; 31 end 32 33 endmodule 该代码就是一个典型的组合逻辑电路和时序逻辑电路分开写的风格。之前我们给出的代码 都很简单,要么只有组合逻辑电路,要么只有时序逻辑电路,我们一直强调组合逻辑电路和时序 逻辑电路分开写,但是如何写,想必大家还是朦朦胧胧、云里雾里。看到这里,大家是不是恍然 大悟呀,接下来我们就来简单的带大家分析一下代码。模块名、端口声明、数据类型定义这三项, 相信大家已经很熟了,这里我们不在介绍了,我们直接从第 16 行开始。 第 16 行至 22 行的代码不难理解,主要完成的功能就是一个 4 位的寄存器(即 4 位的 D 触 发器)。第 25 行至 31 行的代码也不难理解,主要完成的功能是判断 DATA_EN 使能位,并进行 移位操作。唯一不容易理解的就属第 28 行的“{”和“}”这一部分,在 Verilog 中“{”和“}” 并不叫大括号,而叫位拼接运算符,我们举例说明,A=2'b10;B=4'b1111; {A,B}=6'b101111。理解 了位拼接运算符,接下来我们再来看下它是如何移位的,我们假设 DATA_OUT 为 0000, DATA_IN 为 1,DATA_EN 为 1,当 DATA_EN 为 1 时,程序将会运行第 28 行,由于 DATA_OUT 等 于 4'b0000 , 所 以 DATA_OUT 的 低 三 位 就 为 3'b000 , 又 因 为 DATA_IN=1'b1 , 所 以 DATA_OUT_N={3'b000, 1'b1}=4'b0001;当程序运行第二次的时候,DATA_OUT 为 0001, 我们假设此时 DATA_IN 为 0,当 DATA_EN 为 1 时,DATA_OUT_N={3'b001, 1'b0}=4'b0010。 依次类推,我们最终便能实现移位寄存器。 §4.4 计数器 下面我们讲解的是计数器,计数器也是今后我们在 FPGA 设计中,最常用到的一种时序电 路,什么叫做计数器,所谓计数器就是一种能统计输入脉冲个数的时序电路,也就是说,你一共 来了多少次脉冲,我可以通过输出的结果看出来,这样的特性我们不仅可以直接用于计数,还可 以用于定时,分频等多种功能。 4.4.1 计数器的原理 为了让大家能够进一步了解和明白计数器,这里我们同寄存器一样举例进行说明,下面我们 给出计数器的电路结构图,如图 4.18 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 71 CLK F1 DQ Q Q1 G1 =1 G4 G2 & =1 F2 DQ Q Q2 F3 DQ Q Q3 G3 & =1 G5 F4 DQ Q Q4 图 4.18 由四位 D 触发器组成的计数器电路图 这里的电路结构图还是稍微有点复杂的,我们并不能像看寄存器一样很直观的看出计数器 的逻辑功能,大家看计数器的结构,它是由 F1 、 F2 、 F3 和 F4 这四个边沿 D 触发器,并加上三 个异或门和二个与门组成的。下面我们来通过分析了解一下这个电路是如何被用来计数的。 我们假设现在电路的初始状态是 0000,也就是输出端口 Q1Q2Q3Q4  0000 ,下面我们来看 下这四个 D 触发器此时的输入信号是什么,我们先看 F1 , F1 的输入信号 D ,是由 Q1 反馈回来 的,我们已知此时的 Q 是 0,那么 Q1 就是 1,这个 1 反馈给输入信号 D ,此时 F1 的输入信号就 是 1,下面再看 F2 , F2 的输入信号,是 Q1 和 Q2 的值经过一个异或门之后得到的,我们已经此 时的 Q1 是 0,Q2 也是 0,那么这两个 0,经过异或门,根据异或门的逻辑规律,相同出 0,相异 出 1,这里异或门的输出就是 0 了, F2 的输入信号也是 0。下面再看 F3 , F3 的输入信号,是由 Q1 和 Q2 经过一个与门之后的输出值,与 Q3 的值相异或得到的,我们看,Q1 和 Q2 都是 0,两个 0 相与,输出肯定还是 0,这个输出的 0,再与 Q3 的值相异或,根据异或门的规律,两个输入现 在都是 0,那么异或门的输出也是 0, F3 的输入此时就是 0,讲完了 F3 ,我们再来看 F4 , F4 的 输入信号是由, Q1 、 Q2 和 Q3 经过一个与门之后,得到的输出值,再与 Q4 的值相异或得到的, Q1 、 Q2 和 Q3 此时都是 0,它们相与之后,得到的输出值也还是 0,那么这个 0 再与 Q4 的值相 异或,根据异或门的逻辑规律,两个输入值都是 0,那么异或门输出也是 0, F4 的输入此时就是 0。 到此,我们已经分析出了 F1 、 F2 、 F3 和 F4 ,这四个触发器此时的输入值了,下面我们就 可以根据 D 触发器的逻辑规律知道下一刻电路的输出值了,那么,现在我们给 CLK 端口一个上 升沿,也就是 CLK 由 0 变为 1 了,那么四个边沿 D 触发器将会同时触发,当 CLK 这个时钟信 号的上升沿到来时,D 触发器的输入值将会被锁存,根据逻辑规律,下一刻 4 个 D 触发器的输 出值就分别为 1,0,0,0。这里如果我们把 Q4 的值当做二进制数的最高位,把 Q1 的值当做二进制 数的最低位,那么现在计数器所输出的值,就是二进制数 0001,也就是十进制的 1。计数器,接 收到了第一个时钟信号的上升沿,那么计数器就输出二进制数 0001,依次类推,如果第二个时 http://www.fpga.gs/ 72 数字电路篇 §4 钟信号的上升沿到来时,大家可以试着自己推一下,这个时候计数器将会输出二进制数 0010, 也就是十进制数 2,每当电路多到来一个时钟上升沿,计数器就会作加 1 运算。当电路计到第十 六个脉冲时,电路状态将由 1111 又变为 0000,完成一个循环周期,所以该电路也称为模 16 同 步加法计数器。所谓同步就是指该电路中的四个边沿 D 型触发器共用一个时钟脉冲 CLK ,当时 钟上升沿到来时,它们能够同时触发,这就叫同步,既然有同步,那肯定也有异步,所谓的异步 就是它们不是共用一个时钟脉冲,且触发不是同时发生的。 那么,讲到这个,大家应该已经了解了计数器的工作原理了,下面我们根据上面的分析,画 出模 16 同步加法计数器的特性表,如表 4.6 所示。 表 4.6 模 16 同步加法计数器的特性表 0 0000 0 0 0 1 1 0001 0 0 1 0 2 0010 0 0 1 1 3 0011 0 1 0 0 4 0100 0 1 0 1 5 0101 0 1 1 0 …… …… …… 14 1 1 1 0 1 1 1 1 15 1 1 1 1 0 0 0 0 由于该特性表过于啰嗦,这里我们就省略了一部分内容,由于模 16 同步加法计数器的特性 表比较容易理解,这里我们就不在进一步讲解,下面我们给出模 16 同步加法计数器的状态图, 如图 4.19 所示。 0 CLK1 1 CLK2 2 CLK3 3 CLK16 15 14 CLK15 图 4.19 模 16 同步加法计数器的状态图 4.4.2 计数器的应用 了解完了计数器的工作原理,下面我们来讲解一个计数器的应用,一提到计数器的应用,最 先能够想到的,就是秒表了,秒表相信大家都知道,秒表就是一个典型的计数器,这里我们先不 考虑秒表的暂停和清零功能,主要先讲解一下秒表的基本工作原理。 一个两位数的秒表可以从 0 一直累加计数到 59,然后再返回 0 循环进行累加,刚刚我们说 过一个可以从 0 到 15 循环累加的计数器,叫做模 16 计数器,那么我们这里从 0 到 59 循环累 加,其实就是一个模 60 计数器,模 60 计数器的电路结构相比之前的模 16 是有点复杂的,如果 Zircon Opto-Electronic Technology CO.,Ltd. §4 时序逻辑电路的基础知识 73 我们想用门电路直接搭一个的话,还是有点麻烦的,所以一般情况,我们不选择直接用模 60 计 数器来实现,而是选择用模 6 计数器加上模 10 计数器的方法实现,为什么要选择模 10 和模 6 呢,大家看,一个两位的秒表,是分为个位和十位的,个位无非是要显示 0 到 9 这 10 个数,十 位无非是要显示 0 到 5 这 6 个数,那么我们可以将十位和个位分开来进行计数,大家看,这个 计数器现在开始计数了,它的个位数字现在每间隔 1 秒变化一次,变化到 9 的时候,它下一刻将 会归 0,然后重新计数,而十位的数字每间隔 10 秒变化一次,变化到 5 的时候,它的下一刻也 将会归 0,然后重新计数,这就是两位数秒表的一种实现方法,下面我给出秒表的电路示意图, 如图 4.20 所示。 10秒 一个上升沿 DDD123 模6 Q1 Q2 计数器 Q3 CLK 1秒 一个上升沿 DDDD1234 模10 Q1 Q2 计数器 Q3 Q4 CLK 显示译码器 显示译码器 十位 0~5 图 4.20 秒表的电路示意图 个位 0~9 从电路示意图中我们可以看出,我们先将个位的数码管和十位的数码管分别与模 10 和模 6 计数器对应,然后,我们将这两个计数器的输出信号引出,连接到相应的译码器上,再通过译码 器译码,将最终的数字显示在数码管上。这就是一个两位数秒表的电路结构了,这里我们要注意 的是,图中的两个计数器,它们的时钟信号不是共用的,模 10 计数器的时钟端,信号的上升沿 是需要间隔 1 秒来一次,而模 6 计数器的时钟端,信号的上升沿是需要间隔 10 秒来一次的,具 体怎么产生我们需要的时钟信号,这里就不具体讲了,等到后面讲解实际项目时,我们再说。 4.4.3 计利用 Verilog 来描述计数器 学完了计数器的原理,接下来我们就来看看如何利用 Verilog 来描述我们的计数器。下面我 们废话不多说,直接上代码,如代码 4.5 所示。 代码 4.5 模 16 加法计数器的 Verilog 代码 1 module Digital_Counter 2( 3 CLK_50M,RST_N 4 ); 5 6 input CLK_50M; http://www.fpga.gs/ 74 数字电路篇 §4 7 input RST_N; 8 9 reg [3:0] time_cnt; 10 reg [3:0] time_cnt_n; 11 12 //时序电路 13 always @ (posedge CLK_50M or negedge RST_N) 14 begin 15 if(!RST_N) 16 time_cnt <= 4'b0; 17 else 18 time_cnt <= time_cnt_n; 19 end 20 21 //组合电路 22 always @ (*) 23 begin 24 if(time_cnt == 4'hf) 25 time_cnt_n = 4'b0; 26 else 27 time_cnt_n = time_cnt + 1'b1; 28 end 29 30 endmodule 上面的代码同样也是时序电路和组合电路分开写的风格,该代码实现的是一个模 16 同步加 法计数器,代码比较简单,我们就不在进一步分析了,如果你在看上述代码没有任何障碍,那么 你的 Verilog 语法已经合格了。至此,时序逻辑电路的基础知识就已经讲完了,下面我们将要开 始讲解时序电路的分析和设计方面的内容了。 Zircon Opto-Electronic Technology CO.,Ltd. 时序逻辑电路的设计与分析 第五章 时序逻辑电路的设计与分析 通过前面的学习,我们知道存储电路中根据存储单元改变的特点,可以将时序电路分为同步 时序电路和异步时序电路两大类,在同步时序电路中,所有存储单元的状态改变是在统一的时钟 脉冲控制下同时发生的。在异步时序电路中,各存储单元的状态改变不是同时发生的,时钟脉冲 只控制存储电路中的部分存储单元,其他则靠输入信号或时序电路内部信号来控制,甚至还有些 异步时序电路没有时钟脉冲,只靠输入信号经过内部电路传递去控制存储单元。由于在 FPGA 中我们设计大都是采用同步设计方法,因此在后续的时序电路分析和设计讲解中我们都以同步 时序电路为主,好奇心强的读者会有这么一个疑问,为什么要采用同步设计呢?好问题,这里我 们就简单的说明一下:异步设计的毛刺无法避免,时序设计过于费时费力,其所需调整的时序路 径和需要附加的相关约束相当繁琐,现在的 EDA 工具都是基于时序驱动的优化策略,异步时序 电路增加了时序分析的难度,需要确定最佳时序路径所需的计算量超出想像。而同步设计不仅能 有效地避免毛刺的影响,使得设计更可靠;还能够使设计出的同步时序电路更易于分析及实现; 不仅仅如此,目前几乎所有的仿真工具都仅能支持同步仿真,所以我们在 FPGA 设计中极力推 荐大家使用同步设计方法,除非在某些特殊的场合。 §5.1 时序逻辑电路的分析方法 在讲解时序逻辑电路的分析方法之前,我们还需要了解一下分析时序电路时所需要用到的 三个描述方程,我们给出时序电路的结构框图,如图 5.1 所示。 X1 Z1 Xi 组合电路 ZJ … … … … Q1 W1 存储电路 Qm Wn 图 5.1 时序逻辑电路的结构框图 通过电路结构框图,我们可以写出如下方程组: Z  F(X ,Qn) W  G(X ,Qn) Qn1  H (W ,Qn ) 其中,输出方程 Z 和驱动方程W 是用来描述组合逻辑关系的,而状态方程,则是用来描述 存储电路的新状态 Qn1 与原状态 Qn 和驱动信号W 之间的关系,因此我们可以发现,这三个方 78 数字电路篇 §5 程充分地反应了时序电路逻辑功能的特点。如果有看到方程就头疼的读者,在这里也不要担心, 后面我们将会在分析电路的过程中进一步讲解。 接下来是不是我们就要进入时序电路的分析了?答案当然不是的,因为我们还需要了解一 下摩尔和米里的概念,在时序电路中,我们还可以根据输出信号的特点,将其分为摩尔(moore) 型和米里(Mealy)型两类电路。在摩尔型电路中,输出信号仅仅取决于存储电路的状态;在米里 型电路中,输出信号不仅取决于存储电路的状态,而且还取决于外部输入信号。关于摩尔型电路 和米里型电路我们将分别进行详细讲解。下面我们就来看看时序电路的分析方法。 5.1.1 摩尔型电路的分析方法 所谓时序逻辑电路的分析,就是对于一个给定的时序逻辑电路,研究它在一系列输入信号的 作用下,将会产生怎样的输出,进而说明它的逻辑功能,因此,我们只要能写出前面提到的三个 方程,那么就可以通过这些方程画出它的特性表、状态图,最终便可以通过特性表和状态图来总 结出时序电路的功能。首先我们分析的是摩尔型时序逻辑电路,下面我们给出摩尔型时序逻辑电 路图,如图 5.2 所示。 & ≥1 & & D0 Q0 D1 Q1 D2 Q2 Z F0 F1 F2 CP 图 5.2 摩尔型时序逻辑的电路图 通过该电路结构图我们可以看出,该电路只有输出没有输入,因此我们可以断定,它是一个 同步摩尔型时序电路,并且由 3 个 D 触发器和 4 个与非门组合而成。根据电路结构图我们可以 写出它的驱动方程和输出方程,它的驱动方程为: D0  Q0 Q1  Q1Q2  Q1Q2 D1  Q0 D2  Q1 它的输出方程为: Z  Q2 然后我们在根据写出的驱动方程代入 D 触发器的特性方程( Qn1  D )中可以得出: F0  Q n1 0  D0  Q0 Q1  Q1Q2  Q1Q2 F1  Q n1 1  D1  Q0 Zircon Opto-Electronic Technology CO.,Ltd. §5 时序逻辑电路的设计与分析 79 F2  Q n1 2  D2  Q1 至此,我们的驱动方程、输出方程和状态方程就已经全部求出,现在我们回头再看那三个复 杂的方程,是不是感觉其实它们也不过如此。接下来我们就通过这三个特性方程来写出它的特性 表,首先我们将 D2 , D1 , D0 取 000,那么 Q2 , Q1 , Q0 也就等于 000,然后我们将得出的 Q2 ,Q1 ,Q0 代入状态方程和输出方程就可以得出 Q2 ,Q1 ,Q0 的新状态 Q Q Q n1 n1 n1 2 1 0  001 , Z  0 。又由于新状态 Q n1 2 、 Q n1 1 和 Q n1 0 反馈回 D2 , D1 , D0 ,所以 D2 , D1 , D0 便为 001, Q2 Q1 Q0 也就等于 001,再把 001 代入状态方程和输出方程就可以得出新状态,依次类 推,我们就可以列出它的特性表,如表 5.1 所示。 表 5.1 摩尔型时序逻辑电路的特性表 Q0 Q1 Q2 Q0n+1 Q1n+1 Q1n+1 Z 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 根据特性表我们来画出它的状态图,下面我们给出它的状态图,如图 5.3 所示。 /Z Q2Q1Q0 /0 /0 /0 000 001 010 101 /1 /1 100 110 111 011 /1 /1 /0 图 5.3 摩尔型时序逻辑的状态图 通过状态图我们可以很直观的看出它状态走向,最后我们便可以根据特性表和状态图来总 结出它的逻辑功能,随着 CLK 脉冲的到来,该电路在七个有效状态中循环变化,而输出 Z 也在 0010111 七个数中不断循环,因此我们可以得出,该电路是一个序列信号发生器,能够输出一个 周期的数字序列信号。在这里我们还可以看出该电路是一个可自启动电路,什么可自启动电路? 所谓可自启动就是时序电路中的所有无效状态经过数个 CLK 脉冲后都能进入有效状态环,下面 http://www.fpga.gs/ 80 数字电路篇 §5 我们将这个状态图稍作修改,它就变成了不可自启动电路。这里我们需要注意的是,下面的状态 图是我们任意修改的,没有任何意义,只是想给大家看下不自启动电路的状态图是怎么样一个情 况,如图 5.4 所示。 000 001 010 101 100 110 111 011 图 5.4 不自启动的状态图示意图 从该状态图中我们可以看出,当电路处于无效状态 000/0 时,不管经过多少个 CLK 脉冲, 它始终都会处于 000→100→000 这个状态,我们只有将电路设置为其他的几个状态,它才能正 常工作。至此,摩尔型时序逻辑电路的分析就告一段落了,下面我们将分析米里型时序逻辑电路。 5.1.2 米里型电路的分析方法 关于米里型时序逻辑电路的分析方法和摩尔型时序逻辑电路的分析方法对比来说,并没有 什么不同,不过在分析米里型时序逻辑电路时要注意,米里型时序逻辑电路的输出信号不仅取决 于存储电路的状态,而且还取决于外部输入信号,因此我们也要将它的输入信号给考虑进去。接 下来我们便直接给出米里型时序电路,如图 5.5 所示。 1 =1 & ≥1 Z & X =1 D1 Q1 D0 Q0 FF1 FF0 CLK 图 5.5 米里型时序逻辑的电路图 通过该电路图中我们可以看出,该电路有一个外部输入信号 X ,因此我们可以断定,它是 一个同步米里型时序电路,并且该电路由 2 个异或、2 个与 1 个非门、1 个或门组合而成。根据 电路结构图我们可以写出它的驱动方程和输出方程,它的驱动方程为: D1  X  Q1  Q0 D0  Q0 它的输出方程为: Zircon Opto-Electronic Technology CO.,Ltd. §5 时序逻辑电路的设计与分析 81 Z  X Q1Q0  XQ1Q 0 接下来后我们在根据写出的驱动方程 D 触发器的特性方程( Qn1  D )中可以得出: Qn1 1  D1  X  Q1  Q0 Qn1 0  D0  Q0 接下来我们就不能按照分析摩尔型电路那样分析了,在这里稍微有点不同,根据它的状态方 程,我们需要分别写出 Q1 的 n+1、Q0 的 n+1 和 Z 的特性表。大家看,这就是它们的特性表, 然后我们在将这三个特性表进行合并,得出米里标准特性表。如表 5.2 所示。 表 5.2 米里型时序逻辑电路的特性表 X Q0 Q1 Q0n+1 Q1n+1 Z 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 0 0 0 0 1 0 1 1 0 0 1 1 1 0 1 0 下面我们就可以根据特性表来画出它的状态图,如图 5.6 所示。 0/0 00 01 1/0 0/1 1/1 1/0 0/0 11 1/0 10 0/0 图 5.6 米里型时序逻辑的状态图 通过特性图我们可以看出,当外部输入 X 等于 0 时,状态转移按 00→01→10→11→00 循环 变化,因此可以实现模 4 加法计数器功能。当外部输入 X 等于 1 时,状态转移按 00→11→10→ 01→00 循环变化,因此可以实现模 4 减法计数器功能。最后我们总结得出,该电路时一个同步 模 4 可逆计数器。至此时序电路的分析就已经讲完啦。下面我们开始讲解时序电路的设计。 http://www.fpga.gs/ 82 数字电路篇 §5 §5.2 时序逻辑电路的设计方法 时序逻辑电路的设计过程也同样和组合电路一样是分析的逆过程,就是要求设计者根据给 出的具体逻辑功能,求出实现这一逻辑功能的逻辑电路。同样我们这里也是举例进行说明,这里 我们就以前面提到过的自动售货机为例设计一个简易的自动售货机。 我们要求该自动售货机只能投入一元硬币,当连续投入三个硬币以后,售货机才会给出一瓶 饮料,假如我们投入了两枚硬币,发现没有硬币了,不好意思,我们的自动售货机是不会退币给 你,直至你投入三枚硬币才会输出饮料。从前面的要求中我们可以分析得到该电路有一个输入和 一个输出是一个米里型电路,这里我们假设 X 为一元硬币输入,投入一元硬币 X 为 1,未投入 一元硬币 X 就为 0, Z 为饮料输出,送出饮料 Z 为 1,未送出饮料 Z 就为 0。我们还能分析得 出该电路的状态,这里我们假设 S0 为初态,S1 为投入一元后的状态,S2 为投入两元后的状态。 下面我们就可以开始设计,建立状态图是进行成功设计的第一步,这一步很关键,而且也是 比较困难的一步,因为它没有规律可循,只有具体问题作具体分析,根据不同的设计要求找出其 对应的逻辑关系并建立出状态图。接下里我们就来进行具体的分析。首先我们设自动售货机处于 S0 状态,紧接着我们投入一个一元硬币,也就是说 X 等于 1,那么电路状态由 S0 转换到 S1 状 态,表示已收到一枚硬币,又因为只收到一个一枚硬币,饮料不会送出,也就是说, Z 为 0。当 电路处于 S1 状态时,我们同样在投入一个一元硬币,也就是说 X 等于 1,那么电路状态会由 S1 状态转换到 S2 状态,表示已连续收到两个一元硬币,但因为只连续收到两个,饮料也不会送出, Z 也就为 0。当电路处于 S2 状态时,我们再投入一枚一元硬币,也就是说 X 等于 1,那么电路 状态会由 S2 状态转换到 S0 状态,表示已连续收到三个一元硬币,此时,饮料变会送出,Z 也就 为 1。结合以上分析我们便可以画出本电路的状态图,如图 5.7 所示。 0/0 00 1/1 1/0 0/0 10 1/0 01 0/0 图 5.7 自动售货机的状态图 下面我们根据状态图,来进行状态编码,我们知道这里我们用到了三个状态,即 M  3 ,根 据 2n1  M  2n ,可以确定触发器个数 n  2 个,我们利用两个触发器就可以来实现三个不同 的状态。这里两个触发器有四种不同的组合状态 00,01,10,11,我们设 S0  00 , S1  01 , S2  10 ,这样可得编码后的特性表,大家看这就是该电路的特性表,如表 5.3 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §5 时序逻辑电路的设计与分析 83 表 5.3 自动售货机的特性表 X Q0 Q1 Q0n+1 Q1n+1 Z 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 1 X X X 1 0 0 1 0 0 1 1 0 0 1 0 1 0 1 0 0 1 1 1 1 X X X 其中,11 为无效状态。我们将特性表拆分可以得出 Qn1 1 、Q0n1 和 Z 的特性表,然后我们依 次根据特性表来写出它的状态方程和输出方程,这里我们用的是边沿 D 触发器来实现电路,所 以我们根据边沿 D 触发器的特性方程( Qn1  D )中可以得出该电路的驱动方程和输出方程, 它的驱动方程为: Qn1 1  D1  X Q1Q0  XQ1Q0 Qn1 0  D0  X Q1Q0  X Q1Q0 它的输出方程为: Z  XQ1Q0 然后我们根据得出的方程最终来画出电路图。 X 1 & Z & ≥1 & D1 Q1 FF1 & ≥1 & D0 Q0 FF0 CLK 图 5.8 自动售货机的电路图 至此自动售货机的设计就已经完成了。下面我们来总结一下时序电路分析和设计的过程。时 序电路的分析就是根据给定的时序电路,分析出电路的逻辑功能。我们可以遵循以下方法来完成 时序电路的分析,第一步,通过时序电路写出激励方程、输出方程和状态方程,第二步,通过状 态方程列出状态表、画出状态图。第三步,就是根据状态表和状态图来总结说明电路的逻辑功能。 时序电路的设计就是根据给定的逻辑功能要求,设计出相应的逻辑电路。它是时序逻辑电路分析 的逆过程,其方法只需要与时序电路分析相反即可完成设计。 http://www.fpga.gs/ 可编程逻辑器件 第六章 可编程逻辑器件 可编程逻辑器件 PLD(即 Programmable Logic Device),PLD 是在专用集成电路的基础上 发展起来的一种新型逻辑器件,其主要特点就是完全由用户通过软件进行配置和编程,从而完成 特定的功能,并且该器件可以反复擦写进行修改。这一特点使硬件设计工作成为软件开发工作, 缩短了系统设计的周期,提高了实现的灵活性并降低了成本,因此获得了广大硬件工程师的青睐, 广泛的应用在各个领域。下面我们来看下 PLD 的发展历程,如图 6.1 所示。 20世纪70年代 至今 PROM PLA PAL GAL CPLD FPGA PLD起源 简单PLD 图 6.1 PLD 的发展历程图 复杂PLD 从图中我们可以看出,可编程逻辑器件的发展大致可以划分为 3 个阶段,从 20 世纪 70 年 代初到 70 年代中为第 1 阶段,第 1 阶段出现了可编程只读存储器(PROM)。20 世纪 70 年代 中到 80 年代中为第 2 阶段,第 2 阶段出现了简单的可编程阵列逻辑 PAL 和可编程逻辑阵列 PLA 器件。20 世纪 80 年代到 90 年代末为第 3 阶段,第 3 阶段出现了复杂的可编程逻辑器件 CPLD 和现场可编程门阵列 FPGA。接下来我们便对这三个阶段分别进行详解,让大家了解 PLD 是如何实现的。下面我们就来看下第 1 阶段,可编程只读存储器 PROM,在讲解 PROM 之前, 我们首先要来了解一下存储器。 §6.1 第一阶段:存储器 所谓存储器就是一种用于长期存储大量数据、资料及运算程序等二进制信息的器件。存储器 的种类很多,从存、取功能上可以分为只读存储器(ROM)和随机存储器(RAM)两大类,下 面我们对这两种类型的存储器分别进行讲解。 6.1.1 只读存储器 存储器 ROM(Read Only Memory)是一种存放固定信息的半导体件,ROM 中存储的信息 是制造时由生产厂家一次写入的。这种器件在正常工作时只能读出信息,而不能写入信息,即使 切断电源,器件中的信息也不会丢失。所以,ROM 通常用来存储那些不经常改变的信息。下面 我们给出 ROM 的电路结构框架图,如图 6.2 所示。 88 数字电路篇 §6 地 址 输 … … 入 地 址 译 … 码 … 器 输 存储矩阵 … 出 缓 … 冲 器 数 据 输 出 地址线 字线 位线 图 6.2 只读存储器 ROM 的电路结构框图 从电路结构框架图中我们可以看出,ROM 是由存储矩阵、地址译码器和输出缓冲期三个组 成部分。存储矩阵是由许多存储单元排列而成,存储单元是用二极管构成,也可以利用双极型三 极管或 MOS 管构成,每个单元能存放 1 位二进制代码,每一个存储单元有一个对应的地址输入 码。地址译码器的作用是将输入的地址输入码译成相应的控制信号,利用这个控制信号从存储矩 阵中将指定的存储单元选出,并把其中的数据送到输出缓冲器。输出缓冲期的作用有两个,一是 能提高存储器的带负载能力,二是实现对输出状态的三态控制,以便与系统的总线连接。 下面我们进一步分析,从电路结构框架图中我们还可以看出,它有 n 位地址输入线,对应图 上 的 A0 ~ An1 , n 位 地 址 线 经 过 地 址 译 码 器 , 可 以 译 出 2n 条 译 码 输 出 线 , 对 应 图 上 的 W0 ~ W2n 1。当给定一个地址输入码时,译码器只有一个输出被选中,这个被选中的线可以在存 储阵列中取得 m 位的二进制信息,使其呈现在数据输出线 F0 ~ Fm1 上,这 m 位的二进制信息 称为一个字,因而W0 ~ W2n 1 称为字线, F0 ~ Fm1 称为位线,字的位数又称为字长。对于有 n 条地址输入线, m 条位线的 ROM,能存储 2n 个字的信息,每个字有 m 为,每位可以存储一个 0,或一个 1 的信息,整个存储阵列的存储容量用字数乘位数来表示。因此我们可以称该 ROM 的存储绒里为 2n  m 。为了让大家更易理解,下面我们以一个存储容量为 4X4 大小的 ROM 为 例进行讲解说明,下面我们给出它的内部结构原理图,如图 6.3 所示。 Vcc A1 A0 W0 W1 W2 W3 D3 D2 D1 D0 图 6.3 只读存储器 ROM 的内部结构原理图 从该电路内部原理图中我们可以看出,该 ROM 具有 2 位地址输入码和 4 为数据输出,2 位 Zircon Opto-Electronic Technology CO.,Ltd. §6 可编程逻辑器件 89 地址输入码 A1 和 A0 能给出 4 个不同的地址,地址译码器将这 4 个地址代码分别译成W0 、W1 、 W2 、W3 。它的地址译码器是由 8 个二极管组成,其中每两个二极管就能构成一个与门,因此 我们也可以将地址译码器称为与门阵列,只有当位线上的两个二极管同时截止的时候,位线才能 选通,存储矩阵实际上是由 4 个二极管或门组成的编码器,当W0 ~ W3 每根线上给出高电平信 号时,都会在 D3 ~ D0 四根线上输出一个 4 位二值代码。 这里的 A1 和 A0 就是地址线,W0 ~ W3 就是字线, D3 ~ D0 就是位线,字线和位线的每个 交叉点都是一个存储单元。交点处接有二极管时相当于存 1,没有接二极管时相当于寸 0。交叉 点的数目也就是存储单元数,在读取数据时,只要输入指定的地址码,则指定地址内各存储单元 所存的数据便会出现在输出数据线上。例如,当 A1A0  10 时,W2  1 ,而其他字线均为低电平。 由于只有 D2 一根线与W2 间接有二极管,所以这个二极管导通后使 D2 位高电平,而 D0 、 D1 和 D3 位低电平。于是在数据输出端得到 D3D2D1D0  0100 。 6.1.2 可编程只读存储器 通过前面的学习我们知道,ROM 中固定信息是制造时存入的,产品出厂后用户无法改动, 然而用户经常希望根据自己的需要来确定 ROM 的存储内容,为了满足这种要求,人们在 ROM 的基础上进行了修改,设计出了 PROM(Programmable Read Only Memory)可编程只读存储 器。下面就来看看只读存储器 ROM 是如何变成可编程只读存储器 PROM 的,我们直接给出 PROM 的内部结构原理图,如图 6.4 所示。 Vcc A1 A0 W0 W1 W2 W3 D3 D2 D1 D0 图 6.4 可编程只读存储器 PROM 的内部结构原理图 从该电路内部原理图中我们可以看出,PROM 的总体结构与 ROM 一样,同样也是由地址 译码器、存储矩阵和输出电路组成,唯一不同的是 PROM 在 ROM 的原有二极管的基础上串了 一个可熔断熔丝。因此 PROM 在出厂时将存储矩阵的所有交叉点全部制作了存储元件,相当于 在所有存储单元中都存入了 1,熔丝用很细的低熔点合金丝或多晶硅导线制成,在写入数据时只 要设法将需要存入 0 的那些存储单元上的熔丝烧断就行了,因此,PROM 的与门阵列是固定的, 而或门阵列就变成了可编程的,PROM 的内容一经写入以后,就不能修改,所以它只能写入一 http://www.fpga.gs/ 90 数字电路篇 §6 次,我们也称可编程只读存储器为一次可编程存储器。 虽然人们实现了可编程只读存储器,但是它只允许编程一次,这仍然不能达到人们需求,因 此人们又设计出了 EPROM(Erasable Programmable Read Only Memory)可擦除、可重新编 程的只读存储器,EPROM 是一种可擦除、可重新编程的只读存储器。对已写入信息的 EPROM, 如果想改写,可用专用的紫外线灯照射芯片上的受光窗口,经过 10~20min 时间,就能将芯片中 的原有信息擦除掉,又可以写入需要的信息。由于该部分内容不是重点,这里我们就不进一步抛 开来将,这里只做了解即可。 由于 EPROM 擦除操作需要紫外线或 X 射线,擦除时间也较长,而且只能整体擦除,不能 单独擦除某一存储单元的内容。作为一个优秀的电子工程师,我们不能止步不前,我们要勇往直 前,因此又设计出了 EEPROM(Electrically Erasable Programmable Read Only Memory)电 可擦可编程只读存储器,也称为 E²PROM,E²PROM 克服了 EPROM 的缺点,E²PROM 的结 构与 EPROM 相似,E²PROM 擦除和编程都用电完成,可整片擦除也可使某数存储单元独立擦 除,擦除时间可在 10ms 以内。这种器件的另一个突出优点是它的重复编程次数大大高于 EPROM,可达 10000 次以上(视型号而异)。 6.1.3 随机存取存储器 随机存取存储器 RAM(Random Access Memory),主要用来存放程序及程序执行过程中 产生的中间数据、运算结果等。RAM 可以按照需要随意地读写其内部存储单元的内容,且读写 的速度与存储单元在存储芯片中的位置无关,它与只读存储器最大的区别就是,随机存储器在断 电时将会丢失其存储内容,而只读存储器不会,所以随机存储器主要用来存储短时间使用的程序。 按照存储单元的工作原理,随机存储器又分为静态随机存储器(Static RAM,SRAM)和动 态随机存储器(Dynamic RAM,DRAM)。SRAM 和 DRAM 最大区别就是:DRAM 是用电容有 无电荷来表示信息 0 和 1,为防止电容漏电而导致读取信息出错,需要周期性地给电容充电,即 刷新;而 SRAM 是利用触发器的两个稳态来表示信息 0 和 1,所以不需要刷新。另外,SRAM 的存取速度比 DRAM 快,价格比 DRAM 高,所以 SRAM 一般容量都比较小,常用作高速缓冲 存储器 Cache。DRAM 保留数据的时间很短,速度也比 SRAM 慢,不过它还是比任何的 ROM 都要快,但从价格上来说 DRAM 相比 SRAM 要便宜很多,计算机内存就是 DRAM 的。 §6.2 第二阶段:可编程逻辑阵列和可编程阵列逻辑 6.2.1 可编程逻辑阵列 通过前面的 ROM 的学习,我们知道一个 2 输入的 ROM 需要 4 个与门,一个 10 输入的 PROM 则需要 210 个与门。在这种固定的与门阵列和可编程的或门阵列组合而成的结构中,随着 输入端口的数量增加,我们可以发现与阵列的规模会急剧增加,器件的工作速度也会变慢,现如 今我们使用的 PLD 输入管脚多达百个,那么想要实现 100 多个输入的 PROM 可编程器件,可 想而知是有多么的恐怖!为了克服这种问题,人们便在 PROM 的结构基础上进行了设计修改, 因此设计出了可编程阵列逻辑 PAL(Programmable Array Logic)和可编程逻辑阵列 PLA (Programmable Logic Arrays)。下面我们就来看一看可编程阵列逻辑 PLA 和可编程逻辑阵列 Zircon Opto-Electronic Technology CO.,Ltd. §6 可编程逻辑器件 91 PAL 是如何从 PROM 的结构中修改而来的。我们给出 PLA 的框架示意图,如图 6.5 所示。 可编程 可编程 与 或 门 门 矩 矩 阵 阵 图 6.5 PLA 的框架示意图 从框架图中我们可以看出,PLA 不仅或门矩阵可以编程,与阵列也是可以可编程的,因此 PLA 的利用率较高,又由于 PLA 与阵列不采用全译码方式,所以在 PAL 中能够很好的解决随 着输入变量的增加规模迅速增加的问题。虽然 PLA 的利用率高,但是与阵列、或阵列都是可编 程的结构导致了软件算法过于复杂, 编程难度和费用上都有所增加,不可避免地使编程后器件 的运行速度下降,PLA 的使用受到了限制。因此,人们又设计出了可编程阵列逻辑 PAL。 6.2.2 可编程阵列逻辑 下面我们给出 PAL 的框架示意图,如图 6.6 所示。 可编程 固定的 与 或 门 门 矩 矩 阵 阵 图 6.6 PAL 的框架示意图 从框架图中我们可以看出,PAL 简易框架图正好与 PROM 相反,这种结构的与阵列也不是 全译码方式的,因而具有 PLA 型结构速度快的优点,同时,它只有一个与阵列是可编程的,因 而它编程容易实现,费用也比较低。 随着电子技术的进步与发展,人们便在 PAL 的基础上进行了改进,设计出了通用阵列逻辑 GAL,GAL 的基本结构和 PAL 类似,下面我们给出它们的内部结构图,如图 6.7 所示。 http://www.fpga.gs/ 92 数字电路篇 §6 PAL16L8 GAL16V8 图 6.7 PAL 与 GAL 的内部结构对比图 从它们的对比图中我们可以看出,它们都是由可编程的与阵列和固定的或阵列组成,其区别 主要是输出结构不同,GAL 继承并发展了 PAL 器件的优点,克服了 PAL 器件的不足,通过引 入电可擦除编程方法与可编程的输出逻辑宏单元,对 PAL 的用途进行了很好的扩展。 §6.3 第三阶段:FPGA和CPLD 下面我们就来介绍第三阶段复杂的可编程逻辑器件 CPLD 和现成可编程门阵列器件 FPGA。 所谓复杂可编程逻辑器件 CPLD(Complex Programmable Logic Device),就是一种用户根据各 自需要而自行构造逻辑功能的数字集成电路,是从 PAL 和 GAL 器件发展出来的器件,相对而言 规模大,结构复杂,属于大规模集成电路范围,其基本设计方法是借助集成开发软件平台,用原 理图、硬件描述语言等方法,生成相应的目标文件,通过下载电缆(“在系统”编程)将代码传 送到目标芯片中,实现设计的数字系统。所谓现场可编程门阵列 FPGA(Field-Programmable Gate Array),就是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定 制电路的不足,又克服了原有可编程器件门电路数有限的缺点,是在 PAL、GAL、CPLD 等可 编程器件的基础上进一步发展的产物。 6.3.1 复杂可编程逻辑器件 首先我们先来看下 CPLD,CPLD 是从 GAL 器件的基础上改进得到的,相对而言规模大, 结构复杂,属于大规模集成电路范围。下面我们就以 MAX3000A CPLD 为例,首先我们给出 MAX3000A 典型的框架结构图,如图 6.8 所示。 Zircon Opto-Electronic Technology CO.,Ltd. §6 可编程逻辑器件 93 图 6.8 MAX 3000A 的结构框架图 从图中我们可以看出,它主要由逻辑阵列块(LAB, Logic Array Block)、 宏单元(Macro cells)、 可编程连线(PIA,Programmable Interface Array)和 I/O 控制块等四部分组成。 宏单元是 CPLD 的基本结构,由它来实现基本的逻辑功能,因为宏单元较多,我们就没有一一画出,可编程连线 PIA 负责信号传递,连接所有的宏单元。I/O 控制块负责 I/O 的电气特性控制。INPUT/GCLK1, NPUT/OE1,INPUT/OE2/GCLK2 是全局时钟,清零和输出使能信号,这几个信号有专用连线 与 CPLD 中每个宏单元相连,信号到每个宏单元的延时相同并且延时最短。 大家看到这里也许就会产生这样一个疑问,前面我们总是说那些简单的 PLD 是复杂 PLD 的 基础,那么在这里我也没有看到那些与门阵列和或门阵列。其实我们这里说它是复杂的 PLD 肯 定是比那些简单的复杂的多。下面我们就来看下 LAB,一个 LAB 是由 1~16 个宏单元组成的, 那宏单元又是什么呢,下面我们给出宏单元的内部电路结构图,如图 6.9 所示。 图 6.9 MAX 3000A 的 LAB 内部结构图 http://www.fpga.gs/ 94 数字电路篇 §6 从图中我们可以看出,它左边的结构框架就是我们所熟悉的与门阵列和或门阵列,右边的结 构框架就是输出结构。 6.3.2 现场可编程门阵列 接下来我们来看下现场可编程门阵列 FPGA,FPGA 是大规模可编程逻辑器件除 CPLD 外 的另一类器件,前面我们提到的 CPLD 是基于乘积项的可编程结构,也就是说,可编程的与阵 列和固定的或项组成,FPGA 则不同于 CPLD 的乘积项结构,它采用了一个全新的构架,下面 我们通过这张图来了解一下 CPLD 构架和 FPGA 构架的不同,如图 6.10 所示。 LAB LAB LAB LAB LAB LAB LAB LAB LAB 全局布线资源 LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB LAB 图 6.10 CPLD 架构与 FPGA 架构对比图 左边是传统的 CPLD 构架,就是我们刚才说的,由逻辑阵列快 LAB 和可编程连线 PIA 组 成,利用 PIA 将 LAB 互相连接起来,CPLD 相对于老的 PLD 器件最大的进步主要是在于它能 够在单个器件中容纳大量的逻辑。理论上,可以不断在 CPLD 中加入 LAB,继续增加逻辑数量。 但实际上,随着 LAB 的增加,可编程连线 PIA 则乘指数性增加,布线资源占据了大量面积,直 到芯片的连线数量超过了逻辑数量,因此,大容量的 CPLD 成本会非常的高。如果我们能够省 去了全局布线资源,把 LAB 更加高密度的排列在器件内,而不是围绕在布线互连周围,情况会 怎么样呢? 现场可编程门阵列 FPGA 便是如此,它没有采用中心全局器件互连,正如其名称所暗示的, 它将 LAB 排在阵列中,布线放置在 LAB 之间的空格上,就像大城市的接到,这种布线被排列成 行列互连的形式,它可以跨过器件的整个长度和宽度,或者器件的一小部分,只覆盖行列中的几 个 LAB。随着 LAB 的增加,它的布线资源是线性增加的,所以,这种结构可以实现大容量、低 成本的逻辑器件。FPGA 的 LAB 和 CPLD 的 LAB 设计也是不同的,CPLD 的 LAB 是由宏单元 构成,每个单元又是我们所熟悉的与门阵列和或门阵列结构,而 FPGA 的 LAB 从根本上抛弃了 大量使用与门阵列和或门阵列的思路,它是由大量的逻辑单元 LE 构成,LE 是基于查找表结构 的。目前 FPGA 中多使用 4 输入的 LUT,所以每个 LUT 可以看成一个又 4 为地址线的 16X1 的 RAM,当用户通过原理图或者 HDL 语言描述一个逻辑电路以后,FPGA 开发软件会自动计算逻 辑电路的所有可能的结果,并把结果实现写入 RAM,这样,每输入一个信号进行逻辑运算就等 Zircon Opto-Electronic Technology CO.,Ltd. §6 可编程逻辑器件 95 于输入一个地址进行查表,找出地址对应的内容,然后输出即可。下面我们举例进行说明,如图 6.11 所示。 实际逻辑电路 LUT的实现方式 a b c & out d 地址线 a b c d 16x1 RAM (LUT) 输出 a,b,c,d输入 0000 0001 …. 1111 逻辑输出 地址 0 0000 0 0001 0 …. 1 1111 图 6.11 LUT 的实现原理图 RAM中存储的内容 0 0 0 1 从图中我们可以看出它是一个 4 输入与门,与门是有 0 就为 0,全 1 就为 1,所以只有 4 个 都为 1 时,输出才会为 1,其他情况就为 0,我们用 LUT 实现的结果也是一样的,我们把输入当 成地址,把 RAM 中存储的内容作为输出,我们只要将地址 0000~1110 内容全写 0,只有 1111 内 容写 1,因此这两个电路完全等同。 知道了 FPGA 的工作原理,下面我们再来看下 FPGA 的内部结构,由于我们 A4 开发板使 用的是 Cyclone IV 系列器件,所以我们这里就以此类器件为例,介绍 FPGA 的内部结构,Cyclone IV 器件主要是由逻辑阵列块(Logic Array Block,LAB)、嵌入式存储器块、嵌入式硬件乘法器、 I/O 单元和 PLL 等模块构成,在各个模块之间存在着丰富的互连线和时钟网络。随着 FPGA 的 不断发展,FPGA 芯片的内部结构也越来越复杂,并且包含的资源种类也越来越多,但是,最基 本的架构还是由 LAB、I/O 单元和灵活多变的连线资源三个部分组成,下面我们就对这三个部分 分别进行介绍。 首先我们介绍的是逻辑阵列块(LAB),Cyclone IV 器件的可编程资源主要来自逻辑阵列块 (LAB),每个 LAB 都是由多个逻辑宏单元 LE(Logic Element,LE)构成,逻辑单元(Logic Element,LE)在 FPGA 器件内部,用于完成用户逻辑的最小单元,其内部结构,如图 6.12 所 示。 http://www.fpga.gs/ 96 数字电路篇 §6 图 6.12 逻辑单元 LE 的内部结构图 从个该图中我们可以看出,一个逻辑单元 LE 主要由一个 4 输入的查找表(LookUp Table, LUT)、可编程的寄存器、进位链和寄存器链四个部分组成,4 输入的 LUT 可以完成所有的 4 输 入 1 输出的组合逻辑功能。每一个 LE 的输出都可以连接到行、列、直连通路、进位链、寄存器 链等布线资源。每个 LE 中的可编程寄存器都可以被配置成 D 触发器,T 触发器,JK 触发器, RS 触发器模式。每个可编程寄存器都具有数据、时钟、时钟使能、清 0 输入信号。LE 有 3 个 输出,一个驱动本地互连,另两个驱动行或列的互连资源。LUT 和寄存器的输出可以单独控制, 进而实现了在一个 LE 中,LUT 驱动一个输出,而寄存器驱动另一个输出(这种计数称为寄存器 打包)。因而在一个 LE 中的寄存器和 LUT 能够用来完成不相关的功能,因此能够提高 LE 的资 源利用率。在一个逻辑阵列块中的 LE 还可以通过寄存器链进行级联。在同一个 LAB 中的 LE 里 的寄存器可以通过寄存器链级联在一起,构成一个移位寄存器,那些 LE 中的 LUT 资源可以单 独实现组合逻辑功能,两者互不相关。Cyclone IV 的 LE 可以工作在两种操作模式下,即普通模 式和算术模式。普通模式下的 LE 适合通用逻辑应用和组合逻辑应用的实现。算术模式下的 LE 可以更好地实现加法器、计数器、累加器和比较器。 介绍完了逻辑阵列块(LAB),接下来我们介绍的是 I/O 单元,I/O 单元是可编程输入/输出单 元(IOB)的简称,它是芯片与外界电路的接口部分,完成不同电气特性下对输入/输出信号的驱 动与匹配要求,比如从基本的 LVTTL/LVCMOS 接口到 PCI/LVDS/RSDS 甚至各种各样的差分 接口,从 5V 兼容到 3.3V/2.5V/1.8V/1.5V 的电平接口。为了便于管理和适应多种电器标准,FPGA 的 IOB 被划分为若干个组(bank),每组都能够独立地支持不同的 I/O 标准,通过软件的灵活配 置,可匹配不同的电器标准与 IO 物理特性,而且可以调整驱动电流的大小,可以改变上/下拉电 阻,Cyclone IV 设备有 8 个 IO blank(组),如图 6.13 所。 Zircon Opto-Electronic Technology CO.,Ltd. §6 可编程逻辑器件 97 图 6.13 Cyclone IV 器件中的 8 个 IO blank 分布图 介绍完了 I/O 单元,最后我们再来看下灵活多变的连线资源,FPGA 中的布局布线资源主要 包括三部分:连线盒 CB(Connection box)、开关盒 SB(Switch box)和行列连线。布线资源 的目的是为了能够让位于不同位置的逻辑资源块、时钟处理单元、BLOCK、RAM、DSP 和接口 模块等资源能够相互通信,从而协调合作,完成所需功能,如图 6.14 所示。 图 6.14 内部结构连线图 FPGA 中的布线资源,就好比绘制 PCB 板时的连线资源一样,虽然器件 A 和器件 B 的位 置和连接关系没有任何改变,但很可能因为周边电路的布局、布线的一些变化,使得前后两次 A、 B 之间的连线形态发生很大的变化。因此,与采用固定长度的金属线将所有宏单元连接在一起的 CPLD 不同,FPGA 中任意两点之间的线延迟是无法预测的,必须等到布局、布线完成之后才能 确定。这也是为什么在 FPGA 的开发中,时序约束和时序分析这两样工作时必不可少的。 至此,可编程逻辑器件的基础就已经讲完啦,每一个最后看来很成功的新事物,从诞生到发 展壮大都不可避免地经历过艰难的历程,FPGA 也是如此,它并不是凭空出现的,而是一步步发 http://www.fpga.gs/ 98 数字电路篇 §6 展而来的。 Zircon Opto-Electronic Technology CO.,Ltd. 版权声明 (1) 南京锆石光电科技有限公司对其发行的或与合作公司共同发行的包括但不限于产品或 服务的全部内容拥有版权等知识产权,受法律保护。 (2) 所有产品及资料内容仅供用户学习使用。 (3) 未经本公司书面许可,任何单位及个人不得以任何方式或理由对上述产品、服务、信息、 材料的任何部分进行复制、修改、抄录或与其它产品捆绑使用、销售。 (4) 凡侵犯本公司版权等知识产权的,本公司必依法追究其法律责任。 声明单位:南京锆石光电科技有限公司

Top_arrow
回到顶部
EEWORLD下载中心所有资源均来自网友分享,如有侵权,请发送举报邮件到客服邮箱bbs_service@eeworld.com.cn 或通过站内短信息或QQ:273568022联系管理员 高进,我们会尽快处理。