FPGA设计流程与规范.docx

上传人:b****3 文档编号:27264682 上传时间:2023-06-28 格式:DOCX 页数:89 大小:878.16KB
下载 相关 举报
FPGA设计流程与规范.docx_第1页
第1页 / 共89页
FPGA设计流程与规范.docx_第2页
第2页 / 共89页
FPGA设计流程与规范.docx_第3页
第3页 / 共89页
FPGA设计流程与规范.docx_第4页
第4页 / 共89页
FPGA设计流程与规范.docx_第5页
第5页 / 共89页
点击查看更多>>
下载资源
资源描述

FPGA设计流程与规范.docx

《FPGA设计流程与规范.docx》由会员分享,可在线阅读,更多相关《FPGA设计流程与规范.docx(89页珍藏版)》请在冰豆网上搜索。

FPGA设计流程与规范.docx

FPGA设计流程与规范

 

FPGA设计流程与规范

 

前言

在大规模的逻辑设计过程中,按照标准的设计流程和代码规范来进行FPGA、CPLD的开发是很重要的,它能够使整个开发过程实现合理性、一致性、高效性。

对于一个不规范的设计程序,若隔了比较长的时间来进行调试或修改的话,估计很多信号和模块的功能都忘了,若做了一半时需要由别的工程师来接着做的话,估计也得重头开始整个设计了。

而且,一个不规范的设计也无法实现代码的可重用性。

因此,FPGA设计流程和代码的规范化是很重要的,鉴于此原因笔者编写了本文档,以供FPGA设计参考用。

同时,本文档还对FPGA开发过程中的一些常用技巧和需要注意的问题进行了阐述。

 

1.基于HDL的FPGA设计流程概述

1.1设计流程图

 

说明:

●逻辑仿真器主要指modelsim,Verilog-XL等。

●逻辑综合器主要指LeonardoSpectrum、Precision、Synplify、FPGACompiler等。

●FPGA厂家工具指的是Max+PlusII、QuartusII、ISE等。

1.2关键步骤的实现

1.2.1功能仿真

说明:

“调用模块的行为仿真模型”指的是RTL代码中引用的由厂家提供的宏模块/IP,如Altera提供的LPM库中的乘法器、存储器等部件的行为模型,Xilinx提供的各种基本部件的仿真模型、或者是由Synopsys公司提供的SmartModel模型等,当然也可以是设计者自己编写的仿真模型。

1.2.2逻辑综合

说明:

“调用模块的黑盒子接口”的导入,是由于RTL代码调用了一些外部模块,而这些外部模块不能被综合或无需综合,但逻辑综合器需要其接口的定义来检查逻辑并保留这些模块的接口。

1.2.3前仿真

说明:

一般来说,只要针对所用的逻辑综合器和所选的FPGA器件来说,RTL设计是完全可综合的,那么前仿真这一步可以跳过不做,这一步主要用于发现综合后有无逻辑功能上的问题,有的话就需要修改源代码或者综合约束。

1.2.4布局布线

1.2.5后仿真(时序仿真)

3.逻辑仿真

考虑到性能和易用性,首选的逻辑仿真器是MentorGraphics的modelsim。

3.1测试程序(testbench)

测试程序对于设计功能和时序的验证有着举足轻重的影响,测试激励的完备性和真实性是关键所在,有以下原则须遵循:

(1)测试激励输入和响应输出采集的时序应当兼顾功能仿真(无延时)和时序仿真(有延时)的情况。

(2)对于周期较多的测试,为提高效率,尽可能采用程序语句来判断响应与标准结果是否一致,给出成功或出错标志,而不是通过观察波形来判断。

(3)采用基于文件的测试是很好的办法,即由matlab或spw等系统工具产生测试数据,测试程序将其读入产生激励,再把响应结果写入到文件,再交给上述工具进行处理或分析。

(4)仿真器支持几乎所有的VHDL、VerilogHDL语法,而不仅仅是常用的RTL的描述,设计者在编写测试平台时应当要充分利用这一点,使测试程序尽可能简洁、清楚,篇幅长的要尽量采用procedure、task来描述。

3.2使用预编译库

在进行功能仿真和后仿真时都需要某些模块的行为仿真模型和门级仿真模型,如AlteraQuartus里的220model.v(LPM模块行为仿真模型)和apex20ke_atoms.v(20KE系列门级仿真模型),为避免在不同的设计目录中多次编译这些模型,应当采用一次编译,多次使用的方法。

具体做法如下(以20KE门级库为例):

1:

在某个工作目录下新建一库名apex20ke,将apex20ke_atoms.v编译到其中。

2:

在图形界面中的LoadDesign对话框中装入仿真设计时,在Verilog标签下指定预编译库的完整路径。

(见下图)

4.逻辑综合

目前可用的FPGA综合工具有MentorGraphics的LeonardoSpectrum、Precision,Synplicity的Synplify,Synopsys的FPGACompilerII/FPGAExpress。

Precision和Synplify由于性能和速度最好,成为我们首选的综合器,目前在FPGA逻辑综合市场也是各占半壁天下。

另外设计者也可以使用QuartusII和ISE自带的综合器。

4.1逻辑综合的一些原则

4.1.1关于逻辑综合

HDL代码综合后电路质量的好坏主要取决于三个方面:

RTL实现是否合理、对厂家器件特点的理解、和对综合器掌握的程度,这一点FPGA工程师应该高度重视并熟练运用。

RTL级实现的合理性对综合后电路的影响至关重要。

划分合理的功能模块、安排正确的process或task、设计高效的状态机等,这些都决定着最终电路的质量。

LeonardoSpectrum、Precision、Synplify这些工具对综合的控制能力比较强,但使用也略为复杂,故需要在使用前尽量熟悉其功能,才能取得较好的综合结果。

当出现综合结果不能满足约束条件时,不要急于修改设计源文件,应当通过综合器提供的时序和面积分析命令找出关键所在,然后更改综合控制或修改代码。

4.1.2大规模设计的综合

●分块综合

当设计规模很大时,综合也会耗费很多时间。

如果设计只更改某个模块时,或者需要对某个模块单独进行综合从而达到比较好的效果时,可以分块综合。

如有设计top.v包含a.v和b.v两个模块,当只修改a.v或者为了使b.v能够综合出比较好的结果,可以先单独综合b.v,输出其网表b.edf,编写一个b模块的黑盒子接口b_syn.v,每次修改a.v后只综合top.v、a.v、b_syn.v,将综合后的网表和b.edf送去布线,可以节约综合b模块的时间。

●采用脚本命令

当设计规模比较大时,逻辑综合的控制也许会比较复杂,可以考虑采用脚本控制文件的方式进行综合控制,基本上所有的仿真、综合、布线工具都支持TCL(ToolCommandLanguage)语言,采用脚本控制可以提供比图形界面更灵活和更方便的控制手段。

4.1.3必须重视工具产生的警告信息

综合工具对设计进行处理可能会产生各种警告信息,有些是可以忽略的,但设计者应该尽量去除,不去除也必须要确认每条警告的含义,避免因此使设计的实现产生隐患。

这个原则对仿真和布局布线同样适用。

4.2调用模块的黑盒子方法

使用黑盒子(BlackBox)方法的原因主要有两点:

一是HDL代码中调用了一些FPGA厂家提供的模块(如Altera的LPM模块)或第三方提供的IP,这些模块不需要综合,而且有些综合器也不能综合。

因此须提供一个黑盒子接口给综合器,所调用的模块到布局布线时才进行连接。

二是方便代码的移植,由于厂家提供的模块或第三方提供的IP通常都是与工艺有关的,直接在代码中调用的话将不利于修改,影响代码移植。

5.VHDL语言编写规范

该规范涉及VHDL编码风格、规定,编码中应注意的问题,VHDL代码书写范例等。

编写该规范的目的是提高书写VHDL代码的可读性、可修改性、可重用性,优化代码综合和仿真的结果,指导设计工程师使用VHDL规范代码和优化电路,规范化公司的CPLD/FPGA设计输入,从而做到:

(1)逻辑功能正确,

(2)可快速仿真,(3)综合结果最优,(4)可读性较好。

本章节中提到的VHDL编码规则和建议既适用于VHDL数字电路设计中的任何一级(RTL,behavioral,gate_level),也适用于出于仿真、综合或二者结合的目的而设计的模块。

5.1VHDL编码风格

5.1.1标识符命名习惯

标识符用于定义实体名、结构体名、信号和变量名等,选择有意义的命名对设计是十分重要的。

命名包含信号或变量诸如出处、有效状态等基本含义。

下面给出一些命名的规则包括VHDL语言的保留字。

1.标识符定义命名规定

⏹标识符第一个字符必须是字母,最后一个字符不能是下划线,不许出现连续两个下划线

⏹基本标识符只能由字母、数字和下划线组成

⏹标识符两词之间须用下划线连接:

如Packet_addr,Data_in,Mem_wr,Mem_ce

⏹标识符不得与保留字同名

2.标识符大小写规定

⏹对常量、数据类型、实体名和结构体名采用全部大写

⏹对变量采用小写

⏹对信号采用第一个词首字符大写

⏹保留字一律小写

3.信号名连贯缩写的规定

长的名字对书写和记忆会带来不便,甚至带来错误。

采用缩写时应注意同一信号在模块中的一致性。

一致性的缩写习惯有利于文件的阅读理解和交流。

部分缩写的统一规定为:

Addraddress;Clkclock;Clrclear;Cntcounter;

Enenable;Incincrease;Lchlatch;Memmemory;

Pntrpointer;Pstpreset;Rstreset;

Regregister;Rdreader;Wrwrite

常用多个单词的缩写:

ROMRAMCPUFIFOALUCSCE

自定义的缩写必须在文件头注释。

4.信号名缩写的大小写规定

⏹单词的缩写若是信号名的第一个单词则首字符大写,如Addr_in中的Addr。

若该单词缩写不是第一个单词则小写,如Addr_en中的en

⏹多个单词的首字符缩写都大写,不管该缩写在标识符的什么位置,如RAM_addr、

Rd_CPU_en

5.信号名一致性规定

同一信号在不同层次应保持一致性。

6.信号命名有关建议

⏹建议用有意义而有效的名字,能简单包含该信号的全部或部分信息,如输入输出信息:

Data_in总线数据输入、Din单根数据线输入、FIFO_outFIFO、数据总线输出;如宽度信息:

Cnt8_q8位计数器输出信号的命名

⏹建议添加有意义的后缀,使信号名更加明确,常用的后缀如下:

说明:

1.采用D触发器对信号进行延迟,延迟信号的命名在原信号名之后加后缀_L,若是在流水线设计中有级延迟,再分别加后缀_L1,_L2.....。

L表示lock

2.模块内的反馈信号,在原信号名之后加后缀_s。

s表示same

5.1.2数据对象和类型

1.类型使用规定

⏹VHDL是很强的类型语言,可综合的数据类型为标量类型(包含可枚举类型、整型、浮点型、物理类型)和组合类型(包含记录、数组),模拟模型的数据类型可为存取类型、文件型。

可综合的VHDL代码的编写不采用模拟类型、浮点型、物理类型

⏹不同基本类型的数据不能由另一类型赋值,不同类型间的赋值需使用运算符的重载。

如:

Cnt8_q为STD_LOGIC_VECTOR类型,若不对‘+’运算符重载,则Cnt8_q<=Cnt8_q+1语句在综合中将出错。

可通过对+运算符进行重载即使用

useIEEE.std_logic_arith.all语句,则上句赋值语句是正确的

⏹常量名和数据类型必须用大写标识符表示

2.数据及数据类型使用建议

⏹为改善代码的可读性,建议可把常用的常量和自定义的数据类型在程序包中定义

⏹建议使用别名来标识一组数据类型有利于代码的清晰。

如:

signalAddr:

STD_LOGIC_VECTOR(31downto0);

aliasTop_addr:

STD_LOGIC_VECTOR(3downto0)isAddr(31downto28);

3.数据使用注意内容

可枚举类型的值为标识符或单个字母的字面量,是区分大小写的,如Z与z将是两个不同的量。

5.1.3信号和变量

1.信号不许赋初值。

2.变量使用建议

变量主要用在高层次的模拟模型建模及用于运算的用途,但变量的综合较难定义,对于编写可综合的VHDL模块,在没有把握综合结果情况下建议不使用。

3.信号和变量使用注意内容

⏹在VHDL中,信号(signal)代表硬件连线,因此可以是逻辑门的输入输出,同时,信号也可表达存贮元件的状态。

端口也是信号。

⏹在进程(process)中,信号是在进程结束时被赋值,因此在一个进程中,当一个信号被多个信号所赋值时,只有最后一个赋值语句起作用。

如下例:

Sig_p:

process(A,B,C)

begin

D<=A;-----ignored!

!

X<=CorD;

D<=B;----overrids!

!

Y<=CxorD;

endprocess;

上面实际的结果是B赋值给D,CxorB结果赋值给X、Y。

⏹变量不能表达连线或存贮元件,变量的赋值是直接的、非预设的。

变量将保持其值直到对它重新赋值。

如下例:

Ver_p:

process(ABC)

Variable:

dSTD_LOGIC;

begin

d:

=A;

X<=Cord;

d:

=B;

Y<=Cxord;

endprocess;

实际结果是X<=CorA,Y<=CxorB。

5.1.4实体和结构体

1.实体、结构体使用规定

⏹libraryIEEE;useIEEE.std_logic_1164.all;除IEEE大写外其余小写

⏹实体名和结构体名必须用大写标识,实体名必须与文件名同名。

自定义的其他标识符如信号名、变量名、标号等,不得与实体名、结构体名同名

⏹实体端口数据模式不准使用buffer模式。

缓冲模式主要用在实体内部可读的端口,如计数器的输出。

为简化大型设计各模

块间接口的配合,要求不要使用。

需要反馈的信号可定义内部信号来解决。

⏹实体端口数据类型规定

实体端口的数据类型采用IEEEstd_logic_1164标准支持的和提供的最适合于综合的数据类型STD_ULOGICSTD_LOGIC和这些类型的数组。

不采用IEEE1076/93标准支持和提供的BIT、BIT数组、INTEGER及其派生类型,这是为保证模拟模型和综合模型的一致性及减少转换时间和错误。

⏹一个文件只对应一个实体

实体是设计文件的基本单元其书写规范要求如下。

⏹一条语句占用一行,每行应限制在80个字符以内

⏹如果较长(超出80个字符)则要换行

⏹代码书写要有层次即层层缩进格式、清晰、美观

⏹要有必要的注释(25%)

⏹实体开始处应注明文件名、功能描述、引用模块、设计者、设计时间、及版权信息等。

2.实体使用建议

⏹实体名的命名建议能大致反映该实体的功能,如:

COUNTER8(8位宽的计数器模块),

DECODER38(3-8线译码器模块)

⏹行为级的结构体名命名为BEHAVIOR,结构级的结构体名命名为STRUCTURE,若有多个结构体用后缀AB......

⏹一个实体可以有多个结构体,对单个结构体的实体,文件要包含结构体和实体说明便于查阅。

对多个结构体的实体,建议把常用的结构体放在文件中,其余结构体用单独文件表示,使用时用configuration语句进行配置

⏹结构体的描述分为行为级描述、数据流描述、和结构化描述,若无特殊要求,建议采用行为级描述和数据流的描述,不采用结构化描述或BOOLEAN数据流的描述

⏹VHDL设计中,如果可以避免采用器件厂商的专用元件库(硬Core)则尽量不要使用,除非只有采用该库元件才能实现你设计的性能指标,这是因为要充分利用VHDL独立于工艺且易于维护的优点

3.实体使用注意内容

⏹VHDL设计应是层级型的设计。

VHDL设计实体由实体说明和结构体组合而成。

实体是一个设计的基本单元模块,即顶层的设计模块由次一级的实体构成,每个次一级实体又可由再下一层次的实体构成,最低层模块可以是表达式或最基本的实体模块构成。

这种设计方法就是Top-To-down的设计方法

⏹实体端口模式为in、out、buffer、inout,模式为in的信号不能被驱动;模式out的信号不能用于反馈,同时必须仅被一个信号所驱动;缓冲模式的端口不能被多重驱动(除非用决断函数解决外),同时仅可以连接内部信号或另一个实体的缓冲模式的某个端口

⏹VHDL设计各模块接口定义时要考虑模块间配合的方便,如实体端口的模式,端口的数

据类型等

5.1.5语句

1.VHDL各语句使用规定

⏹with-select-when语句书写规范规定

with-select-when语句提供选择信号赋值,是根据选定信号的值对信号赋值。

代码的书写规范为:

withselection_signalselect

Select_name<=value_awhenvalue_1_of_selection_signal,

value_bwhenvalue_2_of_selection_signal,

value_cwhenvalue_3_of_selection_signal,

.......

value_xwhenlast_value_of_selection_signal;

⏹with-select-when语句的selection_signal的所有值必须具备完整性,若没写完整必须有一个others语句,如下三个写法,其综合的效果是一致的,因为S的元素不是已知的逻辑值,X将不被定义,但对RTL仿真而言,其结果是不一致的,这是因为RTL仿真支持多值元素。

建议不使用第三种写法。

⏹with-select-when语句中对有相同的支项可合并书写,如X<=Awhen“00”|“10”

⏹when_else语句书写规范规定

when_else语句提供为条件信号赋值,即一个信号根据条件被赋一值,代码书写规范为:

Signal_name<=value_awhencondition1else

value_bwhencondition2else

value_cwhencondition3else

........

value_x;

⏹当条件是表达式时表达式须用()括起来,使代码更为清晰,如

whena=bandC=1else

⏹if必须有一个else对应(除在如下面例子的情况下可不写else语句)。

process(Clk,Rst)

begin

if(Rst='1')then

Q<='0';

elsif(Clk‘eventandClk=‘1’)then

Q<=D;

endif;

endprocess;

当没有else语句时将产生不希望的存储器。

⏹case-when语句书写规范规定

该语句用于规定一组根据给定选择信号的值而执行的语句,可用with-select-when语句等效代码的书写规范为:

case-selection_signalis

whenvalue1_of_selectionsignal=>

Statements1;

whenvalue2_of_selectionsignal=>

Statements2;

....

whenlast_value_of_selectionsignal=>

Statementsx;

whenothers=>

Statementsx;

endcase;

⏹case_when语句必须有whenothers支项。

⏹若信号在if-else或case-when语句作非完全赋值,必须给定一个缺省值。

⏹process显示敏感列表必须完整

对有Clk的process,不同综合工具有不同的要求,大多数只要写Clk和Rst就可建议根据具体情况简化设计书写。

⏹每个process前须加个lable。

⏹不同逻辑功能采用不同的process进程块,把相同功能的放在同一进程中。

⏹generate语句书写规范规定

在需要重复生成多个器件如多个器件的重复例化时,使用生成机构可简便代码书写。

如下32位总线的三态缓冲器的例化:

Gen_lab1:

forIin0to31generate

inst_lab:

threestateportmap(

Din=>Value(i),

Rd=>Rd,

Dout=>Value_out(i)

);

endgenerate;

⏹生成机构必须有一个标号,如上的Gen_lab1

⏹if-then用在生成机构中,不能有else或elsif语句,如下复杂的生成机构语句:

G1:

forIin0to3generate

G2:

forjin0to7generate

G3:

if(I<1)thengenerate

Ua:

thrstportmap(Val(j),Rd,Val_out(j));

endgenerate;

G4:

if(i=1)thengenerate

.......

⏹portmap语句书写规范规定

Uxx:

Module_name

portmap(

port1=>port1,

port2=>port2,

.....

portn=>portn

);

⏹为便于阅读,portmap采用名字对应(=>)映射方法。

⏹portmap中总线到总线映射时(XdowntoY)要写全。

⏹向量采用降序方法,即XdowntoY格式,向量有效位顺序的定义为从大数到小数。

⏹portmap的module(设计者自编写的entity)名用Uxx标识,cell(如厂家提供的库元件、RAM、Core等)名用Vxx标识。

2.VHDL语句使用建议

⏹作为可综合的代码编写,‘-’值建议不用。

如下一个代码

withtmpselect

X<=Awhen“1---”,

Bwhen“-1--”,

Cwhen“--1-”,

Dwhen“---1”,

0whenothers;

该代码在RTL级仿真中不会出错,但在综合过程中可能编译出错,视综合工具而定

⏹由于不同综合工具支持能力问题,建议不采用wait语句即不使用隐式敏感表。

3.VHDL语句使用注意内容

⏹when_else语句具有优先级,第一个when条件级别最高,最后一个最低可用顺序语句的if-else替代,书写时必须考虑敏感路径

⏹当信号的值为不相关的值时,最好用选择信号赋值语句,如多路选择器;当信号的值为相关时,选用when-else语句,如编写优先编码器

⏹注意If--elsif---elsif---else的优先级。

最后一个else优先级最低,必须把关键路径放在优先级高的语句中

5.1.6运算符

1.表达式书写规定

为便于理解用()表示逻辑运算符执行的优先级,如

X<=(AandB)and(Cor(notD));

建议运算操作符两边都加上空格.

2.比较运算符规定

向量比较时,比较的向量的位宽要相等,否责会引起warning或error,除非重载等值比较运算符(调用numeric_std库)。

5.1.7函数(Function)

1.function使用规定

⏹function代码书写规范规定:

funct

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1