aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2017-09-15 16:31:37 +0200
committerClifford Wolf <clifford@clifford.at>2017-09-15 16:31:37 +0200
commit1c8266869ad5179e99f5c063ad203c80f37b65c5 (patch)
treeb64f69290558909ae500673bfa27521c4288131c
parenta412d3ea69618960d6cfd900b5b4e99a9161992f (diff)
parent797c21e95cc80e985801ef0a08b3bb734e2118f4 (diff)
downloadpicorv32-1c8266869ad5179e99f5c063ad203c80f37b65c5.tar.gz
picorv32-1c8266869ad5179e99f5c063ad203c80f37b65c5.zip
Merge branch 'picosoc'
-rw-r--r--picosoc/.gitignore1
-rw-r--r--picosoc/Makefile20
-rw-r--r--picosoc/README.md3
-rw-r--r--picosoc/firmware.S126
-rw-r--r--picosoc/firmware.c105
-rw-r--r--picosoc/hx8kdemo.pcf20
-rw-r--r--picosoc/hx8kdemo.v30
-rw-r--r--picosoc/hx8kdemo_tb.v2
-rw-r--r--picosoc/picosoc.v8
-rw-r--r--picosoc/sections.lds2
-rw-r--r--picosoc/start.s61
11 files changed, 225 insertions, 153 deletions
diff --git a/picosoc/.gitignore b/picosoc/.gitignore
index ab0e16e..9ec714d 100644
--- a/picosoc/.gitignore
+++ b/picosoc/.gitignore
@@ -3,7 +3,6 @@
/spiflash_tb.vcd
/spiflash_tb.vvp
/firmware.elf
-/firmware_up.elf
/firmware.hex
/firmware.bin
/hx8kdemo.asc
diff --git a/picosoc/Makefile b/picosoc/Makefile
index 49dc126..1a6ac94 100644
--- a/picosoc/Makefile
+++ b/picosoc/Makefile
@@ -19,6 +19,9 @@ hx8kprog: hx8kdemo.bin firmware.bin
iceprog hx8kdemo.bin
iceprog -o 1M firmware.bin
+hx8kprog_fw: firmware.bin
+ iceprog -o 1M firmware.bin
+
hx8ksim: hx8kdemo_tb.vvp firmware.hex
vvp -N $<
@@ -46,25 +49,22 @@ hx8kdemo.bin: hx8kdemo.asc
# ---- Example Firmware ----
-firmware.elf: sections.lds firmware.S
- riscv32-unknown-elf-gcc -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf firmware.S
-
-firmware_up.elf: firmware.elf
- riscv32-unknown-elf-objcopy --change-addresses 0x100000 firmware.elf firmware_up.elf
+firmware.elf: sections.lds start.s firmware.c
+ riscv32-unknown-elf-gcc -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf start.s firmware.c
-firmware.hex: firmware_up.elf
- riscv32-unknown-elf-objcopy -O verilog firmware_up.elf firmware.hex
+firmware.hex: firmware.elf
+ riscv32-unknown-elf-objcopy -O verilog firmware.elf /dev/stdout | sed -e '2,65537 d;' > firmware.hex
firmware.bin: firmware.elf
- riscv32-unknown-elf-objcopy -O binary firmware.elf firmware.bin
+ riscv32-unknown-elf-objcopy -O binary firmware.elf /dev/stdout | tail -c +1048577 > firmware.bin
# ---- Clean ----
clean:
rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd
- rm -f firmware.elf firmware_up.elf firmware.hex firmware.bin
+ rm -f firmware.elf firmware.hex firmware.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
-.PHONY: testbench spiflash_tb hx8kprog hx8ksim hx8ksynsim clean
+.PHONY: testbench spiflash_tb hx8kprog hx8kprog_fw hx8ksim hx8ksynsim clean
diff --git a/picosoc/README.md b/picosoc/README.md
index 77ea038..2fd558c 100644
--- a/picosoc/README.md
+++ b/picosoc/README.md
@@ -38,6 +38,9 @@ and upload them to a connected iCE40-HX8K Breakout Board.
| 0x02000008 .. 0x0200000B | UART Send/Recv Data Register |
| 0x03000000 .. 0xFFFFFFFF | Memory mapped user peripherals |
+The addresses in the internal SRAM region beyond the end of the physical
+SRAM map to the corresponding addresses in serial flash.
+
Reading from the UART Send/Recv Data Register will return the last received
byte, or -1 (all 32 bits set) when the receive buffer is empty.
diff --git a/picosoc/firmware.S b/picosoc/firmware.S
deleted file mode 100644
index efd49b4..0000000
--- a/picosoc/firmware.S
+++ /dev/null
@@ -1,126 +0,0 @@
-// write RAM code (a sequence of nops followed by ret)
-li x5,0x00000013 // nop
-sw x5,4(x0)
-sw x5,8(x0)
-sw x5,12(x0)
-sw x5,16(x0)
-sw x5,20(x0)
-sw x5,24(x0)
-sw x5,28(x0)
-sw x5,32(x0)
-sw x5,36(x0)
-sw x5,40(x0)
-sw x5,44(x0)
-sw x5,48(x0)
-sw x5,52(x0)
-sw x5,56(x0)
-sw x5,60(x0)
-sw x5,64(x0)
-sw x5,68(x0)
-sw x5,72(x0)
-sw x5,76(x0)
-sw x5,80(x0)
-sw x5,84(x0)
-sw x5,88(x0)
-sw x5,92(x0)
-sw x5,96(x0)
-sw x5,100(x0)
-sw x5,104(x0)
-sw x5,108(x0)
-sw x5,112(x0)
-sw x5,116(x0)
-sw x5,120(x0)
-sw x5,124(x0)
-sw x5,128(x0)
-sw x5,132(x0)
-sw x5,136(x0)
-sw x5,140(x0)
-sw x5,144(x0)
-sw x5,148(x0)
-sw x5,152(x0)
-sw x5,156(x0)
-sw x5,160(x0)
-sw x5,164(x0)
-sw x5,168(x0)
-sw x5,172(x0)
-sw x5,176(x0)
-sw x5,180(x0)
-sw x5,184(x0)
-sw x5,188(x0)
-sw x5,192(x0)
-li x5,0x00008067 // ret
-sw x5,196(x0)
-
-// write a few chars to UART
-li x5,0x02000004
-li x6,104
-sw x6,0(x5)
-li x5,0x02000008
-li x6,'H'
-sw x6,0(x5)
-li x6,'e'
-sw x6,0(x5)
-li x6,'l'
-sw x6,0(x5)
-li x6,'l'
-sw x6,0(x5)
-li x6,'o'
-sw x6,0(x5)
-li x6,' '
-sw x6,0(x5)
-li x6,'W'
-sw x6,0(x5)
-li x6,'o'
-sw x6,0(x5)
-li x6,'r'
-sw x6,0(x5)
-li x6,'l'
-sw x6,0(x5)
-li x6,'d'
-sw x6,0(x5)
-li x6,'!'
-sw x6,0(x5)
-li x6,'\r'
-sw x6,0(x5)
-li x6,'\n'
-sw x6,0(x5)
-
-#if 0
-// switch spimemio to continous qspi ddr mode
-li x5,0x02000000
-li x6,0x80000071
-sw x6,0(x5)
-#endif
-
-// setup gpio address in x5
-li x5,0x03000000
-sw x0,0(x5)
-
-// initial entry point into RAM code
-li x3,4
-
-// initialize RAM counter
-sw x0,0(x0)
-
-// start of loop. remember this address
-auipc x4,0
-
-// execute RAM code, come back here
-jalr x3
-
-// load counter and increment
-lw x6,0(x0)
-addi x6,x6,1
-
-// store counter and update gpios
-sw x6,0(x5)
-sw x6,0(x0)
-
-// calculate new entry point into RAM code
-slli x3,x6,2
-andi x3,x3,127
-addi x3,x3,32
-
-// execute RAM code, come back to start of loop
-mv x1,x4
-jr x3
diff --git a/picosoc/firmware.c b/picosoc/firmware.c
new file mode 100644
index 0000000..660ef56
--- /dev/null
+++ b/picosoc/firmware.c
@@ -0,0 +1,105 @@
+#include <stdint.h>
+
+#define reg_spictrl (*(volatile uint32_t*)0x02000000)
+#define reg_uart_clkdiv (*(volatile uint32_t*)0x02000004)
+#define reg_uart_data (*(volatile uint32_t*)0x02000008)
+#define reg_leds (*(volatile uint32_t*)0x03000000)
+
+void print(const char *p)
+{
+ while (*p) {
+ if (*p == '\n')
+ reg_uart_data = '\r';
+ reg_uart_data = *(p++);
+ }
+}
+
+char getchar_prompt(char *prompt)
+{
+ int32_t c = -1;
+
+ uint32_t cycles_begin, cycles_now, cycles;
+ __asm__ volatile ("rdcycle %0" : "=r"(cycles_begin));
+
+ if (prompt)
+ print(prompt);
+
+ reg_leds = ~0;
+ while (c == -1) {
+ __asm__ volatile ("rdcycle %0" : "=r"(cycles_now));
+ cycles = cycles_now - cycles_begin;
+ if (cycles > 12000000) {
+ if (prompt)
+ print(prompt);
+ cycles_begin = cycles_now;
+ reg_leds = ~reg_leds;
+ }
+ c = reg_uart_data;
+ }
+ reg_leds = 0;
+ return c;
+}
+
+char getchar()
+{
+ return getchar_prompt(0);
+}
+
+// --------------------------------------------------------
+
+extern uint32_t cmd_read_spi_flash_id_worker_begin;
+extern uint32_t cmd_read_spi_flash_id_worker_end;
+
+void cmd_read_spi_flash_id()
+{
+ uint32_t *src_ptr = &cmd_read_spi_flash_id_worker_begin;
+ uint32_t *dst_ptr = (uint32_t*)0;
+
+ while (src_ptr != &cmd_read_spi_flash_id_worker_end)
+ *(dst_ptr++) = *(src_ptr++);
+
+ ((void(*)())0)();
+}
+
+// --------------------------------------------------------
+
+void main()
+{
+ reg_uart_clkdiv = 104;
+ while (getchar_prompt("Press ENTER to continue..\n") != '\r') { /* wait */ }
+
+ print("\n");
+ print(" ____ _ ____ ____\n");
+ print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n");
+ print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n");
+ print(" | __/| | (_| (_) |__) | (_) | |___\n");
+ print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n");
+
+ while (1)
+ {
+ print("\n");
+ print("\n");
+ print("Select an action:\n");
+ print("\n");
+ print(" [1] Read SPI Flash ID\n");
+ print("\n");
+
+ for (int rep = 10; rep > 0; rep--)
+ {
+ print("Command> ");
+ char cmd = getchar();
+ if (cmd > 32 && cmd < 127)
+ reg_uart_data = cmd;
+ print("\n");
+
+ switch (cmd)
+ {
+ case '1':
+ cmd_read_spi_flash_id();
+ rep = 0;
+ break;
+ }
+ }
+ }
+}
+
diff --git a/picosoc/hx8kdemo.pcf b/picosoc/hx8kdemo.pcf
index 8e082f8..418bae8 100644
--- a/picosoc/hx8kdemo.pcf
+++ b/picosoc/hx8kdemo.pcf
@@ -7,12 +7,28 @@ set_io flash_csb R12
set_io flash_clk R11
set_io flash_io0 P12
set_io flash_io1 P11
-set_io flash_io2 T9 # center on J3
-set_io flash_io3 P8 # center on J3
+
+# for QSPI mode the flash chip on the iCE40-HX8K Breakout Board
+# must be replaced with one that supports QSPI and the IO2 and IO3
+# pins must be soldered to T9 and P8 (center on J3)
+set_io flash_io2 T9
+set_io flash_io3 P8
set_io ser_tx B12
set_io ser_rx B10
+# left on J3
+set_io debug_ser_tx T1
+set_io debug_ser_rx R3
+
+# right on J3
+set_io debug_flash_csb T15
+set_io debug_flash_clk R16
+set_io debug_flash_io0 N12
+set_io debug_flash_io1 P13
+set_io debug_flash_io2 T13
+set_io debug_flash_io3 T14
+
set_io leds[7] B5 # D9
set_io leds[6] B4 # D8
set_io leds[5] A2 # D7
diff --git a/picosoc/hx8kdemo.v b/picosoc/hx8kdemo.v
index 97f97b1..9cf6605 100644
--- a/picosoc/hx8kdemo.v
+++ b/picosoc/hx8kdemo.v
@@ -30,7 +30,17 @@ module hx8kdemo (
inout flash_io0,
inout flash_io1,
inout flash_io2,
- inout flash_io3
+ inout flash_io3,
+
+ output debug_ser_tx,
+ output debug_ser_rx,
+
+ output debug_flash_csb,
+ output debug_flash_clk,
+ output debug_flash_io0,
+ output debug_flash_io1,
+ output debug_flash_io2,
+ output debug_flash_io3
);
reg [5:0] reset_cnt = 0;
wire resetn = &reset_cnt;
@@ -62,14 +72,11 @@ module hx8kdemo (
reg [31:0] iomem_rdata;
reg [31:0] gpio;
- reg [4:0] gpio_shr;
-
- assign leds = gpio >> gpio_shr;
+ assign leds = gpio;
always @(posedge clk) begin
if (!resetn) begin
gpio <= 0;
- gpio_shr <= 0;
end else begin
iomem_ready <= 0;
if (iomem_valid && !iomem_ready && iomem_addr[31:24] == 8'h 03) begin
@@ -80,9 +87,6 @@ module hx8kdemo (
if (iomem_wstrb[2]) gpio[23:16] <= iomem_wdata[23:16];
if (iomem_wstrb[3]) gpio[31:24] <= iomem_wdata[31:24];
end
- if (&leds && gpio_shr < 10) begin
- gpio_shr <= gpio_shr + 1;
- end
end
end
@@ -118,4 +122,14 @@ module hx8kdemo (
.iomem_wdata (iomem_wdata ),
.iomem_rdata (iomem_rdata )
);
+
+ assign debug_ser_tx = ser_tx;
+ assign debug_ser_rx = ser_rx;
+
+ assign debug_flash_csb = flash_csb;
+ assign debug_flash_clk = flash_clk;
+ assign debug_flash_io0 = flash_io0_di;
+ assign debug_flash_io1 = flash_io1_di;
+ assign debug_flash_io2 = flash_io2_di;
+ assign debug_flash_io3 = flash_io3_di;
endmodule
diff --git a/picosoc/hx8kdemo_tb.v b/picosoc/hx8kdemo_tb.v
index ffb292f..585c8dd 100644
--- a/picosoc/hx8kdemo_tb.v
+++ b/picosoc/hx8kdemo_tb.v
@@ -41,7 +41,7 @@ module testbench;
wire flash_io3;
always @(leds) begin
- $display("%b", leds);
+ #1 $display("%b", leds);
end
hx8kdemo uut (
diff --git a/picosoc/picosoc.v b/picosoc/picosoc.v
index a648b0e..116b237 100644
--- a/picosoc/picosoc.v
+++ b/picosoc/picosoc.v
@@ -51,7 +51,7 @@ module picosoc (
);
parameter integer MEM_WORDS = 256;
parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory
- parameter [31:0] PROGADDR_RESET = 32'h 0110_0000; // 1 MB into flash
+ parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash
wire mem_valid;
wire mem_instr;
@@ -87,7 +87,7 @@ module picosoc (
assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata :
spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do :
- simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h xxxx_xxxx;
+ simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000;
picorv32 #(
.STACKADDR(STACKADDR),
@@ -107,7 +107,7 @@ module picosoc (
spimemio spimemio (
.clk (clk),
.resetn (resetn),
- .valid (mem_valid && mem_addr[31:24] == 8'h 01),
+ .valid (mem_valid && mem_addr >= 4*MEM_WORDS && mem_addr < 32'h 0200_0000),
.ready (spimem_ready),
.addr (mem_addr[23:0]),
.rdata (spimem_rdata),
@@ -157,7 +157,7 @@ module picosoc (
always @(posedge clk) begin
ram_ready <= 0;
- if (mem_valid && !mem_ready && mem_addr[31:24] == 8'h 00) begin
+ if (mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) begin
ram_ready <= 1;
ram_rdata <= memory[mem_addr >> 2];
if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0];
diff --git a/picosoc/sections.lds b/picosoc/sections.lds
index 5c92529..1fe7919 100644
--- a/picosoc/sections.lds
+++ b/picosoc/sections.lds
@@ -1,6 +1,6 @@
SECTIONS {
.memory : {
- . = 0x000000;
+ . = 0x100000;
start*(.text);
*(.text);
*(*);
diff --git a/picosoc/start.s b/picosoc/start.s
new file mode 100644
index 0000000..47312d8
--- /dev/null
+++ b/picosoc/start.s
@@ -0,0 +1,61 @@
+.section .text
+
+start:
+addi x1, zero, 0
+addi x2, zero, 0
+addi x3, zero, 0
+addi x4, zero, 0
+addi x5, zero, 0
+addi x6, zero, 0
+addi x7, zero, 0
+addi x8, zero, 0
+addi x9, zero, 0
+addi x10, zero, 0
+addi x11, zero, 0
+addi x12, zero, 0
+addi x13, zero, 0
+addi x14, zero, 0
+addi x15, zero, 0
+addi x16, zero, 0
+addi x17, zero, 0
+addi x18, zero, 0
+addi x19, zero, 0
+addi x20, zero, 0
+addi x21, zero, 0
+addi x22, zero, 0
+addi x23, zero, 0
+addi x24, zero, 0
+addi x25, zero, 0
+addi x26, zero, 0
+addi x27, zero, 0
+addi x28, zero, 0
+addi x29, zero, 0
+addi x30, zero, 0
+addi x31, zero, 0
+
+li sp, 4*256
+call main
+j start
+
+.global cmd_read_spi_flash_id_worker_begin
+.global cmd_read_spi_flash_id_worker_end
+
+cmd_read_spi_flash_id_worker_begin:
+li t0,0x02000008
+li t1,'F'
+sw t1,0(t0)
+li t1,'I'
+sw t1,0(t0)
+li t1,'X'
+sw t1,0(t0)
+li t1,'M'
+sw t1,0(t0)
+li t1,'E'
+sw t1,0(t0)
+li t1,'\r'
+sw t1,0(t0)
+li t1,'\n'
+sw t1,0(t0)
+ret
+cmd_read_spi_flash_id_worker_end:
+