|
|
|
@ -90,6 +90,7 @@ localparam |
|
|
|
logic [1:0] pending_y_read; |
|
|
|
logic [1:0] pending_y_read; |
|
|
|
logic pending_rel_branch; |
|
|
|
logic pending_rel_branch; |
|
|
|
logic pending_nz_alu_update; |
|
|
|
logic pending_nz_alu_update; |
|
|
|
|
|
|
|
logic pending_c_alu_update; |
|
|
|
wire is_arith; |
|
|
|
wire is_arith; |
|
|
|
logic [2:0] extra_timing; |
|
|
|
logic [2:0] extra_timing; |
|
|
|
reg [3:0] state_after_delay; |
|
|
|
reg [3:0] state_after_delay; |
|
|
|
@ -107,6 +108,7 @@ 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 pending_nz_alu_update = 0; |
|
|
|
initial pending_nz_alu_update = 0; |
|
|
|
|
|
|
|
initial pending_c_alu_update = 0; |
|
|
|
initial mem_aux_addr = 0; |
|
|
|
initial mem_aux_addr = 0; |
|
|
|
initial instr = 0; |
|
|
|
initial instr = 0; |
|
|
|
initial extra_timing = 0; |
|
|
|
initial extra_timing = 0; |
|
|
|
@ -234,6 +236,46 @@ 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 (decoded_instr == I_ASL) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (address_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
alu_op_1 = A; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
alu_op_1 = mem_data; |
|
|
|
|
|
|
|
alu_op_2 = SHIFT_LEFT; |
|
|
|
|
|
|
|
alu_op_c = 0; |
|
|
|
|
|
|
|
alu_op_sel = OP_SHF; |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if (decoded_instr == I_LSR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (address_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
alu_op_1 = A; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
alu_op_1 = mem_data; |
|
|
|
|
|
|
|
alu_op_2 = SHIFT_RIGHT; |
|
|
|
|
|
|
|
alu_op_c = 0; |
|
|
|
|
|
|
|
alu_op_sel = OP_SHF; |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if (decoded_instr == I_ROL) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (address_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
alu_op_1 = A; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
alu_op_1 = mem_data; |
|
|
|
|
|
|
|
alu_op_2 = SHIFT_LEFT; |
|
|
|
|
|
|
|
alu_op_c = P[P_C]; |
|
|
|
|
|
|
|
alu_op_sel = OP_ROT; |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if (decoded_instr == I_ROR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (address_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
alu_op_1 = A; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
alu_op_1 = mem_data; |
|
|
|
|
|
|
|
alu_op_2 = SHIFT_RIGHT; |
|
|
|
|
|
|
|
alu_op_c = P[P_C]; |
|
|
|
|
|
|
|
alu_op_sel = OP_ROT; |
|
|
|
|
|
|
|
end |
|
|
|
else |
|
|
|
else |
|
|
|
begin |
|
|
|
begin |
|
|
|
alu_op_1 = A; |
|
|
|
alu_op_1 = A; |
|
|
|
@ -333,6 +375,12 @@ always @(posedge clk) |
|
|
|
end |
|
|
|
end |
|
|
|
pending_nz_alu_update <= 0; |
|
|
|
pending_nz_alu_update <= 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pending_c_alu_update) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
P[P_C] <= alu_c; |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
pending_c_alu_update <= 0; |
|
|
|
|
|
|
|
|
|
|
|
PC <= PC + 1; |
|
|
|
PC <= PC + 1; |
|
|
|
state <= STATE_EXECUTE; |
|
|
|
state <= STATE_EXECUTE; |
|
|
|
end |
|
|
|
end |
|
|
|
@ -383,7 +431,11 @@ always @(posedge clk) |
|
|
|
begin |
|
|
|
begin |
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
if (decoded_instr == I_INC || |
|
|
|
if (decoded_instr == I_INC || |
|
|
|
decoded_instr == I_DEC) |
|
|
|
decoded_instr == I_DEC || |
|
|
|
|
|
|
|
decoded_instr == I_ASL || |
|
|
|
|
|
|
|
decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || |
|
|
|
|
|
|
|
decoded_instr == I_ROR ) |
|
|
|
begin |
|
|
|
begin |
|
|
|
state <= STATE_READ_ADDR_ZP; |
|
|
|
state <= STATE_READ_ADDR_ZP; |
|
|
|
end |
|
|
|
end |
|
|
|
@ -397,7 +449,11 @@ always @(posedge clk) |
|
|
|
begin |
|
|
|
begin |
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
if (decoded_instr == I_INC || |
|
|
|
if (decoded_instr == I_INC || |
|
|
|
decoded_instr == I_DEC) |
|
|
|
decoded_instr == I_DEC || |
|
|
|
|
|
|
|
decoded_instr == I_ASL || |
|
|
|
|
|
|
|
decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || |
|
|
|
|
|
|
|
decoded_instr == I_ROR) |
|
|
|
begin |
|
|
|
begin |
|
|
|
state <= STATE_READ_ADDR_ZP; |
|
|
|
state <= STATE_READ_ADDR_ZP; |
|
|
|
end |
|
|
|
end |
|
|
|
@ -432,6 +488,14 @@ always @(posedge clk) |
|
|
|
pending_y_read <= READ_SOURCE_ALU; |
|
|
|
pending_y_read <= READ_SOURCE_ALU; |
|
|
|
state <= STATE_FETCH; |
|
|
|
state <= STATE_FETCH; |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
else if (decoded_instr == I_ASL || decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || decoded_instr == I_ROR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
pending_a_read <= READ_SOURCE_ALU; |
|
|
|
|
|
|
|
pending_nz_alu_update <= 1; |
|
|
|
|
|
|
|
pending_c_alu_update <= 1; |
|
|
|
|
|
|
|
state <= STATE_FETCH; |
|
|
|
|
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
else if (decoded_instr == I_BNE) |
|
|
|
else if (decoded_instr == I_BNE) |
|
|
|
begin |
|
|
|
begin |
|
|
|
@ -487,8 +551,13 @@ always @(posedge clk) |
|
|
|
pending_a_read <= READ_SOURCE_ALU; |
|
|
|
pending_a_read <= READ_SOURCE_ALU; |
|
|
|
end |
|
|
|
end |
|
|
|
else if (decoded_instr == I_DEC || |
|
|
|
else if (decoded_instr == I_DEC || |
|
|
|
decoded_instr == I_INC) |
|
|
|
decoded_instr == I_INC || |
|
|
|
|
|
|
|
decoded_instr == I_ASL || |
|
|
|
|
|
|
|
decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || |
|
|
|
|
|
|
|
decoded_instr == I_ROR) |
|
|
|
begin |
|
|
|
begin |
|
|
|
|
|
|
|
pending_c_alu_update <= 1; |
|
|
|
pending_nz_alu_update <= 1'b1; |
|
|
|
pending_nz_alu_update <= 1'b1; |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
@ -541,7 +610,9 @@ always @(posedge clk) |
|
|
|
mem_aux_addr[7:0] <= mem_data; |
|
|
|
mem_aux_addr[7:0] <= mem_data; |
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
|
|
|
|
|
|
|
|
if (decoded_instr == I_DEC || decoded_instr == I_INC) |
|
|
|
if (decoded_instr == I_DEC || decoded_instr == I_INC || |
|
|
|
|
|
|
|
decoded_instr == I_ASL || decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || decoded_instr == I_ROR) |
|
|
|
begin |
|
|
|
begin |
|
|
|
state <= STATE_EXECUTE_ABS_ALU; |
|
|
|
state <= STATE_EXECUTE_ABS_ALU; |
|
|
|
end |
|
|
|
end |
|
|
|
@ -609,6 +680,12 @@ always @(posedge clk) |
|
|
|
begin |
|
|
|
begin |
|
|
|
extra_timing <= 1; |
|
|
|
extra_timing <= 1; |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
if (decoded_instr == I_ASL || decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || decoded_instr == I_ROR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
pending_nz_alu_update <= 1; |
|
|
|
|
|
|
|
pending_c_alu_update <= 1; |
|
|
|
|
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
else if (state == STATE_WRITE_ABS_ALU) |
|
|
|
else if (state == STATE_WRITE_ABS_ALU) |
|
|
|
begin |
|
|
|
begin |
|
|
|
@ -660,7 +737,11 @@ always_comb |
|
|
|
mem_data_wr = Y; |
|
|
|
mem_data_wr = Y; |
|
|
|
end |
|
|
|
end |
|
|
|
else if(decoded_instr == I_DEC || |
|
|
|
else if(decoded_instr == I_DEC || |
|
|
|
decoded_instr == I_INC) |
|
|
|
decoded_instr == I_INC || |
|
|
|
|
|
|
|
decoded_instr == I_ASL || |
|
|
|
|
|
|
|
decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || |
|
|
|
|
|
|
|
decoded_instr == I_ROR) |
|
|
|
begin |
|
|
|
begin |
|
|
|
mem_wr = 1'b1; |
|
|
|
mem_wr = 1'b1; |
|
|
|
mem_data_wr = alu_op_result; |
|
|
|
mem_data_wr = alu_op_result; |
|
|
|
@ -1248,6 +1329,146 @@ always @(posedge clk) |
|
|
|
assert(Y == f_prev_Y); |
|
|
|
assert(Y == f_prev_Y); |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
always @(posedge clk) |
|
|
|
|
|
|
|
if (f_prev_valid && state == STATE_EXECUTE) |
|
|
|
|
|
|
|
if (f_prev_instruction == I_ASL || f_prev_instruction == I_LSR || |
|
|
|
|
|
|
|
f_prev_instruction == I_ROL || f_prev_instruction == I_ROR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
cover(f_prev_addr_code == ADDR_MODE_IMPLIED); |
|
|
|
|
|
|
|
cover(f_prev_addr_code == ADDR_MODE_ZP); |
|
|
|
|
|
|
|
cover(f_prev_addr_code == ADDR_MODE_INDEXED_ZP); |
|
|
|
|
|
|
|
cover(f_prev_addr_code == ADDR_MODE_ABSOLUTE); |
|
|
|
|
|
|
|
cover(f_prev_addr_code == ADDR_MODE_INDEXED_ABSOLUTE_X); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (f_prev_addr_code != ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(mem_wr, 2) == 1'b1); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (f_prev_instruction == I_ASL) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (f_prev_addr_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert(f_prev_A[6:0] == A[7:1]); |
|
|
|
|
|
|
|
assert(A[0] == 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(f_prev_A[7] == P[P_C]); |
|
|
|
|
|
|
|
assert((A == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert(A[7] == P[P_N]); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7:1], 2) == $past(mem_data[6:0], 2)); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[0], 2) == 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert($past(mem_data[7], 2) == P[P_C]); |
|
|
|
|
|
|
|
assert(($past(mem_data_wr, 2) == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7], 2) == P[P_N]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(A == f_prev_A); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if (f_prev_instruction == I_LSR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (f_prev_addr_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert(f_prev_A[7:1] == A[6:0]); |
|
|
|
|
|
|
|
assert(A[7] == 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(f_prev_A[0] == P[P_C]); |
|
|
|
|
|
|
|
assert((A == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert(A[7] == P[P_N]); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(mem_data_wr[6:0], 2) == $past(mem_data[7:1], 2)); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7], 2) == 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert($past(mem_data[0], 2) == P[P_C]); |
|
|
|
|
|
|
|
assert(($past(mem_data_wr, 2) == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7], 2) == P[P_N]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(A == f_prev_A); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if (f_prev_instruction == I_ROR) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (f_prev_addr_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert(f_prev_A[7:1] == A[6:0]); |
|
|
|
|
|
|
|
assert(A[7] == f_prev_P[P_C]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(f_prev_A[0] == P[P_C]); |
|
|
|
|
|
|
|
assert((A == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert(A[7] == P[P_N]); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(mem_data_wr[6:0], 2) == $past(mem_data[7:1], 2)); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7], 2) == f_prev_P[P_C]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert($past(mem_data[0], 2) == P[P_C]); |
|
|
|
|
|
|
|
assert(($past(mem_data_wr, 2) == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7], 2) == P[P_N]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(A == f_prev_A); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if (f_prev_instruction == I_ROL) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
if (f_prev_addr_code == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert(f_prev_A[6:0] == A[7:1]); |
|
|
|
|
|
|
|
assert(A[0] == f_prev_P[P_C]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(f_prev_A[7] == P[P_C]); |
|
|
|
|
|
|
|
assert((A == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert(A[7] == P[P_N]); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7:1], 2) == $past(mem_data[6:0], 2)); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[0], 2) == f_prev_P[P_C]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert($past(mem_data[7], 2) == P[P_C]); |
|
|
|
|
|
|
|
assert(($past(mem_data_wr, 2) == 0) == P[P_Z]); |
|
|
|
|
|
|
|
assert($past(mem_data_wr[7], 2) == P[P_N]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(A == f_prev_A); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ($past(address_code) == ADDR_MODE_IMPLIED) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(PC) == $past(f_prev_PC) + 16'd1); |
|
|
|
|
|
|
|
assert(f_prev_instr_cycles == 2); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if ($past(address_code) == ADDR_MODE_ZP) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(PC) == $past(f_prev_PC) + 16'd2); |
|
|
|
|
|
|
|
assert(f_prev_instr_cycles == 5); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if ($past(address_code) == ADDR_MODE_INDEXED_ZP) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(PC) == $past(f_prev_PC) + 16'd2); |
|
|
|
|
|
|
|
assert(f_prev_instr_cycles == 6); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if ($past(address_code) == ADDR_MODE_ABSOLUTE) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(PC) == $past(f_prev_PC) + 16'd3); |
|
|
|
|
|
|
|
assert(f_prev_instr_cycles == 6); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
else if ($past(address_code) == ADDR_MODE_INDEXED_ABSOLUTE_X) |
|
|
|
|
|
|
|
begin |
|
|
|
|
|
|
|
assert($past(PC) == $past(f_prev_PC) + 16'd3); |
|
|
|
|
|
|
|
assert(f_prev_instr_cycles == 7); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(S == f_prev_S); |
|
|
|
|
|
|
|
assert(X == f_prev_X); |
|
|
|
|
|
|
|
assert(Y == f_prev_Y); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
always @(posedge clk) |
|
|
|
always @(posedge clk) |
|
|
|
if (f_past_valid) |
|
|
|
if (f_past_valid) |
|
|
|
begin |
|
|
|
begin |
|
|
|
@ -1268,6 +1489,10 @@ begin |
|
|
|
decoded_instr == I_INY || |
|
|
|
decoded_instr == I_INY || |
|
|
|
decoded_instr == I_DEC || |
|
|
|
decoded_instr == I_DEC || |
|
|
|
decoded_instr == I_INC || |
|
|
|
decoded_instr == I_INC || |
|
|
|
|
|
|
|
decoded_instr == I_ASL || |
|
|
|
|
|
|
|
decoded_instr == I_LSR || |
|
|
|
|
|
|
|
decoded_instr == I_ROR || |
|
|
|
|
|
|
|
decoded_instr == I_ROL || |
|
|
|
decoded_instr == I_BNE || |
|
|
|
decoded_instr == I_BNE || |
|
|
|
decoded_instr == I_JMP |
|
|
|
decoded_instr == I_JMP |
|
|
|
); |
|
|
|
); |
|
|
|
|