1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
package vexriscv.demo
import java.nio.{ByteBuffer, ByteOrder}
import spinal.core._
import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
import spinal.lib.bus.misc.SizeMapping
import spinal.lib.misc.{HexTools, InterruptCtrl, Prescaler, Timer}
import spinal.lib._
import spinal.lib.bus.simple._
import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus}
class MuraxMasterArbiter(pipelinedMemoryBusConfig : PipelinedMemoryBusConfig, bigEndian : Boolean = false) extends Component{
val io = new Bundle{
val iBus = slave(IBusSimpleBus(null))
val dBus = slave(DBusSimpleBus(bigEndian))
val masterBus = master(PipelinedMemoryBus(pipelinedMemoryBusConfig))
}
io.masterBus.cmd.valid := io.iBus.cmd.valid || io.dBus.cmd.valid
io.masterBus.cmd.write := io.dBus.cmd.valid && io.dBus.cmd.wr
io.masterBus.cmd.address := io.dBus.cmd.valid ? io.dBus.cmd.address | io.iBus.cmd.pc
io.masterBus.cmd.data := io.dBus.cmd.data
io.masterBus.cmd.mask := io.dBus.genMask(io.dBus.cmd)
io.iBus.cmd.ready := io.masterBus.cmd.ready && !io.dBus.cmd.valid
io.dBus.cmd.ready := io.masterBus.cmd.ready
val rspPending = RegInit(False) clearWhen(io.masterBus.rsp.valid)
val rspTarget = RegInit(False)
when(io.masterBus.cmd.fire && !io.masterBus.cmd.write){
rspTarget := io.dBus.cmd.valid
rspPending := True
}
when(rspPending && !io.masterBus.rsp.valid){
io.iBus.cmd.ready := False
io.dBus.cmd.ready := False
io.masterBus.cmd.valid := False
}
io.iBus.rsp.valid := io.masterBus.rsp.valid && !rspTarget
io.iBus.rsp.inst := io.masterBus.rsp.data
io.iBus.rsp.error := False
io.dBus.rsp.ready := io.masterBus.rsp.valid && rspTarget
io.dBus.rsp.data := io.masterBus.rsp.data
io.dBus.rsp.error := False
}
case class MuraxPipelinedMemoryBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, pipelinedMemoryBusConfig : PipelinedMemoryBusConfig, bigEndian : Boolean = false) extends Component{
val io = new Bundle{
val bus = slave(PipelinedMemoryBus(pipelinedMemoryBusConfig))
}
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
io.bus.rsp.valid := RegNext(io.bus.cmd.fire && !io.bus.cmd.write) init(False)
io.bus.rsp.data := ram.readWriteSync(
address = (io.bus.cmd.address >> 2).resized,
data = io.bus.cmd.data,
enable = io.bus.cmd.valid,
write = io.bus.cmd.write,
mask = io.bus.cmd.mask
)
io.bus.cmd.ready := True
if(onChipRamHexFile != null){
HexTools.initRam(ram, onChipRamHexFile, 0x80000000l)
if(bigEndian)
// HexTools.initRam (incorrectly) assumes little endian byte ordering
for((word, wordIndex) <- ram.initialContent.zipWithIndex)
ram.initialContent(wordIndex) =
((word & 0xffl) << 24) |
((word & 0xff00l) << 8) |
((word & 0xff0000l) >> 8) |
((word & 0xff000000l) >> 24)
}
}
case class Apb3Rom(onChipRamBinFile : String) extends Component{
import java.nio.file.{Files, Paths}
val byteArray = Files.readAllBytes(Paths.get(onChipRamBinFile))
val wordCount = (byteArray.length+3)/4
val buffer = ByteBuffer.wrap(Files.readAllBytes(Paths.get(onChipRamBinFile))).order(ByteOrder.LITTLE_ENDIAN);
val wordArray = (0 until wordCount).map(i => {
val v = buffer.getInt
if(v < 0) BigInt(v.toLong & 0xFFFFFFFFl) else BigInt(v)
})
val io = new Bundle{
val apb = slave(Apb3(log2Up(wordCount*4),32))
}
val rom = Mem(Bits(32 bits), wordCount) initBigInt(wordArray)
// io.apb.PRDATA := rom.readSync(io.apb.PADDR >> 2)
io.apb.PRDATA := rom.readAsync(RegNext(io.apb.PADDR >> 2))
io.apb.PREADY := True
}
class MuraxPipelinedMemoryBusDecoder(master : PipelinedMemoryBus, val specification : Seq[(PipelinedMemoryBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
val masterPipelined = PipelinedMemoryBus(master.config)
if(!pipelineMaster) {
masterPipelined.cmd << master.cmd
masterPipelined.rsp >> master.rsp
} else {
masterPipelined.cmd <-< master.cmd
masterPipelined.rsp >> master.rsp
}
val slaveBuses = specification.map(_._1)
val memorySpaces = specification.map(_._2)
val hits = for((slaveBus, memorySpace) <- specification) yield {
val hit = memorySpace.hit(masterPipelined.cmd.address)
slaveBus.cmd.valid := masterPipelined.cmd.valid && hit
slaveBus.cmd.payload := masterPipelined.cmd.payload.resized
hit
}
val noHit = !hits.orR
masterPipelined.cmd.ready := (hits,slaveBuses).zipped.map(_ && _.cmd.ready).orR || noHit
val rspPending = RegInit(False) clearWhen(masterPipelined.rsp.valid) setWhen(masterPipelined.cmd.fire && !masterPipelined.cmd.write)
val rspNoHit = RegNext(False) init(False) setWhen(noHit)
val rspSourceId = RegNextWhen(OHToUInt(hits), masterPipelined.cmd.fire)
masterPipelined.rsp.valid := slaveBuses.map(_.rsp.valid).orR || (rspPending && rspNoHit)
masterPipelined.rsp.payload := slaveBuses.map(_.rsp.payload).read(rspSourceId)
when(rspPending && !masterPipelined.rsp.valid) { //Only one pending read request is allowed
masterPipelined.cmd.ready := False
slaveBuses.foreach(_.cmd.valid := False)
}
}
class MuraxApb3Timer extends Component{
val io = new Bundle {
val apb = slave(Apb3(
addressWidth = 8,
dataWidth = 32
))
val interrupt = out Bool()
}
val prescaler = Prescaler(16)
val timerA,timerB = Timer(16)
val busCtrl = Apb3SlaveFactory(io.apb)
val prescalerBridge = prescaler.driveFrom(busCtrl,0x00)
val timerABridge = timerA.driveFrom(busCtrl,0x40)(
ticks = List(True, prescaler.io.overflow),
clears = List(timerA.io.full)
)
val timerBBridge = timerB.driveFrom(busCtrl,0x50)(
ticks = List(True, prescaler.io.overflow),
clears = List(timerB.io.full)
)
val interruptCtrl = InterruptCtrl(2)
val interruptCtrlBridge = interruptCtrl.driveFrom(busCtrl,0x10)
interruptCtrl.io.inputs(0) := timerA.io.full
interruptCtrl.io.inputs(1) := timerB.io.full
io.interrupt := interruptCtrl.io.pendings.orR
}
object MuraxApb3TimerGen extends App{
SpinalVhdl(new MuraxApb3Timer())
}
|