--- /dev/null
+/* This code is directly from Microwatt and is Copyright and Licensed
+ under the same terms as Microwatt source code.
+ https://github.com/antonblanchard/microwatt/blob/master/include/console.h
+*/
+
+#include <stddef.h>
+
+void console_init(void);
+void console_set_irq_en(bool rx_irq, bool tx_irq);
+int getchar(void);
+int putchar(int c);
+int puts(const char *str);
+
+#ifndef __USE_LIBC
+size_t strlen(const char *s);
+#endif
--- /dev/null
+/* This code is directly from Microwatt and is Copyright and Licensed
+ under the same terms as Microwatt source code.
+ https://github.com/antonblanchard/microwatt/blob/master/include/io.h
+*/
+
+#ifndef __IO_H
+#define __IO_H
+
+static inline uint8_t readb(unsigned long addr)
+{
+ uint8_t val;
+ __asm__ volatile("sync; lbzcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
+ return val;
+}
+
+static inline uint16_t readw(unsigned long addr)
+{
+ uint16_t val;
+ __asm__ volatile("sync; lhzcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
+ return val;
+}
+
+static inline uint32_t readl(unsigned long addr)
+{
+ uint32_t val;
+ __asm__ volatile("sync; lwzcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
+ return val;
+}
+
+static inline uint64_t readq(unsigned long addr)
+{
+ uint64_t val;
+ __asm__ volatile("sync; ldcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
+ return val;
+}
+
+static inline void writeb(uint8_t val, unsigned long addr)
+{
+ __asm__ volatile("sync; stbcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void writew(uint16_t val, unsigned long addr)
+{
+ __asm__ volatile("sync; sthcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void writel(uint32_t val, unsigned long addr)
+{
+ __asm__ volatile("sync; stwcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void writeq(uint64_t val, unsigned long addr)
+{
+ __asm__ volatile("sync; stdcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
+}
+
+#endif /* __IO_H */
+
--- /dev/null
+/* This code is directly from Microwatt and is Copyright and Licensed
+ under the same terms as Microwatt source code.
+https://github.com/antonblanchard/microwatt/blob/master/include/microwatt_soc.h
+*/
+
+#ifndef __MICROWATT_SOC_H
+#define __MICROWATT_SOC_H
+
+/*
+ * Microwatt SoC memory map
+ */
+
+#define MEMORY_BASE 0x00000000 /* "Main" memory alias, either BRAM or DRAM */
+#define DRAM_BASE 0x40000000 /* DRAM if present */
+#define BRAM_BASE 0x80000000 /* Internal BRAM */
+
+#define SYSCON_BASE 0xc0000000 /* System control regs */
+#define UART_BASE 0xc0002000 /* UART */
+#define XICS_ICP_BASE 0xc0004000 /* Interrupt controller */
+#define XICS_ICS_BASE 0xc0005000 /* Interrupt controller */
+#define SPI_FCTRL_BASE 0xc0006000 /* SPI flash controller registers */
+#define DRAM_CTRL_BASE 0xc8000000 /* LiteDRAM control registers */
+#define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */
+#define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */
+#define SPI_FLASH_BASE 0xf0000000 /* SPI Flash memory map */
+#ifdef STANDALONE_MINI_BIOS
+#define DRAM_INIT_BASE 0x00000000 /* alternative, for verilator simulation */
+#else
+#define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */
+#endif
+
+/*
+ * Interrupt numbers
+ */
+#define IRQ_UART0 0
+#define IRQ_ETHERNET 1
+
+/*
+ * Register definitions for the syscon registers
+ */
+
+#define SYS_REG_SIGNATURE 0x00
+#define SYS_REG_INFO 0x08
+#define SYS_REG_INFO_HAS_UART (1ull << 0)
+#define SYS_REG_INFO_HAS_DRAM (1ull << 1)
+#define SYS_REG_INFO_HAS_BRAM (1ull << 2)
+#define SYS_REG_INFO_HAS_SPI_FLASH (1ull << 3)
+#define SYS_REG_INFO_HAS_LITEETH (1ull << 4)
+#define SYS_REG_INFO_HAS_LARGE_SYSCON (1ull << 5)
+#define SYS_REG_INFO_HAS_UART1 (1ull << 6)
+#define SYS_REG_INFO_HAS_ARTB (1ull << 7)
+#define SYS_REG_BRAMINFO 0x10
+#define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull
+#define SYS_REG_DRAMINFO 0x18
+#define SYS_REG_DRAMINFO_SIZE_MASK 0xfffffffffffffull
+#define SYS_REG_CLKINFO 0x20
+#define SYS_REG_CLKINFO_FREQ_MASK 0xffffffffffull
+#define SYS_REG_CTRL 0x28
+#define SYS_REG_CTRL_DRAM_AT_0 (1ull << 0)
+#define SYS_REG_CTRL_CORE_RESET (1ull << 1)
+#define SYS_REG_CTRL_SOC_RESET (1ull << 2)
+#define SYS_REG_DRAMINITINFO 0x30
+#define SYS_REG_SPI_INFO 0x38
+#define SYS_REG_SPI_INFO_FLASH_OFF_MASK 0xffffffff
+#define SYS_REG_UART0_INFO 0x40
+#define SYS_REG_UART1_INFO 0x48
+#define SYS_REG_UART_IS_16550 (1ull << 32)
+#define SYS_REG_BRAM_BOOTADDR 0x50
+
+
+/*
+ * Register definitions for the potato UART
+ */
+#define POTATO_CONSOLE_TX 0x00
+#define POTATO_CONSOLE_RX 0x08
+#define POTATO_CONSOLE_STATUS 0x10
+#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
+#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
+#define POTATO_CONSOLE_STATUS_RX_FULL 0x04
+#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
+#define POTATO_CONSOLE_CLOCK_DIV 0x18
+#define POTATO_CONSOLE_IRQ_EN 0x20
+#define POTATO_CONSOLE_IRQ_RX 0x01
+#define POTATO_CONSOLE_IRQ_TX 0x02
+
+/*
+ * Register definitionss for our standard (16550 style) UART
+ */
+#define UART_REG_RX 0x00
+#define UART_REG_TX 0x00
+#define UART_REG_DLL 0x00
+#define UART_REG_IER 0x04
+#define UART_REG_IER_RDI 0x01
+#define UART_REG_IER_THRI 0x02
+#define UART_REG_IER_RLSI 0x04
+#define UART_REG_IER_MSI 0x08
+#define UART_REG_DLM 0x04
+#define UART_REG_IIR 0x08
+#define UART_REG_FCR 0x08
+#define UART_REG_FCR_EN_FIFO 0x01
+#define UART_REG_FCR_CLR_RCVR 0x02
+#define UART_REG_FCR_CLR_XMIT 0x04
+#define UART_REG_FCR_TRIG1 0x00
+#define UART_REG_FCR_TRIG4 0x40
+#define UART_REG_FCR_TRIG8 0x80
+#define UART_REG_FCR_TRIG14 0xc0
+#define UART_REG_LCR 0x0c
+#define UART_REG_LCR_5BIT 0x00
+#define UART_REG_LCR_6BIT 0x01
+#define UART_REG_LCR_7BIT 0x02
+#define UART_REG_LCR_8BIT 0x03
+#define UART_REG_LCR_STOP 0x04
+#define UART_REG_LCR_PAR 0x08
+#define UART_REG_LCR_EVEN_PAR 0x10
+#define UART_REG_LCR_STIC_PAR 0x20
+#define UART_REG_LCR_BREAK 0x40
+#define UART_REG_LCR_DLAB 0x80
+#define UART_REG_MCR 0x10
+#define UART_REG_MCR_DTR 0x01
+#define UART_REG_MCR_RTS 0x02
+#define UART_REG_MCR_OUT1 0x04
+#define UART_REG_MCR_OUT2 0x08
+#define UART_REG_MCR_LOOP 0x10
+#define UART_REG_LSR 0x14
+#define UART_REG_LSR_DR 0x01
+#define UART_REG_LSR_OE 0x02
+#define UART_REG_LSR_PE 0x04
+#define UART_REG_LSR_FE 0x08
+#define UART_REG_LSR_BI 0x10
+#define UART_REG_LSR_THRE 0x20
+#define UART_REG_LSR_TEMT 0x40
+#define UART_REG_LSR_FIFOE 0x80
+#define UART_REG_MSR 0x18
+#define UART_REG_SCR 0x1c
+
+
+/*
+ * Register definitions for the SPI controller
+ */
+#define SPI_REG_DATA 0x00 /* Byte access: single wire transfer */
+#define SPI_REG_DATA_DUAL 0x01 /* Byte access: dual wire transfer */
+#define SPI_REG_DATA_QUAD 0x02 /* Byte access: quad wire transfer */
+#define SPI_REG_CTRL 0x04 /* Reset and manual mode control */
+#define SPI_REG_CTRL_RESET 0x01 /* reset all registers */
+#define SPI_REG_CTRL_MANUAL_CS 0x02 /* assert CS, enable manual mode */
+#define SPI_REG_CTRL_CKDIV_SHIFT 8 /* clock div */
+#define SPI_REG_CTRL_CKDIV_MASK (0xff << SPI_REG_CTRL_CKDIV_SHIFT)
+#define SPI_REG_AUTO_CFG 0x08 /* Automatic map configuration */
+#define SPI_REG_AUTO_CFG_CMD_SHIFT 0 /* Command to use for reads */
+#define SPI_REG_AUTO_CFG_CMD_MASK (0xff << SPI_REG_AUTO_CFG_CMD_SHIFT)
+#define SPI_REG_AUTO_CFG_DUMMIES_SHIFT 8 /* # dummy cycles */
+#define SPI_REG_AUTO_CFG_DUMMIES_MASK (0x7 << SPI_REG_AUTO_CFG_DUMMIES_SHIFT)
+#define SPI_REG_AUTO_CFG_MODE_SHIFT 11 /* SPI wire mode */
+#define SPI_REG_AUTO_CFG_MODE_MASK (0x3 << SPI_REG_AUTO_CFG_MODE_SHIFT)
+#define SPI_REG_AUT_CFG_MODE_SINGLE (0 << 11)
+#define SPI_REG_AUT_CFG_MODE_DUAL (2 << 11)
+#define SPI_REG_AUT_CFG_MODE_QUAD (3 << 11)
+#define SPI_REG_AUTO_CFG_ADDR4 (1u << 13) /* 3 or 4 addr bytes */
+#define SPI_REG_AUTO_CFG_CKDIV_SHIFT 16 /* clock div */
+#define SPI_REG_AUTO_CFG_CKDIV_MASK (0xff << SPI_REG_AUTO_CFG_CKDIV_SHIFT)
+#define SPI_REG_AUTO_CFG_CSTOUT_SHIFT 24 /* CS timeout */
+#define SPI_REG_AUTO_CFG_CSTOUT_MASK (0x3f << SPI_REG_AUTO_CFG_CSTOUT_SHIFT)
+
+
+#endif /* __MICROWATT_SOC_H */
--- /dev/null
+/* This code is directly from Microwatt and is Copyright and Licensed
+ under the same terms as Microwatt source code.
+ https://github.com/antonblanchard/microwatt/blob/master/lib/console.c
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "console.h"
+#include "microwatt_soc.h"
+#include "io.h"
+
+#define UART_BAUDS 115200
+
+/*
+ * Core UART functions to implement for a port
+ */
+
+bool uart_is_std;
+
+static uint64_t uart_base;
+
+static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds)
+{
+ return uart_freq / (bauds * 16);
+}
+
+static uint64_t potato_uart_reg_read(int offset)
+{
+ return readq(uart_base + offset);
+}
+
+static void potato_uart_reg_write(int offset, uint64_t val)
+{
+ writeq(val, uart_base + offset);
+}
+
+static int potato_uart_rx_empty(void)
+{
+ uint64_t val;
+
+ val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
+
+ if (val & POTATO_CONSOLE_STATUS_RX_EMPTY)
+ return 1;
+
+ return 0;
+}
+
+static int potato_uart_tx_full(void)
+{
+ uint64_t val;
+
+ val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
+
+ if (val & POTATO_CONSOLE_STATUS_TX_FULL)
+ return 1;
+
+ return 0;
+}
+
+static char potato_uart_read(void)
+{
+ uint64_t val;
+
+ val = potato_uart_reg_read(POTATO_CONSOLE_RX);
+
+ return (char)(val & 0x000000ff);
+}
+
+static void potato_uart_write(char c)
+{
+ uint64_t val;
+
+ val = c;
+
+ potato_uart_reg_write(POTATO_CONSOLE_TX, val);
+}
+
+static void potato_uart_init(uint64_t uart_freq)
+{
+ unsigned long div = uart_divisor(uart_freq, UART_BAUDS) - 1;
+ potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, div);
+}
+
+static void potato_uart_set_irq_en(bool rx_irq, bool tx_irq)
+{
+ uint64_t en = 0;
+
+ if (rx_irq)
+ en |= POTATO_CONSOLE_IRQ_RX;
+ if (tx_irq)
+ en |= POTATO_CONSOLE_IRQ_TX;
+ potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, en);
+}
+
+static bool std_uart_rx_empty(void)
+{
+ return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_DR);
+}
+
+static uint8_t std_uart_read(void)
+{
+ return readb(uart_base + UART_REG_RX);
+}
+
+static bool std_uart_tx_full(void)
+{
+ return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_THRE);
+}
+
+static void std_uart_write(uint8_t c)
+{
+ writeb(c, uart_base + UART_REG_TX);
+}
+
+static void std_uart_set_irq_en(bool rx_irq, bool tx_irq)
+{
+ uint8_t ier = 0;
+
+ if (tx_irq)
+ ier |= UART_REG_IER_THRI;
+ if (rx_irq)
+ ier |= UART_REG_IER_RDI;
+ writeb(ier, uart_base + UART_REG_IER);
+}
+
+static void std_uart_init(uint64_t uart_freq)
+{
+ unsigned long div = uart_divisor(uart_freq, UART_BAUDS);
+
+ writeb(UART_REG_LCR_DLAB, uart_base + UART_REG_LCR);
+ writeb(div & 0xff, uart_base + UART_REG_DLL);
+ writeb(div >> 8, uart_base + UART_REG_DLM);
+ writeb(UART_REG_LCR_8BIT, uart_base + UART_REG_LCR);
+ writeb(UART_REG_MCR_DTR |
+ UART_REG_MCR_RTS, uart_base + UART_REG_MCR);
+ writeb(UART_REG_FCR_EN_FIFO |
+ UART_REG_FCR_CLR_RCVR |
+ UART_REG_FCR_CLR_XMIT, uart_base + UART_REG_FCR);
+}
+
+int getchar(void)
+{
+ if (uart_is_std) {
+ while (std_uart_rx_empty())
+ /* Do nothing */ ;
+ return std_uart_read();
+ } else {
+ while (potato_uart_rx_empty())
+ /* Do nothing */ ;
+ return potato_uart_read();
+ }
+}
+
+int putchar(int c)
+{
+ if (uart_is_std) {
+ while(std_uart_tx_full())
+ /* Do Nothing */;
+ std_uart_write(c);
+ } else {
+ while (potato_uart_tx_full())
+ /* Do Nothing */;
+ potato_uart_write(c);
+ }
+ return c;
+}
+
+int puts(const char *str)
+{
+ unsigned int i;
+
+ for (i = 0; *str; i++) {
+ char c = *(str++);
+ if (c == 10)
+ putchar(13);
+ putchar(c);
+ }
+ return 0;
+}
+
+#ifndef __USE_LIBC
+size_t strlen(const char *s)
+{
+ size_t len = 0;
+
+ while (*s++)
+ len++;
+
+ return len;
+}
+#endif
+
+void console_init(void)
+{
+ uint64_t sys_info;
+ uint64_t proc_freq;
+ uint64_t uart_info = 0;
+ uint64_t uart_freq = 0;
+
+ proc_freq = readq(SYSCON_BASE + SYS_REG_CLKINFO) & SYS_REG_CLKINFO_FREQ_MASK;
+ sys_info = readq(SYSCON_BASE + SYS_REG_INFO);
+
+ if (sys_info & SYS_REG_INFO_HAS_LARGE_SYSCON) {
+ uart_info = readq(SYSCON_BASE + SYS_REG_UART0_INFO);
+ uart_freq = uart_info & 0xffffffff;
+ }
+ if (uart_freq == 0)
+ uart_freq = proc_freq;
+
+ uart_base = UART_BASE;
+ if (uart_info & SYS_REG_UART_IS_16550) {
+ uart_is_std = true;
+ std_uart_init(proc_freq);
+ } else {
+ uart_is_std = false;
+ potato_uart_init(proc_freq);
+ }
+}
+
+void console_set_irq_en(bool rx_irq, bool tx_irq)
+{
+ if (uart_is_std)
+ std_uart_set_irq_en(rx_irq, tx_irq);
+ else
+ potato_uart_set_irq_en(rx_irq, tx_irq);
+}
from gram.core import gramCore
from gram.phy.ecp5ddrphy import ECP5DDRPHY
-from gram.modules import MT41K256M16
+from gram.modules import MT41K256M16, MT41K64M16
from gram.frontend.wishbone import gramWishbone
from nmigen_boards.versa_ecp5 import VersaECP5Platform
class DDR3SoC(SoC, Elaboratable):
def __init__(self, *,
+ dram_cls,
uart_pins, ddr_pins,
ddrphy_addr, dramcore_addr,
ddr_addr, fw_addr=0x0000_0000,
'ulx3s': 'Trellis',
'sim': None,
}.get(fpga, None)
+ dram_cls = {'arty_a7': None,
+ 'versa_ecp5': MT41K64M16,
+ 'ulx3s': None,
+ 'sim': None,
+ }.get(fpga, None)
if platform_kls is not None:
platform = platform_kls(toolchain=toolchain)
else:
# get DDR resource pins
ddr_pins = None
- if False and platform is not None and fpga in ['versa_ecp5', 'arty_a7']:
+ if platform is not None and fpga in ['versa_ecp5', 'arty_a7']:
ddr_pins = platform.request("ddr3", 0,
dir={"dq":"-", "dqs":"-"},
xdr={"clk":4, "a":4, "ba":4, "clk_en":4,
"odt":4, "ras":4, "cas":4, "we":4})
# set up the SOC
- soc = DDR3SoC(ddrphy_addr=0xff000000, # DRAM firmware init base
+ soc = DDR3SoC(dram_cls,
+ ddrphy_addr=0xff000000, # DRAM firmware init base
dramcore_addr=0x80000000,
ddr_addr=0x10000000,
- #fw_addr=fw_addr,
- fw_addr=None,
+ fw_addr=fw_addr,
+ #fw_addr=None,
ddr_pins=ddr_pins,
uart_pins=uart_pins,
firmware=firmware,