文章目录
- 前言
- 一、流水线
- 1、16bit加法器
- 2、无符号4bit乘法器
- 3、编写一个4bit乘法器模块,并例化该乘法器求解c=12*a+5*b
- 二、降低FPGA功耗
- 1、静态功耗
- 2、动态功耗
前言
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[15:8];
b_r <= b[15:8];
{cout_r, sum_r} <= a[7:0] + b[7:0] + cin;
end
//第二级寄存器
always@(posedge clk)begin
{cout, sum[15:8]} <= 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位有效编码或格雷码
- 选择合适的低功耗器件