diff --git a/src/cpu.verilog b/src/cpu.verilog index d210f15..5429a43 100644 --- a/src/cpu.verilog +++ b/src/cpu.verilog @@ -18,7 +18,7 @@ module cpu localparam STATE_START_0 = 4'hb; localparam STATE_FETCH = 0; localparam STATE_EXECUTE = 1; - localparam STATE_WRITE = 2; + localparam STATE_EXECUTE_ZPX = 2; localparam STATE_EXECUTE_ZP = 3; localparam STATE_FETCH_DATA_2 = 4; localparam STATE_EXECUTE_DATA_2 = 5; @@ -80,6 +80,7 @@ localparam logic [1:0] pending_x_read; logic [1:0] pending_y_read; logic pending_rel_branch; + wire is_arith; initial A = 0; initial X = 0; @@ -93,11 +94,14 @@ initial pending_a_read = 0; initial pending_x_read = 0; initial pending_y_read = 0; initial pending_rel_branch = 0; +initial mem_aux_addr = 0; assign o_state[3:0] = state; assign o_state[31:24] = A; assign o_state[23:16] = X; +assign is_arith = (decoded_instr == I_ADC); + alu alui( .A(alu_op_1), .B(alu_op_2), @@ -150,6 +154,10 @@ always_comb begin mem_aux_addr_lo = mem_data; end + else if (address_code == ADDR_MODE_INDEXED_ZP) + begin + mem_aux_addr_lo = mem_aux_addr; + end end always_comb @@ -174,29 +182,31 @@ always_comb end else if (address_code == ADDR_MODE_IMMEDIATE || address_code == ADDR_MODE_ABSOLUTE || - address_code == ADDR_MODE_ZP) + address_code == ADDR_MODE_ZP || + address_code == ADDR_MODE_INDEXED_ZP) begin + alu_op_1 = A; + alu_op_2 = mem_data; if (decoded_instr == I_EOR) begin - alu_op_1 = A; - alu_op_2 = mem_data; alu_op_c = 0; alu_op_sel = OP_EOR; end else if (decoded_instr == I_AND) begin - alu_op_1 = A; - alu_op_2 = mem_data; alu_op_c = 0; alu_op_sel = OP_AND; end else if (decoded_instr == I_ORA) begin - alu_op_1 = A; - alu_op_2 = mem_data; alu_op_c = 0; alu_op_sel = OP_OR; end + else if (decoded_instr == I_ADC) + begin + alu_op_c = P[P_C]; + alu_op_sel = OP_ADC; + end end end @@ -214,6 +224,11 @@ always @(posedge clk) A <= alu_op_result; P[P_Z] <= alu_z; P[P_N] <= alu_n; + if (is_arith) + begin + P[P_C] <= alu_c; + P[P_V] <= alu_v; + end end pending_a_read <= READ_SOURCE_NONE; @@ -268,7 +283,8 @@ always @(posedge clk) end else if (decoded_instr == I_EOR || decoded_instr == I_AND || - decoded_instr == I_ORA) + decoded_instr == I_ORA || + decoded_instr == I_ADC) begin pending_a_read <= READ_SOURCE_ALU; end @@ -282,6 +298,12 @@ always @(posedge clk) state <= STATE_EXECUTE_ZP; PC <= PC + 1; end + else if (address_code == ADDR_MODE_INDEXED_ZP) + begin + mem_sel <= DMUX_AUX; + state <= STATE_EXECUTE_ZPX; + PC <= PC + 1; + end else if (address_code == ADDR_MODE_IMPLIED) begin if (decoded_instr == I_DEX) @@ -309,9 +331,17 @@ always @(posedge clk) end end end + else if (state == STATE_EXECUTE_ZPX) + begin + mem_aux_addr <= mem_data + X; + state <= STATE_EXECUTE_ZP; + end else if (state == STATE_EXECUTE_ZP) begin - mem_aux_addr <= mem_data; + if (address_code == ADDR_MODE_ZP) + begin + mem_aux_addr <= mem_data; + end mem_sel <= DMUX_PC; pending_a_read <= READ_SOURCE_ALU; @@ -345,9 +375,9 @@ always @(posedge clk) state <= STATE_FETCH; if (decoded_instr == I_EOR || decoded_instr == I_AND || - decoded_instr == I_ORA) + decoded_instr == I_ORA || + decoded_instr == I_ADC) begin - tmp <= mem_data; pending_a_read <= READ_SOURCE_ALU; end else if(decoded_instr == I_JMP) @@ -510,6 +540,8 @@ always @(posedge clk) assert(A == ($past(A) & $past(mem_data))); else if ($past(decoded_instr, 2) == I_ORA) assert(A == ($past(A) | $past(mem_data))); + else if ($past(decoded_instr, 2) == I_ADC) + assert(A == ($past(A) + $past(mem_data) + $past(P[P_C]))); else assume(0); @@ -519,11 +551,23 @@ always @(posedge clk) assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2)); else if ($past(address_code, 2) == ADDR_MODE_ZP) assert($past(mem_data, 2) == $past(mem_addr_eff, 2)); + else if ($past(address_code, 2) == ADDR_MODE_INDEXED_ZP) + assert((($past(mem_data, 3) + $past(X, 3)) & 16'hff) == $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], 2)); - assert(P[P_V] == $past(P[P_V], 2)); + if ($past(decoded_instr) == I_ADC) + begin + assert(P[P_C] == ({1'b0, $past(A)} + + {1'b0, $past(mem_data)} + + {8'b0, $past(P[P_C])} >= 9'h100)); + assert(P[P_V] == (($past(A[7]) ^ A[7]) & ($past(mem_data[7]) ^ A[7]))); + end + else + begin + assert(P[P_C] == $past(P[P_C], 2)); + assert(P[P_V] == $past(P[P_V], 2)); + end 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)); @@ -537,6 +581,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_INDEXED_ZP) + assert($past(PC, 2) == $past(PC, 5) + 16'd2); else if ($past(address_code, 2) == ADDR_MODE_IMMEDIATE) assert($past(PC, 1) == $past(PC, 3) + 16'd2); end