低功耗技术——流水线设计(加法器和乘法器)

时间:2022-04-19 01:20:01


前言

2023.3.31 今天学习降低功耗的一些方法


低功耗技术——流水线设计(加法器和乘法器)

一、流水线

电路最高工作频率:取决于最长的组合逻辑电路的延时值

数据传播时,在某一个时刻,该路径下许多电路逻辑单元都没有工作,电路效率很低。

流水线:将组合逻辑系统地分割,并在各个部分(分级)之间插入寄存器,并暂存中间数据的方法。

低功耗技术——流水线设计(加法器和乘法器)

举例:两级组合逻辑,非流水线操作,一个周期就能输出结果;
流水线设计的话,插入两级寄存器,输出第一个数据需要两个周期,接下来每个周期输出一个数据。

优点:每一小部分并行处理,提高了数据吞吐率;同时小部分的延时较小,提高电路时钟频率。

缺点:插入寄存器,实际上是用面积换速度的方法,会导致芯片面积增加,布线困难,时钟偏差增加,功耗也会增加。

应用场景

  • 组合逻辑较长
  • 功能模块之间的流水线,用乒乓来交换数据

1、16bit加法器

非流水线设计:
低功耗技术——流水线设计(加法器和乘法器)

module adder(
	input [15:0] a,
	input [15:0] b,
	input clk,
	input cin,
	output cout,
	output [15:0] sum
);
	assign {cout,sum} = a + b + cin;
endmodule

流水线设计:
低功耗技术——流水线设计(加法器和乘法器)
有个疑问,第二级寄存器是不是也可以不需要,但是加法计算需要时间?

module adder(
	input [15:0] a,
	input [15:0] b,
	input clk,
	input cin,
	output cout,
	output reg [15:0] sum
);
	reg [7:0] a_r;
	reg [7:0] b_r;
	reg cout_r;
	reg [7:0] sum_r;
	
	//第一级寄存器,除了寄存低8bit的计算结果,还要寄存没有用到的高8bit,所有数据经过寄存器要相同,这样数据才会同时达到第二级寄存器
	always@(posedge clk)begin
		a_r <= a[158];
		b_r <= b[158];
		{cout_r, sum_r} <= a[7:0] + b[7:0] + cin;
	end
	
	//第二级寄存器
	always@(posedge clk)begin
		{cout, sum[158]} <= a_r + b_r + cout_r;
		sum[7:0] <= sum_r;
	end
endmodule

2、无符号4bit乘法器

乘法器:并行(*)、移位相加、查找表、加法树、并行乘法器

下面是流水线乘法器的电路图
低功耗技术——流水线设计(加法器和乘法器)

module multi_pipe#(
	parameter size = 4
)(
	input 						clk 		,   
	input 						rst_n		,
	input	[size-1:0]			mul_a		,
	input	[size-1:0]			mul_b		,
 
 	output	reg	[size*2-1:0]	mul_out		
);

	parameter N = size * 2;
    //defination
    wire [N - 1 : 0] temp [3:0];
     
    reg [N - 1 : 0] adder_0;
    reg [N - 1 : 0] adder_1;
     
    //output
    genvar i;
    generate
        for(i = 0; i < 4; i = i + 1)begin : loop
            assign temp[i] = mul_b[i] ? mul_a << i : 'd0;
        end
    endgenerate
     
     //这一部分为了更清楚,也可以分开写成两个,因为这里用到了两级寄存器
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) begin
        	adder_0 <= 'd0;
        	adder_1 <= 'd0;
        	mul_out <= 'd0;
        end
        else begin
	        adder_0 <= temp[0] + temp[1];
	        adder_1 <= temp[2] + temp[3];
	        mul_out <= adder_0 + adder_1;
        end
    end
endmodule

3、编写一个4bit乘法器模块,并例化该乘法器求解c=12a+5b

//4bit乘法器模块
module mul(
    input [3:0] a,
    input [3:0] b,
    output [7:0] c
);
    wire [7:0] tmp [3:0];
    genvar i;
    generate for (i=0; i<4; i=i+1) begin
        assign tmp[i] = a[i] ? b << i : 'd0;
    end
    endgenerate
    
    assign c = tmp[0] + tmp[1] + tmp[2] + tmp[3];
    
endmodule

module calculation(
	input clk,
	input rst_n,
	input [3:0] a,
	input [3:0] b,
	output [8:0] c
	);
    
    wire [7:0] tmp0;
    wire [7:0] tmp1;
    reg  [8:0] c_r;
    
    mul mul_0 (a, 12, tmp0);
    mul mul_1 (b, 5 , tmp1);
    
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            c_r <= 'd0;
        end
        else begin
            c_r <= tmp0 + tmp1;
        end
    end
    assign c = c_r;
endmodule

二、降低FPGA功耗

1、静态功耗

使用低功耗的工艺来设计芯片,减小漏电流;也可以降低温度来降低静态功耗。

2、动态功耗

  • 选择适当的IO标准,IO端电压高,功耗大
  • 信号使能,用片选或者时钟使能来控制寄存器
  • 禁止非活动状态的时钟树翻转,之前时钟使能是使得时钟不总是翻转,但是时钟树总是在翻转的,这样还是会有功耗,因此要把非活跃区域的时钟树禁止翻转来减少功耗
  • 减少状态机的转换量,使用1位有效编码或格雷码
  • 选择合适的低功耗器件