|
|
|
|
@ -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; |
|
|
|
|
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; |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
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)); |
|
|
|
|
if ($past(decoded_instr) == I_ADC) |
|
|
|
|
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)); |
|
|
|
|
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 |
|
|
|
|
@ -681,27 +791,105 @@ always @(posedge clk)
@@ -681,27 +791,105 @@ 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(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); |
|
|
|
|
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_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 |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
|