diff --git a/README.md b/README.md index ddf0003..e9d4c40 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,20 @@ # CompArch HW b0100: Register File # +Kaitlyn Keil + +## Instructions to Run ## + +Run code with: + +``` +>>>iverilog -o regfile.t.v +>>>./ +``` + +The terminal will display whether all the tests passed (```DUT Passed: 1```) or failed, along with the test case that failed. + +Written work is in the pdf [hw4written.pdf](https://github.com/KaitlynKeil/HW4/blob/master/hw4written.pdf). + **Due:** Monday, October 16 This homework is intended to introduce behavioral Verilog and practice test bench design. You will create your first memory, a register file, which will be reused in your CPU design. diff --git a/hw4written.pdf b/hw4written.pdf new file mode 100644 index 0000000..8d114b0 Binary files /dev/null and b/hw4written.pdf differ diff --git a/mux.v b/mux.v new file mode 100644 index 0000000..3a05730 --- /dev/null +++ b/mux.v @@ -0,0 +1,54 @@ +module mux32to1by1 +( + output out, + input[4:0] address, + input[31:0] inputs +); + assign outputofmux = inputs[address]; +endmodule + +module mux32to1by32 +( +output[31:0] out, +input[4:0] address, +input[31:0] input0, input1, input2, input3, input4, input5, input6, input7, input8, input9, input10, input11, input12, input13, input14, input15, input16, input17, input18, input19, input20, input21, input22, input23, input24, input25, input26, input27, input28, input29, input30, input31 +); + + wire[31:0] mux[31:0]; // Create a 2D array of wires + + // Connect the sources of the array + assign mux[0] = input0; + assign mux[1] = input1; + assign mux[2] = input2; + assign mux[3] = input3; + assign mux[4] = input4; + assign mux[5] = input5; + assign mux[6] = input6; + assign mux[7] = input7; + assign mux[8] = input8; + assign mux[9] = input9; + assign mux[10] = input10; + assign mux[11] = input11; + assign mux[12] = input12; + assign mux[13] = input13; + assign mux[14] = input14; + assign mux[15] = input15; + assign mux[16] = input16; + assign mux[17] = input17; + assign mux[18] = input18; + assign mux[19] = input19; + assign mux[20] = input20; + assign mux[21] = input21; + assign mux[22] = input22; + assign mux[23] = input23; + assign mux[24] = input24; + assign mux[25] = input25; + assign mux[26] = input26; + assign mux[27] = input27; + assign mux[28] = input28; + assign mux[29] = input29; + assign mux[30] = input30; + assign mux[31] = input31; + + assign out = mux[address]; // Connect the output of the array +endmodule \ No newline at end of file diff --git a/regfile.t.v b/regfile.t.v index f13815a..7a0d931 100644 --- a/regfile.t.v +++ b/regfile.t.v @@ -3,6 +3,8 @@ // 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 @@ -109,7 +111,6 @@ output reg Clk // Test Case 1: // Write '42' to register 2, verify with Read Ports 1 and 2 - // (Passes because example register file is hardwired to return 42) WriteRegister = 5'd2; WriteData = 32'd42; RegWrite = 1; @@ -123,6 +124,291 @@ output reg Clk $display("Test Case 1 Failed"); end + // Test Case 1.0: + // Write nothing, verify that 2 is '42' and nothing else has changed + WriteRegister = 5'd2; + WriteData = 32'd42; + RegWrite = 0; + ReadRegister1 = 5'd2; + ReadRegister2 = 5'd0; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 != 0)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.0 Failed"); + end + + ReadRegister2 = 5'd1; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.1 Failed"); + end + + ReadRegister2 = 5'd3; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.3 Failed"); + end + + ReadRegister2 = 5'd4; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.4 Failed"); + end + + ReadRegister2 = 5'd5; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.5 Failed"); + end + + ReadRegister2 = 5'd6; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.6 Failed"); + end + + ReadRegister2 = 5'd7; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.7 Failed"); + end + + ReadRegister2 = 5'd8; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.8 Failed"); + end + + ReadRegister2 = 5'd9; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.9 Failed"); + end + + ReadRegister2 = 5'd10; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.10 Failed"); + end + + ReadRegister2 = 5'd11; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.11 Failed"); + end + + ReadRegister2 = 5'd12; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.12 Failed"); + end + + ReadRegister2 = 5'd13; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.13 Failed"); + end + + ReadRegister2 = 5'd14; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.14 Failed"); + end + + ReadRegister2 = 5'd15; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.15 Failed"); + end + + ReadRegister2 = 5'd16; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.16 Failed"); + end + + ReadRegister2 = 5'd17; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.17 Failed"); + end + + ReadRegister2 = 5'd18; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.18 Failed"); + end + + ReadRegister2 = 5'd19; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.19 Failed"); + end + + ReadRegister2 = 5'd20; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.20 Failed"); + end + + ReadRegister2 = 5'd21; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.21 Failed"); + end + + ReadRegister2 = 5'd22; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.22 Failed"); + end + + ReadRegister2 = 5'd23; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.23 Failed"); + end + + ReadRegister2 = 5'd24; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.24 Failed"); + end + + ReadRegister2 = 5'd25; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.25 Failed"); + end + + ReadRegister2 = 5'd26; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.26 Failed"); + end + + ReadRegister2 = 5'd27; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.27 Failed"); + end + + ReadRegister2 = 5'd28; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.28 Failed"); + end + + ReadRegister2 = 5'd29; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.29 Failed"); + end + + ReadRegister2 = 5'd30; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.30 Failed"); + end + + ReadRegister2 = 5'd31; + #5 Clk=1; #5 Clk=0; // Generate single clock pulse + + // Verify expectations and report test result + if((ReadData1 != 42) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; // Set to 'false' on failure + $display("Test Case 1.31 Failed"); + end + // Test Case 2: // Write '15' to register 2, verify with Read Ports 1 and 2 // (Fails with example register file, but should pass with yours) @@ -138,6 +424,77 @@ output reg Clk $display("Test Case 2 Failed"); end + // Test Case 3: + // Write '15' to register 2, read unassigned ports and make sure they are + // unassigned + WriteRegister = 5'd2; + WriteData = 32'd15; + RegWrite = 1; + ReadRegister1 = 5'd5; + ReadRegister2 = 5'd3; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 !== 32'bx) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; + $display("Test Case 3 Failed"); + end + + // Test Case 4: + // Attempt to write '25' to register 0, verify failure with Read Ports 1 and 2 + WriteRegister = 5'd0; + WriteData = 32'd25; + RegWrite = 1; + ReadRegister1 = 5'd0; + ReadRegister2 = 5'd0; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 != 32'b0) || (ReadData2 != 32'b0)) begin + dutpassed = 0; + $display("Test Case 4 Failed"); + end + + // Test Case 5: + // Write '25' to register 1, verify port 1 is 25 and port 4 is not + WriteRegister = 5'd1; + WriteData = 32'd25; + RegWrite = 1; + ReadRegister1 = 5'd1; + ReadRegister2 = 5'd4; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 != 32'd25) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; + $display("Test Case 5 Failed"); + end + + // Test Case 6: + // Write '15' to register 4, verify that register 1 is 25 + // and register 4 is 15. + WriteRegister = 5'd4; + WriteData = 32'd15; + RegWrite = 1; + ReadRegister1 = 5'd1; + ReadRegister2 = 5'd4; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 != 32'd25) || (ReadData2 != 32'd15)) begin + dutpassed = 0; + $display("Test Case 6 Failed"); + end + + // Test Case 7: + // Make sure write enable is working. + WriteRegister = 5'd5; + WriteData = 32'd15; + RegWrite = 0; + ReadRegister1 = 5'd5; + ReadRegister2 = 5'd5; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 !== 32'bx) || (ReadData2 !== 32'bx)) begin + dutpassed = 0; + $display("Test Case 7 Failed"); + end // All done! Wait a moment and signal test completion. #5 diff --git a/regfile.v b/regfile.v index b8a3c74..ab6563a 100644 --- a/regfile.v +++ b/regfile.v @@ -5,6 +5,9 @@ // 2 asynchronous read ports // 1 synchronous, positive edge triggered write port //------------------------------------------------------------------------------ +`include "register.v" +`include "decoders.v" +`include "mux.v" module regfile ( @@ -18,10 +21,18 @@ input RegWrite, // Enable writing of register when High input Clk // Clock (Positive Edge Triggered) ); - // These two lines are clearly wrong. They are included to showcase how the - // test harness works. Delete them after you understand the testing process, - // and replace them with your actual code. - assign ReadData1 = 42; - assign ReadData2 = 42; + genvar i; + wire[31:0] whichWrite; + wire [31:0] register[31:0]; + + register32zero setZero(register[0], WriteData, 1, Clk); // Make sure register[0] is always zero + + decoder1to32 chooseWrite(whichWrite, RegWrite, WriteRegister); + for(i = 1; i < 32; i= i+1) begin: write + register32 writeToReg(register[i], WriteData, whichWrite[i], Clk); + end + + mux32to1by32 read1(ReadData1, ReadRegister1, register[0],register[1], register[2], register[3], register[4], register[5], register[6], register[7], register[8], register[9], register[10], register[11], register[12], register[13], register[14], register[15], register[16], register[17], register[18], register[19], register[20], register[21], register[22], register[23], register[24], register[25], register[26], register[27], register[28], register[29], register[30],register[31]); + mux32to1by32 read2(ReadData2, ReadRegister2, register[0],register[1], register[2], register[3], register[4], register[5], register[6], register[7], register[8], register[9], register[10], register[11], register[12], register[13], register[14], register[15], register[16], register[17], register[18], register[19], register[20], register[21], register[22], register[23], register[24], register[25], register[26], register[27], register[28], register[29], register[30],register[31]); endmodule \ No newline at end of file diff --git a/register.v b/register.v index dc9b8cb..a1226fd 100644 --- a/register.v +++ b/register.v @@ -14,4 +14,31 @@ input clk end end +endmodule + +module register32zero +( + output reg [31:0] q, + input [31:0] d, + input wrenable, + input clk +); + always @(posedge clk) begin + q = 0; + end +endmodule + +module register32 #( + parameter WIDTH = 32 +) ( + output reg [WIDTH-1:0] q, + input [WIDTH-1:0] d, + input wrenable, + input clk +); + always @(posedge clk) begin + if(wrenable) begin + q = d; + end + end endmodule \ No newline at end of file