853e7d9aa42b751aefb5c90e11bd688e7fa28abc
2 from migen
.genlib
.roundrobin
import *
3 from migen
.genlib
.fsm
import FSM
, NextState
4 from migen
.genlib
.fifo
import SyncFIFO
6 from misoc
.cores
.lasmicon
.multiplexer
import *
10 def __init__(self
, colbits
, address_align
):
11 self
.colbits
= colbits
12 self
.address_align
= address_align
14 def row(self
, address
):
15 split
= self
.colbits
- self
.address_align
16 if isinstance(address
, int):
17 return address
>> split
19 return address
[split
:]
21 def col(self
, address
):
22 split
= self
.colbits
- self
.address_align
23 if isinstance(address
, int):
24 return (address
& (2**split
- 1)) << self
.address_align
26 return Cat(Replicate(0, self
.address_align
), address
[:split
])
29 class BankMachine(Module
):
30 def __init__(self
, geom_settings
, timing_settings
, controller_settings
, address_align
, bankn
, req
):
31 self
.refresh_req
= Signal()
32 self
.refresh_gnt
= Signal()
33 self
.cmd
= CommandRequestRW(geom_settings
.addressbits
, geom_settings
.bankbits
)
38 layout
= [("we", 1), ("adr", len(req
.adr
))]
39 req_in
= Record(layout
)
41 self
.submodules
.req_fifo
= SyncFIFO(layout_len(layout
),
42 controller_settings
.req_queue_size
)
44 self
.req_fifo
.din
.eq(req_in
.raw_bits()),
45 reqf
.raw_bits().eq(self
.req_fifo
.dout
)
49 req_in
.adr
.eq(req
.adr
),
50 self
.req_fifo
.we
.eq(req
.stb
),
51 req
.req_ack
.eq(self
.req_fifo
.writable
),
53 self
.req_fifo
.re
.eq(req
.dat_w_ack | req
.dat_r_ack
),
54 req
.lock
.eq(self
.req_fifo
.readable
)
57 slicer
= _AddressSlicer(geom_settings
.colbits
, address_align
)
60 has_openrow
= Signal()
61 openrow
= Signal(geom_settings
.rowbits
)
63 self
.comb
+= hit
.eq(openrow
== slicer
.row(reqf
.adr
))
65 track_close
= Signal()
69 openrow
.eq(slicer
.row(reqf
.adr
))
79 self
.cmd
.ba
.eq(bankn
),
81 self
.cmd
.a
.eq(slicer
.row(reqf
.adr
))
83 self
.cmd
.a
.eq(slicer
.col(reqf
.adr
))
87 # Respect write-to-precharge specification
88 precharge_ok
= Signal()
89 t_unsafe_precharge
= 2 + timing_settings
.tWR
- 1
90 unsafe_precharge_count
= Signal(max=t_unsafe_precharge
+1)
91 self
.comb
+= precharge_ok
.eq(unsafe_precharge_count
== 0)
93 If(self
.cmd
.stb
& self
.cmd
.ack
& self
.cmd
.is_write
,
94 unsafe_precharge_count
.eq(t_unsafe_precharge
)
96 unsafe_precharge_count
.eq(unsafe_precharge_count
-1)
100 # Control and command generation FSM
102 self
.submodules
+= fsm
106 ).Elif(self
.req_fifo
.readable
,
109 # NB: write-to-read specification is enforced by multiplexer
111 req
.dat_w_ack
.eq(self
.cmd
.ack
& reqf
.we
),
112 req
.dat_r_ack
.eq(self
.cmd
.ack
& ~reqf
.we
),
113 self
.cmd
.is_read
.eq(~reqf
.we
),
114 self
.cmd
.is_write
.eq(reqf
.we
),
115 self
.cmd
.cas_n
.eq(0),
116 self
.cmd
.we_n
.eq(~reqf
.we
)
118 NextState("PRECHARGE")
121 NextState("ACTIVATE")
127 # 1. we are presenting the column address, A10 is always low
128 # 2. since we always go to the ACTIVATE state, we do not need
129 # to assert track_close.
132 If(self
.cmd
.ack
, NextState("TRP")),
133 self
.cmd
.ras_n
.eq(0),
135 self
.cmd
.is_cmd
.eq(1)
142 self
.cmd
.is_cmd
.eq(1),
143 If(self
.cmd
.ack
, NextState("TRCD")),
147 self
.refresh_gnt
.eq(precharge_ok
),
149 self
.cmd
.is_cmd
.eq(1),
150 If(~self
.refresh_req
, NextState("REGULAR"))
152 fsm
.delayed_enter("TRP", "ACTIVATE", timing_settings
.tRP
-1)
153 fsm
.delayed_enter("TRCD", "REGULAR", timing_settings
.tRCD
-1)