Skip to content

Commit e1fa2e6

Browse files
authored
Merge pull request #4 from Kev-J/add_err_i_sig
Add wishbone error signals as options
2 parents cc0a9a0 + 5fd6f1a commit e1fa2e6

File tree

3 files changed

+120
-14
lines changed

3 files changed

+120
-14
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
project/
2+
target/
3+
4+
**/*.swp

src/main/scala/wbplumbing/wbplumbing.scala

+25-7
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,39 @@ import chisel3.experimental._
88
// (no SEL, no TAG, no pipeline, ...)
99
class WbMaster (val dwidth: Int,
1010
val awidth: Int,
11-
val iname: String = "Noname") extends Bundle {
11+
val iname: String = "Noname",
12+
val feature_err: Boolean = false) extends Bundle {
1213
val adr_o = Output(UInt(awidth.W))
1314
val dat_i = Input(UInt(dwidth.W))
1415
val dat_o = Output(UInt(dwidth.W))
1516
val we_o = Output(Bool())
1617
val stb_o = Output(Bool())
1718
val ack_i = Input(Bool())
1819
val cyc_o = Output(Bool())
20+
val err_i = if (feature_err == true) Some(Input(Bool())) else None
1921
}
2022

2123
// Wishbone slave interface
2224
class WbSlave (val dwidth: Int,
2325
val awidth: Int,
24-
val iname: String = "Noname") extends Bundle {
26+
val iname: String = "Noname",
27+
val feature_err: Boolean = false) extends Bundle {
2528
val adr_i = Input(UInt(awidth.W))
2629
val dat_i = Input(UInt(dwidth.W))
2730
val dat_o = Output(UInt(dwidth.W))
2831
val we_i = Input(Bool())
2932
val stb_i = Input(Bool())
3033
val ack_o = Output(Bool())
34+
val err_o = if (feature_err == true) Some(Output(Bool())) else None
3135
val cyc_i = Input(Bool())
3236
}
3337

3438
// Wishbone Intercon Pass Trought : one master, one slave
3539
class WbInterconPT (val awbm: WbMaster,
3640
val awbs: WbSlave) extends Module {
3741
val io = IO(new Bundle{
38-
val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth))
39-
val wbs = Flipped(new WbSlave(awbs.dwidth, awbs.awidth))
42+
val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth, awbm.iname, awbm.feature_err))
43+
val wbs = Flipped(new WbSlave(awbs.dwidth, awbs.awidth, awbs.iname, awbs.feature_err))
4044
})
4145

4246
assert(awbm.dwidth == awbs.dwidth,
@@ -54,21 +58,28 @@ class WbInterconPT (val awbm: WbMaster,
5458
io.wbm.ack_i := io.wbs.ack_o
5559
io.wbm.dat_i := io.wbs.dat_o
5660

61+
if (io.wbm.feature_err && io.wbs.feature_err) {
62+
io.wbm.err_i.get := io.wbs.err_o.get
63+
}
5764
}
5865

5966
// Wishbone Intercon with one master and several slaves
6067
// data bus is same size as master
6168
class WbInterconOneMaster(val awbm: WbMaster,
62-
val awbs: Seq[WbSlave]) extends Module {
69+
val awbs: Seq[WbSlave]
70+
) extends Module {
6371
val io = IO(new Bundle{
64-
val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth))
65-
val wbs = MixedVec(awbs.map{i => Flipped(new WbSlave(i.dwidth, i.awidth, i.iname))})
72+
val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth, awbm.iname, awbm.feature_err))
73+
val wbs = MixedVec(awbs.map{i => Flipped(new WbSlave(i.dwidth, i.awidth, i.iname, i.feature_err))})
6674
})
6775

6876
var addrSlave = Seq(0)
6977

7078
io.wbm.dat_i := 0.U
7179
io.wbm.ack_i := 0.U
80+
if (io.wbm.feature_err) {
81+
io.wbm.err_i.get := false.B
82+
}
7283
val dataByteSize = awbm.dwidth/8
7384
for(wbs <- io.wbs) {
7485
val slaveInterfaceName = wbs.iname
@@ -94,6 +105,13 @@ class WbInterconOneMaster(val awbm: WbMaster,
94105
wbs.cyc_i := io.wbm.cyc_o
95106
io.wbm.dat_i := wbs.dat_o
96107
io.wbm.ack_i := wbs.ack_o
108+
if (wbs.feature_err) {
109+
io.wbm.err_i.get := wbs.err_o.get
110+
}
111+
}.otherwise {
112+
if (io.wbm.feature_err) {
113+
io.wbm.err_i.get := true.B
114+
}
97115
}
98116
}
99117

src/test/scala/wbplumbing/testwbplumbing.scala

+91-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package wbplumbing
33
import chisel3._
44
import chisel3.experimental.BundleLiterals._
55
import chisel3.simulator.EphemeralSimulator._
6-
import org.scalatest.freespec.AnyFreeSpec
6+
import org.scalatest.flatspec.AnyFlatSpec
77
import org.scalatest.matchers.must.Matchers
88

99
object general {
@@ -13,13 +13,15 @@ object general {
1313
)
1414
}
1515

16-
class WbInterconPTSpec extends AnyFreeSpec with Matchers {
16+
class WbInterconPTSpec extends AnyFlatSpec with Matchers {
1717

18-
"WbInterconPT should read and write wishbone value on one slave" in {
18+
behavior of "WbInterconPT"
19+
20+
it should "read and write wishbone value on one slave" in {
1921
val args = general.optn
2022
val dataWidth = 16
21-
val wbm = new WbMaster(dataWidth, 2)
22-
val wbs = new WbSlave(dataWidth, 2)
23+
val wbm = new WbMaster(dataWidth, 2, feature_err=true)
24+
val wbs = new WbSlave(dataWidth, 2, feature_err=true)
2325

2426
simulate(new WbInterconPT(wbm, wbs)){ dut =>
2527
// just a stupid testbench that verify point to point connexion
@@ -29,6 +31,7 @@ class WbInterconPTSpec extends AnyFreeSpec with Matchers {
2931
dut.io.wbm.stb_o.poke(true.B)
3032
dut.io.wbm.cyc_o.poke(true.B)
3133
dut.io.wbs.ack_o.poke(true.B)
34+
dut.io.wbs.err_o.get.poke(true.B)
3235
dut.io.wbs.dat_o.poke(1.U)
3336
dut.clock.step(1)
3437
dut.io.wbm.adr_o.expect(1.U, "Wrong value read on wbm.adr_o")
@@ -37,13 +40,15 @@ class WbInterconPTSpec extends AnyFreeSpec with Matchers {
3740
dut.io.wbm.stb_o.expect(true.B, "Wrong value read on wbm.stb_o")
3841
dut.io.wbm.cyc_o.expect(true.B, "Wrong value read on wbm.cyc_o")
3942
dut.io.wbs.ack_o.expect(true.B, "Wrong value read on wbs.ack_o")
43+
dut.io.wbs.err_o.get.expect(true.B, "Wrong value read on wbs.err_o")
4044
dut.io.wbs.dat_o.expect(1.U, "Wrong value read on wbs.dat_o")
4145
dut.io.wbm.adr_o.poke(0.U)
4246
dut.io.wbm.dat_o.poke(0.U)
4347
dut.io.wbm.we_o.poke(false.B)
4448
dut.io.wbm.stb_o.poke(false.B)
4549
dut.io.wbm.cyc_o.poke(false.B)
4650
dut.io.wbs.ack_o.poke(false.B)
51+
dut.io.wbs.err_o.get.poke(false.B)
4752
dut.io.wbs.dat_o.poke(0.U)
4853
dut.clock.step(1)
4954
dut.io.wbm.adr_o.expect(0.U, "Wrong value read on wbm.adr_o")
@@ -52,14 +57,17 @@ class WbInterconPTSpec extends AnyFreeSpec with Matchers {
5257
dut.io.wbm.stb_o.expect(false.B, "Wrong value read on wbm.stb_o")
5358
dut.io.wbm.cyc_o.expect(false.B, "Wrong value read on wbm.cyc_o")
5459
dut.io.wbs.ack_o.expect(false.B, "Wrong value read on wbs.ack_o")
60+
dut.io.wbs.err_o.get.expect(false.B, "Wrong value read on wbs.err_o")
5561
dut.io.wbs.dat_o.expect(0.U, "Wrong value read on wbs.dat_o")
5662
}
5763
}
5864
}
5965

60-
class WbInterconOneMasterSpec extends AnyFreeSpec with Matchers {
66+
class WbInterconOneMasterSpec extends AnyFlatSpec with Matchers {
67+
68+
behavior of "WbInterconOneMaster"
6169

62-
"A WbInterconOneMaster should read and write wishbone value on two slaves" in {
70+
it should "read and write wishbone value on two slaves" in {
6371
val args = general.optn
6472
val dataWidth = 16
6573
val wbm = new WbMaster(dataWidth, 7, "Spi2WbMaster")
@@ -93,4 +101,80 @@ class WbInterconOneMasterSpec extends AnyFreeSpec with Matchers {
93101

94102
}
95103
}
104+
105+
it should "raise the err_i line of the master if read address is unmapped" in {
106+
val dataWidth = 16
107+
val wbm = new WbMaster(dataWidth, 3, "Spi2WbMaster", feature_err=true)
108+
val wbs1 = new WbSlave(dataWidth, 2, "Ksz1")
109+
110+
simulate(new WbInterconOneMaster(wbm, Seq(wbs1))) { dut =>
111+
dut.io.wbm.err_i.get.expect(false.B, "bad init of err_i")
112+
113+
// Read on unmapped address
114+
dut.io.wbm.adr_o.poke(0x4)
115+
dut.io.wbm.we_o.poke(false.B)
116+
dut.io.wbm.cyc_o.poke(true.B)
117+
dut.io.wbm.stb_o.poke(true.B)
118+
dut.clock.step(1)
119+
dut.io.wbm.err_i.get.expect(true.B, "err_i not raised")
120+
121+
// Stop transaction
122+
dut.io.wbm.cyc_o.poke(false.B)
123+
dut.io.wbm.stb_o.poke(false.B)
124+
dut.clock.step(1)
125+
dut.io.wbm.err_i.get.expect(false.B, "err_i not resetted correctly")
126+
}
127+
}
128+
129+
it should "raise the err_i line of the master if write address is unmapped" in {
130+
val dataWidth = 16
131+
val wbm = new WbMaster(dataWidth, 3, "Spi2WbMaster", feature_err=true)
132+
val wbs1 = new WbSlave(dataWidth, 2, "Ksz1")
133+
134+
simulate(new WbInterconOneMaster(wbm, Seq(wbs1))) { dut =>
135+
dut.io.wbm.err_i.get.expect(false.B, "bad init of err_i")
136+
137+
// Write on unmapped address
138+
dut.io.wbm.adr_o.poke(0x4)
139+
dut.io.wbm.we_o.poke(true.B)
140+
dut.io.wbm.cyc_o.poke(true.B)
141+
dut.io.wbm.stb_o.poke(true.B)
142+
dut.clock.step(1)
143+
dut.io.wbm.err_i.get.expect(true.B, "err_i not raised")
144+
145+
// Stop transaction
146+
dut.io.wbm.we_o.poke(false.B)
147+
dut.io.wbm.cyc_o.poke(false.B)
148+
dut.io.wbm.stb_o.poke(false.B)
149+
dut.clock.step(1)
150+
dut.io.wbm.err_i.get.expect(false.B, "err_i not resetted correctly")
151+
}
152+
}
153+
154+
it should "pass through the err_o line of the slave to the err_i line of the master" in {
155+
val dataWidth = 16
156+
val wbm = new WbMaster(dataWidth, 3, "Spi2WbMaster", feature_err=true)
157+
val wbs1 = new WbSlave(dataWidth, 2, "Ksz1", feature_err=true)
158+
159+
simulate(new WbInterconOneMaster(wbm, Seq(wbs1))) { dut =>
160+
dut.io.wbm.err_i.get.expect(false.B, "bad init of err_i")
161+
162+
// Write on unmapped address
163+
dut.io.wbm.adr_o.poke(0x0)
164+
dut.io.wbm.we_o.poke(false.B)
165+
dut.io.wbm.cyc_o.poke(true.B)
166+
dut.io.wbm.stb_o.poke(true.B)
167+
dut.clock.step(1)
168+
dut.io.wbs(0).err_o.get.poke(true.B)
169+
dut.io.wbm.err_i.get.expect(true.B, "err_i not raised")
170+
171+
// Reset err_o
172+
dut.io.wbm.we_o.poke(false.B)
173+
dut.io.wbm.cyc_o.poke(false.B)
174+
dut.io.wbm.stb_o.poke(false.B)
175+
dut.io.wbs(0).err_o.get.poke(false.B)
176+
dut.clock.step(1)
177+
dut.io.wbm.err_i.get.expect(false.B, "err_i not resetted correctly")
178+
}
179+
}
96180
}

0 commit comments

Comments
 (0)