def matchHandler(self, mem, key: Handshaked, match_res: Handshaked): key_data = key.data if self.USE_VLD_BIT: key_data = Concat(key.data, BIT.from_py(1)) out_one_hot = [] for i in range(self.ITEMS): b = mem[i]._eq(key_data) out_one_hot.append(b) match_res.data(Concat(*reversed(out_one_hot))) StreamNode([key], [match_res]).sync()
def receive_write_confirm(self, b: Axi4_b, read_confirm: Handshaked): read_confirm.data(b.id) StreamNode([b], [read_confirm]).sync()
class ArrayItemGetter(Unit): """ Get specific item from array by index .. hwt-schematic:: """ def _config(self): self.ITEMS = Param(32) self.ITEM_WIDTH = Param(32) self.ID = Param(0) self.ID_WIDTH = Param(4) self.DATA_WIDTH = Param(64) self.ADDR_WIDTH = Param(32) self.MAX_TRANS_OVERLAP = Param(16) def _declr(self): addClkRstn(self) # addr of start of array self.base = VectSignal(self.ADDR_WIDTH) # input index of item to get self.index = Handshaked() self.index.DATA_WIDTH.set(log2ceil(self.ITEMS)) # output item from array self.item = Handshaked()._m() self.item.DATA_WIDTH.set(self.ITEM_WIDTH) self.ITEMS_IN_DATA_WORD = int(self.DATA_WIDTH) // int(self.ITEM_WIDTH) with self._paramsShared(): # interface for communication with datapump self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) if self.ITEMS_IN_DATA_WORD > 1: assert isPow2(self.ITEMS_IN_DATA_WORD) f = self.itemSubIndexFifo = HandshakedFifo(Handshaked) f.DATA_WIDTH.set(log2ceil(self.ITEMS_IN_DATA_WORD)) f.DEPTH.set(self.MAX_TRANS_OVERLAP) def _impl(self): propagateClkRstn(self) ITEM_WIDTH = int(self.ITEM_WIDTH) DATA_WIDTH = int(self.DATA_WIDTH) ITEMS_IN_DATA_WORD = self.ITEMS_IN_DATA_WORD ITEM_SIZE_IN_WORDS = 1 if ITEM_WIDTH % 8 != 0 or ITEM_SIZE_IN_WORDS * DATA_WIDTH != ITEMS_IN_DATA_WORD * ITEM_WIDTH: raise NotImplementedError(ITEM_WIDTH) req = self.rDatapump.req req.id(self.ID) req.len(ITEM_SIZE_IN_WORDS - 1) req.rem(0) if ITEMS_IN_DATA_WORD == 1: addr = Concat(self.index.data, vec(0, log2ceil(ITEM_WIDTH // 8))) req.addr(self.base + fitTo(addr, req.addr)) StreamNode(masters=[self.index], slaves=[req]).sync() self.item.data(self.rDatapump.r.data) StreamNode(masters=[self.rDatapump.r], slaves=[self.item]).sync() else: r = self.rDatapump.r.data f = self.itemSubIndexFifo subIndexBits = f.dataIn.data._dtype.bit_length() itemAlignBits = log2ceil(ITEM_WIDTH // 8) addr = Concat(self.index.data[:subIndexBits], vec(0, itemAlignBits + subIndexBits)) req.addr(self.base + fitTo(addr, req.addr)) f.dataIn.data(self.index.data[subIndexBits:]) StreamNode(masters=[self.index], slaves=[req, f.dataIn]).sync() Switch(f.dataOut.data).addCases([ (ITEMS_IN_DATA_WORD - i - 1, self.item.data(r[(ITEM_WIDTH * (i + 1)): (ITEM_WIDTH * i)])) for i in range(ITEMS_IN_DATA_WORD) ]) StreamNode(masters=[self.rDatapump.r, f.dataOut], slaves=[self.item]).sync()
class MdioMaster(Unit): """ Master for MDIO interface. :ivar ~.FREQ: frequency of input clock :ivar ~.MDIO_FREQ: frequency of output MDIO clock * based on: * https://opencores.org/websvn/filedetails?repname=ethmac10g&path=%2Fethmac10g%2Ftrunk%2Frtl%2Fverilog%2Fmgmt%2Fmdio.v * https://github.com/NetFPGA/netfpga/blob/master/lib/verilog/core/io/mdio/src/nf2_mdio.v .. hwt-autodoc:: """ def _config(self): self.FREQ = Param(int(100e6)) self.MDIO_FREQ = Param(int(2.5e6)) def _declr(self): addClkRstn(self) self.md = Mdio()._m() self.rdata = Handshaked()._m() self.rdata.DATA_WIDTH = Mdio.D_W self.req = MdioReq() def _packet_sequence_timer(self, mdio_clk_rising, mdio_clk_falling, rst_n): """ Create timers for all important events in protocol main FSM """ PRE_W = Mdio.PRE_W ADDR_BLOCK_W = Mdio.ADDR_BLOCK_W TA_W = Mdio.TA_W preamble_last = self._sig("preamble_last") addr_block_last = self._sig("addr_block_last") turnarround_last_en = self._sig("turnarround_last_en") data_last = self._sig("data_last") CNTR_MAX = PRE_W + ADDR_BLOCK_W + TA_W + Mdio.D_W - 1 timer = self._reg("packet_sequence_timer", dtype=Bits(log2ceil(CNTR_MAX)), def_val=0, rst=self.rst_n & rst_n) If(mdio_clk_falling, timer(timer + 1)) preamble_last(mdio_clk_falling & timer._eq(PRE_W - 1)) addr_block_last(mdio_clk_falling & timer._eq(PRE_W + ADDR_BLOCK_W - 1)) turnarround_last_en(timer._eq(PRE_W + ADDR_BLOCK_W + TA_W - 1)) data_last(mdio_clk_rising & timer._eq(CNTR_MAX)) return preamble_last, addr_block_last, turnarround_last_en, data_last def _impl(self): # timers and other registers CLK_HALF_PERIOD_DIV = ceil(self.clk.FREQ / (self.MDIO_FREQ * 2)) mdio_clk = self._reg("mdio_clk", def_val=0) r_data_vld = self._reg("r_data_vld", def_val=0) req = self.req clk_half_period_en = ClkBuilder(self, self.clk).timer( ("clk_half_period_en", CLK_HALF_PERIOD_DIV)) If( clk_half_period_en, mdio_clk(~mdio_clk), ) mdio_clk_rising = clk_half_period_en & ~mdio_clk mdio_clk_falling = clk_half_period_en & mdio_clk idle = self._sig("idle") preamble_last, addr_block_last, turnarround_last_en, data_last =\ self._packet_sequence_timer( mdio_clk_rising, mdio_clk_falling, ~idle) is_rx = self._reg("is_rx", def_val=0) # protocol FSM st_t = HEnum("st_t", ["idle", "pre", "addr_block", "ta", "data"]) st = FsmBuilder(self, st_t)\ .Trans(st_t.idle, (req.vld & ~r_data_vld, st_t.pre))\ .Trans(st_t.pre, (preamble_last, st_t.addr_block))\ .Trans(st_t.addr_block, (addr_block_last, st_t.ta))\ .Trans(st_t.ta, (turnarround_last_en & ( (is_rx & mdio_clk_falling) | (~is_rx & mdio_clk_rising)), st_t.data))\ .Trans(st_t.data, (data_last, st_t.idle)).stateReg idle(st._eq(st_t.idle)) req.rd(idle & ~r_data_vld) If(idle, is_rx(req.opcode._eq(Mdio.OP.READ))) # TX logic md = self.md TX_W = md.ST_W + md.OP_W + md.PA_W + md.RA_W + md.TA_W + md.D_W tx_reg = self._reg("tx_reg", Bits(TX_W)) If( idle & req.vld, tx_reg( Concat( Mdio.ST, req.opcode, req.addr.phy, req.addr.reg, Mdio.TA, req.wdata))).Elif( mdio_clk_falling & In(st, [st_t.addr_block, st_t.data, st_t.ta, st_t.data]), tx_reg(tx_reg << 1)) md.c(mdio_clk) # because MDIO uses open-drain, this means that if t=0 the value of the signal is 1 md.io.o(0) tx_bit = tx_reg[tx_reg._dtype.bit_length() - 1] md.io.t(~idle & ~tx_bit & (st._eq(st_t.addr_block) | (In(st, [st_t.data, st_t.ta]) & ~is_rx))) # RX logic rx_reg = self._reg("rx_reg", Bits(md.D_W)) If( st._eq(st_t.data) & is_rx & mdio_clk_rising, shift_in_msb_first(rx_reg, self.md.io.i)) If(idle & self.rdata.rd, r_data_vld(0)).Elif(addr_block_last, r_data_vld(is_rx)) self.rdata.vld(idle & r_data_vld) self.rdata.data(rx_reg)
class ArrayItemGetter(Unit): """ Get specific item from array by index .. hwt-schematic:: """ def _config(self): self.ITEMS = Param(32) self.ITEM_WIDTH = Param(32) self.ID = Param(0) self.ID_WIDTH = Param(4) self.DATA_WIDTH = Param(64) self.ADDR_WIDTH = Param(32) self.MAX_TRANS_OVERLAP = Param(16) def _declr(self): addClkRstn(self) # addr of start of array self.base = VectSignal(self.ADDR_WIDTH) # input index of item to get self.index = Handshaked() self.index.DATA_WIDTH.set(log2ceil(self.ITEMS)) # output item from array self.item = Handshaked()._m() self.item.DATA_WIDTH.set(self.ITEM_WIDTH) self.ITEMS_IN_DATA_WORD = int(self.DATA_WIDTH) // int(self.ITEM_WIDTH) with self._paramsShared(): # interface for communication with datapump self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) if self.ITEMS_IN_DATA_WORD > 1: assert isPow2(self.ITEMS_IN_DATA_WORD) f = self.itemSubIndexFifo = HandshakedFifo(Handshaked) f.DATA_WIDTH.set(log2ceil(self.ITEMS_IN_DATA_WORD)) f.DEPTH.set(self.MAX_TRANS_OVERLAP) def _impl(self): propagateClkRstn(self) ITEM_WIDTH = int(self.ITEM_WIDTH) DATA_WIDTH = int(self.DATA_WIDTH) ITEMS_IN_DATA_WORD = self.ITEMS_IN_DATA_WORD ITEM_SIZE_IN_WORDS = 1 if ITEM_WIDTH % 8 != 0 or ITEM_SIZE_IN_WORDS * DATA_WIDTH != ITEMS_IN_DATA_WORD * ITEM_WIDTH: raise NotImplementedError(ITEM_WIDTH) req = self.rDatapump.req req.id(self.ID) req.len(ITEM_SIZE_IN_WORDS - 1) req.rem(0) if ITEMS_IN_DATA_WORD == 1: addr = Concat(self.index.data, vec(0, log2ceil(ITEM_WIDTH // 8))) req.addr(self.base + fitTo(addr, req.addr)) StreamNode(masters=[self.index], slaves=[req]).sync() self.item.data(self.rDatapump.r.data) StreamNode(masters=[self.rDatapump.r], slaves=[self.item]).sync() else: r = self.rDatapump.r.data f = self.itemSubIndexFifo subIndexBits = f.dataIn.data._dtype.bit_length() itemAlignBits = log2ceil(ITEM_WIDTH // 8) addr = Concat(self.index.data[:subIndexBits], vec(0, itemAlignBits + subIndexBits)) req.addr(self.base + fitTo(addr, req.addr)) f.dataIn.data(self.index.data[subIndexBits:]) StreamNode(masters=[self.index], slaves=[req, f.dataIn]).sync() Switch(f.dataOut.data).addCases([ (ITEMS_IN_DATA_WORD - i - 1, self.item.data(r[(ITEM_WIDTH * (i + 1)):(ITEM_WIDTH * i)])) for i in range(ITEMS_IN_DATA_WORD) ]) StreamNode(masters=[self.rDatapump.r, f.dataOut], slaves=[self.item]).sync()