Пример #1
0
 def DCR_check_logic_modes():
     # -- LOGIC MODES DRC
     return If(
         In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux),
         self.deassign_xyz_mux()
     ).Elif(
         In(qopmode_o_mux,
            LOGIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1),
         deassign_xyz_mux_if_PREG_eq_1(),
     ).Else(
         # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000)
     )
Пример #2
0
    def main_op(self, dst_stage: OOOOpPipelineStage,
                src_stage: OOOOpPipelineStage):
        """
        A main opration of counter incrementation

        :note: This function is called for write back state and its predecessor.
            However because of write bypass this function is called multiple times for each bypass as well.
        """
        dst = dst_stage.data
        src = src_stage.data
        prev_st = self.pipeline[dst_stage.index - 1]
        OP = self.OPERATION
        prev_st_op = prev_st.transaction_state.operation

        return If(
            prev_st.valid & prev_st.transaction_state.key_match
            & In(prev_st_op, [OP.LOOKUP, OP.LOOKUP_OR_SWAP]),
            # lookup or lookup_or_swap with found
            dst.item_valid(src.item_valid),
            dst.key(src.key),
            self.main_op_on_lookup_match_update(dst_stage, src_stage),
        ).Elif(
            prev_st.valid & prev_st_op._eq(OP.SWAP),
            # swap or lookup_or_swap with not found
            dst(prev_st.data),
        ).Elif(
            prev_st.valid & ~prev_st.transaction_state.key_match,
            #  not match not swap, keep as it is
            dst(src),
        )
Пример #3
0
    def _impl(self):
        cmd = self.cntrl.cmd
        cmd_ack = self.cntrl.rd

        stT = HEnum("stT", [
            "idle", "start_0", "start_1", "start_2", "start_3", "start_4",
            "stop_0", "stop_1", "stop_2", "stop_3", "rd_0", "rd_1", "rd_2",
            "rd_3", "wr_0", "wr_1", "wr_2", "wr_3"
        ])

        fsm = FsmBuilder(self, stT)
        st = fsm.stateReg

        # check SDA status (multi-master arbitration)
        sda_chk = self._reg("sda_chk", def_val=0)
        scl_t = self._reg("scl_t", def_val=0)
        sda_t = self._reg("sda_t", def_val=0)

        scl = self.filter("scl", self.i2c.scl.i)
        sda = self.filter("sda", self.i2c.sda.i)

        _, stopCond, scl_sync = self.detectStartAndStop(scl, sda, scl_t)
        stateClkEn = self.stateClkGen(scl_sync, scl_t, scl)
        al = self.arbitrationLostDriver(st, sda, sda_chk, sda_t, stopCond,
                                        stateClkEn)

        def stateSequence(sequneceName, stateCnt):
            for i in range(stateCnt):
                stateFrom = getattr(stT, f"{sequneceName}_{i:d}")
                if i == stateCnt - 1:
                    stateTo = stT.idle
                else:
                    _i = i + 1
                    stateTo = getattr(stT, f"{sequneceName}_{_i:d}")

                fsm.Trans(stateFrom, (al, stT.idle), stateTo)

        fsm.Trans(
            stT.idle,
            (al, stT.idle),
            (cmd._eq(NOP), stT.idle),
            (cmd._eq(START), stT.start_0),
            (cmd._eq(STOP), stT.stop_0),
            (cmd._eq(WRITE), stT.wr_0),
            (cmd._eq(READ), stT.rd_0),
        )
        stateSequence("start", 5)
        stateSequence("stop", 4)
        stateSequence("rd", 4)
        stateSequence("wr", 4)

        If(
            al,
            cmd_ack(0),
            sda_t(0),
            scl_t(0),
            sda_chk(0),
        ).Else(
            If(
                In(st, [
                    stT.start_1, stT.start_2, stT.start_3, stT.stop_1,
                    stT.stop_2, stT.stop_3, stT.rd_1, stT.rd_2, stT.wr_1,
                    stT.wr_2
                ]), scl_t(0)).Elif(
                    In(st, [
                        stT.start_4, stT.stop_0, stT.rd_0, stT.rd_3, stT.wr_0,
                        stT.wr_3
                    ]), scl_t(1)),
            If(
                In(st, [
                    stT.start_0, stT.start_1, stT.stop_3, stT.rd_0, stT.rd_1,
                    stT.rd_2, stT.rd_3
                ]), sda_t(0)).Elif(
                    In(st, [
                        stT.start_2, stT.start_3, stT.start_4, stT.stop_0,
                        stT.stop_1, stT.stop_2
                    ]), sda_t(1)).Elif(
                        In(st, [stT.wr_0, stT.wr_1, stT.wr_2, stT.wr_3]),
                        sda_t(~self.cntrl.din)),
            # cmd ack at the end of state sequence
            cmd_ack(In(st, [stT.start_4, stT.stop_3, stT.rd_3, stT.wr_3])))

        self.i2c.scl.o(0)
        self.i2c.sda.o(0)
        self.i2c.scl.t(scl_t)
        self.i2c.sda.t(sda_t)
Пример #4
0
    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)
Пример #5
0
    def flush_or_read_node(
            self,
            d_arr_r: RamHsR,
            d_arr_w: AddrDataHs,
            st2_out: HsStructIntf,
            data_arr_read: Axi4_r,
            tag_update: AxiCacheTagArrayUpdateIntf,  # out
    ):
        ########################## st1 - post (victim flushing, read forwarding) ######################
        in_w = AxiSBuilder(self, self.s.w)\
            .buff(self.tag_array.LOOKUP_LATENCY + 4)\
            .end

        st2 = st2_out.data
        d_arr_w.addr(
            self.addr_in_data_array(st2.victim_way,
                                    self.parse_addr(st2.replacement_addr)[1]))
        data_arr_read_data = d_arr_r.data  # HsBuilder(self, d_arr_r.data).buff(1, latency=(1, 2)).end
        d_arr_w.data(in_w.data)
        d_arr_w.mask(in_w.strb)

        self.s.b.id(st2.write_id)
        self.s.b.resp(RESP_OKAY)

        data_arr_read.id(st2.read_id)
        data_arr_read.data(data_arr_read_data.data)
        data_arr_read.resp(RESP_OKAY)
        data_arr_read.last(1)

        m = self.m
        m.aw.addr(st2.victim_addr)
        m.aw.id(st2.write_id)
        m.aw.len(0)
        self.axiAddrDefaults(m.aw)

        m.w.data(data_arr_read_data.data)
        m.w.strb(mask(m.w.data._dtype.bit_length() // 8))
        m.w.last(1)

        # flushing needs to have higher priority then read in order
        # to prevent deadlock
        # write replacement after victim load with higher priority
        # else if found just write the data to data array
        is_flush = st2.data_array_op._eq(data_trans_t.write_and_flush)
        contains_write = rename_signal(
            self,
            In(st2.data_array_op, [
                data_trans_t.write, data_trans_t.write_and_flush,
                data_trans_t.read_and_write
            ]), "contains_write")
        contains_read = rename_signal(
            self,
            In(st2.data_array_op, [
                data_trans_t.read, data_trans_t.write_and_flush,
                data_trans_t.read_and_write
            ]), "contains_read")
        contains_read_data = rename_signal(
            self,
            In(st2.data_array_op,
               [data_trans_t.read, data_trans_t.read_and_write]),
            "contains_read_data")

        flush_or_read_node = StreamNode(
            [st2_out, data_arr_read_data, in_w
             ],  # collect read data from data array, collect write data
            [data_arr_read, m.aw, m.w, d_arr_w, self.s.b
             ],  # to read block or to slave connected on "m" interface
            # write data to data array and send write acknowledge
            extraConds={
                data_arr_read_data: contains_read,
                in_w: contains_write,
                data_arr_read: contains_read_data,
                m.aw: is_flush,
                m.w: is_flush,
                d_arr_w: contains_write,
                self.s.b: contains_write,
            },
            skipWhen={
                data_arr_read_data: ~contains_read,
                in_w: ~contains_write,
                data_arr_read: ~contains_read_data,
                m.aw: ~is_flush,
                m.w: ~is_flush,
                d_arr_w: ~contains_write,
                self.s.b: ~contains_write,
            })
        flush_or_read_node.sync()
        m.b.ready(1)

        tag_update.vld(st2_out.vld & contains_write)
        tag_update.delete(0)
        tag_update.way_en(binToOneHot(st2.victim_way))
        tag_update.addr(st2.replacement_addr)
        # [TODO] initial clean
        lru_array_set = self.lru_array.set
        lru_array_set.addr(None)
        lru_array_set.data(None)
        lru_array_set.vld(0)
Пример #6
0
    def _impl(self):
        # internal signals
        ACASCREG, ADREG, ALUMODEREG, AREG, AUTORESET_PATDET, A_INPUT, BCASCREG, BREG, B_INPUT, CARRYINREG, CARRYINSELREG, \
        CREG, DREG, INMODEREG, IS_ALUMODE_INVERTED, IS_CARRYIN_INVERTED, IS_CLK_INVERTED, IS_INMODE_INVERTED, IS_OPMODE_INVERTED, MASK, MREG, \
        OPMODEREG, PATTERN, PREG, SEL_MASK, SEL_PATTERN, USE_DPORT, USE_MULT, USE_PATTERN_DETECT, USE_SIMD, ACOUT, \
        BCOUT, CARRYCASCOUT, CARRYOUT, MULTSIGNOUT, OVERFLOW, P, PATTERNBDETECT, PATTERNDETECT, PCOUT, UNDERFLOW, \
        A, ACIN, ALUMODE, B, BCIN, C, CARRYCASCIN, CARRYIN, CARRYINSEL, CEA1, \
        CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL, CED, CEINMODE, \
        CEM, CEP, CLK, D, INMODE, MULTSIGNIN, OPMODE, PCIN, RSTA, RSTALLCARRYIN, \
        RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP = \
        self.ACASCREG, self.ADREG, self.ALUMODEREG, self.AREG, self.AUTORESET_PATDET, self.A_INPUT, self.BCASCREG, self.BREG, self.B_INPUT, self.CARRYINREG, self.CARRYINSELREG, \
        self.CREG, self.DREG, self.INMODEREG, self.IS_ALUMODE_INVERTED, self.IS_CARRYIN_INVERTED, self.IS_CLK_INVERTED, self.IS_INMODE_INVERTED, self.IS_OPMODE_INVERTED, self.MASK, self.MREG, \
        self.OPMODEREG, self.PATTERN, self.PREG, self.SEL_MASK, self.SEL_PATTERN, self.USE_DPORT, self.USE_MULT, self.USE_PATTERN_DETECT, self.USE_SIMD, self.ACOUT, \
        self.BCOUT, self.CARRYCASCOUT, self.CARRYOUT, self.MULTSIGNOUT, self.OVERFLOW, self.P, self.PATTERNBDETECT, self.PATTERNDETECT, self.PCOUT, self.UNDERFLOW, \
        self.A, self.ACIN, self.ALUMODE, self.B, self.BCIN, self.C, self.CARRYCASCIN, self.CARRYIN, self.CARRYINSEL, self.CEA1, \
        self.CEA2, self.CEAD, self.CEALUMODE, self.CEB1, self.CEB2, self.CEC, self.CECARRYIN, self.CECTRL, self.CED, self.CEINMODE, \
        self.CEM, self.CEP, self.CLK, self.D, self.INMODE, self.MULTSIGNIN, self.OPMODE, self.PCIN, self.RSTA, self.RSTALLCARRYIN, \
        self.RSTALUMODE, self.RSTB, self.RSTC, self.RSTCTRL, self.RSTD, self.RSTINMODE, self.RSTM, self.RSTP
        #------------------- constants -------------------------
        CARRYOUT_W = 4
        A_W = 30
        ALUMODE_W = 4
        A_MULT_W = 25
        B_W = 18
        B_MULT_W = 18
        D_W = 25
        INMODE_W = 5
        OPMODE_W = 7
        ALU_FULL_W = 48

        IS_ALUMODE_INVERTED_BIN = self._sig("IS_ALUMODE_INVERTED_BIN",
                                            Bits(4),
                                            def_val=IS_ALUMODE_INVERTED)
        IS_CARRYIN_INVERTED_BIN = self._sig("IS_CARRYIN_INVERTED_BIN",
                                            def_val=IS_CARRYIN_INVERTED)
        IS_CLK_INVERTED_BIN = self._sig("IS_CLK_INVERTED_BIN",
                                        def_val=IS_CLK_INVERTED)
        IS_INMODE_INVERTED_BIN = self._sig("IS_INMODE_INVERTED_BIN",
                                           Bits(5),
                                           def_val=IS_INMODE_INVERTED)
        IS_OPMODE_INVERTED_BIN = self._sig("IS_OPMODE_INVERTED_BIN",
                                           Bits(7),
                                           def_val=IS_OPMODE_INVERTED)
        a_o_mux = self._sig("a_o_mux", Bits(30))
        qa_o_mux = self._sig("qa_o_mux", Bits(30))
        qa_o_reg1 = self._sig("qa_o_reg1", Bits(30))
        qa_o_reg2 = self._sig("qa_o_reg2", Bits(30))
        qacout_o_mux = self._sig("qacout_o_mux", Bits(30))
        # new
        qinmode_o_mux = self._sig("qinmode_o_mux", Bits(5))
        qinmode_o_reg = self._sig("qinmode_o_reg", Bits(5))
        # new
        a_preaddsub = self._sig("a_preaddsub", Bits(25))
        b_o_mux = self._sig("b_o_mux", Bits(18))
        qb_o_mux = self._sig("qb_o_mux", Bits(18))
        qb_o_reg1 = self._sig("qb_o_reg1", Bits(18))
        qb_o_reg2 = self._sig("qb_o_reg2", Bits(18))
        qbcout_o_mux = self._sig("qbcout_o_mux", Bits(18))
        qcarryinsel_o_mux = self._sig("qcarryinsel_o_mux", Bits(3))
        qcarryinsel_o_reg1 = self._sig("qcarryinsel_o_reg1", Bits(3))
        # new
        #d_o_mux = self._sig("d_o_mux", Bits(D_W))
        qd_o_mux = self._sig("qd_o_mux", Bits(D_W))
        qd_o_reg1 = self._sig("qd_o_reg1", Bits(D_W))
        qmult_o_mux = self._sig("qmult_o_mux", Bits(A_MULT_W + B_MULT_W))
        qmult_o_reg = self._sig("qmult_o_reg", Bits(A_MULT_W + B_MULT_W))
        # 42:0
        qc_o_mux = self._sig("qc_o_mux", Bits(48))
        qc_o_reg1 = self._sig("qc_o_reg1", Bits(48))
        qp_o_mux = self._sig("qp_o_mux", Bits(48))
        qp_o_reg1 = self._sig("qp_o_reg1", Bits(48))
        qx_o_mux = self._sig("qx_o_mux", Bits(48))
        qy_o_mux = self._sig("qy_o_mux", Bits(48))
        qz_o_mux = self._sig("qz_o_mux", Bits(48))
        qopmode_o_mux = self._sig("qopmode_o_mux", Bits(7))
        qopmode_o_reg1 = self._sig("qopmode_o_reg1", Bits(7))
        qcarryin_o_mux0 = self._sig("qcarryin_o_mux0")
        qcarryin_o_reg0 = self._sig("qcarryin_o_reg0")
        qcarryin_o_mux7 = self._sig("qcarryin_o_mux7")
        qcarryin_o_reg7 = self._sig("qcarryin_o_reg7")
        qcarryin_o_mux = self._sig("qcarryin_o_mux")
        qalumode_o_mux = self._sig("qalumode_o_mux", Bits(4))
        qalumode_o_reg1 = self._sig("qalumode_o_reg1", Bits(4))
        self.invalid_opmode = self._sig("invalid_opmode", def_val=1)
        self.opmode_valid_flag = opmode_valid_flag = self._sig(
            "opmode_valid_flag", def_val=1)
        #   reg [47:0] alu_o;
        alu_o = self._sig("alu_o", Bits(48))
        qmultsignout_o_reg = self._sig("qmultsignout_o_reg")
        multsignout_o_mux = self._sig("multsignout_o_mux")
        multsignout_o_opmode = self._sig("multsignout_o_opmode")
        pdet_o_mux = self._sig("pdet_o_mux")
        pdetb_o_mux = self._sig("pdetb_o_mux")
        the_pattern = self._sig("the_pattern", Bits(48))
        the_mask = self._sig("the_mask", Bits(48), def_val=0)
        carrycascout_o = self._sig("carrycascout_o")
        the_auto_reset_patdet = self._sig("the_auto_reset_patdet")
        carrycascout_o_reg = self._sig("carrycascout_o_reg", def_val=0)
        carrycascout_o_mux = self._sig("carrycascout_o_mux", def_val=0)

        # CR 588861
        carryout_o_reg = self._sig("carryout_o_reg", Bits(4), def_val=0)
        carryout_o_mux = self._sig("carryout_o_mux", Bits(4))
        carryout_x_o = self._sig("carryout_x_o", Bits(4))
        pdet_o = self._sig("pdet_o")
        pdetb_o = self._sig("pdetb_o")
        pdet_o_reg1 = self._sig("pdet_o_reg1")
        pdet_o_reg2 = self._sig("pdet_o_reg2")
        pdetb_o_reg1 = self._sig("pdetb_o_reg1")
        pdetb_o_reg2 = self._sig("pdetb_o_reg2")
        overflow_o = self._sig("overflow_o")
        underflow_o = self._sig("underflow_o")
        mult_o = self._sig("mult_o", Bits(A_MULT_W + B_MULT_W))
        #   reg [(MSB_A_MULT+MSB_B_MULT+1):0] mult_o;  // 42:0
        # new
        ad_addsub = self._sig("ad_addsub", Bits(A_MULT_W))
        ad_mult = self._sig("ad_mult", Bits(A_MULT_W))
        qad_o_reg1 = self._sig("qad_o_reg1", Bits(A_MULT_W))
        qad_o_mux = self._sig("qad_o_mux", Bits(A_MULT_W))
        b_mult = self._sig("b_mult", Bits(B_MULT_W))
        # cci_drc_msg = self._sig("cci_drc_msg", def_val=0b0)
        # cis_drc_msg = self._sig("cis_drc_msg", def_val=0b0)
        opmode_in = self._sig("opmode_in", Bits(OPMODE_W))
        alumode_in = self._sig("alumode_in", Bits(ALUMODE_W))
        carryin_in = self._sig("carryin_in")
        clk_in = self._sig("clk_in")
        inmode_in = self._sig("inmode_in", Bits(INMODE_W))
        #*** Y mux
        # 08-06-08
        # IR 478378
        y_mac_cascd = rename_signal(
            self,
            qopmode_o_mux[7:4]._eq(0b100)._ternary(replicate(48, MULTSIGNIN),
                                                   Bits(48).from_py(mask(48))),
            "y_mac_cascd")
        #--####################################################################
        #--#####                         ALU                              #####
        #--####################################################################
        co = self._sig("co", Bits(ALU_FULL_W))
        s = self._sig("s", Bits(ALU_FULL_W))
        comux = self._sig("comux", Bits(ALU_FULL_W))
        smux = self._sig("smux", Bits(ALU_FULL_W))
        carryout_o = self._sig("carryout_o", Bits(CARRYOUT_W))
        # FINAL ADDER
        s0 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[11:0], qcarryin_o_mux) +
            Concat(BIT.from_py(0), smux[12:0]), "s0")
        cout0 = rename_signal(self, comux[11] + s0[12], "cout0")
        C1 = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else s0[12], "C1")
        co11_lsb = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else comux[11],
            "co11_lsb")
        s1 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[23:12], co11_lsb) +
            Concat(BIT.from_py(0), smux[24:12]) +
            Concat(Bits(12).from_py(0), C1), "s1")
        cout1 = rename_signal(self, comux[23] + s1[12], "cout1")
        C2 = rename_signal(
            self,
            BIT.from_py(0b0) if (USE_SIMD in ["TWO24", "FOUR12"]) else s1[12],
            "C2")
        co23_lsb = rename_signal(
            self,
            BIT.from_py(0b0) if
            (USE_SIMD in ["TWO24", "FOUR12"]) else comux[23], "co23_lsb")
        s2 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[35:24], co23_lsb) +
            Concat(BIT.from_py(0), smux[36:24]) +
            Concat(Bits(12).from_py(0), C2), "s2")
        cout2 = rename_signal(self, comux[35] + s2[12], "cout2")
        C3 = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else s2[12], "C3")
        co35_lsb = rename_signal(
            self,
            BIT.from_py(0b0) if USE_SIMD == "FOUR12" else comux[35],
            "co35_lsb")
        s3 = rename_signal(
            self,
            Concat(BIT.from_py(0), comux[48:36], co35_lsb) +
            Concat(Bits(2).from_py(0), smux[48:36]) +
            Concat(Bits(13).from_py(0), C3), "s3")
        cout3 = rename_signal(self, s3[12], "cout3")
        #cout4 = rename_signal(self, s3[13], "cout4")
        qcarryin_o_mux_tmp = self._sig("qcarryin_o_mux_tmp")

        ACOUT(qacout_o_mux)
        BCOUT(qbcout_o_mux)
        CARRYCASCOUT(carrycascout_o_mux)
        CARRYOUT(carryout_x_o)
        MULTSIGNOUT(multsignout_o_mux)
        OVERFLOW(overflow_o)
        P(qp_o_mux)
        PCOUT(qp_o_mux)
        PATTERNDETECT(pdet_o_mux)
        PATTERNBDETECT(pdetb_o_mux)
        UNDERFLOW(underflow_o)
        alumode_in(ALUMODE ^ IS_ALUMODE_INVERTED_BIN)
        carryin_in(CARRYIN ^ IS_CARRYIN_INVERTED_BIN)
        clk_in(CLK ^ IS_CLK_INVERTED_BIN)
        inmode_in(INMODE ^ IS_INMODE_INVERTED_BIN)
        opmode_in(OPMODE ^ IS_OPMODE_INVERTED_BIN)

        #*********************************************************
        #**********  INMODE signal registering        ************
        #*********************************************************
        If(
            clk_in._onRisingEdge(),
            If(RSTINMODE, qinmode_o_reg(0b0)).Elif(CEINMODE,
                                                   qinmode_o_reg(inmode_in)))
        if INMODEREG == 0:
            qinmode_o_mux(inmode_in)
        elif INMODEREG == 1:
            qinmode_o_mux(qinmode_o_reg)
        else:
            raise AssertionError()

        if A_INPUT == "DIRECT":
            a_o_mux(A)
        elif A_INPUT == "CASCADE":
            a_o_mux(ACIN)
        else:
            raise AssertionError()

        if AREG in (1, 2):
            If(
                clk_in._onRisingEdge(),
                If(RSTA, qa_o_reg1(0b0), qa_o_reg2(0b0)).Else(
                    If(CEA1, qa_o_reg1(a_o_mux)),
                    If(
                        CEA2,
                        qa_o_reg2(a_o_mux if AREG ==
                                  1 else qa_o_reg1 if AREG == 2 else None))))
        else:
            qa_o_reg1(None)

        if AREG == 0:
            qa_o_mux(a_o_mux)
        elif AREG == 1:
            qa_o_mux(qa_o_reg2)
        elif AREG == 2:
            qa_o_mux(qa_o_reg2)
        else:
            raise AssertionError()

        if ACASCREG == 1:
            qacout_o_mux(qa_o_reg1 if AREG == 2 else qa_o_mux)
        elif ACASCREG == 0:
            qacout_o_mux(qa_o_mux)
        elif ACASCREG == 2:
            qacout_o_mux(qa_o_mux)
        else:
            raise AssertionError()

        If(qinmode_o_mux[1], a_preaddsub(0b0)).Elif(
            qinmode_o_mux[0],
            a_preaddsub(qa_o_reg1[25:0]),
        ).Else(a_preaddsub(qa_o_mux[25:0]), )
        if B_INPUT == "DIRECT":
            b_o_mux(B)
        elif B_INPUT == "CASCADE":
            b_o_mux(BCIN)
        else:
            raise AssertionError()

        if BREG in (1, 2):
            If(
                clk_in._onRisingEdge(),
                If(RSTB, qb_o_reg1(0b0), qb_o_reg2(0b0)).Else(
                    If(CEB1, qb_o_reg1(b_o_mux)),
                    If(
                        CEB2,
                        qb_o_reg2(b_o_mux if BREG ==
                                  1 else qb_o_reg1 if BREG == 1 else None))))
        else:
            qb_o_reg1(None)

        if BREG == 0:
            qb_o_mux(b_o_mux)
        elif BREG == 1:
            qb_o_mux(qb_o_reg2)
        elif BREG == 2:
            qb_o_mux(qb_o_reg2)
        else:
            raise AssertionError()

        if BCASCREG == 1:
            qbcout_o_mux(qb_o_reg1 if BREG == 2 else qb_o_mux)
        elif BCASCREG == 0:
            qbcout_o_mux(qb_o_mux)
        elif BCASCREG == 2:
            qbcout_o_mux(qb_o_mux)
        else:
            raise AssertionError()

        b_mult(qinmode_o_mux[4]._ternary(qb_o_reg1, qb_o_mux))

        #*********************************************************
        #*** Input register C with 1 level deep of register
        #*********************************************************
        If(clk_in._onRisingEdge(),
           If(RSTC, qc_o_reg1(0b0)).Elif(CEC, qc_o_reg1(C)))
        if CREG == 0:
            qc_o_mux(C)
        elif CREG == 1:
            qc_o_mux(qc_o_reg1)
        else:
            raise AssertionError()

        #*********************************************************
        #*** Input register D with 1 level deep of register
        #*********************************************************
        If(clk_in._onRisingEdge(),
           If(RSTD, qd_o_reg1(0b0)).Elif(CED, qd_o_reg1(D)))
        if DREG == 0:
            qd_o_mux(D)
        elif DREG == 1:
            qd_o_mux(qd_o_reg1)
        else:
            raise AssertionError()

        ad_addsub(qinmode_o_mux[3]._ternary(
            -a_preaddsub + qinmode_o_mux[2]._ternary(qd_o_mux, 0b0),
            a_preaddsub + qinmode_o_mux[2]._ternary(qd_o_mux, 0b0)))

        If(clk_in._onRisingEdge(),
           If(RSTD, qad_o_reg1(0b0)).Elif(CEAD, qad_o_reg1(ad_addsub)))
        if ADREG == 0:
            qad_o_mux(ad_addsub)
        elif ADREG == 1:
            qad_o_mux(qad_o_reg1)
        else:
            raise AssertionError()

        ad_mult(qad_o_mux if USE_DPORT == "TRUE" else a_preaddsub)

        #*********************************************************
        #*********************************************************
        #***************      25x18 Multiplier     ***************
        #*********************************************************
        # 05/26/05 -- FP -- Added warning for invalid mult when USE_MULT=NONE
        # SIMD=FOUR12 and SIMD=TWO24
        # Made mult_o to be "X"
        if USE_MULT == "NONE" or USE_SIMD != "ONE48":
            mult_o(0b0)
        else:
            If(CARRYINSEL._eq(0b010), mult_o(None)).Else(
                mult_o(
                    replicate(18, ad_mult[24])._concat(ad_mult[25:0]) *
                    replicate(25, b_mult[17])._concat(b_mult)))

        If(clk_in._onRisingEdge(),
           If(RSTM, qmult_o_reg(0b0)).Elif(CEM, qmult_o_reg(mult_o)))

        If(qcarryinsel_o_mux._eq(0b010), qmult_o_mux(None)).Else(
            qmult_o_mux(qmult_o_reg if MREG == 1 else mult_o))

        #*** X mux
        # ask jmt
        # add post 2014.4
        # else
        Switch(qopmode_o_mux[2:0])\
            .Case(0b00,
                # X_SEL.ZERO
                qx_o_mux(0b0))\
            .Case(0b01,
                # X_SEL.M
                qx_o_mux(replicate(5, qmult_o_mux[A_MULT_W + B_MULT_W - 1])._concat(qmult_o_mux)))\
            .Case(0b10,
                # X_SEL.P
                qx_o_mux(qp_o_mux if PREG == 1 else None))\
            .Case(0b11,
                # X_SEL.A_B
                qx_o_mux(None)
                if USE_MULT == "MULTIPLY" and (
                    (AREG == 0 and BREG == 0 and MREG == 0) or
                    (AREG == 0 and BREG == 0 and PREG == 0) or
                    (MREG == 0 and PREG == 0))
                # print("OPMODE Input Warning : The OPMODE[1:0] %b to DSP48E1 instance %m is invalid when using attributes USE_MULT = MULTIPLY at %.3f ns. Please set USE_MULT to either NONE or DYNAMIC.", qopmode_o_mux[slice(2, 0)], sim.now // 1000.000000)
                else qx_o_mux(qa_o_mux[A_W:0]._concat(qb_o_mux[B_W:0]))
            )

        # add post 2014.4
        Switch(qopmode_o_mux[4:2])\
            .Case(0b00,
                qy_o_mux(0b0))\
            .Case(0b01,
                qy_o_mux(0b0))\
            .Case(0b10,
                qy_o_mux(y_mac_cascd))\
            .Case(0b11,
                qy_o_mux(qc_o_mux))

        #*** Z mux
        # ask jmt
        # add post 2014.4
        Switch(qopmode_o_mux[7:4])\
            .Case(0b000,
                qz_o_mux(0b0))\
            .Case(0b001,
                qz_o_mux(PCIN))\
            .Case(0b010,
                qz_o_mux(qp_o_mux))\
            .Case(0b011,
                qz_o_mux(qc_o_mux))\
            .Case(0b100,
                qz_o_mux(qp_o_mux))\
            .Case(0b101,
                qz_o_mux(replicate(17, PCIN[47])._concat(PCIN[48:17])))\
            .Case(0b110,
                qz_o_mux(replicate(17, qp_o_mux[47])._concat(qp_o_mux[48:17])))\
            .Case(0b111,
                qz_o_mux(replicate(17, qp_o_mux[47])._concat(qp_o_mux[48:17])))

        #*** CarryInSel and OpMode with 1 level of register
        If(
            clk_in._onRisingEdge(),
            If(RSTCTRL, qcarryinsel_o_reg1(0b0),
               qopmode_o_reg1(0b0)).Elif(CECTRL,
                                         qcarryinsel_o_reg1(CARRYINSEL),
                                         qopmode_o_reg1(opmode_in)))
        if CARRYINSELREG == 0:
            qcarryinsel_o_mux(CARRYINSEL)

        elif CARRYINSELREG == 1:
            qcarryinsel_o_mux(qcarryinsel_o_reg1)
        else:
            raise AssertionError()

        # CR 219047 (3)
        # If(qcarryinsel_o_mux._eq(0b010),
        #    If(~((cci_drc_msg._eq(0b1) | qopmode_o_mux._eq(0b1001000)) | (MULTSIGNIN._eq(0b0) & CARRYCASCIN._eq(0b0))),
        #        #print("DRC warning : CARRYCASCIN can only be used in the current DSP48E1 instance %m if the previous DSP48E1 is performing a two input ADD or SUBTRACT operation, or the current DSP48E1 is configured in the MAC extend opmode 7'b1001000 at %.3f ns.", sim.now // 1000.000000),
        #        cci_drc_msg(0b1)
        #    ),
        #    If(~((qopmode_o_mux[4:0] != 0b0101)._isOn())._isOn(),
        #        #print("DRC warning : CARRYINSEL is set to 010 with OPMODE set to multiplication (xxx0101). This is an illegal mode and may show deviation between simulation results and hardware behavior. DSP48E1 instance %m at %.3f ns.", sim.now // 1000.000000)
        #    ),
        #    If(~cis_drc_msg._eq(0b1),
        #        #print("DRC warning : CARRYINSEL is set to 010 with OPMODEREG set to 0. This causes unknown values after reset occurs. It is suggested to use OPMODEREG = 1 when cascading large adders. DSP48E1 instance %m at %.3f ns.", sim.now // 1000.000000),
        #        cis_drc_msg(0b1)
        #    ) if OPMODEREG == 0b1 else []
        # )
        if OPMODEREG == 0:
            qopmode_o_mux(opmode_in)
        elif OPMODEREG == 1:
            qopmode_o_mux(qopmode_o_reg1)
        else:
            raise AssertionError()

        #*** ALUMODE with 1 level of register
        If(
            clk_in._onRisingEdge(),
            If(RSTALUMODE,
               qalumode_o_reg1(0b0)).Elif(CEALUMODE,
                                          qalumode_o_reg1(alumode_in)))
        if ALUMODEREG == 0:
            qalumode_o_mux(alumode_in)
        elif ALUMODEREG == 1:
            qalumode_o_mux(qalumode_o_reg1)
        else:
            raise AssertionError()

        def deassign_xyz_mux_if_PREG_eq_1():
            if PREG != 1:
                return self.display_invalid_opmode()
            else:
                return self.deassign_xyz_mux()

        def DCR_check_logic_modes():
            # -- LOGIC MODES DRC
            return If(
                In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux),
                self.deassign_xyz_mux()
            ).Elif(
                In(qopmode_o_mux,
                   LOGIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1),
                deassign_xyz_mux_if_PREG_eq_1(),
            ).Else(
                # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000)
            )

        # display_invalid_opmode
        arith_mode_tmp = qopmode_o_mux._concat(qcarryinsel_o_mux)
        # no check at first 100ns
        Switch(qalumode_o_mux[4:2])\
            .Case(0b00,
                # -- ARITHMETIC MODES DRC
                If(In(arith_mode_tmp, ARITHMETIC_MODES_DRC_deassign_xyz_mux),
                    self.deassign_xyz_mux()
                ).Elif(In(arith_mode_tmp, ARITHMETIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1),
                    deassign_xyz_mux_if_PREG_eq_1()
                ).Else(
                    # CR 444150
                    # If(qopmode_o_mux._concat(qcarryinsel_o_mux)._eq(0b0000000010)._isOn() & (OPMODEREG._eq(1)._isOn() & CARRYINSELREG._eq(0)._isOn())._isOn(),
                    #    print("DRC warning : CARRYINSELREG is set to %d. It is required to have CARRYINSELREG be set to 1 to match OPMODEREG, in order to ensure that the simulation model will match the hardware behavior in all use cases.", CARRYINSELREG)
                    # ),
                    # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is either invalid or the CARRYINSEL %b for that specific OPMODE is invalid at %.3f ns. This warning may be due to a mismatch in the OPMODEREG and CARRYINSELREG attribute settings. It is recommended that OPMODEREG and CARRYINSELREG always be set to the same value. ", qopmode_o_mux, qcarryinsel_o_mux, sim.now // 1000.000000)
                )
            )\
            .Case(0b01,
               DCR_check_logic_modes()
            )\
            .Case(0b11,
               DCR_check_logic_modes()
            )\
            .Default(
                # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000)
            )

        If(
            qalumode_o_mux[0],
            co(qx_o_mux & qy_o_mux
               | ~qz_o_mux & qy_o_mux | qx_o_mux & ~qz_o_mux),
            s(~qz_o_mux ^ qx_o_mux ^ qy_o_mux)).Else(
                co(qx_o_mux & qy_o_mux | qz_o_mux & qy_o_mux
                   | qx_o_mux & qz_o_mux), s(qz_o_mux ^ qx_o_mux ^ qy_o_mux))

        If(
            qalumode_o_mux[2],
            comux(0),
        ).Else(comux(co), )
        smux(qalumode_o_mux[3]._ternary(co, s))

        carryout_o_hw = self._sig("carryout_o_hw", Bits(CARRYOUT_W))
        carryout_o_hw[0](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout0, cout0))
        carryout_o_hw[1](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout1, cout1))
        carryout_o_hw[2](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout2, cout2))
        carryout_o_hw[3](
            (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout3, cout3))
        alu_o(qalumode_o_mux[1]._ternary(
            ~Concat(s3[12:0], s2[12:0], s1[12:0], s0[12:0]),
            Concat(s3[12:0], s2[12:0], s1[12:0], s0[12:0])))
        carrycascout_o(cout3)
        multsignout_o_opmode(
            (qopmode_o_mux[7:4]._eq(0b100))._ternary(MULTSIGNIN,
                                                     qmult_o_mux[42]))
        If(
            (qopmode_o_mux[4:0]._eq(0b0101) | (qalumode_o_mux[4:2] != 0b00)),
            carryout_o[3](None),
            carryout_o[2](None),
            carryout_o[1](None),
            carryout_o[0](None),
        ).Else(
            carryout_o[3](carryout_o_hw[3]),
            carryout_o[2](carryout_o_hw[2] if USE_SIMD == "FOUR12" else None),
            carryout_o[1](carryout_o_hw[1] if USE_SIMD in
                          ["TWO24", "FOUR12"] else None),
            carryout_o[0](carryout_o_hw[0] if USE_SIMD == "FOUR12" else None),
        )

        #--########################### END ALU ################################
        #*** CarryIn Mux and Register
        #-------  input 0
        If(
            clk_in._onRisingEdge(),
            If(RSTALLCARRYIN,
               qcarryin_o_reg0(0b0)).Elif(CECARRYIN,
                                          qcarryin_o_reg0(carryin_in)))
        if CARRYINREG == 0:
            qcarryin_o_mux0(carryin_in)
        elif CARRYINREG == 1:
            qcarryin_o_mux0(qcarryin_o_reg0)
        else:
            raise AssertionError()

        #-------  input 7
        If(
            clk_in._onRisingEdge(),
            If(RSTALLCARRYIN, qcarryin_o_reg7(0b0)).Elif(
                CEM, qcarryin_o_reg7(ad_mult[24]._eq(b_mult[17]))))

        if MREG == 0:
            qcarryin_o_mux7(ad_mult[24]._eq(b_mult[17]))
        elif MREG == 1:
            qcarryin_o_mux7(qcarryin_o_reg7)
        else:
            raise ValueError(
                "MREG is set to %d. Legal values for this attribute are 0 or 1.",
                MREG)

        Switch(qcarryinsel_o_mux)\
            .Case(CARRYIN_SEL.CARRYIN.value,
                qcarryin_o_mux_tmp(qcarryin_o_mux0))\
            .Case(CARRYIN_SEL.PCIN_47_n.value,
                qcarryin_o_mux_tmp(~PCIN[47]))\
            .Case(CARRYIN_SEL.CARRYCASCIN.value,
                qcarryin_o_mux_tmp(CARRYCASCIN))\
            .Case(CARRYIN_SEL.PCIN_47.value,
                qcarryin_o_mux_tmp(PCIN[47]))\
            .Case(CARRYIN_SEL.CARRYCASCOUT.value,
                qcarryin_o_mux_tmp(carrycascout_o_mux))\
            .Case(CARRYIN_SEL.P_47_n.value,
                qcarryin_o_mux_tmp(~qp_o_mux[47]))\
            .Case(CARRYIN_SEL.A_27_eq_B_17.value,
                qcarryin_o_mux_tmp(qcarryin_o_mux7))\
            .Case(CARRYIN_SEL.P_47.value,
                qcarryin_o_mux_tmp(qp_o_mux[47]))

        # disable carryin when performing logic operation
        If(qalumode_o_mux[3] | qalumode_o_mux[2],
           qcarryin_o_mux(0b0)).Else(qcarryin_o_mux(qcarryin_o_mux_tmp))

        if AUTORESET_PATDET == "RESET_MATCH":
            the_auto_reset_patdet(pdet_o_reg1)
        elif AUTORESET_PATDET == "RESET_NOT_MATCH":
            the_auto_reset_patdet(pdet_o_reg2 & ~pdet_o_reg1)
        else:
            the_auto_reset_patdet(0)

        #--####################################################################
        #--#####      CARRYOUT, CARRYCASCOUT. MULTSIGNOUT and PCOUT      ######
        #--####################################################################
        #*** register with 1 level of register
        If(
            clk_in._onRisingEdge(),
            If(RSTP._isOn() | the_auto_reset_patdet._isOn(),
               carryout_o_reg(0b0), carrycascout_o_reg(0b0),
               qmultsignout_o_reg(0b0),
               qp_o_reg1(0b0)).Elif(CEP, carryout_o_reg(carryout_o),
                                    carrycascout_o_reg(carrycascout_o),
                                    qmultsignout_o_reg(multsignout_o_opmode),
                                    qp_o_reg1(alu_o)))
        if PREG == 0:
            carryout_o_mux(carryout_o)
            carrycascout_o_mux(carrycascout_o)
            multsignout_o_mux(multsignout_o_opmode)
            qp_o_mux(alu_o)

        elif PREG == 1:
            carryout_o_mux(carryout_o_reg)
            carrycascout_o_mux(carrycascout_o_reg)
            multsignout_o_mux(qmultsignout_o_reg)
            qp_o_mux(qp_o_reg1)
        else:
            raise AssertionError()

        carryout_x_o(
            Concat(
                carryout_o_mux[3],
                carryout_o_mux[2]
                if USE_SIMD == "FOUR12" else BIT.from_py(None),
                carryout_o_mux[1]
                if USE_SIMD in ["TWO24", "FOUR12"] else BIT.from_py(None),
                carryout_o_mux[0]
                if USE_SIMD == "FOUR12" else BIT.from_py(None),
            ))

        the_pattern(PATTERN if SEL_PATTERN == "PATTERN" else qc_o_mux)

        # selet mask
        if USE_PATTERN_DETECT == "NO_PATDET":
            the_mask(mask(48))
        elif SEL_MASK == "MASK":
            the_mask(MASK)
        elif SEL_MASK == "C":
            the_mask(qc_o_mux)
        elif SEL_MASK == "ROUNDING_MODE1":
            the_mask(~qc_o_mux << 1)
        elif SEL_MASK == "ROUNDING_MODE2":
            the_mask(~qc_o_mux << 2)
        else:
            raise AssertionError()

        If(
            opmode_valid_flag,
            pdet_o(And(*(~(the_pattern ^ alu_o) | the_mask))),
            pdetb_o(And(*(the_pattern ^ alu_o | the_mask))),
        ).Else(
            pdet_o(None),
            pdetb_o(None),
        )
        pdet_o_mux(pdet_o_reg1 if PREG == 1 else pdet_o)
        pdetb_o_mux(pdetb_o_reg1 if PREG == 1 else pdetb_o)

        #*** Output register PATTERN DETECT and UNDERFLOW / OVERFLOW
        If(
            clk_in._onRisingEdge(),
            If(RSTP._isOn() | the_auto_reset_patdet._isOn(), pdet_o_reg1(0b0),
               pdet_o_reg2(0b0), pdetb_o_reg1(0b0),
               pdetb_o_reg2(0b0)).Elif(CEP, pdet_o_reg2(pdet_o_reg1),
                                       pdet_o_reg1(pdet_o),
                                       pdetb_o_reg2(pdetb_o_reg1),
                                       pdetb_o_reg1(pdetb_o)))
        if PREG == 1 or USE_PATTERN_DETECT == "PATDET":
            overflow_o(pdet_o_reg2 & ~pdet_o_reg1 & ~pdetb_o_reg1),
            underflow_o(pdetb_o_reg2 & ~pdet_o_reg1 & ~pdetb_o_reg1)
        else:
            overflow_o(None),
            underflow_o(None)
Пример #7
0
    def _rx_logic(self, rmii: Rmii, rx: VldSyncedDataErrLast,
                  D_W: int, RMII_W: int, clk_edge):
        CNTR_W = D_W // RMII_W

        clk = (rmii.ref_clk, clk_edge)
        # register for all input signals
        din = self._reg("rx_din", Bits(RMII_W), clk=clk)
        din_vld = self._reg("rx_din_vld", clk=clk, def_val=0)
        din(rmii.rx.d)
        din_vld(rmii.rx.crs_dv)

        # register for temporary RX byte
        reg0 = self._reg("rx_reg0", Bits(D_W, signed=False),
                         def_val=0,
                         clk=clk)
        # register for Rx byte for clock edge sync
        reg1 = self._reg("rx_reg1", Bits(D_W, signed=False),
                         def_val=0,
                         clk=rmii.ref_clk)
        reg1_vld = self._reg("rx_reg1_vld", def_val=0)
        # one hot counter with rotating 1
        cntr = self._reg("rx_cntr", Bits(CNTR_W, signed=False),
                         def_val=1,
                         clk=clk)
        # counter of preambule bytes
        preamble_cnt = self._reg("rx_preamble_cntr",
                                 Bits(log2ceil(8), signed=False),
                                 clk=clk)

        st_t = HEnum("rx_state_t", ["skip0", "preamble_and_sfd", "data", "error"])
        st = self._reg("rx_state", st_t, def_val=st_t.skip0, clk=clk)
        last_in_B = cntr[CNTR_W - 1] & din_vld
        actual_rx_B = self._sig("rx_actual_val", dtype=Bits(8))
        actual_rx_B(Concat(din, reg0[:RMII_W]))

        Switch(st)\
        .Case(st_t.skip0,
            If(din_vld & (din != 0),
               st(st_t.preamble_and_sfd),
               preamble_cnt(8-1),
            ),
        ).Case(st_t.preamble_and_sfd,
            If(last_in_B,
                If(preamble_cnt._eq(0),
                    If(actual_rx_B != ETH.SFD,
                       st(st_t.error)
                    ).Else(
                       st(st_t.data)
                    )
                ).Elif(actual_rx_B != ETH.PREAMBLE_1B,
                    st(st_t.error),
                ),
                preamble_cnt(preamble_cnt - 1)
            )
        ).Case(st_t.error,
            If(~din_vld,
               st(st_t.skip0),
            )
        ).Case(st_t.data,
            If(cntr[CNTR_W - 1] & ~din_vld,
               st(st_t.skip0)
            )
        )

        # bit collection logic
        If(st._eq(st_t.skip0),
            cntr(1<<1),
            reg0(Concat(din, Bits(D_W - RMII_W).from_py(0))),
        ).Elif(In(st, [st_t.preamble_and_sfd, st_t.data]),
            # shift in LSB first
            # :note: only D_W - RMII_W bits is captured in reg0
            reg0(Concat(din, reg0[:RMII_W])),
            cntr(rol(cntr, 1)),
        )

        reg1_vld(st._eq(st_t.data) & last_in_B)
        If(reg1_vld.next,
           reg1(actual_rx_B),
        )
        err = st._eq(st_t.error)
        If(err,
            rx.data(None),
        ).Else(
            rx.data(reg1)
        )

        rx.err(err)
        rx.last(~din_vld)
        rx.vld(reg1_vld | st._eq(st_t.error))
Пример #8
0
    def _impl(self):
        propagateClkRstn(self)
        r, s = self._reg, self._sig
        req = self.rDatapump.req
        f = self.dataFifo
        dIn = self.rDatapump.r
        dBuffIn = f.dataIn

        ALIGN_BITS = self.addrAlignBits()
        ID = self.ID
        BUFFER_CAPACITY = self.BUFFER_CAPACITY
        BURST_LEN = BUFFER_CAPACITY // 2
        ID_LAST = self.ID_LAST
        bufferHasSpace = s("bufferHasSpace")
        bufferHasSpace(f.size < (BURST_LEN + 1))
        # we are counting base next addr as item as well
        inBlock_t = Bits(log2ceil(self.ITEMS_IN_BLOCK + 1))
        ringSpace_t = Bits(self.PTR_WIDTH)

        downloadPending = r("downloadPending", def_val=0)

        baseIndex = r("baseIndex", Bits(self.ADDR_WIDTH - ALIGN_BITS))
        inBlockRemain = r("inBlockRemain_reg",
                          inBlock_t,
                          def_val=self.ITEMS_IN_BLOCK)
        self.inBlockRemain(inBlockRemain)

        # Logic of tail/head
        rdPtr = r("rdPtr", ringSpace_t, def_val=0)
        wrPtr = r("wrPtr", ringSpace_t, def_val=0)
        If(self.wrPtr.dout.vld, wrPtr(self.wrPtr.dout.data))
        self.wrPtr.din(wrPtr)
        self.rdPtr.din(rdPtr)

        # this means items are present in memory
        hasSpace = s("hasSpace")
        hasSpace(wrPtr != rdPtr)
        doReq = s("doReq")
        doReq(bufferHasSpace & hasSpace & ~downloadPending & req.rd)
        req.rem(0)
        self.dataOut(f.dataOut)

        # logic of baseAddr and baseIndex
        baseAddr = Concat(baseIndex, Bits(ALIGN_BITS).from_py(0))
        req.addr(baseAddr)
        self.baseAddr.din(baseAddr)
        dataAck = dIn.valid & In(dIn.id, [ID, ID_LAST]) & dBuffIn.rd

        If(self.baseAddr.dout.vld,
           baseIndex(self.baseAddr.dout.data[:ALIGN_BITS])).Elif(
               dataAck & downloadPending,
               If(dIn.last & dIn.id._eq(ID_LAST),
                  baseIndex(dIn.data[self.ADDR_WIDTH:ALIGN_BITS])).Else(
                      baseIndex(baseIndex + 1)))

        sizeByPtrs = s("sizeByPtrs", ringSpace_t)
        sizeByPtrs(wrPtr - rdPtr)

        inBlockRemain_asPtrSize = fitTo(inBlockRemain, sizeByPtrs)
        constraingSpace = s("constraingSpace", ringSpace_t)
        If(inBlockRemain_asPtrSize < sizeByPtrs,
           constraingSpace(inBlockRemain_asPtrSize)).Else(
               constraingSpace(sizeByPtrs))

        constrainedByInBlockRemain = s("constrainedByInBlockRemain")
        constrainedByInBlockRemain(
            fitTo(sizeByPtrs, inBlockRemain) >= inBlockRemain)

        If(
            constraingSpace > BURST_LEN,
            # download full burst
            req.id(ID),
            req.len(BURST_LEN - 1),
            If(doReq, inBlockRemain(inBlockRemain - BURST_LEN))
        ).Elif(
            constrainedByInBlockRemain & (inBlockRemain < BURST_LEN),
            # we know that sizeByPtrs <= inBlockRemain thats why we can resize it
            # we will download next* as well
            req.id(ID_LAST),
            req.len(constraingSpace, fit=True),
            If(doReq, inBlockRemain(self.ITEMS_IN_BLOCK))).Else(
                # download data leftover
                req.id(ID),
                req.len(constraingSpace - 1, fit=True),
                If(
                    doReq,
                    inBlockRemain(inBlockRemain -
                                  fitTo(constraingSpace, inBlockRemain))))

        # logic of req dispatching
        If(downloadPending, req.vld(0),
           If(dataAck & dIn.last, downloadPending(0))).Else(
               req.vld(bufferHasSpace & hasSpace),
               If(req.rd & bufferHasSpace & hasSpace, downloadPending(1)))

        # into buffer pushing logic
        dBuffIn.data(dIn.data)

        isMyData = s("isMyData")
        isMyData(dIn.id._eq(ID) | (~dIn.last & dIn.id._eq(ID_LAST)))
        If(self.rdPtr.dout.vld, rdPtr(self.rdPtr.dout.data)).Else(
            If(dIn.valid & downloadPending & dBuffIn.rd & isMyData,
               rdPtr(rdPtr + 1)))
        # push data into buffer and increment rdPtr
        StreamNode(masters=[dIn],
                   slaves=[dBuffIn],
                   extraConds={
                       dIn:
                       downloadPending,
                       dBuffIn: (dIn.id._eq(ID)
                                 | (dIn.id._eq(ID_LAST)
                                    & ~dIn.last)) & downloadPending
                   }).sync()