From 494ee94d20965b7403588f9c66601cd253da3684 Mon Sep 17 00:00:00 2001 From: Denis Tereshkin Date: Thu, 6 Nov 2025 19:24:57 +0700 Subject: [PATCH] Add ZP address mode --- src/cpu.verilog | 123 +++++++++++++++++++++++++++++++++++++----------- src/mio.verilog | 8 +++- 2 files changed, 102 insertions(+), 29 deletions(-) diff --git a/src/cpu.verilog b/src/cpu.verilog index 44bc8e0..2577d55 100644 --- a/src/cpu.verilog +++ b/src/cpu.verilog @@ -19,7 +19,7 @@ module cpu localparam STATE_FETCH = 0; localparam STATE_EXECUTE = 1; localparam STATE_WRITE = 2; - localparam STATE_FETCH_DATA_1 = 3; + localparam STATE_EXECUTE_ZP = 3; localparam STATE_FETCH_DATA_2 = 4; localparam STATE_EXECUTE_DATA_2 = 5; localparam STATE_BRANCH = 7; @@ -61,6 +61,8 @@ localparam logic [7:0] mem_data_wr; logic [2:0] mem_sel; logic [7:0] mem_aux_addr; + logic [7:0] mem_aux_addr_lo; + logic [7:0] mem_aux_addr_hi; logic [7:0] alu_op_1; logic [7:0] alu_op_2; @@ -127,13 +129,27 @@ dmux dmuxi( .i_x(X), .i_y(Y), .i_sp(S), - .i_aux({mem_data, mem_aux_addr}), + .i_aux({mem_aux_addr_hi, mem_aux_addr_lo}), .o_mux(mem_addr)); initial state = STATE_FETCH; initial PC = 0; initial mem_sel = 0; +always_comb + begin + mem_aux_addr_lo = mem_aux_addr; + mem_aux_addr_hi = 0; + if (address_code == ADDR_MODE_ABSOLUTE) + begin + mem_aux_addr_hi = mem_data; + end + else if (address_code == ADDR_MODE_ZP) + begin + mem_aux_addr_lo = mem_data; + end + end + always_comb begin alu_op_1 = 0; @@ -147,7 +163,8 @@ always_comb alu_op_c = 1'b1; alu_op_sel = OP_SUB; end - if (address_code == ADDR_MODE_ABSOLUTE) + else if (address_code == ADDR_MODE_ABSOLUTE || + address_code == ADDR_MODE_ZP) begin if (decoded_instr == I_EOR) begin @@ -156,6 +173,20 @@ always_comb 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 end end @@ -217,6 +248,12 @@ always @(posedge clk) PC <= PC + 1; end end + else if (address_code == ADDR_MODE_ZP) + begin + mem_sel <= DMUX_AUX; + state <= STATE_EXECUTE_ZP; + PC <= PC + 1; + end else if (address_code == ADDR_MODE_IMPLIED) begin if (decoded_instr == I_DEX) @@ -240,6 +277,14 @@ always @(posedge clk) end end end + else if (state == STATE_EXECUTE_ZP) + begin + mem_aux_addr <= mem_data; + mem_sel <= DMUX_PC; + pending_a_read <= READ_SOURCE_ALU; + + state <= STATE_FETCH; + end else if (state == STATE_BRANCH) begin if (pending_rel_branch) @@ -266,7 +311,9 @@ always @(posedge clk) begin mem_sel <= DMUX_PC; state <= STATE_FETCH; - if (decoded_instr == I_EOR) + if (decoded_instr == I_EOR || + decoded_instr == I_AND || + decoded_instr == I_ORA) begin tmp <= mem_data; pending_a_read <= READ_SOURCE_ALU; @@ -293,6 +340,14 @@ always_comb end end end + else if (state == STATE_EXECUTE_ZP) + begin + if(decoded_instr == I_STA) + begin + mem_data_wr = A; + mem_wr = 1'b1; + end + end end `ifdef FORMAL @@ -398,32 +453,44 @@ always @(posedge clk) if (f2_past_valid && state == STATE_EXECUTE && $past(state) == STATE_FETCH && - $past(state, 2) == STATE_EXECUTE_DATA_2) - if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE) - begin - if ($past(decoded_instr, 2) == I_EOR) - assert(A == $past(A, 2) ^ $past(mem_data)); - else - assume(0); - - assert($past(mem_wr, 2) == 1'b0); + ($past(state, 2) == STATE_EXECUTE_DATA_2 || + $past(state, 2) == STATE_EXECUTE_ZP)) + begin + if ($past(decoded_instr, 2) == I_EOR) + assert(A == ($past(A) ^ $past(mem_data))); + else if ($past(decoded_instr, 2) == I_AND) + assert(A == ($past(A) & $past(mem_data))); + else if ($past(decoded_instr, 2) == I_ORA) + assert(A == ($past(A) | $past(mem_data))); + else + assume(0); + + assert($past(mem_wr, 2) == 1'b0); + + if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE) assert($past(f_abs_address, 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)); - - if (f3_past_valid) - begin + else + 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)); + + if (f3_past_valid) + begin + if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE) assert($past(PC, 2) == $past(PC, 5) + 16'd3); - end - end + else if ($past(address_code, 2) == ADDR_MODE_ZP) + assert($past(PC, 2) == $past(PC, 4) + 16'd2); + end + end always @(posedge clk) if (f2_past_valid && state == STATE_FETCH) diff --git a/src/mio.verilog b/src/mio.verilog index 6a3d59f..621cd0c 100644 --- a/src/mio.verilog +++ b/src/mio.verilog @@ -25,7 +25,13 @@ module mio(clk, i_data, i_addr, i_wr, o_data, o_led); initial o_led = 6'h3f; `ifndef FORMAL -initial $readmemh("foo.hex", memory); +initial $readmemh("foo.hex", memory, 0, 32); +initial begin + for (integer i = 32; i < 256; i++) + begin + memory[i] = 0; + end + end `else reg f_init_done = 0; always @(posedge clk)