Browse Source

Add DEY instruction

master
Denis Tereshkin 4 weeks ago
parent
commit
69162741e2
  1. 86
      src/cpu.verilog

86
src/cpu.verilog

@ -78,6 +78,7 @@ localparam
reg [2:0] mem_addr_offset; reg [2:0] mem_addr_offset;
logic [1:0] pending_a_read; logic [1:0] pending_a_read;
logic [1:0] pending_x_read; logic [1:0] pending_x_read;
logic [1:0] pending_y_read;
logic pending_rel_branch; logic pending_rel_branch;
initial A = 0; initial A = 0;
@ -90,6 +91,7 @@ initial mem_wr = 0;
assign mem_addr_eff = mem_addr; assign mem_addr_eff = mem_addr;
initial pending_a_read = 0; initial pending_a_read = 0;
initial pending_x_read = 0; initial pending_x_read = 0;
initial pending_y_read = 0;
initial pending_rel_branch = 0; initial pending_rel_branch = 0;
assign o_state[3:0] = state; assign o_state[3:0] = state;
@ -163,7 +165,15 @@ always_comb
alu_op_c = 1'b1; alu_op_c = 1'b1;
alu_op_sel = OP_SUB; alu_op_sel = OP_SUB;
end end
else if (address_code == ADDR_MODE_ABSOLUTE || else if (decoded_instr == I_DEY)
begin
alu_op_1 = Y;
alu_op_2 = 1'b1;
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_ZP) address_code == ADDR_MODE_ZP)
begin begin
if (decoded_instr == I_EOR) if (decoded_instr == I_EOR)
@ -220,6 +230,21 @@ always @(posedge clk)
P[P_N] <= alu_n; P[P_N] <= alu_n;
end end
pending_x_read <= READ_SOURCE_NONE; pending_x_read <= READ_SOURCE_NONE;
if (pending_y_read == READ_SOURCE_MEM)
begin
Y <= mem_data;
P[P_Z] <= (mem_data == 0);
P[P_N] <= mem_data[7];
end
else if (pending_y_read == READ_SOURCE_ALU)
begin
Y <= alu_op_result;
P[P_Z] <= alu_z;
P[P_N] <= alu_n;
end
pending_y_read <= READ_SOURCE_NONE;
PC <= PC + 1; PC <= PC + 1;
state <= STATE_EXECUTE; state <= STATE_EXECUTE;
end end
@ -236,18 +261,21 @@ always @(posedge clk)
if (decoded_instr == I_LDX) if (decoded_instr == I_LDX)
begin begin
pending_x_read <= READ_SOURCE_MEM; pending_x_read <= READ_SOURCE_MEM;
state <= STATE_FETCH;
PC <= PC + 1;
end end
else if (decoded_instr == I_LDA) else if (decoded_instr == I_LDA)
begin begin
pending_a_read <= READ_SOURCE_MEM; pending_a_read <= READ_SOURCE_MEM;
end
else if (decoded_instr == I_EOR ||
decoded_instr == I_AND ||
decoded_instr == I_ORA)
begin
pending_a_read <= READ_SOURCE_ALU;
end
state <= STATE_FETCH; state <= STATE_FETCH;
PC <= PC + 1; PC <= PC + 1;
end end
end
else if (address_code == ADDR_MODE_ZP) else if (address_code == ADDR_MODE_ZP)
begin begin
mem_sel <= DMUX_AUX; mem_sel <= DMUX_AUX;
@ -259,7 +287,11 @@ always @(posedge clk)
if (decoded_instr == I_DEX) if (decoded_instr == I_DEX)
begin begin
pending_x_read <= READ_SOURCE_ALU; pending_x_read <= READ_SOURCE_ALU;
state <= STATE_FETCH;
end
else if (decoded_instr == I_DEY)
begin
pending_y_read <= READ_SOURCE_ALU;
state <= STATE_FETCH; state <= STATE_FETCH;
end end
end end
@ -386,7 +418,7 @@ always @(posedge clk)
if (f2_past_valid && state == STATE_EXECUTE) if (f2_past_valid && state == STATE_EXECUTE)
if ($past(decoded_instr) == I_DEX) if ($past(decoded_instr) == I_DEX)
begin begin
assert(X == $past(X, 2) - 8'd1); assert(X == $past(X, 3) - 8'd1);
assert($past(PC) == $past(PC, 3) + 16'd1); assert($past(PC) == $past(PC, 3) + 16'd1);
assert(P[P_Z] == (X == 0)); assert(P[P_Z] == (X == 0));
assert(P[P_N] == (X[7] == 1)); assert(P[P_N] == (X[7] == 1));
@ -397,6 +429,21 @@ always @(posedge clk)
assert($stable(P[P_I])); assert($stable(P[P_I]));
end end
always @(posedge clk)
if (f2_past_valid && state == STATE_EXECUTE)
if ($past(decoded_instr) == I_DEY)
begin
assert(Y == $past(Y, 3) - 8'd1);
assert($past(PC) == $past(PC, 3) + 16'd1);
assert(P[P_Z] == (Y == 0));
assert(P[P_N] == (Y[7] == 1));
assert($stable(P[P_C]));
assert($stable(P[P_V]));
assert($stable(P[P_B]));
assert($stable(P[P_D]));
assert($stable(P[P_I]));
end
always @(posedge clk) always @(posedge clk)
if (f2_past_valid && state == STATE_EXECUTE) if (f2_past_valid && state == STATE_EXECUTE)
if ($past(decoded_instr) == I_LDX && $past(address_code) == ADDR_MODE_IMMEDIATE) if ($past(decoded_instr) == I_LDX && $past(address_code) == ADDR_MODE_IMMEDIATE)
@ -450,11 +497,12 @@ always @(posedge clk)
end end
always @(posedge clk) always @(posedge clk)
if (f2_past_valid && if (f4_past_valid &&
state == STATE_EXECUTE && state == STATE_EXECUTE &&
$past(state) == STATE_FETCH && $past(state) == STATE_FETCH &&
($past(state, 2) == STATE_EXECUTE_DATA_2 || ($past(state, 2) == STATE_EXECUTE_DATA_2 ||
$past(state, 2) == STATE_EXECUTE_ZP)) $past(state, 2) == STATE_EXECUTE_ZP ||
$past(state, 2) == STATE_EXECUTE))
begin begin
if ($past(decoded_instr, 2) == I_EOR) if ($past(decoded_instr, 2) == I_EOR)
assert(A == ($past(A) ^ $past(mem_data))); assert(A == ($past(A) ^ $past(mem_data)));
@ -469,19 +517,19 @@ always @(posedge clk)
if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE) if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE)
assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2)); assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2));
else 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));
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));
assert(P[P_C] == $past(P[P_C], 3)); assert(P[P_C] == $past(P[P_C], 2));
assert(P[P_V] == $past(P[P_V], 3)); assert(P[P_V] == $past(P[P_V], 2));
assert(P[P_B] == $past(P[P_B], 3)); assert(P[P_B] == $past(P[P_B], 2));
assert(P[P_D] == $past(P[P_D], 3)); assert(P[P_D] == $past(P[P_D], 2));
assert(P[P_I] == $past(P[P_I], 3)); assert(P[P_I] == $past(P[P_I], 2));
assert(S == $past(S, 3)); assert(S == $past(S, 2));
assert(X == $past(X, 3)); assert(X == $past(X, 2));
assert(Y == $past(Y, 3)); assert(Y == $past(Y, 2));
if (f3_past_valid) if (f3_past_valid)
begin begin
@ -489,6 +537,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_IMMEDIATE)
assert($past(PC, 1) == $past(PC, 3) + 16'd2);
end end
end end

Loading…
Cancel
Save