系统的比较,与大家共享:
尽管FPGA和CPLD都是可编程ASIC器件,有很多共同特点,但由于CPLD和FPGA结构上的差异,具有各自的特点:
①CPLD更适合完成各种算法和组合逻辑,FP GA更适合于完成时序逻辑。换句话说,FPGA更适合于触发器丰富的结构,而CPLD更适合于触发器有限而乘积项丰富的结构。
②CPLD的连续式布线结构决定了它的时序延迟是均匀的和可预测的,而FPGA的分段式布线结构决定了其延迟的不可预测性。
③在编程上FPGA比CPLD具有更大的灵活性。CPLD通过修改具有固定内连电路的逻辑功能来编程,FPGA主要通过改变内部连线的布线来编程;FP GA可在逻辑门下编程,而CPLD是在逻辑块下编程。
④FPGA的集成度比CPLD高,具有更复杂的布线结构和逻辑实现。
⑤CPLD比FPGA使用起来更方便。CPLD的编程采用E2PROM或FASTFLASH技术,无需外部存储器芯片,使用简单。而FPGA的编程信息需存放在外部存储器上,使用方法复杂。
⑥CPLD的速度比FPGA快,并且具有较大的时间可预测性。这是由于FPGA是门级编程,并且CLB之间采用分布式互联,而CPLD是逻辑块级编程,并且其逻辑块之间的互联是集总式的。
⑦在编程方式上,CPLD主要是基于E2PROM或FLASH存储器编程,编程次数可达1万次,优点是系统断电时编程信息也不丢失。CPLD又可分为在编程器上编程和在系统编程两类。FPGA大部分是基于SRAM编程,编程信息在系统断电时丢失,每次上电时,需从器件外部将编程数据重新写入SRAM中。其优点是可以编程任意次,可在工作中快速编程,从而实现板级和系统级的动态配置。
⑧CPLD保密性好,FPGA保密性差。
⑨一般情况下,CPLD的功耗要比FPGA大,且集成度越高越明显。
随著复杂可编程逻辑器件(CPLD)密度的提高,数字器件设计人员在进行大型设计时,既灵活又容易,而且产品可以很快进入市场。许多设计人员已经感受到CPLD容易使用、时序可预测和速度高等优点,然而,在过去由于受到CPLD密度的限制,他们只好转向FPGA和ASIC。现在,设计人员可以体会到密度高达数十万门的CPLD所带来的好处。
CPLD结构在一个逻辑路径上采用1至16个乘积项,因而大型复杂设计的运行速度可以预测。因此,原有设计的运行可以预测,也很可靠,而且修改设计也很容易。CPLD在本质上很灵活、时序简单、路由性能极好,用户可以改变他们的设计同时保持引脚输出不变。与FPGA相比,CPLD的I/O更多,尺寸更小。
如今,通信系统使用很多标准,必须根据客户的需要配置设备以支持不同的标准。CPLD可让设备做出相应的调整以支持多种协议,并随著标准和协议的演变而改变功能。这为系统设计人员带来很大的方便,因为在标准尚未完全成熟之前他们就可以著手进行硬件设计,然后再修改代码以满足最终标准的要求。CPLD的速度和延迟特性比纯软件方案更好,它的NRE费用低於ASIC,更灵活,产品也可以更快入市。CPLD可编程方案的优点如下:
●逻辑和存储器资源丰富(Cypress Delta39K200的RAM超过480 Kb)
●带冗余路由资源的灵活时序模型
●改变引脚输出很灵活
●可以装在系统上后重新编程
●I/O数目多
●具有可保证性能的集成存储器控制逻辑
●提供单片CPLD和可编程PHY方案
由于有这些优点,设计建模成本低,可在设计过程的任一阶段添加设计或改变引脚输出,可以很快上市
CPLD的结构
CPLD是属於粗粒结构的可编程逻辑器件。它具有丰富的逻辑资源(即逻辑门与寄存器的比例高)和高度灵活的路由资源。CPLD的路由是连接在一起的,而FPGA的路由是分割开的。FPGA可能更灵活,但包括很多跳线,因此速度较CPLD慢。
CPLD以群阵列(array of clusters)的形式排列,由水平和垂直路由通道连接起来。这些路由通道把信号送到器件的引脚上或者传进来,并且把CPLD内部的逻辑群连接起来。
CPLD之所以称作粗粒,是因为,与路由数量相比,逻辑群要大得到。CPLD的逻辑群比FPGA的基本单元大得多,因此FPGA是细粒的。
CPLD的功能块
CPLD最基本的单元是宏单元。一个宏单元包含一个寄存器(使用多达16个乘积项作为其输入)及其它有用特性。
因为每个宏单元用了16个乘积项,因此设计人员可部署大量的组合逻辑而不用增加额外的路径。这就是为何CPLD被认为是“逻辑丰富”型的。
宏单元以逻辑模块的形式排列(LB),每个逻辑模块由16个宏单元组成。宏单元执行一个AND操作,然后一个OR操作以实现组合逻辑。
每个逻辑群有8个逻辑模块,所有逻辑群都连接到同一个可编程互联矩阵。
每个群还包含两个单端口逻辑群存储器模块和一个多端口通道存储器模块。前者每模块有8,192b存储器,后者包含4,096b专用通信存储器且可配置为单端口、多端口或带专用控制逻辑的FIFO。
CPLD有什麽好处?
I/O数量多
CPLD的好处之一是在给定的器件密度上可提供更多的I/O数,有时甚至高达70%。
时序模型简单
CPLD优于其它可编程结构之处在于它具有简单且可预测的时序模型。这种简单的时序模型主要应归功于CPLD的粗粒度特性。
CPLD可在给定的时间内提供较宽的相等状态,而与路由无关。这一能力是设计成功的关键,不但可加速初始设计工作,而且可加快设计调试过程。
粗粒CPLD结构的优点
CPLD是粗粒结构,这意味著进出器件的路径经过较少的开关,相应地延迟也小。因此,与等效的FPGA相比,CPLD可工作在更高的频率,具有更好的性能。
CPLD的另一个好处是其软件编译快,因为其易于路由的结构使得布放设计任务更加容易执行。
细粒FPGA结构的优点
FPGA是细粒结构,这意味著每个单元间存在细粒延迟。如果将少量的逻辑紧密排列在一起,FPGA的速度相当快。然而,随著设计密度的增加,信号不得不通过许多开关,路由延迟也快速增加,从而削弱了整体性能。CPLD的粗粒结构却能很好地适应这一设计布局的改变。
灵活的输出引脚
CPLD的粗粒结构和时序特性可预测,因此设计人员在设计流程的后期仍可以改变输出引脚,而时序仍保持不变。
新的CPLD封装
CPLD有多种密度和封装类型,包括单芯片自引导方案。自引导方案在单个封装内集成了FLASH存储器和CPLD,无须外部引导单元,从而可降低设计复杂性并节省板空间。在给定的封装尺寸内,有更高的器件密度共享引脚输出。这就为设计人员提供了“放大”设计的便利,而无须更改板上的引脚输出。
/<br>
经常会看到在状态机设计中别人使用各种不同的编码方式,那么一般情况下,这种编码方式的选择依据是什么?
我们知道,在数字逻辑设计中最常用的有三种编码方式:二进制,格雷码 Gray,独热编码One-hot One hot 编码使用一组码元,每一个码元仅有1bit有效,例如
IDLE = 0001,
WRITE = 0010,
READ = 0100,
WAIT = 1000
这种编码的译码部分可以最简,因此可以总结出One-hot编码的特点:
组合逻辑最少,触发器最多,工作时钟频率可以做到最高。
FPGA 的一个最小结构单元(CLB/LE)中含有查找表(实现组合逻辑)和DFF(实现时序逻辑),布局布线最好的结果是同一个结构单元中的查找表和DFF都使用,但是大部分情况是仅使用其中一种资源,这样另外的资源就是闲置而浪费。而CPLD中DFF资源本来就很少,由此可见One-hot编码更适合于 FPGA设计,而不适合CPLD设计,在CPLD中应该选择二进制编码。
IC设计中,应该综合考虑。因为One-hot编码使用DFF会大大增加设计面积(die size),因此在时序可以满足的条件下尽可能使用二进制编码。就面积与速度的折中考虑来说Gray码是最好的选择,当然Gray码还有其他很多好的特性,暂时不属于这次讨论的范畴。一般的综合工具对状态机进行综合时都可以让用户对这三种编码进行选择。基本依据就以上所说。
二进制与格雷码之间的转换
自然二进制码转换成二进制格雷码,其法则是保留自然二进制码的最高位作为格雷码的最高位,而次高位格雷码为二进制码的高位与次高位相异或,而格雷码其余各位与次高位的求法相类似
二进制格雷码转换成自然二进制码,其法则是保留格雷码的最高位作为自然二进制码的最高位,而次高位自然二进制码为高位自然二进制码与次高位格雷码相异或,而自然二进制码的其余各位与次高位自然二进制码的求法相类似
通过减少寄存器间的逻辑延时来提高工作频率,或通过流水线设计来优化数据处理时的数据通路来满足高速环境下FPGA或CPLD中的状态机设计要求。本文给出了采用这些技术的高速环境状态机设计的规范及分析方法和优化方法,并给出了相应的示例。
为了使FPGA或CPLD中的状态机设计满足高速环境要求,设计工程师需要认识到以下几点:寄存器资源和逻辑资源已经不是问题的所在,状态机本身所占用的FPGA或CPLD逻辑资源或寄存器资源非常小;状态机对整体数据流的是串行操作,如果希望数据处理的延时非常小,就必须提高操作的并行程度,压缩状态机中状态转移的路径长度;高速环境下应合理分配状态机的状态及转移条件。本文将结合实际应用案例来说明。
状态机设计规范
1. 使用一位有效的方式进行状态编码
状态机中状态编码主要有三种:连续编码(sequential encoding)、一位有效(one-hot encoding)方式编码以及不属于这两种的编码。例如,对于一个5个状态(State0~State4)的状态机,连续编码方式状态编码为:State0-000、State1-001、State2-010、State3-011、State4-100。一位有效方式为下为:State0-00001、State1-00010、State2-00100、State3-01000、State4-10000。对于自行定义的编码则差别很大,例如试图将状态机的状态位直接作为输出所需信号,这可能会增加设计难度。
使用一位有效编码方式使逻辑实现更简洁,因为一个状态只需要用一位来指示,而为此增加的状态寄存器数目相对于整个设计来说可以忽略。一位有效至少有两个含义:对每个状态位,该位为1对应唯一的状态,判断当前状态是否为该状态,只需判断该状态位是否为1;如果状态寄存器输入端该位为1,则下一状态将转移为该状态,判断下一状态是否为该状态,只需判断表示下一状态的信号中该位是否为1。
2. 合理分配状态转移条件
在状态转移图中,每个状态都有对应的出线和入线,从不同状态经不同的转移条件到该状态的入线数目不能太多。以采用与或逻辑的CPLD设计来分析,如果这样的入线太多则将会需要较多的乘积项及或逻辑,这就需要更多级的逻辑级联来完成,从而增加了寄存器间的延迟;对于FPGA则需要多级查找表来实现相应的逻辑,同样会增加延迟。状态机的应用模型如图1所示。
状态机设计的分析方法
状态机设计的分析方法可以分为两种:一种是流程处理分析,即分析数据如何分步处理,将相应处理的步骤依次定为不同状态,该方法能够分析非常复杂的状态机,类似于编写一个软件程序的分析,典型设计如读写操作和数据包字节分析;另一种方法是关键条件分析,即根据参考信号的逻辑条件来确定相应的状态,这样的参考信号如空或满指示、起始或结束、握手应答信号等。这两种分析方法并没有严格的界限,在实际的状态机设计分析时往往是这两种方法结合使用。下面分别说明这两种分析方法。
1. 流程处理分析
例如,在一个读取ZBT SRAM中数据包的设计中,要根据读出的数据中EOP(End of Packet)信号是否为1来决定一个包的读操作是否结束,由于读取数据的延后,这样就会从ZBT SRAM中多读取数据,为此可以设计一个信号VAL_out来过滤掉多读的数据。
根据数据到达的先后及占用的时钟周期数,可以设计如图2所示的状态机(本文设定:文字说明及插图中当前状态表示为s_State[n:0],为状态寄存器的输出;下一状态next_State[n:0],为状态寄存器的输入;信号之间的逻辑关系采用Verilog语言(或C语言)中的符号表示;#R表示需要经过一级寄存器,输出信号对应寄存器的输出端)。该状态机首先判断是否已经到达包尾,如果是,则依次进入6个等待状态,等待状态下的数据无效,6个等待状态结束后将正常处理数据。
2. 关键条件分析
图3为一个路由器线卡高速数据包分发处理的框图,较高速率的数据包经过分发模块以包为单位送往两个较低速率数据通路(即写入FIFO1或FIFO2)。
对于分发模块设计,关键参考信号是EOP及快满信号AF1、AF2,参考EOP可以实现每次处理一个包,参考AF1、AF2信号可以决定相应的包该往哪个FIFO中写入。分发算法为:FIFO1未满(AF1=0),数据包将写入FIFO1;如果FIFO1将满且FIFO2未满(AF1=1,且AF2=0),则下一数据包将写入FIFO2;如果FIFO1、FIFO2都将满(AF1=1且AF2=1),则进入丢包状态。状态机描述如图4所示:UseFifo1状态下数据包将写入FIFO1,UseFifo2状态下数据包将写入FIFO2,丢包状态下数据包被丢弃,提供丢包计数使能DropCountEnable。
状态机的进一步优化
1. 利用一位有效编码方式HSPACE=12 ALT="图2:对从ZBT RAM已读出的包数据的过滤处理的状态机。">
如前所述,状态机的工作频率跟状态机中各个状态对应的不同转移条件的入线数目有关。如果到一个状态的转移条件相同但入线数非常多,其逻辑实现很可能并不复杂。在一位有效编码方式下,对于某个状态,如果其他所有状态经相同的转移条件到该状态,那么其逻辑实现可以很好地化简。
例4:一位有效编码方式下状态位s_State[n:0]中,
s_State[1] | s_State[2] | ... | s_State[n]=1与 s_State[0]=1等价,那么
next_State[0]=(s_State[0]&S) | (s_State[1]&T) | (s_State[2]&T) | ... | (s_State[n]) 可以化简为:
next_State[0]=(s_State[0]&S) | ((~s_State[0])&T),右端输入信号数目大大减少。
2. 利用寄存器的使能信号
多数FPGA或CPLD寄存器提供使能端,如果所有的状态机转移必须至少满足某个条件,那么这个条件可以通过使能信号连接实现,从而可以降低寄存器输入端的逻辑复杂度。如上例中不同状态间转移必须以EOP为1作为前提,因而可以将该信号作为使能信号来设计。
3. 结合所选FPGA或CPLD内部逻辑单元结构编写代码
以Xilinx FPGA为例,一个单元内2个4输入查找表及相关配置逻辑可以实现5个信号输入的最复杂的逻辑,或8~9个信号的简单逻辑(例如全与或者全或),延时为一级查找表及配置逻辑延时;如果将相邻单元的4个4输入查找表输出连接到一个4输入查找表,那么可以实现最复杂的6输入逻辑,此时需要两级查找表延时及相关配置逻辑延时。更复杂的逻辑需要更多的级连来实现。针对高速状态机的情况,可以尽量将状态寄存器输入端的逻辑来源控制在7个信号以内,从而自主控制查找表的级连级数,提高设计的工作频率。
4. 通过修改状态机
如果一个状态机达不到工作频率要求,则必须根据延时最大路径修改设计,通常的办法有:改变状态设置,添加新状态或删除某些状态,简化转移条件及单个状态连接的转移数目;修改转移条件设置,包括改变转移条件的组合,以及将复杂的逻辑改为分级经寄存器输出由寄存器信号再形成的逻辑,后者将会改变信号时序,因而可能需要改变状态设置。
5. 使用并行逻辑
很多情况下要参考的关键信号可能非常多,如果参考这些关键信号直接设计状态机所得到的结果可能很复杂,个别状态的出线或入线将会非常多,因而将降低工作频率。可以考虑通过设计并行逻辑来提供状态机的关键信号以及所需的中间结果,状态机负责维护并行逻辑以及产生数据处理的流程。并行逻辑应分级设计,级间为寄存器,从而减少寄存器到寄存器的延时。
图5为一个使用并行逻辑的状态机,该设计用于使用单一数据总线将FIFO1~4中的数据发送到4个数据通路上去,该设计中并行逻辑产生每次操作时的通路及FIFO选择结果,状态机负责控制每次操作的流程:在“Idle”状态下,如果FIFO1~4中有数据包供读取,则进入“Schedule”状态;获得调度结果后“Schedule”经过一个“Wait”状态,然后进入“ReadData”状态读取数据,同时开始计数,计数到达所指定数值或者读到数据包尾时进入空闲状态“Idle”,依次循环下去。
流水线设计
流水线(Pipelining)设计是将一个时钟周期内执行的逻辑操作分成几步较小的操作,并在较高速时钟下完成。图6a中逻辑被分为图6b中三小部分,如果它的Tpd为T,则该电路最高时钟频率为1/T,而在图6b中假设每部分的Tpd为T/3,则其时钟频率可提高到原来的3倍,因而单位时间内的数据流量可以达到原来的三倍。代价是输出信号相对于输入滞后3个周期,时序有所改变(图6b中输出信号的总延时与图6a中一样,但数据吞吐量提高了),同时增加了寄存器资源,而FPGA具有丰富的寄存器资源。
本文所强调的通过减少寄存器间的逻辑延时来提高状态机的工作频率,与流水线设计的出发点一样,不同的是流水线所强调的是数据处理时的数据通路优化,而本文所强调的是状态机中控制逻辑的优化
mealy&moore状态机典型程序
Verilog
// Example of a 5-state Mealy FSM
module mealy (data_in, data_out, reset, clock);
output data_out;
input [1:0] data_in;
input reset, clock;
reg data_out;
reg [2:0] pres_state, next_state;
parameter st0=3'd0, st1=3'd1, st2=3'd2, st3=3'd3, st4=3'd4;
// FSM register
always @ (posedge clock or negedge reset)
begin: statereg
if(!reset)// asynchronous reset
pres_state = st0;
else
pres_state = next_state;
end // statereg
// FSM combinational block
always @(pres_state or data_in)
begin: fsm
case (pres_state)
st0: case(data_in)
2'b00: next_state=st0;
2'b01: next_state=st4;
2'b10: next_state=st1;
2'b11: next_state=st2;
endcase
st1: case(data_in)
2'b00: next_state=st0;
2'b10: next_state=st2;
default: next_state=st1;
endcase
st2: case(data_in)
2'b0x: next_state=st1;
2'b1x: next_state=st3;
endcase
st3: case(data_in)
2'bx1: next_state=st4;
default: next_state=st3;
endcase
st4: case(data_in)
2'b11: next_state=st4;
default: next_state=st0;
endcase
default: next_state=st0;
endcase
end // fsm
// Mealy output definition using pres_state w/ data_in
always @(data_in or pres_state)
begin: outputs
case(pres_state)
st0: case(data_in)
2'b00: data_out=1'b0;
default: data_out=1'b1;
endcase
st1: data_out=1'b0;
st2: case(data_in)
2'b0x: data_out=1'b0;
default: data_out=1'b1;
endcase
st3: data_out=1'b1;
st4: case(data_in)
2'b1x: data_out=1'b1;
default: data_out=1'b0;
endcase
default: data_out=1'b0;
endcase
end // outputs
endmodule
Verilog
// Example of a 5-state Moore FSM
module moore (data_in, data_out, reset, clock);
output data_out;
input [1:0] data_in;
input reset, clock;
reg data_out;
reg [2:0] pres_state, next_state;
parameter st0=3'd0, st1=3'd1, st2=3'd2, st3=3'd3, st4=3'd4;
//FSM register
always @(posedge clock or negedge reset)
begin: statereg
if(!reset)
pres_state = st0;
else
pres_state = next_state;
end // statereg
// FSM combinational block
always @(pres_state or data_in)
begin: fsm
case (pres_state)
st0: case(data_in)
2'b00: next_state=st0;
2'b01: next_state=st4;
2'b10: next_state=st1;
2'b11: next_state=st2;
endcase
st1: case(data_in)
2'b00: next_state=st0;
2'b10: next_state=st2;
default: next_state=st1;
endcase
st2: case(data_in)
2'b0x: next_state=st1;
2'b1x: next_state=st3;
endcase
st3: case(data_in)
2'bx1: next_state=st4;
default: next_state=st3;
endcase
st4: case(data_in)
2'b11: next_state=st4;
default: next_state=st0;
endcase
default: next_state=st0;
endcase
end // fsm
// Moore output definition using pres_state only
always @(pres_state)
begin: outputs
case(pres_state)
st0: data_out=1'b1;
st1: data_out=1'b0;
st2: data_out=1'b1;
st3: data_out=1'b0;
st4: data_out=1'b1;
default: data_out=1'b0;
endcase
end // outputs
endmodule // Moore
使用状态机做时钟产生电路-独特却又最为精准(CPU设计中常用方法)
介绍一款时钟发生器--独特却又最为精准(CPU设计中常用方法)
时钟发生器 clkgen 利用外来时钟信号clk 来生成一系列时钟信号clk1、fetch、alu_clk 送往CPU的其他部件。其中fetch是外来时钟 clk 的八分频信号。利用fetch的上升沿来触发CPU控制器开始执行一条指令,同时fetch信号还将控制地址多路器输出指令地址和数据地址。clk1信号用作指令寄存器、累加器、状态控制器的时钟信号。alu_clk 则用于触发算术逻辑运算单元。
module clk_gen (clk,reset,clk1,clk2,clk4,fetch,alu_clk);
input clk,reset;
output clk1,clk2,clk4,fetch,alu_clk;
wire clk,reset;
reg clk2,clk4,fetch,alu_clk;
reg[7:0] state;
parameter S1 = 8'b00000001,
S2 = 8'b00000010,
S3 = 8'b00000100,
S4 = 8'b00001000,
S5 = 8'b00010000,
S6 = 8'b00100000,
S7 = 8'b01000000,
S8 = 8'b10000000,
idle = 8'b00000000;
assign clk1 = ~clk;
always @(negedge clk)
if(reset)
begin
clk2 <= 0;
clk4 <= 1;
fetch <= 0;
alu_clk <= 0;
state <= idle;
end
else
begin
case(state)
S1:
begin
clk2 <= ~clk2;
alu_clk <= ~alu_clk;
state <= S2;
end
S2:
begin
clk2 <= ~clk2;
clk4 <= ~clk4;
alu_clk <= ~alu_clk;
state <= S3;
end
S3:
begin
clk2 <= ~clk2;
state <= S4;
end
S4:
begin
clk2 <= ~clk2;
clk4 <= ~clk4;
fetch <= ~fetch;
state <= S5;
end
S5:
begin
clk2 <= ~clk2;
state <= S6;
end
S6:
begin
clk2 <= ~clk2;
clk4 <= ~clk4;
state <= S7;
end
S7:
begin
clk2 <= ~clk2;
state <= S8;
end
S8:
begin
clk2 <= ~clk2;
clk4 <= ~clk4;
fetch <= ~fetch;
state <= S1;
end
idle: state <= S1;
default: state <= idle;
endcase
end
endmodule
//--------------------------------------------------------------------------------
由于在时钟发生器的设计中采用了同步状态机的设计方法,不但使clk_gen模块的源程序可以被各种综合器综合,也使得由其生成的clk1、clk2、clk4、fetch、alu_clk 在跳变时间同步性能上有明显的提高,为整个系统的性能提高打下了良好的基础。
诸位.这样的时钟发生器无论在时序上还是功能上都是完美的,难怪一直在CPU设计中采用.
评论
查看更多