type
status
date
slug
summary
tags
category
icon
password
6.1 同步时序电路的基本概念
6.1.1 时序逻辑电路的定义与结构
6.1.1.1 时序逻辑电路的特点
任一时刻的输出既与即刻输入有关(若有输入),还与电路当时的状态有关(和以前的输入有关)。即电路具有记忆能力。
6.1.1.2 时序逻辑电路的结构
时序逻辑电路的结构如下图:
其中存储元件就是触发器了
其中各个符号的含义为:
这里的Z(tn)就可以理解为触发器的输入端了,这个输入会导致电路状态的转移。
因此时序逻辑电路一般用以下三个方程描述:
- 输出方程: Y(tn)=F[X(tn),Q(tn)]
- 激励方程: Z(tn)=G[X(tn),Q(tn)]
- 状态方程: Q(tn+1)=H[Z(tn),Q(tn)]
需要注意的是这三个方程中一定不能包含触发器的输入端信号名称。如分析某个JK触发器构成的时序逻辑电路,那么这三个方程中不能出现J和K,只能使用X(tn)和Q(tn)来表示。换句话说,在得出状态方程的时候,一定要带入激励方程。如下面这个例子:
这里在最后得出的状态方程中就是把激励方程带入了状态方程中。
6.1.2 时序逻辑电路的分类
- 按电路中触发器状态变化是否同步分类:若时钟CP同时加到每一个存储元件上为同步,否则为异步。
- 同步时序逻辑电路
- 异步时序逻辑电路
- 按输出信号的特性分类
- Moore型(简洁型):无输入X,或有输入X,但:Y(tn)=F[Q(tn)]
- Mealy型:一定有输入X,且Y(tn)=F[X(tn) ,Q(tn)]
总而言之就是摩尔型时序逻辑电路的输出信号仅与状态有关。这里提到的简洁也是因为摩尔型时序逻辑电路的输出信号的逻辑表达式比较简单
即米里型状态机的输出与输入信号还有关
6.1.3 同步时序逻辑电路的描述方法
- 方程组:输出方程、激励方程和状态方程
- 状态转换真值表(实际上就是真值表)
- 状态转换图(状态机)
- 时序图或称工作波形图
6.2 同步时序电路分析
6.2.1 分析方法
- 列方程组
- 根据方程组列出状态转换表
- 作出状态图
- 作出时序图(时间图、工作波形图)
考试的时候如果时间允许(或者看看题目的要求)的话可以画一下这个波形图
- 用文字描述电路的功能
与组合逻辑电路一样,通常情况下,在时序逻辑电路的分析中将会给出电路图
这里给出一个时序逻辑电路的分析示例:
- 求方程组
- 求状态转换表
- 状态转换图
需要注意的是,在状态图中只需要关注主循环的功能
- 波形图
- 描述电路功能:该电路为7进制加法计数器
在CP为周期信号时,计数器可以用作分频器:
其余的题都差不多,这里就不再赘述了
需要知道一些常用的功能:
- 计数器
- 可异计数器:也就是可以根据输入信号调整电路的加减功能
- 无权计数器:触发器中的值没有实际含义,但是状态图中仍然存在计数器的状态圈
- 串行加法器
- 单脉冲发生器
6.3 同步时序电路设计
同步时序电路的设计步骤为:
- 分析要求,作状态图;
- 状态化简;
- 选触发器及确定触发器的个数;
- 状态分配(状态编码);
- 作状态转换真值表;
- 求出状态方程、激励方程和输出方程;
- 对存在无效状态的电路,检查能否自启动;
- 电路图。
6.3.1 形成原始状态图与状态表
在这里会提到一个东西就是状态表,这个并不是步骤中要求的,这相当于是一个在设计同步时序逻辑电路过程中出现的一个中间产物(在ppt上应该被称为原始状态表)。
6.3.1仅仅对应了同步时序逻辑电路设计步骤中的第一步
这里以结合一个例题来看:
- 形成原始状态图
- 与组合逻辑电路的设计相同,首先需要对要求进行逻辑抽象
- 然后按照题目需求绘制状态转换图即可
例如在序列检测器中,可能就需要先规定S0是未检测到有效字符,S1为检测到一个有效字符。。。等等
上题中的状态图应该为:
在序列检测器中,通常最简米里状态机的状态数量恰好等于需要检测的字符串的长度。如本题检测101序列,那么最简米里状态机中的状态数量就是三个。而摩尔状态机就会多一个检测到全部字符的状态,因此最简摩尔状态机的状态通常为需要检测的字符串的长度加一。
- 绘制状态表
这里不太好描述状态表是什么样的,所以直接看例题的状态表:
状态不是满的 的时候,需要补充d。这个补充d是一个伏笔,在后面提到能否自启动的时候会涉及到。
另外关于状态表,就是在化简之前,都会使用上述这个形式的状态表;如果能保证是最简的化,就到了后面的步骤——绘制状态转换真值表了。这里由于已经是最简状态机了,因此可以直接得到状态转换真值表:
- 完全确定状态表与不完全确定状态表
- 完全确定状态表:若状态表中的次态和输出都有确定的状态和输出,则称为完全确定状态表。
- 不完全确定状态表:存在约束项的状态表称不完全确定状态表,它所描述的电路叫不完全确定电路。
在上面的例题中,状态表中存在无效状态(也就是存在d),这就引出了一个状态表的分类
6.3.2 状态化简
状态化简通常是基于前面的那个临时状态表来做的。
- 化简的目的
- 减少触发器的数量
- 简化激励方程
对这个简化激励方程的理解是:触发器数量减少了,激励方程的个数自然就减少了(因为激励方程是在描述每一个触发器的输入端情况)
- 化简的目的:省略等效状态
等效状态最简单的判别方法是:“输入相同,输出相同,到达的次态也相同”。也就是对两个状态而言,他们在临时状态表中对应的行完全相同。但是这个判断并不是完备的,不能找到所有的等效类。具体判断状态等效的方法在后面会介绍。
6.3.2.1 完全确定状态表的化简
首先需要知道一些概念:
- 等效状态:设状态S1和S2是完全确定状态表中的两个状态,如果对于所有可能的输入序列,分别从状态S1和S2出发,所得到的输出和次态序列完全相同,则状态S1和S2是等效的。记为(S1,S2)
需要注意的是,这里说的是次态序列,而不是单一的一个次态。这个条件就是完备的了,能够找出所有的最大等效类
- 等效状态的性质——传递性:若状态S1和S2是等效的,状态S2和S3是等效的,则状态S1和S3也是等效的。
- 等效类:是彼此等效的状态的集合称为等效类。
- 最大等效类:若一个等效类不是任何其它等效类的子集,则此等效类称为最大等效类。即使是一个状态,只要它不包含在别的等效类中,它也是最大等效类。
就是不能再向这个等效类中添加其他的状态了(大的不能再大)
因此:状态化简就是从原始状态表中找出最大等效类的集合,然后用一个新符号表示最大等效类,从而得到最小化状态表。
- 判定等效的方法
- 它们的输出完全相同
- 它们的次态满足下列条件之一(实际上就是判断次态序列是否完全相同)
- 次态相同
- 次态交错(循环)
- 次态保持原状态不变;
- 次态对等效。
在各种输入取值下:
这个就是最简单的判断条件了,用上面那个不完备的定义都可以判定出来
就是当状态图中存在这样的循环的时候,就需要小心看看能不能化简了。
这里是一个次态交错的例子:
这里是AB等效,CD等效。
还有一个例子:
这里是Se和Sj等效。
感觉这个相当于是第一个条件的扩展。有了这个条件,甚至可以是次次态对等效也能向上推出等效。
- 观察法化简
感觉观察法不太靠谱,还是使用后面的隐含表法好一点。这里就稍微提一下就好了。
观察法化简实际上就是使用上面那个不完备的等效定义来做的——也就是对两个状态而言,他们在临时状态表中对应的行完全相同。
如:
可以发现CD对应的行是完全相同的,因此CD是等效的。化简后得到的状态表为:
- 隐含表法状态化简
- 基本思想:对原始状态表中的所有状态两两比较,先找出一部分等效状态对。然后利用等效状态的传递性得到等效类和最大等效类;最后将最大等效类中的状态合并,得到最小化状态表。
- 隐含表的绘制:横向少尾,纵向少头。这里举一个例子:
- 隐含表的使用——顺序比较(相当于隐含表初始化吧,这里可以找到满足次态相等的等效)
- 状态对等效(在方格内填√)
- 状态对不等效(在方格内填×)
- 状态对是否等效需要进一步检查(填入次态对)
- 隐含表的使用——关联比较
- 次态交错:在上表中,已知C、F等效,而B、E又与A、E构成循环(这里就是次态交错?),故A、E是等效对,B、E也是等效对。
- 次态对等效:AB对应的方格中次态为CF,而CF有“√”表明CF等效,故判定AB等效。
- 确定最大等效类,作最小化状态表。
使用隐含表可以包含上面提到的判断等效时对次态要求中的第一点和第四点,二三点好像只能通过我们自己观察?
那么一句横向少尾,纵向少头的原则,隐含表的横向应该为变量A-F,纵向应该为变量B-G,即:
这里说的顺序比较是指:先将水平方向A与纵向的所有状态一一比较,再将水平方向B与纵向一一比较,依此类推。
比较的结果有三种情况:
这里说的不等效一般是看输出得出来的结论,就是两个状态在输出相同的时候,输出不同,那么这两个状态一定是不等效的。
如果出现自循环的话就假设是等效的。比如这个例子中的A和B在输入为1时的情况。
接着上面的例子,进行顺序比较之后的结果为:
实际上就是进一步检查隐含表中不确定是否等效的情况,在这里需要考虑次态交错和次态对等效的情况
这个其实就是上面的例1
需要注意的是,关联比较可能需要比较多次,才能得到最终的隐含表
上面各种修改隐含表都只是在求等效对,这里就需要使用传递性来找最大等效类了。等效对合并为最大等效类比较简单,这里就不再赘述了。
最终得到的最小状态表为
需要注意,在隐含表化简中没有在任何一个最大等效类中的变量也需要单独作为一个最大等效类体现在最简状态表中。
6.3.2.2 不完全确定状态表的化简
同样给出一些个概念:
- 相容状态:设S1和S2是不完全确定状态表中的两个状态,如果对于所有的有效输入序列,分别从S1和S2出发,所得到的输出响应序列和次态(除不确定的那些位外)是完全相同的,则S1和S2是相容的。记为(S1,S2),或者说S1和S2是相容状态对
- 相容类:所有状态之间都是两两相容的状态的集合,称为相容类。
要求两两相容是因为相容状态没有传递性
- 最大相容类:若一个相容类不是任何其它相容类的子集,则称该相容类为最大相容类。
也就是在这个相容类中无法再添加其他状态了
- 状态合并图:它将状态以“点”的形式均匀的绘在圆周上,然后把所有相容对都用线段连接起来,而所有点之间都有连线的多边型就构成了一个最大相容类。
这里说的“所有点之间都有连线的多边型”实际上就是一个完全图。所以我是感觉这个东西没啥太大用。。。
这里展示了一个包含五个状态的最大相容类的状态合并图:
- 相容状态的性质——无传递性:若S1和S2相容,S2和S3相容,但S1和S3不一定相容
这就是因为可能S2输出中有d,但是在将其和S1当成相容对的时候可能就会将d认为是0;而当将其和S3当成相容对的时候可能就会将d认为是1,这样S1和S3就不是相容的了(当然如果d的值被确定为同一个值的话,还是可以相容的)。
- 相容状态的判定
- 在输入的各种取值下
- 它们的输出完全相同,或者其中的一个或两个输出为任意值(d)。
- 它们的次态满足下列条件之一
- 次态相同;
- 次态交错;
- 次态保持原状态不变;
- 次态对相容
- 其中一个(或两个)为任意值。
这里仅仅是判定两个状态是否是相容的,所以只会在隐含表中用到。
- 不完全确定状态表的化简过程
- 作隐含表,寻找相容状态对(化简完全确定状态表相同)
- 画出状态合并图,找出最大相容类;
- 作出最小化状态表。
- 覆盖性:即所选的相容类的集合应包含原始状态表中的全部状态。
- 最小性:即所选相容类集合中的相容类个数应最少。(这也就要求每个相容类中包含的状态个数要尽可能多)
- 闭合性:即所选相容类集合中的任一相容类,在原始状态表中任一输入条件下产生的次态应该属于该集合中的某一相容类。(次状态们不跨类)
- 做隐含表,寻找相容状态对
- 作状态合并图,求最大相容类。
- 做闭覆盖表检查相容类
- 做最小状态表
这里需要使用上面的相容状态的判定方式来做,只不过这里还需要判定d。由于这个相容判定与等效判定的条件几乎一样,所以这里确实与上面化简完全确定状态表相同。
需要注意的是,关联比较并不是基于传递性的。
作最小化状态表时,先要从最大相容类中选出一组能覆盖原始状态表中全部状态的相容类,这一组相容类必须满足以下三个条件:
满足这三个条件的相容类的结合被称为最小闭覆盖
这里给出一个例子:
在相容状态的隐含表中,也是需要进行顺序比较和关联比较的。
由隐含表可以找到相容状态对,进而可以得出状态合并图:
检查之后发现目前得到的最大相容类集合为最小闭覆盖
这里使用A代替(A,B,F),用状态C代替(B,C,D,E,F)
表中X=0时,A的次态为A或C,那是因为(A,B,F)在X=0时的次态为B,而B既属于(A,B,F)又属于(B,C,D,E,F),所以可以用任意项“d”来表示。因此最终得到的最小化状态表为:
6.3.3 状态分配
状态分配有以下三个原则(在思考这些原则的原理的时候脑袋里想想卡诺图):
- 在相同输入条件下具有相同次态的现状态应分配逻辑相邻编码。
输入相同,并且如果为现状态分配了逻辑相邻的编码,那么这两种情况(这里的情况是指输入和状态的组合),他们是在卡诺图中相邻的。又由于他们的次态相同,因此在次态的每一位的卡诺图中,这两种情况的取值永远都是相同的,就可以使更多的“1”相邻(“0”如果也相邻的话,“1”相对的也相邻了)
- 同一现状态在相邻输入条件下的不同次态应分配逻辑相邻编码。
相邻输入条件,同一现态的情况在卡诺图中也是相邻的。为了尽可能使这两个相邻的情况的所填入的值(也就是次态某一位的值)相同,因此要尽可能保证这两种情况对应的次态尽可能相同,因此要给这两个次态分配逻辑相邻的编码。
- 在所有输入条件下具有相同输出的现状态应分配逻辑相邻编码。
在输出信号的卡诺图中,所有输入条件下(这个条件可以减弱为在相同输入的情况下),并且如果为这些输出相同的现状态分配逻辑相邻的编码的话,那么这些情况在卡诺图中也是相邻的,这样就可以使输出信号的卡诺图中有更多的“1”相邻。
通常情况下,状态分配将按照原则1→原则2→原则3的优先顺序进行分配。
这里给出一个例题:
总结出一个规律:先看纵向(也就是相同输入,不同现态,相同次态,即原则1),再看横向(相同现态,相邻输入,不同次态,即原则2),最后纵向看整行(也就是不同现态,所有输入,相同输出即原则3)。
状态分配在实际的题里面好像都没有要求,只要给出一种状态分配情况即可
在状态编码分配之后,就需要做出状态转换真值表。画真值表比较简单,这里不再赘述了。
6.3.4 求激励方程和输出方程
相较于上面的时序逻辑电路描述中的三个方程少了一个状态方程,这是因为状态方程实际上并不是我们直接通过门电路实现的,而是通过使用门电路实现激励方程来间接实现的。此外状态转化真值表本身也就表示了状态方程。而输出方程是比较简单的,直接通过卡诺图化简得到即可。因此这一节描述的重点是如何求激励方程。
求这激励方程有两种方法:
- 从状态方程中提取激励方程
在上面提到了,状态转换真值表本身就相当于是一个状态方程,因此这个方法就相当于直接从真值表中通过卡诺图得到状态方程,然后再得到激励方程
举一个例子(使用JK触发器):
从上面的状态转换真值表中可以得到卡诺图以及状态方程:
在本题中使用的是JK触发器,因此在圈卡诺圈的时候要有意识地朝着JK触发器特征方程去化简。如对Q2卡诺图,就需要按照Q2“0”和“1”的不同取值将卡诺图分开(在上面的例子中就是分成左边两列和右边两列),然后分别化简。
接下来就只需要对比这个状态方程和边沿JK的标准特征方程,即可得到激励方程了。
这个方法感觉比较熟练,尽量使用这个方法。
- 直接求激励方程
这个方法的思路就是,直接根据现态和次态的关系,以及触发器激励输入对状态的影响,直接得出各个触发器的激励输入。
从真值表中可以得到下图:
接下来就只需要对J2、K2、J1、K1分别使用卡诺图进行化简即可。
6.3.5 检查自启动
- 需要检查自启动的电路:存在无效状态(注意不是输出信号为d)的电路
- 如何检查是否能自启动:检查所有无效状态能否在有限个时钟脉冲作用下进入有效状态且输出正确
“输出正确”这一条件可以通过在使用卡诺图化简输出信号的时候不圈d来实现(不圈
d就相当于是给d赋值为0了)
而检查“是否能进入有效状态”这个条件时,同样在通过卡诺图化简激励方程的时候就已经给卡诺图中的d赋值了,因此实际上只需要在最终的状态转换真值表中将d替换为卡诺图中设定的值,然后再检查对应的状态图即可
- 如何修改不能自启动的电路:修改状态转换表或采取适当的解决措施。
这里说的修改状态转换表实际上就是直接去修改状态转换表中无效状态的次态,让他们的次态能够进入到有效循环中。
在后面会有需要检查自启动的题目。
至此就可以使用门电路和触发器绘制出电路图以实现特定的功能了。
6.4 典型同步时序电路及Verilog实现——有限状态机
6.4.1 米里状态机和摩尔状态机
这里主要是回忆一下米里和摩尔状态机的区别:
- 米里状态机:输出与输入和当前电路状态都有关
- 摩尔状态机:输出仅与当前电路的状态有关
有限状态机的Verilog描述步骤:
- 画出状态图
- 状态化简
- 状态编码
- 使用Verilog描述状态机
- 状态寄存器描述(定义现态与次态关系);
- 状态逻辑关系描述(描述状态图的变迁关系);
- 输出逻辑描述。
这里实际上就对应了代码中的三个always块。
按照时序逻辑电路设计的步骤,还需要绘制出状态转换真值表、得出激励方程和输出方程、检查自启动、绘制电路图。但是在有限状态机的Verilog描述中,后面这些步骤都是没有必要的,这是因为有限状态机的Verilog描述更偏向于算法层面(也就是行为级),但后面的步骤是更偏向于电路结构的(也就是数据流级)。后面的步骤中唯一需要注意的就是自启动。在有限状态机的Verilog描述中,自启动是交给状态转移always块中的default分支处理的。
6.4.2 摩尔状态机Verilog描述
这里给出一个例题:
这个应该是可重叠的序列检测器。
- 绘制摩尔状态机
在摩尔状态机中,会将输出放在状态内部,而输入信号仍然放在边上,这是因为摩尔状态机的输出仅仅由状态决定,因此就可以直接与状态绑定在一起了
- 状态编码
在状态编码之前不需要进行状态化简是因为能直接看出来这个摩尔状态机是最简的。
在前面有提到过,在序列检测器中,最简米里状态机拥有的状态数量恰好等于需要检测序列的长度;最简摩尔状态机拥有的状态数量为需要检测序列的长度加一。
- 编写Verilog代码
需要注意的是,这里第一个always块是有具体的敏感事件表的,但后面两个always块都是对所有事件敏感。
6.4.3 米里状态机Verilog描述
同样结合一个例题来看米里状态机:
同样为可重叠
- 绘制米里状态机
- 状态编码
- 编写Verilog代码
一般状态机Verilog实现会有下面这几种题型:
- 序列检测器:检测特定序列,需要注意序列是否可以重叠。
- 代码检测器:代码检测器检测的对象是依次输入的指定代码。检测时应按各代码的规定进行分组,组与组之间不能混淆。(也就是一定要输入一定的位数才能检测一次,并不是能随时返回初始状态的)
- 计数器:计数器(就是那种有权计数器)实际上可以使用更简单的Verilog代码(这种实现甚至不需要使用状态机)实现,如果题目中没有要求使用状态机的话就直接使用更简单的方式实现即可。
这里举一个例子吧(可逆计数器,简单的Verilog):
另外需要注意的是,在实现状态机之前也需要关注题目中要求使用什么触发器实现,这涉及到第一个always块中的敏感事件表。如果题目中没有指明使用哪种触发器,那么就自己说明一下要用什么触发器实现。
在做写状态机的Verilog代码的时候,需要考虑的有:
- 使用什么触发器实现?——涉及到敏感事件表中clk信号是上升沿还是下降沿
- 清零(置位)信号是同步还是异步?——涉及到敏感事件表中是否需要写clr(set)信号
- 清零(置位)信号是高电平有效还是低电平有效?——涉及到敏感事件表中clr(set)信号是上升沿触发还是下降沿触发。
- 输出信号是什么?——如果题目中没有要求输出什么的话,就自己描述一下,然后多输出一点信号。
6.4.4 上板实现状态机(实验相关)
顶层模块/电路原理图如下:
因此如果需要上板实现序列检测器的状态机的话,需要三个模块:
- 时钟降频模块
- 单脉冲发生器
- 序列检测器
6.4.4.1 时钟分频器
降频相当于是为了后面的防抖做铺垫。如果没有降频的话,可能按键抖动的前抖动就没办法消除了。所以在ppt上描述这个模块的功能为:怎么手动产生可捕捉的0、1。
时钟分频器Verilog代码(行为级)如下:
这里通过计数变量q的第17位对板载时钟进行降频
6.4.4.2 单脉冲发生器
单脉冲发生器的电路原理图为:
该电路通过各个触发器状态变化之间的时间差来实现单脉冲的输出:
单脉冲发生器的Verilog代码(行为级)如下:
因为这里涉及到边沿触发,但是数据流级没办法直接描述边沿触发,因此这里只能使用行为级描述。
6.4.4.3 顶层模块实现
Verilog代码为:
错题
这个是因为比较难观察出来电路的功能
这里需要注意的是题目中的一个词:串行,也就是一位一位输入。如果一下输入四位数据的话,就可以直接使用组合逻辑电路实现了。
约束条件要在状态表中体现出来,无论是无效状态,还是无效输入(比如这里的11)
这里涉及到不能自启动的问题。从这里看应该是设计自启动的时候,需要按照题目情况(或者说要看有效循环的特征)来修改真值表比如这里的环形计数器,在有效循环中只有一个1,所以当1多了就需要一直移位添0直到只有一个1;1少了就需要移位添1,这样就可以进入到有效循环了。
这里是说切断Q4到D1的连接线,实际上应该直接保持现态不变,修改Qn+1即可。
当然如果找不到有效循环的特征的话,直接强行修改次态应该也是可以的(当然修改的位数越少越好,修改的次态越少越好。如果修改的次态比较多的话,最好修改同一位)
问题
在隐含表中如何找出来次态交错导致的等效以及自环(也就是保持原状态不变)导致的等效?
- 作者:Noah
- 链接:https://imnoah.top/article/DigLogic/Chapter6
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。