114a539713141d3a5d41c8798836112a07293eb5
1 from migen
.fhdl
.std
import *
2 from migen
.genlib
.fsm
import FSM
, NextState
3 from migen
.bank
.description
import *
4 from migen
.bank
.eventmanager
import *
5 from migen
.flow
.actor
import *
6 from migen
.actorlib
import dma_lasmi
8 # Slot status: EMPTY=0 LOADED=1 PENDING=2
9 class _Slot(Module
, AutoCSR
):
10 def __init__(self
, addr_bits
, alignment_bits
):
11 self
.ev_source
= EventSourceLevel()
12 self
.address
= Signal(addr_bits
)
13 self
.address_reached
= Signal(addr_bits
)
14 self
.address_valid
= Signal()
15 self
.address_done
= Signal()
17 self
._r
_status
= CSRStorage(2, write_from_dev
=True)
18 self
._r
_address
= CSRStorage(addr_bits
+ alignment_bits
, alignment_bits
=alignment_bits
, write_from_dev
=True)
23 self
.address
.eq(self
._r
_address
.storage
),
24 self
.address_valid
.eq(self
._r
_status
.storage
[0]),
25 self
._r
_status
.dat_w
.eq(2),
26 self
._r
_status
.we
.eq(self
.address_done
),
27 self
._r
_address
.dat_w
.eq(self
.address_reached
),
28 self
._r
_address
.we
.eq(self
.address_done
),
29 self
.ev_source
.trigger
.eq(self
._r
_status
.storage
[1])
32 class _SlotArray(Module
, AutoCSR
):
33 def __init__(self
, nslots
, addr_bits
, alignment_bits
):
34 self
.submodules
.ev
= EventManager()
35 self
.address
= Signal(addr_bits
)
36 self
.address_reached
= Signal(addr_bits
)
37 self
.address_valid
= Signal()
38 self
.address_done
= Signal()
42 slots
= [_Slot(addr_bits
, alignment_bits
) for i
in range(nslots
)]
43 for n
, slot
in enumerate(slots
):
44 setattr(self
.submodules
, "slot"+str(n
), slot
)
45 setattr(self
.ev
, "slot"+str(n
), slot
.ev_source
)
48 change_slot
= Signal()
49 current_slot
= Signal(max=nslots
)
50 self
.sync
+= If(change_slot
, [If(slot
.address_valid
, current_slot
.eq(n
)) for n
, slot
in reversed(list(enumerate(slots
)))])
51 self
.comb
+= change_slot
.eq(~self
.address_valid | self
.address_done
)
54 self
.address
.eq(Array(slot
.address
for slot
in slots
)[current_slot
]),
55 self
.address_valid
.eq(Array(slot
.address_valid
for slot
in slots
)[current_slot
])
57 self
.comb
+= [slot
.address_reached
.eq(self
.address_reached
) for slot
in slots
]
58 self
.comb
+= [slot
.address_done
.eq(self
.address_done
& (current_slot
== n
)) for n
, slot
in enumerate(slots
)]
61 def __init__(self
, lasmim
, nslots
):
64 alignment_bits
= bits_for(bus_dw
//8) - 1
66 fifo_word_width
= 24*bus_dw
//32
67 self
.frame
= Sink([("sof", 1), ("pixels", fifo_word_width
)])
68 self
._r
_frame
_size
= CSRStorage(bus_aw
+ alignment_bits
, alignment_bits
=alignment_bits
)
69 self
.submodules
._slot
_array
= _SlotArray(nslots
, bus_aw
, alignment_bits
)
70 self
.ev
= self
._slot
_array
.ev
74 # address generator + maximum memory word count to prevent DMA buffer overrun
75 reset_words
= Signal()
78 current_address
= Signal(bus_aw
)
79 mwords_remaining
= Signal(bus_aw
)
81 self
._slot
_array
.address_reached
.eq(current_address
),
82 last_word
.eq(mwords_remaining
== 1)
86 current_address
.eq(self
._slot
_array
.address
),
87 mwords_remaining
.eq(self
._r
_frame
_size
.storage
)
89 current_address
.eq(current_address
+ 1),
90 mwords_remaining
.eq(mwords_remaining
- 1)
95 memory_word
= Signal(bus_dw
)
97 for i
in range(bus_dw
//32):
100 pixbits
.append(self
.frame
.payload
.pixels
[b
+6:b
+8])
101 pixbits
.append(self
.frame
.payload
.pixels
[b
:b
+8])
104 self
.comb
+= memory_word
.eq(Cat(*pixbits
))
107 self
.submodules
._bus
_accessor
= dma_lasmi
.Writer(lasmim
)
109 self
._bus
_accessor
.address_data
.payload
.a
.eq(current_address
),
110 self
._bus
_accessor
.address_data
.payload
.d
.eq(memory_word
)
115 self
.submodules
+= fsm
119 self
.frame
.ack
.eq(~self
._slot
_array
.address_valid | ~self
.frame
.payload
.sof
),
120 If(self
._slot
_array
.address_valid
& self
.frame
.payload
.sof
& self
.frame
.stb
, NextState("TRANSFER_PIXELS"))
122 fsm
.act("TRANSFER_PIXELS",
123 self
.frame
.ack
.eq(self
._bus
_accessor
.address_data
.ack
),
125 self
._bus
_accessor
.address_data
.stb
.eq(1),
126 If(self
._bus
_accessor
.address_data
.ack
,
128 If(last_word
, NextState("EOF"))
133 If(~self
._bus
_accessor
.busy
,
134 self
._slot
_array
.address_done
.eq(1),
135 NextState("WAIT_SOF")
140 return [self
._r
_frame
_size
] + self
._slot
_array
.get_csrs()