之前介绍过了了芯片设计全流程介绍(芯片设计全流程详解 包括:正向流程和反向流程)。由于当时的经验十分有限,所以对于正向设计,特别是对于从RTL级代码开始的设计介绍得不是很清楚。经过这一段时间的学习,对于从RTL级代码开始的Asic芯片设计有了更多的认识,现在总结一下,一方面给自己整理思路,另一方面也希望抛砖引玉,让大家各抒己见,分享一下各自的设计经验,促进我们的共同进步。 笔者原本打算详细的介绍学习中的收获,将各类知识点写成文章,但经过反复考量之后,发现这种详细照搬别人知识的做法其实没什么意思。与其原封不动的转述别人书中的内容,不如直接提供参阅的书目,这样就免得在转述别人的知识的时候误解作者想要表达的真正意义。所以本系列的文章,笔者将个人学习的经验加以整合,将经验知识点罗列出来,并附加所参阅的书籍。另外涉及到实践操作过程的章节,将会把具体使用的工具罗列出来,并附上一些参考性的代码和脚本。 本系列文章主要分为十二个部分,分别为: (一)工具及书籍文档推荐 (二)软件环境搭建 (三)RTL设计 (四)验证 (五)工艺库说明 (六)形式验证 (七)综合 (八)可测性设计 (九)低功耗设计 (十)静态时序分析 (十一)数模混合仿真 (十二)可测性设计 介绍这么多,不是显得个人有多少经验,其实本人也只是菜鸟,关注这么多内容,主要是为了让自己的知识储备更全面一下,这样考虑设计问题的时候遗漏的东西会更少一些。在本系列文章中,每个章节的详略是不同的,主要是跟个人工作经验有关,有介绍得简单的地方,麻烦大家帮忙补充。每个部分的内容基本采用“理论+工具+示例”的行文结构,有些EDA工具笔者没有使用过的就暂不能提供实例了。 (一)工具及书籍文档一、前言 对于RTL级的Asic设计所涉及到的软件是非常之多的,笔者也并没有每一个都使用过。 二、工具介绍 RTL代码规则检查工具:nlint,spyglass。这两个软件主要是用于检查代码的语法和语义错误的,并且比其他的工具能检测出更多的问题,比如说命名规格,时序风险,功耗等。详细介绍请参考软件的使用教程,nlint有Windows版和linux版,软件的linux版本和使用教程可以在eetop上搜索到。 RTL代码仿真工具:这类仿真工具有较多的组合,比如说:qustasim/modelsim,NC_verilog+Verdi,VCS+DVE,VCS+Verdi等等。目前笔者使用的组合是VCS+Verdi。这两个软件是业内主流的仿真软件,还可以结合UVM库进行仿真,当然这是验证方法学的内容。 综合工具:Design Complier。最常用的综合工具,没有之一,该软件主要是将RTL代码“翻译+优化+映射”成与工艺库对应的门级网表。并且还包含功耗分析软件Power Complier和边界扫描寄存器插入软件 BSD Complier。 可测性设计:DFT Complier + TetraMAX。软件在DC之后使用,DFT Complier 用于将设计的内部寄存器替换成扫描寄存器并组成一条或多条扫描链,TetraMAX是用于自动生成测试向量的。 形式验证工具:Formality、Conforml(candence出品)。等价性验证工具,主要是在DFT Complier插入扫描链之后进行验证,另外,在版图综合时钟树,插入BUFFER之后,也需要用该工具进行等效性验证。 静态时序分析工具: Prime Time。业界最常用的时序分析工具之一,该软件包括功耗分析PTPX工具,功耗分析必备。cadence也有对应的时序分析工具——Encounter Timing System。 自动布局布线工具(APR):ICC,Enconter。其中Encounter是Cadence公司的。 数模混合仿真: nanosim + VCS,nanosim的升级版为XA。 这是一篇有关于synopsysEDA工具软件的介绍,希望对于EDA软件的用途不清楚的伙伴有帮助。http://bbs./thread-151171-1-1.html 三、书籍推荐 《Verilog HDL 硬件描述语言》 《设计与验证Verilog HDL》 《企业用verilog代码风格规范》 《verilog语言编码风格》 《verilogHDL代码风格规范》 《Verilog HDL高级数字设计》 《Soc设计方法与实现》 《高级ASIC芯片综合》 《华为Verilog典型电路设计》 《数字IC系统设计》 《数字集成电路--电路、系统与设计》 《专用集成电路设计实用教程》 《集成电路静态时序分析与建模》 《CMOS集成电路后端设计与实战》 《makefile教程》 《鸟哥的私房菜》 《SystemVerilog与功能验证》 《UVM实战》 《通信IC设计(上下册)》 《数字图像处理与图像通信》 《数字信号处理的FPGA实现中文版》 各类Synopsy userguide,EETOP有16年版的。 三、工艺库说明 使用DC,PT,FM,ICC或者ENCOUNTER软件需要工艺库文件,主要包括数字逻辑单元文件,符号库,综合库,寄生电容参数库,版图文件LEF,milkway库等等。 有关工艺库各文件夹的作用,笔者将会在将“工艺库说明”的章节进行详细介绍,如果有遗漏还请大家包涵。 (二)环境搭建一、前言 先介绍一下个人的使用环境。由于网络上已经存在很多安装教程,笔者就不再废话,直接给出他们的连接,并附带其他需要注意的关键点,如果有安装问题,请追问。Synopsys软件安装包下载地址在笔者前一篇文章“工具及书籍文档”,都是来自EETOP的大牛们提供的。在安装的过程中需要具备一些Linux系统的使用经验,不然会很难理解这些步骤是做什么的。 个人的环境如下:1、vmware 12;2、RHEL6.5系统;3、synopsys软件,Lib Complier,VCS,Verdi,Desgin Complier,PrimeTime,Formality,ICC。一共7个软件,几乎都是15年版本的。 二、步骤 环境搭建需要准备以下三件事: 1,vmware12虚拟机安装;安装教程如下。https://jingyan.baidu.com/article/215817f78879c21edb142379.html 2, RHEL6.5操作系统安装,当然也可以使用CentOs6.5,安装教程如下。http://www./Linux/2016-05/131701.htm ——》RHEL6.5 https://www.kafan.cn/edu/488101.html ——》Centos6.5 a、安装vmware tools。在虚拟机中把系统安装好了之后,需要安装vmware tools,安装教程如下,http://www./Linux/2015-08/122031.htm ,安装该软件之后才可以启用共享文件夹以利于RHEL6.5与windows系统进行文件交换。 b、更新YUM源,RHEL和Centos都需要更新YUM源,操作步骤一致,YUM是一个链接到软件库的一个软件,随后安装软件需要用到。https://jingyan.baidu.com/article/b24f6c8239c6aa86bee5da60.html 注意:该教程某些步骤可能会失效,需要结合自己具体的情况使用。安装好YUM之后,可以使用yum install gvim命令测试一下。 c、安装GCC,G++,这两个软件在VCS+Verdi仿真时会调用到。命令:yum install gcc 命令:yum install gcc-c++ 3、 Synopsys软件安装 Synopsys软件安装教程,链接如下:https://wenku.baidu.com/view/c02c271d9b6648d7c0c74670.html http://bbs./thread-553702-1-1.html 高版本和低版本的Synopsy软件安装步骤一致,区别在于license的问题。用EETOP上的最新license即可使用15版的软件。在使用RHEL操作系统需要懂一些SHELL脚本,makefile脚本,这样便于提高操作效率,后文会提到。 注意:此外还需要修改四个文件的hostname,使得这四处的hostname保持一致。 a、synopsys.dat中的第一行hostname; b、synopsys.bashrc中的export SNPSLMD_LICENSE_FILE=27000@localhost行,“@”符号后的hostname; c、/etc/sysconfig/network配置文件中hostname; d、/etc/hosts配置文件中的127.0.0.1这一行的 ,第三个参数hostname; 这四个hostname一定要一致,才能正确启动DC,PT,FM,ICC,VCS,VERDI软件。 在启动DC,PT,FM,ICC,VCS,VERDI软件之前需要先启动Synopsys的license管理器。 有关软件的使用教程可以参考官方的userguide。或者EETOP上,小伙伴们的教程。 (三)工艺库说明 (略,请点击阅读原文查看) (四)RTL设计数字电路设计 RTL设计所需要的理论知识庞杂而繁多,本文所介绍的内容均由个人参阅了许多书籍之后加以整合的,很多内容本人也不是很熟,只是罗列出来作为参考学习的资料。主要有三个部分的内容,第一部分主要是数字电路设计的基础,这是在大学时期应该予以掌握的内容,第二部分是进阶的学习内容附带一个专业方向——MCU,第三部分是有关于各类算法处理的专业知识,需要更多的复合型知识,例如通信方向需要有较好的数学功底—傅立叶变换。由于这部分内容实在太多,个人没有能力也没有必要将每一部分的内容都详细的罗列出来,所以这里只是整理出一些需要把握的关键点。至于具体的内容,还请大家按照个人需求,参阅推荐的各类书籍。 一、基础 组合逻辑与时序逻辑:布尔代数,卡诺图,基本与非门,锁存器,触发器,冲突与冒险。——《Verilog HDL高级数字设计》 Verilog语言基础:数值类型,表达式与运算符,assign语句,always语句,if-else语句,case语句,阻塞与非阻塞。——《Verilog HDL 硬件描述语言》 状态机:一段式、二段式、三段式状态机的区别;独热码、二进制码、格雷码的区别及应用场合。——《Verilog HDL高级数字设计》 同步电路和异步电路:两者的本质,异步电路跨时钟域,亚稳态。——IC_learner博客 复位与时钟:同步复位、异步复位、异步复位同步释放的区别,时钟分频——二分频、三分频、任意整数分频,门控时钟,时钟切换。——《深入浅出玩转FPGA》,百度文档 数据通路与控制通路:本质上任何数字电路都可以划分为简单的两种类型——控制通路与数据通路,控制通路的核心是状态机,数据通路是各类算术处理算法、并行总线等等。——《Verilog HDL高级数字设计》 Testbench验证:无论什么电路,最终都需要验证其功能的正确性。Testbench的结构主要由a,复位和时钟,b,激励产生电路,c,系统监视器,d,结果比较电路,e,波形产生函数,f,待验证的MODULE等主要模块组成,其中,b是最重要的模块,一切验证都是从激励信号开始的。——《verilogHDL代码风格规范》。初学者推荐使用windows版qustasim 或者modelsim 仿真工具,简单又方便,以后可学习使用VCS+Verdi(比较折腾人)。 二、进阶 代码风格:良好的代码风格很有必要,参考一下企业用的代码风格,有助于个人养成良好的编码习惯。——《企业用verilog代码风格规范》《verilog语言编码风格》 基本常用电路:具备以上庞杂的理论基础之后,需要积累一些常用的基础电路。——《华为Verilog典型电路设计》 接口电路,I2C,UART,SPI:接口电路是中小规模芯片常用的对外接口电路,无论是与上位机(PC)通信还是控制其它芯片。I2C从机常用于EEPROM芯片中,主机可以直接使用单片机模拟,ARM单片机直接集成了I2C主机,I2C的IP代码网络上有现成的;UART是全双工电路,宏晶单片机通过UART进行烧录,SPI电路最常用于SD卡上。——《Verilog HDL高级数字设计》《通信IC设计(上下册)》有简单的UART和SPI的代码。 RISC,8051 MCU ——IP:通过下载EETOP上相关的IP及文档来学习。 三、专业 数值的表示方法:浮点数,定点数的表示办法——《Verilog HDL高级数字设计》《通信IC设计(上下册)》 算术处理算法:浮点数的加法、乘法电路设计。——《Verilog HDL高级数字设计》 通信算法:FIR滤波器,IIR滤波器,傅立叶变换,冗余编码等等各种通信方向必须掌握的。——《通信IC设计(上下册)》《数字信号处理的FPGA实现》 图像处理算法:静态图像,动态图像去噪。——《数字图像处理与图像通信》 SOC:SOC类芯片的组成结构,AMBA总线,IP复用,SV验证。——《Soc设计方法与实现》 四、工具: 文档代码编辑器:GVIM,Notpad++ RTL设计规则检查:Nlin,spyglass 五、示例 下列代码为UART全双工串口示例代码,代码来源于《Verilog HDL高级数字设计》,随后的章节将会使用到该示例代码,代码功能细节需结合书籍了解。 下面的代码已经过modelsim验证。 UART发送器: module UART_XMTR #( parameter word_size = 8 )( output Serial_out, input [word_size - 1 : 0] Data_Bus, input Load_XMT_datareg, Byte_ready, T_byte, Clock, rst_b ); Control_Unit M0( Load_XMT_DR, Load_XMT_shftreg,start,shift,clear, Load_XMT_datareg,Byte_ready,T_byte,BC_lt_Bcmax, Clock,rst_b); Datapath_Unit M1( Serial_out,BC_lt_Bcmax,Data_Bus,Load_XMT_DR, Load_XMT_shftreg,start,shift,clear,Clock,rst_b); endmodule module Control_Unit #( parameter one_hot_count = 3, state_count = one_hot_count, size_bit_count = 3, idle = 3'b001, waiting = 3'b010, sending = 3'b100 // all_ones = 9'b1_1111_11111 )( output reg Load_XMT_DR, output reg Load_XMT_shftreg, output reg start, output reg shift, output reg clear, input Load_XMT_datareg, input Byte_ready, input T_byte, input BC_lt_Bcmax, input Clock, input rst_b ); reg [state_count - 1 : 0] state, next_state; always @(state, Load_XMT_datareg,Byte_ready,T_byte,BC_lt_Bcmax) begin:Output_and_next_state Load_XMT_DR = 0; Load_XMT_shftreg = 0; start = 0; shift = 0; clear = 0; next_state = idle; case(state) idle: if(Load_XMT_datareg == 1'b1)begin Load_XMT_DR = 1; next_state = idle; end else if(Byte_ready == 1'b1)begin Load_XMT_shftreg = 1; next_state = waiting; end waiting: if(T_byte == 1) begin start = 1; next_state =sending; end else next_state = waiting; sending: if(BC_lt_Bcmax) begin shift = 1; next_state = sending; end else begin clear = 1; next_state = idle; end default: next_state = idle; endcase end always @(posedge Clock,negedge rst_b) begin: State_Transitions if(rst_b == 1'b0) state <= idle; else state <= next_state; end endmodule module Datapath_Unit #( parameter word_size = 8, size_bit_count = 3, all_ones = 9'b1_1111_1111 )( output Serial_out, BC_lt_Bcmax, input [word_size -1:0] Data_Bus, input Load_XMT_DR, input Load_XMT_shftreg, input start, input shift, input clear, input Clock, input rst_b ); reg [word_size -1:0] XMT_datareg; reg [word_size :0] XMT_shftreg; reg [size_bit_count:0] bit_count; assign Serial_out = XMT_shftreg [0]; assign BC_lt_Bcmax = (bit_count < word_size +1); always @(posedge Clock,negedge rst_b) if(rst_b == 0) begin XMT_shftreg <= all_ones; XMT_datareg <= 9'b0_0000_0000; bit_count <= 0; end else begin:Register_Transfers if(Load_XMT_DR == 1'b1) XMT_datareg <= Data_Bus; if(Load_XMT_shftreg == 1'b1) XMT_shftreg <= {XMT_datareg,1'b1}; if(start == 1'b1) XMT_shftreg[0] <= 0; if(clear == 1'b1) bit_count <= 0; if(shift ==1'b1) begin XMT_shftreg <= {1'b1,XMT_shftreg[word_size:1]}; bit_count <= bit_count + 1; end end endmodule UART接收器: module UART_RCVR #( parameter word_size = 8, half_word =word_size/2 )( output [word_size - 1 :0] RCV_datareg, output read_not_ready_out, Error1,Error2, input Serial_in, read_not_ready_in, Sample_clk, rst_b ); Control_Unit2 M0( read_not_ready_out,Error1,Error2, clr_Sample_counter,inc_Sample_counter, clr_Bit_counter,inc_Bit_counter,shift, load,read_not_ready_in,Ser_in_0,SC_eq_3, SC_lt_7,BC_eq_8,Sample_clk,rst_b); Datapath_Unit2 M1( RCV_datareg,Ser_in_0,SC_eq_3,SC_lt_7, BC_eq_8,Serial_in,clr_Sample_counter, inc_Sample_counter,clr_Bit_counter, inc_Bit_counter,shift,load,Sample_clk,rst_b); endmodule module Control_Unit2 #( parameter word_size = 8, half_word = word_size/2, Num_state_bits = 2, idle = 2'b00, starting = 2'b01, receiving = 2'b10 )( output reg read_not_ready_out, Error1,Error2, clr_Sample_counter, inc_Sample_counter, clr_Bit_counter, inc_Bit_counter, shift, load, input read_not_ready_in, Ser_in_0, SC_eq_3, SC_lt_7, BC_eq_8, Sample_clk, rst_b ); reg [word_size - 1 :0] RCV_shftreg; reg [Num_state_bits - 1 : 0] state; reg [Num_state_bits - 1 : 0] next_state; always @(posedge Sample_clk or negedge rst_b) if(rst_b == 1'b0) state <= idle; else state <= next_state; always @(state,Ser_in_0,SC_eq_3,SC_lt_7,read_not_ready_in) begin read_not_ready_out = 0; clr_Sample_counter = 0; clr_Bit_counter = 0; inc_Sample_counter = 0; inc_Bit_counter = 0; shift = 0; Error1 = 0; Error2 = 0; load = 0; next_state = idle; case(state) idle: if(Ser_in_0 == 1'b1) next_state = starting; else next_state = idle; starting: if(Ser_in_0 ==1'b0) begin next_state = idle; clr_Sample_counter = 1; end else if(SC_eq_3 == 1'b1) begin next_state = receiving; clr_Sample_counter = 1; end else begin inc_Sample_counter = 1; next_state = starting; end receiving: if(SC_lt_7 == 1'b1) begin inc_Sample_counter = 1; next_state = receiving; end else begin clr_Sample_counter = 1; if(!BC_eq_8) begin &nb (五)验证(1) 一、前言 借助于前文RTL设计中提到的UART代码,本章节将在后面给出对应的testbench以及说明如何在questa/modelsim、VCS+DVE、VCS+Verdi工具中使用。推荐书籍:《vcs User Guide 2016》 二、Testbench Testbench的结构,正如上文提到的,主要由a,复位和时钟,b,激励产生电路,c,系统监视器,d,结果比较电路,e,波形产生函数,f,待验证的MODULE,g,控制仿真时间这几个部分组成。本章节提供的testbench只包含a,b,e,f,g部分,至于c,d更高级的内容,暂时无法涉及,questa/modelsim将不会使用到e部分的代码,使用questa/modelsim仿真时要屏蔽掉全部e段的内容。同样,在使用VCS+DVE进行仿真时要屏蔽VCS+VERDI的e段内容 三、工具使用 3.1modelsim仿真 对于modelsim仿真, 仿真文件包含:1,verilog源文件(前文已全部提供);2,testbench文件(后面会提供) modelsim使用教程:https://wenku.baidu.com/view/db638e25b9d528ea81c779cc.html 有关在modelsim软件中如何使用本示例请参考以上教程。 仿真结果图: 3.2 VCS+DVE和VCS+VERDI仿真 对于VCS+DVE和VCS+VERDI, 仿真文件包含: 1,verilog源文件(前文已全部提供); 2,testbench文件(后面会提供), 3,包含verilog、testbench文件路径的uart.f文件(必要时需自行修改), 4,makefile仿真启动文件。在终端中运行make命令即可运行仿真,一定要注意文件路径问题。 makefile教程:http://blog.csdn.net/liang13664759/article/details/1771246 VCS+DVE 使用教程,https://wenku.baidu.com/view/48912cf558fb770bf68a55b4.html DVE是VCS软件自带的波形查看器。 本章实例对应的VCS+DVE makefile启动脚本: all:VCS DVE VCS: vcs -f uart.f -full64 -debug_all -R DVE: dve -vpd wave.vpd -mode64 将以上内容复制到文本文件中,并将该文本文件改名为makeflile。 uart.f内容: /home/Lance/synopsys/UART/testbench.v //必须放在文件中的第一行。 /home/Lance/synopsys/UART/UART_XMTR.v /home/Lance/synopsys/UART/Control_Unit.v /home/Lance/synopsys/UART/Datapath_Unit.v /home/Lance/synopsys/UART/UART_RCVR.v /home/Lance/synopsys/UART/Control_Unit2.v /home/Lance/synopsys/UART/Datapath_Unit2.v DVE波形查看器启动命令: dve -vpd wave.vpd -mode64 此外,在运行makefile启动脚本之前,还需要在testbench中添加如下代码: initial begin $vcdplusfile("wave.vpd");//保存的波形文件名字 $vcdpluson(1,tb);//tb对应testbench文件的内的module名字 end 该段代码为e,波形产生函数,主要是生成DVE波形查看器使用的VPD格式的波形文件。 仿真结果图: VCS+Verdi,Verdi是debussy的升级版,是一个独立的软件,这对软件组合使用方式与VCS+DVE差不多。 VCS+Verdi makefile启动脚本: all:VCS VERDI VCS: vcs +v2k -sverilog -debug_all -P /usr/synopsys/Verdi/K-2015.09/share/PLI/VCS/LINUX64/novas.tab /usr/synopsys/Verdi/K-2015.09/share/PLI/VCS/LINUX64/pli.a +vcs+lic+wait \ -f uart.f -y ./ +libext+.v -full64 -R VERDI: verdi -f uart.f -ssf wave.fsdb & 将以上内容复制到文本文件中,并将该文本文件改名为makeflile。 注意:-P /usr/synopsys/Verdi/K-2015.09/share/PLI/VCS/LINUX64/novas.tab /usr/synopsys/Verdi/K-2015.09/share/PLI/VCS/LINUX64/pli.a主要是调用Verdi的接口函数以生成fsdb波形。 Verdi波形查看器启动命令: verdi -f uart.f -ssf wave.fsdb & 此外,在运行makefile启动命令前,还需要在testbench中添加如下代码: initial begin $fsdbDumpfile("wave.fsdb"); $fsdbDumpvars(0,tb); end 以生成Verdi波形查看器使用的FSDB格式的波形文件。 仿真结果图: 注意: 启动脚本相关问题,需要学习makefile有关内容,有关VCS和Verdi的详细使用教程,还请参考其它资料。 四、Testbench代码附件: `timescale 1ns/1ns module tb; parameter num = 500; reg [7 : 0] Data_Bus; reg Load_XMT_datareg; reg Byte_ready; reg T_byte; reg read_not_ready_in; reg Clock; reg rst_b; reg Sample_clk; wire serial; wire Error1,Error2; wire [7:0] RCV_datareg; wire read_not_ready_out; //a,时钟和复位部分 initial begin rst_b = 1; Sample_clk = 0; Clock = 0; #100; rst_b = 0; #100; rst_b = 1; end always #(8*num) Clock = ~Clock; always #num Sample_clk = ~Sample_clk; //b,激励产生部分 initial begin Data_Bus = 8'b1110_0101; Load_XMT_datareg = 1'b1; Byte_ready = 1'b0; T_byte = 1'b0; read_not_ready_in = 1'b0; // #(2*8*num); Load_XMT_datareg = 1'b0; #(2*8*num); Byte_ready = 1'b1; #(2*8*num); T_byte = 1'b1; // #(2*8*num) Load_XMT_datareg = 1'b1; Byte_ready = 1'b0; T_byte = 1'b0; end //c,系统监视器 //d,结果比较电路 //e,波形产生函数 //vpd initial begin $vcdplusfile("wave.vpd"); $vcdpluson(1,tb); end //fsdb // initial // begin // $fsdbDumpfile("wave.fsdb"); // $fsdbDumpvars(0,tb); // end //g,控制仿真时间 initial begin $finish; end //f,待验证的MODULE UART_XMTR m0( .Serial_out(serial), .Data_Bus(Data_Bus), .Load_XMT_datareg(Load_XMT_datareg), .Byte_ready(Byte_ready), .T_byte(T_byte), .Clock(Clock), .rst_b(rst_b) ); UART_RCVR m1( .RCV_datareg(RCV_datareg), .read_not_ready_out(read_not_ready_out), .Error1(Error1), .Error2(Error2), (六)验证(2) (七) 综合(八)形式验证(九)数模混合仿真(十)静态时序分析(十一)低功耗设计(十二)可测性设计 |
|
来自: 毕杰lb7q1kq7pr > 《待分类》