diff --git a/src/cpu.verilog b/src/cpu.verilog index e38b16f..3e46f1d 100644 --- a/src/cpu.verilog +++ b/src/cpu.verilog @@ -23,8 +23,10 @@ module cpu localparam STATE_FETCH_DATA_2 = 4; localparam STATE_EXECUTE_DATA_2 = 5; localparam STATE_BRANCH = 7; - localparam STATE_EXECUTE_PRE_IDX_1 = 8; - localparam STATE_EXECUTE_PRE_IDX_2 = 9; + localparam STATE_EXECUTE_IDX_1 = 8; + localparam STATE_EXECUTE_IDX_2 = 9; + localparam STATE_EXECUTE_POST_IDX_1 = 10; + localparam STATE_EXECUTE_POST_IDX_2 = 11; localparam READ_SOURCE_NONE = 2'h0, @@ -173,6 +175,21 @@ always_comb begin {mem_aux_addr_hi, mem_aux_addr_lo} = {mem_data, mem_aux_addr} + Y; end + else if (address_code == ADDR_MODE_POSTINDEXED_INDIRECT) + begin + if (state == STATE_EXECUTE_POST_IDX_1) + begin + {mem_aux_addr_hi, mem_aux_addr_lo} = {8'h0, mem_data}; + end + else if (state == STATE_EXECUTE_POST_IDX_2) + begin + {mem_aux_addr_hi, mem_aux_addr_lo} = {8'h0, mem_aux2_addr}; + end + else + begin + {mem_aux_addr_hi, mem_aux_addr_lo} = {mem_data, mem_aux_addr} + Y; + end + end end always_comb @@ -195,13 +212,7 @@ always_comb 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_INDEXED_ABSOLUTE_X || - address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y || - address_code == ADDR_MODE_ZP || - address_code == ADDR_MODE_INDEXED_ZP || - address_code == ADDR_MODE_PREINDEXED_INDIRECT) + else begin alu_op_1 = A; alu_op_2 = mem_data; @@ -330,7 +341,12 @@ always @(posedge clk) end else if (address_code == ADDR_MODE_PREINDEXED_INDIRECT) begin - state <= STATE_EXECUTE_PRE_IDX_1; + state <= STATE_EXECUTE_IDX_1; + end + else if(address_code == ADDR_MODE_POSTINDEXED_INDIRECT) + begin + mem_sel <= DMUX_AUX; + state <= STATE_EXECUTE_POST_IDX_1; end else if (address_code == ADDR_MODE_IMPLIED) begin @@ -371,7 +387,22 @@ always @(posedge clk) mem_aux_addr <= mem_data; end mem_sel <= DMUX_PC; - pending_a_read <= READ_SOURCE_ALU; + if (decoded_instr == I_LDA) + begin + pending_a_read <= READ_SOURCE_MEM; + end + else if (decoded_instr == I_LDX) + begin + pending_x_read <= READ_SOURCE_MEM; + end + else if (decoded_instr == I_LDY) + begin + pending_y_read <= READ_SOURCE_MEM; + end + else + begin + pending_a_read <= READ_SOURCE_ALU; + end state <= STATE_FETCH; end @@ -384,21 +415,38 @@ always @(posedge clk) pending_rel_branch <= 0; state <= STATE_FETCH; end - else if (state == STATE_EXECUTE_PRE_IDX_1) + else if (state == STATE_EXECUTE_IDX_1) begin mem_sel <= DMUX_AUX2; - mem_aux2_addr[7:0] <= mem_data + X; + if (address_code == ADDR_MODE_PREINDEXED_INDIRECT) + begin + mem_aux2_addr[7:0] <= mem_data + X; + end + else + begin + mem_aux2_addr[7:0] <= mem_data; + end mem_aux2_addr[15:8] <= 0; - state <= STATE_EXECUTE_PRE_IDX_2; + state <= STATE_EXECUTE_IDX_2; end - else if (state == STATE_EXECUTE_PRE_IDX_2) + else if (state == STATE_EXECUTE_IDX_2) begin mem_aux_addr <= mem_data; mem_aux2_addr[7:0] <= mem_aux2_addr[7:0] + 1'b1; state <= STATE_FETCH_DATA_2; end + else if (state == STATE_EXECUTE_POST_IDX_1) + begin + mem_aux2_addr <= mem_data + 1'b1; + state <= STATE_EXECUTE_POST_IDX_2; + end + else if (state == STATE_EXECUTE_POST_IDX_2) + begin + mem_aux_addr <= mem_data; + state <= STATE_EXECUTE_DATA_2; + end else if (state == STATE_FETCH_DATA_2) begin mem_aux_addr[7:0] <= mem_data; @@ -423,6 +471,14 @@ always @(posedge clk) begin pending_a_read <= READ_SOURCE_MEM; end + else if(decoded_instr == I_LDX) + begin + pending_x_read <= READ_SOURCE_MEM; + end + else if(decoded_instr == I_LDY) + begin + pending_y_read <= READ_SOURCE_MEM; + end else if(decoded_instr == I_JMP) begin PC <= mem_addr; @@ -463,6 +519,11 @@ always_comb logic f5_past_valid; logic f6_past_valid; + logic [7:0] f_prev_instruction; + logic [4:0] f_prev_addr_code; + +initial f_prev_instruction = 0; +initial f_prev_addr_code = 0; initial f_past_valid = 0; initial f2_past_valid = 0; initial f3_past_valid = 0; @@ -492,6 +553,18 @@ always @(posedge clk) if (f5_past_valid) f6_past_valid <= 1; + logic [7:0] f_instr_count; +always @(posedge clk) + if (state == STATE_FETCH) + f_instr_count <= f_instr_count + 1'b1; + +always @(posedge clk) + if (f2_past_valid && state == STATE_FETCH) + begin + f_prev_instruction <= $past(decoded_instr); + f_prev_addr_code <= $past(address_code); + end + always @(posedge clk) if (f2_past_valid && state == STATE_EXECUTE) if ($past(decoded_instr) == I_DEX) @@ -582,18 +655,32 @@ always @(posedge clk) $past(state, 2) == STATE_EXECUTE_ZP || $past(state, 2) == STATE_EXECUTE)) begin - if ($past(decoded_instr, 2) == I_EOR) + if (f_prev_instruction == I_EOR) assert(A == ($past(A) ^ $past(mem_data))); - else if ($past(decoded_instr, 2) == I_AND) + else if (f_prev_instruction == I_AND) assert(A == ($past(A) & $past(mem_data))); - else if ($past(decoded_instr, 2) == I_ORA) + else if (f_prev_instruction == I_ORA) assert(A == ($past(A) | $past(mem_data))); - else if ($past(decoded_instr, 2) == I_ADC) + else if (f_prev_instruction == I_ADC) assert(A == ($past(A) + $past(mem_data) + $past(P[P_C]))); + else if (f_prev_instruction == I_LDA) + assert(A == $past(mem_data)); + else if (f_prev_instruction == I_LDX) + assert(X == $past(mem_data)); + else if (f_prev_instruction == I_LDY) + assert(Y == $past(mem_data)); else assume(0); - assert($past(mem_wr, 2) == 1'b0); + if (f_prev_instruction == I_STA) + begin + assert($past(mem_wr, 2) == 1'b1); + assert($past(mem_data_wr) == A); + end + else + begin + assert($past(mem_wr, 2) == 1'b0); + end if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE) assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2)); @@ -610,10 +697,27 @@ always @(posedge clk) assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2)); assert($past(mem_addr_eff, 4) == (($past(mem_data, 5) + $past(X, 5)) & 8'hff)); end + else if ($past(address_code, 2) == ADDR_MODE_POSTINDEXED_INDIRECT) + begin + assert(($past(f_abs_address, 2) + $past(Y, 2)) == $past(mem_addr_eff, 2)); + end - assert(P[P_Z] == (A == 0)); - assert(P[P_N] == (A[7] == 1)); - if ($past(decoded_instr) == I_ADC) + if (f_prev_instruction == I_LDX) + begin + assert(P[P_Z] == (X == 0)); + assert(P[P_N] == (X[7] == 1)); + end + else if (f_prev_instruction == I_LDY) + begin + assert(P[P_Z] == (Y == 0)); + assert(P[P_N] == (Y[7] == 1)); + end + else + begin + assert(P[P_Z] == (A == 0)); + assert(P[P_N] == (A[7] == 1)); + end + if (f_prev_instruction == I_ADC) begin assert(P[P_C] == ({1'b0, $past(A)} + {1'b0, $past(mem_data)} + @@ -629,8 +733,14 @@ always @(posedge clk) 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 (f_prev_instruction != I_LDX) + begin + assert(X == $past(X, 2)); + end + if (f_prev_instruction != I_LDY) + begin + assert(Y == $past(Y, 2)); + end if (f3_past_valid) begin @@ -680,28 +790,106 @@ always @(posedge clk) always @(posedge clk) cover(state == STATE_EXECUTE); +always @(posedge clk) + cover(f_instr_count > 16); + +always @(posedge clk) + begin + if (decoded_instr == I_ADC) + begin + cover(address_code == ADDR_MODE_IMMEDIATE); + cover(address_code == ADDR_MODE_ABSOLUTE); + cover(address_code == ADDR_MODE_ZP); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); + cover(address_code == ADDR_MODE_INDEXED_ZP); + cover(address_code == ADDR_MODE_PREINDEXED_INDIRECT); + end + end + +always @(posedge clk) + begin + if (decoded_instr == I_LDA) + begin + cover(address_code == ADDR_MODE_IMMEDIATE); + cover(address_code == ADDR_MODE_ABSOLUTE); + cover(address_code == ADDR_MODE_ZP); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); + cover(address_code == ADDR_MODE_INDEXED_ZP); + cover(address_code == ADDR_MODE_PREINDEXED_INDIRECT); + end + end + +always @(posedge clk) + begin + if (decoded_instr == I_LDX) + begin + cover(address_code == ADDR_MODE_IMMEDIATE); + cover(address_code == ADDR_MODE_ABSOLUTE); + cover(address_code == ADDR_MODE_ZP); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); + cover(address_code == ADDR_MODE_INDEXED_ZP); + end + end + +always @(posedge clk) + begin + if (decoded_instr == I_EOR) + begin + cover(address_code == ADDR_MODE_IMMEDIATE); + cover(address_code == ADDR_MODE_ABSOLUTE); + cover(address_code == ADDR_MODE_ZP); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); + cover(address_code == ADDR_MODE_INDEXED_ZP); + cover(address_code == ADDR_MODE_PREINDEXED_INDIRECT); + end + end + +always @(posedge clk) + begin + if (decoded_instr == I_AND) + begin + cover(address_code == ADDR_MODE_IMMEDIATE); + cover(address_code == ADDR_MODE_ABSOLUTE); + cover(address_code == ADDR_MODE_ZP); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); + cover(address_code == ADDR_MODE_INDEXED_ZP); + cover(address_code == ADDR_MODE_PREINDEXED_INDIRECT); + end + end + always @(posedge clk) begin - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_IMMEDIATE); - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_ABSOLUTE); - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_ZP); - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_INDEXED_ZP); - cover(decoded_instr == I_ADC && address_code == ADDR_MODE_PREINDEXED_INDIRECT); + if (decoded_instr == I_ORA) + begin + cover(address_code == ADDR_MODE_IMMEDIATE); + cover(address_code == ADDR_MODE_ABSOLUTE); + cover(address_code == ADDR_MODE_ZP); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); + cover(address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); + cover(address_code == ADDR_MODE_INDEXED_ZP); + cover(address_code == ADDR_MODE_PREINDEXED_INDIRECT); + end end always @(posedge clk) begin - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_IMMEDIATE); - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_ABSOLUTE); - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_ZP); - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y); - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_INDEXED_ZP); - cover(decoded_instr == I_LDA && address_code == ADDR_MODE_PREINDEXED_INDIRECT); + if (decoded_instr == I_DEX) + begin + cover(address_code == ADDR_MODE_IMPLIED); + end end +always @(posedge clk) + begin + if (decoded_instr == I_DEY) + begin + cover(address_code == ADDR_MODE_IMPLIED); + end + end `endif endmodule