Source code for hwtLib.handshaked.ramAsAddrDataRdVld
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from hwt.code import If
from hwt.constants import DIRECTION
from hwt.hwIO import HwIO
from hwt.hwIOs.agents.universalComposite import UniversalCompositeAgent
from hwt.hwIOs.std import HwIODataRdVld, HwIOBramPort_noClk
from hwt.hwIOs.utils import addClkRstn
from hwt.hwModule import HwModule
from hwt.hwParam import HwParam
from hwt.hdl.types.defs import BIT
from hwt.hdl.types.struct import HStruct
from hwt.serializer.mode import serializeParamsUniq
from hwtLib.commonHwIO.addr_data import HwIOAddrDataRdVld
from hwtSimApi.hdlSimulator import HdlSimulator
from hwt.pyUtils.typingFuture import override
[docs]
class HwIORamRdVldR(HwIO):
"""
HwIODataRdVld RAM port
.. hwt-autodoc::
"""
@override
def hwConfig(self):
self.ADDR_WIDTH = HwParam(8)
self.DATA_WIDTH = HwParam(8)
@override
def hwDeclr(self):
a = self.addr = HwIODataRdVld()
a.DATA_WIDTH = self.ADDR_WIDTH
with self._hwParamsShared():
self.data = HwIODataRdVld(masterDir=DIRECTION.IN)
[docs]
@override
def _initSimAgent(self, sim: HdlSimulator):
self._ag = UniversalCompositeAgent(sim, self)
[docs]
@serializeParamsUniq
class RamAsAddrDataRdVld(HwModule):
"""
Converter from a single ram port to handshaked interfaces
.. hwt-autodoc::
"""
@override
def hwConfig(self):
HwIOBramPort_noClk.hwConfig(self)
@override
def hwDeclr(self):
assert self.HAS_R or self.HAS_W
addClkRstn(self)
with self._hwParamsShared():
if self.HAS_R:
self.r = HwIORamRdVldR()
if self.HAS_W:
self.w = HwIOAddrDataRdVld()
self.w.HAS_MASK = self.HAS_BE
self.ram = HwIOBramPort_noClk()._m()
[docs]
def read_logic(self, r: HwIORamRdVldR, ram: HwIOBramPort_noClk):
readDataPending = self._reg("readDataPending", def_val=0)
readData = self._reg("readData",
HStruct((r.data.data._dtype, "data"),
(BIT, "vld")),
def_val={"vld": 0}
)
readDataOverflow = self._reg("readDataOverflow",
readData._dtype, def_val={"vld": 0})
rEn = (~readDataOverflow.vld | r.data.rd) & (~readData.vld | r.data.rd)
readDataPending(r.addr.vld & rEn)
If(readDataPending,
If(~readData.vld | r.data.rd,
# can store directly to readData register
readData.data(ram.dout),
readData.vld(1),
readDataOverflow.vld(0),
).Else(
# need to store to overflow register
readDataOverflow.data(ram.dout),
readDataOverflow.vld(1),
),
).Else(
If(r.data.rd,
# pop data from readDataOverflow register
readData.data(readDataOverflow.data),
readData.vld(readDataOverflow.vld),
readDataOverflow.vld(0)
)
)
r.addr.rd(rEn)
return rEn, readData
@override
def hwImpl(self):
ram = self.ram
if self.HAS_R:
r = self.r
rEn, readData = self.read_logic(r, ram)
if self.HAS_W:
# read/write
w = self.w
if self.HAS_BE:
ram.be(w.mask)
If(rEn & r.addr.vld,
ram.we(0),
ram.addr(r.addr.data)
).Else(
ram.we(1),
ram.addr(w.addr)
)
wEn = ~rEn | ~r.addr.vld
w.rd(wEn)
ram.din(w.data)
ram.en((rEn & r.addr.vld) | w.vld)
r.data.data(readData.data)
r.data.vld(readData.vld)
else:
# read only
ram.addr(r.addr.data)
ram.en(rEn & r.addr.vld)
r.data.data(readData.data)
r.data.vld(readData.vld)
elif self.HAS_W:
# write only
w = self.w
w.rd(1)
if self.HAS_BE:
ram.we(w.mask)
ram.addr(w.addr)
ram.din(w.data)
ram.en(w.vld)
if __name__ == "__main__":
from hwt.synth import to_rtl_str
m = RamAsAddrDataRdVld()
print(to_rtl_str(m))