diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb2ebfc --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +work/ +transcript +vsim.wlf +waveform.vcd \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a48a76e --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +# Default target +all: run + +# Run the simulation +run: + cd ./tools/sim && vsim -c -do run.do && cd ../.. + +# Clean the build files +clean: + rm -rf ./tools/sim/work ./tools/sim/transcript ./tools/sim/vsim.wlf ./tools/sim/waveform.vcd + rm -rf transcript + +# View the waveform +view: + vsim -view ./tools/sim/vsim.wlf + +.PHONY: all compile run clean view diff --git a/README.md b/README.md index 26273ad..0f278cb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# NAME-of-REPO +# CPU Regfiles -Blah.. blah.. blah +The 31x64-bit register file with a read and write port used on the [Arm-compliant CPU](https://git.long-vega.ts.net/eyhc/Pipline_Arm_CPU). diff --git a/src/hdl/DFF_with_enable.sv b/src/hdl/DFF_with_enable.sv new file mode 100644 index 0000000..ce6a06b --- /dev/null +++ b/src/hdl/DFF_with_enable.sv @@ -0,0 +1,16 @@ +// eneabled dff using 2:1 mux and dff +`timescale 1ns/10ps +module DFF_with_enable (d, reset, clk, en, q); + input logic d, reset, clk, en; + output logic q; + + // internal wire to connect mux to the dff + logic in; + + // a 2:1 mux that when enabled intput d is dff's output q, otherwise loop q back into itself + mux2_1 m1 (in, q, d, en); + + D_FF d1 (q, in, reset, clk); + +endmodule + diff --git a/src/hdl/D_FF.sv b/src/hdl/D_FF.sv new file mode 100644 index 0000000..7bb80e2 --- /dev/null +++ b/src/hdl/D_FF.sv @@ -0,0 +1,11 @@ +// Data Flip Flop +module D_FF (q, d, reset, clk); + output reg q; + input d, reset, clk; + + always_ff @(posedge clk) + if (reset) + q <= 0; // On reset, set to 0 + else + q <= d; // Otherwise out = d +endmodule \ No newline at end of file diff --git a/src/hdl/decoder_2x4.sv b/src/hdl/decoder_2x4.sv new file mode 100644 index 0000000..4e161d2 --- /dev/null +++ b/src/hdl/decoder_2x4.sv @@ -0,0 +1,24 @@ +// Test bench for Register file +`timescale 1ns/10ps + +module decoder_2x4(in, en, out); + // 2 bit input, 4 bit output + input logic [1:0] in; + input logic en; + output logic [3:0] out; + + // store !in + logic [1:0] not_in; + + // !in inverting logic + not #0.05 not0(not_in[0], in[0]); + not #0.05 not1(not_in[1], in[1]); + + // out logic + and #0.05 and0(out[0], not_in[0], not_in[1], en); + and #0.05 and1(out[1], in[0], not_in[1], en); + and #0.05 and2(out[2], not_in[0], in[1], en); + and #0.05 and3(out[3], in[0], in[1], en); + +endmodule + diff --git a/src/hdl/decoder_3x8.sv b/src/hdl/decoder_3x8.sv new file mode 100644 index 0000000..1dc3ba7 --- /dev/null +++ b/src/hdl/decoder_3x8.sv @@ -0,0 +1,29 @@ +// a gate-level 3 by 8 decoder +`timescale 1ns/10ps +module decoder_3x8 (in, en, out); + // 3 bit input, 8 bit output + input logic [2:0] in; + input logic en; + output logic [7:0] out; + + // store !in + logic [2:0] not_in; + + // !in inverting logic + not #0.05 not0(not_in[0], in[0]); + not #0.05 not1(not_in[1], in[1]); + not #0.05 not2(not_in[2], in[2]); + + // out logic + and #0.05 out0(out[0], not_in[0], not_in[1], not_in[2], en); + and #0.05 out1(out[1], not_in[2], not_in[1], in[0], en); + and #0.05 out2(out[2], not_in[2], in[1], not_in[0], en); + and #0.05 out3(out[3], not_in[2], in[1], in[0], en); + and #0.05 out4(out[4], in[2], not_in[1], not_in[0], en); + and #0.05 out5(out[5], in[2], not_in[1], in[0], en); + and #0.05 out6(out[6], in[2], in[1], not_in[0], en); + and #0.05 out7(out[7], in[0], in[1], in[2], en); + +endmodule + +// tb diff --git a/src/hdl/decoder_5x32.sv b/src/hdl/decoder_5x32.sv new file mode 100644 index 0000000..1589144 --- /dev/null +++ b/src/hdl/decoder_5x32.sv @@ -0,0 +1,19 @@ +// 5 to 32 using basic gates +`timescale 1ns/10ps +module decoder_5x32(in, out, en); + // 5 bits input, 32 bit output + input logic [4:0] in; + input logic en; + output logic [31:0] out; + + // create local wires for the 2x4 decoder to the four 3x8 decoders + logic [3:0] decoder_2x4_out; + + // using one 2x4 decoder to conect and enable four 3x8 decoders to make a 5x32 decoder + decoder_2x4 dec0(in[4:3], en, decoder_2x4_out[3:0]); + decoder_3x8 dec1(in[2:0], decoder_2x4_out[0], out[7:0]); + decoder_3x8 dec2(in[2:0], decoder_2x4_out[1], out[15:8]); + decoder_3x8 dec3(in[2:0], decoder_2x4_out[2], out[23:16]); + decoder_3x8 dec4(in[2:0], decoder_2x4_out[3], out[31:24]); +endmodule + diff --git a/src/hdl/mux16.sv b/src/hdl/mux16.sv new file mode 100644 index 0000000..1f26215 --- /dev/null +++ b/src/hdl/mux16.sv @@ -0,0 +1,16 @@ +// create a 16:1 mux from two 8:1 mux which by a 2:1 mux +`timescale 1ns/10ps +module mux16 (out, in, sel); + input logic [15:0] in; + input logic [3:0] sel; + output logic out; + + // internal wire to connect the muxes input/output + logic w1, w2, w3; + + // two mux 8:1 which output connects to a 2:1 mux + mux8 m1 (.out(w1), .in(in[7:0]), .sel(sel[2:0])); + mux8 m2 (.out(w2), .in(in[15:8]), .sel(sel[2:0])); + mux2_1 m3 (.out, .i0(w1), .i1(w2), .sel(sel[3])); +endmodule + diff --git a/src/hdl/mux2_1.sv b/src/hdl/mux2_1.sv new file mode 100644 index 0000000..d777ff6 --- /dev/null +++ b/src/hdl/mux2_1.sv @@ -0,0 +1,17 @@ +// a gate-level 2:1 mux +`timescale 1ns/10ps +module mux2_1 #(parameter DELAY_NS=0.05) (out, i0, i1, sel); + // 2 bit input, 1 bit selector, and 1 bit output + output logic out; + input logic i0, i1, sel; + + // wire inverting selector bit, and the output of two and gate + logic invSel, nand1, nand2; + + // out logic + not #DELAY_NS nselect(invSel, sel); + nand #DELAY_NS u1(nand1, i1, sel); + nand #DELAY_NS u2(nand2, i0, invSel); + nand #DELAY_NS res(out, nand1, nand2); +endmodule + diff --git a/src/hdl/mux32.sv b/src/hdl/mux32.sv new file mode 100644 index 0000000..e74b707 --- /dev/null +++ b/src/hdl/mux32.sv @@ -0,0 +1,16 @@ +// create a 32:1 mux from two 16:1 mux which by a 2:1 mux +`timescale 1ns/10ps +module mux32(out, in, sel); + input logic [31:0] in; + input logic [4:0] sel; + output logic out; + + // internal wire to connect the muxes input/output + logic w1, w2, w3; + + // two mux 16:1 which output connects to a 2:1 mux + mux16 m1 (.out(w1), .in(in[15:0]), .sel(sel[3:0])); + mux16 m2 (.out(w2), .in(in[31:16]), .sel(sel[3:0])); + mux2_1 m3 (.out, .i0(w1), .i1(w2), .sel(sel[4])); +endmodule + diff --git a/src/hdl/mux32_64.sv b/src/hdl/mux32_64.sv new file mode 100644 index 0000000..6541697 --- /dev/null +++ b/src/hdl/mux32_64.sv @@ -0,0 +1,27 @@ +// 64 bits 32:1 mux from 64 31:1 mux +`timescale 1ns/10ps +module mux32_64 #(parameter WIDTH=64, ADDR=5) (readDat, datIn, readReg); + input logic [31:0][WIDTH - 1:0] datIn; + input logic [ADDR - 1:0] readReg; + output logic [WIDTH - 1:0] readDat; + + // internal wire that transposed the width and depth of the module's data to 64 mux32:1's data + logic [WIDTH - 1 : 0][31:0] transposed; + integer j, k; + // wire 32 64-bit-DFF's buses to 64 32:1 mux's + always_comb begin + for (j = 0; j < WIDTH; j++) begin + for (k = 0; k < 32; k++) begin + transposed[j][k] = datIn[k][j]; + end + end + end + // generate 64 of 32:1 mux + genvar i; + generate + for (i = 0; i < WIDTH; i ++) begin : genmux + mux32 muxes (.out(readDat[i]), .in(transposed[i]), .sel(readReg)); + end + endgenerate +endmodule + diff --git a/src/hdl/mux4_1.sv b/src/hdl/mux4_1.sv new file mode 100644 index 0000000..c46ddd8 --- /dev/null +++ b/src/hdl/mux4_1.sv @@ -0,0 +1,18 @@ +// create a 4:1 mux from two 2:1 mux with another 2:1 mux +`timescale 1ns/10ps +module mux4_1 (out, in, sel); + input logic [3:0] in; + input logic [1:0] sel; + output logic out; + + // internal wire to connect the muxes input/output + logic w1, w2, w3; + + // two mux 2:1 which output connects to a third 2:1 mux + mux2_1 m1 (.out(w1), .i0(in[0]), .i1(in[1]), .sel(sel[0])); + mux2_1 m2 (.out(w2), .i0(in[2]), .i1(in[3]), .sel(sel[0])); + mux2_1 m3 (.out, .i0(w1), .i1(w2), .sel(sel[1])); + + +endmodule + diff --git a/src/hdl/mux8.sv b/src/hdl/mux8.sv new file mode 100644 index 0000000..1e7d98e --- /dev/null +++ b/src/hdl/mux8.sv @@ -0,0 +1,18 @@ +// create a 8:1 mux from two 4:1 mux which by a 2:1 mux +`timescale 1ns/10ps +module mux8 (out, in, sel); + input logic [7:0] in; + input logic [2:0] sel; + output logic out; + + // internal wire to connect the muxes input/output + logic w1, w2, w3; + + // two mux 4:1 which output connects to a 2:1 mux + mux4_1 m1 (.out(w1), .in(in[3:0]), .sel(sel[1:0])); + mux4_1 m2 (.out(w2), .in(in[7:4]), .sel(sel[1:0])); + mux2_1 m3 (.out, .i0(w1), .i1(w2), .sel(sel[2])); + + +endmodule + diff --git a/src/hdl/reg16.sv b/src/hdl/reg16.sv new file mode 100644 index 0000000..2a70216 --- /dev/null +++ b/src/hdl/reg16.sv @@ -0,0 +1,15 @@ +// a 16-bit register from four 4-bit registers +`timescale 1ns/10ps +module reg16 (in, out, en, clk, reset); + input logic [15:0] in; + input logic en, clk, reset; + output logic [15:0] out; + + // 4 DFF_E, each represents 1 bit in the register + reg4 r0 (in[3:0], out[3:0], en, clk, reset); + reg4 r1 (in[7:4], out[7:4], en, clk, reset); + reg4 r2 (in[11:8], out[11:8], en, clk, reset); + reg4 r3 (in[15:12], out[15:12], en, clk, reset); + +endmodule + diff --git a/src/hdl/reg4.sv b/src/hdl/reg4.sv new file mode 100644 index 0000000..c850594 --- /dev/null +++ b/src/hdl/reg4.sv @@ -0,0 +1,15 @@ +// four bits register from four enabled register +`timescale 1ns/10ps +module reg4 (in, out, en, clk, reset); + input logic [3:0] in; + input logic en, clk, reset; + output logic [3:0] out; + + // 4 DFF_E, each represents 1 bit in the register + DFF_with_enable d0 (in[0], reset, clk, en, out[0]); + DFF_with_enable d1 (in[1], reset, clk, en, out[1]); + DFF_with_enable d2 (in[2], reset, clk, en, out[2]); + DFF_with_enable d3 (in[3], reset, clk, en, out[3]); + +endmodule + diff --git a/src/hdl/reg64.sv b/src/hdl/reg64.sv new file mode 100644 index 0000000..8366b1d --- /dev/null +++ b/src/hdl/reg64.sv @@ -0,0 +1,15 @@ +// a 64-bit enabled register from four 16-bit registers +`timescale 1ns/10ps +module reg64 (in, out, en, clk, reset); + input logic [63:0] in; + input logic en, clk, reset; + output logic [63:0] out; + + // 4 DFF_Enabled, each represents 1 bit in the register + reg16 r0 (in[15:0], out[15:0], en, clk, reset); + reg16 r1 (in[31:16], out[31:16], en, clk, reset); + reg16 r2 (in[47:32], out[47:32], en, clk, reset); + reg16 r3 (in[63:48], out[63:48], en, clk, reset); + +endmodule + diff --git a/src/hdl/reg64x32.sv b/src/hdl/reg64x32.sv new file mode 100644 index 0000000..8949604 --- /dev/null +++ b/src/hdl/reg64x32.sv @@ -0,0 +1,20 @@ +// 32 64-bits dff connected in parallel +`timescale 1ns/10ps +module reg64x32 (in, out, en, clk, reset); + input logic [63:0] in; + input logic [31:0] en; + input logic clk, reset; + output logic [31:0][63:0] out; + + genvar i; + // use for loop to generate an array of 31 64-bit registers + generate + for (i = 0; i < 31; i++) begin : manyDFFs + reg64 bigReg (.in(in), .out(out[i]), .en(en[i]), .clk, .reset); + end + endgenerate + + // the 32nd register is the zero register, always write zero to it. + reg64 reg0 (.in(64'd0), .out(out[31]), .en(1'b1), .clk, .reset); +endmodule + diff --git a/src/hdl/regfile.sv b/src/hdl/regfile.sv new file mode 100644 index 0000000..cdb222b --- /dev/null +++ b/src/hdl/regfile.sv @@ -0,0 +1,32 @@ +// toplevel for register file, with two 5-bit read selector input and one 5-bit write inputs, and takes in 64-bit data and returns two 63-bit data depends on the output, with write enebled option +`timescale 1ns/10ps +module regfile(RegWrite, clk, ReadRegister1, ReadRegister2, WriteData, WriteRegister, ReadData1, ReadData2); + input logic RegWrite; + input logic clk; + input logic [4:0] ReadRegister1; + input logic [4:0] ReadRegister2; + input logic [63:0] WriteData; + input logic [4:0] WriteRegister; + output logic [63:0] ReadData1; + output logic [63:0] ReadData2; + + // generate wires to connect decodes to DFF's enable, and from DFF data to two muxes + logic [31:0] en; + logic [31:0][63:0] dataBus; + + // call the array of 32 64-bit registers + reg64x32 regs(.clk(clk), .reset(1'b0), .en, .in(WriteData), .out(dataBus)); + + // create two 64-bit 31:1 muxes to allow select different register output + mux32_64 mux1(.datIn(dataBus), .readReg(ReadRegister1), .readDat(ReadData1)); + // defined the mux's selector bits and inputs bit + defparam mux1.ADDR = 5; + defparam mux1.WIDTH = 64; + + mux32_64 mux2( .datIn(dataBus), .readReg(ReadRegister2), .readDat(ReadData2)); + defparam mux2.ADDR = 5; + defparam mux2.WIDTH = 64; + + // connect the 5x32 decoder to the 64bit registers to allow at most only one register to be able to get write value each time + decoder_5x32 decoder(.en(RegWrite), .in(WriteRegister), .out(en)); +endmodule diff --git a/src/tb/DFF_with_enable_tb.sv b/src/tb/DFF_with_enable_tb.sv new file mode 100644 index 0000000..5a32ff1 --- /dev/null +++ b/src/tb/DFF_with_enable_tb.sv @@ -0,0 +1,26 @@ +module DFF_with_enable_testbench(); + + logic d, q, reset, clk, en; + + DFF_with_enable dut (.d, .reset, .clk, .en, .q); + + // Set up a simulated clock. + parameter CLOCK_PERIOD=10; + initial begin + clk <= 0; + forever #(CLOCK_PERIOD/2) clk <= ~clk; // Forever toggle the clock + end + + // Set up the inputs to the design. Each line is a clock cycle. + initial begin + reset <= 1; @(posedge clk); // Always reset FSMs at start + // check if enable works properly by writing data when turn on enable + reset <= 0; d <= 1; q <= 0; en <= 0; @(posedge clk); + en <= 1; @(posedge clk); + d <= 0; @(posedge clk); + // check if data output would stay when enable is off + en <= 0; @(posedge clk); + repeat(2) @(posedge clk); + $stop; // End the simulation. + end +endmodule \ No newline at end of file diff --git a/src/tb/decoder_2x4_tb.sv b/src/tb/decoder_2x4_tb.sv new file mode 100644 index 0000000..8bae496 --- /dev/null +++ b/src/tb/decoder_2x4_tb.sv @@ -0,0 +1,20 @@ +module decoder_2x4_testbench(); + logic [1:0] in; + logic en; + logic [3:0] out; + + decoder_2x4 dut (.in, .en, .out); + + integer i, j; + + initial begin // Test all input variations + for(i=0; i<4; i++) begin + en = 1; + in[1:0] = i; #1; + end + for(j=0; j<4; j++) begin + en = 0; + in[1:0] = j; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/decoder_3x8_tb.sv b/src/tb/decoder_3x8_tb.sv new file mode 100644 index 0000000..2b8d7b3 --- /dev/null +++ b/src/tb/decoder_3x8_tb.sv @@ -0,0 +1,21 @@ +module decoder_3x8_testbench(); + logic [2:0] in; + logic [7:0] out; + logic en; + logic [2:0] not_in; + + decoder_3x8 dut (.in, .en, .out); + + integer i, j; + + initial begin // Test all input variations + for(i=0; i<8; i++) begin + en = 1; + in[2:0] = i; #1; + end + for(j=0; j<8; j++) begin + en = 0; + in[2:0] = j; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/decoder_5x32_tb.sv b/src/tb/decoder_5x32_tb.sv new file mode 100644 index 0000000..d2047aa --- /dev/null +++ b/src/tb/decoder_5x32_tb.sv @@ -0,0 +1,22 @@ +module decoder_5x32_testbench(); + logic [4:0] in; + logic en; + logic [31:0] out; + + logic [3:0] decoder_2x4_out; + + decoder_5x32 dut (.in, .en, .out); + + integer i, j; + + initial begin // Test all input variations + for(i=0; i<32; i++) begin + en = 1; + in[4:0] = i; #1; + end + for(j=0; j<32; j++) begin + en = 0; + in[4:0] = j; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/mux16_tb.sv b/src/tb/mux16_tb.sv new file mode 100644 index 0000000..44860ba --- /dev/null +++ b/src/tb/mux16_tb.sv @@ -0,0 +1,13 @@ +module mux16_testbench(); + logic [15:0] in; + logic [3:0] sel; + logic out; + mux16 dut (.*); + + integer i; + initial begin // Test all input variations + for (i = 0; i < 2**20; i++) begin + {in, sel} = i; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/mux2_1_tb.sv b/src/tb/mux2_1_tb.sv new file mode 100644 index 0000000..1ab7aff --- /dev/null +++ b/src/tb/mux2_1_tb.sv @@ -0,0 +1,12 @@ +module mux2_1_testbench(); + logic i0, i1, sel; + logic out; + mux2_1 dut (.out, .i0, .i1, .sel); + + integer i; + initial begin // Test all input variations + for (i = 0; i < 2**3; i++) begin + {i0, i1, sel} = i; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/mux32_64_tb.sv b/src/tb/mux32_64_tb.sv new file mode 100644 index 0000000..702793e --- /dev/null +++ b/src/tb/mux32_64_tb.sv @@ -0,0 +1,17 @@ +module mux32_64_testbench(); + logic [31:0][63:0] datIn; + logic [4:0] readReg; + logic [63:0] readDat; + mux32_64 dut (.*); + + integer i; + initial begin + for (i=0; i<32; i=i+1) begin + datIn[i] = i * 64'h00000000000000A0; // addr # multiplies a fixed hex seed + end + + for (i = 0; i < 2**5; i++) begin + readReg = i; #10; // select an addr to output + end + end +endmodule \ No newline at end of file diff --git a/src/tb/mux32_tb.sv b/src/tb/mux32_tb.sv new file mode 100644 index 0000000..bee7216 --- /dev/null +++ b/src/tb/mux32_tb.sv @@ -0,0 +1,13 @@ +module mux32_testbench(); + logic [31:0] in; + logic [4:0] sel; + logic out; + mux32 dut (.*); + + integer i; + initial begin // Test all input variations + for (i = 0; i < 2**10; i++) begin + {in, sel} = i; #1; + end + end +endmodule diff --git a/src/tb/mux4_1_tb.sv b/src/tb/mux4_1_tb.sv new file mode 100644 index 0000000..ba0fa36 --- /dev/null +++ b/src/tb/mux4_1_tb.sv @@ -0,0 +1,13 @@ +module mux4_1_testbench(); + logic [3:0] in; + logic [1:0] sel; + logic out; + mux4_1 dut (.*); + + integer i; + initial begin // Test all input variations + for (i = 0; i < 2**6; i++) begin + {in, sel} = i; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/mux8_tb.sv b/src/tb/mux8_tb.sv new file mode 100644 index 0000000..2c3b853 --- /dev/null +++ b/src/tb/mux8_tb.sv @@ -0,0 +1,13 @@ +module mux8_testbench(); + logic [7:0] in; + logic [2:0] sel; + logic out; + mux8 dut (.*); + + integer i; + initial begin // Test all input variations + for (i = 0; i < 2**11; i++) begin + {in, sel} = i; #1; + end + end +endmodule \ No newline at end of file diff --git a/src/tb/reg16_tb.sv b/src/tb/reg16_tb.sv new file mode 100644 index 0000000..eaf7f52 --- /dev/null +++ b/src/tb/reg16_tb.sv @@ -0,0 +1,27 @@ +module reg16_testbench(); + + logic [15:0] in, out; + logic reset, clk, en; + + reg16 dut (.in, .out, .en, .clk, .reset); + + // Set up a simulated clock. + parameter CLOCK_PERIOD=10; + initial begin + clk <= 0; + forever #(CLOCK_PERIOD/2) clk <= ~clk; // Forever toggle the clock + end + + initial begin + reset <= 1; @(posedge clk); // Always reset FSMs at start + // write in some values and check if register values stays when enable is low, or if is writes in if enable is high. + reset <= 0; en <= 0; in <= 4'd65536; @(posedge clk); + en <= 1; in <= 16'd11451; @(posedge clk); + en <= 1; in <= 16'd19198; @(posedge clk); + en <= 0; in <= 16'd19198; @(posedge clk); + en <= 0; in <= 16'd14; @(posedge clk); + en <= 1; in <= 16'd32; @(posedge clk); + repeat(2) @(posedge clk); + $stop; + end +endmodule \ No newline at end of file diff --git a/src/tb/reg4_tb.sv b/src/tb/reg4_tb.sv new file mode 100644 index 0000000..09e5dfa --- /dev/null +++ b/src/tb/reg4_tb.sv @@ -0,0 +1,27 @@ +module reg4_testbench(); + + logic [3:0] in, out; + logic reset, clk, en; + + reg4 dut (.in, .out, .en, .clk, .reset); + + // Set up a simulated clock. + parameter CLOCK_PERIOD=10; + initial begin + clk <= 0; + forever #(CLOCK_PERIOD/2) clk <= ~clk; // Forever toggle the clock + end + + initial begin + reset <= 1; @(posedge clk); // Always reset FSMs at start + // write in some values and check if register values stays when enable is low, or if is writes in if enable is high. + reset <= 0; en <= 0; in <= 4'b1111; @(posedge clk); + en <= 1; in <= 4'b1111; @(posedge clk); + en <= 1; in <= 4'b1001; @(posedge clk); + en <= 0; in <= 4'b1001; @(posedge clk); + en <= 0; in <= 4'b1111; @(posedge clk); + en <= 1; in <= 4'b0000; @(posedge clk); + repeat(2) @(posedge clk); + $stop; + end +endmodule \ No newline at end of file diff --git a/src/tb/reg64_tb.sv b/src/tb/reg64_tb.sv new file mode 100644 index 0000000..1a16a18 --- /dev/null +++ b/src/tb/reg64_tb.sv @@ -0,0 +1,27 @@ +module reg64_testbench(); + + logic [63:0] in, out; + logic reset, clk, en; + + reg64 dut (.in, .out, .en, .clk, .reset); + + // Set up a simulated clock. + parameter CLOCK_PERIOD=10; + initial begin + clk <= 0; + forever #(CLOCK_PERIOD/2) clk <= ~clk; // Forever toggle the clock + end + + initial begin + reset <= 1; @(posedge clk); // Always reset FSMs at start + // write in some values and check if register values stays when enable is low, or if is writes in if enable is high. + reset <= 0; en <= 0; in <= 64'd4254663563463457; @(posedge clk); + en <= 1; in <= 64'd1145141919810; @(posedge clk); + en <= 1; in <= 64'd8689689680; @(posedge clk); + en <= 0; in <= 64'd0; @(posedge clk); + en <= 0; in <= 64'd8689689680; @(posedge clk); + en <= 1; in <= 64'd1145141919810; @(posedge clk); + repeat(2) @(posedge clk); + $stop; + end +endmodule \ No newline at end of file diff --git a/src/tb/reg64x32_tb.sv b/src/tb/reg64x32_tb.sv new file mode 100644 index 0000000..7a58835 --- /dev/null +++ b/src/tb/reg64x32_tb.sv @@ -0,0 +1,48 @@ +module reg64x32_testbench(); + logic [63:0] in; + logic [31:0] en; + logic clk, reset; + logic [31:0][63:0] out; // output + + integer i; + + assign reset = 1'b0; + + reg64x32 dut (.*); + + initial $timeformat(-9, 2, " ns", 10); + + initial begin // Set up the clock + clk <= 0; + forever #(5000/2) clk <= ~clk; // clk delay is 5000 + end + + initial begin + // Try to write the value 0xA0 into register 31. + // Register 31 should always be at the value of 0. + $display("%t Attempting overwrite of register 31, which should always be 0", $time); + en <= 31'b1 << 31; + in <= 64'h00000000000000A0; + @(posedge clk); + // $display("%t Writing pattern to all registers.", $time); + for (i=0; i<31; i=i+1) begin + en <= 0; + @(posedge clk); + $display("%t Writing pattern to %i", $time, i); + en <= 31'b1 << i; + in <= i*64'h0000010204080001; + @(posedge clk); + end + // Go back and verify that the registers + // retained the data. + $display("%t Checking pattern.", $time); + en <= 31'b0; + for (i=0; i<32; i=i+1) begin + // WriteRegister <= i; + in <= i*64'h0000000000000100+i; + @(posedge clk); + end + $stop; + end + +endmodule \ No newline at end of file diff --git a/src/tb/regstim.sv b/src/tb/regstim.sv new file mode 100644 index 0000000..2ef0117 --- /dev/null +++ b/src/tb/regstim.sv @@ -0,0 +1,79 @@ +// Test bench for Register file +`timescale 1ns/10ps + +module regstim(); + + parameter ClockDelay = 5000; + + logic [4:0] ReadRegister1, ReadRegister2, WriteRegister; + logic [63:0] WriteData; + logic RegWrite, clk; + logic [63:0] ReadData1, ReadData2; + + integer i; + + // Your register file MUST be named "regfile". + // Also you must make sure that the port declarations + // match up with the module instance in this stimulus file. + regfile dut (.ReadData1, .ReadData2, .WriteData, + .ReadRegister1, .ReadRegister2, .WriteRegister, + .RegWrite, .clk); + + // Force %t's to print in a nice format. + initial $timeformat(-9, 2, " ns", 10); + + initial begin // Set up the clock + clk <= 0; + forever #(ClockDelay/2) clk <= ~clk; + end + + initial begin + // Try to write the value 0xA0 into register 31. + // Register 31 should always be at the value of 0. + RegWrite <= 5'd0; + ReadRegister1 <= 5'd0; + ReadRegister2 <= 5'd0; + WriteRegister <= 5'd31; + WriteData <= 64'h00000000000000A0; + @(posedge clk); + + $display("%t Attempting overwrite of register 31, which should always be 0", $time); + RegWrite <= 1; + @(posedge clk); + + // Write a value into each register. + $display("%t Writing pattern to all registers.", $time); + for (i=0; i<31; i=i+1) begin + RegWrite <= 0; + ReadRegister1 <= i-1; + ReadRegister2 <= i; + WriteRegister <= i; + WriteData <= i*64'h0000010204080001; + @(posedge clk); + RegWrite <= 1; + @(posedge clk); + end + + // Go back and verify that the registers + // retained the data. + $display("%t Checking pattern.", $time); + for (i=0; i<32; i=i+1) begin + RegWrite <= 0; + ReadRegister1 <= i-1; + ReadRegister2 <= i; + WriteRegister <= i; + WriteData <= i*64'h0000000000000100+i; + @(posedge clk); + + if (ReadData1 !== (i-1)*64'h0000010204080001 && i-1 >= 0) begin + $error("%t ReadData1 mismatch at register %d: \n\tExpected %h, got %h", $time, i, (i-1)*64'h0000010204080001, ReadData1); + end + + if (ReadData2 !== i*64'h0000010204080001 && i != 31) begin + $error("%t ReadData2 mismatch at register %d: \n\tExpected %h, got %h", $time, i, i*64'h0000010204080001, ReadData2); + end + + end + $finish; + end +endmodule diff --git a/tools/sim/run.do b/tools/sim/run.do new file mode 100644 index 0000000..55d6219 --- /dev/null +++ b/tools/sim/run.do @@ -0,0 +1,8 @@ +vlib work +vlog ../../src/hdl/* +vlog ../../src/tb/* +vsim work.regstim +log * -r +vcd file waveform.vcd +vcd add -r /* +run -all \ No newline at end of file