from migen.fhdl.std import * from migen.bus import wishbone from migen.genlib.fsm import FSM, NextState from migen.genlib.cdc import MultiReg class FSMCBridge(Module): def __init__(self, fsmc_pins): self.master = master = wishbone.Interface(16) fsmc_a = Signal(11) self.d_in = fsmc_d_in = Signal(16) self.d_out = fsmc_d_out = Signal(16) fsmc_bl = Signal(2) fsmc_e = Signal() fsmc_oe = Signal() fsmc_we = Signal() d_ts = TSTriple(16) self.specials += d_ts.get_tristate(fsmc_pins.d) self.comb += d_ts.oe.eq(~fsmc_pins.ne & ~fsmc_pins.noe) self.comb += d_ts.o.eq(fsmc_d_out) self.specials += MultiReg(fsmc_pins.a, fsmc_a) self.specials += MultiReg(d_ts.i, fsmc_d_in) self.specials += MultiReg(~fsmc_pins.nbl, fsmc_bl) self.specials += MultiReg(~fsmc_pins.ne, fsmc_e) self.specials += MultiReg(~fsmc_pins.noe, fsmc_oe) self.specials += MultiReg(~fsmc_pins.nwe, fsmc_we) start_read_cycle = Signal() start_write_cycle = Signal() end_cycle = Signal() sample_data = Signal() fsm = FSM() fsm.act('IDLE', If(fsmc_e, # Read If(fsmc_oe, start_read_cycle.eq(1), NextState('READ_WAIT_ACK'), ), # Write If(fsmc_we, start_write_cycle.eq(1), NextState('WRITE_WAIT_ACK'), ), ), ) fsm.act('WRITE_WAIT_ACK', If(master.ack, end_cycle.eq(1), NextState('WRITE_WAIT'), ), ) fsm.act('WRITE_WAIT', If(~fsmc_we, NextState('IDLE'), ), ) fsm.act('READ_WAIT_ACK', If(master.ack, sample_data.eq(1), end_cycle.eq(1), NextState('READ_WAIT'), ), ) fsm.act('READ_WAIT', If(~fsmc_oe, NextState('IDLE'), ), ) self.submodules.fsm = fsm self.sync += If(start_read_cycle, master.cyc.eq(1), master.stb.eq(1), master.adr.eq(fsmc_a), master.sel.eq(fsmc_bl), master.we.eq(0), ) self.sync += If(start_write_cycle, master.cyc.eq(1), master.stb.eq(1), master.adr.eq(fsmc_a), master.sel.eq(fsmc_bl), master.we.eq(1), master.dat_w.eq(fsmc_d_in), ) self.sync += If(end_cycle, fsmc_d_out.eq(master.dat_r), ) self.sync += If(end_cycle, master.cyc.eq(0), master.stb.eq(0), )