Skip to content

Commit cda1381

Browse files
author
electronut
committed
added picosoc gpio
1 parent abe6742 commit cda1381

21 files changed

+3050
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ These projects use the Lattice iCE40HX1k and the *icestorm* open source FPGA too
2121

2222
- **ultrasonic** - talking to ultrasonic sensor HC-SR04 and displaying distance on a 4-digit 7-segment display
2323

24+
**picosoc_gpio** - simpe RISC-V based Picosoc demo that shows how to enable interrupts.
25+
2426
## Migen Examples
2527

2628
- **blinky** - a simple blinky in Migen/Python

ice40up5k/picosoc_gpio/.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/spiflash_tb.vcd
2+
/spiflash_tb.vvp
3+
/lice40up5k.asc
4+
/lice40up5k.bin
5+
/lice40up5k.json
6+
/lice40up5k.log
7+
/lice40up5k.rpt
8+
/lice40up5k_syn.v
9+
/lice40up5k_syn_tb.vvp
10+
/lice40up5k_tb.vvp
11+
/lice40up5k_fw.elf
12+
/lice40up5k_fw.hex
13+
/lice40up5k_fw.bin
14+
/lice40up5k_sections.lds
15+
/testbench.vcd
16+
/cmos.log
17+

ice40up5k/picosoc_gpio/Makefile

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
2+
CROSS=riscv32-unknown-elf-
3+
CFLAGS=
4+
5+
PICORV32_DIR=../picorv32
6+
PICOSOC_DIR=$(PICORV32_DIR)
7+
8+
# ---- Lattice iCE40 Ultra Plus Breakout Board ----
9+
10+
lice40upsim: lice40up_tb.vvp lice40up_fw.hex
11+
vvp -N $< +firmware=lice40up_fw.hex
12+
13+
lice40upsynsim: lice40up_syn_tb.vvp lice40up_fw.hex
14+
vvp -N $< +firmware=lice40up_fw.hex
15+
16+
lice40up.json: lice40up.v ice40up5k_spram.v spimemio.v simpleuart.v picosoc.v $(PICORV32_DIR)/picorv32.v
17+
yosys -ql lice40up.log -p 'synth_ice40 -top lice40up -json lice40up.json' $^
18+
19+
lice40up_tb.vvp: lice40up_tb.v lice40up.v ice40up5k_spram.v spimemio.v simpleuart.v picosoc.v $(PICORV32_DIR)/picorv32.v spiflash.v
20+
iverilog -s testbench -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v`
21+
22+
lice40up_syn_tb.vvp: lice40up_tb.v lice40up_syn.v spiflash.v
23+
iverilog -s testbench -o $@ $^ `yosys-config --datdir/ice40/cells_sim.v`
24+
25+
lice40up_syn.v: lice40up.json
26+
yosys -p 'read_json lice40up.json; write_verilog lice40up_syn.v'
27+
28+
lice40up.asc: lice40up.pcf lice40up.json
29+
nextpnr-ice40 --freq 13 --up5k --asc lice40up.asc --pcf lice40up.pcf --json lice40up.json
30+
31+
lice40up.bin: lice40up.asc
32+
icetime -d up5k -c 12 -mtr lice40up.rpt lice40up.asc
33+
icepack lice40up.asc lice40up.bin
34+
35+
lice40upprog: lice40up.bin lice40up_fw.bin
36+
iceprog lice40up.bin
37+
iceprog -o 1M lice40up_fw.bin
38+
39+
lice40upprog_fw: lice40up_fw.bin
40+
iceprog -o 1M lice40up_fw.bin
41+
42+
lice40up_sections.lds: sections.lds
43+
$(CROSS)cpp -P -DLICE40UP -o $@ $^
44+
45+
lice40up_fw.elf: lice40up_sections.lds start.s firmware_lice40up.c
46+
$(CROSS)gcc $(CFLAGS) -DLICE40UP -march=rv32ic -Wl,-Bstatic,-T,lice40up_sections.lds,--strip-debug -ffreestanding -nostdlib -o lice40up_fw.elf start.s firmware_lice40up.c
47+
48+
lice40up_fw.hex: lice40up_fw.elf
49+
$(CROSS)objcopy -O verilog lice40up_fw.elf lice40up_fw.hex
50+
51+
lice40up_fw.bin: lice40up_fw.elf
52+
$(CROSS)objcopy -O binary lice40up_fw.elf lice40up_fw.bin
53+
54+
# ---- Testbench for SPI Flash Model ----
55+
56+
spiflash_tb: spiflash_tb.vvp firmware.hex
57+
vvp -N $<
58+
59+
spiflash_tb.vvp: spiflash.v spiflash_tb.v
60+
iverilog -s testbench -o $@ $^
61+
62+
# ---- ASIC Synthesis Tests ----
63+
64+
cmos.log: spimemio.v simpleuart.v picosoc.v $(PICORV32_DIR)/picorv32.v
65+
yosys -l cmos.log -p 'synth -top picosoc; abc -g cmos2; opt -fast; stat' $^
66+
67+
# ---- Clean ----
68+
69+
clean:
70+
rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd
71+
rm -f lice40up_fw.elf lice40up_fw.hex lice40up_fw.bin
72+
rm -f lice40up.json lice40up.log lice40up.asc lice40up.rpt lice40up.bin
73+
rm -f lice40up_syn.v lice40up_syn_tb.vvp lice40up_tb.vvp
74+
75+
.PHONY: spiflash_tb clean
76+
.PHONY: lice40upprog lice40upprog_fw lice40upsim lice40upsynsim

ice40up5k/picosoc_gpio/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## picosoc_gpio
2+
3+
A simple demo of interrupts on RISC-V Picosoc on iCEUP5k FPGA.
4+
5+
Install picorv32 from:
6+
7+
https://github.com/cliffordwolf/picorv32
8+
9+
Ensure that you set `PICORV32_DIR` to the correct path in the Makefile.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// This is free and unencumbered software released into the public domain.
2+
//
3+
// Anyone is free to copy, modify, publish, use, compile, sell, or
4+
// distribute this software, either in source code form or as a compiled
5+
// binary, for any purpose, commercial or non-commercial, and by any
6+
// means.
7+
8+
#define regnum_q0 0
9+
#define regnum_q1 1
10+
#define regnum_q2 2
11+
#define regnum_q3 3
12+
13+
#define regnum_x0 0
14+
#define regnum_x1 1
15+
#define regnum_x2 2
16+
#define regnum_x3 3
17+
#define regnum_x4 4
18+
#define regnum_x5 5
19+
#define regnum_x6 6
20+
#define regnum_x7 7
21+
#define regnum_x8 8
22+
#define regnum_x9 9
23+
#define regnum_x10 10
24+
#define regnum_x11 11
25+
#define regnum_x12 12
26+
#define regnum_x13 13
27+
#define regnum_x14 14
28+
#define regnum_x15 15
29+
#define regnum_x16 16
30+
#define regnum_x17 17
31+
#define regnum_x18 18
32+
#define regnum_x19 19
33+
#define regnum_x20 20
34+
#define regnum_x21 21
35+
#define regnum_x22 22
36+
#define regnum_x23 23
37+
#define regnum_x24 24
38+
#define regnum_x25 25
39+
#define regnum_x26 26
40+
#define regnum_x27 27
41+
#define regnum_x28 28
42+
#define regnum_x29 29
43+
#define regnum_x30 30
44+
#define regnum_x31 31
45+
46+
#define regnum_zero 0
47+
#define regnum_ra 1
48+
#define regnum_sp 2
49+
#define regnum_gp 3
50+
#define regnum_tp 4
51+
#define regnum_t0 5
52+
#define regnum_t1 6
53+
#define regnum_t2 7
54+
#define regnum_s0 8
55+
#define regnum_s1 9
56+
#define regnum_a0 10
57+
#define regnum_a1 11
58+
#define regnum_a2 12
59+
#define regnum_a3 13
60+
#define regnum_a4 14
61+
#define regnum_a5 15
62+
#define regnum_a6 16
63+
#define regnum_a7 17
64+
#define regnum_s2 18
65+
#define regnum_s3 19
66+
#define regnum_s4 20
67+
#define regnum_s5 21
68+
#define regnum_s6 22
69+
#define regnum_s7 23
70+
#define regnum_s8 24
71+
#define regnum_s9 25
72+
#define regnum_s10 26
73+
#define regnum_s11 27
74+
#define regnum_t3 28
75+
#define regnum_t4 29
76+
#define regnum_t5 30
77+
#define regnum_t6 31
78+
79+
// x8 is s0 and also fp
80+
#define regnum_fp 8
81+
82+
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
83+
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
84+
85+
#define picorv32_getq_insn(_rd, _qs) \
86+
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
87+
88+
#define picorv32_setq_insn(_qd, _rs) \
89+
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
90+
91+
#define picorv32_retirq_insn() \
92+
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
93+
94+
#define picorv32_maskirq_insn(_rd, _rs) \
95+
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
96+
97+
#define picorv32_waitirq_insn(_rd) \
98+
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
99+
100+
#define picorv32_timer_insn(_rd, _rs) \
101+
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
102+
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#include <stdint.h>
2+
#include <stdbool.h>
3+
4+
5+
// a pointer to this is a null pointer, but the compiler does not
6+
// know that because "sram" is a linker symbol from sections.lds.
7+
extern uint32_t sram;
8+
9+
#define reg_spictrl (*(volatile uint32_t*)0x02000000)
10+
#define reg_uart_clkdiv (*(volatile uint32_t*)0x02000004)
11+
#define reg_uart_data (*(volatile uint32_t*)0x02000008)
12+
#define reg_leds (*(volatile uint32_t*)0x03000000)
13+
#define reg_btns (*(volatile uint32_t*)0x03000004)
14+
15+
16+
// --------------------------------------------------------
17+
18+
void putchar(char c)
19+
{
20+
if (c == '\n')
21+
putchar('\r');
22+
reg_uart_data = c;
23+
}
24+
25+
void print(const char *p)
26+
{
27+
while (*p)
28+
putchar(*(p++));
29+
}
30+
31+
void print_hex(uint32_t v, int digits)
32+
{
33+
for (int i = 7; i >= 0; i--) {
34+
char c = "0123456789abcdef"[(v >> (4*i)) & 15];
35+
if (c == '0' && i >= digits) continue;
36+
putchar(c);
37+
digits = i;
38+
}
39+
}
40+
41+
void print_dec(uint32_t v)
42+
{
43+
if (v >= 1000) {
44+
print(">=1000");
45+
return;
46+
}
47+
48+
if (v >= 900) { putchar('9'); v -= 900; }
49+
else if (v >= 800) { putchar('8'); v -= 800; }
50+
else if (v >= 700) { putchar('7'); v -= 700; }
51+
else if (v >= 600) { putchar('6'); v -= 600; }
52+
else if (v >= 500) { putchar('5'); v -= 500; }
53+
else if (v >= 400) { putchar('4'); v -= 400; }
54+
else if (v >= 300) { putchar('3'); v -= 300; }
55+
else if (v >= 200) { putchar('2'); v -= 200; }
56+
else if (v >= 100) { putchar('1'); v -= 100; }
57+
58+
if (v >= 90) { putchar('9'); v -= 90; }
59+
else if (v >= 80) { putchar('8'); v -= 80; }
60+
else if (v >= 70) { putchar('7'); v -= 70; }
61+
else if (v >= 60) { putchar('6'); v -= 60; }
62+
else if (v >= 50) { putchar('5'); v -= 50; }
63+
else if (v >= 40) { putchar('4'); v -= 40; }
64+
else if (v >= 30) { putchar('3'); v -= 30; }
65+
else if (v >= 20) { putchar('2'); v -= 20; }
66+
else if (v >= 10) { putchar('1'); v -= 10; }
67+
68+
if (v >= 9) { putchar('9'); v -= 9; }
69+
else if (v >= 8) { putchar('8'); v -= 8; }
70+
else if (v >= 7) { putchar('7'); v -= 7; }
71+
else if (v >= 6) { putchar('6'); v -= 6; }
72+
else if (v >= 5) { putchar('5'); v -= 5; }
73+
else if (v >= 4) { putchar('4'); v -= 4; }
74+
else if (v >= 3) { putchar('3'); v -= 3; }
75+
else if (v >= 2) { putchar('2'); v -= 2; }
76+
else if (v >= 1) { putchar('1'); v -= 1; }
77+
else putchar('0');
78+
}
79+
80+
char getchar_prompt(char *prompt)
81+
{
82+
int32_t c = -1;
83+
84+
uint32_t cycles_begin, cycles_now, cycles;
85+
__asm__ volatile ("rdcycle %0" : "=r"(cycles_begin));
86+
87+
reg_leds = ~0;
88+
89+
if (prompt)
90+
print(prompt);
91+
92+
while (c == -1) {
93+
__asm__ volatile ("rdcycle %0" : "=r"(cycles_now));
94+
cycles = cycles_now - cycles_begin;
95+
if (cycles > 12000000) {
96+
if (prompt)
97+
print(prompt);
98+
cycles_begin = cycles_now;
99+
reg_leds = ~reg_leds;
100+
}
101+
c = reg_uart_data;
102+
}
103+
104+
reg_leds = 0;
105+
return c;
106+
}
107+
108+
char getchar()
109+
{
110+
return getchar_prompt(0);
111+
}
112+
113+
static void delay_ms(uint16_t delayms)
114+
{
115+
uint32_t N = 25*delayms;
116+
for (uint32_t i = 0; i < N; i++) {
117+
// do nothing
118+
}
119+
}
120+
121+
122+
void test_leds()
123+
{
124+
print("testing LEDs...\n\n");
125+
126+
reg_leds = 0xff;
127+
128+
for(uint8_t i = 0; i < 10; i++) {
129+
reg_leds = 0x0;
130+
delay_ms(1000);
131+
reg_leds = 0x2 ;
132+
delay_ms(1000);
133+
}
134+
}
135+
136+
uint32_t set_irq_mask(uint32_t mask); asm (
137+
".global set_irq_mask\n"
138+
"set_irq_mask:\n"
139+
".word 0x0605650b\n"
140+
"ret\n"
141+
);
142+
143+
//void irq_handler(uint32_t irqs, uint32_t *regs)
144+
uint32_t* irq_handler(uint32_t irqs, uint32_t *regs)
145+
//uint32_t *irq(uint32_t *regs, uint32_t irqs)
146+
//uint32_t* irq(uint32_t irqs, uint32_t* regs)
147+
{
148+
if ((irqs & (1<<5)) != 0) {
149+
print("i\n");
150+
//reg_leds ^= 0x01;
151+
}
152+
153+
return regs;
154+
}
155+
156+
void main() {
157+
// test with UART 115200 8N1
158+
reg_uart_clkdiv = 104;
159+
160+
set_irq_mask(0x00);
161+
162+
print("\n");
163+
print(" ____ _ ____ ____\n");
164+
print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n");
165+
print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n");
166+
print(" | __/| | (_| (_) |__) | (_) | |___\n");
167+
print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n");
168+
169+
// blink the user LED
170+
uint32_t led_timer = 0;
171+
172+
while (1) {
173+
reg_leds = led_timer >> 16;
174+
led_timer = led_timer + 1;
175+
}
176+
}

0 commit comments

Comments
 (0)