The traditional way to implement HALT has been to keep PC on the same instruction and execute NOPs. PC is incremented as part of acknowledging the next interrupt to step over it. However, this has been shown to not match the real Z80 CPU behaviour, and it's possible to detect the difference in code.
The following article describes it, in the section "Halt and the special reset":
http://www.primrosebank.net/computers/z80/z80_special_reset.htm
When HALT is executed it puts the CPU into a halted state (already implemented in your core). It also advances PC to point to the next instruction. During the halted state the opcode fetch runs on this new PC value but a NOP is executed instead, and PC isn't advanced. When an interrupt occurs the halted state is cleared and execution continues from the current point as normal.
It's possible to detect this behaviour with a HALT in the last byte before a contention boundary, such as 0x7FFF on the ZX Spectrum. The incorrect behaviour reads from 0x7FFF for each NOP executed at the HALT, which has more contention than the correct fetches from 0x8000. The difference in timing can be detected by measuring how much has R changed when the next interrupt is ackknowledged.
The traditional way to implement HALT has been to keep PC on the same instruction and execute NOPs. PC is incremented as part of acknowledging the next interrupt to step over it. However, this has been shown to not match the real Z80 CPU behaviour, and it's possible to detect the difference in code.
The following article describes it, in the section "Halt and the special reset":
http://www.primrosebank.net/computers/z80/z80_special_reset.htm
When HALT is executed it puts the CPU into a halted state (already implemented in your core). It also advances PC to point to the next instruction. During the halted state the opcode fetch runs on this new PC value but a NOP is executed instead, and PC isn't advanced. When an interrupt occurs the halted state is cleared and execution continues from the current point as normal.
It's possible to detect this behaviour with a HALT in the last byte before a contention boundary, such as 0x7FFF on the ZX Spectrum. The incorrect behaviour reads from 0x7FFF for each NOP executed at the HALT, which has more contention than the correct fetches from 0x8000. The difference in timing can be detected by measuring how much has R changed when the next interrupt is ackknowledged.