def elaborate(self, platform): m = Module() shifter = Signal(self._width) pos = Signal(self._width, reset=0b1) with m.If(self.i_enable): empty = Signal() m.d.usb += [ pos.eq(pos >> 1), shifter.eq(shifter >> 1), self.o_get.eq(empty), ] with m.If(empty): m.d.usb += [ shifter.eq(self.i_data), pos.eq(1 << (self._width - 1)), ] with m.If(self.i_clear): m.d.usb += [shifter.eq(0), pos.eq(1)] m.d.comb += [ empty.eq(pos[0]), self.o_empty.eq(empty), self.o_data.eq(shifter[0]), ] return m
def elab(self, m: Module): buffering = Signal() # True if there is a value being buffered buffered_value = Signal.like(Value.cast(self.input.payload)) # Pipe valid and ready back and forth m.d.comb += [ self.input.ready.eq(~buffering | self.output.ready), self.output.valid.eq(buffering | self.input.valid), self.output.payload.eq( Mux(buffering, buffered_value, self.input.payload)) ] # Buffer when have incoming value but cannot output just now with m.If(~buffering & ~self.output.ready & self.input.valid): m.d.sync += buffering.eq(True) m.d.sync += buffered_value.eq(self.input.payload) # Handle cases when transfering out from buffer with m.If(buffering & self.output.ready): with m.If(self.input.valid): m.d.sync += buffered_value.eq(self.input.payload) with m.Else(): m.d.sync += buffering.eq(False) # Reset all state with m.If(self.reset): m.d.sync += buffering.eq(False) m.d.sync += buffered_value.eq(0)
def elaborate(self, platform): m = Module() with m.If(self.pending.w_stb): m.d.sync += self.pending.r_data.eq(self.pending.r_data & ~self.pending.w_data) with m.If(self.enable.w_stb): m.d.sync += self.enable.r_data.eq(self.enable.w_data) for i, event in enumerate(self._events): m.d.sync += self.status.r_data[i].eq(event.stb) if event.mode in ("rise", "fall"): event_stb_r = Signal.like(event.stb, name_suffix="_r") m.d.sync += event_stb_r.eq(event.stb) event_trigger = Signal(name="{}_trigger".format(event.name)) if event.mode == "level": m.d.comb += event_trigger.eq(event.stb) elif event.mode == "rise": m.d.comb += event_trigger.eq(~event_stb_r & event.stb) elif event.mode == "fall": m.d.comb += event_trigger.eq(event_stb_r & ~event.stb) else: assert False # :nocov: with m.If(event_trigger): m.d.sync += self.pending.r_data[i].eq(1) m.d.comb += self.irq.eq( (self.pending.r_data & self.enable.r_data).any()) return m
def instantiate_dut(self): m = Module() # Create a module that only has our stretched strobe signal. m.strobe_in = Signal() m.stretched_strobe = stretch_strobe_signal(m, m.strobe_in, to_cycles=2) return m
def elaborate(self, platform): m = Module() for k in reversed(range(self.width)): with m.If(self.i[k]): m.d.comb += self.o.eq(k) m.d.comb += self.none.eq(self.i == 0) # no requests return m
def elaborate(self, platform): m = Module() with m.If(self.op): m.d.comb += self.y.eq(self.a + self.b) with m.Else(): m.d.comb += self.y.eq(self.a - self.b) return m
def elaborate(self, platform): m = Module() interface = self.interface setup = self.interface.setup # # Class request handlers. # with m.If(setup.type == USBRequestType.CLASS): with m.Switch(setup.request): # SET_LINE_CODING: The host attempts to tell us how it wants serial data # encoding. Since we output a stream, we'll ignore the actual line coding. with m.Case(self.SET_LINE_CODING): # Always ACK the data out... with m.If(interface.rx_ready_for_response): m.d.comb += interface.handshakes_out.ack.eq(1) # ... and accept whatever the request was. with m.If(interface.status_requested): m.d.comb += self.send_zlp() with m.Case(): # # Stall unhandled requests. # with m.If(interface.status_requested | interface.data_requested): m.d.comb += interface.handshakes_out.stall.eq(1) return m
def elaborate(self, platform): m = Module() # # Our module has three core parts: # - an encoder, which converts from our one-hot signal to a mux select line # - a multiplexer, which handles multiplexing e.g. payload signals # - a set of OR'ing logic, which joints together our simple or'd signals # Create our encoder... m.submodules.encoder = encoder = Encoder(len(self._inputs)) for index, interface in enumerate(self._inputs): # ... and tie its inputs to each of our 'valid' signals. valid_signal = getattr(interface, self._valid_field) m.d.comb += encoder.i[index].eq(valid_signal) # Create our multiplexer, and drive each of our output signals from it. with m.Switch(encoder.o): for index, interface in enumerate(self._inputs): # If an interface is selected... with m.Case(index): for identifier in self._mux_signals: # ... connect all of its muxed signals through to the output. output_signal = self._get_signal(self.output, identifier) input_signal = self._get_signal(interface, identifier) m.d.comb += output_signal.eq(input_signal) # Create the OR'ing logic for each of or or_signals. for identifier in self._or_signals: # Figure out the signals we want to work with... output_signal = self._get_signal(self.output, identifier) input_signals = (self._get_signal(i, identifier) for i in self._inputs) # ... and OR them together. or_reduced = functools.reduce(operator.__or__, input_signals, 0) m.d.comb += output_signal.eq(or_reduced) # Finally, pass each of our pass-back signals from the output interface # back to each of our input interfaces. for identifier in self._pass_signals: output_signal = self._get_signal(self.output, identifier) for interface in self._inputs: input_signal = self._get_signal(interface, identifier) m.d.comb += input_signal.eq(output_signal) return m
def test_synth_realcase(): m = Module() m.submodules.axi2axil = axi2axil = Axi2AxiLite(32, 16, 5) m.submodules.xbar = xbar = AxiLiteXBar(32, 16) slaves = [DemoAxi(32, 16) for _ in range(5)] for i, s in enumerate(slaves): m.submodules['slave_' + str(i)] = s xbar.add_slave(s.axilite, 0x1000 * i, 0x1000) xbar.add_master(axi2axil.axilite) ports = list(axi2axil.axi.fields.values()) synth(m, ports)
def elaborate(self, platform): m = Module() m.submodules.bridge = self._bridge # Grab our LEDS... leds = Cat(platform.request("led", i) for i in range(6)) # ... and update them on each register write. with m.If(self._output.w_stb): m.d.sync += leds.eq(self._output.w_data) return m
def elaborate(self, platform): m = Module() m.submodules.bridge = self._bridge # Core connection register. m.d.comb += self.connect.eq(self._connect.r_data) with m.If(self._connect.w_stb): m.d.usb += self._connect.r_data.eq(self._connect.w_data) # Reset-detection event. m.d.comb += self._reset_irq.stb.eq(self.bus_reset) return m
def elaborate(self, platform): m = Module() last_data = Signal() with m.If(self.i_valid): m.d.usb_io += [ last_data.eq(self.i_dk), self.o_data.eq(~(self.i_dk ^ last_data)), self.o_se0.eq((~self.i_dj) & (~self.i_dk)), ] m.d.usb_io += self.o_valid.eq(self.i_valid), return m
def elaborate(self, platform): m = Module() if self.own_register_window: m.submodules.reg_window = self.register_window # Add the registers that represent each of our signals. self.populate_ulpi_registers(m) # Generate logic to handle changes on each of our registers. first_element = True for address, signals in self._register_signals.items(): conditional = m.If if first_element else m.Elif first_element = False # If we're requesting a write on the given register, pass that to our # register window. with conditional(signals['write_requested']): # Keep track of when we'll be okay to start a write: # it's when there's a write request, we're not complete. # and the bus is idle. We'll use this below. request_write = \ signals['write_requested'] & \ ~self.register_window.done & \ self.bus_idle m.d.comb += [ # Control signals. signals['write_done'] .eq(self.register_window.done), # Register window signals. self.register_window.address .eq(address), self.register_window.write_data .eq(signals['write_value']), self.register_window.write_request .eq(request_write), # Status signals ] m.d.usb += self.busy.eq(request_write | self.register_window.busy) # If no register accesses are active, provide default signal values. with m.Else(): m.d.comb += self.register_window.write_request.eq(0) m.d.usb += self.busy.eq(self.register_window.busy) # Ensure our register window is never performing a read. m.d.comb += self.register_window.read_request.eq(0) return m
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
def elaborate(self, platform): m = Module() # If we have an opportunity to stall... with m.If(self.interface.data_requested | self.interface.status_requested): # ... and our stall condition is met ... with m.If(self.condition(self.interface.setup)): # ... do so. m.d.comb += self.interface.handshakes_out.stall.eq(1) return m
def elaborate(self, platform): m = Module() # Create a set of registers, and expose them over SPI. board_spi = platform.request("debug_spi") spi_registers = SPIRegisterInterface(default_read_value=-1) m.submodules.spi_registers = spi_registers # Identify ourselves as the SPI flash bridge. spi_registers.add_read_only_register(REGISTER_ID, read=0x53504946) # # SPI flash passthrough connections. # flash_sdo = Signal() spi_flash_bus = platform.request('spi_flash') spi_flash_passthrough = ECP5ConfigurationFlashInterface( bus=spi_flash_bus) m.submodules += spi_flash_passthrough m.d.comb += [ spi_flash_passthrough.sck.eq(board_spi.sck), spi_flash_passthrough.sdi.eq(board_spi.sdi), flash_sdo.eq(spi_flash_passthrough.sdo), ] # # Structural connections. # spi = synchronize(m, board_spi) # Select the passthrough or gateware SPI based on our chip-select values. gateware_sdo = Signal() with m.If(board_spi.cs): m.d.comb += board_spi.sdo.eq(gateware_sdo) with m.Else(): m.d.comb += board_spi.sdo.eq(flash_sdo) # Connect our register interface to our board SPI. m.d.comb += [ spi_registers.spi.sck.eq(spi.sck), spi_registers.spi.sdi.eq(spi.sdi), gateware_sdo.eq(spi_registers.spi.sdo), spi_registers.spi.cs.eq(spi.cs) ] return m
def elaborate(self, platform): m = Module() # An RxCmd is present when three conditions are met: # - We're not actively undergoing a register read. # - Direction has been high for more than one cycle. # - NXT is low. # To implement the first condition, we'll first create a delayed # version of DIR, and then logically AND it with the current value. direction_delayed = Signal() m.d.usb += direction_delayed.eq(self.ulpi.dir) receiving = Signal() m.d.comb += receiving.eq(direction_delayed & self.ulpi.dir) # Default our strobes to 0, unless asserted. m.d.usb += [ self.rx_start .eq(0), self.rx_stop .eq(0) ] # Sample the DATA lines whenever these conditions are met. with m.If(receiving & ~self.ulpi.nxt & ~self.register_operation_in_progress): m.d.usb += self.last_rx_command.eq(self.ulpi.data.i) # If RxActive has just changed, strobe the start or stop signals, rx_active = self.ulpi.data.i[4] with m.If(~self.rx_active & rx_active): m.d.usb += self.rx_start.eq(1) with m.If(self.rx_active & ~rx_active): m.d.usb += self.rx_stop.eq(1) # Break the most recent RxCmd into its UTMI-equivalent signals. # From table 3.8.1.2 in the ULPI spec; rev 1.1/Oct-20-2004. m.d.comb += [ self.line_state .eq(self.last_rx_command[0:2]), self.vbus_valid .eq(self.last_rx_command[2:4] == 0b11), self.session_valid .eq(self.last_rx_command[2:4] == 0b10), self.session_end .eq(self.last_rx_command[2:4] == 0b00), self.rx_active .eq(self.last_rx_command[4]), self.rx_error .eq(self.last_rx_command[4:6] == 0b11), self.host_disconnect .eq(self.last_rx_command[4:6] == 0b10), self.id_digital .eq(self.last_rx_command[6]), ] return m
def elaborate(self, platform): m = Module() m.submodules.soc = self.soc # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator( clock_frequencies=CLOCK_FREQUENCIES_MHZ) # Connect up our UART. uart_io = platform.request("uart", 0) m.d.comb += [ uart_io.tx.eq(self.uart_pins.tx), self.uart_pins.rx.eq(uart_io.rx) ] if hasattr(uart_io.tx, 'oe'): m.d.comb += uart_io.tx.oe.eq(~self.soc.uart._phy.tx.rdy), # Create our USB device. ulpi = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=ulpi) # Connect up our device controller. m.d.comb += self.usb_device_controller.attach(usb) # Add our eptri endpoint handlers. usb.add_endpoint(self.usb_setup) usb.add_endpoint(self.usb_in_ep) usb.add_endpoint(self.usb_out_ep) return m
def elaborate(self, platform): m = Module() # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator() # Create our USB device interface... bus = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=bus) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() usb.add_standard_control_endpoint(descriptors) # Connect our device as a high speed device by default. m.d.comb += [ usb.connect.eq(1), usb.full_speed_only.eq(1 if os.getenv('LUNA_FULL_ONLY') else 0), ] # ... and for now, attach our LEDs to our most recent control request. m.d.comb += [ platform.request_optional('led', 0, default=NullPin()).o.eq( usb.tx_activity_led), platform.request_optional('led', 1, default=NullPin()).o.eq( usb.rx_activity_led), platform.request_optional('led', 2, default=NullPin()).o.eq(usb.suspended), ] return m
def elaborate(self, platform): """ Generate the Blinky tester. """ m = Module() # Grab our I/O connectors. leds = [ platform.request_optional("led", i, default=NullPin()).o for i in range(0, 8) ] user_io = [ platform.request_optional("user_io", i, default=NullPin()).o for i in range(0, 8) ] # Clock divider / counter. counter = Signal(28) m.d.sync += counter.eq(counter + 1) # Attach the LEDs and User I/O to the MSBs of our counter. m.d.comb += Cat(leds).eq(counter[-7:-1]) m.d.comb += Cat(user_io).eq(counter[7:21]) # Return our elaborated module. return m
def elaborate(self, platform): m = Module() # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator() # Create our USB device interface... ulpi = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=ulpi) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() usb.add_standard_control_endpoint(descriptors) # Add a stream endpoint to our device. iso_ep = USBIsochronousInEndpoint( endpoint_number=self.ISO_ENDPOINT_NUMBER, max_packet_size=self.MAX_ISO_PACKET_SIZE) usb.add_endpoint(iso_ep) # We'll tie our address directly to our value, ensuring that we always # count as each offset is increased. m.d.comb += [ iso_ep.bytes_in_frame.eq(self.MAX_ISO_PACKET_SIZE * 3), iso_ep.value.eq(iso_ep.address) ] # Connect our device as a high speed device by default. m.d.comb += [ usb.connect.eq(1), usb.full_speed_only.eq(1 if os.getenv('LUNA_FULL_ONLY') else 0), ] return m
def elaborate(self, platform): m = Module() m.submodules.soc = self.soc # Check for our prerequisites before building. if not os.path.exists("eptri_example.bin"): logging.error( "Firmware binary not found -- you may want to build this with `make program`." ) sys.exit(-1) # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator( clock_frequencies=CLOCK_FREQUENCIES_MHZ) # Connect up our UART. uart_io = platform.request("uart", 0) m.d.comb += [ uart_io.tx.eq(self.uart_pins.tx), self.uart_pins.rx.eq(uart_io.rx) ] # Create our USB device. ulpi = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=ulpi) # Connect up our device controller. m.d.comb += self.controller.attach(usb) # Add our eptri endpoint handlers. usb.add_endpoint(self.setup) usb.add_endpoint(self.in_ep) usb.add_endpoint(self.out_ep) return m
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
def elaborate(self, platform): m = Module() m.submodules += self.ila # Generate our clock domains. clocking = LunaECP5DomainGenerator(clock_frequencies=CLOCK_FREQUENCIES) m.submodules.clocking = clocking # Clock divider / counter. m.d.fast += self.counter.eq(self.counter + 1) # Set our ILA to trigger each time the counter is at a random value. # This shows off our example a bit better than counting at zero. m.d.comb += self.ila.trigger.eq(self.counter == 7) # Grab our I/O connectors. leds = [platform.request("led", i, dir="o") for i in range(0, 6)] spi_bus = synchronize(m, platform.request('debug_spi'), o_domain='fast') # Attach the LEDs and User I/O to the MSBs of our counter. m.d.comb += Cat(leds).eq(self.counter[-7:-1]) # Connect our ILA up to our board's aux SPI. m.d.comb += self.ila.spi.connect(spi_bus) # Return our elaborated module. return m
def elaborate(self, platform): m = Module() m.submodules += Instance( "jt51", i_clk=self.clk, i_rst=self.rst, i_cen=self.cen, i_cen_p1=self.cen_p1, i_cs_n=self.cs_n, i_wr_n=self.wr_n, i_a0=self.a0, i_din=self.din, o_dout=self.dout, o_ct1=self.ct1, o_ct2=self.ct2, o_irq_n=self.irq_n, o_sample=self.sample, o_left=self.left, o_right=self.right, o_xleft=self.xleft, o_xright=self.xright, o_dacleft=self.dacleft, o_dacright=self.dacright, ) return m
def elaborate(self, platform): m = Module() # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator() # Create our USB device interface... ulpi = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=ulpi) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() usb.add_standard_control_endpoint(descriptors) # Add our endpoint. test_ep = StressTestEndpoint(endpoint_number=BULK_ENDPOINT_NUMBER, max_packet_size=MAX_BULK_PACKET_SIZE, constant=CONSTANT_TO_SEND) usb.add_endpoint(test_ep) # Connect our device as a high speed device by default. m.d.comb += [ usb.connect.eq(1), usb.full_speed_only.eq(1 if os.getenv('LUNA_FULL_ONLY') else 0), ] return m
def elaborate(self, platform): m = Module() # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator() # Create the 32-bit counter we'll be using as our status signal. counter = Signal(32) m.d.usb += counter.eq(counter + 1) # Create our USB device interface... ulpi = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=ulpi) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() usb.add_standard_control_endpoint(descriptors) # Create an interrupt endpoint which will carry the value of our counter to the host # each time our interrupt EP is polled. status_ep = USBSignalInEndpoint(width=32, endpoint_number=1, endianness="big") usb.add_endpoint(status_ep) m.d.comb += status_ep.signal.eq(counter) # Connect our device as a high speed device by default. m.d.comb += [ usb.connect.eq(1), usb.full_speed_only.eq(1 if os.getenv('LUNA_FULL_ONLY') else 0), ] return m
def elaborate(self, platform): m = Module() # Make the output `rollover` always equal to this comparison, # which will only be 1 for a single cycle every counter period. m.d.comb += self.rollover.eq(self.counter == self.limit - 1) # Conditionally reset the counter to 0 on rollover, otherwise # increment it. We could write the comparison out again here # to the same effect. with m.If(self.rollover): m.d.sync += self.counter.eq(0) with m.Else(): m.d.sync += self.counter.eq(self.counter + 1) return m
def elaborate(self, platform): m = Module() # Create our clock domains. m.domains.fast = self.fast = ClockDomain() m.domains.sync = self.sync = ClockDomain() m.domains.usb = self.usb = ClockDomain() # Call the hook that will create any submodules necessary for all clocks. self.create_submodules(m, platform) # Generate and connect up our clocks. m.d.comb += [ self.clk_usb.eq(self.generate_usb_clock(m, platform)), self.clk_sync.eq(self.generate_sync_clock(m, platform)), self.clk_fast.eq(self.generate_fast_clock(m, platform)), ClockSignal(domain="fast").eq(self.clk_fast), ClockSignal(domain="sync").eq(self.clk_sync), ClockSignal(domain="usb").eq(self.clk_usb), ] # Call the hook that will connect up our reset signals. self.create_usb_reset(m, platform) return m
def elaborate(self, platform): m = Module() interface = self.interface # Create our transfer manager, which will be used to sequence packet transfers for our stream. m.submodules.tx_manager = tx_manager = USBInTransferManager( self._max_packet_size) m.d.comb += [ # Always generate ZLPs; in order to pass along when stream packets terminate. tx_manager.generate_zlps.eq(1), # We want to handle packets only that target our endpoint number. tx_manager.active.eq( interface.tokenizer.endpoint == self._endpoint_number), # Connect up our transfer manager to our input stream... tx_manager.transfer_stream.stream_eq(self.stream), # ... and our output stream... interface.tx.stream_eq(tx_manager.packet_stream), interface.tx_pid_toggle.eq(tx_manager.data_pid), # ... and connect through our token/handshake signals. interface.tokenizer.connect(tx_manager.tokenizer), tx_manager.handshakes_out.connect(interface.handshakes_out), interface.handshakes_in.connect(tx_manager.handshakes_in) ] return m