8feab0069c33ae1e099eab1e827bdb7b89ce2267
2 from migen
.genlib
.fsm
import FSM
, NextState
4 from misoc
.interconnect
.csr
import *
5 from misoc
.interconnect
.csr_eventmanager
import *
7 # TODO: rewrite dma_lasmi module
8 # TODO: use stream packets to resync DMA
9 #from misoc.mem.sdram.frontend import dma_lasmi
12 # Slot status: EMPTY=0 LOADED=1 PENDING=2
13 class _Slot(Module
, AutoCSR
):
14 def __init__(self
, addr_bits
, alignment_bits
):
15 self
.ev_source
= EventSourceLevel()
16 self
.address
= Signal(addr_bits
)
17 self
.address_reached
= Signal(addr_bits
)
18 self
.address_valid
= Signal()
19 self
.address_done
= Signal()
21 self
._status
= CSRStorage(2, write_from_dev
=True)
22 self
._address
= CSRStorage(addr_bits
+ alignment_bits
, alignment_bits
=alignment_bits
, write_from_dev
=True)
27 self
.address
.eq(self
._address
.storage
),
28 self
.address_valid
.eq(self
._status
.storage
[0]),
29 self
._status
.dat_w
.eq(2),
30 self
._status
.we
.eq(self
.address_done
),
31 self
._address
.dat_w
.eq(self
.address_reached
),
32 self
._address
.we
.eq(self
.address_done
),
33 self
.ev_source
.trigger
.eq(self
._status
.storage
[1])
37 class _SlotArray(Module
, AutoCSR
):
38 def __init__(self
, nslots
, addr_bits
, alignment_bits
):
39 self
.submodules
.ev
= EventManager()
40 self
.address
= Signal(addr_bits
)
41 self
.address_reached
= Signal(addr_bits
)
42 self
.address_valid
= Signal()
43 self
.address_done
= Signal()
47 slots
= [_Slot(addr_bits
, alignment_bits
) for i
in range(nslots
)]
48 for n
, slot
in enumerate(slots
):
49 setattr(self
.submodules
, "slot"+str(n
), slot
)
50 setattr(self
.ev
, "slot"+str(n
), slot
.ev_source
)
53 change_slot
= Signal()
54 current_slot
= Signal(max=nslots
)
55 self
.sync
+= If(change_slot
, [If(slot
.address_valid
, current_slot
.eq(n
)) for n
, slot
in reversed(list(enumerate(slots
)))])
56 self
.comb
+= change_slot
.eq(~self
.address_valid | self
.address_done
)
59 self
.address
.eq(Array(slot
.address
for slot
in slots
)[current_slot
]),
60 self
.address_valid
.eq(Array(slot
.address_valid
for slot
in slots
)[current_slot
])
62 self
.comb
+= [slot
.address_reached
.eq(self
.address_reached
) for slot
in slots
]
63 self
.comb
+= [slot
.address_done
.eq(self
.address_done
& (current_slot
== n
)) for n
, slot
in enumerate(slots
)]
67 def __init__(self
, lasmim
, nslots
):
70 alignment_bits
= bits_for(bus_dw
//8) - 1
72 fifo_word_width
= 24*bus_dw
//32
73 self
.frame
= Sink([("sof", 1), ("pixels", fifo_word_width
)])
74 self
._frame
_size
= CSRStorage(bus_aw
+ alignment_bits
, alignment_bits
=alignment_bits
)
75 self
.submodules
._slot
_array
= _SlotArray(nslots
, bus_aw
, alignment_bits
)
76 self
.ev
= self
._slot
_array
.ev
80 # address generator + maximum memory word count to prevent DMA buffer overrun
81 reset_words
= Signal()
84 current_address
= Signal(bus_aw
)
85 mwords_remaining
= Signal(bus_aw
)
87 self
._slot
_array
.address_reached
.eq(current_address
),
88 last_word
.eq(mwords_remaining
== 1)
92 current_address
.eq(self
._slot
_array
.address
),
93 mwords_remaining
.eq(self
._frame
_size
.storage
)
95 current_address
.eq(current_address
+ 1),
96 mwords_remaining
.eq(mwords_remaining
- 1)
101 memory_word
= Signal(bus_dw
)
103 for i
in range(bus_dw
//32):
106 pixbits
.append(self
.frame
.pixels
[b
+6:b
+8])
107 pixbits
.append(self
.frame
.pixels
[b
:b
+8])
110 self
.comb
+= memory_word
.eq(Cat(*pixbits
))
113 self
.submodules
._bus
_accessor
= dma_lasmi
.Writer(lasmim
)
115 self
._bus
_accessor
.address_data
.a
.eq(current_address
),
116 self
._bus
_accessor
.address_data
.d
.eq(memory_word
)
121 self
.submodules
+= fsm
125 self
.frame
.ack
.eq(~self
._slot
_array
.address_valid | ~self
.frame
.sof
),
126 If(self
._slot
_array
.address_valid
& self
.frame
.sof
& self
.frame
.stb
, NextState("TRANSFER_PIXELS"))
128 fsm
.act("TRANSFER_PIXELS",
129 self
.frame
.ack
.eq(self
._bus
_accessor
.address_data
.ack
),
131 self
._bus
_accessor
.address_data
.stb
.eq(1),
132 If(self
._bus
_accessor
.address_data
.ack
,
134 If(last_word
, NextState("EOF"))
139 If(~self
._bus
_accessor
.busy
,
140 self
._slot
_array
.address_done
.eq(1),
141 NextState("WAIT_SOF")
146 return [self
._frame
_size
] + self
._slot
_array
.get_csrs()