今天给大侠带来 FPGA Xilinx Zynq 系列 第二部分 Part B ,第二部分是关于使用 zynq 进行 Xilinx SoC开发的相关方面问题的深度解析, 包括嵌入式系统设计的概念、IP 块的创建与集成,以及软硬件协同设计。其中还有一个特殊的“亮点”章节,专注于正在增长中的用于IP快速开发的HLS的重要领域。
今天带来第十九篇,Zynq SoC & 硬件设计 之 嵌入式系统和 FPGA,本篇内容目录简介如下:
9. 嵌入式系统和 FPGA
9.1 什么是嵌入式系统?
9.1.1 应用
9.1.2 一般嵌入式系统架构
9.2 处理器
9.2.1 协处理器
9.2.2 处理器 cache
9.2.3 执行周期
9.2.4 中断
本系列分享来源于《The Zynq Book》,Louise H. Crockett, Ross A. Elliot,Martin A. Enderwitz, Robert W. Stewart. L. H. Crockett, R. A. Elliot, M. A. Enderwitz and R. W. Stewart, The Zynq Book: Embedded Processing with the ARM Cortex-A9 on the Xilinx Zynq-7000 All Programmable SoC, First Edition, Strathclyde Academic Media, 2016。
嵌入式系统和 FPGA
在描述很多不同的应用的时候都会广泛使用 “ 嵌入式系统 ” 这个术语。现在也出现了大量的嵌入式系统平台,从小的单片机和 DSP,到大的 FPGA 和 GPP 的平台都有,要准确定义嵌入式系统由什么组成已经变得越来越有挑战了。本章的目的是介绍嵌入式系统的概念,并给出一些例子来说明嵌入式系统会被 部署在怎样的实际应用中。然后我们就集中关注使用在 FPGA 上搭建的嵌入式系统,并探索一般性的嵌入式系统。这个架构的每个部件会从处理器开始详细讨论,还会从高层概要讨论某些基础的操作,比如中断和执行周期。另外也会涉及到一些基础的总线操作和特性,比如总线属性、存储器传输和带宽等。
9.1 什么是嵌入式系统?
嵌入式系统是一种专门的计算系统,优化以执行单一或非常少的特定功能。嵌入式系统形成了更大的设备的组成部分,作用是在那些机器中控制特定的功能。嵌入式系统的预先设定的功能性和 GPP 正好相反,就是个人计算机 (PC)那种系统,那种系统中,单个处理器会从事很多非常不同的工作。
GPP不是设计来做任何特定的任务的。比如桌面计算机可以用来做大量的任务, 包括文档的创建和编辑、家庭娱乐系统、图像和视频编辑系统或互联网终端。嵌入式系统是指定应用的,因此能精密优化来得到所做应用所需的特性。那些特性可以是提供一定范围内非常高的性能,或低的功耗。只有让系统是服务于特定应用的,才能让它实现如此的性能。GPP 也许能做到嵌入式系统的功能,但是无法达到相同的系统性能,或相同的功耗需求。GPP 的通用可编程能力还带来了成本问题,因为GPP 一般比用于嵌入式系统的要贵很多。
9.1.1 应用
嵌入式系统被部署在广泛领域的大量的设备中。图 9.1 给出了嵌入式系统主要用于的一些领域。
图 9.1: 嵌入式系统应用领域
下面详细列出了每个重点领域中的一些应用:
- 通信 — 移动电话、路由器、消费无线电和电视。
- 医疗电子 — 人体扫描设备如 MRI、听诊器和心脏起搏器。
- 消费电子 — 数字相机、视频游戏和洗衣机。
- 军事和航空 — 雷达和声纳、制导导弹系统、卫星站和飞行导航系统。
- 运输系统 — 防抱死刹车系统(ABS)、气囊、车载娱乐、GPS和卫星导航系统。
9.1.2 一般嵌入式系统架构
一般来说,一个嵌入式系统的架构遵循图 9.2 的框图。
图 9.2: 一般嵌入式系统架构
图 9.2 中的每个部件定义如下:
- 处理器 — 这是系统的 “ 大脑 ”。它被编程来执行嵌入式系统的特定应用。
- 储存控制器 — 存储控制器管理嵌入式系统中的主存储器的数据读写。存储 控制器位于片内的软核中,实现系统存储器和所有其他部分之间的接口。
- 外围设备 —这些是围绕着中央处理单元的部件。外设可以实现为单独的集 成电路芯片,也可以包含在片内与处理器一起,还可以位于像 FPGA 这样的可编程逻辑的某个区域中。
- 系统总线 — 在有多个总线的嵌入式系统中,系统总线把处理器、存储控制器 和其他高速器件连接在一起。因此,它是系统中具有最大带宽的总线。
- 外设总线 — 第二条总线创建了系统的两个独立的部分,让两个仲裁器可以 控制和管理跨越两条总线的通信。这样,即使高优先级的处理器 - 存储器会话正在系统总线上进行的时候,外设总线上的设备还可以互相通信。
9.2 处理器
处理器是嵌入式系统中的主控单元。它控制和安排系统、支持软件并协调与外设部件的数据交换。在使用了操作系统来管理系统的嵌入式系统中,操作系统是运行在处理器上的。
在嵌入式系统中有各种可以使用的处理器,简列如下:
- 微处理器 — 微处理器是单片集成电路芯片,包括完整的中央处理单元,此外别无他物。为了让微处理器能运作,必须加上 RAM 和 ROM 形式的外部存储器和其他的外围设备。PC 中的 CPU 正是一种微处理器。
- 单片机(微控制器) — 单片机在单片芯片上包含有完整的计算机系统。与微处理器不同,单片机在单个集成电路 (IC)内包括了一个 CPU 和一定数量的RAM/ROM 和外围设备。
- 数字信号处理器 (DSP) — DSP 是一种设计专用于数字信号处理的处理器, 它的指令集的设计目的是数字信号处理。DSP 设计成能快速执行算术运算,能在单个时钟周期里开展多重累加运算。这使得 DSP 在用作特定的音频 / 视频处理时非常高效,性能高而且功耗低,但是由于它的指令集有限,用作其他任务时非常糟糕。
- 嵌入处理器 — 嵌入处理器是物理上位于 FPGA 芯片内的可编程部分内的处理器。嵌入处理器有两种类型 —— 硬处理器和软处理器。硬处理器是在专门的硅面积内,在 FPGA 芯片的通用逻辑之外构建的。而软处理器则必须综合进FPGA 部分。无论哪种,无论硬的还是软的,内部存储器、总线互联、存储控制器和内部外围设备都必须是由 FPGA 通用逻辑来实现的。
9.2.1 协处理器
协处理器是一个处理核心,它弥补了主处理器的功能不足,优化于从事单一特定的任务。通过把计算任务从主处理器卸载到一个甚至多个协处理器上,整个系统的性能可以得到加速。
与主处理器可能用于各种不同的任务不同,协处理器一般用于从事专门的任务。可能在专门的协处理器上运行的任务的例子包括:
- 高速计算
- 图像与视频处理
- 数字信号处理
- 数字加密
对于基于 FPGA 的嵌入式系统,可编程逻辑提供了一个完美的平台,可以在其中创建协处理器核心来利用它的并行执行能力。这意味着需要大量连续 CPU 时钟周期来计算的复杂任务可以在基于 PL 的协处理器上执行地快很多。这就是软处理器核心。还有其他形式的用专门硬件处理核心但不在 FPGA 上的加速方式。总的来说,这种任务卸载处理方式叫做硬件加速。
9.2.2 处理器 cache
Cache 是一小块位于 CPU 和主存储器之间的存储器。它具有比主存储器低的访问时间,而且不能通过系统总线访问。cache 用来保存被处理器从主存储器中频繁访问的数据。因此使用在 cache 中的数据就比只在主存储器中的数据快很多。
通常一个处理器读数据的速度比系统的主存储器要快很多,因此处理器的速度是受到存储器的速度的制约的。通过在系统中引入 cache 存储器 —— cache 中存放了频繁访问的数据,能以比主存储器更高的速率读取 —— 处理器就不再受到主存储器速度的限制了。这导致了数据访问效率的提升。不过,在 cache 失配时,处理器的速度还是受限的 —— 这个时候,处理器要读写的数据不在 cache 中。这样 就要读写主存储器中的数据,从而提高了访问延迟。
一个系统中可以有不同级别的 cache。图 9.3 给出了概图,随后做了解释。
图 9.3: cache 级别和它们与核心及主存储器的位置关系
在进一步讨论 cache 的不同级别之前,首先应该来介绍要用到的两种类型的存储器 — 动态 RAM (DRAM)和静态 RAM (SRAM)。
动态 RAM (DRAM)
DRAM 是在计算机系统中最常见的存储器类型。DRAM 芯片包括大量存储单元,每 个单元用电容保存 1 位的数据。每个存储单元还配有一个晶体管,它像一个开关一样让控制电路可以读或写这个电容的状态。由于电容和晶体管都极为微小,单个DRAM 芯片中可以放几百万个独立的存储单元。由于电容会自己漏电,每个存储单元所保存的一位的数据的状态最终会消失, 除非这个电容上的电荷能周期性地被存储控制器所刷新。存储控制器通过读每个存储单元的状态然后再写回去来实现这个刷新。这正是动态 RAM 得名的由来。
静态 RAM
(SRAM) SRAM 采用与 DRAM 不同的技术来保存数据。DRAM 的每一位是存储在电容中的, 而 SRAM 用了锁存器来保存数据。每个存储单元需要 4 或 6 个锁存器来保存数据的一178L3第 9 章 : 嵌入式系统和 FPGA,因此比 DRAM 需要更多的芯片面积,从而导致它更贵。SRAM 的好处是不需要刷新,因此比 DRAM 快很多。由于 SRAM 的高价,通常只用于高速、低容量的存储芯片中。
1 级 (L1)
Cache L1 cache 是最小的 cache 存储器,典型的大小是 8 到 128kB。它是以在处理器 核心所在的硅片上的 SRAM 来实现的,因此具有与处理器相同的时钟速度。L1 cache 通常分成两个部分:数据 cache 和指令 cache。L1 cache 用来保存常用数据和指令的本地拷贝,使得处理器能瞬间访问它们。
2 级 (L2)
Cache L2 cache 通常是独立于处理器核心之外的,但是离得非常近。它比 L1 cache 大,通常在 256 到 1024kB 之间,但是访问速度较慢。L2 cache 是 DRAM 的形式,只 有统一的一块区域(不像 L1 那样分成两块区域)。较大量的数据会不断地由主存储器读入 L2 cache,然后再馈送给 L1。
3 级 (L3)
Cache L3 cache 是在所有的处理器核心之间共享的,它也是 DRAM 的形式,是最大的 cache 存储器,通常具有 2MB 甚至更大的容量。
9.2.3 执行周期
为了让一个保存在存储器中的程序能被处理器执行,程序必须经过一个指令执行的周期。这个过程是系统从存储器获取一条指令、判断指令所需的动作然后执行这样的动作。每条指令的执行可以被划分成三个独特的部分,如图 9.4 所示。由于一些明显的理由,这个过程有时候被称作取值 - 执行周期或取值 - 译码 - 执行周期。
图 9.4: 指令执行周期的步骤
在详细了解指令执行周期的每个阶段之前,应该先来理解一些会用到的术语:
- 机器码 — 在写软件程序的时候,通常用的是高级语言(比如 C/C ),这种语言易于被程序员所理解,而且是人可读的。这种形式的代码对于处理器系统是无意义的,必须被转换,或者说编译成处理器可以理解的形式。这最后的低级的能被处理器所阅读的输出结果,就是机器码 —— 一串和程序相关的、处 理器能解释和操作的二进制数据。
- 操作码 — 一个操作码是一个运算编码,唯一地定义了要做的一个功能 —— 一条机器码代表了一个处理器指令。一个处理器可以执行许多不同的运算,因此每条指令都被指定了唯一的数字编码。
- CPU 指令集 —某个处理器的指令集是处理器能理解的命令的基本集合。它包含了每个操作码的定义和可以由处理器执行的本地命令。
取指
取指是指令执行周期的第一个阶段。图 9.5 描绘了下面的操作流程:
图 9.5: F 取指的流程
根据图 9.5,取值的流程是这样的:
1. 程序计数器寄存器里有表示存储器里要执行的下一条指令的地址。
2. 这个值被传送给存储器的地址寄存器,在那里,控制单元检查这个值并从存储器中获得相应的指令。
3. 那条指令于是就被保存在存储器缓冲寄存器中,然后再被传输给指令寄存器。
4. 控制单元改变程序计数器寄存器,让它的值符合下一条要执行的指令的地址。
译码指令
一旦指令被从存储器中取出,下一步就是把指令变成处理器能理解的形式。这就是译码阶段。在这个时刻,控制单元检查保存在指令寄存器里的指令。这个检查识别出操作码和所用的寻址方式,以及接下来必须要执行什么动作来正确地执行这条指令。有三种主要的寻址方式:
- 立即寻址 — 这是不需要找数据的,因为所有要用到的数据都在指令的操作数部分里了。因此立即寻址是最快,但是最不灵活的方式。
- 直接寻址 — 指令的操作数部分包含了所需的数据的存储器地址。所需的数据必须从这个地址获得。
- 间接寻址 — 指令的操作数部分包含了一个存储器地址。在这个地址上的存储器内容是一个指向所需数据地址的指针。因此间接寻址是最灵活的,但是由于要做两次数据查找,所以也是最慢的。
执行指令
根据译码阶段所决定的操作码,在这个阶段可能做各种不同的动作。总的来 说,有四大类动作:
- 在处理器和存储器之间传输数据。
- 在处理器和 I/O 设备之间传输数据。
- 处理数据,比如用算术逻辑单元 (Arithmetic Logic Unit,ALU)。
- 会改变后续操作的顺序的控制操作。这些可能是基于某个标志寄存器的值的条件操作。
一旦指令被执行了,下一条要处理的指令就被取了过来。
图 9.6 表示了一个执行周期的流程。
图 9.6: 执行指令的流程
根据图 9.6,流程是这样的:
1. 控制单元把译码阶段的译码数据 (作为控制信号的结果)传送给所需的处理器功能单元。比如,可能是要从寄存器读值或写入一个寄存器。
2. 处理器做所需的操作,而输出可能是保存在存储器中,也可能要发送给输出设备。
3. 如果用到了 ALU,就会有一个条件信号被转发回控制单元。比如,这个信号可能要改变程序计数器的地址,这样新地址上的下一条指令就会被取过来。
9.2.4 中断
中断是一个信号,产生来通知处理器引起它的注意。中断可以由硬件处理单元和外部设备产生,也可以由软件本身产生。对硬件来说,中断信号是一个由某个处理单元产生的异步信号,用来引起处理器的注意。对软件来说,中断还是一种异步事件,用来通知处理器需要改变代码的执行了。不过,轮询所产生的中断的过程是同步的。
当处理器收到中断,它会停下当前正在做的任务,然后跳转到需要引起注意的地方去。这和轮询的方式是相反的,轮询是由软件同步获取设备的状态。在中断方式中,不需要由处理器不断地轮询设备的 I/O 端口来查看是否需要注意,设备本身会中断处理器的。
硬件中断可以进一步被分类为以下几种类型:
- 可屏蔽中断(Maskable Interrupts,IRQ) — 触发可屏蔽中断的事件源不总是重要的。程序员需要决定这个事件是否应该导致程序跳到所需处理的地方去。可能使用可屏蔽中断的设备包括定时器、比较器和 ADC。
- 不可屏蔽中断(Non-Maskable Interrupts,NMI) — 这些是不应该被忽视的中断,因此绝对比可屏蔽中断重要得多。需要 NMI 的事件包括上电、外部重启(用实际的按钮)和严重的设备失效。
- 处理器间中断(Inter-Processor Interrupts,IPI) — 在多处理器系统中, 一个处理器可能需要中断另一个处理器的操作。在这种情况下,就会产生一个IPI。
第十九篇到此结束,下一篇将带来第二十篇,嵌入式系统和 FPGA的总线等相关内容。欢迎各位大侠一起交流学习,共同进步。
END
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!