文档库 最新最全的文档下载
当前位置:文档库 › FPGA入门教程

FPGA入门教程

FPGA入门教程

1.数字电路设计入门2.FPGA简介

3.FPGA开发流程4.RTL设计

5.QuartusⅡ设计实例

6. ModelSim和Testbench

1.数字电路设计入门

1.1数字电路设计

数字电路设计的核心是逻辑设计。通常,数字电路的逻辑值只有‘1’和‘0’,表征的是模拟电压或电流的离散值,一般‘1’代表高电平,‘0’代表低电平。

高低电平的含义可以理解为,存在一个判决电平,当信号的电压值高于判决电平时,我们就认为该信号表征高电平,即为‘1’。反之亦然。

当前的数字电路中存在许多种电平标准,比较常见的有TTL、CMOS、LVTTL、LVCMOS、ECL、PECL、LVDS、HSTL、SSTL等。这些电平的详细指标请见《补充教程1:电平标准》。

数字电路设计大致可分为组合逻辑电路和时序逻辑电路。

一般的数字设计的教材中对组合逻辑电路和时序逻辑电路的定义分别为:组合逻辑电路的输出仅与当前的输入有关,而时序逻辑电路的输出不但与输入有关,还和系统上一个状态有关。

但是在设计中,我们一般以时钟的存在与否来区分该电路的性质。由时钟沿驱动工作的电路为时序逻辑电路。大家注意,这两种电路并不是独立存在的,他们相互交错存在于整个电路系统的设计中。

1.1.1组合逻辑电路

组合逻辑电路由任意数目的逻辑门电路组成,一般包括与门、或门、非门、异或门、与非门、或非门等。一般的组合逻辑电路如下图:

其中A,B,C,D,E,F为输入,G为输出。

1.1.2时序逻辑电路

时序逻辑电路由时钟的上升沿或下降沿驱动工作,其实真正被时钟沿驱动的是电路中的触发器(Register),也称为寄存器。触发器的工作原理和参数如下图:

下面是两个简单的时序逻辑电路例子:

(1)、时钟分频电路

该时序电路的功能为实现对时钟’clk’的4分频,其中’clk_2’为2分频时钟,’clk_4’为4分频时钟,’enable’为该电路的使能信号。其功能仿真波形如下图所示:

(2)、序列检测器

该时序电路实现了一个序列检测器,当输入序列‘datain’中出现‘101’时,标志位F将输出‘1’,其他时刻输出‘0’。电路中‘clk’为时钟信号,‘D1’,‘D2’,‘D3’为移位寄存器的输出,’enable’为该电路的使能信号。其功能仿真波形如下图所示:

可见,时序电路设计的核心是时钟和触发器,这两者也是我们设计电路时需重点关注的。

1.2毛刺的产生与消除

1.2.1竞争与冒险

当一个逻辑门的输入有两个或两个以上的变量发生改变时,由于这些变量是经过不同路径产生的,使得它们状态改变的时刻有先有后,这种时差引起的现象称为竞争(Race)。竞争的结果将很可能导致冒险(Hazard)发生(例如产生毛刺),造成错误的后果,并影响系统的工作。

组合逻辑电路的冒险仅在信号状态改变的时刻出现毛刺,这种冒险是过渡性的,它不会使稳态值偏离正常值,但在时序电路中,冒险是本质的,可导致电路的输出值永远偏离正常值或者发生振荡。

避免冒险的最简单的方法是同一时刻只允许单个输入变量发生变化,或者使用寄存器采样的办法。

1.2.2毛刺的产生与危害

信号在FPGA器件中通过逻辑单元连线时,一定存在延时。延时的大小不仅和连线的长短和逻辑单元的数目有关,而且也和器件的制造工艺、工作环境等有关。因此,信号在器件中传输的时候,所需要的时间是不能精确估计的,当多路信号同时发生跳变的瞬间,就产生了“竞争冒险”。这时,往往会出现一些不正确的尖峰信号,这些尖峰信号就是“毛刺”。

让我们来具体看一下毛刺是如何产生的。下图是一个与门电路,

我们期望的设计是,a和b信号同时变化,这样输出OUT将一直为0,但是实际中OUT 产生了毛刺,它的仿真波形如下所示:

可见,即使是在最简单的逻辑运算中,如果出现多路信号同时跳变的情况,在通过内部走线之后,就一定会产生毛刺。而现在数字电路设计中的信号往往是由时钟控制的,如果将带有毛刺的输出信号直接连接到时钟输入端、清零或置位端口的设计,可能会导致严重的后果;此外对于多数据输入的复杂运算系统,每个数据都由相当多的位数组成。这时,每一级的毛刺都会对结果有严重的影响,如果是多级的设计,那么毛刺累加后甚至会影响整个设计的可靠性和精确性。

判断一个逻辑电路在某些输入信号发生变化时是否会产生毛刺,首先要判断信号是否会同时变化,然后判断在信号同时变化的时候,是否会产生毛刺,这可以通过逻辑函数的卡诺图或逻辑函数表达式来进行判断。

1.2.3毛刺的消除

毛刺是数字电路设计中的棘手问题,它的出现会影响电路工作的稳定性、可靠性,严重时会导致整个数字系统的误动作和逻辑紊乱。

可以通过以下几种方法来消除毛刺:

1、输出加D触发器

这是一种比较传统的去除毛刺的方法。原理就是用一个D触发器去读带毛刺的信号,利用D触发器对输入信号的毛刺不敏感的特点,去除信号中的毛刺。在实际中,对于简单的逻辑电路,尤其是对信号中发生在非时钟跳变沿的毛刺信号,去除效果非常的明显。

但是如果毛刺信号发生在时钟信号的跳变沿,D触发器的效果就没有那么明显了(加D 触发器以后的输出q,仍含有毛刺)。另外,D触发器的使用还会给系统带来一定的延时,特别是在系统级数较多的情况下,延时也将变大,因此在使用D触发器去除毛刺的时候,一定要视情况而定,并不是所有的毛刺都可以用D触发器来消除。

2、信号同步法

设计数字电路的时候采用同步电路可以大大减少毛刺。由于大多数毛刺都比较短(大概几个纳秒),只要毛刺不出现在时钟跳变沿,毛刺信号就不会对系统造成危害了。因此一般认为,只要在整个系统中使用同一个时钟就可以实现系统同步。但是,时钟信号在FPGA 器件中传递时是有延时的,我们无法预知时钟跳变沿的精确位置。也就是说我们无法保证在某个时钟的跳变沿读取的数据是一个稳定的数据,尤其是在多级设计中,这个问题就更加突出。因此,做到真正的"同步"就是去除毛刺信号的关键问题。所以同步的关键就是保证在时钟的跳变沿读取的数据是稳定的数据而不是毛刺数据。以下为两种具体的信号同步方法。

(1)信号延时同步法

信号延时法,它的原理就是在两级信号传递的过程中加一个延时环节,从而保证在下一个模块中读取到的数据是稳定后的数据,即不包含毛刺信号。这里所指的信号延时可以是数据信号的延时,也可以是时钟信号的延时。

(2)状态机控制

使用状态机也可以实现信号的同步和消除毛刺的目的。在数据传递比较复杂的多模块系统中,由状态机在特定的时刻分别发出控制特定模块的时钟信号或者模块使能信号,状态机的循环控制就可以使得整个系统协调运作,同时减少毛刺信号。那么只要我们在状态机的触发时间上加以处理,就可以避免竞争冒险,从而抑制毛刺的产生。

3、格雷码计数器

对于一般的二进制或十进制计数器,在计数时,将有多位信号同时跳变。例如一个3bit 二进制计数器,由’111’转换为’000’时,必将产生毛刺。此时,使用格雷码计数器将避免毛

刺的出现,因为格雷码计数器的输出每次只有一位跳变。

其他关于毛刺的详细讨论,请见补充教程2:关于毛刺问题的探讨。

1.3同步电路设计

同步电路是指所有电路在同一个公共时钟的上升沿或下降沿的触发下同步地工作。但在实际系统中,往往存在多时钟域的情况,这时同步的概念有所延伸,不再专指整个设计同步于同一时钟沿,而是指设计应该做到局部同步,在每个时钟域内的电路要同步于同一时钟沿。

1.3.1 同步电路设计的优点:

1.同步设计能有效地避免毛刺的影响,使得设计更可靠;

2.同步设计易于添加异步复位reset,以使整个电路有一个确定的初始状态;

3.同步设计可以减小环境对芯片的影响,避免器件受温度,电压,工艺的影响;

4.同步设计可以使静态时序分析变得简单和可靠;

5.同步设计可以很容易地组织流水线,提高芯片的运行速度。

1.3.2同步电路的设计准则:

1.尽可能在设计中使用同一时钟,时钟走全局时钟网络。走全局时钟网络的时钟是最简单、最可预测的时钟,它具有很强的驱动能力,可以驱动FPGA内部中的所有触发器,并保证Clock skew可以小到忽略的地步。

2.避免使用混合时钟沿采样数据,即避免在设计中同时使用时钟的上升沿和下降沿。

3.尽量少在模块内部使用计数器分频所产生的时钟。计数器分频时钟需完成的逻辑功能完全可由PLL锁相环或时钟使能电路替代。计数器分频时钟的缺点是使得系统内时钟不可控,并产生较大的Clock skew,还使静态时序分析变得复杂。

4.避免使用门控时钟。因为经组合逻辑产生的门控时钟极可能产生毛刺,使D触发器误动作。

5.当整个电路需要多个时钟来实现,则可以将整个电路分成若干局部同步电路(尽量以同一个时钟为一个模块),局部同步电路之间接口当作异步接口考虑,而且每个时钟信号的时钟偏差(△T)要严格控制。

6.电路的实际最高工作频率不应大于理论最高工作频率,留有设计余量,保证芯片可靠工作。

7.电路中所有寄存器、状态机在系统被reset 复位时应处在一个已知的状态。 关于同步电路设计中的其他问题请详见补充教程3:华为同步电路设计规范。

1.3.3关于时钟设计的讨论

目前的工程设计中一般使用同步时序电路来完成整个系统的设计,由上一节可见,时钟

在同步电路设计中起着至关重要的作用。那么,我们在设计时首先要完成的是对时钟的设计。 如今在设计中常见的时钟类型包括: 全局时钟、内部逻辑时钟和门控时钟。

1. 全局时钟

全局时钟即同步时钟,它通过FPGA 芯片内的全局时钟布线网络或区域时钟网络来驱动,全局时钟具有高扇出、高精度、低Jitter 和低Skew 的特点,它到芯片中的每一个寄存器的延迟最短,且该延迟可被认为是固定值。所以我们推荐在所有的设计中的时钟都使用全局时钟。全局时钟的设计有以下几种方法:

(1). 由PLL 锁相环来产生全局时钟。

(2). 将FPGA 芯片内部逻辑产生的时钟分配至全局时钟布线网络。 (3). 将外部时钟通过专用的全局时钟输入引脚引入FPGA。

在我们的设计中,一般推荐电路中的所有的时钟都由PLL 锁相环产生。一方面,PLL 锁相环可实现倍频和移相的操作,使我们很方便地获得所需频率和相位的时钟;另一方面,PLL 锁相环默认将其驱动的时钟分配至全局时钟网络或区域时钟网络,Jitter 和Skew 都很小。 下图取自我们项目中的一个PLL 锁相环设计,该PLL 用于驱动DDR 的接口模块。因为功能所需,DDR 接口需要三个133MHz 的时钟,相位分别是‘-90’、‘0’、‘-180’,图中所示即为该时钟的产生模块。我们使用Quartus Ⅱ的Megawizard 生成PLL 锁相环的IP core 。其中‘inclk_66’为PLL 锁相环的输入时钟,由外部的66MHz 晶振提供,经过PLL 倍频和移相后得到所需的三个全局时钟。

o

o

o

2.内部逻辑时钟

内部逻辑时钟即指由芯片内部的组合逻辑或计数器分频产生的时钟。

对于组合逻辑时钟,特别是由多级组合逻辑产生的时钟,是要被严格禁止使用的,因

为一方面组合逻辑极容易产生毛刺,特别是对多级组合逻辑;另一方面组合逻辑电路的Jitter

和Skew比较大,这将恶化时钟的质量。所以,一般组合逻辑产生的内部时钟仅仅适用于时

钟频率较低、时钟精度要求不高的情况。

对于计数器分频产生的时钟,也应该尽量少地使用,因为这种时钟会带来比较大的延

迟,降低设计的可靠性,也使得静态时序分析变得复杂。计数器分频时钟需完成的逻辑功能

完全可由PLL锁相环或时钟使能电路替代。

还有一种由触发器产生的时钟—行波时钟,即一个触发器的输出用作另一个触发器的

时钟输入。文中1.1.2节描述的时钟分频电路就是一种行波时钟。因为各触发器的时钟之间

产生较大的时间偏移,很容易就会违反建立时间、保持时间的要求,导致亚稳态的发生。所

以,这种行波时钟要被严格禁止使用。

3.门控时钟

一般情况下,应该避免使用门控时钟。因为经组合逻辑产生的门控时钟极可能产生毛

刺,对系统造成很大危害。但对于某些功耗很大的系统而言,需要使用门控时钟来降低功耗。

我们推荐使用右图中描述的门控时钟的设

因为触发器避免了毛刺的产生,而亚稳态只可能

出现在源时钟的下降沿,但是随后它与源时钟低

相位相与,最后不会产生影响。

source_clk

clk_en

qout

gated_clk

门控时钟最好只在顶层模块中出现,并将其分离到一个在顶层的独立模块中。这同时保

证了底层的每个模块有单一的时钟,且在本模块中的时钟不进行门控。

在补充教程4和补充教程5中,我们对时钟和时序的设计进行了更详细的讨论。

1.3.4 亚稳态

在同步电路或异步电路中,如果触发器的setup 时间或hold 时间不能得到满足,就可能产生亚稳态,此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的状态,在这段时间里Q端将会产生毛刺并不断振荡、最终固定在某一电压值上,此电压值并不一定等于原来数据输入端D

的值。这段时间称为决断时间

(resolution time)。经过决断

时间之后,Q端将稳定到0或

1上,但是究竟是0还是1,

这是随机的,与输入没有必然

的关系。

亚稳态的危害主要体

现在破坏系统得稳定性上,由于输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值,因此亚稳态除了导致逻辑误判之外,严重情况下输出0~1之间的中间电压值还会使下一级产生亚稳态(即导致亚稳态的传播)。逻辑误判将导致功能性错误,而亚稳态的传播则扩大了故障面,严重时将导致系统崩溃。

在异步时序电路中更容易发生亚稳态,因为异步电路一般具有多个时钟域,数据在两个时钟域间传递时,非常容易导致setup 时间或hold 时间不满足而发生亚稳态。在同步时序电路中,当两个触发器间的组合逻辑延迟过大时,会导致setup 时间不满足而发生亚稳态。

1.3.5 对跨时钟域数据的处理

对跨时钟域数据的处理的核心就是要保证下级时钟对上级数据采样的setup 时间或hold 时间满足要求,即尽量避免亚稳态的发生和传播。但是,我们知道,只要系统中有异步元件,亚稳态就是无法避免的,因此设计的电路首先要减少亚稳态导致错误的发生,其次要使系统对产生的错误不敏感。我们推荐使用以下方法来解决异步时钟域数据同步问题。

1.用触发器打两拍

如下图,左边为异步输入端,经过两级触发器同步,在右边的输出将是同步的,而且该输出基本不存在亚稳态。其原理是即使第一个触发器的输出端存在亚稳态,经过一个CLK 周期后,第二个触发器D端的电平仍未稳定的概率非常小,因此第二个触发器Q端基本不会产生亚稳态。然而,亚稳态是无法被根除的,一旦亚稳态发生,后果的严重程度依赖于你

设计系统对产生的错误是否敏感。

2. 异步FIFO 或DPRAM

因为异步FIFO 或DPRAM 使用格雷码计数器设计读写地址的指针,所以它可以很

好地避免亚稳态的发生。使用方法如下,将上级芯片提供的数据随路时钟作为写信号,将数据写入异步FIFO 或DPRAM ,然后使用本级的采样时钟将数据读出即可。唯一需要注意的是,当两级时钟频率不同时,需要设计好缓冲区,并通过监控full 、half 、empty 、useword 3. 调整时钟相位

信号,保证数据不会溢出,也不会被读空。

而且适用面有限。首先需对跨时钟域数据的路径进行详

细的静态时序分析,然后将违反setup 时间和hold 时间的情况一一列出,在不影响其它设计性能的前提下,综合考虑调整两级时钟的相位关系,最终使其setup 时间和hold 时间满足要求。

这种方法的设计难度较大,

2.FPGA 简介

2.1什么是FPGA

mable Gate Array 的缩写,即现场可编程门阵列, 是一种可编程的IC

以下是目前项目中使用的几种FPGA 芯片:

FPGA 是Field Program 芯片(集成电路芯片)

2.2 FPGA 的结构与组成的可编程逻辑单元构成阵列,又由可编程I/O 单元围绕阵

排成阵列的逻辑单元由布线通道中的可编程内连线连接起来实现一定的逻辑功能。

FPGA 的可编程逻辑单元一般由查找表和触发器构成。下图所示即为Cyclone 系列FPGA 芯LE )组成。 图左边所示的电路,查找表是这样实现的:首先FPGA 开发软件会自动计算逻辑电路的所有等于输入一个地址进行查表,找出地址对应的内容后输出,即实现了该逻辑功能。

通常FPGA 由布线资源分隔列构成整个芯片,目前我们使用的片的逻辑单元(

查找表(Look-Up-Table)简称为LUT,其本质上就是一个静态存储器SRAM。 对于下可能的结果,然后把结果事先写入查找表中,FPGA

工作时,输入信号所进行的逻辑运算就

实际逻辑电路 LUT 的实现方式

a,b,c,d 输入

逻辑输出

地址 RAM 中存储的内容

0000 0 0000 0 0001 0 0001 0 .... 0 ... 0 1111

1

1111

1

如果所设计的是时序电路,需要触发器,则FPGA 开发软件会自动将触发器配置在查

找表的后面,实现组合逻辑时就将触发器旁路掉。

当然,对于复杂的设计,一个LUT 是无法完成的,FPGA 可以通过进位逻辑将多个LUT 相连起来,实现n 输入的查找表,实现设计要求。 表、触发器和布线资源组成。下图内部结构,其中一对查找表和触发器构成逻辑单元LE,

LE 组各种布线资源,就是一个FPGA 详细的介绍请见:补充教程2.3 FPGA 与ASIC 设计的区别 ASIC 和FPGA 个发展方向,两者唯一的区别在于,ASIC 的逻FPGA 。

设计的代码风格有明显差异,特别是在功耗、速度、时序等要求上。例如意识地采用某些组合逻辑、门控时钟等,以降低功耗或提高速度。

通俗地说,FPGA 就是由查找是一个Cyclone 系列FPGA 芯片的若干个成逻辑阵列块LAB ,最后再配上芯片了。

6 FPGA PLD 结构与原理。

ASIC 是Application Specific Integrated Circuit 的缩写,即专用集成电路。属于SOC (System on a chip 片上系统)的两辑电路是固化在其芯片中的,我们可以将ASIC 理解为不可编程的由于FPGA 设计是基于固有的硬件结构(如逻辑单元、块RAM 、PLL/DLL 、时钟资源等)的;而ASIC 设计结构灵活,目标多样,所以ASIC 设计的代码风格和FPGA ASIC 设计中根据要求会有

3. FPGA开发流程

HDL(Hardware Design Language)和原理图是两种最常用的数字硬件电路描述方法,HDL设计法具有更好的可移植性、通用性和模块划分与重用性的特点,在目前的工程设计中被广泛使用。所以,我们在使用FPGA设计数字电路时,其

开发流程是基于HDL的。

3.1需求定义(功能定义)

设计和实现一个系统的第一步,是明确整个系统的性能指标,然后进一步将系统功能划分为可实现的具体功能模块,同时明确各模块的功能与基本时序,还可大致确定模块间的接口,如时钟、读写信号、数据流和控制信号等。

3.2 RTL级HDL描述

RTL级(寄存器传输级)指不关注寄存器和组合逻辑的细节(如使用了多少逻辑门、逻辑门的连接拓扑结构等),通过描述寄存器到寄存器之间的逻辑功能的HDL设计方法。RTL 级比门级更抽象,同时也更简单和高效。RTL级的最大特点是可以直接用综合工具将其综合为门级网表。RTL级设计直接决定着系统的功能和效率。我们使用的HDL语言是verilog。

3.3功能仿真(前仿真)

功能仿真也称综合前仿真,其目的是验证RTL级描述是否与设计意图一致。为了提高效率,功能仿真需要建立testbench,其测试激励一般使用行为级HDL语言描述。

3.4管脚分配与设计约束

无论是RTL级还是门级的HDL设计方法,在实现该逻辑时都需要与实际的FPGA芯片相匹配。管脚分配是指将设计文件的输入输出信号指定到器件的某个管脚,设置此管脚的电平标准、电流强度等。设计约束指对设计的时序约束和在综合、布局布线阶段附加的约束等。

3.5综合

将RTL级HDL语言翻译成由与、或、非门等基本逻辑单元组成的门级连接(网表),并根据设计目标与要求(约束条件)优化所生成的逻辑连接,输出门级网表文件。

3.6门级仿真(综合后仿真)

在综合后通过后仿真来检查综合结果是否与原设计一致。一般,综合后仿真和功能仿真的测试激励相同。由于综合工具日益完善,在目前的FPGA设计中,这一步骤被省略掉。3.7布局布线

布局布线就是使用综合后的网表文件,将工程的逻辑与时序要求与器件的可用资源相匹配。也可以简单地将布局布线理解为对FPGA内部查找表和寄存器资源的合理配置,那么‘布

局’ 可以被理解挑选可实现设计网表的最优的资源组合,‘布线’就是将这些查找表和寄存器 通过时序/时延分析获得布局布线后系统的延时信息,不仅包括门延时,而且还有实际的lation ),即不满足时序约束条件或者器件固有时序规则(建立

局布线后的配置文件下载至FPGA 中,对其硬件进行编配置文件一般为.pof 或.sof 式,下载方式包括AS (主动)、PS (被动)、(边界扫描)等方式。

资源以最优方式连接起来。

3.8时序/时延分析

布线延时。时序/时延分析的时序仿真是最准确的,能较好地反映芯片的实际工作情况,同时发现时序违规(Timing Vio 时间、保持时间)的情况。3.9配置与下载

通过编程器(programmer )将布程。文件格JTAG

4.RTL 设计

4.1使用verilog 进行RTL 设计

TL 设计一般可归纳为3种基本的描述方式:

2、行为描述:使用always 语句或initial 语句块的过程赋值语句。

3、结构化描述:实例化已有的功能模块或原语,即平常所说的元件例化和IP core 。 其中,连续赋值语句是连续驱动的,也就是说只要输入变化,都会导致该语句的重新计。其被赋值的变量不会被电路寄存。过程赋值语句包括非阻塞过程赋值、阻塞过程赋值和连续过程赋值。对于这些抽象的概念,我们将在其后的实际例子中详细解释。

4.1.1硬件设计意识

RTL 设计其实就是用语描述硬件电路行为的过程。这同一般的软件设计有很大区别,因为对于很多的软件代码,硬件电路是无法实现的(即无法综合,从语言到硬件电路的解析过程称为综合)。我们只能使用可综合的代码结构来实现我们所需的硬件电路。

首先,我们需要建立硬件设计的意识,硬件意识是RTL 级设计的基础。

1.电路在物理上是并行工作的。其含义是,一旦接通电源,所有电路都同时工作。

2.电路行为的先后顺序通过时钟节拍得顺序来体现。

4.1.2 RLT 级设计时需注意的问题:

1.凡是在always 或initial 语句中赋值的变量,一定是reg 类型变量;凡是在assign 语句中赋值的变量,一定是wire 类型变量;

2. 定义存储器:reg [3] MEMORY [0:7]; 地址为0~7,每个存储单元都是4bit ; 3.由于硬件是并行工作的,在Verilog 语言的module 中,所有描述语句(包括连续赋值语句assign 、行为语句块ways 和initial 语句块以及模块实例化)都是并发执行的。

4.使用完备的if…else 语句,使用条件完备的case 语句并设置default 操作,以防止产生锁存器latch ,因为锁存器对毛刺敏5.严禁设计组合逻辑反馈环路,它最容易引起振荡、毛刺、时序违规等问题。 6.不要在两个或两个以上的语句块(always 或initial )中对同一个信号赋值。 使用verilog 进行R 1、数据流描述:采用assign 连续赋值语句

算言的方式去:0al 感。

4.1.3阻塞赋值与非阻塞赋值

在中,有两种过程性赋值方式,即阻塞赋值(Verilog HDL blocking assignment )和非阻塞(non-blocking assignment )。这两种赋值方式有着根本的区别,如果使用不当,赋值综合出来的结果会和设计的期望结果相去甚远。

1.阻塞赋值的操作符为 “ = ”。它的含义是在计算等式右侧表达式值及完成其赋值时不会被其他的verilog 语句打断,就是说,在当前赋值没有完成之前,它阻塞了其他verilog 语句的执行。

例如:begin

end

语句2的,它"阻塞"语句2的执行。这里说的"执行完"指的是在本时刻计算完y+c 的值,并赋给y=5(旧值),c=4,a=3,b=1,则x=9,y=4。

的两个always 语句块。

过程2:

always @ (posedge clk or negedge rst_n) always @ (posedge clk or negedge rst_n) begi if ( rst_n == 1'b0) y = 1'b0; x = 1'b1; end end

,则在复位完后,x、y 1;如果先执行过程1,则x、0。

的标准,上例中两个always 块是并行执行的,与书写的前后顺序无关,但是,verilog 标准没有规定在这种特殊情况下的执行顺序。所以,这需要我们在编程时避免这样的代码。

<= ”。它的含义是在赋值操作时刻开始时计算等式右边,赋值操作时刻结束时更新等式左边。在这期间,可以执行其它塞例如: begin

x = y + c ; //语句1 y = a + b ; //语句2

语句1和语句2都要求在同一仿真时刻执行,但在语句1没有执行完之前,是不会执行y 。若该仿真时刻还有下面的情况,过程1和过程2是同一个module 中过程1: n begin

if ( rst_n == 1'b0) else else

y = x; x = y; 仿真开始时,两个always 语句块将并行地同时执行。如果仿真器先执行过程2的话的值最终都会变为y 的值最终都会变为为什么会出现这种情况呢?因为按照Verilog 2.非阻塞赋值的操作符为 “verilog 语句,也不阻其它verilog 语句的执行。

y <= a + b; //语句2

的在语句2之前,但是由于是非阻塞赋值,语句1的执行不影响语句2的执时刻完了后,才更新左端的值。若该仿真时刻y=5(旧值),c=4,a=3,b=1,则同样,对于下面的情况,过程1和过程2是同一个module 中的两个always 语句块。 过程: 过程2:

if ( rst_n == 1'b0) if ( rst_n == 1'b0) 将最终形成一反馈移位寄2.在组合逻辑中,使用阻塞赋值;

always 4.在同一个always 块中,如果既有组合逻辑又有时序逻辑,使用非阻塞赋值;5.always 模块的敏感表为电平敏感信号时,使用阻塞赋值; 7.不要在阻塞赋值中使用时延语句。

另外一点需注意的就是,阻塞赋值是相对时间赋值,非阻塞赋值是绝对时间赋值。

码的可综合性

码都是对硬件行为的一种描述,但不一定是可直接对应成电路的设计信息。行为描述可以基于不同的层次,如系统级,算法级,寄存器传输级(RTL)、RTL 的模式来编写代码,而不能随心所欲得

x <= y + c; //语句1 end

虽然语句1行,在该仿真x=8,y=4。

1 always @ (posedge clk or negedge rst_n) always @ (posedge clk or negedge rst_n) begin begin

y = 1'b0; x = 1'b1; else else

y = x; x = y; end end

由于仿真时刻完了后才会去更新左端的值,所以上面两个过程存器。

在实际使用中,我们需要遵循以下的原则: 1.在时序逻辑中,使用非阻塞赋值; 3.在同一个块中,不要混合使用阻塞赋值和非阻塞赋值;

6.不要使用#0时延进行赋值。 8.在行为级描述中,若语句间是顺序执行的关系,使用阻塞赋值。

4.2 HDL 代 任何符合HDL 语法标准的代门级等等。以目前大部分EDA 软件的综合能力来说,只有RTL 或更低层次的行为描述才能保证是可综合的。绝大部分电路设计必须遵循

写仅4.2.,我们举几个例子来说明这个问题: 的延迟语句(如:#delay )、,他们所描述的功能对硬件而言是不。比如,实现两个变量相除运算的代码:

c<=A/B; 我们将发现这句代码只能在前仿真中正确执行,在Quartus Ⅱ和其他EDA 软件中都不能将其综合成硬件。

除、求余、移位。试除和求余需要减法器,商数和余数的中间结果必须有寄存器存储;而这些运算显然不能在一完成,它需要一个状态机来控制时序,经过多个时钟周期才能得出结果。次描述的EDA (注:有些FPGA 的配套软件提供乘除法的运算模块,但也只能支持直接调用,不支持把形如C=A/B 的语句综合成除法模块)。

3.对于不定次数的循环运算是不可综合的,比如对于如下的代码段:

是有限的、固定的。当综合软件遇到循环语句时,总是将其展开成若干条顺序执行的语句,是常数,则展开的语句数是确定的,具有可综合性;而对应的硬件电路数量也不能确定,无法被综合。这样的语句还包括while ,repeat ,forever 等,他们都不可综合。

通常EDA 软件对HDL 代码的综合能力总是比人的思维差。也就是说,对于一段代码,那EDA 软件肯定也不行。比如说,加法器、,所以类似A+B-C ,(A>B)?C:D 这样的运算一定可以综合。实仅符合语法的HDL 代码。

1哪些是不可综合的代码

我们不可能将所有不可综合的代码都一一列出 1.对于一些抽象的行为描述代码是不可综合的。比如我们常见初始化语句initial 以及等待语句wait 都是不可综合的可实现的。

2.对于一些抽象的运算代码也是不可综合的always @(posedge clk) 试想一下,如果我们自己用笔算除法是怎么做的?从高位到低位逐次试个时钟延上一句简单的C=A/B 同所有这些相比显得太抽象,对于只能接受RTL 或更低层软件来说确实太难实现。for (i=0; i

当wordlength 为变量时,任何EDA 软件都不能综合这个代码。这是因为硬件规模必须然后再综合成电路。若wordlength 若它是变量时,展开的语句数不确定,4.2.2如何判断自己写的代码是可综合的

如果你不能想象出一个较直观的硬件实现方法,多路选择器是大家都很熟悉的电路而除法、开根、对数等等较复杂的运算,必须通过一定的算法实现,没有直观简单的现方法,则可以判断那些计算式是不能综合的,必须按它们的算法写出更具体的代码才能实现。此外,硬件无法支持的抽象行为描述,当然也不能被综合。

相关文档
相关文档 最新文档