Table of Contents
Fun with Multicomp CP/M
Here I am going to put in various snippets of information gathered from the forums and my own experience in the hope that they will help someone. I assume that you have already built a Multicomp and successfully programmed it using the Altera Quartus II 13.1 web edition software. I'll further assume you have followed Grant's instructions and have a CP/M (or other) computer up and running.
My Setup
I'll begin by documenting my basic Multicomp setup.
- Cyclone II development board
- Cyclone II-C carrier board, fully populated (apart from the second SRAM chip, RTC and RS-232 level shifter)
- 128k Alliance SRAM as shown on Grant's page
- 2GB micro SD card in a SD card adapter. This card is not high speed.
- Standard CP/M build, again as shown on Grant's page
- An enclosure made of a couple of pieces of matte Perspex and black plastic risers
- A USB-serial adapter, plugged into the Serial A header
- VHDL per Grant's design, with the CPU clock set to 25Mhz and SPI clock at 50Mhz.
VHDL to get the basic rig up to 25Mhz
Grant explains on his build page that you set the CPU and SPI clocks by changing a section of VHDL, like this:
-- SYSTEM CLOCKS GO HERE -- SUB-CIRCUIT CLOCK SIGNALS serialClock <= serialClkCount(15); process (clk) begin if rising_edge(clk) then if cpuClkCount <1 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz cpuClkCount <= cpuClkCount + 1; else cpuClkCount <= (others=>'0'); end if; if cpuClkCount <1 then -- 2 when 10MHz, 2 when 12.5MHz, 2 when 16.6MHz, 1 when 25MHz cpuClock <= '0'; else cpuClock <= '1'; end if; if sdClkCount <1 then -- 1 = 50MHz sdClkCount <= sdClkCount + 1; else sdClkCount <= (others=>'0'); end if; if sdClkCount <25 then sdClock <= '0'; else sdClock <= '1'; end if;
This code acts as a pair of clock dividers - one for the CPU clock and the other for the SD card clock - but it is limited to 1/2 the on board clock speed (which is 50Mhz). If you find you cannot run your Multicomp at this speed, check for long wires (especially to the SD card / SRAM), or, if you are using the Cyclone II-C card, look for bad solder joints. I found that, even with a Multicomp connected to the SRAM and SD card with jumper leads (with RAM and SD on small carrier boards), I could run the CPU at 25Mhz. You might want to experiment with the CPU clock speed before adjusting the SD card speed, as a non-booting Multicomp is difficult to debug if you are trying more than one change at a time.
If you want to proceed to the next step, ensure you can run your CPU at 25Mhz.
Overclocking using a PLL
The Cyclone II has what Altera refer to as PLLs (“Phase Locked Loop”). A PLL is normally used to stabilise a clock circuit (that is, ensure the clock frequency does not drift) and the three inbuilt PLLs on the Cyclone II do perform this function. However, they are also able to act as clock multipliers or dividers, within certain limits. Given that we only have an onboard 50Mhz clock and we have to divide that to produce the logic “1” and “0” in the Multicomp's VHDL, if we wish to go faster we need to use a PLL.
Altera have included a facility called a MegaWizard to assist you when creating VHDL for commonly used modules such as PLLs. Here is the procedure for creating a new PLL for your Multicomp:
- Open the Microcomputer project in Quartus II
- Select the menu option Tools → Megawizard Plug-in Manager
- Select “Create a new custom Megafunction variation” and click “Next >”
- In the tree view on the left hand side of the next dialog box, open the I/O folder and double click “ALTPLL”. (Confusingly, it's not in the PLL folder..)
- Select VHDL output file and append a filename (with VHD extension) to the end of the full path, such as “/PLL.vhd”, then click the “Next >” button.
- The dialog box you see configures the PLL.
- In the “Parameter Settings” tab, click “Inputs/Lock” and deselect “Create an 'areset' input” and “Create 'locked' output”. You should see the diagram lose two connections (leaving inclk0 and c0).
- In the “Clock Outputs” tab, click “clk c0” and you will see the current clock settings for the PLL. You can either specify a new clock speed (by entering it in the box at the top) or use the multiply / divide values to set it. Start with 25Mhz so that the clock is the same speed as your non-PLL implementation. Leave duty cycle at 50% and don't adjust the phase shift.
- Click the “Finish” button, twice.
A set of files named “PLL” (.vhd, .qip, .ppf, .cmp) will appear in your Microcomputer directory. These files contain the definition of the PLL you just created using the Megawizard. We now need to include them in the “Microcomputer” project that Quartus II is maintaining, so that they will be compiled along with the other parts of the Microcomputer. Quartus II assumes you want to do this, and pops up a dialog box asking for permission. Click “Yes”.
Now we need to add an instance of the PLL to our Microcomputer's VHDL code. Again, in Quartus, open the Microcomputer.vhd file and locate the section where the clocks are defined. Comment out the CPU clock lines and add an instance for the PLL (in this example, it is called “pll1”):
-- ____________________________________________________________________________________ -- SYSTEM CLOCKS GO HERE -- SUB-CIRCUIT CLOCK SIGNALS serialClock <= serialClkCount(15); -- PLL pll1 : entity work.pll port map( inclk0 => clk, -- connect the Cyclone II's system clock to the input of the PLL c0 => cpuClock -- connect the output of the PLL directly to the cpuClock signal ); process (clk) begin if rising_edge(clk) then -- CPU clock divider code is replaced by the PLL, so it is commented out --if cpuClkCount <1 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz --cpuClkCount <= cpuClkCount + 1; --else --cpuClkCount <= (others=>'0'); --end if; --if cpuClkCount <1 then -- 2 when 10MHz, 2 when 12.5MHz, 2 when 16.6MHz, 1 when 25MHz --cpuClock <= '0'; --else --cpuClock <= '1'; --end if;
Save the file and recompile, then reprogram the Cyclone II board. You should find that the Microcomputer behaves as normal (assuming you already had it running at 25Mhz using the colck divider code you just commented out).
Now, when you look at the component list in the main Quartus window, you should see an additional component. It will be called PLL:pll1 and will have the “wizard” icon next to it. You can double click this component and go back into the wizard, from where you can adjust the speed of the PLL, or add more clock outputs (up to three). Let's see how to replace the SD clock VHDL with another PLL based clock:
- Double click on the PLL:pll1 component to launch the wizard
- Click the “[2] Output Clocks” tab, then the clk c1 tab.
- Enable the clock output by clicking the checkbox “Use this clock”. You will see the c1 wire appear on the schematic of the clock.
- As before, enter the desired clock frequency that you will use for your SD card. I set this to 50Mhz.
- Click the “Finish” button twice. The wizard will warn you that it will overwrite the PLL files; click OK.
Now, integrate the PLL's second clock output with the SD card clock signal. We need to alter the instanciation code for the PLL and comment out the SD clock divider code as it is not necessary:
-- PLL pll1 : entity work.pll port map( inclk0 => clk, -- connect the Cyclone II's system clock to the input of the PLL c0 => cpuClock, -- connect PLL's first clock outpuT directly to the cpuClock signal c1 => sdClock -- connect PLL's second clock output to the SD clock signal );
Comment out the SD clock divider code:
-- SD card clock divider code is replced by the PLL c1 output --if sdClkCount <49 then -- 1MHz --sdClkCount <= sdClkCount + 1; --else --sdClkCount <= (others=>'0'); --end if; --if sdClkCount <25 then --sdClock <= '0'; --else --sdClock <= '1'; --end if;
Now, recompile and reprogram the Cyclone II card. You should find it's a bit quicker to access the SD card now, although testing indicates that the CPU becomes a bottleneck when the SD clock is at 50Mhz.
You can now experiment with the CPU and SD clocks to determine how fast your Cyclone II will run at. I found that with the “Alliance” SRAM, the highest I could get it to was 33Mhz CPU, 50Mhz SD.
Make it faster with better SRAM
Retrobrew forum member Bingo600 performed some experiments with faster SRAM. The Alliance SRAM access speed is 50ns but it is possible to improve on this by using a Samsung chip, as explained in his thread here: https://www.retrobrewcomputers.org/forum/index.php?t=msg&th=98&goto=1263&
The Samsung K6R4008V1D-JC10 RAM has a 10ns access time and it needs to be mounted on an adapter card (shown in the thread). Soldering it to the board is as tricky as it looks; you need a fine point iron and patience (thin solder wire helps, too). Ask on the forum for supplies of the board and if you need to get it fabricated yourself, the gerbers were uploaded here: https://www.retrobrewcomputers.org/forum/index.php?t=msg&th=342&goto=5576&#msg_5576
Replace the Alliance SRAM chip with one of these Samsung chips, mounted on a board and you can up the PLL c0 output (CPU clock speed). Bingo600 managed 90Mhz with a 6809 core, but the best I managed on my Z80 core was 50Mhz.
Improve the VGA screen font
I never liked the look of the PC-like screen font that Grant's original design uses, so I looked to see if I could find an alternative. I found an 8×8 font that fits the bill, built into a short executable that loads it on an Amstrad PCW. It's called “SanSerif”. Using a hex editor, I stripped out the loader code to leave a bitmapped 8×8 font which is in the same format as the font file that comes with Grant's download. The easiest way to incorporate this into your Multicomp is to replace the existing font file with mine.
The font file is located in the Multicomp Components/TERMINAL directory and it's called CGAFontBold.hex (also, CGAFontBoldReduced.hex).
Copy these two files to that location, rebuild your Multicomp in Quartus II and reprogram the Cyclone II board. When you disconnect the programmer and reboot, you should get a nice surprise..