Use new FSM API
This commit is contained in:
parent
93efc7297e
commit
f3e2f85dfa
|
@ -1,5 +1,5 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.genlib.fsm import FSM
|
from migen.genlib.fsm import FSM, NextState
|
||||||
from migen.bank.description import *
|
from migen.bank.description import *
|
||||||
from migen.bank.eventmanager import *
|
from migen.bank.eventmanager import *
|
||||||
from migen.flow.actor import *
|
from migen.flow.actor import *
|
||||||
|
@ -119,38 +119,36 @@ class DMA(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# control FSM
|
# control FSM
|
||||||
fsm = FSM("WAIT_SOF", "TRANSFER_PIXEL", "TO_MEMORY", "EOF")
|
fsm = FSM()
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act(fsm.WAIT_SOF,
|
fsm.act("WAIT_SOF",
|
||||||
reset_words.eq(1),
|
reset_words.eq(1),
|
||||||
self.frame.ack.eq(~self._slot_array.address_valid | ~sof),
|
self.frame.ack.eq(~self._slot_array.address_valid | ~sof),
|
||||||
If(self._slot_array.address_valid & sof & self.frame.stb, fsm.next_state(fsm.TRANSFER_PIXEL))
|
If(self._slot_array.address_valid & sof & self.frame.stb, NextState("TRANSFER_PIXEL"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.TRANSFER_PIXEL,
|
fsm.act("TRANSFER_PIXEL",
|
||||||
self.frame.ack.eq(1),
|
self.frame.ack.eq(1),
|
||||||
If(self.frame.stb,
|
If(self.frame.stb,
|
||||||
write_pixel.eq(1),
|
write_pixel.eq(1),
|
||||||
If(last_pixel,
|
If(last_pixel, NextState("TO_MEMORY"))
|
||||||
fsm.next_state(fsm.TO_MEMORY)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.TO_MEMORY,
|
fsm.act("TO_MEMORY",
|
||||||
self._bus_accessor.address_data.stb.eq(1),
|
self._bus_accessor.address_data.stb.eq(1),
|
||||||
If(self._bus_accessor.address_data.ack,
|
If(self._bus_accessor.address_data.ack,
|
||||||
count_word.eq(1),
|
count_word.eq(1),
|
||||||
If(last_word,
|
If(last_word,
|
||||||
fsm.next_state(fsm.EOF)
|
NextState("EOF")
|
||||||
).Else(
|
).Else(
|
||||||
fsm.next_state(fsm.TRANSFER_PIXEL)
|
NextState("TRANSFER_PIXEL")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.EOF,
|
fsm.act("EOF",
|
||||||
If(~self._bus_accessor.busy,
|
If(~self._bus_accessor.busy,
|
||||||
self._slot_array.address_done.eq(1),
|
self._slot_array.address_done.eq(1),
|
||||||
fsm.next_state(fsm.WAIT_SOF)
|
NextState("WAIT_SOF")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.fhdl.specials import Tristate
|
from migen.fhdl.specials import Tristate
|
||||||
from migen.genlib.cdc import MultiReg
|
from migen.genlib.cdc import MultiReg
|
||||||
from migen.genlib.fsm import FSM
|
from migen.genlib.fsm import FSM, NextState
|
||||||
from migen.genlib.misc import chooser
|
from migen.genlib.misc import chooser
|
||||||
from migen.bank.description import AutoCSR
|
from migen.bank.description import AutoCSR
|
||||||
|
|
||||||
|
@ -102,79 +102,76 @@ class EDID(Module, AutoCSR):
|
||||||
self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
|
self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
|
||||||
self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))
|
self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))
|
||||||
|
|
||||||
states = ["WAIT_START",
|
fsm = FSM()
|
||||||
"RCV_ADDRESS", "ACK_ADDRESS0", "ACK_ADDRESS1", "ACK_ADDRESS2",
|
|
||||||
"RCV_OFFSET", "ACK_OFFSET0", "ACK_OFFSET1", "ACK_OFFSET2",
|
|
||||||
"READ", "ACK_READ"]
|
|
||||||
fsm = FSM(*states)
|
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act(fsm.RCV_ADDRESS,
|
fsm.act("WAIT_START")
|
||||||
|
fsm.act("RCV_ADDRESS",
|
||||||
If(counter == 8,
|
If(counter == 8,
|
||||||
If(din[1:] == 0x50,
|
If(din[1:] == 0x50,
|
||||||
update_is_read.eq(1),
|
update_is_read.eq(1),
|
||||||
fsm.next_state(fsm.ACK_ADDRESS0)
|
NextState("ACK_ADDRESS0")
|
||||||
).Else(
|
).Else(
|
||||||
fsm.next_state(fsm.WAIT_START)
|
NextState("WAIT_START")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_ADDRESS0,
|
fsm.act("ACK_ADDRESS0",
|
||||||
If(~scl_i, fsm.next_state(fsm.ACK_ADDRESS1))
|
If(~scl_i, NextState("ACK_ADDRESS1"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_ADDRESS1,
|
fsm.act("ACK_ADDRESS1",
|
||||||
zero_drv.eq(1),
|
zero_drv.eq(1),
|
||||||
If(scl_i, fsm.next_state(fsm.ACK_ADDRESS2))
|
If(scl_i, NextState("ACK_ADDRESS2"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_ADDRESS2,
|
fsm.act("ACK_ADDRESS2",
|
||||||
zero_drv.eq(1),
|
zero_drv.eq(1),
|
||||||
If(~scl_i,
|
If(~scl_i,
|
||||||
If(is_read,
|
If(is_read,
|
||||||
fsm.next_state(fsm.READ)
|
NextState("READ")
|
||||||
).Else(
|
).Else(
|
||||||
fsm.next_state(fsm.RCV_OFFSET)
|
NextState("RCV_OFFSET")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act(fsm.RCV_OFFSET,
|
fsm.act("RCV_OFFSET",
|
||||||
If(counter == 8,
|
If(counter == 8,
|
||||||
oc_load.eq(1),
|
oc_load.eq(1),
|
||||||
fsm.next_state(fsm.ACK_OFFSET0)
|
NextState("ACK_OFFSET0")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_OFFSET0,
|
fsm.act("ACK_OFFSET0",
|
||||||
If(~scl_i, fsm.next_state(fsm.ACK_OFFSET1))
|
If(~scl_i, NextState("ACK_OFFSET1"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_OFFSET1,
|
fsm.act("ACK_OFFSET1",
|
||||||
zero_drv.eq(1),
|
zero_drv.eq(1),
|
||||||
If(scl_i, fsm.next_state(fsm.ACK_OFFSET2))
|
If(scl_i, NextState("ACK_OFFSET2"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_OFFSET2,
|
fsm.act("ACK_OFFSET2",
|
||||||
zero_drv.eq(1),
|
zero_drv.eq(1),
|
||||||
If(~scl_i, fsm.next_state(fsm.RCV_ADDRESS))
|
If(~scl_i, NextState("RCV_ADDRESS"))
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act(fsm.READ,
|
fsm.act("READ",
|
||||||
If(~scl_i,
|
If(~scl_i,
|
||||||
If(counter == 8,
|
If(counter == 8,
|
||||||
data_drv_stop.eq(1),
|
data_drv_stop.eq(1),
|
||||||
fsm.next_state(fsm.ACK_READ)
|
NextState("ACK_READ")
|
||||||
).Else(
|
).Else(
|
||||||
data_drv_en.eq(1)
|
data_drv_en.eq(1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACK_READ,
|
fsm.act("ACK_READ",
|
||||||
If(scl_rising,
|
If(scl_rising,
|
||||||
oc_inc.eq(1),
|
oc_inc.eq(1),
|
||||||
If(sda_i,
|
If(sda_i,
|
||||||
fsm.next_state(fsm.WAIT_START)
|
NextState("WAIT_START")
|
||||||
).Else(
|
).Else(
|
||||||
fsm.next_state(fsm.READ)
|
NextState("READ")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for state in states:
|
for state in fsm.actions.keys():
|
||||||
fsm.act(getattr(fsm, state), If(start, fsm.next_state(fsm.RCV_ADDRESS)))
|
fsm.act(state, If(start, NextState("RCV_ADDRESS")))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.bus.asmibus import *
|
from migen.bus.asmibus import *
|
||||||
from migen.genlib.roundrobin import *
|
from migen.genlib.roundrobin import *
|
||||||
from migen.genlib.fsm import FSM
|
from migen.genlib.fsm import FSM, NextState
|
||||||
from migen.genlib.misc import optree
|
from migen.genlib.misc import optree
|
||||||
from migen.genlib.fifo import SyncFIFO
|
from migen.genlib.fifo import SyncFIFO
|
||||||
|
|
||||||
|
@ -91,14 +91,13 @@ class BankMachine(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# Control and command generation FSM
|
# Control and command generation FSM
|
||||||
fsm = FSM("REGULAR", "PRECHARGE", "ACTIVATE", "REFRESH", delayed_enters=[
|
fsm = FSM()
|
||||||
("TRP", "ACTIVATE", timing_settings.tRP-1),
|
|
||||||
("TRCD", "REGULAR", timing_settings.tRCD-1)
|
|
||||||
])
|
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
fsm.act(fsm.REGULAR,
|
fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
|
||||||
|
fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD-1)
|
||||||
|
fsm.act("REGULAR",
|
||||||
If(self.refresh_req,
|
If(self.refresh_req,
|
||||||
fsm.next_state(fsm.REFRESH)
|
NextState("REFRESH")
|
||||||
).Elif(self.req_fifo.readable,
|
).Elif(self.req_fifo.readable,
|
||||||
If(has_openrow,
|
If(has_openrow,
|
||||||
If(hit,
|
If(hit,
|
||||||
|
@ -110,34 +109,34 @@ class BankMachine(Module):
|
||||||
self.cmd.cas_n.eq(0),
|
self.cmd.cas_n.eq(0),
|
||||||
self.cmd.we_n.eq(~reqf.we)
|
self.cmd.we_n.eq(~reqf.we)
|
||||||
).Else(
|
).Else(
|
||||||
fsm.next_state(fsm.PRECHARGE)
|
NextState("PRECHARGE")
|
||||||
)
|
)
|
||||||
).Else(
|
).Else(
|
||||||
fsm.next_state(fsm.ACTIVATE)
|
NextState("ACTIVATE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.PRECHARGE,
|
fsm.act("PRECHARGE",
|
||||||
# Notes:
|
# Notes:
|
||||||
# 1. we are presenting the column address, A10 is always low
|
# 1. we are presenting the column address, A10 is always low
|
||||||
# 2. since we always go to the ACTIVATE state, we do not need
|
# 2. since we always go to the ACTIVATE state, we do not need
|
||||||
# to assert track_close.
|
# to assert track_close.
|
||||||
If(precharge_ok,
|
If(precharge_ok,
|
||||||
self.cmd.stb.eq(1),
|
self.cmd.stb.eq(1),
|
||||||
If(self.cmd.ack, fsm.next_state(fsm.TRP)),
|
If(self.cmd.ack, NextState("TRP")),
|
||||||
self.cmd.ras_n.eq(0),
|
self.cmd.ras_n.eq(0),
|
||||||
self.cmd.we_n.eq(0)
|
self.cmd.we_n.eq(0)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.ACTIVATE,
|
fsm.act("ACTIVATE",
|
||||||
s_row_adr.eq(1),
|
s_row_adr.eq(1),
|
||||||
track_open.eq(1),
|
track_open.eq(1),
|
||||||
self.cmd.stb.eq(1),
|
self.cmd.stb.eq(1),
|
||||||
If(self.cmd.ack, fsm.next_state(fsm.TRCD)),
|
If(self.cmd.ack, NextState("TRCD")),
|
||||||
self.cmd.ras_n.eq(0)
|
self.cmd.ras_n.eq(0)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.REFRESH,
|
fsm.act("REFRESH",
|
||||||
self.refresh_gnt.eq(precharge_ok),
|
self.refresh_gnt.eq(precharge_ok),
|
||||||
track_close.eq(1),
|
track_close.eq(1),
|
||||||
If(~self.refresh_req, fsm.next_state(fsm.REGULAR))
|
If(~self.refresh_req, NextState("REGULAR"))
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.genlib.roundrobin import *
|
from migen.genlib.roundrobin import *
|
||||||
from migen.genlib.misc import optree
|
from migen.genlib.misc import optree
|
||||||
from migen.genlib.fsm import FSM
|
from migen.genlib.fsm import FSM, NextState
|
||||||
from migen.bank.description import AutoCSR
|
from migen.bank.description import AutoCSR
|
||||||
|
|
||||||
from milkymist.lasmicon.perf import Bandwidth
|
from milkymist.lasmicon.perf import Bandwidth
|
||||||
|
@ -147,12 +147,11 @@ class Multiplexer(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
# Control FSM
|
# Control FSM
|
||||||
fsm = FSM("READ", "WRITE", "REFRESH", delayed_enters=[
|
fsm = FSM()
|
||||||
("RTW", "WRITE", timing_settings.read_latency-1),
|
|
||||||
("WTR", "READ", timing_settings.tWTR-1)
|
|
||||||
])
|
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
fsm.act(fsm.READ,
|
fsm.delayed_enter("RTW", "WRITE", timing_settings.read_latency-1)
|
||||||
|
fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
|
||||||
|
fsm.act("READ",
|
||||||
read_time_en.eq(1),
|
read_time_en.eq(1),
|
||||||
choose_req.want_reads.eq(1),
|
choose_req.want_reads.eq(1),
|
||||||
choose_cmd.cmd.ack.eq(1),
|
choose_cmd.cmd.ack.eq(1),
|
||||||
|
@ -161,11 +160,11 @@ class Multiplexer(Module, AutoCSR):
|
||||||
steerer.sel[phy_settings.rdphase].eq(STEER_REQ),
|
steerer.sel[phy_settings.rdphase].eq(STEER_REQ),
|
||||||
If(write_available,
|
If(write_available,
|
||||||
# TODO: switch only after several cycles of ~read_available?
|
# TODO: switch only after several cycles of ~read_available?
|
||||||
If(~read_available | max_read_time, fsm.next_state(fsm.RTW))
|
If(~read_available | max_read_time, NextState("RTW"))
|
||||||
),
|
),
|
||||||
If(go_to_refresh, fsm.next_state(fsm.REFRESH))
|
If(go_to_refresh, NextState("REFRESH"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.WRITE,
|
fsm.act("WRITE",
|
||||||
write_time_en.eq(1),
|
write_time_en.eq(1),
|
||||||
choose_req.want_writes.eq(1),
|
choose_req.want_writes.eq(1),
|
||||||
choose_cmd.cmd.ack.eq(1),
|
choose_cmd.cmd.ack.eq(1),
|
||||||
|
@ -173,15 +172,16 @@ class Multiplexer(Module, AutoCSR):
|
||||||
steerer.sel[1-phy_settings.wrphase].eq(STEER_CMD),
|
steerer.sel[1-phy_settings.wrphase].eq(STEER_CMD),
|
||||||
steerer.sel[phy_settings.wrphase].eq(STEER_REQ),
|
steerer.sel[phy_settings.wrphase].eq(STEER_REQ),
|
||||||
If(read_available,
|
If(read_available,
|
||||||
If(~write_available | max_write_time, fsm.next_state(fsm.WTR))
|
If(~write_available | max_write_time, NextState("WTR"))
|
||||||
),
|
),
|
||||||
If(go_to_refresh, fsm.next_state(fsm.REFRESH))
|
If(go_to_refresh, NextState("REFRESH"))
|
||||||
)
|
)
|
||||||
fsm.act(fsm.REFRESH,
|
fsm.act("REFRESH",
|
||||||
steerer.sel[0].eq(STEER_REFRESH),
|
steerer.sel[0].eq(STEER_REFRESH),
|
||||||
If(~refresher.req, fsm.next_state(fsm.READ))
|
If(~refresher.req, NextState("READ"))
|
||||||
)
|
)
|
||||||
# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
|
# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
|
||||||
self.comb += refresher.ack.eq(fsm._state == fsm.REFRESH)
|
fsm.finalize()
|
||||||
|
self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"])
|
||||||
|
|
||||||
self.submodules.bandwidth = Bandwidth(choose_req.cmd)
|
self.submodules.bandwidth = Bandwidth(choose_req.cmd)
|
||||||
|
|
|
@ -52,17 +52,17 @@ class Refresher(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# Control FSM
|
# Control FSM
|
||||||
fsm = FSM("IDLE", "WAIT_GRANT", "WAIT_SEQ")
|
fsm = FSM()
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
fsm.act(fsm.IDLE, If(start, fsm.next_state(fsm.WAIT_GRANT)))
|
fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
|
||||||
fsm.act(fsm.WAIT_GRANT,
|
fsm.act("WAIT_GRANT",
|
||||||
self.req.eq(1),
|
self.req.eq(1),
|
||||||
If(self.ack,
|
If(self.ack,
|
||||||
seq_start.eq(1),
|
seq_start.eq(1),
|
||||||
fsm.next_state(fsm.WAIT_SEQ)
|
NextState("WAIT_SEQ")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act(fsm.WAIT_SEQ,
|
fsm.act("WAIT_SEQ",
|
||||||
self.req.eq(1),
|
self.req.eq(1),
|
||||||
If(seq_done, fsm.next_state(fsm.IDLE))
|
If(seq_done, NextState("IDLE"))
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue