当前课程知识点:IC设计与方法 > 3、Verilog语法 > i)时序电路的设计 > Video
下面我们再来看一下非阻塞赋值语句
实现时序逻辑电路的时候的一些特点
这些幻灯片
我们前面已经看到过了
那这再强调一次
在非阻塞赋值语句实现时序逻辑电路的时候
在这里面
我们用的是时钟有效沿
所谓这是时序逻辑电路
我们要求用非阻塞赋值语句
对应实现是每一条语句对应了一个D触发器
每一条语句对应了一个D触发器
或者说每一个对不同信号赋值的语句
对应了一个D触发器
所以上面这段代码产生了3个级联的D触发器
这是正确的
如果再时序逻辑电路设计
因为这条语句决定了
我们设计的是一个时序逻辑电路
如果用到了阻塞赋值语句的话
得到的结果可能并不是你所预期的一个结果
我们说刚才这些幻灯片
产生的是一个移位寄存器
或者说若干个D触发器级联在一起
就在实际工程电路里面
是有具体的用处的
我们通常把这种形式的电路
称之为叫移位寄存器
移位寄存器的写法
我们可以看一下下面这段代码
用一个always块
对若干个信号Q信号去进行赋值
这是一种常见的写法
把输入的信号给D0
把输入的信号给Q0
Q0再给Q1 Q1给Q2 Q2给Q3
所以这四句话的话呢
分别产生4个不同的D触发器
它们之间的关系是级联的
会把输入的信号经过4排以后
从Q0一直移到Q3
我们称之为叫移位寄存器
这种方式对应的
通常用在什么串并转化电路
或者是并串转换电路
这些电路里边
根据非阻塞赋值语句定义
我们可以想象
这四条语句相当于是在同时执行
我们放在一个always块里面
同样
我们说每一个always块
相当于是一个独立的小电路 对吧
所以对于移位寄存器的话
我们还有另一种写法
就是把这4个电路再分开
我们可以把它分解成4个always块
每一个always块里边只写其中的一句话
这也都是完全等效的
只是两种不同的代码书写风格
移位寄存器的话
还有另一种写法
通常移位寄存器
是对有一定位宽的信号去进行移位的
比如说我们输入的这个信号
要变成一个8位的信号
把输入的一个串行的一个信号
串行输入信号并行着变成8位输出
我们可以用这么一个方式来看
前面是信号的整个电路模块的D1
我们有输入的1bit的数据信号
时钟信号和复位信号
然后并行转换成8位数据进行输出
怎么做呢
我们在复位信号有效的时候
就是在时钟上升沿
如果复位信号有效的时候
把数据先清零
我们用的是
因为复位信号clr信号
没有放到敏感表里面去
所以我们知道这用的是同步清零的方式
并且用的是信号的高电频
然后当清零信号无效的时候
这时候我们要做移位操作
我们把dout
我们定义的是一个8位的dout
每次让它左移一位
用这种方式左移一位
表示把dout的0位给1
dout1给第dout2
一直到dout6给dout7 对吧
这样的一个移位操作送给dout
移位完了以后的话
最后一句话我们是把下一句话
我们是把din信号送到dout零端
也就是送到dout的最低端
用这种方式完成了一个数据从低位进入
从低位进入高位移出的过程
在这里面
其实我们可以看到有一个小问题
对dout0
我们在上面这句话
这句话里面dout是一个矢量 是吧
所以实际上是对8位
dout的8位同时进行操作
所以在上面这句话
对第dout0其实也赋了一个值
在下面这句话又得dout0进行赋值
在Verilog里面规定
如果有连续多条语句
对一个信号进行赋值的话
最后一条语句是有效的
对一个变量连续赋值多次
只有最后一次值有效
结合前面几个例子
不管是组合逻辑电路也好
还是时序逻辑电路也好
我们下面来仔细的分析一下
Verilog代码里面的每一句话
跟电路之间的一个映射关系
我会不断的去强调这个概念
因为我们讲过
在电路设计过程中
我们虽然写的是代码
实际上涉及的是上面这样的电路图
我们脑子里要有
在写代码的时候
就要想着我这个代码最终出来的电路
是一个什么样子
在时序逻辑电路设计的时候
我们所有电路设计的模型
都是一个基于D触发器设计的电路
所以我们写完代码
最终分析出来的话
也都是一个D触发器类型的电路
以这个例子为例
以这段标准的代码为例
我们来看具体是一个什么样的分析过程
我们首先从第一句话来看
碰到一个always块
always at clock有效沿的块
我们就知道
这段代码描述的是一个带有D触发器的进程
对应的也就是说
这段电路的最右端是一个D触发器
D触发器的时钟信号叫clock
D触发器的时钟信号
是一个上升沿的一个什么信号
这是描述这个D触发器的这部分时钟部分
然后再看代码内部
赋值语句左边的信号叫Q
也就是说
这个电路的输出信号叫Q
也就是说D触发器的输出信号叫Q
我们就画完了这一部分
D触发器的时钟信号和输出信号
D触发器的输入信号是什么呢
要看电路的内部的语句了
条件判断语句
从进程分析的时候
从代码分析的时候
从代码的条件判断的
最外层往里面一层层分析进去
我们电路的话
就顺着D触发器
然后从右往左画
碰到一个条件判断语句
我们就知道
这是一个2选1的多路选择器
判断条件是漏的
多路选择器的选择信号是漏的
条件满足的时候
Q被清零
也就是说条件满足 这可以写个1
条件满足的时候 Q被清零
条件不满足的时候
Q是零的时候
要做什么事呢
Q加1赋给Q
也就是说有一个加法器
加法器的一端是1
加法器另一端是Q 是吧
那Q的话呢
就是指的D触发器输出会反馈过来
作为输入端的Q
所以这样的话
我们就能够根据代码
一步一步的把所对应的电路给它画出来了
我们总结一下
刚才的分析过程
我们碰到的赋值语句
碰到的赋值语句
对应的就是逻辑函数 对吧
对应的就是一小块一小块的子电路
对应的就是一小块小块子电路
比如说加法器
比如说一个值
或者说一些逻辑函数
或者一些简单的门
碰到边沿性的条件分支
边沿性的条件分支
就是类似这样
我这写的变异性条件分支
是针对这个VHDL而言
在Verilog里面就是说碰到这种沿的判断
那就表示我们电路一定是有D触发器
碰到这种条件分支 if-else条件分支
或者是case语句这样的语句话
我们就知道出来的就是2选1的多数选择器
或者是更多的四选一 八选一
或者十六选一的多路选择器
这就是我们对于代码
和具体电路之间的一个对应关系
或者说进程语句的物理含义
刚才我们讲完了
时序逻辑电路设计的一些Verilog的要素
下面我们来看一个比较小的实际的例子
我们来看一个8位计数器的设计例子
在具体做这个例子之前的话
我们先简单的回顾一下
这个时序逻辑电路设计的一个过程
第一步 我们是分析需求
第二步的话
其实是画出电路的一个大致的一个结构图
结构图应该都映射在每个人的脑子里边了
是吧
也就是说
我们用硬件描述语言来设计电路的时候
它的固有的电路模型
或者电路结构应该是什么样子
第三步
根据这样的一个结构写出电路代码
然后第四步
再检查一下代码有没有错误
然后再根据代码反过来
再把电路结构在回画一遍
确定有没有错误
最后是软件仿真及真正的电路实现
大致是这么一个过程
不管多小的电路
其实我们都是这么一个过程
在这里面
怎么画这个电路图
我们就跳过去了
待会会有单独的章节来讲这份工作
首先
我们举个例子
是一个8位的计数器
这个计数器我想在很多本科的课程里边
或者大家做的习题里面都做过
通常计数器的话
我们称之为叫有多功能的
包括它可以清零
它可以这个装载数据
清零或是装在一个计数数值
从某个计数值开始
可以加计数
可以减计数等等等等这样的功能
我们来看一下
我们做这个计数器
它有8位的这个数据
可以装载一个8位数据
我们计数的过程中的话
计数值也是一个8位的
可以清零
然后可以加计数 可以减计数
有相应的信号来支持族不同的工作
这么一个计数器做完以后的代码
或者设计完了电路是一个什么样子
这种代码的写法其实
并没有完全按照我们刚才说的过程来写
因为计数器是一个比较特殊的一个电路
所以的话可以用这样一种方式做的话更简单
实际上标准的计数器的话
如果是按照标准流程设计出来的计数器
长的是另外一个样子
代码看起来是跟这个有点不一样的
在每个时钟沿
我们判断那些输入信号
如果是有清零信号的话
如果是由低电频的清零信号的话
计数器的值要清零
没有清零信号的话
我们判断一下
如果有装载信号的话
直接把输入的数据D装载到这个计数器里面来
然后如果有这个加信号
如果是这个加信号
加减计数信号是1的话
计数器是加1
如果是加减信号是零的话
那计数器的值被减1
就是说这个信号是高电频的话
就加计数
是低电频的话就是减计数
这样一段代码就描述了一个刚才我们所说的
具有多个功能的这样一个8位计数器
大家看一下这段代码
看起来是不是非常的直观
有没有什么问题
仔细看一下
在这里面我们要设计的是一个持续逻辑电路
赋值语句应该用什么
应该用这个非阻塞赋值语句
对吧
那实际上的话
这里面我们用的是阻塞赋值语句
是不符合代码设计规范的要求
当然没有语法错误
实际上的话在这样一个情况
用阻塞赋值语句也没有什么错误
电路功能也是正确的
也是正确的
这只是一个特例
为什么说是一个特例呢
正好是我们所有的条件分支全部是分散的
全部是并排的并列的
应该说所有条件都是并列的
然后每个分支里面
又只对一个信号进行了赋值
所以的话
用哪种赋值语句没有什么本质差异
但是从工程的角度来说
一般来说我们要养成一个习惯
只要是碰到这样的情况
我们这都是应该是小于等于直接来用
我们再来回顾一下时序逻辑电路的设计方法
第一步确定电路的外特性
它的输入和输出都是什么东西
第二步
确定电路的内部的状态的个数转移的条件
画出电路的状态转移图
电路的状态转移表等等等等
从某个角度来说
到第二步做完
我们的设计人员的设计工作已经完成了
或者说一个项目组的
项目经理的事情已经做完了
下面是下面的这个工作人员
具体的工程师开始干下面的活了
按照传统设计方法
下面就是简化状态图
然后这个指定触发器类型
然后进行状态化简等等等等这些工作
剩下琐碎的工作
现在都可以由计算机来帮助完成
用EDA软件来帮助完成
所以作为设计人员
我们现在要做的事情是什么
画出电路的结构图
这个结构图其实就是说
我们的电路的模型是一个什么形
所有电路的结构图都是一样的
如果说你已经非常熟练的话
第三步就已经跳过去了
我们可以直接进入到第四步
写出电路的对应的代码
然后由EDA软件把最终的电路图产生出来
用软件去仿真代码的功能是不是正确
基于这样的一个设计方法的设计模型
就是这么一个模型
我们的电路核心是一个D触发器 是吧
这个模型在我们第一讲里面讲过了
核心是一个D触发器
然后有两块组合逻辑电路
一块是状态计算逻辑
用来计算根据当前的状态
根据电路的当前状态计算电路的下一个状态
next-stage是什么
然后另外一块是电路的输出逻辑
输出逻辑也是一块组合逻辑电路
它根据电路的当前状态
以及输入的信号来判断电路的输出是什么
如果是摩尔状态机虚线就不存在 对吧
只是根据电路的当前状态判断出
当前状态的输出
如果是Mily状态机
那这根虚线就存在了
在每一个当前状态下
电路的输出还会跟输入有一定的关系
这就是我们的电路的模型
所以我们的VHDL代码也是参考这个模型来设计
在这个模型里边
有几部分赋值语句
一个是D触发器
D触发器是一个时序逻辑电路 对吧
如果让大家
我们前面已经举了好多
关于D触发器的process怎么写
D触发器的这个always块怎么写
在这个always块的话里边
我们是把next-state相当于D触发器D端的型号
赋给current-state
写法的话时序逻辑电路
所以是next-state是个小于等于
赋给current-state
对于组合逻辑电路1和组合逻辑电路2而言
它们是组合逻辑电路
所以在这两个电路里边
我们是应该用作阻塞赋值语句去完成
这两块电路的设计
当然当你对代码描写熟练以后
可以把组合逻辑电路1
跟组合逻辑电路2合并在一起
合并在一起以后表示
从意义上来说
从对照这张图的意义上来说
表示在时钟的有效沿到来的时候
有效沿的时候
是把这个组合逻辑计算的结果
直接送到current-state 对吧
所以从某个角度说
next-state的这个信号都可以不用写了
对应的话在这个always块里边
这个always时序逻辑电路里边写的话
只要写成是关于in和cs
关于输入信号和CS计算的结果
直接复制给CS
我们在这条语句里边
这个cs表示的是当前的状态
其实表示这个状态 赋给CS
为什么又赋给cs
在这边的这个赋值号左边的cs呢
已经是电路的下一个状态了
这也就是说赋值号的这的CS
表示是current-state
在这儿的这个CS
表示的是next-state
在使用上升沿之后
这个操作完成
刚才讲的是比较简单的
时序逻辑电路的设计方法
如果时序逻辑电路更复杂
我们是一个什么模型
从物理上来说
持续逻辑电路
在实现的时候
实现完了以后都是一堆寄存器
一堆D触发器
加上一堆组合逻辑电路 对吧
如果我们把这些D触发器
它可能是一堆D触发器
我们把它展开以后变成一个一个D触发器
两个D触发器之间是夹杂了一些组合逻辑电路
电路的行为的话
或者电路功能的话
我们可以看成是从一个D触发器的输出
经过一堆组合逻辑的传递计算以后
传递到另一个D触发器的输入
从英语上来说
就是register
或者叫寄存器传输级 是吧
寄存器传输级
顾名思义就是这么过来的
对应这样的一个电路模型
我们用Verilog语言描述的时候
这个代码是一个什么样子
就always块的条件
如果有reset时候赋一个值
reset条件不存在的时候
是有一大堆语句
语句可能只有一句话
可能有1000句话描述的
是两个D触发器之间的组合逻辑电路
有时候这个东西我们也把它称之为叫做云图
对于复杂的时序逻辑电路
我们就不能只用一个简单的有限状态机来表示了
复杂的时序逻辑电路通常除了有状态转移部分
另外还要完成更复杂的计算操作
不仅仅是指输出一两个控制信号
所以的话
我们通常要用右边这样一个幻灯片
右边这样Data Path部分
它完成电路的动作
比如说要计算数据
这个数据的话
可能要受到有限状态机的控制
决定有限状态机产生一个控制信号
控制Data Path在每一个节拍完成不同的操作
Data Path又把当前的操作结果
反馈给有限状态机
让它决定下面到底应该相应的去对动作
或者计算做什么样的调整
这样的话
我们电路就分成这么两部分
对于这样一个模型里边有限状态机
还是用我们传统的有限状态机的设计方法
来进行设计
Data Path的话是独立的分离出来的电路
我们作为设计人员的话
通常是先设计Data Path
先确定我们这个电路计算的时候
都有哪些计算部件
比如说加法器 减法器 乘法器等等
然后确定它们的数据是怎么传递的
以及这些计算部件都需要哪些控制信号
然后用一个有限状态机来协调
或者说控制这个Data Path
来完成预定的这个目标
我们下面举一个简单的例子
一个非常简单的例子
在这个例子里面
其实
Data Path部分可以省略掉了
只用简单的有限状态机就可以做
假设我们的电路要循环的输出1935
1935这四个数
循环输出
根据这个电路的需求
我们可以确定
或者我们可以看出来电路每四拍循环一遍
每四拍循环一遍 对吧
所以大致可以觉得
这个电路可以用一个
具有4个状态的状态机来实现
在每一个状态输出一个值
分别输出1935
按照传统的设计方法
或者说按照现在我们所要求的设计方法
我们首先应该把这个状态机给它画出来
画出状态转移图
画出电路的模型
然后去写代码
在这我们就先把它省略掉了
我们看一下一个初学者经常会写出来的代码
长的是什么样子的
前面的头我们就去掉了
这里面我们定义了一个state信号
因为是一个四状态的状态机
所谓state信号是一个两位的
下面用一个always过程描述电路的特性
首先用的是时钟的上升沿
如果有清零信号的话
状态机被复位 清到零状态
然后case语句表示在当前状态是0的时候
下一个状态是1
因为状态机的转移是无条件的转移
对吧
所以就从0转到1 从1转到2 从2转到3
3转到0
然后当前状态是零的时候
Q输出1
其它状态依次输出1935
就是这么一个简单的电路
能够完成我们所需要的这个功能
大家看一下这个代码有没有什么问题
先仔细检查
好ok 是时序逻辑电路
然后case语句都写全了
状态之间的转换好像也都什么没有
都没有什么问题
但实际上这段代码是有问题的
为什么呢
我们说有限状态机
有限状态机在这个always块里边
应该只描述状态机部分
回顾一下我们的图
工作的电路图
回顾一下我们电路图
我们应该是有几个进程去描述电路
一个是状态计算的always块
表述D触发器阵列部分
然后另外有一个输出电路组合逻辑电路
状态计算的组合逻辑电路
以及状态转移的D触发器
对吧
应该有三块电路
对应的话可能会存在三个always块
当然
你简写完了以后可能是两个块
但是简写到一个块的可能性非常小
所以的话
问题就出在这个地方
对于Q的输出
我们不应该把它放到状态转移电路
状态计算的这个always块里边
而应该用一个单独的always去描述
这部分电路应该是一个组合逻辑电路输出
如果按照这种写法
电路里边就会多出一个关于Q的D触发器
或者计算器
导致电路的性质又发生了变化
针对刚才这样的一个电路
我们来结合电路的模型
这是我们的电路结构图来看
代码应该怎么写
我们标准的有限状态机
或者说标准的时序逻辑电路
我们在实现的时候
它的电路模型是这么一个模型 对吧
分为D触发器部分
计算逻辑部分
状态计算逻辑部分以及输出逻辑部分
我们在写的话
正常情况下应该有三段代码
第一段代码是状态计算逻辑
根据它是一个组合逻辑电路
注意它是一个组合逻辑电路
所以它case的是current-state
根据的是当前的状态
我们没有外部的输入的信号
所以它只是根据当前信号
当前状态来判断
如果当前状态是0 0的话
然后下一个状态是0 1
0 1转1 0
1 0转1 1
1 1转0 0 对吧
是这么一个情况
如果我们电路里边还要去对复位信号
进行判断的话
我们要把复位信号加进来
这个电路 这个代码有个小瑕疵
第二个进程描述的D触发器
在时钟的上升沿把next-state
送给current-state
所以的话
我们大概的意思就是
在时钟的上升沿描述的是一个时序逻辑电路
把next-state送给current-state
如果有复位信号的话 把它清零
复位信号的判断可以放在这
也可以放到上面都可以
这两种方式都可以的
第三个逻辑是组合逻辑电路
输出逻辑电路
这是一个输出逻辑电路
它也是组合逻辑电路
所以的话
是按照组合逻辑电路的方法来进行设计
如果是当前状态的话
如果是它的输入信号是当前状态
根据当前状态判断输出的都是什么值
这地方还是刚才所说的小瑕疵
clr信号应该放到敏感表里面去
这样的话
是用3个process
或者说3个always块
来分别表示这三段电路
这是一个标准的书写方法
当然
在工程里边还有各种组合的方式
我们可以把这两个always块
合并成一个always块
描述一个相对复杂的组合逻辑电路
也可以把这两个合在一起
因为它们俩性质都是组合逻辑电路
我们可以把它们合在一起
单独留出D触发器
这也是一种方法
实际上一共有3种代码的书写方式
刚才所直接给出了代码
不是这3种方式之一
就是错误的
最后我们来总结一下
在电路实现的时候的各种方法
我们前面已经理论上
已经把电路实现的用always块的方式
怎么实现电路
以及用连续赋值语句的方式怎么实现电路
最后的话
还有一个元件例化的方式还没有讲
我们在后面会结合实际的例子来讲
怎么用元件例化去实现小电路
我们可以看在一个module里面
我们举一个例子
在一个module里边
可能会存在若干个assign语句
会存在若干个always块
会存在若干个元件例化语句
当然这些元件例化与always块
和assign语句的次序完全可以打乱
可以把这个always块写到前面去
可以把assign句写到后边来
这个元件例化语句也可以写到中间去
它们之间是完全并行的
因为每一个块每一个assign语句
每一个always块
或者每一个元件例化语句对应的
都是一个电路模块
它们之间完全是并行的
然后这些信号的名字表述了
这些块之间的一些块之间的这个链接关系
这就是我们的代码跟电路之间的一个对应关系
大家脑子里一定要有这么一个直观的印象
或者说脑子里看的是这段代码
但是想的是我们电路是一个什么样子
它们之间连接是一个什么样子
-软件下载说明
-a) 集成电路的应用及市场
-a) 集成电路的应用及市场--作业
-b)集成电路的制造过程
-b)集成电路的制造过程--作业
-c)从CPU的发展看IC的进展
-c)从CPU的发展看IC的进展--作业
-d)从行业的发展看IC的进展
--Video
-d)从行业的发展看IC的进展--作业
-e)从ISSCC看IC的发展方向
--讲课视频
-e)从ISSCC看IC的发展方向--作业
-a)数字系统的实现方法 (ASSP/FPGA/ASIC的对比)
--讲课视频
-a)数字系统的实现方法 (ASSP/FPGA/ASIC的对比)
-b)组合逻辑电路
--Video
-2、数字集成电路设计方法--b)组合逻辑电路
-c)时序逻辑电路(1)
-d)时序逻辑电路(2)
-2、数字集成电路设计方法--d)时序逻辑电路(2)
-a)Verilog的历史和学习要点
--讲课视频
-b)端口、信号及数据类型
--讲课视频
-b)端口、信号及数据类型--作业
-c)逻辑电平及数据操作
--讲课视频
-3、Verilog语法--c)逻辑电平及数据操作
-d)Assign 语句
-e)Assign 举例
-f)Always
-f)Always--作业
-g)阻塞与非阻塞赋值
--Video
-3、Verilog语法--g)阻塞与非阻塞赋值
-h)D触发器的描述
--Video
-i)时序电路的设计
--Video
-i)时序电路的设计--作业
-j) 面向测试的Verilog语法(1)
-k) 面向测试的Verilog语法(2)
-k) 面向测试的Verilog语法(2)--作业
-a)电路设计实例1
--Video
-b)电路设计实例2
--讲课视频
-b)电路设计实例2--作业
-c)电路设计实例3
--讲课视频
-Modelsim仿真
-a)综合及相关基本概念
--Video
-a)综合及相关基本概念--作业
-b)综合及优化
--Video
-c)门级仿真
--门级仿真
-d)Quartus综合及分析(1)
--讲课视频
-e)Quartus综合及分析(2)
--讲课视频
-e)Quartus综合及分析(2)--作业
-f)Quartus综合及分析(3)
--Video
-g)Quartus综合及分析(4)
--Video
-g)Quartus综合及分析(4)--作业