from migen.fhdl.std import *
from migen.bus import wishbone
from migen.flow.actor import *


class Reader(Module):
    def __init__(self):
        self.bus = wishbone.Interface()
        self.address = Sink([("a", 30)])
        self.data = Source([("d", 32)])
        self.busy = Signal()

        ###

        bus_stb = Signal()
        data_reg_loaded = Signal()
        data_reg = Signal(32)

        self.comb += [
            self.busy.eq(data_reg_loaded),
            self.bus.we.eq(0),
            bus_stb.eq(self.address.stb & (~data_reg_loaded | self.data.ack)),
            self.bus.cyc.eq(bus_stb),
            self.bus.stb.eq(bus_stb),
            self.bus.adr.eq(self.address.a),
            self.address.ack.eq(self.bus.ack),
            self.data.stb.eq(data_reg_loaded),
            self.data.d.eq(data_reg)
        ]
        self.sync += [
            If(self.data.ack, data_reg_loaded.eq(0)),
            If(self.bus.ack,
                data_reg_loaded.eq(1),
                data_reg.eq(self.bus.dat_r)
            )
        ]


class Writer(Module):
    def __init__(self):
        self.bus = wishbone.Interface()
        self.address_data = Sink([("a", 30), ("d", 32)])
        self.busy = Signal()

        ###

        self.comb += [
            self.busy.eq(0),
            self.bus.we.eq(1),
            self.bus.cyc.eq(self.address_data.stb),
            self.bus.stb.eq(self.address_data.stb),
            self.bus.adr.eq(self.address_data.a),
            self.bus.sel.eq(0xf),
            self.bus.dat_w.eq(self.address_data.d),
            self.address_data.ack.eq(self.bus.ack)
        ]