class SimpleSyncRom(SimpleRom): """ .. hwt-schematic:: """ def _declr(self): super()._declr() self.clk = Clk() def _impl(self): rom = self._sig("rom_data", Bits(8)[4], defVal=[1, 2, 3, 4]) If(self.clk._onRisingEdge(), self.dout(rom[self.addr]))
class SimpleSyncRam(SimpleAsyncRam): """ .. hwt-autodoc:: """ def _declr(self): super()._declr() self.clk = Clk() def _impl(self): self._ram = ram = self._sig("ram_data", Bits(8)[4]) If(self.clk._onRisingEdge(), self.dout(ram[self.addr_out]), ram[self.addr_in](self.din))
class SimpleSyncRom(SimpleRom): """ .. hwt-schematic:: """ def _declr(self): super()._declr() self.clk = Clk() def _impl(self): rom = self._sig("rom_data", Bits(8)[4], defVal=[1, 2, 3, 4]) If(self.clk._onRisingEdge(), self.dout(rom[self.addr]) )
class SimpleSyncRam(SimpleAsyncRam): """ .. hwt-schematic:: """ def _declr(self): super()._declr() self.clk = Clk() def _impl(self): self._ram = ram = self._sig("ram_data", Bits(8)[4]) If(self.clk._onRisingEdge(), self.dout(ram[self.addr_out]), ram[self.addr_in](self.din) )
class RamSingleClock(Unit): """ RAM with only one clock signal .. hwt-schematic:: """ def _config(self): self.DATA_WIDTH = Param(64) self.ADDR_WIDTH = Param(4) self.PORT_CNT = Param(1) def _declr(self): PORTS = int(self.PORT_CNT) self.clk = Clk() with self._paramsShared(): # to let IDEs resolve type of port self.a = BramPort_withoutClk() for i in range(PORTS - 1): self._sportPort(i + 1) def _sportPort(self, index) -> None: name = self.genPortName(index) setattr(self, name, BramPort_withoutClk()) @staticmethod def genPortName(index) -> str: return chr(ord('a') + index) def getPortByIndx(self, index) -> BramPort_withoutClk: return getattr(self, self.genPortName(index)) def connectPort(self, port: BramPort_withoutClk, mem: RtlSignal): If(self.clk._onRisingEdge() & port.en, If(port.we, mem[port.addr](port.din) ), port.dout(mem[port.addr]) ) def _impl(self): PORTS = int(self.PORT_CNT) dt = Bits(self.DATA_WIDTH)[power(2, self.ADDR_WIDTH)] self._mem = self._sig("ram_memory", dt) for i in range(PORTS): self.connectPort(getattr(self, self.genPortName(i)), self._mem)
class RamSingleClock(Unit): """ RAM with only one clock signal .. hwt-schematic:: """ def _config(self): self.DATA_WIDTH = Param(64) self.ADDR_WIDTH = Param(4) self.PORT_CNT = Param(1) def _declr(self): PORTS = int(self.PORT_CNT) self.clk = Clk() with self._paramsShared(): # to let IDEs resolve type of port self.a = BramPort_withoutClk() for i in range(PORTS - 1): self._sportPort(i + 1) def _sportPort(self, index) -> None: name = self.genPortName(index) setattr(self, name, BramPort_withoutClk()) @staticmethod def genPortName(index) -> str: return chr(ord('a') + index) def getPortByIndx(self, index) -> BramPort_withoutClk: return getattr(self, self.genPortName(index)) def connectPort(self, port: BramPort_withoutClk, mem: RtlSignal): If(self.clk._onRisingEdge() & port.en, If(port.we, mem[port.addr](port.din)), port.dout(mem[port.addr])) def _impl(self): PORTS = int(self.PORT_CNT) dt = Bits(self.DATA_WIDTH)[power(2, self.ADDR_WIDTH)] self._mem = self._sig("ram_memory", dt) for i in range(PORTS): self.connectPort(getattr(self, self.genPortName(i)), self._mem)
class FifoAsync(Fifo): """ Asynchronous fifo using BRAM memory, based on: http://www.asic-world.com/examples/vhdl/asyn_fifo.html .. hwt-schematic:: _example_FifoAsync """ def _declr(self): assert int(self.DEPTH) > 0, "FifoAsync is disabled in this case, do not use it entirely" assert isPow2(self.DEPTH), "FifoAsync DEPTH has to be power of 2" # pow 2 because of gray conter counters if int(self.EXPORT_SIZE) or int(self.EXPORT_SPACE): raise NotImplementedError() self.dataIn_clk = Clk() self.dataOut_clk = Clk() self.rst_n = Rst_n() with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn = FifoWriter() with self._associated(clk=self.dataOut_clk): self.dataOut = FifoReader()._m() self.pWr = GrayCntr() self.pRd = GrayCntr() self.addrW = log2ceil(self.DEPTH) for cntr in [self.pWr, self.pRd]: cntr.DATA_WIDTH.set(self.addrW) def _impl(self): ST_EMPTY, ST_FULL = 0, 1 memory_t = Bits(self.DATA_WIDTH)[self.DEPTH] memory = self._sig("memory", memory_t) full = self._sig("full", defVal=0) empty = self._sig("empty", defVal=1) status = self._sig("status", defVal=ST_EMPTY) In = self.dataIn InClk = self.dataIn_clk._onRisingEdge() Out = self.dataOut OutClk = self.dataOut_clk._onRisingEdge() self.pWr.en(In.en & ~full) self.pWr.clk(self.dataIn_clk) self.pWr.rst_n(self.rst_n) pNextWordToWrite = self.pWr.dataOut self.pRd.en(Out.en & ~empty) self.pRd.clk(self.dataOut_clk) self.pRd.rst_n(self.rst_n) pNextWordToRead = self.pRd.dataOut # data out logic If(OutClk, If(Out.en & ~empty, Out.data(memory[pNextWordToRead]) ) ) # data in logic If(InClk, If(In.en & ~full, memory[pNextWordToWrite](In.data) ) ) equalAddresses = pNextWordToWrite._eq(pNextWordToRead) aw = self.addrW nw = pNextWordToWrite nr = pNextWordToRead setStatus = nw[aw - 2]._eq(nr[aw - 1]) & (nw[aw - 1] ^ nr[aw - 2]) rstStatus = (nw[aw - 2] ^ nr[aw - 1]) & nw[aw - 1]._eq(nr[aw - 2]) # status latching If(rstStatus | self.rst_n._isOn(), status(ST_EMPTY) ).Elif(setStatus, status(ST_FULL) ) # data in logic presetFull = status & equalAddresses # D Flip-Flop with Asynchronous Preset. If(self.rst_n._isOn(), full(0) ).Elif(presetFull, full(1) ).Elif(InClk, full(0) ) In.wait(full) # data out logic presetEmpty = ~status & equalAddresses # D Flip-Flop w/ Asynchronous Preset. If(self.rst_n._isOn(), empty(0) ).Elif(presetEmpty, empty(1) ).Elif(OutClk, empty(0) ) Out.wait(empty)
class FifoAsync(Fifo): """ Asynchronous fifo using BRAM memory, based on: http://www.asic-world.com/examples/vhdl/asyn_fifo.html .. hwt-schematic:: _example_FifoAsync """ def _declr(self): assert int( self.DEPTH ) > 0, "FifoAsync is disabled in this case, do not use it entirely" assert isPow2(self.DEPTH), "FifoAsync DEPTH has to be power of 2" # pow 2 because of gray conter counters if int(self.EXPORT_SIZE) or int(self.EXPORT_SPACE): raise NotImplementedError() self.dataIn_clk = Clk() self.dataOut_clk = Clk() self.rst_n = Rst_n() with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn = FifoWriter() with self._associated(clk=self.dataOut_clk): self.dataOut = FifoReader()._m() self.pWr = GrayCntr() self.pRd = GrayCntr() self.addrW = log2ceil(self.DEPTH) for cntr in [self.pWr, self.pRd]: cntr.DATA_WIDTH.set(self.addrW) def _impl(self): ST_EMPTY, ST_FULL = 0, 1 memory_t = Bits(self.DATA_WIDTH)[self.DEPTH] memory = self._sig("memory", memory_t) full = self._sig("full", defVal=0) empty = self._sig("empty", defVal=1) status = self._sig("status", defVal=ST_EMPTY) In = self.dataIn InClk = self.dataIn_clk._onRisingEdge() Out = self.dataOut OutClk = self.dataOut_clk._onRisingEdge() self.pWr.en(In.en & ~full) self.pWr.clk(self.dataIn_clk) self.pWr.rst_n(self.rst_n) pNextWordToWrite = self.pWr.dataOut self.pRd.en(Out.en & ~empty) self.pRd.clk(self.dataOut_clk) self.pRd.rst_n(self.rst_n) pNextWordToRead = self.pRd.dataOut # data out logic If(OutClk, If(Out.en & ~empty, Out.data(memory[pNextWordToRead]))) # data in logic If(InClk, If(In.en & ~full, memory[pNextWordToWrite](In.data))) equalAddresses = pNextWordToWrite._eq(pNextWordToRead) aw = self.addrW nw = pNextWordToWrite nr = pNextWordToRead setStatus = nw[aw - 2]._eq(nr[aw - 1]) & (nw[aw - 1] ^ nr[aw - 2]) rstStatus = (nw[aw - 2] ^ nr[aw - 1]) & nw[aw - 1]._eq(nr[aw - 2]) # status latching If(rstStatus | self.rst_n._isOn(), status(ST_EMPTY)).Elif(setStatus, status(ST_FULL)) # data in logic presetFull = status & equalAddresses # D Flip-Flop with Asynchronous Preset. If(self.rst_n._isOn(), full(0)).Elif(presetFull, full(1)).Elif(InClk, full(0)) In.wait(full) # data out logic presetEmpty = ~status & equalAddresses # D Flip-Flop w/ Asynchronous Preset. If(self.rst_n._isOn(), empty(0)).Elif(presetEmpty, empty(1)).Elif(OutClk, empty(0)) Out.wait(empty)