|
|
|
|
@ -23,6 +23,8 @@ module cpu
@@ -23,6 +23,8 @@ 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 |
|
|
|
|
READ_SOURCE_NONE = 2'h0, |
|
|
|
|
@ -64,6 +66,8 @@ localparam
@@ -64,6 +66,8 @@ localparam
|
|
|
|
|
logic [7:0] mem_aux_addr_lo; |
|
|
|
|
logic [7:0] mem_aux_addr_hi; |
|
|
|
|
|
|
|
|
|
logic [15:0] mem_aux2_addr; |
|
|
|
|
|
|
|
|
|
logic [7:0] alu_op_1; |
|
|
|
|
logic [7:0] alu_op_2; |
|
|
|
|
logic alu_op_c; |
|
|
|
|
@ -95,6 +99,7 @@ initial pending_x_read = 0;
@@ -95,6 +99,7 @@ initial pending_x_read = 0;
|
|
|
|
|
initial pending_y_read = 0; |
|
|
|
|
initial pending_rel_branch = 0; |
|
|
|
|
initial mem_aux_addr = 0; |
|
|
|
|
initial instr = 0; |
|
|
|
|
|
|
|
|
|
assign o_state[3:0] = state; |
|
|
|
|
assign o_state[31:24] = A; |
|
|
|
|
@ -136,6 +141,7 @@ dmux dmuxi(
@@ -136,6 +141,7 @@ dmux dmuxi(
|
|
|
|
|
.i_y(Y), |
|
|
|
|
.i_sp(S), |
|
|
|
|
.i_aux({mem_aux_addr_hi, mem_aux_addr_lo}), |
|
|
|
|
.i_aux2(mem_aux2_addr), |
|
|
|
|
.o_mux(mem_addr)); |
|
|
|
|
|
|
|
|
|
initial state = STATE_FETCH; |
|
|
|
|
@ -146,7 +152,8 @@ always_comb
@@ -146,7 +152,8 @@ always_comb
|
|
|
|
|
begin |
|
|
|
|
mem_aux_addr_lo = mem_aux_addr; |
|
|
|
|
mem_aux_addr_hi = 0; |
|
|
|
|
if (address_code == ADDR_MODE_ABSOLUTE) |
|
|
|
|
if (address_code == ADDR_MODE_ABSOLUTE || |
|
|
|
|
address_code == ADDR_MODE_PREINDEXED_INDIRECT) |
|
|
|
|
begin |
|
|
|
|
mem_aux_addr_hi = mem_data; |
|
|
|
|
end |
|
|
|
|
@ -158,6 +165,14 @@ always_comb
@@ -158,6 +165,14 @@ always_comb
|
|
|
|
|
begin |
|
|
|
|
mem_aux_addr_lo = mem_aux_addr; |
|
|
|
|
end |
|
|
|
|
else if (address_code == ADDR_MODE_INDEXED_ABSOLUTE_X) |
|
|
|
|
begin |
|
|
|
|
{mem_aux_addr_hi, mem_aux_addr_lo} = {mem_data, mem_aux_addr} + X; |
|
|
|
|
end |
|
|
|
|
else if (address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y) |
|
|
|
|
begin |
|
|
|
|
{mem_aux_addr_hi, mem_aux_addr_lo} = {mem_data, mem_aux_addr} + Y; |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
always_comb |
|
|
|
|
@ -182,8 +197,11 @@ always_comb
@@ -182,8 +197,11 @@ always_comb
|
|
|
|
|
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_INDEXED_ZP || |
|
|
|
|
address_code == ADDR_MODE_PREINDEXED_INDIRECT) |
|
|
|
|
begin |
|
|
|
|
alu_op_1 = A; |
|
|
|
|
alu_op_2 = mem_data; |
|
|
|
|
@ -266,7 +284,9 @@ always @(posedge clk)
@@ -266,7 +284,9 @@ always @(posedge clk)
|
|
|
|
|
else if (state == STATE_EXECUTE) |
|
|
|
|
begin |
|
|
|
|
instr <= mem_data; |
|
|
|
|
if (address_code == ADDR_MODE_ABSOLUTE) |
|
|
|
|
if (address_code == ADDR_MODE_ABSOLUTE || |
|
|
|
|
address_code == ADDR_MODE_INDEXED_ABSOLUTE_X || |
|
|
|
|
address_code == ADDR_MODE_INDEXED_ABSOLUTE_Y) |
|
|
|
|
begin |
|
|
|
|
PC <= PC + 1; |
|
|
|
|
state <= STATE_FETCH_DATA_2; |
|
|
|
|
@ -277,6 +297,10 @@ always @(posedge clk)
@@ -277,6 +297,10 @@ always @(posedge clk)
|
|
|
|
|
begin |
|
|
|
|
pending_x_read <= READ_SOURCE_MEM; |
|
|
|
|
end |
|
|
|
|
if (decoded_instr == I_LDY) |
|
|
|
|
begin |
|
|
|
|
pending_y_read <= READ_SOURCE_MEM; |
|
|
|
|
end |
|
|
|
|
else if (decoded_instr == I_LDA) |
|
|
|
|
begin |
|
|
|
|
pending_a_read <= READ_SOURCE_MEM; |
|
|
|
|
@ -304,6 +328,10 @@ always @(posedge clk)
@@ -304,6 +328,10 @@ always @(posedge clk)
|
|
|
|
|
state <= STATE_EXECUTE_ZPX; |
|
|
|
|
PC <= PC + 1; |
|
|
|
|
end |
|
|
|
|
else if (address_code == ADDR_MODE_PREINDEXED_INDIRECT) |
|
|
|
|
begin |
|
|
|
|
state <= STATE_EXECUTE_PRE_IDX_1; |
|
|
|
|
end |
|
|
|
|
else if (address_code == ADDR_MODE_IMPLIED) |
|
|
|
|
begin |
|
|
|
|
if (decoded_instr == I_DEX) |
|
|
|
|
@ -356,9 +384,22 @@ always @(posedge clk)
@@ -356,9 +384,22 @@ always @(posedge clk)
|
|
|
|
|
pending_rel_branch <= 0; |
|
|
|
|
state <= STATE_FETCH; |
|
|
|
|
end |
|
|
|
|
else if (state == STATE_FETCH_DATA_2) |
|
|
|
|
else if (state == STATE_EXECUTE_PRE_IDX_1) |
|
|
|
|
begin |
|
|
|
|
if (address_code == ADDR_MODE_ABSOLUTE) |
|
|
|
|
mem_sel <= DMUX_AUX2; |
|
|
|
|
mem_aux2_addr[7:0] <= mem_data + X; |
|
|
|
|
mem_aux2_addr[15:8] <= 0; |
|
|
|
|
|
|
|
|
|
state <= STATE_EXECUTE_PRE_IDX_2; |
|
|
|
|
end |
|
|
|
|
else if (state == STATE_EXECUTE_PRE_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_FETCH_DATA_2) |
|
|
|
|
begin |
|
|
|
|
mem_aux_addr[7:0] <= mem_data; |
|
|
|
|
mem_sel <= DMUX_AUX; |
|
|
|
|
@ -366,13 +407,11 @@ always @(posedge clk)
@@ -366,13 +407,11 @@ always @(posedge clk)
|
|
|
|
|
state <= STATE_EXECUTE_DATA_2; |
|
|
|
|
PC <= PC + 1'b1; |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
else if (state == STATE_EXECUTE_DATA_2) |
|
|
|
|
begin |
|
|
|
|
if (address_code == ADDR_MODE_ABSOLUTE) |
|
|
|
|
begin |
|
|
|
|
mem_sel <= DMUX_PC; |
|
|
|
|
state <= STATE_FETCH; |
|
|
|
|
|
|
|
|
|
if (decoded_instr == I_EOR || |
|
|
|
|
decoded_instr == I_AND || |
|
|
|
|
decoded_instr == I_ORA || |
|
|
|
|
@ -380,12 +419,15 @@ always @(posedge clk)
@@ -380,12 +419,15 @@ always @(posedge clk)
|
|
|
|
|
begin |
|
|
|
|
pending_a_read <= READ_SOURCE_ALU; |
|
|
|
|
end |
|
|
|
|
else if(decoded_instr == I_LDA) |
|
|
|
|
begin |
|
|
|
|
pending_a_read <= READ_SOURCE_MEM; |
|
|
|
|
end |
|
|
|
|
else if(decoded_instr == I_JMP) |
|
|
|
|
begin |
|
|
|
|
PC <= mem_addr; |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
always_comb |
|
|
|
|
begin |
|
|
|
|
@ -419,12 +461,14 @@ always_comb
@@ -419,12 +461,14 @@ always_comb
|
|
|
|
|
logic f3_past_valid; |
|
|
|
|
logic f4_past_valid; |
|
|
|
|
logic f5_past_valid; |
|
|
|
|
logic f6_past_valid; |
|
|
|
|
|
|
|
|
|
initial f_past_valid = 0; |
|
|
|
|
initial f2_past_valid = 0; |
|
|
|
|
initial f3_past_valid = 0; |
|
|
|
|
initial f4_past_valid = 0; |
|
|
|
|
initial f5_past_valid = 0; |
|
|
|
|
initial f6_past_valid = 0; |
|
|
|
|
always @(posedge clk) |
|
|
|
|
f_past_valid <= 1; |
|
|
|
|
|
|
|
|
|
@ -444,11 +488,15 @@ always @(posedge clk)
@@ -444,11 +488,15 @@ always @(posedge clk)
|
|
|
|
|
if (f4_past_valid) |
|
|
|
|
f5_past_valid <= 1; |
|
|
|
|
|
|
|
|
|
always @(posedge clk) |
|
|
|
|
if (f5_past_valid) |
|
|
|
|
f6_past_valid <= 1; |
|
|
|
|
|
|
|
|
|
always @(posedge clk) |
|
|
|
|
if (f2_past_valid && state == STATE_EXECUTE) |
|
|
|
|
if ($past(decoded_instr) == I_DEX) |
|
|
|
|
begin |
|
|
|
|
assert(X == $past(X, 3) - 8'd1); |
|
|
|
|
assert(X == $past(X, 2) - 8'd1); |
|
|
|
|
assert($past(PC) == $past(PC, 3) + 16'd1); |
|
|
|
|
assert(P[P_Z] == (X == 0)); |
|
|
|
|
assert(P[P_N] == (X[7] == 1)); |
|
|
|
|
@ -463,7 +511,7 @@ always @(posedge clk)
@@ -463,7 +511,7 @@ 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(Y == $past(Y, 2) - 8'd1); |
|
|
|
|
assert($past(PC) == $past(PC, 3) + 16'd1); |
|
|
|
|
assert(P[P_Z] == (Y == 0)); |
|
|
|
|
assert(P[P_N] == (Y[7] == 1)); |
|
|
|
|
@ -476,11 +524,11 @@ always @(posedge clk)
@@ -476,11 +524,11 @@ always @(posedge clk)
|
|
|
|
|
|
|
|
|
|
always @(posedge clk) |
|
|
|
|
if (f2_past_valid && state == STATE_EXECUTE) |
|
|
|
|
if ($past(decoded_instr) == I_LDX && $past(address_code) == ADDR_MODE_IMMEDIATE) |
|
|
|
|
if ($past(decoded_instr) == I_LDY && $past(address_code) == ADDR_MODE_IMMEDIATE) |
|
|
|
|
begin |
|
|
|
|
assert(X == $past(mem_data)); |
|
|
|
|
assert(P[P_Z] == (X == 0)); |
|
|
|
|
assert(P[P_N] == (X[7] == 1)); |
|
|
|
|
assert(Y == $past(mem_data)); |
|
|
|
|
assert(P[P_Z] == (Y == 0)); |
|
|
|
|
assert(P[P_N] == (Y[7] == 1)); |
|
|
|
|
if (f3_past_valid) |
|
|
|
|
begin |
|
|
|
|
assert($past(PC) == $past(PC, 3) + 16'd2); |
|
|
|
|
@ -527,7 +575,7 @@ always @(posedge clk)
@@ -527,7 +575,7 @@ always @(posedge clk)
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
always @(posedge clk) |
|
|
|
|
if (f4_past_valid && |
|
|
|
|
if (f6_past_valid && |
|
|
|
|
state == STATE_EXECUTE && |
|
|
|
|
$past(state) == STATE_FETCH && |
|
|
|
|
($past(state, 2) == STATE_EXECUTE_DATA_2 || |
|
|
|
|
@ -553,6 +601,15 @@ always @(posedge clk)
@@ -553,6 +601,15 @@ always @(posedge clk)
|
|
|
|
|
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)); |
|
|
|
|
else if ($past(address_code, 2) == ADDR_MODE_INDEXED_ABSOLUTE_X) |
|
|
|
|
assert((($past(f_abs_address, 2) + $past(X, 2)) & 16'hffff) == $past(mem_addr_eff, 2)); |
|
|
|
|
else if ($past(address_code, 2) == ADDR_MODE_INDEXED_ABSOLUTE_Y) |
|
|
|
|
assert((($past(f_abs_address, 2) + $past(Y, 2)) & 16'hffff) == $past(mem_addr_eff, 2)); |
|
|
|
|
else if ($past(address_code, 2) == ADDR_MODE_PREINDEXED_INDIRECT) |
|
|
|
|
begin |
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
assert(P[P_Z] == (A == 0)); |
|
|
|
|
assert(P[P_N] == (A[7] == 1)); |
|
|
|
|
@ -623,7 +680,27 @@ always @(posedge clk)
@@ -623,7 +680,27 @@ always @(posedge clk)
|
|
|
|
|
always @(posedge clk) |
|
|
|
|
cover(state == STATE_EXECUTE); |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
`endif |
|
|
|
|
|
|
|
|
|
|