`timescale 1us/1us module instruction_decode_tb; logic [15:0] tst_instruction, tst_result; logic tst_destination_A, tst_destination_D, tst_destination_pA; logic [15:0] tst_data_A, tst_data_D, tst_data_pA; logic tst_should_jump; instruction_decode uut ( .instruction_in(tst_instruction), .dst_A_out(tst_destination_A), .dst_D_out(tst_destination_D), .dst_pA_out(tst_destination_pA), .A_in(tst_data_A), .D_in(tst_data_D), .pA_in(tst_data_pA), .result_out(tst_result), .do_jump_out(tst_should_jump) ); string filename; initial begin `ifdef DUMP_FILE_NAME filename=`DUMP_FILE_NAME; `else filename="instruction_decode.lxt2"; `endif $dumpfile(filename); $dumpvars(); end `define TB_CHECK(result, expected) assert(result == expected) else $error("Expected %x, got %x", expected, result); initial begin #1 // LDI 0 tst_instruction = 0; tst_data_A = 0; tst_data_D = 0; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 0); `TB_CHECK(tst_destination_A, 1); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // LDI ff tst_instruction = 'hff; tst_data_A = 0; tst_data_D = 0; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'hff); `TB_CHECK(tst_destination_A, 1); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // Unless otherwise specified, // X=D // Y=A // (nodest) = D & A tst_instruction = 'h8000; tst_data_A = 0; tst_data_D = 0; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'h00); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // A = D & A tst_instruction = 'h8020; tst_data_A = 0; tst_data_D = 0; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'h0); `TB_CHECK(tst_destination_A, 1); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // D = D & A tst_instruction = 'h8010; tst_data_A = 0; tst_data_D = 0; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'h0); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 1); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // M = D & A tst_instruction = 'h8008; tst_data_A = 0; tst_data_D = 0; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'h0); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 1); `TB_CHECK(tst_should_jump, 0); #1 // (result) = D & A tst_instruction = 'h8000; tst_data_A = 'b1100; tst_data_D = 'b1010; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'b1000); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = D | A tst_instruction = 'h8100; tst_data_A = 'b1100; tst_data_D = 'b1010; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'b1110); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = A ^ D tst_instruction = 'h8200; tst_data_A = 'b1100; tst_data_D = 'b1010; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'b0110); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = ~D tst_instruction = 'h8300; tst_data_A = 'b1010; tst_data_D = 'haaaa; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 'h5555); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = D + A tst_instruction = 'h8400; tst_data_A = 2; tst_data_D = 3; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 5); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = D + 1 tst_instruction = 'h8500; tst_data_A = 5; tst_data_D = 7; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 8); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = D - A tst_instruction = 'h8600; tst_data_A = 7; tst_data_D = 13; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 6); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // (result) = D - 1 tst_instruction = 'h8700; tst_data_A = 5; tst_data_D = 7; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 6); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // bit 12: M // (result) = D & M tst_instruction = 'h9000; tst_data_A = 0; tst_data_D = 'b1010; tst_data_pA = 'b1100; #1 `TB_CHECK(tst_result, 'b1000); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // bit 7: zx // (result) = 0 + A tst_instruction = 'h8480; tst_data_A = 2; tst_data_D = 3; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 2); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // bit 6: sw // (result) = A - D tst_instruction = 'h8640; tst_data_A = 13; tst_data_D = 7; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 6); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // bit 6+7: sw+zx // (result) = 0 - D tst_instruction = 'h86c0; tst_data_A = 13; tst_data_D = 7; tst_data_pA = 0; #1 `TB_CHECK(tst_result, 16'(-7)); `TB_CHECK(tst_destination_A, 0); `TB_CHECK(tst_destination_D, 0); `TB_CHECK(tst_destination_pA, 0); `TB_CHECK(tst_should_jump, 0); #1 // bit2(jl), bit1(je), bit0(jg) // --zero // (result) = D(0) + A(0), jl tst_instruction = 'h8404; tst_data_A = 0; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 0); #1 // (result) = D(0) + A(0), je tst_instruction = 'h8402; tst_data_A = 0; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 1); #1 // (result) = D(0) + A(0), jg tst_instruction = 'h8401; tst_data_A = 0; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 0); #1 // -- >0 // (result) = D(0) + A(0), jl tst_instruction = 'h8404; tst_data_A = 1; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 0); #1 // (result) = D(0) + A(0), je tst_instruction = 'h8402; tst_data_A = 1; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 0); #1 // (result) = D(0) + A(0), jg tst_instruction = 'h8401; tst_data_A = 1; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 1); #1 // -- <0 // (result) = D(0) + A(0), jl tst_instruction = 'h8404; tst_data_A = -1; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 1); #1 // (result) = D(0) + A(0), je tst_instruction = 'h8402; tst_data_A = -1; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 0); #1 // (result) = D(0) + A(0), jg tst_instruction = 'h8401; tst_data_A = -1; tst_data_D = 0; #1 `TB_CHECK(tst_should_jump, 0); #1 $finish(); end endmodule