Decoding the NEC V20 Microcode
Unlocking the Secrets of the NEC V20 Microcode
The path toward achieving flawless emulation of the 8088 CPU was paved in 2020 when reenigne successfully decoded its microcode. While I had already integrated NEC V20 support into MartyPC, the implementation was flawed: it lacked cycle-accuracy.
Essentially, my V20 core was merely an 8088 in disguise—a copy of the 8088 core with V20-specific instructions appended. While functional, it wasn't ideal. However, attempting to achieve cycle-exact timing through blind trial and error felt like an exhausting and discouraging prospect.
The Physical Evidence
To solve this, I commissioned InfoSecDJ to capture high-resolution die photographs of an NEC V20. Interestingly, the chip used was a second-source version manufactured by Sharp, though it remains a V20 at its heart.

The resulting photomosaic is staggering in scale: 5.6 Gigapixels ( pixels). The image is so massive that it exceeds the limits of the standard JPEG format.
Analyzing the ROM
The main microcode ROM is located in the rectangular area just below the center of the die.

| Feature | Specification |
|---|---|
| ROM Array Dimensions | |
| Total Bit Count | bits |
| Word Length | bits |
| Calculated Words | words |
While we expected words, the math suggests a slightly larger array.
Upon closer inspection of the ROM:
- Bright horizontal lines: Metal layer traces.
- Yellowish dots: Interconnects between the metal and the underlying polysilicon.
- Vertical bars: Polysilicon layers.
Crucially, I noticed that gaps in the polysilicon on either side of an interconnect indicate the presence of a transistor, which represents a binary 1.
The Extraction Process
Extracting nearly 30,000 bits manually is impossible. I initially tried using MaskRomTool by Travis Goodspeed to automate the process.
- Define bit coordinates in
MaskRomTool - Use automated thresholding to detect bits FAILED
The thresholding failed because the contrast between "bit" and "non-bit" was too low, partly due to the interference of the bright metal layer. I didn't want to risk damaging the chip by asking InfoSecDJ to remove the metal layer.
A New Strategy: Machine Learning
Instead of automated thresholding, I decided to use a Convolutional Neural Network (CNN).
- Coordinate Export: I used
MaskRomToolto export the bit positions as a.jsonfile. - Image Slicing: I wrote a Python script to crop a pixel square around every single bit position, saving them as individual PNGs. This resulted in a 105MB ZIP file.
- Training Data: To teach the AI, I needed a labeled dataset. I built a simple
tkintertool to manually classify bits by pressing0or1on my keyboard.
"The problem is quite literally 'Hotdog or Not Hot Dog'."
I manually sorted roughly 1,000 bits to create the training and validation sets. Although I had no prior experience with CNNs, I was able to implement the model in a single afternoon using available tutorials.
The Pipeline
Training Results
The CNN learned rapidly. Here is the log of the training epochs:
[Epoch 01] train: loss=0.6945 acc=0.7273 f1=0.0164 | val: loss=0.6924 acc=0.7876 f1=0.0000
[Epoch 02] train: loss=0.6860 acc=0.7151 f1=0.3826 | val: loss=0.6257 acc=0.7965 f1=0.0729
[Epoch 03] train: loss=0.3751 acc=0.8914 f1=0.7213 | val: loss=0.3900 acc=0.7655 f1=0.6327
[Epoch 04] train: loss=0.1159 acc=0.9523 f1=0.9139 | val: loss=0.0495 acc=0.9912 f1=0.9773
[Epoch 05] train: loss=0.0251 acc=0.9945 f1=0.9888 | val: loss=0.0460 acc=0.9867 f1=0.9744
[Epoch 06] train: loss=0.0319 acc=0.9933 f1=0.9802 | val: loss=0.0438 acc=0.9823 f1=0.9659
[Epoch 07] train: loss=0.0185 acc=0.9945 f1=0.9212 | val: loss=0.0274 acc=0.9956 f1=0.9891
[Epoch 08] train: loss=0.0141 acc=0.9956 f1=0.9913 | val: loss=0.0271 acc=0.9956 f1=0.9891
[Epoch 09] train: loss=0.0101 acc=0.9978 f1=0.9940 | val: loss=0.0447 acc=0.9867 f1=0.9735
[Epoch 10] train: ...
Visualizing the Inference
The transition from the first attempt to the final model was stark:
Initial Inference:

Final Inference:

By leveraging AI, the daunting task of manually identifying 29,928 bits was transformed into a manageable afternoon project. The source code for this process is available on my GitHub.
