原则:通过有效信号对总线锁存降低总线反转。
例如:总线数据信号需要打2拍使用,”相对暴力“方法如下代码14~17行:
module bus_power #(
parameter DATA_WIDTH = 8
)(
input clk ,
input rst_n ,
input vld_in ,
input [DATA_WIDTH-1:0] data_in ,
output reg [DATA_WIDTH-1:0] data_out
);
reg [DATA_WIDTH-1:0] data_in_ff1;
reg [DATA_WIDTH-1:0] data_in_ff2;
always @ (posedge clk) begin
data_in_ff1 <= data_in;
data_in_ff2 <= data_in_ff1;
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_out <= {DATA_WIDTH{1'b0}};
end
else begin
data_out <= data_in_ff2;
end
end
endmodule
这样使用的总线数据data_in_ff2随着时钟翻转而改变,动态功耗就大。大可不必这样,因为使用的数据总线必须在vld_in有效才能使用,可以通过有效信号vld_in控制。
代码优化如下:
module bus_power #(
parameter DATA_WIDTH = 8
)(
input clk ,
input rst_n ,
input vld_in ,
input [DATA_WIDTH-1:0] data_in ,
output reg [DATA_WIDTH-1:0] data_out
);
reg vld_in_ff1;
reg vld_in_ff2;
reg [DATA_WIDTH-1:0] data_in_ff1;
reg [DATA_WIDTH-1:0] data_in_ff2;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
vld_in_ff1 <= 1'b0;
vld_in_ff2 <= 1'b0;
end
else begin
vld_in_ff1 <= vld_in;
vld_in_ff2 <= vld_in_ff1;
end
end
always @ (posedge clk) begin
if (vld_in) begin
data_in_ff1 <= data_in;
end
if (vld_in_ff1) begin
data_in_ff2 <= data_in_ff1;
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_out <= {DATA_WIDTH{1'b0}};
end
else begin
data_out <= data_in_ff2;
end
end
endmodule
代码16~35行,新增vld_in_ff1/vld_in_ff2两个信号量。只有在二者信号有效时锁存,不必随时钟时刻翻转,这样功耗就小。
使用Vivado对以上两段代码综合,查看二者功耗。
优化前:
优化前功耗
优化后:
优化后功耗
优化前的动态功耗:2.068W,优化后的动态功耗:2.052W。符合预期,虽然降低不多,但是随着数据位宽增大,降低百分比必然会更明显。
若有不正确的地方,欢迎大家指正。