Exemple #1
0
    def elaborate(self, platform):
        # For virtual platforms just use a regular counter
        if platform is None:
            m = Module()

            counter = Signal(2)

            domain = getattr(m.d, self.indomain)
            domain += counter.eq(counter + 1)

            m.domains += ClockDomain(self.outdomain, reset_less=True)
            m.d.comb += ClockSignal(self.outdomain).eq(counter[1])

            return m

        m = Module()

        clkin = Signal()  # Buffered output of input clock, into PLL
        clkfbout = Signal()  # Unbuffered feedback out of PLL
        clkfbout_buf = Signal()  # Buffered feedback into PLL
        clkout = Signal()  # Unbuffered output from PLL
        div4clk = Signal()  # Buffered output of output clock

        m.submodules.clockdiv = Instance("PLLE2_ADV",
                                         p_BANDWIDTH="OPTIMIZED",
                                         p_COMPENSATION="ZHOLD",
                                         p_STARTUP_WAIT="FALSE",
                                         p_DIVCLK_DIVIDE=1,
                                         p_CLKFBOUT_MULT=4,
                                         p_CLKFBOUT_PHASE=0.000,
                                         p_CLKOUT0_DIVIDE=16,
                                         p_CLKOUT0_PHASE=0.000,
                                         p_CLKOUT0_DUTY_CYCLE=0.500,
                                         p_CLKIN1_PERIOD=4.000,
                                         o_CLKFBOUT=clkfbout,
                                         o_CLKOUT0=clkout,
                                         i_CLKFBIN=clkfbout_buf,
                                         i_CLKIN1=clkin,
                                         i_CLKIN2=0,
                                         i_CLKINSEL=1,
                                         i_DADDR=0,
                                         i_DCLK=0,
                                         i_DEN=0,
                                         i_DI=0,
                                         i_DWE=0,
                                         i_PWRDWN=0,
                                         i_RST=0)

        m.submodules.inbuf = Instance("BUFG",
                                      i_I=ClockSignal(self.indomain),
                                      o_O=clkin)

        m.submodules.outbuf = Instance("BUFG", i_I=clkout, o_O=div4clk)

        m.submodules.clockfb = Instance("BUFG", i_I=clkfbout, o_O=clkfbout_buf)

        m.domains += ClockDomain(self.outdomain, reset_less=True)
        m.d.comb += ClockSignal(self.outdomain).eq(div4clk)

        return m
Exemple #2
0
    def elaborate(self, platform):
        m = Module()
        for i, val in enumerate(self._clocks):
            if val is not None:
                clk, freq = val
                unbuf = Signal(name='pl_clk{}_unbuf'.format(i))
                platform.add_clock_constraint(unbuf, freq)

                m.d.comb += unbuf.eq(self._ports[self.CLK][i])
                buf = Instance('BUFG_PS', i_I=unbuf, o_O=clk)
                m.submodules['clk{}_buffer'.format(i)] = buf

        for i, rst in enumerate(self._resets):
            if rst is not None:
                m.d.comb += rst.eq(~self._ports['EMIOGPIOO'][-1 - i])

        for i, irq in enumerate(self._irqs):
            if irq is not None:
                m.d.comb += self._ports[self.IRQ[i // 8]][i % 8].eq(irq)

        ps_i = Instance(
            'PS8',
            a_DONT_TOUCH="true",
            **self._get_instance_ports(),
        )

        m.submodules.ps_i = ps_i
        return m
Exemple #3
0
    def elaborate(self, platform):
        # For virtual platforms just alias the clocks
        if platform is None:
            m = Module()
            m.d.comb += self.clk120.eq(self.clk125)
            return m

        m = Module()

        clkin = Signal()  # Buffered output of input clock, into PLL
        clkfbout = Signal()  # Unbuffered feedback out of PLL
        clkfbout_buf = Signal()  # Buffered feedback into PLL
        clkout = Signal()  # Unbuffered output from PLL

        # VCO = inclk * clkfbout_mult / divclk_divide
        #     = 125MHz * 48 / 5
        #     = 1200MHz
        # out = VCO / CLKOUT0_DIVIDE
        #     = 1200MHz / 10
        #     = 120MHz

        m.submodules.clockdiv = Instance("PLLE2_ADV",
                                         p_BANDWIDTH="LOW",
                                         p_COMPENSATION="BUFIN",
                                         p_STARTUP_WAIT="FALSE",
                                         p_DIVCLK_DIVIDE=5,
                                         p_CLKFBOUT_MULT=48,
                                         p_CLKFBOUT_PHASE=0.000,
                                         p_CLKOUT0_DIVIDE=10,
                                         p_CLKOUT0_PHASE=0.000,
                                         p_CLKOUT0_DUTY_CYCLE=0.500,
                                         p_CLKIN1_PERIOD=8.000,
                                         o_CLKFBOUT=clkfbout,
                                         o_CLKOUT0=clkout,
                                         i_CLKFBIN=clkfbout_buf,
                                         i_CLKIN1=clkin,
                                         i_CLKIN2=0,
                                         i_CLKINSEL=1,
                                         i_DADDR=0,
                                         i_DCLK=0,
                                         i_DEN=0,
                                         i_DI=0,
                                         i_DWE=0,
                                         i_PWRDWN=0,
                                         i_RST=0)

        m.submodules.inbuf = Instance("BUFG", i_I=self.clk125, o_O=clkin)

        m.submodules.outbuf = Instance("BUFG", i_I=clkout, o_O=self.clk120)

        m.submodules.clockfb = Instance("BUFG", i_I=clkfbout, o_O=clkfbout_buf)

        return m
Exemple #4
0
    def elaborate(self, platform):
        m = Module()

        # Create our domains...
        m.domains.usb = ClockDomain()
        m.domains.usb_io = ClockDomain()
        m.domains.fast = ClockDomain()

        # ... and create our 12 MHz USB clock.
        m.submodules.pll = Instance(
            "SB_PLL40_CORE",
            i_REFERENCECLK=ClockSignal("sync"),
            i_RESETB=Const(1),
            i_BYPASS=Const(0),
            o_PLLOUTCORE=ClockSignal("usb"),

            # Create a 24 MHz PLL clock...
            p_FEEDBACK_PATH="SIMPLE",
            p_DIVR=0,
            p_DIVF=15,
            p_DIVQ=5,
            p_FILTER_RANGE=4,

            # ... and divide it by half to get 12 MHz.
            p_PLLOUT_SELECT="GENCLK_HALF")

        # We'll use our 48MHz clock for everything _except_ the usb_io domain...
        m.d.comb += [
            ClockSignal("usb_io").eq(ClockSignal("sync")),
            ClockSignal("fast").eq(ClockSignal("sync"))
        ]

        return m
Exemple #5
0
    def elaborate(self, platform):
        m = Module()

        # Create our domains...
        m.domains.sync = ClockDomain()
        m.domains.usb = ClockDomain()
        m.domains.usb_io = ClockDomain()
        m.domains.fast = ClockDomain()

        # ... create our 48 MHz IO and 12 MHz USB clock...
        m.submodules.pll = Instance(
            "SB_PLL40_2F_CORE",
            i_REFERENCECLK=platform.request(platform.default_clk),
            i_RESETB=Const(1),
            i_BYPASS=Const(0),
            o_PLLOUTCOREA=ClockSignal("sync"),
            o_PLLOUTCOREB=ClockSignal("usb"),

            # Create a 48 MHz PLL clock...
            p_FEEDBACK_PATH="SIMPLE",
            p_PLLOUT_SELECT_PORTA="GENCLK",
            p_PLLOUT_SELECT_PORTB="SHIFTREG_0deg",
            p_DIVR=0,
            p_DIVF=47,
            p_DIVQ=4,
            p_FILTER_RANGE=1,
        )

        # We'll use our 48MHz clock for everything _except_ the usb domain...
        m.d.comb += [
            ClockSignal("usb_io").eq(ClockSignal("sync")),
            ClockSignal("fast").eq(ClockSignal("sync"))
        ]

        return m
Exemple #6
0
def _generate_wide_incrementer(m, platform, adder_input):
    """ Attempts to create an optimal wide-incrementer for counters.

    Yosys on certain platforms (ice40 UltraPlus) doesn't currently use hardware resources
    effectively for wide adders. We'll manually instantiate the relevant resources
    to get rid of an 18-bit carry chain; avoiding a long critical path.

    Parameters:
        platform    -- The platform we're working with.
        adder_input -- The input to our incrementer.
    """

    # If this isn't an iCE40 UltraPlus, let Yosys do its thing.
    if (not platform) or not platform.device.startswith('iCE40UP'):
        return adder_input + 1

    # Otherwise, we'll create a DSP adder itself.
    output = Signal.like(adder_input)
    m.submodules += Instance('SB_MAC16',

        # Hook up our inputs and outputs.
        # A = upper bits of input; B = lower bits of input
        i_A      = adder_input[16:],
        i_B      = adder_input[0:16],
        o_O      = output,

        p_TOPADDSUB_UPPERINPUT =0b1,  # Use as a normal adder
        p_TOPADDSUB_CARRYSELECT=0b11, # Connect our top and bottom adders together.
        p_BOTADDSUB_UPPERINPUT =0b1,  # Use as a normal adder.
        p_BOTADDSUB_CARRYSELECT=0b01  # Always increment.
    )

    return output
    def elaborate(self, platform):
        m = Module()

        # Get the SDRAM pins
        dir_dict = {
            "a": "-",
            "ba": "-",
            "cke": "-",
            "clk": "-",
            "clk_en": "-",
            "dq": "-",
            "dqm": "-",
            "cas": "-",
            "cs": "-",
            "ras": "-",
            "we": "-",
        }

        sdram = platform.request("sdram", dir=dir_dict)

        # Create the controller
        m.submodules.ctrl = ctrl = Sdram()

        m.d.comb += [
            # Set the chip output pins
            sdram.a.eq(ctrl.sd_addr),
            sdram.dqm.eq(ctrl.sd_dqm),
            sdram.ba.eq(ctrl.sd_ba),
            sdram.cs.eq(ctrl.sd_cs),
            sdram.we.eq(ctrl.sd_we),
            sdram.ras.eq(ctrl.sd_ras),
            sdram.cas.eq(ctrl.sd_cas),
            sdram.clk_en.eq(1),
            sdram.clk.eq(ClockSignal("sdram_clk")),
            # Set the controller input pins
            ctrl.init.eq(self.init),
            ctrl.din.eq(self.data_in),
            ctrl.addr.eq(self.address),
            ctrl.we.eq(self.req_write),
            ctrl.oe.eq(self.req_read),
            ctrl.sync.eq(self.sync),
            ctrl.ds.eq(C(0b11, 2)),
            # Set output pins
            self.data_out.eq(ctrl.dout)
        ]

        # Set dq to input or output depending on sd_data_dir
        for i in range(16):
            dq_io = Instance("BB",
                             io_B=sdram.dq[i],
                             i_T=~ctrl.sd_data_dir,
                             i_I=ctrl.sd_data_out[i],
                             o_O=ctrl.sd_data_in[i])

            m.submodules += dq_io
        return m
Exemple #8
0
    def elaborate(self, platform):
        args = {f"p_{key.upper()}": val for (key, val) in self.params.items()}
        for port, (dirn, shape) in self.ports.items():
            if port.lower() in self.ports_used:
                args[f"{dirn}_{port}"] = self.ports_used[port.lower()]
            elif self.defaults and port in self.defaults:
                args[f"{dirn}_{port}"] = self.defaults[port]
            elif port in self.required_ports:
                raise ValueError(f"{self.itype}: Required port {port} missing")

        return Instance(self.itype, **args)
Exemple #9
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()
        for ip_name in self._ips.keys():
            args = getattr(self, ip_name)
            try:
                inst = Instance(ip_name, **args)
                setattr(m.submodules, ip_name, inst)
            except TypeError:
                error(f"couldn't create instance of {ip_name} "
                      f"using args: {args}")

        return m
Exemple #10
0
    def elaborate(self, platform):
        m = Module()
        locked = Signal()

        # Create our domains...
        m.domains.sync   = ClockDomain()
        m.domains.usb    = ClockDomain()
        m.domains.usb_io = ClockDomain()
        m.domains.fast   = ClockDomain()

        # ... create our 48 MHz IO and 12 MHz USB clock...
        clk48  = Signal()
        clk12  = Signal()
        m.submodules.pll = Instance("SB_PLL40_2F_CORE",
            i_REFERENCECLK  = platform.request(platform.default_clk),
            i_RESETB        = Const(1),
            i_BYPASS        = Const(0),

            o_PLLOUTCOREA   = clk48,
            o_PLLOUTCOREB   = clk12,
            o_LOCK          = locked,

            # Create a 48 MHz PLL clock...
            p_FEEDBACK_PATH = "SIMPLE",
            p_PLLOUT_SELECT_PORTA = "GENCLK",
            p_PLLOUT_SELECT_PORTB = "SHIFTREG_0deg",
            p_DIVR          = 0,
            p_DIVF          = 47,
            p_DIVQ          = 4,
            p_FILTER_RANGE  = 1,
        )

        # ... and constrain them to their new frequencies.
        platform.add_clock_constraint(clk48, 48e6)
        platform.add_clock_constraint(clk12, 12e6)

        # We'll use our 48MHz clock for everything _except_ the usb domain...
        m.d.comb += [
            ClockSignal("usb")     .eq(clk12),
            ClockSignal("sync")    .eq(clk48),
            ClockSignal("usb_io")  .eq(clk48),
            ClockSignal("fast")    .eq(clk48),

            ResetSignal("usb")     .eq(~locked),
            ResetSignal("sync")    .eq(~locked),
            ResetSignal("usb_io")  .eq(~locked),
            ResetSignal("fast")    .eq(~locked)
        ]

        return m
Exemple #11
0
    def elaborate(self, platform):
        m = Module()
        m.submodules.demoaxi_i = Instance(
            'demoaxi',
	        p_C_S_AXI_DATA_WIDTH=self.data_w,
	        p_C_S_AXI_ADDR_WIDTH=self.addr_w,
            i_S_AXI_ACLK=ClockSignal(self.domain),
            i_S_AXI_ARESETN=~ResetSignal(self.domain),
            **get_ports_for_instance(self.axilite, prefix='S_AXI_'),
        )

        if isinstance(platform, Platform):
            for d in self.DEPENDENCIES:
                add_verilog_file(platform, d)
        return m
    def elaborate(self, platform):
        m = Module()
        import os
        dir_path = os.path.dirname(os.path.realpath(__file__))
        with open(dir_path + "/sdram_controller.v") as f:
            platform.add_file("sdram_controller.v", f.read())

        dir_dict = {
            "a": "-",
            "ba": "-",
            "cke": "-",
            "clk": "-",
            "clk_en": "-",
            "dq": "-",
            "dqm": "-",
            "cas": "-",
            "cs": "-",
            "ras": "-",
            "we": "-",
        }

        sdram = platform.request("sdram", dir=dir_dict)

        m.submodules += Instance(
            "sdram_controller",
            i_CLOCK_50=ClockSignal("compute"),
            i_CLOCK_100=ClockSignal("sdram"),
            i_CLOCK_100_del_3ns=ClockSignal("sdram_180_deg"),
            i_rst=ResetSignal("sdram"),
            i_address=self.address,
            i_req_read=self.req_read,
            i_req_write=self.req_write,
            i_data_in=self.data_in,
            o_data_out=self.data_out,
            o_data_valid=self.data_valid,
            o_write_complete=self.write_complete,
            o_DRAM_ADDR=sdram.a,
            o_DRAM_BA=sdram.ba,
            o_DRAM_CKE=sdram.clk_en,
            o_DRAM_CLK=sdram.clk,
            io_DRAM_DQ=sdram.dq,
            o_DRAM_DQM=sdram.dqm,
            o_DRAM_CAS_N=sdram.cas,
            o_DRAM_CS_N=sdram.cs,
            o_DRAM_RAS_N=sdram.ras,
            o_DRAM_WE_N=sdram.we)

        return m
Exemple #13
0
    def elaborate(self, platform):
        m = Module()
        locked = Signal()

        # Create our domains...
        m.domains.sync = ClockDomain()
        m.domains.pol = ClockDomain()

        # clocks 50 MHz circuit
        #         1 MHz update frequency motor
        clk50 = Signal()
        # clk1 = Signal()
        # details see iCE40 sysCLOCK PLL Design and Usage
        # settings comment out are for SB_PLL40_2F_CORE
        m.submodules.pll = \
            Instance("SB_PLL40_CORE",
                     i_REFERENCECLK=platform.request(platform.default_clk),
                     i_RESETB=Const(1),
                     # i_BYPASS=Const(0),
                     o_PLLOUTGLOBAL=clk50,
                     o_LOCK=locked,
                     # Create a 50 MHz PLL clock...
                     p_FEEDBACK_PATH="SIMPLE",
                     # internally generated PLL
                     # p_PLLOUT_SELECT_PORTA="GENCLK",
                     # p_PLLOUT_SELECT_PORTB="SHIFTREG_0deg",
                     p_DIVR=0,
                     p_DIVF=7,
                     p_DIVQ=4,
                     p_FILTER_RANGE=5,
                     )

        # ... and constrain them to their new frequencies.
        platform.add_clock_constraint(clk50, 50e6)
        # platform.add_clock_constraint(clk1, 1e6)

        # We'll use our 50MHz clock for everything _except_ the polynomal
        # which create ticks for the motors
        m.d.comb += [
            # ClockSignal("pol").eq(clk1),
            ClockSignal("sync").eq(clk50),
            # ResetSignal("pol").eq(~locked),
            ResetSignal("sync").eq(~locked),
        ]

        return m
Exemple #14
0
    def elaborate(self, platform):
        m = Module()

        # Create our domains...
        m.domains.sync = ClockDomain()
        m.domains.usb = ClockDomain()
        m.domains.usb_io = ClockDomain()
        m.domains.fast = ClockDomain()

        # ... ensure our clock is never instantiated with a Global buffer.
        platform.lookup(platform.default_clk).attrs['GLOBAL'] = False

        # ... create our 48 MHz IO and 12 MHz USB clocks...
        clk48 = Signal()
        clk12 = Signal()
        m.submodules.pll = Instance(
            "SB_PLL40_2F_PAD",
            i_PACKAGEPIN=platform.request(platform.default_clk, dir="i"),
            i_RESETB=Const(1),
            i_BYPASS=Const(0),
            o_PLLOUTGLOBALA=clk48,
            o_PLLOUTGLOBALB=clk12,

            # Create a 48 MHz PLL clock...
            p_FEEDBACK_PATH="SIMPLE",
            p_PLLOUT_SELECT_PORTA="GENCLK",
            p_PLLOUT_SELECT_PORTB="SHIFTREG_0deg",
            p_DIVR=0,
            p_DIVF=63,
            p_DIVQ=4,
            p_FILTER_RANGE=1,
        )

        # ... and constrain them to their new frequencies.
        platform.add_clock_constraint(clk48, 48e6)
        platform.add_clock_constraint(clk12, 12e6)

        # We'll use our 48MHz clock for everything _except_ the usb domain...
        m.d.comb += [
            ClockSignal("usb_io").eq(clk48),
            ClockSignal("fast").eq(clk48),
            ClockSignal("sync").eq(clk48),
            ClockSignal("usb").eq(clk12)
        ]

        return m
Exemple #15
0
def delay(m, signal, interval, *, out=None):
    """ Creates a delayed copy of a given I/O signal.

    Currently only works at the FPGA's I/O boundary, and only on ECP5s.

    Parameters:
        signal -- The signal to be delayed. Must be either an I/O
                  signal connected directly to a platform resource.
        delay  -- Delay, in arbitrary units. These units will vary
                  from unit to unit, but seem to be around 300ps on
                  most ECP5 FPGAs. On ECP5s, maxes out at 127.
        out    -- The signal to received the delayed signal; or
                  None ot have a signal created for you.

    Returns:
        delayed -- The delayed signal. Will be equivalent to 'out'
                   if provided; or a new signal otherwise.
    """

    # If we're not being passed our output signal, create one.
    if out is None:
        out = Signal.like(signal)

    # If we have more than one signal, call this function on each
    # of the subsignals.
    if len(signal) > 1:

        # If we have a vector of signals, but a integer delay,
        # convert that integer to a vector of same-valued delays.
        if isinstance(interval, int):
            interval = [interval] * len(signal)

        return Cat(
            delay(m, s, d, out=o) for s, d, o in zip(signal, interval, out))

    #
    # Base case: create a delayed version of the relevant signal.
    #
    m.submodules += Instance("DELAYG",
                             i_A=signal,
                             o_Z=out,
                             p_DEL_VALUE=interval)

    return out
Exemple #16
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()
        instance_args = {}

        for internal_name, ports in _group_by_internal_name(self._ports):
            # Ports must be groupped to allow connecting
            # multiple ports into one, wider port
            #
            # ext_name1[7:6] ---\
            # ext_name2[5:4] ----*-- internal_name[7:0]
            # [fillers]      ---/
            # ext_name3[1:0] ---/

            # Ports must be sorted.
            # The order of concatentation is : Cat(a,b,c) == cba
            ports_sorted = sorted(ports, key=lambda p: p.bounds[2])
            prefix = port_direction_to_prefix(ports_sorted[0].direction)

            # fill the empty slices in the list with Signals
            # the list is iterated starting from last position
            # in order not to change indices
            # or mess up when en alement is inserted
            for i in range(len(ports_sorted) - 2, -1, -1):
                port1 = ports_sorted[i]
                port2 = ports_sorted[i + 1]
                if (isinstance(port1, WrapperPort)
                        and isinstance(port2, WrapperPort)):
                    diff = port2.bounds[3] - port1.bounds[2] - 1
                    if diff > 0:
                        ports_sorted = (ports_sorted[:i + 1] + [Signal(diff)] +
                                        ports_sorted[i + 1:])

            diff = ports_sorted[0].bounds[3]
            # insert signal in front, if the first doesn't start from 0
            if diff > 0:
                ports_sorted = [Signal(diff)] + ports_sorted

            instance_args[prefix + internal_name] = Cat(*ports_sorted)

        instance_args = {**instance_args, **self._parameters}

        m.submodules.ip = Instance(self.ip_name, **instance_args)
        return m
Exemple #17
0
    def elaborate(self, platform):
        m = Module()

        if platform is not None:
            # platform.default_clk_frequency is in Hz
            coeff = self._calc_freq_coefficients(
                platform.default_clk_frequency / 1_000_000, self.freq_out)
            # clk_pin = platform.request(platform.default_clk)

            lock = Signal()

            pll = Instance(
                "SB_PLL40_CORE",
                p_FEEDBACK_PATH='SIMPLE',
                p_DIVR=coeff.divr,
                p_DIVF=coeff.divf,
                p_DIVQ=coeff.divq,
                p_FILTER_RANGE=0b001,
                p_DELAY_ADJUSTMENT_MODE_FEEDBACK='FIXED',
                p_FDA_FEEDBACK=0b0000,
                p_DELAY_ADJUSTMENT_MODE_RELATIVE='FIXED',
                p_FDA_RELATIVE=0b0000,
                p_SHIFTREG_DIV_MODE=0b00,
                p_PLLOUT_SELECT='GENCLK',
                p_ENABLE_ICEGATE=0b0,
                i_REFERENCECLK=ClockSignal(),
                o_PLLOUTCORE=ClockSignal(self.domain_name),
                i_RESETB=ResetSignal(),
                i_BYPASS=Const(0),
                o_LOCK=lock,
            )
            rs = ResetSynchronizer(~lock, domain=self.domain_name)

            m.submodules += [pll, rs]

        m.domains += ClockDomain(self.domain_name)

        return m
Exemple #18
0
    def elaborate(self, platform):
        m = Module()

        # Get the ECP5 block that's responsible for driving the MCLK pin,
        # and drive it using our SCK line.
        user_mclk = Instance('USRMCLK', i_USRMCLKI=self.sck, i_USRMCLKTS=0)
        m.submodules += user_mclk

        # Connect up each of our other signals.
        m.d.comb += [
            self.bus.sdi   .eq(self.sdi),
            self.sdo       .eq(self.bus.sdo)
        ]

        if self.use_cs:
            m.d.comb += [
                self.bus.cs.o.eq(self.cs),
                self.bus.cs.oe.eq(1)
            ]
        else:
            m.d.comb += self.bus.cs.oe.eq(0)

        return m
Exemple #19
0
    def elaborate(self, platform):
        m = Module()

        # Create our clock domains.
        m.domains.fast = ClockDomain()
        m.domains.sync = ClockDomain()
        m.domains.usb = ClockDomain()
        m.domains.clkref = ClockDomain()

        # Grab our clock and global reset signals.
        clk_16m384 = platform.request(platform.default_clk)
        # reset      = platform.request(platform.default_rst)

        # Generate the clocks we need for our PLL.
        feedback = Signal()
        locked = Signal()

        m.submodules.pll = Instance(
            "EHXPLLL",
            i_CLKI=clk_16m384,
            o_CLKOP=ClockSignal("fast"),
            o_CLKOS=ClockSignal("sync"),

            # Status.
            o_LOCK=locked,
            i_CLKFB=ClockSignal("fast"),

            # Control signals.
            i_RST=0,
            i_STDBY=0,
            # i_CLKINTFB         = 0,
            i_PHASESEL0=0,
            i_PHASESEL1=0,
            i_PHASEDIR=1,
            i_PHASESTEP=1,
            i_PHASELOADREG=1,
            i_PLLWAKESYNC=0,
            i_ENCLKOP=0,
            i_ENCLKOS=0,
            i_ENCLKOS2=0,
            i_ENCLKOS3=0,
            p_PLLRST_ENA="DISABLED",
            p_INTFB_WAKE="DISABLED",
            p_STDBY_ENABLE="DISABLED",
            p_DPHASE_SOURCE="DISABLED",
            p_CLKI_DIV=1,
            p_CLKOP_ENABLE="ENABLED",
            p_CLKOP_DIV=4,
            p_CLKOP_CPHASE=1,
            p_CLKOP_FPHASE=0,
            # p_CLKOP_TRIM_DELAY = 0,
            # p_CLKOP_TRIM_POL   = "FALLING",
            p_CLKOS_ENABLE="ENABLED",
            p_CLKOS_DIV=8,
            p_CLKOS_CPHASE=1,
            p_CLKOS_FPHASE=0,
            # p_CLKOS_TRIM_DELAY = 0,
            # p_CLKOS_TRIM_POL   = "FALLING",
            p_FEEDBK_PATH="CLKOP",
            p_CLKFB_DIV=12,
            p_CLKOS3_FPHASE=0,
            p_CLKOS3_CPHASE=0,
            p_CLKOS2_FPHASE=0,
            p_CLKOS2_CPHASE=0,
            p_PLL_LOCK_MODE=0,
            p_OUTDIVIDER_MUXD="DIVD",
            p_CLKOS3_ENABLE="DISABLED",
            p_OUTDIVIDER_MUXC="DIVC",
            p_CLKOS2_ENABLE="DISABLED",
            p_OUTDIVIDER_MUXB="DIVB",
            p_OUTDIVIDER_MUXA="DIVA",
            p_CLKOS3_DIV=1,
            p_CLKOS2_DIV=1,

            # Synthesis attributes.
            a_FREQUENCY_PIN_CLKI="16.384000",
            a_FREQUENCY_PIN_CLKOP="196.608000",
            a_FREQUENCY_PIN_CLKOS="98.304000",
            a_ICP_CURRENT="12",
            a_LPF_RESISTOR="8",
            a_MFG_ENABLE_FILTEROPAMP="1",
            a_MFG_GMCREF_SEL="2",
        )

        m.d.comb += [
            ClockSignal("clkref").eq(clk_16m384),
            ResetSignal("sync").eq(~locked),
            ResetSignal("fast").eq(~locked),
            # ResetSignal("framer").eq(0),
        ]

        return m
Exemple #20
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_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")
        adc_d_i = platform.request("adc_d_i")
        adc_oe_o = platform.request("adc_oe_o")
        adc_shdn_o = platform.request("adc_shdn_o")
        ext1 = platform.request("ext1")
        pa_en_n_o = platform.request("pa_en_n_o")
        mix_en_n_o = platform.request("mix_en_n_o")

        # signals
        clk80 = Signal()
        pll_fb = Signal()
        chan_a = Signal(self.ADC_WIDTH)
        chan_b = Signal(self.ADC_WIDTH)
        lsb = Signal()
        lock = Signal(RAW_STATE)
        sample_ctr = Signal(range(self.DECIMATE * self.FFT_LEN))
        sample_ctr_max = Const(self.DECIMATE * self.FFT_LEN - 1)
        cons_done = Signal()
        cons_done_clk80_dom = Signal()
        send_start = Signal()
        send_stop = Signal()
        wait_prod = Signal()
        lock_ftclk_dom = Signal()
        lock_ftclk_dom_last = Signal()

        # clock domains
        clk40_neg = ClockDomain("clk40_neg", clk_edge="neg")
        m.domains.clk40_neg = clk40_neg
        m.d.comb += ClockSignal("clk40_neg").eq(ClockSignal("sync"))

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

        # ======================== submodules ========================
        # PLL
        m.submodules += Instance(
            "PLLE2_BASE",
            ("p", "CLKFBOUT_MULT", 24),
            ("p", "DIVCLK_DIVIDE", 1),
            ("p", "CLKOUT0_DIVIDE", 12),
            ("p", "CLKIN1_PERIOD", 25),
            ("o", "CLKOUT0", clk80),
            ("i", "CLKIN1", ClockSignal("sync")),
            ("i", "RST", 0),
            ("o", "CLKFBOUT", pll_fb),
            ("i", "CLKFBIN", pll_fb),
        )

        # ADC
        m.submodules.ltc2292 = ltc2292 = LTC2292(
            posedge_domain="sync", negedge_domain="clk40_neg"
        )
        m.d.comb += [
            ltc2292.di.eq(adc_d_i.i),
            chan_a.eq(ltc2292.dao),
            chan_b.eq(ltc2292.dbo),
        ]

        # FIFO
        m.submodules.fifo = fifo = AsyncFIFO(
            width=self.USB_WIDTH,
            depth=self.DECIMATE * self.FFT_LEN * 2,
            r_domain="clk60",
            w_domain="clk80",
        )
        with m.If(lsb):
            m.d.comb += fifo.w_data.eq(chan_a[: self.USB_WIDTH])
        with m.Else():
            m.d.comb += fifo.w_data.eq(
                Cat(
                    chan_a[self.USB_WIDTH :],
                    Const(0, 2 * self.USB_WIDTH - self.ADC_WIDTH),
                )
            )

        # consumption done sync
        m.submodules.cons_done_sync = cons_done_sync = FFSynchronizer(
            i=cons_done, o=cons_done_clk80_dom, o_domain="clk80"
        )

        # lock synch
        m.submodules.lock_sync = lock_sync = FFSynchronizer(
            i=lock, o=lock_ftclk_dom, o_domain="clk60"
        )

        # =========================== logic ==========================
        m.d.comb += [
            pa_en_n_o.o.eq(1),
            mix_en_n_o.o.eq(1),
            adc_oe_o.o.eq(0b01),
            adc_shdn_o.o.eq(0b00),
            ext1.o[0].eq(0b0),
            ext1.o[3].eq(lock),
            ext1.o[1].eq(0b0),
            ext1.o[4].eq(fifo.r_en),
            ext1.o[2].eq(0b0),
            ext1.o[5].eq(fifo.w_en),
        ]

        # write clock domain
        with m.If(lock == RAW_STATE.PROD):
            with m.If(sample_ctr == sample_ctr_max):
                m.d.clk80 += [
                    lock.eq(RAW_STATE.CONS),
                    sample_ctr.eq(0),
                    lsb.eq(0),
                ]
            with m.Else():
                with m.If(lsb):
                    m.d.clk80 += sample_ctr.eq(sample_ctr + 1)
                m.d.clk80 += lsb.eq(~lsb)
        with m.Else():
            with m.If(cons_done_clk80_dom):
                m.d.clk80 += [
                    lock.eq(RAW_STATE.PROD),
                    sample_ctr.eq(0),
                    lsb.eq(0),
                ]

        with m.Switch(lock):
            with m.Case(RAW_STATE.PROD):
                m.d.comb += fifo.w_en.eq(1)
            with m.Case(RAW_STATE.CONS):
                m.d.comb += fifo.w_en.eq(0)

        # read clock domain
        m.d.clk60 += lock_ftclk_dom_last.eq(lock_ftclk_dom)
        with m.If(lock_ftclk_dom == RAW_STATE.CONS & ~wait_prod):
            with m.If(~fifo.r_rdy):
                m.d.clk60 += wait_prod.eq(1)
        with m.Elif(lock_ftclk_dom == RAW_STATE.CONS):
            m.d.clk60 += wait_prod.eq(1)
        with m.Else():
            m.d.clk60 += wait_prod.eq(0)

        m.d.comb += [
            ft_oe_n_o.o.eq(1),
            ft_rd_n_o.o.eq(1),
            ft_siwua_n_o.o.eq(1),
        ]
        with m.Switch(lock_ftclk_dom):
            with m.Case(RAW_STATE.PROD):
                m.d.comb += [
                    send_start.eq(0),
                    send_stop.eq(0),
                    ft_data_io.o.eq(0),
                    ft_wr_n_o.o.eq(1),
                    fifo.r_en.eq(0),
                ]
            with m.Case(RAW_STATE.CONS):
                with m.If(lock_ftclk_dom_last == RAW_STATE.PROD):
                    m.d.comb += send_start.eq(1)
                with m.Else():
                    m.d.comb += send_start.eq(0)

                with m.If(~fifo.r_rdy):
                    m.d.comb += [send_stop.eq(1), cons_done.eq(1)]
                with m.Else():
                    m.d.comb += [send_stop.eq(0), cons_done.eq(0)]

                with m.If(send_start):
                    m.d.comb += [
                        ft_data_io.o.eq(self.START_FLAG),
                        ft_wr_n_o.o.eq(ft_txe_n_i.i),
                        fifo.r_en.eq(1),
                    ]
                with m.Elif(send_stop):
                    m.d.comb += [
                        ft_data_io.o.eq(self.STOP_FLAG),
                        ft_wr_n_o.o.eq(ft_txe_n_i.i),
                        fifo.r_en.eq(0),
                    ]
                with m.Else():
                    with m.If(wait_prod):
                        m.d.comb += [
                            ft_data_io.o.eq(0),
                            ft_wr_n_o.o.eq(1),
                            fifo.r_en.eq(0),
                        ]
                    with m.Else():
                        m.d.comb += [
                            ft_data_io.o.eq(fifo.r_data),
                            ft_wr_n_o.o.eq(~(~ft_txe_n_i.i & fifo.r_en)),
                            fifo.r_en.eq(~ft_txe_n_i.i & fifo.r_rdy),
                        ]

        return m
    def elaborate(self, platform):
        m = Module()

        # Create clock out signals
        self.clk = {cfg.cd_name: Signal() for cfg in self.clock_config}
        self._pll_lock = Signal()

        # Create our clock domains.
        for cfg in self.clock_config:
            m.domains += ClockDomain(cfg.cd_name)
            m.d.comb += ClockSignal(domain=cfg.cd_name).eq(
                self.clk[cfg.cd_name])
            m.d.comb += ResetSignal(cfg.cd_name).eq(~self._pll_lock),

        # Grab our input clock
        clock_name = self.clock_name if self.clock_name else platform.default_clk

        try:
            self.clkin_frequency = platform.lookup(
                clock_name).clock.frequency / 1e6
            input_clock_pin = platform.request(clock_name)
        except:
            input_clock_pin = ClockSignal(clock_name)
            # TODO: Make this nicer, remove clock_signal_freq
            self.clkin_frequency = self.clock_signal_freq / 1e6

        # Calculate configuration parameters
        params = self.calc_pll_params(self.clkin_frequency,
                                      self.clock_config[0].freq)
        if len(self.clock_config) > 1:
            self.generate_secondary_output(params, 0,
                                           self.clock_config[1].freq,
                                           self.clock_config[1].phase)
        if len(self.clock_config) > 2:
            self.generate_secondary_output(params, 1,
                                           self.clock_config[2].freq,
                                           self.clock_config[2].phase)
        if len(self.clock_config) > 3:
            self.generate_secondary_output(params, 2,
                                           self.clock_config[3].freq,
                                           self.clock_config[3].phase)

        for i, p in enumerate([
                params, params["secondary"][0], params["secondary"][1],
                params["secondary"][2]
        ]):
            if p["error"] > 0:
                logger.warning(
                    "ClockDomain {} has an error of {:.3f} MHz ({} instead of {})"
                    .format(self.clock_config[i].cd_name, p["error"],
                            p["freq"], p["freq_requested"]))
                if not self.skip_checks:
                    assert (p["error"] <= self.clock_config[i].error)

        m.submodules.pll = Instance(
            "EHXPLLL",
            # Clock in.
            i_CLKI=input_clock_pin,

            # Generated clock outputs.
            o_CLKOP=self.clk[self.clock_config[0].cd_name],
            o_CLKOS=self.clk[self.clock_config[1].cd_name]
            if len(self.clock_config) > 1 else Signal(),
            o_CLKOS2=self.clk[self.clock_config[2].cd_name]
            if len(self.clock_config) > 2 else Signal(),
            o_CLKOS3=self.clk[self.clock_config[3].cd_name]
            if len(self.clock_config) > 3 else Signal(),

            # Status.
            o_LOCK=self._pll_lock,

            # PLL parameters...
            p_PLLRST_ENA="DISABLED",
            p_INTFB_WAKE="DISABLED",
            p_STDBY_ENABLE="DISABLED",
            p_DPHASE_SOURCE="DISABLED",
            p_OUTDIVIDER_MUXA="DIVA",
            p_OUTDIVIDER_MUXB="DIVB",
            p_OUTDIVIDER_MUXC="DIVC",
            p_OUTDIVIDER_MUXD="DIVD",
            p_CLKI_DIV=params["refclk_div"],
            p_CLKOP_ENABLE="ENABLED",
            p_CLKOP_DIV=params["output_div"],
            p_CLKOP_CPHASE=params["primary_cphase"],
            p_CLKOP_FPHASE=0,
            p_CLKOS_ENABLE="ENABLED"
            if params["secondary"][0]["enabled"] else "DISABLED",
            p_CLKOS_FPHASE=params["secondary"][0]["fphase"],
            p_CLKOS_CPHASE=params["secondary"][0]["cphase"],
            p_CLKOS_DIV=params["secondary"][0]["div"],
            p_CLKOS2_ENABLE="ENABLED"
            if params["secondary"][1]["enabled"] else "DISABLED",
            p_CLKOS2_FPHASE=params["secondary"][1]["fphase"],
            p_CLKOS2_CPHASE=params["secondary"][1]["cphase"],
            p_CLKOS2_DIV=params["secondary"][1]["div"],
            p_CLKOS3_ENABLE="ENABLED"
            if params["secondary"][2]["enabled"] else "DISABLED",
            p_CLKOS3_FPHASE=params["secondary"][2]["fphase"],
            p_CLKOS3_CPHASE=params["secondary"][2]["cphase"],
            p_CLKOS3_DIV=params["secondary"][2]["div"],
            p_FEEDBK_PATH="CLKOP",  # TODO: external feedback
            p_CLKFB_DIV=params["feedback_div"],

            # Internal feedback.
            i_CLKFB=self.clk[self.clock_config[0].cd_name],

            # TODO: Reset
            i_RST=0,

            # TODO: Standby
            i_STDBY=0,

            # TODO: Dynamic mode
            i_PHASESEL0=0,
            i_PHASESEL1=0,
            i_PHASEDIR=0,
            i_PHASESTEP=0,
            i_PHASELOADREG=0,
            i_PLLWAKESYNC=0,

            # Output Enables.
            i_ENCLKOP=0,
            i_ENCLKOS=0,
            i_ENCLKOS2=0,
            i_ENCLKOS3=0,

            # Synthesis attributes.
            a_FREQUENCY_PIN_CLKI=str(self.clkin_frequency),
            a_FREQUENCY_PIN_CLKOP=str(self.clock_config[0].freq),
            a_FREQUENCY_PIN_CLKOS=str(self.clock_config[1].freq)
            if len(self.clock_config) > 1 else "0",
            a_FREQUENCY_PIN_CLKOS2=str(self.clock_config[2].freq)
            if len(self.clock_config) > 2 else "0",
            a_FREQUENCY_PIN_CLKOS3=str(self.clock_config[3].freq)
            if len(self.clock_config) > 3 else "0",
            a_ICP_CURRENT="12",
            a_LPF_RESISTOR="8",
            a_MFG_ENABLE_FILTEROPAMP="1",
            a_MFG_GMCREF_SEL="2",
        )
        return m
Exemple #22
0
    def elaborate(self, platform):
        m = Module()

        # Grab our default input clock.
        input_clock = platform.request(platform.default_clk, dir="i")

        # Create our domains; but don't do anything else for them, for now.
        m.domains.sync = ClockDomain()
        m.domains.usb = ClockDomain()
        m.domains.usb_io = ClockDomain()
        m.domains.fast = ClockDomain()

        m.submodules.pll = Instance(
            "EHXPLLL",

            # Clock in.
            i_CLKI=input_clock,

            # Generated clock outputs.
            o_CLKOP=ClockSignal("sync"),
            o_CLKOS=ClockSignal("usb"),

            # Status.
            #o_LOCK=self._pll_lock,

            # PLL parameters...
            p_PLLRST_ENA="DISABLED",
            p_INTFB_WAKE="DISABLED",
            p_STDBY_ENABLE="DISABLED",
            p_DPHASE_SOURCE="DISABLED",
            p_CLKOS3_FPHASE=0,
            p_CLKOS3_CPHASE=0,
            p_CLKOS2_FPHASE=0,
            p_CLKOS2_CPHASE=7,
            p_CLKOS_FPHASE=0,
            p_CLKOS_CPHASE=5,
            p_CLKOP_FPHASE=0,
            p_CLKOP_CPHASE=5,
            p_PLL_LOCK_MODE=0,
            p_CLKOS_TRIM_DELAY="0",
            p_CLKOS_TRIM_POL="FALLING",
            p_CLKOP_TRIM_DELAY="0",
            p_CLKOP_TRIM_POL="FALLING",
            p_OUTDIVIDER_MUXD="DIVD",
            p_CLKOS3_ENABLE="DISABLED",
            p_OUTDIVIDER_MUXC="DIVC",
            p_CLKOS2_ENABLE="DISABLED",
            p_OUTDIVIDER_MUXB="DIVB",
            p_CLKOS_ENABLE="ENABLED",
            p_OUTDIVIDER_MUXA="DIVA",
            p_CLKOP_ENABLE="ENABLED",
            p_CLKOS3_DIV=1,
            p_CLKOS2_DIV=8,
            p_CLKOS_DIV=48,
            p_CLKOP_DIV=12,
            p_CLKFB_DIV=1,
            p_CLKI_DIV=1,
            p_FEEDBK_PATH="CLKOP",

            # Internal feedback.
            i_CLKFB=ClockSignal("sync"),

            # Control signals.
            i_RST=0,
            i_PHASESEL0=0,
            i_PHASESEL1=0,
            i_PHASEDIR=1,
            i_PHASESTEP=1,
            i_PHASELOADREG=1,
            i_STDBY=0,
            i_PLLWAKESYNC=0,

            # Output Enables.
            i_ENCLKOP=0,
            i_ENCLKOS=0,
            i_ENCLKOS2=0,
            i_ENCLKOS3=0,

            # Synthesis attributes.
            a_FREQUENCY_PIN_CLKI="48.000000",
            a_FREQUENCY_PIN_CLKOS="48.000000",
            a_FREQUENCY_PIN_CLKOP="12.000000",
            a_ICP_CURRENT="12",
            a_LPF_RESISTOR="8")

        # We'll use our 48MHz clock for everything _except_ the usb domain...
        m.d.comb += [
            ClockSignal("usb_io").eq(ClockSignal("sync")),
            ClockSignal("fast").eq(ClockSignal("sync"))
        ]

        return m
 def elaborate(self, platform):
     m = Instance("OSCH",
                  p_NOM_FREQ=self._freq_str,
                  i_STDBY=Const(0),
                  o_OSC=self.out)
     return m
Exemple #24
0
    def create_submodules(self, m, platform):

        self._pll_lock = Signal()

        # Figure out our platform's clock frequencies -- grab the platform's
        # defaults, and then override any with our local, caller-provided copies.
        new_clock_frequencies = platform.DEFAULT_CLOCK_FREQUENCIES_MHZ.copy()
        if self.clock_frequencies:
            new_clock_frequencies.update(self.clock_frequencies)
        self.clock_frequencies = new_clock_frequencies

        # Use the provided clock name for our input; or the default clock
        # if no name was provided.
        clock_name = self.clock_name if self.clock_name else platform.default_clk

        # Create absolute-frequency copies of our PLL outputs.
        # We'll use the generate_ methods below to select which domains
        # apply to which components.
        self._clk_240MHz = Signal()
        self._clk_120MHz = Signal()
        self._clk_60MHz = Signal()
        self._clock_options = {
            60: self._clk_60MHz,
            120: self._clk_120MHz,
            240: self._clk_240MHz
        }

        # Grab our input clock
        # For debugging: if our clock name is "OSCG", allow using the internal
        # oscillator. This is mostly useful for debugging.
        if clock_name == "OSCG":
            logging.warning(
                "Using FPGA-internal oscillator for an approximately 62MHz.")
            logging.warning("USB communication won't work for f_OSC != 60MHz.")

            input_clock = Signal()
            m.submodules += Instance("OSCG",
                                     p_DIV=self.OSCG_DIV,
                                     o_OSC=input_clock)
        else:
            input_clock = platform.request(clock_name)

        # Instantiate the ECP5 PLL.
        # These constants generated by Clarity Designer; which will
        # ideally be replaced by an open-source component.
        # (see https://github.com/SymbiFlow/prjtrellis/issues/34.)
        m.submodules.pll = Instance(
            "EHXPLLL",

            # Clock in.
            i_CLKI=input_clock,

            # Generated clock outputs.
            o_CLKOP=self._clk_240MHz,
            o_CLKOS=self._clk_120MHz,
            o_CLKOS2=self._clk_60MHz,

            # Status.
            o_LOCK=self._pll_lock,

            # PLL parameters...
            p_PLLRST_ENA="DISABLED",
            p_INTFB_WAKE="DISABLED",
            p_STDBY_ENABLE="DISABLED",
            p_DPHASE_SOURCE="DISABLED",
            p_CLKOS3_FPHASE=0,
            p_CLKOS3_CPHASE=0,
            p_CLKOS2_FPHASE=0,
            p_CLKOS2_CPHASE=7,
            p_CLKOS_FPHASE=0,
            p_CLKOS_CPHASE=3,
            p_CLKOP_FPHASE=0,
            p_CLKOP_CPHASE=1,
            p_PLL_LOCK_MODE=0,
            p_CLKOS_TRIM_DELAY="0",
            p_CLKOS_TRIM_POL="FALLING",
            p_CLKOP_TRIM_DELAY="0",
            p_CLKOP_TRIM_POL="FALLING",
            p_OUTDIVIDER_MUXD="DIVD",
            p_CLKOS3_ENABLE="DISABLED",
            p_OUTDIVIDER_MUXC="DIVC",
            p_CLKOS2_ENABLE="ENABLED",
            p_OUTDIVIDER_MUXB="DIVB",
            p_CLKOS_ENABLE="ENABLED",
            p_OUTDIVIDER_MUXA="DIVA",
            p_CLKOP_ENABLE="ENABLED",
            p_CLKOS3_DIV=1,
            p_CLKOS2_DIV=8,
            p_CLKOS_DIV=4,
            p_CLKOP_DIV=2,
            p_CLKFB_DIV=4,
            p_CLKI_DIV=1,
            p_FEEDBK_PATH="CLKOP",

            # Internal feedback.
            i_CLKFB=self._clk_240MHz,

            # Control signals.
            i_RST=0,
            i_PHASESEL0=0,
            i_PHASESEL1=0,
            i_PHASEDIR=0,
            i_PHASESTEP=0,
            i_PHASELOADREG=0,
            i_STDBY=0,
            i_PLLWAKESYNC=0,

            # Output Enables.
            i_ENCLKOP=0,
            i_ENCLKOS=0,
            i_ENCLKOS2=0,
            i_ENCLKOS3=0,

            # Synthesis attributes.
            a_FREQUENCY_PIN_CLKI="60.000000",
            a_FREQUENCY_PIN_CLKOS2="60.000000",
            a_FREQUENCY_PIN_CLKOS="120.000000",
            a_FREQUENCY_PIN_CLKOP="240.000000",
            a_ICP_CURRENT="9",
            a_LPF_RESISTOR="8")

        # Set up our global resets so the system is kept fully in reset until
        # our core PLL is fully stable. This prevents us from internally clock
        # glitching ourselves before our PLL is locked. :)
        m.d.comb += [
            ResetSignal("sync").eq(~self._pll_lock),
            ResetSignal("fast").eq(~self._pll_lock),
        ]
Exemple #25
0
    def elaborate(self, platform):
        if platform is not None:
            platform.add_file("picorv32.v", open("picorv32.v", "r"))

        if not os.path.exists("build"):
            os.makedirs("build")

        subprocess.run(
            [
                "cargo", "objcopy", "--release", "--", "-O", "binary",
                "../build/app.bin"
            ],
            cwd="app",
        ).check_returncode()

        with open("build/app.bin", "rb") as f:
            b = bytearray(f.read())
            b.extend([0] * (4 - (len(b) % 4)))
            app = np.frombuffer(b, dtype='<u4').tolist()

        # MEM_SIZE = 256 # words
        RAM_SIZE = 256  # words
        init = ([0] * RAM_SIZE) + app
        MEM_SIZE = len(init)

        mem = Memory(
            width=32,
            depth=MEM_SIZE,
            init=init,
        )

        resetn = Signal()
        mem_valid = Signal()
        mem_ready = Signal()
        mem_addr = Signal(32)
        mem_wdata = Signal(32)
        mem_wstrb = Signal(4)
        mem_rdata = Signal(32)

        m = Module()

        m.d.comb += resetn.eq(~ResetSignal())

        m.submodules.picorv32 = Instance(
            "picorv32",
            p_ENABLE_COUNTERS=0,
            p_LATCHED_MEM_RDATA=1,
            p_TWO_STAGE_SHIFT=0,
            p_TWO_CYCLE_ALU=1,
            p_CATCH_MISALIGN=0,
            p_CATCH_ILLINSN=0,
            p_COMPRESSED_ISA=1,
            p_ENABLE_MUL=1,
            p_PROGADDR_RESET=1024,
            p_PROGADDR_IRQ=1024 + 0x10,
            i_clk=ClockSignal(),
            i_resetn=resetn,
            o_mem_valid=mem_valid,
            i_mem_ready=mem_ready,
            o_mem_addr=mem_addr,
            o_mem_wdata=mem_wdata,
            o_mem_wstrb=mem_wstrb,
            i_mem_rdata=mem_rdata,
        )
        m.submodules.read_port = read_port = mem.read_port(transparent=False)
        m.submodules.write_port = write_port = mem.write_port(granularity=8)

        m.d.sync += mem_ready.eq(0)

        m.d.comb += [
            read_port.addr.eq(mem_addr >> 2),
            mem_rdata.eq(read_port.data),
            read_port.en.eq((~mem_wstrb).bool()),
            write_port.addr.eq(mem_addr >> 2),
            write_port.data.eq(mem_wdata),
            write_port.en.eq(mem_wstrb),
        ]

        with m.If(resetn & mem_valid & ~mem_ready):
            with m.If((mem_addr >> 2) < MEM_SIZE):
                m.d.sync += mem_ready.eq(1)

            for mapping in self.memory_mappings:
                if mapping.writing_enabled:
                    with m.If(mem_wstrb.bool() & (mem_addr == mapping.addr)):
                        if mapping.write is not None:
                            mapping.write(m, mem_wdata)
                        else:
                            m.d.sync += [
                                mapping.signal.eq(mem_wdata),
                                mem_ready.eq(1),
                            ]
                if mapping.read:
                    with m.If((~mem_wstrb).bool()
                              & (mem_addr == mapping.addr)):
                        m.d.comb += mem_rdata.eq(mapping.signal)
                        m.d.sync += mem_ready.eq(1)
                if not mapping.read and not (mapping.write
                                             or mapping.writing_enabled):
                    print(mapping.addr)
                    print("mapping doesn't specify read or write",
                          file=sys.stderr)

        return m