
VETUS PARS RETRO CHIP TESTER
TEST CODE WRITING MANUAL
*Attention* here is a new 6502 test file with comments to show you how to work with CPUs like the 6502.
1. Introduction
The Vetus Pars Retro Chip Tester uses an interpreted instruction system.
Every chip test is written as a list of instructions, one per line, each consisting of:
OPCODE ARG1 ARG2 ARG3
The Vetus GUI software converts these text instructions into 32-bit program words and uploads them to the device. The Vetus Pars then executes the instructions to test the chip installed in the ZIF socket.
End users may write their test scripts manually using any text editor they prefer (Notepad, TextEdit, Sublime, VS Code, etc.), as long as they follow the formatting rules described here.
However, the Vetus GUI will insert opcode values automatically if they select instructions from the provided menus.
2. Required Tools
Two things are required to develop or test chip scripts:
1. The Vetus GUI software
• Used to upload new chip definitions, images, metadata, and test code.
• Used to run tests interactively while developing a script.
2. A plain text editor (optional)
• If users prefer to write tests manually.
• The GUI can load and import these files.
3. File Format for Test Scripts
A test script is a plain text file containing:
1. A header line:
META:
2. A second header:
CODE:
3. Lines of instructions:
OPCODE ARG1 ARG2 ARG3 – please note that even if the argument is not used you must use 0x0 at least when using each opcode. For instance, if you use ENDTEST which takes no arguments, you still need to add all three arguments. Ex: ENDTEST 0x0 0x0 0x0
The GUI software will validate and convert this into program code automatically.
4. Opcode Byte Values
Each instruction corresponds to a single opcode byte (the low byte of the first program word).
Here are the opcodes and their byte values:
SETPIN: 0x01
SETIN: 0x02
SETOUT: 0x09
RDPIN: 0x03
MULTIO: 0x05
MULTII: 0x06
MULTIHI: 0x07
MULTILO: 0x08
ASAFE: 0x0B
GOSTRT: 0x0D
ALLDIR: 0x0E
ALLEVEL: 0x0F
DEFADDR: 0x22
SETADDR: 0x21
ADDRBIT: 0x20
ADDRCLR: 0x2
LOOP: 0x10
ENDLOOP: 0x11
BRKLOOP: 0x13
DELUS: 0x16
DELMS: 0x17
WHILE: 0x18
ENDWHL: 0x19
JMP: 0x1A
DOUNTIL: 0x1B
ENDUNTIL: 0x1C
CLKST: 0x1D
CLKSTP: 0x1E
IF: 0x50
ENDIF: 0x51
LEDON: 0x6C
LEDOFF: 0x6D
REGLOD: 0x40
REGCLR: 0x41
REGINC: 0x42
REGDEC: 0x43
ADD: 0x44
SUBTR: 0x45
MULT: 0x46
DIV: 0x47
RNG: 0x49
AND: 0x4A
OR: 0x4B
SHL: 0x4C
SHR: 0x4D
NOT: 0x4E
XOR: 0x4F
BTNPR: 0x6A
BTNWT: 0x6B
FILSCR: 0x61
SHOSTR: 0x60
TXTCOL: 0x63
PROG: 0x64
UDSCRN: 0x6F
PASSFAIL: 0xF2
ENDTEST: 0xF0
BLNKON: 0x68
BLNKOFF: 0x69
FANON: 0x24
ARRADD: 0x25
ARRGET: 0x26
GETADDR: 0x27
PHIZ: 0x28
TOGPIN: 0x29
PIN2ARR: 0x2A
DEF8: 0x2B
SET8: 0x2C
GET8: 0x2D
5. Registers
The Vetus Pars test engine has 32 registers named R0 through R31.
To reference a register, prefix with “#”:
#R0
#R1
#R2… and so forth up to 32 registers total.
Registers hold numbers, loop counters, results from GETADDR, GET8, or values read from pins.
In code, if you are getting a value from the register then you need to use #Rn where n is the register number. If you are doing anything to a register other then using its value then you should simply use the register number for the argument.
6. DEF8 / SET8 / GET8 Table System
Many chips use lookup tables for writing or verifying patterns.
DEF8 index value extra
Defines an 8-bit entry.
SET8 index value flags
Writes a value to the DEF8 entry or to the chip pins depending on the definition.
GET8 dstIndex srcIndex flags
Reads from the table and stores the result in R(dstIndex).
Example:
DEF8 0x0 0x1020304 0x1011
SET8 0x2 0xF 0x1
GET8 0x2 0x2 0x0
7. Pin Control Instructions
ALLDIR sets direction for all pins at once.
ALLEVEL sets initial logic levels for output pins.
SETPIN controls one pin at a time.
DELUS waits for microseconds.
DELMS waits for milliseconds.
SETOUT sets a pin as output.
SETIN sets the pin as input
Example:
SETPIN 0x8 0x1 0x0
DELUS 0x10 0x0 0x0
SETPIN 0x8 0x0 0x0
SETOUT 0x1 0x0 0x0
SETIN 0xA 0x0 0x0
8. Loops
LOOP num. empty empty
ENDLOOP ends the loop.
The internal counter decreases automatically.
Example:
LOOP 0x10 0x0 0x0
SET8 0x2 0xF 0x1
ENDLOOP 0x0 0x0 0x0
Loops the code inside of it 16 times (0x10)
9. Conditionals
IF condition value value
ENDIF
Example:
IF 0x1 #R2 0xF
PASSFAIL 0x0 0x0 0x0
ENDTEST 0x0 0x0 0x0
ENDIF
This would mean, if register2 is NOT equal to 15 (0xF)
10. Display Output
The tester has a built-in text display.
Use these to show results or messages during testing:
SHOSTR stringIndex x y
UDSCRN 0x0 0x0 0x0
TXTCOL (if text color is supported in your firmware)
Example:
SHOSTR 0x0 0x0 0x30
UDSCRN 0x0 0x0 0x0
11. Finishing the Test
Every program must end with ENDTEST in order to exit the test:
ENDTEST 0x1 0x0 0x0
If PASSFAIL was set to 1 it will pass. Setting it to 0 for failure.
12. Full Example Test (Copy-Paste Friendly)
Below is a complete example test similar to a DRAM walking pattern. No code box formatting is used so it can be copied directly.
[chipfile]
type = single
[chips]
[meta]
name = 4164 RAM
pins = 16
type = 1
imageIndex = 3
[code]
PASSFAIL 0x1 0x0 0x0
ALLDIR 0x1FF 0x1FF 0x0
ALLEVEL 0x80 0x101 0x0
DEF8 0x0 0x1020304 0x1011
DEF8 0x1 0xF070605 0x0
DEF8 0x2 0xB0C0D0E 0x0
REGLOD 0x0 0x0 0x0
REGLOD 0x1 0x0 0x0
SETPIN 0x8 0x0 0x0
SETPIN 0x10 0x1 0x0
SET8 0x2 0xF 0x1
LOOP 0x100 0x0 0x0
SET8 0x2 0xF 0x1
ENDLOOP 0x0 0x0 0x0
SHOSTR 0x0 0x0 0x30
DELMS 0x2 0x0 0x0
UDSCRN 0x0 0x0 0x0
LOOP 0xF 0x0 0x0
SET8 0x0 #R0 1×0
SET8 0x1 #R1 0x1
SETPIN 0x10 0x0 0x0
DELUS 0x10 0x0 0x0
SETPIN 0x10 0x1 0x0
REGINC 0x1 0x0 0x0
ENDLOOP 0x0 0x0 0x0
SET8 0x2 0xFF 0x0
REGLOD 1×0 0x0 0x0
LOOP 0xF 0x0 0x0
SET8 0x1 #R1 0x1
GET8 0x2 0x2 0x0
IF 0x1 #R2 0xF
PASSFAIL 0x0 0x0 0x0
ENDTEST 0x0 0x0 0x0
ENDIF 0x0 0x0 0x0
DELMS 0x1 0x0 0x0
REGINC 0x1 0x0 0x0
ENDLOOP 0x0 0x0 0x0
SHOSTR 0x1 0x0 0x48
DELMS 0x2 0x0 0x0
UDSCRN 0x0 0x0 0x0
ENDTEST 0x0 0x0 0x0
13. Uploading and Testing
The GUI must be used for:
- uploading new chip metadata
- uploading pin maps
- uploading test code
- uploading images
- validating text scripts
- running test code on the device
- debugging test output in real-time
The device imports scripts via USB through the Vetus GUI app.
VETUS PARS — FULL ADDRESSING SYSTEM (WITH GETADDR)
The Vetus Pars uses a flexible, universal addressing system because different chips handle addressing in different ways. Some have a full 16-bit bus (SRAM/EPROM), some are multiplexed (DRAM), some use small 3–8-bit “select lines” (decoders, multiplexers), and some only need simple bit-toggling.
To support all of these, the tester implements three addressing systems:
1. DEFADDR / SETADDR / GETADDR / ADDRBIT — full 16-bit addressing
2. DEF8 / SET8 / GET8 — small 8-bit address groups
3. Manual per-pin control — for unconventional chips
____________________________________________________________
WHAT ADDRESSING ACTUALLY MEANS
Addressing is simply a way to choose one item out of many.
For example:
- In SRAM, the address pins A0–Axx select which memory cell to read.
- In EPROMs, the address chooses which byte is output on D0–D7.
- In DRAM, the address is split into row and column (multiplexed).
- In 74HC138, the inputs A/B/C select which output goes LOW.
- In a multiplexer like CD4051, the address selects which input is routed out.
The Vetus Pars must therefore drive address pins very precisely.
____________________________________________________________
ADDRESS SYSTEM 1:
16-BIT ADDRESS BUS (DEFADDR / SETADDR / GETADDR / ADDRBIT)
This is the main addressing system for large memory chips and structured logic.
It supports a full 16-bit virtual address bus: A0 through A15.
⸻
HOW TO THINK ABOUT IT
You tell the tester:
- Which chip pins are A0–A15
- What value you want on those address lines
- What direction each pin should be (input or output) – As related to the tester. If the chip pin needs an input then you want to OUTPUT from the tester.
The tester handles the ZIF mapping automatically based on the chip’s pin count (important!).
⸻
DEFADDR — Define Chip Pin Positions for A0–A15
Correct argument meaning:
- Argument 1 chooses LOW or HIGH address byte
0x0 = define A0–A7
0x8 = define A8–A15 - Argument 2 = four packed chip pins for the first four address bits
- Argument 3 = four packed chip pins for the next four address bits
Example of packed format for Arg2:
0x04030201 means:
A0 = pin 1
A1 = pin 2
A2 = pin 3
A3 = pin 4
The important part:
Each packed 32-bit value holds exactly 4 chip pin numbers, each of which must be 2-digit hex values. The tester uses the chip’s pin count from metadata to remap these automatically to ZIF pins.
⸻
SETADDR — Send a 16-Bit Address
Arguments:
- Arg1 = number of bits to drive (2-8)
- Arg2 = address byte (0x00–0xFF)
- Arg3 = direction (0 for input, 1 for output) <~ Again: input or output to/from the Vetus Pars tester.
SETADDR 0x8 0xFF 0X1 -> set the address to 255 output.
Before reading from a chip:
- Set Arg3 = 0 (input mode)
This avoids bus contention when the chip drives data lines. The read function automatically set the pins to input but it’s preferred to add this anyway as a precaution.
⸻
GETADDR — Read the Current Address Bits Into a Register
GETADDR reads the defined address lines that were configured using DEFADDR (or ADDRBIT) and places the resulting 8-bit value into one of the tester’s registers.
Correct arguments:
- Arg1 = bit count (0–8), meaning how many address bits you want to read
- Arg2 = register number to store the result
- Arg3 = 0 (reserved, unused but must exist)
The tester reads the physical chip pins, applies the DEFADDR mapping, and assembles the result into an 8-bit value stored in the register.
Typical uses:
- Verify that a counter chip is producing address lines correctly
- Confirm the correct address appears after DRAM RAS/CAS strobes
- Debug address decode logic
- Detect stuck address pins
- Reading data from data pins
⸻
ADDRBIT — Define or Override One Address Bit
Arguments:
- Arg1 = bit number (0–15)
- Arg2 = chip pin number
ADDRBIT is useful for:
- Fixing one bad mapping
- Supporting weirdly pinned chips
- Dynamic reconfiguration
- Row/column testing in DRAM
________________________________________________________
ADDRESS SYSTEM 2:
8-BIT ADDRESS GROUPS (DEF8 / SET8 / GET8)
DEF8 gives the tester fast, compact addressing banks used for many logic chips.
This system is ideal for:
- 74HC138
- 74HC154
- 4051 multiplexers
- 74HC157
- Many ALUs
- Small ROM lookup tables
- DRAM row/column high-level helpers
⸻
DEF8 — Define an 8-Bit Address Bank
Arguments:
- Arg1 = index of the 8-bit bank
- Arg2 = chip pins for low nibble A0–A3
- Arg3 = chip pins for high nibble A4–A7
The pins are in the same packed 32-bit format as DEFADDR.
Each DEF8 bank is like a small “virtual port” that can be reused anywhere in the test.
⸻
SET8 — Drive an 8-Bit Value Onto the Bank
Arguments:
- Arg1 = number of bits to write (0–8)
- Arg2 = value to output (0–255)
- Arg3 = direction (0=input, 1=output)
Most common pattern:
- Set direction = 1 before writing
- Set direction = 0 before reading
⸻
GET8 — Read 8 Bits From a DEF8 Bank Into a Register
Arguments:
- Arg1 = DEF8 index
- Arg2 = output register
- Arg3 = reserved (0)
This:
- Reads the actual physical chip pins as mapped by DEF8
- Packs them into a byte
- Stores them in a register
Useful for:
- Testing counters
- Reading DRAM sense lines
- Reading multiplexer outputs
- Verifying correct logic state sequences
_______________________________________________________
CHOOSING BETWEEN DEFADDR AND DEF8
Use DEFADDR / SETADDR / GETADDR when:
- Chip has more than 8 address pins
- You need true 16-bit addressing
- You are testing SRAM/EPROM/DRAM/large ROM
- You need classical A0–Axx behavior
Use DEF8 / SET8 / GET8 when:
- Chip only has 2–8 address pins
- You are making repeated index lookups
- You want fast looping and compact test code
- You want simple nibble-based mapping
ALLDIR AND ALLEVEL QUICK GUIDE
────────────────────────────────────
These two instructions handle all address/data/control pins at once using a single binary mask.
They affect every defined pin in your chip’s metadata pin map.
You express pin direction or pin level using a binary pattern such as:
0b00000000
0b11111111
0b10101010
0b00001111
0b00110011
Each bit corresponds to ONE chip pin with SideA (whole left side starting at pin 1) being argument1 and SideB (the pin higher numbers) being argument2. The pins go from top of the chip to the bottom of the chip for each side starting with the LSB (far right) Ex: 0b00000001 The 1 here would be pin #1. If we were doing SideB then 1 would be the highest numbered pin on the chip whatever number that happens to be. You can input these as HEX, Decimal or Binary. It is easier however to use binary as each bit represents a chip pin. Vetus GUI will automatically translate it to HEX, which is what it must be saved as.
────────────────────────────────────
SETTING ALL PIN DIRECTIONS (ALLDIR)
Instruction meaning:
ALLDIR sets whether each test pin is input (read) or output (drive).
Binary meaning:
0 = Input (high-impedance, listening)
1 = Output (driving logic level)
Example meaning:
0b00000000
Every pin is input (safe mode for first power-up)
0b11111111
Every pin is output (only safe if truly required)
0b11110000
Upper 4 pins output, lower 4 pins input
When to use it:
• Just before test begins to safely define pin roles
• To switch bus between read cycles and write cycles
• Before reading memory, all address pins should be outputs, data pins inputs
SETTING ALL PIN LEVELS (ALLEVEL)
Instruction meaning:
ALLEVEL sets logic HIGH/LOW on every output pin defined in metadata.
Binary meaning:
0 = logic LOW
1 = logic HIGH
Example meanings:
0b00001111
Lower pins HIGH, upper pins LOW
0b10101010
Alternating pattern HIGH/LOW
0b11111111
All HIGH
When to use:
• Apply full address lines at once
• Pre-charge DRAM
• Enable control signals in a single step
• Drive entire bus pattern for comparison, ALU chips, ROM selects, etc.
SAFETY RULE
When unsure, ALWAYS begin with:
ALLDIR = 0b00000000
All pins high-Z input, nothing driven.
Then selectively drive only what is required.
Never set ALLDIR to all outputs against a powered chip unless you know every bus line is safe to assert simultaneously.
PRACTICAL FLOW DURING TESTING
Typical scan sequence:
- ALLDIR → 0b00000000 (all input, safe) or ALLSAFE (this sets every pin to HI-Z)
- ALLDIR → set address pins output, data pins input
- ALLEVEL → drive full address and control pattern
- Read data pins
- Change address pattern
- Repeat
For write-capable memory:
- ALLDIR → set address + data pins output
- ALLEVEL → drive write data
- Pulse write enable
- Switch data pins back to input (ALLDIR)
- Read to verify
WHY BINARY IS USED INSTEAD OF HEX
Binary directly reflects physical bus states.
You can visually see which pins are:
1 → driving logic high
0 → low or high-Z depending on DIR mode
It prevents confusion and speeds debugging.