The rules of magic were about as regular as the instruction set on a Z80.
-- Wizard's Bane, Rick Cook, 1997
Not much documentation here, since it's still a work in progress and will likely change radically from time to time. Still, there's some information in each file, as well as in z80fi_tests.md.
You will need:
- yosys
- Symbiyosys
- yices2
- boolector
Follow the instructions to install these. It is highly recommended to follow those instructions, especially for yosys since the git repo has many more fixes than the official release.
Individual tests are run as:
sby -f *sby-file*
-f tells sby to overwrite the output directory, rather than
immediately quit if it already exists.
Changing the signals included in z80fi (Z80 Formal Interface) requires running z80fi_generate.py to generate lots of macros for bunches of signals.
Adding a new z80fi_insn_spec*.sv file also requires running the generator, since it creates the corresponding .sby file and adds the new instruction to the coverage test.
Running make in the z80fi directory will run all the tests. Using make -jN, where N is one less than the number of processors you have, is highly recommended so that more than one test runs at the same time. On my machine, each test can last anywhere between 30 and 45 minutes.
-
alu8,alu16Implements an 8-bit and a 16-bit combinatorial Arithmetic Logic Unit, with flags output. Makes no attempt to be subtle or space-efficient.
The 8-bit ALU implements addition, addition with carry, subtraction, subtraction with borrow, AND, XOR, OR, rotate arithmetic and logical right and left, and shift arithmetic and logical right and left.
The 16-bit ALU implements addition, addition with carry, subtraction, and subtraction with borrow.
Used in:
sequencer
-
edgelordReproduces the clock signal without using the clock signal in combinatorial logic. This is a good thing in FPGAs, where the clock is a special signal that might get badly routed if it has to go through anything other than the clock inputs of flipflops.
Used in:
m1mrd_wr_iomrd_wr_mem
-
instr_decoderGiven a sequence of at most 4 bytes, and an instruction length between 0 and 2, determine if the instruction needs more bytes, is illegal, or is legal. If legal, determine its general group and the total number of bytes it needs, including its operands.
Used in:
sequencer_program
-
instr_ixiy_bits_decoderGiven the 4th byte in an IX/IY bits instruction (
DDCBorFDCB), determine if the instruction is legal or not, and if legal, what its general group is.Note that this module is included in
instr_decoder.sv.Used in:
sequencer_program
-
registersHolds the
A,B,C,D,E,H,L,F,A',B',C',D',E',H',L',F',IX,IY, andSPregisters. Can write them individually or as paired registers. Continuously outputs onto two busses one register or register pair. Can also implement higher-level functions such as exchanges and block increments.Used in:
sequencer
-
ir_registersHolds the I and R registers and the IFF1 and IFF2 flipflops. Can write the I and R registers, and can manipulate the IFF flipflops for the
EI,DI, andRETNinstructions, and for nonmaskable interrupts.Used in:
sequencer
-
m1,mrd_wr_io,mrd_wr_memImplements timing for the M1 machine cycle, and cycles for reading and writing I/O and memory.
Used in:
mcycle
Uses:
edgelord
-
mcycleMerges timing and signals from
m1,mrd_wr_io, andmrd_wr_mem.Used in:
z80
Uses:
m1mrd_wr_iomrd_wr_mem
-
sequencer_programA strictly combinatorial module. Implements a kind of microinstruction to determine what should happen on the next clock cycle.
Used in:
sequencer
Uses:
instr_decoderinstr_ixiy_bits_decoder
-
sequencerImplements the main logic of the Z80 by presenting signals to
sequencer_programand executing its desires.Used in:
z80
Uses:
alu8alu16ir_registersregisterssequencer_program
-
z80Primarily a conversion layer between
sequencerand the Z80's pins. Also kicks off the various machine cycles requested by the sequencer.Uses:
mcyclesequencer
-
sequencer_tasks.vhContains tasks used by
sequencer_program. -
z80.vhContains all constants, a few functions, and some bundles of signals useful for passing the contents of all registers around during debugging or tests.