diff --git a/inputs/ori.txt b/inputs/ori.txt new file mode 100644 index 0000000..996347b --- /dev/null +++ b/inputs/ori.txt @@ -0,0 +1,8 @@ +34040003 +00000008 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 \ No newline at end of file diff --git a/rtl/mips_cpu_control.v b/rtl/mips_cpu_control.v index 6f5c186..f51c723 100644 --- a/rtl/mips_cpu_control.v +++ b/rtl/mips_cpu_control.v @@ -1,5 +1,4 @@ module mips_cpu_control( - input logic[31:0] Instr, input logic ALUCond, @@ -12,17 +11,8 @@ module mips_cpu_control( output logic CtrlMemWrite, output logic CtrlALUSrc, output logic CtrlRegWrite - ); -/* logic[5:0] op; -logic[5:0] funct; -logic[4:0] rt; */ - -/* assign op = Instr[31:26]; -assign funct = Instr[5:0]; -assign rt = Instr[20:16]; */ - typedef enum logic[5:0]{ SPECIAL = 6'd0, REGIMM = 6'd1, @@ -52,7 +42,7 @@ typedef enum logic[5:0]{ SW = 6'd43 } op_enum; op_enum op; -assign op = Instr[31:26]; +assign op = Instr[31:26]; typedef enum logic[5:0]{ SLL = 6'd0, @@ -87,10 +77,11 @@ typedef enum logic[4:0]{ BGEZAL = 5'd17 } rt_enum; rt_enum rt; -assign rt = Instr[20:16]; +assign rt = Instr[20:16]; -always_comb begin - + + +always @(*) begin //CtrlRegDst logic if((op==ADDIU) || (op==ANDI) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LUI) || (op==LW) || (op==LWL) || (op==LWR) || (op==ORI) || (op==SLTI) || (op==SLTIU) || (op==XORI))begin // CtrlRegDst = 2'd0; //Write address comes from rt @@ -107,7 +98,8 @@ always_comb begin CtrlPC = 2'd2; // Jumps within 256MB Region using 26-bit immediate in J type instruction end else if((op==JR) || (op==JALR))begin CtrlPC = 2'd3; // Jumps using Register. - end else begin CtrlPC = 2'd0;end // No jumps or branches, just increment to next word + $display("Ctrl PC Jump Register"); + end else begin CtrlPC = 2'd0; $display("Ctrl PC No Jump/Branch");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) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR))begin @@ -197,7 +189,7 @@ always_comb begin end else begin CtrlALUSrc = 1'bx;end //CtrlRegWrite logic - if(op == (ADDIU | ANDI | LB | LBU | LH | LHU | LUI | LW | LWL | LWR | ORI | SLTI | SLTIU | XORI | (SPECIAL & (funct == (ADDU | AND | DIV | DIVU | MULT | MULTU | JALR | OR | SLL | SLLV | SLT | SLTU | SRA | SRAV | SRL | SRLV | SUBU | XOR)))))begin + if((op == ADDIU | op == ANDI | op == LB | op == LBU | op == LH | op == LHU | op == LUI | op == LW | op == LWL | op == LWR | op == ORI | op == SLTI | op == SLTIU | op == XORI | (op == SPECIAL & ((funct == ADDU | funct == AND | funct == DIV | funct == DIVU | funct == MULT | funct == MULTU | funct == JALR | funct == OR | funct == SLL | funct == SLLV | funct == SLT | funct == SLTU | funct == SRA | funct == SRAV | funct == SRL | funct == SRLV | funct == SUBU | funct == XOR)))))begin CtrlRegWrite = 1;//The Registers are Write Enabled end else begin CtrlRegWrite = 0;end // The Registers are Write Disabled ((op==ADDIU) || (op==ANDI) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LUI) || (op==LW) || (op==LWL) || (op==LWR) || (op==ORI) || (op==SLTI) || (op==XORI) || ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==DIV) || (funct==DIVU) || (funct==MULT) || (funct==MULTU) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR)))) diff --git a/rtl/mips_cpu_memory.v b/rtl/mips_cpu_memory.v index c8bb8fc..45aa576 100644 --- a/rtl/mips_cpu_memory.v +++ b/rtl/mips_cpu_memory.v @@ -31,36 +31,34 @@ module mips_cpu_memory( ); parameter RAM_INIT_FILE = ""; - reg [31:0] memory [4294967295:0]; // 2^32 memory locations of 32 bits size + reg [31:0] memory [0:7]; // 2^30 set as 8 for now for small testcases initial begin integer i; //Initialise to zero by default - for (i=0; i<4294967296; i++) begin + for (i=0; i<8; i++) begin memory[i]=0; end //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, 32'hBFC00000, 32'd0); + $display("RAM: Loading RAM contents from %s", RAM_INIT_FILE); + $readmemh(RAM_INIT_FILE, memory, 32'h4); //32'hBFC00000 equivalent for small memory as byte 16 + end + + //Display what's in memory for debugging + for (integer j = 0; j<$size(memory); j++) begin + $display("Byte %d, %h", j*4, memory[j]); end end //Combinatorial read path for data and instruction. - 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 - data_readdata = data_readdata; - instr_readdata = instr_address; - end - end + assign data_readdata = data_read ? {memory[data_address],memory[data_address+1],memory[data_address+2],memory[data_address+3]} : 16'hxxxx; + assign instr_readdata = memory[instr_address/4]; //Synchronous write path always_ff @(posedge clk) begin + $display("Instruction Read: %h", instr_readdata); //$display("RAM : INFO : data_read=%h, data_address = %h, mem=%h", data_read, data_address, memory[data_address]); if (!data_read & data_write) begin //cannot read and write to memory in the same cycle if (instr_address != data_address) begin //cannot modify the instruction being read @@ -70,3 +68,4 @@ module mips_cpu_memory( end endmodule + diff --git a/rtl/mips_cpu_regfile.v b/rtl/mips_cpu_regfile.v index 9247da9..bce55e1 100644 --- a/rtl/mips_cpu_regfile.v +++ b/rtl/mips_cpu_regfile.v @@ -15,12 +15,11 @@ reg[31:0] memory [31:0]; //32 register slots, 32-bits wide initial begin integer i; //Initialise to zero by default - for (i = 1; i < 32; i++) begin + for (i = 0; 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 @@ -29,7 +28,9 @@ always_comb begin end always_ff @(negedge clk) begin - if (regwrite) begin + if (writereg == 5'b00000) begin + // skip writing if rd is $0 + end else if (regwrite) begin case (opcode) 6'b100000: begin //lb, load byte case (readdata1[1:0]) diff --git a/test/test_mips_cpu_harvard.sh b/test/test_mips_cpu_harvard.sh index 20e8f96..63cae06 100644 --- a/test/test_mips_cpu_harvard.sh +++ b/test/test_mips_cpu_harvard.sh @@ -23,41 +23,30 @@ echo ${INSTR}; if [[ ${INSTR} == "No instruction specified: running all testcases" ]]; then # All Testcase Files - TESTCASES=$(ls ./inputs | grep ".hex.txt"); + TESTCASES=$(ls ./inputs | grep ".txt"); echo ${TESTCASES} for TESTCASE in ${TESTCASES} do - # Run Each Testcase File - echo ${TESTCASE} -#iverilog -g 2012 \ -# -s mips_cpu_harvard_tb \ -# -P mips_cpu_harvard_tb.RAM_INIT_FILE=\"inputs/"${TESTCASE}\" \ -# -o program/mips_cpu_harvard_tb_${INSTR} testbench/mips_cpu_harvard_tb.v \ -# ${SRC} + # Run Each Testcase File + echo ${TESTCASE} +/mnt/c/Windows/System32/cmd.exe /C \ +iverilog -Wall -g2012 \ + -s mips_cpu_harvard_tb \ + -P mips_cpu_harvard_tb.RAM_INIT_FILE=\"inputs/${TESTCASE}.txt\" \ + -o exec/mips_cpu_harvard_tb_${TESTCASE} testbench/mips_cpu_harvard_tb.v \ + ${SRC} +/mnt/c/Windows/System32/cmd.exe /C vvp ./exec/mips_cpu_harvard_tb_${TESTCASE}; done else - echo ${INSTR}; # Run Testcase File Of Specified Instruction -# 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}.txt\" \ -# -o program/mips_cpu_harvard_tb_${INSTR} testbench/mips_cpu_harvard_tb.v \ -# ${SRC} - -# Linux Iverilog -iverilog -g2012 \ + echo ${INSTR}; +/mnt/c/Windows/System32/cmd.exe /C \ +iverilog -Wall -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 \ + -o exec/mips_cpu_harvard_tb_${INSTR} testbench/mips_cpu_harvard_tb.v \ ${SRC} +/mnt/c/Windows/System32/cmd.exe /C vvp ./exec/mips_cpu_harvard_tb_${INSTR}; fi -#/mnt/c/Windows/System32/cmd.exe /C \ # need this to run verilog on windows -#iverilog -g 2012 \ -# -s mips_cpu_harvard_tb \ -# -P mips_cpu_harvard_tb.RAM_INIT_FILE=\"inputs/addiu.hex.txt\" \ -# -o program/mips_cpu_harvard_tb testbench/mips_cpu_harvard_tb.v test/mips_cpu_harvard.v \ -# test/mips_cpu_control.v test/mips_cpu_alu.v test/mips_cpu_memory.v test/mips_cpu_regfile.v test/mips_cpu_pc.v - diff --git a/testbench/mips_cpu_harvard_tb.v b/testbench/mips_cpu_harvard_tb.v index 1bae99d..fcb4499 100644 --- a/testbench/mips_cpu_harvard_tb.v +++ b/testbench/mips_cpu_harvard_tb.v @@ -1,14 +1,10 @@ module mips_cpu_harvard_tb; - timeunit 1ns / 10ps; - parameter RAM_INIT_FILE = "inputs/"; - parameter TIMEOUT_CYCLES = 10000; + parameter RAM_INIT_FILE = "inputs/addu.txt"; + parameter TIMEOUT_CYCLES = 100; - logic clk, clk_enable, reset, active; - logic[31:0] register_v0; - logic[31:0] instr_address, instr_readdata; - logic data_read, data_write; - logic[31:0] data_readdata, data_writedata, data_address; + logic clk, clk_enable, reset, active, data_read, data_write; + logic[31:0] register_v0, instr_address, instr_readdata, data_readdata, data_writedata, data_address; mips_cpu_memory #(RAM_INIT_FILE) ramInst( .clk(clk), @@ -50,24 +46,29 @@ module mips_cpu_harvard_tb; end initial begin + $display("Initial Reset 0"); reset <= 0; - + + + $display("Initial Reset 1"); @(posedge clk); reset <= 1; + $display("Initial Reset 0: Start Program"); @(posedge clk); reset <= 0; @(posedge clk); - assert(active==1) // Is this assert still valid? - else $display("TB : CPU did not set active=1 after reset."); + assert(active==1); + else $display("TB: CPU did not set active=1 after reset."); while (active) begin @(posedge clk); + $display("Register v0: %d", register_v0); end - $display("TB : finished; running=0"); - $display("%d",register_v0); + $display("TB: finished; active=0"); + $display("Output: %d", register_v0); $finish; end