Browse Source

Add compare instructions

master
Denis Tereshkin 2 hours ago
parent
commit
3358706760
  1. 6
      src/alu.verilog
  2. 153
      src/cpu.verilog
  3. 1
      src/parameters.vh

6
src/alu.verilog

@ -53,6 +53,12 @@ always_comb
r_c = sum[8]; r_c = sum[8];
r_v = !(A[7] ^ B[7]) & (A[7] ^ sum[7]); r_v = !(A[7] ^ B[7]) & (A[7] ^ sum[7]);
end end
OP_CMP:
begin
result = {1'b0, A} - {1'b0, B};
r_c = diff[8];
r_v = 0;
end
OP_SUB: OP_SUB:
begin begin
result = diff; result = diff;

153
src/cpu.verilog

@ -276,6 +276,20 @@ always_comb
alu_op_c = P[P_C]; alu_op_c = P[P_C];
alu_op_sel = OP_ROT; alu_op_sel = OP_ROT;
end end
else if (decoded_instr == I_CPX)
begin
alu_op_1 = X;
alu_op_2 = mem_data;
alu_op_c = 1'b1;
alu_op_sel = OP_CMP;
end
else if (decoded_instr == I_CPY)
begin
alu_op_1 = Y;
alu_op_2 = mem_data;
alu_op_c = 1'b1;
alu_op_sel = OP_CMP;
end
else else
begin begin
alu_op_1 = A; alu_op_1 = A;
@ -305,6 +319,11 @@ always_comb
alu_op_c = P[P_C]; alu_op_c = P[P_C];
alu_op_sel = OP_SUB; alu_op_sel = OP_SUB;
end end
else if (decoded_instr == I_CMP)
begin
alu_op_c = 1;
alu_op_sel = OP_CMP;
end
end end
end end
@ -423,6 +442,13 @@ always @(posedge clk)
begin begin
pending_a_read <= READ_SOURCE_ALU; pending_a_read <= READ_SOURCE_ALU;
end end
else if (decoded_instr == I_CMP ||
decoded_instr == I_CPX ||
decoded_instr == I_CPY)
begin
pending_nz_alu_update <= 1;
pending_c_alu_update <= 1;
end
state <= STATE_FETCH; state <= STATE_FETCH;
PC <= PC + 1; PC <= PC + 1;
@ -590,7 +616,10 @@ always @(posedge clk)
decoded_instr == I_ASL || decoded_instr == I_ASL ||
decoded_instr == I_LSR || decoded_instr == I_LSR ||
decoded_instr == I_ROL || decoded_instr == I_ROL ||
decoded_instr == I_ROR) decoded_instr == I_ROR ||
decoded_instr == I_CMP ||
decoded_instr == I_CPX ||
decoded_instr == I_CPY)
begin begin
pending_c_alu_update <= 1; pending_c_alu_update <= 1;
pending_nz_alu_update <= 1'b1; pending_nz_alu_update <= 1'b1;
@ -686,6 +715,13 @@ always @(posedge clk)
begin begin
PC <= mem_addr; PC <= mem_addr;
end end
else if(decoded_instr == I_CMP ||
decoded_instr == I_CPX ||
decoded_instr == I_CPY)
begin
pending_c_alu_update <= 1;
pending_nz_alu_update <= 1;
end
end end
else if (state == STATE_READ_ADDR_ZP) else if (state == STATE_READ_ADDR_ZP)
begin begin
@ -716,7 +752,9 @@ always @(posedge clk)
extra_timing <= 1; extra_timing <= 1;
end end
if (decoded_instr == I_ASL || decoded_instr == I_LSR || if (decoded_instr == I_ASL || decoded_instr == I_LSR ||
decoded_instr == I_ROL || decoded_instr == I_ROR) decoded_instr == I_ROL || decoded_instr == I_ROR ||
decoded_instr == I_CMP || decoded_instr == I_CPX ||
decoded_instr == I_CPY )
begin begin
pending_nz_alu_update <= 1; pending_nz_alu_update <= 1;
pending_c_alu_update <= 1; pending_c_alu_update <= 1;
@ -1320,6 +1358,114 @@ 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_CMP)
begin
cover($past(address_code) == ADDR_MODE_IMMEDIATE);
cover($past(address_code) == ADDR_MODE_ZP);
cover($past(address_code) == ADDR_MODE_INDEXED_ZP);
cover($past(address_code) == ADDR_MODE_ABSOLUTE);
cover($past(address_code) == ADDR_MODE_INDEXED_ABSOLUTE_X);
cover($past(address_code) == ADDR_MODE_INDEXED_ABSOLUTE_Y);
cover($past(address_code) == ADDR_MODE_PREINDEXED_INDIRECT);
cover($past(address_code) == ADDR_MODE_POSTINDEXED_INDIRECT);
if ($past(address_code) == ADDR_MODE_IMMEDIATE)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd2);
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 == 3);
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 == 4);
end
else if ($past(address_code) == ADDR_MODE_ABSOLUTE)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd3);
assert(f_prev_instr_cycles == 4);
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 == 4);
end
else if ($past(address_code) == ADDR_MODE_INDEXED_ABSOLUTE_Y)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd3);
assert(f_prev_instr_cycles == 4);
end
else if ($past(address_code) == ADDR_MODE_PREINDEXED_INDIRECT)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd2);
assert(f_prev_instr_cycles == 6);
end
else if ($past(address_code) == ADDR_MODE_POSTINDEXED_INDIRECT)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd2);
assert(f_prev_instr_cycles == 5);
end
assert(P[P_Z] == (A == $past(mem_data)));
assert(P[P_C] == ({1'b0, f_prev_A} - {1'b0, $past(mem_data)} >= 9'h100));
assert(P[P_N] == (((A - $past(mem_data)) & 8'h80) == 8'h80));
assert(P[P_V] == f_prev_P[P_V]);
assert(A == f_prev_A);
assert(S == f_prev_S);
assert(X == f_prev_X);
assert(Y == f_prev_Y);
end
always @(posedge clk)
if (f_prev_valid && state == STATE_EXECUTE)
if (f_prev_instruction == I_CPX || f_prev_instruction == I_CPY)
begin
cover($past(address_code) == ADDR_MODE_IMMEDIATE);
cover($past(address_code) == ADDR_MODE_ZP);
cover($past(address_code) == ADDR_MODE_ABSOLUTE);
if ($past(address_code) == ADDR_MODE_IMMEDIATE)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd2);
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 == 3);
end
else if ($past(address_code) == ADDR_MODE_ABSOLUTE)
begin
assert($past(PC) == $past(f_prev_PC) + 16'd3);
assert(f_prev_instr_cycles == 4);
end
if (f_prev_instruction == I_CPX)
begin
assert(P[P_Z] == (X == $past(mem_data)));
assert(P[P_C] == ({1'b0, f_prev_X} - {1'b0, $past(mem_data)} >= 9'h100));
assert(P[P_N] == (((X - $past(mem_data)) & 8'h80) == 8'h80));
end
else if (f_prev_instruction == I_CPY)
begin
assert(P[P_Z] == (Y == $past(mem_data)));
assert(P[P_C] == ({1'b0, f_prev_Y} - {1'b0, $past(mem_data)} >= 9'h100));
assert(P[P_N] == (((Y - $past(mem_data)) & 8'h80) == 8'h80));
end
assert(P[P_V] == f_prev_P[P_V]);
assert(A == f_prev_A);
assert(S == f_prev_S);
assert(X == f_prev_X);
assert(Y == f_prev_Y);
end
always @(posedge clk) always @(posedge clk)
if (f_prev_valid && state == STATE_EXECUTE) if (f_prev_valid && state == STATE_EXECUTE)
if (f_prev_instruction == I_INC || if (f_prev_instruction == I_INC ||
@ -1627,6 +1773,9 @@ begin
decoded_instr == I_CLI || decoded_instr == I_CLI ||
decoded_instr == I_SEI || decoded_instr == I_SEI ||
decoded_instr == I_CLV || decoded_instr == I_CLV ||
decoded_instr == I_CMP ||
decoded_instr == I_CPX ||
decoded_instr == I_CPY ||
decoded_instr == I_BNE || decoded_instr == I_BNE ||
decoded_instr == I_JMP decoded_instr == I_JMP
); );

1
src/parameters.vh

@ -18,6 +18,7 @@ localparam OP_ADC = 3;
localparam OP_SUB = 4; localparam OP_SUB = 4;
localparam OP_ROT = 5; localparam OP_ROT = 5;
localparam OP_SHF = 6; localparam OP_SHF = 6;
localparam OP_CMP = 7;
localparam SHIFT_LEFT = 0; localparam SHIFT_LEFT = 0;
localparam SHIFT_RIGHT = 1; localparam SHIFT_RIGHT = 1;

Loading…
Cancel
Save