MCPU
module MCPU( CLK, RST, CurPC, instcode );
input CLK;
input RST;
output [31:0] CurPC;
output [31:0] instcode;
wire [5:0] op;
wire [4:0] rs;
wire [4:0] rt;
wire [4:0] rd;
wire [4:0] sa;
wire [15:0] immediate;
wire [25:0] address;
wire [31:0] NextPC;
wire [31:0] PC4;
wire [31:0] BeqPC;
wire [31:0] JumpPC;
wire ExtSel;
wire PCWre;
wire InsMemRW;
wire IRWre;
wire WrRegDSrc;
wire [1:0] RegDst;
wire RegWre;
wire [2:0] ALUOP;
wire [1:0] PCSrc;
wire ALUSrcA;
wire ALUSrcB;
wire RD;
wire WR;
wire DBDataSrc;
wire [4:0] WriteRegAddr;
wire [31:0] Reg1Out;
wire [31:0] Reg2Out;
wire [31:0] WriteData;
wire [31:0] ALU_Input_A;
wire [31:0] ALU_Input_B;
wire [31:0] ALU_Out;
wire zero;
wire [31:0] MemOut;
wire [31:0] Ext_Imm;
wire [31:0] ADR_Out;
wire [31:0] BDR_Out;
wire [31:0] ALUOutDR_Out;
wire [31:0] DBDR_In;
wire [31:0] DBDR_Out;
PC my_PC( CLK, RST, PCWre, NextPC, CurPC );
ALU_For_Next my_ALU_For_Next( CurPC, PC4 );
ALU_For_Beq my_ALU_For_Beq( PC4, Ext_Imm, BeqPC );
Mux_FourToOne_PC my_Mux_FourToOne_PC( PC4, BeqPC, Reg1Out, JumpPC, PCSrc, NextPC);
InstructionMemory my_InstructionMemory( CurPC, InsMemRW, instcode );
IR my_IR( CLK, instcode, IRWre, op, rs, rt, rd, sa, immediate, address );
Extend_For_Address my_Extend_For_Address( PC4, address, JumpPC );
Mux_ThreeToOne_WriteReg my_Mux_ThreeToOne_WriteReg( rt, rd, RegDst, WriteRegAddr );
Mux_TwoToOne_Data my_MuxTwoToOne_For_WriteData( WrRegDSrc, PC4, DBDR_Out, WriteData );
Sign_Zero_Extend my_Sign_Zero_Extend( immediate, ExtSel, Ext_Imm );
RegisterFile my_RegisterFile( RegWre, CLK, rs, rt, WriteRegAddr, WriteData, Reg1Out, Reg2Out );
DR my_ADR( CLK, Reg1Out, ADR_Out );
DR my_BDR( CLK, Reg2Out, BDR_Out );
Mux_TwoToOne_For_InputA my_Mux_TwoToOne_For_InputA( ALUSrcA, ADR_Out, sa, ALU_Input_A );
Mux_TwoToOne_Data my_Mux_TwoToOne_For_InputB( ALUSrcB, BDR_Out, Ext_Imm, ALU_Input_B );
ALU my_ALU( ALU_Input_A, ALU_Input_B, ALUOP, ALU_Out, zero );
DR my_ALUOutDR( CLK, ALU_Out, ALUOutDR_Out );
DataMemory my_DataMemory( CLK, ALUOutDR_Out, RD, WR, BDR_Out, MemOut );
Mux_TwoToOne_Data my_MuxTwoToOne_For_DBDR( DBDataSrc, ALU_Out, MemOut, DBDR_In );
DR my_DBDR( CLK, DBDR_In, DBDR_Out );
ControlUnit my_ControlUnit( CLK, RST, zero, op, DBDataSrc, WR, RD, ALUSrcB, ALUSrcA, ALUOP, RegWre, RegDst, WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel, PCSrc );
endmodule
PC
module PC( CLK, RST, PCWre, NextPC, CurPC );
input CLK, RST, PCWre;
input [31:0] NextPC;
output reg [31:0] CurPC;
/*initial begin
Address = 0;
end*/
always @( negedge CLK or negedge RST )
begin
if (RST == 0) begin
CurPC = 0;
end
else if (PCWre) begin
CurPC = NextPC;
end
end
endmodule
ALU_For_Next
module ALU_For_Next( CurPC, PC4 );
input [31:0] CurPC;
output reg [31:0] PC4;
always@( CurPC ) begin
PC4 = CurPC + 4;
end
endmodule
ALU_For_Beq
module ALU_For_Beq( PC4, Aim, BeqPC );
input [31:0] PC4, Aim;
output reg [31:0] BeqPC;
always@( PC4 or Aim ) begin
BeqPC = PC4 + Aim * 4;
end
endmodule
Mux_FourToOne_PC
module Mux_FourToOne_PC( PC4, BeqPC, JrPC, JumpPC, PCSrc, NextPC );
input [31:0] PC4, BeqPC, JrPC, JumpPC;
input [1:0] PCSrc;
output reg [31:0] NextPC;
always@( PC4 or BeqPC or JrPC or JumpPC or PCSrc ) begin
case ( PCSrc )
2'b00 : NextPC = PC4;
2'b01 : NextPC = BeqPC;
2'b10 : NextPC = JrPC;
2'b11 : NextPC = JumpPC;
endcase
end
endmodule
InstructionMemory
module InstructionMemory( CurPC, InstMemRW, instcode );
input [31:0] CurPC;
input InstMemRW;
output reg [31:0] instcode;
reg [7:0] InstMemory [255:0];
initial begin
$readmemb("H:/CPU/Multiple_CPU/instruction.txt", InstMemory);
end
always@( CurPC or InstMemRW ) begin
if (InstMemRW == 1) begin
instcode = { InstMemory[CurPC], InstMemory[CurPC + 1], InstMemory[CurPC + 2], InstMemory[CurPC + 3] };
end
$display("InstMem PC", CurPC, " INST: ", instcode);
end
endmodule
IR
module IR( CLK, instcode, IRWre, op, rs, rt, rd, sa, immediate, address );
input CLK;
input [31:0] instcode;
input IRWre;
output reg [5:0] op;
output reg [4:0] rs, rt, rd, sa;
output reg [15:0] immediate;
output reg [25:0] address;
always@( negedge CLK ) begin
if (IRWre == 1) begin
op = instcode[31:26];
rs = instcode[25:21];
rt = instcode[20:16];
rd = instcode[15:11];
sa = instcode[10:6];
immediate = instcode[15:0];
address = instcode[25:0];
end
end
endmodule
Extend_For_Address
module Extend_For_Address( PC4, Address, JumpPC );
input [31:0] PC4;
input [25:0] Address;
output reg [31:0] JumpPC;
always@( PC4 or Address ) begin
JumpPC = { PC4[31:28], Address[25:0], 2'b00 };
end
endmodule
Mux_ThreeToOne_WriteReg
module Mux_ThreeToOne_WriteReg( rt, rd, RegDst, WriteReg );
input [4:0] rt, rd;
input [1:0] RegDst;
output reg [4:0] WriteReg;
always@( rt or rd or RegDst ) begin
case(RegDst)
2'b00 : WriteReg = 5'b11111;
2'b01 : WriteReg = rt;
2'b10 : WriteReg = rd;
endcase
end
endmodule
Mux_TwoToOne_Data
module Mux_TwoToOne_Data( Select, DataA, DataB, DataOut );
input Select;
input [31:0] DataA, DataB;
output reg [31:0] DataOut;
always@( Select or DataA or DataB ) begin
if (Select == 0)
DataOut = DataA;
else
DataOut = DataB;
end
endmodule
Sign_Zero_Extend
module Sign_Zero_Extend( Imm_Number, ExtSel, Result );
input [15 :0] Imm_Number;
input ExtSel;
output reg [31:0] Result;
always@( Imm_Number or ExtSel) begin
if (ExtSel == 0 || Imm_Number[15] == 0)
Result = ;
else
Result = ;
end
endmodule
RegisterFile
module RegisterFile( RegWre, CLK, Reg1, Reg2, WriteReg, WriteData, DataOut1, DataOut2 );
input RegWre;
input CLK;
input [4:0] Reg1, Reg2;
input [4:0] WriteReg;
input [31:0] WriteData;
output [31:0] DataOut1, DataOut2;
reg [31:0] registers[1:31];
assign DataOut1 = ( Reg1 == 0 ) ? 0 : registers[Reg1];
assign DataOut2 = ( Reg2 == 0 ) ? 0 : registers[Reg2];
always@( posedge CLK ) begin
$display("RegWre: ", RegWre);
if (( WriteReg != 0 ) && ( RegWre )) begin
$display("WriteData: ", WriteData, " WriteReg: ", WriteReg);
registers[WriteReg] <= WriteData;
end
end
endmodule
DR
module DR( CLK, DataIn, DataOut );
input CLK;
input [31:0] DataIn;
output reg [31:0] DataOut;
always@( negedge CLK ) begin
DataOut <= DataIn;
end
endmodule
module Mux_TwoToOne_For_InputA( ALUSrcA, DataIn, sa, DataOut );
input ALUSrcA;
input [31:0] DataIn;
input [4:0] sa;
output reg [31:0] DataOut;
always@( ALUSrcA or DataIn or sa ) begin
if ( ALUSrcA == 0 )
DataOut = DataIn;
else
DataOut = { 27'b000000000000000000000000000, sa };
end
endmodule
ALU
module ALU( Reg1, Reg2, ALUOp, result, zero );
input [31:0] Reg1;
input [31:0] Reg2;
input [2:0] ALUOp;
output reg [31:0] result;
output zero;
assign zero = ( result == 0 ) ? 1 : 0;
always@( ALUOp or Reg1 or Reg2 ) begin
case (ALUOp)
3'b000 : result = Reg1 + Reg2; // Y = A + B
3'b001 : result = Reg1 - Reg2; // Y = A - B
3'b010 : begin
if (Reg1 < Reg2 && ((Reg1[31] == 0 && Reg2[31] == 0) || (Reg1[31] == 1 && Reg2[31] == 1)))
result = 1;
else if (Reg1[31] == 0 && Reg2[31] == 1)
result = 0;
else if (Reg1[31] == 1 && Reg2[31] == 0)
result = 1;
else
result = 0;
end
3'b011 : result = (Reg1 < Reg2) ? 1 : 0; // Y=(A < B)? 1 : 0
3'b100 : result = Reg2 << Reg1; // Y = B << A
3'b101 : result = Reg1 | Reg2; // Y = A | B
3'b110 : result = Reg1 & Reg2; // Y = A & B
3'b111 : result = Reg1 ^ Reg2; // Y = A ^ B
endcase
end
endmodule
DataMemory
module DataMemory( CLK, DAddr, RD, WR, DataIn, DataOut );
input CLK;
input [31:0] DAddr;
input RD;
input WR;
input [31:0] DataIn;
output reg [31:0] DataOut;
reg [7:0] dataMemory [0:60];
always@( * ) begin
if (RD == 0) begin
DataOut[7:0] = dataMemory[DAddr + 3];
DataOut[15:8] = dataMemory[DAddr + 2];
DataOut[23:16] = dataMemory[DAddr + 1];
DataOut[31:24] = dataMemory[DAddr];
end
end
always@( posedge CLK ) begin
if (WR == 0) begin
dataMemory[DAddr + 3] <= DataIn[7:0];
dataMemory[DAddr + 2] <= DataIn[15:8];
dataMemory[DAddr + 1] <= DataIn[23:16];
dataMemory[DAddr] <= DataIn[31:24];
end
end
endmodule
ControlUnit
module ControlUnit( CLK, RST, zero, op, DBDataSrc, WR, RD, ALUSrcB, ALUSrcA, ALUOP, RegWre, RegDst, WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel, PCSrc );
input CLK, RST, zero;
input [5:0] op;
output reg DBDataSrc, WR, RD, ALUSrcB, ALUSrcA;
output reg [2:0] ALUOP;
output reg RegWre;
output reg [1:0] RegDst;
output reg WrRegDSrc, IRWre, InsMemRW, PCWre, ExtSel;
output reg [1:0] PCSrc;
reg [2:0] CurState, NextState;
initial begin
CurState = 3'b000;
NextState = 3'b001;
end
always@( RST ) begin
if (RST) begin
CurState = 3'b000;
NextState = 3'b001;
end
end
always@( posedge CLK ) begin
if (RST == 1) begin
CurState = NextState;
end
end
always@( * ) begin
if (op == 6'b000000 || op == 6'b000001 || op == 6'b000010 || op == 6'b010000 || op == 6'b010001 || op == 6'b010010 || op == 6'b011000 || op == 6'b100110 || op == 6'b100111) begin
NextState[2] = CurState[2] ^ CurState[0];
NextState[1] = CurState[2] ^ CurState[0];
NextState[0] = ~CurState[0];
end
if (op == 6'b110100) begin
NextState[2] = ~CurState[2] & CurState[0];
NextState[1] = 0;
NextState[0] = ~CurState[2];
end
if (op == 6'b110001) begin
NextState[2] = CurState[1] & CurState[0];
NextState[1] = CurState[1] ^ CurState[0];
NextState[0] = ~CurState[2] & ~CurState[0];
end
if (op == 6'b110000) begin
NextState[2] = 0;
NextState[1] = CurState[1] ^ CurState[0];
NextState[0] = ~CurState[0];
end
if (op == 6'b111000 || op == 6'b111010 || op == 6'b111001 || op == 6'b111111) begin
NextState[2] = 0;
NextState[1] = 0;
NextState[0] = ~CurState[0];
end
case (CurState)
3'b000 : begin // IF
PCWre = (op == 6'b111111) ? 0 : 1;
InsMemRW = 1;
IRWre = 0;
RD = 1;
WR = 1;
RegWre = 0;
end
3'b001 : begin // ID
PCWre = 0;
ExtSel = (op == 6'b010010) ? 0 : 1;
IRWre = 1;
WrRegDSrc = (op == 6'b111010) ? 0 : 1;
if (op == 6'b111010)
RegDst = 2'b00;
else if (op == 6'b000010 || op == 6'b010010 ||op == 6'b100111 || op == 6'b110001)
RegDst = 2'b01;
else
RegDst = 2'b10;
PCSrc[0] = (op == 6'b111010 || op == 6'b111000) ? 1 : 0;
PCSrc[1] = (op == 6'b111001 || op == 6'b111010 || op == 6'b111000) ? 1 : 0;
RegWre = (op == 6'b111010) ? 1 : 0;
end
3'b110 : begin // EXE for add,sub,addi,or,and,ori,slt,slti,sll
IRWre = 0;
ALUOP[0] = (op == 6'b000001 || op == 6'b010000 || op == 6'b010010) ? 1 : 0;
ALUOP[1] = (op == 6'b010001 || op == 6'b100110 || op == 6'b100111) ? 1 : 0;
ALUOP[2] = (op == 6'b010000 || op == 6'b010001 || op == 6'b010010 || op == 6'b011000) ? 1 : 0;
ALUSrcA = (op == 6'b011000) ? 1 : 0;
ALUSrcB = (op == 6'b000010 || op == 6'b010010 || op == 6'b100111) ? 1 : 0;
DBDataSrc = 0;
end
3'b101 : begin // EXE for beq
IRWre = 0;
ALUOP = 3'b001;
ALUSrcA = 0;
ALUSrcB = 0;
PCSrc = (zero == 1) ? 2'b01 : 2'b00;
end
3'b010 : begin //EXE for sw,lw
IRWre = 0;
ALUOP = 3'b000;
ALUSrcA = 0;
ALUSrcB = 1;
DBDataSrc = 1;
end
3'b011 : begin // MEM for sw,lw
RD = (op == 6'b110001) ? 0 : 1;
WR = (op == 6'b110000) ? 0 : 1;
end
3'b111 : begin // WB for add,sub,addi,or,and,ori,slt,slti,sll
RD = 1;
WR = 1;
RegWre = 1;
end
3'b100 : begin // WB for lw
RD = 1;
WR = 1;
RegWre = 1;
end
endcase
end
endmodule