Browse Source

Add shift/rotate operations

master
Denis Tereshkin 5 days ago
parent
commit
8a1f41bfa8
  1. 235
      src/cpu.verilog

235
src/cpu.verilog

@ -90,6 +90,7 @@ localparam @@ -90,6 +90,7 @@ localparam
logic [1:0] pending_y_read;
logic pending_rel_branch;
logic pending_nz_alu_update;
logic pending_c_alu_update;
wire is_arith;
logic [2:0] extra_timing;
reg [3:0] state_after_delay;
@ -107,6 +108,7 @@ initial pending_x_read = 0; @@ -107,6 +108,7 @@ initial pending_x_read = 0;
initial pending_y_read = 0;
initial pending_rel_branch = 0;
initial pending_nz_alu_update = 0;
initial pending_c_alu_update = 0;
initial mem_aux_addr = 0;
initial instr = 0;
initial extra_timing = 0;
@ -234,6 +236,46 @@ always_comb @@ -234,6 +236,46 @@ always_comb
alu_op_c = 1'b1;
alu_op_sel = OP_SUB;
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
begin
alu_op_1 = A;
@ -333,6 +375,12 @@ always @(posedge clk) @@ -333,6 +375,12 @@ always @(posedge clk)
end
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;
state <= STATE_EXECUTE;
end
@ -383,7 +431,11 @@ always @(posedge clk) @@ -383,7 +431,11 @@ always @(posedge clk)
begin
mem_sel <= DMUX_AUX;
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
state <= STATE_READ_ADDR_ZP;
end
@ -397,7 +449,11 @@ always @(posedge clk) @@ -397,7 +449,11 @@ always @(posedge clk)
begin
mem_sel <= DMUX_AUX;
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
state <= STATE_READ_ADDR_ZP;
end
@ -432,6 +488,14 @@ always @(posedge clk) @@ -432,6 +488,14 @@ always @(posedge clk)
pending_y_read <= READ_SOURCE_ALU;
state <= STATE_FETCH;
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
else if (decoded_instr == I_BNE)
begin
@ -487,8 +551,13 @@ always @(posedge clk) @@ -487,8 +551,13 @@ always @(posedge clk)
pending_a_read <= READ_SOURCE_ALU;
end
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
pending_c_alu_update <= 1;
pending_nz_alu_update <= 1'b1;
end
@ -541,7 +610,9 @@ always @(posedge clk) @@ -541,7 +610,9 @@ always @(posedge clk)
mem_aux_addr[7:0] <= mem_data;
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
state <= STATE_EXECUTE_ABS_ALU;
end
@ -609,6 +680,12 @@ always @(posedge clk) @@ -609,6 +680,12 @@ always @(posedge clk)
begin
extra_timing <= 1;
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
else if (state == STATE_WRITE_ABS_ALU)
begin
@ -660,7 +737,11 @@ always_comb @@ -660,7 +737,11 @@ always_comb
mem_data_wr = Y;
end
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
mem_wr = 1'b1;
mem_data_wr = alu_op_result;
@ -1248,6 +1329,146 @@ always @(posedge clk) @@ -1248,6 +1329,146 @@ always @(posedge clk)
assert(Y == f_prev_Y);
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)
if (f_past_valid)
begin
@ -1268,6 +1489,10 @@ begin @@ -1268,6 +1489,10 @@ begin
decoded_instr == I_INY ||
decoded_instr == I_DEC ||
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_JMP
);

Loading…
Cancel
Save