From 68c69136b969773e122e2c7ac92e42feca74a828 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 19 Aug 2018 13:38:59 +0200 Subject: [PATCH] Add icebreaker example PicoSoC implementation Signed-off-by: Clifford Wolf --- picosoc/.gitignore | 9 ++-- picosoc/Makefile | 34 ++++++++----- picosoc/README.md | 31 +++++++----- picosoc/firmware.c | 118 +++++++++++++++++++++++++++++++++++++++------ picosoc/spiflash.v | 3 ++ 5 files changed, 151 insertions(+), 44 deletions(-) diff --git a/picosoc/.gitignore b/picosoc/.gitignore index c8e45ae..1817f7d 100644 --- a/picosoc/.gitignore +++ b/picosoc/.gitignore @@ -1,8 +1,5 @@ /spiflash_tb.vcd /spiflash_tb.vvp -/firmware.elf -/firmware.hex -/firmware.bin /hx8kdemo.asc /hx8kdemo.bin /hx8kdemo.blif @@ -11,6 +8,9 @@ /hx8kdemo_syn.v /hx8kdemo_syn_tb.vvp /hx8kdemo_tb.vvp +/hx8kdemo_fw.elf +/hx8kdemo_fw.hex +/hx8kdemo_fw.bin /icebreaker.asc /icebreaker.bin /icebreaker.json @@ -19,5 +19,8 @@ /icebreaker_syn.v /icebreaker_syn_tb.vvp /icebreaker_tb.vvp +/icebreaker_fw.elf +/icebreaker_fw.hex +/icebreaker_fw.bin /testbench.vcd /cmos.log diff --git a/picosoc/Makefile b/picosoc/Makefile index 3615f91..db4cf92 100644 --- a/picosoc/Makefile +++ b/picosoc/Makefile @@ -33,6 +33,15 @@ hx8kprog: hx8kdemo.bin firmware.bin hx8kprog_fw: firmware.bin iceprog -o 1M firmware.bin +hx8kdemo_fw.elf: sections.lds start.s firmware.c + riscv32-unknown-elf-gcc -DHX8KDEMO -march=rv32imc -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o hx8kdemo_fw.elf start.s firmware.c + +hx8kdemo_fw.hex: hx8kdemo_fw.elf + riscv32-unknown-elf-objcopy -O verilog hx8kdemo_fw.elf hx8kdemo_fw.hex + +hx8kdemo_fw.bin: hx8kdemo_fw.elf + riscv32-unknown-elf-objcopy -O binary hx8kdemo_fw.elf hx8kdemo_fw.bin + # ---- iCE40 IceBreaker Board ---- icebsim: icebreaker_tb.vvp firmware.hex @@ -60,23 +69,21 @@ icebreaker.bin: icebreaker.asc icetime -d up5k -c 12 -mtr icebreaker.rpt icebreaker.asc icepack icebreaker.asc icebreaker.bin -icebprog: icebreaker.bin firmware.bin +icebprog: icebreaker.bin icebreaker_fw.bin iceprog icebreaker.bin - iceprog -o 1M firmware.bin + iceprog -o 1M icebreaker_fw.bin -icebprog_fw: firmware.bin - iceprog -o 1M firmware.bin +icebprog_fw: icebreaker_fw.bin + iceprog -o 1M icebreaker_fw.bin -# ---- Example Firmware ---- +icebreaker_fw.elf: sections.lds start.s firmware.c + riscv32-unknown-elf-gcc -DICEBREAKER -march=rv32ic -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o icebreaker_fw.elf start.s firmware.c -firmware.elf: sections.lds start.s firmware.c - riscv32-unknown-elf-gcc -march=rv32ic -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf start.s firmware.c +icebreaker_fw.hex: icebreaker_fw.elf + riscv32-unknown-elf-objcopy -O verilog icebreaker_fw.elf icebreaker_fw.hex -firmware.hex: firmware.elf - riscv32-unknown-elf-objcopy -O verilog firmware.elf firmware.hex - -firmware.bin: firmware.elf - riscv32-unknown-elf-objcopy -O binary firmware.elf firmware.bin +icebreaker_fw.bin: icebreaker_fw.elf + riscv32-unknown-elf-objcopy -O binary icebreaker_fw.elf icebreaker_fw.bin # ---- Testbench for SPI Flash Model ---- @@ -95,7 +102,8 @@ cmos.log: spimemio.v simpleuart.v picosoc.v ../picorv32.v clean: rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd - rm -f firmware.elf firmware.hex firmware.bin cmos.log + rm -f hx8kdemo_fw.elf hx8kdemo_fw.hex hx8kdemo_fw.bin cmos.log + rm -f icebreaker_fw.elf icebreaker_fw.hex icebreaker_fw.bin rm -f hx8kdemo.blif hx8kdemo.log hx8kdemo.asc hx8kdemo.rpt hx8kdemo.bin rm -f hx8kdemo_syn.v hx8kdemo_syn_tb.vvp hx8kdemo_tb.vvp rm -f icebreaker.json icebreaker.log icebreaker.asc icebreaker.rpt icebreaker.bin diff --git a/picosoc/README.md b/picosoc/README.md index dcb45ba..4d02128 100644 --- a/picosoc/README.md +++ b/picosoc/README.md @@ -20,21 +20,28 @@ The reset vector is set to 0x00100000, i.e. at 1MB into in the flash memory. See the included demo firmware and linker script for how to build a firmware image for this system. -Run `make test` to run the test bench (and create `testbench.vcd`). +Run `make hx8ksim` or `make icebsim` to run the test bench (and create `testbench.vcd`). -Run `make prog` to build the configuration bit-stream and firmware images +Run `make hx8kprog` to build the configuration bit-stream and firmware images and upload them to a connected iCE40-HX8K Breakout Board. -| File | Description | -| ----------------------------- | --------------------------------------------------------------- | -| [picosoc.v](picosoc.v) | Top-level PicoSoC Verilog module | -| [spimemio.v](spimemio.v) | Memory controller that interfaces to external SPI flash | -| [simpleuart.v](simpleuart.v) | Simple UART core connected directly to SoC TX/RX lines | -| [start.s](start.s) | Assembler source for firmware.hex/firmware.bin | -| [firmware.c](firmware.c) | C source for firmware.hex/firmware.bin | -| [sections.lds](sections.lds) | Linker script for firmware.hex/firmware.bin | -| [hx8kdemo.v](hx8kdemo.v) | FPGA-based example implementation on iCE40-HX8K Breakout Board | -| [hx8kdemo.pcf](hx8kdemo.pcf) | Pin constraints for implementation on iCE40-HX8K Breakout Board | +Run `make icebprog` to build the configuration bit-stream and firmware images +and upload them to a connected iCEBreaker Board. + +| File | Description | +| --------------------------------- | --------------------------------------------------------------- | +| [picosoc.v](picosoc.v) | Top-level PicoSoC Verilog module | +| [spimemio.v](spimemio.v) | Memory controller that interfaces to external SPI flash | +| [simpleuart.v](simpleuart.v) | Simple UART core connected directly to SoC TX/RX lines | +| [start.s](start.s) | Assembler source for firmware.hex/firmware.bin | +| [firmware.c](firmware.c) | C source for firmware.hex/firmware.bin | +| [sections.lds](sections.lds) | Linker script for firmware.hex/firmware.bin | +| [hx8kdemo.v](hx8kdemo.v) | FPGA-based example implementation on iCE40-HX8K Breakout Board | +| [hx8kdemo.pcf](hx8kdemo.pcf) | Pin constraints for implementation on iCE40-HX8K Breakout Board | +| [hx8kdemo\_tb.v](hx8kdemo_tb.v) | Testbench for implementation on iCE40-HX8K Breakout Board | +| [icebreaker.v](hx8kdemo.v) | FPGA-based example implementation on iCEBreaker Board | +| [icebreaker.pcf](hx8kdemo.pcf) | Pin constraints for implementation on iCEBreaker Board | +| [icebreaker\_tb.v](hx8kdemo_tb.v) | Testbench for implementation on iCEBreaker Board | ### Memory map: diff --git a/picosoc/firmware.c b/picosoc/firmware.c index 2db2588..be3bf52 100644 --- a/picosoc/firmware.c +++ b/picosoc/firmware.c @@ -1,6 +1,29 @@ +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + #include #include +#if !defined(ICEBREAKER) && !defined(HX8KDEMO) +# error "Set -DICEBREAKER or -DHX8KDEMO when compiling firmware.c" +#endif + // a pointer to this is a null pointer, but the compiler does not // know that because "sram" is a linker symbol from sections.lds. extern uint32_t sram; @@ -28,11 +51,10 @@ void flashio(uint8_t *data, int len, uint8_t wrencmd) ((void(*)(uint8_t*, uint32_t, uint32_t))func)(data, len, wrencmd); } +#ifdef HX8KBOARD void set_flash_qspi_flag() { uint8_t buffer[8]; - -#if 1 uint32_t addr_cr1v = 0x800002; // Read Any Register (RDAR 65h) @@ -52,26 +74,26 @@ void set_flash_qspi_flag() buffer[3] = addr_cr1v; buffer[4] = cr1v | 2; // Enable QSPI flashio(buffer, 5, 0x06); -#else - // Read Status Register 1 (RDSR1 05h) - buffer[0] = 0x05; - buffer[1] = 0x00; // rdata - flashio(buffer, 2, 0); - uint8_t sr1v = buffer[1]; +} +#endif + +#ifdef ICEBREAKER +void set_flash_qspi_flag() +{ + uint8_t buffer[8]; // Read Configuration Registers (RDCR1 35h) buffer[0] = 0x35; buffer[1] = 0x00; // rdata flashio(buffer, 2, 0); - uint8_t cr1v = buffer[1]; + uint8_t sr2 = buffer[1]; - // Write Enable (WREN 06h) + Write Registers (WRR 01h) - buffer[0] = 0x01; - buffer[1] = sr1v; - buffer[2] = cr1v | 2; // Enable QSPI - flashio(buffer, 3, 0x06); -#endif + // Write Enable Volatile (50h) + Write Status Register 2 (31h) + buffer[0] = 0x31; + buffer[1] = sr2 | 2; // Enable QSPI + flashio(buffer, 2, 0x50); } +#endif void set_flash_latency(uint8_t value) { @@ -185,6 +207,7 @@ void cmd_read_flash_id() // -------------------------------------------------------- +#ifdef HX8KDEMO uint8_t cmd_read_flash_regs_print(uint32_t addr, const char *name) { set_flash_latency(8); @@ -213,6 +236,70 @@ void cmd_read_flash_regs() uint8_t cr3v = cmd_read_flash_regs_print(0x800004, "CR3V"); uint8_t vdlp = cmd_read_flash_regs_print(0x800005, "VDLP"); } +#endif + +#ifdef ICEBREAKER +uint8_t cmd_read_flash_reg(uint8_t cmd) +{ + set_flash_latency(8); + + uint8_t buffer[2] = {cmd, 0}; + flashio(buffer, 2, 0); + return buffer[1]; +} + +void print_reg_bit(int val, const char *name) +{ + for (int i = 0; i < 12; i++) { + if (*name == 0) + putchar(' '); + else + putchar(*(name++)); + } + + putchar(val ? '1' : '0'); + putchar('\n'); +} + +void cmd_read_flash_regs() +{ + putchar('\n'); + + uint8_t sr1 = cmd_read_flash_reg(0x05); + uint8_t sr2 = cmd_read_flash_reg(0x35); + uint8_t sr3 = cmd_read_flash_reg(0x15); + + print_reg_bit(sr1 & 0x01, "S0 (BUSY)"); + print_reg_bit(sr1 & 0x02, "S1 (WEL)"); + print_reg_bit(sr1 & 0x04, "S2 (BP0)"); + print_reg_bit(sr1 & 0x08, "S3 (BP1)"); + print_reg_bit(sr1 & 0x10, "S4 (BP2)"); + print_reg_bit(sr1 & 0x20, "S5 (TB)"); + print_reg_bit(sr1 & 0x40, "S6 (SEC)"); + print_reg_bit(sr1 & 0x80, "S7 (SRP)"); + putchar('\n'); + + print_reg_bit(sr2 & 0x01, "S8 (SRL)"); + print_reg_bit(sr2 & 0x02, "S9 (QE)"); + print_reg_bit(sr2 & 0x04, "S10 ----"); + print_reg_bit(sr2 & 0x08, "S11 (LB1)"); + print_reg_bit(sr2 & 0x10, "S12 (LB2)"); + print_reg_bit(sr2 & 0x20, "S13 (LB3)"); + print_reg_bit(sr2 & 0x40, "S14 (CMP)"); + print_reg_bit(sr2 & 0x80, "S15 (SUS)"); + putchar('\n'); + + print_reg_bit(sr3 & 0x01, "S16 ----"); + print_reg_bit(sr3 & 0x02, "S17 ----"); + print_reg_bit(sr3 & 0x04, "S18 (WPS)"); + print_reg_bit(sr3 & 0x08, "S19 ----"); + print_reg_bit(sr3 & 0x10, "S20 ----"); + print_reg_bit(sr3 & 0x20, "S21 (DRV0)"); + print_reg_bit(sr3 & 0x40, "S22 (DRV1)"); + print_reg_bit(sr3 & 0x80, "S23 (HOLD)"); + putchar('\n'); +} +#endif // -------------------------------------------------------- @@ -483,4 +570,3 @@ void main() } } } - diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v index 18b918b..1ade543 100644 --- a/picosoc/spiflash.v +++ b/picosoc/spiflash.v @@ -32,6 +32,9 @@ // Cypress S25FL064L http://www.cypress.com/file/316661/download // Cypress S25FL128L http://www.cypress.com/file/316171/download // +// SPI flash used on iCEBreaker board: +// https://www.winbond.com/resource-files/w25q128jv%20dtr%20revb%2011042016.pdf +// module spiflash ( input csb,