EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。今天和大侠聊一聊FPGA研发设计相关规范,养成良好的个人习惯,代码设计风格等,都有助于日后发展。有哪些设计规范,从文档到工程建立等,聊一聊也许你会学到很多东西,少走很多弯路哦。话不多说,上货。
4 |. U z, b. g2 H' x$ Y0 U2 v5 _5 T! ?5 H9 W* P
6 J7 O* Z- u/ e 在团队项目开发中,为了使开发的高效性、一致性、正确性,团队应当要有一个规范的设计流程。按照规范来完成项目的设计开发工作,归类清晰明了的工程文件夹级别;项目应拥有良好风格和完整的文档,如设计思路与调试记录及器件选型等;代码书写高效,即统一的书写规范,文件头包含的信息完整,无论自己还是团队他人阅读便一目了然。. t: L, }% F( a, [; H1 L+ S
( ^* T- s: b: t
- H2 j+ u5 k, H3 G' m$ }
一、文档命名:
! M/ W" Q( `$ C) Z3 g9 U6 O
) ^: U- ~# E. a0 s( a x
' Q7 \1 Z2 o6 a5 K D9 W$ G清晰的文档命名能够让我们思路非常的清晰,所以FPGA工程文件夹的目录要求层次鲜明,归类清晰。一个工程必须要有一个严整的框架结构,用来存放相关的文档、设计,不仅方便自己查看,也提高了项目的团队工作效率。
7 K+ N7 c! A, {# p& ~" u
) D) ]1 _; g& J) ?0 ?( N& ]下面我们来举例说明:
/ Z- V2 F, l; R8 v& N# I1 S) J$ X8 t2 b% l
0 c$ B+ r# |2 ?# A
一级文件夹为工程名<project>3 s$ ~' K$ D$ [6 v, E' l# y7 Y
二级文件夹多个:用以存放源文件<src>用以存放Testbench文件<sim> u, H; D8 C9 F& U9 Z
用来存放设计思路相关类的文件<doc> 用来存放IP 核的文件<core>等等…
n2 h4 l7 P: i- K1 j& y1 F$ m
" m, ^7 }2 T" ~
" z7 s% E; q4 F' z+ t5 G. D/ G6 ` C( g7 m- N4 ]' \! k' M
二、设计文档化:
4 D7 |1 y: Y6 D+ t' E3 j% b e3 R$ L. R7 w0 n
& ~, ]. P. z4 y, u& T# x
将自己对设计的思路和调试记录在文档中,有利于以后对模块功能的添加和维护,并且在项目联调时方便项目组其他人员读代码。也方便不同厂家的FPGA之间移植,以及FPGA到ASIC的移植。如下图就是设计文档化的举例说明,文档介绍清晰,功能分析明确,有利于以后对模块功能的添加和维护。) u: _8 d" c7 ]/ L2 t
7 p, g0 E( P5 v5 [
" [, m+ V9 R( e& Y+ p5 c+ z6 h0 q/ C5 g3 z0 c
, ]2 `: G. r, w% ]! p4 [
8 L# w( V& r( n# m8 \: Q
设计思路:
/ |* l o& F; w9 X0 i1 t: v
- G1 q4 O2 O Y5 g
/ ^2 X1 D, b/ h- N4 F. ~% j% G 按照项目的要求,自顶向下的分成若干模块,分别编写功能。顶层尽量只做行为描述,逻辑描述在底层编写。模块的编写要有硬件电路思维方式,每一个模块的设计都应考虑是否存在该硬件电路,尽量采用同步设计。, y/ V! R$ o- Z0 R/ P
# q6 Z9 u- E: i4 g
, R- W: ^" L5 G+ d% H) j; S9 ~
. C3 r7 C& l8 n* e+ E& @ u# |三、编码风格:) F; W+ ~) n& V: L" w: S3 b
) |5 ^, I: s* `9 o3 u7 k
$ s& [0 F7 z3 C$ ^
7 S+ L, c Q3 j! a" {& Z1 p, U, R1 L3 S
每个module应存在于单独的源文件中,源文件名应与其所包含的模块名相同。每个设计都应该有一个完善的文件头,包含公司名称、设计者、设计时间、文件名、所属项目、模块名称及功能、修改记录及版本信息等内容。代码中的标识符采用传统C语言的命名方法,在单词之间用下划线分开,采用有意义,能反应对象特征、作用和性质的单词命名标识符,以此来增强程序的可读性。为避免标识符过于冗长,较长的单词可以适当的缩写。0 @( _$ {5 e% m8 O
6 R1 f3 q1 g6 W+ n% _6 y3 a四、代码规范:
" p/ b" W' B- [0 o2 A+ h# N
4 W- h7 ^& z9 ?! F7 ]. n# D f# a& k+ R
R# J* p; | }# ]0 b. B
低电平有效的信号,后缀名要用“_n”,比如低电平有效的复位信号“rst_n”% F" ~; q& p/ _0 [
模块名和信号名统一小写
& B4 Q% G2 o# K4 r$ m 变量名要小写,如wire、reg、input、output等定义的 变量命名应按照变量的功能用英文简洁表示出来“xxx_xxx_xxx”,避免过长
' ^8 C, K- ^" q) T7 s 采用大写字母定义常量参数,参数名小于20个字母,如parameter TIME=206 S/ w; L$ L* ^ r
时钟信号应前缀“clk”,复位信号应前缀“rst”8 F3 c0 y/ U: N8 z4 }! r2 B3 G
对于顶层模块的输出信号尽量被寄存# q! H) U6 I# L) H" f
三态逻辑避免在子模块使用,可以在顶层模块使用 到其它模块的接口信号按:输入、(双向)、输出的顺序定义端口 一个模块至少要有一个输入、输出,避免书写空模块 时钟事件的表达式用“posedge”或“negedge”的形式 If语句嵌套不能太多 建议不要使用include语句 建议每个模块添加timescale 代码中给出必要的注释 每个文件有个一头文件 每个文件只包含一个模块 模块名和文件名保持一致 异步复位,用if(xxx==1’b1) 或 if(xxx==1’b0) 同步时序逻辑的always block中有且只有一个时钟信号,并且在同一个沿动作 采用同步设计,避免使用异步逻辑 一般不要将时钟信号作为数据信号的输入 不要在时钟路径上添加任何buffer 在顶层模块中,时钟信号必须可见 不要采用向量定义的方式定义一组时钟信号 不要在模块内部生成时钟信号,使用pll产生 尽量不使用任务 不使用事件变量 不使用系统函数 不使用disable语句 尽量不使用forever、repeat、while等循环语句 不使用不可综合的运算符 在一个always语句中有且只能有一个事件列表 移位变量必须是一个常数 时序逻辑语块中统一使用非阻塞型赋值 组合逻辑语块中使用阻塞型赋值 . F4 v H/ G6 d; {* d: m
五、注释规则
% C( x/ R5 @% x- [: Z& ` a
2 ^: A! ]& q' ^( K9 l* z, a8 a, C- f2 O
% w. [1 N0 T' x7 s1、每个文件有一个文件头,文件头中注明文件名、功能描述、引用模块、设计者、设计时间、版权信息以及修改信息等;
9 }. r5 J& ]* x% _$ U( K6 d. l% g
* Q' \4 X& I( s# Y# g( j2、对信号、参量、引脚、模块、函数及进程等加以说明,便于阅读与维护,如信号的作用、频率、占空比、高低电平宽度等。用“//”做小于1行的注释,用“/* */”做多于1行的注释。更新的内容要做注释,记录修改原因,修改日期和修改人。
* C$ ?2 ~( g, F4 B
4 A: i- S# x5 s+ s( L$ |
( z3 L+ r8 W/ I! p5 z6 p& e# ~) M0 {2 e E" K" h" E
六、模块规则! L1 [* y+ Z T9 q
3 a) n* m7 ?1 D1 v1 M' x* [% l5 U& R1 {8 v
3 C. x% G3 p. z8 q! N8 Z1、module例化名用u_xx_x标示;2 D3 b( ]6 v* M9 j. l
2、建议给每个模块要加timescale;0 o/ m8 j! d8 J5 F
3、不要书写空的模块,即:一个模块至少要有一个输入和一个输出;7 z& i, h* I2 b
4、为了保持代码的清晰、美观和层次感,一条语句应占用一行,每行限制在80个字符以内,如果较长(超出80个字符)则换行;
6 N7 u2 {0 V! L9 p& J! ^+ f5、采用基于名字(name_based)的调用而不是基于顺序的(order_based)的调用;- |" q) o8 t* J
6、模块的接口信号按输入、双向、输出顺序定义;
/ G, A2 d; a7 I/ D7、使用降序定义向量有效位顺序,最低位为0;, f- C9 [2 R V# o2 N
8、管脚和信号说明部分:一个管脚和一组总线占用一行,说明要清晰;
% {- [% o& |! L; |9、不要采用向量的方式定义一组时钟信号;' c8 e% Q) c- j8 N
10、逻辑内部不对input进行驱动,在module内不存在没有驱动源的信号,更不能在模块端口存在没有驱动的输出信号,避免在elabarate和compile时产生warning;4 v3 h& Q) g, ?
11、在顶层模块中,除了内部的互连和module的例化外,避免在做其他逻辑;, \# O% y2 S, s$ I7 m) D
12、出于层次设计和同步设计的考虑,子模块输出信号建议用寄存器;
. S. Y$ L3 G) I; S* c* l# ?/ d13、内部模块端口避免inout,最好在最顶层模块处理双向总线;/ x; e! a: V7 d/ Z& v4 G
14、子模块中禁止使用三态逻辑,可以在顶层模块使用;- U2 a. R, A* |. { l( i
15、禁止出现未连接的端口;4 @# X3 T9 v# r) i
16、为逻辑升级保留的无用端口和信号要注释;对于层次化设计的逻辑,在升级中采用增量编译;建议采用层次化设计,模块之间相对独立。6 `& a6 `! f; ~
' O! D& u) f' M I9 G) v! K
- q3 v+ o1 z* h3 c* ~7 ^七、线网和寄存器规则# t; k- o# u+ t# c
) [- R* q% m; n/ H, q& _
1、锁存器和触发器不允许在不同的always块中赋值,造成多重驱动;8 o* ?9 `: ?3 I! x
2、出于功能仿真考虑,非阻塞赋值应该增加单位延时,对于寄存器类型的变量赋值时,尤其要注意这一点;阻塞赋值不允许使用单位延时;" n3 X$ |3 D. a% ]; u
3、always语句实现时序逻辑采用非阻塞赋值;always语句实现的组合逻辑和assign语句块中使用阻塞赋值;
3 \; C6 u5 W' M' B4 n; H( Z4、同一信号赋值不能同时使用阻塞和非阻塞两种方式;2 F! g: c5 l+ J! z, A
5、不允许出现定义了parameter、wire、reg却没有使用的情况;
- E) z; |' `! y6 A; l% K! E6、不建议使用integer类型寄存器;5 d( E3 {: K# G1 z
7、寄存器类型的信号要初始化;
+ ]1 w; ~3 f) j' }# e p8、除移位寄存器外,每个always语句只对一个变量赋值,尽量避免在一个always语句出现多个变量进行运算或赋值。
# H7 W4 V& f+ |& P
1 l; D3 v' c. |+ u八、表达式规则
0 l; @6 [: {& m0 W5 H5 h) ^" P* W2 s2 x& y, Z2 a0 j+ i
1、在表达式内使用括号表示运算的优先级,一行中不能出现多个表达式;1 t# o+ l' Q8 O* N
2、不要给信号赋“x”态,以免x值传递;
% `: n! \* |- j) z" m! f) Z3、设计中使用到的0,1,z等常数采用基数表示法书写(即表示为1'b0,1'b1,1'bz或十六进制);& l+ ]) S M% j/ x& ]
4、端口申明、比较、赋值等操作时,数据位宽要匹配。
7 U$ V( P: M4 r) G) g* d {& ]; I0 Z E4 J
) \' @8 ?4 t |: B4 h$ G3 {
; [1 e+ \# h& M, Z; A九、条件语句规则
4 h1 v5 A$ g/ B8 y- C: g& Y# `' s7 a
4 @) `. ^, H/ i& R
1、if 都有else和它对应,变量在if-else或case语句中所有变量在所有分支中都赋值;
. R! v3 R j( q2、如果用到case语句,记得default项;
" [1 V1 b1 n% [: d3、禁止使用casex,case语句item必须使用常数;% @4 q2 `1 A5 N! P6 n/ N w( Q [, ?
4、不允许使用常数作为if语句的条件表达式;8 h6 M: U0 [; d, A6 n5 E
5、条件表达式必须是1bit value;
, s6 I* {' F0 F3 w" N5 n; k# Y6、如异步复位:高电平有效使用“if(asynch_reset==1'b1)”,低电平“if(asynch_reset==1'b0)”,不要写成:“if(!asynch_reset)”或者“if(asynch_reset==0)”;! R& r7 B6 }9 w) M0 D
7、不推荐嵌套使用5级以上if…else if…结构。
; B" P8 c: p# c& C+ J) z$ D$ N+ @; F5 G( P5 t0 f
十、可综合部分规则
4 Z$ c; H2 C* ` V1 X9 S E; X0 z ?7 ]3 P/ o6 t, ?' i+ L7 g) p
% {$ ^2 I( {. }5 Y1 p; Y
1、不要使用include语句;3 _+ S$ N8 g( X% |, p
2、不要使用disable、initial等综合工具不支持的电路,而应采用复位方式进行初始化,但在testbench电路中可以使用;! @+ }& h% m( X3 _; J3 X% t
3、不使用specify模块,不使用===、!==等不可综合的操作符;9 G/ b* V+ O4 S8 s. i( R* G! n
4、除仿真外,不使用fork-join语句;
0 \9 c0 G W* k5 b5、除仿真外,不使用while语句;$ }9 V; m8 T- L* u7 l5 [
6、除仿真外,不使用repeat语句;8 m* u" j6 e4 e' A4 S
7、除仿真外,不使用forever语句;& Q7 S; g- `0 p% x
8、除仿真外,不使用系统任务($);
8 s8 ~$ F! Q1 k+ E, Y9、除仿真外,不使用deassign语句;2 ~/ m8 [2 b# k
10、除仿真外,不使用force,release语句;! `2 K" l4 V+ [! K8 F/ l
11、除仿真外,不使用named events语句;不在连续赋值语句中引入驱动强度和延时;! k0 `! B/ I S5 ]: o3 a. x4 o
12、禁止使用trireg型线网;+ X" M" }" Y, Y6 ?
13、制止使用tri1、tri0、triand和trior型的连接;
0 y2 O2 z2 J( F2 B) l8 D' `14、不要给驱动supply0和supply1型的线网赋值;
6 q3 ^& F6 c! Q2 S' w15、设计中不使用macro_module;
& d6 p. C3 z, U, l1 w16、不要在RTL代码中实例化门级单元,其下列单元:(CMOS/RCOMS/NMOS/PMOS/RNMOS/RPMOS/trans/rtrans/tranif0/tranif1/rtranif0/tranif1/pull_gate)。
1 a4 e7 |& _5 ^* q% d) c3 P
8 |( l* W+ l( `7 g/ E. A0 P2 V
: Z7 B, W4 C) {: r. m( k十一、可重用部分规则
& H: E9 C3 [6 o- P# j" i" o8 l9 {' b: Z1 ^3 {' _8 }* A0 F
6 }& ^. s Q" W- g- h1、考虑未使用的输入信号power_down,避免传入不稳定态;
R/ C- D2 g& v: n( b7 L$ \2、接口信号尽量少,接口时序尽量简单;
j3 o" f; R: w3、将状态机(FSM)电路与其它电路分开,便于综合和后端约束;8 i5 C0 p2 d7 y* |! e5 a- z' g3 R
4、将异步电路和同步电路区分开,便于综合和后端约束,将相关的逻辑放在一个模块内;# b+ s- L) n/ W; |* r* _4 h
5、合理划分设计的功能模块,保证模块功能的独立性;
6 W7 N% A, }6 Z8 F/ f$ d1 ^$ L+ C6、合理划分模块的大小,避免模块过大;
* X1 C2 I( K) ?+ ]; o- w7、在设计的顶层(top)模块,将I/O口、Boundary scan电路、以及设计逻辑(corelogic)区分开。
3 `1 w: h$ N0 ~) {/ c
7 P: }* O3 l7 s E( M2 n7 @& w, B十二、同步设计规则
% Z V+ Q( L( m3 X( V0 U: k! T/ a; V8 T& s# L% X* D8 U
2 ^' n( A+ }2 ~( }& ]4 Q% S1、同一个module中,要在时钟信号的同一个沿动作;
) B* M, S/ K* K7 q% B, V1 z2、如果必须使用时钟上升沿和时钟下降沿,则要分两个module设计;
( `2 v U& b5 V1 z3、在顶层模块中,时钟信号必须可见,不在模块内部生成时钟信号,而要使用DCM/PLL产生的时钟信号;
- e/ M/ ]# v8 }! U4、避免使用门控时钟和门控复位;
/ j6 t/ j% H4 _4 S' T5、同步复位电路,建议在同一时钟域使用单一的全局同步复位电路;异步复位电路,建议使用单一的全局异步复位电路;8 {- J. ?! [ u+ W
6、不在时钟路径上添加任何buffer;7 s& o b7 Z- q7 B9 ^
7、不在复位路径上添加任何buffer;
1 v& V1 d" W4 n) a6 p/ x8、避免使用latch;
& o$ m9 l: F3 U( |/ L- ~9、寄存器的异步复位和异步置位信号不能同时有效;
' Q! [- o6 j$ f- @' \10、避免使用组合反馈电路;
5 R! c9 ^( P0 X6 A4 h11、always有且仅有一个的敏感事件列表,敏感事件列表要完整,否则可能会造成前后仿真的结果不一致;3 N' N: P* |0 o
12、异步复位情况下需要异步复位信号和时钟沿做敏感量,同步复位情况下只需要时钟沿做敏感量;) D4 u8 r6 g* D5 R5 l
13、时钟事件的表达式要用:“negedge<clk_name>”或“posedge<clock_name>”的形式;# h! j3 A3 b' N& f6 v/ f
14、复杂电路将组合逻辑和时序逻辑电路分成独立的always描述。, Q I2 N. t1 J9 Q7 Q0 t# i r
( B! H2 B; f E/ ]8 I: ~
; A6 | {# t3 R7 N, e& t5 |+ d! ^/ T$ S! [! u& S: M
十三、循环语句规则
# ^' P5 x9 J- u' I- w, H0 x4 C! _5 C; W- }3 n' x V5 w& K
1 {( m" E' \1 E& z1、在设计中不推荐使用循环语句;
# K) ]6 i, F3 p2、在非常有必要使用的循环语句时,可以使用for语句。
1 y! m8 L& R/ \* C- o. _
! Q9 g! D- v' i) K2 J十四、约束规则
! y' D' T$ }7 F- i2 A6 q
* a7 j6 S4 ?9 t% s9 ~8 x/ w1 u3 Z1 _0 w
1、对所有时钟频率和占空比都进行约束;
0 [* l9 u! J; ?- @2 h% `' y/ R2、对全局时钟skew进行约束;; @8 q5 v M/ {6 G
3、对于时序要求的路径需要针对特殊要求进行约束,如锁相环鉴相信号;; ~' u; F* u' J
4、要根据输出管脚驱动要求进行约束,包括驱动电流和信号边沿特性;
, l( x5 F2 T0 Z5、要根据输入和输出信号的特性进行管脚上下拉约束;
) f1 j! b! _! q) G( [6、针对关键I/O是否约束了输入信号和输入时钟的相位关系,控制输入信号在CLK信号之后或之前多少ns到达输入pad;
4 Y+ N. m2 `; G7 {+ E$ K7、综合设置时,fanout建议设置为3030;
: A: k& i( L* g7 W% ?8、要使用输入输出模块中的寄存器,如Xinlinx公司的IOB,map properties选项pack I/O register/latches into IOBsactor需要设置成为“for input and output”,这样可以控制管脚到内部触发器的延时时间;" s& u# L* X0 k: P) G! Z2 F# K+ U, z
9、布局布线报告中IOB、LUTs、RAM等资源利用率应小于百分之八十;2 i# ^$ n D* w* o3 e
10、对于逻辑芯片对外输入接口,进行tsu/th约束;对于逻辑芯片对外输出接口,进行约束。" @$ K% u$ `/ {
5 r. R/ V# A( {9 S; }* @& V3 I( Q
十五、PLL/DCM
% U0 U/ w1 j7 F7 U! N6 A, T' q
. _4 Q% x$ J; `- d; v1、如果使用FPGA内部DCM和PLL时,应该保证输入时钟的抖动小于300ps,防止DCM/PLL失锁;如果输入时钟瞬断后必须复位PLL/DCM。
$ |. {# f. `% o* z2 x2、对于所有厂家的FPGA,其片内锁相环只能使用同频率的时钟信号进行锁相,如果特殊情况下需要使用不同频率的信号进行锁相,需要得到厂家的认可,以避免出时钟。
9 k7 H* _( t- p) ~) A/ R8 g3 R/ C/ y' r! Y1 H% J( S. w* F
十六、代码编辑由于不同编辑器处理不同,对齐代码使用空格,而不是tab键。
% n8 b( ~* N( _0 z) K. l& w# \* e7 ]! {) z# f% J+ g+ ? ?' [
***可综合和不可综合详解***! O: z, G Y, J: t0 }2 b
(1)所有综合工具都支持的结构:always,assign,begin,end,case,wire,tri,aupply0,supply1,reg,integer,default,for,function,and,nand,or,nor,xor,xnor,buf,not, bufif0,bufif1,notif0,notif1,if,inout,input,instantitation,module,negedge,posedge,operators,output,parameter。( O7 e9 w3 E+ V. u' l5 T
(2)所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait。(3)有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。
" c, u2 y( V) G4 ?- s& t: B3 ?- T: y
建立可综合模型的原则3 R) t( v6 l% ~- e# Z
要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:
. _/ j) j3 ]9 y( T
% L& M" j6 o/ ^: J' @(1)不使用initial。7 C! y a& U, z9 a; w
(2)不使用#10。
) d' G* |1 l8 |: K$ B7 j(3)不使用循环次数不确定的循环语句,如forever、while等。 * o8 N, \! I' E) B7 u# x
(4)不使用用户自定义原语(UDP元件)。 ; d& H2 }' S3 e$ x5 h
(5)尽量使用同步方式设计电路。
: {% F% R) m* z5 {& J(6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。 , L7 @7 ?) [2 K, a |7 r
(7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。
* B- ~2 e0 J. a% s2 q(8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。 - ~$ R# ^+ E* f3 w( ^9 `3 q
(9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。 1 w0 h5 t& S6 M7 u' Q
(10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。 2 Q) y4 V2 ?; G: x
(11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。 (12)避免混合使用上升沿和下降沿触发的触发器。 8 r) w( q/ X+ i" H+ w8 K
(13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。 ( V b+ }# j! U! Z/ @; E
(14)避免在case语句的分支项中使用x值或z值。
8 p- F3 y- V6 v/ h4 M- p) [0 i# S! T, c% B, R! L5 \+ H
1、initial 只能在test bench中使用,不能综合。(用ISE9.1综合时,有的简单的initial也可以综合,不知道为什么) ! _ ^3 }9 {) D# I. K: _
2、events
' {. V, y: z6 l; z" W$ Z6 aevent在同步test bench时更有用,不能综合。
% G; k3 |, s, c, q* w- W6 C7 M3、real. {8 K, \1 n- u& |+ u9 i# J6 v
不支持real数据类型的综合。
7 f2 W' S: m+ w4、time
, u! t0 ^5 m# x4 B不支持time数据类型的综合。
$ z. B1 N9 T% \8 f: i! P$ J) Z: g5、force 和release
/ @0 S4 z( ?" S8 s7 d" j0 v3 P a) y: Z不支持force和release的综合。
: l7 C2 C2 K' r% p6、assign 和deassign
. L5 S% o1 o2 H! {不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。% ?$ s. z' Z: K6 Y% d/ ~9 m" S; M' c+ n0 A
7、fork join
* b6 W8 `, S0 s* z0 ~不可综合,可以使用非块语句达到同样的效果。 + ]8 H4 n" G0 v. z; G
8、primitives
4 e/ Z" t+ w: l支持门级原语的综合,不支持非门级原语的综合。
: E- [, w: r' i1 k# d: \9、table 5 M. b2 g8 ~0 v7 y; n3 \
不支持UDP 和table的综合。
, J* h+ W' b) Z10、敏感列表里同时带有posedge和negedge% V4 e5 {' E! w9 {' [6 G
如:always @(posedge clk or negedge clk) begin...end这个always块不可综合。
8 V8 N7 g: W7 a7 G, S3 G11、同一个reg变量被多个always块驱动
( |3 C, J! s# H* b12、延时
: o$ Z) x5 L c# x$ Y; |0 s* O以#开头的延时不可综合成硬件电路延时,综合工具会忽略所有延时代码,但不会报错。
, h: q0 n+ @0 Z5 ^4 ]# _ z) ~如:a=#10 b;这里的#10是用于仿真时的延时,在综合的时候综合工具会忽略它。也就是说,在综合的时候上式等同于a=b;! W, M9 l" Y0 G
13、与X、Z的比较
V1 j+ v8 u% l3 ]! L& \可能会有人喜欢在条件表达式中把数据和X(或Z)进行比较,殊不知这是不可综合的,综合工具同样会忽略。所以要确保信号只有两个状态:0或1。如:
, D, \1 W0 {$ ~) c
( }# e8 e1 x, R0 {0 H9 u& j- R, X0 m. s+ |: [) G
以上是个人整理出来的一些设计规范,有些部分有重复,但无伤大雅,适用于FPGA Verilog HDL设计,VHDL的话设计思想是一样,大同小异,大家可以举一反三。[tr]后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。[tr]大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!# k: I$ H4 `/ r6 c2 z3 C
. [6 @9 _* H" j3 Q6 g: J6 p
|