871d087b6237dbf7d116df3c5149ef26a2146eec
1 from functools
import reduce
2 from operator
import or_
5 from migen
.genlib
.fsm
import FSM
, NextState
6 from migen
.genlib
.misc
import WaitTimer
8 from misoc
.interconnect
import dfi
as dfibus
9 from misoc
.interconnect
import wishbone
13 def __init__(self
, colbits
, bankbits
, rowbits
, address_align
):
14 self
.colbits
= colbits
15 self
.bankbits
= bankbits
16 self
.rowbits
= rowbits
17 self
.address_align
= address_align
18 self
.addressbits
= colbits
- address_align
+ bankbits
+ rowbits
20 def row(self
, address
):
21 split
= self
.bankbits
+ self
.colbits
- self
.address_align
22 if isinstance(address
, int):
23 return address
>> split
25 return address
[split
:self
.addressbits
]
27 def bank(self
, address
):
28 split
= self
.colbits
- self
.address_align
29 if isinstance(address
, int):
30 return (address
& (2**(split
+ self
.bankbits
) - 1)) >> split
32 return address
[split
:split
+self
.bankbits
]
34 def col(self
, address
):
35 split
= self
.colbits
- self
.address_align
36 if isinstance(address
, int):
37 return (address
& (2**split
- 1)) << self
.address_align
39 return Cat(Replicate(0, self
.address_align
), address
[:split
])
45 def __init__(self
, geom_settings
):
47 self
.row
= Signal(geom_settings
.rowbits
)
49 self
.idle
= Signal(reset
=1)
54 row
= Signal(geom_settings
.rowbits
)
60 self
.comb
+= self
.hit
.eq(~self
.idle
& (self
.row
== row
))
63 class Minicon(Module
):
64 def __init__(self
, phy_settings
, geom_settings
, timing_settings
):
65 if phy_settings
.memtype
in ["SDR"]:
66 burst_length
= phy_settings
.nphases
*1 # command multiplication*SDR
67 elif phy_settings
.memtype
in ["DDR", "LPDDR", "DDR2", "DDR3"]:
68 burst_length
= phy_settings
.nphases
*2 # command multiplication*DDR
69 burst_width
= phy_settings
.dfi_databits
*phy_settings
.nphases
70 address_align
= log2_int(burst_length
)
74 self
.dfi
= dfi
= dfibus
.Interface(geom_settings
.addressbits
,
75 geom_settings
.bankbits
,
76 phy_settings
.dfi_databits
,
79 self
.bus
= bus
= wishbone
.Interface(burst_width
)
81 rdphase
= phy_settings
.rdphase
82 wrphase
= phy_settings
.wrphase
84 precharge_all
= Signal()
90 # Compute current column, bank and row from wishbone address
91 slicer
= _AddressSlicer(geom_settings
.colbits
,
92 geom_settings
.bankbits
,
93 geom_settings
.rowbits
,
101 for i
in range(2**geom_settings
.bankbits
):
102 bank
= _Bank(geom_settings
)
104 bank
.open.eq(activate
),
105 bank
.reset
.eq(precharge_all
),
106 bank
.row
.eq(slicer
.row(bus
.adr
))
109 self
.submodules
+= banks
112 for i
, bank
in enumerate(banks
):
113 cases
[i
] = [bank
.ce
.eq(1)]
114 self
.comb
+= Case(slicer
.bank(bus
.adr
), cases
)
117 bank_hit
.eq(reduce(or_
, [bank
.hit
& bank
.ce
for bank
in banks
])),
118 bank_idle
.eq(reduce(or_
, [bank
.idle
& bank
.ce
for bank
in banks
])),
122 write2precharge_timer
= WaitTimer(2 + timing_settings
.tWR
- 1)
123 self
.submodules
+= write2precharge_timer
124 self
.comb
+= write2precharge_timer
.wait
.eq(~write
)
126 refresh_timer
= WaitTimer(timing_settings
.tREFI
)
127 self
.submodules
+= refresh_timer
128 self
.comb
+= refresh_timer
.wait
.eq(~refresh
)
131 self
.submodules
.fsm
= fsm
= FSM()
133 If(refresh_timer
.done
,
134 NextState("PRECHARGE-ALL")
135 ).Elif(bus
.stb
& bus
.cyc
,
143 If(write2precharge_timer
.done
,
144 NextState("PRECHARGE")
147 NextState("ACTIVATE")
153 dfi
.phases
[rdphase
].ras_n
.eq(1),
154 dfi
.phases
[rdphase
].cas_n
.eq(0),
155 dfi
.phases
[rdphase
].we_n
.eq(1),
156 dfi
.phases
[rdphase
].rddata_en
.eq(1),
157 NextState("WAIT-READ-DONE"),
159 fsm
.act("WAIT-READ-DONE",
160 If(dfi
.phases
[rdphase
].rddata_valid
,
167 dfi
.phases
[wrphase
].ras_n
.eq(1),
168 dfi
.phases
[wrphase
].cas_n
.eq(0),
169 dfi
.phases
[wrphase
].we_n
.eq(0),
170 dfi
.phases
[wrphase
].wrdata_en
.eq(1),
171 NextState("WRITE-LATENCY")
177 fsm
.act("PRECHARGE-ALL",
179 dfi
.phases
[rdphase
].ras_n
.eq(0),
180 dfi
.phases
[rdphase
].cas_n
.eq(1),
181 dfi
.phases
[rdphase
].we_n
.eq(0),
182 NextState("PRE-REFRESH")
185 # do no reset bank since we are going to re-open it
186 dfi
.phases
[0].ras_n
.eq(0),
187 dfi
.phases
[0].cas_n
.eq(1),
188 dfi
.phases
[0].we_n
.eq(0),
193 dfi
.phases
[0].ras_n
.eq(0),
194 dfi
.phases
[0].cas_n
.eq(1),
195 dfi
.phases
[0].we_n
.eq(1),
200 dfi
.phases
[rdphase
].ras_n
.eq(0),
201 dfi
.phases
[rdphase
].cas_n
.eq(0),
202 dfi
.phases
[rdphase
].we_n
.eq(1),
203 NextState("POST-REFRESH")
205 fsm
.delayed_enter("WRITE-LATENCY", "WRITE-ACK", phy_settings
.write_latency
-1)
206 fsm
.delayed_enter("TRP", "ACTIVATE", timing_settings
.tRP
-1)
207 fsm
.delayed_enter("TRCD", "IDLE", timing_settings
.tRCD
-1)
208 fsm
.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings
.tRP
-1)
209 fsm
.delayed_enter("POST-REFRESH", "IDLE", timing_settings
.tRFC
-1)
212 for phase
in dfi
.phases
:
213 if hasattr(phase
, "reset_n"):
214 self
.comb
+= phase
.reset_n
.eq(1)
215 if hasattr(phase
, "odt"):
216 self
.comb
+= phase
.odt
.eq(1)
220 phase
.bank
.eq(slicer
.bank(bus
.adr
)),
222 phase
.address
.eq(2**10)
224 phase
.address
.eq(slicer
.row(bus
.adr
))
226 phase
.address
.eq(slicer
.col(bus
.adr
))
232 bus
.dat_r
.eq(Cat(phase
.rddata
for phase
in dfi
.phases
)),
233 Cat(phase
.wrdata
for phase
in dfi
.phases
).eq(bus
.dat_w
),
234 Cat(phase
.wrdata_mask
for phase
in dfi
.phases
).eq(~bus
.sel
),