Updated Harvard, ALU, PC, Control, and Regfile

This commit is contained in:
jc4419 2020-12-08 01:46:01 +04:00
parent 8f5e582f33
commit 9de2b59bbb
5 changed files with 142 additions and 101 deletions

View file

@ -77,8 +77,6 @@ assign ALUOps = ALUOp;
always_comb begin always_comb begin
case(ALUOps) case(ALUOps)
ADD: begin ADD: begin
ALURes = $signed(A) + $signed(B); ALURes = $signed(A) + $signed(B);

View file

@ -3,10 +3,10 @@ module mips_cpu_control(
input logic[31:0] Instr, input logic[31:0] Instr,
input logic ALUCond, input logic ALUCond,
output logic CtrlRegDst, output logic[1:0] CtrlRegDst,
output logic[1:0] CtrlPC, output logic[1:0] CtrlPC,
output logic CtrlMemRead, output logic CtrlMemRead,
output logic CtrlMemtoReg, output logic[1:0] CtrlMemtoReg,
output logic[4:0] CtrlALUOp, output logic[4:0] CtrlALUOp,
output logic[4:0] Ctrlshamt, output logic[4:0] Ctrlshamt,
output logic CtrlMemWrite, output logic CtrlMemWrite,
@ -93,27 +93,31 @@ always_comb begin
//CtrlRegDst logic //CtrlRegDst logic
if(op == (ADDIU | ANDI | LB | LBU | LH | LHU | LUI | LW | LWL | LWR | ORI | SLTI | SLTIU | XORI))begin 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 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 end else begin CtrlRegDst = 1'bx; end//Not all instructions are encompassed so, added incase for debug purposes
//CtrlPC logic //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 CtrlPC = 2'd1; // Branches - Jumps relative to PC
end else if(op == (J | JAL))begin end else if(op == (J | JAL))begin
CtrlPC = 2'd2; // Jumps within 256MB Region using 26-bit immediate in J type instruction CtrlPC = 2'd2; // Jumps within 256MB Region using 26-bit immediate in J type instruction
end else if(op == (JR | JALR))begin end else if(op == (JR | JALR))begin
CtrlPC = 2'd3; // Jumps using Register. 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. //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 if(op == (LB | LBU | LH | LHU | LW | LWL | LWR))begin
CtrlMemRead = 1;//Memory is read enabled 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 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 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 end else begin CtrlMemRead = 1'bx;end//Not all instructions are encompassed so, added incase for debug purposes
//CtrlALUOp Logic //CtrlALUOp Logic

View file

@ -9,104 +9,141 @@ module mips_cpu_harvard(
input logic clk_enable, input logic clk_enable,
/* Combinatorial read access to instructions */ /* Combinatorial read access to instructions */
output logic[31:0] instr_address, output logic[31:0] instr_address,//Port from PC out to instruction memory address input.
input logic[31:0] instr_readdata, input logic[31:0] instr_readdata,//port from instruction memory out, going to various inputs.
/* Combinatorial read and single-cycle write access to instructions */ /* Combinatorial read and single-cycle write access to instructions */
output logic[31:0] data_address, output logic[31:0] data_address,//Port from ALURes going into Data Memory 'Address' port
output logic data_write, output logic data_write,//Control line from 'control' CtrlMemWrite enabling/disabling write access for Data Memory.
output logic data_read, output logic data_read,//Control line from 'control' CtrlMemRead enabling/disabling read access for Data Memory.
output logic[31:0] data_writedata, 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 input logic[31:0] data_readdata//port from data memory out, going to the 'Write Register' port in regfile.
); );
//Control Flags always_comb begin
logic Jump, Branch, ALUSrc, ALUZero, RegWrite; instr_address = out_pc_out;
logic[5:0] ALUOp = instr_readdata[31:26]; data_address = out_ALURes;
logic[30:0] ALUFlags; //Not sure if this is needed anymore data_write = out_MemWrite;
logic[1:0] RegDst, MemtoReg; data_read = out_MemRead;
data_writedata = out_readdata2;
end
//PC wires logic[31:0] in_pc_in;
logic[31:0] pc_curr; logic[4:0] in_readreg1;
logic[31:0] pc_curr_next = pc_curr + 3'd4; //Added due to compilation error logic[4:0] in_readreg2;
logic[31:0] pc_delay; //Added due to compilation error logic[4:0] in_writereg;
logic[31:0] Jump_addr = {pc_curr_next[31:28], instr_readdata[25:0], 2'b00}; logic[31:0] in_writedata;
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[5:0] in_opcode;
logic PCSrc = Branch && ALUZero; logic[31:0] in_B;
//Instruction MEM always_comb begin
assign instr_address = pc_delay;
//deconstruction of instruction :) in_readreg1 = instr_readdata[25:21];
logic[5:0] opcode = instr_readdata[31:26]; in_readreg2 = instr_readdata[20:16];
logic[4:0] rs = instr_readdata[25:21]; in_opcode = instr_readdata[31:26];
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
//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 //Picking what register should be written to.
logic[31:0] alu_in1 = read_data1; case(out_RegDst)
logic[31:0] alu_in2 = ALUSrc ? {{16{immediate[15]}},immediate} : read_data2; 2'd0:begin
logic[31:0] ALUOut; 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 //Picking which output should be written to regfile.
assign data_address = ALUOut; //address to be written to comes from ALU case(out_MemtoReg)
assign data_writedata = read_data2; //data to be written comes from reg read bus 2 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 //Picking which output should be taken as the second operand for ALU.
logic[31:0] writeback = MemtoReg==2'b10 ? {pc_curr_next} : MemtoReg==2'b01 ? data_readdata : ALUOut; case(out_ALUSrc)
1'b1:begin
always_ff @(posedge clk) begin in_B = {{16{instr_readdata[15]}},instr_readdata[15:0]};//Output from the 16-bit immediate values sign extened to 32bits.
pc_delay <= pc_curr; end
1'b0:begin
in_B = out_readdata2;//Output from 'Read data 2' port of regfile.
end
endcase
end end
pc pc( pc pc(
.clk(clk), //PC inputs
.rst(reset), .clk(clk),//clk taken from the Standard signals
.pc_in(pc_next), .rst(reset),//clk taken from the Standard signals
.pc_out(pc_curr) .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 mips_cpu_control control( //instance of the 'mips_cpu_control' module called 'control' in top level 'harvard'
.Instr(opcode), //opcode to be decoded //Inputs to control
.Jump(Jump), //jump flag: 0 - increment or branch, 1 - J-type jump .Instr(instr_readdata), //Full instruction taken from the Instruction Memory.
.Branch(Branch), //branch flag: 0 - increment, 1 - branch if ALU.Zero == 1 .ALUCond(out_ALUCond), //Active high condition check from ALU
.Memread(data_read), //tells data memory to read out data at dMEM[ALUout] //Outputs from control
.Memtoreg(MemtoReg), //0: writeback = ALUout, 1: writeback = data_readdata .CtrlRegDst(out_RegDst),
.Memwrite(data_write), //tells data memory to store data_writedata at data_writeaddress .CtrlPC(out_PC),
.Alusrc(ALUSrc), //0: ALUin2 = read_data2, 1: ALUin2 = signextended(instr_readdata[15:0]) .CtrlMemRead(out_MemRead),
.Regwrite(RegWrite), //tells register file to write writeback to rd .CtrlMemtoReg(out_MemtoReg),
.Regdst(RegDst) //select Rt, Rd or $ra to store to .CtrlALUOp(out_ALUOp),
.Ctrlshamt(out_shamt),
.CtrlMemWrite(out_MemWrite),
.CtrlALUSrc(out_ALUSrc),
.CtrlRegWrite(out_RegWrite)
); );
regfile regfile( mips_cpu_regfile regfile(
.clk(clk), //clock input for triggering write port //Inputs to refile
.readreg1(rs), //read port 1 selector .clk(clk), //clock input for triggering write port
.readreg2(rt), //read port 2 selector .readreg1(in_readreg1), //read port 1 selector
.writereg(rd), //write port selector .readreg2(in_readreg2), //read port 2 selector
.writedata(writeback), //write port input data .writereg(in_writereg), //write port selector
.regwrite(RegWrite), //enable line for write port .writedata(in_writedata), //write port input data
.opcode(opcode), //opcode input for controlling partial load weirdness .regwrite(out_RegWrite), //enable line for write port
.readdata1(read_data1), //read port 1 output .opcode(in_opcode), //opcode input for controlling partial load weirdness
.readdata2(read_data2), //read port 2 output //Outputs from regfile
.regv0(register_v0) //debug output of $v0 or $2 (first register for returning function results .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( mips_cpu_alu alu(
//.ALUFlags(ALUFlags), //selects the operation carried out by the ALU //Inputs to ALU
.A(alu_in1), //operand 1 .A(out_readdata1), //operand 1 taken from 'Read data 1' aka the data stored in GPR rs.
.B(alu_in2), //operand 2 .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.
.ALUCond(ALUZero), //is the result zero, used for checks .ALUOp(out_ALUOp), //Operation selection for ALU decided, and output by control.
.ALURes(ALUOut), //output/result of operation .shamt(out_shamt), //Shift amount required for shift instruction taken from control.
.shamt(shamt), //Outputs from ALU
.ALUOp(ALUOp) .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

View file

@ -9,17 +9,19 @@ reg[31:0] pc_curr;
initial begin initial begin
pc_curr = 32'hBFC00000; pc_curr = 32'hBFC00000;
end : initial end // initial
always_comb begin always_comb begin
if (rst) begin if (rst) begin
pc_curr = 32'hBFC00000; pc_curr = 32'hBFC00000;
end else begin
pc_curr = pc_in;
end end
pc_out = pc_curr;
end end
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
pc_curr <= pc_in; pc_out <= pc_curr;
end end
endmodule : pc endmodule // pc

View file

@ -1,8 +1,8 @@
module regfile( module mips_cpu_regfile(
input logic clk, //clock input for triggering write port input logic clk, //clock input for triggering write port
input logic[4:0] readreg1, //read port 1 selector input logic[4:0] readreg1, //read port 1 register selector
input logic[4:0] readreg2, //read port 2 selector input logic[4:0] readreg2, //read port 2 register selector
input logic[4:0] writereg, //write port selector input logic[4:0] writereg, //write port register selector
input logic[31:0] writedata, //write port input data input logic[31:0] writedata, //write port input data
input logic regwrite, //enable line for write port input logic regwrite, //enable line for write port
input[5:0] opcode, //opcode input for controlling partial load weirdness input[5:0] opcode, //opcode input for controlling partial load weirdness
@ -80,4 +80,4 @@ always_ff @(negedge clk) begin
end end
end end
endmodule : regfile endmodule