Merge branch 'main' of https://github.com/supleed2/AM04_CPU into main

This commit is contained in:
jc4419 2020-12-07 15:55:12 +04:00
commit 2ab6ff12eb
18 changed files with 83864 additions and 75 deletions

83537
exec/mips_cpu_harvard_tb_addu Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
350C0003
350D0005
018D5021
01000008
34040003
34050005
00851021
00000008

7
inputs/beq.txt Normal file
View file

@ -0,0 +1,7 @@
50004043
50005043
20005801
00006C42
80000000
10002043
80000000

6
inputs/bgez.txt Normal file
View file

@ -0,0 +1,6 @@
30004043
20001840
00006C42
80000000
10002043
80000000

7
inputs/bgezal.txt Normal file
View file

@ -0,0 +1,7 @@
30004043
30001940
00006C42
10002442
80000000
10002043
80000000

6
inputs/bgtz.txt Normal file
View file

@ -0,0 +1,6 @@
30004043
200008C1
00006C42
80000000
10002043
80000000

6
inputs/blez.txt Normal file
View file

@ -0,0 +1,6 @@
FFFF4043
20000881
00006C42
80000000
10002043
80000000

6
inputs/bltz.txt Normal file
View file

@ -0,0 +1,6 @@
FFFF4043
20000840
00006C42
80000000
10002043
80000000

7
inputs/bltzal.txt Normal file
View file

@ -0,0 +1,7 @@
FFFF4043
20000940
00006C42
10002442
80000000
10002043
80000000

7
inputs/bne.txt Normal file
View file

@ -0,0 +1,7 @@
30004043
50005043
20005841
00006C42
80000000
10002043
80000000

View file

@ -20,25 +20,172 @@ ORI $5,$0,5
ADDU $2,$4,$5
JR $0
350C0003
350D0005
018D5021
01000008
34040003
34050005
00851021
00000008
register_vo = 8
register_v0 = 8
== AND Bitwise and ==
ANDI Bitwise and immediate
BEQ Branch on equal
BGEZ Branch on greater than or equal to zero
BGEZAL Branch on non-negative (>=0) and link
BGTZ Branch on greater than zero
BLEZ Branch on less than or equal to zero
BLTZ Branch on less than zero
BLTZAL Branch on less than zero and link
BNE Branch on not equal
==BEQ Branch on equal==
ORI $4,$0,5
ORI $5,$0,5
BEQ $4,$5,2
ADDIU $6,$6,0
JR $0
ORI $2,$0,1
JR $0
50004043
50005043
20005801
00006C42
80000000
10002043
80000000
register_v0 = 1
==BGEZ Branch on greater than or equal to zero==
ORI $4,$0,3
BGEZ $4,2
ADDIU $6,$6,0
JR $0
ORI $2,$0,1
JR $0
30004043
20001840
00006C42
80000000
10002043
80000000
register_v0 = 1
==BGEZAL Branch on non-negative (>=0) and link==
ORI $4,$0,3
BGEZAL $4,3
ADDIU $6,$6,0
ADDIU $2,$2,1
JR $0
ORI $2,$0,1
JR $31
30004043
30001940
00006C42
10002442
80000000
10002043
80000000
register_v0 = 2
==BGTZ Branch on greater than zero==
ORI $4,$0,3
BGTZ $4,2
ADDIU $6,$6,0
JR $0
ORI $2,$0,1
JR $0
30004043
200008C1
00006C42
80000000
10002043
80000000
register_v0 = 1
==BLEZ Branch on less than or equal to zero==
ORI $4,$0,-1
BLEZ $4,2
ADDIU $6,$6,0
JR $0
ORI $2,$0,1
JR $0
FFFF4043
20000881
00006C42
80000000
10002043
80000000
register_v0 = 1
==BLTZ Branch on less than zero==
ORI $4,$0,-1
BLTZ $4,2
ADDIU $6,$6,0
JR $0
ORI $2,$0,1
JR $0
FFFF4043
20000840
00006C42
80000000
10002043
80000000
register_v0 = 1
==BLTZAL Branch on less than zero and link==
ORI $4,$0,-1
BLTZAL $4,3
ADDIU $6,$6,0
ADDIU $2,$2,1
JR $0
ORI $2,$0,1
JR $31
FFFF4043
20000940
00006C42
10002442
80000000
10002043
80000000
register_v0 = 2
==BNE Branch on not equal==
ORI $4,$0,3
ORI $5,$0,5
BNE $4,$5,2
ADDIU $6, $6, 0
JR $0
ORI $2,$0,1
JR $
30004043
50005043
20005841
00006C42
80000000
10002043
80000000
register_v0 = 1
DIV Divide
DIVU Divide unsigned
J Jump

View file

@ -5,7 +5,7 @@ module mips_cpu_alu(
input logic [4:0] shamt, //5-bit input used to specify shift amount for shift operations. Taken directly from the R-type instruction (Non-Variable) or from
output logic ALUCond, //If a relevant condition is met, this output goes high(Active High). Note: Relevant as in related to current condition being tested.
output signed logic[31:0] ALURes, // The ouput of the ALU
output logic signed[31:0] ALURes // The ouput of the ALU
);
/*
@ -73,7 +73,7 @@ Alu Operations:
Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming errors, as a result of enum implemetnation.
assign ALUOps = ALUOp
assign ALUOps = ALUOp;
always_comb begin
@ -97,39 +97,39 @@ assign ALUOps = ALUOp
end
AND: begin
ALUOut = A & B;
ALURes = A & B;
end
OR: begin
ALUOut = A | B;
ALURes = A | B;
end
XOR: begin
ALUOut = A^B;
ALURes = A^B;
end
SLL: begin
ALUOut = B << shamt;
ALURes = B << shamt;
end
SLLV: begin
ALUOut = B << A;
ALURes = B << A;
end
SRL: begin
ALUOut = B >> shamt;
ALURes = B >> shamt;
end
SRLV: begin
ALUOut = B >> A;
ALURes = B >> A;
end
SRA: begin
ALUOut = B >>> shamt;
ALURes = B >>> shamt;
end
SRAV: begin
ALUOut = B >>> A;
ALURes = B >>> A;
end
EQ: begin

View file

@ -23,13 +23,15 @@ module mips_cpu_harvard(
//Control Flags
logic Jump, Branch, ALUSrc, ALUZero, RegWrite;
logic[5:0] ALUOp = instr_readdata[31:26];
logic[999999999999999999999999999999999999999999999999999999999999999999:0] ALUFlags;
logic[30:0] ALUFlags; //Not sure if this is needed anymore
logic[1:0] RegDst, MemtoReg;
//PC wires
logic[31:0] pc_curr;
logic[31:0] pc_next = Jump ? Jump_addr : PCSrc ? {pc_curr+4+{{14{instr_readdata[15]}}, instr_readdata[15:0], 2'b00}} : {pc_curr+4};
logic[31:0] Jump_addr = {{pc_curr+4}[31:28], instr_readdata[25:0], 2'b00};
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;
//Instruction MEM
@ -54,7 +56,7 @@ 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
//Writeback logic
logic[31:0] writeback = MemtoReg==2'b10 ? {pc_curr+4} : MemtoReg==2'b01 ? data_readdata : ALUOut;
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;
@ -67,16 +69,16 @@ pc pc(
.pc_out(pc_curr)
);
control control( //control flags block
.opcode(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( //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
);
regfile regfile(
@ -91,19 +93,20 @@ regfile regfile(
.readdata2(read_data2), //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
);
alu alu(
.ALUFlags(ALUFlags), //selects the operation carried out by the ALU
*/
mips_cpu_alu alu(
//.ALUFlags(ALUFlags), //selects the operation carried out by the ALU
.A(alu_in1), //operand 1
.B(alu_in2), //operand 2
.ALUzero(ALUZero), //is the result zero, used for checks
.ALUOut(ALUOut), //output/result of operation
.shamt(shamt)
.ALUCond(ALUZero), //is the result zero, used for checks
.ALURes(ALUOut), //output/result of operation
.shamt(shamt),
.ALUOp(ALUOp)
);
endmodule : mips_cpu_harvard

View file

@ -42,18 +42,20 @@ module mips_cpu_memory(
//Load contents from file if specified
if (RAM_INIT_FILE != "") begin
$display("RAM : INIT : Loading RAM contents from %s", RAM_INIT_FILE);
$readmemh(RAM_INIT_FILE, memory[3217031168:0]);
$readmemh(RAM_INIT_FILE, memory, 32'hBFC00000, 32'd0);
end
end
//Combinatorial read path for data and instruction.
if (clk == 1) begin
assign data_readdata = data_read ? memory[data_address] : 16'hxxxx;
assign instr_readdata = memory[instr_address];
always_comb begin
if (clk == 1'd1) begin
data_readdata = data_read ? memory[data_address] : 16'hxxxx;
instr_readdata = memory[instr_address];
end
else begin
assign data_readdata = data_readdata;
assign instr_readdata = instr_address;
data_readdata = data_readdata;
instr_readdata = instr_address;
end
end

View file

@ -15,11 +15,12 @@ reg[31:0] memory [31:0]; //32 register slots, 32-bits wide
initial begin
integer i; //Initialise to zero by default
for (i = 0; i < 31; i++) begin
for (i = 1; i < 32; i++) begin
memory[i] = 0;
end
end
assign memory[0] = 32'h00000000;
assign regv0 = memory[2]; //assigning debug $v0 line to $2 of memory
always_comb begin
@ -31,16 +32,32 @@ always_ff @(negedge clk) begin
if (regwrite) begin
case (opcode)
6'b100000: begin //lb, load byte
memory[writereg] <= {{24{writedata[7]}}, writedata[7:0]};
case (readdata1[1:0])
2'b00: memory[writereg] <= {{24{writedata[7]}}, writedata[7:0]};
2'b01: memory[writereg] <= {{24{writedata[15]}}, writedata[15:8]};
2'b10: memory[writereg] <= {{24{writedata[23]}}, writedata[23:16]};
2'b11: memory[writereg] <= {{24{writedata[31]}}, writedata[31:24]};
endcase // readdata1[1:0]
end
6'b100100: begin //lbu, load byte unsigned
memory[writereg] <= {{24{1'b0}}, writedata[7:0]};
case (readdata1[1:0])
2'b00: memory[writereg] <= {{24{1'b0}}, writedata[7:0]};
2'b01: memory[writereg] <= {{24{1'b0}}, writedata[15:8]};
2'b10: memory[writereg] <= {{24{1'b0}}, writedata[23:16]};
2'b11: memory[writereg] <= {{24{1'b0}}, writedata[31:24]};
endcase // readdata1[1:0]
end
6'b100001: begin //lh, load half-word
memory[writereg] <= {{16{writedata[15]}}, writedata[15:0]};
case (readdata1[1:0]) // must be half-word aligned, readdata1[0] = 0
2'b00: memory[writereg] <= {{16{writedata[15]}}, writedata[15:0]};
2'b10: memory[writereg] <= {{16{writedata[31]}}, writedata[31:16]};
endcase // readdata1[1:0]
end
6'b100101: begin //lhu, load half-word unsigned
memory[writereg] <= {{16{1'b0}}, writedata[15:0]};
case (readdata1[1:0]) // must be half-word aligned, readdata1[0] = 0
2'b00: memory[writereg] <= {{16{1'b0}}, writedata[15:0]};
2'b10: memory[writereg] <= {{16{1'b0}}, writedata[31:16]};
endcase // readdata1[1:0]
end
6'b100010: begin //lwl, load word left
case (readdata1[1:0])

View file

@ -37,13 +37,21 @@ then
done
else
echo "ELSE";
echo ${INSTR};
# Run Testcase File Of Specified Instruction
# iverilog -g 2012 \
# Windows Iverilog with WSL
#/mnt/c/Windows/System32/cmd.exe /C iverilog -g2012 \
# -s mips_cpu_harvard_tb \
# -P mips_cpu_harvard_tb.RAM_INIT_FILE=\"inputs/${INSTR}.hex.txt\" \
# -P mips_cpu_harvard_tb.RAM_INIT_FILE=\"inputs/${INSTR}.txt\" \
# -o program/mips_cpu_harvard_tb_${INSTR} testbench/mips_cpu_harvard_tb.v \
# ${SRC}
# Linux Iverilog
iverilog -g2012 \
-s mips_cpu_harvard_tb \
-P mips_cpu_harvard_tb.RAM_INIT_FILE=\"inputs/${INSTR}.txt\" \
-o program/mips_cpu_harvard_tb_${INSTR} testbench/mips_cpu_harvard_tb.v \
${SRC}
fi
#/mnt/c/Windows/System32/cmd.exe /C \ # need this to run verilog on windows

View file

@ -1,4 +1,4 @@
module CPU_MU0_delay1_tb;
module mips_cpu_bus_tb;
timeunit 1ns / 10ps;
parameter RAM_INIT_FILE = "test/01-binary/countdown.hex.txt";

View file

@ -10,8 +10,30 @@ module mips_cpu_harvard_tb;
logic data_read, data_write;
logic[31:0] data_readdata, data_writedata, data_address;
mips_cpu_memory #(RAM_INIT_FILE) ramInst(clk, data_address, data_write, data_read, data_writedata, data_readdata, instr_address, instr_readdata);
mips_cpu_harvard cpuInst(clk, reset, active, register_v0, clk_enable, instr_address, instr_readdata, data_address, data_write, data_read, data_writedata, data_readdata);
mips_cpu_memory #(RAM_INIT_FILE) ramInst(
.clk(clk),
.data_address(data_address),
.data_write(data_write),
.data_read(data_read),
.data_writedata(data_writedata),
.data_readdata(data_readdata),
.instr_address(instr_address),
.instr_readdata(instr_readdata)
);
mips_cpu_harvard cpuInst(
.clk(clk),
.reset(reset),
.active(active),
.register_v0(register_v0),
.clk_enable(clk_enable),
.instr_address(instr_address),
.instr_readdata(instr_readdata),
.data_address(data_address),
.data_write(data_write),
.data_read(data_read),
.data_writedata(data_writedata),
.data_readdata(data_readdata)
);
// Generate clock
initial begin
@ -37,14 +59,15 @@ module mips_cpu_harvard_tb;
reset <= 0;
@(posedge clk);
assert(running==1)
else $display("TB : CPU did not set running=1 after reset.");
assert(active==1) // Is this assert still valid?
else $display("TB : CPU did not set active=1 after reset.");
while (running) begin
while (active) begin
@(posedge clk);
end
$display("TB : finished; running=0");
$display("%d",register_v0);
$finish;
end