233 lines
12 KiB
Verilog

module controller #(
/*
field of all one bit signal
*/
parameter T = 1'b1,
parameter F = 1'b0,
/*
field of use_stage
0 : be used in ID
1 : be used in EX
*/
parameter ID = 1'b0,
parameter EX = 1'b1,
/*
LS_bit field
value to tell the difference between word, half word and btye
*/
parameter NONE = 2'b00,
parameter WORD = 2'b01,
parameter HALF = 2'b10,
parameter BYTE = 2'b11,
/*
Branch field
tag to distinguish Branch
*/
parameter BEQ = 4'b0000, // branch equal
parameter BNE = 4'b0001, // branch not equal
parameter BGEZ = 4'b0010, // branch greater than or equal to zero
parameter BGTZ = 4'b0011, // branch greater than zero
parameter BLEZ = 4'b0100, // branch less than or equal to zero
parameter BLTZ = 4'b0101, // branch less than zero
parameter BGEZAL = 4'b0110, // branch greater than or equal to zero and link
parameter BLTZAL = 4'b0111, // branch less than zero and link
parameter NO_BRANCH = 4'b1000, // no branch
/*
RegDst field
tag to decide which register may be updated
*/
parameter RT = 3'b000, // to GPR[rt]
parameter RD = 3'b001, // to GPR[rd]
parameter RA = 3'b010, // to GPR[31]
parameter HI = 3'b011, // to GPR[32]
parameter LO = 3'b100, // to GPR[33]
parameter PROD = 3'b101, // to HI and LO
/*
DataDst field
tag to decide what may be wirtten to regfile
*/
parameter ALU_OUT = 3'b000,
parameter PC_ADD_OUT = 3'b001,
parameter HIGH_OUT = 3'b010,
parameter LOW_OUT = 3'b011,
parameter CP0_OUT = 3'b100,
/*
ALUOp field
tag to decide which operation will be done in alu
*/
parameter USE_R_TYPE = 4'b0000,
parameter USE_ADD = 4'b0001,
parameter USE_ADDU = 4'b0010,
parameter USE_SUB = 4'b0011,
parameter USE_SUBU = 4'b0100,
parameter USE_SLT = 4'b0101,
parameter USE_SLTU = 4'b0110,
parameter USE_AND = 4'b0111,
parameter USE_OR = 4'b1000,
parameter USE_NOR = 4'b1001,
parameter USE_XOR = 4'b1010,
parameter USE_LUI = 4'b1011,
/*
field of ExcCode
*/
parameter NO_EXC = 4'b0000
// TODO : finish interface with cp0
)(
input [ 5: 0] opcode,
input [ 4: 0] rs,
input [ 4: 0] rt,
input [ 5: 0] funct,
output reg use_stage,
output reg [ 1: 0] LS_bit,
output reg [ 2: 0] RegDst,
output reg [ 2: 0] DataDst,
output reg MemtoReg,
output reg [ 3: 0] ALUOp,
output reg MemWrite,
output reg ALUSrc,
output reg ShamtSrc,
output reg RegWrite,
output reg Ext_op, // 1 : signed ext 0 : unsigned ext
output reg [ 3: 0] ExcCode,
output reg [ 3: 0] Branch,
output reg Jump,
output reg Jr
);
/*
opcode field
*/
parameter opcode_is_RType = 6'b000000;
// conditional transfer
parameter opcode_is_BEQ = 6'b000100;
parameter opcode_is_BNE = 6'b000101;
parameter opcode_is_BGTZ = 6'b000111;
parameter opcode_is_BLEZ = 6'b000110;
parameter opcode_is_REGIMM = 6'b000001;
// when opcode_is_REGIMM, rt
parameter rt_is_BGEZ = 5'b00001;
parameter rt_is_BLTZ = 5'b00000;
parameter rt_is_BGEZAL = 5'b10001;
parameter rt_is_BLTZAL = 5'b10000;
// I type R op
parameter opcode_is_ADDI = 6'b001000;
parameter opcode_is_ADDIU = 6'b001001;
parameter opcode_is_SLTI = 6'b001010;
parameter opcode_is_SLTIU = 6'b001011;
parameter opcode_is_ANDI = 6'b001100;
parameter opcode_is_LUI = 6'b001111;
parameter opcode_is_ORI = 6'b001101;
parameter opcode_is_XORI = 6'b001110;
// load and save
parameter opcode_is_LW = 6'b100011;
parameter opcode_is_LH = 6'b100001;
parameter opcode_is_LHU = 6'b100101;
parameter opcode_is_LB = 6'b100000;
parameter opcode_is_LBU = 6'b100100;
parameter opcode_is_SW = 6'b101011;
parameter opcode_is_SH = 6'b101001;
parameter opcode_is_SB = 6'b101000;
// J Type
parameter opcode_is_J = 6'b000010;
parameter opcode_is_JAL = 6'b000011;
// self trap
parameter opcode_is_COP0 = 6'b010000;
// COP0 field
parameter rs_is_MFC0 = 5'b00000;
parameter rs_is_MTC0 = 5'b00100;
parameter funct_is_ERET = 6'b011000;
/*
funct code field
*/
parameter funct_is_MULT = 6'b011000;
parameter funct_is_MULTU = 6'b011001;
parameter funct_is_DIV = 6'b011010;
parameter funct_is_DIVU = 6'b011011;
parameter funct_is_JR = 6'b001000; // PC ← GPR[rs] rd : data :
parameter funct_is_SLLV = 6'b000100; // GPR[rd] ← GPR[rt] << GPR[rs] (logical) rd : rd data : alu
parameter funct_is_SRLV = 6'b000110; // GPR[rd] ← GPR[rt] >> GPR[rs] (logical) rd : rd data : alu
parameter funct_is_SRAV = 6'b000111; // GPR[rd] ← GPR[rt] >> GPR[rs] (arithmetic) rd : rd data : alu
parameter funct_is_MFHI = 6'b010000; // GPR[rd] ← HI rd : rd data : high_out
parameter funct_is_MFLO = 6'b010010; // GPR[rd] ← LO rd : rd data : low_out
parameter funct_is_MTHI = 6'b010001; // HI ← GPR[rs] rd : 32 data : alu
parameter funct_is_MTLO = 6'b010011; // LO ← GPR[rs] rd : 33 data : alu
// MTHI & MTLO can be seen as HI ← alu_out ← GPR[rs]
`define SIGNAL {use_stage, LS_bit, RegDst, DataDst, MemtoReg, ALUOp, MemWrite, ALUSrc, ShamtSrc, RegWrite, Ext_op, ExcCode, Branch, Jump, Jr}
always @(*) begin
case (opcode)
opcode_is_RType : begin
case (funct)
funct_is_MULT : `SIGNAL = {EX, NONE, PROD, ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_MULTU : `SIGNAL = {EX, NONE, PROD, ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_DIV : `SIGNAL = {EX, NONE, PROD, ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_DIVU : `SIGNAL = {EX, NONE, PROD, ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_JR : `SIGNAL = {ID, NONE, RD , ALU_OUT , F, USE_R_TYPE, F, F, F, F, F, NO_EXC, NO_BRANCH, F, T};
funct_is_SLLV : `SIGNAL = {EX, NONE, RD , ALU_OUT , F, USE_R_TYPE, F, F, T, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_SRLV : `SIGNAL = {EX, NONE, RD , ALU_OUT , F, USE_R_TYPE, F, F, T, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_SRAV : `SIGNAL = {EX, NONE, RD , ALU_OUT , F, USE_R_TYPE, F, F, T, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_MFHI : `SIGNAL = {EX, NONE, RD , HIGH_OUT, F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_MFLO : `SIGNAL = {EX, NONE, RD , LOW_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_MTHI : `SIGNAL = {EX, NONE, HI , ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
funct_is_MTLO : `SIGNAL = {EX, NONE, LO , ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
default : `SIGNAL = {EX, NONE, RD , ALU_OUT , F, USE_R_TYPE, F, F, F, T, F, NO_EXC, NO_BRANCH, F, F};
endcase
end
opcode_is_BEQ : `SIGNAL = {ID, NONE, RD, ALU_OUT, F, USE_R_TYPE, F, F, F, F, T, NO_EXC, BEQ , F, F};
opcode_is_BNE : `SIGNAL = {ID, NONE, RD, ALU_OUT, F, USE_R_TYPE, F, F, F, F, T, NO_EXC, BNE , F, F};
opcode_is_BGTZ : `SIGNAL = {ID, NONE, RD, ALU_OUT, F, USE_R_TYPE, F, F, F, F, T, NO_EXC, BGTZ, F, F};
opcode_is_BLEZ : `SIGNAL = {ID, NONE, RD, ALU_OUT, F, USE_R_TYPE, F, F, F, F, T, NO_EXC, BLEZ, F, F};
opcode_is_REGIMM : begin
case (rt)
rt_is_BGEZ : `SIGNAL = {ID, NONE, RD, ALU_OUT , F, USE_R_TYPE, F, F, F, F, T, NO_EXC, BGEZ , F, F};
rt_is_BLTZ : `SIGNAL = {ID, NONE, RD, ALU_OUT , F, USE_R_TYPE, F, F, F, F, T, NO_EXC, BLTZ , F, F};
rt_is_BGEZAL : `SIGNAL = {ID, NONE, RA, PC_ADD_OUT, F, USE_R_TYPE, F, F, F, T, T, NO_EXC, BGEZAL, F, F};
rt_is_BLTZAL : `SIGNAL = {ID, NONE, RA, PC_ADD_OUT, F, USE_R_TYPE, F, F, F, T, T, NO_EXC, BLTZAL, F, F};
endcase
end
opcode_is_ADDI : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_ADD , F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_ADDIU : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_ADDU, F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_SLTI : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_SLT , F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_SLTIU : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_SLTU, F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_ANDI : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_AND , F, T, F, T, F, NO_EXC, NO_BRANCH, F, F};
opcode_is_ORI : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_OR , F, T, F, T, F, NO_EXC, NO_BRANCH, F, F};
opcode_is_XORI : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_XOR , F, T, F, T, F, NO_EXC, NO_BRANCH, F, F};
opcode_is_LUI : `SIGNAL = {EX, NONE, RT, ALU_OUT, F, USE_LUI , F, T, F, T, F, NO_EXC, NO_BRANCH, F, F};
opcode_is_LW : `SIGNAL = {EX, WORD, RT, ALU_OUT, T, USE_ADD , F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_LH : `SIGNAL = {EX, HALF, RT, ALU_OUT, T, USE_ADD , F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_LHU : `SIGNAL = {EX, HALF, RT, ALU_OUT, T, USE_ADD , F, T, F, T, F, NO_EXC, NO_BRANCH, F, F};
opcode_is_LB : `SIGNAL = {EX, BYTE, RT, ALU_OUT, T, USE_ADD , F, T, F, T, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_LBU : `SIGNAL = {EX, BYTE, RT, ALU_OUT, T, USE_ADD , F, T, F, T, F, NO_EXC, NO_BRANCH, F, F};
opcode_is_SW : `SIGNAL = {EX, WORD, RT, ALU_OUT, F, USE_ADD , T, T, F, F, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_SH : `SIGNAL = {EX, HALF, RT, ALU_OUT, F, USE_ADD , T, T, F, F, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_SB : `SIGNAL = {EX, BYTE, RT, ALU_OUT, F, USE_ADD , T, T, F, F, T, NO_EXC, NO_BRANCH, F, F};
opcode_is_J : `SIGNAL = {ID, NONE, RD, ALU_OUT , F, USE_ADD , F, T, F, F, F, NO_EXC, NO_BRANCH, T, F};
opcode_is_JAL : `SIGNAL = {ID, NONE, RA, PC_ADD_OUT, F, USE_ADD , F, T, F, T, F, NO_EXC, NO_BRANCH, T, F};
opcode_is_COP0 : begin
case (rs)
// TODO : finish the signal, the completed SIGNAL is incorrect
rs_is_MFC0 : `SIGNAL = {ID, NONE, RA, PC_ADD_OUT, F, USE_ADD , F, T, F, T, F, NO_EXC, NO_BRANCH, T, F};
rs_is_MTC0 : `SIGNAL = {ID, NONE, RA, PC_ADD_OUT, F, USE_ADD , F, T, F, T, F, NO_EXC, NO_BRANCH, T, F};
default : begin
if (funct == funct_is_ERET)
`SIGNAL = {ID, NONE, RA, PC_ADD_OUT, F, USE_ADD , F, T, F, T, F, NO_EXC, NO_BRANCH, T, F};
end
endcase
end
endcase
end
endmodule //controller