├── .gitignore ├── LICENSE ├── README.md ├── docs ├── compiling-bootloader.md └── mackerel-08-board-assembly.md ├── firmware ├── .gitignore ├── Makefile ├── bootloader.c ├── ch376s.c ├── ch376s.h ├── fat16.c ├── fat16.h ├── fatfs_demo.c ├── glue.c ├── hello.c ├── ide.c ├── ide.h ├── kernel.c ├── linker_ram.scr ├── linker_ram_10.scr ├── linker_ram_30.scr ├── linker_rom.scr ├── linker_rom_10.scr ├── linker_rom_30.scr ├── mackerel.c ├── mackerel.h ├── sd.c ├── sd.h ├── spi.c ├── spi.h ├── start.c ├── start_ram.c ├── term.c ├── term.h ├── vectors_08.s ├── vectors_10.s └── vectors_30.s ├── hardware ├── AP1084.kicad_sym ├── mack-10-proto │ ├── mackerel-10-dram │ │ ├── fp-lib-table │ │ ├── mackerel-10-dram.kicad_pcb │ │ ├── mackerel-10-dram.kicad_pro │ │ └── mackerel-10-dram.kicad_sch │ ├── mackerel-10-ide │ │ ├── mackerel-10-ide.kicad_pcb │ │ ├── mackerel-10-ide.kicad_pro │ │ └── mackerel-10-ide.kicad_sch │ └── mackerel-10-v1 │ │ ├── duart.kicad_sch │ │ ├── expansion.kicad_sch │ │ ├── fp-lib-table │ │ ├── low_mem.kicad_sch │ │ ├── mackerel-10-v1.kicad_pcb │ │ ├── mackerel-10-v1.kicad_pro │ │ ├── mackerel-10-v1.kicad_sch │ │ ├── power_reset.kicad_sch │ │ └── sym-lib-table ├── mackerel-08-v1 │ ├── fp-lib-table │ ├── mackerel-08-duart.kicad_sch │ ├── mackerel-08-expansion.kicad_sch │ ├── mackerel-08-memory.kicad_sch │ ├── mackerel-08-power-reset.kicad_sch │ ├── mackerel-08-v1.kicad_pcb │ ├── mackerel-08-v1.kicad_pro │ ├── mackerel-08-v1.kicad_sch │ └── sym-lib-table ├── mackerel-10-v1 │ ├── dram.kicad_sch │ ├── duart.kicad_sch │ ├── expansion.kicad_sch │ ├── fp-lib-table │ ├── glue_cpld.kicad_sch │ ├── ide.kicad_sch │ ├── low_mem.kicad_sch │ ├── mackerel-10-v1.kicad_pcb │ ├── mackerel-10-v1.kicad_pro │ ├── mackerel-10-v1.kicad_sch │ ├── power_reset.kicad_sch │ └── sym-lib-table ├── mackerel-30-proto │ ├── dram.kicad_sch │ ├── expansion.kicad_sch │ ├── fp-lib-table │ ├── fpu.kicad_sch │ ├── ide.kicad_sch │ ├── low_mem.kicad_sch │ ├── mackerel-30-proto.kicad_pcb │ ├── mackerel-30-proto.kicad_pro │ ├── mackerel-30-proto.kicad_sch │ ├── power.kicad_sch │ ├── sym-lib-table │ └── uart.kicad_sch ├── mackerel-68k-symbols.kicad_sym └── mackerel.pretty │ ├── PGA169.kicad_mod │ ├── SIMM-30.kicad_mod │ └── SIMM-72.kicad_mod ├── media └── images │ ├── Screenshot_2024-11-12_15-42-25.png │ ├── cbr_refresh_sim.png │ ├── cbr_refresh_timing.png │ ├── cbr_scope.png │ ├── dram-cbr-refresh-simulation.png │ ├── dram_read_cycle_simulation.png │ ├── dram_read_sim.png │ ├── dram_read_timing.png │ ├── mack-10-linux-mem-layout.png │ ├── mack-10-v1-render.png │ ├── mack-10-v1-routing.png │ ├── mack-10-with-dram-controller.jpg │ ├── mack10_ide_proto.jpg │ ├── mackerel-08-cpu-banner.jpg │ ├── mackerel-08-rev0.jpg │ ├── mackerel-08-rev1.1-assembled.jpg │ ├── mackerel-08-rev1.1.jpg │ ├── mackerel-08-sbc-v1-board-bringup.jpg │ ├── mackerel-08-sbc-v1-render.png │ ├── mackerel-08-sbc-v1-routing.png │ ├── mackerel-08-sbc-v1.1-render.png │ ├── mackerel-08-v1.1_cropped.jpg │ ├── mackerel-10-proto.jpg │ ├── mackerel-10-sbc-proto-render.png │ ├── mackerel-10-v1-with-drive.jpg │ ├── mackerel-10-v1.2.jpg │ ├── mackerel-10-v1_cropped.jpg │ ├── mackerel-30-v0.1-bringup.jpg │ ├── mackerel-30-v0.1-routing.png │ └── uclinux-4.4-first-real-boot.png ├── pld ├── .gitignore ├── mackerel-08 │ ├── Makefile │ ├── address_decoder.pld │ ├── dtack_decoder.pld │ └── interrupt_decoder.pld ├── mackerel-10 │ ├── dram_controller │ │ ├── .gitignore │ │ ├── dram_controller.qpf │ │ ├── dram_controller.qsf │ │ ├── dram_controller.v │ │ └── dram_controller_tb.v │ └── system-controller │ │ ├── .gitignore │ │ ├── boot_signal.v │ │ ├── clock_gen.v │ │ ├── irq_encoder.v │ │ ├── irq_encoder_tb.v │ │ ├── system-controller.qpf │ │ ├── system-controller.qsf │ │ ├── system-controller.v │ │ └── system-controller_description.txt └── mackerel-30 │ ├── dram_controller │ ├── .gitignore │ ├── dram_controller.qpf │ ├── dram_controller.qsf │ └── dram_controller.v │ └── system_controller │ ├── .gitignore │ ├── boot_signal.v │ ├── irq_encoder.v │ ├── system_controller.qpf │ ├── system_controller.qsf │ └── system_controller.v ├── releases ├── mackerel-08 │ └── v1.1 │ │ ├── address_decoder.jed │ │ ├── dtack_decoder.jed │ │ ├── interrupt_decoder.jed │ │ ├── mackerel-08-bootloader-v0.1.2.bin │ │ ├── mackerel-08-uclinux-v4.4-sd.bin │ │ ├── mackerel-08-uclinux-v4.4-serial.bin │ │ ├── mackerel-08-v1.1-BOM.csv │ │ ├── mackerel-08-v1.1-gbr.zip │ │ └── mackerel-08-v1.1.pdf ├── mackerel-10 │ ├── proto │ │ ├── mackerel-10-dram.gbr.zip │ │ ├── mackerel-10-dram.pdf │ │ ├── mackerel-10-proto.gbr.zip │ │ └── mackerel-10-v1.pdf │ ├── v1.1 │ │ ├── mackerel-10-v1.1-bom.csv │ │ ├── mackerel-10-v1.1.gbr.zip │ │ └── mackerel-10-v1.1.pdf │ ├── v1.2 │ │ ├── bootloader-v0.2.0-lower.bin │ │ ├── bootloader-v0.2.0-upper.bin │ │ ├── dram_controller.pof │ │ ├── mackerel-10-v1.2-BOM.csv │ │ ├── mackerel-10-v1.2.gbr.zip │ │ ├── mackerel-10-v1.2.pdf │ │ └── system-controller.pof │ └── v1 │ │ ├── mackerel-10-v1.gbr.zip │ │ └── mackerel-10-v1.pdf └── mackerel-30 │ └── v0.1 │ ├── mackerel-30-proto.pdf │ ├── mackerel-30-v0.1-BOM.csv │ └── mackerel-30-v0.1.gbr.zip └── tools ├── .gitignore ├── build_cross_compiler.sh ├── format_disk.sh ├── install_reqs_arch.sh ├── install_reqs_deb.sh └── mackerel_crosstools_defconfig /.gitignore: -------------------------------------------------------------------------------- 1 | # C/ASM 2 | *.o 3 | *.elf 4 | 5 | # GAL 6 | *.chp 7 | *.fus 8 | *.pin 9 | 10 | # For PCBs designed using KiCad: https://www.kicad.org/ 11 | # Format documentation: https://kicad.org/help/file-formats/ 12 | 13 | # Temporary files 14 | *.000 15 | *.bak 16 | *.bck 17 | *.kicad_pcb-bak 18 | *.kicad_sch-bak 19 | *-backups 20 | *.kicad_prl 21 | *.sch-bak 22 | *~ 23 | _autosave-* 24 | *.tmp 25 | *-save.pro 26 | *-save.kicad_pcb 27 | fp-info-cache 28 | 29 | # Netlist files (exported from Eeschema) 30 | *.net 31 | 32 | # Autorouter files (exported from Pcbnew) 33 | *.dsn 34 | *.ses 35 | 36 | # Exported BOM files 37 | *.xml 38 | 39 | pld/mackerel-10/dram_controller/dsn 40 | pld/mackerel-10/dram_controller/test.vcd 41 | 42 | *.lck 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Colin Maykish 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mackerel 68k 2 | 3 | Mackerel 68k is a series of single-board computers based on the Motorola 68000. The goal of this project is to build a computer with each of the major processors in the family, from the 68008 through the 68040. Each iteration will add additional hardware peripherals, but the main software goal is to run Linux on every board. 4 | 5 | See the [Hackaday Project Page](https://hackaday.io/project/183861-mackerel-68k-computer) for more pictures, build logs, etc. 6 | 7 | ## Docs 8 | 9 | 1. [Mackerel-08 Assembly](docs/mackerel-08-board-assembly.md) 10 | 2. [Compiling The Bootloader and GAL Logic](docs/compiling-bootloader.md) 11 | 12 | ## Chapters 13 | 14 | Each of the following systems represents a chapter in the project. In total, four SBCs will be designed and built. Note: each chapter includes the hardware peripherals of the previous one. Only new requirements are listed for each board. 15 | 16 | ### Mackerel-08 17 | Status: Complete 18 | 19 | - 68008 CPU (52-pin PLCC variant) 20 | - 512 KB of Flash ROM, 3.5MB SRAM 21 | - Dual serial ports, bit-banged SPI interface 22 | - uClinux 4.4 23 | 24 | ### Mackerel-10 25 | Status: Complete 26 | 27 | - 68000 or 68010 CPU 28 | - Up to 16 MB of 30-pin DRAM 29 | - IDE interface 30 | - uClinux 4.4 31 | 32 | ### Mackerel-30 33 | Status: In Development 34 | 35 | - 68030 CPU at 25 MHz 36 | - 64 MB of 72-pin DRAM 37 | - Ethernet interface (via SPI) 38 | - Linux kernel v6.x with MMU support 39 | 40 | ### Mackerel-40 41 | Status: Planning 42 | 43 | - 68040 CPU at 33 MHz 44 | - 256 MB of 72-pin DRAM 45 | - VGA display 46 | - Linux v6.x + X server GUI 47 | 48 | ## Hardware 49 | 50 | ### Mackerel-08 51 | 52 | ![Mackerel-08 SBC v1](media/images/mackerel-08-v1.1_cropped.jpg) 53 | 54 | Based on the original prototype hardare, this SBC combines the 52-pin PLCC MC68008, a 512KB Flash ROM, up to 3.5MB of SRAM, and a XR68C681 DUART on a single PCB. The DUART exposes two serial ports and three bit-banged SPI headers. One of these headers is currently used with an SD card breakout board to provide bulk storage. 55 | 56 | Three 22V10 PLDs are used for address decoding, interrupt mapping, and DTACK generation. An expansion header breaks out address, data, and control lines to allow additional peripherals to be connected directly to the processor bus. 57 | 58 | Although the 68008 is only rated to 8/10 MHz, the CPU runs reliably overclocked to 16 MHz. 59 | 60 | The address space is mapped as follows: 61 | 62 | - RAM: 0x000000 - 0x37FFFF (up to 3.5 MB) 63 | - ROM: 0x380000 - 0x3FBFFF (496/512 KB usable) 64 | - DUART: 0x3FC000 - 0x3DFFFF (8KB) 65 | - Exp: 0x3FE000 - 0x3FFFFF (Expansion header, 8KB) 66 | 67 | Mackerel-08 uses a 74HC595 shift register to create a BOOT signal for the first eight /AS cycles of the CPU after reset. This BOOT signal is used by the address decoder PLD to map the ROM to address 0x000000 long enough for the CPU to read the initial stack pointer and program counter vectors from ROM. RAM is mapped to 0x000000 after that. 68 | 69 | ### Mackerel-10 70 | 71 | ![Mackerel-10 v1](media/images/mackerel-10-v1.2.jpg) 72 | 73 | Mackerel-10 is the second SBC in the project. It expands on the design of Mackerel-08 with a MC68010 CPU (or equivalent), the same XR68C681 DUART, 1MB of Flash ROM, 1MB of SRAM, up to 16 MB of DRAM, and an IDE drive interface. Two CPLDs act as the glue logic and DRAM controller for the board. The SRAM is optional and the address space can be filled almost entirely with DRAM. 74 | 75 | The memory map looks like this: 76 | 77 | - DRAM: 0x000000 - 0xEFFFFF (15MB) 78 | - ROM: 0xF00000 - 0xFF4000 (not quite 1MB) 79 | - I/O: 0xF40000 - 0xFFFFFF 80 | 81 | ### Mackerel-30 82 | 83 | ![Mackerel-30 v0.1](media/images/mackerel-30-v0.1-bringup.jpg) 84 | 85 | Mackerel-30 is based on the 68030 CPU. It includes the DUART and IDE interface from Mackerel-10 and upgrades the DRAM controller to use a 72-pin SIMM. It also includes a MC68882 FPU. 86 | 87 | ## Software 88 | 89 | ### Bootloader and Bare-metal Programs 90 | Mackerel runs a small bootloader program installed on the Flash ROM. This provides a simple set of debugging tools (peek, poke, memtest, etc.) as well as two methods for loading external code into RAM. 91 | 92 | The bootloader can load program data coming in over the serial port (`load` command) or it can read data from an SD card (`boot` command). Either way, the program code gets loaded into RAM at address 0x400 and then the bootloader jumps to that address to start the program. 93 | 94 | ### uClinux 95 | Mackerel supports two versions of uClinux. [Version 2.0](https://github.com/crmaykish/mackerel-uclinux-20040218) dates from 2004 and runs Linux kernel 2.0. This version is actually small enough when compiled to fit entirely in a single 512KB ROM in which case, there is no bootloader and Linux boots immediately on power-up. It can also be loaded into RAM via serial by the bootloader like any other program. 96 | 97 | The newer port of uClinux 4.4 is [here](https://github.com/crmaykish/mackerel-uclinux-20160919). This version dates from 2016 and runs the much newer (and much larger) 4.4 Linux kernel. The image for this version does not fit in ROM and has to be loaded over serial or from the SD/IDE. 98 | 99 | In both versions, the Linux system is fairly minimal. There is an interactive bash-style shell, and a few basic programs. Mackerel-10+ has an IDE driver for persistent storage. 100 | 101 | ### Compilers and Tools 102 | The bootloader and other bare-metal programs can be built with a standard m68k-elf cross-compiler. There is a script to build one from modern binutils and gcc in [the tools folder](tools/build_cross_compiler.sh). 103 | 104 | The toolchains to build uClinux are a bit more complicated. I have been working on building my own from scratch, but for now the precompiled toolchains that were built along with the uClinux releases are working well. 105 | 106 | The toolchain to build uClinux 2.0 is in this [Github repo](https://github.com/crmaykish/mackerel-m68k-elf-tools-2003). This runs fine for me on Debian 12, but requires enabling the i386 architecture and installing libc:i386 and libgcc:i386 since it's 32-bit toolchain. 107 | 108 | I've been using this [toolchain from Sourceforce](https://sourceforge.net/projects/uclinux/files/Tools/m68k-uclinux-20160822/m68k-uclinux-tools-20160822.tar.bz2/download) to build uClinux 4.4. This also runs with no issues on my modern Debian 12 installation. 109 | 110 | My serial transfer tool is [here](https://github.com/crmaykish/ctt). This is used in combination with the bootloader to transfer data (usually program code) into RAM. 111 | 112 | ## Building Linux v6.13 for Mackerel-30 113 | 114 | ### Setting up a toolchain 115 | 116 | 1. Run one of the `tools/install_reqs_` scripts based on your Linux distribution. 117 | 118 | 2. Compile crosstools-ng: 119 | 120 | ``` 121 | git clone https://github.com/crosstool-ng/crosstool-ng.git 122 | cd crosstool-ng 123 | ./bootstrap 124 | ./configure --prefix=/home/$(whoami)/crosstools 125 | make 126 | make install 127 | ``` 128 | 129 | 3. Use crosstools-ng to build a toolchain for Mackerel: 130 | 131 | ``` 132 | cd 133 | 134 | # Make sure the newly built crosstools-ng binary is available in the path 135 | export PATH=$PATH:/home/$(whoami)$/crosstools/bin 136 | 137 | # Copy the toolchain defconfig from this repo into the workspace 138 | cp /tools/mackerel_crosstools_defconfig defconfig 139 | 140 | # Build the Mackerel toolchain, this can take a while (5-20 minutes) 141 | ct-ng build 142 | ``` 143 | 144 | 4. Verify the build: 145 | 146 | ``` 147 | ~/x-tools/m68k-mackerel-linux-gnu/bin/m68k-mackerel-linux-gnu-gcc --version 148 | 149 | m68k-mackerel-linux-gnu-gcc (crosstool-NG 1.27.0.20_329bb4d) 14.2.0 150 | Copyright (C) 2024 Free Software Foundation, Inc. 151 | This is free software; see the source for copying conditions. There is NO 152 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 153 | ``` 154 | 155 | ### Building the Linux kernel for Mackerel-30 156 | 157 | ``` 158 | cd 159 | git checkout mackerel-30-config 160 | 161 | # Put the toolchain on the path 162 | export PATH=$PATH:/home/$(whoami)$/x-tools/m68k-mackerel-linux-gnu/bin 163 | 164 | # Load the Mackerel-30 config 165 | make ARCH=m68k mackerel30_defconfig 166 | 167 | # Compile the kernel 168 | make ARCH=m68k CROSS_COMPILE=m68k-mackerel-linux-gnu- -j$(nproc) 169 | ``` 170 | -------------------------------------------------------------------------------- /docs/compiling-bootloader.md: -------------------------------------------------------------------------------- 1 | # Compiling The Bootloader and GAL Logic 2 | 3 | This document describes building the bootloader and other bare metal programs from source. This process requires a Linux PC, preferably Debian or Ubuntu or one of its derivatives. This will also work in a virtual machine and should work in WSL, but I have not verified this. 4 | 5 | ## Building the Cross-Compiler 6 | 7 | The cross-compiler is made up of three pieces: binutils, gcc, and Baselibc. All of these need to be built locally before they can be used to compile programs for Mackerel. 8 | 9 | I've created a [script to automate this process](../tools/build_cross_compiler.sh). If you'd prefer to do this manually or customize any part of it, refer to the script anyway. It will serve as a guide to downloading and building the various pieces of the toolchain. 10 | 11 | ## Build the Bootloader 12 | 13 | Once you have the cross-compiler built and installed, the bootloader and other programs can be compiled by running `make` from the [firmware](../firmware/) folder. By default, this is will create programs for Mackerel-08. To build for Mackerel-10 instead, run `make BOARD=mack10`. 14 | 15 | ## Running From ROM vs. RAM 16 | 17 | The bootloader is compiled to run from ROM. Other bare-metal programs run from RAM. This is set up in the [Makefile](../firmware/Makefile). 18 | 19 | To compile a new programs, add an entry in the Makefile. 20 | 21 | ## Building GAL Logic 22 | 23 | On Mackerel-08, three 22V10 GAL chips provide the glue logic for the system. The logic equations for these are defined in the [PLD directory](../pld/mackerel-08/). Compiling them into JED files requires the [galasm tool](https://github.com/daveho/GALasm). There's a `Makefile` in the PLD directory to build all of these JEDs, just run `make`. -------------------------------------------------------------------------------- /docs/mackerel-08-board-assembly.md: -------------------------------------------------------------------------------- 1 | # Building Mackerel-08 2 | 3 | This document describes the process to assemble and bring up Mackerel-08. It is up to date as of the [v1.1 hardware](../releases/mackerel-08/v1.1/) revision. 4 | 5 | ## Parts 6 | 7 | Most of the passives and simpler components are standard values and readily available. Refer to the [BOM](../releases/mackerel-08/v1.1/mackerel-08-v1.1-BOM.csv) for a detailed list. 8 | 9 | The 3.3v regulator is an AP1084. There are several alternate part numbers that can be dropped in here as well, just confirm the pinout. This regulator is only required if 3.3v SPI devices are used. In all other cases, it can be omitted without impacting the core system functionality. 10 | 11 | ### CPU 12 | 13 | The Motorola 68008 is available in 8 and 10 MHz speed variants. There's not a huge difference between them and they both overclock to 14+ MHz in my experience. Use whichever version you can find. 14 | 15 | ### RAM and ROM 16 | 17 | Any standard 512 KB ROM chip should work, but I have only personally validated the SST39SF040 in DIP-32 or PLCC ([with adapter](https://github.com/crmaykish/adapters-and-breakout-boards/tree/main/PLCC-32-to-DIP-32)). 18 | 19 | The SRAM chips are a little more particular. I've had the best luck with Alliance AS6C4008-55PCN modules in DIP-32 or the Alliance AS7C4096A-15JIN in SOJ-36 ([with adapter](https://github.com/crmaykish/adapters-and-breakout-boards/tree/main/SOJ-36-to-DIP-32-SRAM)). 20 | 21 | ### Programmable Logic 22 | 23 | Three 22V10 GALs are needed to handle the glue logic. These are fairly standard parts and any variant with a 15ns rating or better should work, but I can only vouch for the Atmel/Microchip ATF22V10C-15PU chips. 24 | 25 | ### DUART 26 | 27 | The XR68C681 DUART has recently been marked end-of-life. It's still available at the time of writing (November 2024) on Digikey and some other retailers. I've also had good luck finding them on eBay. Just stick to highly-rated sellers. 28 | 29 | ### Oscillators 30 | 31 | The DUART requires an oscillator running at 3.6864 MHz. Either the half- or full-size can can be installed. 32 | 33 | There's a bit more flexibility with the CPU oscillator. Technically, the 68008 can run as slow as 2 MHz and as high as its rated speed, 8 or 10 MHz. I'd recommend using a 10 MHz oscillator in either case. Higher speeds make Linux more usable and all of the CPUs I have tested can handle 14+ MHz without much issue. 34 | 35 | I recommend socketing the oscillators so you can experiment. 36 | 37 | ### SD 38 | 39 | Mackerel-08 was designed with this [Adafruit Micro SD breakout](https://www.adafruit.com/product/254) in mind. It slots directly into the SD header on board. 40 | 41 | It might be possible to use other SD breakout/level-shifter boards, but a lot of the no-name versions are poor quality or their level shifters are too slow. Try them at your own risk. If you're not using the Adafruit board, you will need to pay attention to the pinouts and make the appropriate adjustments when connecting them to Mackerel. If you do find an alternative that works well, let me know! 42 | 43 | ## Tools 44 | 45 | Besides basic soldering tools, you'll also need some method to program the ROM and the three PLDs. I use and recommend a TL866II Plus programmer. It will handle both the ROM and the PLDs and works with [minipro](https://davidgriffith.gitlab.io/minipro/) software. 46 | 47 | ## Board Bring-up 48 | 49 | ### PCB Prep 50 | 51 | Once you have all the components and sockets soldered to the board, I recommend giving it a good cleaning with isopropyl alcohol followed by soap and water. Scrub as much of the solder flux residue off the board as you can. Let it dry fully and then populate the sockets. 52 | 53 | ### Programming The Chips 54 | 55 | Download the bootloader ROM and the three JED files from the [release folder](../releases/mackerel-08/v1.1/). 56 | 57 | Use `minipro` to flash the bootloader to the ROM chip: 58 | 59 | `minipro -p SST39SF040 -s -w bootloader.bin` 60 | 61 | Similarly, each of the three PLDs can be programmed: 62 | 63 | 1. `minipro -p "ATF22V10C(UES)" -w address_decoder.jed` 64 | 2. `minipro -p "ATF22V10C(UES)" -w interrupt_decoder.jed` 65 | 3. `minipro -p "ATF22V10C(UES)" -w dtack_decoder.jed` 66 | 67 | If you have another method for programming ROMs and PLDs, that will almost certainly work as well. 68 | 69 | ### Booting Up 70 | 71 | Connect a serial terminal to UART B. Use 115200 baud, 1 stop bit, no parity bits (likely the default settings). 72 | 73 | Apply 12v DC power. You should be greeted with the Mackerel-08 bootloader. 74 | 75 | ``` 76 | ### Mackerel-08 Bootloader v0.1 ### 77 | ### crmaykish - 2024 ### 78 | > 79 | ``` 80 | 81 | I'd recommend running a memory test at this point: `memtest 8000 37F000` 82 | 83 | If it passes without errors, congrats! Mackerel-08 is operational. 84 | -------------------------------------------------------------------------------- /firmware/.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | -------------------------------------------------------------------------------- /firmware/Makefile: -------------------------------------------------------------------------------- 1 | CC = m68k-mackerel-elf-gcc 2 | AS = m68k-mackerel-elf-as 3 | LD = m68k-mackerel-elf-ld 4 | OBJCOPY = m68k-mackerel-elf-objcopy 5 | 6 | BOARD = mack08 7 | 8 | ifeq ($(BOARD),mack30) 9 | CPPFLAGS = -DMACKEREL_30 10 | MEMORY_MAP_ROM = linker_rom_30.scr 11 | MEMORY_MAP_RAM = linker_ram_30.scr 12 | VECTORS = vectors_30.s 13 | CFLAGS = -m68030 -msoft-float -fomit-frame-pointer 14 | AFLAGS = -m68030 15 | else ifeq ($(BOARD),mack10) 16 | # Mackerel-10 17 | CPPFLAGS = -DMACKEREL_10 18 | MEMORY_MAP_ROM = linker_rom_10.scr 19 | MEMORY_MAP_RAM = linker_ram_10.scr 20 | VECTORS = vectors_10.s 21 | CFLAGS = -m68010 22 | AFLAGS = -m68010 23 | else 24 | # Mackerel-08 25 | CPPFLAGS = -DMACKEREL_08 26 | MEMORY_MAP_ROM = linker_rom.scr 27 | MEMORY_MAP_RAM = linker_ram.scr 28 | VECTORS = vectors_08.s 29 | CFLAGS = -m68000 30 | AFLAGS = -m68000 31 | endif 32 | 33 | COMMON_OBJS_ROM = $(VECTORS) start.o glue.o mackerel.o term.o 34 | COMMON_OBJS_RAM = start_ram.o glue.o mackerel.o term.o 35 | 36 | BASE_BINS = bootloader.bin hello.bin kernel.bin fatfs_demo.bin 37 | 38 | ifeq ($(BOARD),mack10) 39 | # Mackerel-10 40 | BINS = $(BASE_BINS) $(addsuffix -upper.bin, $(basename $(BASE_BINS))) $(addsuffix -lower.bin, $(basename $(BASE_BINS))) 41 | else 42 | # Mackerel-08 / Mackerel-30 43 | BINS = $(BASE_BINS) 44 | endif 45 | 46 | .SECONDARY: *.elf *.bin 47 | 48 | all: $(BINS) 49 | 50 | %.o: %.c 51 | $(CC) $(CFLAGS) $(CPPFLAGS) -g -Wall -c $< -o $@ -O 52 | 53 | %.o: %.s 54 | $(AS) $(AFLAGS) $< -o $@ 55 | 56 | %.bin: %.elf 57 | $(OBJCOPY) $< -O binary $@ 58 | 59 | bootloader.elf: $(COMMON_OBJS_ROM) bootloader.o sd.o spi.o ide.o fat16.o 60 | $(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--build-id=none -T $(MEMORY_MAP_ROM) -nostartfiles $^ -o $@ 61 | 62 | hello.elf: $(COMMON_OBJS_RAM) hello.o ide.o 63 | $(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--build-id=none -T $(MEMORY_MAP_RAM) -nostartfiles $^ -o $@ 64 | 65 | fatfs_demo.elf: $(COMMON_OBJS_RAM) fatfs_demo.o fat16.o sd.o spi.o ide.o 66 | $(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--build-id=none -T $(MEMORY_MAP_RAM) -nostartfiles $^ -o $@ 67 | 68 | kernel.elf: $(COMMON_OBJS_RAM) kernel.o 69 | $(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--build-id=none -T $(MEMORY_MAP_RAM) -nostartfiles $^ -o $@ 70 | 71 | %-upper.bin: %.bin 72 | $(OBJCOPY) --interleave=2 --byte=0 -I binary -O binary $< $@ 73 | 74 | %-lower.bin: %.bin 75 | $(OBJCOPY) --interleave=2 --byte=1 -I binary -O binary $< $@ 76 | 77 | clean: 78 | rm -f *.o *.elf *.bin 79 | -------------------------------------------------------------------------------- /firmware/bootloader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "mackerel.h" 6 | #include "sd.h" 7 | #include "ide.h" 8 | #include "fat16.h" 9 | 10 | #define VERSION "0.4.0" 11 | 12 | #define INPUT_BUFFER_SIZE 32 13 | 14 | void handler_runram(); 15 | void handler_runrom(); 16 | void handler_load(uint32_t addr); 17 | void handler_boot(); 18 | void handler_zero(uint32_t addr, uint32_t size); 19 | void handler_ide(); 20 | uint8_t readline(char *buffer); 21 | void command_not_found(char *command); 22 | void memdump(uint32_t address, uint32_t bytes); 23 | void print_string_bin(char *str, uint8_t max); 24 | 25 | void memtest(uint8_t *start, uint32_t size); 26 | void memtest8(uint8_t *start, uint32_t size, uint8_t target); 27 | void memtest32(uint32_t *start, uint32_t size); 28 | 29 | char buffer[INPUT_BUFFER_SIZE]; 30 | 31 | int main() 32 | { 33 | printf("\r\n### %s Bootloader v%s ###\r\n### crmaykish - 2025 ###\r\n", SYSTEM_NAME, VERSION); 34 | 35 | while (true) 36 | { 37 | // Present the command prompt and wait for input 38 | duart_puts("> "); 39 | readline(buffer); 40 | duart_puts("\r\n"); 41 | 42 | if (strncmp(buffer, "load", 4) == 0) 43 | { 44 | strtok(buffer, " "); 45 | char *param1 = strtok(NULL, " "); 46 | uint32_t addr = strtoul(param1, 0, 16); 47 | handler_load(addr); 48 | } 49 | else if (strncmp(buffer, "boot", 4) == 0) 50 | { 51 | handler_boot(); 52 | } 53 | else if (strncmp(buffer, "ide", 3) == 0) 54 | { 55 | handler_ide(); 56 | } 57 | else if (strncmp(buffer, "runrom", 6) == 0) 58 | { 59 | handler_runrom(); 60 | } 61 | else if (strncmp(buffer, "run", 3) == 0 || strncmp(buffer, "runram", 6) == 0) 62 | { 63 | handler_runram(); 64 | } 65 | else if (strncmp(buffer, "dump", 4) == 0) 66 | { 67 | strtok(buffer, " "); 68 | char *param1 = strtok(NULL, " "); 69 | uint32_t addr = strtoul(param1, 0, 16); 70 | 71 | memdump(addr, 256); 72 | } 73 | else if (strncmp(buffer, "peek", 4) == 0) 74 | { 75 | strtok(buffer, " "); 76 | char *param1 = strtok(NULL, " "); 77 | uint32_t addr = strtoul(param1, 0, 16); 78 | 79 | printf("%02X", MEM(addr)); 80 | } 81 | else if (strncmp(buffer, "poke", 4) == 0) 82 | { 83 | strtok(buffer, " "); 84 | char *param1 = strtok(NULL, " "); 85 | char *param2 = strtok(NULL, " "); 86 | uint32_t addr = strtoul(param1, 0, 16); 87 | uint8_t val = (uint8_t)strtoul(param2, 0, 16); 88 | 89 | MEM(addr) = val; 90 | } 91 | else if (strncmp(buffer, "mem8", 4) == 0) 92 | { 93 | strtok(buffer, " "); 94 | char *param1 = strtok(NULL, " "); 95 | char *param2 = strtok(NULL, " "); 96 | uint32_t start = strtoul(param1, 0, 16); 97 | uint32_t size = strtoul(param2, 0, 16); 98 | memtest((uint8_t *)start, size); 99 | } 100 | else if (strncmp(buffer, "mem32", 5) == 0) 101 | { 102 | strtok(buffer, " "); 103 | char *param1 = strtok(NULL, " "); 104 | char *param2 = strtok(NULL, " "); 105 | uint32_t start = strtoul(param1, 0, 16); 106 | uint32_t size = strtoul(param2, 0, 16); 107 | memtest32((uint32_t *)start, size); 108 | } 109 | else if (strncmp(buffer, "zero", 4) == 0) 110 | { 111 | strtok(buffer, " "); 112 | char *param1 = strtok(NULL, " "); 113 | char *param2 = strtok(NULL, " "); 114 | uint32_t start = strtoul(param1, 0, 16); 115 | uint32_t size = strtoul(param2, 0, 16); 116 | handler_zero(start, size); 117 | } 118 | else 119 | { 120 | command_not_found(buffer); 121 | } 122 | 123 | duart_puts("\r\n"); 124 | } 125 | 126 | return 0; 127 | } 128 | 129 | void handler_runram() 130 | { 131 | duart_puts("Jumping to 0x400\r\n"); 132 | asm("jsr 0x400"); 133 | } 134 | 135 | void handler_runrom() 136 | { 137 | duart_puts("Jumping to 0x100000\r\n"); 138 | asm("jsr 0x100000"); 139 | } 140 | 141 | void handler_boot() 142 | { 143 | printf("Loading Linux from SD card...\n"); 144 | 145 | if (!sd_init()) 146 | return; 147 | 148 | unsigned char first[512]; 149 | unsigned char *mem = (unsigned char *)0x400; 150 | 151 | // Read the first block of the SD card to determine the Linux image size 152 | sd_read(0, first); 153 | uint32_t image_size = strtoul((char *)first, 0, 10); 154 | printf("Image size: %u\n", image_size); 155 | 156 | // Read the rest of the SD card to load the Linux image into RAM 157 | printf("Loading kernel into 0x%X...\n", (int)mem); 158 | 159 | uint32_t blocks = (image_size / 512) + 1; 160 | 161 | for (int block = 1; block <= blocks; block++) 162 | { 163 | if (block % 10 == 0) 164 | { 165 | printf("%d/%d\n", block, blocks); 166 | } 167 | 168 | sd_read(block, mem); 169 | mem += 512; 170 | } 171 | 172 | printf("Done\n"); 173 | 174 | handler_runram(); 175 | } 176 | 177 | void block_read(uint32_t block_num, uint8_t *block) 178 | { 179 | IDE_read_sector((uint16_t *)block, block_num); 180 | } 181 | 182 | void handler_ide() 183 | { 184 | fat16_boot_sector_t boot_sector; 185 | fat16_dir_entry_t files_list[16] = {0}; 186 | 187 | printf("Attempting to load Linux kernel from IDE...\r\n"); 188 | 189 | // Reset the IDE interface 190 | uint16_t buf[256]; 191 | IDE_reset(); 192 | IDE_device_info(buf); 193 | 194 | // Initialize FAT16 library with the IDE block read function 195 | if (fat16_init(block_read) != 0) 196 | { 197 | printf("Failed to initialize FAT16 library\r\n"); 198 | return; 199 | } 200 | 201 | fat16_read_boot_sector(2048, &boot_sector); 202 | fat16_print_boot_sector_info(&boot_sector); 203 | 204 | printf("\r\nReading files on disk...\r\n"); 205 | fat16_list_files(&boot_sector, files_list); 206 | 207 | bool kernel_found = false; 208 | 209 | for (int i = 0; i < 16; i++) 210 | { 211 | if (files_list[i].file_size > 0) 212 | { 213 | char filename[13]; 214 | fat16_get_file_name(&files_list[i], filename); 215 | 216 | if (strncmp(filename, "IMAGE .BIN", 12) == 0) 217 | { 218 | printf("\r\nFound IMAGE.BIN, reading it into RAM...\r\n"); 219 | 220 | uint8_t *file = (uint8_t *)0x400; 221 | 222 | int bytes_read = fat16_read_file(&boot_sector, files_list[i].first_cluster_low, file, files_list[i].file_size); 223 | 224 | printf("\r\n"); 225 | 226 | printf("Read %d of %d bytes\r\n", bytes_read, files_list[i].file_size); 227 | 228 | if (bytes_read != files_list[i].file_size) 229 | { 230 | printf("File read failed\r\n"); 231 | } 232 | else 233 | { 234 | printf("File read successfully\r\n"); 235 | kernel_found = true; 236 | } 237 | 238 | break; 239 | } 240 | } 241 | } 242 | 243 | if (kernel_found) 244 | { 245 | handler_runram(); 246 | } 247 | else 248 | { 249 | printf("ERROR: Could not find IMAGE.BIN on disk\r\n"); 250 | } 251 | } 252 | 253 | void handler_load(uint32_t addr) 254 | { 255 | int in_count = 0; 256 | int end_count = 0; 257 | uint8_t in = 0; 258 | 259 | if (addr == 0) 260 | { 261 | addr = 0x400; 262 | } 263 | 264 | printf("Loading from serial into 0x%X...\r\n", addr); 265 | 266 | while (end_count != 3) 267 | { 268 | in = duart_getc(); 269 | 270 | MEM(addr + in_count) = in; 271 | 272 | if (in == 0xDE) 273 | { 274 | end_count++; 275 | } 276 | else 277 | { 278 | end_count = 0; 279 | } 280 | 281 | in_count++; 282 | } 283 | 284 | MEM(addr + in_count - 3) = 0; 285 | 286 | printf("Done! Transferred %d bytes.\r\n", in_count - 3); 287 | } 288 | 289 | void handler_zero(uint32_t addr, uint32_t size) 290 | { 291 | for (uint32_t i = addr; i < addr + size; i++) 292 | { 293 | MEM(i) = 0x00; 294 | } 295 | } 296 | 297 | void command_not_found(char *command_name) 298 | { 299 | duart_puts("Command not found: "); 300 | duart_puts(command_name); 301 | } 302 | 303 | uint8_t readline(char *buffer) 304 | { 305 | uint8_t count = 0; 306 | uint8_t in = duart_getc(); 307 | 308 | while (in != '\n' && in != '\r') 309 | { 310 | // Character is printable ASCII 311 | if (in >= 0x20 && in < 0x7F) 312 | { 313 | duart_putc(in); 314 | 315 | buffer[count] = in; 316 | count++; 317 | } 318 | else if (0x08) 319 | { 320 | // Backspace 321 | if (count > 0) 322 | { 323 | duart_puts("\e[1D"); // Move cursor to the left 324 | duart_putc(' '); // Clear last character 325 | duart_puts("\e[1D"); // Move cursor to the left again 326 | count--; // Move input buffer index back 327 | } 328 | } 329 | 330 | in = duart_getc(); 331 | } 332 | 333 | buffer[count] = 0; 334 | 335 | return count; 336 | } 337 | 338 | void memtest(uint8_t *start, uint32_t size) 339 | { 340 | memtest8(start, size, 0x00); 341 | memtest8(start, size, 0xAA); 342 | memtest8(start, size, 0x55); 343 | memtest8(start, size, 0xFF); 344 | 345 | printf("Test complete\r\n"); 346 | } 347 | 348 | void memtest8(uint8_t *start, uint32_t size, uint8_t target) 349 | { 350 | printf("8-bit Mem Test: %X to %X w/ val %02X\r\n", (uint32_t)start, (uint32_t)(start + size), target); 351 | 352 | for (uint8_t *i = start; i < (uint8_t *)(start + size); i++) 353 | { 354 | *i = target; 355 | } 356 | 357 | for (uint8_t *i = start; i < (uint8_t *)(start + size); i++) 358 | { 359 | if (*i != target) 360 | { 361 | printf("Error at 0x%X, expected 0x%02X, got 0x%02X\r\n", (uint32_t)i, target, *i); 362 | } 363 | } 364 | 365 | printf("\r\n"); 366 | } 367 | 368 | // Write the 32-bit address value to the same address in RAM 369 | void memtest32(uint32_t *start, uint32_t size) 370 | { 371 | printf("32-bit Mem Test: %X to %X\r\n", (uint32_t)start, (uint32_t)start + (uint32_t)size); 372 | 373 | printf("Writing...\r\n"); 374 | for (uint32_t *i = start; i < (uint32_t *)(start + size / 4); i++) 375 | { 376 | *i = (uint32_t)i; 377 | 378 | if ((*i % 0x10000) == 0) 379 | { 380 | duart_putc('.'); 381 | } 382 | } 383 | 384 | printf("\r\nReading...\r\n"); 385 | for (uint32_t *i = start; i < (uint32_t *)(start + size / 4); i++) 386 | { 387 | if (*i != (uint32_t)i) 388 | { 389 | printf("Error at 0x%X, expected 0x%02X, got 0x%02X\r\n", (uint32_t)i, (uint32_t)i, *i); 390 | } 391 | 392 | if ((*i % 0x10000) == 0) 393 | { 394 | duart_putc('.'); 395 | } 396 | } 397 | 398 | printf("\r\nTest complete\r\n"); 399 | } 400 | -------------------------------------------------------------------------------- /firmware/ch376s.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ch376s.h" 3 | #include "mackerel.h" 4 | 5 | static bool interrupt_ready() 6 | { 7 | return ((MEM(USB_COMMAND) & 0b10000000) == 0); 8 | } 9 | 10 | static uint8_t wait_for_interrupt() 11 | { 12 | while (!interrupt_ready()) 13 | { 14 | } 15 | 16 | MEM(USB_COMMAND) = CH376S_CMD_GET_STATUS; 17 | return MEM(USB_DATA); 18 | } 19 | 20 | static void send_string(char *s) 21 | { 22 | int i = 0; 23 | while (s[i] != 0) 24 | { 25 | MEM(USB_DATA) = s[i]; 26 | i++; 27 | } 28 | 29 | MEM(USB_DATA) = 0; 30 | } 31 | 32 | uint8_t usb_reset() 33 | { 34 | MEM(USB_COMMAND) = CH376S_CMD_RESET_ALL; 35 | delay(20000); 36 | MEM(USB_COMMAND) = CH376S_CMD_SET_MODE; 37 | MEM(USB_DATA) = CH376S_USB_HOST_MODE; 38 | delay(10000); 39 | 40 | return MEM(USB_DATA); 41 | } 42 | 43 | size_t file_read(char *file_name, uint8_t *buffer) 44 | { 45 | size_t total_bytes_read = 0; 46 | uint8_t response = 0; 47 | 48 | MEM(USB_COMMAND) = CH376S_CMD_SET_FILENAME; 49 | send_string(file_name); 50 | 51 | response = MEM(USB_DATA); 52 | 53 | MEM(USB_COMMAND) = CH376S_CMD_FILE_OPEN; 54 | response = wait_for_interrupt(); 55 | 56 | if (response == CH376S_USB_INT_SUCCESS) 57 | { 58 | bool file_done = false; 59 | bool page_done = false; 60 | 61 | while (!file_done) 62 | { 63 | page_done = false; 64 | 65 | MEM(USB_COMMAND) = CH376S_CMD_BYTE_READ; 66 | MEM(USB_DATA) = 0x00; 67 | MEM(USB_DATA) = 0x10; 68 | 69 | response = wait_for_interrupt(); 70 | 71 | if (response == CH376S_USB_INT_SUCCESS) 72 | { 73 | page_done = true; 74 | file_done = true; 75 | } 76 | 77 | while (!page_done) 78 | { 79 | if (response == CH376S_USB_INT_DISK_READ) 80 | { 81 | MEM(USB_COMMAND) = CH376S_CMD_READ_USB_DATA0; 82 | uint8_t bytes_available = MEM(USB_DATA); 83 | 84 | for (int i = 0; i < bytes_available; i++) 85 | { 86 | buffer[total_bytes_read] = MEM(USB_DATA); 87 | total_bytes_read++; 88 | } 89 | 90 | MEM(USB_COMMAND) = CH376S_CMD_BYTE_RD_GO; 91 | response = wait_for_interrupt(); 92 | } 93 | else if (response == CH376S_USB_INT_SUCCESS) 94 | { 95 | page_done = true; 96 | } 97 | else 98 | { 99 | // printf("Failed to read file data: %02X\r\n", response); 100 | page_done = true; 101 | file_done = true; 102 | } 103 | } 104 | 105 | mputc('.'); 106 | } 107 | } 108 | 109 | MEM(USB_COMMAND) = CH376S_CMD_FILE_CLOSE; 110 | MEM(USB_DATA) = 0; 111 | 112 | wait_for_interrupt(); 113 | 114 | return total_bytes_read; 115 | } 116 | -------------------------------------------------------------------------------- /firmware/ch376s.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ch376s.h 3 | * @author Colin Maykish (crmaykish@gmail.com) 4 | * @brief Control API for the CH376S USB module in UART mode 5 | * @date 2022-01-26 6 | * 7 | * @copyright Copyright (c) 2022 8 | */ 9 | 10 | #ifndef CH376S_H 11 | #define CH376S_H 12 | 13 | #include 14 | #include 15 | #include "mackerel.h" 16 | 17 | // Command return values 18 | #define CH376S_CMD_RET_SUCCESS 0x51 19 | #define CH376S_CMD_RET_ABORT 0x5F 20 | 21 | // Interrupt return values 22 | #define CH376S_USB_INT_SUCCESS 0x14 23 | #define CH376S_USB_INT_CONNECT 0x15 24 | #define CH376S_USB_INT_DISCONNECT 0x16 25 | #define CH376S_USB_INT_DISK_READ 0x1D 26 | 27 | #define CH376S_ERR_OPEN_DIR 0x41 28 | #define CH376S_ERR_MISS_FILE 0x42 29 | #define CH376S_ERR_FILE_CLOSE 0xB4 30 | 31 | // Status register bits 32 | #define CH376S_PARA_STATE_INTB 0b10000000 33 | #define CH376S_PARA_STATE_BZ 0b00010000 34 | 35 | // USB command bytes 36 | #define CH376S_CMD_SET_BAUDRATE 0x02 37 | #define CH376S_CMD_RESET_ALL 0x05 38 | #define CH376S_CMD_CHECK_EXIST 0x06 39 | #define CH376S_CMD_SET_MODE 0x15 40 | #define CH376S_CMD_GET_STATUS 0x22 41 | #define CH376S_CMD_READ_USB_DATA0 0x27 42 | #define CH376S_CMD_SET_FILENAME 0x2F 43 | #define CH376S_CMD_DISK_CONNECT 0x30 44 | #define CH376S_CMD_DISK_MOUNT 0x31 45 | #define CH376S_CMD_FILE_OPEN 0x32 46 | #define CH376S_CMD_NEXT_FILE 0x33 47 | #define CH376S_CMD_FILE_CLOSE 0x36 48 | #define CH376S_CMD_DIR_INFO 0x37 49 | #define CH376S_CMD_BYTE_READ 0x3A 50 | #define CH376S_CMD_BYTE_RD_GO 0x3B 51 | 52 | // Mode values 53 | #define CH376S_USB_HOST_MODE 0x05 54 | 55 | uint8_t usb_reset(); 56 | 57 | size_t file_read(char *file_name, uint8_t *buffer); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /firmware/fat16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "fat16.h" 4 | 5 | fat16_read_sector_f read_sector = NULL; 6 | 7 | void bswap_boot_sector(fat16_boot_sector_t *b) 8 | { 9 | if (b == NULL) 10 | return; 11 | 12 | b->bytes_per_sector = bswap16(b->bytes_per_sector); 13 | b->reserved_sectors = bswap16(b->reserved_sectors); 14 | b->root_entries = bswap16(b->root_entries); 15 | b->total_sectors_16 = bswap16(b->total_sectors_16); 16 | b->fat_size_16 = bswap16(b->fat_size_16); 17 | b->sectors_per_track = bswap16(b->sectors_per_track); 18 | b->heads = bswap16(b->heads); 19 | b->hidden_sectors = bswap32(b->hidden_sectors); 20 | b->total_sectors_32 = bswap32(b->total_sectors_32); 21 | b->volume_id = bswap32(b->volume_id); 22 | b->boot_sector_signature = bswap16(b->boot_sector_signature); 23 | } 24 | 25 | void bswap_dir_entry(fat16_dir_entry_t *d) 26 | { 27 | if (d == NULL) 28 | return; 29 | 30 | d->creation_time = bswap16(d->creation_time); 31 | d->creation_date = bswap16(d->creation_date); 32 | d->last_access_date = bswap16(d->last_access_date); 33 | d->first_cluster_high = bswap16(d->first_cluster_high); 34 | d->modification_time = bswap16(d->modification_time); 35 | d->modification_date = bswap16(d->modification_date); 36 | d->first_cluster_low = bswap16(d->first_cluster_low); 37 | d->file_size = bswap32(d->file_size); 38 | } 39 | 40 | int fat16_init(fat16_read_sector_f read_sector_fun) 41 | { 42 | if (read_sector_fun) 43 | { 44 | read_sector = read_sector_fun; 45 | return 0; 46 | } 47 | 48 | return -1; 49 | } 50 | 51 | void fat16_read_boot_sector(uint32_t starting_sector, fat16_boot_sector_t *buffer) 52 | { 53 | read_sector(starting_sector, (uint8_t *)(buffer)); 54 | bswap_boot_sector(buffer); 55 | } 56 | 57 | void fat16_print_boot_sector_info(fat16_boot_sector_t *buffer) 58 | { 59 | printf("\r\nBoot sector info:\r\n"); 60 | printf("Bytes per sector: %u\n", buffer->bytes_per_sector); 61 | printf("Sectors per cluster: %u\n", buffer->sectors_per_cluster); 62 | printf("Reserved sectors: %u\n", buffer->reserved_sectors); 63 | printf("FAT count: %u\n", buffer->num_fats); 64 | printf("Root directory entries: %u\n", buffer->root_entries); 65 | printf("Total sectors: %u\n", buffer->total_sectors_16); 66 | printf("FAT size (sectors): %u\n", buffer->fat_size_16); 67 | printf("Sectors per track: %u\n", buffer->sectors_per_track); 68 | printf("Head count: %u\n", buffer->heads); 69 | printf("Hidden sectors: %u\n", buffer->hidden_sectors); 70 | printf("Total sectors (large): %u\n", buffer->total_sectors_32); 71 | } 72 | 73 | int fat16_list_files(fat16_boot_sector_t *boot_sector, fat16_dir_entry_t files_list[]) 74 | { 75 | if (read_sector == NULL) 76 | { 77 | printf("read_sector function pointer is NULL. Call fat16_init() first\r\n"); 78 | return -1; 79 | } 80 | 81 | if (boot_sector == NULL) 82 | { 83 | printf("boot_sector is NULL\r\n"); 84 | return -1; 85 | } 86 | 87 | int valid_files = 0; 88 | 89 | uint32_t root_dir_sector = 2048 + boot_sector->reserved_sectors + (boot_sector->num_fats * boot_sector->fat_size_16); 90 | uint8_t buffer[512]; 91 | 92 | read_sector(root_dir_sector, buffer); 93 | 94 | // TODO: this 16 value should be determined by the root directory count in the boot sector 95 | // After 16 entries, a new sector needs to be read (I think) 96 | for (int i = 0; i < 16; i++) 97 | { 98 | fat16_dir_entry_t *entry = (fat16_dir_entry_t *)(buffer + i * 32); 99 | 100 | bswap_dir_entry(entry); 101 | 102 | // Check if the entry is free (0x00) or deleted (0xE5) 103 | if (entry->filename[0] == 0x00 || entry->filename[0] == 0xE5) 104 | { 105 | continue; // Skip empty or deleted entries 106 | } 107 | 108 | // Check if the entry represents a valid file or directory 109 | if (entry->attributes & 0x10) 110 | { 111 | // This is a directory (attribute 0x10) 112 | continue; 113 | } 114 | 115 | memcpy(&files_list[valid_files], entry, 32); 116 | valid_files++; 117 | } 118 | 119 | return valid_files; 120 | } 121 | 122 | void fat16_get_file_name(fat16_dir_entry_t *dir_entry, char *filename) 123 | { 124 | if (dir_entry == NULL) 125 | { 126 | return; 127 | } 128 | 129 | if (filename == NULL) 130 | { 131 | return; 132 | } 133 | 134 | memset(filename, ' ', 13); 135 | 136 | // Copy the name 137 | strncpy(filename, (char *)dir_entry->filename, 8); 138 | // Add a dot between the name and extension 139 | filename[8] = '.'; 140 | // Copy the extension 141 | strncpy(filename + 9, (char *)dir_entry->extension, 3); 142 | 143 | filename[12] = 0; // Null-terminate the string 144 | } 145 | 146 | // Function to get the next cluster from the FAT 147 | uint16_t get_fat_entry(fat16_boot_sector_t *boot_sector, uint16_t cluster) 148 | { 149 | // The FAT16 entry for a cluster is at cluster * 2 (since each entry is 2 bytes) 150 | uint32_t fat_offset = cluster * 2; // Offset of the entry in the FAT table (in bytes) 151 | 152 | // Calculate the FAT sector (add hidden sectors + reserved sectors + the offset) 153 | uint32_t fat_sector = boot_sector->hidden_sectors + boot_sector->reserved_sectors + (fat_offset / boot_sector->bytes_per_sector); 154 | 155 | uint32_t fat_entry_offset = fat_offset % boot_sector->bytes_per_sector; // Offset within the sector 156 | 157 | uint8_t fat_buffer[boot_sector->bytes_per_sector]; // Buffer to hold one FAT sector 158 | read_sector(fat_sector, fat_buffer); 159 | 160 | // The entry is 2 bytes long, so read the next 2 bytes for the cluster chain 161 | uint16_t next_cluster = (fat_buffer[fat_entry_offset] | (fat_buffer[fat_entry_offset + 1] << 8)) & 0xFFFF; 162 | 163 | return next_cluster; 164 | } 165 | 166 | int fat16_read_file(fat16_boot_sector_t *boot_sector, uint16_t starting_cluster, uint8_t *buffer, uint32_t buffer_size) 167 | { 168 | uint32_t buffer_index = 0; 169 | uint16_t current_cluster = starting_cluster; 170 | 171 | // Calculate the first sector of the cluster 172 | uint32_t sector_size = boot_sector->bytes_per_sector; 173 | uint32_t sectors_per_cluster = boot_sector->sectors_per_cluster; 174 | 175 | while (current_cluster != 0xFFFF && buffer_index < buffer_size) 176 | { 177 | // printf("current cluster: %u\r\n", current_cluster); 178 | 179 | duart_putc('.'); 180 | 181 | // TODO: where is this magic 32 coming from? 182 | uint32_t first_sector_of_cluster = 32 + 2048 + (current_cluster - 2) * sectors_per_cluster + boot_sector->reserved_sectors + (boot_sector->num_fats * boot_sector->fat_size_16); 183 | 184 | // Read the sectors of the current cluster into the buffer 185 | for (uint32_t sector_offset = 0; sector_offset < sectors_per_cluster && buffer_index < buffer_size; sector_offset++) 186 | { 187 | uint32_t sector = first_sector_of_cluster + sector_offset; 188 | uint8_t sector_buffer[sector_size]; 189 | 190 | // Read the sector into the buffer 191 | // printf("file sector %u\r\n", sector); 192 | read_sector(sector, sector_buffer); 193 | 194 | // Copy the sector data into the main buffer 195 | uint32_t bytes_to_copy = (buffer_size - buffer_index < sector_size) ? (buffer_size - buffer_index) : sector_size; 196 | memcpy(buffer + buffer_index, sector_buffer, bytes_to_copy); 197 | buffer_index += bytes_to_copy; 198 | } 199 | 200 | // Get the next cluster from the FAT 201 | current_cluster = get_fat_entry(boot_sector, current_cluster); 202 | } 203 | 204 | return buffer_index; // Returns the number of bytes read 205 | } -------------------------------------------------------------------------------- /firmware/fat16.h: -------------------------------------------------------------------------------- 1 | #ifndef FAT16_H_ 2 | #define FAT16_H_ 3 | 4 | #include "mackerel.h" 5 | 6 | // Function to read a single sector from a block device 7 | typedef void (*fat16_read_sector_f)(uint32_t, uint8_t *); 8 | 9 | typedef struct __attribute__((packed)) 10 | { 11 | uint8_t jump_instruction[3]; // Jump instruction to boot code (0xEB + 2 bytes) 12 | uint8_t oem_name[8]; // OEM Name (e.g., "MSWIN4.1") 13 | uint16_t bytes_per_sector; // Bytes per sector (usually 512) 14 | uint8_t sectors_per_cluster; // Sectors per cluster (1 byte, usually 1, 2, 4, or 8) 15 | uint16_t reserved_sectors; // Reserved sectors before the first FAT 16 | uint8_t num_fats; // Number of FATs (typically 2) 17 | uint16_t root_entries; // Maximum number of entries in the root directory 18 | uint16_t total_sectors_16; // Total number of sectors (16-bit field) 19 | uint8_t media_descriptor; // Media descriptor type (0xF8 for hard drives) 20 | uint16_t fat_size_16; // Size of one FAT in sectors (16-bit) 21 | uint16_t sectors_per_track; // Sectors per track (for compatibility with BIOS) 22 | uint16_t heads; // Number of heads (for compatibility with BIOS) 23 | uint32_t hidden_sectors; // Number of hidden sectors (usually 0) 24 | uint32_t total_sectors_32; // Total number of sectors (32-bit field, used for larger drives) 25 | 26 | // FAT16 specific BPB (BIOS Parameter Block) 27 | uint8_t drive_number; // Drive number (usually 0x80 for hard drives) 28 | uint8_t reserved_1; // Reserved (0x00) 29 | uint8_t boot_signature; // Boot signature (0x29) 30 | uint32_t volume_id; // Volume ID (unique to each volume) 31 | uint8_t volume_label[11]; // Volume label (e.g., "NO NAME ") 32 | uint8_t fs_type[8]; // File system type (e.g., "FAT16 ") 33 | 34 | uint8_t boot_code[448]; // Boot code (can be used by the bootloader) 35 | uint16_t boot_sector_signature; // Boot sector signature (0x55AA) 36 | } fat16_boot_sector_t; 37 | 38 | typedef struct __attribute__((packed)) 39 | { 40 | uint8_t filename[8]; // 8 characters for file name 41 | uint8_t extension[3]; // 3 characters for file extension 42 | uint8_t attributes; // File attributes (e.g., 0x20 for regular files) 43 | uint8_t reserved; // Reserved (usually 0) 44 | uint8_t creation_time_tenth; // Creation time (tenth of second) 45 | uint16_t creation_time; // Creation time 46 | uint16_t creation_date; // Creation date 47 | uint16_t last_access_date; // Last access date 48 | uint16_t first_cluster_high; // High word of first cluster 49 | uint16_t modification_time; // Last modification time 50 | uint16_t modification_date; // Last modification date 51 | uint16_t first_cluster_low; // Low word of first cluster 52 | uint32_t file_size; // File size (in bytes) 53 | } fat16_dir_entry_t; 54 | 55 | int fat16_init(fat16_read_sector_f read_sector); 56 | 57 | void fat16_read_boot_sector(uint32_t starting_sector, fat16_boot_sector_t *buffer); 58 | 59 | void fat16_print_boot_sector_info(fat16_boot_sector_t *buffer); 60 | 61 | int fat16_list_files(fat16_boot_sector_t *boot_sector, fat16_dir_entry_t files_list[]); 62 | 63 | void fat16_get_file_name(fat16_dir_entry_t *dir_entry, char *filename); 64 | 65 | int fat16_read_file(fat16_boot_sector_t *boot_sector, uint16_t starting_cluster, uint8_t *buffer, uint32_t buffer_size); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /firmware/fatfs_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "mackerel.h" 5 | #include "fat16.h" 6 | 7 | #ifdef MACKEREL_08 8 | #include "sd.h" 9 | #else 10 | #include "ide.h" 11 | #endif 12 | 13 | void block_read(uint32_t block_num, uint8_t *block) 14 | { 15 | #ifdef MACKEREL_08 16 | sd_read(block_num, block); 17 | #else 18 | IDE_read_sector((uint16_t *)block, block_num); 19 | #endif 20 | } 21 | 22 | int main() 23 | { 24 | fat16_boot_sector_t boot_sector; 25 | 26 | fat16_dir_entry_t files_list[16] = {0}; 27 | 28 | printf("FAT Filesystem Demo\r\n"); 29 | 30 | #ifdef MACKEREL_08 31 | // Setup SD card 32 | if (!sd_init()) 33 | { 34 | return 1; 35 | } 36 | #else 37 | // Reset the IDE interface 38 | uint16_t buf[256]; 39 | IDE_reset(); 40 | IDE_device_info(buf); 41 | #endif 42 | 43 | // Initialize FAT16 library with the block read function 44 | if (fat16_init(block_read) != 0) 45 | { 46 | printf("Failed to initialize FAT16 library\r\n"); 47 | return -1; 48 | } 49 | 50 | // TODO: read the MBR to find the partition location (for now, just assume partition starts at sector 2048) 51 | printf("Reading boot sector of first partition\r\n"); 52 | fat16_read_boot_sector(2048, &boot_sector); 53 | fat16_print_boot_sector_info(&boot_sector); 54 | 55 | printf("Listing files in partition:\r\n"); 56 | fat16_list_files(&boot_sector, files_list); 57 | 58 | for (int i = 0; i < 16; i++) 59 | { 60 | if (files_list[i].file_size > 0) 61 | { 62 | char filename[13]; 63 | fat16_get_file_name(&files_list[i], filename); 64 | printf("%s, %u\r\n", filename, files_list[i].file_size); 65 | } 66 | } 67 | 68 | printf("Printing hello.txt...\r\n"); 69 | 70 | for (int i = 0; i < 16; i++) 71 | { 72 | if (files_list[i].file_size > 0) 73 | { 74 | char filename[13]; 75 | fat16_get_file_name(&files_list[i], filename); 76 | 77 | if (strncmp(filename, "HELLO .TXT", 12) == 0) 78 | { 79 | printf("Found file: %s - cluster: %u\r\n", filename, files_list[i].first_cluster_low); 80 | 81 | uint8_t *file = (uint8_t *)0x80000; 82 | 83 | int bytes_read = fat16_read_file(&boot_sector, files_list[i].first_cluster_low, file, files_list[i].file_size); 84 | 85 | if (bytes_read != files_list[i].file_size) 86 | { 87 | printf("File read failed\r\n"); 88 | } 89 | 90 | printf("\r\n"); 91 | 92 | memdump((uint32_t)file, bytes_read); 93 | 94 | break; 95 | } 96 | } 97 | } 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /firmware/glue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mackerel.h" 3 | 4 | // Glue code for Baselibc 5 | 6 | size_t uart_write(FILE *instance, const char *bp, size_t n) 7 | { 8 | for (size_t c = 0; c < n; c++) 9 | { 10 | duart_putc(bp[c]); 11 | } 12 | return n; 13 | } 14 | 15 | const struct File_methods output_methods = { uart_write, NULL }; 16 | struct File stdout_data = { &output_methods }; 17 | FILE* const stdout = &stdout_data; 18 | -------------------------------------------------------------------------------- /firmware/hello.c: -------------------------------------------------------------------------------- 1 | #include "mackerel.h" 2 | #include "ide.h" 3 | #include 4 | #include 5 | 6 | void __attribute__((interrupt)) timer_isr() 7 | { 8 | // duart_putc('.'); 9 | } 10 | 11 | void __attribute__((interrupt)) ide_isr() 12 | { 13 | uint8_t status = MEM(IDE_STATUS); 14 | printf("\r\nIDE_INT: %u\r\n", status); 15 | } 16 | 17 | int main() 18 | { 19 | uint16_t buf[256] = {0}; 20 | 21 | set_exception_handler(EXCEPTION_AUTOVECTOR + IRQ_NUM_TIMER, timer_isr); 22 | set_exception_handler(EXCEPTION_AUTOVECTOR + IRQ_NUM_IDE, ide_isr); 23 | 24 | set_interrupts(true); 25 | 26 | printf("IDE Demo\r\n"); 27 | 28 | printf("reset IDE device\r\n"); 29 | MEM(IDE_COMMAND) = IDE_CMD_RESET; 30 | IDE_wait_for_device_ready(); 31 | 32 | printf("IDE is ready\r\n"); 33 | 34 | IDE_device_info(buf); 35 | 36 | printf("read sector 1\r\n"); 37 | IDE_read_sector(buf, 1); 38 | 39 | memdump((uint32_t)buf, 512); 40 | 41 | printf("read sector 2\r\n"); 42 | IDE_read_sector(buf, 2); 43 | 44 | memdump((uint32_t)buf, 512); 45 | 46 | printf("Done\r\n"); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /firmware/ide.c: -------------------------------------------------------------------------------- 1 | #include "ide.h" 2 | #include "mackerel.h" 3 | #include 4 | 5 | // Reverse the order of the low 8-bits in a 16-bit number 6 | uint16_t reverse_lowest_8_bits(uint16_t num) 7 | { 8 | uint8_t low_bits = num & 0xFF; 9 | 10 | uint8_t reversed_low_bits = 0; 11 | for (int i = 0; i < 8; i++) 12 | { 13 | reversed_low_bits |= ((low_bits >> i) & 1) << (7 - i); 14 | } 15 | 16 | return (num & 0xFF00) | reversed_low_bits; 17 | } 18 | 19 | void read_sector_internal(uint16_t *buf) 20 | { 21 | for (uint16_t i = 0; i < 256; i++) 22 | { 23 | // IDE_wait_for_data_ready(); // needed at higher speeds? 24 | buf[i] = MEM16(IDE_DATA); 25 | 26 | #ifdef MACKEREL_30 27 | // NOTE: Mackerel-30 v0.1 has the low byte of the IDE interface wired in reverse order 28 | buf[i] = reverse_lowest_8_bits(buf[i]); 29 | #endif 30 | } 31 | } 32 | 33 | void IDE_wait_for_device_ready() 34 | { 35 | while ((MEM(IDE_STATUS) & IDE_SR_DRDY) == 0) 36 | { 37 | } 38 | } 39 | 40 | void IDE_wait_for_data_ready() 41 | { 42 | while ((MEM(IDE_STATUS) & IDE_SR_DRQ) == 0) 43 | { 44 | } 45 | } 46 | 47 | void IDE_read_sector(uint16_t *buf, uint32_t lba) 48 | { 49 | // NOTE: IDE sector count starts at 1 (not true in LBA mode?) 50 | 51 | // NOTE: limited to 24 bit LBA addressing (~8GB) 52 | 53 | // Select master drive 54 | MEM(IDE_DRIVE_SEL) = 0xE0; 55 | 56 | MEM(IDE_SECTOR_COUNT) = 1; 57 | 58 | MEM(IDE_SECTOR_START) = (uint8_t)(lba & 0xFF); 59 | MEM(IDE_LBA_MID) = (uint8_t)((lba >> 8) & 0xFF); 60 | MEM(IDE_LBA_HIGH) = (uint8_t)((lba >> 16) & 0xFF); 61 | 62 | // Send the read sector command 63 | MEM(IDE_COMMAND) = IDE_CMD_READ_SECTOR; 64 | IDE_wait_for_data_ready(); 65 | read_sector_internal(buf); 66 | } 67 | 68 | void IDE_device_info(uint16_t *buf) 69 | { 70 | printf("Reading IDE device info...\r\n"); 71 | MEM(IDE_COMMAND) = IDE_CMD_IDENTIFY; 72 | IDE_wait_for_data_ready(); 73 | read_sector_internal(buf); 74 | 75 | // Model 76 | for (int i = 27; i <= 46; i++) 77 | { 78 | printf("%c%c", (char)((buf[i] & 0x00FF)), (char)((buf[i] & 0xFF00) >> 8)); 79 | } 80 | 81 | printf("\r\n"); 82 | 83 | // Version 84 | for (int i = 23; i <= 26; i++) 85 | { 86 | printf("%c%c", (char)((buf[i] & 0x00FF)), (char)((buf[i] & 0xFF00) >> 8)); 87 | } 88 | 89 | printf("\r\n"); 90 | 91 | // Serial number 92 | for (int i = 10; i <= 19; i++) 93 | { 94 | printf("%c%c", (char)((buf[i] & 0x00FF)), (char)((buf[i] & 0xFF00) >> 8)); 95 | } 96 | 97 | printf("\r\n"); 98 | } 99 | 100 | void IDE_reset() 101 | { 102 | MEM(IDE_COMMAND) = IDE_CMD_RESET; 103 | IDE_wait_for_device_ready(); 104 | } 105 | -------------------------------------------------------------------------------- /firmware/ide.h: -------------------------------------------------------------------------------- 1 | #ifndef IDE_H_ 2 | #define IDE_H_ 3 | 4 | #include "mackerel.h" 5 | 6 | // IDE mem-mapped registers 7 | #define IDE_DATA IDE_BASE + 0x00 8 | // #define IDE_ERROR IDE_BASE + 0x02 9 | #define IDE_FEATURE IDE_BASE + 0x02 10 | #define IDE_SECTOR_COUNT IDE_BASE + 0x04 11 | #define IDE_SECTOR_START IDE_BASE + 0x06 12 | #define IDE_LBA_MID IDE_BASE + 0x08 13 | #define IDE_LBA_HIGH IDE_BASE + 0x0A 14 | #define IDE_DRIVE_SEL IDE_BASE + 0x0C 15 | #define IDE_STATUS IDE_BASE + 0x0E 16 | #define IDE_COMMAND IDE_BASE + 0x0E 17 | 18 | // IDE commands 19 | #define IDE_CMD_RESET 0x08 20 | #define IDE_CMD_READ_SECTOR 0x20 21 | #define IDE_CMD_WRITE_SECTOR 0x30 22 | #define IDE_CMD_IDENTIFY 0xEC 23 | #define IDE_CMD_SET_FEATURES 0xEF 24 | 25 | // Status register bits 26 | #define IDE_SR_BSY 0x80 // Busy 27 | #define IDE_SR_DRDY 0x40 // Drive ready 28 | #define IDE_SR_DF 0x20 // Drive write fault 29 | #define IDE_SR_DSC 0x10 // Drive seek complete 30 | #define IDE_SR_DRQ 0x08 // Data request ready 31 | #define IDE_SR_CORR 0x04 // Corrected data 32 | #define IDE_SR_IDX 0x02 // Index 33 | #define IDE_SR_ERR 0x01 // Error 34 | 35 | void IDE_wait_for_device_ready(); 36 | 37 | void IDE_wait_for_data_ready(); 38 | 39 | void IDE_read_sector(uint16_t *buf, uint32_t lba); 40 | 41 | void IDE_device_info(uint16_t *buf); 42 | 43 | void IDE_reset(); 44 | 45 | #endif -------------------------------------------------------------------------------- /firmware/kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mackerel.h" 4 | 5 | void __attribute__((interrupt)) duart1_isr() 6 | { 7 | // Determine the type of interrupt 8 | uint8_t misr = MEM(DUART1_MISR); 9 | 10 | if (misr & DUART_INTR_RXRDY) 11 | { 12 | // RX character available 13 | uint8_t a = MEM(DUART1_RBB); // Read the available byte. This clears the interrupt 14 | duart_putc(a); // Print the character back out 15 | } 16 | else if (misr & DUART_INTR_COUNTER) 17 | { 18 | MEM(DUART1_OPR_RESET); 19 | duart_putc('y'); 20 | } 21 | } 22 | 23 | void __attribute__((interrupt)) timer_isr() 24 | { 25 | duart_putc('.'); 26 | } 27 | 28 | int main() 29 | { 30 | uint32_t i = 0; 31 | 32 | printf("Starting Mackerel kernel...\n"); 33 | 34 | set_exception_handler(EXCEPTION_AUTOVECTOR + IRQ_NUM_TIMER, &timer_isr); 35 | set_exception_handler(EXCEPTION_USER + IRQ_NUM_DUART, &duart1_isr); 36 | 37 | // Setup DUART 1 38 | MEM(DUART1_IVR) = EXCEPTION_USER + IRQ_NUM_DUART; // Set interrupt base register 39 | 40 | // Setup DUART 1 timer as 5 Hz interrupt 41 | MEM(DUART1_ACR) = 0xF0; // Set timer mode X/16 42 | MEM(DUART1_CUR) = 0x5A; // Counter upper byte, (3.6864MHz / 2 / 16 / 0x5A00) = 5 Hz 43 | MEM(DUART1_CLR) = 0x00; // Counter lower byte 44 | MEM(DUART1_OPR); // Start counter 45 | 46 | MEM(DUART1_IMR) = DUART_INTR_RXRDY | DUART_INTR_COUNTER; // Unmask interrupts 47 | 48 | printf("Starting kernel...%X\r\n", 0xC0FFEE); 49 | 50 | // Turn interrupts on 51 | set_interrupts(true); 52 | 53 | while (true) 54 | { 55 | printf("Loop: %X\r\n", i); 56 | 57 | i++; 58 | 59 | delay(50000); 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /firmware/linker_ram.scr: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | RAM(RWX) : ORIGIN = 0x400, LENGTH = 0x380000 - 0x400 4 | } 5 | 6 | SECTIONS 7 | { 8 | .text 0x400 : { *(.text) } > RAM 9 | .rodata : { *(.rodata) } > RAM 10 | .bss : { *(.bss) } > RAM 11 | } 12 | -------------------------------------------------------------------------------- /firmware/linker_ram_10.scr: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | RAM(RWX) : ORIGIN = 0x400, LENGTH = 0xF00000 - 0x4000 - 0x400 4 | } 5 | 6 | SECTIONS 7 | { 8 | .text 0x400 : { *(.text) } > RAM 9 | .rodata : { *(.rodata) } > RAM 10 | .bss : { *(.bss) } > RAM 11 | } 12 | -------------------------------------------------------------------------------- /firmware/linker_ram_30.scr: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | RAM_CODE(RX) : ORIGIN = 0x400, LENGTH = 0x10000 - 0x400 4 | RAM_DATA(RW) : ORIGIN = 0x10000, LENGTH = 0x70000 - 0x1000 # 0x1000 for the stack 5 | } 6 | 7 | SECTIONS 8 | { 9 | .text 0x400 : { *(.text) } > RAM_CODE 10 | .rodata : { *(.rodata) } > RAM_DATA 11 | .bss : { *(.bss) } > RAM_DATA 12 | } 13 | -------------------------------------------------------------------------------- /firmware/linker_rom.scr: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ROM(RX) : ORIGIN = 0x380000, LENGTH = 0x7C000 4 | RAM(RW) : ORIGIN = 0x380000 - 0x1000, LENGTH = 0x1000 5 | } 6 | 7 | SECTIONS 8 | { 9 | .vectors 0x380000 : { *(.vectors) } > ROM 10 | .text : { *(.text) } > ROM 11 | .rodata : { *(.rodata) } > ROM 12 | .bss 0x380000 - 0x1000 : { *(.bss) } > RAM 13 | } 14 | -------------------------------------------------------------------------------- /firmware/linker_rom_10.scr: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ROM(RX) : ORIGIN = 0xF00000, LENGTH = 0xF8000 4 | RAM(RW) : ORIGIN = 0xF00000 - 0x4000, LENGTH = 0x4000 - 0x1000 5 | } 6 | 7 | SECTIONS 8 | { 9 | .vectors 0xF00000 : { *(.vectors) } > ROM 10 | .text : { *(.text) } > ROM 11 | .rodata : { *(.rodata) } > ROM 12 | .bss 0xF00000 - 0x4000 : { *(.bss) } > RAM 13 | } 14 | -------------------------------------------------------------------------------- /firmware/linker_rom_30.scr: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ROM(RX) : ORIGIN = 0xE0000000, LENGTH = 0x80000 4 | RAM(RX) : ORIGIN = 0x80000 - 0x4000, LENGTH = 0x4000 - 0x1000 5 | } 6 | 7 | SECTIONS 8 | { 9 | .vectors 0xE0000000 : { *(.vectors) } > ROM 10 | .text : { *(.text) } > ROM 11 | .rodata : { *(.rodata) } > ROM 12 | .bss 0x80000 - 0x4000 : { *(.bss) } > RAM 13 | } 14 | -------------------------------------------------------------------------------- /firmware/mackerel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mackerel.h" 3 | #include "term.h" 4 | 5 | void set_interrupts(bool enabled) 6 | { 7 | if (enabled) 8 | { 9 | // Set minimum interrupt level to 0 in the status register 10 | asm("and.w #0xF8FF, %sr"); 11 | } 12 | else 13 | { 14 | // Set minimum interrupt level to 7, i.e. only non-maskable interrupts enabled 15 | asm("or.w #0x700, %sr"); 16 | } 17 | } 18 | 19 | void set_exception_handler(unsigned char exception_number, void (*exception_handler)()) 20 | { 21 | MEM32(exception_number * 4) = (uint32_t)exception_handler; 22 | } 23 | 24 | void duart_init(void) 25 | { 26 | MEM(DUART1_IMR) = 0x00; // Mask all interrupts 27 | MEM(DUART1_MR1B) = 0b00010011; // No Rx RTS, No Parity, 8 bits per character 28 | MEM(DUART1_MR2B) = 0b00000111; // Channel mode normal, No Tx RTS, No CTS, stop bit length 1 29 | MEM(DUART1_ACR) = 0x80; // Baudrate set 2 30 | MEM(DUART1_CRB) = 0x80; // Set Rx extended bit 31 | MEM(DUART1_CRB) = 0xA0; // Set Tx extended bit 32 | MEM(DUART1_CSRB) = 0x88; // 115200 baud 33 | MEM(DUART1_CRB) = 0b0101; // Enable Tx/Rx 34 | } 35 | 36 | void duart_putc(char c) 37 | { 38 | while ((MEM(DUART1_SRB) & 0b00000100) == 0) 39 | { 40 | } 41 | 42 | MEM(DUART1_TBB) = c; 43 | 44 | if (c == 0x0A) 45 | { 46 | duart_putc(0x0D); 47 | } 48 | } 49 | 50 | char duart_getc(void) 51 | { 52 | while ((MEM(DUART1_SRB) & 0b00000001) == 0) 53 | { 54 | } 55 | 56 | return MEM(DUART1_RBB); 57 | } 58 | 59 | void duart_puts(const char *s) 60 | { 61 | unsigned i = 0; 62 | 63 | while (s[i] != 0) 64 | { 65 | duart_putc(s[i]); 66 | i++; 67 | } 68 | } 69 | 70 | void print_string_bin(char *str, uint8_t max) 71 | { 72 | uint8_t i = 0; 73 | 74 | while (i < max) 75 | { 76 | if (str[i] >= 32 && str[i] < 127) 77 | { 78 | duart_putc(str[i]); 79 | } 80 | else 81 | { 82 | duart_putc('.'); 83 | } 84 | 85 | i++; 86 | } 87 | } 88 | 89 | void memdump(uint32_t address, uint32_t bytes) 90 | { 91 | uint32_t i = 0; 92 | uint32_t b = 0; 93 | 94 | printf("%08X ", address); 95 | 96 | while (i < bytes) 97 | { 98 | b = MEM(address + i); 99 | 100 | if (b == 0) 101 | { 102 | term_set_color(TERM_FG_GREY); 103 | } 104 | 105 | printf("%02X ", b); 106 | 107 | term_set_color(TERM_RESET); 108 | 109 | i++; 110 | 111 | if (i % 16 == 0 && i < bytes) 112 | { 113 | printf(" |"); 114 | print_string_bin((char *)(address + i - 16), 16); 115 | 116 | printf("|\r\n%08X ", address + i); 117 | } 118 | else if (i % 8 == 0) 119 | { 120 | duart_putc(' '); 121 | } 122 | } 123 | 124 | duart_putc('|'); 125 | print_string_bin((char *)(address + i - 16), 16); 126 | duart_putc('|'); 127 | } 128 | 129 | uint16_t bswap16(uint16_t value) 130 | { 131 | return (value >> 8) | (value << 8); 132 | } 133 | 134 | uint32_t bswap32(uint32_t value) 135 | { 136 | return ((value >> 24) & 0xFF) | 137 | ((value >> 8) & 0xFF00) | 138 | ((value << 8) & 0xFF0000) | 139 | ((value << 24) & 0xFF000000); 140 | } 141 | 142 | void delay(int time) 143 | { 144 | for (int delay = 0; delay < time; delay++) 145 | __asm__ __volatile__(""); 146 | } 147 | 148 | #ifdef MACKEREL_30 149 | void set_vbr(unsigned int vbr_val) 150 | { 151 | asm volatile("movec %0,%%vbr" 152 | : : "d"(vbr_val)); 153 | } 154 | 155 | unsigned int get_vbr() 156 | { 157 | unsigned int vbr_value; 158 | asm volatile( 159 | "movec %%vbr, %0" 160 | : "=d"(vbr_value)); 161 | return vbr_value; 162 | } 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /firmware/mackerel.h: -------------------------------------------------------------------------------- 1 | #ifndef _MACKEREL_H 2 | #define _MACKEREL_H 3 | 4 | #include 5 | 6 | // NOTE: Baselibc has no stdint header 7 | typedef unsigned char uint8_t; 8 | typedef unsigned short uint16_t; 9 | typedef unsigned int uint32_t; 10 | 11 | #define EXCEPTION_AUTOVECTOR 24 12 | #define EXCEPTION_USER 64 13 | 14 | #define IRQ_NUM_IDE 3 15 | #define IRQ_NUM_DUART 5 16 | #define IRQ_NUM_TIMER 6 17 | 18 | #ifdef MACKEREL_30 19 | #define SYSTEM_NAME "Mackerel-30" 20 | #define DUART1_BASE 0xF0000000 21 | #define IDE_BASE 0xF0010000 22 | #elif MACKEREL_10 23 | #define SYSTEM_NAME "Mackerel-10" 24 | #define DUART1_BASE 0xFF8000 25 | #define IDE_BASE 0xFFC000 26 | #elif MACKEREL_08 27 | #define SYSTEM_NAME "Mackerel-08" 28 | #define DUART1_BASE 0x3FC000 29 | // IDE is not supported on Mackerel-08 30 | #define IDE_BASE 0xFFFFFF 31 | #endif 32 | 33 | #define DUART1_MR1A (DUART1_BASE + 0x01) 34 | #define DUART1_MR2A (DUART1_BASE + 0x01) 35 | #define DUART1_SRA (DUART1_BASE + 0x03) 36 | #define DUART1_CSRA (DUART1_BASE + 0x03) 37 | #define DUART1_CRA (DUART1_BASE + 0x05) 38 | #define DUART1_MISR (DUART1_BASE + 0x05) 39 | #define DUART1_RBA (DUART1_BASE + 0x07) 40 | #define DUART1_TBA (DUART1_BASE + 0x07) 41 | #define DUART1_IPCR (DUART1_BASE + 0x09) 42 | #define DUART1_ACR (DUART1_BASE + 0x09) 43 | #define DUART1_ISR (DUART1_BASE + 0x0B) 44 | #define DUART1_IMR (DUART1_BASE + 0x0B) 45 | #define DUART1_CUR (DUART1_BASE + 0x0D) 46 | #define DUART1_CLR (DUART1_BASE + 0x0F) 47 | #define DUART1_MR1B (DUART1_BASE + 0x11) 48 | #define DUART1_MR2B (DUART1_BASE + 0x11) 49 | #define DUART1_SRB (DUART1_BASE + 0x13) 50 | #define DUART1_CSRB (DUART1_BASE + 0x13) 51 | #define DUART1_CRB (DUART1_BASE + 0x15) 52 | #define DUART1_RBB (DUART1_BASE + 0x17) 53 | #define DUART1_TBB (DUART1_BASE + 0x17) 54 | #define DUART1_IVR (DUART1_BASE + 0x19) 55 | #define DUART1_IP (DUART1_BASE + 0x1B) 56 | #define DUART1_OPCR (DUART1_BASE + 0x1B) 57 | #define DUART1_OPR (DUART1_BASE + 0x1D) 58 | #define DUART1_OPR_RESET (DUART1_BASE + 0x1F) 59 | 60 | // Interrupt bits 61 | #define DUART_INTR_COUNTER 0b0001000 62 | #define DUART_INTR_RXRDY 0b00100000 63 | 64 | // Get the value at a memory address 65 | #define MEM(address) (*(volatile uint8_t *)(address)) 66 | 67 | #define MEM16(address) (*(volatile uint16_t *)(address)) 68 | 69 | // Get the value starting at memory address as a uint 70 | #define MEM32(address) (*(volatile uint32_t *)(address)) 71 | 72 | // Enable/disable CPU interrupts 73 | void set_interrupts(bool enabled); 74 | 75 | // Assign a handler function to an exception number (0x00 - 0xFF) 76 | void set_exception_handler(unsigned char exception_number, void (*exception_handler)()); 77 | 78 | // DUART 79 | void duart_init(void); 80 | void duart_putc(char c); 81 | void duart_puts(const char *s); 82 | char duart_getc(void); 83 | 84 | // Utils 85 | void memdump(uint32_t address, uint32_t bytes); 86 | 87 | uint16_t bswap16(uint16_t value); 88 | uint32_t bswap32(uint32_t value); 89 | 90 | // Timing 91 | void delay(int time); 92 | 93 | #ifdef MACKEREL_30 94 | void set_vbr(unsigned int vbr_val); 95 | unsigned int get_vbr(); 96 | #endif 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /firmware/sd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "sd.h" 4 | #include "spi.h" 5 | 6 | static uint8_t CMD0[6] = {0x40 + 0, 0x00, 0x00, 0x00, 0x00, 0x95}; 7 | static uint8_t CMD8[6] = {0x40 + 8, 0x00, 0x00, 0x01, 0xAA, 0x87}; 8 | static uint8_t CMD58[6] = {0x40 + 58, 0x00, 0x00, 0x00, 0x00, 0x01}; 9 | static uint8_t CMD55[6] = {0x40 + 55, 0x00, 0x00, 0x00, 0x00, 0x01}; 10 | static uint8_t ACMD41[6] = {0x40 + 41, 0x40, 0x00, 0x00, 0x00, 0x01}; 11 | static uint8_t CMD17[6] = {0x40 + 17, 0x00, 0x00, 0x00, 0x00, 0x01}; 12 | 13 | static uint8_t sd_get_response(); 14 | 15 | bool sd_reset() 16 | { 17 | int i; 18 | uint8_t b; 19 | bool init_done = false; 20 | 21 | spi_init(CS_SD); 22 | 23 | delay(100); 24 | 25 | spi_loop_clk(); 26 | 27 | b = spi_transfer(CS_SD, SPI_EMPTY); 28 | 29 | if (b != SPI_EMPTY) 30 | { 31 | printf("First SD byte read failed: %02X\r\n", b); 32 | return false; 33 | } 34 | 35 | // CMD0 36 | b = sd_command(CMD0); 37 | 38 | if (b != 0x01) 39 | { 40 | printf("CMD0 failed: %02X\r\n", b); 41 | return false; 42 | } 43 | 44 | // CMD8 45 | b = sd_command(CMD8); 46 | 47 | if (b != 0x01) 48 | { 49 | printf("CMD8 failed %02X\r\n", b); 50 | return false; 51 | } 52 | 53 | // Read the rest of the response and discard 54 | spi_transfer(CS_SD, SPI_EMPTY); 55 | spi_transfer(CS_SD, SPI_EMPTY); 56 | spi_transfer(CS_SD, SPI_EMPTY); 57 | spi_transfer(CS_SD, SPI_EMPTY); 58 | 59 | // CMD58 60 | b = sd_command(CMD58); 61 | 62 | if (b != 0x01) 63 | { 64 | printf("CMD58 failed %02X\r\n", b); 65 | return false; 66 | } 67 | 68 | // Read the rest of the response and discard 69 | spi_transfer(CS_SD, SPI_EMPTY); 70 | spi_transfer(CS_SD, SPI_EMPTY); 71 | spi_transfer(CS_SD, SPI_EMPTY); 72 | spi_transfer(CS_SD, SPI_EMPTY); 73 | 74 | i = 0; 75 | 76 | printf("Sending SD init command...\r\n"); 77 | while (!init_done && i < SPI_RETRY_LIMIT) 78 | { 79 | 80 | b = sd_command(CMD55); 81 | 82 | if (b != 0x01) 83 | { 84 | printf("CMD55 failed %02X\r\n", b); 85 | return false; 86 | } 87 | 88 | b = sd_command(ACMD41); 89 | 90 | if (b == 0x00) 91 | { 92 | init_done = true; 93 | } 94 | 95 | i++; 96 | } 97 | 98 | if (init_done) 99 | { 100 | printf("SD card ready!\r\n"); 101 | } 102 | else 103 | { 104 | printf("Failed to initialize SD card\r\n"); 105 | } 106 | 107 | return init_done; 108 | } 109 | 110 | bool sd_init() 111 | { 112 | bool sd_ready = false; 113 | 114 | for (int i = 0; i < 5; i++) 115 | { 116 | sd_ready = sd_reset(); 117 | 118 | if (sd_ready) 119 | break; 120 | } 121 | 122 | return sd_ready; 123 | } 124 | 125 | uint8_t sd_command(uint8_t command[6]) 126 | { 127 | int i; 128 | 129 | for (i = 0; i < 6; i++) 130 | { 131 | spi_transfer(CS_SD, command[i]); 132 | } 133 | 134 | return sd_get_response(); 135 | } 136 | 137 | void sd_read(uint32_t block_num, uint8_t *block) 138 | { 139 | int i; 140 | uint8_t result; 141 | uint8_t command[6]; 142 | memcpy(command, CMD17, 6); 143 | 144 | if (!block) 145 | { 146 | printf("block pointer cannot be NULL\r\n"); 147 | return; 148 | } 149 | 150 | command[4] = (block_num & 0xFF); 151 | command[3] = ((block_num & 0xFF00) >> 8); 152 | 153 | result = sd_command(command); 154 | 155 | if (result != 0x00) 156 | { 157 | printf("CMD17 failed\r\n"); 158 | return; 159 | } 160 | 161 | while (result != 0xFE) 162 | { 163 | result = sd_get_response(); 164 | } 165 | 166 | for (i = 0; i < 512; i++) 167 | { 168 | block[i] = spi_transfer(CS_SD, SPI_EMPTY); 169 | } 170 | 171 | // read the 16 bit CRC and ignore 172 | spi_transfer(CS_SD, SPI_EMPTY); 173 | spi_transfer(CS_SD, SPI_EMPTY); 174 | } 175 | 176 | static uint8_t sd_get_response() 177 | { 178 | uint8_t response = spi_transfer(CS_SD, SPI_EMPTY); 179 | int count = 0; 180 | 181 | while (response == 0xFF && count < SPI_RETRY_LIMIT) 182 | { 183 | response = spi_transfer(CS_SD, SPI_EMPTY); 184 | count++; 185 | } 186 | 187 | return response; 188 | } 189 | -------------------------------------------------------------------------------- /firmware/sd.h: -------------------------------------------------------------------------------- 1 | #ifndef SD_H 2 | #define SD_H 3 | 4 | #include 5 | #include "mackerel.h" 6 | #include "spi.h" 7 | 8 | #define CS_SD CS2 // Use CS0 for the SD card 9 | 10 | // Setup the SD card interface 11 | // Return true on success, false on error 12 | bool sd_init(); 13 | 14 | // Send a 6 byte command to the SD card 15 | // Returns the first byte of the response 16 | uint8_t sd_command(uint8_t command[6]); 17 | 18 | // Read a single block of SD card data into the block pointer 19 | void sd_read(uint32_t block_num, uint8_t *block); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /firmware/spi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "spi.h" 3 | #include "mackerel.h" 4 | 5 | #define GPIO_ON(pin) MEM(DUART1_OPR_RESET) = (1 << pin) 6 | #define GPIO_OFF(pin) MEM(DUART1_OPR) = (1 << pin); 7 | #define MISO_GET() (MEM(DUART1_IP) & (1 << MISO)) 8 | 9 | void spi_init(uint8_t cs) 10 | { 11 | // Default state of the SPI pins 12 | GPIO_ON(cs); 13 | GPIO_ON(MOSI); 14 | GPIO_OFF(SCLK); 15 | 16 | GPIO_OFF(LED); 17 | } 18 | 19 | uint8_t spi_transfer(uint8_t cs, uint8_t byte_to_send) 20 | { 21 | uint8_t byte_received = 0; 22 | int i; 23 | 24 | GPIO_OFF(SCLK); 25 | 26 | // Set chip select (active low) 27 | GPIO_OFF(cs); 28 | 29 | for (i = 7; i >= 0; i--) 30 | { 31 | if (byte_to_send & (1 << i)) 32 | { 33 | GPIO_ON(MOSI); 34 | } 35 | else 36 | { 37 | GPIO_OFF(MOSI); 38 | } 39 | 40 | // Clock high 41 | GPIO_ON(SCLK); 42 | 43 | // Shift in a bit 44 | if (MISO_GET()) 45 | { 46 | byte_received |= (1 << i); 47 | } 48 | 49 | // Clock low 50 | GPIO_OFF(SCLK); 51 | } 52 | 53 | // disable SD card 54 | GPIO_ON(cs); 55 | 56 | return byte_received; 57 | } 58 | 59 | void spi_loop_clk() 60 | { 61 | // Toggle the SPI clock 80 times with CS disabled 62 | for (int i = 0; i < 80; i++) 63 | { 64 | GPIO_ON(SCLK); 65 | GPIO_OFF(SCLK); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /firmware/spi.h: -------------------------------------------------------------------------------- 1 | #ifndef SPI_H 2 | #define SPI_H 3 | 4 | #include "mackerel.h" 5 | 6 | // SPI output pins 7 | #define SCLK (3) 8 | #define MOSI (2) // DI on SD card 9 | #define CS0 (4) 10 | #define CS1 (5) 11 | #define CS2 (6) 12 | 13 | // SPI input pins 14 | #define MISO (4) // DO on SD card 15 | 16 | #define LED (7) 17 | 18 | #define SPI_EMPTY 0xFF 19 | 20 | #define SPI_RETRY_LIMIT 10 21 | 22 | // Set up the GPIO pins needed for SPI 23 | void spi_init(uint8_t cs); 24 | 25 | // Send and receive a single byte over SPI 26 | uint8_t spi_transfer(uint8_t cs, uint8_t b); 27 | 28 | void spi_loop_clk(); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /firmware/start.c: -------------------------------------------------------------------------------- 1 | #include "mackerel.h" 2 | 3 | extern int main(); 4 | 5 | void panic(const char *err) 6 | { 7 | duart_puts("\r\nPANIC: "); 8 | duart_puts(err); 9 | duart_puts("\r\n"); 10 | 11 | while (1) 12 | { 13 | } 14 | } 15 | 16 | void __attribute((interrupt)) exception_unhandled() { panic("Unhandled exception"); } 17 | void __attribute((interrupt)) exception_bus_error() { panic("Bus error"); } 18 | void __attribute((interrupt)) exception_addr_error() { panic("Address error"); } 19 | void __attribute((interrupt)) exception_illegal_inst() { panic("Illegal instruction"); } 20 | void __attribute((interrupt)) exception_div_zero() { panic("Divide by zero"); } 21 | void __attribute((interrupt)) exception_chk() { panic("Chk instruction out of bounds"); } 22 | void __attribute((interrupt)) exception_trapv() { panic("Trap v"); } 23 | void __attribute((interrupt)) exception_priv_violation() { panic("Privilege violation"); } 24 | void __attribute((interrupt)) exception_unimp_inst() { panic("Unimplemented instruction"); } 25 | void __attribute((interrupt)) exception_uninit_int_vector() { panic("Uninitialized interrupt vector"); } 26 | void __attribute((interrupt)) exception_spurious_intr() { panic("Spurious interrupt"); } 27 | void __attribute((interrupt)) autovector() { panic("Autovector"); } 28 | void __attribute((interrupt)) trap() { panic("Trap"); } 29 | void __attribute((interrupt)) user_interrupt() { panic("User interrupt"); } 30 | 31 | void _start() 32 | { 33 | // Disable interrupts 34 | set_interrupts(false); 35 | 36 | set_exception_handler(0, 0); 37 | set_exception_handler(1, 0); 38 | set_exception_handler(2, exception_bus_error); 39 | set_exception_handler(3, exception_addr_error); 40 | set_exception_handler(4, exception_illegal_inst); 41 | set_exception_handler(5, exception_div_zero); 42 | set_exception_handler(6, exception_chk); 43 | set_exception_handler(7, exception_trapv); 44 | set_exception_handler(8, exception_priv_violation); 45 | set_exception_handler(10, exception_unimp_inst); 46 | set_exception_handler(11, exception_unimp_inst); 47 | set_exception_handler(15, exception_uninit_int_vector); 48 | set_exception_handler(24, exception_spurious_intr); 49 | 50 | for (int i = 25; i < 32; i += 1) 51 | { 52 | set_exception_handler(i, &autovector); 53 | } 54 | 55 | // Trap block 56 | for (int i = 32; i < 48; i += 1) 57 | { 58 | set_exception_handler(i, &trap); 59 | } 60 | 61 | // User interrupts 62 | for (int i = 64; i <= 255; i += 1) 63 | { 64 | set_exception_handler(i, &user_interrupt); 65 | } 66 | 67 | // Setup the hardware peripherals 68 | duart_init(); 69 | 70 | // Call main 71 | main(); 72 | } 73 | -------------------------------------------------------------------------------- /firmware/start_ram.c: -------------------------------------------------------------------------------- 1 | extern int main(); 2 | 3 | void _start() 4 | { 5 | // Call main 6 | main(); 7 | } 8 | -------------------------------------------------------------------------------- /firmware/term.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "term.h" 3 | 4 | void term_set_color(char *color) 5 | { 6 | duart_puts("\033["); 7 | duart_puts(color); 8 | duart_putc('m'); 9 | } 10 | 11 | void term_cursor_move(term_cursor_dir_e dir, uint8_t steps) 12 | { 13 | printf("\033[%d%c", steps, dir); 14 | } 15 | 16 | void term_cursor_set_x(uint8_t x) 17 | { 18 | printf("\033[%dG", x); 19 | } 20 | 21 | void term_cursor_set_pos(uint8_t x, uint8_t y) 22 | { 23 | printf("\033[%d;%dH", x, y); 24 | } 25 | 26 | void term_cursor_set_vis(bool visible) 27 | { 28 | duart_puts(visible ? TERM_CURSOR_SHOW : TERM_CURSOR_HIDE); 29 | } 30 | 31 | void term_clear() 32 | { 33 | term_set_color(TERM_RESET); 34 | duart_puts("\033[2J\033[H"); 35 | } 36 | -------------------------------------------------------------------------------- /firmware/term.h: -------------------------------------------------------------------------------- 1 | #ifndef TERM_H_ 2 | #define TERM_H_ 3 | 4 | #include "mackerel.h" 5 | 6 | // Terminal colors 7 | #define TERM_RESET "0" 8 | #define TERM_FG_RED "31" 9 | #define TERM_FG_GREEN "32" 10 | #define TERM_FG_YELLOW "33" 11 | #define TERM_FG_BLUE "34" 12 | #define TERM_FG_MAGENTA "35" 13 | #define TERM_FG_CYAN "36" 14 | #define TERM_FG_GREY "90" 15 | #define TERM_FG_BRIGHT_RED "91" 16 | #define TERM_FG_BRIGHT_GREEN "92" 17 | #define TERM_FG_BRIGHT_YELLOW "93" 18 | #define TERM_FG_BRIGHT_BLUE "94" 19 | #define TERM_FG_BRIGHT_MAGENTA "95" 20 | #define TERM_FG_BRIGHT_CYAN "96" 21 | 22 | #define TERM_BG_RED "41" 23 | #define TERM_BG_GREEN "42" 24 | #define TERM_BG_YELLOW "43" 25 | #define TERM_BG_BLUE "44" 26 | #define TERM_BG_MAGENTA "45" 27 | #define TERM_BG_CYAN "46" 28 | #define TERM_BG_BRIGHT_RED "101" 29 | #define TERM_BG_BRIGHT_GREEN "102" 30 | #define TERM_BG_BRIGHT_YELLOW "103" 31 | #define TERM_BG_BRIGHT_BLUE "104" 32 | #define TERM_BG_BRIGHT_MAGENTA "105" 33 | #define TERM_BG_BRIGHT_CYAN "106" 34 | 35 | // Terminal cursor controls 36 | #define TERM_CURSOR_HIDE "\033[?25l" 37 | #define TERM_CURSOR_SHOW "\033[?25h" 38 | 39 | typedef uint8_t term_cursor_dir_e; 40 | #define TERM_CURSOR_UP 'A' 41 | #define TERM_CURSOR_DOWN 'B' 42 | #define TERM_CURSOR_RIGHT 'C' 43 | #define TERM_CURSOR_LEFT 'D' 44 | 45 | void term_set_color(char *color); 46 | void term_cursor_move(term_cursor_dir_e dir, uint8_t steps); 47 | void term_cursor_set_x(uint8_t x); 48 | void term_cursor_set_pos(uint8_t x, uint8_t y); 49 | void term_cursor_set_vis(bool visible); 50 | void term_clear(); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /firmware/vectors_08.s: -------------------------------------------------------------------------------- 1 | .align 2 2 | 3 | .section .vectors, "a" 4 | 5 | .long 0x380000 | Initial stack pointer 6 | .long _start | Program counter value 7 | -------------------------------------------------------------------------------- /firmware/vectors_10.s: -------------------------------------------------------------------------------- 1 | .align 2 2 | 3 | .section .vectors, "a" 4 | 5 | .long 0xF00000 | Initial stack pointer 6 | .long _start | Program counter value 7 | -------------------------------------------------------------------------------- /firmware/vectors_30.s: -------------------------------------------------------------------------------- 1 | .align 2 2 | 3 | .section .vectors, "a" 4 | 5 | .long 0x80000 | Initial stack pointer 6 | .long _start | Program counter value 7 | -------------------------------------------------------------------------------- /hardware/AP1084.kicad_sym: -------------------------------------------------------------------------------- 1 | (kicad_symbol_lib 2 | (version 20231120) 3 | (generator "kicad_symbol_editor") 4 | (generator_version "8.0") 5 | (symbol "AP1084" 6 | (exclude_from_sim no) 7 | (in_bom yes) 8 | (on_board yes) 9 | (property "Reference" "U" 10 | (at -1.27 2.54 0) 11 | (effects 12 | (font 13 | (size 1.27 1.27) 14 | ) 15 | ) 16 | ) 17 | (property "Value" "" 18 | (at 0 0 0) 19 | (effects 20 | (font 21 | (size 1.27 1.27) 22 | ) 23 | ) 24 | ) 25 | (property "Footprint" "" 26 | (at 0 0 0) 27 | (effects 28 | (font 29 | (size 1.27 1.27) 30 | ) 31 | (hide yes) 32 | ) 33 | ) 34 | (property "Datasheet" "" 35 | (at 0 0 0) 36 | (effects 37 | (font 38 | (size 1.27 1.27) 39 | ) 40 | (hide yes) 41 | ) 42 | ) 43 | (property "Description" "" 44 | (at 0 0 0) 45 | (effects 46 | (font 47 | (size 1.27 1.27) 48 | ) 49 | (hide yes) 50 | ) 51 | ) 52 | (symbol "AP1084_0_1" 53 | (rectangle 54 | (start -6.35 3.81) 55 | (end 6.35 -3.81) 56 | (stroke 57 | (width 0) 58 | (type default) 59 | ) 60 | (fill 61 | (type none) 62 | ) 63 | ) 64 | ) 65 | (symbol "AP1084_1_1" 66 | (pin power_in line 67 | (at 0 -6.35 90) 68 | (length 2.54) 69 | (name "GND" 70 | (effects 71 | (font 72 | (size 1.27 1.27) 73 | ) 74 | ) 75 | ) 76 | (number "1" 77 | (effects 78 | (font 79 | (size 1.27 1.27) 80 | ) 81 | ) 82 | ) 83 | ) 84 | (pin power_out line 85 | (at 8.89 0 180) 86 | (length 2.54) 87 | (name "Vout" 88 | (effects 89 | (font 90 | (size 1.27 1.27) 91 | ) 92 | ) 93 | ) 94 | (number "2" 95 | (effects 96 | (font 97 | (size 1.27 1.27) 98 | ) 99 | ) 100 | ) 101 | ) 102 | (pin power_in line 103 | (at -8.89 0 0) 104 | (length 2.54) 105 | (name "Vin" 106 | (effects 107 | (font 108 | (size 1.27 1.27) 109 | ) 110 | ) 111 | ) 112 | (number "3" 113 | (effects 114 | (font 115 | (size 1.27 1.27) 116 | ) 117 | ) 118 | ) 119 | ) 120 | ) 121 | ) 122 | ) 123 | -------------------------------------------------------------------------------- /hardware/mack-10-proto/mackerel-10-dram/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | (lib (name "mackerel")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel.pretty")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /hardware/mack-10-proto/mackerel-10-ide/mackerel-10-ide.kicad_pro: -------------------------------------------------------------------------------- 1 | { 2 | "board": { 3 | "3dviewports": [], 4 | "design_settings": { 5 | "defaults": { 6 | "apply_defaults_to_fp_fields": false, 7 | "apply_defaults_to_fp_shapes": false, 8 | "apply_defaults_to_fp_text": false, 9 | "board_outline_line_width": 0.05, 10 | "copper_line_width": 0.2, 11 | "copper_text_italic": false, 12 | "copper_text_size_h": 1.5, 13 | "copper_text_size_v": 1.5, 14 | "copper_text_thickness": 0.3, 15 | "copper_text_upright": false, 16 | "courtyard_line_width": 0.05, 17 | "dimension_precision": 4, 18 | "dimension_units": 3, 19 | "dimensions": { 20 | "arrow_length": 1270000, 21 | "extension_offset": 500000, 22 | "keep_text_aligned": true, 23 | "suppress_zeroes": false, 24 | "text_position": 0, 25 | "units_format": 1 26 | }, 27 | "fab_line_width": 0.1, 28 | "fab_text_italic": false, 29 | "fab_text_size_h": 1.0, 30 | "fab_text_size_v": 1.0, 31 | "fab_text_thickness": 0.15, 32 | "fab_text_upright": false, 33 | "other_line_width": 0.1, 34 | "other_text_italic": false, 35 | "other_text_size_h": 1.0, 36 | "other_text_size_v": 1.0, 37 | "other_text_thickness": 0.15, 38 | "other_text_upright": false, 39 | "pads": { 40 | "drill": 0.762, 41 | "height": 1.524, 42 | "width": 1.524 43 | }, 44 | "silk_line_width": 0.1, 45 | "silk_text_italic": false, 46 | "silk_text_size_h": 1.0, 47 | "silk_text_size_v": 1.0, 48 | "silk_text_thickness": 0.1, 49 | "silk_text_upright": false, 50 | "zones": { 51 | "min_clearance": 0.5 52 | } 53 | }, 54 | "diff_pair_dimensions": [], 55 | "drc_exclusions": [], 56 | "meta": { 57 | "version": 2 58 | }, 59 | "rule_severities": { 60 | "annular_width": "error", 61 | "clearance": "error", 62 | "connection_width": "warning", 63 | "copper_edge_clearance": "error", 64 | "copper_sliver": "warning", 65 | "courtyards_overlap": "error", 66 | "diff_pair_gap_out_of_range": "error", 67 | "diff_pair_uncoupled_length_too_long": "error", 68 | "drill_out_of_range": "error", 69 | "duplicate_footprints": "warning", 70 | "extra_footprint": "warning", 71 | "footprint": "error", 72 | "footprint_symbol_mismatch": "warning", 73 | "footprint_type_mismatch": "ignore", 74 | "hole_clearance": "error", 75 | "hole_near_hole": "error", 76 | "holes_co_located": "warning", 77 | "invalid_outline": "error", 78 | "isolated_copper": "warning", 79 | "item_on_disabled_layer": "error", 80 | "items_not_allowed": "error", 81 | "length_out_of_range": "error", 82 | "lib_footprint_issues": "warning", 83 | "lib_footprint_mismatch": "warning", 84 | "malformed_courtyard": "error", 85 | "microvia_drill_out_of_range": "error", 86 | "missing_courtyard": "ignore", 87 | "missing_footprint": "warning", 88 | "net_conflict": "warning", 89 | "npth_inside_courtyard": "ignore", 90 | "padstack": "warning", 91 | "pth_inside_courtyard": "ignore", 92 | "shorting_items": "error", 93 | "silk_edge_clearance": "warning", 94 | "silk_over_copper": "warning", 95 | "silk_overlap": "warning", 96 | "skew_out_of_range": "error", 97 | "solder_mask_bridge": "error", 98 | "starved_thermal": "error", 99 | "text_height": "warning", 100 | "text_thickness": "warning", 101 | "through_hole_pad_without_hole": "error", 102 | "too_many_vias": "error", 103 | "track_dangling": "warning", 104 | "track_width": "error", 105 | "tracks_crossing": "error", 106 | "unconnected_items": "error", 107 | "unresolved_variable": "error", 108 | "via_dangling": "warning", 109 | "zones_intersect": "error" 110 | }, 111 | "rules": { 112 | "max_error": 0.005, 113 | "min_clearance": 0.0, 114 | "min_connection": 0.0, 115 | "min_copper_edge_clearance": 0.5, 116 | "min_hole_clearance": 0.25, 117 | "min_hole_to_hole": 0.25, 118 | "min_microvia_diameter": 0.2, 119 | "min_microvia_drill": 0.1, 120 | "min_resolved_spokes": 2, 121 | "min_silk_clearance": 0.0, 122 | "min_text_height": 0.8, 123 | "min_text_thickness": 0.08, 124 | "min_through_hole_diameter": 0.3, 125 | "min_track_width": 0.0, 126 | "min_via_annular_width": 0.1, 127 | "min_via_diameter": 0.5, 128 | "solder_mask_to_copper_clearance": 0.0, 129 | "use_height_for_length_calcs": true 130 | }, 131 | "teardrop_options": [ 132 | { 133 | "td_onpadsmd": true, 134 | "td_onroundshapesonly": false, 135 | "td_ontrackend": false, 136 | "td_onviapad": true 137 | } 138 | ], 139 | "teardrop_parameters": [ 140 | { 141 | "td_allow_use_two_tracks": true, 142 | "td_curve_segcount": 0, 143 | "td_height_ratio": 1.0, 144 | "td_length_ratio": 0.5, 145 | "td_maxheight": 2.0, 146 | "td_maxlen": 1.0, 147 | "td_on_pad_in_zone": false, 148 | "td_target_name": "td_round_shape", 149 | "td_width_to_size_filter_ratio": 0.9 150 | }, 151 | { 152 | "td_allow_use_two_tracks": true, 153 | "td_curve_segcount": 0, 154 | "td_height_ratio": 1.0, 155 | "td_length_ratio": 0.5, 156 | "td_maxheight": 2.0, 157 | "td_maxlen": 1.0, 158 | "td_on_pad_in_zone": false, 159 | "td_target_name": "td_rect_shape", 160 | "td_width_to_size_filter_ratio": 0.9 161 | }, 162 | { 163 | "td_allow_use_two_tracks": true, 164 | "td_curve_segcount": 0, 165 | "td_height_ratio": 1.0, 166 | "td_length_ratio": 0.5, 167 | "td_maxheight": 2.0, 168 | "td_maxlen": 1.0, 169 | "td_on_pad_in_zone": false, 170 | "td_target_name": "td_track_end", 171 | "td_width_to_size_filter_ratio": 0.9 172 | } 173 | ], 174 | "track_widths": [], 175 | "tuning_pattern_settings": { 176 | "diff_pair_defaults": { 177 | "corner_radius_percentage": 80, 178 | "corner_style": 1, 179 | "max_amplitude": 1.0, 180 | "min_amplitude": 0.2, 181 | "single_sided": false, 182 | "spacing": 1.0 183 | }, 184 | "diff_pair_skew_defaults": { 185 | "corner_radius_percentage": 80, 186 | "corner_style": 1, 187 | "max_amplitude": 1.0, 188 | "min_amplitude": 0.2, 189 | "single_sided": false, 190 | "spacing": 0.6 191 | }, 192 | "single_track_defaults": { 193 | "corner_radius_percentage": 80, 194 | "corner_style": 1, 195 | "max_amplitude": 1.0, 196 | "min_amplitude": 0.2, 197 | "single_sided": false, 198 | "spacing": 0.6 199 | } 200 | }, 201 | "via_dimensions": [], 202 | "zones_allow_external_fillets": false 203 | }, 204 | "ipc2581": { 205 | "dist": "", 206 | "distpn": "", 207 | "internal_id": "", 208 | "mfg": "", 209 | "mpn": "" 210 | }, 211 | "layer_presets": [], 212 | "viewports": [] 213 | }, 214 | "boards": [], 215 | "cvpcb": { 216 | "equivalence_files": [] 217 | }, 218 | "erc": { 219 | "erc_exclusions": [], 220 | "meta": { 221 | "version": 0 222 | }, 223 | "pin_map": [ 224 | [ 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 0, 231 | 1, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 2 237 | ], 238 | [ 239 | 0, 240 | 2, 241 | 0, 242 | 1, 243 | 0, 244 | 0, 245 | 1, 246 | 0, 247 | 2, 248 | 2, 249 | 2, 250 | 2 251 | ], 252 | [ 253 | 0, 254 | 0, 255 | 0, 256 | 0, 257 | 0, 258 | 0, 259 | 1, 260 | 0, 261 | 1, 262 | 0, 263 | 1, 264 | 2 265 | ], 266 | [ 267 | 0, 268 | 1, 269 | 0, 270 | 0, 271 | 0, 272 | 0, 273 | 1, 274 | 1, 275 | 2, 276 | 1, 277 | 1, 278 | 2 279 | ], 280 | [ 281 | 0, 282 | 0, 283 | 0, 284 | 0, 285 | 0, 286 | 0, 287 | 1, 288 | 0, 289 | 0, 290 | 0, 291 | 0, 292 | 2 293 | ], 294 | [ 295 | 0, 296 | 0, 297 | 0, 298 | 0, 299 | 0, 300 | 0, 301 | 0, 302 | 0, 303 | 0, 304 | 0, 305 | 0, 306 | 2 307 | ], 308 | [ 309 | 1, 310 | 1, 311 | 1, 312 | 1, 313 | 1, 314 | 0, 315 | 1, 316 | 1, 317 | 1, 318 | 1, 319 | 1, 320 | 2 321 | ], 322 | [ 323 | 0, 324 | 0, 325 | 0, 326 | 1, 327 | 0, 328 | 0, 329 | 1, 330 | 0, 331 | 0, 332 | 0, 333 | 0, 334 | 2 335 | ], 336 | [ 337 | 0, 338 | 2, 339 | 1, 340 | 2, 341 | 0, 342 | 0, 343 | 1, 344 | 0, 345 | 2, 346 | 2, 347 | 2, 348 | 2 349 | ], 350 | [ 351 | 0, 352 | 2, 353 | 0, 354 | 1, 355 | 0, 356 | 0, 357 | 1, 358 | 0, 359 | 2, 360 | 0, 361 | 0, 362 | 2 363 | ], 364 | [ 365 | 0, 366 | 2, 367 | 1, 368 | 1, 369 | 0, 370 | 0, 371 | 1, 372 | 0, 373 | 2, 374 | 0, 375 | 0, 376 | 2 377 | ], 378 | [ 379 | 2, 380 | 2, 381 | 2, 382 | 2, 383 | 2, 384 | 2, 385 | 2, 386 | 2, 387 | 2, 388 | 2, 389 | 2, 390 | 2 391 | ] 392 | ], 393 | "rule_severities": { 394 | "bus_definition_conflict": "error", 395 | "bus_entry_needed": "error", 396 | "bus_to_bus_conflict": "error", 397 | "bus_to_net_conflict": "error", 398 | "conflicting_netclasses": "error", 399 | "different_unit_footprint": "error", 400 | "different_unit_net": "error", 401 | "duplicate_reference": "error", 402 | "duplicate_sheet_names": "error", 403 | "endpoint_off_grid": "warning", 404 | "extra_units": "error", 405 | "global_label_dangling": "warning", 406 | "hier_label_mismatch": "error", 407 | "label_dangling": "error", 408 | "lib_symbol_issues": "warning", 409 | "missing_bidi_pin": "warning", 410 | "missing_input_pin": "warning", 411 | "missing_power_pin": "error", 412 | "missing_unit": "warning", 413 | "multiple_net_names": "warning", 414 | "net_not_bus_member": "warning", 415 | "no_connect_connected": "warning", 416 | "no_connect_dangling": "warning", 417 | "pin_not_connected": "error", 418 | "pin_not_driven": "error", 419 | "pin_to_pin": "warning", 420 | "power_pin_not_driven": "error", 421 | "similar_labels": "warning", 422 | "simulation_model_issue": "ignore", 423 | "unannotated": "error", 424 | "unit_value_mismatch": "error", 425 | "unresolved_variable": "error", 426 | "wire_dangling": "error" 427 | } 428 | }, 429 | "libraries": { 430 | "pinned_footprint_libs": [], 431 | "pinned_symbol_libs": [] 432 | }, 433 | "meta": { 434 | "filename": "mackerel-10-ide.kicad_pro", 435 | "version": 1 436 | }, 437 | "net_settings": { 438 | "classes": [ 439 | { 440 | "bus_width": 12, 441 | "clearance": 0.2, 442 | "diff_pair_gap": 0.25, 443 | "diff_pair_via_gap": 0.25, 444 | "diff_pair_width": 0.2, 445 | "line_style": 0, 446 | "microvia_diameter": 0.3, 447 | "microvia_drill": 0.1, 448 | "name": "Default", 449 | "pcb_color": "rgba(0, 0, 0, 0.000)", 450 | "schematic_color": "rgba(0, 0, 0, 0.000)", 451 | "track_width": 0.2, 452 | "via_diameter": 0.6, 453 | "via_drill": 0.3, 454 | "wire_width": 6 455 | } 456 | ], 457 | "meta": { 458 | "version": 3 459 | }, 460 | "net_colors": null, 461 | "netclass_assignments": null, 462 | "netclass_patterns": [] 463 | }, 464 | "pcbnew": { 465 | "last_paths": { 466 | "gencad": "", 467 | "idf": "", 468 | "netlist": "", 469 | "plot": "", 470 | "pos_files": "", 471 | "specctra_dsn": "", 472 | "step": "", 473 | "svg": "", 474 | "vrml": "" 475 | }, 476 | "page_layout_descr_file": "" 477 | }, 478 | "schematic": { 479 | "annotate_start_num": 0, 480 | "bom_export_filename": "", 481 | "bom_fmt_presets": [], 482 | "bom_fmt_settings": { 483 | "field_delimiter": ",", 484 | "keep_line_breaks": false, 485 | "keep_tabs": false, 486 | "name": "CSV", 487 | "ref_delimiter": ",", 488 | "ref_range_delimiter": "", 489 | "string_delimiter": "\"" 490 | }, 491 | "bom_presets": [], 492 | "bom_settings": { 493 | "exclude_dnp": false, 494 | "fields_ordered": [ 495 | { 496 | "group_by": false, 497 | "label": "Reference", 498 | "name": "Reference", 499 | "show": true 500 | }, 501 | { 502 | "group_by": true, 503 | "label": "Value", 504 | "name": "Value", 505 | "show": true 506 | }, 507 | { 508 | "group_by": false, 509 | "label": "Datasheet", 510 | "name": "Datasheet", 511 | "show": true 512 | }, 513 | { 514 | "group_by": false, 515 | "label": "Footprint", 516 | "name": "Footprint", 517 | "show": true 518 | }, 519 | { 520 | "group_by": false, 521 | "label": "Qty", 522 | "name": "${QUANTITY}", 523 | "show": true 524 | }, 525 | { 526 | "group_by": true, 527 | "label": "DNP", 528 | "name": "${DNP}", 529 | "show": true 530 | } 531 | ], 532 | "filter_string": "", 533 | "group_symbols": true, 534 | "name": "Grouped By Value", 535 | "sort_asc": true, 536 | "sort_field": "Reference" 537 | }, 538 | "connection_grid_size": 50.0, 539 | "drawing": { 540 | "dashed_lines_dash_length_ratio": 12.0, 541 | "dashed_lines_gap_length_ratio": 3.0, 542 | "default_line_thickness": 6.0, 543 | "default_text_size": 50.0, 544 | "field_names": [], 545 | "intersheets_ref_own_page": false, 546 | "intersheets_ref_prefix": "", 547 | "intersheets_ref_short": false, 548 | "intersheets_ref_show": false, 549 | "intersheets_ref_suffix": "", 550 | "junction_size_choice": 3, 551 | "label_size_ratio": 0.375, 552 | "operating_point_overlay_i_precision": 3, 553 | "operating_point_overlay_i_range": "~A", 554 | "operating_point_overlay_v_precision": 3, 555 | "operating_point_overlay_v_range": "~V", 556 | "overbar_offset_ratio": 1.23, 557 | "pin_symbol_size": 25.0, 558 | "text_offset_ratio": 0.15 559 | }, 560 | "legacy_lib_dir": "", 561 | "legacy_lib_list": [], 562 | "meta": { 563 | "version": 1 564 | }, 565 | "net_format_name": "", 566 | "page_layout_descr_file": "", 567 | "plot_directory": "", 568 | "spice_current_sheet_as_root": false, 569 | "spice_external_command": "spice \"%I\"", 570 | "spice_model_current_sheet_as_root": true, 571 | "spice_save_all_currents": false, 572 | "spice_save_all_dissipations": false, 573 | "spice_save_all_voltages": false, 574 | "subpart_first_id": 65, 575 | "subpart_id_separator": 0 576 | }, 577 | "sheets": [ 578 | [ 579 | "38207e99-4b7f-4c84-9dcd-59c75f1de58f", 580 | "Root" 581 | ] 582 | ], 583 | "text_variables": {} 584 | } 585 | -------------------------------------------------------------------------------- /hardware/mack-10-proto/mackerel-10-v1/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | (lib (name "mackerel")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel.pretty")(options "")(descr "")) 4 | (lib (name "herring")(type "KiCad")(uri "/home/colin/Workspace/herring-6502/hardware/herring.pretty")(options "")(descr "")) 5 | ) 6 | -------------------------------------------------------------------------------- /hardware/mack-10-proto/mackerel-10-v1/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (version 7) 3 | (lib (name "mackerel-68k-symbols")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel-68k-symbols.kicad_sym")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /hardware/mackerel-08-v1/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | ) 4 | -------------------------------------------------------------------------------- /hardware/mackerel-08-v1/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (version 7) 3 | (lib (name "mackerel-68k-symbols")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel-68k-symbols.kicad_sym")(options "")(descr "")) 4 | (lib (name "AP1084")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/AP1084.kicad_sym")(options "")(descr "")) 5 | ) 6 | -------------------------------------------------------------------------------- /hardware/mackerel-10-v1/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | (lib (name "mackerel")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel.pretty")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /hardware/mackerel-10-v1/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (version 7) 3 | (lib (name "mackerel-68k-symbols")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel-68k-symbols.kicad_sym")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /hardware/mackerel-30-proto/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | (lib (name "mackerel")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel.pretty")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /hardware/mackerel-30-proto/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (version 7) 3 | (lib (name "mackerel-68k-symbols")(type "KiCad")(uri "/home/colin/Workspace/mackerel-68k/hardware/mackerel-68k-symbols.kicad_sym")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /hardware/mackerel.pretty/SIMM-30.kicad_mod: -------------------------------------------------------------------------------- 1 | (footprint "SIMM-30" 2 | (version 20240108) 3 | (generator "pcbnew") 4 | (generator_version "8.0") 5 | (layer "F.Cu") 6 | (property "Reference" "REF**" 7 | (at -38.75 -5.75 180) 8 | (unlocked yes) 9 | (layer "F.SilkS") 10 | (uuid "6cc26923-8165-468e-863e-bac6fb1ec12c") 11 | (effects 12 | (font 13 | (size 1 1) 14 | (thickness 0.1) 15 | ) 16 | ) 17 | ) 18 | (property "Value" "SIMM-30" 19 | (at -38.5 2 0) 20 | (unlocked yes) 21 | (layer "F.Fab") 22 | (uuid "61ef1861-5943-45db-8560-96c180868474") 23 | (effects 24 | (font 25 | (size 1 1) 26 | (thickness 0.15) 27 | ) 28 | ) 29 | ) 30 | (property "Footprint" "" 31 | (at 0 0 0) 32 | (unlocked yes) 33 | (layer "F.Fab") 34 | (hide yes) 35 | (uuid "118114f1-1277-49a2-a4fc-a2cc78713277") 36 | (effects 37 | (font 38 | (size 1 1) 39 | (thickness 0.15) 40 | ) 41 | ) 42 | ) 43 | (property "Datasheet" "" 44 | (at 0 0 0) 45 | (unlocked yes) 46 | (layer "F.Fab") 47 | (hide yes) 48 | (uuid "e0ade148-ab82-4e09-969e-aea8a128c312") 49 | (effects 50 | (font 51 | (size 1 1) 52 | (thickness 0.15) 53 | ) 54 | ) 55 | ) 56 | (property "Description" "" 57 | (at 0 0 0) 58 | (unlocked yes) 59 | (layer "F.Fab") 60 | (hide yes) 61 | (uuid "10114809-31dc-4809-9808-cbbb3d1ed59a") 62 | (effects 63 | (font 64 | (size 1 1) 65 | (thickness 0.15) 66 | ) 67 | ) 68 | ) 69 | (attr through_hole) 70 | (fp_line 71 | (start -86 4) 72 | (end -86 10.5) 73 | (stroke 74 | (width 0.1) 75 | (type default) 76 | ) 77 | (layer "F.SilkS") 78 | (uuid "e97a4f5e-2fa6-4294-af15-e8a422c05f91") 79 | ) 80 | (fp_line 81 | (start -79.5 4) 82 | (end -79.5 10.5) 83 | (stroke 84 | (width 0.1) 85 | (type default) 86 | ) 87 | (layer "F.SilkS") 88 | (uuid "bab2e4b1-7fd2-4fda-a09f-292bb224c526") 89 | ) 90 | (fp_line 91 | (start -76 -4.75) 92 | (end 2.5 -4.75) 93 | (stroke 94 | (width 0.1) 95 | (type default) 96 | ) 97 | (layer "F.SilkS") 98 | (uuid "44f0c5f3-4cab-4c19-837f-c9aebebb848f") 99 | ) 100 | (fp_line 101 | (start -76 -3.5) 102 | (end -86 -3.5) 103 | (stroke 104 | (width 0.1) 105 | (type default) 106 | ) 107 | (layer "F.SilkS") 108 | (uuid "bc14454a-2f8d-4534-921b-9851f572ef30") 109 | ) 110 | (fp_line 111 | (start -76 -3.5) 112 | (end -76 -4.75) 113 | (stroke 114 | (width 0.1) 115 | (type default) 116 | ) 117 | (layer "F.SilkS") 118 | (uuid "8e721ab5-0459-4649-883e-80db9ada3547") 119 | ) 120 | (fp_line 121 | (start 2.5 -4.75) 122 | (end 2.5 -3.5) 123 | (stroke 124 | (width 0.1) 125 | (type default) 126 | ) 127 | (layer "F.SilkS") 128 | (uuid "8f9ba9bc-406a-40d9-ae26-7a60d686900c") 129 | ) 130 | (fp_line 131 | (start 2.5 -3.5) 132 | (end 12 -3.5) 133 | (stroke 134 | (width 0.1) 135 | (type default) 136 | ) 137 | (layer "F.SilkS") 138 | (uuid "828164e3-ae6c-446e-a953-a4ae3c6bf021") 139 | ) 140 | (fp_line 141 | (start 5.5 4) 142 | (end 5.5 10.5) 143 | (stroke 144 | (width 0.1) 145 | (type default) 146 | ) 147 | (layer "F.SilkS") 148 | (uuid "6e2f1fc0-9821-48a7-af6a-7b8805ac9e82") 149 | ) 150 | (fp_line 151 | (start 12 4) 152 | (end 12 10.5) 153 | (stroke 154 | (width 0.1) 155 | (type default) 156 | ) 157 | (layer "F.SilkS") 158 | (uuid "29bf77d7-257c-477e-aa70-a195e52917b5") 159 | ) 160 | (fp_rect 161 | (start -86 -3.5) 162 | (end -86 4) 163 | (stroke 164 | (width 0.1) 165 | (type default) 166 | ) 167 | (fill none) 168 | (layer "F.SilkS") 169 | (uuid "1562b96f-a6b6-4994-bcf4-e64793519ec1") 170 | ) 171 | (fp_rect 172 | (start -86 10.5) 173 | (end -79.5 10.5) 174 | (stroke 175 | (width 0.1) 176 | (type default) 177 | ) 178 | (fill none) 179 | (layer "F.SilkS") 180 | (uuid "22add9f8-6ff7-41fd-a43c-ad9db17ab5f9") 181 | ) 182 | (fp_rect 183 | (start -79.5 4) 184 | (end 5.5 4) 185 | (stroke 186 | (width 0.1) 187 | (type default) 188 | ) 189 | (fill none) 190 | (layer "F.SilkS") 191 | (uuid "e9568e79-23ec-42ae-8d52-2f0afcfd9fbd") 192 | ) 193 | (fp_rect 194 | (start 5.5 10.5) 195 | (end 12 10.5) 196 | (stroke 197 | (width 0.1) 198 | (type default) 199 | ) 200 | (fill none) 201 | (layer "F.SilkS") 202 | (uuid "2cec4cfe-2ee5-49b6-a46f-eb7d07882c02") 203 | ) 204 | (fp_rect 205 | (start 12 -3.5) 206 | (end 12 4) 207 | (stroke 208 | (width 0.1) 209 | (type default) 210 | ) 211 | (fill none) 212 | (layer "F.SilkS") 213 | (uuid "60241319-e5a8-4d8d-b0c0-ae5fb104a539") 214 | ) 215 | (fp_circle 216 | (center -83.185 0) 217 | (end -81.915 0) 218 | (stroke 219 | (width 0.05) 220 | (type default) 221 | ) 222 | (fill none) 223 | (layer "Edge.Cuts") 224 | (uuid "fc5cab27-ab4c-4d5c-8b08-bd206a6c58a5") 225 | ) 226 | (fp_circle 227 | (center 9.525 0) 228 | (end 10.4775 0) 229 | (stroke 230 | (width 0.05) 231 | (type default) 232 | ) 233 | (fill none) 234 | (layer "Edge.Cuts") 235 | (uuid "0f0a4f52-23bf-475d-8c6e-c25aa412b6a5") 236 | ) 237 | (fp_text user "${REFERENCE}" 238 | (at -38.5 -2 0) 239 | (unlocked yes) 240 | (layer "F.Fab") 241 | (uuid "4f13abfd-21bd-48e1-8ada-affbf12e490b") 242 | (effects 243 | (font 244 | (size 1 1) 245 | (thickness 0.15) 246 | ) 247 | ) 248 | ) 249 | (pad "1" thru_hole rect 250 | (at 0 0) 251 | (size 1.524 1.524) 252 | (drill 0.762) 253 | (layers "*.Cu" "*.Mask") 254 | (remove_unused_layers no) 255 | (uuid "a0cdc277-ab8a-4d14-aa62-ea2bdd01c04f") 256 | ) 257 | (pad "2" thru_hole circle 258 | (at -2.54 0) 259 | (size 1.524 1.524) 260 | (drill 0.762) 261 | (layers "*.Cu" "*.Mask") 262 | (remove_unused_layers no) 263 | (uuid "e5f235be-2d4c-49e6-92d8-1f7ad24050e0") 264 | ) 265 | (pad "3" thru_hole circle 266 | (at -5.08 0) 267 | (size 1.524 1.524) 268 | (drill 0.762) 269 | (layers "*.Cu" "*.Mask") 270 | (remove_unused_layers no) 271 | (uuid "5bbe2552-2d5f-421c-a556-8734da19ea39") 272 | ) 273 | (pad "4" thru_hole circle 274 | (at -7.62 0) 275 | (size 1.524 1.524) 276 | (drill 0.762) 277 | (layers "*.Cu" "*.Mask") 278 | (remove_unused_layers no) 279 | (uuid "a963ac90-554b-49ba-a55f-819f790fc3d6") 280 | ) 281 | (pad "5" thru_hole circle 282 | (at -10.16 0) 283 | (size 1.524 1.524) 284 | (drill 0.762) 285 | (layers "*.Cu" "*.Mask") 286 | (remove_unused_layers no) 287 | (uuid "22a4e2bc-1106-4ffb-b3dc-e83799c28aac") 288 | ) 289 | (pad "6" thru_hole circle 290 | (at -12.7 0) 291 | (size 1.524 1.524) 292 | (drill 0.762) 293 | (layers "*.Cu" "*.Mask") 294 | (remove_unused_layers no) 295 | (uuid "ce70e541-b30d-43b1-a5c0-4461c0a4a03e") 296 | ) 297 | (pad "7" thru_hole circle 298 | (at -15.24 0) 299 | (size 1.524 1.524) 300 | (drill 0.762) 301 | (layers "*.Cu" "*.Mask") 302 | (remove_unused_layers no) 303 | (uuid "7392b67e-07bc-4a03-8202-3f2e3b7985f1") 304 | ) 305 | (pad "8" thru_hole circle 306 | (at -17.78 0) 307 | (size 1.524 1.524) 308 | (drill 0.762) 309 | (layers "*.Cu" "*.Mask") 310 | (remove_unused_layers no) 311 | (uuid "3516a98a-f715-4372-bc5e-4722a1ca073e") 312 | ) 313 | (pad "9" thru_hole circle 314 | (at -20.32 0) 315 | (size 1.524 1.524) 316 | (drill 0.762) 317 | (layers "*.Cu" "*.Mask") 318 | (remove_unused_layers no) 319 | (uuid "3a206229-f9d7-4317-895e-993b7a8ecff5") 320 | ) 321 | (pad "10" thru_hole circle 322 | (at -22.86 0) 323 | (size 1.524 1.524) 324 | (drill 0.762) 325 | (layers "*.Cu" "*.Mask") 326 | (remove_unused_layers no) 327 | (uuid "b69f9509-eb17-4a32-b705-6321955da8d9") 328 | ) 329 | (pad "11" thru_hole circle 330 | (at -25.4 0) 331 | (size 1.524 1.524) 332 | (drill 0.762) 333 | (layers "*.Cu" "*.Mask") 334 | (remove_unused_layers no) 335 | (uuid "8a1892b1-f804-4d9c-90f1-901a86974d1a") 336 | ) 337 | (pad "12" thru_hole circle 338 | (at -27.94 0) 339 | (size 1.524 1.524) 340 | (drill 0.762) 341 | (layers "*.Cu" "*.Mask") 342 | (remove_unused_layers no) 343 | (uuid "aab6dcdf-6b12-4b74-b6cd-a02a84e1b34b") 344 | ) 345 | (pad "13" thru_hole circle 346 | (at -30.48 0) 347 | (size 1.524 1.524) 348 | (drill 0.762) 349 | (layers "*.Cu" "*.Mask") 350 | (remove_unused_layers no) 351 | (uuid "39ec6b50-4ed0-4533-bdd7-e4786d178596") 352 | ) 353 | (pad "14" thru_hole circle 354 | (at -33.02 0) 355 | (size 1.524 1.524) 356 | (drill 0.762) 357 | (layers "*.Cu" "*.Mask") 358 | (remove_unused_layers no) 359 | (uuid "ceb2096e-dfa2-4c6f-9e53-710d20b2e1f3") 360 | ) 361 | (pad "15" thru_hole circle 362 | (at -35.56 0) 363 | (size 1.524 1.524) 364 | (drill 0.762) 365 | (layers "*.Cu" "*.Mask") 366 | (remove_unused_layers no) 367 | (uuid "ecc97409-f7b4-4d93-ada3-d4f2ccb2f71a") 368 | ) 369 | (pad "16" thru_hole circle 370 | (at -38.1 0) 371 | (size 1.524 1.524) 372 | (drill 0.762) 373 | (layers "*.Cu" "*.Mask") 374 | (remove_unused_layers no) 375 | (uuid "dab16296-d49c-412f-b2f3-ce56649a52d4") 376 | ) 377 | (pad "17" thru_hole circle 378 | (at -40.64 0) 379 | (size 1.524 1.524) 380 | (drill 0.762) 381 | (layers "*.Cu" "*.Mask") 382 | (remove_unused_layers no) 383 | (uuid "c226a12d-2249-42a7-9593-b410e9002812") 384 | ) 385 | (pad "18" thru_hole circle 386 | (at -43.18 0) 387 | (size 1.524 1.524) 388 | (drill 0.762) 389 | (layers "*.Cu" "*.Mask") 390 | (remove_unused_layers no) 391 | (uuid "65975f65-3e75-4fe5-8810-af771acf3ecc") 392 | ) 393 | (pad "19" thru_hole circle 394 | (at -45.72 0) 395 | (size 1.524 1.524) 396 | (drill 0.762) 397 | (layers "*.Cu" "*.Mask") 398 | (remove_unused_layers no) 399 | (uuid "5de5caaa-84cd-4b53-8a86-b1d9b1c78bb9") 400 | ) 401 | (pad "20" thru_hole circle 402 | (at -48.26 0) 403 | (size 1.524 1.524) 404 | (drill 0.762) 405 | (layers "*.Cu" "*.Mask") 406 | (remove_unused_layers no) 407 | (uuid "134ee0a6-2467-4567-ab98-ab2faf0edcf3") 408 | ) 409 | (pad "21" thru_hole circle 410 | (at -50.8 0) 411 | (size 1.524 1.524) 412 | (drill 0.762) 413 | (layers "*.Cu" "*.Mask") 414 | (remove_unused_layers no) 415 | (uuid "a2747afc-c50b-4a70-b7d5-97a2163e9b38") 416 | ) 417 | (pad "22" thru_hole circle 418 | (at -53.34 0) 419 | (size 1.524 1.524) 420 | (drill 0.762) 421 | (layers "*.Cu" "*.Mask") 422 | (remove_unused_layers no) 423 | (uuid "9d1e8931-f25c-440d-acc3-cdcc07067f76") 424 | ) 425 | (pad "23" thru_hole circle 426 | (at -55.88 0) 427 | (size 1.524 1.524) 428 | (drill 0.762) 429 | (layers "*.Cu" "*.Mask") 430 | (remove_unused_layers no) 431 | (uuid "15113748-f0b8-4ce8-a334-1a3b1bbb2326") 432 | ) 433 | (pad "24" thru_hole circle 434 | (at -58.42 0) 435 | (size 1.524 1.524) 436 | (drill 0.762) 437 | (layers "*.Cu" "*.Mask") 438 | (remove_unused_layers no) 439 | (uuid "1005c2ed-beb2-4f40-9812-57bd0c7141d3") 440 | ) 441 | (pad "25" thru_hole circle 442 | (at -60.96 0) 443 | (size 1.524 1.524) 444 | (drill 0.762) 445 | (layers "*.Cu" "*.Mask") 446 | (remove_unused_layers no) 447 | (uuid "3f9a092e-1b2b-49dc-9efc-6d3c2010f3a7") 448 | ) 449 | (pad "26" thru_hole circle 450 | (at -63.5 0) 451 | (size 1.524 1.524) 452 | (drill 0.762) 453 | (layers "*.Cu" "*.Mask") 454 | (remove_unused_layers no) 455 | (uuid "0356200c-ed0d-41e5-9211-e87e11767930") 456 | ) 457 | (pad "27" thru_hole circle 458 | (at -66.04 0) 459 | (size 1.524 1.524) 460 | (drill 0.762) 461 | (layers "*.Cu" "*.Mask") 462 | (remove_unused_layers no) 463 | (uuid "74bd0811-e6fc-4923-a158-d0fa26929ee2") 464 | ) 465 | (pad "28" thru_hole circle 466 | (at -68.58 0) 467 | (size 1.524 1.524) 468 | (drill 0.762) 469 | (layers "*.Cu" "*.Mask") 470 | (remove_unused_layers no) 471 | (uuid "473c8474-4af3-4555-82d3-f42c7e4e4323") 472 | ) 473 | (pad "29" thru_hole circle 474 | (at -71.12 0) 475 | (size 1.524 1.524) 476 | (drill 0.762) 477 | (layers "*.Cu" "*.Mask") 478 | (remove_unused_layers no) 479 | (uuid "67ddc1ff-b66d-4f39-bacd-de3deeea3401") 480 | ) 481 | (pad "30" thru_hole circle 482 | (at -73.66 0) 483 | (size 1.524 1.524) 484 | (drill 0.762) 485 | (layers "*.Cu" "*.Mask") 486 | (remove_unused_layers no) 487 | (uuid "ad710132-39b1-4ec7-861f-e86bf71f2e5c") 488 | ) 489 | ) 490 | -------------------------------------------------------------------------------- /media/images/Screenshot_2024-11-12_15-42-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/Screenshot_2024-11-12_15-42-25.png -------------------------------------------------------------------------------- /media/images/cbr_refresh_sim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/cbr_refresh_sim.png -------------------------------------------------------------------------------- /media/images/cbr_refresh_timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/cbr_refresh_timing.png -------------------------------------------------------------------------------- /media/images/cbr_scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/cbr_scope.png -------------------------------------------------------------------------------- /media/images/dram-cbr-refresh-simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/dram-cbr-refresh-simulation.png -------------------------------------------------------------------------------- /media/images/dram_read_cycle_simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/dram_read_cycle_simulation.png -------------------------------------------------------------------------------- /media/images/dram_read_sim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/dram_read_sim.png -------------------------------------------------------------------------------- /media/images/dram_read_timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/dram_read_timing.png -------------------------------------------------------------------------------- /media/images/mack-10-linux-mem-layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mack-10-linux-mem-layout.png -------------------------------------------------------------------------------- /media/images/mack-10-v1-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mack-10-v1-render.png -------------------------------------------------------------------------------- /media/images/mack-10-v1-routing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mack-10-v1-routing.png -------------------------------------------------------------------------------- /media/images/mack-10-with-dram-controller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mack-10-with-dram-controller.jpg -------------------------------------------------------------------------------- /media/images/mack10_ide_proto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mack10_ide_proto.jpg -------------------------------------------------------------------------------- /media/images/mackerel-08-cpu-banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-cpu-banner.jpg -------------------------------------------------------------------------------- /media/images/mackerel-08-rev0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-rev0.jpg -------------------------------------------------------------------------------- /media/images/mackerel-08-rev1.1-assembled.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-rev1.1-assembled.jpg -------------------------------------------------------------------------------- /media/images/mackerel-08-rev1.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-rev1.1.jpg -------------------------------------------------------------------------------- /media/images/mackerel-08-sbc-v1-board-bringup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-sbc-v1-board-bringup.jpg -------------------------------------------------------------------------------- /media/images/mackerel-08-sbc-v1-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-sbc-v1-render.png -------------------------------------------------------------------------------- /media/images/mackerel-08-sbc-v1-routing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-sbc-v1-routing.png -------------------------------------------------------------------------------- /media/images/mackerel-08-sbc-v1.1-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-sbc-v1.1-render.png -------------------------------------------------------------------------------- /media/images/mackerel-08-v1.1_cropped.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-08-v1.1_cropped.jpg -------------------------------------------------------------------------------- /media/images/mackerel-10-proto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-10-proto.jpg -------------------------------------------------------------------------------- /media/images/mackerel-10-sbc-proto-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-10-sbc-proto-render.png -------------------------------------------------------------------------------- /media/images/mackerel-10-v1-with-drive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-10-v1-with-drive.jpg -------------------------------------------------------------------------------- /media/images/mackerel-10-v1.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-10-v1.2.jpg -------------------------------------------------------------------------------- /media/images/mackerel-10-v1_cropped.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-10-v1_cropped.jpg -------------------------------------------------------------------------------- /media/images/mackerel-30-v0.1-bringup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-30-v0.1-bringup.jpg -------------------------------------------------------------------------------- /media/images/mackerel-30-v0.1-routing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/mackerel-30-v0.1-routing.png -------------------------------------------------------------------------------- /media/images/uclinux-4.4-first-real-boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/media/images/uclinux-4.4-first-real-boot.png -------------------------------------------------------------------------------- /pld/.gitignore: -------------------------------------------------------------------------------- 1 | *.jed 2 | -------------------------------------------------------------------------------- /pld/mackerel-08/Makefile: -------------------------------------------------------------------------------- 1 | GALASM = galasm 2 | 3 | all: address_decoder.jed interrupt_decoder.jed dtack_decoder.jed 4 | 5 | %.jed: %.pld 6 | $(GALASM) $< 7 | 8 | clean: 9 | rm -f *.chp *.fus *.jed *.pin 10 | -------------------------------------------------------------------------------- /pld/mackerel-08/address_decoder.pld: -------------------------------------------------------------------------------- 1 | GAL22V10 2 | ADDR_DEC 3 | 4 | BOOT AS IACK A13 A14 A15 A16 A17 A18 A19 A20 GND 5 | A21 EXP RAM6 RAM5 RAM4 RAM3 RAM2 RAM1 RAM0 ROM DUART VCC 6 | 7 | /RAM0 = BOOT * /AS * IACK * /A21 * /A20 * /A19 8 | /RAM1 = BOOT * /AS * IACK * /A21 * /A20 * A19 9 | /RAM2 = BOOT * /AS * IACK * /A21 * A20 * /A19 10 | /RAM3 = BOOT * /AS * IACK * /A21 * A20 * A19 11 | /RAM4 = BOOT * /AS * IACK * A21 * /A20 * /A19 12 | /RAM5 = BOOT * /AS * IACK * A21 * /A20 * A19 13 | /RAM6 = BOOT * /AS * IACK * A21 * A20 * /A19 14 | 15 | /DUART = BOOT * /AS * IACK * A21 * A20 * A19 * A18 * A17 * A16 * A15 * A14 * /A13 16 | 17 | /EXP = BOOT * /AS * IACK * A21 * A20 * A19 * A18 * A17 * A16 * A15 * A14 * A13 18 | 19 | /ROM = /BOOT * /AS * IACK 20 | + BOOT * /AS * IACK * A21 * A20 * A19 * A18 * A17 * A16 * A15 * /A14 21 | + BOOT * /AS * IACK * A21 * A20 * A19 * A18 * A17 * A16 * /A15 22 | + BOOT * /AS * IACK * A21 * A20 * A19 * A18 * A17 * /A16 23 | + BOOT * /AS * IACK * A21 * A20 * A19 * A18 * /A17 24 | + BOOT * /AS * IACK * A21 * A20 * A19 * /A18 25 | 26 | DESCRIPTION 27 | Mackerel-08 v1 - Address Decoder 28 | 29 | RAM0-6 is mapped 0x000000 - 0x380000 (3.5MB total) after BOOT 30 | ROM is mapped 0x380000 - 0x3FC000 (496/512 KB usable) (mapped to 0x000000 at BOOT) 31 | DUART is mapped 0x3FC000 - 0x3FE000 (8KB) 32 | EXP is mapped 0x3FE000 - 0x400000 (8KB) 33 | -------------------------------------------------------------------------------- /pld/mackerel-08/dtack_decoder.pld: -------------------------------------------------------------------------------- 1 | GAL22V10 2 | DTAK_DEC 3 | 4 | NAS ROM DUART NC EXP DTKDUART DTKEXP IACKEXP IACKDUAR NC NC GND 5 | NC NC NC NC NC NC NC NC NC NC DTKCPU VCC 6 | 7 | /DTKCPU = /DUART * /DTKDUART 8 | + /EXP * /DTKEXP 9 | + /IACKDUAR * /DTKDUART 10 | + /IACKEXP * /DTKEXP 11 | + DUART * EXP 12 | 13 | DESCRIPTION 14 | Mackerel-08 v1 - DTACK Logic 15 | 16 | When either the DUART or the expansion bus are selected, pass their DTACK signals to the CPU, 17 | otherwise, assert /DTACK all the time 18 | 19 | When either the DUART or expansion bus IACK signals are asserted, pass their DTACK signal to the CPU 20 | -------------------------------------------------------------------------------- /pld/mackerel-08/interrupt_decoder.pld: -------------------------------------------------------------------------------- 1 | GAL22V10 2 | INTR_DEC 3 | 4 | FC0 FC1 FC2 AS IRQDUART IRQEXP NC NC NC A1 A2 GND 5 | A3 NC NC NC NAS IACKEXP IACKDUAR IPL2 IPL1 IPL0 IACK VCC 6 | 7 | NAS = /AS 8 | 9 | /IACK = FC0 * FC1 * FC2 10 | 11 | /IPL0 = /IRQDUART * IRQEXP 12 | /IPL1 = /IRQEXP 13 | IPL2 = VCC 14 | 15 | /IACKDUAR = /AS * FC0 * FC1 * FC2 * /A3 * /A2 * A1 16 | /IACKEXP = /AS * FC0 * FC1 * FC2 * /A3 * A2 * /A1 17 | 18 | DESCRIPTION 19 | Mackerel-08 v1 - Interrupt Logic 20 | 21 | NAS is an inverted /AS pin 22 | 23 | /IACK is active when FC pins are all high 24 | 25 | DUART interrupt is mapped to IRQ level 1 26 | EXP interrupt is mapped to IRQ level 2 27 | 28 | Return IACK signals match the input IRQ levels 29 | -------------------------------------------------------------------------------- /pld/mackerel-10/dram_controller/.gitignore: -------------------------------------------------------------------------------- 1 | # Working with Altera Quartus II (Q2) and do proper versioning is not that easy 2 | # but if you follow some rules it can be accomplished. :) 3 | # This file should be placed into the main directory where the .qpf file is 4 | # found. Generally Q2 throws all entities and so on in the main directory, but 5 | # you can place all stuff also in separate folders. This approach is followed 6 | # here. So when you create a new design create one or more folders where your 7 | # entities will be located and put a .gitignore in there that overrides the 8 | # ignores of this file, e.g. one single rule stating "!*" which allows now all 9 | # type of files. When you add a MegaFunction or another entity to your design, 10 | # simply add it to one of your private folders and Q2 will be happy and manage 11 | # everything quite good. When you want to do versioning of your generated 12 | # SOF/POF files, you can do this by redirecting the generated output to an own 13 | # folder. To do this go to: 14 | # "Assignments" 15 | # -> "Settings 16 | # -> "Compilation Process Settings" 17 | # -> "Save project output files in specified directory" 18 | # Now you can either place a .gitignore in the directory and allow the following 19 | # list of types: 20 | # !*.sof 21 | # !*.pof 22 | # or you create an own submodule in the folder to keep binary files out of your 23 | # design. 24 | 25 | # Need to keep all HDL files 26 | # *.vhd 27 | # *.v 28 | 29 | # ignore Quartus II generated files 30 | *_generation_script* 31 | *_inst.vhd 32 | *.bak 33 | *.cmp 34 | *.done 35 | *.eqn 36 | *.hex 37 | *.html 38 | *.jdi 39 | *.jpg 40 | # *.mif 41 | *.pin 42 | *.pof 43 | *.ptf.* 44 | *.qar 45 | *.qarlog 46 | *.qws 47 | *.rpt 48 | *.smsg 49 | *.sof 50 | *.sopc_builder 51 | *.summary 52 | *.tcl 53 | *.txt # Explicitly add any text files used 54 | *~ 55 | *example* 56 | *sopc_* 57 | # *.sdc # I want those timing files 58 | 59 | # ignore Quartus II generated folders 60 | */db/ 61 | */incremental_db/ 62 | */simulation/ 63 | */timing/ 64 | */testbench/ 65 | */*_sim/ 66 | incremental_db/ 67 | db/ 68 | output_files/ 69 | PLLJ_PLLSPE_INFO.txt 70 | 71 | simulation/ 72 | -------------------------------------------------------------------------------- /pld/mackerel-10/dram_controller/dram_controller.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 18:38:20 September 02, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | 25 | QUARTUS_VERSION = "13.0" 26 | DATE = "18:38:20 September 02, 2024" 27 | 28 | # Revisions 29 | 30 | PROJECT_REVISION = "dram_controller" 31 | -------------------------------------------------------------------------------- /pld/mackerel-10/dram_controller/dram_controller.qsf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 18:38:20 September 02, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | # 25 | # Notes: 26 | # 27 | # 1) The default values for assignments are stored in the file: 28 | # dram_controller_assignment_defaults.qdf 29 | # If this file doesn't exist, see file: 30 | # assignment_defaults.qdf 31 | # 32 | # 2) Altera recommends that you do not modify this file. This 33 | # file is updated automatically by the Quartus II software 34 | # and any changes you make may be lost or overwritten. 35 | # 36 | # -------------------------------------------------------------------------- # 37 | 38 | 39 | set_global_assignment -name FAMILY MAX7000S 40 | set_global_assignment -name DEVICE "EPM7128SLC84-15" 41 | set_global_assignment -name TOP_LEVEL_ENTITY dram_controller 42 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" 43 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "18:38:20 SEPTEMBER 02, 2024" 44 | set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" 45 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 46 | set_global_assignment -name DEVICE_FILTER_PIN_COUNT 84 47 | set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 15 48 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1" 49 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 50 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 51 | set_global_assignment -name VERILOG_FILE dram_controller.v 52 | set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)" 53 | set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation 54 | set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation 55 | set_global_assignment -name MAX7000_DEVICE_IO_STANDARD TTL 56 | 57 | set_location_assignment PIN_74 -to ADDR_IN[23] 58 | set_location_assignment PIN_73 -to ADDR_IN[22] 59 | set_location_assignment PIN_70 -to ADDR_IN[21] 60 | set_location_assignment PIN_69 -to ADDR_IN[20] 61 | set_location_assignment PIN_68 -to ADDR_IN[19] 62 | set_location_assignment PIN_67 -to ADDR_IN[18] 63 | set_location_assignment PIN_65 -to ADDR_IN[17] 64 | set_location_assignment PIN_64 -to ADDR_IN[16] 65 | set_location_assignment PIN_63 -to ADDR_IN[15] 66 | set_location_assignment PIN_61 -to ADDR_IN[14] 67 | set_location_assignment PIN_60 -to ADDR_IN[13] 68 | set_location_assignment PIN_58 -to ADDR_IN[12] 69 | set_location_assignment PIN_57 -to ADDR_IN[11] 70 | set_location_assignment PIN_56 -to ADDR_IN[10] 71 | set_location_assignment PIN_55 -to ADDR_IN[9] 72 | set_location_assignment PIN_54 -to ADDR_IN[8] 73 | set_location_assignment PIN_52 -to ADDR_IN[7] 74 | set_location_assignment PIN_51 -to ADDR_IN[6] 75 | set_location_assignment PIN_50 -to ADDR_IN[5] 76 | set_location_assignment PIN_49 -to ADDR_IN[4] 77 | set_location_assignment PIN_48 -to ADDR_IN[3] 78 | set_location_assignment PIN_46 -to ADDR_IN[2] 79 | set_location_assignment PIN_45 -to ADDR_IN[1] 80 | set_location_assignment PIN_44 -to AS 81 | set_location_assignment PIN_41 -to UDS 82 | set_location_assignment PIN_40 -to LDS 83 | set_location_assignment PIN_39 -to RW 84 | set_location_assignment PIN_25 -to DTACK_DRAM 85 | set_location_assignment PIN_24 -to CS 86 | set_location_assignment PIN_4 -to ADDR_OUT[10] 87 | set_location_assignment PIN_5 -to ADDR_OUT[9] 88 | set_location_assignment PIN_6 -to ADDR_OUT[8] 89 | set_location_assignment PIN_8 -to ADDR_OUT[7] 90 | set_location_assignment PIN_9 -to ADDR_OUT[6] 91 | set_location_assignment PIN_10 -to ADDR_OUT[5] 92 | set_location_assignment PIN_11 -to ADDR_OUT[4] 93 | set_location_assignment PIN_12 -to ADDR_OUT[3] 94 | set_location_assignment PIN_15 -to ADDR_OUT[2] 95 | set_location_assignment PIN_16 -to ADDR_OUT[1] 96 | set_location_assignment PIN_17 -to ADDR_OUT[0] 97 | set_location_assignment PIN_18 -to CASB0 98 | set_location_assignment PIN_20 -to CASA0 99 | set_location_assignment PIN_21 -to CASA1 100 | set_location_assignment PIN_22 -to CASB1 101 | set_location_assignment PIN_83 -to CLK 102 | set_location_assignment PIN_2 -to CLK_ALT 103 | set_location_assignment PIN_75 -to RASA 104 | set_location_assignment PIN_77 -to RASB 105 | set_location_assignment PIN_76 -to RST 106 | set_location_assignment PIN_80 -to WRA 107 | set_location_assignment PIN_81 -to WRB 108 | set_location_assignment PIN_79 -to ADDR_OUT_11 -------------------------------------------------------------------------------- /pld/mackerel-10/dram_controller/dram_controller.v: -------------------------------------------------------------------------------- 1 | module dram_controller( 2 | input CLK, 3 | input CLK_ALT, 4 | input RST, 5 | input AS, 6 | input LDS, 7 | input UDS, 8 | input RW, 9 | input CS, // DRAM chip-select 10 | input [23:1] ADDR_IN, 11 | 12 | output ADDR_OUT_11, 13 | 14 | output reg [10:0] ADDR_OUT = 11'b0, // Note: this implies 4MB SIMMs 15 | output reg RASA = 1'b1, 16 | output reg RASB = 1'b1, 17 | output reg CASA0 = 1'b1, 18 | output reg CASA1 = 1'b1, 19 | output reg CASB0 = 1'b1, 20 | output reg CASB1 = 1'b1, 21 | output reg WRA, 22 | output reg WRB, 23 | output reg DTACK_DRAM = 1'b1 24 | ); 25 | 26 | // Assuming 32ms total refresh time at 50 MHz clock 27 | localparam REFRESH_CYCLE_CNT = 781; 28 | 29 | // DRAM controller states 30 | localparam IDLE = 4'd0; 31 | localparam RW1 = 4'd1; 32 | localparam RW2 = 4'd2; 33 | localparam RW3 = 4'd3; 34 | localparam RW4 = 4'd4; 35 | localparam RW5 = 4'd5; 36 | localparam REFRESH1 = 4'd6; 37 | localparam REFRESH2 = 4'd7; 38 | localparam REFRESH3 = 4'd8; 39 | localparam REFRESH4 = 4'd9; 40 | localparam PRECHARGE = 4'd10; 41 | 42 | reg [3:0] state = IDLE; 43 | 44 | assign ADDR_OUT_11 = 1'b0; // A11 is not used on 4MB SIMMs 45 | 46 | wire BANK_A = ~ADDR_IN[23]; // Bank A is the bottom 8 MB of DRAM, Bank B the top 8 MB 47 | 48 | // ==== Periodic refresh generator 49 | reg refresh_request = 1'b0; 50 | reg refresh_ack = 1'b0; 51 | reg [11:0] cycle_count = 12'b0; 52 | 53 | always @(posedge CLK_ALT) begin 54 | if (~RST) cycle_count <= 12'b0; 55 | else begin 56 | cycle_count <= cycle_count + 12'b1; 57 | 58 | if (cycle_count == REFRESH_CYCLE_CNT) begin 59 | refresh_request <= 1'b1; 60 | cycle_count <= 12'b0; 61 | end 62 | 63 | if (refresh_ack) refresh_request <= 1'b0; 64 | end 65 | end 66 | 67 | // ==== Double-flop inputs from CPU clock domain into DRAM clock domain 68 | 69 | // Note: it's also possible to run the CPU and the DRAM controller 70 | // on the same oscillator with the DRAM running at 1x, 2x, or 4x the 71 | // frequency of the CPU 72 | 73 | reg AS1 = 1; 74 | reg CS1 = 1; 75 | reg AS2 = 1; 76 | reg CS2 = 1; 77 | 78 | always @(posedge CLK_ALT) begin 79 | AS1 <= AS; 80 | CS1 <= CS; 81 | AS2 <= AS1; 82 | CS2 <= CS1; 83 | end 84 | 85 | // ==== DRAM controller state machine 86 | always @(posedge CLK_ALT) begin 87 | if (~RST) begin 88 | state <= IDLE; 89 | RASA <= 1'b1; 90 | CASA0 <= 1'b1; 91 | CASA1 <= 1'b1; 92 | RASB <= 1'b1; 93 | CASB0 <= 1'b1; 94 | CASB1 <= 1'b1; 95 | WRA <= 1'b1; 96 | WRB <= 1'b1; 97 | DTACK_DRAM <= 1'b1; 98 | end 99 | else begin 100 | case (state) 101 | IDLE: begin 102 | if (refresh_request) begin 103 | // Start CAS-before-RAS refresh cycle 104 | state <= REFRESH1; 105 | end 106 | else if (~CS2 && ~AS2) begin 107 | // DRAM selected, start normal R/W cycle 108 | state <= RW1; 109 | end 110 | end 111 | 112 | RW1: begin 113 | // Mux in the address 114 | ADDR_OUT <= ADDR_IN[11:1]; 115 | state <= RW2; 116 | end 117 | 118 | RW2: begin 119 | // Row address is valid, lower RAS 120 | if (BANK_A) RASA <= 1'b0; 121 | else RASB <= 1'b0; 122 | state <= RW3; 123 | end 124 | 125 | RW3: begin 126 | // Mux in the column address 127 | ADDR_OUT <= ADDR_IN[22:12]; 128 | 129 | // Set the WE line 130 | if (BANK_A) WRA <= RW; 131 | else WRB <= RW; 132 | 133 | state <= RW4; 134 | end 135 | 136 | RW4: begin 137 | // Column address is valid, lower CAS 138 | if (BANK_A) begin 139 | CASA0 <= LDS; 140 | CASA1 <= UDS; 141 | end 142 | else begin 143 | CASB0 <= LDS; 144 | CASB1 <= UDS; 145 | end 146 | state <= RW5; 147 | end 148 | 149 | RW5: begin 150 | // Data is valid, lower DTACK 151 | DTACK_DRAM <= 1'b0; 152 | 153 | // When AS returns high, the bus cycle is complete 154 | if (AS) state <= PRECHARGE; 155 | end 156 | 157 | REFRESH1: begin 158 | // Acknowledge the refresh request 159 | refresh_ack <= 1'b1; 160 | 161 | // Lower CAS 162 | CASA0 <= 1'b0; 163 | CASA1 <= 1'b0; 164 | CASB0 <= 1'b0; 165 | CASB1 <= 1'b0; 166 | WRA <= 1'b1; 167 | WRB <= 1'b1; 168 | state <= REFRESH2; 169 | end 170 | 171 | REFRESH2: begin 172 | // Lower RAS 173 | RASA <= 1'b0; 174 | RASB <= 1'b0; 175 | state <= REFRESH3; 176 | end 177 | 178 | REFRESH3: begin 179 | // Raise CAS 180 | CASA0 <= 1'b1; 181 | CASA1 <= 1'b1; 182 | CASB0 <= 1'b1; 183 | CASB1 <= 1'b1; 184 | state <= REFRESH4; 185 | end 186 | 187 | REFRESH4: begin 188 | // Raise RAS 189 | RASA <= 1'b1; 190 | RASB <= 1'b1; 191 | state <= PRECHARGE; 192 | end 193 | 194 | PRECHARGE: begin 195 | // Reset the refresh acknowledge to allow the next refresh cycle 196 | refresh_ack <= 1'b0; 197 | 198 | // DRAM cycle finished, bring RAS and CAS HIGH 199 | DTACK_DRAM <= 1'b1; 200 | RASA <= 1'b1; 201 | CASA0 <= 1'b1; 202 | CASA1 <= 1'b1; 203 | RASB <= 1'b1; 204 | CASB0 <= 1'b1; 205 | CASB1 <= 1'b1; 206 | ADDR_OUT <= 11'b0; 207 | state <= IDLE; 208 | end 209 | endcase 210 | end 211 | end 212 | 213 | endmodule 214 | -------------------------------------------------------------------------------- /pld/mackerel-10/dram_controller/dram_controller_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module dram_controller_tb; 4 | 5 | reg reset = 1; 6 | reg clk = 0; 7 | reg cs = 1; 8 | reg [23:1] address = 0; 9 | reg as = 1; 10 | reg lds = 1; 11 | reg uds = 1; 12 | reg rw = 1; 13 | 14 | wire [10:0] addr_out = 11'b0; 15 | wire ras, cas0, cas1; 16 | wire dtack; 17 | 18 | // Start clock 19 | always #10 clk = !clk; 20 | 21 | initial begin 22 | $dumpfile("test.vcd"); 23 | $dumpvars(0, dram_controller_tb); 24 | 25 | // Power on reset 26 | #100 reset = 0; 27 | #100 reset = 1; 28 | #100 29 | 30 | // 16-bit memory access cycle 31 | #100 32 | address = 24'h120034; 33 | cs = 0; 34 | rw = 1; 35 | as = 0; 36 | lds = 0; 37 | uds = 0; 38 | 39 | #200 40 | as = 1; 41 | lds = 1; 42 | uds = 1; 43 | cs = 1; 44 | 45 | // Wait for a while and expect to see some CBR refreshes 46 | 47 | #1000000 48 | 49 | // TODO: simulate 8-bit memory cycle 50 | 51 | // TODO: simulate memory cycle during refresh 52 | 53 | // TODO: simulate write cycle 54 | 55 | #100000 $finish; 56 | end 57 | 58 | dram_controller dram1( 59 | .CLK_ALT(clk), 60 | .RST(reset), 61 | .CS(cs), 62 | .AS(as), 63 | .LDS(lds), 64 | .UDS(uds), 65 | .RW(rw), 66 | .ADDR_IN(address), 67 | .ADDR_OUT(addr_out), 68 | .RASA(ras), 69 | .CASA0(cas0), 70 | .CASA1(cas1), 71 | .DTACK_DRAM(dtack) 72 | ); 73 | 74 | endmodule 75 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/.gitignore: -------------------------------------------------------------------------------- 1 | # Working with Altera Quartus II (Q2) and do proper versioning is not that easy 2 | # but if you follow some rules it can be accomplished. :) 3 | # This file should be placed into the main directory where the .qpf file is 4 | # found. Generally Q2 throws all entities and so on in the main directory, but 5 | # you can place all stuff also in separate folders. This approach is followed 6 | # here. So when you create a new design create one or more folders where your 7 | # entities will be located and put a .gitignore in there that overrides the 8 | # ignores of this file, e.g. one single rule stating "!*" which allows now all 9 | # type of files. When you add a MegaFunction or another entity to your design, 10 | # simply add it to one of your private folders and Q2 will be happy and manage 11 | # everything quite good. When you want to do versioning of your generated 12 | # SOF/POF files, you can do this by redirecting the generated output to an own 13 | # folder. To do this go to: 14 | # "Assignments" 15 | # -> "Settings 16 | # -> "Compilation Process Settings" 17 | # -> "Save project output files in specified directory" 18 | # Now you can either place a .gitignore in the directory and allow the following 19 | # list of types: 20 | # !*.sof 21 | # !*.pof 22 | # or you create an own submodule in the folder to keep binary files out of your 23 | # design. 24 | 25 | # Need to keep all HDL files 26 | # *.vhd 27 | # *.v 28 | 29 | # ignore Quartus II generated files 30 | *_generation_script* 31 | *_inst.vhd 32 | *.bak 33 | *.cmp 34 | *.done 35 | *.eqn 36 | *.hex 37 | *.html 38 | *.jdi 39 | *.jpg 40 | # *.mif 41 | *.pin 42 | *.pof 43 | *.ptf.* 44 | *.qar 45 | *.qarlog 46 | *.qws 47 | *.rpt 48 | *.smsg 49 | *.sof 50 | *.sopc_builder 51 | *.summary 52 | *.tcl 53 | *.txt # Explicitly add any text files used 54 | *~ 55 | *example* 56 | *sopc_* 57 | # *.sdc # I want those timing files 58 | 59 | # ignore Quartus II generated folders 60 | */db/ 61 | */incremental_db/ 62 | */simulation/ 63 | */timing/ 64 | */testbench/ 65 | */*_sim/ 66 | incremental_db/ 67 | db/ 68 | output_files/ 69 | PLLJ_PLLSPE_INFO.txt 70 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/boot_signal.v: -------------------------------------------------------------------------------- 1 | // BOOT signal is active HIGH indicated the first four bus cycles after reset have completed 2 | module boot_signal( 3 | input RESET_n, 4 | input AS_n, 5 | output reg BOOT = 1'b0 6 | ); 7 | 8 | localparam BOOT_CYCLE_MAX = 4; 9 | 10 | reg [2:0] bus_cycles = 0; 11 | 12 | always @(posedge AS_n) begin 13 | if (~RESET_n) begin 14 | bus_cycles = 0; 15 | BOOT <= 1'b0; 16 | end 17 | else begin 18 | if (~BOOT) begin 19 | bus_cycles <= bus_cycles + 3'b1; 20 | if (bus_cycles == BOOT_CYCLE_MAX) BOOT <= 1'b1; 21 | end 22 | end 23 | end 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/clock_gen.v: -------------------------------------------------------------------------------- 1 | module clock_gen( 2 | input CLK_IN, 3 | output CLK_OUT 4 | ); 5 | 6 | // Generate CPU clock from source oscillator 7 | reg clk_buf = 1'b0; 8 | assign CLK_OUT = clk_buf; // Divide source clock by 2 to get CPU clock 9 | always @(posedge CLK_IN) clk_buf <= clk_buf + 1'b1; 10 | 11 | endmodule 12 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/irq_encoder.v: -------------------------------------------------------------------------------- 1 | // Priority encode 7 interrupt sources (active high) to three interrupt priority level pins (active low) 2 | 3 | module irq_encoder( 4 | input irq1, 5 | input irq2, 6 | input irq3, 7 | input irq4, 8 | input irq5, 9 | input irq6, 10 | input irq7, 11 | output reg ipl0_n, 12 | output reg ipl1_n, 13 | output reg ipl2_n 14 | ); 15 | 16 | always @(*) begin 17 | if (irq7) begin 18 | ipl0_n = 0; 19 | ipl1_n = 0; 20 | ipl2_n = 0; 21 | end 22 | else if (irq6) begin 23 | ipl0_n = 1; 24 | ipl1_n = 0; 25 | ipl2_n = 0; 26 | end 27 | else if (irq5) begin 28 | ipl0_n = 0; 29 | ipl1_n = 1; 30 | ipl2_n = 0; 31 | end 32 | else if (irq4) begin 33 | ipl0_n = 1; 34 | ipl1_n = 1; 35 | ipl2_n = 0; 36 | end 37 | else if (irq3) begin 38 | ipl0_n = 0; 39 | ipl1_n = 0; 40 | ipl2_n = 1; 41 | end 42 | else if (irq2) begin 43 | ipl0_n = 1; 44 | ipl1_n = 0; 45 | ipl2_n = 1; 46 | end 47 | else if (irq1) begin 48 | ipl0_n = 0; 49 | ipl1_n = 1; 50 | ipl2_n = 1; 51 | end 52 | else begin 53 | ipl0_n = 1; 54 | ipl1_n = 1; 55 | ipl2_n = 1; 56 | end 57 | end 58 | 59 | endmodule 60 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/irq_encoder_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module irq_encoder_tb; 4 | 5 | reg irq1 = 0; 6 | reg irq2 = 0; 7 | reg irq3 = 0; 8 | reg irq4 = 0; 9 | reg irq5 = 0; 10 | reg irq6 = 0; 11 | reg irq7 = 0; 12 | reg irq8 = 0; 13 | 14 | wire ipl0, ipl1, ipl2; 15 | 16 | initial begin 17 | $dumpfile("irq_encoder.vcd"); 18 | $dumpvars(0, irq_encoder_tb); 19 | 20 | irq1 = 1; 21 | 22 | #100 23 | 24 | irq2 = 1; 25 | 26 | #100 27 | 28 | irq5 = 1; 29 | irq6 = 1; 30 | 31 | #100 32 | 33 | irq1 = 0; 34 | irq2 = 0; 35 | irq3 = 0; 36 | irq4 = 0; 37 | irq5 = 0; 38 | irq6 = 0; 39 | irq7 = 0; 40 | 41 | #100 $finish; 42 | end 43 | 44 | irq_encoder e1( 45 | irq1, 46 | irq2, 47 | irq3, 48 | irq4, 49 | irq5, 50 | irq6, 51 | irq7, 52 | ipl0, 53 | ipl1, 54 | ipl2 55 | ); 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/system-controller.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 13:18:03 August 29, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | 25 | QUARTUS_VERSION = "13.0" 26 | DATE = "13:18:03 August 29, 2024" 27 | 28 | # Revisions 29 | 30 | PROJECT_REVISION = "system-controller" 31 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/system-controller.qsf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 13:18:03 August 29, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | # 25 | # Notes: 26 | # 27 | # 1) The default values for assignments are stored in the file: 28 | # system-controller_assignment_defaults.qdf 29 | # If this file doesn't exist, see file: 30 | # assignment_defaults.qdf 31 | # 32 | # 2) Altera recommends that you do not modify this file. This 33 | # file is updated automatically by the Quartus II software 34 | # and any changes you make may be lost or overwritten. 35 | # 36 | # -------------------------------------------------------------------------- # 37 | 38 | 39 | set_global_assignment -name FAMILY MAX7000S 40 | set_global_assignment -name DEVICE "EPM7128SLC84-15" 41 | set_global_assignment -name TOP_LEVEL_ENTITY system_controller 42 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" 43 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:18:03 AUGUST 29, 2024" 44 | set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" 45 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 46 | set_global_assignment -name DEVICE_FILTER_PACKAGE PLCC 47 | set_global_assignment -name DEVICE_FILTER_PIN_COUNT 84 48 | set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 15 49 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1" 50 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 51 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 52 | set_global_assignment -name MAX7000_DEVICE_IO_STANDARD TTL 53 | 54 | set_location_assignment PIN_83 -to CLK 55 | set_location_assignment PIN_25 -to GPIO[2] 56 | set_location_assignment PIN_27 -to GPIO[3] 57 | set_location_assignment PIN_5 -to ADDR_H[23] 58 | set_location_assignment PIN_6 -to ADDR_H[22] 59 | set_location_assignment PIN_8 -to ADDR_H[21] 60 | set_location_assignment PIN_9 -to ADDR_H[20] 61 | set_location_assignment PIN_10 -to ADDR_H[19] 62 | set_location_assignment PIN_11 -to ADDR_H[18] 63 | set_location_assignment PIN_12 -to ADDR_H[17] 64 | set_location_assignment PIN_15 -to ADDR_H[16] 65 | set_location_assignment PIN_16 -to ADDR_H[15] 66 | set_location_assignment PIN_17 -to ADDR_H[14] 67 | set_location_assignment PIN_52 -to CLK_CPU 68 | set_location_assignment PIN_58 -to DATA[7] 69 | set_location_assignment PIN_61 -to DATA[6] 70 | set_location_assignment PIN_64 -to DATA[5] 71 | set_location_assignment PIN_70 -to DATA[4] 72 | set_location_assignment PIN_69 -to DATA[3] 73 | set_location_assignment PIN_68 -to DATA[2] 74 | set_location_assignment PIN_67 -to DATA[1] 75 | set_location_assignment PIN_65 -to DATA[0] 76 | set_location_assignment PIN_40 -to FC0 77 | set_location_assignment PIN_41 -to FC1 78 | set_location_assignment PIN_44 -to FC2 79 | set_location_assignment PIN_56 -to RW 80 | set_location_assignment PIN_18 -to ADDR_L[1] 81 | set_location_assignment PIN_20 -to ADDR_L[2] 82 | set_location_assignment PIN_21 -to ADDR_L[3] 83 | set_location_assignment PIN_33 -to IDE_INT 84 | set_location_assignment PIN_35 -to IDE_RDY 85 | set_global_assignment -name VERILOG_FILE clock_gen.v 86 | set_global_assignment -name VERILOG_FILE boot_signal.v 87 | set_global_assignment -name VERILOG_FILE "system-controller.v" 88 | set_global_assignment -name VERILOG_FILE irq_encoder.v 89 | set_location_assignment PIN_4 -to RST_n 90 | set_location_assignment PIN_63 -to AS_n 91 | set_location_assignment PIN_51 -to DTACK_n 92 | set_location_assignment PIN_46 -to IPL0_n 93 | set_location_assignment PIN_45 -to IPL1_n 94 | set_location_assignment PIN_48 -to IPL2_n 95 | set_location_assignment PIN_49 -to VPA_n 96 | set_location_assignment PIN_60 -to UDS_n 97 | set_location_assignment PIN_57 -to LDS_n 98 | set_location_assignment PIN_73 -to CS_ROM0_n 99 | set_location_assignment PIN_75 -to CS_ROM1_n 100 | set_location_assignment PIN_74 -to CS_SRAM1_n 101 | set_location_assignment PIN_76 -to CS_SRAM0_n 102 | set_location_assignment PIN_54 -to CS_DRAM_n 103 | set_location_assignment PIN_55 -to DTACK_DRAM_n 104 | set_location_assignment PIN_28 -to CS_EXP_n 105 | set_location_assignment PIN_30 -to DTACK_EXP_n 106 | set_location_assignment PIN_81 -to DTACK_DUART_n 107 | set_location_assignment PIN_79 -to CS_DUART_n 108 | set_location_assignment PIN_80 -to IACK_DUART_n 109 | set_location_assignment PIN_77 -to IRQ_DUART_n 110 | set_location_assignment PIN_31 -to IACK_EXP_n 111 | set_location_assignment PIN_29 -to IRQ_EXP_n 112 | set_location_assignment PIN_39 -to IDE_BUF_n 113 | set_location_assignment PIN_34 -to CS_IDE0_n 114 | set_location_assignment PIN_36 -to IDE_RD_n 115 | set_location_assignment PIN_37 -to IDE_WR_n 116 | set_location_assignment PIN_50 -to CS_IDE1_n 117 | set_location_assignment PIN_22 -to GPIO[0] 118 | set_location_assignment PIN_24 -to GPIO[1] -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/system-controller.v: -------------------------------------------------------------------------------- 1 | module system_controller( 2 | input CLK, 3 | input RST_n, 4 | 5 | output CLK_CPU, 6 | 7 | output IPL0_n, IPL1_n, IPL2_n, 8 | 9 | output DTACK_n, 10 | 11 | output reg VPA_n, 12 | 13 | input [7:0] DATA, 14 | 15 | input [23:14] ADDR_H, 16 | input [3:1] ADDR_L, 17 | 18 | input AS_n, UDS_n, LDS_n, RW, 19 | 20 | input FC0, FC1, FC2, 21 | 22 | output CS_ROM0_n, CS_ROM1_n, 23 | output CS_SRAM0_n, CS_SRAM1_n, 24 | 25 | output CS_EXP_n, 26 | input IRQ_EXP_n, 27 | input DTACK_EXP_n, 28 | output IACK_EXP_n, 29 | 30 | output CS_DUART_n, 31 | input IRQ_DUART_n, 32 | input DTACK_DUART_n, 33 | output IACK_DUART_n, 34 | 35 | output CS_DRAM_n, 36 | input DTACK_DRAM_n, 37 | 38 | input IDE_INT, 39 | output CS_IDE0_n, 40 | output CS_IDE1_n, 41 | input IDE_RDY, 42 | output IDE_RD_n, 43 | output IDE_WR_n, 44 | output IDE_BUF_n, 45 | 46 | output [3:0] GPIO 47 | ); 48 | 49 | // Source oscillator frequency 50 | localparam OSC_FREQ_HZ = 20000000; 51 | // CPU frequency (half the oscillator frequency) 52 | localparam CPU_FREQ_HZ = OSC_FREQ_HZ / 2; 53 | // Frequency of the periodic timer interrupt 54 | localparam TIMER_FREQ_HZ = 50; 55 | // CPU cycles between timer interrupts 56 | localparam TIMER_DELAY_CYCLES = CPU_FREQ_HZ / TIMER_FREQ_HZ; 57 | 58 | // Unused signals 59 | assign IACK_EXP_n = 1; 60 | assign CS_EXP_n = 1'b1; 61 | 62 | assign GPIO = 4'b0; 63 | 64 | // Reconstruct the full address bus 65 | wire [24:0] ADDR_FULL = {ADDR_H, 10'b0, ADDR_L, 1'b0}; 66 | 67 | // CPU is responding to an interrupt request 68 | wire IACK_n = ~(FC0 && FC1 && FC2); 69 | 70 | assign IACK_DUART_n = ~(~IACK_n && ~AS_n && ADDR_L[3:1] == 3'd5); 71 | 72 | // DTACK from DUART 73 | //wire DTACK0 = ((~CS_DUART_n || ~IACK_DUART_n) && DTACK_DUART_n); 74 | wire DTACK0 = 1'b0; // DUART DTACK is always low anyway? 75 | // DTACK from DRAM 76 | wire DTACK1 = (~CS_DRAM_n && DTACK_DRAM_n); 77 | // DTACK from IDE 78 | //wire DTACK2 = ((~CS_IDE0_n || ~CS_IDE1_n) && ~IDE_RDY); 79 | wire DTACK2 = 1'b0; 80 | // DTACK to CPU 81 | assign DTACK_n = DTACK0 || DTACK1 || DTACK2 || ~VPA_n; // NOTE: DTACK and VPA cannot be LOW at the same time 82 | 83 | // BOOT signal generation 84 | wire BOOT; 85 | boot_signal bs1(RST_n, AS_n, BOOT); 86 | 87 | // Generate CPU clock from source oscillator 88 | clock_gen cg1(CLK, CLK_CPU); 89 | 90 | // Encode interrupt sources to the CPU's IPL pins 91 | irq_encoder ie1( 92 | .irq1(0), 93 | .irq2(0), 94 | .irq3(IDE_INT), 95 | .irq4(0), 96 | .irq5(~IRQ_DUART_n), 97 | .irq6(IRQ_TIMER), 98 | .irq7(0), 99 | .ipl0_n(IPL0_n), 100 | .ipl1_n(IPL1_n), 101 | .ipl2_n(IPL2_n) 102 | ); 103 | 104 | reg[23:0] clock_cycles = 0; 105 | reg IRQ_TIMER = 0; 106 | 107 | always @(posedge CLK_CPU) begin 108 | clock_cycles <= clock_cycles + 1'b1; 109 | 110 | if (~RST_n) begin 111 | clock_cycles <= 24'b0; 112 | end 113 | else if (clock_cycles == TIMER_DELAY_CYCLES) begin 114 | IRQ_TIMER <= 1; 115 | clock_cycles <= 24'b0; 116 | end 117 | 118 | // Autovector the non-DUART interrupts 119 | if (~IACK_n && IACK_DUART_n && ~AS_n) begin 120 | VPA_n <= 1'b0; 121 | IRQ_TIMER <= 0; 122 | end 123 | else VPA_n <= 1'b1; 124 | end 125 | 126 | //================================// 127 | // Address Decoding 128 | //================================// 129 | 130 | // ROM at 0xF00000 - 0xFF4000 (0x000000 on BOOT) 131 | wire ROM_EN = ~BOOT || (IACK_n && ADDR_FULL >= 24'hF00000 && ADDR_FULL < 24'hFF4000); 132 | assign CS_ROM0_n = ~(~AS_n && ~LDS_n && ROM_EN); 133 | assign CS_ROM1_n = ~(~AS_n && ~UDS_n && ROM_EN); 134 | 135 | // SRAM enabled at 0xE00000 - 0xF00000 (1 MB) 136 | wire RAM_EN = BOOT && IACK_n && ADDR_FULL >= 24'hE00000 && ADDR_FULL < 24'hF00000; 137 | assign CS_SRAM0_n = ~(~AS_n && ~LDS_n && RAM_EN); 138 | assign CS_SRAM1_n = ~(~AS_n && ~UDS_n && RAM_EN); 139 | 140 | // DRAM at 0x000000 - 0xE00000 (14 MB) 141 | assign CS_DRAM_n = ~(BOOT && IACK_n && ADDR_FULL < 24'hE00000); 142 | 143 | // DUART at 0xFF8000 144 | assign CS_DUART_n = ~(BOOT && IACK_n && ~LDS_n && ADDR_FULL >= 24'hFF8000 && ADDR_FULL < 24'hFFC000); 145 | 146 | // IDE at 0xFF4000 and 0xFFC000 147 | assign CS_IDE0_n = ~(BOOT && IACK_n && ADDR_FULL >= 24'hFFC000); 148 | assign CS_IDE1_n = ~(BOOT && IACK_n && ADDR_FULL >= 24'hFF4000 && ADDR_FULL < 24'hFF8000); 149 | assign IDE_BUF_n = ~(~CS_IDE0_n || ~CS_IDE1_n); 150 | assign IDE_RD_n = ~(RW && ~AS_n && ~UDS_n); 151 | assign IDE_WR_n = ~(~RW && ~AS_n && ~UDS_n); 152 | 153 | endmodule 154 | -------------------------------------------------------------------------------- /pld/mackerel-10/system-controller/system-controller_description.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/pld/mackerel-10/system-controller/system-controller_description.txt -------------------------------------------------------------------------------- /pld/mackerel-30/dram_controller/.gitignore: -------------------------------------------------------------------------------- 1 | # Working with Altera Quartus II (Q2) and do proper versioning is not that easy 2 | # but if you follow some rules it can be accomplished. :) 3 | # This file should be placed into the main directory where the .qpf file is 4 | # found. Generally Q2 throws all entities and so on in the main directory, but 5 | # you can place all stuff also in separate folders. This approach is followed 6 | # here. So when you create a new design create one or more folders where your 7 | # entities will be located and put a .gitignore in there that overrides the 8 | # ignores of this file, e.g. one single rule stating "!*" which allows now all 9 | # type of files. When you add a MegaFunction or another entity to your design, 10 | # simply add it to one of your private folders and Q2 will be happy and manage 11 | # everything quite good. When you want to do versioning of your generated 12 | # SOF/POF files, you can do this by redirecting the generated output to an own 13 | # folder. To do this go to: 14 | # "Assignments" 15 | # -> "Settings 16 | # -> "Compilation Process Settings" 17 | # -> "Save project output files in specified directory" 18 | # Now you can either place a .gitignore in the directory and allow the following 19 | # list of types: 20 | # !*.sof 21 | # !*.pof 22 | # or you create an own submodule in the folder to keep binary files out of your 23 | # design. 24 | 25 | # Need to keep all HDL files 26 | # *.vhd 27 | # *.v 28 | 29 | # ignore Quartus II generated files 30 | *_generation_script* 31 | *_inst.vhd 32 | *.bak 33 | *.cmp 34 | *.done 35 | *.eqn 36 | *.hex 37 | *.html 38 | *.jdi 39 | *.jpg 40 | # *.mif 41 | *.pin 42 | *.pof 43 | *.ptf.* 44 | *.qar 45 | *.qarlog 46 | *.qws 47 | *.rpt 48 | *.smsg 49 | *.sof 50 | *.sopc_builder 51 | *.summary 52 | *.tcl 53 | *.txt # Explicitly add any text files used 54 | *~ 55 | *example* 56 | *sopc_* 57 | # *.sdc # I want those timing files 58 | 59 | # ignore Quartus II generated folders 60 | */db/ 61 | */incremental_db/ 62 | */simulation/ 63 | */timing/ 64 | */testbench/ 65 | */*_sim/ 66 | incremental_db/ 67 | db/ 68 | output_files/ 69 | PLLJ_PLLSPE_INFO.txt 70 | -------------------------------------------------------------------------------- /pld/mackerel-30/dram_controller/dram_controller.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 16:56:52 November 25, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | 25 | QUARTUS_VERSION = "13.0" 26 | DATE = "16:56:52 November 25, 2024" 27 | 28 | # Revisions 29 | 30 | PROJECT_REVISION = "dram_controller" 31 | -------------------------------------------------------------------------------- /pld/mackerel-30/dram_controller/dram_controller.qsf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 16:56:52 November 25, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | # 25 | # Notes: 26 | # 27 | # 1) The default values for assignments are stored in the file: 28 | # dram_controller_assignment_defaults.qdf 29 | # If this file doesn't exist, see file: 30 | # assignment_defaults.qdf 31 | # 32 | # 2) Altera recommends that you do not modify this file. This 33 | # file is updated automatically by the Quartus II software 34 | # and any changes you make may be lost or overwritten. 35 | # 36 | # -------------------------------------------------------------------------- # 37 | 38 | 39 | set_global_assignment -name FAMILY MAX7000S 40 | set_global_assignment -name DEVICE "EPM7128SLC84-15" 41 | set_global_assignment -name TOP_LEVEL_ENTITY dram_controller 42 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" 43 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "16:56:52 NOVEMBER 25, 2024" 44 | set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" 45 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 46 | set_global_assignment -name DEVICE_FILTER_PIN_COUNT 84 47 | set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 15 48 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1" 49 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 50 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 51 | set_global_assignment -name VERILOG_FILE dram_controller.v 52 | set_global_assignment -name MAX7000_DEVICE_IO_STANDARD TTL 53 | set_location_assignment PIN_21 -to ADDR[27] 54 | set_location_assignment PIN_22 -to ADDR[26] 55 | set_location_assignment PIN_24 -to ADDR[25] 56 | set_location_assignment PIN_25 -to ADDR[24] 57 | set_location_assignment PIN_28 -to ADDR[23] 58 | set_location_assignment PIN_27 -to ADDR[22] 59 | set_location_assignment PIN_31 -to ADDR[21] 60 | set_location_assignment PIN_30 -to ADDR[20] 61 | set_location_assignment PIN_34 -to ADDR[19] 62 | set_location_assignment PIN_29 -to ADDR[18] 63 | set_location_assignment PIN_37 -to ADDR[17] 64 | set_location_assignment PIN_33 -to ADDR[16] 65 | set_location_assignment PIN_40 -to ADDR[15] 66 | set_location_assignment PIN_36 -to ADDR[14] 67 | set_location_assignment PIN_44 -to ADDR[13] 68 | set_location_assignment PIN_39 -to ADDR[12] 69 | set_location_assignment PIN_35 -to ADDR[11] 70 | set_location_assignment PIN_45 -to ADDR[10] 71 | set_location_assignment PIN_48 -to ADDR[9] 72 | set_location_assignment PIN_41 -to ADDR[8] 73 | set_location_assignment PIN_46 -to ADDR[7] 74 | set_location_assignment PIN_55 -to ADDR[6] 75 | set_location_assignment PIN_49 -to ADDR[5] 76 | set_location_assignment PIN_50 -to ADDR[4] 77 | set_location_assignment PIN_51 -to ADDR[3] 78 | set_location_assignment PIN_52 -to ADDR[2] 79 | set_location_assignment PIN_20 -to ADDR[1] 80 | set_location_assignment PIN_18 -to ADDR[0] 81 | set_location_assignment PIN_69 -to ADDR_DRAM[11] 82 | set_location_assignment PIN_73 -to ADDR_DRAM[10] 83 | set_location_assignment PIN_67 -to ADDR_DRAM[9] 84 | set_location_assignment PIN_68 -to ADDR_DRAM[8] 85 | set_location_assignment PIN_70 -to ADDR_DRAM[7] 86 | set_location_assignment PIN_74 -to ADDR_DRAM[6] 87 | set_location_assignment PIN_76 -to ADDR_DRAM[5] 88 | set_location_assignment PIN_75 -to ADDR_DRAM[4] 89 | set_location_assignment PIN_77 -to ADDR_DRAM[3] 90 | set_location_assignment PIN_80 -to ADDR_DRAM[2] 91 | set_location_assignment PIN_79 -to ADDR_DRAM[1] 92 | set_location_assignment PIN_81 -to ADDR_DRAM[0] 93 | set_location_assignment PIN_17 -to AS_n 94 | set_location_assignment PIN_63 -to CAS0_n 95 | set_location_assignment PIN_58 -to CAS1_n 96 | set_location_assignment PIN_61 -to CAS2_n 97 | set_location_assignment PIN_60 -to CAS3_n 98 | set_location_assignment PIN_83 -to CLK 99 | set_location_assignment PIN_2 -to CLK_CPU 100 | set_location_assignment PIN_10 -to CS_n 101 | set_location_assignment PIN_54 -to DRAM_WR_n 102 | set_location_assignment PIN_16 -to DS_n 103 | set_location_assignment PIN_57 -to RAS0_n 104 | set_location_assignment PIN_56 -to RAS1_n 105 | set_location_assignment PIN_64 -to RAS2_n 106 | set_location_assignment PIN_65 -to RAS3_n 107 | set_location_assignment PIN_4 -to RST_n 108 | set_location_assignment PIN_11 -to RW 109 | set_location_assignment PIN_12 -to SIZ0 110 | set_location_assignment PIN_15 -to SIZ1 111 | set_location_assignment PIN_9 -to DSACK0_DRAM_n 112 | set_location_assignment PIN_8 -to DSACK1_DRAM_n -------------------------------------------------------------------------------- /pld/mackerel-30/dram_controller/dram_controller.v: -------------------------------------------------------------------------------- 1 | module dram_controller( 2 | input RST_n, 3 | input CLK, 4 | input CLK_CPU, 5 | 6 | input CS_n, 7 | 8 | input RW, 9 | 10 | input SIZ0, SIZ1, 11 | 12 | input AS_n, DS_n, 13 | 14 | output reg DRAM_WR_n, 15 | 16 | input [27:0] ADDR, 17 | 18 | output reg [11:0] ADDR_DRAM = 12'b0, 19 | 20 | output reg RAS0_n, RAS1_n, RAS2_n, RAS3_n, 21 | output reg CAS0_n, CAS1_n, CAS2_n, CAS3_n, 22 | 23 | output reg DSACK0_DRAM_n, 24 | output reg DSACK1_DRAM_n 25 | ); 26 | 27 | // Assuming 32ms total refresh time at 50 MHz clock 28 | localparam REFRESH_CYCLE_CNT = 781; 29 | 30 | // DRAM controller states 31 | localparam IDLE = 4'd0; 32 | localparam RW1 = 4'd1; 33 | localparam RW2 = 4'd2; 34 | localparam RW3 = 4'd3; 35 | localparam RW4 = 4'd4; 36 | localparam RW5 = 4'd5; 37 | localparam REFRESH1 = 4'd6; 38 | localparam REFRESH2 = 4'd7; 39 | localparam REFRESH3 = 4'd8; 40 | localparam REFRESH4 = 4'd9; 41 | localparam PRECHARGE = 4'd10; 42 | 43 | reg [3:0] state = IDLE; 44 | 45 | // ==== Periodic refresh generator 46 | reg refresh_request = 1'b0; 47 | reg refresh_ack = 1'b0; 48 | reg [11:0] cycle_count = 12'b0; 49 | 50 | always @(posedge CLK) begin 51 | if (~RST_n) cycle_count <= 12'b0; 52 | else begin 53 | cycle_count <= cycle_count + 12'b1; 54 | 55 | if (cycle_count == REFRESH_CYCLE_CNT) begin 56 | refresh_request <= 1'b1; 57 | cycle_count <= 12'b0; 58 | end 59 | 60 | if (refresh_ack) refresh_request <= 1'b0; 61 | end 62 | end 63 | 64 | // ==== Double clock input signals from CPU clock domain 65 | reg AS1_n = 1; 66 | reg CS1_n = 1; 67 | reg AS2_n = 1; 68 | reg CS2_n = 1; 69 | 70 | always @(posedge CLK) begin 71 | AS1_n <= AS_n; 72 | CS1_n <= CS_n; 73 | AS2_n <= AS1_n; 74 | CS2_n <= CS1_n; 75 | end 76 | 77 | // ==== Translate cycle type to appropriate CAS signals 78 | // This comes directly from Table 7-4 in the MC68030 datasheet 79 | wire [3:0] CYCLE_TYPE = {SIZ1, SIZ0, ADDR[1], ADDR[0]}; 80 | reg [3:0] CAS; // active high 81 | 82 | always @(*) begin 83 | case (CYCLE_TYPE) 84 | // CYCLE TYPE <= CAS[3:0] 85 | 86 | // byte 87 | 4'b0100: CAS <= 4'b1000; 88 | 4'b0101: CAS <= 4'b0100; 89 | 4'b0110: CAS <= 4'b0010; 90 | 4'b0111: CAS <= 4'b0001; 91 | 92 | // word 93 | 4'b1000: CAS <= 4'b1100; 94 | 4'b1001: CAS <= 4'b0110; 95 | 4'b1010: CAS <= 4'b0011; 96 | 4'b1011: CAS <= 4'b0001; 97 | 98 | // 3-byte 99 | 4'b1100: CAS <= 4'b1110; 100 | 4'b1101: CAS <= 4'b0111; 101 | 4'b1110: CAS <= 4'b0011; 102 | 4'b1111: CAS <= 4'b0001; 103 | 104 | // long word 105 | 4'b0000: CAS <= 4'b1111; 106 | 4'b0001: CAS <= 4'b0111; 107 | 4'b0010: CAS <= 4'b0011; 108 | 4'b0011: CAS <= 4'b0001; 109 | 110 | default: CAS <= 4'b1111; 111 | endcase 112 | end 113 | 114 | // ==== DRAM controller state machine 115 | always @(posedge CLK) begin 116 | if (~RST_n) begin 117 | state <= IDLE; 118 | RAS0_n <= 1'b1; 119 | RAS1_n <= 1'b1; 120 | RAS2_n <= 1'b1; 121 | RAS3_n <= 1'b1; 122 | CAS0_n <= 1'b1; 123 | CAS1_n <= 1'b1; 124 | CAS2_n <= 1'b1; 125 | CAS3_n <= 1'b1; 126 | DRAM_WR_n <= 1'b1; 127 | DSACK0_DRAM_n <= 1'b1; 128 | DSACK1_DRAM_n <= 1'b1; 129 | end 130 | else begin 131 | case (state) 132 | IDLE: begin 133 | if (refresh_request) begin 134 | // Start CAS-before-RAS refresh cycle 135 | state <= REFRESH1; 136 | end 137 | else if (~CS2_n && ~AS2_n) begin 138 | // DRAM selected, start normal R/W cycle 139 | state <= RW1; 140 | end 141 | end 142 | 143 | RW1: begin 144 | // Mux in the address 145 | ADDR_DRAM <= ADDR[13:2]; 146 | state <= RW2; 147 | end 148 | 149 | RW2: begin 150 | // Row address is valid, lower RAS 151 | 152 | // NOTE: This is set up for 64/128 MB SIMMs 153 | // If A26 is 0, the first side of the SIMM is selected, else the other side is selected 154 | 155 | RAS0_n <= ADDR[26]; 156 | RAS1_n <= ~ADDR[26]; 157 | RAS2_n <= ADDR[26]; 158 | RAS3_n <= ~ADDR[26]; 159 | 160 | state <= RW3; 161 | end 162 | 163 | RW3: begin 164 | // Mux in the column address 165 | ADDR_DRAM <= ADDR[25:14]; 166 | 167 | // Set the WE line 168 | DRAM_WR_n <= RW; 169 | 170 | state <= RW4; 171 | end 172 | 173 | RW4: begin 174 | // Column address is valid, lower CAS 175 | CAS0_n <= ~CAS[0]; 176 | CAS1_n <= ~CAS[1]; 177 | CAS2_n <= ~CAS[2]; 178 | CAS3_n <= ~CAS[3]; 179 | 180 | state <= RW5; 181 | end 182 | 183 | RW5: begin 184 | // Data is valid, lower DSACK 185 | 186 | // TODO: figure out which DSACK pins to assert based on bus cycle width? 187 | 188 | DSACK0_DRAM_n <= 1'b0; 189 | DSACK1_DRAM_n <= 1'b0; 190 | 191 | // When AS returns high, the bus cycle is complete 192 | if (AS_n) state <= PRECHARGE; 193 | end 194 | 195 | REFRESH1: begin 196 | // Acknowledge the refresh request 197 | refresh_ack <= 1'b1; 198 | 199 | // Lower CAS 200 | CAS0_n <= 1'b0; 201 | CAS1_n <= 1'b0; 202 | CAS2_n <= 1'b0; 203 | CAS3_n <= 1'b0; 204 | DRAM_WR_n <= 1'b1; 205 | state <= REFRESH2; 206 | end 207 | 208 | REFRESH2: begin 209 | // Lower RAS 210 | RAS0_n <= 1'b0; 211 | RAS1_n <= 1'b0; 212 | RAS2_n <= 1'b0; 213 | RAS3_n <= 1'b0; 214 | state <= REFRESH3; 215 | end 216 | 217 | REFRESH3: begin 218 | // Raise CAS 219 | CAS0_n <= 1'b1; 220 | CAS1_n <= 1'b1; 221 | CAS2_n <= 1'b1; 222 | CAS3_n <= 1'b1; 223 | state <= REFRESH4; 224 | end 225 | 226 | REFRESH4: begin 227 | // Raise RAS 228 | RAS0_n <= 1'b1; 229 | RAS1_n <= 1'b1; 230 | RAS2_n <= 1'b1; 231 | RAS3_n <= 1'b1; 232 | state <= PRECHARGE; 233 | end 234 | 235 | PRECHARGE: begin 236 | // Reset the refresh acknowledge to allow the next refresh cycle 237 | refresh_ack <= 1'b0; 238 | 239 | // DRAM cycle finished, bring RAS and CAS HIGH 240 | DSACK0_DRAM_n <= 1'b1; 241 | DSACK1_DRAM_n <= 1'b1; 242 | RAS0_n <= 1'b1; 243 | RAS1_n <= 1'b1; 244 | RAS2_n <= 1'b1; 245 | RAS3_n <= 1'b1; 246 | CAS0_n <= 1'b1; 247 | CAS1_n <= 1'b1; 248 | CAS2_n <= 1'b1; 249 | CAS3_n <= 1'b1; 250 | ADDR_DRAM <= 12'b0; 251 | 252 | state <= IDLE; 253 | end 254 | endcase 255 | end 256 | end 257 | 258 | endmodule 259 | -------------------------------------------------------------------------------- /pld/mackerel-30/system_controller/.gitignore: -------------------------------------------------------------------------------- 1 | # Working with Altera Quartus II (Q2) and do proper versioning is not that easy 2 | # but if you follow some rules it can be accomplished. :) 3 | # This file should be placed into the main directory where the .qpf file is 4 | # found. Generally Q2 throws all entities and so on in the main directory, but 5 | # you can place all stuff also in separate folders. This approach is followed 6 | # here. So when you create a new design create one or more folders where your 7 | # entities will be located and put a .gitignore in there that overrides the 8 | # ignores of this file, e.g. one single rule stating "!*" which allows now all 9 | # type of files. When you add a MegaFunction or another entity to your design, 10 | # simply add it to one of your private folders and Q2 will be happy and manage 11 | # everything quite good. When you want to do versioning of your generated 12 | # SOF/POF files, you can do this by redirecting the generated output to an own 13 | # folder. To do this go to: 14 | # "Assignments" 15 | # -> "Settings 16 | # -> "Compilation Process Settings" 17 | # -> "Save project output files in specified directory" 18 | # Now you can either place a .gitignore in the directory and allow the following 19 | # list of types: 20 | # !*.sof 21 | # !*.pof 22 | # or you create an own submodule in the folder to keep binary files out of your 23 | # design. 24 | 25 | # Need to keep all HDL files 26 | # *.vhd 27 | # *.v 28 | 29 | # ignore Quartus II generated files 30 | *_generation_script* 31 | *_inst.vhd 32 | *.bak 33 | *.cmp 34 | *.done 35 | *.eqn 36 | *.hex 37 | *.html 38 | *.jdi 39 | *.jpg 40 | # *.mif 41 | *.pin 42 | *.pof 43 | *.ptf.* 44 | *.qar 45 | *.qarlog 46 | *.qws 47 | *.rpt 48 | *.smsg 49 | *.sof 50 | *.sopc_builder 51 | *.summary 52 | *.tcl 53 | *.txt # Explicitly add any text files used 54 | *~ 55 | *example* 56 | *sopc_* 57 | # *.sdc # I want those timing files 58 | 59 | # ignore Quartus II generated folders 60 | */db/ 61 | */incremental_db/ 62 | */simulation/ 63 | */timing/ 64 | */testbench/ 65 | */*_sim/ 66 | incremental_db/ 67 | db/ 68 | output_files/ 69 | PLLJ_PLLSPE_INFO.txt 70 | -------------------------------------------------------------------------------- /pld/mackerel-30/system_controller/boot_signal.v: -------------------------------------------------------------------------------- 1 | // BOOT signal is active HIGH indicated the first eight bus cycles after reset have completed 2 | module boot_signal( 3 | input RESET_n, 4 | input AS_n, 5 | output reg BOOT = 1'b0 6 | ); 7 | 8 | localparam BOOT_CYCLE_MAX = 4'd8; 9 | 10 | reg [3:0] bus_cycles = 0; 11 | 12 | always @(posedge AS_n) begin 13 | if (~RESET_n) begin 14 | bus_cycles = 0; 15 | BOOT <= 1'b0; 16 | end 17 | else begin 18 | if (~BOOT) begin 19 | bus_cycles <= bus_cycles + 4'b1; 20 | if (bus_cycles == BOOT_CYCLE_MAX) BOOT <= 1'b1; 21 | end 22 | end 23 | end 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /pld/mackerel-30/system_controller/irq_encoder.v: -------------------------------------------------------------------------------- 1 | // Priority encode 7 interrupt sources (active high) to three interrupt priority level pins (active low) 2 | 3 | module irq_encoder( 4 | input irq1, 5 | input irq2, 6 | input irq3, 7 | input irq4, 8 | input irq5, 9 | input irq6, 10 | input irq7, 11 | output reg ipl0_n, 12 | output reg ipl1_n, 13 | output reg ipl2_n 14 | ); 15 | 16 | always @(*) begin 17 | if (irq7) begin 18 | ipl0_n = 0; 19 | ipl1_n = 0; 20 | ipl2_n = 0; 21 | end 22 | else if (irq6) begin 23 | ipl0_n = 1; 24 | ipl1_n = 0; 25 | ipl2_n = 0; 26 | end 27 | else if (irq5) begin 28 | ipl0_n = 0; 29 | ipl1_n = 1; 30 | ipl2_n = 0; 31 | end 32 | else if (irq4) begin 33 | ipl0_n = 1; 34 | ipl1_n = 1; 35 | ipl2_n = 0; 36 | end 37 | else if (irq3) begin 38 | ipl0_n = 0; 39 | ipl1_n = 0; 40 | ipl2_n = 1; 41 | end 42 | else if (irq2) begin 43 | ipl0_n = 1; 44 | ipl1_n = 0; 45 | ipl2_n = 1; 46 | end 47 | else if (irq1) begin 48 | ipl0_n = 0; 49 | ipl1_n = 1; 50 | ipl2_n = 1; 51 | end 52 | else begin 53 | ipl0_n = 1; 54 | ipl1_n = 1; 55 | ipl2_n = 1; 56 | end 57 | end 58 | 59 | endmodule 60 | -------------------------------------------------------------------------------- /pld/mackerel-30/system_controller/system_controller.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 19:01:53 November 22, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | 25 | QUARTUS_VERSION = "13.0" 26 | DATE = "19:01:53 November 22, 2024" 27 | 28 | # Revisions 29 | 30 | PROJECT_REVISION = "system_controller" 31 | -------------------------------------------------------------------------------- /pld/mackerel-30/system_controller/system_controller.qsf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2013 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 64-Bit 20 | # Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 19:01:53 November 22, 2024 22 | # 23 | # -------------------------------------------------------------------------- # 24 | # 25 | # Notes: 26 | # 27 | # 1) The default values for assignments are stored in the file: 28 | # system_controller_assignment_defaults.qdf 29 | # If this file doesn't exist, see file: 30 | # assignment_defaults.qdf 31 | # 32 | # 2) Altera recommends that you do not modify this file. This 33 | # file is updated automatically by the Quartus II software 34 | # and any changes you make may be lost or overwritten. 35 | # 36 | # -------------------------------------------------------------------------- # 37 | 38 | 39 | set_global_assignment -name FAMILY MAX7000S 40 | set_global_assignment -name DEVICE "EPM7128SLC84-15" 41 | set_global_assignment -name TOP_LEVEL_ENTITY system_controller 42 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" 43 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:01:53 NOVEMBER 22, 2024" 44 | set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" 45 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 46 | set_global_assignment -name DEVICE_FILTER_PIN_COUNT 84 47 | set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 15 48 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1" 49 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 50 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 51 | set_global_assignment -name MAX7000_DEVICE_IO_STANDARD TTL 52 | set_location_assignment PIN_67 -to AH[31] 53 | set_location_assignment PIN_69 -to AH[30] 54 | set_location_assignment PIN_68 -to AH[29] 55 | set_location_assignment PIN_70 -to AH[28] 56 | set_location_assignment PIN_41 -to AL[3] 57 | set_location_assignment PIN_40 -to AL[2] 58 | set_location_assignment PIN_39 -to AL[1] 59 | set_location_assignment PIN_37 -to AL[0] 60 | set_location_assignment PIN_48 -to AM[19] 61 | set_location_assignment PIN_46 -to AM[18] 62 | set_location_assignment PIN_45 -to AM[17] 63 | set_location_assignment PIN_44 -to AM[16] 64 | set_location_assignment PIN_54 -to AS_n 65 | set_location_assignment PIN_49 -to AVEC_n 66 | set_location_assignment PIN_55 -to BERR_n 67 | set_location_assignment PIN_61 -to CIIN_n 68 | set_location_assignment PIN_83 -to CLK 69 | set_location_assignment PIN_18 -to CS_DUART_n 70 | set_location_assignment PIN_31 -to CS_ROM_n 71 | set_location_assignment PIN_34 -to CS_SRAM_n 72 | set_location_assignment PIN_50 -to DSACK0_n 73 | set_location_assignment PIN_51 -to DSACK1_n 74 | set_location_assignment PIN_56 -to DS_n 75 | set_location_assignment PIN_63 -to FC[2] 76 | set_location_assignment PIN_64 -to FC[1] 77 | set_location_assignment PIN_65 -to FC[0] 78 | set_location_assignment PIN_16 -to IACK_DUART_n 79 | set_location_assignment PIN_75 -to IPL_n[2] 80 | set_location_assignment PIN_76 -to IPL_n[1] 81 | set_location_assignment PIN_77 -to IPL_n[0] 82 | set_location_assignment PIN_4 -to RST_n 83 | set_location_assignment PIN_60 -to RW 84 | set_location_assignment PIN_58 -to SIZ0 85 | set_location_assignment PIN_57 -to SIZ1 86 | set_location_assignment PIN_52 -to STERM_n 87 | set_location_assignment PIN_5 -to P5 88 | set_location_assignment PIN_6 -to P6 89 | set_location_assignment PIN_8 -to P8 90 | set_location_assignment PIN_9 -to P9 91 | set_location_assignment PIN_10 -to P10 92 | set_global_assignment -name VERILOG_FILE irq_encoder.v 93 | set_global_assignment -name VERILOG_FILE boot_signal.v 94 | set_global_assignment -name VERILOG_FILE system_controller.v 95 | set_location_assignment PIN_21 -to IRQ_DUART_n 96 | set_location_assignment PIN_20 -to DTACK_DUART_n 97 | set_location_assignment PIN_35 -to CS_FPU_n 98 | set_location_assignment PIN_24 -to IDE_BUF_n 99 | set_location_assignment PIN_33 -to DSACK0_FPU_n 100 | set_location_assignment PIN_36 -to DSACK1_FPU_n 101 | set_location_assignment PIN_25 -to IDE_CS0_n 102 | set_location_assignment PIN_22 -to IDE_CS1_n 103 | set_location_assignment PIN_27 -to IDE_INT 104 | set_location_assignment PIN_28 -to IDE_RDY 105 | set_location_assignment PIN_29 -to IDE_RD_n 106 | set_location_assignment PIN_30 -to IDE_WR_n 107 | set_location_assignment PIN_73 -to CS_DRAM_n 108 | set_location_assignment PIN_74 -to DSACK0_DRAM_n 109 | set_location_assignment PIN_81 -to DSACK1_DRAM_n -------------------------------------------------------------------------------- /pld/mackerel-30/system_controller/system_controller.v: -------------------------------------------------------------------------------- 1 | module system_controller( 2 | input RST_n, 3 | input CLK, 4 | 5 | input [31:28] AH, // Address bus (high) 6 | input [19:16] AM, // Address bus (mid) 7 | input [3:0] AL, // Address bus (low) 8 | 9 | output reg DSACK0_n, DSACK1_n, 10 | output BERR_n, 11 | output reg AVEC_n = 1'b1, 12 | output CIIN_n, 13 | output STERM_n, 14 | 15 | input [2:0] FC, 16 | output [2:0] IPL_n, 17 | 18 | input AS_n, DS_n, 19 | input SIZ0, SIZ1, 20 | input RW, 21 | 22 | output CS_ROM_n, 23 | output CS_SRAM_n, 24 | 25 | output CS_DRAM_n, 26 | input DSACK0_DRAM_n, 27 | input DSACK1_DRAM_n, 28 | 29 | output CS_FPU_n, 30 | input DSACK0_FPU_n, 31 | input DSACK1_FPU_n, 32 | 33 | output CS_DUART_n, 34 | output IACK_DUART_n, 35 | input IRQ_DUART_n, 36 | input DTACK_DUART_n, 37 | 38 | output IDE_BUF_n, 39 | output IDE_CS0_n, 40 | output IDE_CS1_n, 41 | output IDE_WR_n, 42 | output IDE_RD_n, 43 | input IDE_RDY, 44 | input IDE_INT, 45 | 46 | output P5, P6, P8, P9, P10 47 | ); 48 | 49 | // === COMMON SIGNALS === // 50 | 51 | // Processor is addressing CPU space 52 | wire CPU_SPACE = (FC == 3'b111); 53 | // Processor is responding to an interrupt 54 | wire IACK_n = ~(CPU_SPACE && ~AS_n && AM[19:16] == 4'b1111); 55 | 56 | // Currently unused outputs 57 | assign BERR_n = 1'b1; 58 | assign CIIN_n = 1'b1; 59 | assign STERM_n = 1'b1; 60 | 61 | // === BOOT SIGNAL === // 62 | 63 | wire BOOT; 64 | boot_signal bs(RST_n, AS_n, BOOT); 65 | 66 | // === INTERRUPT HANDLING === // 67 | 68 | irq_encoder ie1( 69 | .irq1(0), 70 | .irq2(0), 71 | .irq3(IDE_INT), 72 | .irq4(0), 73 | .irq5(~IRQ_DUART_n), 74 | .irq6(0), 75 | .irq7(0), 76 | .ipl0_n(IPL_n[0]), 77 | .ipl1_n(IPL_n[1]), 78 | .ipl2_n(IPL_n[2]) 79 | ); 80 | 81 | // Autovector the non-DUART interrupts 82 | always @(posedge CLK) begin 83 | // Autovector the non-DUART interrupts 84 | if (~IACK_n && IACK_DUART_n && ~AS_n) AVEC_n <= 1'b0; 85 | else AVEC_n <= 1'b1; 86 | end 87 | 88 | // DUART IACK is mapped to IRQ level 5 89 | assign IACK_DUART_n = ~(~IACK_n && ~AS_n && AL[3:1] == 3'd5); 90 | 91 | // === ADDRESS DECODING === // 92 | 93 | // ROM at 0xE0000000 (mapped to 0x0000 for the first eight bus cycles) 94 | wire ROM_EN = ~BOOT || (AH == 4'b1110); 95 | assign CS_ROM_n = ~(~CPU_SPACE && ~AS_n && ROM_EN); 96 | 97 | // SRAM at 0x00000000 98 | assign CS_SRAM_n = ~(BOOT && ~CPU_SPACE && ~AS_n && ~DS_n && AH == 4'b0000); 99 | 100 | // DRAM at 0x80000000 101 | assign CS_DRAM_n = ~(BOOT && ~CPU_SPACE && AH == 4'b1000); 102 | 103 | // DUART at 0xF0000000 104 | assign CS_DUART_n = ~(BOOT && ~CPU_SPACE && ~AS_n && ~DS_n && AH == 4'b1111 && AM == 4'b0000); 105 | 106 | // IDE CS0 at 0xF0010000 107 | assign IDE_CS0_n = ~(BOOT && ~CPU_SPACE && AH == 4'b1111 && AM == 4'b0001); 108 | // IDE CS1 at 0xF0020000 109 | assign IDE_CS1_n = ~(BOOT && ~CPU_SPACE && AH == 4'b1111 && AM == 4'b0010); 110 | // If either IDE CS pin is active, enable the IDE buffers 111 | assign IDE_BUF_n = ~(~IDE_CS0_n || ~IDE_CS1_n); 112 | assign IDE_RD_n = ~(RW && ~AS_n && ~DS_n); 113 | assign IDE_WR_n = ~(~RW && ~AS_n && ~DS_n); 114 | 115 | assign CS_FPU_n = 1'b1; 116 | 117 | // TODO: Does it matter if the requested cycle width is not matched by the DSACK signals? 118 | // e.g. If the CPU requests 8 bits from DRAM, but the DRAM responds with 32 119 | 120 | wire IDE_SELECTED = ~AS_n && (~IDE_CS0_n || ~IDE_CS1_n); 121 | 122 | // === DSACK GENERATION === // 123 | 124 | always @(*) begin 125 | if (~AVEC_n) begin 126 | // DSACK and AVEC should not be asserted at the same time 127 | DSACK0_n <= 1'b1; 128 | DSACK1_n <= 1'b1; 129 | end 130 | else if (~CS_DRAM_n) begin 131 | DSACK0_n <= DSACK0_DRAM_n; 132 | DSACK1_n <= DSACK1_DRAM_n; 133 | end 134 | else if (IDE_SELECTED) begin 135 | DSACK0_n <= 1'b1; 136 | DSACK1_n <= ~IDE_RDY; // TODO: All IDE access is 16-bit - is that alright? 137 | end 138 | else begin 139 | DSACK0_n <= 1'b0; // All other accesses are 8-bit 140 | DSACK1_n <= 1'b1; 141 | end 142 | end 143 | 144 | endmodule 145 | -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/address_decoder.jed: -------------------------------------------------------------------------------- 1 |  2 | Used Program: GALasm 2.1 3 | GAL-Assembler: GALasm 2.1 4 | Device: GAL22V10 5 | 6 | *F0 7 | *G0 8 | *QF5892 9 | *L0044 11111111111111111111111111111111111111111111 10 | *L0088 01111011011110110111011101110111011101110101 11 | *L0440 11111111111111111111111111111111111111111111 12 | *L0484 10111011011111111111111111111111111111111111 13 | *L0528 01111011011111111011011101110111011101110101 14 | *L0572 01111011011111111111101101110111011101110101 15 | *L0616 01111011011111111111111110110111011101110101 16 | *L0660 01111011011111111111111111111011011101110101 17 | *L0704 01111011011111111111111111111111101101110101 18 | *L0924 11111111111111111111111111111111111111111111 19 | *L0968 01111011011111111111111111111111111110111010 20 | *L1496 11111111111111111111111111111111111111111111 21 | *L1540 01111011011111111111111111111111111101111010 22 | *L2156 11111111111111111111111111111111111111111111 23 | *L2200 01111011011111111111111111111111111110110110 24 | *L2904 11111111111111111111111111111111111111111111 25 | *L2948 01111011011111111111111111111111111101110110 26 | *L3652 11111111111111111111111111111111111111111111 27 | *L3696 01111011011111111111111111111111111110111001 28 | *L4312 11111111111111111111111111111111111111111111 29 | *L4356 01111011011111111111111111111111111101111001 30 | *L4884 11111111111111111111111111111111111111111111 31 | *L4928 01111011011111111111111111111111111110110101 32 | *L5368 11111111111111111111111111111111111111111111 33 | *L5412 01111011011101110111011101110111011101110101 34 | *L5808 01010101010101010101 35 | *L5828 0100000101000100010001000101001001011111010001000100010101000011 36 | *C85b1 37 | * 38 | 2304 39 | -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/dtack_decoder.jed: -------------------------------------------------------------------------------- 1 |  2 | Used Program: GALasm 2.1 3 | GAL-Assembler: GALasm 2.1 4 | Device: GAL22V10 5 | 6 | *F0 7 | *G0 8 | *QF5892 9 | *L0044 11111111111111111111111111111111111111111111 10 | *L0088 11111111101111111111101111111111111111111111 11 | *L0132 11111111111111111011111110111111111111111111 12 | *L0176 11111111111111111111101111111111101111111111 13 | *L0220 11111111111111111111111110111011111111111111 14 | *L0264 11111111011111110111111111111111111111111111 15 | *L5808 01000000000000000000 16 | *L5828 0100010001010100010000010100101101011111010001000100010101000011 17 | *C2279 18 | * 19 | 67cf 20 | -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/interrupt_decoder.jed: -------------------------------------------------------------------------------- 1 |  2 | Used Program: GALasm 2.1 3 | GAL-Assembler: GALasm 2.1 4 | Device: GAL22V10 5 | 6 | *F0 7 | *G0 8 | *QF5892 9 | *L0000 11111111111111111111111111111111111111111111 10 | *L0044 11111111111111111111111111111111111111111111 11 | *L0088 01110111011111111111111111111111111111111111 12 | *L0440 11111111111111111111111111111111111111111111 13 | *L0484 11111111111111111011011111111111111111111111 14 | *L0924 11111111111111111111111111111111111111111111 15 | *L0968 11111111111111111111101111111111111111111111 16 | *L1496 11111111111111111111111111111111111111111111 17 | *L1540 11111111111111111111111111111111111111111111 18 | *L2156 11111111111111111111111111111111111111111111 19 | *L2200 01110111011110111111111111111111111101111010 20 | *L2904 11111111111111111111111111111111111111111111 21 | *L2948 01110111011110111111111111111111111110110110 22 | *L3652 11111111111111111111111111111111111111111111 23 | *L3696 11111111111110111111111111111111111111111111 24 | *L5808 01010111010111000000 25 | *L5828 0100100101001110010101000101001001011111010001000100010101000011 26 | *C542a 27 | * 28 | c0ba 29 | -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/mackerel-08-bootloader-v0.1.2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-08/v1.1/mackerel-08-bootloader-v0.1.2.bin -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/mackerel-08-uclinux-v4.4-sd.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-08/v1.1/mackerel-08-uclinux-v4.4-sd.bin -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/mackerel-08-uclinux-v4.4-serial.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-08/v1.1/mackerel-08-uclinux-v4.4-serial.bin -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/mackerel-08-v1.1-BOM.csv: -------------------------------------------------------------------------------- 1 | "Reference","Value","Datasheet","Footprint","Qty","DNP" 2 | "C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17","0.1uF","~","Capacitor_THT:C_Disc_D4.3mm_W1.9mm_P5.00mm","17","" 3 | "C18,C19","1000uF","~","Capacitor_THT:CP_Radial_D10.0mm_P5.00mm","2","" 4 | "C20,C21,C22","10uF","~","Capacitor_THT:CP_Radial_D5.0mm_P2.50mm","3","" 5 | "D1,D2,D4","LED","~","LED_THT:LED_D5.0mm","3","" 6 | "D3","1N5822","~","Diode_THT:D_DO-27_P15.24mm_Horizontal","1","" 7 | "H1,H2,H3,H4","MountingHole","~","MountingHole:MountingHole_3.2mm_M3_Pad","4","" 8 | "HS1","Heatsink","~","Heatsink:Heatsink_Stonecold_HS-S02_13.21x9.53mm","1","" 9 | "J1","Conn_01x08","~","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","1","" 10 | "J2","Conn_02x09_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x09_P2.54mm_Vertical","1","" 11 | "J3,J4","Conn_01x06","~","Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Horizontal","2","" 12 | "J5","Barrel_Jack_MountingPin","~","Connector_BarrelJack:BarrelJack_Horizontal","1","" 13 | "J6,J7,J10","Conn_02x03_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical","3","" 14 | "J8","Conn_02x20_Odd_Even","~","Connector_IDC:IDC-Header_2x20_P2.54mm_Vertical","1","" 15 | "J9","Conn_02x10_Odd_Even","~","Connector_IDC:IDC-Header_2x10_P2.54mm_Vertical","1","" 16 | "L1","100uH","~","Inductor_THT:L_Radial_D10.0mm_P5.00mm_Fastron_07M","1","" 17 | "R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R16,R17,R18,R19","4k7","~","Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder","18","" 18 | "R15,R20,R23","1k","~","Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder","3","" 19 | "R21,R22","10k","~","Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder","2","" 20 | "SW1","SW_Push","~","Button_Switch_THT:SW_PUSH_6mm_H5mm","1","" 21 | "U1","MC68008","","Package_LCC:PLCC-52_THT-Socket","1","" 22 | "U2","74HC595","http://www.ti.com/lit/ds/symlink/sn74hc595.pdf","Package_DIP:DIP-16_W7.62mm","1","" 23 | "U3,U4,U5","ATF22V10C","","Package_DIP:DIP-24_W7.62mm","3","" 24 | "U6,U7,U8,U9,U10,U11,U12","AS6C4008-55PCN","https://www.alliancememory.com/wp-content/uploads/pdf/AS6C4008.pdf","Package_DIP:DIP-32_W15.24mm","7","" 25 | "U13","SST39SF040","","Socket:DIP_Socket-32_W11.9_W12.7_W15.24_W17.78_W18.5_3M_232-1285-00-0602J","1","" 26 | "U14","XR68C681","","Package_LCC:PLCC-44_THT-Socket","1","" 27 | "U15","LM2576T-5","http://www.ti.com/lit/ds/symlink/lm2576.pdf","Package_TO_SOT_THT:TO-220-5_Vertical","1","" 28 | "U16","NE555P","http://www.ti.com/lit/ds/symlink/ne555.pdf","Package_DIP:DIP-8_W7.62mm","1","" 29 | "U17","AP1084","","Package_TO_SOT_SMD:TO-252-2","1","" 30 | "X1,X2","CXO_DIP14","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-14","2","" 31 | -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/mackerel-08-v1.1-gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-08/v1.1/mackerel-08-v1.1-gbr.zip -------------------------------------------------------------------------------- /releases/mackerel-08/v1.1/mackerel-08-v1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-08/v1.1/mackerel-08-v1.1.pdf -------------------------------------------------------------------------------- /releases/mackerel-10/proto/mackerel-10-dram.gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/proto/mackerel-10-dram.gbr.zip -------------------------------------------------------------------------------- /releases/mackerel-10/proto/mackerel-10-dram.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/proto/mackerel-10-dram.pdf -------------------------------------------------------------------------------- /releases/mackerel-10/proto/mackerel-10-proto.gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/proto/mackerel-10-proto.gbr.zip -------------------------------------------------------------------------------- /releases/mackerel-10/proto/mackerel-10-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/proto/mackerel-10-v1.pdf -------------------------------------------------------------------------------- /releases/mackerel-10/v1.1/mackerel-10-v1.1-bom.csv: -------------------------------------------------------------------------------- 1 | "Reference","Value","Datasheet","Footprint","Qty","DNP" 2 | "C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C41,C42,C48","0.1uF","~","Capacitor_THT:C_Disc_D4.3mm_W1.9mm_P5.00mm","37","" 3 | "C17,C18,C19,C20,C40,C49","470uF","~","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","6","" 4 | "C39,C43,C44","1000uF","~","Capacitor_THT:CP_Radial_D10.0mm_P5.00mm","3","" 5 | "C45,C46,C47","10uF","~","-- mixed values --","3","" 6 | "D1,D2,D4","LED","~","LED_THT:LED_D5.0mm","3","" 7 | "D3","1N5822","~","Diode_THT:D_DO-27_P15.24mm_Horizontal","1","" 8 | "HS1","Heatsink","~","Heatsink:Heatsink_Stonecold_HS-S02_13.21x9.53mm","1","" 9 | "J1,J3","Conn_02x05_Odd_Even","~","Connector_IDC:IDC-Header_2x05_P2.54mm_Vertical","2","" 10 | "J2,J10,J11,J12","Conn_02x03_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical","4","" 11 | "J4","Screw_Terminal_01x04","~","TerminalBlock:TerminalBlock_bornier-4_P5.08mm","1","" 12 | "J5,J13","Conn_02x20_Odd_Even","~","-- mixed values --","2","" 13 | "J6,J7","Conn_01x06","~","Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical","2","" 14 | "J8","Conn_02x10_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x10_P2.54mm_Vertical","1","" 15 | "J9","Barrel_Jack_MountingPin","~","Connector_BarrelJack:BarrelJack_Horizontal","1","" 16 | "L1","100uH","~","Inductor_THT:L_Radial_D10.0mm_P5.00mm_Fastron_07M","1","" 17 | "R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R19,R20","4k7","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","19","" 18 | "R18,R21,R24","1k","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","3","" 19 | "R22,R23","10k","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","2","" 20 | "SW1","SW_Push","~","Button_Switch_THT:SW_PUSH_6mm_H5mm","1","" 21 | "U1","68010D","https://www.nxp.com/docs/en/reference-manual/MC68000UM.pdf","Package_DIP:DIP-64_W22.86mm","1","" 22 | "U2,U7,U8,U9,U10,U11","~","","-- mixed values --","6","" 23 | "U3,U5","SST39SF040","http://ww1.microchip.com/downloads/en/DeviceDoc/25022B.pdf","Package_DIP:DIP-32_W15.24mm","2","" 24 | "U4,U6","AS6C4008-55PCN","https://www.alliancememory.com/wp-content/uploads/pdf/AS6C4008.pdf","Package_DIP:DIP-32_W15.24mm","2","" 25 | "U12,U13","74HC245","http://www.ti.com/lit/gpn/sn74HC245","Package_DIP:DIP-20_W7.62mm_Socket","2","" 26 | "U14","XR68C681","","Package_LCC:PLCC-44_THT-Socket","1","" 27 | "U15","LM2576T-5","http://www.ti.com/lit/ds/symlink/lm2576.pdf","Package_TO_SOT_THT:TO-220-5_Vertical","1","" 28 | "U16","AMS1117-3.3","http://www.advanced-monolithic.com/pdf/ds1117.pdf","Package_TO_SOT_SMD:SOT-223-3_TabPin2","1","" 29 | "U17","NE555P","http://www.ti.com/lit/ds/symlink/ne555.pdf","Package_DIP:DIP-8_W7.62mm","1","" 30 | "X1,X2","50MHz","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-14","2","" 31 | "X3","3.6864MHz","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-8","1","" 32 | -------------------------------------------------------------------------------- /releases/mackerel-10/v1.1/mackerel-10-v1.1.gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.1/mackerel-10-v1.1.gbr.zip -------------------------------------------------------------------------------- /releases/mackerel-10/v1.1/mackerel-10-v1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.1/mackerel-10-v1.1.pdf -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/bootloader-v0.2.0-lower.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.2/bootloader-v0.2.0-lower.bin -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/bootloader-v0.2.0-upper.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.2/bootloader-v0.2.0-upper.bin -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/dram_controller.pof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.2/dram_controller.pof -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/mackerel-10-v1.2-BOM.csv: -------------------------------------------------------------------------------- 1 | "Reference","Value","Datasheet","Footprint","Qty","DNP" 2 | "C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C41,C42","0.1uF","~","Capacitor_THT:C_Disc_D4.3mm_W1.9mm_P5.00mm","36","" 3 | "C17,C18,C19,C20,C40,C49","470uF","~","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","6","" 4 | "C39,C43,C44","1000uF","~","Capacitor_THT:CP_Radial_D10.0mm_P5.00mm","3","" 5 | "C45,C46","10uF","~","Capacitor_THT:CP_Radial_D5.0mm_P2.00mm","2","" 6 | "C47","0.01uF","~","Capacitor_THT:C_Disc_D4.3mm_W1.9mm_P5.00mm","1","" 7 | "D1,D2,D4","LED","~","LED_THT:LED_D5.0mm","3","" 8 | "D3","1N5822","~","Diode_THT:D_DO-27_P15.24mm_Horizontal","1","" 9 | "HS1","Heatsink","~","Heatsink:Heatsink_Stonecold_HS-S02_13.21x9.53mm","1","" 10 | "J1,J3","Conn_02x05_Odd_Even","~","Connector_IDC:IDC-Header_2x05_P2.54mm_Vertical","2","" 11 | "J2,J10,J11,J12","Conn_02x03_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical","4","" 12 | "J4","Screw_Terminal_01x04","~","TerminalBlock:TerminalBlock_bornier-4_P5.08mm","1","" 13 | "J5,J13","Conn_02x20_Odd_Even","~","-- mixed values --","2","" 14 | "J6,J7","Conn_01x06","~","Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical","2","" 15 | "J8","Conn_02x10_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x10_P2.54mm_Vertical","1","" 16 | "J9","Barrel_Jack_MountingPin","~","Connector_BarrelJack:BarrelJack_Horizontal","1","" 17 | "L1","100uH","~","Inductor_THT:L_Radial_D10.0mm_P5.00mm_Fastron_07M","1","" 18 | "R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R19,R20","4k7","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","19","" 19 | "R18,R21,R22","1k","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","3","" 20 | "SW1","SW_Push","~","Button_Switch_THT:SW_PUSH_6mm_H5mm","1","" 21 | "U1","68010D","https://www.nxp.com/docs/en/reference-manual/MC68000UM.pdf","Package_DIP:DIP-64_W22.86mm","1","" 22 | "U2,U7,U8,U9,U10,U11","~","","-- mixed values --","6","" 23 | "U3,U5","SST39SF040","http://ww1.microchip.com/downloads/en/DeviceDoc/25022B.pdf","Package_DIP:DIP-32_W15.24mm","2","" 24 | "U4,U6","AS6C4008-55PCN","https://www.alliancememory.com/wp-content/uploads/pdf/AS6C4008.pdf","Package_DIP:DIP-32_W15.24mm","2","" 25 | "U12,U13","74HC245","http://www.ti.com/lit/gpn/sn74HC245","Package_DIP:DIP-20_W7.62mm_Socket","2","" 26 | "U14","XR68C681","","Package_LCC:PLCC-44_THT-Socket","1","" 27 | "U15","LM2576T-5","http://www.ti.com/lit/ds/symlink/lm2576.pdf","Package_TO_SOT_THT:TO-220-5_Vertical","1","" 28 | "U16","AMS1117-3.3","http://www.advanced-monolithic.com/pdf/ds1117.pdf","Package_TO_SOT_SMD:SOT-223-3_TabPin2","1","" 29 | "U17","DS1233","","Package_TO_SOT_THT:TO-92L_Inline","1","" 30 | "X1,X2","50MHz","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-14","2","" 31 | "X3","3.6864MHz","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-8","1","" 32 | -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/mackerel-10-v1.2.gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.2/mackerel-10-v1.2.gbr.zip -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/mackerel-10-v1.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.2/mackerel-10-v1.2.pdf -------------------------------------------------------------------------------- /releases/mackerel-10/v1.2/system-controller.pof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1.2/system-controller.pof -------------------------------------------------------------------------------- /releases/mackerel-10/v1/mackerel-10-v1.gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1/mackerel-10-v1.gbr.zip -------------------------------------------------------------------------------- /releases/mackerel-10/v1/mackerel-10-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-10/v1/mackerel-10-v1.pdf -------------------------------------------------------------------------------- /releases/mackerel-30/v0.1/mackerel-30-proto.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-30/v0.1/mackerel-30-proto.pdf -------------------------------------------------------------------------------- /releases/mackerel-30/v0.1/mackerel-30-v0.1-BOM.csv: -------------------------------------------------------------------------------- 1 | "Reference","Value","Datasheet","Footprint","Qty","DNP" 2 | "C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C29,C30,C31,C32,C33,C34,C35,C36,C38,C39,C40,C42,C43,C44,C45,C46,C47,C48,C49,C50,C51,C54,C55,C56","0.1uF","~","-- mixed values --","46","" 3 | "C11,C37,C41,C52,C53,C57","470uF","~","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","6","" 4 | "C24,C26","1000uF","~","Capacitor_THT:CP_Radial_D10.0mm_P5.00mm","2","" 5 | "C25,C27","10uF","~","Capacitor_THT:CP_Radial_D5.0mm_P2.00mm","2","" 6 | "C28","0.01uF","~","Capacitor_THT:C_Disc_D4.3mm_W1.9mm_P5.00mm","1","" 7 | "D1,D3,D4","LED","~","LED_THT:LED_D5.0mm","3","" 8 | "D2","1N5822","~","Diode_THT:D_DO-27_P15.24mm_Horizontal","1","" 9 | "HS1","Heatsink","~","Heatsink:Heatsink_Stonecold_HS-S02_13.21x9.53mm","1","" 10 | "J1,J2","Conn_01x02","~","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","2","" 11 | "J3,J11","Conn_02x05_Odd_Even","~","Connector_IDC:IDC-Header_2x05_P2.54mm_Vertical","2","" 12 | "J4,J5","Conn_01x06","~","Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical","2","" 13 | "J6","Conn_02x10_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x10_P2.54mm_Vertical","1","" 14 | "J7","Barrel_Jack_MountingPin","~","Connector_BarrelJack:BarrelJack_Horizontal","1","" 15 | "J8,J9,J10","Conn_02x03_Odd_Even","~","Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical","3","" 16 | "J12","Screw_Terminal_01x04","~","TerminalBlock:TerminalBlock_bornier-4_P5.08mm","1","" 17 | "J13","Conn_02x20_Odd_Even","~","Connector_IDC:IDC-Header_2x20_P2.54mm_Vertical","1","" 18 | "J14","DIN41612_03x32_ABC","~","Connector_DIN:DIN41612_C_3x32_Female_Vertical_THT","1","" 19 | "J15","Conn_01x05","~","Connector_PinHeader_2.54mm:PinHeader_1x05_P2.54mm_Vertical","1","" 20 | "L1","100uH","~","Inductor_THT:L_Radial_D10.0mm_P5.00mm_Fastron_07M","1","" 21 | "R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R19,R20,R21,R22,R23,R24,R25,R26,R28,R29","4k7","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","26","" 22 | "R17,R18,R27","1k","~","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","3","" 23 | "SW1","SW_Push","~","Button_Switch_THT:SW_PUSH_6mm_H5mm","1","" 24 | "U1","MC68030RC","","mackerel:PGA169","1","" 25 | "U2,U9","EPM7128","","Package_LCC:PLCC-84_THT-Socket","2","" 26 | "U3","SST39SF040","http://ww1.microchip.com/downloads/en/DeviceDoc/25022B.pdf","Package_DIP:DIP-32_W15.24mm_Socket","1","" 27 | "U4","AS6C4008-55PCN","https://www.alliancememory.com/wp-content/uploads/pdf/AS6C4008.pdf","Package_DIP:DIP-32_W15.24mm_Socket","1","" 28 | "U5","XR68C681","","Package_LCC:PLCC-44_THT-Socket","1","" 29 | "U6","LM2576T-5","http://www.ti.com/lit/ds/symlink/lm2576.pdf","Package_TO_SOT_THT:TO-220-5_Vertical","1","" 30 | "U7","AMS1117-3.3","http://www.advanced-monolithic.com/pdf/ds1117.pdf","Package_TO_SOT_SMD:SOT-223-3_TabPin2","1","" 31 | "U8","DS1233","","Package_TO_SOT_THT:TO-92L_Inline","1","" 32 | "U10","SIMM72","","mackerel:SIMM-72","1","" 33 | "U11","MC68882","","Package_LCC:PLCC-68_THT-Socket","1","" 34 | "U12,U13,U14,U15,U16","74HC245","http://www.ti.com/lit/gpn/sn74HC245","Package_DIP:DIP-20_W7.62mm_Socket","5","" 35 | "X1,X3","CXO_DIP14","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-14","2","" 36 | "X2","3.6864MHz","http://cdn-reichelt.de/documents/datenblatt/B400/OSZI.pdf","Oscillator:Oscillator_DIP-8","1","" 37 | -------------------------------------------------------------------------------- /releases/mackerel-30/v0.1/mackerel-30-v0.1.gbr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crmaykish/mackerel-68k/1ce0e3ca3313f8b16f17cccdbe138d44fec8fbc2/releases/mackerel-30/v0.1/mackerel-30-v0.1.gbr.zip -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | Baselibc 2 | gcc* 3 | binutils* 4 | -------------------------------------------------------------------------------- /tools/build_cross_compiler.sh: -------------------------------------------------------------------------------- 1 | # This script will build a cross-compiler for Mackerel. It uses a modern gcc and binutils version. 2 | # I tested this script on Debian 12 and Arch. 3 | # Note: the cross-compiler built by this script will build the bootloader and other bare-metal programs. 4 | # It will not build Linux/uClinux. 5 | 6 | #!/bin/sh 7 | 8 | set -e 9 | 10 | export PREFIX="/home/$(whoami)/mackerel/cross" 11 | export TARGET=m68k-mackerel-elf 12 | export PATH="$PREFIX/bin:$PATH" 13 | 14 | BINUTILS_VERSION="2.44" 15 | GCC_VERSION="14.2.0" 16 | 17 | log_message() { 18 | echo "" 19 | echo "=======================================" 20 | echo "$1" 21 | echo "=======================================" 22 | } 23 | 24 | rm -rf binutils* gcc* Baselibc 25 | 26 | # Download binutils 27 | log_message "Downloading binutils version ${BINUTILS_VERSION}" 28 | wget -q "http://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VERSION}.tar.gz" 29 | 30 | log_message "Building binutils ${BINUTILS_VERSION}" 31 | 32 | tar xzf "binutils-${BINUTILS_VERSION}.tar.gz" 33 | cd "binutils-${BINUTILS_VERSION}" 34 | mkdir build 35 | cd build 36 | ../configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror 37 | make -j $(nproc) 38 | make install 39 | 40 | log_message "Installed binutils ${BINUTILS_VERSION} to $PREFIX" 41 | 42 | cd ../../ 43 | 44 | 45 | # Download and build gcc 46 | log_message "Downloading gcc version ${GCC_VERSION}" 47 | wget -q "http://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.gz" 48 | 49 | log_message "Building gcc ${GCC_VERSION}" 50 | tar xzf "gcc-${GCC_VERSION}.tar.gz" 51 | cd "gcc-${GCC_VERSION}" 52 | mkdir build 53 | cd build 54 | ../configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers 55 | make -j $(nproc) all-gcc 56 | make -j $(nproc) all-target-libgcc 57 | make install-gcc 58 | make install-target-libgcc 59 | 60 | log_message "Installed gcc ${GCC_VERSION} to $PREFIX" 61 | 62 | cd ../../ 63 | 64 | log_message "Installing Baselibc" 65 | 66 | git clone https://github.com/crmaykish/Baselibc.git 67 | cd Baselibc 68 | 69 | make PLATFORM=mackerel 70 | cp -r include/ "${PREFIX}/${TARGET}/" 71 | cp libc.a "${PREFIX}/${TARGET}/lib/" 72 | 73 | log_message "Installed Baselibc" 74 | 75 | cd ../ 76 | 77 | log_message "Cleaning up" 78 | 79 | rm -rf binutils* gcc* Baselibc 80 | 81 | log_message "Done! Add ${PREFIX}/bin to your PATH to use the ${TARGET} tools." 82 | 83 | set +e 84 | -------------------------------------------------------------------------------- /tools/format_disk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$(id -u)" -ne 0 ]; then 4 | echo "This script must be run with sudo privileges." 5 | exit 1 6 | fi 7 | 8 | if [ -z "$1" ]; then 9 | echo "Usage: $0 " 10 | exit 1 11 | fi 12 | 13 | drive="$1" 14 | 15 | echo "Warning! This will erase all data on the $drive" 16 | read -p "Proceed? (yes/no): " confirm 17 | 18 | if [[ "$confirm" != "yes" && "$confirm" != "y" ]]; then 19 | echo "Exiting." 20 | exit 1 21 | fi 22 | 23 | # Create a new MS-DOS partition table 24 | parted --script $drive mklabel msdos 25 | 26 | # Create a 64 MB FAT16 partition 27 | parted --script $drive mkpart primary fat16 0% 64MB 28 | 29 | # Create a 1 GB ext2 partition 30 | parted --script $drive mkpart primary ext2 64MB 1064MB 31 | 32 | mkfs.fat -F 16 ${drive}1 33 | mkfs.ext2 ${drive}2 34 | 35 | fdisk -l $drive 36 | 37 | echo "Formatting completed on: $drive" 38 | -------------------------------------------------------------------------------- /tools/install_reqs_arch.sh: -------------------------------------------------------------------------------- 1 | echo "Installing required packages for Mackerel-68k build tools" 2 | 3 | sudo pacman -S --noconfirm base-devel wget unzip git bc 4 | -------------------------------------------------------------------------------- /tools/install_reqs_deb.sh: -------------------------------------------------------------------------------- 1 | echo "Installing required packages for Mackerel-68k build tools" 2 | 3 | sudo apt-get update 4 | sudo apt-get install -y build-essential flex bison libgmp3-dev libmpc-dev libmpfr-dev texinfo wget libncurses5-dev bc genromfs unzip git 5 | 6 | echo "Done!" 7 | -------------------------------------------------------------------------------- /tools/mackerel_crosstools_defconfig: -------------------------------------------------------------------------------- 1 | CT_CONFIG_VERSION="4" 2 | CT_ARCH_M68K=y 3 | CT_STATIC_TOOLCHAIN=y 4 | CT_TARGET_VENDOR="mackerel" 5 | CT_KERNEL_LINUX=y 6 | CT_LINUX_SRC_DEVEL=y 7 | CT_LINUX_DEVEL_URL="https://github.com/crmaykish/mackerel-linux-mmu.git" 8 | CT_LINUX_DEVEL_BRANCH="mackerel-30-config" 9 | --------------------------------------------------------------------------------