6 days ago •
As I mentioned in yesteday's log, I finally got the computer to run some code from ROM, but that is was unreliable and always seemed to wander off into oblivion after some time (a few tens-of-thousands of microseconds).---------- more ----------
From doing a lot of poking and prodding, and running trace after trace with the analyzer, I thought this was related to timing. My ROMs should be fast enough (just) to run with DTACK grounded, but clearly something was off.
For testing, I jury-rigged a DTACK generator using a 74LS93 binary counter in 3-bit mode. It looks like this:
7 days ago •
After a frustrating few days, the rosco_m68k is now successfully running code from the EEPROMs! It turns out I'd wired the ROMs to the wrong half of the data bus (facepalm, endianness again), and also needed to make a few other tweaks to get it working.---------- more ----------
The board currently looks like this (with a few not-yet-permanent fixes):
The key differences are:
DTACK is no longer grounded. The upper left breadboard in the picture contains a (temporary, but possibly soon to be permanently wired on the main board) DTACK generator based on a 74LS93 binary counter (in 3-bit mode) and a NOR gate. This is driven by the AS line (which drives the counters reset line) and the CLK, with DTACK being generated by the negated output of Q1, Q2 or Q3 depending on how long the delay needs to be (hardwired configuration right now).
Theres also an extra breadboard plonked on top of the main board in this pic, which is just a bank of resistors that are weakly pulling the data bus high.
Both of these changes are attempting to improve reliability. While the system does properly boot every time and starts running code, it occasionally wandered off into the wilderness and ended up double faulting (and asserting the HALT line).
The DTACK generation seems to have helped quite a bit in this regard - without it, the system felt a lot less reliable that it does with it. Sadly though it's still not 100% - although it will often run for several minutes it usually ends up halting for some reason.
But for now, I'm just happy it's doing anything at all - I've been a few days figuring out what was going wrong, and with only 8 channels on my logic analyzer it's been a challenge to try and see what the various bus lines were doing.
05/08/2019 at 16:06 •
While building the address decoder, I realised I'd made a couple of mistakes in the design. Now they're fixed, I'm posting the updated schematics (They're available on Github as usual, too).---------- more ----------
05/08/2019 at 15:36 •
So I finally gathered all the parts I needed, and since I have some time off work this week I managed to build the address decoder. I'm happy to say it was fairly painless although time-consuming - routing all the wires has taken the best part of a day. To be fair, a couple of hours of that were spent debugging a couple of mis-wired connections though.
It looks like this:---------- more ----------
This handles all the address decoding I've talked about previously, and has the /BOOT line generator as well (the slightly out-of-place looking IC in the center top is a DM54174 - a military-grade variant of the 74174 Hex-D Flip-flop I found in my parts bin, and which pulls /BOOT low for 4 memory cycles after reset).
I did realise while building this that I had the odd/even RAM/ROM selects mixed up - the m68k is big-endian of course, so I've fixed that in the build and also pushed new schematics and simulation to Github. I'll also update the previous log in which I showed the address decoder to reflect the fix.
Here's another pic showing the build in-progress, when I had all the inputs wired through jumpers so I could make sure things worked as I built it:
And here is a full shot of the board in its current state. You'll notice that I've added a bare board in the center which I'm using to break out the control, address and data buses (not everything is wired up yet):
Finally, if you want to see it in action, I made a short video where I manually drive the control lines and have some LEDs displaying the output of the decoder:
That's all for now, tomorrow I'm planning to finish hooking up the memory chips, and then burn something simple to the ROMs and get this thing running some real code!
05/05/2019 at 19:40 •
Because I'm still waiting on some new breadboards (I've run out of space building the address decoder), I decided to take a slightly different tack and finish off the emulator I've been writing for the rosco_m68k.
I wanted to build an emulator with the same address-space layout and features as the real hardware, so I could make a start on developing software in parallel with the hardware build.
It's pretty simple - I've used the excellent Musashi m68k CPU emulator, and tied it together with a bit of C++ glue code to simulate the architecture. As the hardware design grows, I hope to keep the emulator up to date with it.
(Caveat: at the moment there's a couple of MSVC-specific lines in there, and the firmware is written for Easy68k. I'll fix that soon, once I move everything over to my main Linux development box. I've already got a 68k cross build of GCC and a basic build using that and VASM, so almost there...)
04/28/2019 at 10:50 •
Just a quick log - since I'm about to start building the address decoder and connecting the CPU up to actual RAM and ROM, I thought I'd better quickly draw up a schematic for the free-run configuration before I tear it down.
Here it is:
Obviously the /HALT, /RESET and /CLK lines are connected to the circuits shown in previous logs.
As always, the EAGLE file is on Github.
04/27/2019 at 23:36 •
[Edit: I've added a schematic for this circuit at the bottom of the log!]
I'm not sure what exactly I was thinking of when I wrote the previous log about handing the /BOOT line, but it's completely and utterly wrong. Luckily, I realised this when actually designing it properly (rather than just hacking around in Logisim).
The short version is that, in the log, I said I needed to hold the /BOOT line low for the first four clock cycles - this is wrong in a very important way: it's not four clock cycles, but four memory cycles!
Once I'd realised it was wrong, I went back to the 68000 users manual to check the timings for those initial reads. I also hooked up the logic analyzer to the 68010 to make myself absolutely certain that the chip would actually do the four 16-bit reads I expected after /HALT and /RESET are deasserted. I wanted to double-check this because if it did eight 8-bit reads I'd have to redesign the address decoder to support /UDS and /LDS when /BOOT was asserted.
Thankfully, it looks like it does exactly what I expected (I've annotated the screenshot for clarity):
You'll notice it's actually 16 clock cycles for the four reads (assuming zero wait states). However, this doesn't actually matter - because I know it's four memory cycles, I can simply drive the shift register with the /AS line instead of CLK. Once there have been four cycles, /BOOT will be deasserted and all will be right with the world.
Also, as mentioned in the screenshot, because the initial SSP and PC are fetched with 16-bit reads, I don't need to worry about /UDS and /LDS when /BOOT is low.
So yeah, dodged a bit of a bullet there...
Update: Here is the schematic for the actual circuit that handles the /BOOT line:
And how it looks when analyzed (The important lines here are /AS and /BOOT, the other Qs are the outputs of the intermediate flip-flops I was looking at while debugging a mis-wired connection):
04/21/2019 at 20:59 •
(EDIT: This log is wrong. I was obviously not thinking properly when I wrote it. The full story is in the next log but TL;DR is that it's four memoy cycles, not four clock cycles).
As discussed in the previous log about the address decoder, I need a way to hold a /BOOT line low for the first four clock cycles after a reset. This means using some kind of counter.
I don't have any of the 7400-series counters to hand, and neither does my awesome local electronics store at the moment, but what i do happen to have is a ton of 74LS174 hex D-Flip-flops (with common reset, unlike the 72LS74). So I'm just going to add one chip and use five of the flip-flops instead.
I've not even EAGLEd this yet, but the concept looks like this in Logisim (when the reset line is active):
And, after reset goes high and the first couple of clocks have passed, /BOOT is still low:
But from the fifth clock onward, /BOOT goes high, and stays high, until /RST goes low again.
This is pretty simple (it's really just a 5-bit shift-register with its input tied high) and stays with my philosophy of trying to work with what I've got, rather than reaching out for another IC that does what I need, but probably stuff I don't need, too.
Anyway, the theory's there. I'll find out if it works once the rest of the parts for the address decoder arrive and I can actually build it.
04/21/2019 at 20:34 •
Address decoding for the m68k is a bit more involved than for most (all?) of the 8-bit CPUs that were around at the same time, and so requires a bit more careful design. The specific things that make it complicated are:
- The larger (16MB) address space
- The different address spaces supported by the processor (e.g. Supervisor program)
- The /UDS and /LDS lines (used to select upper byte, lower byte, or both bytes for a 16-bit operation)
- The fact that there's no separate IO address space
- The requirement to have ROM at 0x00 for the first four clock cycles, then RAM there afterward
My address decoder design completely ignores the second item on that list, and just uses one address space. I may decide later to expand to support the different address spaces, but for now I don't need it.
The /UDS and /LDS lines are easily supported in the usual way for m68k builds - having odd and even ROM and RAM chips. This means that chips must always come in pairs, but it simplifies the logic quite a lot and anyway, I've found parallel chips are easier to get with 8-bit data width.
The last point is quite interesting - At startup, the m68k family expects the first eight bytes of memory to contain two 32-bit longwords, one each for the initial stack pointer and the initial program counter. Therefore, at startup (or on reset) the first eight bytes of memory should really be ROM. However, during normal execution the m68k requires RAM at the bottom of memory, to allow interrupt vectors to be modified (at least, the 68000 does. With the 68010 its not strictly necessary due to the 010 having the VBR register, but I want to have RAM at the bottom of memory in normal running anyway). The 68000 Programmers Manual does actually recommend a solution to this - simply map ROM low for the first four clock cycles. So the address decoder has to have a way to make that happen.
The memory map I decided I wanted for this system is:
- 0x000000 - 0x0FFFFF - Onboard RAM (1MB)
- 0x100000 - 0xF7FFFF - Expansion Ram (Initially, will just generate /BERR)
- 0xF80000 - 0xFBFFFF - IO (256KB)
- 0xFC0000 - 0xFFFFFF - ROM (256KB)
(With the caveat previously mentioned that, for the first four cycles after reset, ROM will be mapped low).
I fired up Logisim, and after a few (read: a lot of) iterations I had the following design, which I think does everything I need it to do:
The address bus is at the top left, and currently set to address 0x0. Notice the /BOOT line, which is low in the image - this is how I'm controlling whether the ROM is currently mapped low or not. You can see that, with that active, the /ROMCS lines are active.
When the /BOOT line is high (i.e. during normal running) the /RAMCS lines are active instead:
As you can see, the /BOOT line just directly selects ROM, bypassing the normal way it is selected, using the highest four address lines. This means that ROM is just shadowed low with this setup.
It also doesn't do anything with the /UDS and /LDS lines, meaning that when /BOOT is low, the chip can only do full 16-bit memory accesses - this should be fine because, according to the manual, that's all it will do during those first clock cycles, in order to read those two 32-bit values. After that point, /BOOT will go high, and the /UDS and /LDS lines are decoded as normal and used to select the appropriate chips.
The /IOSEL line indicates that the address decoded falls into the IO range - this will need further decoding to select the appropriate IO device - since I have none at this point, I'm doing nothing further with it. The same goes for the /EXPANSIONSEL line (which indicates a RAM address outside the 1MB I'll have on the board) - I might eventually use this to drive decoding on a memory expansion board, but for now I'll just tie it to /BERR on the CPU.
This is how it looks in EAGLE:
The major difference to notice is that I just haven't been able to get hold of XNOR gates in the 74LS series. There are some listed but they seem only to be available in the later HC series which isn't TTL compatible. I could probably have gotten them in HCT, but to be honest I have a bunch of 72LS02 chips so I decided to just go ahead and build the XNORs with NOR gates. It ups the chip count by one, but to be honest I was tired of trying to source the chips and wanted to just go with what I had.
That said, this still isn't built yet because I'm waiting on a couple of chips (a 74LS32 and a 74LS00) but they should be here in a few days, so I'll update once its built.
The one thing left to do is handle that /BOOT line, which I'll write up in the next log.
04/13/2019 at 13:15 •
I know I literally just said that the next log would be about the address decoder, but then I remembered I've been meaning to write a quick log about the EEPROM programmer I hacked together for the m68k project, so here's that instead.
(TL;DR - It's on Github: https://github.com/roscopeco/eeprom-programmer)
Once the address decoder is built, I'm obviously going to need to program the EEPROMS for the m68k build. I could go the easy route and just buy one, but I decided I had enough stuff lying around that I should be able to hack one together. It turns out I did, but I had to make some, ahem, compromises to make it work.
Quoted from the README on Github:
This project uses an ESP8266 dev board (NodeMCU 1.0) along with three 74LS174 hex D-flip flops to program the 64 Kbit EEPROMs I'm using in my m68k breadboard computer. The choice of components may seem a bit odd - the design was driven entirely by what I had available on the bench at the time, and my being too impatient to wait for a ten-quid programmer to arrive in the post. So I just hacked this together quickly to tide me over.
So basically I just built a shift register driven by the NodeMCU and then used some of the spare GPIOs to drive the W/E line on the ROM. Obviously I could have used shift registers instead of the flip-flops, but I didn't have any.
I'll say no more about it here, it's well documented on Github and the code is there too. So I'll just post a picture of it and move on to address decoding (for real, this time).