Re-implement parallel mapping
- Support byte-masked SRAM, yay - Also nuke a bunch of bugs
This commit is contained in:
@@ -201,6 +201,9 @@ trait HasSimpleTestGenerator {
|
||||
def extraPorts: Seq[mdf.macrolib.MacroExtraPort] = List()
|
||||
def extraTag: String = ""
|
||||
|
||||
// "Effective" libMaskGran by considering write_enable.
|
||||
val effectiveLibMaskGran = libMaskGran.getOrElse(libWidth)
|
||||
|
||||
// Override this in the sub-generator if you need a more specific name.
|
||||
// Defaults to using reflection to pull the name of the test using this
|
||||
// generator.
|
||||
@@ -242,16 +245,62 @@ trait HasSimpleTestGenerator {
|
||||
writeToLib(lib, Seq(libSRAM))
|
||||
writeToMem(mem, Seq(memSRAM))
|
||||
|
||||
// For masks, width it's a bit tricky since we have to consider cases like
|
||||
// memMaskGran = 4 and libMaskGran = 8.
|
||||
// Consider the actually usable libWidth in cases like the above.
|
||||
val usableLibWidth = if (memMaskGran.getOrElse(Int.MaxValue) < effectiveLibMaskGran) memMaskGran.get else libWidth
|
||||
|
||||
// Number of lib instances needed to hold the mem, in both directions.
|
||||
// Round up (e.g. 1.5 instances = effectively 2 instances)
|
||||
val depthInstances = math.ceil(memDepth.toFloat / libDepth).toInt
|
||||
val widthInstances = math.ceil(memWidth.toFloat / libWidth).toInt
|
||||
val widthInstances = math.ceil(memWidth.toFloat / usableLibWidth).toInt
|
||||
|
||||
// Number of width bits in the last width-direction memory.
|
||||
// e.g. if memWidth = 16 and libWidth = 8, this would be 8 since the last memory 0_1 has 8 bits of input width.
|
||||
// e.g. if memWidth = 9 and libWidth = 8, this would be 1 since the last memory 0_1 has 1 bit of input width.
|
||||
val lastWidthBits = if (memWidth % libWidth == 0) libWidth else (memWidth % libWidth)
|
||||
val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth)
|
||||
val selectBits = mem_addr_width - lib_addr_width
|
||||
|
||||
/**
|
||||
* Convenience function to generate a mask statement.
|
||||
* @param widthInst Width instance (mem_0_x)
|
||||
* @param depthInst Depth instance (mem_x_0)
|
||||
*/
|
||||
def generateMaskStatement(widthInst: Int, depthInst: Int): String = {
|
||||
// Width of this submemory.
|
||||
val myMemWidth = if (widthInst == widthInstances - 1) lastWidthBits else usableLibWidth
|
||||
// Base bit of this submemory.
|
||||
// e.g. if libWidth is 8 and this is submemory 2 (0-indexed), then this
|
||||
// would be 16.
|
||||
val myBaseBit = usableLibWidth*widthInst
|
||||
|
||||
if (libMaskGran.isDefined) {
|
||||
if (memMaskGran.isEmpty) {
|
||||
// If there is no memory mask, we should just turn all the lib mask
|
||||
// bits high.
|
||||
s"""mem_${depthInst}_${widthInst}.lib_mask <= UInt<${libMaskBits}>("h${((1 << libMaskBits) - 1).toHexString}")"""
|
||||
} else {
|
||||
// Calculate which bit of outer_mask contains the given bit.
|
||||
// e.g. if memMaskGran = 2, libMaskGran = 1 and libWidth = 4, then
|
||||
// calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1
|
||||
def calculateMaskBit(bit:Int): Int = bit / memMaskGran.getOrElse(memWidth)
|
||||
|
||||
val bitsArr = ((libMaskBits - 1 to 0 by -1) map (x => {
|
||||
if (x*libMaskGran.get > myMemWidth) {
|
||||
// If we have extra mask bits leftover after the effective width,
|
||||
// disable those bits.
|
||||
"""UInt<1>("h0")"""
|
||||
} else {
|
||||
val outerMaskBit = calculateMaskBit(x*libMaskGran.get + myBaseBit)
|
||||
s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})"
|
||||
}
|
||||
}))
|
||||
val maskVal = bitsArr.reduceRight((bit, rest) => s"cat($bit, $rest)")
|
||||
s"mem_${depthInst}_${widthInst}.lib_mask <= ${maskVal}"
|
||||
}
|
||||
} else ""
|
||||
}
|
||||
|
||||
// Generate the header (contains the circuit statement and the target memory
|
||||
// module.
|
||||
def generateHeader(): String = {
|
||||
@@ -293,8 +342,6 @@ circuit $mem_name :
|
||||
def generateFooter(): String = {
|
||||
require (libSRAM.ports.size == 1, "Footer generator only supports single port lib")
|
||||
|
||||
val readEnable = if (libSRAM.ports(0).readEnable.isDefined) s"input ${libPortPrefix}_read_en : UInt<1>" else ""
|
||||
val footerMask = if (libHasMask) s"input ${libPortPrefix}_mask : UInt<${libMaskBits}>" else ""
|
||||
s"""
|
||||
extmodule $lib_name :
|
||||
${generateFooterPorts}
|
||||
|
||||
@@ -4,14 +4,105 @@ import mdf.macrolib._
|
||||
|
||||
// Test the ability of the compiler to deal with various mask combinations.
|
||||
|
||||
// Simple powers of two with bit-masked lib.
|
||||
|
||||
trait MasksTestSettings {
|
||||
this: MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator =>
|
||||
override lazy val memDepth = 2048
|
||||
override lazy val libDepth = 1024
|
||||
}
|
||||
|
||||
// Try all four different kinds of mask config:
|
||||
/**
|
||||
*
|
||||
* Non-masked mem Masked mem
|
||||
* ---------------------------------
|
||||
* Non-masked lib | | |
|
||||
* ---------------------------------
|
||||
* Masked lib | | |
|
||||
* ---------------------------------
|
||||
*/
|
||||
|
||||
class Masks_FourTypes_NonMaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 32
|
||||
override lazy val memMaskGran = None
|
||||
override lazy val libWidth = 8
|
||||
override lazy val libMaskGran = None
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
class Masks_FourTypes_NonMaskedMem_MaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 32
|
||||
override lazy val memMaskGran = None
|
||||
override lazy val libWidth = 8
|
||||
override lazy val libMaskGran = Some(2)
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
class Masks_FourTypes_MaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 32
|
||||
override lazy val memMaskGran = Some(8)
|
||||
override lazy val libWidth = 8
|
||||
override lazy val libMaskGran = None
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 32
|
||||
override lazy val memMaskGran = Some(4)
|
||||
override lazy val libWidth = 8
|
||||
override lazy val libMaskGran = None
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
class Masks_FourTypes_MaskedMem_MaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 32
|
||||
override lazy val memMaskGran = Some(8)
|
||||
override lazy val libWidth = 16
|
||||
override lazy val libMaskGran = Some(4)
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 32
|
||||
override lazy val memMaskGran = Some(8)
|
||||
override lazy val libWidth = 16
|
||||
override lazy val libMaskGran = Some(8)
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
class Masks_FourTypes_MaskedMem_MaskedLib_SmallerMaskGran extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
override lazy val depth = 1024
|
||||
override lazy val memWidth = 64
|
||||
override lazy val memMaskGran = Some(4)
|
||||
override lazy val libWidth = 32
|
||||
override lazy val libMaskGran = Some(8)
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
// FPGA-style byte-masked memories.
|
||||
|
||||
class Masks_FPGAStyle_32_8 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings {
|
||||
override lazy val width = 32
|
||||
override lazy val memMaskGran = Some(32)
|
||||
override lazy val libMaskGran = Some(8)
|
||||
|
||||
compileExecuteAndTest(mem, lib, v, output)
|
||||
}
|
||||
|
||||
// Simple powers of two with bit-masked lib.
|
||||
|
||||
class Masks_PowersOfTwo_8_1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings {
|
||||
override lazy val width = 64
|
||||
override lazy val memMaskGran = Some(8)
|
||||
|
||||
@@ -29,26 +29,7 @@ s"""
|
||||
}
|
||||
|
||||
for (i <- 0 to depthInstances - 1) {
|
||||
// We only support simple masks for now (either libMask == memMask or libMask == 1)
|
||||
val maskStatement = if (libHasMask) {
|
||||
if (libMaskGran.get == memMaskGran.get) {
|
||||
s"""mem_${i}_0.lib_mask <= bits(outer_mask, 0, 0)"""
|
||||
} else if (libMaskGran.get == 1) {
|
||||
// Construct a mask string.
|
||||
// Each bit gets the # of bits specified in maskGran.
|
||||
// Specify in descending order (MSB first)
|
||||
|
||||
// This builds an array like m[1], m[1], m[0], m[0]
|
||||
val maskBitsArr: Seq[String] = ((memMaskBits - 1 to 0 by -1) flatMap (maskBit => {
|
||||
((0 to memMaskGran.get - 1) map (_ => s"bits(outer_mask, ${maskBit}, ${maskBit})"))
|
||||
}))
|
||||
// Now build it into a recursive string like
|
||||
// cat(m[1], cat(m[1], cat(m[0], m[0])))
|
||||
val maskBitsStr: String = maskBitsArr.reverse.tail.foldLeft(maskBitsArr.reverse.head)((prev: String, next: String) => s"cat(${next}, ${prev})")
|
||||
s"""mem_${i}_0.lib_mask <= ${maskBitsStr}"""
|
||||
} else "" // TODO: implement when non-bitmasked memories are supported
|
||||
} else "" // No mask
|
||||
|
||||
val maskStatement = generateMaskStatement(0, i)
|
||||
val enableIdentifier = if (selectBits > 0) s"""eq(outer_addr_sel, UInt<${selectBits}>("h${i.toHexString}"))""" else "UInt<1>(\"h1\")"
|
||||
output.append(
|
||||
s"""
|
||||
|
||||
@@ -24,40 +24,28 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator {
|
||||
// Generate submemory connection blocks.
|
||||
output append (for (i <- 0 to widthInstances - 1) yield {
|
||||
// Width of this submemory.
|
||||
val myMemWidth = if (i == widthInstances - 1) lastWidthBits else libWidth
|
||||
val myMemWidth = if (i == widthInstances - 1) lastWidthBits else usableLibWidth
|
||||
// Base bit of this submemory.
|
||||
// e.g. if libWidth is 8 and this is submemory 2 (0-indexed), then this
|
||||
// would be 16.
|
||||
val myBaseBit = libWidth*i
|
||||
val myBaseBit = usableLibWidth*i
|
||||
|
||||
val maskStatement = if (libMaskGran.isDefined) {
|
||||
if (memMaskGran.isEmpty) {
|
||||
// If there is no memory mask, we should just turn all the lib mask
|
||||
// bits high.
|
||||
s"""mem_0_${i}.lib_mask <= UInt<${libMaskBits}>("h${((1 << libMaskBits) - 1).toHexString}")"""
|
||||
} else if (libMaskGran.get == memMaskGran.get) {
|
||||
s"mem_0_${i}.lib_mask <= bits(outer_mask, ${i}, ${i})"
|
||||
} else if (libMaskGran.get == 1) {
|
||||
// Calculate which bit of outer_mask contains the given bit.
|
||||
// e.g. if memMaskGran = 2, libMaskGran = 1 and libWidth = 4, then
|
||||
// calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1
|
||||
def calculateMaskBit(bit:Int): Int = (bit / libMaskGran.get) / memMaskGran.getOrElse(memWidth)
|
||||
val maskStatement = generateMaskStatement(i, 0)
|
||||
|
||||
// We need to use writeEnable as a crude "mask" if mem has a mask but
|
||||
// lib does not.
|
||||
val writeEnableBit = if (libMaskGran.isEmpty && memMaskGran.isDefined) {
|
||||
val outerMaskBit = myBaseBit / memMaskGran.get
|
||||
s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})"
|
||||
} else """UInt<1>("h1")"""
|
||||
|
||||
val bitsArr = ((libMaskBits - 1 to 0 by -1) map (x => {
|
||||
val outerMaskBit = calculateMaskBit(x*libMaskGran.get + myBaseBit)
|
||||
s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})"
|
||||
}))
|
||||
val maskVal = bitsArr.init.foldRight(bitsArr.last)((bit, rest) => s"cat($bit, $rest)")
|
||||
s"mem_0_${i}.lib_mask <= ${maskVal}"
|
||||
} else "" // We support only bit-level masks for now.
|
||||
} else ""
|
||||
s"""
|
||||
mem_0_${i}.lib_clk <= outer_clk
|
||||
mem_0_${i}.lib_addr <= outer_addr
|
||||
node outer_dout_0_${i} = bits(mem_0_${i}.lib_dout, ${myMemWidth - 1}, 0)
|
||||
mem_0_${i}.lib_din <= bits(outer_din, ${myBaseBit + myMemWidth - 1}, ${myBaseBit})
|
||||
${maskStatement}
|
||||
mem_0_${i}.lib_write_en <= and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1"))
|
||||
mem_0_${i}.lib_write_en <= and(and(outer_write_en, ${writeEnableBit}), UInt<1>("h1"))
|
||||
"""
|
||||
}).reduceLeft(_ + _)
|
||||
|
||||
|
||||
@@ -188,90 +188,41 @@ circuit T_2172_ext :
|
||||
input RW0_wmode : UInt<1>
|
||||
input RW0_wmask : UInt<4>
|
||||
|
||||
inst mem_0_0 of SRAM1RW64x8
|
||||
inst mem_0_1 of SRAM1RW64x8
|
||||
inst mem_0_2 of SRAM1RW64x8
|
||||
inst mem_0_3 of SRAM1RW64x8
|
||||
inst mem_0_4 of SRAM1RW64x8
|
||||
inst mem_0_5 of SRAM1RW64x8
|
||||
inst mem_0_6 of SRAM1RW64x8
|
||||
inst mem_0_7 of SRAM1RW64x8
|
||||
inst mem_0_8 of SRAM1RW64x8
|
||||
inst mem_0_9 of SRAM1RW64x8
|
||||
inst mem_0_10 of SRAM1RW64x8
|
||||
inst mem_0_11 of SRAM1RW64x8
|
||||
inst mem_0_0 of SRAM1RW64x32
|
||||
inst mem_0_1 of SRAM1RW64x32
|
||||
inst mem_0_2 of SRAM1RW64x32
|
||||
inst mem_0_3 of SRAM1RW64x32
|
||||
mem_0_0.clk <= RW0_clk
|
||||
mem_0_0.addr <= RW0_addr
|
||||
node RW0_rdata_0_0 = bits(mem_0_0.dout, 7, 0)
|
||||
mem_0_0.din <= bits(RW0_wdata, 7, 0)
|
||||
node RW0_rdata_0_0 = bits(mem_0_0.dout, 19, 0)
|
||||
mem_0_0.din <= bits(RW0_wdata, 19, 0)
|
||||
mem_0_0.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 0, 0)), UInt<1>("h1"))
|
||||
mem_0_1.clk <= RW0_clk
|
||||
mem_0_1.addr <= RW0_addr
|
||||
node RW0_rdata_0_1 = bits(mem_0_1.dout, 7, 0)
|
||||
mem_0_1.din <= bits(RW0_wdata, 15, 8)
|
||||
mem_0_1.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 0, 0)), UInt<1>("h1"))
|
||||
node RW0_rdata_0_1 = bits(mem_0_1.dout, 19, 0)
|
||||
mem_0_1.din <= bits(RW0_wdata, 39, 20)
|
||||
mem_0_1.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 1, 1)), UInt<1>("h1"))
|
||||
mem_0_2.clk <= RW0_clk
|
||||
mem_0_2.addr <= RW0_addr
|
||||
node RW0_rdata_0_2 = bits(mem_0_2.dout, 3, 0)
|
||||
mem_0_2.din <= bits(RW0_wdata, 19, 16)
|
||||
mem_0_2.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 0, 0)), UInt<1>("h1"))
|
||||
node RW0_rdata_0_2 = bits(mem_0_2.dout, 19, 0)
|
||||
mem_0_2.din <= bits(RW0_wdata, 59, 40)
|
||||
mem_0_2.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 2, 2)), UInt<1>("h1"))
|
||||
mem_0_3.clk <= RW0_clk
|
||||
mem_0_3.addr <= RW0_addr
|
||||
node RW0_rdata_0_3 = bits(mem_0_3.dout, 7, 0)
|
||||
mem_0_3.din <= bits(RW0_wdata, 27, 20)
|
||||
mem_0_3.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 1, 1)), UInt<1>("h1"))
|
||||
mem_0_4.clk <= RW0_clk
|
||||
mem_0_4.addr <= RW0_addr
|
||||
node RW0_rdata_0_4 = bits(mem_0_4.dout, 7, 0)
|
||||
mem_0_4.din <= bits(RW0_wdata, 35, 28)
|
||||
mem_0_4.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 1, 1)), UInt<1>("h1"))
|
||||
mem_0_5.clk <= RW0_clk
|
||||
mem_0_5.addr <= RW0_addr
|
||||
node RW0_rdata_0_5 = bits(mem_0_5.dout, 3, 0)
|
||||
mem_0_5.din <= bits(RW0_wdata, 39, 36)
|
||||
mem_0_5.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 1, 1)), UInt<1>("h1"))
|
||||
mem_0_6.clk <= RW0_clk
|
||||
mem_0_6.addr <= RW0_addr
|
||||
node RW0_rdata_0_6 = bits(mem_0_6.dout, 7, 0)
|
||||
mem_0_6.din <= bits(RW0_wdata, 47, 40)
|
||||
mem_0_6.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 2, 2)), UInt<1>("h1"))
|
||||
mem_0_7.clk <= RW0_clk
|
||||
mem_0_7.addr <= RW0_addr
|
||||
node RW0_rdata_0_7 = bits(mem_0_7.dout, 7, 0)
|
||||
mem_0_7.din <= bits(RW0_wdata, 55, 48)
|
||||
mem_0_7.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 2, 2)), UInt<1>("h1"))
|
||||
mem_0_8.clk <= RW0_clk
|
||||
mem_0_8.addr <= RW0_addr
|
||||
node RW0_rdata_0_8 = bits(mem_0_8.dout, 3, 0)
|
||||
mem_0_8.din <= bits(RW0_wdata, 59, 56)
|
||||
mem_0_8.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 2, 2)), UInt<1>("h1"))
|
||||
mem_0_9.clk <= RW0_clk
|
||||
mem_0_9.addr <= RW0_addr
|
||||
node RW0_rdata_0_9 = bits(mem_0_9.dout, 7, 0)
|
||||
mem_0_9.din <= bits(RW0_wdata, 67, 60)
|
||||
mem_0_9.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 3, 3)), UInt<1>("h1"))
|
||||
mem_0_10.clk <= RW0_clk
|
||||
mem_0_10.addr <= RW0_addr
|
||||
node RW0_rdata_0_10 = bits(mem_0_10.dout, 7, 0)
|
||||
mem_0_10.din <= bits(RW0_wdata, 75, 68)
|
||||
mem_0_10.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 3, 3)), UInt<1>("h1"))
|
||||
mem_0_11.clk <= RW0_clk
|
||||
mem_0_11.addr <= RW0_addr
|
||||
node RW0_rdata_0_11 = bits(mem_0_11.dout, 3, 0)
|
||||
mem_0_11.din <= bits(RW0_wdata, 79, 76)
|
||||
mem_0_11.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 3, 3)), UInt<1>("h1"))
|
||||
node RW0_rdata_0 = cat(RW0_rdata_0_11, cat(RW0_rdata_0_10, cat(RW0_rdata_0_9, cat(RW0_rdata_0_8, cat(RW0_rdata_0_7, cat(RW0_rdata_0_6, cat(RW0_rdata_0_5, cat(RW0_rdata_0_4, cat(RW0_rdata_0_3, cat(RW0_rdata_0_2, cat(RW0_rdata_0_1, RW0_rdata_0_0)))))))))))
|
||||
node RW0_rdata_0_3 = bits(mem_0_3.dout, 19, 0)
|
||||
mem_0_3.din <= bits(RW0_wdata, 79, 60)
|
||||
mem_0_3.write_en <= and(and(RW0_wmode, bits(RW0_wmask, 3, 3)), UInt<1>("h1"))
|
||||
node RW0_rdata_0 = cat(RW0_rdata_0_3, cat(RW0_rdata_0_2, cat(RW0_rdata_0_1, RW0_rdata_0_0)))
|
||||
RW0_rdata <= mux(UInt<1>("h1"), RW0_rdata_0, UInt<1>("h0"))
|
||||
|
||||
extmodule SRAM1RW64x8 :
|
||||
extmodule SRAM1RW64x32 :
|
||||
input clk : Clock
|
||||
input addr : UInt<6>
|
||||
input din : UInt<8>
|
||||
output dout : UInt<8>
|
||||
input din : UInt<32>
|
||||
output dout : UInt<32>
|
||||
input write_en : UInt<1>
|
||||
|
||||
defname = SRAM1RW64x8
|
||||
|
||||
defname = SRAM1RW64x32
|
||||
|
||||
module T_1090_ext :
|
||||
input RW0_clk : Clock
|
||||
|
||||
Reference in New Issue
Block a user