`define INSN_LDx_AHL 8'b001xx010 // LDD/LDI A,(HL) / (HL),A
`define INSN_ALU8 8'b10xxxxxx // 10 xxx yyy
`define INSN_NOP 8'b00000000
+`define INSN_RST 8'b11xxx111
+`define INSN_RET 8'b110x1001 // 1 = RETI, 0 = RET
`define INSN_reg_A 3'b111
`define INSN_reg_B 3'b000
reg [7:0] buswdata;
assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
+ reg ie = 0;
+
initial begin
registers[ 0] <= 0;
registers[ 1] <= 0;
`EXEC_NEWCYCLE;
`EXEC_INC_PC;
end
+ `INSN_RST: begin
+ case (cycle)
+ 0: begin
+ `EXEC_INC_PC; // This goes FIRST
+ end
+ 1: begin
+ wr <= 1;
+ address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
+ wdata <= registers[`REG_PCH];
+ end
+ 2: begin
+ wr <= 1;
+ address <= {registers[`REG_SPH],registers[`REG_SPL]}-2;
+ wdata <= registers[`REG_PCL];
+ end
+ 3: begin
+ `EXEC_NEWCYCLE;
+ {registers[`REG_PCH],registers[`REG_PCL]} <=
+ {10'b0,opcode[5:3],3'b0};
+ end
+ endcase
+ end
+ `INSN_RET: begin
+ case (cycle)
+ 0: begin
+ rd <= 1;
+ address <= {registers[`REG_SPH],registers[`REG_SPL]};
+ end
+ 1: begin
+ rd <= 1;
+ address <= {registers[`REG_SPH],registers[`REG_SPL]} + 1;
+ end
+ 2: begin /* twiddle thumbs */ end
+ 3: begin
+ `EXEC_NEWCYCLE;
+ // do NOT increment PC!
+ end
+ endcase
+ end
default:
$stop;
endcase
end
end
`INSN_NOP: begin /* NOP! */ end
+ `INSN_RST: begin
+ case (cycle)
+ 0: cycle <= 1;
+ 1: cycle <= 2;
+ 2: cycle <= 3;
+ 3: begin
+ cycle <= 0;
+ {registers[`REG_SPH],registers[`REG_SPL]} <=
+ {registers[`REG_SPH],registers[`REG_SPL]}-2;
+ end
+ endcase
+ end
+ `INSN_RET: begin
+ case (cycle)
+ 0: cycle <= 1;
+ 1: begin
+ cycle <= 2;
+ registers[`REG_PCL] <= rdata;
+ end
+ 2: begin
+ cycle <= 3;
+ registers[`REG_PCH] <= rdata;
+ end
+ 3: begin
+ cycle <= 0;
+ {registers[`REG_SPH],registers[`REG_SPL]} <=
+ {registers[`REG_SPH],registers[`REG_SPL]} + 2;
+ if (opcode[4]) /* RETI */
+ ie <= 1;
+ end
+ endcase
+ end
endcase
state <= `STATE_FETCH;
end