auto compile.docx
《auto compile.docx》由会员分享,可在线阅读,更多相关《auto compile.docx(26页珍藏版)》请在冰豆网上搜索。
![auto compile.docx](https://file1.bdocx.com/fileroot1/2023-2/21/4a0224db-cb08-4bb0-abd4-3a7093493a18/4a0224db-cb08-4bb0-abd4-3a7093493a181.gif)
autocompile
自动综合IC设计流程教程
张建良shandy98@
2005年春季
一、自动综合流程概述
下图是一个比较完整的自动综合IC设计流程:
图中用不同颜色标出了设计的各个阶段采用的工具软件,主要有:
●NCVerilog/Modelsim:
NCVerilog是Cadence公司的chip级仿真软件,Modelsim是MentorGraphic公司推出的工业界应用广泛的仿真软件,都可以进行verilog/VHDL的仿真
●DesignCompiler:
synopsys公司的综合软件
●SiliconEnsemble:
cadence公司的自动布局布线工具
●Virtuoso:
cadence公司的版图编辑软件
●Icfb:
cadence公司的芯片设计集成环境
●Assura/Diva/Dracula/Calibre:
Assura/Diva/Dracula是cadence公司的DRC/LVS版图验证和寄生参数提取软件,Calibre是MentorGraphic公司的DRC/LVS版图验证和寄生参数提取软件
如何获取帮助:
1.synopsys的帮助文档可以用命令:
sold打开
2.cadence的帮助文档可以用命令:
cdsdoc打开,由于路径设置的问题,可能需要从菜单启动netscape浏览器
3.一般图形界面中都有“帮助”按钮,可以获得帮助信息
4.SMTHBBSIM/METECH
5.google
二、一个加法器的设计实例
下面以一个32位无符号整数乘法器的设计为例,介绍自动综合的设计流程。
所使用的库为SMIC0.18umCMOS标准单元Logic工艺库。
2.1系统功能定义(SPEC)
设计的第一步是确定用户需求,定义系统功能。
本设计中,要求:
1.设计一个32位无符号整数乘法器,采用SMIC0.18umCMOS标准单元Logic工艺库
2.输入端口定义在后面给出
3.速度尽可能快,面积不限,功耗不限
4.工作方式在后面给出
图2.1系统端口定义
表2.1系统端口定义
端口
方向
说明
cs
I
片选信号,低电平有效。
信号有效时才可以对乘法器执行读写操作
rw
I
读写信号,低电平为读操作,高电平为写操作
addr
I
4位地址总线,用于选择内部寄存器
clk
I
时钟输入
reset
I
复位信号,低电平有效
data
I/O
32位数据总线
finish
O
完成指示信号,低电平有效
乘法器内部包含多个寄存器用于存储当前状态、操作数、运算结果等,列表说明如下:
表2.2系统寄存器定义
寄存器
地址
允许操作
说明
M0,M1
0x1,0x2
R/W
乘数和被乘数,均为32位
P0
0x3
R
乘积低32位寄存器
P1
0x4
R
乘积高32位寄存器
STATUS
0x5
R/W
32位状态寄存器,详细定义见后面
所有寄存器在reset为低电平时清零。
STATUS寄存器定义:
b31-b1
b0
RUN
未定义,读出为0
写入1表示开始运算,读出0表示运算完成
工作流程:
1.reset=0
2.reset=1,cs=0,rw=1,addr=0x1,data=M0
3.reset=1,cs=0,rw=1,addr=0x2,data=M1
4.reset=1,cs=0,rw=1,addr=0x5,data=0x1
5.reset=1,cs=0,rw=0,addr=0x5直到读到data[0]=0为止或等待Finish信号为低电平
6.reset=1,cs=0,rw=0,addr=0x3得到data为乘积的低32位
7.reset=1,cs=0,rw=0,addr=0x4得到data为乘积的高32位
8.返回2继续做下一次运算
注意:
本设计中认为输入输出信号均与时钟信号同步,在实际的芯片设计中经常遇到片内时钟与片外时钟不同步(例如使用PLL等)的情况,这时候需要考虑输入信号的亚稳态问题。
2.2算法选择、优化和验证
确定了系统功能定义后需要选择合适的算法实现,由于本设计对于面积、功耗等没有特别的要求,且无符号整数乘法运算可以直接综合得到,本设计中不采用特殊设计的乘法算法,由综合器自动生成,可省略这一步的工作。
2.3结构级设计与前仿真
确定了算法之后,通过对算法的细致分析,可以划分系统结构,确定实现方案。
通常把系统划分为控制通路和数据通路两大部分,本设计中也采用这样的划分模式,把控制逻辑划分为控制通路,乘法运算作为数据通路。
图2.2系统划分
基于系统划分可以划出系统的详细框图(略),并采用Verilog描述:
//--------------------------------------------------------------------------------------
//mul32:
32x32intergermultiplier
//port:
dir:
function
//cs:
I:
chipselect,activelow
//clk:
I:
clock
//reset:
I:
reset,activelow
//rw:
I:
read(0)/write
(1)
//addr:
I:
addressbus
//datain:
I:
datain
//dataout:
O:
dataout
//finish:
O:
finishindicator
modulemul32(cs,clk,reset,rw,addr,datain,dataout,finish);
inputcs,clk,reset,rw;
input[3:
0]addr;
input[31:
0]datain;
output[31:
0]dataout;
outputfinish;
wire[31:
0]M0;
wire[31:
0]M1;
wire[63:
0]P;
datapathudatapath(M0,M1,P);
controlucontrol(cs,clk,reset,rw,addr,datain,dataout,finish,M0,M1,P);
endmodule
//--------------------------------------------------------------------------------------
//datapath
//port:
dir:
function
//M0:
I:
multiplicand
//M1:
I:
multiplier
//P:
O:
productor
moduledatapath(M0,M1,P);
input[31:
0]M0;
input[31:
0]M1;
output[63:
0]P;
assignP=M0*M1;
endmodule
//--------------------------------------------------------------------------------------
//controller
//port:
dir:
function
//cs:
I:
chipselect,activelow
//clk:
I:
clock
//reset:
I:
reset,activelow
//rw:
I:
read(0)/write
(1)
//addr:
I:
addressbus
//datain:
I:
datain
//dataout:
O:
dataout
//finish:
O:
finishindicator
//M0:
I:
multiplicand
//M1:
I:
multiplier
//P:
O:
productor
modulecontrol(cs,clk,reset,rw,addr,datain,dataout,finish,M0,M1,P);
inputcs,clk,reset,rw;
input[3:
0]addr;
input[31:
0]datain;
output[31:
0]dataout;
outputfinish;
output[31:
0]M0;
output[31:
0]M1;
input[63:
0]P;
reg[31:
0]M0;
reg[31:
0]M1;
reg[31:
0]P0;
reg[31:
0]P1;
regfinish;
reg[31:
0]dataout;
//always@(csorrworaddrorP0orP1orfinish)
always@(posedgeclk)
begin
if(~cs&&~rw)begin
case(addr)
4'h3:
dataout<=P0;
4'h4:
dataout<=P1;
4'h5:
dataout<=finish;
default:
dataout<=0;
endcase
endelsebegin
dataout<=0;
end
end
always@(posedgeclkornegedgereset)
begin
if(~reset)begin
M0<=0;
M1<=0;
{P1,P0}<=0;
finish<=1;
endelsebegin
if(~finish){P1,P0}<=P;
finish<=1;
if(~cs&&rw)begin
case(addr)
4'h1:
M0<=datain;
4'h2:
M1<=datain;
4'h5:
finish<=datain[0];
endcase
end
end
end
endmodule
//--------------------------------------------------------------------------------------
需要注意的是,对于设计中使用的双向端口可以先按照单向端口设计,再通过外层加一个模块把单向端口转换成双向端口:
//--------------------------------------------------------------------------------------
`include"mul32.v"
`include"control.v"
`include"datapath.v"
//top:
topmodulewithpads
//port:
dir:
function
//cs:
I:
chipselect,activelow
//clk:
I:
clock
//reset:
I:
reset,activelow
//rw:
I:
read(0)/write
(1)
//addr:
I:
addressbus
//data:
I/O:
databus
//finish:
O:
finishindicator
moduletop(cs,clk,reset,rw,addr,data,finish);
inputcs,clk,reset,rw;
input[3:
0]addr;
inout[31:
0]data;
outputfinish;
wirecs_core,clk_core,reset_core,rw_core;
wire[3:
0]addr_core;
wire[31:
0]datain_core,dataout_core;
wirefinish_core;
`ifdefDONT_USE_PAD
//don'tusepad,payattentiontotheinoutbus
assigncs_core=cs;
assignclk_core=clk;
assignreset_core=reset;
assignrw_core=rw;
assignaddr_core=addr;
assignfinish_core=finish;
assigndata=(!
rw)?
dataout_core:
32'hzzzzzzzz;
assigndatain_core=data;
`else
//wecanusePADsfromiolib
PIUPAD0(.PAD(cs),.C(cs_core));
PIUPAD1(.PAD(clk),.C(clk_core));
PIUPAD2(.PAD(reset),.C(reset_core));
PIUPAD3(.PAD(rw),.C(rw_core));
PIUPAD4(.PAD(addr[3]),.C(addr_core[3]));
PIUPAD5(.PAD(addr[2]),.C(addr_core[2]));
PIUPAD6(.PAD(addr[1]),.C(addr_core[1]));
PIUPAD7(.PAD(addr[0]),.C(addr_core[0]));
PO8UPAD8(.PAD(finish),.I(finish_core));
PB8UPAD9(.PAD(data[31]),.OEN(rw_core),.I(dataout_core[31]),.C(datain_core[31]));
PB8UPAD10(.PAD(data[30]),.OEN(rw_core),.I(dataout_core[30]),.C(datain_core[30]));
PB8UPAD11(.PAD(data[29]),.OEN(rw_core),.I(dataout_core[29]),.C(datain_core[29]));
PB8UPAD12(.PAD(data[28]),.OEN(rw_core),.I(dataout_core[28]),.C(datain_core[28]));
PB8UPAD13(.PAD(data[27]),.OEN(rw_core),.I(dataout_core[27]),.C(datain_core[27]));
PB8UPAD14(.PAD(data[26]),.OEN(rw_core),.I(dataout_core[26]),.C(datain_core[26]));
PB8UPAD15(.PAD(data[25]),.OEN(rw_core),.I(dataout_core[25]),.C(datain_core[25]));
PB8UPAD16(.PAD(data[24]),.OEN(rw_core),.I(dataout_core[24]),.C(datain_core[24]));
PB8UPAD17(.PAD(data[23]),.OEN(rw_core),.I(dataout_core[23]),.C(datain_core[23]));
PB8UPAD18(.PAD(data[22]),.OEN(rw_core),.I(dataout_core[22]),.C(datain_core[22]));
PB8UPAD19(.PAD(data[21]),.OEN(rw_core),.I(dataout_core[21]),.C(datain_core[21]));
PB8UPAD20(.PAD(data[20]),.OEN(rw_core),.I(dataout_core[20]),.C(datain_core[20]));
PB8UPAD21(.PAD(data[19]),.OEN(rw_core),.I(dataout_core[19]),.C(datain_core[19]));
PB8UPAD22(.PAD(data[18]),.OEN(rw_core),.I(dataout_core[18]),.C(datain_core[18]));
PB8UPAD23(.PAD(data[17]),.OEN(rw_core),.I(dataout_core[17]),.C(datain_core[17]));
PB8UPAD24(.PAD(data[16]),.OEN(rw_core),.I(dataout_core[16]),.C(datain_core[16]));
PB8UPAD25(.PAD(data[15]),.OEN(rw_core),.I(dataout_core[15]),.C(datain_core[15]));
PB8UPAD26(.PAD(data[14]),.OEN(rw_core),.I(dataout_core[14]),.C(datain_core[14]));
PB8UPAD27(.PAD(data[13]),.OEN(rw_core),.I(dataout_core[13]),.C(datain_core[13]));
PB8UPAD28(.PAD(data[12]),.OEN(rw_core),.I(dataout_core[12]),.C(datain_core[12]));
PB8UPAD29(.PAD(data[11]),.OEN(rw_core),.I(dataout_core[11]),.C(datain_core[11]));
PB8UPAD30(.PAD(data[10]),.OEN(rw_core),.I(dataout_core[10]),.C(datain_core[10]));
PB8UPAD31(.PAD(data[9]),.OEN(rw_core),.I(dataout_core[9]),.C(datain_core[9]));
PB8UPAD32(.PAD(data[8]),.OEN(rw_core),.I(dataout_core[8]),.C(datain_core[8]));
PB8UPAD33(.PAD(data[7]),.OEN(rw_core),.I(dataout_core[7]),.C(datain_core[7]));
PB8UPAD34(.PAD(data[6]),.OEN(rw_core),.I(dataout_core[6]),.C(datain_core[6]));
PB8UPAD35(.PAD(data[5]),.OEN(rw_core),.I(dataout_core[5]),.C(datain_core[5]));
PB8UPAD36(.PAD(data[4]),.OEN(rw_core),.I(dataout_core[4]),.C(datain_core[4]));
PB8UPAD37(.PAD(data[3]),.OEN(rw_core),.I(dataout_core[3]),.C(datain_core[3]));
PB8UPAD38(.PAD(data[2]),.OEN(rw_core),.I(dataout_core[2]),.C(datain_core[2]));
PB8UPAD39(.PAD(data[1]),.OEN(rw_core),.I(dataout_core[1]),.C(datain_core[1]));
PB8UPAD40(.PAD(data[0]),.OEN(rw_core),.I(dataout_core[0]),.C(datain_core[0]));
`endif
mul32umul32(cs_core,clk_core,reset_core,rw_core,addr_core,datain_core,dataout_core,finish_core);
endmodule
//--------------------------------------------------------------------------------------
为了处理反标时序信息时总线端口会被打散成单个位信号的问题(参见后面的反标部分),在外层加了一个“包裹”模块。
//--------------------------------------------------------------------------------------
`ifdefPOST_SIM
`include"top_post.v"
`else
`include"top.v"
`endif
//top_wrap:
topwrapmodule
//port:
dir:
function
//cs:
I:
chipselect,activelow
//clk:
I:
clock
//reset:
I:
reset,activelow
//rw:
I:
read(0)/write
(1)
//addr:
I:
addressbus
//data:
I/O:
databus
//finish:
O:
finishindicator
moduletop_wrap(cs,clk,reset,rw,addr,data,finish);
inputcs,clk,reset,rw;
input[3:
0]addr;
inout[31:
0]data;
outputfinish;
`ifdefPOST_SIM
`else
topu0(