From c3e2bd3c4ea71354cea34e53a1dc41b36a66b5f5 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Mon, 10 Jan 2022 16:28:54 +0800 Subject: [PATCH] Add support for multiple CS pin for SDRAM controller --- .../spinal/lib/memory/sdram/SdramLayout.scala | 8 ++-- .../spinal/lib/memory/sdram/sdr/Sdram.scala | 2 +- .../lib/memory/sdram/sdr/SdramCtrl.scala | 38 ++++++++++--------- .../lib/memory/sdram/sdr/sim/SdramModel.scala | 4 +- .../memory/sdram/xdr/phy/SdrInferedPhy.scala | 2 +- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/lib/src/main/scala/spinal/lib/memory/sdram/SdramLayout.scala b/lib/src/main/scala/spinal/lib/memory/sdram/SdramLayout.scala index acbcb951b0..7bf2a1de81 100644 --- a/lib/src/main/scala/spinal/lib/memory/sdram/SdramLayout.scala +++ b/lib/src/main/scala/spinal/lib/memory/sdram/SdramLayout.scala @@ -46,10 +46,12 @@ case class SdramLayout( generation : SdramGeneration, bankWidth : Int, columnWidth : Int, rowWidth : Int, - dataWidth : Int){ + dataWidth : Int, + csWidth : Int = 1){ def bytePerWord = dataWidth/8 - def wordAddressWidth = bankWidth + columnWidth + rowWidth - def byteAddressWidth = bankWidth + columnWidth + rowWidth + log2Up(bytePerWord) + def csAddressWidth = if (csWidth == 1) 0 else log2Up(csWidth) + def wordAddressWidth = bankWidth + columnWidth + rowWidth + csAddressWidth + def byteAddressWidth = wordAddressWidth + log2Up(bytePerWord) def chipAddressWidth = Math.max(columnWidth,rowWidth) def bankCount = 1 << bankWidth def capacity = BigInt(1) << byteAddressWidth diff --git a/lib/src/main/scala/spinal/lib/memory/sdram/sdr/Sdram.scala b/lib/src/main/scala/spinal/lib/memory/sdram/sdr/Sdram.scala index 435eaa5c34..3962346978 100644 --- a/lib/src/main/scala/spinal/lib/memory/sdram/sdr/Sdram.scala +++ b/lib/src/main/scala/spinal/lib/memory/sdram/sdr/Sdram.scala @@ -26,7 +26,7 @@ case class SdramInterface(g : SdramLayout) extends Bundle with IMasterSlave{ val DQM = Bits(g.bytePerWord bits) val CASn = Bool() val CKE = Bool() - val CSn = Bool() + val CSn = Bits(g.csWidth bits) val RASn = Bool() val WEn = Bool() diff --git a/lib/src/main/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala b/lib/src/main/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala index 8f76ad4dba..4575326464 100644 --- a/lib/src/main/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala +++ b/lib/src/main/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala @@ -110,6 +110,7 @@ case class SdramCtrlBackendCmd[T <: Data](c : SdramLayout,contextType : T) exten val data = Bits(c.dataWidth bits) val mask = Bits(c.bytePerWord bits) val context = cloneOf(contextType) + val cs = Bits(c.csWidth bits) } case class SdramCtrlBank(c : SdramLayout) extends Bundle{ @@ -153,13 +154,14 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co val frontend = new Area{ - val banks = Reg(Vec(SdramCtrlBank(l),l.bankCount)) - banks.foreach(_.active init(False)) + val banks = Reg(Vec(Vec(SdramCtrlBank(l),l.bankCount), l.csWidth)) + banks.foreach(_.foreach(_.active init(False))) val address = new Bundle{ val column = UInt(l.columnWidth bits) val bank = UInt(l.bankWidth bits) val row = UInt(l.rowWidth bits) + val chip = UInt(l.csAddressWidth bits) } address.assignFromBits(io.bus.cmd.address.asBits) @@ -171,6 +173,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co rsp.data := io.bus.cmd.data rsp.mask := io.bus.cmd.mask rsp.context := io.bus.cmd.context + rsp.cs := ~(B(l.csWidth bits, 0 -> True, default -> False) |<< address.chip) io.bus.cmd.ready := False @@ -207,10 +210,11 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co default { //RUN when(refresh.pending){ rsp.valid := True - when(banks.map(_.active).reduce(_ || _)){ + // When any of the banks are active + when(banks.map(_.map(_.active).reduce(_ || _)).reduce(_ || _)){ rsp.task := PRECHARGE_ALL when(rsp.ready){ - banks.foreach(_.active := False) + banks.foreach(_.foreach(_.active := False)) } } otherwise { rsp.task := REFRESH @@ -220,15 +224,15 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co } }elsewhen(io.bus.cmd.valid){ rsp.valid := True - val bank = banks(address.bank) + val bank = banks(address.chip)(address.bank) + when(bank.active && bank.row =/= address.row){ rsp.task := PRECHARGE_SINGLE when(rsp.ready){ - banks(address.bank).active := False + bank.active := False } - } elsewhen (!banks(address.bank).active) { + } elsewhen (!bank.active) { rsp.task := ACTIVE - val bank = banks(address.bank) bank.row := address.row when(rsp.ready){ bank.active := True @@ -357,7 +361,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co when(remoteCke){ sdram.DQ.read := io.sdram.DQ.read - sdram.CSn := False + sdram.CSn.clearAll() sdram.RASn := True sdram.CASn := True sdram.WEn := True @@ -369,13 +373,13 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co switch(cmd.task) { is(PRECHARGE_ALL) { sdram.ADDR(10) := True - sdram.CSn := False + sdram.CSn.clearAll() sdram.RASn := False sdram.CASn := True sdram.WEn := False } is(REFRESH) { - sdram.CSn := False + sdram.CSn.clearAll() sdram.RASn := False sdram.CASn := False sdram.WEn := True @@ -388,7 +392,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co sdram.ADDR(8 downto 7) := 0 sdram.ADDR(9) := False sdram.BA := 0 - sdram.CSn := False + sdram.CSn.clearAll() sdram.RASn := False sdram.CASn := False sdram.WEn := False @@ -396,7 +400,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co is(ACTIVE) { sdram.ADDR := cmd.rowColumn.asBits sdram.BA := cmd.bank.asBits - sdram.CSn := False + sdram.CSn := cmd.cs sdram.RASn := False sdram.CASn := True sdram.WEn := True @@ -408,7 +412,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co sdram.DQ.write := cmd.data sdram.DQM := ~cmd.mask sdram.BA := cmd.bank.asBits - sdram.CSn := False + sdram.CSn := cmd.cs sdram.RASn := True sdram.CASn := False sdram.WEn := False @@ -418,7 +422,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co sdram.ADDR := cmd.rowColumn.asBits sdram.ADDR(10) := False sdram.BA := cmd.bank.asBits - sdram.CSn := False + sdram.CSn := cmd.cs sdram.RASn := True sdram.CASn := False sdram.WEn := True @@ -426,7 +430,7 @@ case class SdramCtrl[T <: Data](l : SdramLayout, t : SdramTimings, CAS : Int, co is(PRECHARGE_SINGLE) { sdram.BA := cmd.bank.asBits sdram.ADDR(10) := False - sdram.CSn := False + sdram.CSn := cmd.cs sdram.RASn := False sdram.CASn := True sdram.WEn := False @@ -452,4 +456,4 @@ object SdramCtrlMain{ val device = IS42x320D SpinalConfig(defaultClockDomainFrequency = FixedFrequency(100 MHz)).generateVhdl(SdramCtrl(device.layout,device.timingGrade7,3,UInt(8 bits))) } -} \ No newline at end of file +} diff --git a/lib/src/main/scala/spinal/lib/memory/sdram/sdr/sim/SdramModel.scala b/lib/src/main/scala/spinal/lib/memory/sdram/sdr/sim/SdramModel.scala index c57d9d3bbf..b6f8b7fcb2 100644 --- a/lib/src/main/scala/spinal/lib/memory/sdram/sdr/sim/SdramModel.scala +++ b/lib/src/main/scala/spinal/lib/memory/sdram/sdr/sim/SdramModel.scala @@ -67,7 +67,7 @@ case class SdramModel(io : SdramInterface, } def report(msg : String) = println(simTime() + " " + msg) clockDomain.onSamplings{ - if(!io.CSn.toBoolean && ckeLast){ + if(!io.CSn(0).toBoolean && ckeLast){ val code = (if(io.RASn.toBoolean) 0x4 else 0) | (if(io.CASn.toBoolean) 0x2 else 0) | (if(io.WEn.toBoolean) 0x1 else 0) val ba = io.BA.toInt val addr = io.ADDR.toInt @@ -136,4 +136,4 @@ case class SdramModel(io : SdramInterface, } } } -} \ No newline at end of file +} diff --git a/lib/src/main/scala/spinal/lib/memory/sdram/xdr/phy/SdrInferedPhy.scala b/lib/src/main/scala/spinal/lib/memory/sdram/xdr/phy/SdrInferedPhy.scala index a5856d4da3..5e485f0740 100644 --- a/lib/src/main/scala/spinal/lib/memory/sdram/xdr/phy/SdrInferedPhy.scala +++ b/lib/src/main/scala/spinal/lib/memory/sdram/xdr/phy/SdrInferedPhy.scala @@ -35,7 +35,7 @@ case class SdrInferedPhy(sl : SdramLayout) extends Component{ regs.DQM := io.ctrl.phases(0).DM(0) regs.CASn := io.ctrl.phases(0).CASn regs.CKE := io.ctrl.phases(0).CKE - regs.CSn := io.ctrl.phases(0).CSn + regs.CSn(0) := io.ctrl.phases(0).CSn regs.RASn := io.ctrl.phases(0).RASn regs.WEn := io.ctrl.phases(0).WEn