input CLK, Rstn;
output [31:0]InstAddr, DAddr;
input [15:0]Inst;
outputDW;
output [31:0]WData;
input [31:0]RData;
// IA stage
reg[31:0]PC_reg;//PC register
wire[31:0]PC_add2, PC_addoffset, PC;//new data for PC
wire[1:0]PC_Sel;//select signal for PC
regPC_W;//write signal for PC register
// DC stage
reg[15:0]IFDC_reg;//pipeline register for IFDC
regIFDC_W;//write signal for IFDC register
wireIFDC_Flush;//clear signal for IFDC register
reg[31:0]RegFile[31:0];//register file
wire[31:0]Reg0, Reg1;//operand 0 and 1
reg[3:0]DC_ALU_OP;//ALU operation code from decoder
regDC_WB, DC_DW, DC_LD;//writeback,store,load sigal from decoder
reg[3:0]DC_BJ;//branch condition from decoder
// EX stage
regDCEX_Flush;//clear signal for DCEX register
reg [3:0]DCEX_ALU_OP;//ALU operation code in DCEX register
regDCEX_DW, DCEX_LD, DCEX_WB;//store,load,writeback signal in DCEX register
reg [31:0]DCEX_Reg0, DCEX_Reg1;//operand 0, 1 in DCEX register
reg [4:0]DCEX_imm, DCEX_RegAddr0, DCEX_RegAddr1; //immediate data, register address 0 and 1 in DCEX register
wire signed [ 32:0]ALU_OP0, ALU_OP1;//operand 0 , 1 for ALU
reg signed [32:0]ALU_Result;// result from ALU
regALU_Z, ALU_N;// flag Z, N from ALU
regALU_Z_reg, ALU_N_reg;// flag registers for Z and N
wire [31:0]EX_WData;// witeback data in EX stage
// WB stage
regEXWB_WB;// writeback signal in EXWB register
reg[4:0]EXWB_WAddr;// writeback address in EXWB register
reg[31:0]EXWB_WData;// writeback data in EXWB register
wire[31:0]EX_STData, EX_OP0, EX_OP1;// store data, operand 0 and 1 in EX stage
wire[1:0]EX_BP_Sel_MA_Addr, EX_BP_Sel_MA_Data, EX_BP_Sel_OP0,EX_BP_Sel_OP1;// bypass select siganls
// XX stage
regWBXX_WB;// writeback signal in WBXX register
reg[4:0]WBXX_WAddr;// writeback address in WBXX register
reg[31:0]WBXX_WData;// writeback data in WBXX regsiter
//
// IA stage
//
assign PC_add2 = PC_reg + 2'b10;
assign PC_addoffset = PC_reg + {{21{IFDC_reg[9]}},IFDC_reg[9:0],1'b0}; //two different way ?
assign PC = (PC_Sel == 2'b00)? PC_add2 : (PC_Sel == 2'b01) ? PC_addoffset : {21'h000000,IFDC_reg[9:0],1'b0};// normal case; branch; jump
//
// IF stage
//
// PC register
always@(posedge CLK or negedge Rstn)
begin
if (!Rstn)
PC_reg <= 32'h00000000;
else if (PC_W)
PC_reg <= PC;
end
// instruction address for InstRAM
assign InstAddr = PC_reg;
//
// DC stage
//
// IFDC
register
always@(posedge CLK or negedge Rstn)
begin
if (!Rstn)
IFDC_reg <= 16'h0000;
else if (IFDC_Flush)
IFDC_reg <= 16'h0000;
else if (IFDC_W)
IFDC_reg <= Inst;
end
// RegFile
always@(posedge CLK)
begin
if (EXWB_WB) //write signle enable
RegFile[EXWB_WAddr] <= EXWB_WData;
end
// operand 0 and 1 from register file
assign Reg0 = RegFile[IFDC_reg[9:5]];
assign Reg1 = RegFile[IFDC_reg[4:0]];
// decoder
// DC_ALU_OP: operation code of ALU
//0000(ADD), 0001(SUB,CMP),0010(AND),0011(OR),0100(XOR),0101(LSL),0110(LSR),0111(ASR),1000(MOV),1111(others)
// DC_WB: writeback siganl
// DC_DW: ST signal
// DC_LD: LD signal
// DC_BJ: Branch or Jump conditions
//0001(BNZ),0010(BZ),0011(BLE),0100(BLT),0101(BGE),0110(BGT),0111(B),1000(JUMP),0000(others
// PC_W: write enable sigal for PC_reg
// IFDC_W: write enable signal for IFDC pipeline register
// DCEX_Flush: clear sigal for DCEX pipeline register
always@(IFDC_reg[15:10])
begin
case(IFDC_reg[15:10])
6'b010000: begin
DC_ALU_OP= 4'b0000;//ADD
DC_WB = 1'b1;
DC_DW = 1'b0;
DC_LD = 1'b0;
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
//**********************************************************************
//Please finish the RTL code here!
//**********************************************************************
//==================pc_W IFdc_w ecex_flush?
6'b010001: begin
DC_ALU_OP= 4'b0001;//SUB
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b010010: begin
DC_ALU_OP= 4'b0001;//CMP
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b010100: begin
DC_ALU_OP= 4'b0010;//AND
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b010101: begin
DC_ALU_OP= 4'b0011;//0R
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b010110: begin
DC_ALU_OP= 4'b0100;//XOR
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
en
d
6'b100000: begin
DC_ALU_OP= 4'b0101;//LSL
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b100001: begin
DC_ALU_OP= 4'b0110;//LSR
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b100010: begin
DC_ALU_OP= 4'b0111;//ASR
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b100111: begin
DC_ALU_OP= 4'b1000;//MOV
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b011000: begin
DC_ALU_OP= 4'b1111;//LD
DC_WB = 1'b1; //result save
DC_DW = 1'b0; //no store
DC_LD = 1'b1; //load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b011001: begin
DC_ALU_OP= 4'b1111;//ST
DC_WB = 1'b0; //result no save
DC_DW = 1'b1; //store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0;
end
6'b110000: begin
DC_ALU_OP= 4'b1111;//BZ
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0010;//BZ
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b110001: begin
DC_ALU_OP= 4'b1111;//BNZ
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0001;//BNZ
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b110010: begin
DC_ALU_OP= 4'b1111;//BLE
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0011;//BLE
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b110011: begin
DC_ALU_OP= 4'b1111;//BLT
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0100;//BLT
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b110100: begin
DC_ALU_OP= 4'b1111;//BGE
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0101;//BGE
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b110101: begin
DC_ALU_OP= 4'b1111;//BGT
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0110;//BGT
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b110110: begin
DC_ALU_OP= 4'b1111;//B
DC_WB = 1'b0; //result no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0111;// B
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b111000: begin
DC_ALU_OP= 4'b1111;//JUMP
DC_WB = 1'b0; //no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b1000;// JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b1;
end
6'b000000: begin
DC_ALU_OP= 4'b1111;//NOP
DC_WB = 1'b0; //no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b1;
IFDC_W = 1'b1;
DCEX_Flush = 1'b0; //do no thing
end
6'b000001: begin
DC_ALU_OP= 4'b1111;//WAIT
DC_WB = 1'b0; //no save
DC_DW = 1'b0; //no store
DC_LD = 1'b0; //no load
DC_BJ = 4'b0000;// no Branch, no JUMP
PC_W = 1'b0;
IFDC_W = 1'b0;
DCEX_Flush = 1'b1; //
end
endcase
end
// Branch
// PC select signal decided by branch condition(DC_BJ) and flag registers
//01: Branch
//10: JUMP
//00: no branch and no JUMP;
//**********************************************************************
//Please finish the RTL code here!
//**********************************************************************
assign PC_Sel = (DC_BJ == 4'b0000)?2'b00: //0
(DC_BJ == 4'b0010&&ALU_Z==1)?2'b01: //bz
(DC_BJ == 4'b0001&&ALU_Z==0)?2'b01: //bnz
(DC_BJ == 4'b0011&&(ALU_Z==1||ALU_N==1))?2'b01: //ble
(DC_BJ == 4'b0100&&(ALU_Z==0&&ALU_N==1))?2'b01: //blt
(DC_BJ == 4'b0101&&(ALU_Z==1||ALU_N==0))?2'b01: //bge
(DC_BJ == 4'b0110&&(ALU_Z==0&&ALU_N==0))?2'b01: //bgt
(DC_BJ == 4'b0111)?2'b01: //b
(DC_BJ == 4'b1000)?2'b10:2'b00; //jump
// clear signal for IFDC register
assign IFDC_Flush = (PC_Sel != 2'b00 && DC_BJ != 4'b0000) ? 1'b1 : 1'b0;
//
// EX stage
//
// DCEX registers
always@(posedge CLK or negedge Rstn)
begin
if (!Rstn) begin
DCEX_ALU_OP <= 4'b0000;
DCEX_DW<= 1'b0;
DCEX_LD<= 1'b0;
DCEX_WB<= 1'b0;
DCEX_Reg0 <= 32'h00000000;
DCEX_Reg1<= 32'h00000000;
DCEX_imm<= 5'h00;
DCEX_RegAddr0 <= 5'h00;
DCEX_RegAddr1 <=
5'h00;
end
else if (DCEX_Flush) begin
DCEX_ALU_OP <= 4'b0000;
DCEX_DW<= 1'b0;
DCEX_LD<= 1'b0;
DCEX_WB<= 1'b0;
DCEX_Reg0 <= 32'h00000000;
DCEX_Reg1<= 32'h00000000;
DCEX_imm<= 5'h00;
DCEX_RegAddr0 <= 5'h00;
DCEX_RegAddr1 <= 5'h00;
end
else begin
DCEX_ALU_OP <= DC_ALU_OP;
DCEX_DW<= DC_DW;
DCEX_LD<= DC_LD;
DCEX_WB<= DC_WB;
DCEX_Reg0 <= Reg0;
DCEX_Reg1<= Reg1;
DCEX_imm<= IFDC_reg[4:0];
DCEX_RegAddr0 <= IFDC_reg[9:5];
DCEX_RegAddr1 <= IFDC_reg[4:0];
end
end
// bypass controller
// 01: bypass from EXWB pipeline register
// 10:bypass from WBXX pipeline register
// 00: no bypass
//**********************************************************************
//Please finish the following RTL code!
//**********************************************************************//judge adress
// bypass select signal for address to DataRAM
assign EX_BP_Sel_MA_Addr = ((DCEX_RegAddr1==EXWB_WAddr)&&EXWB_WB)?2'b01:
((DCEX_RegAddr1==WBXX_WAddr)&&WBXX_WB)?2'b10:2'b00;
// bypass select signal for data to DataRAM
assign EX_BP_Sel_MA_Data = ((DCEX_RegAddr0==EXWB_WAddr)&&EXWB_WB)?2'b01:
((DCEX_RegAddr0==WBXX_WAddr)&&WBXX_WB)?2'b10:2'b00;
// bypass select signal for operand 0 to ALU
assign EX_BP_Sel_OP0 = ((DCEX_RegAddr0==EXWB_WAddr)&&EXWB_WB)?2'b01:
((DCEX_RegAddr0==WBXX_WAddr)&&WBXX_WB)?2'b10:2'b00;
// bypass select signal for operand 1 to ALU
assign EX_BP_Sel_OP1 = ((DCEX_RegAddr1==EXWB_WAddr)&&EXWB_WB)?2'b01:
((DCEX_RegAddr1==WBXX_WAddr)&&WBXX_WB)?2'b10:2'b00;
// DataRAM interface
assign DW = DCEX_DW;
assign DAddr = (EX_BP_Sel_MA_Addr == 2'b00) ? DCEX_Reg1 :
(EX_BP_Sel_MA_Addr == 2'b01) ? EXWB_WData :
WBXX_WData;
assign WData = (EX_BP_Sel_MA_Data == 2'b00) ? DCEX_Reg0 :
(EX_BP_Sel_MA_Data == 2'b01) ? EXWB_WData :
WBXX_WData;
// ALU
// operands
assign ALU_OP0 = (EX_BP_Sel_OP0 == 2'b00) ? {DCEX_Reg0[31], DCEX_Reg0} :
(EX_BP_Sel_OP0 == 2'b01) ? {EXWB_WData[31], EXWB_WData}:
{WBXX_WData[31], WBXX_WData};
assign ALU_OP1 = (EX_BP_Sel_OP1 == 2'b00) ? {DCEX_Reg1[31], DCEX_Reg1} :
(EX_BP_Sel_OP1 == 2'b01) ? {EXWB_WData[31], EXWB_WData}:
{WBXX_WData[31], WBXX_WData};
// ALU operations
always@(*)
begin
case(DCEX_ALU_OP)
4'b0000: begin//ADD
ALU_Result = ALU_OP0 + ALU_OP1;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
//**********************************************************************
//Please finish the following RTL code!
//**********************************************************************
4'b0001
: begin//SUB
ALU_Result = ALU_OP0 - ALU_OP1;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b0010: begin//AND
ALU_Result = ALU_OP0&ALU_OP1;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b0011: begin//OR
ALU_Result = ALU_OP0|ALU_OP1;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b0100: begin//XOR
ALU_Result = ALU_OP0 ^ ALU_OP1;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b0101: begin//LSL
ALU_Result = ALU_OP0 << DCEX_imm;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b0110: begin//LSR
ALU_Result = ALU_OP0 >> DCEX_imm;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b0111: begin//ASR
ALU_Result = ALU_OP0 >>> DCEX_imm;
if (ALU_Result == 0)
ALU_Z = 1'b1;
else
ALU_Z = 1'b0;
if (ALU_Result[32:31] == 2'b11)
ALU_N = 1'b1;
else
ALU_N = 1'b0;
end
4'b1000: begin//moV
ALU_Result = DCEX_imm;
ALU_Z<= ALU_Z_reg;
ALU_N <= ALU_N_reg ;
end
4'b1111: begin//other
ALU_Z<= ALU_Z_reg;
ALU_N <= ALU_N_reg ;
end
endcase
end
// flag registers
always@(posedge CLK or negedge Rstn)
begin
if (!Rstn) begin
ALU_Z_reg <= 1'b0;
ALU_N_reg <= 1'b0;
end
else begin
ALU_Z_reg <= ALU_Z;
ALU_N_reg <= ALU_N;
end
end
// writeback data in EX stage
assign EX_WData = (DCEX_LD) ? RData : ALU_Result[31:0];
//
// EXWB
//
// EXWB registers
always@(posedge CLK or negedge Rstn)
begin
if (!Rstn) begin
EXWB_WB <= 1'b0;
EXWB_WAddr <= 5'h00;
EXWB_WData <= 32'h00000000;
end
else begin
EXWB_WB <= DCEX_WB;
EXWB_WAddr <= DCEX_RegAddr0;
EXWB_WData <= EX_WData;
end
end
//
// WBXX
//
// WBXX registers
always@(posedge CLK or negedge Rstn)
begin
if (!Rstn) begin
WBXX_WB <= 1'b0;
WBXX_WAddr <= 5'h00;
WBXX_WData <= 32'h00000000;
end
else begin
WBXX_WB <= EXWB_WB;
WBXX_WAddr <= EXWB_WAddr;
WBXX_WData <= EXWB_WData;
end
end
endmodule下载本文