Design Compiler工具学习笔记(6)



目录

引言

知识储备

实际操作

设计源码

仿真源码

VCS执行仿真

DC 综合

TCL编程练习






引言

本篇继续学习 DC的基本使用。本篇主要学习 DC 综合之后的效果分析,重点在时序分析。

前文链接:

Design Compiler工具学习笔记(1)

Design Compiler工具学习笔记(2)

Design Compiler工具学习笔记(3)

Design Compiler工具学习笔记(4)

Design Compiler工具学习笔记(5)



知识储备

 小数点精度位数一般为 13 (-significant_digits)

 report_timing ::仅报告最差的路径时序;

report_timing -max_paths 2 :报告出两条最差的路径,但是这两条路径的终点不同

report_timing -nworst 2 -max_paths 2:报告出整个设计中最差的两条路径,可以是同一个终点

 建立时间违规必须全部修改,面积违规和保持时间违规可以保留。

出现违规时可能的情况:输入/出延迟过大,约束过紧;设计的组合逻辑部分延迟过大。

 

 

 

 

 

 

 

 

 

 

 





实际操作

以单比特信号以握手方式完成时钟域跨越。

设计源码

// |===================================== TOP ==============================
// |Author:Xu Y. B.
// |Date:2022-11-23
// |Description: TOP module 
// |			 about single bit signal CDC using handshake mode
// |			 CDC:100MHz-->50MHz
// |========================================================================

module TOP (
// ======================= module input ports specify ================== 
// time domain 100MHz
input 						I_CLK_100M,
input 						I_RSTN_100M,


// time domain 200MHz
input 						I_CLK_50M,
input 						I_RSTN_50M,

// operate enable
input 						I_OPR_EN,//high,start 1 CDC test

// ======================= module output ports specify ================== 
output 		reg 			O_CDC_DONE

);
// ======================= module local parameters =====================


// ======================= module internal signals =====================
// register input signal I_OPR_EN  
reg 						[1:0]				R_I_OPR_EN;
wire 											W_I_OPR_EN_PDG;
reg 											R_CDC_QST_100M;
reg 						[1:0]				R_CDC_QST_50M;

reg 											R_CDC_ACK_50M;
reg 						[1:0]				R_CDC_ACK_100M;

// ======================= module design logic =========================
always @ (posedge I_CLK_100M)
begin:pro_opr_en_reg
	if(~I_RSTN_100M)
	begin
		R_I_OPR_EN <= 2'b00;
	end
	else
	begin
		R_I_OPR_EN[0] <= I_OPR_EN;
		R_I_OPR_EN[1] <= R_I_OPR_EN[0];
	end
end

assign W_I_OPR_EN_PDG = R_I_OPR_EN[0] & (~R_I_OPR_EN[1]);

always @ (posedge I_CLK_100M)
begin
	if(~I_RSTN_100M)
	begin
		R_CDC_QST_100M <= 0;
	end
	else
	begin
		if(W_I_OPR_EN_PDG)
		begin
			R_CDC_QST_100M <= 1;
		end
		else if(R_CDC_ACK_100M[1])
		begin
			R_CDC_QST_100M <= 0;
		end
		else
		begin
			R_CDC_QST_100M <= R_CDC_QST_100M;
		end
	end
end

always @ (posedge I_CLK_100M)
begin
	if(~I_RSTN_100M)
	begin
		R_CDC_ACK_100M <=2'b0;
	end
	else
	begin
		R_CDC_ACK_100M[0] <= R_CDC_ACK_50M;
		R_CDC_ACK_100M[1] <= R_CDC_ACK_100M[0];
	end
end

// 50M
always @ (posedge I_CLK_50M)
begin
	if(~I_RSTN_50M)
	begin
		R_CDC_ACK_50M <= 0;
	end
	else
	begin
		if(R_CDC_QST_50M[1])
		begin
			R_CDC_ACK_50M <= 1;
		end
		else
		begin
			R_CDC_ACK_50M <= 0;
		end
	end
end

always @ (posedge I_CLK_50M)
begin
	if(~I_RSTN_50M)
	begin
		R_CDC_QST_50M <= 2'b00;
	end
	else
	begin
		R_CDC_QST_50M[0] <= R_CDC_QST_100M;
		R_CDC_QST_50M[1] <= R_CDC_QST_50M[0];
	end
end

always @ (posedge I_CLK_100M)
begin
	if(~I_RSTN_100M)
	begin
		O_CDC_DONE <= 0;
	end
	else
	begin
		if(R_CDC_ACK_100M)
		begin
			O_CDC_DONE <= 1;
		end
		else
		begin
			O_CDC_DONE <= 0;
		end
	end
end



endmodule

仿真源码

// |========================== Test Bench ===========================
// |Author:Xu Y. B.
// |Date:2022-11-23
// |Description: TOP module 
// |			 about single bit signal CDC using handshake mode
// |			 CDC:100MHz-->50MHz
// |			 Test Bench
// |==================================================================


module TB ();

// time domain 100MHz
reg 						I_CLK_100M;
reg 						I_RSTN_100M;


// time domain 200MHz
reg 						I_CLK_50M;
reg 						I_RSTN_50M;

// operate enable
reg 						I_OPR_EN;//high,start 1 CDC test

// ======================= module output ports specify ================== 
wire			 			O_CDC_DONE;


// ======================= generate clocks ==============================
initial I_CLK_100M = 0;
always #5 I_CLK_100M = ~I_CLK_100M;

initial I_CLK_50M = 0;
always #10 I_CLK_50M = ~I_CLK_50M;

initial
begin
	I_RSTN_100M = 0;
	I_RSTN_50M = 0;
	I_OPR_EN = 0;
	#20;
	I_RSTN_100M = 1;
	#40;
	I_RSTN_50M = 1;
	#20;
	I_OPR_EN = 1;

	@(negedge O_CDC_DONE)
	#50;
	$finish;
end

initial
begin
	`ifdef VPD_TEST
		$vcdpluson();
	`endif
end

TOP INST_TOP
	(
		.I_CLK_100M  (I_CLK_100M),
		.I_RSTN_100M (I_RSTN_100M),
		.I_CLK_50M   (I_CLK_50M),
		.I_RSTN_50M  (I_RSTN_50M),
		.I_OPR_EN    (I_OPR_EN),
		.O_CDC_DONE  (O_CDC_DONE)
	);


endmodule

VCS执行仿真

makefile 文件:

# =======================================================
# ========================== MAKE FILE ==================
# By:Xu Y. B.
# Date:2022-11-23
# Note:
# reuse this makefile ,the followings should be changed:
# -1- OUTPUT
# -2- TB file add the following:
# 	  `ifdef VPD_TEST
# 			$vcdpluson();
# 	  `endif
# =======================================================

.PHONY: com cov clean debug

OUTPUT = SIMV_CDC_TEST

VPD_SW_DEFINE = +define+VPD_TEST


# code coverage command
CM = -cm line+cond+fsm+branch+tgl
CM_NAME = -cm_name $(OUTPUT)
CM_DIR = -cm_dir ./$(OUTPUT).vdb

# vpdfile name
VPD_NAME = $(OUTPUT).vpd


# compile command
VCS = vcs -full64 -cpp g++-4.8 -cc gcc-4.8 -LDFLAGS -Wl,--no-as-needed   \
	  -simprofile 							 \
	  -sverilog +v2k -timescale=1ns/1ns      \
      -debug_access+r 	             		 \
      -Mupdate								 \
      +notimingcheck			     		 \
      +nospecify			                 \
      +vcs+flush+all			             \
      $(VPD_SW_DEFINE)						 \
      -o $(OUTPUT)							 \
      -l compile.log						 
      # $(CM)				                 	 \
      # $(CM_NAME)							 \
      # $(CM_DIR)								 
# -cm_hier ./vcs_cov.cfg
      							 
      

# simulation command
SIM = ./$(OUTPUT)							 \
      -l $(OUTPUT).log						 \
	  $(CM) $(CM_NAME) $(CM_DIR)	         \
	  $(VPD_NAME)							 \
	  

# start complie
com:	
	find -name "*.v" >filelist.f 
	$(VCS) -f filelist.f


# start simulation
sim:
	$(SIM)
	mv vcdplus.vpd $(VPD_NAME)

# show the coverage
cov:
	dve -full64 -covdir *.vdb &
debug:
	dve -full64 -vpd $(OUTPUT).vpd &

# start clean
clean:
	rm -rf ./csrc *.daidir *.log *.vpd *.vdb simv* *.key *race.out* *.so.* *profile* *.f

DC 综合

脚本:

供参考~~~~~~~~~~

# |===========================================================
# | Author 		: Xu Y. B.
# | Date   		: 2022-11-21
# | Description : tcl script for top design 
# |===========================================================


# |===========================================================
# |STEP 1: Read & elaborate the RTL design file list & check
# |===========================================================
set TOP_MODULE CDC_TOP
analyze        -format verilog [list CDC_TOP.v ]
elaborate      $TOP_MODULE     -architecture verilog
current_design $TOP_MODULE

if {[link] == 0} {
	echo "Your Link has errors !";
	exit;
}

if {[check_design] == 0} {
	echo "Your check design has errors !";
	exit;
}

# |===========================================================
# |STEP 2: reset design
# |===========================================================
reset_design


# |===========================================================
# |STEP 3: Write unmapped ddc file
# |===========================================================
uniquify
set uniquify_naming_style "%s_%d"
write -f ddc -hierarchy -output ${UNMAPPED_PATH}/${TOP_MODULE}.ddc


# |===========================================================
# |STEP 4: define clocks
# |===========================================================
# -------------------------- CLK 100MHz ----------------------
set       CLK_NAME          	I_CLK_100M
set       CLK_PERIOD        	10
set       CLK_SKEW	        	[expr {$CLK_PERIOD*0.05}]						
set       CLK_TRANS         	[expr {$CLK_PERIOD*0.01}]						
set       CLK_SRC_LATENCY   	[expr {$CLK_PERIOD*0.1 }]						
set       CLK_LATENCY       	[expr {$CLK_PERIOD*0.1 }]						

create_clock 			-period 	$CLK_PERIOD  	  [get_ports $CLK_NAME]
set_ideal_network 						 			  [get_ports $CLK_NAME]
set_dont_touch_network 					 			  [get_ports $CLK_NAME]
set_drive 				0 							  [get_ports $CLK_NAME]

set_clock_uncertainty   -setup       $CLK_SKEW        [get_clocks $CLK_NAME]
set_clock_transition    -max         $CLK_TRANS       [get_clocks $CLK_NAME]
set_clock_latency       -source -max $CLK_SRC_LATENCY [get_clocks $CLK_NAME]
set_clock_latency       -max         $CLK_LATENCY     [get_clocks $CLK_NAME]

# --------------------------- CLK 50MHz ----------------------
set       CLK_NAME_2          	I_CLK_50M
set       CLK_PERIOD_2        	20
set       CLK_SKEW_2	        [expr {$CLK_PERIOD_2*0.05}]						
set       CLK_TRANS_2         	[expr {$CLK_PERIOD_2*0.01}]						
set       CLK_SRC_LATENCY_2   	[expr {$CLK_PERIOD_2*0.1 }]						
set       CLK_LATENCY_2       	[expr {$CLK_PERIOD_2*0.1 }]						

create_clock 			-period 	$CLK_PERIOD_2  	  [get_ports $CLK_NAME_2]
set_ideal_network 						 			  [get_ports $CLK_NAME_2]
set_dont_touch_network 					 			  [get_ports $CLK_NAME_2]
set_drive 				0 							  [get_ports $CLK_NAME_2]

set_clock_uncertainty   -setup       $CLK_SKEW_2        [get_clocks $CLK_NAME_2]
set_clock_transition    -max         $CLK_TRANS_2       [get_clocks $CLK_NAME_2]
set_clock_latency       -source -max $CLK_SRC_LATENCY_2 [get_clocks $CLK_NAME_2]
set_clock_latency       -max         $CLK_LATENCY_2     [get_clocks $CLK_NAME_2]


# |===========================================================
# |STEP 5: define reset
# |===========================================================
# ------------------------- RST 1 ----------------------------
set RST_NAME 					I_RSTN_100M
set_ideal_network 				[get_ports $RST_NAME]
set_dont_touch_network          [get_ports $RST_NAME]
set_drive             0         [get_ports $RST_NAME]

# ------------------------- RST 2 ----------------------------
set RST_NAME_2 					I_RSTN_50M
set_ideal_network 				[get_ports $RST_NAME_2]
set_dont_touch_network          [get_ports $RST_NAME_2]
set_drive             0         [get_ports $RST_NAME_2]


# |===========================================================
# |STEP 6: set input delay using timing budget
# |Assume a weak cell to drive the input pins
# |===========================================================
set 		LIB_NAME 			typical
set 		WIRE_LOAD_MODEL 	smic18_wl10
set 		DRIVE_CELL 			INVX1
set 		DRIVE_CELL_2 		INVX4
set 		DRIVE_CELL_3		INVX8

set 		DRIVE_PIN 			Y
set 		OPERATE_CONDITION   typical

set 		INPUT_RST 			 [get_ports I_RSTN_100M]
set 		INPUT_RST_2			 [get_ports I_RSTN_50M]


set         INPUT_DELAY 		 [expr {$CLK_PERIOD*0.6}]
set         INPUT_DELAY_2 		 [expr {$CLK_PERIOD_2*0.6}]
# CLK 1
set_input_delay $INPUT_DELAY -clock $CLK_NAME [get_ports I_OPR_EN]
set_input_delay $INPUT_DELAY -clock $CLK_NAME ${INPUT_RST}

# CLK 2
set_input_delay $INPUT_DELAY_2 -clock $CLK_NAME_2 ${INPUT_RST_2}

# DRIVE CELL
set_driving_cell -lib_cell ${DRIVE_CELL}   -pin ${DRIVE_PIN}   ${INPUT_RST}
set_driving_cell -lib_cell ${DRIVE_CELL_2} -pin ${DRIVE_PIN}   ${INPUT_RST_2}
set_driving_cell -lib_cell ${DRIVE_CELL_3} -pin ${DRIVE_PIN}   [get_ports I_OPR_EN]



# |===========================================================
# |STEP 7: set output delay 
# |===========================================================
set OUTPUT_DELAY  [expr {$CLK_PERIOD*0.6}]
set MAX_LOAD      [expr {[load_of $LIB_NAME/INVX4/A] * 10}]

set_output_delay  $OUTPUT_DELAY -clock $CLK_NAME 	 [all_outputs]
set_load 		  [expr {$MAX_LOAD * 3}] 			 [all_outputs]
set_isolate_ports -type buffer 					 	 [all_outputs]


# |===========================================================
# |STEP 8: set max delay for comb logic 
# |===========================================================
# set_input_delay  [expr $CLK_PERIOD * 0.1] -clock $CLK_NAME -add_delay [get_ports I_1]
# set_output_delay [expr $CLK_PERIOD * 0.1] -clock $CLK_NAME -add_delay [get_ports O_1]


# |===========================================================
# |STEP 9: set operating condition & wire load model 
# |===========================================================
set_operating_conditions -max 			$OPERATE_CONDITION \
						 -max_library 	$LIB_NAME

set 					 auto_wire_load_selection false
set_wire_load_mode  	 top
set_wire_load_model		 -name    $WIRE_LOAD_MODEL \
						 -library $LIB_NAME


# |===========================================================
# |STEP 10: set area constraint (Let DC try its best) 
# |===========================================================
set_max_area			 1000


# |===========================================================
# |STEP 11: set DRC constraint 
# |===========================================================
# set MAX_CAPACITANCE [expr {[load_of $LIB_NAME/NAND4X2/Y] * 5}]
# set_max_capacitance $MAX_CAPACITANCE $ALL_INPUT_EXCEPT_CLK


# |===========================================================
# |STEP 12: set group path
# |Avoid getting stack on one path
# |===========================================================
# group_path -name $CLK_NAME -weight 5 				\
# 						   -critical_range  [expr {$CLK_PERIOD * 0.1}] 

# group_path -name INPUTS    -from [all_inputs] 		\
# 					 	   -critical_range  [expr {$CLK_PERIOD * 0.1}] 

# group_path -name OUTPUTS   -to [all_outputs] 		\
# 						   -critical_range  [expr {$CLK_PERIOD * 0.1}] 

# group_path -name COMBS     -from [all_inputs] 		\
# 						   -to [all_outputs] 		\
# 						   -critical_range  [expr {$CLK_PERIOD * 0.1}] 	
# report_path_group


# |===========================================================
# |STEP 13: Elimate the multiple-port inter-connect &
# |			define name style
# |===========================================================
# set_app_var 						verilogout_no_tri 					true
# set_app_var						verilogout_show_unconnected_pins 	true
# set_app_var						bus_naming_style					{%s[%d]}
# simplify_constants 				-boundary_optimization
# set_boundary_optimization 		[current_design] 					true
# set_fix_multiple_port_nets 		-all 								-buffer_constants


# |===========================================================
# |STEP 14: timing exception define
# |===========================================================
# set_false_path -from [get_clocks I_CLK_100M] -to [get_clocks I_CLK_100M]
# set ALL_CLKS [all_clocks]
# foreach_in_collection CUR_CLK $ALL_CLKS 
# {
# 	set OTHER_CLKS [remove_from_collection [all_clocks] $CUR_CLK]
# 	set_false_path -from $CUR_CLK $OTHER_CLKS
# }

# set_false_path -from [get_clocks I_CLK_100M] -to [get_clocks I_CLK_100M]
# set_false_path -from [get_clocks I_CLK_100M] -to [get_clocks I_CLK_100M]

# set_disable_timing TOP/U1 -from a -to y
# set_case_analysis 0 [get_ports sel_i]

# set_multicycle_path -setup 6 -from FFA/CP -through ADD/out -to FFB/D
# set_multicycle_path -hold 5 -from FFA/CP -through ADD/out -to FFB/D
# set_multicycle_path -setup 2 -to FFB/D
# set_multicycle_path -hold 1 -to FFB/D



# |===========================================================
# |STEP 15: compile flow
# |===========================================================
# ungroup -flatten -all

# 1st-pass compile
# compile -map_effort high -area_effort high
# compile -map_effort high -area_effort high -boundary_optimization
compile 

# simplify_constants -boundary_optimization
# set_fix_multiple_port_nets -all -buffer_constants

# compile -map_effort high -area_effort high -incremental_mapping -scan

# 2nd-pass compile
# compile -map_effort high -area_effort high -incremental_mapping -boundary_optimization
# compile_ultra -incr


# |===========================================================
# |STEP 16: write post-process files
# |===========================================================
# change_names -rules verilog -hierarchy
# remove-unconnected_ports [get_cells -hier *] -blast_buses
# Write the mapped files
write -f ddc -hierarchy -output $MAPPED_PATH/${TOP_MODULE}.ddc
# write 	-f verilog 	-hierarchy -output 	$MAPPED_PATH/${TOP_MODULE}.v
# write_sdc -version 	1.7 				$MAPPED_PATH/${TOP_MODULE}.sdc
# write_sdf -version 	2.1 				$MAPPED_PATH/${TOP_MODULE}.sdf

# |===========================================================
# |STEP 17: generate report files
# |===========================================================

在完成编译之后可以用本篇的PPT里面介绍的 时序报告指令进行时序分析。此处不再赘述。

TCL编程练习


# |================================= Tcl coding practice ===========================
# |Coded by:Xu Y. B.
# |Date:2022-11-25
# |Description:basic Tcl syntax 
# |=================================================================================

# ******** example :define your variable  
set FILE_NAME Sample_Test
set VAR_1	  0

# ******** example :if-else 
if {$VAR_1 == 0} {
	echo "Your variable VAR_1 is 0"
}  else  {
	echo "Your variable VAR_1 is not 0"
}

# ******** example :switch
switch -regexp   $FILE_NAME {
	"Sample_Test" {
		echo "The File is Right"	
	}
	"Test" {
		echo "The File is others"
	}
	default {
		echo "The File is nothing !"
	}
}

# ********* example :while
set i 1
while {$i <= 10} {
	echo "i = $i";
	incr i 1;	
}

# ********* example :for
for {set i_a 0} {$i_a <= 20} {incr i_a 2} {					
	if {$i_a == 4 || $i_a == 18} {					
		continue;						
		# break;						
	}					
	echo "i_a = $i_a";					
}					

# ********* example :foreach
# example 1
set MY_LIST [list "Xu Y. B." "is" 23 "years" "old"]

foreach MY_LIST $MY_LIST {
	switch -regexp $MY_LIST {
		"Xu Y. B." {
			echo "$MY_LIST is a name"
		}
		23 {
			echo "$MY_LIST is a number"
		}
		default {
			echo "$MY_LIST"
		}
	}
}

# example 2
set log_file_cnt 0
set v_file_cnt   0
set tcl_file_cnt 0

set my_file_list [glob *.log *.v *.tcl]

foreach f_name $my_file_list {
	set f_ext [file extension $f_name]
	switch  $f_ext {
		".log" {
			incr log_file_cnt
		}
		".v" {
			incr v_file_cnt
		}
		".tcl" {
			incr tcl_file_cnt
		}
	}
}

echo "The current folder contains totally .log file number is $log_file_cnt";
echo "The current folder contains totally .v file number is $v_file_cnt"
echo "The current folder contains totally .tcl file number is $tcl_file_cnt"

# ********** example :Write something to a file
set   TEXT_W "Xu Y. B. is my name"
set   FILE_ID_W [open TEST.txt w+]
puts  $FILE_ID_W $TEXT_W
flush $FILE_ID_W
close $FILE_ID_W


# ********** example :Read something from a file
set TEXT_R ""
set FILE_ID_R [open TEST.txt r]
gets $FILE_ID_R TEXT_R
echo "\" $TEXT_R \"is read from file id $FILE_ID_R"

close $FILE_ID_R

# ********** example :proc
# example 1:
set NAME "Xu Y. B."

proc my_print_var {var_name} \
{	
	global NAME
	echo "var_name is \" $var_name \""
	echo "var_name is \" $NAME \""
}

my_print_var NAME


# example 2:
proc min {a b c d} \
{
	if {$a >= $b} {
		set y $b;
	} else {
		set y $a;
	}

	if {$c >= $d} {
		set z $d;
	} else {
		set z $c;
	}

	if {$y >= $z} {
		set w $z;
	} else {
		set w $y
	}
	return $w;
}

# min 11 21 3 4


# example 3 :
proc sum {args} \
{
	set num_list $args
	set sum 0
	foreach num $num_list {
		set sum [expr ($sum + $num)]
	}
	return $sum
}

# sum 1 2 3 4

# example 4 :
# array set PORTS [list I_CLK 3 I_RSTN 4 I_DATA 5 O_DATA 6]
set PORTS {I_CLK 12 I_RSTN 4 I_DATA 5 O_DATA 6}

proc inc_port {port_num_list} \
{
	array set PORTS_1 $port_num_list
	set port_list [array names PORTS_1]
	foreach port $port_list {
		incr PORTS_1($port) 20
	}
	return [array get PORTS_1]
}


# inc_port  $PORTS

# example 5 :
# create a link to the variable outside
set NUMBER 0					
proc incr_ten {num} {					
	upvar $num local_var					
	incr local_var 10					
}					
					
incr_ten $NUMBER					

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在路上-正出发

哈哈,多少是个心意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值