Skip to content

Commit

Permalink
upgrade to spinal 1.6.0
Browse files Browse the repository at this point in the history
add more handshake example
  • Loading branch information
pwang7 committed Jul 15, 2021
1 parent fb8a8f4 commit fb79692
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"image": "datenlord/spinal-cocotb:1.5.0"
"image": "datenlord/spinal-cocotb:1.6.0",
"extensions": ["scalameta.metals"]
}
2 changes: 1 addition & 1 deletion exercises/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM ubuntu

ARG JDK_VERSION=11
ARG MILL_VERSION=0.9.7
ARG SCALA_VERSION=2.12.13
ARG SCALA_VERSION=2.13.6
ENV DEBIAN_FRONTEND=noninteractive

# Install dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ApbArbiter(
require(numInputSlaves > 0)

val io = new Bundle {
val en = in Bool
val en = in Bool ()
val masterOut = master(Apb3(apbConfig))
val slavesIn = Vec(slave(Apb3(apbConfig)), numInputSlaves)
}
Expand Down
17 changes: 10 additions & 7 deletions exercises/Examples/src/main/scala/exercises/Booth.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ class Booth(width: Int) extends Component {
require(width > 1)

val io = new Bundle {
val load = in Bool
val load = in Bool ()
val multiplicand = in SInt (width bits)
val multipler = in SInt (width bits)
val ready = out Bool
val ready = out Bool ()
val product = out SInt (2 * width bits)
}

val buf = Reg(SInt(2 * width + 1 bits)) init (0) simPublic ()
val upperPart = buf(2 * width downto width + 1) simPublic ()
val lowerPart = buf(width downto 0) simPublic ()

val buf = Reg(SInt(2 * width + 1 bits)) init (0)
val upperPart = buf(2 * width downto width + 1)
val lowerPart = buf(width downto 0)
val cnt = CounterFreeRun(stateCount = width + 2)
cnt.value simPublic ()

buf.simPublic()
upperPart.simPublic()
lowerPart.simPublic()
cnt.value.simPublic()

when(io.load) {
buf := S(0, width bits) @@ io.multipler @@ S(0, 1 bit)
Expand Down
8 changes: 4 additions & 4 deletions exercises/Examples/src/main/scala/exercises/FifoCC.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ class FifoCC[T <: Data](

val io = new Bundle {
val wData = in(dataType())
val wEn = in Bool
val wFull = out Bool
val wEn = in Bool ()
val wFull = out Bool ()
val rData = out(dataType())
val rEn = in Bool
val rEmpty = out Bool
val rEn = in Bool ()
val rEmpty = out Bool ()
}

val ADDR_WIDTH = log2Up(depth + 1)
Expand Down
77 changes: 71 additions & 6 deletions exercises/Examples/src/main/scala/exercises/HandShakePipe.scala
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// https://www.itdev.co.uk/blog/pipelining-axi-buses-registered-ready-signals
// http://fpgacpu.ca/fpga/Pipeline_Skid_Buffer.html

package exercises

import spinal.core._
import spinal.core.sim._
import spinal.lib._
import spinal.sim._
import spinal.lib.fsm._

class HandShakePipe(width: Int) extends Component {
val io = new Bundle {
val input = new Bundle {
val valid = in Bool
val valid = in Bool ()
val payload = in UInt (width bits)
val ready = out Bool
val ready = out Bool ()
}

val output = new Bundle {
val valid = out Bool
val valid = out Bool ()
val payload = out UInt (width bits)
val ready = in Bool
val ready = in Bool ()
}
}
}
Expand Down Expand Up @@ -154,3 +154,68 @@ class BothHandShakePipe2(
}
}
}

class BothHandShakePipe3(
width: Int
) extends HandShakePipe(width) {

object SkidBufState extends SpinalEnum {
val EMPTY, BUSY, FULL = newElement()
}

val load = Bool()
val unload = Bool()
val flow = Bool()
val fill = Bool()
val flush = Bool()

val insert = io.input.valid && io.input.ready
val remove = io.output.valid && io.output.ready

val skidBufferReg = Reg(UInt(width bits)) init (0)
val outBufferReg = Reg(UInt(width bits)) init (0)

val state = Reg(SkidBufState) init (SkidBufState.EMPTY)

load := state === SkidBufState.EMPTY && insert && !remove
unload := state === SkidBufState.BUSY && !insert && remove
flow := state === SkidBufState.BUSY && insert && remove
fill := state === SkidBufState.BUSY && insert && !remove
flush := state === SkidBufState.FULL && !insert && remove

when(flush) {
outBufferReg := skidBufferReg
} elsewhen (load || flow) {
outBufferReg := io.input.payload
}
when(fill) {
skidBufferReg := io.input.payload
}

val nextState = SkidBufState()
nextState := state
switch(state) {
is(SkidBufState.EMPTY) {
when(load) {
nextState := SkidBufState.BUSY
}
}
is(SkidBufState.BUSY) {
when(fill) {
nextState := SkidBufState.FULL
} elsewhen (unload) {
nextState := SkidBufState.EMPTY
}
}
is(SkidBufState.FULL) {
when(flush) {
nextState := SkidBufState.BUSY
}
}
}
state := nextState

io.input.ready := state =/= SkidBufState.FULL
io.output.valid := state =/= SkidBufState.EMPTY
io.output.payload := outBufferReg
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,15 @@ class HandShakePipeTest extends AnyFunSuite {
stream.io.simPublic()
}

def simTest(dut: PipeTB) {
class BothPipe3TB(width: Int) extends PipeTB(width) {
override val pipe = new BothHandShakePipe3(width)
override val stream = new BothPipeStream2(width)

pipe.io.simPublic()
stream.io.simPublic()
}

def simTest(dut: PipeTB): Unit = {
SimTimeout(1000)
dut.clockDomain.forkStimulus(2)

Expand Down Expand Up @@ -145,7 +153,10 @@ class HandShakePipeTest extends AnyFunSuite {
dut.stream.io.sin.valid #= true
dut.stream.io.sin.payload #= din
dut.clockDomain.waitSampling()
assert(dut.pipe.io.input.ready.toBoolean == dut.stream.io.sin.ready.toBoolean)
assert(
dut.pipe.io.input.ready.toBoolean == dut.stream.io.sin.ready.toBoolean,
s"pipe ri=${dut.pipe.io.input.ready.toBoolean} not match stream ri=${dut.stream.io.sin.ready.toBoolean}"
)
if (dut.pipe.io.input.valid.toBoolean && dut.pipe.io.input.ready.toBoolean) {
din += 1
}
Expand All @@ -159,11 +170,14 @@ class HandShakePipeTest extends AnyFunSuite {
dut.pipe.io.output.ready #= randBool
dut.stream.io.sout.ready #= randBool
dut.clockDomain.waitSampling()
assert(dut.pipe.io.output.valid.toBoolean == dut.stream.io.sout.valid.toBoolean)
assert(
dut.pipe.io.output.valid.toBoolean == dut.stream.io.sout.valid.toBoolean,
s"pipe vo=${dut.pipe.io.output.valid.toBoolean} not match stream vo=${dut.stream.io.sout.valid.toBoolean}"
)
if (dut.pipe.io.output.valid.toBoolean && dut.pipe.io.output.ready.toBoolean) {
assert(
dut.pipe.io.output.payload.toInt == dut.stream.io.sout.payload.toInt,
s"dout=${dut.pipe.io.output.payload.toInt} != ${dut.stream.io.sout.payload.toInt}"
s"pipe dout=${dut.pipe.io.output.payload.toInt} not match stream dout=${dut.stream.io.sout.payload.toInt}"
)
matchCnt += 1
if (matchCnt > 100) {
Expand Down Expand Up @@ -224,5 +238,12 @@ class HandShakePipeTest extends AnyFunSuite {
.compile(new BothPipe2TB(width))
.doSim(simTest(_))
}

test("pipeline fsm") {
SimConfig
.withWave
.compile(new BothPipe3TB(width))
.doSim(simTest(_))
}
}

13 changes: 4 additions & 9 deletions exercises/build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import $ivy.`com.goyeau::mill-scalafix:0.2.2`
import com.goyeau.mill.scalafix.ScalafixModule
import mill._, scalalib._, scalafmt._

val SpinalVersion = "1.5.0"
val SpinalVersion = "1.6.0"

trait CommonSpinalModule extends ScalaModule with ScalafmtModule with ScalafixModule {
def scalaVersion = "2.12.13"
def scalaVersion = "2.13.6"
def scalacOptions = Seq("-unchecked", "-deprecation", "-feature")

def ivyDeps = Agg(
Expand All @@ -19,14 +19,9 @@ trait CommonSpinalModule extends ScalaModule with ScalafmtModule with ScalafixMo
def scalafixIvyDeps = Agg(ivy"com.github.liancheng::organize-imports:0.5.0")
}


object Examples extends CommonSpinalModule {
object test extends Tests {
def ivyDeps = Agg(
ivy"org.scalatest::scalatest:3.2.2",
)
def testFrameworks = Seq("org.scalatest.tools.Framework")

object test extends Tests with TestModule.ScalaTest {
def ivyDeps = Agg(ivy"org.scalatest::scalatest:3.2.2")
def testOnly(args: String*) = T.command {
super.runMain("org.scalatest.run", args: _*)
}
Expand Down

0 comments on commit fb79692

Please sign in to comment.