BMOW title
Floppy Emu banner

Archive for the 'Yellowstone' Category

Fixing Laser’s Bugs

Last week I wrote about some test results from Yellowstone, my FPGA-based universal Apple II disk controller based on the Laser UDC design. I described two especially worrisome problems: one with 5.25 inch disks on an Apple IIGS at “fast” CPU speed, and the other with 3.5 inch disks under GSOS. I think I’ve fixed both problems, or at least found work-arounds, but it’s raised a new concern. Both issues look like serious problems in the original Laser UDC ROM code, rather than anything related to my Yellowstone re-implementation. And if the UDC shipped with those bugs, I’m wondering how many other problems it may also have. I don’t want to build a new project on a shaky foundation.

GSOS and 3.5 Inch Disks

In last week’s Yellowstone tests, I discovered that 3.5 inch floppy drives weren’t working under GSOS. They caused an error during booting: Unidisk3.5 requires a driver. Install UniDisk3.5 driver on boot disk and re-boot system. A stock UDC card with the version 4.0 ROM was found to have the same problem. The strange thing was the error mentioning UniDisk3.5 when the drive wasn’t a Unidisk 3.5, but an Apple Disk 3.5. An actual UniDisk 3.5 worked fine. Installing the requested driver didn’t help: the same error still appeared.

After doing some poking, it seemed that the problem was related to the Device Information Block returned in response to a status call. There must be some critical DIB difference between the drives that work and the drives that generate an error. Because the UniDisk 3.5 is an intelligent device, DIB requests are handled by the drive itself. But the Apple Disk 3.5 is a dumb drive, and the Yellowstone firmware (ROM code) must handle DIB requests on its behalf. Presumably GSOS didn’t like something about the DIB response for the Apple Disk 3.5, resulting in that driver error message. I did some testing with various disk controllers and drives, and checked the type and subtype fields in the resulting DIB:

DISK CONTROLLER   DRIVE                          DIB TYPE/SUBTYPE 
IIgs built-in     Apple Disk 3.5                      01/C0
IIgs built-in     Unidisk 3.5 (real drive)            01/00
Yellowstone       Apple Disk 3.5                      01/00
Yellowstone       Unidisk 3.5 (Floppy Emu emulated)   02/20

The Yellowstone firmware, following the example of the UDC firmware, returned the same type/subtype for an Apple Disk 3.5 as the IIGS built-in disk controller does with a real Unidisk 3.5. That probably explains why the error message mentioned UniDisk3.5, but not why there was an error in the first place.

Changing the firmware to return 01/C0 instead of 01/00 changed the error message’s text to AppleDisk3.5, but didn’t help the underlying problem of the disk not working. My guess is GSOS sees the 01/00 or 01/C0 type IDs, and then based on that, it tries to make some extended status or control calls it expects those types of drives to support. But Yellowstone / UDC doesn’t handle those calls as expected, causing GSOS to complain about needing a driver. I’m not sure if Laser never tested the UDC with GSOS and 3.5 inch drives? Or maybe GSOS didn’t exist when the UDC was originally released?

My fix was to change Yellowstone’s type/subtype ID for the Apple Disk 3.5 to 02/00, which should indicate a general removable Smartport hard disk. This eliminated the errors under GSOS, and everything seems to work OK. I’m unsure if this change may create any new problems, however. A floppy disk isn’t the same thing as a removable hard disk, but maybe it doesn’t matter as long as the firmware knows how to read and write the disk. I’ll keep testing.

IIGS Fast Mode and 5.25 Inch Disks

After a closer look at many 5.25 inch disks, I realized that all DOS-based 5.25 inch disks failed to boot properly on a IIGS with the CPU speed set to “fast”. This included the DOS 3.3 System Master disk, Bank Street Writer, Donkey Kong, Choplifter, and many others. But 5.25 inch disks based on ProDOS all seemed OK, including the ProDOS System disk and others like Shrink It. Very strange.

I examined the disk I/O signals with a logic analyzer. For the DOS-based disks, after the initial drive recalibration and loading of sector 0, it looked like all the drive operations were happening about 2.5x too fast. This is roughly the speed difference between code running on a IIGS in fast mode versus normal mode. So for reasons unknown, the disk code wasn’t being automatically slowed to normal 1 MHz speeds as is required for 5.25 inch disk compatibility.

The Yellowstone firmware slows the IIGS to 1 MHz whenever one of Yellowstone’s disk API functions is called, and restores it to the previous speed when the function exits. For ProDOS-based software, I think all the disk I/O happens through the API, so the IIGS speed is adjusted as needed and everything works.

But for DOS-based software, only the loading of sector 0 is directly handled by Yellowstone firmware. After that, DOS’s RWTS routines bypass the Yellowstone firmware and directly control 5.25 inch drives through memory-mapped I/O registers. If the RWTS code runs at “fast” speed, then you get the behavior I observed, and disks won’t boot properly.

This explains why Yellowstone wouldn’t work for DOS-based 5.25 inch disks, but then how do other disk controller cards work? Why doesn’t a Disk II controller card have the same problem on a IIGS at fast speed?

Motor-On Detector Voodoo

Bits 0-3 at address $C036 on the IIGS are used to enable motor-on detection for a Disk II controller card in slot 4 through 7. It’s a nifty feature. Each bit enables motor-on detection for a different slot. When enabled, the IIGS attempts to keep track of the motor-on state for a Disk II controller card in that slot, by watching for memory accesses to $C0x9 (on) and $C0x8 (off), where ‘x’ depends on the slot number. When motor-on detection is enabled and the motor is on, the IIGS is automatically slowed to 1 MHz to ensure that disk-related code works as expected. Thanks to the folks at for clearing this up.

Now why does motor-on detection work for a real Disk II controller card, but not for Yellowstone? I’m not certain, but I suspect the IIGS firmware scans the installed peripheral cards during boot, and checks each card’s ROM signature to see if it’s a Disk II controller. If it is, the IIGS enables motor-on detection for that slot. But Yellowstone has a different ROM with a different signature, so it doesn’t get detected, and motor-on detection remains disabled.

The solution is for Yellowstone’s initialization code to manually enable motor-on detection, but this is trickier than it sounds, and it appears Laser themselves screwed this up. I’m working off UDC ROM version 2.3, which makes no attempt to enable motor-on detection. Patching it won’t be simple, because it’s a massive block of absolute address references with almost no free bytes where a patch could be inserted. UDC ROM version 4.0 was a major rewrite from v2.3, and it enables motor-on detection for ALL of slots 4-7, regardless of which slot the card is actually installed in. This is wrong, and potentially interferes with the operation of other cards in those slots that might use $C0x9 and $C0x8 for unrelated purposes. For now I’ve implemented a temporary “fix” that confirms motor-on detection will solve the problem with DOS-based disks, but my fix breaks other things. I’m still searching for a better solution.

One interesting side-effect of this motor-on detection mechanism is that IIGS disk controllers in slots 4-7 work differently than slots in 1-3. There is no motor-on detection for slots 1-3, so if you install a Disk II controller there, or any other disk controller that relies on motor-on detection, it won’t work for DOS-based 5.25 inch disks when the IIGS speed is set to fast. You can test this yourself. Install a Disk II controller in slot 4, and enable the card in the GS Control Panel. Try booting a DOS 3.3 disk and confirm it works. Now move the Disk II controller to slot 2 and try again, and watch the drive loop endlessly between tracks 0 and 2.

Read 7 comments and join the conversation 

Testing Yellowstone

Work continues on Yellowstone, my FPGA-based universal Apple II disk controller based on the UDC design. I’ve finished some initial testing, and while the results were mostly positive, a few problems may spell trouble.

First the good news: I’ve tested Yellowstone successfully with reading and writing 5.25 inch drives, 3.5 inch drives, and Smartport hard drives. I tried it with an Apple IIe as well as an Apple IIGS, and with a good variety of different disks. I tried GS/OS. I tested a whole pile of copy-protected 5.25 inch disk images. While not everything went smoothly, most of the results have been positive.

The majority of the testing has been with my BMOW Floppy Emu disk emulator rather than any real disk drives, because the current Yellowstone prototype is a 3.3V device without 5V-safe inputs. The next iteration of the prototype will add a 5V buffer for safety. The inability to test with real drives means I also haven’t yet tested daisy-chaining or dual-drive support. But before I realized the potential risk to the 3.3V hardware, I did try the card with a Unidisk 3.5 drive, and everything worked fine. Hopefully I didn’t damage anything.

I’ve also tested Yellowstone in a computer that’s stuffed with other cards in the peripheral slots, rather than just Yellowstone by itself. This was the downfall of my original efforts on this project, a couple of years ago: the card didn’t work when too many other cards were also present, but I couldn’t determine why, and I eventually gave up. That problem seems to be resolved now. I tried the updated card in both the IIe and the IIGS with all slots filled but one, and everything looked good – almost. I did experience one intermittent error on the IIGS with the slots filled, but I think it was a coincidence and the cause of that error is probably unrelated. I wasn’t able to reproduce it after more attempts.

Now for the bad news:

Bad Status Codes in Smartport Request

When booting GS/OS 6.0.2 from a Smartport HD disk image with Yellowstone, twice it failed part-way through the boot sequence with a “status code 0A” error on the Floppy Emu’s display. This means Floppy Emu received a status request of type $0A, which is undefined (valid values are $00 through $03). But it worked normally on about a dozen other attempts, and I wasn’t able to find any pattern to explain what might cause this. The correct behavior would be for Floppy Emu to return a response $21 meaning ‘invalid status code error’ instead of aborting, so I can try this if it happens again. But I’m not sure why it happens at all.

Troublesome 5.25 Inch Disks

A few 5.25 inch disks don’t work. Three of these are copy-protected WOZ disk images that don’t work very reliably on standard disk controllers either, so I’m not too upset, but the behavior is worse with Yellowstone. They freeze during booting or the disk just isn’t recognized at all. These are probably caused by limitations of the Floppy Emu’s WOZ support interacting with Yellowstone. Fortunately it was only three out of my collection of 56 most troublesome disks that had any issues.

Two other 5.25 inch disks crash into the Apple II monitor immediately upon booting with Yellowstone: Anti-M (a pre-boot disk to defeat some copy-protections) and Copy II+. I looked at the source code for Anti-M, and its boot sequence copies and patches the code from the disk controller card’s built-in ROM. It appears to assume the disk controller is a standard Disk II controller, or else one of a few other known types, so it’s doubtful this will ever work without patches to Anti-M. I’m guessing Copy II+ is something similar.

In the next version of Yellowstone, I plan to add a switch to select ‘pure Disk II mode’ for disks like these. When it’s on, this switch will disable Yellowstone’s other behaviors and use a vanilla Disk II controller card ROM image. This will hopefully be enough to get those outlier disks working, though I haven’t yet confirmed this.

IIGS Fast Mode and 5.25 Inch Disks

When the IIGS is running at system speed ‘fast’ (the default), I found two 5.25 inch disk images that wouldn’t boot. Both of them cycle repeatedly between track 0 and track 2. I’d probably be willing to write this off as a known-incompatibility, except one of the disks is the DOS 3.3 System Master! When the system speed is changed to ‘normal’ (meaning slow), those disks load normally.

This is unexpected, because the code in Yellowstone’s ROM specifically sets the IIGS system speed to normal whenever it’s doing disk I/O. What’s more, a real UDC card boots these disks just fine at fast speed. I’m not sure exactly what’s wrong, but it’s probably some interaction between my IWM model and the IIGS fast speed for code that bypasses the Yellowstone ROM and directly controls the IWM. This may be difficult to resolve, but I’m optimistic I can figure it out.

IIGS and 3.5 Inch Disks

3.5 inch disk emulation appears to work fine on the Apple IIe, and on the IIGS with 800K disks like ProDOS and ADT Pro. But when attempting to boot GSOS from a 3.5 inch disk, it reports an error: “Unidisk3.5 requires a driver. Install UniDisk3.5 driver on boot disk and re-boot system.” GSOS 5.0.4 and 6.0.1 report the same error. Changing the system speed has no effect. It doesn’t matter whether the drive is a Floppy Emu in 3.5 inch floppy emulation mode, or a real Apple 3.5 Drive.

The kicker here is that a real UDC card triggers the same error. And if I boot GSOS from the built-in disk controller, and attempt to access Yellowstone or the UDC as a secondary controller with a 3.5 inch disk, I still get the same error as soon as it attempts to access the 3.5 inch disk. So as it stands now, Yellowstone is completely useless as a 3.5 inch disk controller on the IIGS if you’re running GSOS.

This bug is the worst of the bunch, because I have no idea what causes it or how to go about fixing it, and it appears to be a fundamental problem with the UDC design rather than some flaw with my Yellowstone implementation. As far as I know, there was never any driver that shipped with the UDC. I’m not sure why GSOS is even complaining about the ‘Unidisk3.5’ driver when I’m connecting an Apple 3.5 Drive rather than a Unidisk. But if Laser / V-Tech never fixed this incompatibility between the UDC’s 3.5 inch floppy support and GSOS, then I don’t think I’ll be able to either.

I do have one small clue: back in 2015 when I was first implementing Floppy Emu’s 3.5 inch floppy drive emulation for the Apple II, I remember seeing this same error from GSOS. I don’t recall precisely what caused it, but I think it was due to the drive responding in unexpected ways to the disk enable signals. This may be GSOS’s generic error message for “something unexpected happened with your disk” rather than a true need for a driver. Has anyone else ever seen this error, or have any thoughts on where to begin troubleshooting?

Read 3 comments and join the conversation 

Yellowstone 3.5 Inch Drive Support!

Success! My Yellowstone disk controller card for the Apple II now works with 3.5 inch floppy drives! Along with the previously-implemented 5.25 inch floppy and Smartport HD support, this completes the triumvirate of Apple II disk drives. While it’s still very rough around the edges, I now have a working universal disk controller for Apple II that can handle any type of disk drive. This is exciting, because existing disk controllers for two of the three drive types are rare, expensive, or both. After a very long period of slow progress, I feel that everything’s finally starting to come together.

I’m especially pleased to see 3.5 inch floppies working, because 1 MHz Apple II machines like my Apple IIe theoretically aren’t fast enough to keep up with the higher bit rate of 3.5 inch disks. There’s not enough time for the CPU to poll for a new byte, store it, and get ready for the next byte before it’s already passed by. The official 3.5 inch disk controller card from Apple solves this problem by placing an entire second computer on the disk controller, with its own 2 MHz 6502 CPU, RAM, and ROM. But Yellowstone uses some Very Special Tricks in hardware to achieve 3.5 inch floppy support on the 1 MHz CPU. It borrows a technique from the UDC disk controller, and forces the computer’s READY signal low to halt the CPU until a new disk byte is ready. This eliminates the need for software polling, and shaves just enough cycles to make everything work.

So now what? This is just the beginning; a proof of concept more than a finished project. I’ve only done the most cursory testing, and I’m sure there are many compatibility problems still to address, and devilish bugs to find and fix. I know about a few of them already. Here’s some of my planned testing:

  • Test all disk types with more thorough read and write tests
  • Try all the copy-protected 5.25 inch disks that rely on weird behaviors
  • Test formatting disks
  • Test with other cards installed in every slot
  • Test with an NMOS 6502 CPU
  • Boot from another disk controller and access Yellowstone as a secondary
  • Use with Apple IIGS at fast speed
  • Boot GSOS from 3.5 inch floppy and Smartport HD

Yay for testing. It’s important, but not very fun, and I may enlist some beta testers to help. The other big task still ahead is to design the second hardware version of the Yellowstone card. The current prototype has sprouted extra patch wires and even an extra chip glued to the board, but it’s still missing some key features. Here are some of the items on my to-do list:

  • Remove SPI ROM
  • Add external SRAM
  • Add a second disk connector
  • Add a switch to select between 2-port operation or daisy-chain 1-port
  • Buffer to isolate FPGA from disk signals
  • Connect Q3 and IOSTROBE to FPGA clock pins
  • Connect the upper 4 address lines
  • Connect RDY and PHI1
  • Add output buffer for RDY
  • Make better / wider GND connections
  • Improve the bypass capacitors
  • Allowance for in-circuit JTAG / SPI reprogramming
  • Allowance for self-test or external test
  • Add open-drain buffers or inline resistors for disk signals with multiple drivers
  • Label all the unlabeled pins and ports on the card
  • Switch to a bigger LDO voltage regulator
  • Add more power and ground test points
  • Round the corners on PCB

That ought to keep me busy for a while.

Read 11 comments and join the conversation 

Yellowstone 5.25 Inch and Smartport Support

Way back in 2017, I began development of Yellowstone, an FPGA-based disk controller card for the Apple II. It’s hard to believe it’s been almost four years. Sometimes I feel like I’m moving inch by inch along a journey of a thousand miles. But today I made some significant progress, and a milestone of sorts.

My earlier efforts were focused on duplicating the functionality of the Liron disk controller card (for Unidisk 3.5 and Smartport hard drives), and separately on the Disk II controller card for 5.25 inch drives. More recently I’ve been working on mirroring the functionality of the UDC disk controller, because it supports all of those types of drives as well as standard 3.5 inch drives, and it can automatically detect drive types. Today’s good news: when configured as a UDC, Yellowstone is now able to auto-detect, read, and write Unidisk, Smartport, and 5.25 inch drives! That’s basically everything the UDC offers except for 3.5 inch drive support, which is my next goal. It may sound like I’ve merely duplicated what I had before, but the UDC works quite differently from other disk controllers, and reaching this point means I’m getting closer to unlocking the full potential of a “universal” disk controller.

I’ve discovered some interesting things along the way. Many readers probably know that the Disk II controller card was Apple’s first disk controller, designed by WOZ and built entirely from simple off-the-shelf parts. Later Apple developed the IWM or “Integrated Wozniak Machine”, which did everything the Disk II controller could do, all in a single chip. But the IWM wasn’t just a replacement for the Disk II circuitry; it modified and extended it in a backwards-compatible way. The differences are subtle, but important. For example, if you write a byte to the Disk II controller while the disk is turned off, it has no effect. But if you write a byte to the IWM while the disk is turned off, it updates a configuration register that controls some interesting extra features.

I had been working towards creating an accurate IWM model, but what I discovered is that the code in the UDC’s ROM doesn’t really work with an IWM. It expects to be paired with some custom logic whose behavior is much closer to the original Disk II controller. It does strange-seeming things, like reading and writing from Smartport hard drives without ever asserting the drive’s enable signal. And it leaves a few other mysterious behaviors where I must guess at what’s intended. I’ve had to modify my Verilog design, breaking some of the IWM behaviors in order to match the UDC expectations. That makes me a little uneasy; I don’t really want to maintain two different designs. Fortunately the differences aren’t extensive.

3.5 inch drive support is the next step, but there’s so much to do beyond that. The real UDC card supports two independent disk connectors, but Yellowstone only has one. Some later versions of the UDC also support daisy-chaining drives, which I’d love to get working for Yellowstone too. Unfortunately there are UDC versions with Smartport support, and versions with daisy-chaining support, but none with both. Combining the two may be a major challenge.

After Yellowstone is functionally complete, there will still be plenty more work to do. I need to redesign the board to better isolate the FPGA from any 5V signals, and generally make it as robust and foolproof as possible. I need to decide what I’m doing about the required DB-19 female connectors, which are stupidly difficult to find, though I do have some. I need to revisit all that ROM packing stuff I described here recently, to see if I can’t squeeze everything into a more common FPGA with a lower cost. I probably need to build some kind of end-user reprogramming capability too, to allow for bug fixes or new features. I’m using a JTAG programmer and the Lattice development software, but that’s not a user-friendly solution. That could become a major project in its own right. And finally I need to design a self-test capability, or an external testing rig, that can be used to verify large numbers of boards (relatively speaking) after they’ve been assembled. At the rate I’m going, I’ll be busy for a long time!

Read 1 comment and join the conversation 

Yellowstone Progress Update

I’m still working on development of an FPGA-based disk controller card for the Apple II – Yellowstone. Over the past couple of months, I spent a long while analyzing the design of the UDC disk controller. The UDC supports all three major types of Apple II disk drives, making it a promising place to begin learning. After that I spent a long while more exploring how I might squeeze the UDC’s 8K of ROM and 2K of RAM into the limited resources of Yellowstone’s FPGA. Just recently I finally finished up those investigations and returned to actively building and testing the Yellowstone card. Unfortunately it still doesn’t work.

I built a second Yellowstone prototype, identical to the original except for selecting a Lattice MachXO2-2000 FPGA instead of a MachXO2-1200. This new chip is just barely large enough to hold the necessary ROM and RAM for my UDC pseudo-work-alike Verilog code. I’m not sure if I’ll use this solution for the final edition of Yellowstone, or if I’ll use a smaller MachXO2 version paired with a separate ROM or RAM, but at least I’m up and running again.

The card seems to work as expected when I probe its memory space from the Apple II monitor. I can access all 8K of ROM via its custom bank-switching logic, and its 2K of RAM also through bank switching. I can probe its soft-IWM and watch the disk I/O lines change. Everything looks OK. But when I try to actually boot a 5.25 inch disk, it just freezes the computer.

It’s not completely dead; it does do *something*. The disk drive turns on and spins. Using a logic analyzer, I can see some brief activity on the disk I/O lines that I interpret as “hello, are you a 3.5 inch drive?” before it goes silent. If I then reset the Apple II and examine some memory locations where I know the UDC store status info, I can see that it detected one disk drive. But why didn’t it boot? More importantly, why did it freeze?

If this were a normal software program, I could use a debugger to interrupt the program and see where it’s frozen. That alone might be enough to reveal what’s wrong. If not, I could restart the program from the beginning, and step through it line-by-line until I found the problem. But nothing like that is possible here. There’s no facility for Apple II breakpoints or single-stepping through code that’s in ROM, and even if there were, the I/O code is timing-dependent and would likely break when run in the debugger. The poor man’s debugger is printed log messages, flashing LEDs, and similar indicators, but even that will be difficult. I can’t easily add or edit code in the UDC ROM, because it contains lots of absolute address references as well as implicit assumptions about certain chunks of code and data avoiding page boundaries.

I wish I still had my old HP 1631D logic analyzer. Then I could hook up 24 probes to the Apple II’s address bus and data bus and then let the computer run, examining the logged CPU cycles afterwards using the HP’s state listing view. My Saleae logic analyzer is nice for many tasks, but even if it had 24 probes, it’s basically only designed for timing / waveform views. I guess not many people look at parallel busses anymore.

Read 12 comments and join the conversation 

FPGA Block RAM Packing

In an earlier blog post, I was lamenting how one-ninth of an FPGA block RAM was wasted when storing 8-bit ROM data, because there’s no simple way to make use of the 9th parity bit in each word of a block RAM. Horrors! To fight this injustice, I’ve developed a solution that I call packed ROM. It stores nine 8-bit bytes in eight 9-bit words of block RAM, and provides an interface to read the data as if it were an 8-bit memory with a larger depth. Using this method, I’m able to store 1152 bytes of read-only data per block RAM instead of only 1024. The solution relies on the fact that the block RAMs are dual port – you can read from two different addresses simultaneously. Compared with using the same number of block RAMs as a standard 8-bit wide ROM, this solution consumes an extra 54 LUT4s in a MachXO2-1200 FPGA – about 4 percent of the total. It increases the MachXO2-1200’s effective capacity for this type of 8-bit ROM data from 7168 to 8064 bytes.

Here’s the Verilog code, as well as a Python program that reads a plain binary file and writes a “packed” file in .mem format. The code assumes 7 block RAMs, but should be easily adaptable to other numbers.

module packedROM #(parameter NUM_BLOCK_RAMS = 7) (
    input [12:0] addr,
	input clk,
	output reg [7:0] Q
	// packs 1152*NUM_BLOCK_RAMS 8-bit data bytes into 1024*NUM_BLOCK_RAMS 9-bit words 
	// uses 54 LUT4s of the MachXO2
	// may need to change addr width depending on NUM_BLOCK_RAMS. Use $clog2()? 
	// nine bytes A-I are packed into eight 9-bit words as follows:
	// 0: I3 I2 I1 I0 A4 A3 A2 A1 A0
	// 1: I7 I6 I5 I4 B4 B3 B2 B1 B0
	// 2: F7 F6 E7 E6 C4 C3 C2 C1 C0
	// 3: H7 H6 G7 G6 D4 D3 D2 D1 D0
	// 4: A7 A6 A5 E5 E4 E3 E2 E1 E0
	// 5: B7 B6 B5 F5 F4 F3 F2 F1 F0
	// 6: C7 C6 C5 G5 G4 G3 G2 G1 G0
	// 7: D7 D6 D5 H5 H4 H3 H2 H1 H0
	// bytes A-H are sequental in the byte-oriented address space below addr 1024*NUM_BLOCK_RAMS
	// byte I is one of the "extra" bytes, in byte-oriented address space beyond addr 1024*NUM_BLOCK_RAMS
	reg [12:0] wordAddressA;
	reg [12:0] wordAddressB;
	wire [8:0] QA;
	wire [8:0] QB; 
	// dualPortROM is a wrapper for the MachXO2 block RAMs, created by the Lattice IP Express tool.
	// it is actually a dual port RAM with the write input unused
	dualPortROM myDualPortROM(
	wire [12:0] overflowAddr = addr - (NUM_BLOCK_RAMS * 1024);
	always @* begin
		if (addr < NUM_BLOCK_RAMS * 1024) begin
			// packed area, bytes A-H
			wordAddressA <= addr;
			// word address for the upper bits depends on low three bits of the byte address
			case (addr[2:0])
				0: begin // A
					wordAddressB <= { addr[12:3], 3'b100 };
					Q <= { QB[8:6], QA[4:0] };	
				1: begin // B
					wordAddressB <= { addr[12:3], 3'b101 };
					Q <= { QB[8:6], QA[4:0] };	
				2: begin // C
					wordAddressB <= { addr[12:3], 3'b110 };
					Q <= { QB[8:6], QA[4:0] };	
				3: begin // D
					wordAddressB <= { addr[12:3], 3'b111 };
					Q <= { QB[8:6], QA[4:0] };	
				4: begin // E
					wordAddressB <= { addr[12:3], 3'b010 };
					Q <= { QB[6:5], QA[5:0] };	
				5: begin // F
					wordAddressB <= { addr[12:3], 3'b010 };
					Q <= { QB[8:7], QA[5:0] };	
				6: begin // G
					wordAddressB <= { addr[12:3], 3'b011 };
					Q <= { QB[6:5], QA[5:0] };	
				7: begin // H
					wordAddressB <= { addr[12:3], 3'b011 };
					Q <= { QB[8:7], QA[5:0] };	
		else begin
			// overflow area, byte I
			// word address is byte overflow address times 8 for the lower bits, and times 8 plus 1 for the upper bits
			wordAddressA <= { overflowAddr[9:0], 3'b000 };
			wordAddressB <= { overflowAddr[9:0], 3'b001 };
			Q <= { QB[8:5], QA[8:5] };

import os
from array import array

infile = "coderom.bin"
outfile = "coderom.mem"

inputData = array('B')

insize = os.path.getsize(infile)
with open(infile, 'rb') as f:
    inputData.fromfile(f, insize)
    out = open(outfile,"w") 
    num_block_rams = 7
    outsize = 1024 * num_block_rams
    for x in range(0,outsize):
        baseAddr = x & ~7
        if x & 7 == 0:
            out.write('{:02X}\n'.format( (((inputData[outsize+baseAddr//8])&0xF)<<5) | ((inputData[baseAddr])&0x1F)))
        elif x & 7 == 1:
            out.write('{:02X}\n'.format( (((inputData[outsize+baseAddr//8])&0xF0)<<1) | ((inputData[baseAddr+1])&0x1F)))
        elif x & 7 == 2:
            out.write('{:02X}\n'.format( (((inputData[baseAddr+5])&0xC0)<<1) | (((inputData[baseAddr+4])&0xC0)>>1) | ((inputData[baseAddr+2])&0x1F)))
        elif x & 7 == 3:
            out.write('{:02X}\n'.format( (((inputData[baseAddr+7])&0xC0)<<1) | (((inputData[baseAddr+6])&0xC0)>>1) | ((inputData[baseAddr+3])&0x1F)))
        elif x & 7 == 4:
            out.write('{:02X}\n'.format( (((inputData[baseAddr])&0xE0)<<1) | ((inputData[baseAddr+4])&0x3F)))
        elif x & 7 == 5:
            out.write('{:02X}\n'.format( (((inputData[baseAddr+1])&0xE0)<<1) | ((inputData[baseAddr+5])&0x3F)))
        elif x & 7 == 6:
            out.write('{:02X}\n'.format( (((inputData[baseAddr+2])&0xE0)<<1) | ((inputData[baseAddr+6])&0x3F)))
        elif x & 7 == 7:
            out.write('{:02X}\n'.format( (((inputData[baseAddr+3])&0xE0)<<1) | ((inputData[baseAddr+7])&0x3F)))

Read 4 comments and join the conversation 

Older Posts »