# KRZ SoC Kronos Zero Degree (KRZ) is the System-on-Chip packaged in this project to show-off the Kronos core. It is designed for the iCE40UP5K with the following features. - 24MHz system clock. - 128KB of RAM as 2 contiguous banks of 64KB. - 1KB Bootrom for loading program from flash to RAM. - UART TX with 128B buffer. - Configurable baud rate - SPI Master with 256B RX/TX buffers. - Configurable SPI Mode and rate. - Max 12MHz. - 12 Bidirectional configurable GPIO. - Debounced inputs. - 32-bit General Purpose registers ![KRZ SoC](_images/krz_soc.svg) The bootrom, and two 64KB banks of main memory are individually arbitrated. The Kronos Instruction Bus and Data Bus can access different parts of the memory simultaneously without halting each other. They can access the entire memory, and only need to be arbitrated if they are accessing the same section. But, usually, most of the code should be run from bank0, while frequent data like the stack will be in bank1. In a design without cache, this setup will lead to optimal performance. KRZ SoC has the Kronos configured with: - BOOT_ADDR = 0x00 - FAST_BRANCH = 1 - EN_COUNTERS = 1 - EN_COUNTERS64B = 0 - CATCH_ILLEGAL_INSTR = 1 - CATCH_MISALIGNED_JMP = 0 - CATCH_MISALIGNED_LDST = 0 ## Memory Map Address | Section --------|---------- 0x000000 - 0x000400 | 1KB Boot ROM 0x010000 - 0x02ffff | 128KB RAM (split into two individually accessible 64KB banks) 0x800000 | Scratch 0x800004 | Bootvec 0x800008 | GPIO Direction 0x80000C | GPIO Write value 0x800010 | GPIO Read value 0x800014 | UART Control 0x800018 | UART Status 0x80001C | SPIM Control 0x800020 | SPIM Status 0x800100 | UART TX 0x800200 | SPIM RX/TX ###### Scratch 32b general purpose register. Get creative with it. ###### Bootvec The Bootvec register can be used for runtime warmboot. The application can write an address (in the flash) into the `bootvec` and jump to the bootrom start address (0x000000). ###### GPIO 12-bit General Purpose IO controls. GPIO Direction (0=Read - default, 1=Write) sets the config for the bidirectional GPIO. The read value is debounced in hardware to make life just that much easier. ###### UART The UART Control register is used to set the 12-b prescaler, and can clear the TX queue on demand. ``` baud rate (default 115200) = clk/(prescaler+1) 12 11 0 bit +----------+-----------+ | tx clear | prescaler | UART_CTRL +----------+-----------+ 7 0 bit +----------+ | TXQ size | UART_STATUS +----------+ ``` The UART Status reports the current TX queue size (8-bit). Write to the UART peripheral at the UART TX address, `0x800100`. The access should be byte-wide. ###### SPIM The SPI Master Control register is used to set the 8-b prescaler and SPI Mode (CPOL, CPHA). As well as clearing the RX/TX Queues. The SPI Master status register reports the queue sizes ``` SPI clock rate = clk/(2 * prescaler+1) 11 10 9 8 7 0 bit +----------+----------+------+------+-----------+ | rx clear | tx clear | cpha | cpol | prescaler | SPIM_CTRL +----------+----------+------+------+-----------+ 15 7 0 bit +----------+----------+ | RXQ size | TXQ size | SPIM_STATUS +----------+----------+ ``` Read/Write to the SPIM peripheral at the SPIM address, `0x800200`. The access should be byte-wide. ## Build using Radiant From the root of the kronos project, build the project for release. This does require having the riscv toolchain in your PATH. ``` mkdir build cd build cmake .. ``` Next, build the bootloader program. ``` make riscv-krz_bootloader # generates output/data/krz_bootloader.mem ``` When building the project, a run script for [Lattice Radiant](http://www.latticesemi.com/Products/DesignSoftwareAndIP/FPGAandLDS/Radiant) is configured. There should be a script per platform in the `output/radiant` directory. In this example, I am building for the `iCEBreaker`. Launch Radiant with it and go through the implementation flow, and export the gateware. ``` radiant -t output/radiant/krz_icebreaker/build_krz.tcl ``` Look for the `FX276` messages in the synthesis log to ensure that the BRAMs are properly initialized with the compiled bootloader. Finally flash the iCEBreaker using [iceprog](https://github.com/cliffordwolf/icestorm/tree/master/iceprog). ``` iceprog output/radiant/krz_icebreaker/krz_impl/krz_icebreaker_krz_impl.bin ``` ## Flashing Programs The KRZ can boot any program from the attached flash (as long as it fits within the 128KB RAM). The project already comes a demo program for the iCEBreaker - [krz_blinky](https://github.com/SonalPinto/kronos/tree/master/src/krz) - which interfaces with the 3 button + 5 LED PMOD that comes default with every iCEBreaker board. > [Linker Script](https://github.com/SonalPinto/kronos/blob/master/src/krz/link.ld) Build app. The compiled binary is prepended with the program size with a tiny python script ([krz_prog](https://github.com/SonalPinto/kronos/blob/master/utils/krzprog.py)) to get the flashable image. So, if you build your own code, use `krz_prog` to process it. ``` > make krz-riscv-krz_blinky processing /home/sonal/work/kronos/build/output/data/krz_blinky.bin program size: 2064 bytes Ready to Flash: /home/sonal/work/kronos/build/output/data/krz_blinky.krz.bin ``` Finally, use iceprog to burn the flash with the application. The default flashboot vector is at `0x00100000`. ``` iceprog -o 1M output/data/krz_blinky.krz.bin ``` And that's it! Open a terminal on the second channel on the iCEBreaker's FTDI (I use pyterm) to see the prints. ``` ____ __. | |/ _|______ ____ ____ ____ ______ | < \_ __ \/ _ \ / \ / _ \/ ___/ | | \ | | \( <_> ) | ( <_> )___ \ |____|__ \|__| \____/|___| /\____/____ > \/ \/ \/ BTN[0][0][0] BTN[0][0][0] BTN[0][0][0] ```