mirror of
https://github.com/supleed2/ELEC50010-IAC-CW.git
synced 2024-11-10 01:35:49 +00:00
Updated Harvard, ALU, PC, Control, and Regfile
This commit is contained in:
parent
8f5e582f33
commit
9de2b59bbb
|
@ -77,8 +77,6 @@ assign ALUOps = ALUOp;
|
|||
|
||||
always_comb begin
|
||||
|
||||
|
||||
|
||||
case(ALUOps)
|
||||
ADD: begin
|
||||
ALURes = $signed(A) + $signed(B);
|
||||
|
|
|
@ -3,10 +3,10 @@ module mips_cpu_control(
|
|||
input logic[31:0] Instr,
|
||||
input logic ALUCond,
|
||||
|
||||
output logic CtrlRegDst,
|
||||
output logic[1:0] CtrlRegDst,
|
||||
output logic[1:0] CtrlPC,
|
||||
output logic CtrlMemRead,
|
||||
output logic CtrlMemtoReg,
|
||||
output logic[1:0] CtrlMemtoReg,
|
||||
output logic[4:0] CtrlALUOp,
|
||||
output logic[4:0] Ctrlshamt,
|
||||
output logic CtrlMemWrite,
|
||||
|
@ -19,7 +19,7 @@ module mips_cpu_control(
|
|||
logic[5:0] funct;
|
||||
logic[4:0] rt; */
|
||||
|
||||
/* assign op = Instr[31:26];
|
||||
/* assign op = Instr[31:26];
|
||||
assign funct = Instr[5:0];
|
||||
assign rt = Instr[20:16]; */
|
||||
|
||||
|
@ -93,27 +93,31 @@ always_comb begin
|
|||
|
||||
//CtrlRegDst logic
|
||||
if(op == (ADDIU | ANDI | LB | LBU | LH | LHU | LUI | LW | LWL | LWR | ORI | SLTI | SLTIU | XORI))begin
|
||||
CtrlRegDst = 0; //Write address comes from rt
|
||||
CtrlRegDst = 2'd0; //Write address comes from rt
|
||||
end else if (op == (SPECIAL & (funct == (ADDU | AND | JALR | OR | SLL | SLLV | SLT | SLTU | SRA | SRAV | SRL | SRLV | SUBU | XOR))))begin
|
||||
CtrlRegDst = 1; //Write address comes from rd
|
||||
CtrlRegDst = 2'd1; //Write address comes from rd
|
||||
end else if (op == JAL)begin
|
||||
CtrlRegDst = 2'd2; //const reg 31, for writing to the link register
|
||||
end else begin CtrlRegDst = 1'bx; end//Not all instructions are encompassed so, added incase for debug purposes
|
||||
|
||||
//CtrlPC logic
|
||||
if(op == (BEQ | BGTZ | BLEZ | BNE | (REGIMM & (rt == (BGEZ | BGEZAL | BLTZ | BLTZAL)))))begin
|
||||
if(ALUCond & (op == (BEQ | BGTZ | BLEZ | BNE | (REGIMM & (rt == (BGEZ | BGEZAL | BLTZ | BLTZAL))))))begin
|
||||
CtrlPC = 2'd1; // Branches - Jumps relative to PC
|
||||
end else if(op == (J | JAL))begin
|
||||
CtrlPC = 2'd2; // Jumps within 256MB Region using 26-bit immediate in J type instruction
|
||||
end else if(op == (JR | JALR))begin
|
||||
CtrlPC = 2'd3; // Jumps using Register.
|
||||
end else begin CtrlPC = 2'd0;end // No jumps, just increment to next word
|
||||
end else begin CtrlPC = 2'd0;end // No jumps or branches, just increment to next word
|
||||
|
||||
//CtrlMemRead and CtrlMemtoReg logic -- Interesting quirk that they have the same logic. Makes sense bc you'd only want to select the read data out when the memory itself is read enabled.
|
||||
if(op == (LB | LBU | LH | LHU | LW | LWL | LWR))begin
|
||||
CtrlMemRead = 1;//Memory is read enabled
|
||||
CtrlMemtoReg = 1;//write data port of memory is fed from data memory
|
||||
CtrlMemtoReg = 2'd1;//write data port of memory is fed from data memory
|
||||
end else if (op == (ADDIU | ANDI | ORI | SLTI | SLTIU | XORI | (SPECIAL & (funct == (ADDU | AND | DIV | DIVU | MTHI | MTLO | MULT | MULTU | OR | SLL | SLLV | SLT | SLTU | SRA | SRAV | SRL | SRLV | SUBU | XOR)))))begin
|
||||
CtrlMemRead = 0;//Memory is read disabled
|
||||
CtrlMemtoReg = 0;//write data port of memory if fed from ALURes
|
||||
CtrlMemtoReg = 2'd0;//write data port of memory is fed from ALURes
|
||||
end else if (op == (JAL | (SPECIAL &(funct == JALR))))begin
|
||||
CtrlMemtoReg = 2'd2;//write data port of memory is fed from PC + 8
|
||||
end else begin CtrlMemRead = 1'bx;end//Not all instructions are encompassed so, added incase for debug purposes
|
||||
|
||||
//CtrlALUOp Logic
|
||||
|
|
|
@ -7,106 +7,143 @@ module mips_cpu_harvard(
|
|||
|
||||
/* New clock enable. See below. */
|
||||
input logic clk_enable,
|
||||
|
||||
|
||||
/* Combinatorial read access to instructions */
|
||||
output logic[31:0] instr_address,
|
||||
input logic[31:0] instr_readdata,
|
||||
output logic[31:0] instr_address,//Port from PC out to instruction memory address input.
|
||||
input logic[31:0] instr_readdata,//port from instruction memory out, going to various inputs.
|
||||
|
||||
/* Combinatorial read and single-cycle write access to instructions */
|
||||
output logic[31:0] data_address,
|
||||
output logic data_write,
|
||||
output logic data_read,
|
||||
output logic[31:0] data_writedata,
|
||||
input logic[31:0] data_readdata
|
||||
output logic[31:0] data_address,//Port from ALURes going into Data Memory 'Address' port
|
||||
output logic data_write,//Control line from 'control' CtrlMemWrite enabling/disabling write access for Data Memory.
|
||||
output logic data_read,//Control line from 'control' CtrlMemRead enabling/disabling read access for Data Memory.
|
||||
output logic[31:0] data_writedata,//Data from Register file 'Read data 2' port, aka rt's data, going to 'Write data' port on Data Memory.
|
||||
input logic[31:0] data_readdata//port from data memory out, going to the 'Write Register' port in regfile.
|
||||
);
|
||||
|
||||
//Control Flags
|
||||
logic Jump, Branch, ALUSrc, ALUZero, RegWrite;
|
||||
logic[5:0] ALUOp = instr_readdata[31:26];
|
||||
logic[30:0] ALUFlags; //Not sure if this is needed anymore
|
||||
logic[1:0] RegDst, MemtoReg;
|
||||
always_comb begin
|
||||
instr_address = out_pc_out;
|
||||
data_address = out_ALURes;
|
||||
data_write = out_MemWrite;
|
||||
data_read = out_MemRead;
|
||||
data_writedata = out_readdata2;
|
||||
end
|
||||
|
||||
//PC wires
|
||||
logic[31:0] pc_curr;
|
||||
logic[31:0] pc_curr_next = pc_curr + 3'd4; //Added due to compilation error
|
||||
logic[31:0] pc_delay; //Added due to compilation error
|
||||
logic[31:0] Jump_addr = {pc_curr_next[31:28], instr_readdata[25:0], 2'b00};
|
||||
logic[31:0] pc_next = Jump ? Jump_addr : PCSrc ? {pc_curr_next + {{14{instr_readdata[15]}}, instr_readdata[15:0], 2'b00}} : pc_curr_next;
|
||||
logic PCSrc = Branch && ALUZero;
|
||||
logic[31:0] in_pc_in;
|
||||
logic[4:0] in_readreg1;
|
||||
logic[4:0] in_readreg2;
|
||||
logic[4:0] in_writereg;
|
||||
logic[31:0] in_writedata;
|
||||
logic[5:0] in_opcode;
|
||||
logic[31:0] in_B;
|
||||
|
||||
//Instruction MEM
|
||||
assign instr_address = pc_delay;
|
||||
always_comb begin
|
||||
|
||||
//deconstruction of instruction :)
|
||||
logic[5:0] opcode = instr_readdata[31:26];
|
||||
logic[4:0] rs = instr_readdata[25:21];
|
||||
logic[4:0] rt = instr_readdata[20:16];
|
||||
logic[4:0] rd = RegDst==2'b10 ? 5'b11111 : RegDst==2'b01 ? instr_readdata[15:11] : instr_readdata[20:16];
|
||||
logic[15:0] immediate = instr_readdata[15:0];
|
||||
logic[4:0] shamt = instr_readdata[10:6]; // Shamt needed for the sll instruction
|
||||
in_readreg1 = instr_readdata[25:21];
|
||||
in_readreg2 = instr_readdata[20:16];
|
||||
in_opcode = instr_readdata[31:26];
|
||||
|
||||
//Picking what the next value of PC should be.
|
||||
case(out_PC)
|
||||
2'd0: begin
|
||||
in_pc_in = out_pc_out + 32'd4;//No branch or jump or load, so no delay slot.
|
||||
end
|
||||
2'd1: begin
|
||||
in_pc_in = //help
|
||||
end
|
||||
2'd2: begin
|
||||
in_pc_in = //my brain hurts
|
||||
end
|
||||
2'd3: begin
|
||||
in_pc_in = //I need to sleep......
|
||||
end
|
||||
endcase
|
||||
|
||||
//ALU Data
|
||||
logic[31:0] alu_in1 = read_data1;
|
||||
logic[31:0] alu_in2 = ALUSrc ? {{16{immediate[15]}},immediate} : read_data2;
|
||||
logic[31:0] ALUOut;
|
||||
//Picking what register should be written to.
|
||||
case(out_RegDst)
|
||||
2'd0:begin
|
||||
in_writereg = instr_readdata[20:16];//GPR rt
|
||||
end
|
||||
2'd1:begin
|
||||
in_writereg = instr_readdata[15:11];//GPR rd
|
||||
end
|
||||
2'd2:begin
|
||||
in_writereg = 5'd31;//Link Register 31.
|
||||
end
|
||||
endcase
|
||||
|
||||
//Data MEM
|
||||
assign data_address = ALUOut; //address to be written to comes from ALU
|
||||
assign data_writedata = read_data2; //data to be written comes from reg read bus 2
|
||||
//Picking which output should be written to regfile.
|
||||
case(out_MemtoReg)
|
||||
2'd0:begin
|
||||
in_writedata = out_ALURes;//Output from ALU Result.
|
||||
end
|
||||
2'd1:begin
|
||||
in_writedata = data_readdata;//Output from Data Memory.
|
||||
end
|
||||
2'd2:begin
|
||||
in_writedata = (out_pc_out + 32'd8);//Output from PC +8.
|
||||
end
|
||||
endcase
|
||||
|
||||
//Writeback logic
|
||||
logic[31:0] writeback = MemtoReg==2'b10 ? {pc_curr_next} : MemtoReg==2'b01 ? data_readdata : ALUOut;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
pc_delay <= pc_curr;
|
||||
//Picking which output should be taken as the second operand for ALU.
|
||||
case(out_ALUSrc)
|
||||
1'b1:begin
|
||||
in_B = {{16{instr_readdata[15]}},instr_readdata[15:0]};//Output from the 16-bit immediate values sign extened to 32bits.
|
||||
end
|
||||
1'b0:begin
|
||||
in_B = out_readdata2;//Output from 'Read data 2' port of regfile.
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
pc pc(
|
||||
.clk(clk),
|
||||
.rst(reset),
|
||||
.pc_in(pc_next),
|
||||
.pc_out(pc_curr)
|
||||
//PC inputs
|
||||
.clk(clk),//clk taken from the Standard signals
|
||||
.rst(reset),//clk taken from the Standard signals
|
||||
.pc_in(in_pc_in),//what the pc will output on the next clock cycle taken from either: PC itself + 4(Normal/Default Operation); or 16-bit signed valued taken from Instr[15-0] sign extend to 32bit then shifted by 2 then added to PC + 4(Branch Operation); or 26-bit instruction address taken from J-type instr[25-0] shifted left by 2 then concatanated to form Jump Address (PC-region branch); or from the GPR rs.
|
||||
//PC outputs
|
||||
.pc_out(out_pc_out)//What the pc outputs at every clock edge that goes into the 'Read address' port of Instruction Memory.
|
||||
);
|
||||
|
||||
mips_cpu_control control( //control flags block
|
||||
.Instr(opcode), //opcode to be decoded
|
||||
.Jump(Jump), //jump flag: 0 - increment or branch, 1 - J-type jump
|
||||
.Branch(Branch), //branch flag: 0 - increment, 1 - branch if ALU.Zero == 1
|
||||
.Memread(data_read), //tells data memory to read out data at dMEM[ALUout]
|
||||
.Memtoreg(MemtoReg), //0: writeback = ALUout, 1: writeback = data_readdata
|
||||
.Memwrite(data_write), //tells data memory to store data_writedata at data_writeaddress
|
||||
.Alusrc(ALUSrc), //0: ALUin2 = read_data2, 1: ALUin2 = signextended(instr_readdata[15:0])
|
||||
.Regwrite(RegWrite), //tells register file to write writeback to rd
|
||||
.Regdst(RegDst) //select Rt, Rd or $ra to store to
|
||||
mips_cpu_control control( //instance of the 'mips_cpu_control' module called 'control' in top level 'harvard'
|
||||
//Inputs to control
|
||||
.Instr(instr_readdata), //Full instruction taken from the Instruction Memory.
|
||||
.ALUCond(out_ALUCond), //Active high condition check from ALU
|
||||
//Outputs from control
|
||||
.CtrlRegDst(out_RegDst),
|
||||
.CtrlPC(out_PC),
|
||||
.CtrlMemRead(out_MemRead),
|
||||
.CtrlMemtoReg(out_MemtoReg),
|
||||
.CtrlALUOp(out_ALUOp),
|
||||
.Ctrlshamt(out_shamt),
|
||||
.CtrlMemWrite(out_MemWrite),
|
||||
.CtrlALUSrc(out_ALUSrc),
|
||||
.CtrlRegWrite(out_RegWrite)
|
||||
);
|
||||
|
||||
regfile regfile(
|
||||
.clk(clk), //clock input for triggering write port
|
||||
.readreg1(rs), //read port 1 selector
|
||||
.readreg2(rt), //read port 2 selector
|
||||
.writereg(rd), //write port selector
|
||||
.writedata(writeback), //write port input data
|
||||
.regwrite(RegWrite), //enable line for write port
|
||||
.opcode(opcode), //opcode input for controlling partial load weirdness
|
||||
.readdata1(read_data1), //read port 1 output
|
||||
.readdata2(read_data2), //read port 2 output
|
||||
.regv0(register_v0) //debug output of $v0 or $2 (first register for returning function results
|
||||
mips_cpu_regfile regfile(
|
||||
//Inputs to refile
|
||||
.clk(clk), //clock input for triggering write port
|
||||
.readreg1(in_readreg1), //read port 1 selector
|
||||
.readreg2(in_readreg2), //read port 2 selector
|
||||
.writereg(in_writereg), //write port selector
|
||||
.writedata(in_writedata), //write port input data
|
||||
.regwrite(out_RegWrite), //enable line for write port
|
||||
.opcode(in_opcode), //opcode input for controlling partial load weirdness
|
||||
//Outputs from regfile
|
||||
.readdata1(out_readdata1), //read port 1 output
|
||||
.readdata2(out_readdata2), //read port 2 output
|
||||
.regv0(register_v0) //debug output of $v0 or $2 (first register for returning function results
|
||||
);
|
||||
/*
|
||||
alucontrol alucontrol(
|
||||
.ALUOp(ALUOp), //opcode of instruction
|
||||
.funct(immediate[5:0]), //funct of instruction
|
||||
.aluflags(ALUFlags) //ALU Control flags
|
||||
);
|
||||
*/
|
||||
|
||||
mips_cpu_alu alu(
|
||||
//.ALUFlags(ALUFlags), //selects the operation carried out by the ALU
|
||||
.A(alu_in1), //operand 1
|
||||
.B(alu_in2), //operand 2
|
||||
.ALUCond(ALUZero), //is the result zero, used for checks
|
||||
.ALURes(ALUOut), //output/result of operation
|
||||
.shamt(shamt),
|
||||
.ALUOp(ALUOp)
|
||||
//Inputs to ALU
|
||||
.A(out_readdata1), //operand 1 taken from 'Read data 1' aka the data stored in GPR rs.
|
||||
.B(in_B), //operand 2 taken either from: 'Read data 2' aka the data stored in rt; or 16-bit immediate sign extended to 32 bits.
|
||||
.ALUOp(out_ALUOp), //Operation selection for ALU decided, and output by control.
|
||||
.shamt(out_shamt), //Shift amount required for shift instruction taken from control.
|
||||
//Outputs from ALU
|
||||
.ALUCond(out_ALUCond), //condition used by control to decide on branch instructions.
|
||||
.ALURes(out_ALURes) //output/result of operation that goes to either: 'Address' port of Data Memory; or 'Write Data' port of the register file.
|
||||
);
|
||||
endmodule : mips_cpu_harvard
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -9,17 +9,19 @@ reg[31:0] pc_curr;
|
|||
|
||||
initial begin
|
||||
pc_curr = 32'hBFC00000;
|
||||
end : initial
|
||||
end // initial
|
||||
|
||||
always_comb begin
|
||||
if (rst) begin
|
||||
pc_curr = 32'hBFC00000;
|
||||
end else begin
|
||||
pc_curr = pc_in;
|
||||
end
|
||||
pc_out = pc_curr;
|
||||
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
pc_curr <= pc_in;
|
||||
pc_out <= pc_curr;
|
||||
end
|
||||
|
||||
endmodule : pc
|
||||
endmodule // pc
|
|
@ -1,8 +1,8 @@
|
|||
module regfile(
|
||||
module mips_cpu_regfile(
|
||||
input logic clk, //clock input for triggering write port
|
||||
input logic[4:0] readreg1, //read port 1 selector
|
||||
input logic[4:0] readreg2, //read port 2 selector
|
||||
input logic[4:0] writereg, //write port selector
|
||||
input logic[4:0] readreg1, //read port 1 register selector
|
||||
input logic[4:0] readreg2, //read port 2 register selector
|
||||
input logic[4:0] writereg, //write port register selector
|
||||
input logic[31:0] writedata, //write port input data
|
||||
input logic regwrite, //enable line for write port
|
||||
input[5:0] opcode, //opcode input for controlling partial load weirdness
|
||||
|
@ -80,4 +80,4 @@ always_ff @(negedge clk) begin
|
|||
end
|
||||
end
|
||||
|
||||
endmodule : regfile
|
||||
endmodule
|
Loading…
Reference in a new issue