Browse Source

Add indexed zp addr mode

master
Denis Tereshkin 4 weeks ago
parent
commit
2c5e25416b
  1. 68
      src/cpu.verilog

68
src/cpu.verilog

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

Loading…
Cancel
Save