在我设计的PCPU中需要的输出项中有PC,d_addr,d_we,d_dataout,由于PC时刻变化着不适合做门控,所以我对另外三个输出项d_addr,d_we,d_dataout做了门控处理。
门控操作前示意图:
门控操作后示意图:
当指令不为LOAD或STORE时,传入模块DATA_MEMORY的三个数据d_addr,d_we,d_dataout为无效数据,若此时,仍然对它们进行赋值,会产生寄存器的刷新过程,在此过程中会产生大量的无用功耗,此时可以根据传入的指令设置门控,然后通过门控操作的方式,来控制寄存器的刷新过程,使数据无效的寄存器不执行刷新过程,从而降低功耗。
综上所述,可以通过门控的方式减少寄存器的刷新,从而降低功耗。
代码如下:
`define NOP 5'b00000
`define HALT 5'b00001
`define LOAD 5'b00010
`define STORE 5'b00011
`define LDIH 5'b10000
`define ADD 5'b01000
`define ADDI 5'b01001
`define ADDC 5'b10001
`define SUB 5'b01010
`define SUBI 5'b01011
`define SUBC 5'b10010
`define CMP 5'b01100
//Logical / shift
`define AND 5'b01101
`define OR 5'b01110
`define XOR 5'b01111
`define SLL 5'b00100
`define SRL 5'b00111
`define SLA 5'b00101
`define SRA 5'b00110
//Control
`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
//Statement
`define idle 1'b0
`define exec 1'b1
/**********************************************************/
module PCPU(
input wire clk, mclk, reset, enable, start,
input wire [15:0] i_datain, d_datain,
output reg d_we,
output reg [7:0] d_addr, pc,
output reg [15:0] d_dataout
);
/**********************************************************/
/**********************************************************/
reg state;
reg [15:0] gr[7:0];
reg [15:0] id_ir, wb_ir, mem_ir;
reg [15:0] reg_A, reg_B, smdr=16'b0, ex_ir;
reg [15:0] reg_C, reg_C1;
reg [15:0] smdr1, ALU0;
reg dw, zf, nf, cf, in;
/**********************************************************/
/*********************** CLOCK GATE ***********************/
reg [4:0] t_signal;
always @ (posedge mclk or posedge reset)
begin
if(reset)
begin
t_signal <= 5'b0;
end
else
begin
t_signal <= id_ir[15:11];
end
end
wire gate_ex_signal;
assign gate_ex_signal = (t_signal == `LOAD || t_signal == `STORE);
reg gate_mem_signal;
/************************* FINISH *************************/
/**********************************************************/
//CPU_Control
reg next_state = 1'b0;
always @ (posedge mclk or posedge reset)
begin
if(reset)
state <= `idle;
else
state <= next_state;
end
always @ (*)
begin
case(state)
`idle: begin
if((enable==1'b1)&&(start==1'b1)) next_state <= `exec;
else next_state <= `idle;
end
`exec: begin
if((enable==1'b0)||(wb_ir[15:11]==`HALT)) next_state <= `idle;
else next_state <= `exec;
end
default: next_state <= `idle;
endcase
end
/*******************************************************************************/
/*******************************************************************************/
//CPU_IF
always @ (posedge mclk or posedge reset)
begin
if(reset)
begin
id_ir <= 16'b0;
pc <= 8'b0;
end
else if(state == `exec)
be