|
|
|
@ -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 |
|
|
|
|