def elaborate(self, platform): m = Module() # Create RMII clock domain from RMII clock input cd = ClockDomain("rmii", reset_less=True) m.d.comb += cd.clk.eq(self.rmii.ref_clk) m.domains.rmii = cd # Create RX write and TX read ports for RMII use rx_port_w = self.rx_mem.write_port(domain="rmii") tx_port_r = self.tx_mem.read_port(domain="rmii", transparent=False) m.submodules += [self.rx_port, rx_port_w, self.tx_port, tx_port_r] m.d.comb += [self.rx_port.en.eq(1), tx_port_r.en.eq(1)] # Create submodules for PHY and RMII m.submodules.phy_manager = phy_manager = PHYManager( self.clk_freq, self.phy_addr, self.phy_rst, self.mdio.mdio, self.mdio.mdc) m.submodules.stretch = stretch = PulseStretch(int(1e6)) rmii_rx = RMIIRx(self.mac_addr, rx_port_w, self.rmii.crs_dv, self.rmii.rxd0, self.rmii.rxd1) rmii_tx = RMIITx(tx_port_r, self.rmii.txen, self.rmii.txd0, self.rmii.txd1) # Create FIFOs to interface to RMII modules rx_fifo = AsyncFIFO(width=11 + self.rx_port.addr.nbits, depth=4) tx_fifo = AsyncFIFO(width=11 + self.tx_port.addr.nbits, depth=4) m.d.comb += [ # RX FIFO rx_fifo.din.eq(Cat(rmii_rx.rx_offset, rmii_rx.rx_len)), rx_fifo.we.eq(rmii_rx.rx_valid), Cat(self.rx_offset, self.rx_len).eq(rx_fifo.dout), rx_fifo.re.eq(self.rx_ack), self.rx_valid.eq(rx_fifo.readable), # TX FIFO tx_fifo.din.eq(Cat(self.tx_offset, self.tx_len)), tx_fifo.we.eq(self.tx_start), Cat(rmii_tx.tx_offset, rmii_tx.tx_len).eq(tx_fifo.dout), tx_fifo.re.eq(rmii_tx.tx_ready), rmii_tx.tx_start.eq(tx_fifo.readable), # Other submodules phy_manager.phy_reset.eq(self.phy_reset), self.link_up.eq(phy_manager.link_up), stretch.trigger.eq(self.rx_valid), self.eth_led.eq(stretch.pulse), ] rdr = DomainRenamer({"read": "sync", "write": "rmii"}) wdr = DomainRenamer({"write": "sync", "read": "rmii"}) rr = DomainRenamer("rmii") m.submodules.rx_fifo = rdr(rx_fifo) m.submodules.tx_fifo = wdr(tx_fifo) m.submodules.rmii_rx = rr(rmii_rx) m.submodules.rmii_tx = rr(rmii_tx) return m
def __init__(self): self.pads = JTAGPads() self.dataInFIFO = DomainRenamer({ "read": "sync", "write": "sync", })(AsyncFIFO(width = 8, depth = 1024)) self.dataOutFIFO = DomainRenamer({ "read": "sync", "write": "sync", })(AsyncFIFO(width = 8, depth = 1024)) self.subtarget = JTAGPDIInteractiveSubtarget(pads = self.pads, in_fifo = self.dataInFIFO, out_fifo = self.dataOutFIFO, period_cyc = 4000) # 4MHz
def elaborate(self, platform): m = Module() cd_i = m.domain[self.cd_i] cd_o = m.domain[self.cd_o] comb = m.domain.comb fifo = m.submodules.fifo = DomainRenamer({ "read": self.cd_i, "write": self.cd_o })(AsyncFIFO(width=self.width, depth=self.depth)) cd_o += self.output.TDATA.eq(fifo.dout) comb += fifo.re.eq((~self.output.TVALID | self.output.accepted()) & fifo.readable) with m.If(fifo.re): cd_o += self.output.TVALID.eq(1) with m.Elif(self.output.accepted()): cd_o += self.output.TVALID.eq(0) comb += [ fifo.din.eq(self.input.TDATA), fifo.we.eq(self.input.accepted()) ] cd_i += self.input.TREADY.eq(fifo.writable) return m
def __init__(self, bus): from luna.full_devices import USBSerialDevice self.serial = USBSerialDevice(bus=bus, idVendor=1337, idProduct=1337, manufacturer_string="potatocore", product_string="intel 8080 serial port") self.i_fifo = AsyncFIFO(width=8, depth=8, r_domain="usb", w_domain="sync") self.o_fifo = AsyncFIFO(width=8, depth=8, r_domain="sync", w_domain="usb")
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") ext1 = platform.request("ext1") pa_en_n_o = platform.request("pa_en_n_o") # clock domains m.domains += ClockDomain("clk60") m.d.comb += ClockSignal("clk60").eq(ft_clkout_i.i) # signals ctr = Signal(8, reset=0) ctr_last = Signal(8, reset=0) ft_txe_last = Signal(1, reset=0) # submodules m.submodules.fifo = fifo = AsyncFIFO(width=8, depth=1024, r_domain="clk60", w_domain="sync") # logic m.d.comb += [ ft_oe_n_o.o.eq(1), ft_rd_n_o.o.eq(1), ft_siwua_n_o.o.eq(1), ft_data_io.oe.eq(1), pa_en_n_o.o.eq(1), ] m.d.comb += [ ft_data_io.o.eq(fifo.r_data), fifo.w_data.eq(ctr), ] with m.If(fifo.w_rdy): m.d.comb += fifo.w_en.eq(1) m.d.sync += ctr.eq(ctr + 1) with m.Else(): m.d.comb += fifo.w_en.eq(0) with m.If(~ft_txe_n_i & ft_suspend_n_i & fifo.r_rdy): m.d.comb += ft_wr_n_o.o.eq(0) m.d.clk60 += fifo.r_en.eq(1) with m.Else(): m.d.comb += ft_wr_n_o.o.eq(1) m.d.clk60 += fifo.r_en.eq(0) return m
def construct_rgb(self, m, video_timer): fifo = AsyncFIFO(width=16, depth=16) fifo = DomainRenamer({'read': 'sync', 'write': 'app'})(fifo) hfosc = HfOscillator('app') m.domains += hfosc.domain producer = SquareProducer(self.resolution, fifo) producer = DomainRenamer({'sync': 'app'})(producer) rgb = MonoFifoRGB(video_timer, fifo) m.submodules += [fifo, hfosc, producer, rgb] return rgb
def __init__(self, payload_type: Layout, depth: int, sop: bool = True, eop: bool = True): self.source = StreamSource(payload_type, sop, eop) self.sink = StreamSink(payload_type, sop, eop) width = self.source.data.shape().width if sop: width += 1 if eop: width += 1 self.fifo = AsyncFIFO(width=width, depth=depth)
def elaborate(self, platform): m = Module() radio = platform.request("radio") m.d.comb += radio.rst.eq(0) # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator() # Create our USB device interface... ulpi = platform.request("host_phy") m.submodules.usb = usb = USBDevice(bus=ulpi) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() control_ep = usb.add_standard_control_endpoint(descriptors) # Add our vendor request handler handler = DomainRenamer("usb")(RadioSPIRequestHandler()) control_ep.add_request_handler(handler) radio_spi = DomainRenamer("usb")(RadioSPI(clk_freq=60e6)) m.submodules += radio_spi m.d.comb += [ # Output pins radio.sel.eq(radio_spi.sel), radio.sclk.eq(radio_spi.sclk), radio.mosi.eq(radio_spi.mosi), # Input pins radio_spi.miso.eq(radio.miso), # Vendor request handler connections radio_spi.start.eq(handler.spi_start), handler.spi_busy.eq(radio_spi.busy), radio_spi.address.eq(handler.spi_address), radio_spi.write.eq(handler.spi_write), radio_spi.write_value.eq(handler.spi_write_value), ] # Add a stream endpoint to our device. stream_ep = USBStreamInEndpoint(endpoint_number=BULK_ENDPOINT_NUMBER, max_packet_size=MAX_BULK_PACKET_SIZE) usb.add_endpoint(stream_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), ] # Create radio clock domain m.domains.radio = ClockDomain() m.d.comb += [ ClockSignal("radio").eq(radio.rxclk), ResetSignal("radio").eq(ResetSignal()), ] # Get IQ samples & serialize them to bytes ready for USB. iq_rx = IQReceiver() ser = Serializer(w_width=32, r_width=8) m.submodules += [ DomainRenamer("radio")(iq_rx), DomainRenamer("radio")(ser), ] iq_sample = Cat( # 13-bit samples, swapped to little endian & padded to 16-bit each. iq_rx.q_sample[-8:], Const(0, 3), iq_rx.q_sample[1:-8], iq_rx.i_sample[-8:], Const(0, 3), iq_rx.i_sample[1:-8], ) m.d.comb += [ iq_rx.rxd.eq(radio.rxd24), ser.w_data.eq(iq_sample), ser.w_en.eq(iq_rx.sample_valid), ] fifo = AsyncFIFO(width=8, depth=2048, r_domain="usb", w_domain="radio") m.submodules += fifo m.d.comb += [ ser.r_en.eq(fifo.w_rdy), fifo.w_en.eq(ser.r_rdy), fifo.w_data.eq(ser.r_data), fifo.r_en.eq(stream_ep.stream.ready), stream_ep.stream.valid.eq(fifo.r_rdy), stream_ep.stream.payload.eq(fifo.r_data), ] led0 = platform.request("led", 0) m.d.radio += led0.eq(iq_rx.sample_valid) led1 = platform.request("led", 1) m.d.usb += led1.eq(stream_ep.stream.valid) led2 = platform.request("led", 2) m.d.radio += led2.eq(fifo.w_en) tx_start_delay = Signal(26) m.d.radio += tx_start_delay.eq(tx_start_delay + 1) tx_shift_counter = Signal(range(17)) tx_shift_reg = Signal(32) tx_value = Signal(13) with m.If(tx_start_delay[-1]): m.d.radio += tx_start_delay.eq(tx_start_delay) with m.If(tx_shift_counter == 0): m.d.radio += [ tx_shift_counter.eq(15), tx_shift_reg.eq( Cat(0, tx_value, Const(0b01, 2), 0, Const(0, 13), Const(0b10, 2))), tx_value.eq(tx_value + 1), ], with m.Else(): m.d.radio += [ tx_shift_reg.eq(tx_shift_reg << 2), tx_shift_counter.eq(tx_shift_counter - 1), ] txd = Signal(2) m.d.comb += [ radio.txclk.eq(ClockSignal("radio")), txd.eq(tx_shift_reg[-2:]), ] m.submodules += Instance( "ODDRX1F", i_D0=txd[1], i_D1=txd[0], i_SCLK=ClockSignal("radio"), i_RST=ResetSignal(), o_Q=radio.txd, ) 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("host_phy") m.submodules.usb = usb = USBDevice(bus=ulpi) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() control_ep = usb.add_standard_control_endpoint(descriptors) # Add our vendor request handler handler = DomainRenamer("usb")(RadioSPIRequestHandler()) control_ep.add_request_handler(handler) radio = platform.request("radio") m.d.comb += radio.rst.eq(0) # Setup the radio SPI interface. radio_spi = DomainRenamer("usb")(RadioSPI(clk_freq=60e6)) m.submodules += radio_spi m.d.comb += [ # Output pins radio.sel.eq(radio_spi.sel), radio.clk.eq(radio_spi.clk), radio.copi.eq(radio_spi.copi), # Input pins radio_spi.cipo.eq(radio.cipo), # Vendor request handler connections radio_spi.start.eq(handler.spi_start), handler.spi_busy.eq(radio_spi.busy), radio_spi.address.eq(handler.spi_address), radio_spi.write.eq(handler.spi_write), radio_spi.write_value.eq(handler.spi_write_value), ] # Create radio clock domain m.domains.radio = ClockDomain() m.d.comb += [ ClockSignal("radio").eq(radio.rxclk), ResetSignal("radio").eq(ResetSignal()), ] # Get IQ samples. iq_rx = self.get_rx() m.d.comb += iq_rx.rxd.eq(radio.rxd24) # m.submodules += map(DomainRenamer("radio"), self._blocks.values()) m.d.comb += self._connections combined = StreamCombiner( streams=self._usb_outputs, domain="radio", ) m.submodules += combined payload = combined.output.payload usb_data = Cat( # Pad each 13-bit value to 16-bits for now. payload.word_select(i, 13).shift_left(3) for i in range(int(len(payload) / 13))) assert (len(usb_data) % 8) == 0, f"{len(usb_data)}" # Add a stream endpoint to our device. stream_ep = USBMultibyteStreamInEndpoint( byte_width=int(len(usb_data) / 8), endpoint_number=BULK_ENDPOINT_NUMBER, max_packet_size=MAX_BULK_PACKET_SIZE) usb.add_endpoint(stream_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), ] # Connect up the IQ receiver to the USB stream, via a small FIFO. fifo = AsyncFIFO(width=len(usb_data), depth=128, r_domain="usb", w_domain="radio") m.submodules += fifo m.d.comb += [ combined.output.ready.eq(fifo.w_rdy), fifo.w_en.eq(combined.output.valid), fifo.w_data.eq(usb_data), fifo.r_en.eq(stream_ep.stream.ready), stream_ep.stream.valid.eq(fifo.r_rdy), stream_ep.stream.payload.eq(fifo.r_data), stream_ep.stream.last.eq(0), ] # Debug LEDs. led0 = platform.request("led", 0) m.d.radio += led0.eq(iq_rx.outputs[0].valid) led1 = platform.request("led", 1) m.d.usb += led1.eq(stream_ep.stream.valid) led2 = platform.request("led", 2) m.d.radio += led2.eq(fifo.w_rdy) return m
def elaborate(self, platform): m = Module() m.submodules.car = platform.clock_domain_generator() sync_n = ClockDomain("sync_n", clk_edge="neg") m.d.comb += [ sync_n.clk.eq(ClockSignal("sync")), sync_n.rst.eq(ResetSignal("sync")) ] m.domains.sync_n = sync_n # Create our USB-to-serial converter. usb0 = platform.request(platform.default_usb_connection) m.submodules.usb_serial = usb_serial = \ USBSerialDevice(bus=usb0, idVendor=0x16d0, idProduct=0x0f3b) m.submodules.usb_to_sys_fifo = usb_to_sys_fifo = AsyncFIFO( width=(usb_serial.rx.payload.width + 2), depth=2, r_domain="sync_n", w_domain="usb") m.submodules.sys_to_usb_fifo = sys_to_usb_fifo = AsyncFIFO( width=(usb_serial.tx.payload.width + 2), depth=2, r_domain="usb", w_domain="sync_n") m.d.comb += [ usb_serial.tx.payload.eq(sys_to_usb_fifo.r_data[2:]), usb_serial.tx.valid.eq(sys_to_usb_fifo.r_rdy), usb_serial.tx.first.eq(sys_to_usb_fifo.r_data[0]), usb_serial.tx.last.eq(sys_to_usb_fifo.r_data[1]), sys_to_usb_fifo.r_en.eq(usb_serial.tx.ready), usb_to_sys_fifo.w_data[2:].eq(usb_serial.rx.payload), usb_to_sys_fifo.w_en.eq(usb_serial.rx.valid), usb_to_sys_fifo.w_data[0].eq(usb_serial.rx.first), usb_to_sys_fifo.w_data[1].eq(usb_serial.rx.last), usb_serial.rx.ready.eq(usb_to_sys_fifo.w_rdy), # ... and always connect by default. usb_serial.connect.eq(1) ] m.submodules.instruction_file_r = instruction_file_r = Memory( width=8, depth=len(self.brainfuck_code), init=self.brainfuck_code).read_port() register_file_mem = Memory(width=usb_serial.rx.payload.width, depth=self.brainfuck_array_size) m.submodules.register_file_r = register_file_r = register_file_mem.read_port( ) m.submodules.register_file_w = register_file_w = register_file_mem.write_port( ) m.submodules.CPU = CPU = Brainfuck_processor( len(self.brainfuck_code), data_width=register_file_r.data.width, i_addr_width=instruction_file_r.addr.width, d_addr_width=register_file_r.addr.width, stack_depth=32) m.d.comb += [ sys_to_usb_fifo.w_data[0].eq(1), sys_to_usb_fifo.w_data[1].eq(1), sys_to_usb_fifo.w_data[2:].eq(CPU.output_stream.data), sys_to_usb_fifo.w_en.eq(CPU.output_stream.valid), CPU.output_stream.ready.eq(sys_to_usb_fifo.w_rdy), CPU.input_stream.data.eq(usb_to_sys_fifo.r_data[2:]), CPU.input_stream.valid.eq(usb_to_sys_fifo.r_rdy), usb_to_sys_fifo.r_en.eq(CPU.input_stream.ready), instruction_file_r.addr.eq(CPU.instruction_port.addr), CPU.instruction_port.r_data.eq(instruction_file_r.data), register_file_r.addr.eq(CPU.data_port.addr), CPU.data_port.r_data.eq(register_file_r.data), register_file_w.addr.eq(CPU.data_port.addr), register_file_w.data.eq(CPU.data_port.w_data), register_file_w.en.eq(CPU.data_port.w_en) ] rgb = platform.request('rgb_led', 0) red_led = rgb.r green_led = rgb.g blue_led = rgb.b m.submodules.pwm0 = pwm0 = PWM(8) m.submodules.pwm1 = pwm1 = PWM(8) m.submodules.pwm2 = pwm2 = PWM(8) m.d.comb += [ pwm0.dutyCycle.eq(102), pwm1.dutyCycle.eq(101), pwm2.dutyCycle.eq(100), red_led.o.eq(Mux(instruction_file_r.addr[0], pwm0.pwm, 0)), green_led.o.eq(Mux(CPU.error, pwm1.pwm, 0)), blue_led.o.eq(Mux(CPU.error, pwm2.pwm, 0)), ] return m
def __init__(self, *, name=None): layout = [ ("tck", 1), ("tms", 1), ("tdi", 1), ("tdo", 1), ("srst", 1), ] for pin, width in layout: triple = TSTriple(width, name=pin) setattr(self, f'{pin}_t', triple) pads = JTAGPads() dataFIFO = AsyncFIFO(width=8, depth=1024) subtarget = JTAGPDISnifferSubtarget(pads=pads, in_fifo=dataFIFO) tck = pads.tck_t.i tms = pads.tms_t.i tdi = pads.tdi_t.i tdo = pads.tdo_t.i def benchSync(): yield def resetJTAG(): yield tms.eq(1)
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() m.submodules.mig = mig = MIG() m.submodules.fifo_r = fifo_r = AsyncFIFO(width=32, depth=2, r_domain=self._domain, w_domain=mig._domain) m.submodules.fifo_w = fifo_w = AsyncFIFO(width=32 + 26 + 4, depth=2, w_domain=self._domain, r_domain=mig._domain) comb = m.d.comb # HART domain: write to fifo_w, read from fifo_r with m.FSM(domain=self._domain): with m.State("WAIT"): with m.If(fifo_w.w_rdy): with m.If(self.bus.wmask.any()): # BUS WRITE -> write to fifo_w, fire & forget comb += [ fifo_w.w_en.eq(1), fifo_w.w_data.eq( Cat(self.bus.wmask, self.bus.addr[0:26], self.bus.wdata)), ] m.next = "WACK" with m.Elif(self.bus.rmask.any()): # BUS READ -> write to fifo_w, lock the bus comb += [ fifo_w.w_en.eq(1), fifo_w.w_data.eq( Cat(0, 0, 0, 0, self.bus.addr[0:26])), ] m.next = "RACK" with m.State("WACK"): comb += self.bus.ack.eq(1) m.next = "WAIT" with m.State("RACK"): with m.If(fifo_r.r_rdy): # Response from MIG -> read from fifo_r, put data on the bus, release comb += [ self.bus.ack.eq(1), fifo_r.r_en.eq(1), self.bus.rdata.eq(fifo_r.r_data), ] m.next = "WAIT" # MIG domain: write to fifo_r, read from fifo_w with m.FSM(domain=mig._domain): with m.State("WAIT"): with m.If(fifo_w.r_rdy & mig.app_rdy & mig.app_wdf_rdy): # Execute command -> read from fifo_w wmask = fifo_w.r_data[0:4] is_write = wmask.any() addr = fifo_w.r_data[4:4 + 26] data = fifo_w.r_data[4 + 26:4 + 26 + 32] comb += [ fifo_w.r_en.eq(1), mig.app_en.eq(1), mig.app_cmd.eq(~is_write), mig.app_wdf_wren.eq(is_write), mig.app_addr.eq( addr[1:]), # addr is in memory words (16 bits) mig.app_wdf_end.eq(is_write), mig.app_wdf_data.word_select(addr[2:4], 32).eq(data), ] with m.Switch(addr[2:4]): with m.Case(0b00): comb += mig.app_wdf_mask.eq(Cat(~wmask, 0xFFF)) with m.Case(0b01): comb += mig.app_wdf_mask.eq(Cat(0xF, ~wmask, 0xFF)) with m.Case(0b10): comb += mig.app_wdf_mask.eq(Cat(0xFF, ~wmask, 0xF)) with m.Case(0b11): comb += mig.app_wdf_mask.eq(Cat(0xFFF, ~wmask)) with m.If(~is_write): m.next = "READ" with m.State("READ"): with m.If(mig.app_rd_data_valid & fifo_r.w_rdy): # Send read data back -> write to fifo_r comb += [ fifo_r.w_en.eq(1), fifo_r.w_data.eq(mig.app_rd_data), ] m.next = "WAIT" return m