Skip to content

Commit 3c9525f

Browse files
authored
fix(ClockGate): fix bug that ICG is invalid when disable mbist (OpenXiangShan#470)
After adding DFT, if DFT is not enabled, due to the assignment `a.clock := clock`, it will directly assign the ungated clock to the SRAM that requires MCP2, causing errors. Therefore, for the `!hasMbist` case, additionally gate the clock for the SRAM. When DFT is enabled, both `wclk` and `rclk` of `mbistCgCtl` are assigned to `cg.out_clock`. Therefore, although there is the assignment `a.clock := clock`, it does not cause errors. Additionally, clock gate should always be true when enable MCP2. This commit adds the corresponding requirement check for MCP2 SRAM.
1 parent 59f3025 commit 3c9525f

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

src/main/scala/coupledL2/DataStorage.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ class DataStorage(implicit p: Parameters) extends L2Module {
7575
readMCP2 = true,
7676
hasMbist = p(L2ParamKey).hasMbist,
7777
hasSramCtl = p(L2ParamKey).hasSramCtl,
78-
extraHold = enableClockGate,
79-
withClockGate = enableClockGate
78+
extraHold = true,
79+
withClockGate = true
8080
))
8181
array.io_en := io.en
8282
private val mbistPl = MbistPipeline.PlaceMbistPipeline(1, "L2DataStorage", p(L2ParamKey).hasMbist)

src/main/scala/coupledL2/utils/GatedSplittedSRAM.scala

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import chisel3._
44
import chisel3.util._
55
import utility.mbist.MbistClockGateCell
66
import utility.sram.{SramBroadcastBundle, SramHelper}
7+
import utility.ClockGate
78

89
// SplittedSRAM with clockGate to each of the small splitted srams
910
// - this is a requirement from DFT, cause mbist needs to access each sram separately
@@ -39,23 +40,32 @@ class GatedSplittedSRAM[T <: Data]
3940
extClockGate = withClockGate,
4041
suffix = Some(suffix.getOrElse(SramHelper.getSramSuffix(valName.value)))
4142
) {
43+
require(
44+
!readMCP2 || (extraHold && withClockGate),
45+
"When readMCP2 is true, both extraHold and withClockGate must be true"
46+
)
47+
4248
// en is the actual r/w valid (last for one cycle)
4349
// en is used to generate gated_clock for each SRAM
4450
val io_en = IO(Input(Bool()))
4551

4652
// Create a ClockGate module for each element in the array
4753
if (withClockGate) {
48-
array.map(_.map(_.map(a => {
49-
val cg = Module(new MbistClockGateCell(extraHold))
50-
cg.E := io_en
51-
cg.dft.fromBroadcast(a.io.broadcast.getOrElse(0.U.asTypeOf(new SramBroadcastBundle)))
52-
cg.mbist.req := a.io.mbistCgCtl.map(_.en).getOrElse(false.B)
53-
cg.mbist.writeen := a.io.mbistCgCtl.map(_.wckEn).getOrElse(false.B)
54-
cg.mbist.readen := a.io.mbistCgCtl.map(_.rckEn).getOrElse(false.B)
55-
a.io.mbistCgCtl.foreach(_.wclk := cg.out_clock)
56-
a.io.mbistCgCtl.foreach(_.rclk := cg.out_clock)
57-
a.clock := clock
58-
})))
54+
if (hasMbist) {
55+
array.map(_.map(_.map(a => {
56+
val cg = Module(new MbistClockGateCell(extraHold))
57+
cg.E := io_en
58+
cg.dft.fromBroadcast(a.io.broadcast.getOrElse(0.U.asTypeOf(new SramBroadcastBundle)))
59+
cg.mbist.req := a.io.mbistCgCtl.map(_.en).getOrElse(false.B)
60+
cg.mbist.writeen := a.io.mbistCgCtl.map(_.wckEn).getOrElse(false.B)
61+
cg.mbist.readen := a.io.mbistCgCtl.map(_.rckEn).getOrElse(false.B)
62+
a.io.mbistCgCtl.foreach(_.wclk := cg.out_clock)
63+
a.io.mbistCgCtl.foreach(_.rclk := cg.out_clock)
64+
a.clock := clock
65+
})))
66+
} else {
67+
array.map(_.map(_.map(_.clock := ClockGate(false.B, io_en, clock))))
68+
}
5969
}
6070

6171
// TODO: for now, all small SRAMs use the unified `io_en` signal for gating.

0 commit comments

Comments
 (0)