前言
前排提示:xilinx论坛提供了一种更好的方法,我的TCL修改网表的方法,随便看看就好了。
有的时候,比如设计中深层次调用了DDR。DDR控制器的芯片相关的端口需要连接到管脚上,如果一路层层穿出来的话太麻烦。
经过学习发现可以利用TCL修改网表避免层层穿出。
XILINX论坛提供的方法
真是大开眼界,xilinx论坛官方给了一个更好的方法。推荐使用这个方法,我上面的回答随便看看就好了。
下面是复制的回答:
在代码侧可以使用hierarchical naming的方式把底层的管脚直接接到顶层,而无需层层改接口.
Ex:
模块层次clkx_pre_i0/meta_harden_bus_new_i0 , Pin:signal_dst
output my_output,
…
assign my_output = clkx_pre_i0.meta_harden_bus_new_i0.signal_dst;
底层的端口如果是输入,只能悬空,否则会形成多驱动.
如果是输出,可以悬空,也可以连接驱动其他信号.
的确,一般不建议这么写,读底层代码时容易忘记顶层还有连接,可以加注释提醒自己.
TCL修改综合后网表的方法
工程里面的IP 采用的OOC模式综合的,非OOC模式下内部的逻辑会被优化,建议对要层层穿出的模块使用OOC模式综合。
先从一个示例工程看看过程。
代码跳转
修改前
原理图
这个图里可以看到两个差分时钟和复位信号都没有接到顶层。
而且顶层设计中也没有相关的端口。下面开始用TCL进行修改。
TCL修改网表
- 代码中利用(* keep = “true” )避免优化,不能用( dont_touch = “yes” *),dont_touch会导致不能修改网表。
- 创建端口
- 创建BUFER
- 连接net
- 上板测试
# 创建端口
create_port -direction IN -diff_pair sys_clk_p sys_clk_n
create_port -direction IN rst
#创建输入BUF,因为时钟输入直接引到PLL上了所以不用加BUF了
create_cell -reference IBUF rst_IBUF_inst
#创建net
create_net rst_net
#移除 图中wrapper里面的3个lut
remove_cell design_1_wrapper_i/i_0
remove_cell design_1_wrapper_i/i_1
remove_cell design_1_wrapper_i/i_2
#连接 net
connect_net -net rst_net -objects [get_ports rst]
connect_net -net rst_net -objects rst_IBUF_inst/I
connect_net -hier -net design_1_wrapper_i/reset_0 -objects rst_IBUF_inst/O
connect_net -hier -net design_1_wrapper_i/CLK_IN1_D_0_clk_p -objects [get_ports sys_clk_p]
connect_net -hier -net design_1_wrapper_i/CLK_IN1_D_0_clk_n -objects [get_ports sys_clk_n]
#约束端口,新的端口只能在创建后进行约束
set_property IOSTANDARD DIFF_SSTL12 [get_ports sys_clk_p]
set_property IOSTANDARD DIFF_SSTL12 [get_ports sys_clk_n]
set_property PACKAGE_PIN G31 [get_ports sys_clk_p]
set_property PACKAGE_PIN F31 [get_ports sys_clk_n]
set_property IOSTANDARD LVCMOS12 [get_ports rst]
set_property PACKAGE_PIN L19 [get_ports rst]
综合流程中插入tcl
把上面的tc脚本插入图中,就可以避免手动运行了。
上板测试
非OOC模式下
我测试了一下非OOC模式,原理图如图
对比OOC模式下的原理图
逻辑还是被优化了。
参考UG901 p55页对keep的解释
keep能保留对应的信号但是该信号不会驱动任何东西。
参考UG901 P48页对dont_touch的解释,dont_touch可以forward-annotated to place and route阻止相关的逻辑被优化。
但是用dont_touch就不能tcl修改对应的网表。非OOC模式下这个方法暂时还是不行。
只能建议对要层层穿出的模块使用OOC模式综合。然后再用TCL修改网表。
参考文献
相关文件
1,顶层代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/12/01 16:48:50
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module top
(
// input sys_clk_p,
// input sys_clk_n,
// input rst,
(* mark_debug = "true" *)input start,
output q);
(* mark_debug = "true" *)wire [15:0]BRAM_PORTA_0_addr;
wire BRAM_PORTA_0_clk;
(* mark_debug = "true" *)wire [31:0]BRAM_PORTA_0_din;
wire [31:0]BRAM_PORTA_0_dout;
assign BRAM_PORTA_0_dout = 0;
(* mark_debug = "true" *)wire BRAM_PORTA_0_en;
wire BRAM_PORTA_0_rst;
wire [3:0]BRAM_PORTA_0_we;
(* mark_debug = "true" *)wire clk_out_25;
(* dont_touch = "yes" *) wire clk_out_50;
design_1_wrapper design_1_wrapper_i
(.BRAM_PORTA_0_addr(BRAM_PORTA_0_addr),
.BRAM_PORTA_0_clk(BRAM_PORTA_0_clk),
.BRAM_PORTA_0_din(BRAM_PORTA_0_din),
.BRAM_PORTA_0_dout(BRAM_PORTA_0_dout),
.BRAM_PORTA_0_en(BRAM_PORTA_0_en),
.BRAM_PORTA_0_rst(BRAM_PORTA_0_rst),
.BRAM_PORTA_0_we(BRAM_PORTA_0_we),
// .CLK_IN1_D_0_clk_n(sys_clk_n),
// .CLK_IN1_D_0_clk_p(sys_clk_p),
.clk_out_25(clk_out_25),
.clk_out_50(clk_out_50)
// .reset_0(rst)
);
(* mark_debug = "true" *) reg [13:0] addrb;
(* mark_debug = "true" *) wire [31:0] doutb;
(* mark_debug = "true" *) wire [15:0] BRAM_PORTA_0_addr_rshift2;
assign BRAM_PORTA_0_addr_rshift2 = BRAM_PORTA_0_addr>>2;
blk_mem_gen_0 usr_bram (
.clka(BRAM_PORTA_0_clk), // input wire clka
.ena(BRAM_PORTA_0_en), // input wire ena
.wea(BRAM_PORTA_0_we), // input wire [0 : 0] wea
.addra(BRAM_PORTA_0_addr_rshift2), // input wire [13 : 0] addra
.dina(BRAM_PORTA_0_din), // input wire [31 : 0] dina
.clkb(clk_out_25), // input wire clkb
.enb(1'b1), // input wire enb
.addrb(addrb), // input wire [13 : 0] addrb
.doutb(doutb) // output wire [31 : 0] doutb
);
assign q = |doutb;
always@(posedge clk_out_25)begin
if(start)addrb <= 0;
else if(addrb == {14{1'b1}}) addrb <= addrb;
else addrb <= addrb + 1;
end
endmodule
2, design_1_wrapper 代码
//Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2020.2 (win64) Build 3064766 Wed Nov 18 09:12:45 MST 2020
//Date : Thu Dec 2 17:42:39 2021
//Host : DESKTOP-9H6R9V9 running 64-bit major release (build 9200)
//Command : generate_target design_1_wrapper.bd
//Design : design_1_wrapper
//Purpose : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps
module design_1_wrapper
(BRAM_PORTA_0_addr,
BRAM_PORTA_0_clk,
BRAM_PORTA_0_din,
BRAM_PORTA_0_dout,
BRAM_PORTA_0_en,
BRAM_PORTA_0_rst,
BRAM_PORTA_0_we,
// CLK_IN1_D_0_clk_n,
// CLK_IN1_D_0_clk_p,
clk_out_25,
clk_out_50,
// reset_0
);
output [15:0]BRAM_PORTA_0_addr;
output BRAM_PORTA_0_clk;
output [31:0]BRAM_PORTA_0_din;
input [31:0]BRAM_PORTA_0_dout;
output BRAM_PORTA_0_en;
output BRAM_PORTA_0_rst;
output [3:0]BRAM_PORTA_0_we;
// input CLK_IN1_D_0_clk_n;
// input CLK_IN1_D_0_clk_p;
output clk_out_25;
output clk_out_50;
// input reset_0;
wire [15:0]BRAM_PORTA_0_addr;
wire BRAM_PORTA_0_clk;
wire [31:0]BRAM_PORTA_0_din;
wire [31:0]BRAM_PORTA_0_dout;
wire BRAM_PORTA_0_en;
wire BRAM_PORTA_0_rst;
wire [3:0]BRAM_PORTA_0_we;
(* keep = "true" *)wire CLK_IN1_D_0_clk_n;
(* keep = "true" *)wire CLK_IN1_D_0_clk_p;
wire clk_out_25;
wire clk_out_50;
(* keep = "true" *)wire reset_0;
design_1 design_1_i
(.BRAM_PORTA_0_addr(BRAM_PORTA_0_addr),
.BRAM_PORTA_0_clk(BRAM_PORTA_0_clk),
.BRAM_PORTA_0_din(BRAM_PORTA_0_din),
.BRAM_PORTA_0_dout(BRAM_PORTA_0_dout),
.BRAM_PORTA_0_en(BRAM_PORTA_0_en),
.BRAM_PORTA_0_rst(BRAM_PORTA_0_rst),
.BRAM_PORTA_0_we(BRAM_PORTA_0_we),
.CLK_IN1_D_0_clk_n(CLK_IN1_D_0_clk_n),
.CLK_IN1_D_0_clk_p(CLK_IN1_D_0_clk_p),
.clk_out_25(clk_out_25),
.clk_out_50(clk_out_50),
.reset_0(reset_0));
endmodule
3, 约束文件
set_property IOSTANDARD DIFF_SSTL12 [get_nets sys_clk_p]
set_property IOSTANDARD DIFF_SSTL12 [get_nets sys_clk_n]
set_property PACKAGE_PIN G31 [get_nets sys_clk_p]
set_property PACKAGE_PIN F31 [get_nets sys_clk_n]
set_property IOSTANDARD LVCMOS12 [get_nets rst]
set_property PACKAGE_PIN L19 [get_nets rst]
#------------------------------------------------------------
set_property IOSTANDARD LVCMOS18 [get_ports start]
set_property PACKAGE_PIN BE23 [get_ports start]
set_property IOSTANDARD LVCMOS12 [get_ports q]
set_property PACKAGE_PIN AT32 [get_ports q]