Skip to content

Commit

Permalink
Merge pull request #8 from milovanovic/add-sp-shiftreg-mem
Browse files Browse the repository at this point in the history
Extend ShiftRegisterMem with single-port SRAM implementation
  • Loading branch information
jerryz123 committed Dec 21, 2022
2 parents 0ffb46a + 9bf5171 commit 650dffa
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 55 deletions.
66 changes: 34 additions & 32 deletions src/main/scala/craft/ShiftRegisterMem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,57 @@ import chisel3.util._

object ShiftRegisterMem {

// use_sp_mem = use single port SRAMs? if false, use dual-port SRAMs
def apply[T <: Data](in: T, n: Int, en: Bool = true.B, use_sp_mem: Boolean = false, name: String = null): T =
{
requireIsHardware(in)
//require(n%2 == 0, "Odd ShiftRegsiterMem not supported yet")

if (n == 0) {
in
} else if (n == 1) {
val out = RegEnable(in, en)
out
//} else if (use_sp_mem && n%2 == 0) { // TODO: this passes the test but doesn't work for all cases
// val out = Wire(in.cloneType)
// val mem = SyncReadMem(n/2, Vec(in, in))
// if (name != null) {
// println(s"Name support not implemented")
// //sram.setName(name)
// }
// val index_counter = Counter(en, n)._1
// val raddr = (index_counter + 2.U) >> 1.U
// val waddr = RegEnable(index_counter >> 1.U, (n/2-1).U, en)
// val wen = index_counter(0) && en
// val des = Reg(in.cloneType)
// val ser = Reg(in.cloneType)

// val sram_out = Reg(next=mem.read(raddr, !wen))

// when (wen) {
// mem.write(waddr, Vec(des, in))
// out := ser
// } .otherwise {
// des := in
// out := sram_out(0)
// ser := sram_out(1)
// }
// out
} else if (use_sp_mem) {
require(n % 2 == 0, "Odd shift register length with single-port SRAMs is not supported")

val out_sp0 = Wire(in.cloneType)
out_sp0 := DontCare

val out_sp1 = Wire(in.cloneType)
out_sp1 := DontCare

val mem_sp0 = SyncReadMem(n / 2, in.cloneType)
val mem_sp1 = SyncReadMem(n / 2, in.cloneType)

val index_counter = Counter(en, n)._1
val raddr_sp0 = index_counter >> 1.U
val raddr_sp1 = RegEnable(raddr_sp0, (n / 2 - 1).U, en)

val wen_sp0 = index_counter(0)
val wen_sp1 = WireDefault(false.B)
wen_sp1 := ~wen_sp0

when(en) {
val rdwrPort = mem_sp0(raddr_sp0)
when(wen_sp0) { rdwrPort := in }.otherwise { out_sp0 := rdwrPort }
}

when(en) {
val rdwrPort = mem_sp1(raddr_sp1)
when(wen_sp1) { rdwrPort := in }.otherwise { out_sp1 := rdwrPort }
}
val out = Mux(~wen_sp1, out_sp0, out_sp1)
out
} else {
val mem = SyncReadMem(n, in.cloneType)
if (name != null) {
mem.suggestName(name)
}
val raddr = Counter(en, n)._1
val out = mem.read(raddr)
val out = mem.read(raddr, en)

val waddr = RegEnable(raddr, (n-1).U, en) //next, init, enable
when (en) {
val waddr = RegEnable(raddr, (n - 1).U, en)
when(en) {
mem.write(waddr, in)
}

out
}
}
Expand Down
34 changes: 11 additions & 23 deletions src/test/scala/craft/ShiftRegisterMemSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ShiftRegisterMemSpec extends AnyFlatSpec with Matchers {
4 -> true,
5 -> true,
0 -> true,
0 -> true,
0 -> false, //true
0 -> true,
0 -> true,
0 -> true,
Expand All @@ -53,36 +53,22 @@ class ShiftRegisterMemSpec extends AnyFlatSpec with Matchers {
val X = -1

def runTest (dut : (UInt, Bool) => UInt, expected: Seq[Int]) =
chisel3.iotesters.Driver(() => new SRMemModule(dut)) {
chisel3.iotesters.Driver.execute(Array(
"--backend-name", "treadle"), () => new SRMemModule(dut)) {
c => new SRMemTester(c, testVector, expected)
} should be (true)

it should "work with single-ported memories, an enable, and an odd shift" in {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 5, en)

runTest(testMem _,
Seq(X, X, X, X, X, X, 1, 2, 3, 4, 5, 0, 0)
)
}

it should "work with single-ported memories, an enable, and an even shift" in {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 6, en)
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 6, en, use_sp_mem = true)

runTest(testMem _,
Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
)
}

it should "work with single-ported memories, no enable, and an odd shift" in {
def testMem(in: UInt, en: Bool) = ShiftRegisterMem(in, 5)

runTest(testMem _,
Seq(X, X, X, X, X, 1, 6, 2, 3, 4, 5, 0, 0)
//Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
Seq(X, X, X, X, X, X, X, 1, 1, 2, 3, 4, 5)
)
}

it should "work with single-ported memories, no enable, and an even shift" in {
def testMem(in: UInt, en: Bool) = ShiftRegisterMem(in, 6)
def testMem(in: UInt, en: Bool) = ShiftRegisterMem(in, 6, use_sp_mem = true)

runTest(testMem _,
Seq(X, X, X, X, X, X, 1, 6, 2, 3, 4, 5, 0)
Expand All @@ -93,15 +79,17 @@ class ShiftRegisterMemSpec extends AnyFlatSpec with Matchers {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 5, en, use_sp_mem = false)

runTest(testMem _,
Seq(X, X, X, X, X, X, 1, 2, 3, 4, 5, 0, 0)
//Seq(X, X, X, X, X, X, 1, 2, 3, 4, 5, 0, 0)
Seq(X, X, X, X, X, X, 1, 2, 2, 3, 4, 5, 0)
)
}

it should "work with dual-ported memories, an enable, and an even shift" in {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 6, en, use_sp_mem = false)

runTest(testMem _,
Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
//Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
Seq(X, X, X, X, X, X, X, 1, 1, 2, 3, 4, 5)
)
}

Expand Down

0 comments on commit 650dffa

Please sign in to comment.