From 6140824de98026fcc9355074008b3d253242000e Mon Sep 17 00:00:00 2001 From: Pu Wang Date: Tue, 25 May 2021 00:11:30 +0800 Subject: [PATCH] handshake more examples --- .../main/scala/exercises/HandShakePipe.scala | 101 +++++++++++++----- .../scala/exercises/HandShakePipeTest.scala | 43 +++++++- 2 files changed, 117 insertions(+), 27 deletions(-) diff --git a/exercises/Examples/src/main/scala/exercises/HandShakePipe.scala b/exercises/Examples/src/main/scala/exercises/HandShakePipe.scala index cc6125b..3335d0e 100644 --- a/exercises/Examples/src/main/scala/exercises/HandShakePipe.scala +++ b/exercises/Examples/src/main/scala/exercises/HandShakePipe.scala @@ -1,10 +1,11 @@ +// https://www.itdev.co.uk/blog/pipelining-axi-buses-registered-ready-signals + package exercises import spinal.core._ import spinal.core.sim._ import spinal.lib._ import spinal.sim._ -import spinal.lib.sim.SimData class HandShakePipe(width: Int) extends Component { val io = new Bundle { @@ -57,34 +58,18 @@ class S2MHandShakePipe( val validReg = Reg(Bool) init (False) if (noBubble) { - // io.output.payload := validReg ? doutReg | io.input.payload + io.output.valid := io.input.valid || validReg + io.output.payload := validReg ? doutReg | io.input.payload - when(io.output.ready && !readyReg) { - io.output.payload := validReg ? doutReg | io.input.payload - io.output.valid := validReg || io.input.valid - io.input.ready := !validReg - doutReg := 0 - validReg := False - }.elsewhen(io.output.ready && readyReg) { - io.output.payload := io.input.payload - io.output.valid := io.input.valid - io.input.ready := readyReg // True - doutReg := 0 + io.input.ready := ~validReg + + when(io.output.ready) { validReg := False - }.elsewhen(!io.output.ready && readyReg) { // Cache input data if valid - io.output.payload := io.input.payload - io.output.valid := io.input.valid - io.input.ready := readyReg // True + } + + when(io.input.ready && ~io.output.ready) { doutReg := io.input.payload validReg := io.input.valid - }.otherwise { // !io.output.ready && !readyReg - io.output.payload := validReg ? doutReg | io.input.payload - io.output.valid := io.input.valid || validReg - io.input.ready := !validReg - when(io.input.valid && io.input.ready) { // Cache input data if valid - doutReg := io.input.payload - validReg := True - } } } else { io.input.ready := readyReg @@ -103,3 +88,69 @@ class S2MHandShakePipe( } } } + +class BothHandShakePipe( + width: Int +) extends HandShakePipe(width) { + val primDataReg = Reg(UInt(width bits)) init (0) + val primVldReg = Reg(Bool) init (False) + + val sideDataReg = Reg(UInt(width bits)) init (0) + val sideVldReg = Reg(Bool) init (False) + + io.input.ready := ~sideVldReg + io.output.valid := primVldReg || sideVldReg + io.output.payload := sideVldReg ? sideDataReg | primDataReg + + when(io.output.ready) { + sideVldReg := False + } + + when(io.input.ready) { + primDataReg := io.input.payload + primVldReg := io.input.valid + + when(~io.output.ready) { + sideDataReg := primDataReg + sideVldReg := primVldReg + } + } +} + +class BothHandShakePipe2( + width: Int +) extends HandShakePipe(width) { + val firstDataReg = Reg(UInt(width bits)) init (0) + val firstVldReg = Reg(Bool) init (False) + + val interStream = Stream(UInt(width bits)) + + val secondDataReg = Reg(UInt(width bits)) init (0) + val secondVldReg = Reg(Bool) init (False) + + val s2mArea = new Area { + io.input.ready := ~firstVldReg + interStream.valid := io.input.valid || firstVldReg + interStream.payload := firstVldReg ? firstDataReg | io.input.payload + + when(interStream.ready) { + firstVldReg := False + } + + when(io.input.ready && ~interStream.ready) { + firstDataReg := io.input.payload + firstVldReg := io.input.valid + } + } + + val m2sArea = new Area { + io.output.valid := secondVldReg + io.output.payload := secondDataReg + interStream.ready := io.output.ready || ~secondVldReg + + when(interStream.ready) { + secondDataReg := interStream.payload + secondVldReg := interStream.valid + } + } +} diff --git a/exercises/Examples/test/src/scala/exercises/HandShakePipeTest.scala b/exercises/Examples/test/src/scala/exercises/HandShakePipeTest.scala index b7ec706..0c3c219 100644 --- a/exercises/Examples/test/src/scala/exercises/HandShakePipeTest.scala +++ b/exercises/Examples/test/src/scala/exercises/HandShakePipeTest.scala @@ -68,6 +68,14 @@ class HandShakePipeTest extends AnyFunSuite { io.sout << io.sin.s2mPipe() } + class BothPipeStream(width: Int) extends PipeStream(width) { + io.sout << io.sin.m2sPipe().s2mPipe() + } + + class BothPipeStream2(width: Int) extends PipeStream(width) { + io.sout << io.sin.s2mPipe().m2sPipe() + } + abstract class PipeTB(width: Int) extends Component { val pipe: HandShakePipe val stream: PipeStream @@ -93,6 +101,22 @@ class HandShakePipeTest extends AnyFunSuite { pipe.doutReg.simPublic() } + class BothPipeTB(width: Int) extends PipeTB(width) { + override val pipe = new BothHandShakePipe(width) + override val stream = new BothPipeStream(width) + + pipe.io.simPublic() + stream.io.simPublic() + } + + class BothPipe2TB(width: Int) extends PipeTB(width) { + override val pipe = new BothHandShakePipe2(width) + override val stream = new BothPipeStream2(width) + + pipe.io.simPublic() + stream.io.simPublic() + } + def simTest(dut: PipeTB) { SimTimeout(1000) dut.clockDomain.forkStimulus(2) @@ -184,6 +208,21 @@ class HandShakePipeTest extends AnyFunSuite { SimConfig .withWave .compile(new S2MPipeTB(width)) - .doSim(simTest(_))//(seed = 896944298) + .doSim(simTest(_)) + } + + test("valid pipeline + ready pipeline") { + SimConfig + .withWave + .compile(new BothPipeTB(width)) + .doSim(simTest(_)) } -} \ No newline at end of file + + test("ready pipeline + valid pipeline") { + SimConfig + .withWave + .compile(new BothPipe2TB(width)) + .doSim(simTest(_)) + } +} +