Skip to content

Commit 7bdd8c7

Browse files
committed
spi: add SPI files
1 parent 31774e0 commit 7bdd8c7

10 files changed

+668
-0
lines changed

7series.txt

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
# File: 7series.txt
3+
interface ftdi
4+
ftdi device_desc "Digilent USB Device"
5+
ftdi vid_pid 0x0403 0x6010
6+
# channel 1 does not have any functionality
7+
ftdi channel 0
8+
# just TCK TDI TDO TMS, no reset
9+
ftdi layout_init 0x0088 0x008b
10+
reset_config none
11+
adapter speed 10000
12+
13+
source [find cpld/xilinx-xc7.cfg]
14+
source [find cpld/jtagspi.cfg]
15+
init
16+
17+
puts [irscan xc7.tap 0x09]
18+
puts [drscan xc7.tap 32 0]
19+
20+
puts "Programming FPGA..."
21+
pld load 0 build/WildcatTop.bit
22+
exit

Makefile

+15
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,20 @@ latency:
2424
vcd:
2525
sbt "testOnly chisel3.tests.BasicTest -- -DwriteVcd=1"
2626

27+
synpath:
28+
source /home/shared/Xilinx/Vivado/2017.4/settings64.sh
29+
30+
HW = BitBang
31+
32+
synth:
33+
./vivado_synth.sh -t $(HW) -p xc7a100tcsg324-1 -x nexysA7.xdc -o build generated/$(HW).v
34+
35+
cp-bit:
36+
-mkdir build
37+
scp masca@chipdesign1.compute.dtu.dk:~/source/wildcat/build/$(HW).bit build
38+
# Configure the Basys3 or NexysA7 board with open source tools
39+
config:
40+
openocd -f 7series.txt
41+
2742
clean:
2843
git clean -fd

build.sbt

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ developers := List(Developer("schoeberl", "schoeberl", "martin@jopdesign.com", u
2929
licenses += ("BSD-2-Clause", url("https://opensource.org/licenses/BSD-2-Clause"))
3030
publishMavenStyle := true
3131

32+
publishConfiguration := publishConfiguration.value.withOverwrite(true)
33+
3234
// disable publishw ith scala version, otherwise artifact name will include scala version
3335
// e.g cassper_2.11
3436
crossPaths := false

nexysA7.xdc

+230
Large diffs are not rendered by default.

src/main/scala/spi/BitBang.scala

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package spi
2+
3+
import chisel.lib.uart._
4+
import chisel3._
5+
import chisel3.util._
6+
7+
/**
8+
* This is the top level to for the UART output and a test blinking LED.
9+
*/
10+
class BitBang(frequ: Int) extends Module {
11+
val io = IO(new Bundle {
12+
val rx = Input(Bool())
13+
val tx = Output(Bool())
14+
val sw = Input(UInt(4.W))
15+
val led = Output(UInt(4.W))
16+
val ncs = Output(Bool()) // pmod 4, ic 1
17+
val miso = Input(Bool()) // pmod 3, ic 2
18+
val mosi = Output(Bool()) // pmod 2, ic 5
19+
val sck = Output(Bool()) // pmod 1, ic 6
20+
})
21+
io.led := io.sw
22+
23+
val tx = Module(new BufferedTx(100000000, 115200))
24+
val rx = Module(new Rx(100000000, 115200))
25+
26+
io.tx := tx.io.txd
27+
rx.io.rxd := io.rx
28+
29+
tx.io.channel.bits := '0'.U + io.sw
30+
tx.io.channel.valid := rx.io.channel.valid
31+
rx.io.channel.ready := true.B
32+
val regVal = RegEnable('0'.U + rx.io.channel.bits(3, 0), rx.io.channel.valid)
33+
io.led := io.miso ## regVal(2, 0)
34+
35+
io.sck := regVal(0)
36+
io.mosi := regVal(1)
37+
io.ncs := regVal(2)
38+
}
39+
40+
// generate Verilog
41+
object BitBang extends App {
42+
emitVerilog(new BitBang(100000000), Array("--target-dir", "generated"))
43+
}

src/main/scala/spi/GpioPlay.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package spi
2+
3+
import chisel3._
4+
class GpioPlay extends Module {
5+
val io = IO(new Bundle {
6+
val din = Input(UInt(4.W))
7+
val led = Output(UInt(8.W))
8+
})
9+
10+
io.led := io.din
11+
12+
}
13+
14+
object GpioPlay extends App {
15+
emitVerilog(new GpioPlay(), Array("--target-dir", "generated"))
16+
}

src/main/scala/spi/README.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# SPI
2+
3+
Play with SPI devices.
4+
5+
See the `Makefile` for the hardware and test targets.
6+
7+
For running SPI simulation the two Verilog files need to be added in src/test/verilog.
8+
Due to copyright reasons they are not included in this repository.
9+
10+
Pmod pinout can be found at:
11+
12+
## Links
13+
14+
* http://ww1.microchip.com/downloads/en/devicedoc/s71271_04.pdf
15+
* http://www.cypress.com/file/316661/download
16+
* https://ww1.microchip.com/downloads/aemDocuments/documents/MPD/ProductDocuments/DataSheets/23A102423LC1024-1-Mbit-SPI-Serial-SRAM-with-SDI-SQI-Interface-20005142.pdf
17+
* SRAM example: https://www.mouser.dk/datasheet/2/1127/APM_PSRAM_QSPI_APS1604M_SQR_v2_5_PKG-1954861.pdf
18+
* Interesting IO boards: https://www.mikroe.com/flash-2-click
19+
* Slave implementation: https://github.com/nandland/spi-slave/blob/master/Verilog/source/SPI_Slave.v
20+
21+
### Simulation Models
22+
23+
* https://github.com/YosysHQ/picorv32/blob/main/picosoc/spiflash.v
24+
* https://www.cypress.com/verilog/s25fl256s-verilog (results in a .exe to expand)
25+
* see also: https://github.com/pulp-platform/pulp/tree/master/rtl/vip/spi_flash
26+
* https://www.infineon.com/cms/en/product/memories/nor-flash/semper-nor-flash-family/semper-nor-flash/?gad_source=1&gclid=Cj0KCQjwlZixBhCoARIsAIC745BlF0r2uRRUs_tH-uFewg_eQ0zYvxKVwG_Ea77YYKOk0AGSk2u4oVQaAmdSEALw_wcB&gclsrc=aw.ds#!designsupport
27+
28+
### Other Stuff
29+
30+
* https://www.mouser.dk/ProductDetail/Infineon-Technologies/EVAL-S25HL512T?qs=T%252BzbugeAwjiZrIcBHC%252BHKw%3D%3D&utm_source=octopart&utm_medium=aggregator&utm_campaign=727-EVAL-S25HL512T&utm_content=Infineon&_gl=1*1tqxjz0*_ga*MTA4ODI1ODYwNC4xNzEzNzg5NDgw*_ga_15W4STQT4T*MTcxMzgwNDI4MC4zLjAuMTcxMzgwNDI4MC42MC4wLjA.
31+
* SRAM on a PCB: https://www.mouser.dk/ProductDetail/Mikroe/MIKROE-1902?qs=mzRxyRlhVdsdV%2FIU5dBGoQ%3D%3D
32+
* board: https://www.mouser.dk/datasheet/2/272/sram-click-manual-v100-1487260.pdf
33+
* See also (new ?) Click shield versions: https://www.mikroe.com/click/storage/sram
34+
35+
## TODO
36+
37+
* Connect Arduino and/or ESP32
38+
* https://www.mouser.lu/new/adafruit/adafruit-huzzah32-esp32-dev-boards/
39+
* Are there better SPI simulation models? Those working with Verilator?
40+
* Could this be a good example for cosimulation (UVM like?)
41+
* Can I boot from a microSD card, just in hardware?
42+
* Do bit banging via serial port to SPI on the FPGA (PMOD)
43+
* I can explore more SPI on the Nexys:
44+
* SD micro connector
45+
* Accelerometer

src/main/scala/spi/SpiMaster.scala

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package spi
2+
3+
import chisel3._
4+
import chisel3.util._
5+
class SpiMaster extends Module {
6+
val spi = IO (new Bundle {
7+
val ncs = Output(Bool())
8+
val sclk = Output(Bool())
9+
val mosi = Output(Bool())
10+
val miso = Input(Bool())
11+
})
12+
val io = IO(new Bundle {
13+
val dataOut = Output(UInt(8.W))
14+
val dataIn = Input(UInt(8.W))
15+
val dataValid = Input(Bool())
16+
})
17+
18+
object State extends ChiselEnum {
19+
val idle, tx1, tx2, rx1, rx2 = Value
20+
}
21+
import State._
22+
val state = RegInit(idle)
23+
24+
val (x, y) = Counter(true.B, 10)
25+
val mosiReg = RegInit(0.U(8.W))
26+
val misoReg = RegInit(0.U(8.W))
27+
val bitsReg = RegInit(0.U(8.W))
28+
val cntReg = RegInit(0.U(8.W))
29+
30+
31+
spi.ncs := 1.U
32+
spi.sclk := x
33+
spi.mosi := mosiReg(7)
34+
io.dataOut := misoReg
35+
36+
val JTAG_ID = 0x9f.U
37+
val RDSR = 0x05.U
38+
val READ = 0x03.U
39+
40+
switch(state) {
41+
is(idle) {
42+
spi.ncs := 1.U
43+
spi.sclk := 0.U
44+
when(true.B) {
45+
state := tx1
46+
bitsReg := 7.U
47+
cntReg := 0.U
48+
mosiReg := JTAG_ID
49+
}
50+
}
51+
is(tx1) {
52+
spi.ncs := 0.U
53+
spi.sclk := 0.U
54+
cntReg := cntReg + 1.U
55+
when(cntReg === 3.U) {
56+
state := tx2
57+
cntReg := 0.U
58+
}
59+
}
60+
is(tx2) {
61+
spi.ncs := 0.U
62+
spi.sclk := 1.U
63+
cntReg := cntReg + 1.U
64+
when(cntReg === 3.U) {
65+
state := tx1
66+
cntReg := 0.U
67+
mosiReg := mosiReg(6, 0) ## 0.U // io.dataIn(7))
68+
bitsReg := bitsReg - 1.U
69+
when(bitsReg === 0.U) {
70+
state := rx1
71+
}
72+
}
73+
}
74+
is(rx1) {
75+
spi.ncs := 0.U
76+
spi.sclk := 0.U
77+
cntReg := cntReg + 1.U
78+
when(cntReg === 3.U) {
79+
state := rx2
80+
cntReg := 0.U
81+
bitsReg := bitsReg - 1.U
82+
when(bitsReg === 0.U) {
83+
state := rx1
84+
}
85+
}
86+
}
87+
is(rx2) {
88+
spi.ncs := 0.U
89+
spi.sclk := 1.U
90+
cntReg := cntReg + 1.U
91+
when(cntReg === 3.U) {
92+
state := rx1
93+
cntReg := 0.U
94+
bitsReg := bitsReg - 1.U
95+
// probably wrong bit order
96+
misoReg := spi.miso ## misoReg(7, 1)
97+
when(bitsReg === 0.U) {
98+
state := idle
99+
}
100+
}
101+
}
102+
}
103+
}
104+
105+
object SpiMaster extends App {
106+
emitVerilog(new SpiMaster(), Array("--target-dir", "generated"))
107+
}
+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package spi
2+
3+
/*
4+
* Test SPI.
5+
*
6+
* Author: Martin Schoeberl (martin@jopdesign.com)
7+
*
8+
*/
9+
10+
import chisel3._
11+
import chisel3.util._
12+
import chiseltest._
13+
import org.scalatest.flatspec.AnyFlatSpec
14+
15+
class s25hs512t extends HasBlackBoxPath {
16+
val io = IO(new Bundle() {
17+
val SI = Input(Bool())
18+
val SO = Output(Bool())
19+
val SCK = Input(Bool())
20+
val CSNeg = Input(Bool())
21+
val WPNeg = Input(Bool())
22+
val RESETNeg = Input(Bool())
23+
val IO3_RESETNeg = Input(Bool())
24+
}
25+
)
26+
addPath("./src/test/verilog/s25hs512t.sv")
27+
}
28+
29+
30+
class s25fl256s extends HasBlackBoxPath {
31+
val io = IO(new Bundle() {
32+
val SI = Input(Bool())
33+
val SO = Output(Bool())
34+
val SCK = Input(Bool())
35+
val RSTNeg = Input(Bool())
36+
val CSNeg = Input(Bool())
37+
val WPNeg = Input(Bool())
38+
val HOLDNeg = Input(Bool())
39+
}
40+
)
41+
addPath("./src/test/verilog/s25fl256s.v")
42+
}
43+
44+
45+
class TopTest extends Module {
46+
val io = IO(new Bundle {
47+
val dout = Output(UInt(8.W))
48+
})
49+
50+
val ctrl = Module(new SpiMaster)
51+
/*
52+
val flash = Module(new s25hs512t)
53+
flash.io.SI := 0.U
54+
flash.io.SCK := ctrl.spi.sclk
55+
flash.io.CSNeg := false.B
56+
flash.io.WPNeg := true.B
57+
flash.io.RESETNeg := true.B // probably !reset
58+
flash.io.IO3_RESETNeg := true.B
59+
*/
60+
61+
val flash = Module(new s25fl256s)
62+
flash.io.SI := ctrl.spi.mosi
63+
flash.io.SCK := ctrl.spi.sclk
64+
flash.io.CSNeg := ctrl.spi.ncs
65+
flash.io.RSTNeg := !reset.asUInt
66+
flash.io.WPNeg := true.B
67+
flash.io.HOLDNeg := true.B
68+
ctrl.spi.miso := flash.io.SO
69+
70+
ctrl.io.dataIn := 0.U
71+
ctrl.io.dataValid := false.B
72+
73+
io.dout := ctrl.io.dataOut
74+
}
75+
class TestSpiMaster extends AnyFlatSpec with ChiselScalatestTester {
76+
77+
"SpiMaster" should "work" in {
78+
test(new SpiMaster).withAnnotations(Seq(WriteVcdAnnotation)) { dut =>
79+
dut.clock.step(20)
80+
}
81+
}
82+
83+
"TopTest" should "work" in {
84+
test(new TopTest).withAnnotations(Seq(WriteVcdAnnotation, IcarusBackendAnnotation)) { dut =>
85+
dut.clock.step(400)
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)