Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Pico Ice development board #124

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions FemtoRV/BOARDS/pico_ice.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
YOSYS_PICOICE_OPT=-DPICO_ICE -q -p "synth_ice40 -relut -top $(PROJECTNAME) -json $(PROJECTNAME).json"
NEXTPNR_PICOICE_OPT=--force --json $(PROJECTNAME).json --pcf BOARDS/pico_ice.pcf --asc $(PROJECTNAME).asc \
--freq 12 --up5k --package sg48 --opt-timing


#######################################################################################################################

PICOICE: PICOICE.firmware_config PICOICE.synth PICOICE.prog

PICOICE.synth:
yosys $(YOSYS_PICOICE_OPT) $(VERILOGS)
nextpnr-ice40 $(NEXTPNR_PICOICE_OPT)
icetime -p BOARDS/pico_ice.pcf -P sg48 -r $(PROJECTNAME).timings -d up5k -t $(PROJECTNAME).asc
icepack -s $(PROJECTNAME).asc $(PROJECTNAME).bin

PICOICE.show:
yosys $(YOSYS_PICOICE_OPT) $(VERILOGS)
nextpnr-ice40 $(NEXTPNR_PICOICE_OPT) --gui

PICOICE.prog:
# Upload using DFU slot alt 0 (SPI), so the image is permanent
dfu-util -D $(PROJECTNAME).bin -a 0

PICOICE.firmware_config:
BOARD=PICOICE TOOLS/make_config.sh -DPICO_ICE
(cd FIRMWARE; make libs)

PICOICE.lint:
verilator -DPICO_ICE -DBENCH --lint-only --top-module $(PROJECTNAME) \
-IRTL -IRTL/PROCESSOR -IRTL/DEVICES -IRTL/PLL $(VERILOGS)

#######################################################################################################################
33 changes: 33 additions & 0 deletions FemtoRV/BOARDS/pico_ice.pcf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
set_io pclk 35

set_io D1 41 # LED R
set_io D2 39 # LED G
set_io D3 40 # LED B
set_io D4 31 # LED EXT 0
set_io D5 34 # LED EXT 1

set_io TXD 25
set_io RXD 27

set_io spi_cs_n 16
set_io spi_io[0] 14
set_io spi_io[1] 17
set_io spi_io[2] 12
set_io spi_io[3] 13
set_io spi_clk 15

set_io oled_DIN 6
set_io oled_CLK 9
set_io oled_CS 11
set_io oled_DC 4
set_io oled_RST 21

set_io ledmtx_DIN 20
set_io ledmtx_CS 19
set_io ledmtx_CLK 18

set_io irda_TXD 46
set_io irda_RXD 48
set_io irda_SD 3

set_io RESET 10
119 changes: 119 additions & 0 deletions FemtoRV/FIRMWARE/CRT/spiflash_picoice.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* Linker script for programs stored in SPI flash */
/* Inspired from picorv32/picosoc/sections.lds */
/* */
/* text and rodata sections are sent to flash */
/* bss sections are sent to BRAM */
/* data sections are sent to BRAM and have */
/* initialization data in flash. */
/* AT keyword specifies LMA (Load Memory Address) */

MEMORY {
BITSTREAM (r): ORIGIN = 0x00800000, LENGTH = 0x20000 /* 128 KB FPGA configuration region */
FLASH (rx) : ORIGIN = 0x00820000, LENGTH = 0x3E0000 /* 3.8 MiB in flash */
RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x1800 /* 6 kB in RAM */
}

/* Set TARGET, and read the fpga bitstream */
TARGET(binary)
INPUT("../../femtosoc.bin")
/* Reset target format to previous value */
TARGET(elf32-littleriscv)

SECTIONS {

/*
* The PICOICE programmer only supports loading complete
* binary files via DFU mode. Therefore, we will include
* the FPGA bitstream binary directly into the output
* elf file. Note the use of the AT keyword- we need this
* approach because the linker will complain if we try to
* link the bitstream directly to 0x0, as this overlaps with RAM.
*/
.bitstream : {
../../femtosoc.bin
} > BITSTREAM

/*
* This is the initialized data and fastcode section
* The program executes knowing that the data is in the RAM
* but the loader puts the initial values in the FLASH (inidata).
* It is one task of the startup (crt0_spiflash.S) to copy the initial values from FLASH to RAM.
*/
.data_and_fastcode : AT ( _sidata ) {
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
_ram_start = .; /* create a global symbol at ram start (e.g., for garbage collector) */

/* Initialized data */
*(.data)
*(.data*)
*(.sdata)
*(.sdata*)

/* functions with attribute((section(".fastcode"))) */
/* (e.g., some functions in femtoGL) */
*(.fastcode*)

/* integer mul and div */
*/libgcc.a:muldi3.o(.text)
*/libgcc.a:div.o(.text)

/* low-level graphics functions */
*/libfemtorv32.a:ssd1351_1331.o(.text)

/* timing */
wait_cycles.o(.text)

. = ALIGN(4);
_edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
} > RAM

/* The (non fastcode) program code and other data goes into FLASH */
.text : {
. = ALIGN(4);
crt0_spiflash.o(.text) /* c runtime initialization (code) */


/*
* I do not understand why, but if I do not put that here, I got
* an overlapping sections error with some programs (for instance pi.c
* or C++ programs)
*/
*(.eh_frame)
*(.eh_frame_hdr)
*(.init_array)
*(.gcc_except_table*)

*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.srodata) /* .rodata sections (constants, strings, etc.) */
*(.srodata*) /* .rodata* sections (constants, strings, etc.) */
_etext = .; /* define a global symbol at end of code */
_sidata = _etext; /* This is used by the startup in order to initialize the .data section */
} >FLASH

/* Uninitialized data section */
.bss : {
. = ALIGN(4);
_sbss = .; /* define a global symbol at bss start; used by startup code */
*(.bss)
*(.bss*)
*(.sbss)
*(.sbss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end; used by startup code */
} >RAM

/* this is to define the start of the heap, and make sure we have a minimum size */
.heap : {
. = ALIGN(4);
_heap_start = .; /* define a global symbol at heap start */
_end = .; /* as expected by syscalls.c */
} >RAM


}
23 changes: 17 additions & 6 deletions FemtoRV/FIRMWARE/makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,21 @@ uname := $(shell uname)
uname_m := $(shell uname -m)

ifeq ($(uname),Darwin)
$(info Configuring for Mac)
TOOLCHAIN_WEB=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1
TOOLCHAIN_VER=xpack-riscv-none-embed-gcc-10.1.0-1.1
TOOLCHAIN_DL_SUFFIX=-darwin-x64
TOOLCHAIN_GCC_VER=10.1.0
RVTOOLCHAIN_BIN_PREFIX=riscv-none-embed
ifeq ($(uname_m), arm64)
$(info Configuring for Mac (arm64))
TOOLCHAIN_WEB=https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v11.3.0-1
TOOLCHAIN_VER=xpack-riscv-none-elf-gcc-11.3.0-1
TOOLCHAIN_DL_SUFFIX=-darwin-arm64
TOOLCHAIN_GCC_VER=11.3.0
RVTOOLCHAIN_BIN_PREFIX=riscv-none-elf
else
$(info Configuring for Mac (x86_64))
TOOLCHAIN_WEB=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1
TOOLCHAIN_VER=xpack-riscv-none-embed-gcc-10.1.0-1.1
TOOLCHAIN_DL_SUFFIX=-darwin-x64
TOOLCHAIN_GCC_VER=10.1.0
RVTOOLCHAIN_BIN_PREFIX=riscv-none-embed
endif
else
ifeq ($(uname_m),aarch64)
$(info Configuring for ARM64)
Expand Down Expand Up @@ -85,6 +94,8 @@ FIRMWARE_WORDS=$(FIRMWARE_DIR)/TOOLS/firmware_words

ifeq ($(BOARD),icesugar_nano)
TOOLCHAIN_PROG_CMD=icesprog -o 0x20000
else ifeq ($(BOARD), PICOICE)
TOOLCHAIN_PROG_CMD=dfu-util -a 0 -D
else
TOOLCHAIN_PROG_CMD=iceprog -o 128k
endif
Expand Down
1 change: 1 addition & 0 deletions FemtoRV/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ include BOARDS/ecp5_evn.mk
#include BOARDS/arty35_symbiflow.mk
include BOARDS/arty35_yosys_nextpnr.mk
include BOARDS/cmod_a7_yosys_nextpnr.mk
include BOARDS/pico_ice.mk


.PHONY: all clean terminal testbench
Expand Down
33 changes: 33 additions & 0 deletions FemtoRV/RTL/CONFIGS/pico_ice_config.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Default femtosoc configuration file for IceStick

/************************* Devices **********************************************************************************/

`define NRV_NEGATIVE_RESET

`define NRV_IO_LEDS // Mapped IO, LEDs D1,D2,D3,D4 (D5 is used to display errors)
`define NRV_IO_UART // Mapped IO, virtual UART (USB)
`define NRV_MAPPED_SPI_FLASH // SPI flash mapped in address space. Can be used to run code from SPI flash.

/************************* Processor configuration *******************************************************************/

`define NRV_FEMTORV32_QUARK
`define NRV_FREQ 25 // Validated at 25 MHz on pico ice
`define NRV_RESET_ADDR 32'h820000 // Jump execution to SPI Flash
`define NRV_COUNTER_WIDTH 24 // Number of bits in cycles counter
`define NRV_TWOLEVEL_SHIFTER // Faster shifts
// tinyraytracer: 70 MHz, 17:30

/************************* RAM (in bytes, needs to be a multiple of 4)***********************************************/

`define NRV_RAM 6144 // default for ICESTICK (cannot do more !)


/************************* Advanced devices configuration ***********************************************************/

`define NRV_RUN_FROM_SPI_FLASH // Do not 'readmemh()' firmware from '.hex' file
`define NRV_IO_HARDWARE_CONFIG // Comment-out to disable hardware config registers mapped in IO-Space
// (note: firmware libfemtorv32 depends on it)

/********************************************************************************************************************/

`define NRV_CONFIGURED
117 changes: 117 additions & 0 deletions FemtoRV/RTL/DEVICES/MappedSPIFlash.v
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@
`define SPI_FLASH_CONFIGURED
`endif

`ifdef PICO_ICE
/* Note- Quad IO usually requires the QE bit to be set on your flash.
* the PICO ICE has this set from the factory.
*/
`define SPI_FLASH_FAST_READ_QUAD_IO
`define SPI_FLASH_CONFIGURED
`define SPI_FLASH_DUMMY_CLOCKS 6
`endif

`ifndef SPI_FLASH_DUMMY_CLOCKS
`define SPI_FLASH_DUMMY_CLOCKS 8
`endif
Expand Down Expand Up @@ -391,3 +400,111 @@ endmodule
*/

`endif

`ifdef SPI_FLASH_FAST_READ_QUAD_IO

module MappedSPIFlash(
input wire clk, // system clock
input wire rstrb, // read strobe
input wire [19:0] word_address, // address to be read


output wire [31:0] rdata, // data read
output wire rbusy, // asserted if busy receiving data
output wire CLK, // clock
output reg CS_N, // chip select negated (active low)
inout wire [3:0] IO // four bidirectional IO pins
);
reg [31:0] shifter; // Used for sending and receiving data
reg [4:0] clock_cnt; // Count of clocks left before shifter is empty

localparam STATE_IDLE = 2'd0; // Waiting for rstrb
localparam STATE_INSTRUCTION = 2'd1; // Sending instruction
localparam STATE_ADDRESS = 2'd2; // Sending address and dummy clocks
localparam STATE_READ = 2'd3; // Reading data
reg [1:0] state; // State register

// Four data pins are used in bidirectional modes
reg IO_oe = 1'b1;
wire [3:0] IO_out = shifter[31:28];
wire [3:0] IO_in = IO;
// Set IO to high impedance when reading
assign IO = IO_oe ? IO_out : 4'bZZ;

initial CS_N = 1'b1;
initial state = STATE_IDLE;

assign CLK = !CS_N && !clk;
assign rbusy = !CS_N;

// since least significant bytes are read first, we need to swizzle...
assign rdata={shifter[7:0],shifter[15:8],shifter[23:16],shifter[31:24]};

// Splits the bits of an instruction across 4 wires.
// Similar to the DUAL_IO module, this lets us reuse the shifter
// between the instruction and the address/data
function [31:0] instruction;
input [7:0] x;
begin
instruction = {
1'bZ, 1'bZ, 1'bZ, x[7], 1'bZ, 1'bZ, 1'bZ, x[6],
1'bZ, 1'bZ, 1'bZ, x[5], 1'bZ, 1'bZ, 1'bZ, x[4],
1'bZ, 1'bZ, 1'bZ, x[3], 1'bZ, 1'bZ, 1'bZ, x[2],
1'bZ, 1'bZ, 1'bZ, x[1], 1'bZ, 1'bZ, 1'bZ, x[0]
};
end
endfunction


always @(posedge clk) begin
// State machine for sending instruction/addr and reading data
case (state)
STATE_IDLE: begin
if (rstrb) begin
CS_N <= 1'b0;
IO_oe <= 1'b1;
shifter <= instruction(8'hEB);
state <= STATE_INSTRUCTION;
clock_cnt <= 4'd7;
end
end
STATE_INSTRUCTION: begin
if (clock_cnt == 4'd0) begin
// Move to address state. We will send 24 bits in 6 clocks.
shifter <= {2'b00, word_address[19:0], 2'b00, 8'hFF};
state <= STATE_ADDRESS;
clock_cnt <= 4'd5 + `SPI_FLASH_DUMMY_CLOCKS;
end else begin
// Clock out instruction
shifter <= {shifter[27:0], 4'b1111};
clock_cnt <= clock_cnt - 4'd1;
end
end
STATE_ADDRESS: begin
if (clock_cnt == 4'd0) begin
// Move to read state
state <= STATE_READ;
clock_cnt <= 4'd7;
IO_oe <= 1'b0;
end else begin
// Clock out address followed by dummy clocks
shifter <= {shifter[27:0], 4'b1111};
clock_cnt <= clock_cnt - 4'd1;
end
end
STATE_READ: begin
if (clock_cnt == 4'd0) begin
// Set CS_N, return to idle state
CS_N <= 1'b1;
state <= STATE_IDLE;
shifter <= {shifter[27:0], IO_in};
end else begin
shifter <= {shifter[27:0], IO_in};
clock_cnt <= clock_cnt - 3'd1;
end
end
endcase
end
endmodule

`endif
Loading