def elaborate(self, platform): m = Module() board_spi = platform.request("debug_spi") # Create a set of registers, and expose them over SPI. spi_registers = SPIRegisterInterface( default_read_value=0x4C554E41) #default read = u'LUNA' m.submodules.spi_registers = spi_registers # Fill in some example registers. # (Register 0 is reserved for size autonegotiation). spi_registers.add_read_only_register(1, read=0xc001cafe) led_reg = spi_registers.add_register(2, size=6, name="leds") spi_registers.add_read_only_register(3, read=0xdeadbeef) # ... and tie our LED register to our LEDs. led_out = Cat( [platform.request("led", i, dir="o") for i in range(0, 6)]) m.d.comb += led_out.eq(led_reg) # Connect up our synchronized copies of the SPI registers. spi = synchronize(m, board_spi) m.d.comb += spi_registers.spi.connect(spi) 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("target_phy") 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. stream_ep = USBStreamOutEndpoint( endpoint_number=self.BULK_ENDPOINT_NUMBER, max_packet_size=self.MAX_BULK_PACKET_SIZE, buffer_size=self.MAX_BULK_PACKET_SIZE) usb.add_endpoint(stream_ep) leds = Cat(platform.request("led", i) for i in range(6)) user_io = Cat( platform.request("user_io", i, dir="o") for i in range(4)) # Always stream our USB data directly onto our User I/O and LEDS. with m.If(stream_ep.stream.valid): m.d.usb += [ leds.eq(stream_ep.stream.payload), user_io.eq(stream_ep.stream.payload), ] # Always accept data as it comes in. m.d.comb += stream_ep.stream.ready.eq(1) # 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.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() interface = self.interface setup = self.interface.setup # Grab a reference to the board's LEDs. leds = Cat(platform.request("led", i) for i in range(6)) # # Vendor request handlers. # with m.If(setup.type == USBRequestType.VENDOR): with m.Switch(setup.request): # SET_LEDS request handler: handler that sets the board's LEDS # to a user provided value with m.Case(self.REQUEST_SET_LEDS): # If we have an active data byte, splat it onto the LEDs. # # For simplicity of this example, we'll accept any byte in # the packet; and not just the first one; each byte will # cause an update. This is fun; we can PWM the LEDs with # USB packets. :) with m.If(interface.rx.valid & interface.rx.next): m.d.usb += leds.eq(interface.rx.payload) # Once the receive is complete, respond with an ACK. with m.If(interface.rx_ready_for_response): m.d.comb += interface.handshakes_out.ack.eq(1) # If we reach the status stage, send a ZLP. 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() uart = platform.request("uart") clock_freq = int(60e6) char_freq = int(6e6) # Create our UART transmitter. transmitter = UARTTransmitter(divisor=int(clock_freq // 115200)) m.submodules.transmitter = transmitter stream = transmitter.stream # Create a counter that will let us transmit ten times per second. counter = Signal(range(0, char_freq)) with m.If(counter == (char_freq - 1)): m.d.sync += counter.eq(0) with m.Else(): m.d.sync += counter.eq(counter + 1) # Create a simple ROM with a message for ourselves... letters = Array(ord(i) for i in "Hello, world! \r\n") # ... and count through it whenever we send a letter. current_letter = Signal(range(0, len(letters))) with m.If(stream.ready): m.d.sync += current_letter.eq(current_letter + 1) # Hook everything up. m.d.comb += [ stream.payload .eq(letters[current_letter]), stream.valid .eq(counter == 0), uart.tx.o .eq(transmitter.tx), ] # If this platform has an output-enable control on its UART, drive it iff # we're actively driving a transmission. if hasattr(uart.tx, 'oe'): m.d.comb += uart.tx.oe.eq(transmitter.driving), # Turn on a single LED, just to show something's running. led = Cat(platform.request('led', i) for i in range(6)) m.d.comb += led.eq(~transmitter.tx) return m
def elaborate(self, platform): m = Module() board_spi = platform.request("debug_spi") # Create a set of registers, and expose them over SPI. spi_registers = SPIRegisterInterface( default_read_value=0x4C554E41) #default read = u'LUNA' m.submodules.spi_registers = spi_registers # Fill in some example registers. # (Register 0 is reserved for size autonegotiation). spi_registers.add_read_only_register(1, read=0xc001cafe) led_reg = spi_registers.add_register(2, size=6, name="leds") spi_registers.add_read_only_register(3, read=0xdeadbeef) # ... and tie our LED register to our LEDs. led_out = Cat( [platform.request("led", i, dir="o") for i in range(0, 6)]) m.d.comb += led_out.eq(led_reg) # # Structural connections. # sck = Signal() sdi = Signal() sdo = Signal() cs = Signal() # # Synchronize each of our I/O SPI signals, where necessary. # m.submodules += FFSynchronizer(board_spi.sck, sck) m.submodules += FFSynchronizer(board_spi.sdi, sdi) m.submodules += FFSynchronizer(board_spi.cs, cs) m.d.comb += board_spi.sdo.eq(sdo) # Connect our register interface to our board SPI. m.d.comb += [ spi_registers.sck.eq(sck), spi_registers.sdi.eq(sdi), sdo.eq(spi_registers.sdo), spi_registers.cs.eq(cs) ] return m
def elaborate(self, platform): m = Module() # Generate our domain clocks/resets. m.submodules.car = LunaECP5DomainGenerator() # Create our USB device interface... ulpi = platform.request("target_phy") m.submodules.usb = usb = USBDevice(bus=ulpi) # Connect our device by default. m.d.comb += usb.connect.eq(1) # ... and for now, attach our LEDs to our most recent control request. leds = Cat(platform.request("led", i) for i in range(6)) m.d.comb += leds.eq(usb.last_request) return m
def elaborate(self, platform): m = Module() uart = platform.request("uart") clock_freq = int(60e6) char_freq = int(6e6) # Create our UART transmitter. transmitter = UARTTransmitter(divisor=int(clock_freq // 115200)) m.submodules.transmitter = transmitter # Create a counter that will let us transmit ten times per second. counter = Signal(range(0, char_freq)) with m.If(counter == (char_freq - 1)): m.d.sync += counter.eq(0) with m.Else(): m.d.sync += counter.eq(counter + 1) # Create a simple ROM with a message for ourselves... letters = Array(ord(i) for i in "Hello, world! \r\n") # ... and count through it whenever we send a letter. current_letter = Signal(range(0, len(letters))) with m.If(transmitter.accepted): m.d.sync += current_letter.eq(current_letter + 1) # Hook everything up. m.d.comb += [ transmitter.data.eq(letters[current_letter]), transmitter.send.eq(counter == 0), uart.tx.eq(transmitter.tx) ] # Turn on a single LED, just to show something's running. led = Cat(platform.request('led', i) for i in range(6)) m.d.comb += led.eq(~transmitter.tx) return m
def elaborate(self, platform): m = Module() clk_60MHz = platform.request(platform.default_clk) # Drive the sync clock domain with our main clock. m.domains.sync = ClockDomain() m.d.comb += ClockSignal().eq(clk_60MHz) # 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 # Simple applet ID register. spi_registers.add_read_only_register(REGISTER_ID, read=0x54455354) # LED test register. led_reg = spi_registers.add_register(REGISTER_LEDS, size=6, name="leds", reset=0b10) led_out = Cat( [platform.request("led", i, dir="o") for i in range(0, 6)]) m.d.comb += led_out.eq(led_reg) # # Target power test register. # Note: these values assume you've populated the correct AP22814 for # your revision (AP22814As for rev0.2+, and AP22814Bs for rev0.1). # bits [1:0]: 0 = power off # 1 = provide A-port VBUS # 2 = pass through target VBUS # power_test_reg = Signal(3) power_test_write_strobe = Signal() power_test_write_value = Signal(2) spi_registers.add_sfr(REGISTER_TARGET_POWER, read=power_test_reg, write_strobe=power_test_write_strobe, write_signal=power_test_write_value) # Store the values for our enable bits. with m.If(power_test_write_strobe): m.d.sync += power_test_reg[0:2].eq(power_test_write_value) # Decode the enable bits and control the two power supplies. power_a_port = platform.request("power_a_port") power_passthrough = platform.request("pass_through_vbus") with m.If(power_test_reg[0:2] == 1): m.d.comb += [power_a_port.eq(1), power_passthrough.eq(0)] with m.Elif(power_test_reg[0:2] == 2): m.d.comb += [power_a_port.eq(0), power_passthrough.eq(1)] with m.Else(): m.d.comb += [power_a_port.eq(0), power_passthrough.eq(0)] # # User IO GPIO registers. # # Data direction register. user_io_ddr = spi_registers.add_register(REGISTER_USER_IO_DIR, size=4) # Pin (input) state register. user_io_in = Signal(4) spi_registers.add_sfr(REGISTER_USER_IO_IN, read=user_io_in) # Output value register. user_io_out = spi_registers.add_register(REGISTER_USER_IO_OUT, size=4) # Grab and connect each of our user-I/O ports our GPIO registers. for i in range(4): pin = platform.request("user_io", i) m.d.comb += [ pin.oe.eq(user_io_ddr[i]), user_io_in[i].eq(pin.i), pin.o.eq(user_io_out[i]) ] # # ULPI PHY windows # self.add_ulpi_registers(m, platform, clock=clk_60MHz, ulpi_bus="target_phy", register_base=REGISTER_TARGET_ADDR) self.add_ulpi_registers(m, platform, clock=clk_60MHz, ulpi_bus="host_phy", register_base=REGISTER_HOST_ADDR) self.add_ulpi_registers(m, platform, clock=clk_60MHz, ulpi_bus="sideband_phy", register_base=REGISTER_SIDEBAND_ADDR) # # 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. # sck = Signal() sdi = Signal() cs = Signal() gateware_sdo = Signal() # # Synchronize each of our I/O SPI signals, where necessary. # m.submodules += FFSynchronizer(board_spi.sck, sck) m.submodules += FFSynchronizer(board_spi.sdi, sdi) m.submodules += FFSynchronizer(board_spi.cs, cs) # Select the passthrough or gateware SPI based on our chip-select values. with m.If(spi_registers.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.sck.eq(sck), spi_registers.sdi.eq(sdi), gateware_sdo.eq(spi_registers.sdo), spi_registers.cs.eq(cs) ] return m
def elaborate(self, platform): m = Module() # Generate our clock domains. clocking = LunaECP5DomainGenerator(clock_frequencies=CLOCK_FREQUENCIES) m.submodules.clocking = clocking registers = JTAGRegisterInterface(default_read_value=0xDEADBEEF) m.submodules.registers = registers # Simple applet ID register. registers.add_read_only_register(REGISTER_ID, read=0x54455354) # LED test register. led_reg = registers.add_register(REGISTER_LEDS, size=6, name="leds", reset=0b111111) led_out = Cat( [platform.request("led", i, dir="o") for i in range(0, 6)]) m.d.comb += led_out.eq(led_reg) # # Target power test register. # Note: these values assume you've populated the correct AP22814 for # your revision (AP22814As for rev0.2+, and AP22814Bs for rev0.1). # bits [1:0]: 0 = power off # 1 = provide A-port VBUS # 2 = pass through target VBUS # power_test_reg = Signal(3) power_test_write_strobe = Signal() power_test_write_value = Signal(2) registers.add_sfr(REGISTER_TARGET_POWER, read=power_test_reg, write_strobe=power_test_write_strobe, write_signal=power_test_write_value) # Store the values for our enable bits. with m.If(power_test_write_strobe): m.d.sync += power_test_reg[0:2].eq(power_test_write_value) # Decode the enable bits and control the two power supplies. power_a_port = platform.request("power_a_port") power_passthrough = platform.request("pass_through_vbus") with m.If(power_test_reg[0:2] == 1): m.d.comb += [power_a_port.eq(1), power_passthrough.eq(0)] with m.Elif(power_test_reg[0:2] == 2): m.d.comb += [power_a_port.eq(0), power_passthrough.eq(1)] with m.Else(): m.d.comb += [power_a_port.eq(0), power_passthrough.eq(0)] # # User IO GPIO registers. # # Data direction register. user_io_dir = registers.add_register(REGISTER_USER_IO_DIR, size=2) # Pin (input) state register. user_io_in = Signal(2) registers.add_sfr(REGISTER_USER_IO_IN, read=user_io_in) # Output value register. user_io_out = registers.add_register(REGISTER_USER_IO_OUT, size=2) # Grab and connect each of our user-I/O ports our GPIO registers. for i in range(2): pin = platform.request("user_io", i) m.d.comb += [ pin.oe.eq(user_io_dir[i]), user_io_in[i].eq(pin.i), pin.o.eq(user_io_out[i]) ] # # ULPI PHY windows # self.add_ulpi_registers(m, platform, ulpi_bus="target_phy", register_base=REGISTER_TARGET_ADDR) self.add_ulpi_registers(m, platform, ulpi_bus="host_phy", register_base=REGISTER_HOST_ADDR) self.add_ulpi_registers(m, platform, ulpi_bus="sideband_phy", register_base=REGISTER_SIDEBAND_ADDR) # # HyperRAM test connections. # ram_bus = platform.request('ram') psram = HyperRAMInterface(bus=ram_bus) m.submodules += psram psram_address_changed = Signal() psram_address = registers.add_register( REGISTER_RAM_REG_ADDR, write_strobe=psram_address_changed) registers.add_sfr(REGISTER_RAM_VALUE, read=psram.read_data) # Hook up our PSRAM. m.d.comb += [ ram_bus.reset.eq(0), psram.single_page.eq(0), psram.perform_write.eq(0), psram.register_space.eq(1), psram.final_word.eq(1), psram.start_transfer.eq(psram_address_changed), psram.address.eq(psram_address), ] return m
def elaborate(self, platform): m = Module() # Parser parser = SPIParser(self.platform) m.submodules.parser = parser # Busy used to detect move or scanline in action # disabled "dispatching" busy = Signal() # Polynomal Move polynomal = Polynomal(self.platform, self.divider) m.submodules.polynomal = polynomal if platform: board_spi = platform.request("debug_spi") spi = synchronize(m, board_spi) m.submodules.car = platform.clock_domain_generator() laserheadpins = platform.request("laserscanner") steppers = [res for res in get_all_resources(platform, "stepper")] assert len(steppers) != 0 else: platform = self.platform self.spi = SPIBus() self.parser = parser self.pol = polynomal spi = synchronize(m, self.spi) self.laserheadpins = platform.laserhead self.steppers = steppers = platform.steppers self.busy = busy laserheadpins = self.platform.laserhead # Local laser signal clones enable_prism = Signal() lasers = Signal(2) # Laserscan Head if self.simdiode: laserhead = DiodeSimulator(platform=platform, addfifo=False) lh = laserhead m.d.comb += [lh.enable_prism_in.eq(enable_prism | lh.enable_prism), lh.laser0in.eq(lasers[0] | lh.lasers[0]), laserhead.laser1in.eq(lasers[1] | lh.lasers[1])] else: laserhead = Laserhead(platform=platform) m.d.comb += laserhead.photodiode.eq(laserheadpins.photodiode) m.submodules.laserhead = laserhead if platform.name == 'Test': self.laserhead = laserhead # position adder busy_d = Signal() m.d.sync += busy_d.eq(polynomal.busy) coeffcnt = Signal(range(len(polynomal.coeff))) # connect laserhead m.d.comb += [ laserheadpins.pwm.eq(laserhead.pwm), laserheadpins.en.eq(laserhead.enable_prism | enable_prism), laserheadpins.laser0.eq(laserhead.lasers[0] | lasers[0]), laserheadpins.laser1.eq(laserhead.lasers[1] | lasers[1]), ] # connect Parser m.d.comb += [ self.read_data.eq(parser.read_data), laserhead.read_data.eq(parser.read_data), laserhead.empty.eq(parser.empty), self.empty.eq(parser.empty), parser.read_commit.eq(self.read_commit | laserhead.read_commit), parser.read_en.eq(self.read_en | laserhead.read_en), parser.read_discard.eq(self.read_discard | laserhead.read_discard) ] # connect motors for idx, stepper in enumerate(steppers): if idx != (list(platform.stepspermm.keys()) .index(platform.laser_axis)): step = (polynomal.step[idx] & ((stepper.limit == 0) | stepper.dir)) direction = polynomal.dir[idx] # connect the motor in which the laserhead moves to laser core else: step = ((polynomal.step[idx] | laserhead.step) & ((stepper.limit == 0) | stepper.dir)) direction = ((polynomal.dir[idx] & polynomal.busy) | (laserhead.dir & laserhead.process_lines)) m.d.comb += [stepper.step.eq(step), stepper.dir.eq(direction), parser.pinstate[idx].eq(stepper.limit)] m.d.comb += (parser.pinstate[len(steppers):]. eq(Cat(laserhead.photodiode_t, laserhead.synchronized))) # Busy signal m.d.comb += busy.eq(polynomal.busy | laserhead.process_lines) # connect spi m.d.comb += parser.spi.connect(spi) with m.If((busy_d == 1) & (busy == 0)): for idx, position in enumerate(parser.position): m.d.sync += position.eq(position+polynomal.totalsteps[idx]) # pins you can write to pins = Cat(lasers, enable_prism, laserhead.synchronize) with m.FSM(reset='RESET', name='dispatcher'): with m.State('RESET'): m.next = 'WAIT_INSTRUCTION' m.d.sync += pins.eq(0) with m.State('WAIT_INSTRUCTION'): m.d.sync += [self.read_commit.eq(0), polynomal.start.eq(0)] with m.If((self.empty == 0) & parser.execute & (busy == 0)): m.d.sync += self.read_en.eq(1) m.next = 'PARSEHEAD' # check which instruction we r handling with m.State('PARSEHEAD'): byte0 = self.read_data[:8] m.d.sync += self.read_en.eq(0) with m.If(byte0 == INSTRUCTIONS.MOVE): m.d.sync += [polynomal.ticklimit.eq(self.read_data[8:]), coeffcnt.eq(0)] m.next = 'MOVE_POLYNOMAL' with m.Elif(byte0 == INSTRUCTIONS.WRITEPIN): m.d.sync += [pins.eq(self.read_data[8:]), self.read_commit.eq(1)] m.next = 'WAIT' with m.Elif((byte0 == INSTRUCTIONS.SCANLINE) | (byte0 == INSTRUCTIONS.LASTSCANLINE)): m.d.sync += [self.read_discard.eq(1), laserhead.synchronize.eq(1), laserhead.expose_start.eq(1)] m.next = 'SCANLINE' with m.Else(): m.next = 'ERROR' m.d.sync += parser.dispatcherror.eq(1) with m.State('MOVE_POLYNOMAL'): with m.If(coeffcnt < len(polynomal.coeff)): with m.If(self.read_en == 0): m.d.sync += self.read_en.eq(1) with m.Else(): m.d.sync += [polynomal.coeff[coeffcnt].eq( self.read_data), coeffcnt.eq(coeffcnt+1), self.read_en.eq(0)] with m.Else(): m.next = 'WAIT' m.d.sync += [polynomal.start.eq(1), self.read_commit.eq(1)] with m.State('SCANLINE'): m.d.sync += [self.read_discard.eq(0), laserhead.expose_start.eq(0)] m.next = 'WAIT' # NOTE: you need to wait for busy to be raised # in time with m.State('WAIT'): m.d.sync += polynomal.start.eq(0) m.next = 'WAIT_INSTRUCTION' # NOTE: system never recovers user must reset with m.State('ERROR'): m.next = 'ERROR' return m
def elaborate(self, platform: Platform) -> Module: m = Module() m.d.comb += self._ccs.eq(self.ccs) m.d.ph1 += self.ccs.eq(self._ccs) # intermediates carry4 = Signal() carry7 = Signal() carry8 = Signal() overflow = Signal() with m.Switch(self.func): with m.Case(ALU8Func.LD): m.d.comb += self.output.eq(self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.LDCHAIN): m.d.comb += self.output.eq(self.input2) m.d.comb += self._ccs[Flags.Z].eq((self.output == 0) & self.ccs[Flags.Z]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.ADD, ALU8Func.ADC): no_carry = (self.func == ALU8Func.ADD) carry_in = Mux(no_carry, 0, self.ccs[Flags.C]) sum0_3 = Cat(self.output[:4], carry4) m.d.comb += sum0_3.eq(self.input1[:4] + self.input2[:4] + carry_in) sum4_6 = Cat(self.output[4:7], carry7) m.d.comb += sum4_6.eq(self.input1[4:7] + self.input2[4:7] + carry4) sum7 = Cat(self.output[7], carry8) m.d.comb += sum7.eq(self.input1[7] + self.input2[7] + carry7) m.d.comb += overflow.eq(carry7 ^ carry8) m.d.comb += self._ccs[Flags.H].eq(carry4) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.V].eq(overflow) m.d.comb += self._ccs[Flags.C].eq(carry8) with m.Case(ALU8Func.SUB, ALU8Func.SBC, ALU8Func.CPXHI, ALU8Func.CPXLO): carry_in = Mux(self.func != ALU8Func.SBC, 0, self.ccs[Flags.C]) sum0_6 = Cat(self.output[:7], carry7) m.d.comb += sum0_6.eq(self.input1[:7] + ~self.input2[:7] + ~carry_in) sum7 = Cat(self.output[7], carry8) m.d.comb += sum7.eq(self.input1[7] + ~self.input2[7] + carry7) m.d.comb += overflow.eq(carry7 ^ carry8) with m.If(self.func != ALU8Func.CPXLO): m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.V].eq(overflow) with m.If(self.func != ALU8Func.CPXHI): m.d.comb += self._ccs[Flags.C].eq(~carry8) with m.Else(): m.d.comb += self._ccs[Flags.Z].eq((self.output == 0) & self.ccs[Flags.Z]) with m.Case(ALU8Func.AND): m.d.comb += self.output.eq(self.input1 & self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.EOR): m.d.comb += self.output.eq(self.input1 ^ self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.ORA): m.d.comb += self.output.eq(self.input1 | self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.INC): m.d.comb += self.output.eq(self.input2 + 1) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(self.output == 0x80) with m.Case(ALU8Func.DEC): m.d.comb += self.output.eq(self.input2 - 1) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(self.output == 0x7F) with m.Case(ALU8Func.COM): m.d.comb += self.output.eq(0xFF ^ self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) m.d.comb += self._ccs[Flags.C].eq(1) with m.Case(ALU8Func.ROL): # IIIIIIIIC -> # COOOOOOOO m.d.comb += [ LCat(self._ccs[Flags.C], self.output).eq(LCat(self.input2, self.ccs[Flags.C])), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq(self._ccs[Flags.N] ^ self._ccs[Flags.C]), ] with m.Case(ALU8Func.ROR): # CIIIIIIII -> # OOOOOOOOC m.d.comb += [ LCat(self.output, self._ccs[Flags.C]).eq( LCat(self.ccs[Flags.C], self.input2)), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq(self._ccs[Flags.N] ^ self._ccs[Flags.C]), ] with m.Case(ALU8Func.ASL): # IIIIIIII0 -> # COOOOOOOO m.d.comb += [ LCat(self._ccs[Flags.C], self.output).eq(LCat(self.input2, Const(0))), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq(self._ccs[Flags.N] ^ self._ccs[Flags.C]), ] with m.Case(ALU8Func.ASR): # 7IIIIIIII -> ("7" is the repeat of input[7]) # OOOOOOOOC m.d.comb += [ LCat(self.output, self._ccs[Flags.C]).eq( LCat(self.input2[7], self.input2)), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq(self._ccs[Flags.N] ^ self._ccs[Flags.C]), ] with m.Case(ALU8Func.LSR): # 0IIIIIIII -> # OOOOOOOOC m.d.comb += [ LCat(self.output, self._ccs[Flags.C]).eq(LCat(Const(0), self.input2)), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq(self._ccs[Flags.N] ^ self._ccs[Flags.C]), ] with m.Case(ALU8Func.CLC): m.d.comb += self._ccs[Flags.C].eq(0) with m.Case(ALU8Func.SEC): m.d.comb += self._ccs[Flags.C].eq(1) with m.Case(ALU8Func.CLV): m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.SEV): m.d.comb += self._ccs[Flags.V].eq(1) with m.Case(ALU8Func.CLI): m.d.comb += self._ccs[Flags.I].eq(0) with m.Case(ALU8Func.SEI): m.d.comb += self._ccs[Flags.I].eq(1) with m.Case(ALU8Func.CLZ): m.d.comb += self._ccs[Flags.Z].eq(0) with m.Case(ALU8Func.SEZ): m.d.comb += self._ccs[Flags.Z].eq(1) with m.Case(ALU8Func.TAP): m.d.comb += self._ccs.eq(self.input1 | 0b11000000) with m.Case(ALU8Func.TPA): m.d.comb += self.output.eq(self.ccs | 0b11000000) with m.Case(ALU8Func.SEF): m.d.comb += self._ccs.eq(self.input1 | 0b11000000) with m.Case(ALU8Func.DAA): adjust = Signal(8) low = self.input1[:4] high = self.input1[4:] low_ten_or_more = low >= 0xA high_ten_or_more = high >= 0xA with m.If(low_ten_or_more | self.ccs[Flags.H]): m.d.comb += adjust[:4].eq(6) with m.If(high_ten_or_more | self.ccs[Flags.C] | (low_ten_or_more & (high == 9))): m.d.comb += adjust[4:].eq(6) sum9 = LCat(carry8, self.output) m.d.comb += sum9.eq(self.input1 + adjust) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.C].eq(carry8 | self.ccs[Flags.C]) with m.Default(): m.d.comb += self.output.eq(self.input1) return m
def elaborate(self, platform): m = Module() # Generate our clock domains. clocking = LunaECP5DomainGenerator(clock_frequencies=CLOCK_FREQUENCIES) m.submodules.clocking = clocking # 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 # Simple applet ID register. spi_registers.add_read_only_register(REGISTER_ID, read=0x54455354) # LED test register. led_reg = spi_registers.add_register(REGISTER_LEDS, size=6, name="leds", reset=0b10) led_out = Cat([platform.request("led", i, dir="o") for i in range(0, 6)]) m.d.comb += led_out.eq(led_reg) # # Target power test register. # Note: these values assume you've populated the correct AP22814 for # your revision (AP22814As for rev0.2+, and AP22814Bs for rev0.1). # bits [1:0]: 0 = power off # 1 = provide A-port VBUS # 2 = pass through target VBUS # power_test_reg = Signal(3) power_test_write_strobe = Signal() power_test_write_value = Signal(2) spi_registers.add_sfr(REGISTER_TARGET_POWER, read=power_test_reg, write_strobe=power_test_write_strobe, write_signal=power_test_write_value ) # Store the values for our enable bits. with m.If(power_test_write_strobe): m.d.sync += power_test_reg[0:2].eq(power_test_write_value) # Decode the enable bits and control the two power supplies. power_a_port = platform.request("power_a_port") power_passthrough = platform.request("pass_through_vbus") with m.If(power_test_reg[0:2] == 1): m.d.comb += [ power_a_port .eq(1), power_passthrough .eq(0) ] with m.Elif(power_test_reg[0:2] == 2): m.d.comb += [ power_a_port .eq(0), power_passthrough .eq(1) ] with m.Else(): m.d.comb += [ power_a_port .eq(0), power_passthrough .eq(0) ] # # User IO GPIO registers. # # Data direction register. user_io_dir = spi_registers.add_register(REGISTER_USER_IO_DIR, size=4) # Pin (input) state register. user_io_in = Signal(4) spi_registers.add_sfr(REGISTER_USER_IO_IN, read=user_io_in) # Output value register. user_io_out = spi_registers.add_register(REGISTER_USER_IO_OUT, size=4) # Grab and connect each of our user-I/O ports our GPIO registers. for i in range(4): pin = platform.request("user_io", i) m.d.comb += [ pin.oe .eq(user_io_dir[i]), user_io_in[i] .eq(pin.i), pin.o .eq(user_io_out[i]) ] # # ULPI PHY windows # self.add_ulpi_registers(m, platform, ulpi_bus="target_phy", register_base=REGISTER_TARGET_ADDR ) self.add_ulpi_registers(m, platform, ulpi_bus="host_phy", register_base=REGISTER_HOST_ADDR ) self.add_ulpi_registers(m, platform, ulpi_bus="sideband_phy", register_base=REGISTER_SIDEBAND_ADDR ) # # HyperRAM test connections. # ram_bus = platform.request('ram') psram = HyperRAMInterface(bus=ram_bus) m.submodules += psram psram_address_changed = Signal() psram_address = spi_registers.add_register(REGISTER_RAM_REG_ADDR, write_strobe=psram_address_changed) spi_registers.add_sfr(REGISTER_RAM_VALUE, read=psram.read_data) # Hook up our PSRAM. m.d.comb += [ ram_bus.reset .eq(0), psram.single_page .eq(0), psram.perform_write .eq(0), psram.register_space .eq(1), psram.final_word .eq(1), psram.start_transfer .eq(psram_address_changed), psram.address .eq(psram_address), ] # # 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), ] # # Synchronize each of our I/O SPI signals, where necessary. # spi = synchronize(m, board_spi) # Select the passthrough or gateware SPI based on our chip-select values. gateware_sdo = Signal() with m.If(spi_registers.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: Platform) -> Module: m = Module() m.d.comb += self._ccs.eq(self.ccs) m.d.ph1 += self.ccs.eq(self._ccs) # intermediates carry4 = Signal() carry7 = Signal() carry8 = Signal() overflow = Signal() with m.Switch(self.func): with m.Case(ALU8Func.LD): m.d.comb += self.output.eq(self.input2) m.d.comb += self._ccs[_Z].eq(self.output == 0) m.d.comb += self._ccs[_N].eq(self.output[7]) m.d.comb += self._ccs[_V].eq(0) with m.Case(ALU8Func.ADD, ALU8Func.ADC): carry_in = Mux(self.func == ALU8Func.ADD, 0, self.ccs[_C]) sum0_3 = Cat(self.output[:4], carry4) m.d.comb += sum0_3.eq(self.input1[:4] + self.input2[:4] + carry_in) sum4_6 = Cat(self.output[4:7], carry7) m.d.comb += sum4_6.eq(self.input1[4:7] + self.input2[4:7] + carry4) sum7 = Cat(self.output[7], carry8) m.d.comb += sum7.eq(self.input1[7] + self.input2[7] + carry7) m.d.comb += overflow.eq(carry7 ^ carry8) m.d.comb += self._ccs[_H].eq(carry4) m.d.comb += self._ccs[_N].eq(self.output[7]) m.d.comb += self._ccs[_Z].eq(self.output == 0) m.d.comb += self._ccs[_V].eq(overflow) m.d.comb += self._ccs[_C].eq(carry8) with m.Case(ALU8Func.SUB, ALU8Func.SBC): carry_in = Mux(self.func == ALU8Func.SUB, 0, self.ccs[_C]) sum0_6 = Cat(self.output[:7], carry7) m.d.comb += sum0_6.eq(self.input1[:7] + ~self.input2[:7] + ~carry_in) sum7 = Cat(self.output[7], carry8) m.d.comb += sum7.eq(self.input1[7] + ~self.input2[7] + carry7) m.d.comb += overflow.eq(carry7 ^ carry8) m.d.comb += self._ccs[_N].eq(self.output[7]) m.d.comb += self._ccs[_Z].eq(self.output == 0) m.d.comb += self._ccs[_V].eq(overflow) m.d.comb += self._ccs[_C].eq(~carry8) with m.Case(ALU8Func.AND): m.d.comb += self.output.eq(self.input1 & self.input2) m.d.comb += self._ccs[_Z].eq(self.output == 0) m.d.comb += self._ccs[_N].eq(self.output[7]) m.d.comb += self._ccs[_V].eq(0) with m.Case(ALU8Func.EOR): m.d.comb += self.output.eq(self.input1 ^ self.input2) m.d.comb += self._ccs[_Z].eq(self.output == 0) m.d.comb += self._ccs[_N].eq(self.output[7]) m.d.comb += self._ccs[_V].eq(0) with m.Case(ALU8Func.ORA): m.d.comb += self.output.eq(self.input1 | self.input2) m.d.comb += self._ccs[_Z].eq(self.output == 0) m.d.comb += self._ccs[_N].eq(self.output[7]) m.d.comb += self._ccs[_V].eq(0) return m
def elaborate(self, platform): m = Module() m.submodules.ila = ila = self.ila if self._o_domain == self.domain: in_domain_stream = self.stream else: in_domain_stream = StreamInterface( payload_width=self.bits_per_sample) # Count where we are in the current transmission. current_sample_number = Signal(range(0, ila.sample_depth)) # Always present the current sample number to our ILA, and the current # sample value to the UART. m.d.comb += [ ila.captured_sample_number.eq(current_sample_number), in_domain_stream.payload.eq(ila.captured_sample) ] with m.FSM(): # IDLE -- we're currently waiting for a trigger before capturing samples. with m.State("IDLE"): # Always allow triggering, as we're ready for the data. m.d.comb += self.ila.trigger.eq(self.trigger) # Once we're triggered, move onto the SAMPLING state. with m.If(self.trigger): m.next = "SAMPLING" # SAMPLING -- the internal ILA is sampling; we're now waiting for it to # complete. This state is similar to IDLE; except we block triggers in order # to cleanly avoid a race condition. with m.State("SAMPLING"): # Once our ILA has finished sampling, prepare to read out our samples. with m.If(self.ila.complete): m.d.sync += [ current_sample_number.eq(0), in_domain_stream.first.eq(1) ] m.next = "SENDING" # SENDING -- we now have a valid buffer of samples to send up to the host; # we'll transmit them over our stream interface. with m.State("SENDING"): m.d.comb += [ # While we're sending, we're always providing valid data to the UART. in_domain_stream.valid.eq(1), # Indicate when we're on the last sample. in_domain_stream.last.eq( current_sample_number == (self.sample_depth - 1)) ] # Each time the UART accepts a valid word, move on to the next one. with m.If(in_domain_stream.ready): m.d.sync += [ current_sample_number.eq(current_sample_number + 1), in_domain_stream.first.eq(0) ] # If this was the last sample, we're done! Move back to idle. with m.If(self.stream.last): m.next = "IDLE" # If we're not streaming out of the same domain we're capturing from, # we'll add some clock-domain crossing hardware. if self._o_domain != self.domain: in_domain_signals = Cat(in_domain_stream.first, in_domain_stream.payload, in_domain_stream.last) out_domain_signals = Cat(self.stream.first, self.stream.payload, self.stream.last) # Create our async FIFO... m.submodules.cdc = fifo = AsyncFIFOBuffered( width=len(in_domain_signals), depth=16, w_domain="sync", r_domain=self._o_domain) m.d.comb += [ # ... fill it from our in-domain stream... fifo.w_data.eq(in_domain_signals), fifo.w_en.eq(in_domain_stream.valid), in_domain_stream.ready.eq(fifo.w_rdy), # ... and output it into our outupt stream. out_domain_signals.eq(fifo.r_data), self.stream.valid.eq(fifo.r_rdy), fifo.r_en.eq(self.stream.ready) ] # Convert our sync domain to the domain requested by the user, if necessary. if self.domain != "sync": m = DomainRenamer({"sync": self.domain})(m) return m
def provide_all_signals(self, value): all_signals = Cat(self.input_a, self.input_b, self.input_c) yield all_signals.eq(value)
def elaborate(self, platform: Platform) -> Module: m = Module() m.d.sync += self.PSW.eq(self._psw) m.d.comb += self._psw.eq(self.PSW) with m.Switch(self.oper): with m.Case(Operation.NOP): if self.verification is Operation.NOP: with m.If(~Initial()): m.d.comb += [ Assert(self._psw.N == self.PSW.N), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == self.PSW.Z), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.ADC): low = Cat(self.result[:4], self._psw.H) high = Cat(self.result[4:], self._psw.C) m.d.comb += [ low.eq(self.inputa[:4] + self.inputb[:4] + self.PSW.C), high.eq(self.inputa[4:] + self.inputb[4:] + self._psw.H), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), self._psw.V.eq(self.result[7] != self._psw.C), ] if self.verification is Operation.ADC: r = Signal(8) f = Signal(9) h = Signal(5) m.d.comb += [ r.eq(self.inputa.as_signed() + self.inputb.as_signed() + self.PSW.C), f.eq(self.inputa + self.inputb + self.PSW.C), h.eq(self.inputa[:4] + self.inputb[:4] + self.PSW.C), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self.result == f[:8]), Assert(self._psw.N == f[7]), Assert(self._psw.V == (f[7] ^ f[8])), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == h[4]), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(f[:8].bool())), Assert(self._psw.C == f[8]), ] with m.Case(Operation.SBC): low = Cat(self.result[:4], self._psw.H) high = Cat(self.result[4:], self._psw.C) m.d.comb += [ low.eq(self.inputa[:4] - self.inputb[:4] - self.PSW.C), high.eq(self.inputa[4:] - self.inputb[4:] - self._psw.H), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), self._psw.V.eq(self.result[7] != self._psw.C), ] if self.verification is Operation.SBC: r = Signal(8) f = Signal(9) h = Signal(5) m.d.comb += [ r.eq(self.inputa.as_signed() - self.inputb.as_signed() - self.PSW.C), f.eq(self.inputa - self.inputb - self.PSW.C), h.eq(self.inputa[:4] - self.inputb[:4] - self.PSW.C), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self.result == f[:8]), Assert(self._psw.N == f[7]), Assert(self._psw.V == (f[7] ^ f[8])), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == h[4]), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(f[:8].bool())), Assert(self._psw.C == f[8]), ] with m.Case(Operation.CMP): full = Cat(self.result, self._psw.C) m.d.comb += [ full.eq(self.inputa.as_signed() - self.inputb.as_signed()), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), self._psw.V.eq(self.result[7] != self._psw.C), ] if self.verification is Operation.CMP: r = Signal(9) m.d.comb += r.eq(self.inputa.as_signed() - self.inputb.as_signed()) with m.If(~Initial()): m.d.comb += [ Assert(self.result == r[:8]), Assert(self._psw.N == r[7]), Assert(self._psw.V == (r[7] ^ r[8])), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r[:8].bool())), Assert(self._psw.C == r[8]), ] with m.Case(Operation.AND): m.d.comb += [ self.result.eq(self.inputa & self.inputb), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.AND: r = Signal(8) m.d.comb += r.eq(self.inputa & self.inputb) with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.OOR): m.d.comb += [ self.result.eq(self.inputa | self.inputb), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.OOR: r = Signal(8) m.d.comb += [ r.eq(self.inputa | self.inputb), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.EOR): m.d.comb += [ self.result.eq(self.inputa ^ self.inputb), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.EOR: r = Signal(8) m.d.comb += [ r.eq(self.inputa ^ self.inputb), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.INC): m.d.comb += [ self.result.eq(self.inputa + 1), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.INC: r = Signal(8) m.d.comb += [ r.eq(self.inputa + 1), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.DEC): m.d.comb += [ self.result.eq(self.inputa - 1), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.DEC: r = Signal(8) m.d.comb += [ r.eq(self.inputa - 1), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.ASL): m.d.comb += [ Cat(self.result, self._psw.C).eq(Cat(Const(0), self.inputa)), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.ASL: r = Signal(8) m.d.comb += [ r.eq(self.inputa * 2), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.inputa[6]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[7]), ] with m.Case(Operation.LSR): m.d.comb += [ Cat(self._psw.C, self.result).eq(Cat(self.inputa, Const(0))), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.LSR: r = Signal(8) m.d.comb += [ r.eq(self.inputa // 2), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == 0), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[0]), ] with m.Case(Operation.ROL): m.d.comb += [ Cat(self.result, self._psw.C).eq(Cat(self.PSW.C, self.inputa)), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.ROL: r = Signal(8) m.d.comb += [ r.eq(self.inputa * 2 + self.PSW.C), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.inputa[6]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[7]), ] with m.Case(Operation.ROR): m.d.comb += [ Cat(self._psw.C, self.result).eq(Cat(self.inputa, self.PSW.C)), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.ROR: r = Signal(8) m.d.comb += [ r.eq(self.inputa // 2 + Cat(Signal(7), self.PSW.C)), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.PSW.C), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[0]), ] with m.Case(Operation.XCN): m.d.comb += [ self.result.eq(Cat(self.inputa[4:], self.inputa[:4])), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.XCN: r = Signal(8) m.d.comb += [ r.eq(self.inputa * 16 + self.inputa // 16), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.inputa[3]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(self.inputa.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.DAA): temp = Signal().like(self.inputa) with m.If(self.PSW.C | (self.inputa > 0x99)): m.d.comb += self._psw.C.eq(1) m.d.comb += temp.eq(self.inputa + 0x60) with m.Else(): m.d.comb += temp.eq(self.inputa) with m.If(self.PSW.H | (temp[:4] > 0x09)): m.d.comb += self.result.eq(temp + 0x06) m.d.comb += [ self._psw.N.eq(self.result & 0x80), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.DAA: with m.If(~Initial()): m.d.comb += [Assert(False)] with m.Case(Operation.DAS): temp = Signal().like(self.inputa) with m.If(~self.PSW.C | (self.inputa > 0x99)): m.d.comb += self._psw.C.eq(0) m.d.comb += temp.eq(self.inputa - 0x60) with m.Else(): m.d.comb += temp.eq(self.inputa) with m.If(~self.PSW.H | (temp[:4] > 0x09)): m.d.comb += self.result.eq(temp - 0x06) m.d.comb += [ self._psw.N.eq(self.result & 0x80), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.DAS: with m.If(~Initial()): m.d.comb += [Assert(False)] # could be optimized with shift to right with m.Case(Operation.MUL): with m.Switch(self.count): for i in range(0, 8): with m.Case(i): prod = self.inputa * self.inputb[i] if i == 0: prod = Cat(prod[0:7], ~prod[7], Const(1)) elif i == 7: prod = Cat(~prod[0:7], prod[7], Const(1)) else: prod = Cat(prod[0:7], ~prod[7]) m.d.sync += self.partial.eq(self.partial + (prod << i)) m.d.sync += self.count.eq(i + 1) with m.Case(8): m.d.sync += self.partial_hi.eq(self.partial_lo) m.d.sync += self.count.eq(9) m.d.comb += [ self.result.eq(self.partial_hi), self._psw.N.eq(self.partial_hi.as_signed() < 0), self._psw.Z.eq(self.partial_hi == 0), ] with m.Case(9): m.d.sync += self.partial.eq(0) m.d.sync += self.count.eq(0) m.d.comb += [ self.result.eq(self.partial_hi), ] if self.verification is Operation.MUL: r = Signal(16) m.d.comb += [ r.eq(self.inputa.as_signed() * self.inputb.as_signed()), Cover(self.count == 9), ] with m.If(self.count == 9): m.d.comb += [ Assert(Past(self.result) == r[8:16]), Assert(self.result == r[0:8]), Assert(self._psw.N == r[15]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r[8:16].bool())), Assert(self._psw.C == self.PSW.C), ] with m.If(~Initial() & (self.count == 0)): m.d.comb += [ Assert(self.partial == 0), Assert((Past(self.count) == 0) | (Past(self.count) == 9)), ] with m.If(~Initial() & (self.count != 0)): m.d.comb += [ Assert(self.count == Past(self.count) + 1), Assume(self.inputa == Past(self.inputa)), Assume(self.inputb == Past(self.inputb)), ] with m.Case(Operation.DIV): over = Signal(reset=0) with m.Switch(self.count): with m.Case(0): m.d.sync += self.partial_hi.eq(self.inputa) # Y m.d.sync += self.count.eq(1) with m.Case(1): m.d.sync += self.partial_lo.eq(self.inputa) # A m.d.sync += self.count.eq(2) m.d.comb += self._psw.H.eq( Mux(self.partial_hi[0:4] >= self.inputb[0:4], 1, 0)) for i in range(2, 11): with m.Case(i): tmp1_w = Cat(self.partial << 1, over) tmp1_x = Signal(17) tmp1_y = Signal(17) tmp1_z = Signal(17) tmp2 = self.inputb << 9 m.d.comb += tmp1_x.eq(tmp1_w) with m.If(tmp1_w & 0x20000): m.d.comb += tmp1_x.eq((tmp1_w & 0x1FFFF) | 1) m.d.comb += tmp1_y.eq(tmp1_x) with m.If(tmp1_x >= tmp2): m.d.comb += tmp1_y.eq(tmp1_x ^ 1) m.d.comb += tmp1_z.eq(tmp1_y) with m.If(tmp1_y & 1): m.d.comb += tmp1_z.eq((tmp1_y - tmp2) & 0x1FFFF) m.d.sync += Cat(self.partial, over).eq(tmp1_z) m.d.sync += self.count.eq(i + 1) with m.Case(11): m.d.sync += self.count.eq(12) m.d.comb += [ self.result.eq( (Cat(self.partial, over) >> 9)), # Y % ] with m.Case(12): m.d.sync += self.partial.eq(0) m.d.sync += over.eq(0) m.d.sync += self.count.eq(0) m.d.comb += [ self.result.eq(self.partial_lo), # A / self._psw.N.eq(self.partial_lo.as_signed() < 0), self._psw.V.eq(over), self._psw.Z.eq(self.partial_lo == 0), ] if self.verification is Operation.DIV: m.d.comb += [ Cover(self.count == 12), ] with m.If(self.count == 12): m.d.comb += [Assert(False)] return m
def elaborate(self, platform): m = Module() # If we're standalone, generate the things we need. if self.standalone: # Create our tokenizer... m.submodules.tokenizer = tokenizer = USBTokenDetector( utmi=self.utmi) m.d.comb += tokenizer.interface.connect(self.tokenizer) # ... and our timer. m.submodules.timer = timer = USBInterpacketTimer() timer.add_interface(self.timer) m.d.comb += timer.speed.eq(self.speed) # Create a data-packet-deserializer, which we'll use to capture the # contents of the setup data packets. m.submodules.data_handler = data_handler = \ USBDataPacketDeserializer(utmi=self.utmi, max_packet_size=8, create_crc_generator=self.standalone) m.d.comb += self.data_crc.connect(data_handler.data_crc) # Instruct our interpacket timer to begin counting when we complete receiving # our setup packet. This will allow us to track interpacket delays. m.d.comb += self.timer.start.eq(data_handler.new_packet) # Keep our output signals de-asserted unless specified. m.d.usb += [ self.packet.received.eq(0), ] with m.FSM(domain="usb"): # IDLE -- we haven't yet detected a SETUP transaction directed at us with m.State('IDLE'): pid_matches = (self.tokenizer.pid == self.SETUP_PID) # If we're just received a new SETUP token addressed to us, # the next data packet is going to be for us. with m.If(pid_matches & self.tokenizer.new_token): m.next = 'READ_DATA' # READ_DATA -- we've just seen a SETUP token, and are waiting for the # data payload of the transaction, which contains the setup packet. with m.State('READ_DATA'): # If we receive a token packet before we receive a DATA packet, # this is a PID mismatch. Bail out and start over. with m.If(self.tokenizer.new_token): m.next = 'IDLE' # If we have a new packet, parse it as setup data. with m.If(data_handler.new_packet): # If we got exactly eight bytes, this is a valid setup packet. with m.If(data_handler.length == 8): # Collect the signals that make up our bmRequestType [USB2, 9.3]. request_type = Cat(self.packet.recipient, self.packet.type, self.packet.is_in_request) m.d.usb += [ # Parse the setup data itself... request_type.eq(data_handler.packet[0]), self.packet.request.eq(data_handler.packet[1]), self.packet.value.eq( Cat(data_handler.packet[2], data_handler.packet[3])), self.packet.index.eq( Cat(data_handler.packet[4], data_handler.packet[5])), self.packet.length.eq( Cat(data_handler.packet[6], data_handler.packet[7])), # ... and indicate that we have new data. self.packet.received.eq(1), ] # We'll now need to wait a receive-transmit delay before initiating our ACK. # Per the USB 2.0 and ULPI 1.1 specifications: # - A HS device needs to wait 8 HS bit periods before transmitting [USB2, 7.1.18.2]. # Each ULPI cycle is 8 HS bit periods, so we'll only need to wait one cycle. # - We'll use our interpacket delay timer for everything else. with m.If(self.timer.tx_allowed | (self.speed == USBSpeed.HIGH)): # If we're a high speed device, we only need to wait for a single ULPI cycle. # Processing delays mean we've already met our interpacket delay; and we can ACK # immediately. m.d.comb += self.ack.eq(1) m.next = "IDLE" # For other cases, handle the interpacket delay by waiting. with m.Else(): m.next = "INTERPACKET_DELAY" # Otherwise, this isn't; and we should ignore it. [USB2, 8.5.3] with m.Else(): m.next = "IDLE" # INTERPACKET -- wait for an inter-packet delay before responding with m.State('INTERPACKET_DELAY'): # ... and once it equals zero, ACK and return to idle. with m.If(self.timer.tx_allowed): m.d.comb += self.ack.eq(1) m.next = "IDLE" return m
def elaborate(self, platform: Platform) -> Module: m = Module() m.d.comb += self._ccs.eq(self.ccs) m.d.ph1 += self.ccs.eq(self._ccs) # intermediates carry4 = Signal() carry7 = Signal() carry8 = Signal() overflow = Signal() with m.Switch(self.func): with m.Case(ALU8Func.LD): m.d.comb += self.output.eq(self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.ADD, ALU8Func.ADC): carry_in = Mux(self.func == ALU8Func.ADD, 0, self.ccs[Flags.C]) sum0_3 = Cat(self.output[:4], carry4) m.d.comb += sum0_3.eq(self.input1[:4] + self.input2[:4] + carry_in) sum4_6 = Cat(self.output[4:7], carry7) m.d.comb += sum4_6.eq(self.input1[4:7] + self.input2[4:7] + carry4) sum7 = Cat(self.output[7], carry8) m.d.comb += sum7.eq(self.input1[7] + self.input2[7] + carry7) m.d.comb += overflow.eq(carry7 ^ carry8) m.d.comb += self._ccs[Flags.H].eq(carry4) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.V].eq(overflow) m.d.comb += self._ccs[Flags.C].eq(carry8) with m.Case(ALU8Func.SUB, ALU8Func.SBC): carry_in = Mux(self.func == ALU8Func.SUB, 0, self.ccs[Flags.C]) sum0_6 = Cat(self.output[:7], carry7) m.d.comb += sum0_6.eq(self.input1[:7] + ~self.input2[:7] + ~carry_in) sum7 = Cat(self.output[7], carry8) m.d.comb += sum7.eq(self.input1[7] + ~self.input2[7] + carry7) m.d.comb += overflow.eq(carry7 ^ carry8) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.V].eq(overflow) m.d.comb += self._ccs[Flags.C].eq(~carry8) with m.Case(ALU8Func.AND): m.d.comb += self.output.eq(self.input1 & self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.EOR): m.d.comb += self.output.eq(self.input1 ^ self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.ORA): m.d.comb += self.output.eq(self.input1 | self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.INC): m.d.comb += self.output.eq(self.input2 + 1) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(self.output == 0x80) with m.Case(ALU8Func.DEC): m.d.comb += self.output.eq(self.input2 - 1) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(self.output == 0x7F) with m.Case(ALU8Func.COM): m.d.comb += self.output.eq(0xFF ^ self.input2) m.d.comb += self._ccs[Flags.Z].eq(self.output == 0) m.d.comb += self._ccs[Flags.N].eq(self.output[7]) m.d.comb += self._ccs[Flags.V].eq(0) m.d.comb += self._ccs[Flags.C].eq(1) with m.Case(ALU8Func.ROL): # IIIIIIIIC -> # COOOOOOOO m.d.comb += [ LCat(self._ccs[Flags.C], self.output).eq( LCat(self.input2, self.ccs[Flags.C])), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq( self._ccs[Flags.N] ^ self._ccs[Flags.C]) ] with m.Case(ALU8Func.ROR): # CIIIIIIII -> # OOOOOOOOC m.d.comb += [ LCat(self.output, self._ccs[Flags.C]).eq( LCat(self.ccs[Flags.C], self.input2)), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq( self._ccs[Flags.N] ^ self._ccs[Flags.C]) ] with m.Case(ALU8Func.ASL): # IIIIIIII0 -> # COOOOOOOO m.d.comb += [ LCat(self._ccs[Flags.C], self.output).eq( LCat(self.input2, Const(0))), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq( self._ccs[Flags.N] ^ self._ccs[Flags.C]) ] with m.Case(ALU8Func.ASR): # 7IIIIIIII -> ("7" is the repeat of input[7]) # OOOOOOOOC m.d.comb += [ LCat(self.output, self._ccs[Flags.C]).eq( LCat(self.input2[7], self.input2)), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq( self._ccs[Flags.N] ^ self._ccs[Flags.C]) ] with m.Case(ALU8Func.LSR): # 0IIIIIIII -> # OOOOOOOOC m.d.comb += [ LCat(self.output, self._ccs[Flags.C]).eq( LCat(Const(0), self.input2)), self._ccs[Flags.Z].eq(self.output == 0), self._ccs[Flags.N].eq(self.output[7]), self._ccs[Flags.V].eq( self._ccs[Flags.N] ^ self._ccs[Flags.C]) ] with m.Case(ALU8Func.CLC): m.d.comb += self._ccs[Flags.C].eq(0) with m.Case(ALU8Func.SEC): m.d.comb += self._ccs[Flags.C].eq(1) with m.Case(ALU8Func.CLV): m.d.comb += self._ccs[Flags.V].eq(0) with m.Case(ALU8Func.SEV): m.d.comb += self._ccs[Flags.V].eq(1) with m.Case(ALU8Func.CLI): m.d.comb += self._ccs[Flags.I].eq(0) with m.Case(ALU8Func.SEI): m.d.comb += self._ccs[Flags.I].eq(1) with m.Case(ALU8Func.CLZ): m.d.comb += self._ccs[Flags.Z].eq(0) with m.Case(ALU8Func.SEZ): m.d.comb += self._ccs[Flags.Z].eq(1) with m.Case(ALU8Func.TAP): m.d.comb += self._ccs.eq(self.input1 | 0b11000000) with m.Case(ALU8Func.TPA): m.d.comb += self.output.eq(self.ccs | 0b11000000) return m