Introducing the vale8x64 Computer¶
Published on 2019-04-09
I missed the majority of the home computer revolution of the 1970s and ’80s. If I’d been born a few years earlier, I might have used an Apple IIe or Commodore 64 at home. But Nintendo’s marketing game was strong and reached my brother and me at young ages. The NES became the first “computer” in our household. I was fascinated by it, but the NES wasn’t presented as a personal computer. It didn’t welcome exploration. I don’t recall ever feeling encouraged to take it apart to get to know what was inside.
I don’t even remember having a concept of a home computer when we got our first one. It had an 80286 CPU with MS-DOS 3.3, 1 MiB RAM, 5.25” floppy disk drive, 20 MB hard drive, CGA-compatible graphics and a monochrome monitor, custom built at a local computer store.
I was immediately interested in the machine. Information wasn’t as plentiful as it is today, but was available in the computer’s manuals and from the owner of the computer store. I remember going to the library, finding the computer section, and checking out my first programming book. I think this was it.
That book introduced me to the BASIC programming language. Fortunately, DOS provided a BASIC interpreter. I was able to start writing my first programs using the examples in the book, which were simple number guessing games and word games with shallow branching logic.
Not long after, we got Microsoft QuickBASIC. The manual had example programs. I was able to make most of the example programs work, but not all of them. I didn’t comprehend what I was reading in the manual the way I would have needed to use the language in a truly general purpose way. The results I created were the best I could do at the time, but incomplete. But that was fine; I was programming and I was happy.
I learned BASIC and QuickBASIC’s program structure well. Variables, for loops and other control structures, and subroutines made sense. But I didn’t understand the memory model. I didn’t know how to talk to the computer’s hardware. I didn’t know what assembly language was. I was vaguely aware that there were ways to program the computer other than BASIC and QuickBASIC. I knew there were things called binary and hexadecimal, and I thought you could write programs with them. Although I studied geometry, algebra, and calculus in high school and university, I didn’t develop a joy or intuition for how math and programming intertwine during that time. With regard to deeply understanding computers, I kind of got myself stuck. I resigned myself to being an expert computer operator, but only a casual computer programmer, for many years.
Over time, and with much help, I eventually improved at programming to the point that I can now demonstrably be paid to it. I have better intellect and focus to understand the things I couldn’t before. But commercial software development practices and modern consumer hardware favor using libraries, frameworks, and other layers of abstraction over really knowing what happens inside the machine and programming directly against its hardware. And the layers of abstraction increase with each new generation of consumer computers and OS software.
I think there was a time when it was more natural to learn the fundamentals of computing as part of being either a computer enthusiast or professional. In this sense, my comprehension came too late; I had missed out on the first era of low level computing in popular culture.
In the present moment, near future, and near past, I only consider a small slice of all the possible choices and outcomes. Planning into the future is done using a small known set of alternatives, compared to what we learn was possible in retrospect. Perspective widens as history moves further away; looking at time passed, I can see everything I did, but also everything I couldn’t or chose not to do at any time. It’s sometimes natural to see things not done as missed opportunities. But this is only true if the window of opportunity has actually passed. Otherwise, the feeling of having missed out is erroneous; realizing there’s something valuable left undone isn’t identifying a missed opportunity, it’s identifying a new one.
Beginnings (from Breadboard to FPGA)¶
After I started studying electronics and computer architecture last year, I started designing my own computer. I committed to creating most major components (RAM is an exception) from first principles, down to and including its processor. This has become a major project that I’ve named vale8x64 (vale8 for short). I see vale8 as one opportunity to fill gaps in my understanding of technology and gain the experience I previously missed. The exercise of creating vale8 is my means of learning computing down to the metal, silicon, and logic. It’s free, with all HDL and software licensed under GPLv3 from the beginning, in case what I learn during this project will eventually be helpful to someone else as well.
Although I can trace its roots back to my growing interest in emulation, vale8 really began when I started working with TTL logic. Throwing logic chips on breadboards was a fun and tangible way to start building a computer, with the wiring helping me visualize how data flows on the bus. But I quickly grew frustrated with the high cost of parts and long iteration times. Routing and wiring on a breadboard takes careful planning, especially if wiring is to stay neat, so the breadboard method didn’t lend itself to long-term experimentation. I started to look for alternatives.
I knew FPGAs existed and understood them as a way to implement reconfigurable hardware using a programming language, but didn’t understand at all how they worked. I began researching and learning VHDL and Verilog. I reproduced what I had done on the breadboards in VHDL and simulated the results using GHDL. After I’d reached parity between the breadboard design and the VHDL version and felt like I conceptually understood how an HDL describes hardware, I started to look into FPGA boards.
I use free software as exclusively as possible, so the first criterion I chose for my search was a free software toolchain. I was surprised to find only one: Project Icestorm. Apparently the development tooling for FPGAs in general is in a pretty backwards state, with most vendors supplying bloated, node-locked proprietary software packages and keeping the FPGA bitstream details locked away, slowing development of free software alternatives. I was grateful to find IceStorm and familiarized myself with the specs for the Lattice iCE40 line of FPGAs, which is what IceStorm currently supports. I found the iCEstick, a starter board in a USB stick form factor, and ordered it.
I knew I would hit the iCEstick’s limitations pretty quickly. In particular, there wouldn’t be enough GPIO pins to do both VGA and serial I/O at the same time. But since I’d yet to synthesize my first bitstream and program it to an FPGA, it seemed like a good place to start.
I converted all my VHDL to Verilog, since IceStorm doesn’t currently support VHDL. I reached and surpassed my breadboard design, creating a turing complete CPU with a minimal instruction set on the iCEstick board.
It’s been a pleasure so far to use the IceStorm toolchain in my Make-driven workflow and to read its documentation. IceStorm makes me feel like I’ve gotten into FPGA development at a great time.
Here are the currently planned specs for the first version of the vale8 product and some notes on each.
16-bit address/8-bit data CPU¶
I’m developing a custom processor to act as vale8’s CPU. It is influenced by RISC-V, ZipCPU, and others.
The CPU clock speed is to be determined, because it depends on the final configuration of the peripherals and external memory, which is also to be determined.
A 16-bit address width allows the processor to address up to 64 KiB of memory.
8-bit data seems to be a good balance between minimalism and ability for creative expression. The demoscene started on machines with 8-bit processors.
8 bits is also a good size for a programmer to practice use of full adder logic, since add with carry is frequently used to operate with numbers larger than 8 bits.
16-bit address/8-bit data width is a common configuration for 8-bit processors of the day, notably the 6502, 8085, and Z80.
With memory-mapped I/O, both the computer’s memory and its I/O devices use the same address space. In other words, communicating with an I/O device is done simply by reading from or writing to a location in memory.
This is a very simple way to do I/O, and since vale8 has a small number of I/O peripherals, the impact on available system memory should be acceptable.
RS-232 Serial Port I/O¶
The serial port can be used to exchange data between the vale8 computer and a different computer over a serial cable. In this way, you can use another computer to reprogram the vale8’s memory. You can also type commands to it interactively with the other computer’s keyboard.
Supporting serial communication delays the need for both persistent program storage and a keyboard controller.
Character Cell VGA Graphics¶
Character cell graphics is a system in which the display is arranged in rows and columns of characters of equal dimensions. For example, the display may be 320x240 pixels and 40x30 characters. In this case, each character is 8x8 pixels.
The running program selects the character to be used in each row and column of the display from the set of available characters in the computer’s memory. In this way, the program chooses what combination of letters, numbers, or graphical characters appear on the screen to make text or graphics.
The computer usually provides a standard set of characters for convenience, but characters may also be reprogrammable.
Now that we’ve discussed character cell graphics in general, here’s a test image from an early version of the vale8 VGA controller.
vale8’s display resolution, character dimensions and number of available colors are to be determined, although the first version is likely to support one color (monochrome).
I plan for the VGA controller to support programmable characters. In lieu of full bitmap graphics support, this provides some ability to customize graphics.
I’m inspired by subtractive synthesizers like the NES APU and the SID (used in the Commodore 64). The target for the Vale Audio Unit (VAU) is a 4-oscillator sound generator, with each voice independently supporting triangle, variable-duty pulse wave, sawtooth, and noise waveforms. I’m working on the VAU presently, and specs may change depending on what fits on the final FPGA’s resources.
See the vtracker repository if interested in following the progress of the VAU. I’m developing a tracker (music sequencer) along with the VAU itself.
Hosted Machine Code Monitor¶
The machine code monitor is among the most fundamental user programs, so vale8’s ROM will include one. The CPU instruction set has a BRK (“break”) instruction that saves the CPU state and then then jumps into the machine code monitor for interactive debugging.
Non-hosted Assembler for Writing Programs¶
There’s a long standing tradition of using more powerful development workstations to write programs targeting less powerful computers. While vale8 could eventually support a hosted assembler (one that runs on vale8 itself), the initial workflow is to assemble programs on an x64 workstation and then put them on the vale8 over serial connection.
This allows you to take advantage of the power and tools of modern computers to write programs for vale8, and delays the requirement to write an assembler and text editor for vale8 itself.
I’m on the second from-scratch iteration of the assembler. I wrote both the first and second versions in Python. I’ll write the next one in C.
The vale8 assembler supports named labels, forward and backward unnamed labels, and rudimentary macros. It also supports emitting the final positioned machine code with the assembly source code next to it, which is convenient for debugging.
The current development workflow uses the FPGA’s embedded block RAM. This has been convenient for development to this point, but it is too limited for the finished product.
The UP5K FPGA board doesn’t have enough GPIO to add external memory to the configuration, nor have I investigated suitable RAM options in general. I’ll work on this sometime after upgrading to the HX8K FPGA.
Since I’m currently working on the sound generator, the next step is to finish a working prototype of that and test it with the rest of the system.
I plan to upgrade from the UP5K to the HX8K breakout board. I may do this around the same time as integrating the sound generator, because GPIO on the UP5K is getting tight.
I’m optimistic the HX8K board will have enough PLBs and I/O for the final CPU, peripheral and memory configuration. I plan to go no larger than the HX8K for the first version of vale8.
I’ve put some deliberate constraints on vale8’s specs, to keep its scope to what I think I can complete in 2019. I plan to work on it roughly full-time until it’s finished. What happens after that is unknown.
Thanks for reading. If you’re interested in this project, you might like to subscribe to my RSS feed and follow my progress. It’s important to me to learn from the computer engineering community as I work on this. I welcome and appreciate questions and suggestions.