diff --git a/src/cpu.verilog b/src/cpu.verilog index 2577d55..d210f15 100644 --- a/src/cpu.verilog +++ b/src/cpu.verilog @@ -78,6 +78,7 @@ localparam reg [2:0] mem_addr_offset; logic [1:0] pending_a_read; logic [1:0] pending_x_read; + logic [1:0] pending_y_read; logic pending_rel_branch; initial A = 0; @@ -90,6 +91,7 @@ initial mem_wr = 0; assign mem_addr_eff = mem_addr; initial pending_a_read = 0; initial pending_x_read = 0; +initial pending_y_read = 0; initial pending_rel_branch = 0; assign o_state[3:0] = state; @@ -163,7 +165,15 @@ always_comb alu_op_c = 1'b1; alu_op_sel = OP_SUB; end - else if (address_code == ADDR_MODE_ABSOLUTE || + else if (decoded_instr == I_DEY) + begin + alu_op_1 = Y; + alu_op_2 = 1'b1; + alu_op_c = 1'b1; + alu_op_sel = OP_SUB; + end + else if (address_code == ADDR_MODE_IMMEDIATE || + address_code == ADDR_MODE_ABSOLUTE || address_code == ADDR_MODE_ZP) begin if (decoded_instr == I_EOR) @@ -220,6 +230,21 @@ always @(posedge clk) P[P_N] <= alu_n; end pending_x_read <= READ_SOURCE_NONE; + + if (pending_y_read == READ_SOURCE_MEM) + begin + Y <= mem_data; + P[P_Z] <= (mem_data == 0); + P[P_N] <= mem_data[7]; + end + else if (pending_y_read == READ_SOURCE_ALU) + begin + Y <= alu_op_result; + P[P_Z] <= alu_z; + P[P_N] <= alu_n; + end + pending_y_read <= READ_SOURCE_NONE; + PC <= PC + 1; state <= STATE_EXECUTE; end @@ -236,17 +261,20 @@ always @(posedge clk) if (decoded_instr == I_LDX) begin pending_x_read <= READ_SOURCE_MEM; - - state <= STATE_FETCH; - PC <= PC + 1; end else if (decoded_instr == I_LDA) begin pending_a_read <= READ_SOURCE_MEM; - - state <= STATE_FETCH; - PC <= PC + 1; end + else if (decoded_instr == I_EOR || + decoded_instr == I_AND || + decoded_instr == I_ORA) + begin + pending_a_read <= READ_SOURCE_ALU; + end + + state <= STATE_FETCH; + PC <= PC + 1; end else if (address_code == ADDR_MODE_ZP) begin @@ -259,7 +287,11 @@ always @(posedge clk) if (decoded_instr == I_DEX) begin pending_x_read <= READ_SOURCE_ALU; - + state <= STATE_FETCH; + end + else if (decoded_instr == I_DEY) + begin + pending_y_read <= READ_SOURCE_ALU; state <= STATE_FETCH; end end @@ -386,7 +418,7 @@ always @(posedge clk) if (f2_past_valid && state == STATE_EXECUTE) if ($past(decoded_instr) == I_DEX) begin - assert(X == $past(X, 2) - 8'd1); + assert(X == $past(X, 3) - 8'd1); assert($past(PC) == $past(PC, 3) + 16'd1); assert(P[P_Z] == (X == 0)); assert(P[P_N] == (X[7] == 1)); @@ -397,6 +429,21 @@ always @(posedge clk) assert($stable(P[P_I])); end +always @(posedge clk) + if (f2_past_valid && state == STATE_EXECUTE) + if ($past(decoded_instr) == I_DEY) + begin + assert(Y == $past(Y, 3) - 8'd1); + assert($past(PC) == $past(PC, 3) + 16'd1); + assert(P[P_Z] == (Y == 0)); + assert(P[P_N] == (Y[7] == 1)); + assert($stable(P[P_C])); + assert($stable(P[P_V])); + assert($stable(P[P_B])); + assert($stable(P[P_D])); + assert($stable(P[P_I])); + end + always @(posedge clk) if (f2_past_valid && state == STATE_EXECUTE) if ($past(decoded_instr) == I_LDX && $past(address_code) == ADDR_MODE_IMMEDIATE) @@ -450,11 +497,12 @@ always @(posedge clk) end always @(posedge clk) - if (f2_past_valid && + if (f4_past_valid && state == STATE_EXECUTE && $past(state) == STATE_FETCH && ($past(state, 2) == STATE_EXECUTE_DATA_2 || - $past(state, 2) == STATE_EXECUTE_ZP)) + $past(state, 2) == STATE_EXECUTE_ZP || + $past(state, 2) == STATE_EXECUTE)) begin if ($past(decoded_instr, 2) == I_EOR) assert(A == ($past(A) ^ $past(mem_data))); @@ -469,19 +517,19 @@ always @(posedge clk) if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE) assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2)); - else + else if ($past(address_code, 2) == ADDR_MODE_ZP) assert($past(mem_data, 2) == $past(mem_addr_eff, 2)); assert(P[P_Z] == (A == 0)); assert(P[P_N] == (A[7] == 1)); - assert(P[P_C] == $past(P[P_C], 3)); - assert(P[P_V] == $past(P[P_V], 3)); - assert(P[P_B] == $past(P[P_B], 3)); - assert(P[P_D] == $past(P[P_D], 3)); - assert(P[P_I] == $past(P[P_I], 3)); - assert(S == $past(S, 3)); - assert(X == $past(X, 3)); - assert(Y == $past(Y, 3)); + assert(P[P_C] == $past(P[P_C], 2)); + assert(P[P_V] == $past(P[P_V], 2)); + assert(P[P_B] == $past(P[P_B], 2)); + assert(P[P_D] == $past(P[P_D], 2)); + assert(P[P_I] == $past(P[P_I], 2)); + assert(S == $past(S, 2)); + assert(X == $past(X, 2)); + assert(Y == $past(Y, 2)); if (f3_past_valid) begin @@ -489,6 +537,8 @@ always @(posedge clk) assert($past(PC, 2) == $past(PC, 5) + 16'd3); else if ($past(address_code, 2) == ADDR_MODE_ZP) assert($past(PC, 2) == $past(PC, 4) + 16'd2); + else if ($past(address_code, 2) == ADDR_MODE_IMMEDIATE) + assert($past(PC, 1) == $past(PC, 3) + 16'd2); end end