数字电路设计之低功耗设计方法六:旁路(by-passing)

        By_passing:这是在CPU架构上进行的低功耗。这个其实我觉得和clock_gating有着异曲同工之妙,它们都是在做尽可能不要刷新寄存器的值,跳过这一个环节。所以,by_passing是当进行不是load和store的时候,跳过寄存器赋值的环节。

        最初的检测是否by_passing的时候我使用的是组合逻辑,可是我发现这样会导致功耗降得不明显,我觉得应该用时序逻辑更加美好。因为组合逻辑毕竟是实时检测的。

        所以做了如下的修改:但是使用时序逻辑就必须注意时序。我们应该在上一个时钟周期检测是否by_passing,那么就可以在下一个时钟周期来临的时候使用这个by_passing的值,否则如果在同一个时钟周期内使用既要计算by_passing的值又要判断那些寄存器的值那么时序就不正确。所以可以看到我的by_passing是使用了提前一个周期检测。 

     用ISE进行仿真测试,发现频率居然加快了,真是一件好事啊!既降低了功耗,又提高了频率。这就是工程师一直梦寐以求的。只是增大了不少面积。这个方法的精髓我觉得还是clock-gating的思想,就是尽可能地减少寄存器的跳转。不过我后来发现实际上CPU是一种比较特殊的电路,如果在里面使用组合逻辑的话,那么就会导致功耗较大。因为CPU里的寄存器本来就是一个始终周期改变一次,所以尽可能使用时序逻辑是比较合理的。如果使用过多的组合逻辑的话,会导致功耗较大。但是我们在写时序逻辑的时候一定要注意时序,这个是使用时序逻辑的一个难点。


带有by-passing的CPU,相当于是一个三级流水线了,但是还是五级流水线的架构,也就是吞吐量增大了。

`timescale 1ns / 1ps
// state macro define
`define idle 1'b0
`define exec 1'b1
// instruction macro define
`define NOP 5'b00000
`define HALT 5'b00001
`define LOAD 5'b00010
`define STORE 5'b00011
`define SLL 5'b00100
`define SLA 5'b00101
`define SRL 5'b00110
`define SRA 5'b00111
`define ADD 5'b01000
`define ADDI         5'b01001
`define SUB 5'b01010
`define SUBI         5'b01011
`define CMP 5'b01100
`define AND 5'b01101
`define OR 5'b01110
`define XOR 5'b01111
`define LDIH         5'b10000
`define ADDC         5'b10001
`define SUBC         5'b10010
`define JUMP         5'b11000
`define JMPR         5'b11001
`define BZ 5'b11010
`define BNZ 5'b11011
`define BN 5'b11100
`define BNN 5'b11101
`define BC 5'b11110
`define BNC 5'b11111
// general register
`define gr0 3'b000
`define gr1 3'b001
`define gr2 3'b010
`define gr3 3'b011
`define gr4 3'b100
`define gr5 3'b101
`define gr6 3'b110
`define gr7 3'b111
 
module CPU(input wire  reset,
           input wire  enable,
   input wire  start,
   input wire  clock,
           input wire  [15:0]i_datain,
           input wire  [15:0]d_datain,
           output reg  d_we,
           output wire [7:0]i_addr,
   output reg  [7:0]d_addr,
   output reg  [15:0]d_dataout
);
 
reg [15:0]gr[7:0];
reg state,next_state;

assign i_addr      =    pc;
//assign d_we      =    dw;
//assign d_addr    =    reg_C[7:0];
//assign d_dataout =    smdr1;      
//here has some change for pre

//************* CPU control *************//
always @(posedge clock)
begin
if (!reset)
state <= `idle;
else
state <= next_state;
end

always@(*)
begin
case (state)
`idle : 
if ((enable == 1'b1) 
&& (start == 1'b1))
next_state <= `exec;
else
next_state <= `idle;
`exec :
if ((enable == 1'b0) || (wb_ir[15:11] == `HALT))
next_state <= `idle;
else
next_state <= `exec;
endcase
end


reg [15:0]id_ir;
reg [7:0]pc;
//************* IF *************//
always@(posedge clock or negedge reset)
begin
if (!reset)
begin
id_ir <= 16'b0000_0000_0000_0000;
pc <= 8'b0000_0000;
end

else if (state ==`exec)
begin

if(((ex_ir[15:11] == `BZ) && (zf == 1'b1)) || ((ex_ir[15:11] == `BN) && (nf == 1'b1))||
((ex_ir[15:11] == `BNZ) && (zf == 1'b0)) || ((ex_ir[15:11] == `BNN) && (nf == 1'b0))||
((ex_ir[15:11] == `BC) && (cf == 1'b1)) || ((ex_ir[15:11] == `BNC) && (cf == 1'b0))|| 
 ex_ir[15:11] == `JMPR)
begin
pc <= ALUo[7:0];//pc <= reg_C[7:0];
id_ir <= i_datain;
end
else if(id_ir[15:11] == `JUMP)//如果判断出指令是JUMP,直接跳转,就可以减少功耗,不必冒险
begin
pc <= id_ir[7:0];
id_ir <= i_datain;
end
           //-------------对于LOAD的处理
else if((id_ir[15:11] == `LOAD)&&(i_datain[15:11]!=`JUMP)&&(i_datain[15:11]!=`NOP)&&(i_datain[15:11]!=`HALT)&&(i_datain[15:11]!=`LOAD))
begin
if((id_ir[10:8]==i_datain[2:0])&&((i_datain[15:11]==`ADD)||(i_datain[15:11]==`ADDC)||(i_datain[15:11]==`SUB)||(i_datai

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值