Browse Source

Add ZP address mode

master
Denis Tereshkin 4 weeks ago
parent
commit
494ee94d20
  1. 81
      src/cpu.verilog
  2. 8
      src/mio.verilog

81
src/cpu.verilog

@ -19,7 +19,7 @@ module cpu @@ -19,7 +19,7 @@ module cpu
localparam STATE_FETCH = 0;
localparam STATE_EXECUTE = 1;
localparam STATE_WRITE = 2;
localparam STATE_FETCH_DATA_1 = 3;
localparam STATE_EXECUTE_ZP = 3;
localparam STATE_FETCH_DATA_2 = 4;
localparam STATE_EXECUTE_DATA_2 = 5;
localparam STATE_BRANCH = 7;
@ -61,6 +61,8 @@ localparam @@ -61,6 +61,8 @@ localparam
logic [7:0] mem_data_wr;
logic [2:0] mem_sel;
logic [7:0] mem_aux_addr;
logic [7:0] mem_aux_addr_lo;
logic [7:0] mem_aux_addr_hi;
logic [7:0] alu_op_1;
logic [7:0] alu_op_2;
@ -127,13 +129,27 @@ dmux dmuxi( @@ -127,13 +129,27 @@ dmux dmuxi(
.i_x(X),
.i_y(Y),
.i_sp(S),
.i_aux({mem_data, mem_aux_addr}),
.i_aux({mem_aux_addr_hi, mem_aux_addr_lo}),
.o_mux(mem_addr));
initial state = STATE_FETCH;
initial PC = 0;
initial mem_sel = 0;
always_comb
begin
mem_aux_addr_lo = mem_aux_addr;
mem_aux_addr_hi = 0;
if (address_code == ADDR_MODE_ABSOLUTE)
begin
mem_aux_addr_hi = mem_data;
end
else if (address_code == ADDR_MODE_ZP)
begin
mem_aux_addr_lo = mem_data;
end
end
always_comb
begin
alu_op_1 = 0;
@ -147,7 +163,8 @@ always_comb @@ -147,7 +163,8 @@ always_comb
alu_op_c = 1'b1;
alu_op_sel = OP_SUB;
end
if (address_code == ADDR_MODE_ABSOLUTE)
else if (address_code == ADDR_MODE_ABSOLUTE ||
address_code == ADDR_MODE_ZP)
begin
if (decoded_instr == I_EOR)
begin
@ -156,6 +173,20 @@ always_comb @@ -156,6 +173,20 @@ always_comb
alu_op_c = 0;
alu_op_sel = OP_EOR;
end
else if (decoded_instr == I_AND)
begin
alu_op_1 = A;
alu_op_2 = mem_data;
alu_op_c = 0;
alu_op_sel = OP_AND;
end
else if (decoded_instr == I_ORA)
begin
alu_op_1 = A;
alu_op_2 = mem_data;
alu_op_c = 0;
alu_op_sel = OP_OR;
end
end
end
@ -217,6 +248,12 @@ always @(posedge clk) @@ -217,6 +248,12 @@ always @(posedge clk)
PC <= PC + 1;
end
end
else if (address_code == ADDR_MODE_ZP)
begin
mem_sel <= DMUX_AUX;
state <= STATE_EXECUTE_ZP;
PC <= PC + 1;
end
else if (address_code == ADDR_MODE_IMPLIED)
begin
if (decoded_instr == I_DEX)
@ -240,6 +277,14 @@ always @(posedge clk) @@ -240,6 +277,14 @@ always @(posedge clk)
end
end
end
else if (state == STATE_EXECUTE_ZP)
begin
mem_aux_addr <= mem_data;
mem_sel <= DMUX_PC;
pending_a_read <= READ_SOURCE_ALU;
state <= STATE_FETCH;
end
else if (state == STATE_BRANCH)
begin
if (pending_rel_branch)
@ -266,7 +311,9 @@ always @(posedge clk) @@ -266,7 +311,9 @@ always @(posedge clk)
begin
mem_sel <= DMUX_PC;
state <= STATE_FETCH;
if (decoded_instr == I_EOR)
if (decoded_instr == I_EOR ||
decoded_instr == I_AND ||
decoded_instr == I_ORA)
begin
tmp <= mem_data;
pending_a_read <= READ_SOURCE_ALU;
@ -293,6 +340,14 @@ always_comb @@ -293,6 +340,14 @@ always_comb
end
end
end
else if (state == STATE_EXECUTE_ZP)
begin
if(decoded_instr == I_STA)
begin
mem_data_wr = A;
mem_wr = 1'b1;
end
end
end
`ifdef FORMAL
@ -398,16 +453,25 @@ always @(posedge clk) @@ -398,16 +453,25 @@ always @(posedge clk)
if (f2_past_valid &&
state == STATE_EXECUTE &&
$past(state) == STATE_FETCH &&
$past(state, 2) == STATE_EXECUTE_DATA_2)
if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE)
($past(state, 2) == STATE_EXECUTE_DATA_2 ||
$past(state, 2) == STATE_EXECUTE_ZP))
begin
if ($past(decoded_instr, 2) == I_EOR)
assert(A == $past(A, 2) ^ $past(mem_data));
assert(A == ($past(A) ^ $past(mem_data)));
else if ($past(decoded_instr, 2) == I_AND)
assert(A == ($past(A) & $past(mem_data)));
else if ($past(decoded_instr, 2) == I_ORA)
assert(A == ($past(A) | $past(mem_data)));
else
assume(0);
assert($past(mem_wr, 2) == 1'b0);
if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE)
assert($past(f_abs_address, 2) == $past(mem_addr_eff, 2));
else
assert($past(mem_data, 2) == $past(mem_addr_eff, 2));
assert(P[P_Z] == (A == 0));
assert(P[P_N] == (A[7] == 1));
assert(P[P_C] == $past(P[P_C], 3));
@ -421,7 +485,10 @@ always @(posedge clk) @@ -421,7 +485,10 @@ always @(posedge clk)
if (f3_past_valid)
begin
if ($past(address_code, 2) == ADDR_MODE_ABSOLUTE)
assert($past(PC, 2) == $past(PC, 5) + 16'd3);
else if ($past(address_code, 2) == ADDR_MODE_ZP)
assert($past(PC, 2) == $past(PC, 4) + 16'd2);
end
end

8
src/mio.verilog

@ -25,7 +25,13 @@ module mio(clk, i_data, i_addr, i_wr, o_data, o_led); @@ -25,7 +25,13 @@ module mio(clk, i_data, i_addr, i_wr, o_data, o_led);
initial o_led = 6'h3f;
`ifndef FORMAL
initial $readmemh("foo.hex", memory);
initial $readmemh("foo.hex", memory, 0, 32);
initial begin
for (integer i = 32; i < 256; i++)
begin
memory[i] = 0;
end
end
`else
reg f_init_done = 0;
always @(posedge clk)

Loading…
Cancel
Save