讲到这篇时,组合逻辑就告一段落了,下面是一些总结:

  1. 描述组合逻辑时,always 语句中的敏感信号列表中需要列出全部的可能影响输出的变量
  2. 描述组合逻辑时,always 语句中的赋值总是使用阻塞赋值符号 =
  3. 组合逻辑是描述输入和输出关系的功能块,由于延时的原因,输出可能会有毛刺,为避免避免毛刺需要引入冗余逻辑。
  4. if..else case 语句只能用在 always 语句中,而且分支条件必须健全,否则会引入不必要的锁存器。

新的 SystemVerilog 语言中强化了 always 的功能;SystemVerilog 使用 always_ff 表示时序逻辑,用 always_comb 表示组合逻辑,而 always_latch 用来表示锁存逻辑,此外敏感信号列表还可以让综合器来自动推导,所以学好 verilog 是学习 systemverilog 语言的重要基础。

时序逻辑:

组合逻辑和时序逻辑的重要区别就在于组合逻辑中不存在任何的储存电路,而时序逻辑中含有储存电路,既然含有储存电路,输出的结果就必然和现在的输入以及储存电路中的值有关,然而储存电路中的值来自过去的输入电路,所以时序逻辑是既与现态也与次态有关。学过数电的人都知道,最简单的储存器是双稳态电路,其原理在于两个交叉耦合的反相器,目前实用的储存电路有 SR 锁存器、时钟触发的 SR 锁存器、D 锁存器、边沿触发的 D 触发器、带有同步置位和异步复位的 D 触发器和寄存器等等。

—— 内容摘自《FPGA 数字逻辑设计教程 —— Verilog》

SR锁存器:

SR 锁存器电路还存在多个状态:

  1. 当 ~S = 1,~R = 1 时 如果 q 为 1,~q 就为 0 否则 q 为 0,~p 就为 1,这种状态就是我们期望的 储存态
  2. 当 ~S = 0,~R = 0 时 ~q 和 q 的输出都会为 1,这显然破坏了我们的期望,所以这时一种不允许的状态
  3. 当 ~S = 0,~R = 1 时 q 强制为 1,~q 强制为 0,这种状态称为置位
  4. 当 ~S = 1,~R = 0 时 q 强制为 0,~q 强制为 1,这种状态称为复位

可以看到,SR 锁存器显然还有些不足之处,更为重要的问题在与读写的定义模糊,为了解决这一问题,时序逻辑中提供了一个叫做 时钟 的概念来作为控制所需的节拍器,下面是一个比上一个更为实用的电路,时钟触发的 SR 锁存器:

这个器件的功能如下:

  1. 当 clk = 0,无论 S、R 的值如何          ~S = 1、~R = 1,电路进入储存态
  2. 当 clk = 1,如果 S = 0、R = 0,那么 ~S = 1、~R = 1,电路还是储存态
  3. 当 clk = 1,如果 S = 0、R = 1,那么 ~S = 1、~R = 0,q = 0、~q = 1,电路进入复位状态
  4. 当 clk = 1,如果 S = 1、R = 0,那么 ~S = 0、~R = 1,q = 1、~q = 0,电路进入置为状态
  5. 当 clk = 1,如果 S = 1、R = 1,那么 ~S = 0、~R = 0,q = 1、~q = 1,这同样是不允许的。

为了消除上面电路里不允许的状态,可以添加一个反向器使得 S 和 R 的值总是不同的,下面的这个电路称作 D 锁存器:

由于 S R 总是取相反的值,D 锁存器的原理如下:

  1. 当 clk = 0,无论 S、R 的值如何          ~S = 1、~R = 1,电路进入储存态
  2. 当 clk = 1,如果 S = 0、R = 1,那么 ~S = 1、~R = 0,q = 0、~q = 1,电路进入复位状态
  3. 当 clk = 1,如果 S = 1、R = 0,那么 ~S = 0、~R = 1,q = 1、~q = 0,电路进入置为状态

D 锁存器既可以用于储存信号又可以对其进行相应的控制,但问题在于:当时钟为 0 变到 1 的半个时钟周期内,输出总是随输入变化,其最终的结果导致在一个时钟周期内输出值发生多次变化。在数字逻辑设计中,我们希望作为节拍器的 时钟总是作为一个设计中频率最高的信号,其他任何的信号所维持的时间必须是时钟周期的整数倍。解决这个问题的一个可行的方法是设计一个在 只时钟上升沿(从 0 变为 1)将输入锁存,时钟稳定为 1 后保持整个周期输出不变 的一个器件来代替 D 锁存器。

下图展示的电路为 FPGA 设计里被大量使用的 D 触发器:

想要分析这个电路是有些难度而且会花费一些时间,我曾经为了图简便,用 Modelsim 仿真过这个器件,但 Modelsim 总是罢工,为此小弟一直不解,哪位大神看到了请不吝赐教,这里记住 D 触发器的功能是在时钟的上升沿(0 变到 1),把 D 的值锁存并维持一个时钟周期。

上面的电路似乎已经可用了,但还是有一个问题:当系统刚上电的时候,q 的输出是未知的。为此这个电路还需要修改,我们还需要添加复位功能。下图使用了 verilog 来语言描述的一个带有异步复位的 D 触发器,在他人所写的代码中我们经常看到类似这样的描述。

下面的代码是一个八分频电路:

仿真结果:

仿真的结果大致是对的,但 clk_div 的第一个周期却不太正常,把 q 加入输出后进行仿真后得到如下的结果:

很容易的看出 q[0] 维持的时间比正常的短,综合上面的知识,你能给出一个解释吗?

最后,根据上面的代码,读者可以试着修改它来实现一个闪烁灯,假设你板子的晶振和我的一样是 50M,闪烁频率为 1Hz,那么作为计数器的 q 至少需要 26 位。

50M = 50_000_000 < 64*1000*1000 = 2^6*2^10*2^10 =2^26  --->   reg [25:0] q

本章节中简单的时序逻辑就介绍到这里为止了,下一章节介绍数码管的动态显示。

我的 FPGA 学习历程(09)—— 时序逻辑入门的更多相关文章

  1. 我的 FPGA 学习历程(02)—— 实验:点亮 LED 灯

    关于 Quartus 的操作可以使用 Quartus 自带的帮助,帮助中带有全套的操作教程. 中文网络教程链接(链接至 altera中文官网,点击观看) Quartus II 软件设计系列:基础 Qu ...

  2. 我的 FPGA 学习历程(08)—— 实验:点亮单个数码管

    数码管是一种常见的用于显示的电子器件,根据数码管大致可以分为共阴极和共阳极两种,下图所示的是一个共阳极的数码管的电路图(摘自金沙滩工作室的 51 开发板电路图),我的 AX301 开发板与这张图的情况 ...

  3. 我的 FPGA 学习历程(15)—— Verilog 的 always 语句综合

    在本篇里,我们讨论 Verilog 语言的综合问题,Verilog HDL (Hardware Description Language) 中文名为硬件描述语言,而不是硬件设计语言.这个名称提醒我们是 ...

  4. 我的 FPGA 学习历程(01)—— FPGA 基础知识和 Quartus 的安装

    高级的嵌入式市场主要分为以下三类:ARM.DSP 和 FPGA. 其中 ARM 是行业内的佼佼者,目前几乎所有的安卓智能手机都使用 ARM 授权的 CPU架构:而 DSP(数字信号处理器) 早年就被大 ...

  5. 我的 FPGA 学习历程(05)—— 使用 Modelsim 仿真工具

    在第 3 篇中讲到了如何使用图形进行仿真激励输入,图形输入法尽管简单易学,但如若要求复杂的仿真输入激励.较长的仿真时间或是要求打印输出信息乃至输出文件日志则显得不够用了. 本篇以上一篇的 3-8 译码 ...

  6. 我的 FPGA 学习历程(03)—— 使用 Quaruts 自带仿真工具

    在上一篇中详细的介绍了怎样创建原理图工程,这篇同样使用原理图工程新建一个多路选择器,目的是学习使用图形输入的仿真工具输入仿真激励. 新建工程,并绘制以下的原理图. 编译项目,会多出一个警告: Crit ...

  7. 我的 FPGA 学习历程(14)—— PWM 脉冲宽度调制

    PWM 是一种调节输出功率的技术(俗称调压),其原理在于改变输出方波的占空比,具体输出见下图: 输出信号为电压值,当负载为恒阻时,上图中的输出功率分别为 25%.50%.75%. 实现方法如下: 设置 ...

  8. 我的 FPGA 学习历程(12)—— 电子钟项目准备

    初学 FPGA 的时候,我们总是存在很多疑问,比如:xilinx 和 altera 的 FPGA 那种比较好.verilog 语言被如何综合成具体硬件电路.RTL 级电路是什么意思等等.现在我们就不会 ...

  9. 我的 FPGA 学习历程(11)—— 实验:按键消抖

    按键是一个输入设备,在理论上可以归为开关一类,理想的按键波形如下: 然而由于按键的机械特性,断开和闭合动作是不可能在一瞬间完成的,实际的波形如下: 抖动期间电平处于临界值,由于晶振的频率相当的高,数字 ...

随机推荐

  1. Android相关面试题---面试官常问问题

    版权声明:本文为寻梦-finddreams原创文章,请关注: http://blog.csdn.net/finddreams/article/details/44513579 一般的面试流程是笔试完就 ...

  2. SpringMVC-简单总结

    要学习一项技术,首先要知道, 它是什么, 为什么要用它 , 它由哪些东西组成, 每个东西是干什么的, 它们怎么综合在一起的 参考博客: 平凡希: https://www.cnblogs.com/xia ...

  3. 盒子取球C语言 蓝桥杯

    盒子取球方法二今盒子里有 n 个小球,A.B 两人轮流从盒中取球,每个人都可以看到另一个人取了多少个, 也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定:每个人从盒子中取出 ...

  4. windows下Qt5.1 for android开发环境配置

    1.下载安装Qt 5.1.0 for Android (Windows 32-bit, 716 MB)   http://qt-project.org/downloads 2.打开Qt Creator ...

  5. request模块

    一 介绍 二 基于GET请求 三 基于POST请求 四 响应Response 五 高级用法 一 介绍 # 介绍:使用requests可以模拟浏览器的请求,比起之前用到的urllib,requests模 ...

  6. Linux 技巧:让进程在后台可靠运行的几种方法【转】

    我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败.如何让命令提交后不受本地关闭终端窗口/网络断开 ...

  7. 《ASCE1885的信息安全》のCryptoAPI---密钥的产生和交换函数

    在公开密码算法的前提下,数据的安全取决于密钥.因此,密钥的产生.销毁.交换(分发)是数据保密工作中的重要部分. CryptoAPI密钥产生和交换函数主要有生成密钥函数CryptGenKey.派生密钥函 ...

  8. ubuntu常用命令备忘

    1.把一个目录的文件拷贝另一个文件夹 sudo cp -p /home/likewei/lib/needlib/* /home/likewei/lib/11

  9. Codeforces Round #550 (Div. 3) F. Graph Without Long Directed Paths

            F. Graph Without Long Directed Paths time limit per test 2 seconds memory limit per test 256 ...

  10. verilog function功能函数写法

    :] sm2tc; :] din; :] dp; :] dn; :] dout; begin dp = {'b0, din[14:0]}; dn = ~dp + 'b1; dout = (din[] ...