非常好的Verilog设计经验谈
Verilog 的学习心得.

1.数字电路基础知识:布尔代数、门级电路的内部晶体管结构、组合逻辑电路分析与设计、触发器、时序逻辑电路分析与设计2.数字系统的构成:传感器AD 数字处理器DA 执行部件3.程序通在硬件上的执行过程:C语言(经过编译-->该处理器的机器语言(放入存储器-->按时钟的节拍,逐条取出指令、分析指令、执行指令4.DSP处理是个广泛概念,统指在数字系统中做的变换(DFT、滤波、编码解码、加密解密、压缩解压等处理5.数字处理器包括两部分:高速数据通道接口逻辑、高速算法电路逻辑6.当前,IC产业包括IC制造和IC设计两部分,IC设计技术发展速度高于IC 设计7.FPGA设计的前续课程:数值分析、DSP、C语言、算法与数据结构、数字电路、HDL语言计算机微体系结构8.数字处理器处理性能的提高:软件算法的优化、微体系结构的优化9.数字系统的实现方式:编写C程序,然后用编译工具得到通用微处理器的机器指令代码,在通用微处理器上运行(如8051/ARM/PENTUIM专用DSP硬件处理器用FPGA硬件逻辑实现算法,但性能不如ASIC用ASIC实现,经费充足、大批量的情况下使用,因为投片成本高、周期长10.FPGA设计方法:IP核重用、并行设计、层次化模块化设计、top-down 思想FPGA设计分工:前端逻辑设计、后端电路实现、仿真验证11.matlab的应用:matlab中有许多现成的数学函数可以利用,节省了复杂函数的编写时间matlab 可以与C程序接口做算法仿真和验证时能很快生成有用的数据文件和表格DSP builder可以直接将simulink模型转换成HDL代码,跳过了中间的C 语言改写步骤12.常规从算法到硬件电路的开发过程:算法的开发C语言的功能描述并行结构的C语言改写verilog的改写仿真、验证、修正综合、布局布线、投入实用13.C语言改写成verilog代码的困难点:并行C语言的改写,因为C本身是顺序执行,而不是并行执行不使用C语言中的复杂数据结构,如指针目前有将C语言转换成verilog的工具?14.HDLHDL描述方法是从电路图描述方法演化来的,相比来说更容易修改符合IEEE标准的有verilog HDL和VHDLVHDL由美国国防部开发,有1987和1993两个版本verilog由cadence持有,有1995、2001、2005三个版本verilog较VHDL更有前景:具有模拟电路描述能力、不仅可以开发电路还可以验证电路、门级以下描述比VHDL强RTL级和门级的综合已经成熟,主要是注意行为级的综合结果,使用可综合的编程风格SYSTEM VERILOG是VERILOG的一种延伸15.IP核的应用:软核soft core:功能经过验证的、可综合的、实现后门数在5K以上的HDL代码固核firm core:功能经过验证的、可综合的、实现后门数在5K以上的电路结构编码文件,如edif,不可更改硬核hard core: 功能经过验证的、可综合的、实现后门数在5K以上的电路结构版图,已带工艺参数,不可更改16.HDL语言综合后得到EDIF,这是一种标准电路网表EDIF经过具体工艺库匹配、布局布线、延时计算后得到网表EDIF不可更改,作为固核存在17.verilog特点:区分大小写,所有关键字都要求小写不是强类型语言,不同类型数据之间可以赋值和运算//是单行注释可以跨行注释描述风格有系统级描述、行为级描述、RTL级描述、门级描述,其中RTL级和门级别与具体电路结构有关,行为级描述要遵守可综合原则门级描述使用门级模型或者用户自定义模型UDP来代替具体基本元件,在IDE 中针对不同FPGA器件已经有对应的基本元件原语18.verlog语法要点:module endmodule之间由两部分构成:接口描述和逻辑功能描述IO端口种类:input output inout相同位宽的输入输出信号可以一起声明,input[3:0] a,b; 不同位宽的必须分开写内部信号为reg类型,内部信号信号的状态:0 1 x z,3'bx1=3'bxx1 x/z会往左扩展3'b1=3'b001 数字不往左扩展逻辑功能描述中常用assign描述组合逻辑电路,always既可以描述组合逻辑电路又可以描述时序逻辑电路,还可以用元件调用方法描述逻辑功能always之间、assign之间、实例引用之间以及它们之间都是并行执行, always内部是顺序执行常量格式:<+/-><二进制位宽><'><进制><该进制的数值>:默认进制为10进制默认位宽为32位位宽是从二进制宽度角度而言的由位宽决定从低位截取二进制数2'hFF=2'b11,通常由被赋值的reg变量位宽决定parameter常用于定义延迟和变量位宽,可用常量或常量表达式定义变量种类:wire reg memoryIO信号默认为wire类型,除非指定为reg类型wire可以用作任何输入输出端口wire包括input output inoutwire不带寄存功能assign赋值语句中,被赋值的信号都是wire类型assign之所以称为连续赋值,是因为不断检测表达式的变化reg类型可以被赋值后再使用,而不是向wire一样只能输出,类似VHDL 中的buffer端口reg类型变量初始值为x (VHDL中初始值为本类型最小值,通常是0always模块里被赋值的信号都必须定义为reg类型,因为always可以反复执行,而reg表示信号的寄存,可以保留上次执行的值reg类型变量与integer变量不同,即使赋负值,实质上也是按二进制无符号数存储的,integer是有符号数verilog中所有内部信号都是静态变量,因为它们的值都在reg中存储起来了memory型只有一维数组,由reg型变量组成memory初始化只能按地址赋值,不能一次性赋值1*256的memory写法:reg mema[255:0] mema[3]=0;不同位宽的变量之间赋值,处理之前都以被赋值的变量位宽为准扩展或截取A[a:b] 无论a b谁大,a总是实际电路的信号高位,b总是实际电路的信号低位算术运算中如果有X值则结果为Xfor循环中的变量另外定义成integer,因为它不是实际信号,有正负; reg则以无符号数存在== 和!=只比较0、1,遇到z或x时结果都为x (x在if中算做假条件,结果可能是1、0、x===和!==比较更加苛刻,包括x和z的精确比较,结果可能是0、1&&的结果只有1'b1或1'b0两种,A&A的结果位宽则是与A相同的{1,0}为64'h100000000,所以拼接运算中各信号一定要指定位宽移位运算左移将保留4'b1000<<1等于5'b10000,右移则舍弃4'b0011<<1等于4'b0001数字电路里位运算应用普遍,包括按位逻辑运算、移位运算、拼接运算、缩减运算非阻塞式赋值<=与阻塞式赋值=阻塞:在同一个always过程中,后面的赋值语句要等待前一个赋值语句执行完,后面的语句被该赋值语句阻塞非阻塞:在同一个always过程中,非阻塞赋值语句是同时进行的,排在后面的语句不会被该赋值语句阻塞<=:块结束后才能完成赋值块内所有<=语句在always块结束时刻同时赋值<=右边各变量的值是上一次时钟边沿时,这些变量当时的值用于描述可综合的时序电路=:=语句结束之后过程always才可能结束在always过程中,begin end块内按先后顺序立即赋值,在fork join 内同时赋值(可能造成冲突与assign连用描述组合电路begin end中阻塞的含义:begin ...@(A B=C...; end 如果A 事件不发生则永远不能执行下去,被阻塞了由于时钟的延时(往往在ps级,多个always(posedge之间究竟谁先执行是个未知数使用原则:同一个always过程块内建立时序电路用<=纯组合逻辑电路用=,生成的电路结构最简单,执行速度最快同一个always块内不要混用<=和=不要在多个always块内对同一个变量赋值(多源驱动 if else的三种形式,第三种形式适合描述优先编码器if条件中0/x/z当成假,1当成真,非0的数值也当成真case语句的三种:case(四种状态的比较 casez(忽略z casex(忽略x 和z,只看哪些位的信号有用case语句中所有表达式值的位宽必须相等,default中不能将n'bx用'bx代替避免生成锁存器的方法:电平触发时if后加else case中加default ?使用casex会将不必要的状态视为无关项,使得综合出来的电路最简单两种特殊的括号:begin 顺序语句... end fork 并行语句... join,其差别在于块内语句的起止时间、执行顺序、相对延时块被命名后,其内部变量可以被调用,因为变量都是静态的(调用信号:对应电路中的一个信号线被引到另一处initial块只无条件执行一次always块在满足条件时不断执行initial常用来写测试文件,always块常用来写电路描述always既可以描述组合逻辑电路又可以描述时序逻辑电路always如果后面有敏感信号列表则不能用wait语句always既可以描述电平触发又可以描述边沿触发,wait只能描述电平触发assign 常用于描述组合逻辑电路测试文件中一般都是现initial 后always生成语句:生成快的本质是使用循环内的一条语句代替多条重复的verilog语句,简化了用户的编程genvar用于声明生成变量,生成变量只能用在生成快之间仿真时,仿真器会将生成块中的代码展平,在确立后的方针代码中,生成变量是不存在的最好是先想象出来循环生成语句被展平后的电路样子,再写相关的描述语句task和function的区别:task可以定义自己的仿真时间单位,function与主模块共用同一个仿真时间单位函数不能启动任务,任务能够启动函数函数至少要有一个输入变量,任务没有输入变量函数返回一个值,任务不返回值一个模块的设计包括3个部分:电路模块的设计测试模块的设计设计文档的编写设计者通过布局布线工具生成具有布线延迟的电路,再进行后仿真,得到时序分析报告从时序分析报告中可以知道电路的实际延迟t,同步电路内每个时钟周期要大于t,从而可确定该运算逻辑的最高频率综合器之所以能够实现加法器、乘法器是因为库中已经存在可配置的参数化器件模型FPGA内总线宽度容易自定义,以便实现高速数据流,三态数据总线相当于数据流的控制阀门数字系统内数据流的控制:开关(或三态数据总线、数据暂存部件(寄存器、同步状态机控制(整个系统在一个时钟域内流水线操作pipe line:K级流水线就是从组合逻辑的输入到输出恰好有K个寄存器组,上一级的输出是下一级的输入流水线操作获得第一个结果的时间要比不用流水线操作的时间长,但以后结果获得时间都只需要一个时钟周期,提高了数据吞吐量流水线操作的保证:Tclk>K*(组合逻辑延迟+触发器的建立保持时间/触发时间,即时间片段要长于最大路径延迟体现了面积换速度的思想,在综合时考虑的是以面积小为主还是以速度为主本质上是一种同步逻辑同步时序逻辑和异步时序逻辑:同步时序逻辑指所有寄存器组由唯一时钟触发 always@(posedge clk 或always@(negedage clk 异步时序逻辑指触发条件不唯一,任意一个条件都会引起触发 always@(posedge clk or posedage reset 目前的综合器是以同步时序逻辑综合的,因为同步时序逻辑较异步时序逻辑可靠严格的同步要求时钟信号传递速度远远大于各部分的延迟,实际中clk要单独用线,而不要经过反相器等部件 always @(posedge.. begin ...<=... end 表示同步时序逻辑(同时刻赋值不同速率数据接口的处理方法(异步数据的处理方法:帧同步 FIFO 双端口RAM 同步状态机:包括moore和mealy型两种,及其反馈模型(是一种反馈控制系统,当前状态就是其内部状态变量状态机的开发步骤:根据实际问题列出输入输出变量和状态数画出状态图并化简写出状态转移真值表得到逻辑表达式用D触发器或JK触发器构建电路(目前用D触发器多 verilog描述时只需要得到简化的状态图就可以描述状态编码方式:独热码格雷码状态机主体程序有单always描述方式和多always描述方式采用case/casez/casex建立模型最好,因为x是无关态,生成的电路最简单 default: state='bx与实际情况更一致,效果等同于 default: state<=idle 只有同步状态机才能被目前的综合 for 语句会将所有变量的情况展开,占用巨量逻辑资源,替代办法是用计数器和 case 语句说明所有情况有优先级的 if else 结构会消耗更多资源,建议用无优先级的 case 替代模块的复用往往比代码上修改节省的资源多 PLL 的分频、倍频、移相操作会增加设计精度同步时序电路的延时:#x 通常用于仿真测试,实际硬件延时是:长延迟用计数器,小延迟用 D 触发器,此方法用来取代延迟链同步电路中,稳定的数据采用必须满足采样寄存器的建立和保持时间 reg 类型在 always 中不一定综合成时序电路,也可能是组合逻辑电路乒乓操作与作用异步时钟域同步问题延迟包括门延迟和线延迟组合逻辑产生的时钟仅能应用在时钟频率较低、精度要求不高的情况下增减敏感信号得到的结果一样补充部分: verilog HDL 起初是作为写 testbench 而产生的 verilog 有 1995 进入 IEEE 标准,为 IEEE-1364, 于 2001 年进行了扩展,为 IEEE 1364-2001; verilog AMS 可用于模拟电路和数字电路的综合,目前正在不断发展和完善中; verilog 的标识符区分大小写,关键字使用小写;用\\来进行单行注释,用\* *\来进行跨行注释;标识符由字母、数字、下划线构成,并以字母开头;关键字又叫保留字,只有小写的关键字才是保留字;信号的状态有 4 种: 0 1 x z x 和 z 在描述电路时不区分大小写,在仿真时大小写有不同意义;常量表达式中: x z 不区分大小写;进制符号 h o d b 与 H O D B 不区分大小写;十六进制中 a~f 不区分大小写;下划线_用于提高可读性;?在数中可以代替 z; x 和 z 的左端补位;字符和字符串都以 ASICII 码形式存在,也可以当成电路内的信号;字符串必须包含在同一行,不能分成多行书写;如果表达式或者赋值语句中将字符串当成操作数,则字符串中的每个字符都被看成 8 位的 ASCII 值序列;可综合的信号类型:wire reg memory 它们用来描述数字电路不可综合的数据类型:integer real 它们只用仿真,位于testbench 中 wire 是连线的抽象模型,不能保存数据,其值由驱动元的值决定;wire 不能用在 always 或 initial 块中; wire 的默认值为高阻 z; wire 的使用情形:1.作为模块的输出端口 2.用连续赋值语句 assign 赋值; reg 是 1 位寄存器(触发器)的抽象模型,可以保存数据; reg 必须用在 always 或 initial 块中; reg 的默认值为 x; reg 的使用情形:1.阻塞赋值<= 2.非阻塞赋值= memory 只能是一维的;memory 只能对每个单元分别初始化,方法:1.一个一个赋值 2. 通过系统任务$readmem 赋值 reg[3:0] fc;//一个 4 位寄存器 reg fc[3:0] //4 个一位寄存器 parameter的作用:仿真开始以前对其进行赋值,整个仿真过程中保持其值不变;关系运算符将以逻辑 1 或逻辑 0 返回比较的结果; == !=的返回值有 0 1 x 三种情况,=== !==的返回值只有 0 1 两种情况; verilog 由于是描述电路的,用于位的操作较多,有: 位逻辑操作,移位操作,并置操作,归约操作;位逻辑运算的结果中,位数与原操作数一样多;归约符是在原操作数的所有位上进行操作,并产生 1 位结果;并置运算可以发生在 bit 与 bit 之间 bit 与矢量之间矢量与矢量之间用于仿真的系统任务:所有系统任务都必须在 initial 或 always 内;所有系统任务都必须以$开头;常见系统任务:显示任务($diplay 系列和$write 系列监控任务($monitor 系列探测任务($strobe 系列文件打开、输入、关闭任务(&fopen &fclose &fdisplay... 读取文件任务($readmemb $readmemh 仿真结束控制任务($finish $stop 随即信号任务($random 过程块: initial 块和 always 块一个 module 内可以包含多个 initial 或always 模块;所有 initial 或 always 块在 0 时刻开始并行执行,各 initial 或 always 块内部顺序执行; initial 过程块主要是面向 testbench 的,通常不具有可综合性;always 过程块在描述电路时既可以描述组合逻辑电路(电平敏感又可以描述时序逻辑电路(边沿敏感;写 testbench 时 initial 通常用于初始化以及顺序波形的描述,always 通常用于重复波形的描述;任务 task 与函数 function: 为了描述模块中被多次执行的部分以及为了增强代码的易读性 verilog 中的高级程序语句如 for 循环语句只用在写 testbench 中; begin end 和 fork join 是两种特殊的括号 if 语句的第三种形式适合描述优先编码器,case 语句适合描述数据选择器和状态机;case 的条件表达式如果与分支项表达式长度不同,则在比较前将所有表达式都统一为这些表达式的最长长度; casez 忽略 z,casex 忽略 z 和 x; assign 语句只在右端表达式发生变化时才重新计算并重新赋值,其余时间都是连续赋值; assign 语句可以指定 bit、vector 或是任意拼接操作的结果; assign 语句是连续赋值的,用于驱动网线 wire, reg 类型不需要连续赋值, reg 类型一旦被赋值就会一直保存;过程赋值语句有两种:阻塞式=和非阻塞式<=,只能在过程块 initial 和always 中使用; @对事件触发的控制与 wait 语句不能同时使用;。
verilog组合电路的设计

Verilog 是一种硬件描述语言 (HDL),广泛应用于数字电路设计中。
在Verilog 中,组合电路是一种重要的设计模块,它由一系列逻辑门和时序元件组成,能够实现特定的逻辑功能。
本文将介绍 Verilog 组合电路的设计原理、方法和实践经验,旨在帮助读者深入了解 Verilog 组合电路设计的核心概念和技术要点。
【内容概要】1. Verilog 组合电路设计概述2. Verilog 组合电路的建模与描述3. Verilog 组合电路的仿真与验证4. Verilog 组合电路设计案例分析5. Verilog 组合电路设计的未来发展趋势【正文】1. Verilog 组合电路设计概述Verilog 是一种硬件描述语言,它提供了丰富的语法和功能,能够描述数字电路中的各种逻辑元件和时序元件,包括组合电路、时序电路和FSM 等。
在 Verilog 中,组合电路是一种重要的设计模块,它由逻辑门、数据选择器、多路器、解码器等逻辑元件组成,能够实现特定的逻辑功能。
在数字电路设计中,组合电路通常用于实现各种逻辑运算和逻辑控制功能,如加法器、减法器、乘法器、除法器、逻辑门、数据选择器、编码器和解码器等。
2. Verilog 组合电路的建模与描述在 Verilog 中,组合电路可以通过行为建模或结构建模的方式进行描述。
行为建模是指根据组合电路的逻辑功能和特性,使用逻辑表达式、真值表或状态转换图等形式描述其逻辑行为。
结构建模是指根据组合电路的硬件结构和连接关系,使用逻辑门、数据选择器、多路器、解码器等硬件元件的实例化描述其物理结构。
在进行 Verilog 组合电路建模时,应根据具体的设计目标和需求选择合适的建模方式,并遵循Verilog 语言的语法规范和设计规范,确保描述的准确性和完整性。
3. Verilog 组合电路的仿真与验证Verilog 组合电路的仿真与验证是设计过程中至关重要的一环,它能够帮助设计工程师验证电路功能是否符合设计要求,发现和解决潜在的设计缺陷和错误。
每天多学一点:Verilog编写技巧(一)

每天多学一点:Verilog编写技巧(一)来源:网路素材好的设计者一般都要对电路要实现的功能有清晰的认识,对数据流很清楚,知道数据如何从一个点移动到另一个点,这就是所谓的“勾划”(walk-through)。
一旦设计蓝图在脑海中变得清晰,此后釆用Verilog编写数据路径和控制逻辑就会变得思路清晰。
脑海中的模拟正如大多数人玩过的象棋游戏,我们都知道提前谋划是何等重要,要在下一次移动棋子之前考虑好此后的几步棋应该怎么走,以确保不会出错,不被对手捕捉到机会。
电路设计过程与下棋非常相似。
当设计状态机、数据路径或者控制逻辑时,我们知道它们的功能。
在进行设计仿真之前,我们需要思考代码在不同输入和边界条件下如何工作。
如果用心去做好这一步工作,并且分析可能出现的问题,验证工作将会变得非常高效。
另外,这一步也给我们建立了自信,使我们确信整个设计非常扎实,可以很好地工作。
否则很可能出现的情况是在验证阶段反复发现问题并进行电路修改,不断进行补救T.作,并且最终也不能确定设计足否还隐含着没有被发现的问题。
哪种风格—数据流或算法描述组合逻辑有两种方式—使用wire(对应数据流描述方式)或者使用reg(对应算法描述方式)。
这两种方式都能实现相同的逻辑功能,综合后得到相同的门电路,具体使用哪一种方式可以根据个人喜好。
数据流—短表达式举例wire [7:0] regl0_nxt;assign regl0_nxt = wren ? data_in : regl0;算法—短表达式举例reg [7:0] regl0_nxt;always @(*) beginreglO_nxt = reglO;if (wren)regl0_nxt = data_in;end当表达式非常简单时,一般更倾向于使用数据流风格来实现,此时代码行数很少。
然而,当表达式很长并且与很多条件有关时,数据流风格阅读起来较为费力。
此时可以使用算法风格,可以采用if-else 语句进行描述,以易于阅读和减少错误发生。
数字设计中的Verilog语法调整技巧

数字设计中的Verilog语法调整技巧数字设计是现代电子领域中的重要技术之一,Verilog作为一种硬件描述语言,在数字设计中扮演着至关重要的角色。
Verilog语法的准确使用和调整是数字设计过程中的关键一环,下面将从几个方面介绍数字设计中的Verilog语法调整技巧。
首先,在编写Verilog代码时,合理的模块化设计是至关重要的。
通过将整个设计划分为多个模块,可以提高代码的复用性和可维护性。
在模块化设计中,可以使用模块实例化的方式来调用其他模块进行功能实现。
此外,在模块内部也可以进一步进行代码块的划分,提高代码的清晰度和可读性。
其次,对于Verilog语法中的信号赋值,需要合理地选择适合的赋值方式。
在Verilog中,有非阻塞赋值和阻塞赋值两种方式。
对于时序逻辑的描述,通常使用非阻塞赋值,以保证设计在时钟信号的作用下按时序执行;而对于组合逻辑的描述,通常使用阻塞赋值。
正确选择赋值方式可以有效避免由于信号赋值顺序导致的逻辑错误。
另外,在Verilog语法中,对于always块的使用也需要注意一些技巧。
always块是描述Verilog代码的执行顺序的重要部分,其中的敏感列表决定了代码块的执行触发条件。
在编写always块时,需要确保敏感列表中覆盖了所有的输入信号,以避免遗漏导致的逻辑错误。
另外,在时序逻辑设计中,需要使用posedge(上升沿触发)或negedge(下降沿触发)来确保时钟信号的正确触发。
此外,当涉及到多位宽信号的处理时,需要注意Verilog语法中的位操作技巧。
Verilog中提供了丰富的位操作符号,如与(&)、或(|)、异或(^)等,可以方便地实现多位宽信号的逻辑运算。
同时,也可以通过拼接符号{ }来对多位宽信号进行连接或分割,非常适合处理复杂的数据结构。
最后,在Verilog代码的调试和优化过程中,合理利用仿真工具是至关重要的。
通过仿真工具可以实时观察信号波形,验证代码的正确性和功能实现情况。
verilog分享 verilog快速掌握之模块例化

verilog快速掌握之模块例化一、什么是例化1)FPGA逻辑设计中通常是一个大的模块中包含了一个或多个功能子模块,verilog通过模块调用或称为模块实例化的方式来实现这些子模块与高层模块的连接,有利于简化每一个模块的代码,易于维护和修改。
2)如下图,当有了例化的方法之后,当模块中需要两个同样功能的USB模块时,我们只需要编写好一个usb模块的代码,之后通过例化,就可以将俩个usb模块添加到顶层模块之中。
(注意,我们要有硬件思维,例化一个模块,那么就有一个硬件与之对应。
例化多个,就有多个硬件。
)二、例化方法1)首先我们设计好我们需要的功能模块,如下图左边的uart模块;2)之后我们在大模块例化uart模块,如下图右边的例化格式,信号列表中“.”之后的信号是uart模块定义的信号,括号内的信号则是在大模块中申明的信号,这样就将大模块的信号与uart模块信号一一对应起来。
三、参数例化1) 模块例化还有一个好处就是在调用的时候还可以传递/改变参数。
如下图,我们设计了一个uart模块,他的数据位宽只有8位,但是如果我们需要一个16位宽的uart模块,这时候我们可以通过参数例化来减少重新编写模块的工作量。
2)我们定义数据位宽为DATA_W=83)在例化的时候我们可以如下图,在模块名后面加上“#(.DATA_W(16))”,就可以将数据位宽定义为16位。
注意,大家务必掌握参数传递的方法,点拨FPGA课程后面有一部分练习要计时到1秒时间,如果modelsim真的要仿真1秒,跑一个用例就要花费好几分钟或者几个小时,这样的低效率是难以忍受的。
我们仿真时,在测试文件改变1秒的参数值,将它变得很小,这样就能加快仿真迅速。
详细情况,学到相应章节自然会清楚的。
Verilog设计小技巧

Verilog(FPGA/CPLD)设计小技巧(来自Xilinx)这是一个在设计中常犯的错误列表这些错误常使得你的设计不可靠或速度较慢为了提高你的设计性能和提高速度的可靠性你必须确定你的设计通过所有的这些检查可靠性**为时钟信号选用全局时钟缓冲器BUFG• 不选用全局时钟缓冲器的时钟将会引入偏差 。
**只用一个时钟沿来寄存数据• 使用时钟的两个沿是不可靠的因为时钟的某沿或者两个沿会漂移; 如果时钟有漂移而且你只使用了时钟的一个沿你就降低了时钟边沿漂移的风险。
• 这个问题可以这样来解决就是允许CLKDLL自动纠正时钟的占空比以达百分之五十的占空比否则强烈建议你只使用一个时钟沿**除了用CLKDLL或DCM产生的时钟外不要在内部产生时钟.• 这包括产生门控时钟和分频时钟• 作为替代可以建立时钟使能或使用CLKDLL或DCM来产生不同的时钟信号。
• 对于一个纯同步设计建议你在任何可能的情况下只使用一个时钟**不要在内部产生异步的控制信号 例如复位信号或者置位信号• 内部产生的异步控制信号会产生毛刺• 作为替代可以产生一个同步的复位/置位信号这个信号的译码要比需要作用的时刻提前一个时钟周期**不要使用没有相位关系的多个时钟• 你也许并不总能避免这个条件在这些情况下确定你已使用了适当的同步电路来跨越时钟域**不要使用没有相位关系的多个时钟• 再次你也许并不总能避免这个条件相反许多设计都需要这样在这 些情况下确定你已适当地约束了跨越时钟域的路径**不要使用内部锁存器• 内部锁存器会混淆时序而且常常会引入另外的时钟信号• 内部锁存器在透明门打开时可以被看成是组合逻辑但在门被锁存时 可以被看成是同步元件这将会混淆时序分析• 内部锁存器常常会引入门控时钟门控时钟会产生毛刺使得设计变得不可靠性能**逻辑级的时延不要超过时序预算的百分之五十• 每个路径逻辑级时延可以在逻辑级时序报告或布局后时序报告中找到详细分析了每个路径之后时序分析器将生成每个路径时延的统计量检查一下总共的逻辑级时延超过了你的时序预算的百分之五十吗?**IOB 寄存器• IOB寄存器提供了最快的时钟到输出和输入到时钟的时延• 首先有一些限制对于输入寄存器在从管脚到寄存器间不能有组合逻 辑存在对于输出寄存器在寄存器和管脚之间也不能有组合逻辑存在对于三态输出在IOB 中的所有的寄存器必须使用同一个时钟信号和复位信号而且IOB三态寄存器必须低电平有效才能放到IOB中三态缓冲器低电平有效所以在寄存器和三态缓冲器之间不需要一个反相器• 你必须使软件能够选用IOB寄存器你可以设置全局实现选项为输入 输出或输入输出选择IOB寄存器缺省值为关(off)。
数字设计中的Verilog编程技巧

数字设计中的Verilog编程技巧在数字设计中,Verilog是一种常用的硬件描述语言,广泛应用于数字集成电路设计和仿真中。
Verilog编程技巧对于提高设计效率、优化性能和减少错误至关重要。
下面我将介绍几种Verilog编程技巧,帮助您更好地应用Verilog进行数字设计。
首先,合理使用模块化设计。
在Verilog中,模块是设计的基本单元,将复杂系统划分为多个模块可以提高可维护性和复用性。
因此,在设计过程中应该遵循模块化设计原则,将功能模块化、分层和相互独立。
其次,正确使用参数化。
在Verilog中,参数化是指通过参数来描述模块或信号的行为。
合理使用参数可以提高代码的灵活性和可复用性。
通过定义参数,可以轻松地调整模块的行为,使得代码更加通用和易扩展。
此外,熟练掌握Verilog中的时序控制。
时序控制是Verilog设计中的关键部分,用于描述时序逻辑和时序行为。
在设计过程中,需要注意时钟的约束和时序分析,确保设计的正确性和稳定性。
可以使用时钟域划分、时钟同步等技术来解决时序问题。
另外,注意Verilog中的模拟和仿真。
在数字设计中,模拟和仿真是验证设计正确性的重要步骤。
Verilog提供了Simulator工具,可以进行行为级仿真和波形仿真。
通过模拟和仿真可以验证设计是否符合预期,发现和修复设计中的问题。
最后,关注Verilog中的调试和优化。
在设计过程中,经常需要进行调试和优化,以确保设计满足性能和功耗要求。
Verilog提供了一些调试和优化技术,如添加断点、查看波形、进行逻辑分析等。
通过调试和优化可以找到设计中的问题,并对设计进行改进。
总的来说,Verilog编程技巧对于数字设计至关重要。
通过合理的模块化设计、参数化、时序控制、模拟和仿真、调试和优化,可以提高设计效率、优化性能和减少错误。
希望以上介绍的Verilog编程技巧能够帮助您在数字设计中取得更好的结果。
祝您在Verilog编程中取得成功!。
个人总结FPGA设计中Verilog编程的27条经验

个人总结Verilog编程27条经验1.强烈建议用同步设计;2.在设计时总是记住时序问题;3.在一个设计开始就要考虑到地电平或高电平复位、同步或异步复位、上升沿或下降沿触发等问题,在所有模块中都要遵守它;4.在不同的情况下用if和case,最好少用if的多层嵌套(1层或2层比较合适,当在3层以上时,最好修改写法,因为这样不仅可以reduce area,而且可以获得好的timing);5.在锁存一个信号或总线时要小心,对于整个design,尽量避免使用latch,因为在DFT时很难test;6.确信所有的信号被复位,在DFT时,所有的FlipFlop都是controllable;7.永远不要再写入之前读取任何内部存储器(如SRAM);8.从一个时钟到另一个不同的时钟传输数据时用数据缓冲,他工作像一个双时钟FIFO(是异步的),可以用Async SRAM搭建Async FIFO;9.在VHDL中二维数组可以使用,它是非常有用的。
在VERILOG中他仅仅可以使用在测试模块中,不能被综合;10.遵守register-in register-out规则;11.像synopsys的DC的综合工具是非常稳定的,任何bugs都不会从综合工具中产生12.确保FPGA版本与ASIC的版本尽可能的相似,特别是SRAM类型,若版本一致是最理想的,但是在工作中FPGA版本一般用FPGA自带的SRAM,ASIC版本一般用厂商提供的SRAM;13.在嵌入式存储器中使用BIST;14.虚单元和一些修正电路是必需的;15.一些简单的测试电路也是需要的,经常在一个芯片中有许多测试模块;16.除非低功耗不要用门控时钟,强烈建议不要在design中使用gate clock;17.不要依靠脚本来保证设计。
但是在脚本中的一些好的约束能够起到更好的性能(例如前向加法器);18.如果时间充裕,通过时钟做一个多锁存器来取代用MUX;19.不要用内部tri-state, ASIC需要总线保持器来处理内部tri-state,如IOcell;20.在top level中作pad insertion;21.选择pad时要小心(如上拉能力,施密特触发器,5伏耐压等),选择合适的IO cell;22.小心由时钟偏差引起的问题;23.不要试着产生半周期信号;24.如果有很多函数要修正,请一个一个地作,修正一个函数检查一个函数;25.在一个计算等式中排列每个信号的位数是一个好习惯,即使综合工具能做;26.不要使用HDL提供的除法器;27.削减不必要的时钟。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
时序是设计出来的我的boss有在华为及峻龙工作的背景,自然就给我们讲了一些华为及altera 做逻辑的一些东西,而我们的项目规范,也基本上是按华为的那一套去做。
在工作这几个月中,给我感触最深的是华为的那句话:时序是设计出来的,不是仿出来的,更不是湊出来的。
在我们公司,每一个项目都有很严格的评审,只有评审通过了,才能做下一步的工作。
以做逻辑为例,并不是一上来就开始写代码,而是要先写总体设计方案和逻辑详细设计方案,要等这些方案评审通过,认为可行了,才能进行编码,一般来说这部分工作所占的时间要远大于编码的时间。
总体方案主要是涉及模块划分,一级模块和二级模块的接口信号和时序(我们要求把接口信号的时序波形描述出来)以及将来如何测试设计。
在这一级方案中,要保证在今后的设计中时序要收敛到一级模块(最后是在二级模块中)。
什么意思呢?我们在做详细设计的时候,对于一些信号的时序肯定会做一些调整的,但是这种时序的调整最多只能波及到本一级模块,而不能影响到整个设计。
记得以前在学校做设计的时候,由于不懂得设计时序,经常因为有一处信号的时序不满足,结果不得不将其它模块信号的时序也改一下,搞得人很郁闷。
在逻辑详细设计方案这一级的时候,我们已经将各级模块的接口时序都设计出来了,各级模块内部是怎么实现的也基本上确定下来了。
由于做到这一点,在编码的时候自然就很快了,最重要的是这样做后可以让设计会一直处于可控的状态,不会因为某一处的错误引起整个设计从头进行。
==================================================================== 如何提高电路工作频率对于设计者来说,我们当然希望我们设计的电路的工作频率(在这里如无特别说明,工作频率指FPGA片内的工作频率)尽量高。
我们也经常听说用资源换速度,用流水的方式可以提高工作频率,这确实是一个很重要的方法,今天我想进一步去分析该如何提高电路的工作频率。
我们先来分析下是什么影响了电路的工作频率。
我们电路的工作频率主要与寄存器到寄存器之间的信号传播时延及clock skew有关。
在FPGA内部如果时钟走长线的话,clock skew很小,基本上可以忽略, 在这里为了简单起见,我们只考虑信号的传播时延的因素。
信号的传播时延包括寄存器的开关时延、走线时延、经过组合逻辑的时延(这样划分或许不是很准确,不过对分析问题来说应该是没有可以的),要提高电路的工作频率,我们就要在这三个时延中做文章,使其尽可能的小。
我们先来看开关时延,这个时延是由器件物理特性决定的,我们没有办法去改变,所以我们只能通过改变走线方式和减少组合逻辑的方法来提高工作频率。
1.通过改变走线的方式减少时延。
以altera的器件为例,我们在quartus里面的timing closure floorplan 可以看到有很多条条块块,我们可以将条条块块按行和按列分,每一个条块代表1个LAB,每个LAB里有8个或者是10个LE。
它们的走线时延的关系如下:同一个LAB中(最快) < 同列或者同行 < 不同行且不同列。
我们通过给综合器加适当的约束(不可贪心,一般以加5%裕量较为合适,比如电路工作在100Mhz,则加约束加到105Mhz就可以了,贪心效果反而不好,且极大增加综合时间)可以将相关的逻辑在布线时尽量布的靠近一点,从而减少走线的时延。
(注:约束的实现不完全是通过改进布局布线方式去提高工作频率,还有其它的改进措施)2.通过减少组合逻辑的减少时延。
上面我们讲了可以通过加约束来提高工作频率,但是我们在做设计之初可万万不可将提高工作频率的美好愿望寄托在加约束上,我们要通过合理的设计去避免出现大的组合逻辑,从而提高电路的工作频率,这才能增强设计的可移植性,才可以使得我们的设计在移植到另一同等速度级别的芯片时还能使用。
我们知道,目前大部分FPGA都基于4输入LUT的,如果一个输出对应的判断条件大于四输入的话就要由多个LUT级联才能完成,这样就引入一级组合逻辑时延,我们要减少组合逻辑,无非就是要输入条件尽可能的少,,这样就可以级联的LUT更少,从而减少了组合逻辑引起的时延。
我们平时听说的流水就是一种通过切割大的组合逻辑(在其中插入一级或多级D触发器,从而使寄存器与寄存器之间的组合逻辑减少)来提高工作频率的方法。
比如一个32位的计数器,该计数器的进位链很长,必然会降低工作频率,我们可以将其分割成4位和8位的计数,每当4位的计数器计到15后触发一次8位的计数器,这样就实现了计数器的切割,也提高了工作频率。
在状态机中,一般也要将大的计数器移到状态机外,因为计数器这东西一般是经常是大于4输入的,如果再和其它条件一起做为状态的跳变判据的话,必然会增加LUT的级联,从而增大组合逻辑。
以一个6输入的计数器为例,我们原希望当计数器计到111100后状态跳变,现在我们将计数器放到状态机外,当计数器计到111011后产生个enable信号去触发状态跳变,这样就将组合逻辑减少了。
上面说的都是可以通过流水的方式切割组合逻辑的情况,但是有些情况下我们是很难去切割组合逻辑的,在这些情况下我们又该怎么做呢?状态机就是这么一个例子,我们不能通过往状态译码组合逻辑中加入流水。
如果我们的设计中有一个几十个状态的状态机,它的状态译码逻辑将非常之巨大,毫无疑问,这极有可能是设计中的关键路径。
那我们该怎么做呢?还是老思路,减少组合逻辑。
我们可以对状态的输出进行分析,对它们进行重新分类,并根据这个重新定义成一组组小状态机,通过对输入进行选择(case语句)并去触发相应的小状态机,从而实现了将大的状态机切割成小的状态机。
在ATA6的规范中(硬盘的标准),输入的命令大概有20十种,每一个命令又对应很多种状态,如果用一个大的状态机(状态套状态)去做那是不可想象的,我们可以通过case语句去对命令进行译码,并触发相应的状态机,这样做下来这一个模块的频率就可以跑得比较高了。
总结:提高工作频率的本质就是要减少寄存器到寄存器的时延,最有效的方法就是避免出现大的组合逻辑,也就是要尽量去满足四输入的条件,减少LUT级联的数量。
我们可以通过加约束、流水、切割状态的方法提高工作频率。
===================================================================== ==============做逻辑的难点在于系统结构设计和仿真验证刚去公司的时候BOSS就和我讲,做逻辑的难点不在于RTL级代码的设计,而在于系统结构设计和仿真验证方面。
目前国内对可综合的设计强调的比较多,而对系统结构设计和仿真验证方面似乎还没有什么资料,这或许也从一个侧面反映了国内目前的设计水平还比较低下吧。
以前在学校的时候,总是觉得将RTL级代码做好就行了,仿真验证只是形式而已,所以对HDL的行为描述方面的语法不屑一顾,对testbench也一直不愿意去学--因为觉得画波形图方便;对于系统结构设计更是一点都不懂了。
到了公司接触了些东西才发现完全不是这样。
其实在国外,花在仿真验证上的时间和人力大概是花在RTL级代码上的两倍,现在仿真验证才是百万门级芯片设计的关键路径。
仿真验证的难点主要在于怎么建模才能完全和准确地去验证设计的正确性(主要是提高代码覆盖),在这过程中,验证速度也是很重要的。
验证说白了也就是怎么产生足够覆盖率的激励源,然后怎么去检测错误。
我个人认为,在仿真验证中,最基本就是要做到验证的自动化。
这也是为什么我们要写testbench的原因。
在我现在的一个设计中,每次跑仿真都要一个小时左右(这其实算小设计)。
由于画波形图无法做到验证自动化,如果用通过画波形图来仿真的话,一是画波形会画死(特别是对于算法复杂的、输入呈统计分布的设计),二是看波形图要看死,三是检错率几乎为零。
那么怎么做到自动化呢?我个人的水平还很有限,只能简单地谈下BFM (bus function model,总线功能模型)。
以做一个MAC的core为例(背板是PCI总线),那么我们需要一个MAC_BFM 和PCI_BFM及PCI_BM(PCI behavior model)。
MAC_BFM的主要功能是产生以太网帧(激励源),随机的长度和帧头,内容也是随机的,在发送的同时也将其复制一份到PCI_BM中;PCI_BFM的功能则是仿PCI总线的行为,比如被测收到了一个正确帧后会向PCI总线发送一个请求,PCI_BFM则会去响应它,并将数据收进来;PCI_BM的主要功能是将MAC_BFM发送出来的东西与PCI_BFM接收到的东西做比较,由于它具有了MAC_BFM的发送信息和PCI_BFM的接收信息,只要设计合理,它总是可以自动地、完全地去测试被测是否工作正常,从而实现自动检测。
华为在仿真验证方面估计在国内来说是做的比较好的,他们已建立起了比较好的验证平台,大部分与通信有关的BFM都做好了,听我朋友说,现在他们只需要将被测放在测试平台中,并配置好参数,就可以自动地检测被测功能的正确与否。
在功能仿真做完后,由于我们做在是FPGA的设计,在设计时已经基本保证RTL级代码在综合结果和功能仿真结果的一致性,只要综合布局布线后的静态时序报告没有违反时序约束的警告,就可以下到板子上去调试了。
事实上,在华为中兴,他们做FPGA的设计时也是不做时序仿真的,因为做时序仿真很花时间,且效果也不见得比看静态时序分析报告好。
当然了,如果是ASIC的设计话,它们的仿真验证的工作量要大一些,在涉及到多时钟域的设计时,一般还是做后仿的。
不过在做后仿之前,也一般会先用形式验证工具和通过静态时序分序报告去查看有没有违反设计要求的地方,这样做了之后,后仿的工作量可以小很多。
在HDL语言方面,国内语言很多人都在争论VHDL和verilog哪个好,其实我个人认为这并没有多大的意义,外面的大公司基本上都是用verilog在做RTL级的代码,所以还是建议大家尽量学verilog。
在仿真方面,由于VHDL在行为级建模方面弱于verilog,用VHDL做仿真模型的很少,当然也不是说verilog 就好,其实verilog在复杂的行为级建模方面的能力也是有限的,比如目前它还不支持数组。
在一些复杂的算法设计中,需要高级语言做抽象才能描述出行为级模型。
在国外,仿真建模很多都是用System C和E语言,用verilog的都算是很落后的了,国内华为的验证平台好像是用System C写。
在系统结构设计方面,由于我做的设计还不够大,还谈不上什么经验,只是觉得必须要具备一些计算机系统结构的知识才行。
划分的首要依据是功能,之后是选择合适的总线结构、存储结构和处理器架构,通过系统结构划分要使各部分功能模块清晰,易于实现。