diff --git a/HOW_TO_RUN.md b/HOW_TO_RUN.md new file mode 100644 index 0000000..9e1adfd --- /dev/null +++ b/HOW_TO_RUN.md @@ -0,0 +1,23 @@ +# How to Run Test Benches + +```shell +$ make run +``` + +## To run CPU tests + +```shell +$ make cpu +``` + +## To run submodule test benches + +```shell +$ make tests +``` + +## To clean directory + +```shell +$ make clean +``` diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0c951df --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +cpu: cpu_test_addN.t.v cpu_test_fib.t.v cpu_test_xor_sub_slt.t.v + iverilog -o cpu_test_addN.o cpu_test_addN.t.v + iverilog -o cpu_test_fib.o cpu_test_fib.t.v + iverilog -o cpu_test_xor_sub_slt.o cpu_test_xor_sub_slt.t.v + ./cpu_test_addN.o + ./cpu_test_fib.o + ./cpu_test_xor_sub_slt.o + +tests: alu.t.v basicbuildingblocks.t.v instructiondecoder.t.v lut.t.v memory.t.v regfile.t.v + iverilog -o alu.o alu.t.v + iverilog -o basicbuildingblocks.o basicbuildingblocks.t.v + iverilog -o instructiondecoder.o instructiondecoder.t.v + iverilog -o lut.o lut.t.v + iverilog -o memory.o memory.t.v + iverilog -o regfile.o regfile.t.v + ./alu.o + ./basicbuildingblocks.o + ./instructiondecoder.o + ./lut.o + ./memory.o + ./regfile.o + +clean: + rm *.o + rm *.vcd + +run: + make cpu + make tests + make clean diff --git a/_Report.pdf b/_Report.pdf new file mode 100644 index 0000000..efa4e7d Binary files /dev/null and b/_Report.pdf differ diff --git a/alu.t.v b/alu.t.v new file mode 100644 index 0000000..4ef4456 --- /dev/null +++ b/alu.t.v @@ -0,0 +1,246 @@ +//------------------------------------------------------------------------ +// Test Bench for ALU Module +//------------------------------------------------------------------------ + +`timescale 1 ns / 1 ps +`include "alu.v" + +module testALU(); + reg [31:0] operandA, operandB; + reg [2:0] command; + wire [31:0] result; + wire carryout, zero, overflow; + + ALU aluer (result, carryout, zero, overflow, operandA, operandB, command); + + initial begin + $display("--------------------------------------------------"); + $display("ALU tests starting..."); + + $display("Starting ADD tests..."); + // ADD test 1 + command=`ADD; operandA=32'h000A0000; operandB=32'h00000070; #5000 // carryout = 0 + if(result != 32'h000A0070) + $display("ADD test 1 - result: %h, expected: 000A0070", result); + if(carryout != 1'b0) + $display("ADD test 1 - carryout: %h, expected: 0", carryout); + if(zero != 1'b0) + $display("ADD test 1 - zero: %h, expected: 0", zero); + if(overflow != 1'b0) + $display("ADD test 1 - overflow: %h, expected: 0", overflow); + // ADD test 2 + command=`ADD; operandA=32'h7FFFFFFF; operandB=32'h7FFFFFFF; #5000 + if(result != 32'hFFFFFFFE) + $display("ADD test 2 - result: %h, expected: FFFFFFFE", result); + if(carryout != 1'b0) + $display("ADD test 2 - carryout: %h, expected: 0", carryout); + if(zero != 1'b0) + $display("ADD test 2 - zero: %h, expected: 0", zero); + if(overflow != 1'b1) + $display("ADD test 2 - overflow: %h, expected: 1", overflow); + // ADD test 3 + command=`ADD; operandA=32'h00000001; operandB=32'hFFFFFFFF; #5000 + if(result != 32'h00000000) + $display("ADD test 3 - result: %h, expected: 00000000", result); + if(carryout != 1'b1) + $display("ADD test 3 - carryout: %h, expected: 1", carryout); + if(zero != 1'b1) + $display("ADD test 3 - zero: %h, expected: 1", zero); + if(overflow != 1'b0) + $display("ADD test 3 - overflow: %h, expected: 0", overflow); + // ADD test 4 + command=`ADD; operandA=32'h80000000; operandB=32'h80000000; #5000 + if(result != 32'h00000000) + $display("ADD test 4 - result: %h, expected: 00000000", result); + if(carryout != 1'b1) + $display("ADD test 4 - carryout: %h, expected: 1", carryout); + if(zero != 1'b1) + $display("ADD test 4 - zero: %h, expected: 1", zero); + if(overflow != 1'b1) + $display("ADD test 4 - overflow: %h, expected: 1", overflow); + + $display("Starting SUB tests..."); + // SUB test 1 + command=`SUB; operandA=32'h000A0000; operandB=32'hFFFFFF90; #5000 + if(result != 32'h000A0070) + $display("SUB test 1 - result: %h, expected: 000A0070", result); + if(carryout != 1'b0) + $display("SUB test 1 - carryout: %h, expected: 0", carryout); + if(zero != 1'b0) + $display("SUB test 1 - zero: %h, expected: 0", zero); + if(overflow != 1'b0) + $display("SUB test 1 - overflow: %h, expected: 0", overflow); + // SUB test 2 + command=`SUB; operandA=32'h7FFFFFFF; operandB=32'h80000001; #5000 + if(result != 32'hFFFFFFFE) + $display("SUB test 2 - result: %h, expected: FFFFFFFE", result); + if(carryout != 1'b0) + $display("SUB test 2 - carryout: %h, expected: 0", carryout); + if(zero != 1'b0) + $display("SUB test 2 - zero: %h, expected: 0", zero); + if(overflow != 1'b1) + $display("SUB test 2 - overflow: %h, expected: 1", overflow); + // SUB test 3 + command=`SUB; operandA=32'h00000001; operandB=32'h00000001; #5000 + if(result != 32'h00000000) + $display("SUB test 3 - result: %h, expected: 00000000", result); + if(carryout != 1'b1) + $display("SUB test 3 - carryout: %h, expected: 1", carryout); + if(zero != 1'b1) + $display("SUB test 3 - zero: %h, expected: 1", zero); + if(overflow != 1'b0) + $display("SUB test 3 - overflow: %h, expected: 0", overflow); + //SUB test 4 + command=`SUB; operandA=32'h80000000; operandB=32'h70000000; #5000 + if(result != 32'h10000000) + $display("SUB test 4 - result: %h, expected: 10000000", result); + if(carryout != 1'b1) + $display("SUB test 4 - carryout: %h, expected: 1", carryout); + if(zero != 1'b0) + $display("SUB test 4 - zero: %h, expected: 0", zero); + if(overflow != 1'b1) + $display("SUB test 4 - overflow: %h, expected: 1", overflow); + + $display("Starting XOR tests..."); + // XOR test 1 + command=`Xor; operandA=32'h88888888; operandB=32'h11111111; #5000 + if(result != 32'h99999999) + $display("XOR test 1 - result: %h, expected: 99999999", result); + if(zero != 1'b0) + $display("XOR test 1 - zero: %h, expected: 0", zero); + // XOR test 2 + command=`Xor; operandA=32'hCCCCCCCC; operandB=32'hCCCCCCCC; #5000 + if(result != 32'h00000000) + $display("XOR test 2 - result: %h, expected: 00000000", result); + if(zero != 1'b1) + $display("XOR test 2 - zero: %h, expected: 1", zero); + // XOR test 3 + command=`Xor; operandA=32'hBBBBBBBB; operandB=32'h55555555; #5000 + if(result != 32'hEEEEEEEE) + $display("XOR test 3 - result: %h, expected: EEEEEEEE", result); + if(zero != 1'b0) + $display("XOR test 3 - zero: %h, expected: 0", zero); + + $display("Starting SLT tests..."); + // SLT test 1 + command=`SLT; operandA=32'h00000001; operandB=32'h05000000; #5000 //positive numbers + if(result != 32'h00000001) + $display("SLT test 1 - result: %h, expected: 00000001", result); + // SLT test a + command=`SLT; operandA=32'h7FFFFFFF; operandB=32'h80000001; #5000 + if(result != 32'h00000000) + $display("SLT test 2 - result: %h, expected: 00000000", result); + // SLT test b + command=`SLT; operandA=32'h00000001; operandB=32'h00000001; #5000 + if(result != 32'h00000000) + $display("SLT test 2 - result: %h, expected: 00000000", result); + // SLT test 2 + command=`SLT; operandA=32'h05000000; operandB=32'h00000001; #5000 + if(result != 32'h00000000) + $display("SLT test 2 - result: %h, expected: 00000000", result); + // SLT test 3 + command=`SLT; operandA=32'h80000000; operandB=32'hF0000000; #5000 //negative numbers + if(result != 32'h00000001) + $display("SLT test 3 - result: %h, expected: 00000001", result); + // SLT test 4 + command=`SLT; operandA=32'hF0000000; operandB=32'h80000000; #5000 + if(result != 32'h00000000) + $display("SLT test 4 - result: %h, expected: 00000000", result); + // SLT test 5 + command=`SLT; operandA=32'h80000000; operandB=32'h05000000; #5000 //positive and negative numbers + if(result != 32'h00000001) + $display("SLT test 5 - result: %h, expected: 00000001", result); + // SLT test 6 + command=`SLT; operandA=32'h05000000; operandB=32'h80000000; #5000 + if(result != 32'h00000000) + $display("SLT test 6 - result: %h, expected: 00000000", result); + // SLT test 7 + command=`SLT; operandA=32'h00000000; operandB=32'h00000000; #5000 //zeros + if(result != 32'h00000000) + $display("SLT test 7 - result: %h, expected: 00000000", result); + + $display("Starting AND tests..."); + // AND test 1 + command=`And; operandA=32'h88888888; operandB=32'h11111111; #5000 + if(result != 32'h00000000) + $display("AND test 1 - result: %h, expected: 00000000", result); + if(zero != 1'b1) + $display("AND test 1 - zero: %h, expected: 1", zero); + // AND test 2 + command=`And; operandA=32'hCCCCCCCC; operandB=32'hCCCCCCCC; #5000 + if(result != 32'hCCCCCCCC) + $display("AND test 2 - result: %h, expected: CCCCCCCC", result); + if(zero != 1'b0) + $display("AND test 2 - zero: %h, expected: 0", zero); + // AND test 3 + command=`And; operandA=32'hBBBBBBBB; operandB=32'h55555555; #5000 + if(result != 32'h11111111) + $display("AND test 3 - result: %h, expected: 11111111", result); + if(zero != 1'b0) + $display("AND test 3 - zero: %h, expected: 0", zero); + + $display("Starting NAND tests..."); + // NAND test 1 + command=`Nand; operandA=32'h88888888; operandB=32'h11111111; #5000 + if(result != 32'hFFFFFFFF) + $display("NAND test 1 - result: %h, expected: FFFFFFFF", result); + if(zero != 1'b0) + $display("NAND test 1 - zero: %h, expected: 0", zero); + // NAND test 2 + command=`Nand; operandA=32'hCCCCCCCC; operandB=32'hCCCCCCCC; #5000 + if(result != 32'h33333333) + $display("NAND test 2 - result: %h, expected: 33333333", result); + if(zero != 1'b0) + $display("NAND test 2 - zero: %h, expected: 0", zero); + // NAND test 3 + command=`Nand; operandA=32'hBBBBBBBB; operandB=32'h55555555; #5000 + if(result != 32'hEEEEEEEE) + $display("NAND test 3 - result: %h, expected: EEEEEEEE", result); + if(zero != 1'b0) + $display("NAND test 3 - zero: %h, expected: 0", zero); + + $display("Starting NOR tests..."); + // NOR test 1 + command=`Nor; operandA=32'h88888888; operandB=32'h11111111; #5000 + if(result != 32'h66666666) + $display("NOR test 1 - result: %h, expected: 66666666", result); + if(zero != 1'b0) + $display("NOR test 1 - zero: %h, expected: 0", zero); + // NOR test 2 + command=`Nor; operandA=32'hCCCCCCCC; operandB=32'hCCCCCCCC; #5000 + if(result != 32'h33333333) + $display("NOR test 2 - result: %h, expected: 33333333", result); + if(zero != 1'b0) + $display("NOR test 2 - zero: %h, expected: 0", zero); + // NOR test 3 + command=`Nor; operandA=32'hBBBBBBBB; operandB=32'h55555555; #5000 + if(result != 32'h00000000) + $display("NOR test 3 - result: %h, expected: 00000000", result); + if(zero != 1'b1) + $display("NOR test 3 - zero: %h, expected: 1", zero); + + $display("Starting OR tests..."); + // OR test 1 + command=`Or; operandA=32'h88888888; operandB=32'h11111111; #5000 + if(result != 32'h99999999) + $display("OR test 1 - result: %h, expected: 99999999", result); + if(zero != 1'b0) + $display("OR test 1 - zero: %h, expected: 0", zero); + // OR test 2 + command=`Or; operandA=32'hCCCCCCCC; operandB=32'hCCCCCCCC; #5000 + if(result != 32'hCCCCCCCC) + $display("OR test 2 - result: %h, expected: CCCCCCCC", result); + if(zero != 1'b0) + $display("OR test 2 - zero: %h, expected: 0", zero); + // OR test 3 + command=`Or; operandA=32'hBBBBBBBB; operandB=32'h55555555; #5000 + if(result != 32'hFFFFFFFF) + $display("OR test 3 - result: %h, expected: FFFFFFFF", result); + if(zero != 1'b0) + $display("OR test 3 - zero: %h, expected: 0", zero); + + $display("ALU tests done!"); + $display("--------------------------------------------------"); + $finish(); + end +endmodule diff --git a/alu.v b/alu.v new file mode 100644 index 0000000..1e00c89 --- /dev/null +++ b/alu.v @@ -0,0 +1,97 @@ +//------------------------------------------------------------------------ +// ALU Module +//------------------------------------------------------------------------ + +`define ADD 3'd0 +`define SUB 3'd1 +`define Xor 3'd2 +`define SLT 3'd3 +`define And 3'd4 +`define Nand 3'd5 +`define Nor 3'd6 +`define Or 3'd7 +`include "alu_function.v" +`define NOR32 nor //32 input NOR + +module ALU +( +output[31:0] result, +output carryout, +output zero, +output overflow, +input[31:0] operandA, +input[31:0] operandB, +input[2:0] command +); + //declare wires + wire[31:0] out0, out1, out2, out3, out4; + wire cout0, cout1, cout2, cout3, cout4; + wire over0, over1, over2, over3, over4; + wire invert; + wire[2:0] muxindex; + wire[32:0] carryin0; + + //use LUT to get variable assignments for muxindex and invert depending on the input command + ALUcontrolLUT lut(.muxindex(muxindex), .invert(invert), .ALUcommand(command)); + //first carryin of add-subtract module is identical to the invert signal + assign carryin0[0] = invert; + + //bit slice approach, generate 32 of each module for full capability + genvar i; + generate for (i = 0; i < 32; i = i + 1) begin + AddSubN adder(.sum(out0[i]), .carryout(carryin0[i+1]), .a(operandA[i]), .b(operandB[i]), .carryin(carryin0[i]), .subtract(invert)); + + XORmod xorer(.out(out1[i]), .carryout(cout1), .overflow(over1), .a(operandA[i]), .b(operandB[i])); + + NANDmod nander(.out(out3[i]), .carryout(cout3), .overflow(over3), .a(operandA[i]), .b(operandB[i]), .invert(invert)); + + NORmod norer(.out(out4[i]), .carryout(cout4), .overflow(over4), .a(operandA[i]), .b(operandB[i]), .invert(invert)); + end + endgenerate + + SLTmod slter (.slt(out2), .carryout(cout2), .overflow(over2), .a(operandA), .b(operandB)); + + //set carryout for adder, equivalent to the "carryin" of the 33rd bit + assign cout0 = carryin0[32]; + //calculate overflow for adder; overflow if final carryout is not equal to carryin of most significant bit + `XOR OVERFLOW(over0, cout0, carryin0[31]); + + //mux between generated outputs depending on muxindex given by ALUcommand + genvar n; + generate for (n = 0; n < 32; n = n + 1) begin + structuralMultiplexer5 resultmux (.out(result[n]), .command(muxindex), .in0(out0[n]), .in1(out1[n]), .in2(out2[n]), .in3(out3[n]), .in4(out4[n])); + end + endgenerate + + //mux between carryouts + structuralMultiplexer5 coutmux (.out(carryout), .command(muxindex), .in0(cout0), .in1(cout1), .in2(cout2), .in3(cout3), .in4(cout4)); + //mux between overflows + structuralMultiplexer5 overmux (.out(overflow), .command(muxindex), .in0(over0), .in1(over1), .in2(over2), .in3(over3), .in4(over4)); + + //if all bits of the result are zero, the output zero should return zero + `NOR32 norgate(zero, result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], + result[11], result[12], result[13], result[14], result[15], result[16], result[17], result[18], result[19], result[20], result[21], result[22], + result[23], result[24], result[25], result[26], result[27], result[28], result[29], result[30], result[31]); + +endmodule + + +module ALUcontrolLUT +( +output reg[2:0] muxindex, +output reg invert, +input[2:0] ALUcommand +); + always @(ALUcommand) begin + case (ALUcommand) + `ADD: begin muxindex = 0; invert=0; end + `SUB: begin muxindex = 0; invert=1; end + `Xor: begin muxindex = 1; invert=0; end + `SLT: begin muxindex = 2; invert=0; end + `Nand: begin muxindex = 3; invert=0; end + `And: begin muxindex = 3; invert=1; end + `Nor: begin muxindex = 4; invert=0; end + `Or: begin muxindex = 4; invert=1; end + endcase + end +endmodule diff --git a/alu_function.v b/alu_function.v new file mode 100644 index 0000000..539d2b5 --- /dev/null +++ b/alu_function.v @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------ +// Supporting Files for ALU Module +//------------------------------------------------------------------------ + +`define AND and +`define AND4 and +`define OR or +`define XOR xor +`define NOT not +`define NAND nand +`define NOR nor +`define OR5 or + +// Mux for 5 inputs for bit slices +// AND gates set to 0 anything not called with 5 bit input +module structuralMultiplexer5 +( + output out, + input[2:0] command, + input in0, in1, in2, in3, in4 +); + wire[2:0] ncommand; + wire m0,m1,m2,m3,m4; + + `NOT invA(ncommand[0], command[0]); + `NOT invB(ncommand[1], command[1]); + `NOT invC(ncommand[2], command[2]); + + `AND4 andgateA(m0,in0,ncommand[0],ncommand[1], ncommand[2]); + `AND4 andgateB(m1,in1,command[0],ncommand[1], ncommand[2]); + `AND4 andgateC(m2,in2,ncommand[0],command[1], ncommand[2]); + `AND4 andgateD(m3,in3,command[0],command[1], ncommand[2]); + `AND4 andgateE(m4,in4,ncommand[0],ncommand[1], command[2]); + + `OR5 orgate(out,m0,m1,m2,m3,m4); +endmodule + +// Implementation of full adder for bitslices. Called by AddSubN +module structuralFullAdder +( + output sum, carryout, + input a, b, + input carryin +); + wire axorb, ab, caxorb; + + xor AXORB(axorb, a, b); + `AND AANDB(ab, a, b); + xor SUM(sum, carryin, axorb); + `AND CAXORB(caxorb, carryin, axorb); + `OR CARRYOUT(carryout, caxorb, ab); +endmodule + +//Add/Sub for bitslices. +module AddSubN +( + output sum, // 2's complement sum of a and b + output carryout, // Carry out of the summation of a and b + output overflow, // True if the calculation resulted in an overflow + input a, // First operand in 2's complement format + input b, // Second operand in 2's complement format + input carryin, + input subtract +); + wire atest, btest; + wire bsub; + // allows for subtraction + `XOR subtest(bsub, b, subtract); + + structuralFullAdder adder (sum, carryout, a, bsub, carryin); +endmodule + + +// SLT for bitslices. Uses AddSubN as a subtractor to determine relative magnitude of a and b +module SLTmod #( parameter n = 31 ) +( + output[n:0] slt, + output carryout, + output overflow, + input[n:0] a, b +); + wire[n:0] sub; + wire carryout0, over; + wire subtract; + + wire[32:0] carryin0; + + assign subtract = 1'b1; + assign carryin0[0] = subtract; + + genvar i; + generate for (i = 0; i < 32; i = i + 1) begin + AddSubN adder(.sum(sub[i]), .carryout(carryin0[i+1]), .a(a[i]), .b(b[i]), .carryin(carryin0[i]), .subtract(subtract)); + end + endgenerate + + //calculate overflow for adder; overflow if final carryout is not equal to carryin of most significant bit + //used only to calculate SLT, not actual overflow output + `XOR OVERFLOW(over, carryin0[32], carryin0[31]); + // a larger than b if final bit of subraction if overflow != msb of subtraction + // in case where both are 0, both inputs were equal so SLT = 0 anyway + `XOR SLTXOR(slt[0], sub[n], over); + + assign slt[31:1] = 0; + assign carryout = 0; + assign overflow = 0; +endmodule + + +// XOR for bitslices. Carryout and overflow do not apply +module XORmod +( + output out, + output carryout, + output overflow, + input a, b +); + `XOR xorgate(out, a, b); + assign carryout = 0; + assign overflow = 0; +endmodule + + +// NAND for bislices. +module NANDmod +( + output out, + output carryout, + output overflow, + input a, b, + input invert // if invert = 1 functions as an AND module +); + wire interim_out; + `NAND nandgate(interim_out, a, b); + `XOR xorgate(out, interim_out, invert); // Will invert NAND output if meant to function as AND module + assign carryout = 0; + assign overflow = 0; +endmodule + + +// NOR for bitslices. +module NORmod +( + output out, + output carryout, + output overflow, + input a, b, + input invert // if invert = 1 functions as an OR module +); + wire interim_out; + `NOR norgate(interim_out, a, b); + `XOR xorgate(out, interim_out, invert); // Will invert NAND output if meant to function as OR module + assign carryout = 0; + assign overflow = 0; +endmodule diff --git a/asmtest/LaurenSamVivien/addNIntegers.asm b/asmtest/LaurenSamVivien/addNIntegers.asm new file mode 100644 index 0000000..a8eb637 --- /dev/null +++ b/asmtest/LaurenSamVivien/addNIntegers.asm @@ -0,0 +1,15 @@ +addi $a0, $zero, 10 #n +addi $t0, $zero, 0 #num +addi $t1, $zero, 0 #sum + + +add $a0, $a0, 1 +IF: +beq $t0, $a0, ENDIF +add $t1, $t1, $t0 +add $t0, $t0, 1 +j IF + +ENDIF: +add $v0, $t1, 0 + diff --git a/asmtest/LaurenSamVivien/fibfunc.asm b/asmtest/LaurenSamVivien/fibfunc.asm new file mode 100644 index 0000000..3b3a011 --- /dev/null +++ b/asmtest/LaurenSamVivien/fibfunc.asm @@ -0,0 +1,100 @@ +# Function call example: recursive Fibonacci + +main: +# Set up arguments for call to fib_test +addi $a0, $zero, 4 # arg0 = 4 +addi $a1, $zero, 10 # arg1 = 10 +jal fib_test + +# Jump to "exit", rather than falling through to subroutines +j program_end + +#------------------------------------------------------------------------------ +# Fibonacci test function. Equivalent C code: +# int fib_test(arg0, arg1) { +# return Fibonacci(arg0) + Fibonacci(arg1); +# } +# By MIPS calling convention, expects arguments in +# registers a0 and a1, and returns result in register v0. +fib_test: +# We will use s0 and s1 registers in this function, plus the ra register +# to return at the end. Save them to stack in case caller was using them. +addi $sp, $sp, -12 # Allocate three words on stack at once for three pushes +sw $ra, 8($sp) # Push ra on the stack (will be overwritten by Fib function calls) +sw $s0, 4($sp) # Push s0 onto stack +sw $s1, 0($sp) # Push s1 onto stack + +# a1 may be overwritten by called functions, so save it to s1 (saved temporary), +# which called function won't change, so we can use it later for the second fib call +add $s1, $zero, $a1 + +# Call Fib(arg0), save result in s0 +# arg0 is already in register a0, placed there by caller of fib_test +jal fib # Call fib(4), returns in register v0 +add $s0, $zero, $v0 # Move result to s0 so we can call fib again without overwriting + +# Call Fib(arg1), save result in s1 +add $a0, $zero, $s1 # Move original arg1 into register a0 for function call +jal fib +add $s1, $zero, $v0 # Move result to s1 + +# Add Fib(arg0) and Fib(arg1) into v0 (return value for fib_test) +add $v0, $s0, $s1 + +# Restore original values to s0 and s1 registers from stack before returning +lw $s1, 0($sp) # Pop s1 from stack +lw $s0, 4($sp) # Pop s0 from stack +lw $ra, 8($sp) # Pop ra from the stack so we can return to caller +addi $sp, $sp, 12 # Adjust stack pointer to reflect pops + +jr $ra # Return to caller + +#------------------------------------------------------------------------------ +# Recursive Fibonacci function. Equivalent C code: +# +# int Fibonacci(int n) { +# if (n == 0) return 0; // Base case +# if (n == 1) return 1; // Base case +# int fib_1 = Fibonacci(n - 1); +# int fib_2 = Fibonacci(n - 2); +# return fib_1+fib_2; +# } +fib: +# Test base cases. If we're in a base case, return directly (no need to use stack) +bne $a0, 0, testone +add $v0, $zero, $zero # a0 == 0 -> return 0 +jr $ra +testone: +bne $a0, 1, fib_body +add $v0, $zero, $a0 # a0 == 1 -> return 1 +jr $ra + +fib_body: +# Create stack frame for fib: push ra and s0 +addi $sp, $sp, -8 # Allocate two words on stack at once for two pushes +sw $ra, 4($sp) # Push ra on the stack (will be overwritten by recursive function calls) +sw $s0, 0($sp) # Push s0 onto stack + +# Call Fib(n-1), save result in s0 +add $s0, $zero, $a0 # Save a0 argument (n) in register s0 +addi $a0, $a0, -1 # a0 = n-1 +jal fib +add $a0, $s0, -2 # a0 = n-2 +add $s0, $zero, $v0 # s0 = Fib(n-1) + +# Call Fib(n-2), compute final result +jal fib +add $v0, $v0, $s0 # v0 = Fib(n-2) + Fib(n-1) + +# Restore registers and pop stack frame +lw $ra, 4($sp) +lw $s0, 0($sp) +addi $sp, $sp, 8 + +jr $ra # Return to caller + + +#------------------------------------------------------------------------------ +# Jump loop to end execution, so we don't fall through to .data section +program_end: +j program_end \ No newline at end of file diff --git a/asmtest/LaurenSamVivien/test1.asm b/asmtest/LaurenSamVivien/test1.asm new file mode 100644 index 0000000..4526e3e --- /dev/null +++ b/asmtest/LaurenSamVivien/test1.asm @@ -0,0 +1,20 @@ +main: +addi $t1, $zero, 3 +addi $t2, $zero, 7 + +addi $t3, $zero, -5 +addi $t4, $zero, 10 + +addi $t5, $zero, -14 +addi $t6, $zero, -9 + +slt $t0, $t1, $t2 +bne $t3, $t4, branchtaken +slt $t0, $t3, $t4 +j end +branchtaken: +slt $t0, $t5, $t6 +j end + +end: +j end diff --git a/asmtest/LaurenSamVivien/testingREADME.txt b/asmtest/LaurenSamVivien/testingREADME.txt new file mode 100644 index 0000000..b76bc32 --- /dev/null +++ b/asmtest/LaurenSamVivien/testingREADME.txt @@ -0,0 +1,32 @@ +There are 4 assembly files in this folder. +--------------------------------------- +fibfunc.asm +This file tests the fibonacci sequence. +This tests for ADD, ADDI, BNE, LW, SW, J, JAL, JR functionalities +The final answer can be found in $v0$ = 32'h3a +--------------------------------------- + +addNintegers.asm +Tests for adding together 10 consecutive integers. +This tests the BEQ, ADD, ADDI, J functionalities of the CPU +The final answer can be found in $t1$ = 32'h37 +--------------------------------------- + +xor_sub_slt.asm +Tests for XOR SUB SLT sequence. +This tests the ADDI, XORI, SUB, SLT, BNE, J functionality +outputs are found in $t0$ through $t6$ +Where: +$t0$ = 32h'1 +$t1$ = 32h'1 +$t2$ = 32h'7 +$t3$ = 32h'fffffffb +$t4$ = 32h'3 +$t5$ = 32h'fffffff2 +$t6$ = 32h'fffffff7 +-------------------------------------- + +test1.asm +This stores 6 variables into t1 through t6 by using addi. +Then it will SLT the first 2 variables and store it in t0. +Then it bne the next variables. Since these are not equal it should skip the next line and go to SLT the last pair of variables. Then it jumps to end and stays in the end loop until the program is stopped. diff --git a/asmtest/LaurenSamVivien/xor_sub_slt.asm b/asmtest/LaurenSamVivien/xor_sub_slt.asm new file mode 100644 index 0000000..f7c2378 --- /dev/null +++ b/asmtest/LaurenSamVivien/xor_sub_slt.asm @@ -0,0 +1,22 @@ +main: +addi $t1, $zero, 3 +addi $t2, $zero, 7 + +addi $t3, $zero, -5 +addi $t4, $zero, 10 + +addi $t5, $zero, -14 +addi $t6, $zero, -9 + +xori $t1, $t1, 2 +sub $t4, $t4, $t2, +slt $t0, $t1, $t2 +bne $t3, $t4, branchtaken +slt $t0, $t3, $t4 +j end +branchtaken: +slt $t0, $t5, $t6 +j end + +end: +j end \ No newline at end of file diff --git a/asmtest/xor_sub_slt.asm b/asmtest/xor_sub_slt.asm new file mode 100644 index 0000000..f7c2378 --- /dev/null +++ b/asmtest/xor_sub_slt.asm @@ -0,0 +1,22 @@ +main: +addi $t1, $zero, 3 +addi $t2, $zero, 7 + +addi $t3, $zero, -5 +addi $t4, $zero, 10 + +addi $t5, $zero, -14 +addi $t6, $zero, -9 + +xori $t1, $t1, 2 +sub $t4, $t4, $t2, +slt $t0, $t1, $t2 +bne $t3, $t4, branchtaken +slt $t0, $t3, $t4 +j end +branchtaken: +slt $t0, $t5, $t6 +j end + +end: +j end \ No newline at end of file diff --git a/basicbuildingblocks.t.v b/basicbuildingblocks.t.v new file mode 100644 index 0000000..889034a --- /dev/null +++ b/basicbuildingblocks.t.v @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------ +// Test bench for DFF (PC Counter), MUX2 +//------------------------------------------------------------------------ + +`timescale 1 ns / 1 ps +`include "basicbuildingblocks.v" + +module testDFF(); + + reg clk; + reg enable; + reg [31:0] d; + wire [31:0] q; + + dff #(32) dut(.trigger(clk), + .enable(enable), + .d(d), + .q(q)); + + // Generate clock (50MHz) + initial clk=0; + always #10 clk=!clk; // 50MHz Clock + + initial begin + $display("--------------------------------------------------"); + $display("Testing DFF..."); + enable=1'b1; d=32'hAAAAAAAA; #1000 + if(q != 32'hAAAAAAAA) + $display("ERROR Expected: AAAAAAAA, Got: %h", q); + enable=1'b0; d=32'hBBBBBBBB; #1000 + if(q != 32'hAAAAAAAA) + $display("ERROR Expected: AAAAAAAA, Got: %h", q); + enable=1'b1; d=32'hCCCCCCCC; #1000 + if(q != 32'hCCCCCCCC) + $display("ERROR Expected: CCCCCCCC, Got: %h", q); + enable=1'b0; d=32'hDDDDDDDD; #1000 + if(q != 32'hCCCCCCCC) + $display("ERROR Expected: CCCCCCCC, Got: %h", q); + $display("Done with DFF!"); + $display("--------------------------------------------------"); + $finish(); + end +endmodule + +module testMUX2(); + + reg [31:0] in0; + reg [31:0] in1; + reg sel; + wire [31:0] out; + + mux2 #(32) dut(.in0(in0), + .in1(in1), + .sel(sel), + .out(out)); + + initial begin + $display("Testing MUX2..."); + in0=32'hAAAAAAAA; in1=32'hBBBBBBBB; sel=1'b0; #1000 + if(out != 32'hAAAAAAAA) + $display("ERROR Expected: AAAAAAAA, Got: %h", out); + in0=32'hAAAAAAAA; in1=32'hBBBBBBBB; sel=1'b1; #1000 + if(out != 32'hBBBBBBBB) + $display("ERROR Expected: BBBBBBBB, Got: %h", out); + $display("Done with MUX2!"); + end +endmodule diff --git a/basicbuildingblocks.v b/basicbuildingblocks.v new file mode 100644 index 0000000..b280362 --- /dev/null +++ b/basicbuildingblocks.v @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// Basic building block modules (DFF and MUX2) +//----------------------------------------------------------------------------- + +// D flip-flop with parameterized bit width (default: 1-bit) +// Parameters in Verilog: http://www.asic-world.com/verilog/para_modules1.html +module dff #( parameter W = 32 ) +( + input trigger, + input enable, + input [W-1:0] d, + output [W-1:0] q +); + + reg [W-1:0] mem; + + initial begin + mem <= {W{1'b0}}; + end + + always @(posedge trigger) begin + if(enable) begin + mem <= d; + end + end + + assign q = mem; +endmodule + +// Two-input MUX with parameterized bit width (default: 1-bit) +module mux2 #( parameter W = 32 ) +( + input[W-1:0] in0, + input[W-1:0] in1, + input sel, + output[W-1:0] out +); + // Conditional operator - http://www.verilog.renerta.com/source/vrg00010.htm + assign out = (sel) ? in1 : in0; +endmodule diff --git a/cpu.v b/cpu.v new file mode 100644 index 0000000..84608bc --- /dev/null +++ b/cpu.v @@ -0,0 +1,146 @@ +//------------------------------------------------------------------------ +// CPU Compilation +//------------------------------------------------------------------------ + +`include "regfile.v" +// `include "datamemory.v" +`include "memory.v" +`include "basicbuildingblocks.v" +`include "alu.v" +`include "instructiondecoder.v" +`include "lut.v" + +module cpu_all +( + input clk +); + + // control wires + wire RegDst, RegWr, MemWr, MemToReg, ALUsrc, IsJump, IsJAL, IsJR, IsBranch; + wire [2:0] ALUctrl; + wire [31:0] datain; + // decoder wires + wire [5:0] OP, FUNCT; + wire [4:0] RT, RS, RD, SHAMT; + wire [15:0] IMM16; + wire [25:0] TA; + + wire aluadd4carryout, aluadd4zero, aluadd4overflow, aluaddcarryout, aluaddzero, aluaddoverflow, carryout; + + wire [31:0] isjrout, PCplus4, shift2, aluaddsum, isbranchout, isjumpout, mem2regout, alusrcout, INSTRUCT; + wire zero, overflow; + wire [31:0] regDa, regDb, regDin, SE, result; + wire [4:0] Rint, regAw; + wire [31:0] PCcount, jumpaddr, branchaddr; + wire [31:0] memout, instruction; + + memory mem(.clk(clk), + .WrEn(MemWr), + .DataAddr(result), + .DataIn(regDb), + .DataOut(memout), + .InstrAddr(PCcount), + .Instruction(instruction)); + + instructiondecoder decoder(.OP(OP), + .RT(RT), + .RS(RS), + .RD(RD), + .IMM16(IMM16), + .TA(TA), + .SHAMT(SHAMT), + .FUNCT(FUNCT), + .instruction(instruction)); + + instructionLUT lut(.OP(OP), + .FUNCT(FUNCT), + .zero(zero), + .overflow(overflow), + .RegDst(RegDst), + .RegWr(RegWr), + .MemWr(MemWr), + .MemToReg(MemToReg), + .ALUctrl(ALUctrl), + .ALUsrc(ALUsrc), + .IsJump(IsJump), + .IsJAL(IsJAL), + .IsJR(IsJR), + .IsBranch(IsBranch)); + + dff #(32) pccounter(.trigger(clk), + .enable(1'b1), + .d(isjrout), + .q(PCcount)); + + assign PCplus4 = PCcount + 32'h00000004; + + assign jumpaddr = {PCplus4[31:28], TA, 2'b00}; + assign branchaddr = {{14{IMM16[15]}}, IMM16, 2'b00}; + + mux2 #(32) muxshift2(.in0(jumpaddr), + .in1(branchaddr), + .sel(IsBranch), + .out(shift2)); + + assign aluaddsum = PCplus4 + shift2; + + mux2 #(32) muxisbranch(.in0(PCplus4), + .in1(aluaddsum), + .sel(IsBranch), + .out(isbranchout)); + + mux2 #(32) muxisjump(.in0(isbranchout), + .in1(shift2), + .sel(IsJump), + .out(isjumpout)); + + mux2 #(32) muxisjr(.in0(isjumpout), + .in1(regDa), + .sel(IsJR), + .out(isjrout)); + + mux2 #(5) muxregdst(.in0(RT), + .in1(RD), + .sel(RegDst), + .out(Rint)); + + mux2 #(5) muxixjalaw(.in0(Rint), + .in1(5'd31), + .sel(IsJAL), + .out(regAw)); + + mux2 #(32) muxisjaldin(.in0(mem2regout), + .in1(PCplus4), + .sel(IsJAL), + .out(regDin)); + + regfile register(.ReadData1(regDa), + .ReadData2(regDb), + .WriteData(regDin), + .ReadRegister1(RS), + .ReadRegister2(RT), + .WriteRegister(regAw), + .RegWrite(RegWr), + .Clk(clk)); + + ALU alumain(.carryout(carryout), + .zero(zero), + .overflow(overflow), + .result(result), + .operandA(regDa), + .operandB(alusrcout), + .command(ALUctrl)); + + assign SE = {{16{IMM16[15]}}, IMM16}; + + mux2 #(32) muxalusrc(.in0(regDb), + .in1(SE), + .sel(ALUsrc), + .out(alusrcout)); + + mux2 #(32) muxmem2reg(.in0(result), + .in1(memout), + .sel(MemToReg), + .out(mem2regout)); + +endmodule diff --git a/cpu_test_addN.t.v b/cpu_test_addN.t.v new file mode 100644 index 0000000..b8cf996 --- /dev/null +++ b/cpu_test_addN.t.v @@ -0,0 +1,49 @@ +`include "cpu.v" + +//------------------------------------------------------------------------ +// Test bench for adding together 10 consecutive integers. +// The final answer can be found in $t1$ +// This test bench tests the BEQ, ADD, ADDI, J functionalities of the CPU +//------------------------------------------------------------------------ + +module cpu_test_addN (); + + reg clk; + reg reset; + + // Clock generation + initial clk=0; + always #10 clk = !clk; + + // Instantiate CPU + cpu_all cpu(.clk(clk)); + + initial begin + + $readmemh("./dat/addN.dat", cpu.mem.mem,0); // load assembly instructions into memory + // Dump waveforms to file + $dumpfile("cputest.vcd"); + $dumpvars(); + + // Assert reset pulse + reset = 0; #10; + reset = 1; #10; + reset = 0; #10; + #1000 + if(cpu.register.RegisterOutput[2] != 32'h37 || cpu.register.RegisterOutput[4] != 32'hb || cpu.register.RegisterOutput[8] != 32'hb || cpu.register.RegisterOutput[9] != 32'h37) begin + $display("----------------------------------------"); + $display("FAILED ADD_N TEST. $v0$: Expected: %h, ACTUAL: %h", 32'h37, cpu.register.RegisterOutput[2]); + $display("FAILED ADD_N TEST. $a0$: Expected: %h, ACTUAL: %h", 32'hb, cpu.register.RegisterOutput[4]); + $display("FAILED ADD_N TEST. $t0$: Expected: %h, ACTUAL: %h", 32'h3b, cpu.register.RegisterOutput[8]); + $display("FAILED ADD_N TEST. $t1$: Expected: %h, ACTUAL: %h", 32'h37, cpu.register.RegisterOutput[9]); + $display("----------------------------------------"); + end + else begin + $display("----------------------------------------"); + $display("PASSED ADD_N TEST"); + $display("----------------------------------------"); + end + #2000 $finish(); + end + + endmodule diff --git a/cpu_test_fib.t.v b/cpu_test_fib.t.v new file mode 100644 index 0000000..3ba8954 --- /dev/null +++ b/cpu_test_fib.t.v @@ -0,0 +1,48 @@ +`include "cpu.v" + +//------------------------------------------------------------------------ +// Test bench for Fibbanocci sequence +// This tests for ADD, ADDI, BNE, LW, SW, J, JAL, JR functionalities +// The final answer can be found in $v0$ +//------------------------------------------------------------------------ + +module cpu_test_fib (); + + reg clk; + reg reset; + + // Clock generation + initial clk=0; + always #10 clk = !clk; + + // Instantiate CPU + cpu_all cpu(.clk(clk)); + + initial begin + + $readmemh("./dat/fib_func.dat", cpu.mem.mem,0); + + $dumpfile("cpu_fib.vcd"); + $dumpvars(); + + // Assert reset pulse + reset = 0; #10; + reset = 1; #10; + reset = 0; #10; + + #1000000 + if(cpu.register.RegisterOutput[2] != 32'h3a) begin + $display("----------------------------------------"); + $display("FAILED FIB TEST"); + $display("$v0: Expected: %h, ACTUAL: %h", 32'h3a, cpu.register.RegisterOutput[2]); + $display("----------------------------------------"); + end + else begin + $display("----------------------------------------"); + $display("PASSED FIB TEST"); + $display("----------------------------------------"); + end + #2000 $finish(); + end + + endmodule diff --git a/cpu_test_xor_sub_slt.t.v b/cpu_test_xor_sub_slt.t.v new file mode 100644 index 0000000..d7e8dbc --- /dev/null +++ b/cpu_test_xor_sub_slt.t.v @@ -0,0 +1,56 @@ +`include "cpu.v" + +//------------------------------------------------------------------------ +// Test bench for XOR SUB SLT sequence. +// instructions were generated from xor_sub_slt.asm +// This test bench test the ADDI, XORI, SUB, SLT, BNE, J functionality +// outputs are found at verious registers including +//------------------------------------------------------------------------ + +module cpu_test_fib (); + + reg clk; + reg reset; + + // Clock generation + initial clk=0; + always #10 clk = !clk; + + // Instantiate CPU + cpu_all cpu(.clk(clk)); + + initial begin + + $readmemh("./dat/xor_sub_slt.dat", cpu.mem.mem,0); + + $dumpfile("cpu_xor.vcd"); + $dumpvars(); + + // Assert reset pulse + reset = 0; #10; + reset = 1; #10; + reset = 0; #10; + + #1000000 + if(cpu.register.RegisterOutput[8] != 32'h1 || cpu.register.RegisterOutput[9] != 32'h1 || cpu.register.RegisterOutput[10] != 32'h7 || cpu.register.RegisterOutput[11] != 32'hfffffffb || cpu.register.RegisterOutput[12] != 32'h3 || cpu.register.RegisterOutput[13] != 32'hfffffff2 || cpu.register.RegisterOutput[14] != 32'hfffffff7 ) begin// || cpu.register.RegisterOutput[4] != 32'hb || cpu.register.RegisterOutput[8] != 32'hb || cpu.register.RegisterOutput[9] != 32'h37) + $display("----------------------------------------"); + $display("FAILED XOR SUB SLT TEST"); + $display("$t0$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[8]); + $display("$t1$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[9]); + $display("$t2$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[10]); + $display("$t3$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[11]); + $display("$t4$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[12]); + $display("$t5$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[13]); + $display("$t6$: Expected: %h, ACTUAL: %h", 32'h1, cpu.register.RegisterOutput[14]); + $display("----------------------------------------"); + + end + else begin + $display("----------------------------------------"); + $display("PASSED XOR, SUB, SLT TEST"); + $display("----------------------------------------"); + end + #2000 $finish(); + end + + endmodule diff --git a/cputesting.gtkw b/cputesting.gtkw new file mode 100644 index 0000000..57ae6a1 --- /dev/null +++ b/cputesting.gtkw @@ -0,0 +1,117 @@ +[*] +[*] GTKWave Analyzer v3.3.94 (w)1999-2018 BSI +[*] Fri Nov 2 03:27:40 2018 +[*] +[dumpfile] "/home/comparch/Documents/CompArch/Lab3/cpu_fib.vcd" +[dumpfile_mtime] "Fri Nov 2 03:10:24 2018" +[dumpfile_size] 8885083 +[savefile] "/home/comparch/Documents/CompArch/Lab3/cputesting.gtkw" +[timestart] 1002035 +[size] 1512 948 +[pos] -1 -1 +*-3.813424 1175 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] cpu_test_fib. +[treeopen] cpu_test_fib.cpu.register. +[treeopen] cpu_test_fib.cpu.register.genblk1[16]. +[treeopen] cpu_test_fib.cpu.register.genblk1[17]. +[treeopen] cpu_test_fib.cpu.register.genblk1[1]. +[treeopen] cpu_test_fib.cpu.register.genblk1[29]. +[treeopen] cpu_test_fib.cpu.register.genblk1[2]. +[treeopen] cpu_test_fib.cpu.register.genblk1[31]. +[treeopen] cpu_test_fib.cpu.register.genblk1[4]. +[treeopen] cpu_test_fib.cpu.register.genblk1[5]. +[sst_width] 225 +[signals_width] 166 +[sst_expanded] 1 +[sst_vpaned_height] 281 +@28 +cpu_test_fib.cpu.register.genblk1[1].register.clk +@22 +cpu_test_fib.cpu.PCcount[31:0] +cpu_test_fib.cpu.mem.Instruction[31:0] +@2022 +^1 /home/comparch/Documents/CompArch/in-class/day14/filters/mips-opcodes.filter +cpu_test_fib.cpu.OP[5:0] +^2 /home/comparch/Documents/CompArch/in-class/day14/filters/mips-funct.filter +cpu_test_fib.cpu.FUNCT[5:0] +^3 /home/comparch/Documents/CompArch/in-class/day14/filters/mips-regs.filter +cpu_test_fib.cpu.RD[4:0] +^3 /home/comparch/Documents/CompArch/in-class/day14/filters/mips-regs.filter +cpu_test_fib.cpu.RS[4:0] +^3 /home/comparch/Documents/CompArch/in-class/day14/filters/mips-regs.filter +cpu_test_fib.cpu.RT[4:0] +@22 +cpu_test_fib.cpu.IMM16[15:0] +cpu_test_fib.cpu.TA[25:0] +@28 +cpu_test_fib.cpu.IsJAL +cpu_test_fib.cpu.IsJR +@200 +-REG[1] $at$ +@22 +cpu_test_fib.cpu.register.genblk1[1].register.q[31:0] +@200 +-REG[2] $v0$ +@22 +cpu_test_fib.cpu.register.genblk1[2].register.q[31:0] +@200 +-REG[4] $a0$ +@c00022 +cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +@28 +(0)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(1)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(2)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(3)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(4)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(5)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(6)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(7)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(8)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(9)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(10)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(11)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(12)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(13)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(14)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(15)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(16)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(17)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(18)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(19)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(20)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(21)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(22)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(23)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(24)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(25)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(26)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(27)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(28)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(29)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(30)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +(31)cpu_test_fib.cpu.register.genblk1[4].register.q[31:0] +@1401200 +-group_end +@200 +-REG[5] $a1$ +@22 +cpu_test_fib.cpu.register.genblk1[5].register.q[31:0] +@200 +-REG[16] $s0$ +@22 +cpu_test_fib.cpu.register.genblk1[16].register.q[31:0] +@200 +-REG[17] $s1$ +@22 +cpu_test_fib.cpu.register.genblk1[17].register.q[31:0] +@200 +-REG[29] $sp$ +@22 +cpu_test_fib.cpu.register.genblk1[29].register.q[31:0] +@200 +-REG[31] $ra$ +@22 +cpu_test_fib.cpu.register.genblk1[31].register.q[31:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/dat/addN.dat b/dat/addN.dat new file mode 100644 index 0000000..87b7f90 --- /dev/null +++ b/dat/addN.dat @@ -0,0 +1,9 @@ +2004000a +20080000 +20090000 +20840001 +11040003 +01284820 +21080001 +08000004 +21220000 diff --git a/dat/fib_func.dat b/dat/fib_func.dat new file mode 100644 index 0000000..2122ed0 --- /dev/null +++ b/dat/fib_func.dat @@ -0,0 +1,43 @@ +20040004 +2005000a +0c000004 +0800002a +23bdfff4 +afbf0008 +afb00004 +afb10000 +00058820 +0c000014 +00028020 +00112020 +0c000014 +00028820 +02111020 +8fb10000 +8fb00004 +8fbf0008 +23bd000c +03e00008 +20010000 +14240002 +00001020 +03e00008 +20010001 +14240002 +00041020 +03e00008 +23bdfff8 +afbf0004 +afb00000 +00048020 +2084ffff +0c000014 +2204fffe +00028020 +0c000014 +00501020 +8fbf0004 +8fb00000 +23bd0008 +03e00008 +0800002a diff --git a/dat/mem.dat b/dat/mem.dat new file mode 100644 index 0000000..3b5db68 --- /dev/null +++ b/dat/mem.dat @@ -0,0 +1,1024 @@ +1000_0001 +1000_000F +0000_0000 +1000_0001 +1000_0000 +0000_0000 +0000_0000 +0000_0001 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 +0000_0000 diff --git a/dat/xor_sub_slt.dat b/dat/xor_sub_slt.dat new file mode 100644 index 0000000..58f0d6e --- /dev/null +++ b/dat/xor_sub_slt.dat @@ -0,0 +1,15 @@ +20090003 +200a0007 +200bfffb +200c000a +200dfff2 +200efff7 +39290002 +018a6022 +012a402a +156c0002 +016c402a +0800000e +01ae402a +0800000e +0800000e diff --git a/instructiondecoder.t.v b/instructiondecoder.t.v new file mode 100644 index 0000000..29b8da0 --- /dev/null +++ b/instructiondecoder.t.v @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------ +// Test Bench for Instruction Decoder +//------------------------------------------------------------------------ + +`include "instructiondecoder.v" + +module instructiontest(); + wire [5:0] OP, FUNCT; + wire [4:0] RT, RS, RD, SHAMT; + wire [15:0] IMM16; + wire [25:0] TA; + reg [31:0] instruction; + + instructiondecoder dut(.OP(OP), + .RT(RT), + .RS(RS), + .RD(RD), + .IMM16(IMM16), + .TA(TA), + .SHAMT(SHAMT), + .FUNCT(FUNCT), + .instruction(instruction)); + + initial begin + $display("--------------------------------------------------"); + $display("Instruction decoder tests starting..."); + + // J-type instruction + instruction = 32'h0c000016; #1000 + + if (OP == 6'b000011 && RT == 5'b00000 && RS == 5'b00000 && RD == 5'b00000 && IMM16 == 16'b0000000000010110 && + TA == 26'b00000000000000000000010110 && SHAMT == 5'b00000 && FUNCT == 6'b010110) begin + $display("Test 1 Passed!"); + end + else begin + $display("Test 1 Failed :("); + $display("OP: %b, Expected: 000011", OP); + $display("RT: %b, Expected: 00000", RT); + $display("RS: %b, Expected: 00000", RS); + $display("RD: %b, Expected: 00000", RD); + $display("IMM16: %b, Expected: 0000000000010110", IMM16); + $display("TA: %b, Expected: 00000000000000000000010110", TA); + $display("SHAMT: %b, Expected: 00000", SHAMT); + $display("FUNCT: %b, Expected: 010110", FUNCT); + end + + // I-type instruction + instruction = 32'h2004000a; #1000 + + if (OP == 6'b001000 && RT == 5'b00100 && RS == 5'b00000 && RD == 5'b00000 && IMM16 == 16'b0000000000001010 && + TA == 26'b00000001000000000000001010 && SHAMT == 5'b00000 && FUNCT == 6'b001010) begin + $display("Test 2 Passed!"); + end + else begin + $display("Test 2 Failed :("); + $display("OP: %b, Expected: 001000", OP); + $display("RT: %b, Expected: 00100", RT); + $display("RS: %b, Expected: 00000", RS); + $display("RD: %b, Expected: 00000", RD); + $display("IMM16: %b, Expected: 0000000000001010", IMM16); + $display("TA: %b, Expected: 00000001000000000000001010", TA); + $display("SHAMT: %b, Expected: 00000", SHAMT); + $display("FUNCT: %b, Expected: 001010", FUNCT); + end + + // R-type instruction + instruction = 32'h02111020; #1000 + + if (OP == 6'b000000 && RT == 5'b10001 && RS == 5'b10000 && RD == 5'b00010 && IMM16 == 16'b0001000000100000 && + TA == 26'b10000100010001000000100000 && SHAMT == 5'b00000 && FUNCT == 6'b100000) begin + $display("Test 3 Passed!"); + end + else begin + $display("Test 3 Failed :("); + $display("OP: %b, Expected: 000000", OP); + $display("RT: %b, Expected: 10001", RT); + $display("RS: %b, Expected: 10000", RS); + $display("RD: %b, Expected: 00010", RD); + $display("IMM16: %b, Expected: 0001000000100000", IMM16); + $display("TA: %b, Expected: 10000100010001000000100000", TA); + $display("SHAMT: %b, Expected: 00000", SHAMT); + $display("FUNCT: %b, Expected: 100000", FUNCT); + end + + $display("Instruction decoder tests done!"); + $display("--------------------------------------------------"); + end +endmodule diff --git a/instructiondecoder.v b/instructiondecoder.v new file mode 100644 index 0000000..029e8ee --- /dev/null +++ b/instructiondecoder.v @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------ +// Instruction Decoder +//------------------------------------------------------------------------ + +module instructiondecoder +( + output [5:0] OP, // 31:26 bits of all types [operation] + output [4:0] RT, // 20:16 bits of I-type & R-type + output [4:0] RS, // 25:21 bits of I-type & R-type + output [4:0] RD, // 15:11 bits of R-type + output [15:0] IMM16, // 15:0 bits of I-type [16-bit immediate] + output [25:0] TA, // 25:0 bit of J-type [target address] + output [4:0] SHAMT, // 10:6 bits of R-type [shift amount] + output [5:0] FUNCT, // 5:0 bits of R-type [function] + input [31:0] instruction // 32 bits of instruction from instruction memory +); + + assign OP = instruction[31:26]; + assign RT = instruction[20:16]; + assign RS = instruction[25:21]; + assign RD = instruction[15:11]; + assign IMM16 = instruction[15:0]; + assign TA = instruction[25:0]; + assign SHAMT = instruction[10:6]; + assign FUNCT = instruction[5:0]; + +endmodule diff --git a/lut.t.v b/lut.t.v new file mode 100644 index 0000000..6f12513 --- /dev/null +++ b/lut.t.v @@ -0,0 +1,331 @@ +//------------------------------------------------------------------------ +// Test Bench for Behavioral Instruction Look Up Table +//------------------------------------------------------------------------ +`timescale 1 ns / 1 ps +`include "lut.v" + +module testlut(); + + reg [5:0] OP, FUNCT; + reg zero, overflow; + wire RegDst, RegWr, MemWr, MemToReg, ALUsrc, IsJump, IsJAL, IsJR, IsBranch; + wire [2:0] ALUctrl; + + instructionLUT lut(.OP(OP), + .FUNCT(FUNCT), + .zero(zero), + .overflow(overflow), + .RegDst(RegDst), + .RegWr(RegWr), + .MemWr(MemWr), + .MemToReg(MemToReg), + .ALUctrl(ALUctrl), + .ALUsrc(ALUsrc), + .IsJump(IsJump), + .IsJAL(IsJAL), + .IsJR(IsJR), + .IsBranch(IsBranch)); + + initial begin + $display("--------------------------------------------------"); + $display("Instruction LUT tests starting..."); + + // Test 1: Load Word + $display("Testing LW..."); + OP=6'b100011; FUNCT='bx; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with LW RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with LW RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with LW MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b1) + $display("error with LW MemToReg; Expected: 1, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with LW ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b1) + $display("error with LW ALUsrc; Expected: 1, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with LW IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with LW IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with LW IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with LW IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 2: Store Word + $display("Testing SW..."); + OP=6'b101011; FUNCT='bx; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with SW RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b0) + $display("error with SW RegWr; Expected: 0, Got: %d", RegWr); + if(MemWr != 1'b1) + $display("error with SW MemWr; Expected: 1, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with SW MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with SW ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b1) + $display("error with SW ALUsrc; Expected: 1, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with SW IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with SW IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with SW IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with SW IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 3: Jump + $display("Testing J..."); + OP=6'b000010; FUNCT='bx; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with J RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b0) + $display("error with J RegWr; Expected: 0, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with J MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with J MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with J ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with J ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b1) + $display("error with J IsJump; Expected: 1, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with J IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with J IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with J IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 4: Jump Register + $display("Testing JR..."); + OP=6'b000000; FUNCT=6'b001000; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with JR RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b0) + $display("error with JR RegWr; Expected: 0, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with JR MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with JR MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with JR ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with JR ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with JR IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with JR IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b1) + $display("error with JR IsJR; Expected: 1, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with JR IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 5: Jump and Link + $display("Testing JAL..."); + OP=6'b000011; FUNCT='bx; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with JAL RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with JAL RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with JAL MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with JAL MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with JAL ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with JAL ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b1) + $display("error with JAL IsJump; Expected: 1, Got: %d", IsJump); + if(IsJAL != 1'b1) + $display("error with JAL IsJAL; Expected: 1, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with JAL IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with JAL IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 6: Branch on Equal + $display("Testing BEQ..."); + OP=6'b000100; FUNCT='bx; zero=1'b1; overflow=1'b0; #1000 + if(RegDst != 1'b0) + $display("error with BEQ RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b0) + $display("error with BEQ RegWr; Expected: 0, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with BEQ MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with BEQ MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b001) + $display("error with BEQ ALUctrl; Expected: 001, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with BEQ ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with BEQ IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with BEQ IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with BEQ IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b1) + $display("error with BEQ IsBranch true; Expected: 1, Got: %d", IsBranch); + // zero != 1 || overflow != 0 + OP=6'b000100; FUNCT='bx; zero=1'b0; overflow=1'b0; #1000 + if(IsBranch != 1'b0) + $display("error with BEQ IsBranch false; Expected: 0, Got: %d", IsBranch); + + // Test 7: Branch on Not Equal + $display("Testing BNE..."); + OP=6'b000101; FUNCT='bx; zero=1'b1; overflow=1'b0; #1000 + if(RegDst != 1'b0) + $display("error with BNE RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b0) + $display("error with BNE RegWr; Expected: 0, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with BNE MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with BNE MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b001) + $display("error with BNE ALUctrl; Expected: 001, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with BNE ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with BNE IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with BNE IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with BNE IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with BNE IsBranch false; Expected: 0, Got: %d", IsBranch); + OP=6'b000101; FUNCT='bx; zero=1'b0; overflow=1'b0; #1000 + if(IsBranch != 1'b1) + $display("error with BNE IsBranch true; Expected: 1, Got: %d", IsBranch); + + // Test 8: Exclusive OR with Immediate + $display("Testing XORI..."); + OP=6'b001110; FUNCT='bx; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with XORI RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with XORI RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with XORI MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with XORI MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b010) + $display("error with XORI ALUctrl; Expected: 010, Got: %d", ALUctrl); + if(ALUsrc != 1'b1) + $display("error with XORI ALUsrc; Expected: 1, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with XORI IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with XORI IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with XORI IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with XORI IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 9: Add with Immediate + $display("Testing ADDI..."); + OP=6'b001000; FUNCT='bx; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b0) + $display("error with ADDI RegDst; Expected: 0, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with ADDI RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with ADDI MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with ADDI MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with ADDI ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b1) + $display("error with ADDI ALUsrc; Expected: 1, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with ADDI IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with ADDI IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with ADDI IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with ADDI IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 10: Add + $display("Testing ADD..."); + OP=6'b000000; FUNCT=6'b100000; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b1) + $display("error with ADD RegDst; Expected: 1, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with ADD RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with ADD MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with ADD MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b000) + $display("error with ADD ALUctrl; Expected: 000, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with ADD ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with ADD IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with ADD IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with ADD IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with ADD IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 11: Subtract + $display("Testing SUB..."); + OP=6'b000000; FUNCT=6'b100010; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b1) + $display("error with SUB RegDst; Expected: 1, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with SUB RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with SUB MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with SUB MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b001) + $display("error with SUB ALUctrl; Expected: 001, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with SUB ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with SUB IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with SUB IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with SUB IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with SUB IsBranch; Expected: 0, Got: %d", IsBranch); + + // Test 12: Set Less Than + $display("Testing SLT..."); + OP=6'b000000; FUNCT=6'b101010; zero='bx; overflow='bx; #1000 + if(RegDst != 1'b1) + $display("error with SLT RegDst; Expected: 1, Got: %d", RegDst); + if(RegWr != 1'b1) + $display("error with SLT RegWr; Expected: 1, Got: %d", RegWr); + if(MemWr != 1'b0) + $display("error with SLT MemWr; Expected: 0, Got: %d", MemWr); + if(MemToReg != 1'b0) + $display("error with SLT MemToReg; Expected: 0, Got: %d", MemToReg); + if(ALUctrl != 3'b011) + $display("error with SLT ALUctrl; Expected: 011, Got: %d", ALUctrl); + if(ALUsrc != 1'b0) + $display("error with SLT ALUsrc; Expected: 0, Got: %d", ALUsrc); + if(IsJump != 1'b0) + $display("error with SLT IsJump; Expected: 0, Got: %d", IsJump); + if(IsJAL != 1'b0) + $display("error with SLT IsJAL; Expected: 0, Got: %d", IsJAL); + if(IsJR != 1'b0) + $display("error with SLT IsJR; Expected: 0, Got: %d", IsJR); + if(IsBranch != 1'b0) + $display("error with SLT IsBranch; Expected: 0, Got: %d", IsBranch); + + $display("Instruction LUT tests done!!"); + $display("--------------------------------------------------"); + end +endmodule diff --git a/lut.v b/lut.v new file mode 100644 index 0000000..17c08e5 --- /dev/null +++ b/lut.v @@ -0,0 +1,201 @@ +//------------------------------------------------------------------------ +// Behavioral Instruction Look Up Table +//------------------------------------------------------------------------ + +`define opLW 6'b100011 +`define opSW 6'b101011 +`define opJ 6'b000010 +`define opJR 6'b001000 //FUNCT, OP = 6'b000000 +`define opJAL 6'b000011 +`define opBEQ 6'b000100 +`define opBNE 6'b000101 +`define opXORI 6'b001110 +`define opADDI 6'b001000 +`define opADD 6'b100000 //FUNCT, OP = 6'b000000 +`define opSUB 6'b100010 //FUNCT, OP = 6'b000000 +`define opSLT 6'b101010 //FUNCT, OP = 6'b000000 +`define Rtype 6'b000000 + +module instructionLUT +( + input [5:0] OP, + input [5:0] FUNCT, + input zero, + input overflow, + output reg RegDst, + output reg RegWr, + output reg MemWr, + output reg MemToReg, + output reg [2:0] ALUctrl, + output reg ALUsrc, + output reg IsJump, + output reg IsJAL, + output reg IsJR, + output reg IsBranch +); + + always @(OP or FUNCT or zero or overflow) begin + case(OP) + `opLW: begin + RegDst = 0; + RegWr = 1; + MemWr = 0; + MemToReg = 1; + ALUctrl = 3'b000; + ALUsrc = 1; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `opSW: begin + RegDst = 0; + RegWr = 0; + MemWr = 1; + MemToReg = 0; + ALUctrl = 3'b000; + ALUsrc = 1; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `opJ: begin + RegDst = 0; + RegWr = 0; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b000; + ALUsrc = 0; + IsJump = 1; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `opJAL: begin + RegDst = 0; + RegWr = 1; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b000; + ALUsrc = 0; + IsJump = 1; + IsJAL = 1; + IsJR = 0; + IsBranch = 0; + end + `opBEQ: begin + RegDst = 0; + RegWr = 0; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b001; + ALUsrc = 0; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + if ((zero == 1) && (overflow == 0)) + IsBranch = 1; + else + IsBranch = 0; + end + `opBNE: begin + RegDst = 0; + RegWr = 0; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b001; + ALUsrc = 0; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + if ((zero == 1) && (overflow == 0)) + IsBranch = 0; + else + IsBranch = 1; + end + `opXORI: begin + RegDst = 0; + RegWr = 1; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b010; + ALUsrc = 1; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `opADDI: begin + RegDst = 0; + RegWr = 1; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b000; + ALUsrc = 1; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `Rtype: begin + case(FUNCT) + `opJR: begin + RegDst = 0; + RegWr = 0; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b000; + ALUsrc = 0; + IsJump = 0; + IsJAL = 0; + IsJR = 1; + IsBranch = 0; + end + `opADD: begin + RegDst = 1; + RegWr = 1; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b000; + ALUsrc = 0; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `opSUB: begin + RegDst = 1; + RegWr = 1; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b001; + ALUsrc = 0; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end + `opSLT: begin + RegDst = 1; + RegWr = 1; + MemWr = 0; + MemToReg = 0; + ALUctrl = 3'b011; + ALUsrc = 0; + IsJump = 0; + IsJAL = 0; + IsJR = 0; + IsBranch = 0; + end // opSLT + default: begin + $display("ERROR: Invalid operation or function code."); + end + endcase // case(FUNCT) + end // Rtype + default: begin + $display("ERROR: Invalid operation or function code."); + end + endcase // case(OP) + end // always +endmodule diff --git a/memory.t.v b/memory.t.v new file mode 100644 index 0000000..967d95f --- /dev/null +++ b/memory.t.v @@ -0,0 +1,82 @@ +//------------------------------------------------------------------------ +// Test Bench for Memory Module +//------------------------------------------------------------------------ + +`timescale 1 ns / 1 ps +`include "memory.v" + +module testMemory(); + + reg clk; + reg WrEn; + reg[31:0] DataAddr; + reg[31:0] DataIn; + wire[31:0] DataOut; + reg[31:0] InstrAddr; + wire[31:0] Instruction; + + memory mem(.clk(clk), + .WrEn(WrEn), + .DataAddr(DataAddr), + .DataIn(DataIn), + .DataOut(DataOut), + .InstrAddr(InstrAddr), + .Instruction(Instruction)); + + initial clk=0; + always #10 clk = !clk; + + initial begin + $display("--------------------------------------------------"); + $display("Memory tests starting..."); + + $readmemh("./dat/addN.dat", mem.mem, 0); + + // Instruction memory and data memory output tests + InstrAddr = 32'h0; DataAddr = 32'h0; #1000 + if (Instruction == 32'h2004000a && DataOut == 32'h2004000a) begin + $display("Test 1 Passed"); + end + else begin + $display("Test 1 Failed %h", DataOut); + end + + InstrAddr = 32'h10; DataAddr = 32'h10; #1000 + if (Instruction == 32'h11040003 && DataOut == 32'h11040003) begin + $display("Test 2 Passed"); + end + else begin + $display("Test 2 Failed"); + end + + InstrAddr = 32'h14; DataAddr = 32'h14; #1000 + if (Instruction == 32'h01284820 && DataOut == 32'h01284820) begin + $display("Test 3 Passed"); + end + else begin + $display("Test 3 Failed"); + end + + // Data memory input and output tests + WrEn = 1'b1; DataAddr = 32'hFFFFFFFC; DataIn = 32'h12345678; #1000 + if (DataOut == 32'h12345678) begin + $display("Test 4 Passed"); + end + else begin + $display("Test 4 Failed"); + end + + WrEn = 1'b0; DataAddr = 32'hFFFFFFFC; DataIn = 32'habcdef90; #1000 + if (DataOut == 32'h12345678) begin + $display("Test 5 Passed"); + end + else begin + $display("Test 5 Failed"); + end + + $display("Memory tests done!"); + $display("--------------------------------------------------"); + $finish; + end + +endmodule diff --git a/memory.v b/memory.v new file mode 100644 index 0000000..de58f74 --- /dev/null +++ b/memory.v @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------ +// Memory Module (Data and Instruction) +//------------------------------------------------------------------------ + +module memory +( + input clk, + input WrEn, // Data memory write enable + input[31:0] DataAddr, // Data memory address + input[31:0] DataIn, // Data memory input + output[31:0] DataOut, // Data memory output + input[31:0] InstrAddr, // Instruction memory address + output[31:0] Instruction // Instruction memory output +); + + wire [11:0] DataIndex; // Data memory index + wire [11:0] InstrIndex; // Instruction memory index + reg [31:0] mem[4095:0]; // 16kb Memory + + assign InstrIndex = {InstrAddr[13:2]}; + assign DataIndex = {DataAddr[13:2]}; + + always @(posedge clk) begin + if (WrEn) begin + mem[DataIndex] <= DataIn; + end + end + + assign Instruction = mem[InstrIndex]; + assign DataOut = mem[DataIndex]; + +endmodule diff --git a/regfile.t.v b/regfile.t.v new file mode 100644 index 0000000..ef0c0b5 --- /dev/null +++ b/regfile.t.v @@ -0,0 +1,223 @@ +//------------------------------------------------------------------------------ +// Test harness validates hw4testbench by connecting it to various functional +// or broken register files, and verifying that it correctly identifies each +//------------------------------------------------------------------------------ + +`include "regfile.v" + +module hw4testbenchharness(); + + wire[31:0] ReadData1; // Data from first register read + wire[31:0] ReadData2; // Data from second register read + wire[31:0] WriteData; // Data to write to register + wire[4:0] ReadRegister1; // Address of first register to read + wire[4:0] ReadRegister2; // Address of second register to read + wire[4:0] WriteRegister; // Address of register to write + wire RegWrite; // Enable writing of register when High + wire Clk; // Clock (Positive Edge Triggered) + + reg begintest; // Set High to begin testing register file + wire endtest; // Set High to signal test completion + wire dutpassed; // Indicates whether register file passed tests + + // Instantiate the register file being tested. DUT = Device Under Test + regfile DUT + ( + .ReadData1(ReadData1), + .ReadData2(ReadData2), + .WriteData(WriteData), + .ReadRegister1(ReadRegister1), + .ReadRegister2(ReadRegister2), + .WriteRegister(WriteRegister), + .RegWrite(RegWrite), + .Clk(Clk) + ); + + // Instantiate test bench to test the DUT + hw4testbench tester + ( + .begintest(begintest), + .endtest(endtest), + .dutpassed(dutpassed), + .ReadData1(ReadData1), + .ReadData2(ReadData2), + .WriteData(WriteData), + .ReadRegister1(ReadRegister1), + .ReadRegister2(ReadRegister2), + .WriteRegister(WriteRegister), + .RegWrite(RegWrite), + .Clk(Clk) + ); + + // Test harness asserts 'begintest' for 1000 time steps, starting at time 10 + initial begin + begintest=0; + #10; + begintest=1; + #1000; + end + + // Display test results ('dutpassed' signal) once 'endtest' goes high + always @(posedge endtest) begin + $display("DUT passed?: %b", dutpassed); + $display("Register file tests done!"); + end + +endmodule + + +//------------------------------------------------------------------------------ +// Your HW4 test bench +// Generates signals to drive register file and passes them back up one +// layer to the test harness. This lets us plug in various working and +// broken register files to test. +// +// Once 'begintest' is asserted, begin testing the register file. +// Once your test is conclusive, set 'dutpassed' appropriately and then +// raise 'endtest'. +//------------------------------------------------------------------------------ + +module hw4testbench +( +// Test bench driver signal connections +input begintest, // Triggers start of testing +output reg endtest, // Raise once test completes +output reg dutpassed, // Signal test result + +// Register File DUT connections +input[31:0] ReadData1, +input[31:0] ReadData2, +output reg[31:0] WriteData, +output reg[4:0] ReadRegister1, +output reg[4:0] ReadRegister2, +output reg[4:0] WriteRegister, +output reg RegWrite, +output reg Clk +); + + // Initialize register driver signals + initial begin + WriteData=32'd0; + ReadRegister1=5'd0; + ReadRegister2=5'd0; + WriteRegister=5'd0; + RegWrite=0; + Clk=0; + end + + integer i; + + // Once 'begintest' is asserted, start running test cases + always @(posedge begintest) begin + endtest = 0; + dutpassed = 1; + #10 + + $display("--------------------------------------------------"); + $display("Register file tests starting..."); + + // Test Case 1: + // Write '42' to register 2, verify with Read Ports 1 and 2 + WriteRegister = 5'd2; + WriteData = 32'd42; + RegWrite = 1; + ReadRegister1 = 5'd2; + ReadRegister2 = 5'd2; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 !== 42) || (ReadData2 !== 42)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1 Failed"); + end + + // Test Case 2: + // Write '15' to register 2, verify with Read Ports 1 and 2 + WriteRegister = 5'd2; + WriteData = 32'd15; + RegWrite = 1; + ReadRegister1 = 5'd2; + ReadRegister2 = 5'd2; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 !== 15) || (ReadData2 !== 15)) begin + dutpassed = 0; + $display("Test Case 2 Failed"); + end + + // Test Case 3: + // Tests: Write Enable is broken / ignored – Register is always written to. + // Set RegWrite to '0' and "write" '37' to register 5 + // Verify with Read Ports 1 and 2 that register 5 is empty + WriteRegister = 5'd5; + WriteData = 32'd37; + RegWrite = 0; + ReadRegister1 = 5'd5; + ReadRegister2 = 5'd5; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 !== 0) || (ReadData2 !== 0)) begin + dutpassed = 0; + $display("Test Case 3 Failed"); + end + + // Test Case 4: + // Tests: Decoder is broken – All registers are written to. + // Write '26' to register 2 + // Verify that register 2 is '26' and register 31 is empty + WriteRegister = 5'd2; + WriteData = 32'd26; + RegWrite = 1; + ReadRegister1 = 5'd2; + ReadRegister2 = 5'd31; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 !== 26) || (ReadData2 !== 0)) begin + dutpassed = 0; + $display("Test Case 4 Failed"); + end + + // Test Case 5: + // Tests: Register Zero is actually a register instead of the constant value zero. + // Write '89' to register 0 + // Verify with Read Ports 1 and 2 that register 0 is still '0' + WriteRegister = 5'd0; + WriteData = 32'd89; + RegWrite = 1; + ReadRegister1 = 5'd0; + ReadRegister2 = 5'd0; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 !== 0) || (ReadData2 !== 0)) begin + dutpassed = 0; + $display("Test Case 5 Failed"); + end + + // Test Case 6: + // Tests: Port 2 is broken and always reads register 14 (for example). + // Write 'i' to register i, where i is an integer from 0 to 31 + // Verify with Read Ports 1 and 2 that register i is 'i' + for (i = 32'd0; i < 32'd32; i = i + 32'd1) begin + WriteRegister = i; + WriteData = i; + RegWrite = 1; + #5 Clk=1; #5 Clk=0; + end + + for (i = 32'd0; i < 32'd32; i = i + 32'd1) begin + ReadRegister1 = i; + ReadRegister2 = i; + #5 Clk=1; #5 Clk=0; + if((ReadData1 !== i) || (ReadData2 !== i)) begin + dutpassed = 0; + $display("Test Case 6 Failed"); + end + end + + // All done! Wait a moment and signal test completion. + #5 + endtest = 1; + +end + +endmodule diff --git a/regfile.v b/regfile.v new file mode 100644 index 0000000..fbed5a5 --- /dev/null +++ b/regfile.v @@ -0,0 +1,148 @@ +//------------------------------------------------------------------------------ +// MIPS register file +// width: 32 bits +// depth: 32 words (reg[0] is static zero register) +// 2 asynchronous read ports +// 1 synchronous, positive edge triggered write port +//------------------------------------------------------------------------------ + +module regfile +( + output [31:0] ReadData1, // Contents of first register read + output [31:0] ReadData2, // Contents of second register read + input [31:0] WriteData, // Contents to write to register + input [4:0] ReadRegister1, // Address of first register to read + input [4:0] ReadRegister2, // Address of second register to read + input [4:0] WriteRegister, // Address of register to write + input RegWrite, // Enable writing of register when High + input Clk // Clock (Positive Edge Triggered) +); + + wire [31:0] DecoderOutput; + wire [31:0] RegisterOutput[31:0]; + + decoder1to32 decoder(DecoderOutput, RegWrite, WriteRegister); + register32zero register0(RegisterOutput[0], RegWrite, Clk); + + genvar i; + generate for (i = 1; i < 32; i = i + 1) begin + register32 register(RegisterOutput[i], WriteData, DecoderOutput[i], Clk); + end + endgenerate + + mux32to1by32 multiplexer1(ReadData1, ReadRegister1, RegisterOutput[0], RegisterOutput[1], RegisterOutput[2], RegisterOutput[3], + RegisterOutput[4], RegisterOutput[5], RegisterOutput[6], RegisterOutput[7], RegisterOutput[8], RegisterOutput[9], + RegisterOutput[10], RegisterOutput[11], RegisterOutput[12], RegisterOutput[13], RegisterOutput[14], RegisterOutput[15], + RegisterOutput[16], RegisterOutput[17], RegisterOutput[18], RegisterOutput[19], RegisterOutput[20], RegisterOutput[21], + RegisterOutput[22], RegisterOutput[23], RegisterOutput[24], RegisterOutput[25], RegisterOutput[26], RegisterOutput[27], + RegisterOutput[28], RegisterOutput[29], RegisterOutput[30], RegisterOutput[31]); + mux32to1by32 multiplexer2(ReadData2, ReadRegister2, RegisterOutput[0], RegisterOutput[1], RegisterOutput[2], RegisterOutput[3], + RegisterOutput[4], RegisterOutput[5], RegisterOutput[6], RegisterOutput[7], RegisterOutput[8], RegisterOutput[9], + RegisterOutput[10], RegisterOutput[11], RegisterOutput[12], RegisterOutput[13], RegisterOutput[14], RegisterOutput[15], + RegisterOutput[16], RegisterOutput[17], RegisterOutput[18], RegisterOutput[19], RegisterOutput[20], RegisterOutput[21], + RegisterOutput[22], RegisterOutput[23], RegisterOutput[24], RegisterOutput[25], RegisterOutput[26], RegisterOutput[27], + RegisterOutput[28], RegisterOutput[29], RegisterOutput[30], RegisterOutput[31]); + +endmodule + +//------------------------------------------------------------------------------ +// Support Modules +//------------------------------------------------------------------------------ +module register32 #(parameter W = 32) +( + output reg [W-1:0] q, + input [W-1:0] d, + input wrenable, + input clk +); + + initial q = {W{1'b0}}; + + always @(posedge clk) begin + if(wrenable) begin + q <= d; + end + end + +endmodule + + +module register32zero #(parameter W = 32) +( + output reg [W-1:0] q, + input wrenable, + input clk +); + + initial q = {W{1'b0}}; + + always @(posedge clk) begin + if(wrenable) begin + q <= 32'd0;; + end + end + +endmodule + + +// 32 bit decoder with enable signal +// enable=0: all output bits are 0 +// enable=1: out[address] is 1, all other outputs are 0 +module decoder1to32 +( + output [31:0] out, + input enable, + input [4:0] address +); + + assign out = enable<