diff --git a/README.md b/README.md index 0fe8ea5..9ffe3a2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # CompArch HW b0100: Register File # **Due:** ~~Monday, October 16~~ Thursday, October 19 +**_Please see report.md for deliverables 1 and 6 and testing_guide.md for instructions on how to run the tests_** 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/Registers.JPG b/Registers.JPG new file mode 100644 index 0000000..7b795aa Binary files /dev/null and b/Registers.JPG differ diff --git a/decoders.t.v b/decoders.t.v new file mode 100644 index 0000000..616b67b --- /dev/null +++ b/decoders.t.v @@ -0,0 +1,41 @@ +//------------------------------- +// Unit test the decoder module +//------------------------------- + +`include "decoders.v" + +module decoder1to32Test(); + wire[31:0] out; + reg enable; + reg[4:0] address; + + reg dutpassed; // Flag is set to false if any of the tests fail. + + decoder1to32 DUT (out, enable, address); + + initial begin + dutpassed = 1; + + // Test Case 1: do not enable writing to any register. + enable = 0; address = 5'd14; + if (out != 0) begin + $display("Decoder Test Case 1 failed"); + dutpassed = 0; + end // + + // Test Case 2: + // Enable writing to one register only. + #5 + enable = 1; address = 5'd14; + if (out[31:15] != 0 || out[14] != 1 || out[13:0] != 0) begin + $display("Decoder Test Case 2 failed"); + dutpassed = 0; + end + + #5 + + if (dutpassed ==1) begin + $display("All decoder tests passed."); + end + end // +endmodule // decoder1to32Test \ No newline at end of file diff --git a/decoders.v b/decoders.v index dd467c2..bfb1ff9 100644 --- a/decoders.v +++ b/decoders.v @@ -12,3 +12,9 @@ input[4:0] address endmodule +// Enable is set to be the least significant bit of out. The +// value of address (which can be between 0 and 31) indicates +// the number of bits out should be be shifted left by. + +// So, the decoder selects the register which is being written to (if any) +// by using the value of adress. diff --git a/makefile b/makefile new file mode 100644 index 0000000..81d8e6c --- /dev/null +++ b/makefile @@ -0,0 +1,10 @@ +all: register_test mux_test decoder_test regfile_test + +register_test: register.t.v register.v + iverilog -Wall -o register_test register.t.v +mux_test: multiplexer.t.v multiplexer.v + iverilog -Wall -o mux_test multiplexer.t.v +decoder_test: decoders.t.v decoders.v + iverilog -Wall -o decoder_test decoders.t.v +regfile_test: regfile.t.v regfile.v register.v multiplexer.v decoders.v + iverilog -Wall -o regfile_test regfile.t.v diff --git a/multiplexer.t.v b/multiplexer.t.v new file mode 100644 index 0000000..99dced4 --- /dev/null +++ b/multiplexer.t.v @@ -0,0 +1,108 @@ +//-------------------------------- +// Test the multiplexer modules. +//-------------------------------- + +`include "multiplexer.v" + +// Test harness for multiplexer unit test modules. +module multiplexerTestBenchHarness(); + reg begintest0; + reg begintest1; + wire endtest0; + wire endtest1; + wire dutpassed0; + wire dutpassed1; + + mux32to1by1Test test0 (begintest0, endtest0, dutpassed0); + mux32to32by1Test test1 (begintest1, endtest1, dutpassed1); + + initial begin + begintest0 = 0; + begintest1 = 0; + #10; + begintest0 = 1; + begintest1 = 1; + #1000; + end + + always @(posedge endtest0 && endtest1) begin + if (dutpassed0 == 1 || dutpassed1 == 1) begin + $display("All multiplexer tests passed."); + end + end + +endmodule // multiplexerTestBenchHarness + +// Unit test the 32:1 mux module. +module mux32to1by1Test + ( + input begintest, + output reg endtest, + output reg dutpassed + ); + wire out; + reg[4:0] address; + reg[31:0] inputs; + + mux32to1by1 DUT (out, address, inputs); + + always @(posedge begintest) begin + endtest = 0; + dutpassed = 1; + + // Test Case 1: + // Ensure that out is the same as the bit of the input at the + // given address. + inputs = 32'h000FFF; address = 5'd9; + if (out != 1) begin + $display("32:1 mux Test Case 1 Failed."); + dutpassed = 0; + end + + #5 + endtest = 1; + end +endmodule // mux32to1by1Test + +// Unit test the 32 wide 32 deep mux module. +module mux32to32by1Test( + input begintest, + output reg endtest, + output reg dutpassed + ); + wire[31:0] out; + reg[4:0] address; + reg[31:0] input0, input1, input2, input3, input4, input5, input6, input7, input8; + reg[31:0] input9, input10, input11, input12, input13, input14, input15, input16; + reg[31:0] input17, input18, input19, input20, input21, input22, input23, input24; + reg[31:0] input25, input26, input27, input28, input29, input30, input31; + + mux32to1by32 DUT (out, address, 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); + + always @(posedge begintest) begin + endtest = 0; + dutpassed = 1; + + // Test Case 1: + // Ensure that the value chosen by the mux matches the value at the given address + address = 5'd20; + input0 = 32'd0; input1 = 32'd1; input2 = 32'd2; input3 = 32'd3; input4 = 32'd4; + input5 = 32'd5; input6 = 32'd6; input7 = 32'd7; input8 = 32'd8; input9 = 32'd9; + input10 = 32'd10; input11 = 32'd11; input12 = 32'd12; input13 = 32'd13; input14 = 32'd14; + input15 = 32'd15; input16 = 32'd16; input17 = 32'd17; input18 = 32'd18; input19 = 32'd19; + input20 = 32'd20; input21 = 32'd21; input22 = 32'd22; input23 = 32'd23; input24 = 32'd24; + input25 = 32'd25; input26 = 32'd26; input27 = 32'd27; input28 = 32'd28; input29 = 32'd29; + input30 = 32'd30; input31 = 32'd31; + if (out != 20) begin + $display("32 wide 32 deep mux Test Case 1 failed"); + dutpassed = 0; + end + + #5 + endtest = 1; + end +endmodule // mux32to32by1Test + diff --git a/multiplexer.v b/multiplexer.v new file mode 100644 index 0000000..dd4798a --- /dev/null +++ b/multiplexer.v @@ -0,0 +1,56 @@ +// A 32:1 multiplexer. +module mux32to1by1 +( +output out, +input[4:0] address, +input[31:0] inputs +); + assign out = inputs[address]; +endmodule // mux32to1by1 + +module mux32to1by32 +( +output[31:0] out, +input[4:0] address, +input[31:0] input0, input1, input2, input3, input4, input5, input6, input7, input8, +input[31:0] input9, input10, input11, input12, input13, input14, input15, input16, +input[31:0] input17, input18, input19, input20, input21, input22, input23, input24, +input[31:0] input25, input26, input27, input28, input29, input30, input31 +); + + wire[31:0] mux[31:0]; // Create a 2D array of wires + 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]; + +endmodule // mux32to1by32 \ No newline at end of file diff --git a/regfile.t.v b/regfile.t.v index f13815a..059c0ec 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; @@ -117,7 +118,6 @@ output reg Clk 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"); @@ -125,7 +125,6 @@ output reg Clk // 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) WriteRegister = 5'd2; WriteData = 32'd15; RegWrite = 1; @@ -138,6 +137,35 @@ output reg Clk $display("Test Case 2 Failed"); end + // Test Case 3: + // Do not enable writing, check to ensure register + // data is not replaced by WriteData; + WriteRegister = 5'd2; + WriteData = 32'd20; + RegWrite = 0; + ReadRegister1 = 5'd2; + ReadRegister2 = 5'd2; + #5 Clk=1; #5 Clk=0; + + if((ReadData1 != 15) || (ReadData2 != 15)) begin + dutpassed = 0; + $display("Test Case 3 Failed"); + end + + // Test Case 4: + // Attempt to write to the zero register. + // Ensure that the data value is still 32'b0. + WriteRegister = 5'd0; + WriteData = 32'd15; + 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 4 Failed"); + end // All done! Wait a moment and signal test completion. #5 diff --git a/regfile.v b/regfile.v index b8a3c74..893bf11 100644 --- a/regfile.v +++ b/regfile.v @@ -6,22 +6,109 @@ // 1 synchronous, positive edge triggered write port //------------------------------------------------------------------------------ +`include "register.v" +`include "multiplexer.v" +`include "decoders.v" + 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) +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) ); - // 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; + wire[31:0] decoderOut; // Send a wrenable to at most one register. + wire[31:0] register0out; // The output data of the register. + wire[31:0] register1out; + wire[31:0] register2out; + wire[31:0] register3out; + wire[31:0] register4out; + wire[31:0] register5out; + wire[31:0] register6out; + wire[31:0] register7out; + wire[31:0] register8out; + wire[31:0] register9out; + wire[31:0] register10out; + wire[31:0] register11out; + wire[31:0] register12out; + wire[31:0] register13out; + wire[31:0] register14out; + wire[31:0] register15out; + wire[31:0] register16out; + wire[31:0] register17out; + wire[31:0] register18out; + wire[31:0] register19out; + wire[31:0] register20out; + wire[31:0] register21out; + wire[31:0] register22out; + wire[31:0] register23out; + wire[31:0] register24out; + wire[31:0] register25out; + wire[31:0] register26out; + wire[31:0] register27out; + wire[31:0] register28out; + wire[31:0] register29out; + wire[31:0] register30out; + wire[31:0] register31out; + + // The decoder block. + decoder1to32 decoder(decoderOut, RegWrite, WriteRegister); + + // The 32 register blocks. + register32zero reg0 (register0out, WriteData, decoderOut[0], Clk); // The zero register. + register32 reg1 (register1out, WriteData, decoderOut[1], Clk); + register32 reg2 (register2out, WriteData, decoderOut[2], Clk); + register32 reg3 (register3out, WriteData, decoderOut[3], Clk); + register32 reg4 (register4out, WriteData, decoderOut[4], Clk); + register32 reg5 (register5out, WriteData, decoderOut[5], Clk); + register32 reg6 (register6out, WriteData, decoderOut[6], Clk); + register32 reg7 (register7out, WriteData, decoderOut[7], Clk); + register32 reg8 (register8out, WriteData, decoderOut[8], Clk); + register32 reg9 (register9out, WriteData, decoderOut[9], Clk); + register32 reg10 (register10out, WriteData, decoderOut[10], Clk); + register32 reg11 (register11out, WriteData, decoderOut[11], Clk); + register32 reg12 (register12out, WriteData, decoderOut[12], Clk); + register32 reg13 (register13out, WriteData, decoderOut[13], Clk); + register32 reg14 (register14out, WriteData, decoderOut[14], Clk); + register32 reg15 (register15out, WriteData, decoderOut[15], Clk); + register32 reg16 (register16out, WriteData, decoderOut[16], Clk); + register32 reg17 (register17out, WriteData, decoderOut[17], Clk); + register32 reg18 (register18out, WriteData, decoderOut[18], Clk); + register32 reg19 (register19out, WriteData, decoderOut[19], Clk); + register32 reg20 (register20out, WriteData, decoderOut[20], Clk); + register32 reg21 (register21out, WriteData, decoderOut[21], Clk); + register32 reg22 (register22out, WriteData, decoderOut[22], Clk); + register32 reg23 (register23out, WriteData, decoderOut[23], Clk); + register32 reg24 (register24out, WriteData, decoderOut[24], Clk); + register32 reg25 (register25out, WriteData, decoderOut[25], Clk); + register32 reg26 (register26out, WriteData, decoderOut[26], Clk); + register32 reg27 (register27out, WriteData, decoderOut[27], Clk); + register32 reg28 (register28out, WriteData, decoderOut[28], Clk); + register32 reg29 (register29out, WriteData, decoderOut[29], Clk); + register32 reg30 (register30out, WriteData, decoderOut[30], Clk); + register32 reg31 (register31out, WriteData, decoderOut[31], Clk); + + // The multiplexer choosing the data associated with ReadRegister1. + mux32to1by32 mux1 (ReadData1, ReadRegister1, register0out, register1out, + register2out, register3out, register4out, register5out, register6out, + register7out, register8out, register9out, register10out, register11out, + register12out, register13out, register14out, register15out, register16out, + register17out, register18out, register19out, register20out, register21out, + register22out, register23out, register24out, register25out, register26out, + register27out, register28out, register29out, register30out, register31out); + + // The multiplexer choosing the data associated with ReadREegister2. + mux32to1by32 mux2 (ReadData2, ReadRegister2, register0out, register1out, + register2out, register3out, register4out, register5out, register6out, + register7out, register8out, register9out, register10out, register11out, + register12out, register13out, register14out, register15out, register16out, + register17out, register18out, register19out, register20out, register21out, + register22out, register23out, register24out, register25out, register26out, + register27out, register28out, register29out, register30out, register31out); endmodule \ No newline at end of file diff --git a/register.t.v b/register.t.v new file mode 100644 index 0000000..e0821b7 --- /dev/null +++ b/register.t.v @@ -0,0 +1,121 @@ +//-------------------------- +// Test the register modules +//-------------------------- +`include "register.v" + +// Unit tests for the single bit register module. +module registerTest(); + wire q; + reg d; + reg wrenable; + reg clk; + + register DUT (q, d, wrenable, clk); + + initial begin + // Test Case 1: + // Write a 1 to the register. + d = 1; wrenable = 1; + #5 clk = 0; + #5 clk = 1; + if (q != d) begin + $display("Register Test Case 1 failed"); + end + + // Test Case 2: + // Write a 0 to the register. + d = 0; wrenable = 1; + #5 clk = 0; + #5 clk = 1; + if (q != d) begin + $display("Register Test Case 2 failed"); + end + + // Test Case 3: + // Write not enabled, the data written should not match the output. + d = 1; wrenable = 0; + #5 clk = 0; + #5 clk = 1; + if (q == d) begin + $display("Register Test Case 3 failed"); + end + end +endmodule // registerTest + +// Unit tests for the 32 bit register module. +module register32Test(); + + wire[31:0] q; + reg[31:0] d; + reg wrenable; + reg clk; + + register32 DUT (q, d, wrenable, clk); + + initial begin + + // Test Case 1: + // Write to the register + d = 32'hFFFAAA; wrenable = 1; + #5 clk = 0; + #5 clk = 1; + if (q != d) begin + $display("32 bit register Test Case 1 failed"); + end + + // Test Case 2: + // Do not enable writing to register + d = 32'hFFF000; wrenable = 0; + #5 clk = 0; + #5 clk = 1; + if (q == d) begin + $display("32 bit register Test Case 1 failed"); + end + end +endmodule // register32Test + +// Unit tests for the 32 bit zero register module. +module register32zeroTest(); + wire[31:0] q; + reg[31:0] d; + reg wrenable; + reg clk; + + register32zero DUT (q, d, wrenable, clk); + + reg dutpassed; // Flag is set to false if any of the tests fail. + + initial begin + dutpassed = 1; + + // Test Case 1: + // Write to the register + d = 32'hFFFAAA; wrenable = 1; + #5 clk = 0; + #5 clk = 1; + if (q != 0) begin + $display("32 bit zero register Test Case 1 failed"); + dutpassed = 0; + end + + // Test Case 2: + // Do not enable writing to register + #5 + d = 32'hFFF000; wrenable = 0; + #5 clk = 0; + #5 clk = 1; + if (q != 0) begin + $display("32 bit zero register Test Case 2 failed"); + dutpassed = 0; + end + + #5 + + if (dutpassed ==1) begin + $display("All register tests passed."); + end + end +endmodule // register32zeroTest + + + diff --git a/register.v b/register.v index dc9b8cb..8e729ec 100644 --- a/register.v +++ b/register.v @@ -13,5 +13,36 @@ input clk q = d; end end +endmodule // register -endmodule \ No newline at end of file +// 32 bits of D Flip-Flops with enable. +// Positive edge triggered +module register32 +( +output [31:0] q, +input[31:0] d, +input wrenable, +input clk +); + + genvar i; + for (i = 0; i < 32; i = i + 1) begin + register singleRegister (q[i], d[i], wrenable, clk); + end +endmodule // register32 + + +// 1 bit register with constant output 0. +// Inputs are ignored. +module register32zero +( +output [31:0] q, +input[31:0] d, +input wrenable, +input clk +); + genvar i; + for (i = 0; i < 32; i = i + 1) begin + assign q[i] = 1'b0; + end +endmodule // register32zero \ No newline at end of file diff --git a/report.md b/report.md new file mode 100644 index 0000000..8d0848e --- /dev/null +++ b/report.md @@ -0,0 +1,13 @@ + +# HW 4 "Report" + +## Deliverable 1 + + +## Deliverable 6 +Enable is set to be the least significant bit of out. The +value of address (which can be between 0 and 31) indicates +the number of bits out should be be shifted left by. + +So, the decoder selects the register which is being written to (if any) +by using the value of adress. \ No newline at end of file diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..dcca6e7 --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Compile and run the test modules for the register file. + +echo "building tests..." +make && +echo "running register unit tests..." && +./register_test && +echo "running multiplexer unit tests..." && +./mux_test && +echo "running decoder unit tests..." && +./decoder_test && +echo "running regfile test bench..." && +./regfile_test \ No newline at end of file diff --git a/testing_guide.md b/testing_guide.md new file mode 100644 index 0000000..1334adf --- /dev/null +++ b/testing_guide.md @@ -0,0 +1,40 @@ +# How to Run Tests + +*Note: these instructions are specifically for running the tests on a Linux operating system.* + +## Getting Started + +Before being able to run tests, you must compile the verilog files. +To do this, at the command line enter the command `make` This will +compile any of the necessary files to create 4 executables: +* `register_test` unit tests for the register modules. +* `mux_test` unit test for the multiplexer module. +* `decoder_test` unit tests fot the decoder modules. +* `regfile_test` the testbench for the entire register file. + +## Run Single Test + +Enter the command + +```bash +./ +``` + +To run a single file once it has been compiled. If all unit tests pass for a test module, a confirmation of this will be printed to the terminal. The testbench will print "DUT passed? 1" if all tests in the testbench pass. A notice that one or more tests failed will be printed to the terminal otherwise. If the testbench fails, "DUT passed? 0" will be printed to the terminal. + +## Run All Tests + +The script `run_tests.sh` will compile and run all of the tests at once. + +If you are running the script for the first time, you will need to type +```bash +chmod 755 run_tests.sh +``` +In order to gain permission to run the script. + +Once you have gained permission run: +```bash +./run_tests.sh +``` + +If all tests pass, a confirmation of all tests passing for each module and "DUT passed? 1" will be printed to the terminal. Otherwise, notice that one or more tests failed will be printed to the terminal.