diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8439a9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +*.out +*.vcd diff --git a/ALUcontrolLUT.v b/ALUcontrolLUT.v new file mode 100644 index 0000000..1b5bc24 --- /dev/null +++ b/ALUcontrolLUT.v @@ -0,0 +1,28 @@ +// `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 + +module ALUcontrolLUT +( +output reg ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, +input[2:0] ALUcommand +); + + always @(ALUcommand) begin + case (ALUcommand) + 3'd0: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b10000000; end + 3'd1: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b01000000; end + 3'd2: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00100000; end + 3'd3: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00010000; end + 3'd4: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00001000; end + 3'd5: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00000100; end + 3'd6: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00000010; end + 3'd7: begin {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00000001; end + endcase + end +endmodule diff --git a/BitSlice.t.v b/BitSlice.t.v new file mode 100644 index 0000000..ae383e7 --- /dev/null +++ b/BitSlice.t.v @@ -0,0 +1,151 @@ +//Test harness for exhaustively testing individual bit_slice modules + +`include "BitSlice.v" + +module BitSliceTestHarness (); + + // Declare registers for inputs + reg ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, A, B, CIN; + + // Declare output wires + wire cout, sum, res; + + // Instantiate DUT + BitSlice bit_slice (cout, sum, res, ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, A, B, CIN); + + // Declare helper variable registers + reg[3:0] inputs; + reg testfailed; + + initial begin + // Test bench code here. + $dumpfile("BitSlice.vcd"); + $dumpvars(0,bit_slice); + + // Initialize test failed to 0 + testfailed = 0; + + // Test simpler gates, OR, NOR, NAND, AND, XOR + // OR + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00000001; // Set OR flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (res != (A|B)) begin + testfailed = testfailed+1; + $display("Test Case OR Cin:%b A:%b B:%b Failed, Got %b Expected %b", CIN, A, B, res, (A|B)); + end + end + + // NOR + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00000010; // Set NOR flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (res != (A~|B)) begin + testfailed = testfailed+1; + $display("Test Case NOR Cin:%b A:%b B:%b Failed, Got %b Expected %b", CIN, A, B, res, (A~|B)); + end + end + + // NAND + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00000100; // Set NAND flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (res != (A~&B)) begin + testfailed = testfailed+1; + $display("Test Case NAND Cin:%b A:%b B:%b Failed, Got %b Expected %b", CIN, A, B, res, (A~&B)); + end + end + + // AND + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00001000; // Set AND flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (res != (A&B)) begin + testfailed = testfailed+1; + $display("Test Case AND Cin:%b A:%b B:%b Failed, Got %b Expected %b", CIN, A, B, res, (A&B)); + end + end + + // XOR + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00100000; // Set XOR flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (res != (A^B)) begin + testfailed = testfailed+1; + $display("Test Case XOR Cin:%b A:%b B:%b Failed, Got %b Expected %b", CIN, A, B, res, (A^B)); + end + end + + // Test more complicated gates: ADD and SUB + // ADD + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b10000000; // Set ADD flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (sum != (A^B^CIN)) begin + testfailed = testfailed+1; + $display("Test Case ADD Cin:%b A:%b B:%b Failed, Got Sum:%b Expected Sum:%b", CIN, A, B, sum, A^B^CIN); + end + if (res != (A^B^CIN)) begin + testfailed = testfailed+1; + $display("Test Case ADD Cin:%b A:%b B:%b Failed, Got Res:%b Expected Res:%b", CIN, A, B, res, A^B^CIN); + end + if (cout != ((A&B)|((A^B)&CIN))) begin // (A&B)|((A^B)&CIN) is the correct carryout logic + testfailed = testfailed+1; + $display("Test Case ADD Cin:%b A:%b B:%b Failed, Got Cout:%b Expected Cout:%b", CIN, A, B, cout, (A&B)|((A^B)&CIN)); + end + end + + // SUB is identical to ADD but all of the B inputs to the test cases are inverted. + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b01000000; // Set SUB flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (sum != (A^(!B)^CIN)) begin + testfailed = testfailed+1; + $display("Test Case SUB Cin:%b A:%b B:%b Failed, Got Sum:%b Expected Sum:%b", CIN, A, B, sum, A^(!B)^CIN); + end + if (res != (A^(!B)^CIN)) begin + testfailed = testfailed+1; + $display("Test Case SUB Cin:%b A:%b B:%b Failed, Got Res:%b Expected Res:%b", CIN, A, B, res, A^(!B)^CIN); + end + if (cout != ((A&(!B))|((A^(!B))&CIN))) begin // (A&(!B))|((A^(!B))&CIN) is the correct carryout logic + testfailed = testfailed+1; + $display("Test Case SUB Cin:%b A:%b B:%b Failed, Got Cout:%b Expected Cout:%b", CIN, A, B, cout, (A&(!B))|((A^(!B))&CIN)); + end + end + + // SLT is identical to SUB but all of the res outputs should be 0 + {ADD, SUB, XOR, SLT, AND, NAND, NOR, OR} = 8'b00010000; // Set SLT flag + for (inputs=4'b0; inputs<4'b1000; inputs=inputs+4'b1) begin + {CIN, A, B} = inputs; #1000 // Set inputs and wait + // $display( "%b %b %b", index, A, B); // + if (sum != (A^(!B)^CIN)) begin + testfailed = testfailed+1; + $display("Test Case SLT Cin:%b A:%b B:%b Failed, Got Sum:%b Expected Sum:%b", CIN, A, B, sum, A^(!B)^CIN); + end + if (res != 0) begin + testfailed = testfailed+1; + $display("Test Case SLT Cin:%b A:%b B:%b Failed, Got Res:%b Expected Res:%b", CIN, A, B, res, 0); + end + if (cout != ((A&(!B))|((A^(!B))&CIN))) begin // (A&(!B))|((A^(!B))&CIN) is the correct carryout logic + testfailed = testfailed+1; + $display("Test Case SLT Cin:%b A:%b B:%b Failed, Got Cout:%b Expected Cout:%b", CIN, A, B, cout, (A&(!B))|((A^(!B))&CIN)); + end + end + + if(testfailed == 0) begin + $display("Tests Passed"); + end + else begin + $display("%d Test Failures", testfailed); + end + + end + +endmodule diff --git a/BitSlice.v b/BitSlice.v new file mode 100644 index 0000000..a701aca --- /dev/null +++ b/BitSlice.v @@ -0,0 +1,43 @@ +//Single bit slice module for ALU +`define NAND nand #20 +`define NOR nor #20 +`define NOT not #10 +`define XOR xor #30 +`define OR or #30 +`define NAND7 nand #70 + +`include "adder.v" + +module BitSlice +( + output cout, sum, res, + input ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, A, B, CIN +); + // internal wires + wire sum, sub_slt, b_inv, xor_ab, and_ab, nand_ab, nor_ab, or_ab; + // individual outputs into nand collector + wire add_out, sub_out, xor_out, and_out, nand_out, nor_out, or_out; + + // individual operator blocks + `OR or_sub_slt (sub_slt, SUB, SLT); + `XOR inv_input (b_inv, B, sub_slt); + fullAdder adder (sum, cout, A, b_inv, CIN); + `XOR xor_operator (xor_ab, A, B); + `NAND nand_operator (nand_ab, A, B); + `NOR nor_operator (nor_ab, A, B); + `NOT not_nand (and_ab, nand_ab); + `NOT not_nor (or_ab, nor_ab); + + // nand control line selectors + `NAND add_switch (add_out, sum, ADD); + `NAND sub_switch (sub_out, sum, SUB); + `NAND xor_switch (xor_out, xor_ab, XOR); + `NAND and_switch (and_out, and_ab, AND); + `NAND nand_switch (nand_out, nand_ab, NAND); + `NAND nor_switch (nor_out, nor_ab, NOR); + `NAND or_switch (or_out, or_ab, OR); + + // collector for all individual outputs + `NAND7 collector (res, add_out, sub_out, xor_out, and_out, nand_out, nor_out, or_out); + +endmodule diff --git a/FourBitALU.t.v b/FourBitALU.t.v new file mode 100644 index 0000000..2f531b9 --- /dev/null +++ b/FourBitALU.t.v @@ -0,0 +1,209 @@ +//Test harness for exhaustively testing ADD SUB and SLT in 4-bit ALU + +`include "FourBitALU.v" + +module FourBitALUTestHarness (); + + // Declare registers for inputs + reg[3:0] A, B; + reg[2:0] command; + + + // Declare output wires + wire ovf, cout, zero; + wire[3:0] out; + + // Instantiate DUT + FourBitALU four_bit_alu (out, cout, ovf, zero, A, B, command); + + // Declare helper variable registers + reg[4:0] a_index, b_index; + reg signed [4:0] temp_sum; + reg[3:0] ex_out; + reg ex_ovf, ex_cout, ex_zero; + reg testfailed; + + initial begin + $dumpfile("fourbitalu.vcd"); + $dumpvars(0, four_bit_alu); + // Start testing ADD + command = 3'd0; + //Loop A + for (a_index=0; a_index<16; a_index=a_index+1) begin + A = a_index; + // Loop B + for (b_index=0; b_index<16; b_index=b_index+1) begin + B = b_index; #1000 + temp_sum = A + B; // Do an add + + ex_out = temp_sum[3:0]; + + // Set up expected carryout + if (temp_sum > 15) begin + ex_cout = 1; + end else begin + ex_cout = 0; + end + + // set up expected overflow + if (A[3] == B[3] && temp_sum[3] != B[3]) begin + ex_ovf = 1; + end else begin + ex_ovf = 0; + end + + // set up expected zero + if (temp_sum [3:0] == 0) begin + ex_zero = 1; + end else begin + ex_zero = 0; + end + + // set up expected carryout + ex_cout = temp_sum[4]; + + + // Test res + if (out != ex_out) begin + testfailed = testfailed + 1; + $display("Test Case ADD A:%b B:%b Failed, Got Out:%b Expected Out:%b", A, B, out, ex_out); + end + // Test ovf + if (ovf != ex_ovf) begin + testfailed = testfailed + 1; + $display("Test Case ADD A:%b B:%b Failed, Got OVF:%b Expected OVF:%b", A, B, ovf, ex_ovf); + end + // Test zero + if (zero != ex_zero) begin + testfailed = testfailed + 1; + $display("Test Case ADD A:%b B:%b Failed, Got zero:%b Expected zero:%b", A, B, zero, ex_zero); + end + // Test cout + if (cout != ex_cout) begin + testfailed = testfailed + 1; + $display("Test Case ADD A:%b B:%b Failed, Got cout:%b Expected cout:%b", A, B, cout, ex_cout); + end + end + end + + + // Test SUB + command = 3'd1; + //Loop A + for (a_index=0; a_index<16; a_index=a_index+1) begin + A = a_index; + // Loop B + for (b_index=0; b_index<16; b_index=b_index+1) begin + B = b_index; #1000 + temp_sum = {1'b0, A} + {1'b0,(~B)} + 1; //Carefully widen and do a subtract to preserve sign + + ex_out = temp_sum[3:0]; + + // Set up expected carryout + if (temp_sum > 15) begin + ex_cout = 1; + end else begin + ex_cout = 0; + end + + // set up expected overflow + if ((A[3] != B[3]) && (temp_sum[3] == B[3])) begin + ex_ovf = 1; + end else begin + ex_ovf = 0; + end + + // set up expected zero + if (temp_sum [3:0] == 0) begin + ex_zero = 1; + end else begin + ex_zero = 0; + end + + // set up expected carryout + ex_cout = temp_sum[4]; + + + // Test res + if (out != ex_out) begin + testfailed = testfailed + 1; + $display("Test Case SUB A:%b B:%b ~B:%b temp_sum:%b Failed, Got Out:%b Expected Out:%b", A, B, (~B), temp_sum, out, ex_out); + end + // Test ovf + if (ovf != ex_ovf) begin + testfailed = testfailed + 1; + $display("Test Case SUB A:%b B:%b ~B:%b temp_sum:%b Failed, Got OVF:%b Expected OVF:%b", A, B, (~B), temp_sum, ovf, ex_ovf); + end + // Test zero + if (zero != ex_zero) begin + testfailed = testfailed + 1; + $display("Test Case SUB A:%b B:%b ~B:%b temp_sum:%b Failed, Got zero:%b Expected zero:%b", A, B, (~B), temp_sum, zero, ex_zero); + end + // Test cout + if (cout != ex_cout) begin + testfailed = testfailed + 1; + $display("Test Case SUB A:%b B:%b ~B:%b temp_sum:%b Failed, Got cout:%b Expected cout:%b", A, B, (~B), temp_sum, cout, ex_cout); + end + end + end + + + + //Test SLT + command = 3'd3; + //Loop A + for (a_index=0; a_index<16; a_index=a_index+1) begin + A = a_index; + // Loop B + for (b_index=0; b_index<16; b_index=b_index+1) begin + B = b_index; #1000 + + // Set up expected carryout + ex_cout = 0; + + // set up expected overflow + ex_ovf = 0; + + // set up expected zero + ex_zero = 0; + + // set up expected output + if ( (A[3] == 1 && B[3] == 0) || (A[3] == B[3]) && (A < B) ) begin + ex_out = 1; + end else begin + ex_out = 0; + end + + + // Test res + if (out != ex_out) begin + testfailed = testfailed + 1; + $display("Test Case SLT A:%b B:%b Failed, Got Out:%b Expected Out:%b", A, B, out, ex_out); + end + // Test ovf + if (ovf != ex_ovf) begin + testfailed = testfailed + 1; + $display("Test Case SLT A:%b B:%b Failed, Got OVF:%b Expected OVF:%b", A, B, ovf, ex_ovf); + end + // Test zero + if (zero != ex_zero) begin + testfailed = testfailed + 1; + $display("Test Case SLT A:%b B:%b Failed, Got zero:%b Expected zero:%b", A, B, zero, ex_zero); + end + // Test cout + if (cout != ex_cout) begin + testfailed = testfailed + 1; + $display("Test Case SUB A:%b B:%b Failed, Got cout:%b Expected cout:%b", A, B, cout, ex_cout); + end + end + end + + if (testfailed > 0) begin + $display("%d Tests Failed", testfailed); + end else begin + $display("Tests Passed"); + end + + + end +endmodule diff --git a/FourBitALU.v b/FourBitALU.v new file mode 100644 index 0000000..7372b68 --- /dev/null +++ b/FourBitALU.v @@ -0,0 +1,50 @@ +//4 bit ALU module +`define NOR nor #20 +`define AND and #30 +`define OR or #30 +`define XOR xor #30 + +`include "BitSlice.v" +`include "ALUcontrolLUT.v" + +module FourBitALU +( + output[3:0] out, + output carryout, ovf, zero, + input[3:0] a, + input[3:0] b, + input[2:0] cmd +); + genvar j; + // control lines + wire ADD, SUB, XOR, SLT, AND, NAND, NOR, OR; + // other wires + wire[3:0] cout; + wire[3:0] sum; + wire[2:0] zero_out; + wire cin, res0, ovf_raw, zero_raw, slt_raw, slt_out, flag_enable; + + ALUcontrolLUT controlLUT(ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, cmd); + + `OR sub_slt (cin, SUB, SLT); + + BitSlice bitslice0(cout[0], sum[0], res0, ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, a[0], b[0], cin); + BitSlice bitslice1(cout[1], sum[1], out[1], ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, a[1], b[1], cout[0]); + BitSlice bitslice2(cout[2], sum[2], out[2], ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, a[2], b[2], cout[1]); + BitSlice bitslice3(cout[3], sum[3], out[3], ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, a[3], b[3], cout[2]); + + `OR zero_or1(zero_out[1], sum[0], sum[1]); + `OR zero_or (zero_out[2], zero_out[1], sum[2]); + `NOR zero_nor3(zero_raw, zero_out[2], sum[3]); + + `OR add_sub (flag_enable, ADD, SUB); + `XOR ovf_xor (ovf_raw, cout[3], cout[2]); + `XOR slt_xor (slt_raw, ovf_raw, sum[3]); + + `AND ovf_enable (ovf, ovf_raw, flag_enable); + `AND cout_enable (carryout, cout[3], flag_enable); + `AND zero_enable (zero, zero_raw, flag_enable); + `AND slt_enable (slt_out, slt_raw, SLT); + `OR slt_connect (out[0], res0, slt_out); + +endmodule diff --git a/IMG_3525.JPG b/IMG_3525.JPG new file mode 100644 index 0000000..35fb8a8 Binary files /dev/null and b/IMG_3525.JPG differ diff --git a/IMG_3527.JPG b/IMG_3527.JPG new file mode 100644 index 0000000..9354c65 Binary files /dev/null and b/IMG_3527.JPG differ diff --git a/IMG_3528.JPG b/IMG_3528.JPG new file mode 100644 index 0000000..6331b82 Binary files /dev/null and b/IMG_3528.JPG differ diff --git a/IMG_3530.JPG b/IMG_3530.JPG new file mode 100644 index 0000000..70104bf Binary files /dev/null and b/IMG_3530.JPG differ diff --git a/IMG_3531.JPG b/IMG_3531.JPG new file mode 100644 index 0000000..91db0c8 Binary files /dev/null and b/IMG_3531.JPG differ diff --git a/README.md b/README.md index 4384391..a056253 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This lab assignment creates the first component of your processor: the ALU. Additionally, it will help you understand the timing constraints of your designs. -You will work in groups of 2-3. You may shuffle teams from the first lab if you so choose. +You will work in groups of 2-3. You may shuffle teams from the first lab if you so choose. ## Specification ## @@ -24,8 +24,8 @@ The ALU you will implement is a subset of the standard MIPS ALU. The number of o | SLT | `R=(AR=~(A|B) | No | `b110` | +| OR | R=A|B | No | `b111` | Each group will construct ALUs with identical behaviors, but the internal structures will vary based on the design decisions you each make. @@ -90,7 +90,7 @@ For each ALU operation, include the following in your report: 1. A written description of what tests you chose, and why you chose them. This should be roughly a couple sentences per operation. 1. Specific instances where your test bench caught a flaw in your design. -1. As your ALU design evolves, you may find that new test cases should be added to your test bench. This is a good thing. When this happens, record specifically why these tests were added. +1. As your ALU design evolves, you may find that new test cases should be added to your test bench. This is a good thing. When this happens, record specifically why these tests were added. #### Timing Analysis #### @@ -107,7 +107,7 @@ Push your files to your team GitHub repository (the one listed on the team forma 1. Report, as a self-contained PDF or MarkDown file 1. ALU Verilog, with the specified top-level module in `alu.v` 1. Test benches, including top-level `alu.t.v` -1. Any scripts used for testing, commented or with a separate `README` on how to run everything and what to expect as output +1. Any scripts used for testing, commented or with a separate `README` on how to run everything and what to expect as output ## Hints/Notes ## diff --git a/WRITEUP.md b/WRITEUP.md new file mode 100644 index 0000000..0ee1ed0 --- /dev/null +++ b/WRITEUP.md @@ -0,0 +1,223 @@ + +# Lab 1 Writeup +### Taylor Sheneman and Alexander Hoppe + + +## Initial Planning Phase + +Our plan was to sketch out a design for the ALU, then implement the testing procedures from that design, and finally finish the implementation while continuously using the test benches for validation. We started by planning the structure of a single bit slice, as shown. + +bit_slice + +## Developing Test Benches + + We started our test-driven development by developing an exhaustive test protocol for a single bit slice, based on a single looping module through the three possible 1-bit inputs to the bit slice, `CIN`, `A`, and `B`. + +bit_slice_test_cases + +To verify our test benches were detecting failures, first we added dummy code to make sure it would fail. +```verilog +// TODO This is fake testing code + assign cout = 0; + assign res = 0; + assign sum = 0; +``` + + +As expected, we achieved the following failures for the logic-gate only portion of the exhaustive tests. Since the output is always zero, we expected six failures for `OR` and `NAND`, two failures for `NOR` and `AND`, and four failures for `XOR`. +``` +VCD info: dumpfile BitSlice.vcd opened for output. +Test Case OR Cin:0 A:0 B:1 Failed, Got 0 Expected 1 +Test Case OR Cin:0 A:1 B:0 Failed, Got 0 Expected 1 +Test Case OR Cin:0 A:1 B:1 Failed, Got 0 Expected 1 +Test Case OR Cin:1 A:0 B:1 Failed, Got 0 Expected 1 +Test Case OR Cin:1 A:1 B:0 Failed, Got 0 Expected 1 +Test Case OR Cin:1 A:1 B:1 Failed, Got 0 Expected 1 +Test Case NOR Cin:0 A:0 B:0 Failed, Got 0 Expected 1 +Test Case NOR Cin:1 A:0 B:0 Failed, Got 0 Expected 1 +Test Case NAND Cin:0 A:0 B:0 Failed, Got 0 Expected 1 +Test Case NAND Cin:0 A:0 B:1 Failed, Got 0 Expected 1 +Test Case NAND Cin:0 A:1 B:0 Failed, Got 0 Expected 1 +Test Case NAND Cin:1 A:0 B:0 Failed, Got 0 Expected 1 +Test Case NAND Cin:1 A:0 B:1 Failed, Got 0 Expected 1 +Test Case NAND Cin:1 A:1 B:0 Failed, Got 0 Expected 1 +Test Case AND Cin:0 A:1 B:1 Failed, Got 0 Expected 1 +Test Case AND Cin:1 A:1 B:1 Failed, Got 0 Expected 1 +Test Case XOR Cin:0 A:0 B:1 Failed, Got 0 Expected 1 +Test Case XOR Cin:0 A:1 B:0 Failed, Got 0 Expected 1 +Test Case XOR Cin:1 A:0 B:1 Failed, Got 0 Expected 1 +Test Case XOR Cin:1 A:1 B:0 Failed, Got 0 Expected 1 +``` + +While writing the expected/actual comparisons in our actual test loops, we learned that the RTL operations didn't seem to have strictly tighter binding than the comparison operators, and explicitly needed parentheses. i.e. `res != A|B` is not the same as `res != (A|B)` + +``` +VCD info: dumpfile BitSlice.vcd opened for output. +Test Case OR Cin:0 A:0 B:1 Failed, Got 1 Expected 1 +Test Case OR Cin:0 A:1 B:1 Failed, Got 1 Expected 1 +Test Case OR Cin:1 A:0 B:1 Failed, Got 1 Expected 1 +Test Case OR Cin:1 A:1 B:1 Failed, Got 1 Expected 1 +Test Case NAND Cin:0 A:0 B:0 Failed, Got 1 Expected 1 +Test Case NAND Cin:0 A:1 B:0 Failed, Got 1 Expected 1 +Test Case NAND Cin:1 A:0 B:0 Failed, Got 1 Expected 1 +Test Case NAND Cin:1 A:1 B:0 Failed, Got 1 Expected 1 +Test Case ADD Cin:1 A:0 B:1 Failed, Got Cout:1 Expected Cout:1 +Test Case ADD Cin:1 A:1 B:0 Failed, Got Cout:1 Expected Cout:1 +Test Case SUB Cin:1 A:0 B:0 Failed, Got Cout:1 Expected Cout:1 +Test Case SUB Cin:1 A:1 B:1 Failed, Got Cout:1 Expected Cout:1 +``` + +None of these failed after adding parentheses; the bit slice functioned as intended. The only change we made to the bit slice design after this point was to add the `SLT` flag (in the `SLT||SUB` component at the top of the above diagram) to the adder input. Previously, the only input to the `XOR` with `B` was `SUB`, but we wanted to make our control logic simpler by adopting a purely "one-hot" design for control line inputs. + +## Four Bit ALU + +We then sketched out an initial plan for the constant-time logic outside of the bit slices, as below. We decided to first implement a 4-bit ALU to validate this logic exhaustively before moving on to 32 bits. + +alu_block_diagram + +Much of the constant-time logic was familiar from our previous 4-bit adder design, with the exception of the set-less-than logic, and the `ADD||SUB` line for selectively enabling the `cout`, `ovf` and `zero` flags. We had some syntax trouble writing the test benches for this design, to the point where we noticed a flaw in the set-less-than logic before getting any useful information from the test suite. + +In the above diagram, the input to the `SLT` enable line is an `OR` gate connected to the overflow line and the most-significant-bit sum line, under the assumption that the subtraction of a larger number from a smaller number would always result in a negative number or an overflow. We failed to account for the case in which a negative number subtracted from a positive number may also overflow, in which case both `ovf` and the final `sum` would be high, incorrectly triggering `SLT`. We fixed this by replacing the `OR` with an `XOR`. + +The other design change we made at this point was to re-engineer our logic for triggering the `zero` flag. Realizing that our many-input `NOR` gate connected to all the output lines would result in a massive constant delay *after* the final sum line was calculated, we expanded the logic to a series of `OR` gates connected to each sum line in series, and a final `NOR` gate to ensure that the `zero` flag would only be set if all outputs are zero. + +This is our final ALU design, with these changes incorporated. + +revised_alu_block_diagram + +## 32-bit ALU + +Once the four-bit design was complete and the exhaustive tests all passed, it was fairly simple to expand the design to 32 bits. With the exception of the first bit slice, which requires I/O slightly different from all other cases, we automated the creation of the bit slices with a `generate` block, connecting each `CIN` to the previous `cout`. We also wrote a `generate` statement for the chain of zero-flag-checking `OR` gates, which required slightly different formats for the first and last in the series. Otherwise, the code is identical to that of the four-bit case. + +We were pretty confident that our design would function largely identically to the exhaustively-tested four-bit case, with the exception of timing. We formulated the worst-case delay that we could come up with, along with a handful of other interesting cases to validate the functionality of all bit slices. + +Testing all boolean logic blocks. Each bit slice produces entirely independent output for these operations, so these serve as exhaustive tests. + +``` +Test XOR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test XOR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test XOR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test XOR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 + +Test AND A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test AND A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test AND A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test AND A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 + +Test NAND A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NAND A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NAND A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NAND A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 + +Test NOR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NOR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test NOR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test NOR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 + +Test OR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test OR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test OR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test OR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +``` + +Testing individual carryouts, on the end cases. All the middle cases are identical, so we used the first two and the last two to validate this functionality. + +``` +Test ADD A:00000000000000000000000000000001 B:00000000000000000000000000000001 Passed, Expected Out:00000000000000000000000000000010 Got Out:00000000000000000000000000000010 +Test ADD A:00000000000000000000000000000010 B:00000000000000000000000000000010 Passed, Expected Out:00000000000000000000000000000100 Got Out:00000000000000000000000000000100 +Test ADD A:01000000000000000000000000000000 B:01000000000000000000000000000000 Passed, Expected Out:10000000000000000000000000000000 Got Out:10000000000000000000000000000000 +Test ADD A:10000000000000000000000000000000 B:10000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +``` + +"All-bit" and simple overflow case. +``` +Test ADD A:01111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:01111111111111111111111111111110 Got Out:01111111111111111111111111111110 +Test ADD A:11111111111111111111111111111111 B:10000000000000000000000000000000 Passed, Expected Out:01111111111111111111111111111111 Got Out:01111111111111111111111111111111 +``` + +Cases chosen to result in all possible combinations of inputs to the SLT logic: neither negative nor overflow, only negative, only overflow, and both. + +``` +Test SLT A: 5000 B: 5000 Passed, Expected Out: 0 Got Out: 0 +Test SLT A:-2147483647 B: 2147483647 Passed, Expected Out: 1 Got Out: 1 +Test SLT A:-1000000000 B:-2000000000 Passed, Expected Out: 0 Got Out: 0 +Test SLT A: -300000000 B: -100000000 Passed, Expected Out: 1 Got Out: 1 +Test SLT A: 1500000000 B: 1000000000 Passed, Expected Out: 0 Got Out: 0 +``` + +Generic addition and subtraction cases, using positive-positive and negative-negative pairs. + +``` +Test ADD A: 5000 B: 5000 Passed, Expected Out: 10000 Got Out: 10000 +Test ADD A: 5000 B: 5000 Passed, Expected cout:0 Got cout:0 +Test ADD A: 5000 B: 5000 Passed, Expected ovf:0 Got ovf:0 +Test ADD A: 5000 B: 5000 Passed, Expected zero:0 Got zero:0 + +Test ADD A:-1000000000 B:-2000000000 Passed, Expected Out: 1294967296 Got Out:1294967296 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected cout:1 Got cout:1 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected ovf:1 Got ovf:1 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected zero:0 Got zero:0 + +Test ADD A: -300000000 B: -100000000 Passed, Expected Out: -400000000 Got Out:3894967296 +Test ADD A: -300000000 B: -100000000 Passed, Expected cout:1 Got cout:1 +Test ADD A: -300000000 B: -100000000 Passed, Expected ovf:0 Got ovf:0 +Test ADD A: -300000000 B: -100000000 Passed, Expected zero:0 Got zero:0 + +Test ADD A: 1500000000 B: 1000000000 Passed, Expected Out:-1794967296 Got Out:2500000000 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected cout:0 Got cout:0 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected ovf:1 Got ovf:1 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected zero:0 Got zero:0 + +Test SUB A:-2147483647 B: 2147483647 Passed, Expected Out: 2 Got Out: 2 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected cout:1 Got cout:1 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected ovf:1 Got ovf:1 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected zero:0 Got zero:0 + +Test SUB A:-1000000000 B:-2000000000 Passed, Expected Out: 1000000000 Got Out:1000000000 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected cout:1 Got cout:1 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected zero:0 Got zero:0 + +Test SUB A: -300000000 B: -100000000 Passed, Expected Out: -200000000 Got Out:4094967296 +Test SUB A: -300000000 B: -100000000 Passed, Expected cout:0 Got cout:0 +Test SUB A: -300000000 B: -100000000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A: -300000000 B: -100000000 Passed, Expected zero:0 Got zero:0 + +Test SUB A: 1500000000 B: 1000000000 Passed, Expected Out: 500000000 Got Out: 500000000 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected cout:1 Got cout:1 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected zero:0 Got zero:0 +``` + +Zero-flag tests, for addition and subtraction. + +``` +Test ADD A:-2147483647 B: 2147483647 Passed, Expected Out: 0 Got Out: 0 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected cout:1 Got cout:1 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected ovf:0 Got ovf:0 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected zero:1 Got zero:1 + +Test SUB A: 5000 B: 5000 Passed, Expected Out: 0 Got Out: 0 +Test SUB A: 5000 B: 5000 Passed, Expected cout:1 Got cout:1 +Test SUB A: 5000 B: 5000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A: 5000 B: 5000 Passed, Expected zero:1 Got zero:1 +``` + +Worst-case delay: starting with `ovf` and `SLT` high from one operation `-2147483648 SLT 1`, we move directly to a case `0 SLT 0` in which the result from the first bit slice propagates all the way to the final `COUT`, setting `ovf` to low and propagating through the `SLT` logic. + +``` +Test SLT A:10000000000000000000000000000000 B:00000000000000000000000000000001 Passed, Expected Out:00000000000000000000000000000001, Got Out:00000000000000000000000000000001 +Test SLT A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000, Got Out:00000000000000000000000000000000 +``` + +Extrapolating the calculations from our 4-bit full adder out to 32 bits and appending the `SLT` logic, we calculated a worst-case delay of 1480 time units. Our test bench was only waiting 1000 time units, so we had to increase the clock period. The marked section on the diagram below is our estimated worst-case scenario. + +worst_case_timing_diagram + +Additions and subtractions should all be slightly faster (as they lack the extra SLT logic), coming out to 1440 for worst-case addition, and 1470 for subtraction. All the boolean logic is constant-time, as there is no chaining between bit slices, and has a worst-case delay of 110 for `NAND` and `NOR`, and 120 for `XOR`, `AND`, and `OR`. + +## Work Plan Reflection + +We were somewhat conservative on our time estimates for the actual ALU design, and made the questionable decision of subdividing the expected work by operation, which didn't correspond to how we actually spent our time. In reality, we designed an entire bit slice with all operations, then scaled it up gradually to a 32-bit ALU with appropriate constant-time logic. Overall, we probably spent somewhat less time than we expected on ALU design, just in a different distribution. + +However, writing the test benches took way, way longer than we expected. The original time estimate for test benches was three hours, but over the course of our three phases of testing, we probably spent closer to ten hours just writing and debugging tests. A lot of problems arose simply from our shaky knowledge of Verilog, which was rather frustrating. The time spent there greatly outweighed the underestimate for the circuit design, so overall, we ended up spending many more hours on the lab than we budgeted for. diff --git a/adder.v b/adder.v new file mode 100644 index 0000000..8b57e94 --- /dev/null +++ b/adder.v @@ -0,0 +1,23 @@ +// Adder circuit + +`define AND and #20 +`define OR or #20 +`define XOR xor #20 + +module fullAdder +( + output sum, + output carryout, + input a, + input b, + input carryin +); + wire axorb, axorb_andcarryin, aandb; + + `XOR xorab (axorb, a, b); + `XOR xorsumout (sum, carryin, axorb); + `AND andab (aandb, a, b); + `AND andaxorbcarryin (axorb_andcarryin, axorb, carryin); + `OR orcarryout (carryout, aandb, axorb_andcarryin); + +endmodule diff --git a/alu.t.v b/alu.t.v new file mode 100644 index 0000000..50b903e --- /dev/null +++ b/alu.t.v @@ -0,0 +1,287 @@ +//Test harness for testing 32 bit ALU +`define code_ADD 3'b000 +`define code_SUB 3'b001 +`define code_XOR 3'b010 +`define code_SLT 3'b011 +`define code_AND 3'b100 +`define code_NAND 3'b101 +`define code_NOR 3'b110 +`define code_OR 3'b111 + +`include "alu.v" + +module ALUTestHarness (); + // Declare registers for inputs + reg signed [31:0] A, B; + reg[2:0] command; + + // Declare output wires + wire cout, ovf, zero; + wire[31:0] out; + + // Instantiate DUT + ALU alu (out, cout, ovf, zero, A, B, command); + + // Declare helper variable registers + + // Set of operands to loop through for ADD, SUB and SLT + reg[191:0] a_vals = { + 32'd400000000, + 32'd1500000000, + -32'd300000000, + -32'd1000000000, + -32'd2147483647, + 32'd5000 + }; + reg[191:0] b_vals = { + 32'd500000000, + 32'd1000000000, + -32'd100000000, + -32'd2000000000, + 32'd2147483647, + 32'd5000 + }; + + // Expected output flags + // cout | ovf | zero + reg[17:0] add_res = { + 3'b000, + 3'b010, + 3'b100, + 3'b110, + 3'b101, + 3'b000 + }; + + // Expected output flags + // cout | ovf | zero + reg[17:0] sub_res = { + 3'b000, + 3'b100, + 3'b000, + 3'b100, + 3'b110, + 3'b101 + }; + + reg[2:0] logic_index; + reg ex_cout, ex_ovf, ex_zero; + reg[3:0] add_index; + reg[15:0] testfailed; + + initial begin + $dumpfile("alu.vcd"); + $dumpvars(0, alu); + testfailed = 0; + + $display("Test Commence"); + + // Test Worst Case Delay + // Setup by doing SLT on -2147483648 1 + A = -2147483648; B = 1; command = `code_SLT; #2000 + + if ( out != 32'b1 ) begin + testfailed = testfailed +1; + $display("Test SLT A:%b B:%b Failed, Expected Out:%b, Got Out:%b", A, B, 32'b1, out); + end + + // Next measure delay for SLT on 0 0 + A = 0; B = 0; #2000 + if ( out != 32'b0 ) begin + testfailed = testfailed +1; + $display("Test SLT A:%b B:%b Failed, Expected Out:%b, Got Out:%b", A, B, 32'b0, out); + end + + + // Test block logic to check all of the bits + command = `code_XOR; + for (logic_index = 0; logic_index < 4; logic_index = logic_index + 1) begin + A = (logic_index[0]==0) ? 32'd0 : 32'd2147483647; + B = (logic_index[1]==0) ? 32'd0 : 32'd2147483647;#2000 + if (out != (A^B)) begin + testfailed = testfailed +1; + $display("Test XOR A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, A^B, out); + end + if (cout == 1 || ovf == 1 || zero == 1) begin + testfailed = testfailed +1; + $display("Test XOR A:%b B:%b Failed, Produced Flags cout:%b, ovf:%b, zero:%b", A, B, cout, ovf, zero); + end + end + + command = `code_AND; + for (logic_index = 0; logic_index < 4; logic_index = logic_index + 1) begin + A = (logic_index[0]==0) ? 32'd0 : -32'd1; + B = (logic_index[1]==0) ? 32'd0 : -32'd1;#2000 + if (out != (A&B)) begin + testfailed = testfailed +1; + $display("Test AND A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, A&B, out); + end + if (cout == 1 || ovf == 1 || zero == 1) begin + testfailed = testfailed +1; + $display("Test AND A:%b B:%b Failed, Produced Flags cout:%b, ovf:%b, zero:%b", A, B, cout, ovf, zero); + end + end + + command = `code_NAND; + for (logic_index = 0; logic_index < 4; logic_index = logic_index + 1) begin + A = (logic_index[0]==0) ? 32'd0 : -32'd1; + B = (logic_index[1]==0) ? 32'd0 : -32'd1;#2000 + if (out != (A~&B)) begin + testfailed = testfailed +1; + $display("Test NAND A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, A~&B, out); + end + if (cout == 1 || ovf == 1 || zero == 1) begin + testfailed = testfailed +1; + $display("Test NAND A:%b B:%b Failed, Produced Flags cout:%b, ovf:%b, zero:%b", A, B, cout, ovf, zero); + end + end + + command = `code_NOR; + for (logic_index = 0; logic_index < 4; logic_index = logic_index + 1) begin + A = (logic_index[0]==0) ? 32'd0 : -32'd1; + B = (logic_index[1]==0) ? 32'd0 : -32'd1;#2000 + if (out != (A~|B)) begin + testfailed = testfailed +1; + $display("Test NOR A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, A~|B, out); + end + if (cout == 1 || ovf == 1 || zero == 1) begin + testfailed = testfailed +1; + $display("Test NOR A:%b B:%b Failed, Produced Flags cout:%b, ovf:%b, zero:%b", A, B, cout, ovf, zero); + end + end + + command = `code_OR; + for (logic_index = 0; logic_index < 4; logic_index = logic_index + 1) begin + A = (logic_index[0]==0) ? 32'd0 : -32'd1; + B = (logic_index[1]==0) ? 32'd0 : -32'd1;#2000 + if (out != (A|B)) begin + testfailed = testfailed +1; + $display("Test OR A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, A|B, out); + end + if (cout == 1 || ovf == 1 || zero == 1) begin + testfailed = testfailed +1; + $display("Test OR A:%b B:%b Failed, Produced Flags cout:%b, ovf:%b, zero:%b", A, B, cout, ovf, zero); + end + end + + + // Test all signals in ADD by using all bits for a non-zero result + command = `code_ADD; + // 0111... + 1111... + A = 2147483647; B = -1;#2000 + if (out != 2147483646) begin + testfailed = testfailed +1; + $display("Test ADD A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, 2147483646, out); + end + + // 1111... + 1000... + A = -1; B = 32'b1<<31;#2000 + if (out != 2147483647) begin + testfailed = testfailed +1; + $display("Test ADD A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, 2147483647, out); + end + + // Test a few internal carries for ADD + // ...0001 + ...0001 + A = 32'b1; B = 32'b1;#2000 + if (out != 32'b10) begin + testfailed = testfailed +1; + $display("Test ADD A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, 32'b10, out); + end + + // ...0010 + 0010 + A = 32'b10; B =32'b10;#2000 + if (out != 32'b100) begin + testfailed = testfailed +1; + $display("Test ADD A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, 32'b100, out); + end + + // 0100... + 0100... + A = 32'b1<<30; B = 32'b1<<30 ;#2000 + if (out != 32'b1<<31) begin + testfailed = testfailed +1; + $display("Test ADD A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, 32'b1<<31, out); + end + + // 1000... + 1000... + A = 32'b1<<31; B = 32'b1<<31 ;#2000 + if (out != 32'b0) begin + testfailed = testfailed +1; + $display("Test ADD A:%b B:%b Failed, Expected Out:%b Got Out:%b", A, B, 32'b0, out); + end + + + // ADD SUB SLT interesting cases + command = `code_ADD; + for (add_index = 0; add_index<6; add_index = add_index + 1) begin + A = a_vals[((add_index*32)-1)-:32]; // Grab the relevant chunk of the register of queued operations + B = b_vals[((add_index*32)-1)-:32];#2000 + {ex_cout,ex_ovf,ex_zero} = add_res[((add_index*3)-1)-:3]; + + if (out != (A+B)) begin + testfailed = testfailed +1; + $display("Test ADD A:%d B:%d Failed, Expected Out:%d Got Out:%d", A, B, A+B, out); + end + if (cout != ex_cout) begin + testfailed = testfailed +1; + $display("Test ADD A:%d B:%d Failed, Expected cout:%d Got cout:%d", A, B, ex_cout, cout); + end + if (ovf != ex_ovf) begin + testfailed = testfailed +1; + $display("Test ADD A:%d B:%d Failed, Expected ovf:%d Got ovf:%d", A, B, ex_ovf, ovf); + end + if (zero != ex_zero) begin + testfailed = testfailed +1; + $display("Test ADD A:%d B:%d Failed, Expected zero:%d Got zero:%d", A, B, ex_zero, zero); + end + end + + //SUB + command = `code_SUB; + for (add_index = 0; add_index<6; add_index = add_index + 1) begin + A = a_vals[((add_index*32)-1)-:32]; // Grab the relevant chunk of the register of queued operations + B = b_vals[((add_index*32)-1)-:32];#2000 + {ex_cout,ex_ovf,ex_zero} = sub_res[((add_index*3)-1)-:3]; + + if (out != (A-B)) begin + testfailed = testfailed +1; + $display("Test SUB A:%d B:%d Failed, Expected Out:%d Got Out:%d", A, B, A-B, out); + end + if (cout != ex_cout) begin + testfailed = testfailed +1; + $display("Test SUB A:%d B:%d Failed, Expected cout:%d Got cout:%d", A, B, ex_cout, cout); + end + if (ovf != ex_ovf) begin + testfailed = testfailed +1; + $display("Test SUB A:%d B:%d Failed, Expected ovf:%d Got ovf:%d", A, B, ex_ovf, ovf); + end + if (zero != ex_zero) begin + testfailed = testfailed +1; + $display("Test SUB A:%d B:%d Failed, Expected zero:%d Got zero:%d", A, B, ex_zero, zero); + end + end + + //SLT + command = `code_SLT; + for (add_index = 0; add_index<6; add_index = add_index + 1) begin + A = a_vals[((add_index*32)-1)-:32]; // Grab the relevant chunk of the register of queued operations + B = b_vals[((add_index*32)-1)-:32];#2000 + + if (out != ((A 0) begin + $display(" %d Tests Failed", testfailed); + end else begin + $display(" Tests Passed!"); + end + + end +endmodule diff --git a/alu.v b/alu.v new file mode 100644 index 0000000..d8761cd --- /dev/null +++ b/alu.v @@ -0,0 +1,67 @@ +//4 bit ALU module +`define NOR nor #20 +`define AND and #30 +`define OR or #30 +`define XOR xor #30 + +`include "BitSlice.v" +`include "ALUcontrolLUT.v" + +module ALU +( + output[31:0] out, + output carryout, ovf, zero, + input[31:0] a, + input[31:0] b, + input[2:0] cmd +); + genvar i; + genvar j; + // control lines + wire ADD, SUB, XOR, SLT, AND, NAND, NOR, OR; + // other wires + wire[31:0] cout; + wire[31:0] sum; + wire[30:0] zero_out; + wire cin, res0, ovf_raw, zero_raw, slt_raw, slt_out, flag_enable; + + // control LUT, decodes command signal into one-hot control lines + ALUcontrolLUT controlLUT(ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, cmd); + + // the first bitslice's carryin should be 1 if using sub or slt + `OR sub_slt (cin, SUB, SLT); + + // the first bitslice has slightly different output (for slt op) and cin + BitSlice bitslice0(cout[0], sum[0], res0, ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, a[0], b[0], cin); + // all other bitslices cin from the previous cout and output to out[i] + generate + for (i = 1; i < 32; i = i+1) begin : bitslice_generate + BitSlice bitslice (cout[i], sum[i], out[i], ADD, SUB, XOR, SLT, AND, NAND, NOR, OR, a[i], b[i], cout[i-1]); + end + endgenerate + + // zero flag checking: or all but last sum line together + `OR zero_or1(zero_out[1], sum[0], sum[1]); + generate + for (j = 2; j < 31; j = j + 1) begin : zero_or_generate + `OR zero_or (zero_out[j], zero_out[j-1], sum[j]); + end + endgenerate + // high if the whole or string and the last sum are zero + `NOR zero_nor31(zero_raw, zero_out[30], sum[31]); + + // overflow and slt conditions + `XOR ovf_xor (ovf_raw, cout[31], cout[30]); + `XOR slt_xor (slt_raw, ovf_raw, sum[31]); + + // only ADD and SUB set flags + `OR add_sub (flag_enable, ADD, SUB); + `AND ovf_enable (ovf, ovf_raw, flag_enable); + `AND cout_enable (carryout, cout[31], flag_enable); + `AND zero_enable (zero, zero_raw, flag_enable); + + // SLT sets slt output on the first out line + `AND slt_enable (slt_out, slt_raw, SLT); + `OR slt_connect (out[0], res0, slt_out); + +endmodule diff --git a/test_pass_output.txt b/test_pass_output.txt new file mode 100644 index 0000000..97c61fb --- /dev/null +++ b/test_pass_output.txt @@ -0,0 +1,102 @@ +VCD info: dumpfile alu.vcd opened for output. +Test Commence +Test SLT A:10000000000000000000000000000000 B:00000000000000000000000000000001 Passed, Expected Out:00000000000000000000000000000001, Got Out:00000000000000000000000000000001 +Test SLT A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000, Got Out:00000000000000000000000000000000 +Test XOR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test XOR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test XOR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test XOR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test XOR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test XOR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test XOR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test XOR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test AND A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test AND A:00000000000000000000000000000000 B:00000000000000000000000000000000 Failed, Produced Flags cout:0, ovf:0, zero:0 +Test AND A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test AND A:11111111111111111111111111111111 B:00000000000000000000000000000000 Failed, Produced Flags cout:0, ovf:0, zero:0 +Test AND A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test AND A:00000000000000000000000000000000 B:11111111111111111111111111111111 Failed, Produced Flags cout:0, ovf:0, zero:0 +Test AND A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test AND A:11111111111111111111111111111111 B:11111111111111111111111111111111 Failed, Produced Flags cout:0, ovf:0, zero:0 +Test NAND A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NAND A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NAND A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NAND A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NAND A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NAND A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NAND A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test NAND A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NOR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test NOR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NOR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test NOR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NOR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test NOR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test NOR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test NOR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test OR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test OR A:00000000000000000000000000000000 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test OR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test OR A:11111111111111111111111111111111 B:00000000000000000000000000000000 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test OR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test OR A:00000000000000000000000000000000 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test OR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:11111111111111111111111111111111 Got Out:11111111111111111111111111111111 +Test OR A:11111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Produced Flags cout:0, ovf:0, zero:0 +Test ADD A:01111111111111111111111111111111 B:11111111111111111111111111111111 Passed, Expected Out:01111111111111111111111111111110 Got Out:01111111111111111111111111111110 +Test ADD A:11111111111111111111111111111111 B:10000000000000000000000000000000 Passed, Expected Out:01111111111111111111111111111111 Got Out:01111111111111111111111111111111 +Test ADD A:00000000000000000000000000000001 B:00000000000000000000000000000001 Passed, Expected Out:00000000000000000000000000000010 Got Out:00000000000000000000000000000010 +Test ADD A:00000000000000000000000000000010 B:00000000000000000000000000000010 Passed, Expected Out:00000000000000000000000000000100 Got Out:00000000000000000000000000000100 +Test ADD A:01000000000000000000000000000000 B:01000000000000000000000000000000 Passed, Expected Out:10000000000000000000000000000000 Got Out:10000000000000000000000000000000 +Test ADD A:10000000000000000000000000000000 B:10000000000000000000000000000000 Passed, Expected Out:00000000000000000000000000000000 Got Out:00000000000000000000000000000000 +Test ADD A: 5000 B: 5000 Passed, Expected Out: 10000 Got Out: 10000 +Test ADD A: 5000 B: 5000 Passed, Expected cout:0 Got cout:0 +Test ADD A: 5000 B: 5000 Passed, Expected ovf:0 Got ovf:0 +Test ADD A: 5000 B: 5000 Passed, Expected zero:0 Got zero:0 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected Out: 0 Got Out: 0 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected cout:1 Got cout:1 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected ovf:0 Got ovf:0 +Test ADD A:-2147483647 B: 2147483647 Passed, Expected zero:1 Got zero:1 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected Out: 1294967296 Got Out:1294967296 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected cout:1 Got cout:1 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected ovf:1 Got ovf:1 +Test ADD A:-1000000000 B:-2000000000 Passed, Expected zero:0 Got zero:0 +Test ADD A: -300000000 B: -100000000 Passed, Expected Out: -400000000 Got Out:3894967296 +Test ADD A: -300000000 B: -100000000 Passed, Expected cout:1 Got cout:1 +Test ADD A: -300000000 B: -100000000 Passed, Expected ovf:0 Got ovf:0 +Test ADD A: -300000000 B: -100000000 Passed, Expected zero:0 Got zero:0 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected Out:-1794967296 Got Out:2500000000 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected cout:0 Got cout:0 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected ovf:1 Got ovf:1 +Test ADD A: 1500000000 B: 1000000000 Passed, Expected zero:0 Got zero:0 +Test SUB A: 5000 B: 5000 Passed, Expected Out: 0 Got Out: 0 +Test SUB A: 5000 B: 5000 Passed, Expected cout:1 Got cout:1 +Test SUB A: 5000 B: 5000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A: 5000 B: 5000 Passed, Expected zero:1 Got zero:1 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected Out: 2 Got Out: 2 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected cout:1 Got cout:1 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected ovf:1 Got ovf:1 +Test SUB A:-2147483647 B: 2147483647 Passed, Expected zero:0 Got zero:0 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected Out: 1000000000 Got Out:1000000000 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected cout:1 Got cout:1 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A:-1000000000 B:-2000000000 Passed, Expected zero:0 Got zero:0 +Test SUB A: -300000000 B: -100000000 Passed, Expected Out: -200000000 Got Out:4094967296 +Test SUB A: -300000000 B: -100000000 Passed, Expected cout:0 Got cout:0 +Test SUB A: -300000000 B: -100000000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A: -300000000 B: -100000000 Passed, Expected zero:0 Got zero:0 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected Out: 500000000 Got Out: 500000000 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected cout:1 Got cout:1 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected ovf:0 Got ovf:0 +Test SUB A: 1500000000 B: 1000000000 Passed, Expected zero:0 Got zero:0 +Test SLT Passed, cout:0 ovf:0 zero:0 +Test SLT A: 5000 B: 5000 Passed, Expected Out: 0 Got Out: 0 +Test SLT Passed, cout:0 ovf:0 zero:0 +Test SLT A:-2147483647 B: 2147483647 Passed, Expected Out: 1 Got Out: 1 +Test SLT Passed, cout:0 ovf:0 zero:0 +Test SLT A:-1000000000 B:-2000000000 Passed, Expected Out: 0 Got Out: 0 +Test SLT Passed, cout:0 ovf:0 zero:0 +Test SLT A: -300000000 B: -100000000 Passed, Expected Out: 1 Got Out: 1 +Test SLT Passed, cout:0 ovf:0 zero:0 +Test SLT A: 1500000000 B: 1000000000 Passed, Expected Out: 0 Got Out: 0 +Test SLT Passed, cout:0 ovf:0 zero:0 + 99 Tests Passed diff --git a/work_plan.txt b/work_plan.txt new file mode 100644 index 0000000..1f36a25 --- /dev/null +++ b/work_plan.txt @@ -0,0 +1,24 @@ +Requirements +Draft a work plan for this lab. Break down the lab in to small portions, and for each portion predict how long it will take (in hours) and when it will be done by (date). You will be comparing your predictions to reality later. + +Submit this plan by Wednesday, October 4 by pushing work_plan.txt to GitHub. + +Work Plan + +1. Understand bitslice ALUs to some extent - sketch out a block diagram, look up anything relevant (1.5hrs) Thursday Oct 5 + +2. Write test benches - script this, preferably (3hrs) Saturday Oct 7 + +3. Stub out bitslice module with undefined inputs (1hr) Saturday Oct 7 + +4. Implement adder/subtracter - we already know how to do this, so it shouldn't be too bad (2hrs) Sunday Oct 8 + +5. Implement LUT - with a couple working modules, we can try doing this (1.5hrs) Sunday Oct 8 + +6. Implement XOR and SLT - we think we have a pretty good idea of how to do this (1.5hrs) Monday Oct 9 + +7. Implement AND/NAND/NOR/OR - related, and don't seem particularly tricky (1.5hrs) Tuesday Oct 10 + +8. Final block diagram - (.5hrs) Wednesday Oct 11 + +9. Report/timing analysis/reflection - (3.5hrs) Wednesday Oct 11 diff --git a/worst_case_slt_delay.png b/worst_case_slt_delay.png new file mode 100644 index 0000000..a77e8e0 Binary files /dev/null and b/worst_case_slt_delay.png differ