The YGREC8 core is a rather simple collection of sequential and logic gates, that are usually controlled by a stream of instructions coming from the instruction memory.
The core can also be controlled by an outside debugging device through a "test access port" (TAP) that provides a minimal but essential interface to access the state of all the internal resources (memories, registers, IOs...) by reading or writing a sequence of user-invisible registers.
The complexity and size of the TAP and the internal resources must be kept as small as possible to keep the design fast and compact. The TAP can be removed when debugging or inspection are not required, to save room and increase speed.
The basic features are :
- Read the SRC, DST, RESULT, FLAGS, INSTRUCTION, PC and NPC buses, which provide enough information about the core's state (as well as all the user-visible peripherals)
- Write (if needed) the INSTRUCTION and CONTROL registers
The CONTROL register provides several bits:
- RESET : clears all the resetable registers when 0
- START/STOP : lets the core run loose (when 1), or prevents it from running (when 0)
- STEP : runs one clock cycle then stop (when 1, monostable)
- UPDATE : same as STEP but does not increment the PC
- BYPASS : select the source of instruction, either from program memory (when 0) or the TAP (when 1)
- (more bits are reserved for later, for padding and write-as-0)
The INSTRUCTION (INST) register does more than allow execution of arbitrary instructions, it's a way to control the state of the datapath : the DST, SRC and RESULT buses are combinatorially and directly affected by the SRC and DST fields of the instruction, and visible immediately.
More complex interactions and control comes from sequences of values written to the CONTROL and INSTRUCTION registers, by allowing results of fake instructions to be registered or not.
More registers will be available for read/write access to provide breakpoints.
The debug system has one logic view (read and write registers) that can be implemented in any suitable way with circuits. The physical interface to the registers could be synchronous, asynchronous, parallel, multiplexed or serial... But the user can access these registers (as described above) :
- Write :
- CONTROL / CTRL : 16 bits (see the detail of the bits above)
- INSTRUCTION / INST : 16 bits (holds an instruction to execute, but may also contain data to write to the breakpoint registers)
Total : 16+16=32 bits
- Read :
- INST (16 bits) : the instruction coming from the program memory
- DST (8 bits) the DST field, coming from the register set
- SRC (8 bits) the SRC field (either a register value or an immediate value from INST)
- RESULT/RES (8 bits) : the result of the current instruction, before writeback to the register set. Can contain data from INput ports.
- PC (8 bits) : the address of the current instruction
- NPC (8 bits) : the address of the next instruction (before being written to PC, useful for debugging and tracing CALLs)
- FLAGS (8 bits) : the Carry, Sign and Zero flags, as well as the 4 external condition flags
- Core state (16 bits) : reserved for later, one bit is used for the LDCstate bit.
Total : 16+8+8+8+8+8+8+16=80 bits
The timing, as well as the order of writing and reading information, are critical. For example, reading the registers while the core is running makes no sense because data will be garbled.