• 【数字IC设计】DC自动添加门控时钟


    简介

    数字电路的动态功耗主要是由于寄存器翻转带来的,为了降低芯片内部功耗,门控时钟的方案应运而生。作为低功耗设计的一种方法,门控时钟是指在数据无效时将寄存器的时钟关闭,以此来降低动态功耗

    在下图中,展示了加入门控时钟前后电路的变化。由图可知,采取门控时钟技术后,原先的MUX单元消失了(MUX数目和寄存器bit数目有关),但会增加1个额外的门控时钟单元。因此,插入门控时钟并不总是能带来面积上的收益,需要综合数据位宽来考虑。总结一下,就是:

    • 插入门控时钟单元后,电路中的MUX就不需要了,如果数据D是多bit的(一般都是如此),插入CG后的面积可能反而会减少;
    • 如果D是单bit信号,节省的功耗就比较少,但是如果D是一个32bit的信号,那么插入CG后节省的功耗就比较多了。

    这里的决定因素就是D的位宽,若D的位宽很小,那么可能插入的CG面积比原来的MUX大很多,而且节省的功耗又很少,得不偿失。只有当D的位宽超过了一定的bit数后,插入CG的收益才会比较大。
    关于这个临界值,不同的工艺可能不同,DC工具给的默认值是3。即,如果D的位宽超过了3bit,那么DC就会默认插入CG。
    我们可以通过DC命令:

    set_clock_gating_style -minimum_bitwidth 4
    
    • 1

    来控制芯片中,对不同位宽的寄存器是否自动插入CG。然而,一般情况我们都不会去修改它。
    在这里插入图片描述

    关于门控时钟的详细介绍,在文章中已经给出,这里不再赘述。

    DC添加门控时钟

    在实际的ASIC设计过程中,门控时钟不需要开发者自己写代码实现,完全可以通过对综合工具进行相应配置,让工具完成对电路添加合适的门控时钟。
    下面是一个简单的关于门控时钟的实验:

    RTL代码

    数据宽度为3bit时:

    module cg_top_w3 
    (
        input  logic         clk,   
        input  logic         rst_n,   
        input  logic         vld_in,   
        input  logic [3-1:0] data_in,   
    
        output logic         vld_out,   
        output logic [3-1:0] data1_out,
        output logic [3-1:0] data2_out
    );
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            vld_out <= 1'b0;   
        end
        else begin
            vld_out <= vld_in;   
        end
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            data1_out <= 'b0;   
        end
        else if(vld_in) begin
            data1_out <= data_in;   
        end
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            data2_out <= 'b0;
        end
        else if(vld_in) begin
            data2_out <= data_in;
        end
        else begin
            data2_out <= '0;
        end
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    数据宽度为8bit时:

    module cg_top_w8 
    (
        input  logic            clk,   
        input  logic            rst_n,   
        input  logic            vld_in,   
        input  logic [8-1:0]    data_in,   
    
        output logic            vld_out,   
        output logic [8-1:0]    data1_out,   
        output logic [8-1:0]    data2_out                                   
    );
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            vld_out <= 1'b0;   
        end
        else begin
            vld_out <= vld_in;   
        end
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            data1_out <= 'b0;   
        end
        else if(vld_in) begin
            data1_out <= data_in;   
        end
    end
        
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            data2_out <= 'b0;
        end
        else if(vld_in) begin
            data2_out <= data_in;
        end
        else begin
            data2_out <= '0;
        end
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    两者对应的tcl文件分别为:

    set_app_var search_path ./LM
    set_app_var target_library sc_max.db
    set_app_var link_library sc_max.db
    read_file -format sverilog {./cg_top_w3.sv}
    check_design
    create_clock -period 10 [get_ports clk]
    check_design
    set_clock_gating_style -minimum_bitwidth 4
    compile -gate_clock
    report_clock
    report_timing
    report_area
    write_file -format verilog -output cg_top_w3_netlist.v
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    set_app_var search_path ./LM
    set_app_var target_library sc_max.db
    set_app_var link_library sc_max.db
    read_file -format sverilog {./cg_top_w8.sv}
    check_design
    create_clock -period 1 [get_ports clk]
    check_design
    set_clock_gating_style -minimum_bitwidth 4
    compile -gate_clock
    report_clock
    report_timing
    report_power > cg_top_w8.power.rpt
    report_area > cg_top_w8.area.rpt
    write_file -format verilog -output cg_top_w8_netlist.v
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    其中,set_clock_gating_style -minimum_bitwidth 4用于告诉综合工具数据位宽大于等于多少的时候,开启门控时钟。在进行编译的时候,需要加上-gate_clock选项,即compile -gate_clock

    运行综合

    输入dc进入dc shell后,输入source ./xxx.tcl文件运行,可以得到综合后的网表文件。
    数据位宽为3bit:

    /
    // Created by: Synopsys DC Expert(TM) in wire load mode
    // Version   : L-2016.03-SP1
    // Date      : Sat Oct 14 10:44:29 2023
    /
    
    
    module cg_top_w3 ( clk, rst_n, vld_in, data_in, vld_out, data1_out, data2_out
     );
      input [2:0] data_in;
      output [2:0] data1_out;
      output [2:0] data2_out;
      input clk, rst_n, vld_in;
      output vld_out;
      wire   N4, N5, N6, n1;
    
      dfcrq1 vld_out_reg ( .D(vld_in), .CP(clk), .CDN(rst_n), .Q(vld_out) );
      decrq1 \data1_out_reg[2]  ( .D(data_in[2]), .ENN(n1), .CP(clk), .CDN(rst_n), 
            .Q(data1_out[2]) );
      decrq1 \data1_out_reg[1]  ( .D(data_in[1]), .ENN(n1), .CP(clk), .CDN(rst_n), 
            .Q(data1_out[1]) );
      decrq1 \data1_out_reg[0]  ( .D(data_in[0]), .ENN(n1), .CP(clk), .CDN(rst_n), 
            .Q(data1_out[0]) );
      dfcrq1 \data2_out_reg[2]  ( .D(N6), .CP(clk), .CDN(rst_n), .Q(data2_out[2])
             );
      dfcrq1 \data2_out_reg[1]  ( .D(N5), .CP(clk), .CDN(rst_n), .Q(data2_out[1])
             );
      dfcrq1 \data2_out_reg[0]  ( .D(N4), .CP(clk), .CDN(rst_n), .Q(data2_out[0])
             );
      inv0d1 U3 ( .I(vld_in), .ZN(n1) );
      an02d1 U4 ( .A1(vld_in), .A2(data_in[2]), .Z(N6) );
      an02d1 U5 ( .A1(data_in[1]), .A2(vld_in), .Z(N5) );
      an02d1 U6 ( .A1(data_in[0]), .A2(vld_in), .Z(N4) );
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    可以看到,数据位宽为3bit时,网表中没有门控时钟单元。
    数据位宽为8bit时:

    /
    // Created by: Synopsys DC Expert(TM) in wire load mode
    // Version   : L-2016.03-SP1
    // Date      : Sat Oct 14 10:44:38 2023
    /
    
    
    module cg_top_w8 ( clk, rst_n, vld_in, data_in, vld_out, data1_out, data2_out
     );
      input [7:0] data_in;
      output [7:0] data1_out;
      output [7:0] data2_out;
      input clk, rst_n, vld_in;
      output vld_out;
      wire   N4, N5, N6, N7, N8, N9, N10, N11, net21;
    
      SNPS_CLOCK_GATE_HIGH_cg_top_w8 clk_gate_data1_out_reg ( .CLK(clk), .EN(
            vld_in), .ENCLK(net21) );
      dfcrq1 vld_out_reg ( .D(vld_in), .CP(clk), .CDN(rst_n), .Q(vld_out) );
      dfcrq1 \data1_out_reg[7]  ( .D(data_in[7]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[7]) );
      dfcrq1 \data1_out_reg[6]  ( .D(data_in[6]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[6]) );
      dfcrq1 \data1_out_reg[5]  ( .D(data_in[5]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[5]) );
      dfcrq1 \data1_out_reg[4]  ( .D(data_in[4]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[4]) );
      dfcrq1 \data1_out_reg[3]  ( .D(data_in[3]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[3]) );
      dfcrq1 \data1_out_reg[2]  ( .D(data_in[2]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[2]) );
      dfcrq1 \data1_out_reg[1]  ( .D(data_in[1]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[1]) );
      dfcrq1 \data1_out_reg[0]  ( .D(data_in[0]), .CP(net21), .CDN(rst_n), .Q(
            data1_out[0]) );
      dfcrq1 \data2_out_reg[7]  ( .D(N11), .CP(clk), .CDN(rst_n), .Q(data2_out[7])
             );
      dfcrq1 \data2_out_reg[6]  ( .D(N10), .CP(clk), .CDN(rst_n), .Q(data2_out[6])
             );
      dfcrq1 \data2_out_reg[5]  ( .D(N9), .CP(clk), .CDN(rst_n), .Q(data2_out[5])
             );
      dfcrq1 \data2_out_reg[4]  ( .D(N8), .CP(clk), .CDN(rst_n), .Q(data2_out[4])
             );
      dfcrq1 \data2_out_reg[3]  ( .D(N7), .CP(clk), .CDN(rst_n), .Q(data2_out[3])
             );
      dfcrq1 \data2_out_reg[2]  ( .D(N6), .CP(clk), .CDN(rst_n), .Q(data2_out[2])
             );
      dfcrq1 \data2_out_reg[1]  ( .D(N5), .CP(clk), .CDN(rst_n), .Q(data2_out[1])
             );
      dfcrq1 \data2_out_reg[0]  ( .D(N4), .CP(clk), .CDN(rst_n), .Q(data2_out[0])
             );
      an02d1 U3 ( .A1(vld_in), .A2(data_in[5]), .Z(N9) );
      an02d1 U4 ( .A1(data_in[4]), .A2(vld_in), .Z(N8) );
      an02d1 U5 ( .A1(data_in[3]), .A2(vld_in), .Z(N7) );
      an02d1 U6 ( .A1(data_in[2]), .A2(vld_in), .Z(N6) );
      an02d1 U7 ( .A1(data_in[1]), .A2(vld_in), .Z(N5) );
      an02d1 U8 ( .A1(data_in[0]), .A2(vld_in), .Z(N4) );
      an02d1 U9 ( .A1(data_in[7]), .A2(vld_in), .Z(N11) );
      an02d1 U10 ( .A1(data_in[6]), .A2(vld_in), .Z(N10) );
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    可以看到,数据位宽为8bit时,网表中出现了门控时钟单元,即:

    SNPS_CLOCK_GATE_HIGH_cg_top_w8 clk_gate_data1_out_reg ( .CLK(clk), .EN(vld_in), .ENCLK(net21) );
    
    • 1

    同时,由网表可知,data1_out是被门控了的,而data2_out没有被门控,这是因为data2_out在使能信号无效的时候没有保持自身的值,而是将它赋值为0。

    面积比较

    为了比较插入门控时钟前后电路的面积,我们进行了一个实验,即采用如下tcl脚本对数据位宽为8bit的设计进行了综合:

    set_app_var search_path ./LM
    set_app_var target_library sc_max.db
    set_app_var link_library sc_max.db
    read_file -format sverilog {./cg_top_w8.sv}
    check_design
    create_clock -period 1 [get_ports clk]
    check_design
    compile 
    report_clock
    report_timing
    report_power > cg_top_w8_nocg.power.rpt
    report_area > cg_top_w8_nocg.area.rpt
    write_file -format verilog -output cg_top_w8_nocg_netlist.v
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以看到,该脚本和先前脚本的区别是取消了compile命令的-gate_clock选项。下面是综合报告给出的面积数据:
    开启门控时钟的,总面积为114.9:
    在这里插入图片描述

    关闭门控时钟的,总面积为133.6:
    在这里插入图片描述
    由此可见,在数据位宽为8bit的情况下,对当前设计开启门控时钟可以节约14%的面积。

  • 相关阅读:
    Ajax学习笔记第8天
    Nginx的重写功能——Rewrite
    【手把手带你学JavaSE】全方面带你了解异常
    站长号通知:超过三个月未有任何互动的ID将被清理
    图论第6天
    实战PyQt5: 141-QChart图表之箱形图
    使用 Docker 搭建 Hadoop 分布式环境
    NodeJS @kubernetes/client-node连接到kubernetes集群的方法
    servlet基础知识
    [云原生] 初识Kubernetes
  • 原文地址:https://blog.csdn.net/qq_40268672/article/details/133822038