Merge branch 'picosoc'

This commit is contained in:
Clifford Wolf 2017-09-15 16:31:37 +02:00
commit 1c8266869a
11 changed files with 225 additions and 153 deletions

1
picosoc/.gitignore vendored
View File

@ -3,7 +3,6 @@
/spiflash_tb.vcd /spiflash_tb.vcd
/spiflash_tb.vvp /spiflash_tb.vvp
/firmware.elf /firmware.elf
/firmware_up.elf
/firmware.hex /firmware.hex
/firmware.bin /firmware.bin
/hx8kdemo.asc /hx8kdemo.asc

View File

@ -19,6 +19,9 @@ hx8kprog: hx8kdemo.bin firmware.bin
iceprog hx8kdemo.bin iceprog hx8kdemo.bin
iceprog -o 1M firmware.bin iceprog -o 1M firmware.bin
hx8kprog_fw: firmware.bin
iceprog -o 1M firmware.bin
hx8ksim: hx8kdemo_tb.vvp firmware.hex hx8ksim: hx8kdemo_tb.vvp firmware.hex
vvp -N $< vvp -N $<
@ -46,25 +49,22 @@ hx8kdemo.bin: hx8kdemo.asc
# ---- Example Firmware ---- # ---- Example Firmware ----
firmware.elf: sections.lds firmware.S firmware.elf: sections.lds start.s firmware.c
riscv32-unknown-elf-gcc -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf firmware.S riscv32-unknown-elf-gcc -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o firmware.elf start.s firmware.c
firmware_up.elf: firmware.elf firmware.hex: firmware.elf
riscv32-unknown-elf-objcopy --change-addresses 0x100000 firmware.elf firmware_up.elf riscv32-unknown-elf-objcopy -O verilog firmware.elf /dev/stdout | sed -e '2,65537 d;' > firmware.hex
firmware.hex: firmware_up.elf
riscv32-unknown-elf-objcopy -O verilog firmware_up.elf firmware.hex
firmware.bin: firmware.elf 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 ----
clean: clean:
rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd 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.blif hx8kdemo.log hx8kdemo.asc hx8kdemo.rpt hx8kdemo.bin
rm -f hx8kdemo_syn.v hx8kdemo_syn_tb.vvp hx8kdemo_tb.vvp 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

View File

@ -38,6 +38,9 @@ and upload them to a connected iCE40-HX8K Breakout Board.
| 0x02000008 .. 0x0200000B | UART Send/Recv Data Register | | 0x02000008 .. 0x0200000B | UART Send/Recv Data Register |
| 0x03000000 .. 0xFFFFFFFF | Memory mapped user peripherals | | 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 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. byte, or -1 (all 32 bits set) when the receive buffer is empty.

View File

@ -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

105
picosoc/firmware.c Normal file
View File

@ -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;
}
}
}
}

View File

@ -7,12 +7,28 @@ set_io flash_csb R12
set_io flash_clk R11 set_io flash_clk R11
set_io flash_io0 P12 set_io flash_io0 P12
set_io flash_io1 P11 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_tx B12
set_io ser_rx B10 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[7] B5 # D9
set_io leds[6] B4 # D8 set_io leds[6] B4 # D8
set_io leds[5] A2 # D7 set_io leds[5] A2 # D7

View File

@ -30,7 +30,17 @@ module hx8kdemo (
inout flash_io0, inout flash_io0,
inout flash_io1, inout flash_io1,
inout flash_io2, 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; reg [5:0] reset_cnt = 0;
wire resetn = &reset_cnt; wire resetn = &reset_cnt;
@ -62,14 +72,11 @@ module hx8kdemo (
reg [31:0] iomem_rdata; reg [31:0] iomem_rdata;
reg [31:0] gpio; reg [31:0] gpio;
reg [4:0] gpio_shr; assign leds = gpio;
assign leds = gpio >> gpio_shr;
always @(posedge clk) begin always @(posedge clk) begin
if (!resetn) begin if (!resetn) begin
gpio <= 0; gpio <= 0;
gpio_shr <= 0;
end else begin end else begin
iomem_ready <= 0; iomem_ready <= 0;
if (iomem_valid && !iomem_ready && iomem_addr[31:24] == 8'h 03) begin 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[2]) gpio[23:16] <= iomem_wdata[23:16];
if (iomem_wstrb[3]) gpio[31:24] <= iomem_wdata[31:24]; if (iomem_wstrb[3]) gpio[31:24] <= iomem_wdata[31:24];
end end
if (&leds && gpio_shr < 10) begin
gpio_shr <= gpio_shr + 1;
end
end end
end end
@ -118,4 +122,14 @@ module hx8kdemo (
.iomem_wdata (iomem_wdata ), .iomem_wdata (iomem_wdata ),
.iomem_rdata (iomem_rdata ) .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 endmodule

View File

@ -41,7 +41,7 @@ module testbench;
wire flash_io3; wire flash_io3;
always @(leds) begin always @(leds) begin
$display("%b", leds); #1 $display("%b", leds);
end end
hx8kdemo uut ( hx8kdemo uut (

View File

@ -51,7 +51,7 @@ module picosoc (
); );
parameter integer MEM_WORDS = 256; parameter integer MEM_WORDS = 256;
parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory 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_valid;
wire mem_instr; 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 : 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 : 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 #( picorv32 #(
.STACKADDR(STACKADDR), .STACKADDR(STACKADDR),
@ -107,7 +107,7 @@ module picosoc (
spimemio spimemio ( spimemio spimemio (
.clk (clk), .clk (clk),
.resetn (resetn), .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), .ready (spimem_ready),
.addr (mem_addr[23:0]), .addr (mem_addr[23:0]),
.rdata (spimem_rdata), .rdata (spimem_rdata),
@ -157,7 +157,7 @@ module picosoc (
always @(posedge clk) begin always @(posedge clk) begin
ram_ready <= 0; 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_ready <= 1;
ram_rdata <= memory[mem_addr >> 2]; ram_rdata <= memory[mem_addr >> 2];
if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0]; if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0];

View File

@ -1,6 +1,6 @@
SECTIONS { SECTIONS {
.memory : { .memory : {
. = 0x000000; . = 0x100000;
start*(.text); start*(.text);
*(.text); *(.text);
*(*); *(*);

61
picosoc/start.s Normal file
View File

@ -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: