数字集成电路设计与实现(共59页).doc
精选优质文档-倾情为你奉上数字集成电路设计与实现1.绪论2.基本流程2.1 代码编写2.2 功能验证2.3 逻辑综合2.4 静态时序分析2.5 物理综合3.设计技术3.1 RTL代码3.2 数据通道设计3.3 状态机设计3.4 系统设计4.验证技术4.1 测试平台5.逻辑综合技术5.1 标准单元库5.2 设计约束6.物理综合技术第1章 绪论1.1 数字集成电路的特点数字电路通常是由简单的单元电路构成的规模庞大的系统,体现了“简单性”与“复杂性”的对立统一。基本的数字单元电路,如各种逻辑门电路和触发器、锁存器等,其电路结构比较简单,且实现的逻辑功能与其中晶体管尺寸无关。数字电路的性能指标相对较少,主要包括速度、功耗、面积三个方面,设计思路比较简单。但是,一个数字电路系统通常是非常复杂的,可能包含数百万个基本逻辑单元,其逻辑功能也需要有其它领域的知识才能理解。具有存储功能的数字逻辑单元,其输入信号和控制信号需要满足一定的时序关系才能正确实现逻辑功能。在达到一定规模后,各个单元电路的时序要求很难同时满足。制造工艺的进步,对数字电路性能提高作用显著。同样的设计,用特征尺寸更小的工艺实现,各方面都性能会有很大提高。因此,数字电路设计需要有较好的可移植性或重用性,以适应制造工艺的发展。数字电路的这些特点,决定了其设计技术的发展方向。1.2 现代数字电路设计方法在早期的集成电路设计中,数字电路与模拟电路的设计方法没有什么区别,都是全定制设计。全定制设计是一种晶体管级的设计,任何电路都要描述为由晶体管构成的电路网络。由于晶体管与版图之间具有明确的对应关系,这种设计方法的实现步骤相对较少,对EDA工具的依赖程度相对较低。在全定制设计问题中,设计者可以任意确定每个单元电路的结构和其中晶体管的尺寸,理论上讲,能够实现最优化的电路性能。由于具有较高的灵活性和设计自由度,全定制设计至今仍是模拟电路和规模较小的混合信号电路的设计方法。但是,对于规模庞大的数字电路来说,这种设计方法不仅设计工作量大,而且对电路的时序关系验证也十分困难,对于规模达到百万、千万晶体管的电路,完全采用全定制设计是不现实的。现代数字集成电路设计方法来自对传统设计方法的总结和对计算机软件技术的引入。在对电路性能的要求没有达到工艺极限时,不需要对每个单元电路都进行特殊设计,可先设计出各种基本单元电路(cell),包括原理图和版图,形成一个标准单元库,再利用库中的cell实现复杂的逻辑关系。这种方法使得自动化设计成为可能。即使在全定制设计中,对电路功能的描述也是层次化的,而不是直接描述为晶体管网络。有了标准单元库,一个电路就可以理解为由标准单元构成的网表,也就是说“描述级别”由晶体管级提升到了“门级”。复杂的电路在“门级”仍然难以看出逻辑功能,需要更高级别的描述。一个复杂的数字电路系统可以理解为由若干个具有典型逻辑功能的模块和一个控制电路组成的,常见的模块包括寄存器、计数器、算术和逻辑运算单元和存储器等。控制电路是一个有限状态机,在时钟的作用下,状态机根据当前的状态和输入信号不断地进行状态转换,同时产生输出信号,控制各个逻辑模块工作。这种级别的描述称为“架构级”,是最重要的设计级别。最高级别的描述是系统级,在这个级别,一般只定义系统的功能、外部接口和其中主要功能模块。最低级别的描述是版图,版图实际上就是一组几何图形,根据版图可以生成光刻版。一个设计实际上总是要从系统级开始考虑,然后是架构级、门级、晶体管级,最后是版图级。在传统的设计流程中,可验证的设计描述是从晶体管级开始的,用晶体管构成逻辑门,再由逻辑门构成功能模块,最后连接成系统。全部设计工作都要由设计者来完成,尽管也使用EDA工具,但这些工具只是代替了纸、笔和计算器,不能自动生成任何东西。计算机技术的发展,使得从高级别的描述自动生成低级别的描述成为可能,这个过程与从高级语言编写的程序生成机器码的过程相似。用电路图描述复杂电路是很困难的,也很难被计算机理解,于是产生了硬件描述语言。硬件描述语言具有很强的描述能力,一段几百行的代码,有时可以代替几百张图纸。硬件描述语言诞生之初是为了保存设计或进行功能仿真,用于生成电路是后来的事。硬件描述语言也存在级别的概念,分为行为级、寄存器传输级(RTL级)、门级、晶体管级等。版图的细节很难用语言描述,目前还不能自动生成,因此在所谓的自动化设计流程中,标准单元库中的基本单元的版图还是手工设计的。在现代的ASIC设计方法中,标准单元库是由芯片制造厂提供的,设计者只需要用硬件描述语言写出对电路功能的描述,再用EDA工具的脚本语言,写出对电路性能的要求,大部分工作将由EDA工具实现。这种方法极大地提高了设计速度,也提高了设计的重用性。本文主要介绍这种设计方法,按业界习惯说法,简称为ASIC设计方法。ASIC设计方法可以归纳为两部分工作,即设计和实现。设计指描述和验证电路功能,这部分工作需要由设计者完成。另一部分工作是实现的流程,在这部分工作中,设计者的任务是将对电路性能的要求,按EDA工具规定的形式,提供给EDA工具,用EDA工具自动生成基于cell的电路网表、版图和各种性能报告,最后确定设计的交付。用EDA工具自动实现的设计工作称为“综合”,从硬件描述语言得到由cell网表的工作称为逻辑综合,由cell网表自动生成版图的工作称为物理综合。设计过程的主要任务是给出可综合的描述,并验证其逻辑功能的正确性。对于复杂的设计,电路功能需要通过多个级别的描述来完成。数字电路设计分为系统级、架构级、寄存器传输级(RTL)、门级和晶体管级等。所谓级别包括两方面含义,一是设计者对电路的认识,二是允许使用的描述方法。系统级设计的任务主要是定义电路的功能和外部特性,设计者只需要将电路为若干个抽象的功能模块,并将各个功能模块的逻辑功能定义清楚即可。架构级设计要具体一些,在这个级别,电路要描述成相互连接的若干个典型逻辑部件和控制其数据传输的状态机。典型逻辑部件包括计数器、寄存器、算术运算单元等,又称为数据通道(Data path),状态机则是一个设计中具有特殊性的部分,它控制数据通道的工作。以上两种描述,描述方法没有什么限制,将问题说清楚即可。寄存器传输级的描述是ASIC设计中最重要的描述,必须使用硬件描述语言完成。所谓寄存器传输级描述是基于这样一种认识,即任何数字电路,无论功能如何,都是由寄存器和寄存器之间的组合逻辑电路实现的,寄存器用来保存数据,组合电路用于传输数据。RTL代码必须保证可综合性,只能使用硬件描述语言中的部分描述语句。从RTL代码中应可隐约看出电路结构,又不要写得过于具体。细化到逻辑门和触发器的代码并不好,因为从RTL描述到cell的转换是逻辑综合工具的任务,人为 写到cell一级不仅降低了代码的可读性,也不利于优化。在ASIC设计中,门级和晶体管级电路是由EDA工具生成的,设计者的任务是给出功能正确的RTL级代码。验证RTL代码的正确性需要编写验证代码,这部分代码称为测试平台(Testbench)。Testbench用于给RTL代码输入信号和判断输出的正确性,也要用硬件描述语言编写,但与RTL代码不同,这部分代码不需要生成电路,对语言的使用没有限制。1.3 硬件描述语言硬件描述语言(HDL)是一种用于描述电路功能的语言,具有与计算机编程语言类似的语法,看起来与C语言等计算机编程语言很相似,但两者有本质区别。硬件描述语言编写的代码是对电路的描述,而不是程序。程序是指令的序列,是有执行次序的,而电路则不存在执行次序的概念。实际上,HDL语言与SPICE语言属于同一类型,但抽象级别较高。在进行仿真分析,SPICE更精确,但速度太慢,不适合用于大规模电路。HDL代码的仿真速度要快得多,但只能反映逻辑功能和延迟,无法提供全面信息,也不如SPICE精确。常用的硬件描述语言有VHDL,Verilog,SystemC等,这些硬件描述语言各有特点。每一种硬件描述语言都支持多个抽象级别的描述,支持级别有所不同。System C主要用于系统级建模和功能验证。VHDL和Verilog都支持RTL级描述,但VHDL侧重更高级别描述,语法复杂。Verilog主要支持RTL和RTL以下级别,语法与C语言十分相似,应用最为广泛。1.4 设计与实现流程在IC设计领域,设计流程有两层含义,一是指一般意义的设计流程,强调的是设计步骤和各个步骤的关系,但不具体确定各个步骤的所使用的EDA工具。二是具体的设计流程,例如某个公司的设计的特有设计流程,这种流程对EDA工具也有明确要求。图1-1 简化的设计流程图1-1是一般意义的简化设计流程。设计流程并不是直线进行的,往往需要多次迭代,主要是解决时序收敛问题。本文将前端的前3个环节称为“设计”过程,而将以后的环节称为“实现”过程。(1) 编写设计规格书编写设计规格书(SPEC)是最重要设计环节,它实际上包含了系统级和架构级两部分设计内容。SPEC中包括电路功能定义,芯片制造工艺和标准单元库选择,对最高时钟频率、输入输出时序、功耗、面积等性能方面的要求,以及对工作电压范围、环境温度、静电防护(ESD)、可测性等方面的要求等。此外,电路的基本架构一般也要在这个阶段确定。SPRC就是技术文档,一般采用文字、框图、状态机、时序图等表示。大型的电路设计需要一个设计队伍来完成,在这个队伍中,每个人只负责一个环节或一个环节的一部分。SPEC是协调整个设计队伍的依据。(2)编写RTL代码根据Specification,用硬件描述语言编写可综合的代码。工具:文本编辑器,如UltraEdit32,ActiveHDL等。(2) RTL仿真编写测试平台(TestBench),给出输入信号,验证RTL代码与SPEC的一致性。常用的工具有:Modelsim(Windows)、VCS(Unix,Linux)等。(3) 逻辑综合ASIC:利用综合工具将RTL代码转换为门级网表。门级网表中的基本元件包括触发器、逻辑门和缓冲器(Buffer)等称为cell,由流片厂家(Foundry)以库的方式提供,门级网表就是cell和连接关系的集合。常用综合工具是Synopsys的DC(Design Compiler)。规模较大的设计需要考虑可测性设计(DFT,Design For Test)问题,低功耗设计需要进行功耗优化,如时钟门控、操作数隔离等,可使用Synopsys的Power Compiler进行功耗优化。(4)布线前的静态时序分析(STA)和门级仿真。静态时序分析是根据门延迟和设计约束,通过计算分析设计是否满足时序要求。主要工具是Synopsys的PT(PrimeTime)。门级仿真是用门级网表代替RTL代码,利用与RTL仿真相同的Testbench,重新进行功能验证。主要使用Synopsys的VCS。也可以使用Modelsim。布线前的静态时序分析和动态仿真中,cell的延迟是比较基本准确的,但时钟通常使用理想时钟,连线延迟不考虑。因此,在这个阶段,只能说明设计是有可能实现的,允许有一些时序上的violation存在,需要在提取布线信息后解决。(5) 布局布线根据门级网表和流片厂家的库文件,利用工具自动完成电路的版图设计并进行设计规则和电气规则校验。可以使用Synopsys的Astro或Cadence的Encounter进行版图设计。(6) 参数提取参数提取(extract)就是从版图中提取实际的延迟信息和各种寄生参数,可采用Synopsys的Star-rcxt提取。(7) 布线后的静态时序分析(STA)和门级仿真把从版图中提取实际的延迟信息假如到网表中,重新进行STA和动态仿真,如果能够通过,则可交付流片(Tapeout)。否则需返回(6)进行修正,如仍无法解决,需返回(4)甚至返回(2)。第2章 基本流程2.1 概述本章以一个简单例子对数字电路的ASIC设计流程进行展示,目的是使读者迅速了解设计过程的全貌,明确学习目标。2.2 编写RTL代码2.1.1 设计要求本例要求设计一个4位二进制的计数器,输入输出引脚定义如图2-1所示。具体功能要求如下:(1) 正常工作状态下按二进制方式计数,时钟(clk)上沿计数。(2) 采用异步复位模式,复位信号rst高有效。(3) 具有同步预置功能,预置ld输入为1时,时钟上沿后,计数器输出q等于预置输入d。(4) 计数可由使能端控制,使能en信号为1时,可计数,使能为0时,停止计数。(5) 计数值达到1111时,进位输出信号co为1。 主要性能要求为,在负载电容为5PF,最高输入延迟为时钟频率的20%时,最高时钟频率可达到100MHz。要求写出Verilog代码,验证功能的正确性,并用一个标准单元库进行逻辑综合和物理综合,最终得到该电路模块的版图。图2-1 计数器2.1.2 编写设计代码根据设计要求,编写设计代码如下:/-/ Design unit : Example 1 for "Digital IC design and impletation”/ File name : counter.v/ System : Verilog 1993/ Author : XinXiaoNing/ Revision : Version 1.0 2/24/2005/-timescale 1ns/1psmodule counter(rst , clk , ld , en , d , q , co );/-/ data type definitions./- input rst; / system reset signal,active high input clk; / system clock signal.input ld; / signal for load "d" to "q".input en; / count enable signal.input3:0 d; / data input to counter.output3:0 q; / counter outputs.output co; / carray signal./-reg3:0 q;reg co;/-always (posedge clk or posedge rst)begin if(rst = 1'b1) q <= 4'b0000; else if(ld = 1'b1) q <= d; else if(en = 1'b1) q <= q + 1'b1;end/-always (q)begin if(q = 4'b1111) co = 1'b1; else co = 1'b0;end/- END -endmodule这是一个典型的RTL代码,从这个例子中可以看出Verilog语言的基本语法结构,现对主要内容进行总结。(1) Verilog代码的基本单位是模块,以保留字module开始,以endmodule结束。(2) 紧跟module的是模块名称,这里是counter。(3) 模块名称后的括号中的内容是输入、输出端口名称,以逗号分隔;右括号后要有“;”。(4) 代码的主体分为两部分,即信号声明部分和信号赋值部分。(5) 信号声明部分包括端口信号声明和内部信号声明。端口信号要声明其方向和位宽。方向分为input、output和inout等3种,位宽以n:0的格式声明。(6) 内部信号分为reg和wire两种类型;实际的寄存器信号必须用reg声明,但reg类型的信号并不一定对应或生成寄存器。凡以always方式赋值的信号都要声明为reg类型。(7) 时序电路部分,即包含寄存器,又时钟控制的电路,描述方式为always (posedge clk or posedge rst)begin ;end其特征是使用了posedge(上沿)或negedge(下沿)关键字来描述信号变化的条件。其含义为,只有用edge声名的输入信号,发生规定方向的变化时,该赋值语句块内部的信号才可能发生变化。(8) 组合逻辑部分的描述方法为always (q)begin if(q = 4'b1111) co = 1'b1; else co = 1'b0;end特征是不使用posedge或negedge,即任何时刻,当输入信号变化时,输出都有可能发生变化。(9) 两个always语句之间没有执行次序问题,它们都是对电路的描述。(10) / 后写是注释。(11) timescale是定义时间单位和精度,这里定义基本单位为1ns,分辨到1ps,即在仿真时,时间可有3位小数。此外,还需注意Verilog语言是区分大写和小写的,所有保留字都需要小写。以上是设计代码部分,要验证设计部分正确性,需要另外编写一段testbench代码,因为设计代码的输入信号必须从外部提供。学习HDL的关键在于要始终考虑所描述的电路,“写的是代码,想的是电路”。2.1.3 编写验证代码与设计代码不同,验证代码不需要综合出电路,对语言的使用没有限制。为了更方便地生成各种激励信号,验证代码可以写得抽象一些。在验证代码中,可以使用一些类似程序的编写方法,如使用任务、函数、循环和数据文件等。在Verilog中,使用#表示时间的变化,例如#1表示时间走过一个基本单位。仿真工具默认的时间单位是1ns,可以使用timescale语句来修改。Testbench也是一个模块,但没有输入输出端口。/-/ Design unit : testbench of counter/ File name : counter_tb.v/ System : Verilog 1993/ Author : XinXiaoNing/ Revision : Version 1.0 2/24/2005/-timescale 1ns/1psmodule testbench();/-/ Signals for mapping Testting module/-reg rst,clk,ld,en;reg 3:0 di;wire co;wire 3:0 qo;/- Component under test -counter UUT(.rst(rst) , .clk(clk) , .ld(ld) , .en(en) , .d(di) , .q(qo) , .co(co);/-task half_pulse;inout clock; #10 clock = clock;endtask/-task pulse;input7:0 num;integer i; for(i=0;i<num;i=i+1) begin half_pulse(clk); half_pulse(clk); end endtask/- initialbegin rst = 0; clk = 0; en = 0; ld = 0; di = 4'b0000;end/-always begin rst = 1; pulse(2); rst = 0; en = 1; pulse(10); ld = 1; pulse(1); ld = 0; pulse(2); en =0; pulse(2); rst = 1; en = 1; pulse(10); $stop();end/-endmodule/- initialbegin rst = 0; clk = 0; en = 0; ld = 0; di = 4'b0000;end/-always begin rst = 1; pulse(2); rst = 0; en = 1; pulse(10); ld = 1; pulse(1); ld = 0; pulse(2); en =0; pulse(2); rst = 1; en = 1; pulse(10); $stop();end/-endmodule在这段代码中,以下几个问题需要注意:(1) 在testbench中例化设计代码时要求明确写出testbench中的信号与设计代码端口信号的连接关系。语法格式为设计模块名 例化名 (.设计端口信号名(testbench中定义的信号名),);(2) 设计代码的输入信号,在testbench中要声明为reg类型,可用initial语句块或always语句块中赋值。设计代码的输出信号,在testbench中要声明为wire类型,不能赋值。(3) 只有使用了#x,信号的变化才有时间间隔,否则都是同时发生的。(4) $stop()是仿真工具提供的系统函数,不属于verilog语言。以上仅是一个基本的验证代码,需要观察波形才能确定设计的正确性。完善的验证代码应加入判断语句,自动判断结果,并指出问题出现的位置。testbench的编写方法属于验证技术,将在后续章节讨论。2.1.4 基于Modelsim的RTL级仿真Modelsim的基本使用方法很简单,通过以下几个步骤就可看到输出波形。(1) 新建一个project。(2) 将设计代码和testbench代码添加到project;(3) 编译所有文件。(4) 执行仿真simulate。(5) 选择testbench模块。(6) 添加信号波形。(7) 运行仿真。功能验证可能是设计流程中耗时最多的环节,对于复杂电路来说,全面验证其逻辑功能不仅需要严谨的工作态度,还应学习有关理论。2.2 基本的逻辑综合方法逻辑综合是将硬件描述语言编写的设计代码转换为标准单元库中的cell构成的网表的过程。目前,应用最广泛的逻辑综合工具是Synopsys的Design Compiler,简称DC。DC需要在Linux环境下使用,应首先学习Linux操作系统的基本使用方法。深入学习DC是后续章节的任务,这里先介绍一下基本使用方法,目的是验证设计代码的可综合性。RTL代码只能使用Verilog语言的部分描述方法,仿真通过并不能证明可综合性,只有能DC的检查,该代码才是可用的。使用DC之前,必须先建立一个工作目录,并写好一个环境设置文件,该文件名为.synopsys_dc.setup。在该文件中,要定义综合使用的标准单元库的名字和搜索路径。DC在启动时,首先会读安装目录下的.synopsys_dc.setup,然后再读用户目录下的同名文件。如果用户设置与默认设置不同,则以用户设置为准。因此,一定要先进入工作目录,再启动DC。这是Linux操作系统下的软件的共同特点。以下是一个简单的环境设置文件。set target_library fsa0a_c_sc_tc.dbset link_library * fsa0a_c_sc_tc.dbset symbol_library fsa0a_c_sc.sdb set search_path " /usr/iclib/fsa0a_c/2004Q4v1.1/SC/FrontEnd/synopsys "set WORK_DIR "/usr/dc09"这个文件指定了库的名字和路径(要根据实际安装来写),并定义了一个环境变量WORK_DIR,没有修改原环境文件的其它设置。使用DC需要编写脚本文件,其中内容主要是输入、输出文件的路径、电路的外部工作条件和时序约束等,详细内容将在后续章节介绍,以下仅介绍几个最基本的命令,使用这几个命令就可实现对设计代码的可综合性的检查。(1) read_verilog该命令用于读入verilog代码,基本格式为read_verilog 路径和文件名(2) elaborate 该命令用于将设计代码转换为统一的与工艺无关的内部电路,基本格式为elaborate 模块名注意是模块名,不是文件名。实际上,这个命令可以省略。(3) current_design 指定当前需要综合的模块,格式为current_design 模块名注意是模块名,不是文件名。(4) create_clock 用于确定时钟信号的名称、周期和波形等信息。例如, create_clock -name "clk" -period 10 -waveform 0 5 get_ports clk这个命令定义了一个名为clk的时钟信号,时钟周期为10,时间单位在标准单元库中定义,一般为ns。该时钟的占空比为50%,信号来自clk端口。该命令用法比较复杂,将在后续章节继续介绍。(5) set_input_delay这个命令用来定义输入信号的延迟,没有该定义无法综合,详细用法以后介绍。(6) compile执行优化和映射过程的命令,执行后可得到cell网表。以下是一个最简单的脚本,这个脚本主要用来检查代码是否存在不可综合的问题,正式综合时还要加入更多约束。脚本中的其它命令将在后续章节介绍。# 以下是设计代码的路径read_verilog $DC_WORK_DIR/code/counter.v# 指定需要综合的模块current_design counterlink# 每个输出需要驱动4个基本门set_fanout_load 4 all_outputs# 时序约束部分# 时钟频率100MHz。create_clock -name "clk" -period 10 -waveform 0 5 get_ports clk# 模块内部各寄存器时钟引脚处时钟沿的时间差,估计值。set_clock_uncertainty -setup 0.1 clkset_clock_uncertainty -hold 0.1 clk#输入信号相对时钟的延迟set_input_delay -max 2 -clock clk all_inputsset_input_delay -min 0.1 -clock clk all_inputs#暂不考虑时钟网络驱动能力问题 set_dont_touch_network get_clocks clk# 实现综合,映射到cell库compile#生成时序报告report_timing > $DC_WORK_DIR/rpt/setup_time.rptreport_timing -delay min > $DC_WORK_DIR/rpt/hold_time.rpt# 生成Verilog格式的cell网表文件write -format verilog -hier -o $DC_WORK_DIR/nt/counter_gate.vDC有多种启动方式,以下只介绍一种。首先,使用cd命令进入工作目录,然后输入design_vision,回车后将出现图2-2所示图形界面。图2-2 design_vision的操作界面利用菜单操作FileàExcute Script后弹出以下窗口,找到脚本文件后,点“Open”开始执行逻辑综合。图2-3 弹出窗口如果脚本和设计代码无误,即可得到综合后的电路图、网表和时序分析报告等文件。图2-4 综合后的电路图电路中的各个cell,如逻辑门、多路选择器和触发器等都来自标准单元库。MUX如果设计代码中有错误,将在窗口中出现错误或警告信息。电路图是由cell网表得到的,以下是verilog格式的网表,与标准单元库提供的各个cell的verilog文件放在一个project中,就进行“门级”仿真。DC还可生成各种报告文件,其中最重要的是时序报告。以下是网表文件。module counter ( rst, clk, ld, en, d, q, co );input 3:0 d;output 3:0 q;input rst, clk, ld, en;output co; wire n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16; MUX2 U3 ( .O(n15), .S(ld), .A(n7), .B(d2) ); INV2 U4 ( .O(n8), .I(n4) ); MUX2 U5 ( .O(n14)