FPGA(Field Programmable Gate Array)现场可编程逻辑门阵列,ASIC(Application Specific Integrated Circuit)即专用集成电路。
比速度
相同的工艺和设计,在FPGA上的速度应该比ASIC跑得慢。因为FPGA内部是基于通用的结构,也就是LUT(lookuptable),它可以实现加法器,组合逻辑等等,而ASIC,一般加法器就是加法器,而比较器就是比较器,FPGA结构上的通用性必然导致冗余;另外,作为FPGA基本单元是LUT(LUT组成SLICE,SLICE组成CLB--这是xilinx的结构),为此大的设计假如一个LUT实现不了,就得用两个LUT,一个SLICE实现不了就要用CLB,不同结构处于特定的位置,信号之间的互联,导致的wiredelay是不可忽略的一部分。而对于ASIC来说没有结构上的限制,而且对于特定的实际可以在空间上靠得很近,相对之下wiredelay和celldelay都应该比FPGA小。当然LUT中也有DFF,作为高速的设计一般都会在一个简单的组合逻辑操作之后打一拍,再做下一步的处理。
比个头
完全相同的结构的话,FPGA被ASIC远远踢飞。FPGA要规模大得多才能实现ASIC相同的功能,主频还只有几分之一。因此,FPGA相对于ASIC来说还是大很多的。
功耗方面
在相同工艺条件下,FPGA要大于ASIC。FPGA,尤其是基于占用大量硅面积的、每个单元六个晶体管的静态存储器(SRAM)的查寻表(LUT)和配置元件技术的FPGA,其功耗要比对等的ASIC大得多。
比花的银子
FPGA贵在单片,开发工具和风险基本不存在。对于ASIC贵在流片的费用和开发工具,NRE费用随着工艺的提高变相当贵,除非你的芯片一次成功可以量产,否则单片费用将其贵无比!
同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。
同步时序逻辑电路的特点:各触发器的时钟端全部连接在一起,并接在系统时钟端,只有当时钟脉冲到来时,电路的状态才能改变。改变后的状态将一直保持到下一个时钟脉冲的到来,此时无论外部输入x 有无变化,状态表中的每个状态都是稳定的。
异步时序逻辑电路的特点:电路中除可以使用带时钟的触发器外,还可以使用不带时钟的触发器和延迟元件作为存储元件,电路中没有统一的时钟,电路状态的改变由外部输入的变化直接引起。
同步电路:存储电路中所有触发器的时钟输入端都接同一个时钟脉冲源,因而所有触发器的状态的变化都与所加的时钟脉冲信号同步。
异步电路:电路没有统一的时钟,有些触发器的时钟输入端与时钟脉冲源相连,只有这些触发器的状态变化与时钟脉冲同步,而其他的触发器的状态变化不与时钟脉冲同步。
同步复位是在时钟沿变化时,完成复位动作。
优点:
1)抗干扰能力高,可以提出复位信号中周期短于时钟周期的毛刺;
2)有利于静态时序分析工具的分析;
3)有利于基于周期的仿真工具的仿真。
缺点:
1)占用更多资源;
2)对复位信号的脉冲宽度有要求,由于线路上的延迟;可能需要多个时钟周期的复位脉冲的宽度,而且很难保证复位信号到达各个寄存器的时序;
3)同步复位依赖时钟,如果电路中时钟信号出现问题则无法复位。
异步复位是只要复位信号满足条件就完成复位动作。
优点:
1)不需要额外的逻辑资源,实现简单;
2)复位信号不依赖于时钟。
缺点:
1)复位信号易受外界干扰,并对电路内的毛刺敏感;
2)复位信号的随机性可能导致时序违规,也就是复位信号释放时在时钟有效沿附近,会使电路处于亚稳态。
建立时间:触发器在时钟上升沿到来之前,其数据输入端的数据必须保持不变的最小时间。
保持时间:触发器在时钟上升沿到来之后,其数据输入端的数据必须保持不变的最小时间。
①对于建立时间违例的解决办法
降低时钟频率,即增大时钟周期;
在时钟路径上加缓冲器(buffer),让时钟晚到来;
更换具有更小器件延迟的触发器;
组合逻辑优化或插入流水线,缩短关键路径。
②对于保持时间违例的解决办法
在数据路径上插入buffer;
更换具有更大器件延迟的触发器;
优化时钟路径,让时钟更早到来。
因为触发器内部数据的形成是需要一定的时间的,如果不满足建立和保持时间,触发器将进入亚稳态,进入亚稳态后触发器的输出将不稳定,在0和1之间变化,这时需要经过一个恢复时间,其输出才能稳定,但稳定后的值并不一定是你的输入值。这就是为什么要用两级触发器来同步异步输入信号。这样做可以防止由于异步输入信号对于本级时钟可能不满足建立保持时间而使本级触发器产生的亚稳态传播到后面逻辑中,导致亚稳态的传播。
假设第一级触发器的输入不满足其建立保持时间,它在第一个脉冲沿到来后输出的数据就为亚稳态,那么在下一个脉冲沿到来之前,其输出的亚稳态数据在一段恢复时间后必须稳定下来,而且稳定的数据必须满足第二级触发器的建立时间,如果都满足了,在下一个脉冲沿到来时,第二级触发器将不会出现亚稳态,因为其输入端的数据满足其建立保持时间。同步器有效的条件:第一级触发器进入亚稳态后的恢复时间+第二级触发器的建立时间
时序约束主要包括周期约束,偏移约束,静态时序路径约束三种。通过附加时序约束可以综合布线工具调整映射和布局布线,使设计达到时序要求。
时序分析需要关心的路径有以下几点:
从输入到输出的路径;
从输入到寄存器的路径;
从寄存器到输出的路径;
从寄存器到寄存器的路径;
附加时序约束的一般策略是先附加全局约束,然后对快速和慢速例外路径附加专门约束。附加全局约束时,首先定义设计的所有时钟,对各时钟域内的同步元件进行分组,对分组附加周期约束,然后对FPGA/CPLD输入输出PAD附加偏移约束、对全组合逻辑的PAD TO PAD路径附加约束。附加专门约束时,首先约束分组之间的路径,然后约束快、慢速例外路径和多周期路径,以及其他特殊路径。
亚稳态是指触发器无法在某个规定时间段内达到一个可确认的状态。当一个触发器进入亚稳态时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态,并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。
解决方法:1 降低系统时钟频率;2 用反应更快的触发器;3 引入同步机制,防止亚稳态传播(可以采用前面说的加两级触发器);4 改善时钟质量,用边沿变化快速的时钟信号。
串行接口是数据线一根线,通过串行协议传输数据,比如uart
并行接口是一个数据在多根数据线并行传输,比如rgb888、rgb565等等
在组合逻辑中,由于门的输入信号通路中经过了不同的延时,导致到达该门的时间不一致叫竞争。产生毛刺叫冒险。
(1)加封锁脉冲
在输入信号产生竞争冒险的时间内,引入一个脉冲将可能产生尖峰干扰脉冲的门封锁住。封锁脉冲应在输入信号转换前到来,转换结束后消失。
(2)选通脉冲
当电路输出端达到新的稳定状态之后,引人选通脉冲,从而使输出信号是正确的逻辑信号而不包含干扰脉冲。
(3)接入滤波电容
由于尖峰干扰脉冲的宽度一般都很窄,在可能产生尖峰干扰脉冲的门电路输出端与地之间接入一个容量为几十皮法的电容就可吸收掉尖峰干扰脉冲。
(4)用格雷码替代二进制代码
功能定义/器件选型;设计输入;功能仿真;综合优化;综合后仿真;布局布线;时序仿真;版级仿真与验证;芯片编程与调试
1、latch由电平触发,非同步控制。在使能信号有效时latch相当于通路,在使能信号无效时latch保持输出状态。DFF由时钟沿触发,同步控制。
2、latch容易产生毛刺(glitch),DFF则不易产生毛刺。
3、如果使用门电路来搭建latch和DFF,则latch消耗的门资源比DFF要少,这是latch比DFF优越的地方。所以,在ASIC中使用latch的集成度比DFF高,但在FPGA中正好相反,因为FPGA中没有标准的latch单元,但有DFF单元,一个LATCH需要多个LE才能实现。
(1)电容(负载电容、自载电容、连线电容)较小,漏端扩散区的面积应尽可能小。输入电容要考虑: (1)Cgs 随栅压而变化(2)密勒效应(3)自举效应
(2)加大晶体管的尺寸(驱动能力),使晶体管的等效导通电阻(输出电阻)较小。但这同时加大自载电容和负载电容(下一级晶体管的输入电容)。
(3)提高电源电压,提高电源电压可以降低延时,即用功耗换取性能但超过一定程度后改善有限。电压过高会引起可靠性问题(氧化层击穿、热电子等)。
Transition Time(转换时间):上升时间:从10%Vdd上升到90%Vdd的时间,下降时间L从90%Vdd下降到10%dd的时间。上升时间和下降时间统称为Transition Time,也有定义为20%到80%。
Propagation Delay(传播延时):在输入信号变化到50%Vdd到输出信号变化到50%Vdd之间的时间。
高阻态:电路的一种输出状态,既不是高电平也不是低电平,如果高阻态再输入下一级电路的话,对下级电路无任何影响,可以理解为断路,不被任何东西所驱动,也不驱动任何东西。
不定态:如果输入信号不满足建立时间和保持时间,那么电路就会进入不定态。在不定态中,你希望采到的信号为高电平,但实际你采到的可能是低电平也可能是高电平,无法预估。若采到的是低电平,该低电平会对后续的电路产生影响(因为输入错误),这个影响是不可逆的,也就是说不定态可能会引发后续电路不可逆的错误。
施密特触发器有两个稳定状态,但与一般触发器不同的是,施密特触发器采用电位触发方式,其状态由输入信号电位维持;对于负向递减和正向递增两种不同变化方向的输入信号,施密特触发器有不同的阈值电压。
CMOS电路中,存在寄生的三极管PNPN,它们相互影响在VDD与GND间产生一低阻通路,形成大电流,烧坏芯片这就是闩锁效应
Latch up发生的条件:环路增益大于1;两个BJT均导通;电源提供的最大电流大于PNPN导通所需的维持电流IH
Latch up触发原因:
1.VDD变化导致Nwell和Psub间寄生电容产生足够电流,进而触发Latch up
2. 当I/O信号变换超过VDD-GND范围,会有较大电流产生,也会触发Latch up
3. ESD静电泄放时,会从保护电路中引入载流子到阱和衬底中,也会触发Latch up
4. 负载过大,VDD或GND突变时也可能会触发Latch up
5. 阱侧面漏电流过大,也会触发Latch up
避免闩锁的方法就是要减小衬底和N阱的寄生电阻,使寄生的三极管不会处于正偏状态。
wire型数据常用来表示以assign关键字指定的组合逻辑信号,模块的输入输出端口类型都默认为wire型,wire相当于物理连线,默认初始值是z。
reg型表示的寄存器类型,用于always模块内被赋值的信号,必须定义为reg型,代表触发器,常用于时序逻辑电路,reg相当于存储单元,默认初始值是x。
1. 什么是FIFO
FIFO(First In First Out),即先进先出队列。FIFO存储器是一个先入先出的双口缓冲器,即第一个进入其内的数据第一个被移出,其中一个是存储器的输入口,另一个口是存储器的输出口。对于单片FIFO来说,主要有两种结构:触发导向结构和零导向传输结构。触发导向传输结构的FIFO是由寄存器阵列构成的,零导向传输结构的FIFO是由具有读和写地址指针的双口RAM构成。
FPGA 使用的 FIFO 一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存,或者高速异步数据的交互也即所谓的跨时钟域信号传递。它与 FPGA 内部的 RAM 和 ROM 的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像 RAM 和 ROM 那样可以由地址线决定读取或写入某个指定的地址。
根据 FIFO 工作的时钟域,可以将 FIFO 分为同步 FIFO 和异步 FIFO。同步 FIFO 是指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作。异步 FIFO 是指读写时钟不一致,读写时钟是互相独立的。当被配置为同步 FIFO 时,只使用 wr_clk,所有的输入输出信号都同步于 wr_clk 信号。而当被配置为异步 FIFO 时,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟 wr_clk,所有与读相关的信号都是同步于读时钟 rd_clk。
FIFO可用于以下目的:
跨时钟域
在将数据发送到芯片外之前将其缓冲(例如,发送到DRAM或SRAM)
缓冲数据以供软件在以后查看
存储数据以备后用
FIFO的参数
宽度:一次读写操作的数据位
深度:可以存储的 N 位数据的数目(宽度为 N)
满标志: full。FIFO 已满时,由 FIFO 的状态电路送出的信号,阻止 FIFO 写操作
空标志: empty。FIFO 已空时,由 FIFO 的状态电路送出的信号,阻止 FIFO 读操作
读时钟:读操作所遵循的时钟
写时钟:写操作所遵循的时钟
FPGA设计的总功耗由三部分功耗组成:1. 芯片静态功耗;2. 设计静态功耗;3. 设计动态功耗。
1、芯片静态功耗:FPGA在上电后还未配置时,主要由晶体管的泄漏电流所消耗的功耗
2、设计静态功耗:当FPGA配置完成后,当设计还未启动时,需要维持I/O的静态电流,时钟管理和其它部分电路的静态功耗
3、设计动态功耗:FPGA内设计正常启动后,设计的功耗;这部分功耗的多少主要取决于芯片所用电平,以及FPGA内部逻辑和布线资源的占用。
所以,前两部分的功耗取决于FPGA芯片及硬件设计本身,很难有较大的改善。可以优化是第3部分功耗:设计动态功耗,而且这部分功耗占总功耗的90%左右,因此所以降低设计动态功耗是降低整个系统功耗的关键因素
降低功耗带来的好处
①低功耗的器件可以实现更低成本的电源供电系统 。另外 ,更简单的电源系统意味着更少的元件和更小的PCB 面积 ,同样可以降低成本 。
②更低的功耗引起的结温更小 ,因此可以防止热失控 ,可以少用或不用散热器 ,如散热风扇 、散热片等 。
③降低功耗可以降低结温 ,而结温的降低可以提高系统的可靠性 。另外 ,较小的风扇或不使用风扇可以降低EMI。
④延长器件的使用寿命。器件的工作温度每降低10 ℃,使用寿命延长 1 倍。所以对于 FPGA 而言 ,降低功耗的根本在于直接提高了整个系统的性能和质量 ,并减小了体积 ,降低了成本 ,对产品有着非常大的促进作用 。
如何降低FPGA功耗
算法优化;资源使用效率优化;
AHB(高级高性能总线)总线规范是AMBA(高级处理器总线架构)总线规范的一部分,AMBA总线规范是ARM公司提出的总线规范,AHB用于高性能、高时钟频率的系统结构。 AHB总线由Master、Slave和Infrastructure构成。Infrastructure由arbiter、数据多路、地址控制多路、译码器构成。它可以将微控制器(CPU)、高带宽的片上RAM、高带宽的外部存储器接口、DMA总线主机、各种拥有AHB接口的控制器等等连接起来构成一个独立的完整的SOC系统
总线操作
有需要占用总线的Master向arbiter发出请求,arbiter授权给指定的master。任一时间周期只有一个master可以接入总线,对其指定的slave进行读写操作。
AHB总线操作概括
在一次AMBA AHB 传输开始之前总线主机必须被授予访问总线。这个过程开始于总线主机向仲裁器断言一个请求信号。仲裁器指示主机何时能够被授予使用总线。被授权的总线主机通过驱动地址和控制信号来发起一次 AMBA AHB 传输。这些信号提供关于地址、方向和传输宽度的信息,以及表示传输类型是否为一次突发传输的部分。
允许有两种不同类型的突发传输:
增量突发,在地址边界处不回环;
回环突发,在特定的地址边界上回环。
写数据总线用来将数据从主机传输到从机上,而读数据总线用来将数据从从机传输到主机上。
每次传输包含:
一个地址和控制周期;
一个或多个数据周期;
只要FPGA设计中的所有资源不全属于一个时钟域,那么就可能存在跨时钟域问题,因为异步逻辑其实也可以看做一种特殊的跨时钟域问题。发生跨时钟域问题的必要条件是不同时钟域之间存在信息交互。
解决:两级采样法;异步双口RAM;握手法;异步FIFO法;
多时钟域的设计中,对于信号跨时域的处理这里可以采用乒乓操作的方法来进行。乒乓操作的处理流程为:输入数据流通过‘输入数据选择单元”将数据流等时分配到两个数据缓冲区,数据缓冲模块可以为任何存储模块,比较常用的存储单元为双口RAM(DPRAM)、单口RAM(SPRAM)、FIFO等。
不同的时钟域之间信号通信时需要进行同步处理,这样可以防止新时钟域中第一级触发器的亚稳态信号对下级逻辑造成影响,其中对于单个控制信号可以用两级同步器,如电平、边沿检测和脉冲,对多位信号可以用FIFO,双口RAM,握手信号等。
3种方法跨时钟域处理方法:打两拍;异步双口RAM;格雷码转换。
管脚位置约束:set_property PAKAGE_PIN “管脚编号” [get_ports “端口名称”]
任务与函数主要有以下四点不同:
l 函数只能与主模块共用一个仿真时间单位,而任务定义自己的仿真时间单位。
l 函数不能启动任务,任务可以启动其他任务和函数。
l 函数至少要有一个输入变量,而任务可以没有或有多任何类型的变量。
l 函数返回一个值,而任务不返回值。
基于SV的验证方法学(可以简单理解为验证平台的框架)中,目前主要有以下三种:
VMM(Verification Methodology Manual):Synopsys在2006年推出的,集成了寄存器解决方案RAL(Register Abstraction Layer)。
OVM(Open Verification Methodlogy):Candence和Mentor在2008年推出的,从一开始就是开源的。引入了factory机制,功能非常强大,但是没有寄存器解决方案,这是他最大的短板。
UVM(Universal Verification Methodology):正式版是在2011年2月由Accellera推出的,得到了Synopsys,Mentor和Candence的支持。UVM几乎完全继承了OVM,同时由采纳了Synopsys在VMM中的寄存器解决方案RAL。
UVM是一个以SystemVerilog为主体的验证平台开发框架,验证工程师利用其可重用组件可以构建具有标准化层次结构和接口的功能验证环境。
UVM是一个库,在这个库中,几乎所有的东西都是使用类(class)来实现的。类是面向对象编程语言中最伟大的发明之一,是面向对象的精髓所在。
优势:
第一种自动化方法和第二种自动化类库的集合
贯穿于验证平台的可重用性
即插即用的验证IP
通用的验证平台开发
供应商和模拟器独立
高智能的验证平台(即从预先设计的覆盖计划中产生合法的激励)
支持CDV(覆盖率驱动)验证
支持CRV(受限随机)验证
UVM在Accelerate System Initiative下标准化
支持寄存器模型
driver:向sequencer申请sequence_item数据包transaction),并将包里的信息按照总线协议规定驱动到DUT的端口上;
sequencer:组织管理sequence,driver申请数据时,它就把sequence生成的sequence_item发给driver;
scoreboard:比较reference model和monitor分别发送来的数据,根据比较结果判断DUT是否正确工作;
monitor:从DUT接收数据,并将其转成transaction级别的sequence_item,发送给scoreboard,供其比较;
reference model:模仿DUT,完成与DUT相同的功能,为scoreboard提供判断标准;
agent:将sequencer、driver和monitor封装在一起(UVM_ACTIVE/UVM_PASSIVE、两种模式),agent模块的使用提高了代码的可重用性;
env:将平台上的component组件封装在一起,并配置各个组件间的通信端口,实现一个环境多个用例。运行不同用例时,在其中实例化env即可;
base_test(uvm_test_top):例化和配置共同的组件和env,其他的test继承base_test,并进行针对性的修改;
sequence:(不属于验证平台的任一部分)产生激励内容(transaction)。通过sequence中的body任务创建(随机化)事务,并发送给sequence。
由于软件环境中对象的生成是动态的,验证环境的组件也需要UVM提供底层功能完成对象的创建和访问。
UVM需提供环境上下层次中创建、连接和运行组件的顺序控制方法,只有在底层机制上有效地保证这一点,才会避免可能发生的句柄悬空问题。
组件通信中,UVM提供功能更丰富的TLM(Transaction level model)接口,可以保证相邻组件的通信不再通过显式句柄引用,而是独立于组件的通信方式。
对于测试序列(sequence)的生成和传输也是利用了TLM传输在sequence和driver之间完成。对于不同sequence的发送顺序控制,需要实现sequence之间的灵活调度。
为了便于验证环境的调试,UVM的报告机制可将来自不同组件、不同级别的信息并且加以过滤,最终生成测试报告。
核心基类提供最底层的支持,包括一些基本方法例如拷贝、创建、比较和打印。在核心类之上发展了支持UVM特性的各个相关的类群。
工厂类提供注册环境组件、创建组件和覆盖组件类型的方法。
事务类和序列类用来规定在TLM(Transaction Level Model)传输管道中的数据类型和数据生成方式。
环境组件类是构成验证结构的主要部分,组件之间的嵌套关系通过层层例化和连接形成结构层次关系。
事务接口类和通信管道类共同实现组件之间的通信和存储。
线程同步类要比SV自身的同步方法更方便,同步时包含的信息更多。
信息报告类使得从UVM环境中报告的信息一致规范化,便于整体的控制和过滤。
寄存器模型类用来完成对寄存器和存储的建模、访问和验证。
或者我们已经拥uvm_object,为什么我们需要uvm_component这种实际派生自的uvm_object类?(比特大陆、寒武纪面试题)
uvm_component:
准静态实体(在构建阶段之后,它在整个模拟过程中可用)
始终连接到给定硬件(DUT接口)或TLM端口
具有用于控制仿真行为的phase机制
配置组件拓扑结构
uvm_object:
动态实体(在需要时创建,从一个组件转移到另一个组件然后取消引用)
不连接到给定的硬件或任何TLM端口
没有phase机制
(寒武纪、乐鑫面试题)
只有build_phase是自顶而下的,除了run_phase,其他phased都是自底而上的。run_phase自顶而下工作,可以配置测试工作台层次结构,因此我们需要在构建叶子之前构建分支。
connect_phase旨在用于在组件之间建立TLM类型的连接,这就是它在构建阶段之后发生的原因。它自底而上工作,以便在设计层次结构中获得正确的实现,如果从上到下工作,这是不可能的。
只有run_phase(及其并行的12个phase)是task phase(消耗仿真时间的phase),其他phase都是function phase(不消耗仿真时间的非阻塞类型phase)。
(比特大陆面试题)
如前所述,run_phase作为task phase,剩下的都是function phase。run_phase将从仿真(run)开始到仿真结束执行。run_phase非常耗时,测试用例产生激励正是在run_phase中实现。
通过在顶层模块中调用run test(“test1”)来启动UVM phase。当调用run test()方法时,它首先会创建一个test_top的对象然后调用所有phase。
在top模块中写run test(),即不要在变量中提供任何内容。然后在命令行中添加:+UVM_TESTNAME =test1,启动测试用例名为test1的测试用例。
(乐鑫面试题)
模块是在仿真期间始终存在的静态对象。
class是一个动态对象,因为它们可以在仿真的生命周期中来去。
特别指出:interface是静态对象,因此只能用于top、模块等静态对象中,driver为动态的对像类,因此driver等类中使用的为virtual interface,通过虚的指针指向实际的interface。
(比特大陆面试题)
uvm_config_db是一个参数化类,用于将不同类型的参数配置到uvm数据库中,如此它可以被任何较低级别层次结构中的组件使用。
uvm_config_db是一个构建在uvm_resource_db之上的便利层,但这种便利非常重要。特别是,uvm_resource_db使用“最后写入获胜”方法。另一方面,uvm_config_db通过end_of_elaboration查看层次结构中的内容,因此“父获胜”。一旦启动start_of_simulation,config_db就会变成“最后写入获胜”。
uvm_config_db#(T)中的所有函数都是静态的,因此必须使用::运算符调用它们。uvm_config_db#(T)是从uvm_resource_db#(T)扩展而来的,所以它是uvm_resource_db#(T)的子类。