My friend Ken pointed out that unlike a real Elf, my FPGA-Elf didn’t display the contents of memory if you repeatedly press the input button while in load mode with memory protect enabled. At first I couldn’t figure out how the real Elf did that, but careful study of the schematic and the 1802 manual revealed the secret. In load mode, the 1802 continuously reads and ignores the contents of memory. However, it reads from the address one less than the contents of R0. The Elf hardware latches the displays during this read, and NOT during the memory write cycle when you press the input button. Thus the Elf always displays the contents of the address prior to the next address available for writing. This also means that when you first enter load mode, it displays the contents of address FFFF (hexadecimal). On a minimal Elf, the high byte of the address is ignored, so it displays the contents of address 00FF.
I’ve updated my 1802 core and Elf VHDL files to match this behavior.
FPGA-Elf is 100 times faster than original COSMAC Elf
0 Comments Published by Eric July 30th, 2010 in FPGA, RetroChallengeThe original COSMAC Elf ran at 1 to 2 MHz. Every machine cycle required eight oscillator cycles, and each instruction required two or three machine cycles, so each instruction took 8 to 12 microseconds at 2 MHz, or 16 to 24 microseconds at 1 MHz.
The FPGA-Elf runs at 25 MHz when using a Spartan-3E FPGA in the slow speed grade, but it also needs only one oscillator cycle per machine cycle. That means that each instruction takes 80 to 120 nanoseconds. That’s 100 times the speed of a 2 MHz COSMAC Elf!
With the fastest (-4) speed grade of the newer Spartan 6 FPGA, the FPGA-Elf could run at 50 MHz, and with the fastest speed grade of the Virtex 6 FPGA, it could run at 100 MHz.
My 1802 core design hasn’t been heavily optimized for speed, so there might be some room for speed improvements even on the same FPGA. However, since I don’t really need it to run any faster, I’m not likely to spend time on such optimizations.
Richard Ottosen used my cell phone to shoot a short video of me demonstrating the FPGA-Elf, toggling in and running the dice demo.
Thanks to Jim Donnelly, Richard Ottosen, and Jim Phillips for helping me put together the FPGA-Elf front panel! I never would have been able to get the project completed by the deadline without their help. I lost almost two weeks of the schedule to jury duty, and spent most of the remaining time hacking the VHDL code for the FPGA.
Had more time been available, I would have painted the aluminum, laser-etched switch legends, and done a nicer job on the wiring. I originally had hoped to implement the CDP1861 “Pixie” graphics chip, to show some graphics games. Maybe I can do all that for a future RetroChallenge.
I needed a demo program for the FPGA-Elf that was at least a little more interesting than simply counting, so I wrote a dice program. When you press the input button, it simulates rolling a pair of six-sided dice. Perfect for playing board games. The program is 49 bytes long, so it is somewhat tedious to toggle in, but not completely awful. It’s almost certainly possible to do it in fewer bytes, but I’m not going to try to optimize it right now.
For anyone with an Elf that cares to try it, the code (starting at address zero) is:
F8 00 B1 B2 B3 F8 80 A1 F8 81 A2 F8 82 A3 F8 60 52 F8 06 53 3F 14 02 FC F0 52 3A 28 F8 60 52 03 FC FF 53 3A 28 F8 06 53 02 E3 F1 E1 51 64 21 30 14
After much gnashing of teeth and pulling of hair, I finally figured out what was causing load mode to fail on the real hardware despite working on the simulator. My “next state” logic didn’t have a default value, so both the simulator and the synthesizer were inferring a latch. However, somehow the synthesizer wasn’t doing it properly. Adding a “next_state <= state;” statement in the combinatorial process used for the state machine solved the problem.
Now I can toggle in programs and execute them, without needing any initialization of the RAM.
I need to write a slightly fancier demo program, shoot and upload some video, and I can declare victory!
More FPGA-Elf photos and a video
0 Comments Published by Eric July 28th, 2010 in FPGA, RetroChallengeI’ve added some photos of the completed hardware, showing the Avago hexadecimal displays to my FPGA-Elf set. I also shot a brief video showing an LED test, though it is not using the 1802 core. (I got the 1802 core working last night a few hours after I shot the video.)
While I’m on vacation my only camera is a cell phone, and I had to hold it by hand, so the video isn’t very good. Sorry!
I’ll post a video of the actual FPGA-Elf running (using the 1802) soon! I’ve got a bit more debugging to do first.
FPGA-Elf success! Well, mostly.
0 Comments Published by Eric July 27th, 2010 in FPGA, RetroChallengeI got the switches wired up and working, with a little help from Richard Ottosen. I tested the debouncer, which worked. Then I went for broke and loaded the complete Elf system into the FPGA. After a bit more debugging, it partially works.
What doesn’t work is load mode, so I can’t yet toggle in a program. If I include an 1802 program in the FPGA BlockRAM initialization, it executes just fine. I’ve run a program that makes the display count, free-running, and one that counts when the input button is pressed.
I’m a bit surprised that load mode doesn’t work since it worked fine in the simulation. Obviously the simulation is different in some ways than the real thing, so I’ll have to investigate those differences.
Hexadecimal LEDs wired and working
0 Comments Published by Eric July 27th, 2010 in FPGA, RetroChallengeI’ve wired up the Avago hexadecimal LEDs to the FPGA board and verified that they work with some VHDL test code (not yet tried with the VHDL Elf code). Now I need to wire up the switches.
Does anyone have an interesting game that can be toggled into a basic Elf (just the toggle switches, LEDs, and 256 bytes of RAM)?
FPGA-Elf load mode fixed, now can load and run program in simulation
0 Comments Published by Eric July 26th, 2010 in FPGA, RetroChallengeI changed the state machine in my Elf code to something much simpler, based on the observation that in load mode the DMA input cycle *always* is acknowledged immediately, and that I don’t have to wait for the 1802 core state code output to indicate DMA before deasserting the DMA input.
Now I can (in simulation) load a simple program and run it.
I threw together a testbench for the Elf, with the switch debouncing disabled. The testbench tries to use load mode to load a program that has an infinite loop setting and clearing the Q flag, which is available as an output.
The GHDL simulator can dump the state of all the signals as a VCD file, and I’m using GTKwave to view that.
The most obvious bug I found is that the PC was being reset in state_clear_2 rather than state_clear, so after every load, the PC was reset to zero. Load mode sits in state_clear_2, going to state_dma_input when the dma_in_req changes, so every load was to location zero. In looking at my 1802 core design, there’s no obvious reason why the PC reset couldn’t be done in state_clear rather than state_clear_2, so I changed it to do that instead, and that seems to work.
My logic in the Elf wrapper for only asserting dma_in_req from the leading edge of the synchronized pushbutton input until the 1802 state code indicates that a DMA cycle is being done does not work correctly, so I’m getting memory writes to two consecutive locations for each button press. The necessary logic is trickier than I would have expected, and I haven’t quite figured out the best way to fix it.
The good news is that the code actually is getting written to the RAM, and once the run switch is enabled, the code is actually being run. It’s the wrong code due to the problem described above, but it seems that I’m getting very close to having it working.