From 4ea9ac7307e2276edaaaf5b32af716c8988e63b5 Mon Sep 17 00:00:00 2001 From: Denis Tereshkin Date: Mon, 22 Dec 2025 11:02:43 +0700 Subject: [PATCH] Add stack instructions --- src/cpu.verilog | 96 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/cpu.verilog b/src/cpu.verilog index 45359a0..05735c9 100644 --- a/src/cpu.verilog +++ b/src/cpu.verilog @@ -88,6 +88,7 @@ localparam logic [1:0] pending_a_read; logic [1:0] pending_x_read; logic [1:0] pending_y_read; + logic [1:0] pending_p_stack_read; logic pending_rel_branch; logic pending_nz_alu_update; logic pending_c_alu_update; @@ -105,6 +106,7 @@ initial mem_data_wr = 0; initial mem_wr = 0; assign mem_addr_eff = mem_addr; initial pending_a_read = 0; +initial pending_p_stack_read = 0; initial pending_x_read = 0; initial pending_y_read = 0; initial pending_rel_branch = 0; @@ -409,6 +411,12 @@ always @(posedge clk) end pending_c_alu_update <= 0; + if (pending_p_stack_read) + begin + P <= mem_data; + end + pending_p_stack_read <= 0; + if (pending_bit_cmd) begin P[P_Z] <= (A & mem_data) == 0; @@ -574,13 +582,23 @@ always @(posedge clk) P[P_V] <= 0; state <= STATE_FETCH; end - else if (decoded_instr == I_PHA) + else if (decoded_instr == I_PHA || + decoded_instr == I_PHP ) begin mem_aux2_addr <= {8'h01, S}; mem_sel <= DMUX_AUX2; S <= S - 8'h01; state <= STATE_EXECUTE_DATA_2; end + else if (decoded_instr == I_PLA || + decoded_instr == I_PLP ) + begin + mem_aux2_addr <= {8'h01, S}; + mem_sel <= DMUX_AUX2; + S <= S + 8'h01; + state <= STATE_EXECUTE_DATA_2; + extra_timing <= 1'b1; + end end else if (decoded_instr == I_BNE) begin @@ -830,6 +848,14 @@ always @(posedge clk) begin pending_y_read <= READ_SOURCE_MEM; end + else if(decoded_instr == I_PLA) + begin + pending_a_read <= READ_SOURCE_MEM; + end + else if(decoded_instr == I_PLP) + begin + pending_p_stack_read <= 1; + end else if(decoded_instr == I_JMP) begin PC <= mem_addr; @@ -919,6 +945,11 @@ always_comb mem_wr = 1'b1; mem_data_wr = A; end + else if (decoded_instr == I_PHP) + begin + mem_wr = 1'b1; + mem_data_wr = P; + end end else if (state == STATE_EXECUTE_ZP) begin @@ -2121,6 +2152,66 @@ always @(posedge clk) assert(Y == f_prev_Y); end +always @(posedge clk) + if (f_prev_valid && state == STATE_EXECUTE) + if (f_prev_instruction == I_PHP) + begin + cover($past(address_code) == ADDR_MODE_IMPLIED); + + assert($past(PC) == $past(f_prev_PC) + 16'd1); + assert(f_prev_instr_cycles == 3); + + assert($past(mem_addr_eff, 2) == 16'h0100 + f_prev_S); + assert($past(mem_data_wr, 2) == f_prev_P); + assert($past(mem_wr, 2) == 1'b1); + + assert(S == f_prev_S - 8'h01); + + assert(P == f_prev_P); + assert(A == f_prev_A); + assert(X == f_prev_X); + assert(Y == f_prev_Y); + end + +always @(posedge clk) + if (f_prev_valid && state == STATE_EXECUTE) + if (f_prev_instruction == I_PLA) + begin + cover($past(address_code) == ADDR_MODE_IMPLIED); + + assert($past(PC) == $past(f_prev_PC) + 16'd1); + assert(f_prev_instr_cycles == 4); + + assert($past(mem_data, 2) == A); + assert($past(mem_wr, 2) == 1'b0); + + assert(S == f_prev_S + 8'h01); + + assert((A == 0) == P[P_Z]); + assert(A[7] == P[P_N]); + assert(X == f_prev_X); + assert(Y == f_prev_Y); + end + +always @(posedge clk) + if (f_prev_valid && state == STATE_EXECUTE) + if (f_prev_instruction == I_PLP) + begin + cover($past(address_code) == ADDR_MODE_IMPLIED); + + assert($past(PC) == $past(f_prev_PC) + 16'd1); + assert(f_prev_instr_cycles == 4); + + assert($past(mem_data, 2) == P); + assert($past(mem_wr, 2) == 1'b0); + + assert(S == f_prev_S + 8'h01); + + assert(A == f_prev_A); + assert(X == f_prev_X); + assert(Y == f_prev_Y); + end + always @(posedge clk) if (f_past_valid) begin @@ -2165,6 +2256,9 @@ begin decoded_instr == I_BVC || decoded_instr == I_BVS || decoded_instr == I_PHA || + decoded_instr == I_PHP || + decoded_instr == I_PLA || + decoded_instr == I_PLP || decoded_instr == I_JMP ); assume(address_code != ADDR_MODE_INDIRECT);