Skip to content

Commit 9b22a00

Browse files
committed
Add simulation support for SPI Flash
1 parent 207990e commit 9b22a00

File tree

7 files changed

+8614
-0
lines changed

7 files changed

+8614
-0
lines changed

sw/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
TOOLCHAIN_PREFIX ?= riscv64-unknown-elf-
2+
RESET_VECTOR ?= 0
3+
FLASH_ADDR ?= 0x0
24

35
%.elf: %.S
46
$(TOOLCHAIN_PREFIX)gcc -nostartfiles -march=rv32i -mabi=ilp32 -Tlink.ld -o$@ $<
@@ -8,5 +10,19 @@ TOOLCHAIN_PREFIX ?= riscv64-unknown-elf-
810
$(TOOLCHAIN_PREFIX)objcopy -O binary $< $@
911
%.ihex: %.elf
1012
$(TOOLCHAIN_PREFIX)objcopy -O ihex $< $@
13+
%.ub: %.bin
14+
mkimage \
15+
-A riscv \
16+
-C none \
17+
-T standalone \
18+
-a 0x0 \
19+
-e $(RESET_VECTOR) \
20+
-n '$@' \
21+
-d $< \
22+
$@
23+
24+
%.ubvh: %.ub
25+
objcopy --change-addresses $(FLASH_ADDR) -I binary -O verilog $< $@
26+
1127
clean:
1228
rm -f *.elf *.bin *.vh

sw/hello.ubvh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@00000000
2+
27 05 19 56 11 A4 6D 25 5D 53 EE 8A 00 00 00 45
3+
00 00 00 00 00 00 00 00 6D 43 B1 80 05 1A 01 00
4+
68 65 6C 6C 6F 2E 75 62 00 00 00 00 00 00 00 00
5+
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6+
37 15 00 80 13 05 85 00 97 05 00 00 93 85 85 02
7+
83 82 05 00 23 00 55 00 93 85 15 00 83 82 05 00
8+
E3 9A 02 FE B7 15 00 80 93 85 95 00 23 A0 05 00
9+
53 77 65 52 56 2B 46 75 73 65 53 6F 43 20 72 6F
10+
63 6B 73 0A 00

sw/spi_uimage_loader.S

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/* Assembly program to go into the boot ROM
2+
For use with the simple_spi core and standard SPI flash
3+
interface-compatible parts (ST M25P16 for example.)
4+
5+
Loads an image in the U-boot uimage format from SPI Flash
6+
in the the RAM at the address specified in the uimage header.
7+
After loading is completed, it will jump to the entry point
8+
address specified in the uimage header.
9+
10+
To keep it simple, only basic sanity checks are made on the image
11+
*/
12+
13+
/* Base address of the SPI controller used to communicate with the Flash */
14+
#ifndef SPI_BASE
15+
#define SPI_BASE 0x80001040
16+
#endif
17+
18+
/* Base address of the SPI controller used to blink LED */
19+
#ifndef GPIO_BASE
20+
#define GPIO_BASE 0x80001010
21+
#endif
22+
23+
/* 24-bit address in SPI Flash where application image is stored */
24+
#ifndef BOOTROM_ADDR
25+
#define BOOTROM_ADDR 0x000000
26+
#endif
27+
28+
/* Flash needs 300 us to warm up from power-on. In practice, this is only an
29+
issue in simulations as FPGA boot is far longer than 300 us
30+
*/
31+
#ifndef INIT_DELAY
32+
#define INIT_DELAY 700
33+
#endif
34+
35+
#define RAM_INIT_DONE 0x8000100A
36+
37+
#define RETRIES 3
38+
39+
#define SPI_SPCR 0x00
40+
#define SPI_SPSR 0x08
41+
#define SPI_SPDR 0x10
42+
#define SPI_SPER 0x18
43+
#define SPI_SPSS 0x20
44+
45+
#define SPI_SPSS_INIT 0x1
46+
#define SPI_SPSR_RX_CHECK 0x01 /* Check bit 0 is cleared, fifo !empty*/
47+
48+
.globl _start
49+
_start:
50+
/* Registers used
51+
ra link register
52+
t1 temp register
53+
t2 temp register
54+
s0 Image size
55+
s1 Load address
56+
s2 Reset vector
57+
s3 Retry counter
58+
gp SPI master base address
59+
a3 get_rx_data return value
60+
t3 temp register
61+
*/
62+
63+
boot_init:
64+
65+
#if INIT_DELAY
66+
li t1, INIT_DELAY
67+
and t2, zero, zero
68+
1: addi t2,t2,1
69+
bne t1, t2, 1b
70+
#endif
71+
72+
/* Wait until RAM initialization is done */
73+
li t1, RAM_INIT_DONE
74+
1: lbu t2, 0(t1)
75+
beqz t2, 1b
76+
77+
/* Load SPI base address to gp */
78+
li gp, SPI_BASE
79+
80+
li s3, RETRIES
81+
spi_init:
82+
/* Clear slave selects */
83+
sb zero, SPI_SPSS(gp)
84+
fence
85+
86+
/* Set clock divider to 4 (arbitrarily chosen value)
87+
and enable controller */
88+
addi t1, zero, 0x40 | 0x01
89+
sb t1, SPI_SPCR(gp)
90+
fence
91+
92+
/* Set appropriate slave select */
93+
addi t1, zero, 1
94+
sb t1, SPI_SPSS(gp)
95+
fence
96+
97+
/* Set command to READ at BOOTROM_ADDR */
98+
li a0, ((BOOTROM_ADDR & 0xFF) <<24) | ((BOOTROM_ADDR & 0xFF00) << 8) | ((BOOTROM_ADDR & 0xFF0000) >> 8) | 0x3
99+
jal spi_xfer
100+
101+
/* Get magic word */
102+
jal spi_xfer
103+
104+
/* Verify that magic word is (endian-swapped) 0x27051956
105+
Retry a couple of times before we give up */
106+
addi s3, s3, -1
107+
beqz s3, boot_fail
108+
li t1, 0x56190527
109+
bne t1, a1, spi_init
110+
111+
112+
read_header:
113+
/* Dummy read two words */
114+
jal spi_xfer
115+
jal spi_xfer
116+
117+
/* Load image size to s0 */
118+
jal spi_xfer
119+
jal endian_swap
120+
mv s0, a2
121+
122+
/* Load RAM base address to s1 */
123+
jal spi_xfer
124+
jal endian_swap
125+
mv s1, a2
126+
127+
/* Load reset vector to s2 */
128+
jal spi_xfer
129+
jal endian_swap
130+
mv s2, a2
131+
132+
/* Dummy read rest of header */
133+
jal spi_xfer //dcrc
134+
jal spi_xfer //os, arch, type, comp
135+
136+
jal spi_xfer
137+
jal spi_xfer
138+
jal spi_xfer
139+
jal spi_xfer
140+
jal spi_xfer
141+
jal spi_xfer
142+
jal spi_xfer
143+
jal spi_xfer
144+
145+
/* Clear number of copied bytes */
146+
addi s4, zero, 0
147+
copy_to_ram:
148+
jal spi_xfer
149+
150+
/* Set memory store address */
151+
add t1, s1, s4
152+
153+
/* Write word to RAM */
154+
sw a1, 0(t1)
155+
fence
156+
157+
/* Increase counter */
158+
addi s4, s4, 4
159+
160+
/* Check if file is completely copied */
161+
bge s0, s4, copy_to_ram
162+
163+
/* Jump to entry point */
164+
goto_reset:
165+
jr s2
166+
167+
/* Spin here on boot failures */
168+
boot_fail: j boot_fail
169+
170+
/* Reads ddccbbaa from a1, stores aabbccdd to a2 */
171+
endian_swap:
172+
slli a2, a1, 24 // a2 = aa000000
173+
srli t1, a1, 8 // t1 = 00ddccbb
174+
andi t1, t1, 0xff // t1 = 000000bb
175+
slli t1, t1, 16 // t1 = 00bb0000
176+
or a2, a2, t1 // a2 = aabb0000
177+
178+
srli t1, a1, 16 // t1 = 0000ddcc
179+
andi t1, t1, 0xff // t1 = 000000cc
180+
slli t1, t1, 8 // t1 = 0000cc00
181+
or a2, a2, t1 // a2 = aabbcc00
182+
183+
srli t1, a1, 24 // t1 = 000000dd
184+
or a2, a2, t1 // a2 = aabbccdd
185+
186+
ret
187+
188+
spi_xfer:
189+
/* Loop four times */
190+
addi t0, zero, 4
191+
192+
spi_xfer_loop:
193+
/* Send data in a0[7:0] */
194+
sb a0, SPI_SPDR(gp)
195+
fence
196+
197+
spi_xfer_poll:
198+
/* Wait for data in RX FIFO */
199+
lbu t1, SPI_SPSR(gp)
200+
fence
201+
andi t1, t1, SPI_SPSR_RX_CHECK
202+
bnez t1, spi_xfer_poll
203+
204+
srli a1, a1, 8
205+
lbu t1, SPI_SPDR(gp)
206+
slli t1, t1, 24
207+
or a1, a1, t1
208+
209+
srli a0, a0, 8
210+
addi t0, t0, -1
211+
bnez t0, spi_xfer_loop
212+
213+
ret

sw/spi_uimage_loader.vh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
000073B32BC00313
2+
FE731EE300138393
3+
00A3031380001337
4+
FE038EE300034383
5+
04018193800011B7
6+
0201802300300993
7+
041003130FF0000F
8+
0FF0000F00618023
9+
0261802300100313
10+
003005130FF0000F
11+
0C0000EF0C4000EF
12+
08098263FFF98993
13+
5273031356190337
14+
0A8000EFFCB312E3
15+
0A0000EF0A4000EF
16+
0006041306C000EF
17+
060000EF094000EF
18+
088000EF00060493
19+
00060913054000EF
20+
078000EF07C000EF
21+
070000EF074000EF
22+
068000EF06C000EF
23+
060000EF064000EF
24+
058000EF05C000EF
25+
050000EF00000A13
26+
00B3202301448333
27+
004A0A130FF0000F
28+
00090067FF4456E3
29+
018596130000006F
30+
0FF373130085D313
31+
0066663301031313
32+
0FF373130105D313
33+
0066663300831313
34+
006666330185D313
35+
0040029300008067
36+
0FF0000F00A18823
37+
0FF0000F0081C303
38+
FE031AE300137313
39+
0101C3030085D593
40+
0065E5B301831313
41+
FFF2829300855513
42+
00008067FC0298E3
43+
0000000000000000

swervolf.core

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ filesets:
3636
depend : [jtag_vpi]
3737
verilator_waiver: {files: [data/verilator_waiver.vlt : {file_type : vlt}]}
3838

39+
spi_tb:
40+
files:
41+
- tb/s25fl128s.v
42+
- tb/swervolf_spi_tb.v
43+
- sw/hello.ubvh : {file_type : user, copyto : hello.ubvh}
44+
file_type : verilogSource
45+
3946
nexys_a7_files:
4047
files :
4148
- data/vivado_waiver.tcl : {file_type : tclSource}
@@ -48,6 +55,7 @@ filesets:
4855
bootrom:
4956
files :
5057
- sw/blinky.vh : {file_type : user, copyto : blinky.vh}
58+
- sw/spi_uimage_loader.vh : {file_type : user, copyto : spi_uimage_loader.vh}
5159

5260
targets:
5361
sim:
@@ -73,6 +81,25 @@ targets:
7381
verilator_options : [--trace, -Wno-fatal]
7482
toplevel : swervolf_core_tb
7583

84+
spi_tb:
85+
default_tool : modelsim
86+
filesets :
87+
- bootrom
88+
- core
89+
- bfm
90+
- spi_tb
91+
92+
generate : [intercon, swerv_default_config]
93+
parameters : [SIMPRINT=true, ram_init_file, rom_init_file, flash_init_file, mem_clear=true, timeout, vcd]
94+
tools:
95+
modelsim:
96+
vlog_options :
97+
- -mfcu
98+
- -cuautoname=du
99+
- config/common_defines.vh
100+
- -timescale 1ns/1ns
101+
toplevel : swervolf_spi_tb
102+
76103
nexys_a7:
77104
default_tool : vivado
78105
filesets :
@@ -151,6 +178,11 @@ parameters:
151178
description : Verilog hex file to use as initial bootrom RAM contents
152179
paramtype : plusarg
153180

181+
flash_init_file:
182+
datatype: file
183+
description : Verilog hex file to use as initial SPI Flash contents
184+
paramtype : vlogparam
185+
154186
signature:
155187
datatype : file
156188
paramtype : plusarg

0 commit comments

Comments
 (0)