MMU clone project

General discussions or ideas about hardware.
Post Reply
User avatar
exxos
Site Admin
Site Admin
Posts: 8203
Joined: Wed Aug 16, 2017 11:19 pm
Location: UK
Contact:

MMU clone project

Post by exxos » Fri Oct 27, 2017 2:01 pm

As this closely mixes in with issues of bottleneck shifter, I opened up this new threat to discuss the MMU internals..

Thanks to Stephen Leary (TerribleFire) , a semi some sample code for how the internal works of the MMU. I presume this is in verilog format, and not really familiar with this, but the least it should give a starting point as to what is going on..

Code: Select all

`timescale 1ns / 1ps
 
/*
 Copyright (c) 2012, Stephen J. Leary
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
module mmu(
        input           CLK_I,
        input           RST_I,
       
        // cpu wishbone bus
       
        input           CPU_STB,
        input               CPU_CYC,
        input               CPU_WE,
        input  [3:0]   CPU_SEL,
        input  [2:0]   CPU_FC,
       
        output          CPU_ACK,
        output          CPU_ERR,
        output          CPU_RTY,
       
        input  [31:0]   CPU_ADR,
        input  [31:0]   CPU_DAT_I,
        output [31:0]   CPU_DAT_O,
       
        output [2:0]    CPU_IPL,
       
        // shifter wishbone bus
       
        output          SFT_STB,
        output          SFT_CYC,
        output          SFT_WE,
        output [3:0]   SFT_SEL,
       
        input               SFT_ACK,
        input               SFT_ERR,
       
        output [ 7:0]   SFT_ADR,
        output [31:0]   SFT_DAT_O,
        input  [31:0]   SFT_DAT_I,
 
        // blitter wishbone bus
       
        output          BLT_STB,
        output          BLT_CYC,
        output          BLT_WE,
        output [3:0]   BLT_SEL,
       
        input               BLT_ACK,
        input               BLT_ERR,
       
        output [ 5:0]   BLT_ADR,
        output [31:0]   BLT_DAT_O,
        input  [31:0]   BLT_DAT_I,
       
        // mfp68901 wishbone bus
       
        output          MFP_STB,
        output          MFP_CYC,
        output          MFP_WE,
        output [3:0]   MFP_SEL,
       
        input               MFP_ACK,
        input               MFP_ERR,
       
        output [ 5:0]   MFP_ADR,
        output [31:0]   MFP_DAT_O,
        input  [31:0]   MFP_DAT_I,
       
        input           MFP_IRQ_I,
        output          MFP_IACK_O,
       
        // acia wishbone bus
       
        output          ACIA_STB,
        output          ACIA_CYC,
        output          ACIA_WE,
        output [3:0]   ACIA_SEL,
       
        input               ACIA_ACK,
        input               ACIA_ERR,
       
        output [ 2:0]   ACIA_ADR,
        output [31:0]   ACIA_DAT_O,
        input  [31:0]   ACIA_DAT_I,
       
        // mmc wishbone bus
       
        output          MMC_STB,
        output          MMC_CYC,
        output          MMC_WE,
        output [3:0]   MMC_SEL,
       
        input               MMC_ACK,
        input               MMC_ERR,
       
        output [31:0]   MMC_DAT_O,
        input  [31:0]   MMC_DAT_I,
       
        // ram wishbone bus
       
        output          RAM_STB,
        output          RAM_CYC,
        output          RAM_WE,
        output [3:0]   RAM_SEL,
       
        input               RAM_ACK,
        input               RAM_ERR,
       
        output [31:0]   RAM_ADR,
        output [31:0]   RAM_DAT_O,
       
        input  [31:0]   RAM_DAT_I,
       
        input           VBL_IRQ_I,
        input           HBL_IRQ_I
    );
     
wire        ram_enable = mmu_config == 4'hA ? (CPU_ADR[23:0] < 24'h400000) :
                                                 mmu_config == 4'h2 ? (CPU_ADR[23:0] < 24'h200000) :
                                                 mmu_config == 4'h6 ? (CPU_ADR[23:0] < 24'h280000) :
                                                 mmu_config == 4'h5 ? (CPU_ADR[23:0] < 24'h100000) :
                                                 mmu_config == 4'h1 ? (CPU_ADR[23:0] < 24'h080000) : 1'b0;
       
wire        cpu_space = (CPU_FC == 3'b111);
wire        supervisor_mode = (CPU_FC == 3'b101) | (CPU_FC == 3'b110);
wire        acia_enable = {CPU_ADR[23:8]} == {16'hFFFC} && ({CPU_ADR[7:0]} < {8'h04}) && !cpu_space;
wire        midi_enable = {CPU_ADR[23:8]} == {16'hFFFC} && ({CPU_ADR[7:0]} < {8'h08}) && !cpu_space && !acia_enable;
wire        ide_enable = {CPU_ADR[23:8]} == {16'hF000} && ({CPU_ADR[7:0]} < {8'h40}) && !cpu_space;
wire        mmc_enable = {CPU_ADR[23:8]} == {16'hFFFE} && ({CPU_ADR[7:0]} < {8'h04}) && !cpu_space;
wire        blt_enable = 1'b0; //{CPU_ADR[23:8]} == {16'hFF8A} && ({CPU_ADR[7:0]} < {8'h40}) && !cpu_space;
wire        rtc_enable = {CPU_ADR[23:8]} == {16'hFFFC} && ({CPU_ADR[7:0]} > {8'h20}) && !cpu_space;
wire        wd1772_enable = {CPU_ADR[23:8]} == {16'hFF86} & !cpu_space;
wire        psg_enable = ({CPU_ADR[23:8]} == {16'hFF88}) & !cpu_space;
wire        mfp_enable = {CPU_ADR[23:8]} == {16'hFFFA} & !cpu_space;
wire        config_enable = {CPU_ADR[23:0]} == {24'hFF8000} & !cpu_space;
wire        overlay_enable = {CPU_ADR[23:3]} == 21'd0 & !cpu_space; // shadow the rom to the first 8 bytes.
wire        shifter_enable = {CPU_ADR[23:8]} == {16'hFF82} && ((({CPU_ADR[7:0]} >= {8'h40}) & ({CPU_ADR[7:0]} <= {8'h60})) | ({CPU_ADR[7:0]} <= {8'h0C})) &&  !cpu_space;
wire        rom_enable = (CPU_ADR[23:0] >= 24'hE00000) & (CPU_ADR[23:0] < 24'hF00000) | (CPU_ADR[23:0] >= 24'hFA0000) & (CPU_ADR[23:0] < 24'hFF0000);
wire        bank0_enable = !shifter_enable & !overlay_enable & (CPU_ADR[23:0] < 24'h200000) & !cpu_space;
wire        bank1_enable = !shifter_enable & !overlay_enable & (CPU_ADR[23:0] < 24'h400000) & !cpu_space;
wire        write_error  = (overlay_enable | rom_enable) & CPU_WE & !cpu_space;
 
 
wire [31:0] cfg_dat;
 
reg             cfg_ack;
reg         cfg_err;
 
reg  [ 3:0] mmu_config;
 
// dummy hardware.
 
reg         psg_ack;
reg         psg_err;
 
reg         midi_ack;
reg         midi_err;
 
reg         ide_ack;
reg         ide_err;
 
reg         bank1_ack;
reg         bank1_err;
 
reg         wd1772_ack;
reg         wd1772_err;
 
 
wire [7:0]  int_dat;
wire            int_err;
wire            int_ack;
wire            int_rty;
 
interrupts  MMUINT(
   
    .CLK_I      (CLK_I),
    .RST_I      (RST_I),
   
    .FC_I           (CPU_FC),
    .ADR_I      ({CPU_ADR[4:2]}),
    .CYC_I      (CPU_CYC),
    .STB_I      (CPU_STB),
   
    .ACK_O      (int_ack),
    .ERR_O      (int_err),
    .RTY_O      (int_rty),
   
    .DAT_O      (int_dat),
    .IPL_O      (CPU_IPL),
       
    .MFP_IRQ_I  (MFP_IRQ_I),
    .MFP_IACK_O (MFP_IACK_O),
    .MFP_DAT_I  (MFP_DAT_I[7:0]),
   
    .VBL_IRQ_I  (VBL_IRQ_I),
    .HBL_IRQ_I  (HBL_IRQ_I)
);
 
always @(posedge CLK_I) begin
 
    cfg_ack <= 1'b0;
    cfg_err <= 1'b0;
   
    psg_ack <= 1'b0;
    psg_err <= 1'b0;
   
    midi_ack <= 1'b0;
    midi_err <= 1'b0;
   
    ide_ack <= 1'b0;
    ide_err <= 1'b0;
   
    bank1_ack <= 1'b0;
    bank1_err <= 1'b0;
   
    wd1772_ack <= 1'b0;              
    wd1772_err <= 1'b0;
   
    if (RST_I) begin
   
            mmu_config <= 4'd2;
           
            cfg_err <= 1'b1;
            psg_err <= 1'b1;   
            midi_err <= 1'b1;
            ide_err  <= 1'b1;
            wd1772_err <= 1'b1;
       
   
    end else begin
       
        if (config_enable) begin
           
            if (!cfg_ack & CPU_STB & CPU_CYC & (CPU_ADR[7:0] == 8'd0) & CPU_SEL[2] == 1'b1) begin
               
                if (CPU_WE) begin
                    mmu_config <= CPU_DAT_I[19:16];
                end
               
                cfg_ack <= 1'b1;
       
            end
       
        end else if (ide_enable & CPU_STB & CPU_CYC & !ide_ack) begin
       
            ide_ack <= 1'b1;
       
        end else if (midi_enable & CPU_STB & CPU_CYC & !midi_ack) begin
       
            midi_ack    <= 1'b1;
       
        end else if (psg_enable & CPU_STB & CPU_CYC & !psg_ack) begin
 
            psg_ack <= 1'b1;
           
        end else if (wd1772_enable & CPU_STB & CPU_CYC & !wd1772_ack) begin
 
            wd1772_ack <= 1'b1;
           
        end else if (bank1_enable & CPU_STB & CPU_CYC & !bank1_ack) begin
 
            bank1_ack <= 1'b1;
           
        end
   
    end
   
end
 
assign RAM_CYC      = (bank0_enable | rom_enable | overlay_enable) & CPU_CYC & !write_error;
assign RAM_STB      = (bank0_enable | rom_enable | overlay_enable) & CPU_STB & !write_error;
assign RAM_WE       = bank0_enable & CPU_WE & !write_error;
assign RAM_ADR      = bank0_enable      ? {12'd0,CPU_ADR[20:0]} :
                          overlay_enable    ? {16'hE000, CPU_ADR[7:0]} : {8'd0,CPU_ADR[23:0]};
                         
assign RAM_SEL  = CPU_SEL;
assign RAM_DAT_O    = CPU_DAT_I;
 
assign SFT_CYC      = shifter_enable & CPU_CYC;
assign SFT_STB      = shifter_enable & CPU_STB;
assign SFT_WE       = shifter_enable & CPU_WE;
assign SFT_ADR      = CPU_ADR[7:0];
assign SFT_SEL  = CPU_SEL;
assign SFT_DAT_O    = CPU_DAT_I;
 
assign BLT_CYC      = blt_enable & CPU_CYC;
assign BLT_STB      = blt_enable & CPU_STB;
assign BLT_WE       = blt_enable & CPU_WE;
assign BLT_ADR      = CPU_ADR[5:0];
assign BLT_SEL  = CPU_SEL;
assign BLT_DAT_O    = CPU_DAT_I;
 
assign MFP_CYC      = mfp_enable & CPU_CYC;
assign MFP_STB      = mfp_enable & CPU_STB;
assign MFP_WE       = mfp_enable & CPU_WE;
assign MFP_ADR      = CPU_ADR[5:0];
assign MFP_SEL  = CPU_SEL;
assign MFP_DAT_O    = CPU_DAT_I;
 
assign ACIA_CYC     = acia_enable & CPU_CYC;
assign ACIA_STB     = acia_enable & CPU_STB;
assign ACIA_WE          = acia_enable & CPU_WE;
assign ACIA_ADR     = CPU_ADR[2:0];
assign ACIA_SEL         = CPU_SEL;
assign ACIA_DAT_O   = CPU_DAT_I;
 
assign MMC_CYC      = mmc_enable & CPU_CYC;
assign MMC_STB      = mmc_enable & CPU_STB;
assign MMC_WE       = mmc_enable & CPU_WE;
assign MMC_SEL      = CPU_SEL;
assign MMC_DAT_O    = CPU_DAT_I;
 
assign CPU_RTY      =   cpu_space                                           ? int_rty : 1'b0;
 
// note the mfp needs to see interrupt ack cycles
 
assign CPU_ACK  =   cpu_space                                           ? int_ack :
                            write_error                                         ? 1'b0 :
                            (bank0_enable | rom_enable | overlay_enable)    ? RAM_ACK :
                            mfp_enable                                          ? MFP_ACK :
                            shifter_enable                                  ? SFT_ACK :
                            config_enable                                       ? cfg_ack :
                            psg_enable                                          ? psg_ack :
                            acia_enable                                         ? ACIA_ACK :
                            mmc_enable                                          ? MMC_ACK :
                            midi_enable                                         ? midi_ack :
                            ide_enable                                          ? ide_ack :
                            blt_enable                                          ? 1'b1 :
                            rtc_enable                                          ? 1'b1 :                           
                            wd1772_enable                                       ? wd1772_ack : 
                            bank1_enable                                        ? bank1_ack :
                                                                                    1'b0;
                                                                                   
assign CPU_ERR  =  cpu_space                                            ? int_err :
                            write_error                                         ? 1'b1 :
                            (bank0_enable | rom_enable | overlay_enable) ? RAM_ERR :
                            mfp_enable                                          ? MFP_ERR :
                            shifter_enable                                  ? SFT_ERR :
                            config_enable                                       ? cfg_err :
                            psg_enable                                          ? psg_err :
                            acia_enable                                         ? ACIA_ERR :
                            mmc_enable                                          ? MMC_ERR :
                            midi_enable                                         ? midi_err :
                            ide_enable                                          ? ide_err :
                            blt_enable                                          ? 1'b0 :
                            rtc_enable                                          ? 1'b0 :
                            wd1772_enable                                       ? wd1772_err : 
                            bank1_enable                                        ? bank1_err :
                                                                                    1'b1;
 
assign CPU_DAT_O  =     cpu_space                                           ? {24'd0, int_dat} :
                            (bank0_enable | rom_enable | overlay_enable) ? RAM_DAT_I :
                            mfp_enable                                      ? MFP_DAT_I :
                            shifter_enable                                  ? SFT_DAT_I :
                            config_enable                                   ? cfg_dat   :
                            acia_enable                                         ? ACIA_DAT_I :
                            mmc_enable                                          ? MMC_DAT_I :
                            (rtc_enable | wd1772_enable)                    ? 32'hFFFF_FFFF :
                            blt_enable                                          ? BLT_DAT_I :
                                                                                    32'h0000_0000;
                           
assign cfg_dat      = {12'd0, mmu_config, 12'd0, mmu_config};
 
endmodule
`default_nettype wire

4MB STFM 1.44 FD- VELOCE+ 020 STE - 4MB STE 32MHz - STFM 16MHz - STM - MEGA ST - Falcon 030 CT60 - Atari 2600 - Atari 7800 - Gigafile - SD Floppy Emulator - PeST - HxC - CosmosEx - Ultrasatan - various clutter

https://www.exxoshost.co.uk/atari/ All my hardware guides - mods - games - STOS
https://www.exxoshost.co.uk/atari/last/storenew/ - All my hardware mods for sale - Please help support by making a purchase.

User avatar
exxos
Site Admin
Site Admin
Posts: 8203
Joined: Wed Aug 16, 2017 11:19 pm
Location: UK
Contact:

Re: MMU clone project

Post by exxos » Fri Oct 27, 2017 2:02 pm

I do believe however, that this also includes the GLUE logic as it mentions is like ROM & ACIA etc. so likely a lot of this code isn't even needed..

Though if those addresses are removed, it does not look like the MMU does much of anything at all..
4MB STFM 1.44 FD- VELOCE+ 020 STE - 4MB STE 32MHz - STFM 16MHz - STM - MEGA ST - Falcon 030 CT60 - Atari 2600 - Atari 7800 - Gigafile - SD Floppy Emulator - PeST - HxC - CosmosEx - Ultrasatan - various clutter

https://www.exxoshost.co.uk/atari/ All my hardware guides - mods - games - STOS
https://www.exxoshost.co.uk/atari/last/storenew/ - All my hardware mods for sale - Please help support by making a purchase.

keli
Posts: 95
Joined: Tue Aug 22, 2017 1:34 pm

Re: MMU clone project

Post by keli » Fri Oct 27, 2017 3:19 pm

exxos wrote:
Fri Oct 27, 2017 2:02 pm
I do believe however, that this also includes the GLUE logic as it mentions is like ROM & ACIA etc. so likely a lot of this code isn't even needed..

Though if those addresses are removed, it does not look like the MMU does much of anything at all..
It looks almost deceptively simple. In addition to containing a lot of the decoding done by the GLUE in real live, this code seems to interface other components through a "wishbone bus", a bus specification often used to integrate IPs on an FPGA design, AFAIK. Also missing seems to be the actual DRAM timings and column/row decoding. ... and all address generation for the DMA chip and for pushing graphics data to the Shifter.

User avatar
exxos
Site Admin
Site Admin
Posts: 8203
Joined: Wed Aug 16, 2017 11:19 pm
Location: UK
Contact:

Re: MMU clone project

Post by exxos » Fri Oct 27, 2017 3:22 pm

keli wrote:
Fri Oct 27, 2017 3:19 pm
It looks almost deceptively simple. In addition to containing a lot of the decoding done by the GLUE in real live, this code seems to interface other components through a "wishbone bus", a bus specification often used to integrate IPs on an FPGA design, AFAIK. Also missing seems to be the actual DRAM timings and column/row decoding. ... and all address generation for the DMA chip and for pushing graphics data to the Shifter.
I was just looking and it seems to be missing as you say the DMA, DEV, signals etc. yes, no DRAM stuff in there.. assume its using SRAM, but seems too simple somehow, I cannot even work out this has the video address counters in it or not..
4MB STFM 1.44 FD- VELOCE+ 020 STE - 4MB STE 32MHz - STFM 16MHz - STM - MEGA ST - Falcon 030 CT60 - Atari 2600 - Atari 7800 - Gigafile - SD Floppy Emulator - PeST - HxC - CosmosEx - Ultrasatan - various clutter

https://www.exxoshost.co.uk/atari/ All my hardware guides - mods - games - STOS
https://www.exxoshost.co.uk/atari/last/storenew/ - All my hardware mods for sale - Please help support by making a purchase.

Post Reply

Return to “HARDWARE DISCUSSIONS”