Merge branch 'picosoc'
This commit is contained in:
commit
1c8266869a
|
@ -3,7 +3,6 @@
|
|||
/spiflash_tb.vcd
|
||||
/spiflash_tb.vvp
|
||||
/firmware.elf
|
||||
/firmware_up.elf
|
||||
/firmware.hex
|
||||
/firmware.bin
|
||||
/hx8kdemo.asc
|
||||
|
|
|
@ -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.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_up.elf: firmware.elf
|
||||
riscv32-unknown-elf-objcopy --change-addresses 0x100000 firmware.elf firmware_up.elf
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -41,7 +41,7 @@ module testbench;
|
|||
wire flash_io3;
|
||||
|
||||
always @(leds) begin
|
||||
$display("%b", leds);
|
||||
#1 $display("%b", leds);
|
||||
end
|
||||
|
||||
hx8kdemo uut (
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SECTIONS {
|
||||
.memory : {
|
||||
. = 0x000000;
|
||||
. = 0x100000;
|
||||
start*(.text);
|
||||
*(.text);
|
||||
*(*);
|
||||
|
|
|
@ -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:
|
||||
|
Loading…
Reference in New Issue