1 Chip
MSX How-to
=================
What
does the OCM hardware comprise?
------------------------------------
There's
not much to the OCM. The important bits are:
* 21.48
MHz input clock
*
Altera Cyclone EP1C12 FPGA
*
Altera EPCS4 serial configuration device
* 32MB
SDRAM
* Video
out (TV/VGA)
* PS/2
input
There
are also 2 USB ports on the board. The differential I/O lines are connected
directly to the FPGA. As-supplied, these ports do nothing at all. To be able to
use these ports, the FPGA would have to be configured with a USB host or slave
IP core.
There's
an SD/MMC card slot for emulation/transfer of disk images. I don't know much
about this atm.
How
does the OCM work?
----------------------
The
EP1C12 is a relatively small FPGA. As-supplied, the MSX2 core utilises 83% of
the logic. This leaves a lot less room than you would at first think - once you
get above 90% utilisation, you start to hit problems routing and meeting the
timing requirements of real-world designs.
The EP1C12
has (IIRC) about 27KB of SRAM. This is nowhere near enough RAM for the MSX2
BIOS and extended ROMs, Disk ROMs, character ROMs, etc. So where are the ROMs
stored?
The
EPCS4 serial configuration device is a flash-based device that is used to store
the FPGA configuration image. However, it is more than large enough to store an
EP1C12 FPGA image - the remainder can be used by the FPGA application as serial
flash storage. The OCM loads the ROMs into SDRAM when it first boots via a
512-byte "IPL" (Initial Program Load) ROM embedded in the FPGA image
that runs on the Z80 (more details below).
PS/2
input provides emulation of the MSX keyboard on a standard PC keyboard.
The
video output is quite nicely done. The same FPGA bitstream provides a couple of
TV (composite) and VGA output modes, which can be switched on-the-fly with the
<PRINT SCRN> key on the PS/2 keyboard. The default output mode is set on
two of the board's DIP switches. There are also a couple of video
"debug" modes, including an OSD display of the VDP registers, which
can be cycled with the <F12> key.
Again,
there's no SD/MMC slot on my hardware, so I don't know much about this.
Hardware
Requirements for Porting OCM
-------------------------------------
Basically,
you need the "important bits" above, or a super-set there-of.
You
*need* some sort of input clock. Hopefully the PLL multipliers/dividers will
work out OK for you.
You
*need* a Cyclone (EP1C12 or larger) or a Cyclone II (equivalent or larger).
You
*need* an EPCS4 or larger (I've used an EPCS16 for example).
You
*need* at least 1x 32MB SDRAM device. You could use a larger device with
modifications.
You
*need* some sort of video output.
You
*need* some sort of PS/2 input.
SD/MMC
would be a bonus.
DIP
switches would be a bonus.
If you
are hoping to port it to a Xilinx device - good luck! Your biggest problem will
be booting the ROMs. A few days ago I knew absolutely nothing about the MSX or
the OCM - so I found it quite challenging to decypher _any_ of the 512-byte IPL
ROM disassembly (and I _do_ know Z80 inside-out). A hint though - look at the
PLDLOAD/PLDSAVE source code, that has very similar routines! You'll basically
have to completely replace the IPL with something equivalent to boot your ROMs
from wherever you want to boot them - but I don't understand what other magic
'bits' in the core it's twiddling in the process.
The
Port
--------
The
first step is to create a wrapper around the top-level emsx_top.vhd file. You
can leave most of the signals unconnected - the cartidge slots, joysticks, USB
and reserved pins for example. You really only need concern yourself with
clocking/reset, SDRAM, video, PS/2 and dipswitches. I won't go into any more
detail here because if you don't know what you're doing at this point, you
probably shouldn't be attempting the port.
*** I
should note at this point that I've still got glitches with my port. For
instance, my design won't boot from the EPCS without Altera's
"SignalTap" compiled into the project. I'm yet to narrow down the
problem, but it could be related to the lack of pull-ups on the cartridge slot
"inout" ports. Or it could be SDRAM clock skew. I'm not sure. But
it's a good start!
The
next step is to replace the PLL (unless you have the same clock frequency on
your board) in pll4x.vhd. See the comments in emsx_top.vhd where the PLL
component is declared. You need all 3 outputs of the Cyclone(/II) PLL. C0
should be close to 21.48MHz so the video syncs correctly and so the system runs
at the correct speed. C1 and E0/C2 need to be (exactly?) 4x C0, around 85.92MHz
for the SDRAM. E0/C2 should be assigned to a dedicated PLL output pin - it's
likely your board has one PLL output connected to the SDRAM clock pin. Again,
these frequencies don't need to be exact - within 0.5MHz if possible - but the
4x is crucial.
If
you're porting to a Cyclone II, you'll (probably) need to modify emsx_top and
change the instance of the cyclone_asmiblock to cycloneii_asmiblock. This is
the altera-supplied component that twiddles the active-serial-mode pins to the
EPCS device.
If you
don't have dipswitches on your hardware, then hardwire convenient values for
your own purposes. The default as-shipped is all '1', and if you're looking at
the source to work out what does what, the code logic works with the _inverted_
values.
I'd
strongly suggest a manual 'reset' pushbutton/switch as well - wired to the slot
reset,
That
should be about it for the VHDL portion.
It's
worth testing this before bothering to get the ROMs booting. The design thus
far should enable you to see the OSD on your TV/VGA output. Try toggling the
video modes and cycling through the debug modes as outlined above. If you don't
get any output, or unreadable output, it's back to the drawing board.
Booting
from the EPCS device
----------------------------
Ah, the
fun part!
If
you're porting to an EP1CS12, then your job is easy. If not, it's a little more
involved.
Firstly,
there is a 256KByte Intel HEX format file called "emsx_top.hex". This
contains 4x 64KB segments. The 2nd segment contains the BIOS (32KB), extended
(16KB) and some other ROM. The other segments contain some other data which I
assume is critical to the operation of the MSX. This file needs to be
programmed into the EPCS device at the correct address.
The
EPCS4 is a 4Mbit or 512KByte flash device.
The
MSX2 ROM file is 256KB in total - that's exactly half the EPCS4.
The IPL
expects the hex file data to exist at offset $40000 (top half) in the EPCS
device.
An
EP1C12 FPGA bitstream (compressed) will fit into the first half of the EPCS4.
An
EP2C35 FPGA bitstream (compressed) *won't* fit.
If you
have an EPCS4 and something other than an EP1C12, then there's no way you can
configure it with the FPGA image and the MSX ROMS - it simply won't fit. The
compromise is to program the original EP1C12 image with the ROMs, and always
configure the FPGA via JTAG.
*** A
special note here: my hardware gets into a state where I can't program the FPGA
via JTAG if the board is powerd up with an incompatible bitstream in the EPCS
device. Fortunately, I have both JTAG and ASM ports on the board, and the EPCS
device is also socketed. You may not be so lucky - I accept no responsibility
for bricking your device!
BTW you
can configure a larger EPCS device with a .POF file designed for a smaller EPCS
device.
If you
have a larger EPCS device, then you can fit both the FPGA bitstream and the ROM
files into the device. However, you will need to modify the IPL ROM with the
new offset of the ROM file in the EPCS device.
To
create a new .POF file, use the "Convert Programming Files" option in
Quartus "File" menu.
You can
load the exsiting .COF file, or create a new .POF for your chosen EPCS device.
You
need to add both your .SOF FPGA bitstream and "emsx_top.hex" file to
the .POF contents. Select "Compress" on the SOF entry and
"Relative Addressing" on the hex file entry. Ensure that the
"Memory Map File" option is selected and then generate the file. ***
You won't be using this build of the file - see below ***
Open
the .MAP file produced and look at the address for the emsx_top.hex file. AFAIK
it'll be at the _end_ of the device address range, so perhaps you can assume
it'll be fixed for each EPCS device?!?
Now to
modify the IPL ROM to load the ROMs from the new base address in the EPCS
device.
At
offset $86 in the IPL ROM instance in "iplrom.vhd" is the code:
01 00 02
ld de, 0200h
The
"02" at offset $88 corresponds to the '4' in $40000. The code shifts
the address left 1 bit later on.
Modify
this byte to be 1/2 of the upper word of the offset.
For
example, for my EP2C35 image, the offset was $1C0000, so I replaced
"02" with $0E ($1C/2).
Save
the IPL and re-build. You will of course have to re-generate the .POF as you
did earlier.
There
you have it.
Status
======
As I
mentioned, for some reason my design only works with SignalTap built into the
design.
It also
won't boot immediately after power-up or JTAG programming - I need to hit
manual "reset" which is a switch on the board wired to the
"pSltRst_n" port of emsx_top. Not sure why, although there's a
comment about the reset pulse being 48ms in the source - maybe I need to extend
my power-on-reset module in the top level?
At one
stage, when I was banging on every key on the keyboard looking for the
<BREAK> key, it went berserk. It may well have been me simply hitting the
10MHz turbo button, or it could be a problem with clock skew on the SDRAM.
Aside
from that, it looks good! Now I need to hook up my compact flash to the SD/MMC
port of the core design somehow - probably by emulating a SPI device and then
translating the commands appropriately?!? Fun fun fun...
--
email:
msmcdoug_nospam-at-iinet-dot-net-dot-au