Browse Source

Add postindexed address mode

master
Denis Tereshkin 4 weeks ago
parent
commit
63d9b4cf2a
  1. 266
      src/cpu.verilog

266
src/cpu.verilog

@ -23,8 +23,10 @@ module cpu @@ -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 @@ -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 @@ -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) @@ -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) @@ -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) @@ -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) @@ -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 @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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

Loading…
Cancel
Save