本文参考自文章。
除了RTL仿真以外,在IC设计过程中还会进行门级网表的仿真。当设计代码功能仿真通过之后,我们便使用Design Compiler工具对其进行逻辑综合,将RTL代码转化为由与、或、非等门电路和触发器组成的电路,称为门级网表(netlist)。门级网表中包含了电路的实际信息,例如逻辑门单元的扇入扇出系数,延迟等等。对门级网表进行仿真可以发现由于引入这些实际信息所暴露出的错误,因此是必要的。
本文以一个alu设计为例,演示门级网表仿真的流程。
rtl代码
编写的rtl代码如下所示,它是一个简单的alu运算器,支持加、减、乘和比较等运算。
module alu
(
input wire clk,
input wire rst_n,
input wire en,
input wire [1:0] op,
input wire [31:0] A,
input wire [31:0] B,
output reg [31:0] Out
);
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
Out <= 32'd0;
end
else if(en) begin
case(op)
2'd0 : Out <= A + B;
2'd1 : Out <= A - B;
2'd2 : Out <= A * B;
2'd3 : Out <= (A > B) ? 32'd1 : 32'd0;
endcase
end
end
endmodule
逻辑综合
编写如下综合脚本,这里需要输出门级网表和sdf文件。
set_app_var search_path /home/eda/Desktop/alu/digital_lib/TSMC_013/synopsys
set_app_var target_library slow.db
set_app_var link_library slow.db
read_file -format verilog {./alu.v}
check_design
create_clock -period 10 [get_ports clk]
set_input_delay -max 3 -clock clk [remove_from_collection [all_inputs] clk]
set_output_delay -max 2.5 -clock clk [all_outputs]
set_input_transition 0.15 [all_inputs]
check_design
compile
report_clock
report_timing
report_area
write_sdc alu.sdc
write_sdf -version 2.1 alu.sdf
write_file -format verilog -output alu_netlist.v
输入dc,然后source run.tcl开始综合。综合完成后,可以得到alu.sdf文件和alu_netlist.v文件。
SDF文件(Standard Delay File)提供了延迟信息表示的标准ASCII文件格式,VCS支持版本1.0、1.1、2.0、2.1和3.0。在SDF格式中可以指定固有延迟(intrinsic delays),互连延迟(interconnect delays),端口延迟(port delays),时序检查(timing checks),时序约束(timing constraints)和路径脉冲(PATHPULSE)。
下面是alu.sdf的一部分:
下面是alu_netlist文件的一部分:
门级网表仿真
为了对门级网表进行仿真,编写如下tb:
module alu_tb;
reg clk;
reg rst_n;
reg en;
reg [1:0] op;
reg [31:0] A;
reg [31:0] B;
wire [31:0] Out;
initial begin
clk = 1'b0;
forever begin
#5 clk = ~clk;
end
end
initial begin
rst_n = 1'b0;
#100
rst_n = 1'b1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
en <= 1'b0;
op <= 2'b0;
A <= 32'd0;
B <= 32'd0;
end
else if({$random} % 100 <60) begin
en <= 1'b1;
op <= {$random} % 4;
A <= {$random} % 1024;
B <= {$random} % 1024;
end
else begin
en <= 1'b0;
end
end
initial begin
$fsdbDumpfile("alu.fsdb");
$fsdbDumpvars(0);
end
initial begin
`ifdef NET_SIM
$sdf_annotate("./alu.sdf",
alu,,,
"TYPICAL",
"1:1:1",
"FROM_MTM");
`endif
end
initial begin
#1000
$finish;
end
alu alu_inst
(
.clk (clk ),
.rst_n(rst_n),
.en (en ),
.op (op ),
.A (A ),
.B (B ),
.Out (Out )
);
endmodule
与rtl仿真不同的是,在门级网表仿真时,需要使用$sdf_annotate系统任务读取SDF文件,并将延迟值“反向标注(back-annotates)”到设计中,即在源文件中添加或者更改延迟值。该函数的详细使用可以参见文章。
然后,编写仿真的makefile脚本:
OUTPUT = alu
CM = -cm line+cond+fsm+branch+tgl
CM_NAME = -cm_name ${OUTPUT}
CM_DIR = -cm_dir ./${OUTPUT}.vdb
LIB_FILE = -v ./digital_lib/TSMC_013/verilog/tsmc13.v
all: listfile com sim verdi clean
listfile:
find -name "*.v" > filelist.f
com:
vcs -full64 -cpp g++-4.8 -cc gcc-4.8 -LDFLAGS -Wl,--no-as-needed \
-sverilog -debug_access -timescale=1ns/10ps \
-f filelist.f -l com.log -kdb -lca +define+NET_SIM +neg_tchk \
${CM} ${CM_NAME} ${CM_DIR} ${LIB_FILE}
sim:
./simv -l sim.log ${CM} ${CM_NAME} ${CM_DIR}
cov:
dve -full64 -covdir *.vdb &
urg:
urg -dir *.vdb
verdi:
verdi -f filelist.f -ssf *.fsdb -nologo &
clean:
rm -rf csrc *.log *.key *simv* *.vpd *DVE*
rm -rf verdiLog *.fsdb *.bak *.conf *.rc *.f
上述代码中,我们在makefile文件中添加了一个开关选项,由于网表.v文件是由工艺库单元例化的,工艺库中给出了一个verilog文件,包含各个单元。
运行make com; make sim; make verdi
,得到如下仿真波形:
由图可知,输出相对于时钟上升沿有一定的延迟,这是门级网表仿真和rtl仿真不同的地方。