module datapath_tb(); //Signals for regfile testbench reg err; reg [15:0] datapath_in; reg [2:0] writenum, readnum; reg [1:0] shift, ALUop; reg write, clk, loada, loadb, loadc, loads, asel, bsel, vsel; wire [15:0] datapath_out; wire Z_out; datapath DUT (datapath_in, writenum, write, readnum, clk, //reference to main datapath file being testbenched loada, loadb, loadc, loads, asel, bsel, vsel, shift, ALUop, datapath_out, Z_out); task datapathcheck; input [15:0] expected_datapath_out; //providing what output should be input expected_z_out; //providing what Z should be begin if(datapath_tb.DUT.datapath_out !== expected_datapath_out) begin //outputs error if output isn't matching expected $display("ERROR: output is %b, expected %b", datapath_tb.DUT.datapath_out, expected_datapath_out); err = 1'b1; end if(datapath_tb.DUT.Z_out !== expected_z_out) begin //outputs error if Z isnt matching $display("ERROR: Z is %b, expected %b", datapath_tb.DUT.Z_out, expected_z_out); err = 1'b1; end end endtask initial begin clk = 1'b0; #5; //repeating clock in 5ps second intervals forever begin clk = 1'b1; #5; clk = 1'b0; #5; end end initial begin err = 1'b0; $display("Testing input 32"); datapath_in = 16'b0000000000100000; vsel = 1'b1; //use datapath_in write = 1'b1; //allow writing writenum = 3'b101; //write to reg 5 readnum = 3'b101; //read from reg 5 loada = 1'b1; loadb = 1'b1; loadc = 1'b1; loads = 1'b1; //allow the datapath_in inputs through shift = 2'b00; //no shift asel = 1'b0; bsel = 1'b0; ALUop = 2'b11; //use datapath_in inputs and inverse input #26; datapathcheck(16'b1111111111011111, 1'b0); #4; $display("Testing input 108"); datapath_in = 16'b0000000001101100; vsel = 1'b1; write = 1'b1; writenum = 3'b111; //reg 7 read and write readnum = 3'b111; loada = 1'b1; loadb = 1'b1; loadc = 1'b1; loads = 1'b1; shift = 2'b10; //shift right asel = 1'b0; bsel = 1'b0; ALUop = 2'b10; //ANDing inputs #26; datapathcheck(16'b0000000000100100, 1'b0); #4; $display("Testing input 6"); datapath_in = 16'b0000000000000110; vsel = 1'b1; write = 1'b1; writenum = 3'b000; //reg 0 read and write readnum = 3'b000; loada = 1'b1; loadb = 1'b1; loadc = 1'b1; loads = 1'b1; shift = 2'b01; //shift left asel = 1'b1; bsel = 1'b0; ALUop = 2'b00; //use zeros as left input //add the two inputs #26; datapathcheck(16'b0000000000001100, 1'b0); #4; $display("Testing input 1"); datapath_in = 16'b0000000000000001; vsel = 1'b0; //use datapath_out write = 1'b1; writenum = 3'b010; //reg 2 read and write readnum = 3'b010; loada = 1'b1; loadb = 1'b1; loadc = 1'b1; loads = 1'b1; shift = 2'b10; //shift right asel = 1'b0; bsel = 1'b0; ALUop = 2'b01; //subtract the two inputs #26; datapathcheck(16'b0000000000000110, 1'b0); #4; $display("Testing input 99"); datapath_in = 16'b0000000001100011; vsel = 1'b1; write = 1'b1; writenum = 3'b001; //reg 1 read and write readnum = 3'b001; loada = 1'b1; loadb = 1'b1; loadc = 1'b1; loads = 1'b1; shift = 2'b00; //no shift asel = 1'b0; bsel = 1'b0; ALUop = 2'b01; //subtract the two inputs #26; datapathcheck(16'b0000000000000000, 1'b1); //output is zero so Z is 1 #4; $display("Testing input 4"); datapath_in = 16'b0000000000000100; vsel = 1'b1; write = 1'b1; writenum = 3'b010; //reg 2 read and write readnum = 3'b010; loada = 1'b1; loadb = 1'b1; loadc = 1'b0; loads = 1'b0; //dont allow updated datapath_in and Z data shift = 2'b00; //no shift asel = 1'b0; bsel = 1'b0; ALUop = 2'b01; //subtraction #26; datapathcheck(16'b0000000000000000, 1'b1); //outputs are old outputs from previous test #4; $display("Testing input 4"); datapath_in = 16'b0000000000000100; vsel = 1'b1; write = 1'b1; writenum = 3'b100; //reg 4 write readnum = 3'b011; //reg 3 read loada = 1'b1; loadb = 1'b1; loadc = 1'b1; loads = 1'b1; shift = 2'b00; //no shift asel = 1'b0; bsel = 1'b0; ALUop = 2'b01; //subtraction #26; datapathcheck({16{1'bx}}, 1'b0); //output is don't care since reading from non-written register #4; if(~err) $display("PASSED"); else $display("FAILED"); #290; end endmodule