0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简谈FPGA的设计规范

FPGA学习交流 2019-11-14 13:54 次阅读

大家好,又到了每日学习的时间了,有一段时间没有正经更新了,之前有粗略地聊过FPGA的设计规范,那今天我们就详细的聊一聊FPGA做开发的时候,有哪些设计规范,从文档到工程建立等,聊一聊也许你会学到很多东西,少走很多弯路哦!
在团队项目开发中,为了使开发的高效性、一致性、正确性,团队应当要有一个规范的设计流程。按照规范来完成项目的设计开发工作,归类清晰明了的工程文件夹级别;项目应拥有良好风格和完整的文档,如设计思路与调试记录及器件选型等;代码书写高效,即统一的书写规范,文件头包含的信息完整,无论自己还是团队他人阅读便一目了然。


一、文档命名:

清晰的文档命名能够让我们思路非常的清晰,所以FPGA工程文件夹的目录要求层次鲜明,归类清晰。一个工程必须要有一个严整的框架结构,用来存放相关的文档、设计,不仅方便自己查看,也提高了项目的团队工作效率。
下面我们来举例说明:
一级文件夹为工程名
二级文件夹多个:
用以存放源文件
用以存放Testbench文件
用来存放设计思路相关类的文件
用来存放IP 核的文件
等等…


二、设计文档化:
将自己对设计的思路和调试记录在文档中,有利于以后对模块功能的添加和维护,并且在项目联调时方便项目组其他人员读代码。也方便不同厂家的FPGA之间移植,以及FPGA到ASIC的移植。如下图就是设计文档化的举例说明,文档介绍清晰,功能分析明确,有利于以后对模块功能的添加和维护。

image.png

设计思路:按照项目的要求,自顶向下的分成若干模块,分别编写功能。顶层尽量只做行为描述,逻辑描述在底层编写。模块的编写要有硬件电路思维方式,每一个模块的设计都应考虑是否存在该硬件电路,尽量采用同步设计。


三、编码风格:

每个module应存在于单独的源文件中,源文件名应与其所包含的模块名相同。每个设计都应该有一个完善的文件头,包含公司名称、设计者、设计时间、文件名、所属项目、模块名称及功能、修改记录及版本信息等内容。代码中的标识符采用传统C语言的命名方法,在单词之间用下划线分开,采用有意义,能反应对象特征、作用和性质的单词命名标识符,以此来增强程序的可读性。为避免标识符过于冗长,较长的单词可以适当的缩写。


四、代码规范:
低电平有效的信号,后缀名要用“_n”,比如低电平有效的复位信号“rst_n”
模块名和信号名统一小写
变量名要小写,如wire、reg、input、output等定义的
变量命名应按照变量的功能用英文简洁表示出来“xxx_xxx_xxx”,避免过长
采用大写字母定义常量参数,参数名小于20个字母,如parameter TIME=20
时钟信号应前缀“clk”,复位信号应前缀“rst”
对于顶层模块的输出信号尽量被寄存
三态逻辑避免在子模块使用,可以在顶层模块使用
到其它模块的接口信号按:输入、(双向)、输出的顺序定义端口
一个模块至少要有一个输入、输出,避免书写空模块
时钟事件的表达式用“posedge”或“negedge”的形式
If语句嵌套不能太多
建议不要使用include语句
建议每个模块添加timescale
代码中给出必要的注释
每个文件有个一头文件
每个文件只包含一个模块
模块名和文件名保持一致
异步复位,用if(xxx==1’b1) 或 if(xxx==1’b0)
同步时序逻辑的always block中有且只有一个时钟信号,并且在同一个沿动作
采用同步设计,避免使用异步逻辑
一般不要将时钟信号作为数据信号的输入
不要在时钟路径上添加任何buffer
在顶层模块中,时钟信号必须可见
不要采用向量定义的方式定义一组时钟信号
不要在模块内部生成时钟信号,使用pll产生
尽量不使用任务
不使用事件变量
不使用系统函数
不使用disable语句
尽量不使用forever、repeat、while等循环语句
不使用不可综合的运算符
在一个always语句中有且只能有一个事件列表
移位变量必须是一个常数
时序逻辑语块中统一使用非阻塞型赋值
组合逻辑语块中使用阻塞型赋值


五、注释规则

  1. 每个文件有一个文件头,文件头中注明文件名、功能描述、引用模块、设计者、设计时间、版权信息以及修改信息等;

  2. 对信号、参量、引脚、模块、函数及进程等加以说明,便于阅读与维护,如信号的作用、频率、占空比、高低电平宽度等。用“//”做小于1行的注释,用“/* */”做多于1行的注释。更新的内容要做注释,记录修改原因,修改日期和修改人。


六、模块规则

  1. module例化名用u_xx_x标示;

  2. 建议给每个模块要加timescale;

  3. 不要书写空的模块,即:一个模块至少要有一个输入和一个输出;

  4. 为了保持代码的清晰、美观和层次感,一条语句应占用一行,每行限制在80个字符以内,如果较长(超出80个字符)则换行;

  5. 采用基于名字(name_based)的调用而不是基于顺序的(order_based)的调用;

  6. 模块的接口信号按输入、双向、输出顺序定义;

  7. 使用降序定义向量有效位顺序,最低位为0;

  8. 管脚和信号说明部分:一个管脚和一组总线占用一行,说明要清晰;

  9. 不要采用向量的方式定义一组时钟信号;

  10. 逻辑内部不对input进行驱动,在module内不存在没有驱动源的信号,更不能在模块端口存在没有驱动的输出信号,避免在elabarate和compile时产生warning;

  11. 在顶层模块中,除了内部的互连和module的例化外,避免在做其他逻辑;

  12. 出于层次设计和同步设计的考虑,子模块输出信号建议用寄存器

  13. 内部模块端口避免inout,最好在最顶层模块处理双向总线;

  14. 子模块中禁止使用三态逻辑,可以在顶层模块使用;

  15. 如果能确保该信号不会被其它子模块使用,而是直接通过顶层模块输出I/O口,可以在子模块中使用三态;

  16. 禁止出现未连接的端口;

  17. 为逻辑升级保留的无用端口和信号要注释;对于层次化设计的逻辑,在升级中采用增量编译;建议采用层次化设计,模块之间相对独立。

七、线网和寄存器规则

  1. 锁存器和触发器不允许在不同的always块中赋值,造成多重驱动;

  2. 出于功能仿真考虑,非阻塞赋值应该增加单位延时,对于寄存器类型的变量赋值时,尤其要注意这一点;阻塞赋值不允许使用单位延时;

  3. always语句实现时序逻辑采用非阻塞赋值;always语句实现的组合逻辑和assign语句块中使用阻塞赋值;

  4. 同一信号赋值不能同时使用阻塞和非阻塞两种方式;

  5. 不允许出现定义了parameter、wire、reg却没有使用的情况;

  6. 不建议使用integer类型寄存器;

  7. 寄存器类型的信号要初始化;

  8. 除移位寄存器外,每个always语句只对一个变量赋值,尽量避免在一个always语句出现多个变量进行运算或赋值。


八、表达式规则

  1. 在表达式内使用括号表示运算的优先级,一行中不能出现多个表达式;

  2. 不要给信号赋“x”态,以免x值传递;

  3. 设计中使用到的0,1,z等常数采用基数表示法书写(即表示为1'b0,1'b1,1'bz或十六进制);

  4. 端口申明、比较、赋值等操作时,数据位宽要匹配。


九、条件语句规则

  1. if 都有else和它对应,变量在if-else或case语句中所有变量在所有分支中都赋值;

  2. 如果用到case语句,记得default项;

  3. 禁止使用casex,case语句item必须使用常数;

  4. 不允许使用常数作为if语句的条件表达式;

  5. 条件表达式必须是1bit value;

  6. 如异步复位:

    高电平有效使用“if(asynch_reset==1'b1)”,

    低电平“if(asynch_reset==1'b0)”,

    不要写成

    “if(!asynch_reset)”或者“if(asynch_reset==0)”;

  7. 推荐嵌套使用5级以上if…else if…结构。


十、可综合部分规则

  1. 不要使用include语句;

  2. 不要使用disable、initial等综合工具不支持的电路,而应采用复位方式进行初时化,但在testbench电路中可以使用;

  3. 不使用specify模块,不使用===、!==等不可综合的操作符;

  4. 除仿真外,不使用fork-join语句;

  5. 除仿真外,不使用while语句;

  6. 除仿真外,不使用repeat语句;

  7. 除仿真外,不使用forever语句;

  8. 除仿真外,不使用系统任务($);

  9. 除仿真外,不使用deassign语句;

  10. 除仿真外,不使用force,release语句;

  11. 除仿真外,不使用named events语句;不在连续赋值语句中引入驱动强度和延时;

  12. 禁止使用trireg型线网;

  13. 制止使用tri1、tri0、triand和trior型的连接;

  14. 不要位驱动supply0和supply1型的线网赋值;

  15. 设计中不使用macro_module;

  16. 不要在RTL代码中实例门级单元尤,其下列单元:(CMOS/RCOMS/NMOS/PMOS/RNMOS/RPMOS/trans/rtrans/tranif0/tranif1/rtranif0/tranif1/pull_gate)。


十一、可重用部分规则

  1. 考虑未使用的输入信号power_down,避免传入不稳定态;

  2. 接口信号尽量少,接口时序尽量简单;

  3. 将状态机(FSM)电路与其它电路分开,便于综合和后端约束;

  4. 将异步电路和同步电路区分开,便于综合和后端约束,将相关的逻辑放在一个模块内;

  5. 合理划分设计的功能模块,保证模块功能的独立性;

  6. 合理划分模块的大小,避免模块过大;

  7. 在设计的顶层(top)模块,将I/O口、Boundary scan电路、以及设计逻辑(corelogic)区分开。


十二、同步设计规则

  1. 同一个module中,要在时钟信号的同一个沿动作;

  2. 如果必须使用时钟上升沿和时钟下降沿,则要分两个module设计;

  3. 在顶层模块中,时钟信号必须可见,不在模块内部生成时钟信号,而要使用DCM/PLL产生的时钟信号;

  4. 避免使用门控时钟和门控复位;

  5. 同步复位电路,建议在同一时钟域使用单一的全局同步复位电路;

    异步复位电路,建议使用单一的全局异步复位电路;

  6. 不在时钟路径上添加任何buffer;

  7. 不在复位路径上添加任何buffer;

  8. 避免使用latch;

  9. 寄存器的异步复位和异步置位信号不能同时有效;

  10. 避免使用组合反馈电路;

  11. always有且仅有一个的敏感事件列表,敏感事件列表要完整,否则可能会造成前后仿真的结果不一致;

  12. 异步复位情况下需要异步复位信号和时钟沿做敏感量,同步复位情况下只需要时钟沿做敏感量;

  13. 时钟事件的表达式要用:

    “negedge

    “posedge”的形式;

  14. 复杂电路将组合逻辑和时序逻辑电路分成独立的always描述。


十三、循环语句规则

  1. 在设计中不推荐使用循环语句;

  2. 在非常有必要使用的循环语句时,可以使用for语句。


十四、约束规则

  1. 对所有时钟频率和占空比都进行约束;

  2. 对全局时钟skew进行约束;

  3. 对于时序要求的路径需要针对特殊要求进行约束,如锁相环鉴相信号;

  4. 要根据输出管脚驱动要求进行约束,包括驱动电流和信号边沿特性;

  5. 要根据输入和输出信号的特性进行管脚上下拉约束;

  6. 针对关键I/O是否约束了输入信号和输入时钟的相位关系,控制输入信号在CLK信号之后或之前多少ns到达输入pad;

  7. 综合设置时,fanout建议设置为3030;

  8. 要使用输入输出模块中的寄存器,如Xinlinx公司的IOB,map properties选项pack I/O register/latches into IOBsactor需要设置成为“for input and output”,这样可以控制管脚到内部触发器的延时时间;

  9. 布局布线报告中IOB、LUTs、RAM等资源利用率应小于百分之八十;

  10. 对于逻辑芯片对外输入接口,进行tsu/th约束;对于逻辑芯片对外输出接口,进行约束。


十五、PLL/DCM

  1. 如果使用FPGA内部DCM和PLL时,应该保证输入时钟的抖动小于300ps,防止DCM/PLL失锁;如果输入时钟瞬断后必须复位PLL/DCM。

  2. 对于所有厂家的FPGA,其片内锁相环只能使用同频率的时钟信号进行锁相,如果特殊情况下需要使用不同频率的信号进行锁相,需要得到厂家的认可,以避免出时钟。


十六、代码编辑

由于不同编辑器处理不同,对齐代码使用空格,而不是tab键。


***可综合和不可综合详解***

(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。
(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。


建立可综合模型的原则
要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:
(1)不使用initial。
(2)不使用#10。
(3)不使用循环次数不确定的循环语句,如forever、while等。
(4)不使用用户自定义原语(UDP元件)。
(5)尽量使用同步方式设计电路。
(6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。
(7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。
(8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。
(9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。
(10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。
(11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。
(12)避免混合使用上升沿和下降沿触发的触发器。
(13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。
(14)避免在case语句的分支项中使用x值或z值。


1、initial
只能在test bench中使用,不能综合。(我用ISE9.1综合时,有的简单的initial也可以综合,不知道为什么)
2、events
event在同步test bench时更有用,不能综合。
3、real
不支持real数据类型的综合。
4、time
不支持time数据类型的综合。
5、force 和release
不支持force和release的综合。
6、assign 和deassign
不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。
7、fork join
不可综合,可以使用非块语句达到同样的效果。
8、primitives
支持门级原语的综合,不支持非门级原语的综合。
9、table
不支持UDP 和table的综合。
10、敏感列表里同时带有posedge和negedge
如:always @(posedge clk or negedge clk) begin...end
这个always块不可综合。
11、同一个reg变量被多个always块驱动
12、延时
以#开头的延时不可综合成硬件电路延时,综合工具会忽略所有延时代码,但不会报错。
如:a=#10 b;
这里的#10是用于仿真时的延时,在综合的时候综合工具会忽略它。也就是说,在综合的时候上式等同于a=b;
13、与X、Z的比较
可能会有人喜欢在条件表达式中把数据和X(或Z)进行比较,殊不知这是不可综合的,综合工具同样会忽略。所以要确保信号只有两个状态:0或1。
如:
1 module synthesis_compare_xz (a,b);
2 output a;
3 input b;
4 reg a;
5
6 always @ (b)
7 begin
8 if ((b == 1'bz) || (b == 1'bx)) begin
9 a = 1;
10 end else begin
11 a = 0;
12 end
13 end
14
15 endmodule


以上是个人整理出来的一些设计规范,有些部分有重复,但无伤大雅,适用于FPGA Verilog HDL设计,VHDL的话设计思想是一样,大同小异,大家可以举一反三,今天就聊到这里,感谢并祝好。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
收藏 人收藏

    评论

    相关推荐

    110kv变电站设计规范

    110kV变电站设计规范涉及多个方面,包括选址、电气设计、设备选择、安全保护等。以下是根据相关规范和标准整理的一些主要设计规范: 一、总则 目的与范围 :规范适用于电压为35~110k
    的头像 发表于 09-26 09:32 1786次阅读

    pcb设计中有哪些常用设计规范

    在PCB(Printed Circuit Board,印刷电路板)设计中,常用的设计规范涉及多个方面,以确保电路板的性能、可靠性、可制造性和可维护性。以下是一些主要的设计规范: 一、电气设计规范
    的头像 发表于 09-02 14:51 802次阅读

    光伏储能系统设计规范 光伏储能系统设计的难点有哪些

    储能系统的设计规范进行详细阐述,并分析设计过程中可能遇到的难点。 光伏储能系统设计规范 2.1 系统容量设计 系统容量设计是光伏储能系统设计的基础,需要根据用户需求、地理位置、气候条件等因素进行综合考虑。具体包括:
    的头像 发表于 05-24 14:58 1231次阅读

    FPGA研发设计相关规范(很实用)

    今天和大侠聊一聊FPGA研发设计相关规范,养成良好的个人习惯,代码设计风格等,都有助于日后发展。有哪些设计规范,从文档到工程建立等,聊一聊也许你会学到很多东西,少走很多弯路哦。话不多说,上货。 在
    发表于 05-13 15:39

    Xilinx Zynq-7000嵌入式系统设计与实现

    今天给大侠带来Xilinx Zynq-7000嵌入式系统设计与实现,话不多说,上货。 Xilinx的ZYNQ系列FPGA是二种看上去对立面的思想的融合,ARM处理器的串行执行+FP
    发表于 05-08 16:23

    FPGA研发设计相关规范(很实用)

    今天和大侠聊一聊FPGA研发设计相关规范,养成良好的个人习惯,代码设计风格等,都有助于日后发展。有哪些设计规范,从文档到工程建立等,聊一聊也许你会学到很多东西,少走很多弯路哦。话不多说,上货
    发表于 04-16 15:42

    Xilinx Zynq-7000嵌入式系统设计与实现

    今天给大侠带来Xilinx Zynq-7000嵌入式系统设计与实现,话不多说,上货。 Xilinx的ZYNQ系列FPGA是二种看上去对立面的思想的融合,ARM处理器的串行执行+FP
    发表于 04-10 16:00

    干货!原理图设计规范133条checklist

    原理图设计是产品设计的理论基础,设计一份规范的原理图对设计PCB、跟机、做客户资料具有指导性意义,是做好一款产品的基础。原理图设计基本要求: 规范、清晰、准确、易读。因此制定《原理图设计规范》的目的
    发表于 04-01 15:50

    中兴ZTE内部电路设计规范【硬件干货】

      编号 级别 条目内容 备注 1 规定 原理图必须采用公司统一原理图库。   2 规定 原理图应采用0.100栅格   3 规定 原理图正文字体设置参照原理图设计规范,采用默认设置。说明文字为
    的头像 发表于 02-25 15:09 824次阅读
    中兴ZTE内部电路<b class='flag-5'>设计规范</b>【硬件干货】

    PCB layout在布线上的设计规范有哪些?

    一站式PCBA智造厂家今天为大家讲讲pcb layout设计需要注意哪些细节?pcb layout设计规范。Printed Circuit Board (PCB)是一种电子零件,它是连接电子器件,如
    的头像 发表于 02-23 09:19 860次阅读

    解读PCB设计规范

    规范规定了我公司 PCB 设计流程和设计原则,为 PCB 设计人员提供必须遵循的规则和约定。
    的头像 发表于 01-12 11:06 2328次阅读
    解读PCB<b class='flag-5'>设计规范</b>

    FPGA的片内资源

    FPGA的片内资源
    发表于 01-08 22:12

    华为印制电路板(PCB)设计规范

    电子发烧友网站提供《华为印制电路板(PCB)设计规范.pdf》资料免费下载
    发表于 01-02 10:44 43次下载

    印制电路板设计规范

    电子发烧友网站提供《印制电路板设计规范.pdf》资料免费下载
    发表于 01-02 10:37 6次下载

    单通道双输出LED灯光控制触摸芯片DL103W应用之PCB设计规范

    单通道双输出LED灯光控制触摸芯片DL103W应用之PCB设计规范,详细介绍了相关的设计注意事项
    的头像 发表于 12-27 09:12 1082次阅读
    单通道双输出LED灯光控制触摸芯片DL103W应用之PCB<b class='flag-5'>设计规范</b>