Exemplo n.º 1
0
 def multiplex_to_csr_num(self, m: Module):
     with m.If(self._funct12_to_csr_num):
         m.d.comb += self.csr_num.eq(self._funct12)
     with m.Elif(self._mepc_num_to_csr_num):
         m.d.comb += self.csr_num.eq(CSRAddr.MEPC)
     with m.Elif(self._mcause_to_csr_num):
         m.d.comb += self.csr_num.eq(CSRAddr.MCAUSE)
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic for the SignedComparator module."""
        m = Module()
        m.submodules.ucmp = ucmp = UnsignedComparator()

        ult = Signal()  # Unsigned less than

        # Hook up the submodule
        m.d.comb += [
            ucmp.a.eq(self.a),
            ucmp.b.eq(self.b),
            ult.eq(ucmp.lt),
        ]

        is_a_neg = self.a[15]
        is_b_neg = self.b[15]

        with m.If(~is_a_neg & ~is_b_neg):
            m.d.comb += self.lt.eq(ult)
        with m.Elif(is_a_neg & ~is_b_neg):
            m.d.comb += self.lt.eq(1)
        with m.Elif(~is_a_neg & is_b_neg):
            m.d.comb += self.lt.eq(0)
        with m.Else():
            m.d.comb += self.lt.eq(ult)

        return m
Exemplo n.º 3
0
    def ALU(self, m: Module, func: ALU8Func, store: bool = True):
        b = self.instr[6]

        with m.If(self.mode == ModeBits.DIRECT.value):
            operand = self.mode_direct(m)
            self.read_byte(m, cycle=1, addr=operand, comb_dest=self.src8_2)

            with m.If(self.cycle == 2):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)

        with m.Elif(self.mode == ModeBits.EXTENDED.value):
            operand = self.mode_ext(m)
            self.read_byte(m, cycle=2, addr=operand, comb_dest=self.src8_2)

            with m.If(self.cycle == 3):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)

        with m.Elif(self.mode == ModeBits.IMMEDIATE.value):
            operand = self.mode_immediate8(m)

            with m.If(self.cycle == 2):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.src8_2.eq(operand)
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)

        with m.Elif(self.mode == ModeBits.INDEXED.value):
            operand = self.mode_indexed(m)
            self.read_byte(m, cycle=3, addr=operand, comb_dest=self.src8_2)

            with m.If(self.cycle == 4):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)
Exemplo n.º 4
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic of the trap sequencer ROM."""
        m = Module()

        # Defaults
        m.d.comb += [
            self.set_instr_complete.eq(0),
            self.save_trap_csrs.eq(0),
            self.csr_to_x.eq(0),
            self._next_instr_phase.eq(0),
            self.alu_op_to_z.eq(AluOp.NONE),
            self._mcause_to_csr_num.eq(0),
            self.enter_trap.eq(0),
            self.exit_trap.eq(0),
            self.clear_pend_mti.eq(0),
            self.clear_pend_mei.eq(0),
            self.x_mux_select.eq(SeqMuxSelect.X),
            self.y_mux_select.eq(SeqMuxSelect.Y),
            self.z_mux_select.eq(SeqMuxSelect.Z),
            self.pc_mux_select.eq(SeqMuxSelect.PC),
            self.memaddr_mux_select.eq(SeqMuxSelect.MEMADDR),
            self._const.eq(0),
        ]

        m.d.comb += [
            self.load_trap.eq(0),
            self.next_trap.eq(0),
            self.load_exception.eq(0),
            self.next_exception.eq(0),
            self.next_fatal.eq(0),
        ]

        # 4 cases here:
        #
        # 1. It's a trap!
        # 2. It's not a trap, but PC is misaligned.
        # 3. It's not a trap, PC is aligned, but it's a bad instruction.
        # 4. None of the above (allow control by sequencer ROM).

        with m.If(self.trap):
            self.handle_trap(m)

        # True when pc[0:2] != 0 and ~trap.
        with m.Elif(self.instr_misalign):
            self.set_exception(m,
                               ConstSelect.EXC_INSTR_ADDR_MISALIGN,
                               mtval=SeqMuxSelect.PC)

        with m.Elif(self.bad_instr):
            self.set_exception(m,
                               ConstSelect.EXC_ILLEGAL_INSTR,
                               mtval=SeqMuxSelect.INSTR)

        return m
Exemplo n.º 5
0
    def check(self, m: Module, instr: Value, data: FormalData):
        input, actual_output = self.common_check(m, instr, data)
        expected_output = Signal(8)
        pre_c = data.pre_ccs[Flags.C]
        c = Signal()

        with m.If(instr.matches(ROL)):
            # input[7..0], c ->
            # c, output[7..0]
            m.d.comb += [
                c.eq(input[7]),
                expected_output[0].eq(pre_c),
                Downto(expected_output, 7, 1).eq(Downto(input, 6, 0)),
            ]
        with m.Elif(instr.matches(ROR)):
            # c, input[7..0] ->
            # output[7..0], c
            m.d.comb += [
                c.eq(input[0]),
                expected_output[7].eq(pre_c),
                Downto(expected_output, 6, 0).eq(Downto(input, 7, 1)),
            ]
        with m.Elif(instr.matches(ASL)):
            # input[7..0], 0 ->
            # c, output[7..0]
            m.d.comb += [
                c.eq(input[7]),
                expected_output[0].eq(0),
                Downto(expected_output, 7, 1).eq(Downto(input, 6, 0)),
            ]
        with m.Elif(instr.matches(ASR)):
            # input[7], input[7..0] ->
            # output[7..0], c
            m.d.comb += [
                c.eq(input[0]),
                expected_output[7].eq(input[7]),
                Downto(expected_output, 6, 0).eq(Downto(input, 7, 1)),
            ]
        with m.Elif(instr.matches(LSR)):
            # 0, input[7..0] ->
            # output[7..0], c
            m.d.comb += [
                c.eq(input[0]),
                expected_output[7].eq(0),
                Downto(expected_output, 6, 0).eq(Downto(input, 7, 1)),
            ]

        m.d.comb += Assert(expected_output == actual_output)
        n = expected_output[7]
        z = (expected_output == 0)
        v = n ^ c
        self.assertFlags(m, data.post_ccs, data.pre_ccs,
                         Z=z, N=n, V=v, C=c)
Exemplo n.º 6
0
    def formal(cls) -> Tuple[Module, List[Signal]]:
        """Formal verification for the active low 74182 chip."""
        m = Module()
        m.submodules.clu = clu = IC_74182_active_low()

        # Verify the truth tables in the datasheet

        with m.If(clu.np.matches("0000")):
            m.d.comb += Assert(clu.group_np == 0)
        with m.Else():
            m.d.comb += Assert(clu.group_np == 1)

        with m.If(clu.ng.matches("0---") & clu.np.matches("----")):
            m.d.comb += Assert(clu.group_ng == 0)
        with m.Elif(clu.ng.matches("-0--") & clu.np.matches("0---")):
            m.d.comb += Assert(clu.group_ng == 0)
        with m.Elif(clu.ng.matches("--0-") & clu.np.matches("00--")):
            m.d.comb += Assert(clu.group_ng == 0)
        with m.Elif(clu.ng.matches("---0") & clu.np.matches("000-")):
            m.d.comb += Assert(clu.group_ng == 0)
        with m.Else():
            m.d.comb += Assert(clu.group_ng == 1)

        with m.If(clu.ng[0] == 0):
            m.d.comb += Assert(clu.carryout_x == 1)
        with m.Elif((clu.np[0] == 0) & (clu.carryin == 1)):
            m.d.comb += Assert(clu.carryout_x == 1)
        with m.Else():
            m.d.comb += Assert(clu.carryout_x == 0)

        with m.If(clu.ng.matches("--0-") & clu.np.matches("----")):
            m.d.comb += Assert(clu.carryout_y == 1)
        with m.Elif(clu.ng.matches("---0") & clu.np.matches("--0-")):
            m.d.comb += Assert(clu.carryout_y == 1)
        with m.Elif(
                clu.ng.matches("----") & clu.np.matches("--00")
                & (clu.carryin == 1)):
            m.d.comb += Assert(clu.carryout_y == 1)
        with m.Else():
            m.d.comb += Assert(clu.carryout_y == 0)

        with m.If(clu.ng.matches("-0--") & clu.np.matches("----")):
            m.d.comb += Assert(clu.carryout_z == 1)
        with m.Elif(clu.ng.matches("--0-") & clu.np.matches("-0--")):
            m.d.comb += Assert(clu.carryout_z == 1)
        with m.Elif(clu.ng.matches("---0") & clu.np.matches("-00-")):
            m.d.comb += Assert(clu.carryout_z == 1)
        with m.Elif(
                clu.ng.matches("----") & clu.np.matches("-000")
                & (clu.carryin == 1)):
            m.d.comb += Assert(clu.carryout_z == 1)
        with m.Else():
            m.d.comb += Assert(clu.carryout_z == 0)

        return m, clu.ports()
Exemplo n.º 7
0
    def check(self, m: Module, instr: Value, data: FormalData):
        mode = instr[4:6]
        b = instr[6]
        input = Mux(b, data.pre_b, data.pre_a)

        m.d.comb += [
            Assert(data.post_a == data.pre_a),
            Assert(data.post_b == data.pre_b),
            Assert(data.post_x == data.pre_x),
            Assert(data.post_sp == data.pre_sp),
        ]

        with m.If(mode == ModeBits.DIRECT.value):
            m.d.comb += [
                Assert(data.post_pc == data.plus16(data.pre_pc, 2)),
                Assert(data.addresses_read == 1),
                Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
                Assert(data.addresses_written == 1),
                Assert(data.write_addr[0] == data.read_data[0]),
                Assert(data.write_data[0] == input),
            ]
        with m.Elif(mode == ModeBits.EXTENDED.value):
            m.d.comb += [
                Assert(data.post_pc == data.plus16(data.pre_pc, 3)),
                Assert(data.addresses_read == 2),
                Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
                Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)),
                Assert(data.addresses_written == 1),
                Assert(data.write_addr[0] == Cat(data.read_data[1],
                                                 data.read_data[0])),
                Assert(data.write_data[0] == input),
            ]

        with m.Elif(mode == ModeBits.INDEXED.value):
            m.d.comb += [
                Assert(data.post_pc == data.plus16(data.pre_pc, 2)),
                Assert(data.addresses_read == 1),
                Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
                Assert(data.addresses_written == 1),
                Assert(data.write_addr[0] == (data.pre_x +
                                              data.read_data[0])[:16]),
                Assert(data.write_data[0] == input),
            ]

        self.assertFlags(m,
                         data.post_ccs,
                         data.pre_ccs,
                         Z=(input == 0),
                         N=input[7],
                         V=0)
Exemplo n.º 8
0
    def elaborate(self, platform):
        m = Module()

        rdata = Signal.like(self.iport.dat_r)

        # handle transaction logic
        with m.If(self.iport.cyc):
            with m.If(self.iport.ack | self.iport.err | ~self.f_valid):
                m.d.sync += [
                    self.iport.cyc.eq(0),
                    self.iport.stb.eq(0),
                    rdata.eq(self.iport.dat_r)
                ]
        with m.Elif(self.a_valid & ~self.a_stall):  # start transaction
            m.d.sync += [
                self.iport.addr.eq(self.a_pc),
                self.iport.cyc.eq(1),
                self.iport.stb.eq(1)
            ]
        m.d.comb += [
            self.iport.dat_w.eq(0),
            self.iport.sel.eq(0),
            self.iport.we.eq(0),
            self.iport.cti.eq(CycleType.CLASSIC),
            self.iport.bte.eq(0)
        ]

        # in case of error, make the instruction a NOP
        with m.If(self.f_bus_error):
            m.d.comb += self.f_instruction.eq(0x00000013)  # NOP
        with m.Else():
            m.d.comb += self.f_instruction.eq(rdata)

        # excepcion
        with m.If(self.iport.cyc & self.iport.err):
            m.d.sync += [
                self.f_bus_error.eq(1),
                self.f_badaddr.eq(self.iport.addr)
            ]
        with m.Elif(
                ~self.f_stall
        ):  # in case of error, but the pipe is stalled, do not lose the error
            m.d.sync += self.f_bus_error.eq(0)

        # busy flag
        m.d.comb += self.f_busy.eq(self.iport.cyc)

        return m
Exemplo n.º 9
0
    def handle_branch(self, m: Module):
        """Adds the BRANCH logic to the given module.

        cond <- rs1 - rs2 < 0, rs1 - rs2 == 0
        if f(cond):
            PC <- PC + imm
        else:
            PC <- PC + 4

        rs1     -> X
        rs2     -> Y
        ALU SUB -> Z, cond
        --------------------- cond == 1
        PC      -> X
        imm/4   -> Y (imm for cond == 1, 4 otherwise)
        ALU ADD -> Z
        Z       -> PC
        Z       -> memaddr
        --------------------- cond == 0
        PC + 4  -> PC
        PC + 4  -> memaddr
        """
        with m.If(self._instr_phase == 0):
            m.d.comb += [
                self.reg_to_x.eq(1),
                self._x_reg_select.eq(InstrReg.RS1),
                self.reg_to_y.eq(1),
                self._y_reg_select.eq(InstrReg.RS2),
                self.alu_op_to_z.eq(AluOp.SUB),
                self._next_instr_phase.eq(1),
            ]
        with m.Elif(self._instr_phase == 1):
            with m.If(~self._funct3.matches(BranchCond.EQ, BranchCond.NE,
                                            BranchCond.LT, BranchCond.GE,
                                            BranchCond.LTU, BranchCond.GEU)):
                self.handle_illegal_instr(m)

            with m.Else():
                with m.If(self.branch_cond):
                    m.d.comb += self.y_mux_select.eq(SeqMuxSelect.IMM)
                with m.Else():
                    m.d.comb += self._const.eq(ConstSelect.SHAMT_4)
                    m.d.comb += self.y_mux_select.eq(SeqMuxSelect.CONST)

                m.d.comb += [
                    self.x_mux_select.eq(SeqMuxSelect.PC),
                    self.alu_op_to_z.eq(AluOp.ADD),
                ]

                with m.If(self.data_z_in_2_lsb0):
                    self.next_instr(m, NextPC.Z)

                with m.Else():
                    m.d.comb += self._next_instr_phase.eq(2)
                    m.d.comb += self.tmp_mux_select.eq(SeqMuxSelect.Z)

        with m.Else():
            self.set_exception(m,
                               ConstSelect.EXC_INSTR_ADDR_MISALIGN,
                               mtval=SeqMuxSelect.TMP)
Exemplo n.º 10
0
    def elaborate(self, platform):
        m = Module()
        mac = [Signal(8) for _ in range(6)]

        m.d.sync += self.mac_match.eq(
            reduce(operator.and_,
                   [(mac[idx] == self.mac_addr[idx]) | (mac[idx] == 0xFF)
                    for idx in range(6)]))

        with m.FSM():
            with m.State("RESET"):
                m.d.sync += [mac[idx].eq(0) for idx in range(6)]
                with m.If(~self.reset):
                    m.next = "BYTE0"

            for idx in range(6):
                next_state = f"BYTE{idx+1}" if idx < 5 else "DONE"

                with m.State(f"BYTE{idx}"):
                    m.d.sync += mac[idx].eq(self.data)
                    with m.If(self.reset):
                        m.next = "RESET"
                    with m.Elif(self.data_valid):
                        m.next = next_state

            with m.State("DONE"):
                with m.If(self.reset):
                    m.next = "RESET"

        return m
Exemplo n.º 11
0
Arquivo: crc.py Projeto: ret/daqnet
    def elaborate(self, platform):

        m = Module()
        crc = Signal(32)

        self.crctable = Memory(32, 256, make_crc32_table())
        table_port = self.crctable.read_port()
        m.submodules += table_port

        m.d.comb += [
            self.crc_out.eq(crc ^ 0xFFFFFFFF),
            self.crc_match.eq(crc == 0xDEBB20E3),
            table_port.addr.eq(crc ^ self.data),
        ]

        with m.FSM():
            with m.State("RESET"):
                m.d.sync += crc.eq(0xFFFFFFFF)
                m.next = "IDLE"

            with m.State("IDLE"):
                with m.If(self.reset):
                    m.next = "RESET"
                with m.Elif(self.data_valid):
                    m.next = "BUSY"

            with m.State("BUSY"):
                with m.If(self.reset):
                    m.next = "RESET"
                m.d.sync += crc.eq(table_port.data ^ (crc >> 8))
                m.next = "IDLE"

        return m
Exemplo n.º 12
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # Signal defaults
        m.d.comb += self.ft.oe.o.eq(0)
        m.d.comb += self.ft.write.o.eq(0)
        m.d.comb += self.ft.read.o.eq(0)

        with m.FSM():
            with m.State("READY"):
                # If there is data to read, we read it first before entering the write state
                with m.If(self.ft.rxf.i):
                    m.d.comb += self.ft.oe.o.eq(1)

                    m.d.comb += self.ft.data.oe.eq(0)
                    m.d.comb += self.ft.be.oe.eq(0)

                    m.next = "READ"
                with m.Elif(self.ft.txe.i & self.input_valid):
                    m.d.comb += self.ft.data.oe.eq(1)
                    m.d.comb += self.ft.be.oe.eq(1)

                    m.next = "WRITE"

            with m.State("READ"):
                m.d.comb += self.ft.oe.o.eq(1)

                # Set pins in correct direction (input)
                m.d.comb += self.ft.data.oe.eq(0)
                m.d.comb += self.ft.be.oe.eq(0)

                # Connect FIFO
                m.d.comb += self.output_payload.eq(self.ft.data.i)
                m.d.comb += self.output_valid.eq(self.ft.rxf.i)
                m.d.comb += self.ft.read.o.eq(self.output_ready)

                with m.If(~self.ft.rxf.i):
                    m.next = "READY"

            with m.State("WRITE"):
                # Set pins in correct direction (output)
                m.d.comb += self.ft.data.oe.eq(1)
                m.d.comb += self.ft.be.oe.eq(1)

                # All bytes are valid
                m.d.comb += self.ft.oe.o.eq(0)
                m.d.comb += self.ft.be.o.eq(0b11)

                # Connect FIFO
                m.d.comb += self.ft.data.o.eq(self.input_payload)
                m.d.comb += self.input_ready.eq(self.ft.txe.i)
                m.d.comb += self.ft.write.o.eq(self.input_valid)

                # TODO: Should we go to ready if there is data to read, or wait until write is done?
                with m.If(~self.ft.txe.i | ~self.input_valid):
                    m.next = "READY"

        return m
Exemplo n.º 13
0
    def formal_ripple(cls) -> Tuple[Module, List[Signal]]:
        """Formal verification for a bunch of ALUs in ripple-carry mode."""
        m = Module()

        alus = [None] * 8
        m.submodules.alu0 = alus[0] = IC_74181()
        m.submodules.alu1 = alus[1] = IC_74181()
        m.submodules.alu2 = alus[2] = IC_74181()
        m.submodules.alu3 = alus[3] = IC_74181()
        m.submodules.alu4 = alus[4] = IC_74181()
        m.submodules.alu5 = alus[5] = IC_74181()
        m.submodules.alu6 = alus[6] = IC_74181()
        m.submodules.alu7 = alus[7] = IC_74181()

        a = Signal(32)
        b = Signal(32)
        f = Signal(32)
        cin = Signal()
        cout = Signal()
        s = Signal(4)
        mt = Signal()

        for x in range(8):
            m.d.comb += alus[x].a.eq(a[x * 4:x * 4 + 4])
            m.d.comb += alus[x].b.eq(b[x * 4:x * 4 + 4])
            m.d.comb += f[x * 4:x * 4 + 4].eq(alus[x].f)
            m.d.comb += alus[x].m.eq(mt)
            m.d.comb += alus[x].s.eq(s)
        for x in range(7):
            m.d.comb += alus[x + 1].n_carryin.eq(alus[x].n_carryout)
        m.d.comb += alus[0].n_carryin.eq(~cin)
        m.d.comb += cout.eq(~alus[7].n_carryout)

        add_mode = (s == 9) & (mt == 0)
        sub_mode = (s == 6) & (mt == 0)
        m.d.comb += Assume(add_mode | sub_mode)

        y = Signal(33)
        with m.If(add_mode):
            m.d.comb += y.eq(a + b + cin)
            m.d.comb += Assert(f == y[:32])
            m.d.comb += Assert(cout == y[32])
        with m.Elif(sub_mode):
            m.d.comb += y.eq(a - b - ~cin)
            m.d.comb += Assert(f == y[:32])
            m.d.comb += Assert(cout == ~y[32])

            # Check how equality, unsigned gt, and unsigned gte comparisons work.
            with m.If(cin == 0):
                all_eq = Cat(*[i.a_eq_b for i in alus]).all()
                m.d.comb += Assert(all_eq == (a == b))
                m.d.comb += Assert(cout == (a > b))
            with m.Else():
                m.d.comb += Assert(cout == (a >= b))

        return m, [a, b, f, cin, cout, s, mt, y]
Exemplo n.º 14
0
    def elaborate(self, platform):
        m = Module()

        op = Signal()

        m.d.comb += op.eq(self.x_load | self.x_store)

        # transaction logic
        with m.If(self.dport.cyc):
            with m.If(self.dport.ack | self.dport.err | ~self.m_valid):
                m.d.sync += [
                    self.m_load_data.eq(self.dport.dat_r),
                    self.dport.we.eq(0),
                    self.dport.cyc.eq(0),
                    self.dport.stb.eq(0)
                ]
        with m.Elif(op & self.x_valid & ~self.x_stall):
            m.d.sync += [
                self.dport.addr.eq(self.x_addr),
                self.dport.dat_w.eq(self.x_data_w),
                self.dport.sel.eq(self.x_byte_sel),
                self.dport.we.eq(self.x_store),
                self.dport.cyc.eq(1),
                self.dport.stb.eq(1)
            ]
        m.d.comb += [
            self.dport.cti.eq(CycleType.CLASSIC),
            self.dport.bte.eq(0)
        ]

        # exceptions
        with m.If(self.dport.cyc & self.dport.err):
            m.d.sync += [
                self.m_load_error.eq(~self.dport.we),
                self.m_store_error.eq(self.dport.we),
                self.m_badaddr.eq(self.dport.addr)
            ]
        with m.Elif(~self.m_stall):
            m.d.sync += [self.m_load_error.eq(0), self.m_store_error.eq(0)]

        m.d.comb += self.m_busy.eq(self.dport.cyc)

        return m
Exemplo n.º 15
0
    def handle_trap(self, m: Module):
        """Adds trap handling logic.

        For fatals, we store the cause and then halt.
        """
        is_int = ~self.exception

        with m.If(self._instr_phase == 0):
            with m.If(self.fatal):
                m.d.comb += self._next_instr_phase.eq(0)  # hang.
            with m.Else():
                m.d.comb += self._next_instr_phase.eq(1)

            # If set_exception was called, we've already saved the trap CSRs.
            with m.If(is_int):
                with m.If(self.mei_pend):
                    m.d.comb += self._const.eq(ConstSelect.INT_MACH_EXTERNAL)
                    m.d.comb += self.x_mux_select.eq(SeqMuxSelect.CONST)
                    m.d.comb += self.clear_pend_mei.eq(1)
                with m.Elif(self.mti_pend):
                    m.d.comb += self._const.eq(ConstSelect.INT_MACH_TIMER)
                    m.d.comb += self.x_mux_select.eq(SeqMuxSelect.CONST)
                    m.d.comb += self.clear_pend_mti.eq(1)

                m.d.comb += self.y_mux_select.eq(SeqMuxSelect.PC)

                # MTVAL should be zero for non-exceptions, but right now it's just random.
                # X -> MCAUSE, Y -> MEPC, Z -> MTVAL
                m.d.comb += self.save_trap_csrs.eq(1)

        with m.Else():
            # In vectored mode, we calculate the target address with:
            # ((mtvec >> 2) + cause) << 2. This is the same as
            # (mtvec & 0xFFFFFFFC) + 4 * cause, but doesn't require
            # the cause to be shifted before adding.
            # mtvec >> 2
            m.d.comb += self.y_mux_select.eq(SeqMuxSelect.MTVEC_LSR2)
            with m.If(all_true(is_int, self.vec_mode == 1)):
                m.d.comb += [
                    self._mcause_to_csr_num.eq(1),
                    self.csr_to_x.eq(1),
                ]

            m.d.comb += self.load_trap.eq(1)
            m.d.comb += self.next_trap.eq(0)
            m.d.comb += [
                self.alu_op_to_z.eq(AluOp.ADD),
                self.memaddr_mux_select.eq(
                    SeqMuxSelect.Z_LSL2),  # z << 2 -> memaddr, pc
                self.pc_mux_select.eq(SeqMuxSelect.Z_LSL2),
                self.enter_trap.eq(1),
                self.set_instr_complete.eq(1),
            ]
Exemplo n.º 16
0
    def JMP(self, m: Module):
        with m.If(self.mode == ModeBits.EXTENDED.value):
            operand = self.mode_ext(m)

            with m.If(self.cycle == 2):
                self.end_instr(m, operand)

        with m.Elif(self.mode == ModeBits.INDEXED.value):
            operand = self.mode_indexed(m)

            with m.If(self.cycle == 3):
                self.end_instr(m, operand)
Exemplo n.º 17
0
    def elaborate(self, platform):
        i_onoff = self.note_in.i_data.onoff
        i_channel = self.note_in.i_data.channel
        i_note = self.note_in.i_data.note
        i_velocity = self.note_in.i_data.velocity

        o_vn_valid = self.voice_note_out.o_valid
        o_vn_note = self.voice_note_out.o_data.note
        o_vg_valid = self.voice_gate_out.o_valid
        o_vg_gate = self.voice_gate_out.o_data.gate
        o_vg_velocity = self.voice_gate_out.o_data.velocity

        if self.channel is None:
            channel_ok = True
        else:
            channel_ok = i_channel == self.channel

        if self.use_velocity:
            velocity = i_velocity
        else:
            velocity = Const(64)

        m = Module()
        m.d.comb += [
            self.note_in.o_ready.eq(True),
        ]
        with m.If(self.note_in.received()):
            with m.If(channel_ok):
                with m.If(i_onoff):
                    m.d.sync += [
                        o_vn_valid.eq(True),
                        o_vn_note.eq(i_note),
                        o_vg_valid.eq(True),
                        o_vg_gate.eq(True),
                        o_vg_velocity.eq(velocity),
                    ]
                with m.Elif(i_note == o_vn_note):
                    m.d.sync += [
                        o_vg_valid.eq(True),
                        o_vg_gate.eq(False),
                        o_vg_velocity.eq(velocity),
                    ]
        with m.Else():
            with m.If(self.voice_note_out.sent()):
                m.d.sync += [
                    o_vn_valid.eq(False),
                ]
            with m.If(self.voice_gate_out.sent()):
                m.d.sync += [
                    o_vg_valid.eq(False),
                ]
        return m
Exemplo n.º 18
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # receive the valid signal from the previous stage
        # give the stall signal to the previous stage
        if hasattr(self, 'endpoint_a'):
            m.d.comb += [
                self.is_instruction.eq(self.endpoint_a.is_instruction | self.endpoint_a.valid),
                self.valid.eq(self.endpoint_a.valid),
                self.endpoint_a.stall.eq(self.stall)
            ]

        # Add the 'stall' signal from the next stage to the list of stall sources to this stage
        # Generate the local 'kill' signal.
        # Generate the 'stall' (registered) signal
        # 'is_instruction' indicates if the stage was a valid instruction once.
        if hasattr(self, 'endpoint_b'):
            with m.If(self.kill):
                m.d.sync += [
                    self.endpoint_b.valid.eq(0),
                    self.endpoint_b.is_instruction.eq(self.is_instruction)
                ]
            with m.Elif(~self.stall):
                m.d.sync += [
                    self.endpoint_b.valid.eq(self.valid),
                    self.endpoint_b.is_instruction.eq(self.is_instruction)
                ]
            with m.Elif(~self.endpoint_b.stall):
                m.d.sync += [
                    self.endpoint_b.valid.eq(0),
                    self.endpoint_b.is_instruction.eq(0)
                ]

            m.d.comb += self.kill.eq(reduce(or_, self._kill_sources, 0))
            self.add_stall_source(self.endpoint_b.stall)

        m.d.comb += self.stall.eq(reduce(or_, self._stall_sources, 0))

        return m
Exemplo n.º 19
0
    def Start(self, m: Module):
        # Count down bit timer
        m.d.sync += self.count.eq(self.count - 1)

        # Sample signal at middle of bit period
        with m.If(self.count == self.clk_per_bit // 2):
            # Start bit not kept low
            with m.If(self.signal == 1):
                m.next = "IDLE"  # "ERROR"
        # Bit period is complete
        with m.Elif(self.count == 0):
            m.next = "DATA"
            m.d.sync += self.bits.eq(self.bits.reset)
Exemplo n.º 20
0
    def elaborate(self, platform):
        m = Module()

        interface = self.interface
        tokenizer = interface.tokenizer
        tx = interface.tx

        # Counter that stores how many bytes we have left to send.
        bytes_to_send = Signal(range(0, self._max_packet_size + 1), reset=0)

        # True iff we're the active endpoint.
        endpoint_selected = \
            tokenizer.is_in & \
            (tokenizer.endpoint == self._endpoint_number) \

        # Pulses when the host is requesting a packet from us.
        packet_requested = \
            endpoint_selected \
            & tokenizer.ready_for_response

        #
        # Transmit logic
        #

        # Schedule a packet send whenever a packet is requested.
        with m.If(packet_requested):
            m.d.usb += bytes_to_send.eq(self._max_packet_size)

        # Count a byte as send each time the PHY accepts a byte.
        with m.Elif((bytes_to_send != 0) & tx.ready):
            m.d.usb += bytes_to_send.eq(bytes_to_send - 1)

        m.d.comb += [
            # Always send our constant value.
            tx.payload.eq(self._constant),

            # Send bytes, whenever we have them.
            tx.valid.eq(bytes_to_send != 0),
            tx.first.eq(bytes_to_send == self._max_packet_size),
            tx.last.eq(bytes_to_send == 1)
        ]

        #
        # Data-toggle logic
        #

        # Toggle our data pid when we get an ACK.
        with m.If(interface.handshakes_in.ack & endpoint_selected):
            m.d.usb += interface.tx_pid_toggle.eq(~interface.tx_pid_toggle)

        return m
Exemplo n.º 21
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # TODO: Add async FIFOs internally
        # m.submodules.write_fifo = write_fifo = AsyncFIFOBuffered(...)
        # m.submodules.read_fifo = read_fifo = AsyncFIFOBuffered(...)

        m.d.comb += self.ft_data.eq(self.ft_override)

        # Signal defaults
        m.d.comb += self.ft_oe.eq(0)
        m.d.comb += self.ft_write.eq(0)
        m.d.comb += self.ft_read.eq(0)

        with m.FSM():
            with m.State("READY"):
                # If there is data to read, we read it first before entering the write state
                with m.If(self.ft_rxf):
                    m.d.comb += self.ft_oe.eq(1)

                    m.next = "READ"
                with m.Elif(self.ft_txe & self.input_valid):

                    m.next = "WRITE"

            with m.State("READ"):
                m.d.comb += self.ft_oe.eq(1)

                # Connect FIFO, TODO: Add support for IO on the data and be lines
                m.d.comb += self.output_payload.eq(self.ft_data)
                m.d.comb += self.output_valid.eq(self.ft_rxf)
                m.d.comb += self.ft_read.eq(self.output_ready)

                with m.If(~self.ft_rxf):
                    m.next = "READY"

            with m.State("WRITE"):
                m.d.comb += self.ft_be.eq(0b11)

                # Connect FIFO, TODO: Add support for IO on the data and be lines
                m.d.comb += self.ft_data.eq(self.input_payload)
                m.d.comb += self.input_ready.eq(self.ft_txe)
                m.d.comb += self.ft_write.eq(self.input_valid)

                # TODO: Should we go to ready if there is data to read, or wait until write is done?
                with m.If(~self.ft_txe | ~self.input_valid):
                    m.next = "READY"

        return m
Exemplo n.º 22
0
    def elaborate(self, platform: Platform) -> Module:
        m             = Module()

        is_div        = Signal()
        is_divu       = Signal()
        is_rem        = Signal()
        dividend      = Signal(32)
        divisor       = Signal(63)
        quotient      = Signal(32)
        quotient_mask = Signal(32)
        start         = Signal()
        outsign       = Signal()

        m.d.comb += [
            is_div.eq(self.op == Funct3.DIV),
            is_divu.eq(self.op == Funct3.DIVU),
            is_rem.eq(self.op == Funct3.REM)
        ]

        m.d.comb += start.eq(self.start & ~self.busy)

        with m.If(start):
            m.d.sync += [
                dividend.eq(Mux((is_div | is_rem) & self.dat1[-1], -self.dat1, self.dat1)),
                divisor.eq(Mux((is_div | is_rem) & self.dat2[-1], -self.dat2, self.dat2) << 31),
                outsign.eq((is_div & (self.dat1[-1] ^ self.dat2[-1]) & (self.dat2 != 0)) | (is_rem & self.dat1[-1])),
                quotient.eq(0),
                quotient_mask.eq(1 << 31),
                self.busy.eq(1)
            ]
        with m.Elif(quotient_mask == 0 & self.busy):
            m.d.sync += self.busy.eq(0)

            with m.If(is_div | is_divu):
                m.d.sync += self.result.eq(Mux(outsign, -quotient, quotient))
            with m.Else():
                m.d.sync += self.result.eq(Mux(outsign, -dividend, dividend))
        with m.Else():
            with m.If(divisor <= dividend):
                m.d.sync += [
                    dividend.eq(dividend - divisor),
                    quotient.eq(quotient | quotient_mask)
                ]
            m.d.sync += [
                divisor.eq(divisor >> 1),
                quotient_mask.eq(quotient_mask >> 1)
            ]

        return m
Exemplo n.º 23
0
    def elaborate(self, platform):
        bits = self.bits
        bytes = self.bytes

        m = Module()

        frame_count = Signal(7)
        frame_count_next = Signal(7)
        with m.If(bits.multiframe):
            m.d.comb += frame_count_next.eq(0)
        with m.Else():
            m.d.comb += frame_count_next.eq(frame_count + 1)

        m.d.sync += [
            bytes.data_strobe.eq(0),
            bytes.frame_strobe.eq(bits.frame_strobe),
            bytes.multiframe_strobe.eq(bits.multiframe_strobe),
        ]

        bit_count = Signal(3)
        with m.Elif(bits.frame_strobe):
            # First byte in frame is the frame counter and F bit.
            m.d.sync += [
                bytes.data.eq(Cat(bits.data, frame_count_next)),
                bytes.data_strobe.eq(1),
                bit_count.eq(0),
                frame_count.eq(frame_count_next),
            ]
        with m.Elif(bits.data_strobe):
            m.d.sync += [
                bytes.data.eq(Cat(bits.data, bytes.data[1:])),
                bytes.data_strobe.eq(bit_count == 7),
                bit_count.eq(bit_count + 1),
            ]

        return m
Exemplo n.º 24
0
    def elaborate(self, platform):
        m = Module()

        # PLL update
        # Reset the PLLs if asked to.
        with m.If(self.smode1_prst):
            m.d.sync += [
                self.r_hclk.eq(0),
                self.r_vclk.eq(0),

                self.r_hfp.eq(0),
                self.r_hsync.eq(self.synch1_hfp),
                self.r_hbp.eq(self.synch1_hfp + self.synch1_hs),
                self.r_hact.eq(self.synch1_hfp + self.synch1_hs + self.synch1_hbp),
                self.r_hend.eq(720),

                self.r_vfp.eq(0),
                self.r_vsync.eq(self.syncv_vfp + self.syncv_vfpe),
                self.r_vbp.eq(self.syncv_vfp + self.syncv_vfpe + self.syncv_vs),
                self.r_vact.eq(self.syncv_vfp + self.syncv_vfpe + self.syncv_vs + self.syncv_vbp + self.syncv_vbpe),
                self.r_vend.eq(self.syncv_vfp + self.syncv_vfpe + self.syncv_vs + self.syncv_vbp + self.syncv_vbpe + self.syncv_vdp)
            ]

        # Otherwise, update the counters when the PLLs are enabled.
        with m.Elif(self.i_pixclk & self.smode1_sint):
            m.d.sync += self.r_hclk.eq(self.r_hclk + 1)

            with m.If(self.r_hclk == (self.r_hend - 1)):
                m.d.sync += self.r_hclk.eq(0)
                m.d.sync += self.r_vclk.eq(self.r_vclk + 1)

            with m.If(self.r_vclk == (self.r_vend - 1)):
                m.d.sync += self.r_vclk.eq(0)

        m.d.sync += [
            self.d_hfp.eq(self.r_hclk < self.r_hsync),
            self.d_hsync.eq((self.r_hclk >= self.r_hsync) & (self.r_hclk < self.r_hbp)),
            self.d_hbp.eq((self.r_hclk >= self.r_hbp) & (self.r_hclk < self.r_hact)),
            self.d_hblank.eq(self.r_hclk < self.r_hact),

            self.d_vfp.eq(self.r_vclk < self.r_vsync),
            self.d_vsync.eq((self.r_vclk >= self.r_vsync) & (self.r_vclk < self.r_vbp)),
            self.d_vbp.eq((self.r_vclk >= self.r_vbp) & (self.r_vclk < self.r_vact)),
            self.d_vblank.eq(self.r_vclk < self.r_vact)
        ]

        return m
Exemplo n.º 25
0
Arquivo: rmii.py Projeto: ret/daqnet
    def elaborate(self, platform):

        m = Module()

        m.submodules.crc = crc = CRC32()
        m.submodules.mac_match = mac_match = MACAddressMatch(self.mac_addr)
        m.submodules.rxbyte = rxbyte = RMIIRxByte(self.crs_dv, self.rxd0,
                                                  self.rxd1)

        adr = Signal(self.write_port.addr.nbits)

        with m.FSM() as fsm:
            m.d.comb += [
                self.write_port.addr.eq(adr),
                self.write_port.data.eq(rxbyte.data),
                self.write_port.en.eq(rxbyte.data_valid),
                crc.data.eq(rxbyte.data),
                crc.data_valid.eq(rxbyte.data_valid),
                crc.reset.eq(fsm.ongoing("IDLE")),
                mac_match.data.eq(rxbyte.data),
                mac_match.data_valid.eq(rxbyte.data_valid),
                mac_match.reset.eq(fsm.ongoing("IDLE")),
            ]

            # Idle until we see data valid
            with m.State("IDLE"):
                m.d.sync += self.rx_len.eq(0)
                m.d.sync += self.rx_valid.eq(0)
                with m.If(rxbyte.dv):
                    m.d.sync += self.rx_offset.eq(adr)
                    m.next = "DATA"

            # Save incoming data to memory
            with m.State("DATA"):
                with m.If(rxbyte.data_valid):
                    m.d.sync += adr.eq(adr + 1)
                    m.d.sync += self.rx_len.eq(self.rx_len + 1)
                with m.Elif(~rxbyte.dv):
                    m.next = "EOF"

            with m.State("EOF"):
                with m.If(crc.crc_match & mac_match.mac_match):
                    m.d.sync += self.rx_valid.eq(1)
                m.next = "IDLE"

        return m
Exemplo n.º 26
0
    def elaborate(self, platform):
        m  = Module()
        m.submodules.ila = self.ila

        transaction_start = Rose(self.spi.cs)

        # Connect up our SPI transciever to our public interface.
        interface = SPIDeviceInterface(
            word_size=self.bits_per_word,
            clock_polarity=self.clock_polarity,
            clock_phase=self.clock_phase
        )
        m.submodules.spi = interface
        m.d.comb += [
            interface.spi      .connect(self.spi),

            # Always output the captured sample.
            interface.word_out .eq(self.ila.captured_sample)
        ]

        # Count where we are in the current transmission.
        current_sample_number = Signal(range(0, self.ila.sample_depth))

        # Our first piece of data is latched in when the transaction
        # starts, so we'll move on to sample #1.
        with m.If(self.spi.cs):
            with m.If(transaction_start):
                m.d.sync += current_sample_number.eq(1)

            # From then on, we'll move to the next sample whenever we're finished
            # scanning out a word (and thus our current samples are latched in).
            with m.Elif(interface.word_complete):
                m.d.sync += current_sample_number.eq(current_sample_number + 1)

        # Whenever CS is low, we should be providing the very first sample,
        # so reset our sample counter to 0.
        with m.Else():
            m.d.sync += current_sample_number.eq(0)


        # Ensure our ILA module outputs the right sample.
        m.d.sync += [
            self.ila.captured_sample_number .eq(current_sample_number)
        ]

        return m
Exemplo n.º 27
0
    def elaborate(self, platform):
        m = Module()

        crc = Signal(16, reset=self._initial_value)

        # If we're clearing our CRC in progress, move our holding register back to
        # our initial value.
        with m.If(self.clear):
            m.d.ulpi += crc.eq(self._initial_value)

        # Otherwise, update the CRC whenever we have new data.
        with m.Elif(self.valid):
            m.d.ulpi += crc.eq(self._generate_next_crc(crc, self.data))

        m.d.comb += [self.crc.eq(~crc[::-1])]

        return m
Exemplo n.º 28
0
 def elaborate(self, platform):
     counter = Signal(range(-1, self.duration - 1))
     m = Module()
     with m.If(self.i_trg):
         m.d.sync += [
             counter.eq(self.duration - 2),
             self.o_pulse.eq(True),
         ]
     with m.Elif(counter[-1]):
         m.d.sync += [
             self.o_pulse.eq(False),
         ]
     with m.Else():
         m.d.sync += [
             counter.eq(counter - 1),
         ]
     return m
Exemplo n.º 29
0
    def elaborate(self, platform):
        m = Module()

        # pins
        ft_clkout_i = platform.request("ft_clkout_i")
        ft_wr_n_o = platform.request("ft_wr_n_o")
        ft_wr_n_o.o.reset = 1
        ft_txe_n_i = platform.request("ft_txe_n_i")
        ft_suspend_n_i = platform.request("ft_suspend_n_i")
        ft_oe_n_o = platform.request("ft_oe_n_o")
        ft_rd_n_o = platform.request("ft_rd_n_o")
        ft_siwua_n_o = platform.request("ft_siwua_n_o")
        ft_data_io = platform.request("ft_data_io")
        ext1 = platform.request("ext1")
        pa_en_n_o = platform.request("pa_en_n_o")

        # clock domains
        m.domains += ClockDomain("clk60")
        m.d.comb += ClockSignal("clk60").eq(ft_clkout_i.i)

        # signals
        ctr = Signal(8, reset=0)
        ctr_last = Signal(8, reset=0)
        ft_txe_last = Signal(1, reset=0)

        # sync + comb logic
        with m.If(~ft_txe_n_i.i & ft_suspend_n_i.i):
            m.d.clk60 += [ft_wr_n_o.o.eq(0), ctr.eq(ctr + 1), ctr_last.eq(ctr)]
        with m.Elif(ft_txe_n_i.i & ~ft_txe_last):
            m.d.clk60 += [ctr.eq(ctr_last), ft_wr_n_o.o.eq(1)]
        with m.Else():
            m.d.clk60 += [ft_wr_n_o.o.eq(1)]

        m.d.clk60 += [ft_txe_last.eq(ft_txe_n_i.i)]

        m.d.comb += [
            ft_oe_n_o.o.eq(1),
            ft_rd_n_o.o.eq(1),
            ft_siwua_n_o.o.eq(1),
            ft_data_io.o.eq(ctr),
            ft_data_io.oe.eq(1),
            pa_en_n_o.o.eq(1),
        ]

        return m
Exemplo n.º 30
0
    def elaborate(self, platform):
        m = Module()

        pkt_start = Signal()
        pkt_active = Signal()
        pkt_end = Signal()

        with m.FSM(domain="usb_io"):

            for i in range(5):

                with m.State(f"D{i}"):
                    with m.If(self.i_valid):
                        with m.If(self.i_data | self.i_se0):
                            # Receiving '1' or SE0 early resets the packet start counter.
                            m.next = "D0"

                        with m.Else():
                            # Receiving '0' increments the packet start counter.
                            m.next = f"D{i + 1}"

            with m.State("D5"):
                with m.If(self.i_valid):
                    with m.If(self.i_se0):
                        m.next = "D0"
                    # once we get a '1', the packet is active
                    with m.Elif(self.i_data):
                        m.d.comb += pkt_start.eq(1)
                        m.next = "PKT_ACTIVE"

            with m.State("PKT_ACTIVE"):
                m.d.comb += pkt_active.eq(1)
                with m.If(self.i_valid & self.i_se0):
                    m.d.comb += [pkt_active.eq(0), pkt_end.eq(1)]
                    m.next = "D0"

        # pass all of the outputs through a pipe stage
        m.d.comb += [
            self.o_pkt_start.eq(pkt_start),
            self.o_pkt_active.eq(pkt_active),
            self.o_pkt_end.eq(pkt_end),
        ]

        return m