Close
0%
0%

MIKBUG on Multicomp

MIKBUG Running on Multicomp with 6800 CPU

Similar projects worth following
Starting from
$14.00
land_boards has 826 orders / 20reviews
Ships from United States of America
Grant Searle's MultiComp has ROM images for Z80 (CP/M and BASIC), 6502 (BASIC) and 6809 (BASIC) CPUs. Grant also has support for the 6800 but doesn't have a standard software image to run. Source code for the classic MIKBUG exists and makes a nice early retro computer to fill the gap in Grant's MultiComp.

MIKBUG was the classic Motorola ROM for the MC6800 CPU.  Engineering Note 100 has the original source code. The downside of the original code is that it used bit-banging of a Parallel port for serial I/O. 

There is some recent work on MIKBUG.  Mike Lee has a MC6802 build which  has a MC6850 ACIA (UART) instead of the parallel I/O port. This fits nicely with Multicomp which provides two versions of the ACIA. One of the versions is brought to a serial port. The other implements the UART as a VGA output with PS/2 keyboard. This allows the FPGA card to emulate an external terminal without extra hardware.

Mike Lee's board has the following hardware:

  • MC6802 CPU
  • SRAM at $0000-$7FFF (32KB)
  • EPROM at $F000-$FFFF (4KB)
  • (2) MC6821 Dual 8-bit Parallel I/O devices for 32 bits of I/O at $8000/1 and $8008/9
  • MC6850 ACIA at $8018/9

Mike has source code for the SMITHBUGS version of MIKBUG which uses the ACIA for I/O. The code has defines for the PIA but doesn't have any initialization code so it should be possible to build the FPGA without including PIA hardware.

SmithBug is fairly small and only uses space from $C000-$C8FF.  The "Operating System" scratch space RAM is at $7F00-$7FFF so there will need to be RAM at the top of the 32KB SRAM range - should be no problem for the EP4CE15 FPGA. 

Our Implementation

We relocated SmithBug to $F000-$FFFF and opened an I/O space from $FC00-$FCFF for the built-in Video Display Unit (ANSI terminal) and ACIA (Serial Port). That leaves a potential for 60KB of SRAM (if the card has enough SRAM) and plenty of other I/O.

  • Extended SRAM Test

    land-boards.com04/29/2022 at 14:04 0 comments

    The RETRO-EP4CE15 card has 1MB of SRAM on the card. The SRAM is in (2) 8KB windows with 64 banks in each window.

    I wrote a test routine that writes ramp values to the SRAM and verifies it works.

    The test program prints:

    S0++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     1+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++D

    Where:

    • S = start
    • 0/1 = block number
    • + = block good
    • X = bad
    • D = done

    Hit a key at end to avoid resetting the Serial port until done. 

    Jumps back to SmithBUG when done.

    Takes ~2 secs to run with 25MHz ROM/Internal SRAM and 16.7 MHz for External SRAM.

    Assembled using A68 assembler

    "..\..\A68 6800 Assembler\a68.exe" XRAMTEST.ASM -l XRAMTEST.LST -s XRAMTEST.SRE

    Memory Map

    • 0xA000-0xBFFF - 512KB External SRAM
      • 8KB Windows, 64 frames
      • MMU0 provides additional address bit
      • MMU0 initialized to 0
    • 0xC000-0xDFFF - 512KB External SRAM
      • 8KB Window, 64 frames
      • MMU2 provides additional address bits
      • MMU2 initialized to 0
    • 0xFC30 - MMU0 Latch 6-bits
    • 0xFC31 - MMU1 Latch 6-bits

  • FigForth Built-In Words

    land-boards.com04/27/2022 at 18:29 0 comments

    Starting Forth book

    TASK   FORTH   NOOP   VLIST   TRIAD   INDEX   LIST   ?   .   D.   

    D.R   .R   #S   #   SIGN   #>   <#

    SPACES   WHILE   ELSE   IF   REPEAT   AGAIN   END   UNTIL   

    +LOOP   LOOP   DO   THEN   ENDIF   BEGIN

    BACK   FORGET   '   R/W   HI   LO   BLOCK_READ   BLOCK_WRITE   

    ?DISC   -->   LOAD   MESSAGE   .LINE (LINE)   BLOCK   BUFFER   

    DR1   DR0   EMPTY-BUFFERS   UPDATE   +BUF   PREV   USE   DABS   

    ABS   M/MOD

    */   */MOD   MOD   /   /MOD   *   S->D   COLD   ABORT   QUIT   

    (   DEFINITIONS   VOCABULARY   IMMEDIATE INTERPRET   DLITERAL  

     LITERAL   [COMPILE]   CREATE   ID.   ERROR   (ABORT)   -FIND   

    NUMBER   (NUMBER)

    LABD______________   PAD   HOLD   BLANKS   ERASE   FILL      

    QUERY   EXPECT   ?STACK   ."   (.")   -TRAILING

    TYPE   COUNT   DOES>   <BUILDS   ;CODE   (:CODE)   DECIMAL   

    HEX   SMUDGE   ]   [   COMPILE   ?LOADING

    ?CSP   ?PAIRS   ?EXEC   ?COMP   ?ERROR   !CSP   PFA   NFA   

    CFA   LFA   LATEST   TRAVERSE   -DUP   MAX
    MIN   SPACE   ROT   >   <   =   -   C,   ,   ALLOT   HERE   2+   1+   

    COLUMNS   HLD   R#   CSP   FLD

    DPL   BASE   STATE   CURRENT   CONTEXT   OFFSET   SCR   

    OUT   IN   BLK   VOC-LINK   DP   FENCE   WARNING
    WIDTH   TIB   R0   S0   +ORIGIN   B/SCR   B/BUF   LIMIT   FIRST   

    BL   3   2   1   0   USER   VARIABLE

    CONSTANT   ;   :   C!   !   C@   @   TOGGLE   +!   DUP   SWAP   

    DROP   OVER   DMINUS   MINUS   D+   +

    0<   0=   R   R>   >R   LEAVE   ;S   RP!   SP!   SP@   XOR   OR   

    AND   U/   U*   CMOVE   CR   ?TERMINAL

    KEY   EMIT   ENCLOSE   (FIND)   DIGIT   I   (DO)   (+LOOP)   

    (LOOP)   0BRANCH   BRANCH   EXECUTE   LIT    OK

  • figFORTH in ROM

    land-boards.com04/27/2022 at 14:55 0 comments

    Replace SmithBUG with FigForth ROM

    figFORTH can be loaded into ROM in the build instead of the SmithBUG ROM. The reset vector has to point to the FigForth COLD Start.

    Memory Map

    0x0000-0x0FFF - 4KB SRAM
    0x1000-0x2FFF - 6K ROM (using 8KB entity, but only using 6KB)
    0x3000-0x3FFF - 4KB SRAM
    0x4000-0x7FFF - 16KB SRAM
    0xFC00-0xFCFF - I/O Space
    0xFFFE-0xFFFF - ROM start vector (physically top of the 8KB ROM)

    Assemble

    Assemble fig-Forth code using A68 Assembler.

    "..\..\A68 6800 Assembler\a68.exe" fig-FORTH_6800.asm -l fig-FORTH_6800.lst -s fig-FORTH_6800.s

    Manually delete top lines in S record file. After deleting, top lines should be:

    S1131000017E1FA3017E1FD3680000000000007F43
    S113101001000F300FFE0F30001F00000183018319
    

    This matches the source:

       1000   01            ORIG    nop
       1001   7e 1f a3          jmp    CENT
                            ;**************************
                            ;*  W A R M   E N T R Y  **
                            ;**************************
       1004   01                nop
       1005   7e 1f d3          jmp    WENT    ;warm-sta a rt code, keeps current dictionary intact
    

    Use srec_cat to shift addresses down and make Hex file:

    srec_cat fig-FORTH_6800.s -offset - -minimum-addr fig-FORTH_6800.s -o fig-FORTH_6800.hex -Intel

    Clone FPGA Folder

    Archived M6800_MIKBUG_20220427.qar the project as it currently is since it's working well, as-is. Put into new folder and set new entity name (M6800_figForth). Tested as-is and it built/worked.

    Update FPGA Entity

    Bunch of stuff to do.

    • Set up memories
      • Add address selects
    w_SRAMAdr_1 <= '1'     when  w_cpuAddress(15 downto 12) = x"0" else
               '0';
    w_SRAMAdr_2 <= '1'     when  w_cpuAddress(15 downto 12) = x"3" else
               '0';
    w_SRAMAdr_3 <= '1'     when  w_cpuAddress(15 downto 14) = "01" else
               '0';
    w_ROMAdr    <= '1'    when    w_cpuAddress(15 downto 12) = x"1" else
               '1'    when    w_cpuAddress(15 downto 12) = x"2" else
               '0';
    •  Add SRAM entities (2 of 4KB, 1 of 16KB SRAM blocks from Common VHDL folder)
      • No output q latch
    • Add 8KB FigForth ROM entity
      • No output q latch
    • Add reset vector "manually" to read data multiplexer (0xFFFE-0xFFFF = 0x1000)
          -- ____________________________________________________________________________________
          -- CPU Read Data multiplexer
          w_cpuDataIn <=
              io_extSRamData    when w_extSRAM = '1'           else    -- External SRAM (0xA000-0xDFFF)
                      ...
              x"10"             when w_cpuAddress = x"FFFE"    else    -- Reset vector Upper ($1000)
              x"00"             when w_cpuAddress = x"FFFF"    else    -- Reset vector Lower
              w_romData         when w_ROMAdr = '1'            else    -- ROM
      

    Create FPGA .jic file and Download

    Runs!!!

    Saved M6800_FigForth_20220427.qar archive file.

    Issues

    Output looks good on Serial port, but tabbed? over in VDU.

  • FigFORTH Running

    land-boards.com04/26/2022 at 19:22 0 comments

    Ported figFORTH to the card. It runs. Banner is Forth-68.

    Running

    Type J 0100 to run.

    Sources

    Required a bit of tweeking the assembly code so that it would assemble using A68. 

    Ported Source is here.

    Original Source is here.

  • Front Panel for 6800 CPU

    land-boards.com04/22/2022 at 15:44 0 comments
  • Front Panel for 6800 CPU

    land-boards.com04/22/2022 at 15:41 0 comments
  • SmithBug at 0xF000

    land-boards.com04/22/2022 at 15:30 0 comments

    Notes on SmithBug at 0xF000

    • SmithBug is a variant of MIKBUG
      • Updated by Herb Johnson to add S Record loader
    • 60KB SRAM variant
      • Supports much smaller SRAM sizes but requires scratchpad SRAM if ther is less than 60KB of SRAM
        • Scratchpad RAM has to be at 0xEF00-0xEFFF (minimum 256 bytes)

    SmithBug Memory Map

    • 0x0000-0x7FFF - 32KB Internal SRAM
    • 0XEC00-0xEFFF - 1KB Internal SRAM (SCRATCHPAD SRAM USED BY MIKBUG)
    • 0xFC18-0xFC19 - VDU (serSelect J3 JUMPER REMOVED)
    • 0xFC28-0xFC19 - ACIA (serSelect J3 JUMPER installed)
    • 0xFC30-0xFC3F - Front Panel
    • 0xF000-0xFFFF - MIKBUG (Actually SMITHBUG) ROM

    Hardware

    • Tested/runs on all MultiComp based designs
      • SRAM accesses run at 25 MHz on Internal SRAM
      • Different FPGAs can support more of less internal SRAM
      • External SRAM works on all MultiComp based designs and supports 60KB SRAM
        • SRAM accesses run at 16.6 MHz on External SRAM

    Commands

    MIKBUG Commands

    Build Instructions

    • Creates .hex file load load in Quartus II
    ..\a68 DGG_MIKBUG.ASM -l DGG_MIKBUG.LST -s DGG_MIKBUG.s
    ..\srec_cat DGG_MIKBUG.s -offset - -minimum-addr DGG_MIKBUG.s -o DGG_MIKBUG.hex -Intel

  • Links

    land-boards.com04/20/2022 at 14:07 0 comments
  • Minimal Build

    land-boards.com06/26/2021 at 14:24 0 comments

    Put together a minimal build which runs in the EP2C5 FPGA. It does not use any external SRAM. The features are:

    -- MC6800 CPU
    --   Running MIKBUG from back in the day (SmithBug ACIA version)
    --   25 MHz
    --   4K (internal) RAM version
    -- MC6850 ACIA UART
    -- VDU
    --   XGA 80x25 ANSI character display
    --   PS/2 keyboard
    -- SD Card
    --   Not used
    --   Included in pin list with inactive levels (in case a card is installed)
    --
    -- The Memory Map is:
    --   $0000-$0DFF - 3.5KB SRAM (internal RAM in the EPCE15)
    --   $7E00-$7FFF - 512B SRAM (internal RAM in the EPCE15)
    --      $7F00-$7FFF are used as scratchpad RAM by MIKBUG
    --      $7E00-$7EFF can be used by application program
    --   $8018-$8019 - VDU
    --   $8028-$8029 - ACIA
    --     i_SerSelect (Pin_60 of the FPGA) swaps addresses of VDU and ACIA port (requires pullup in FPGA)
    --     Installed (Pin_60 to Ground) uses Serial port
    --   $C000-$FFFF - MIKBUG ROM (repeats 4 times from $C000-$FFFF)

     It works. It's a good baseline for starting a larger build.

  • Speeding Up the CPU

    land-boards.com06/02/2021 at 10:17 0 comments

    I was running the CPU at 12.5 MHz. Speeding up the CPU will requires some attention due to the external SRAM speed. The RETRO-EP4CE15 Card uses a 1MB 45 nS SRAM, the IS62WV10248EBLL-45TLI.

    The critical timing is the write enable strobe:

    The FPGA clock is 50 MHz or 20 nS per clock. Asserting the Write Enable (WE*) for 2 clocks works for the 45 nS parts that are used. 55 nS parts would be marginal but probably would work fine.

    Write Enable should only be asserted while the CPU clock is high so it gets gated with the clock. Note, the logic shown here is inverted, eg, the signal goes high when the active low write enable is NOT asserted.

    o_n_extSRamWE <= w_n_SRAMCE or  w_R1W0  or (not w_vma)  or (w_cpuClock);
    

    This all says we can run the CPU clock at 16.67 Mhz with one 20 nS clock low and 2 clocks high.

    The VHDL code for the CPU clock is:

        -- ____________________________________________________________________________________
        -- CPU Clock
        -- Need 2 clocks high for externl SRAM can get by with 1 clock low
        -- Produces a 40 nS wide wriye strobe - 45 nS SRAMs need a 35 nS write pulse, so this works
    process (i_CLOCK_50)
        begin
            if rising_edge(i_CLOCK_50) then
                if q_cpuClkCount < 2 then    -- 50 MHz / 3 = 16.7
                end if;
                if q_cpuClkCount < 1 then    -- 2 clocks high, one low
                    w_cpuClock <= '0';
                else
                    w_cpuClock <= '1';
                end if;
            end if;
        end process;
    

    And it works!

    25 MHz CPU Speed Upgrade

    It could be possible to run faster by only stretching the CPU clock high width when the external SRAM is accessed. This way the CPU would run at 25 MHz when running from Internal SRAM and only drop to 16.7 Mhz for external SRAM accesses The change to the clock generator is fairly minor:

        -- ____________________________________________________________________________________
        -- CPU Clock
        -- Need 2 clocks high for externl SRAM can get by with 1 clock low
        -- Produces a 40 nS wide wriye strobe - 45 nS SRAMs need a 35 nS write pulse, so this works
    process (i_CLOCK_50, w_n_SRAMCE)
        begin
            if rising_edge(i_CLOCK_50) then
                if w_n_SRAMCE = '0' then
                    if q_cpuClkCount < 2 then                        -- 50 MHz / 3 = 16.7 
                        q_cpuClkCount <= q_cpuClkCount + 1;
                    else
                        q_cpuClkCount <= (others=>'0');
                    end if;
                else
                    if q_cpuClkCount < 1 then                        -- 50 MHz / 2 = 25 
                        q_cpuClkCount <= q_cpuClkCount + 1;
                    else
                        q_cpuClkCount <= (others=>'0');
                    end if;
                end if;
                if q_cpuClkCount < 1 then                        -- 2 clocks high, one low
                    w_cpuClock <= '0';
                else
                    w_cpuClock <= '1';
                end if;
            end if;
        end process;
        
    

    That worked, too!

View all 37 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates