Skip to content

Commit 633a5f9

Browse files
committed
soc/hps*.py: Add Wishbone burst support to NXLRAM interface
This commit adds support for incrementing address burst cycles in NXLRAM Wishbone interface. Ported from enjoy-digital/litex#1267 Signed-off-by: Rafal Kolucki <[email protected]>
1 parent 36bd969 commit 633a5f9

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

soc/hps_lattice_nx.py

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def initval_parameters(contents, width):
7979
class NXLRAM(Module):
8080
def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
8181
self.bus = wishbone.Interface(width)
82+
bus_bursting = True
8283
assert width in [32, 64]
8384
self.width = width
8485
self.size = size
@@ -115,6 +116,81 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
115116
print("sel_bits_start ", sel_bits_start)
116117
print("adr_bits_start ", adr_bits_start)
117118

119+
# # #
120+
121+
adr_burst = Signal()
122+
123+
# Incrementing address burst cycles support - address generator
124+
125+
if bus_bursting:
126+
adr_wrap_mask = Array((0b0000, 0b0011, 0b0111, 0b1111))
127+
adr_wrap_max = adr_wrap_mask[-1].bit_length()
128+
129+
adr_latched = Signal()
130+
131+
adr_counter = Signal(len(self.bus.adr))
132+
adr_counter_base = Signal(len(self.bus.adr))
133+
adr_counter_offset = Signal(adr_wrap_max)
134+
adr_offset_lsb = Signal(adr_wrap_max)
135+
adr_offset_msb = Signal(len(self.bus.adr))
136+
137+
adr_next = Signal(len(self.bus.adr))
138+
139+
# Only incrementing burst cycles are supported
140+
self.comb += [
141+
Case(self.bus.cti, {
142+
# incrementing address burst cycle
143+
0b010: adr_burst.eq(1),
144+
# end current burst cycle
145+
0b111: adr_burst.eq(0),
146+
# unsupported burst cycle
147+
"default": adr_burst.eq(0)
148+
}),
149+
adr_counter_base.eq(
150+
Cat(self.bus.adr & ~adr_wrap_mask[self.bus.bte],
151+
self.bus.adr[adr_wrap_max:]
152+
)
153+
)
154+
]
155+
156+
# Latch initial address - initial address without wrapping bits and wrap offset
157+
self.sync += [
158+
If(self.bus.cyc & self.bus.stb & adr_burst,
159+
adr_latched.eq(1),
160+
# latch initial address, then increment it every clock cycle
161+
If(adr_latched,
162+
adr_counter.eq(adr_counter + 1)
163+
).Else(
164+
adr_counter_offset.eq(self.bus.adr & adr_wrap_mask[self.bus.bte]),
165+
adr_counter.eq(adr_counter_base +
166+
Cat(~self.bus.we, Replicate(0, len(adr_counter)-1))
167+
),
168+
),
169+
If(self.bus.cti == 0b111,
170+
adr_latched.eq(0),
171+
adr_counter.eq(0),
172+
adr_counter_offset.eq(0)
173+
)
174+
).Else(
175+
adr_latched.eq(0),
176+
adr_counter.eq(0),
177+
adr_counter_offset.eq(0)
178+
),
179+
]
180+
181+
# Next address = sum of counter value without wrapped bits
182+
# and wrapped counter bits with offset
183+
self.comb += [
184+
adr_offset_lsb.eq((adr_counter + adr_counter_offset) & adr_wrap_mask[self.bus.bte]),
185+
adr_offset_msb.eq(adr_counter & ~adr_wrap_mask[self.bus.bte]),
186+
adr_next.eq(adr_offset_msb + adr_offset_lsb)
187+
]
188+
189+
else: # bus_bursting = False
190+
self.comb += adr_burst.eq(0)
191+
192+
# # #
193+
118194
if dual_port:
119195
self.b_addrs = []
120196
self.b_douts = []
@@ -124,6 +200,7 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
124200
self.lram_blocks.append([])
125201
# Combine RAMs to increase Width.
126202
for w in range(self.width_cascading):
203+
address = Signal(self.width)
127204
datain = Signal(32)
128205
dataout = Signal(32)
129206
cs = Signal()
@@ -146,13 +223,19 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
146223
self.bus.dat_r[32*w:32*(w+1)].eq(dataout)
147224
]
148225

226+
self.comb += address.eq(self.bus.adr[adr_bits_start:adr_bits_start+14])
227+
if bus_bursting:
228+
self.comb += If(adr_burst & adr_latched,
229+
address.eq(adr_next[adr_bits_start:adr_bits_start+14]),
230+
)
231+
149232
if dual_port:
150233
b_addr = Signal(14)
151234
b_dout = Signal(32)
152235
lram_block = Instance("DPSC512K",
153236
p_ECC_BYTE_SEL = "BYTE_EN",
154237
i_DIA = datain,
155-
i_ADA = self.bus.adr[adr_bits_start:adr_bits_start+14],
238+
i_ADA = address,
156239
i_CLK = ClockSignal(),
157240
i_CEA = 0b1,
158241
i_WEA = wren,
@@ -177,7 +260,7 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
177260
lram_block = Instance("SP512K",
178261
p_ECC_BYTE_SEL = "BYTE_EN",
179262
i_DI = datain,
180-
i_AD = self.bus.adr[adr_bits_start:adr_bits_start+14],
263+
i_AD = address,
181264
i_CLK = ClockSignal(),
182265
i_CE = 0b1,
183266
i_WE = wren,
@@ -190,7 +273,7 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
190273
self.lram_blocks[d].append(lram_block)
191274
self.specials += lram_block
192275

193-
self.sync += self.bus.ack.eq(self.bus.stb & self.bus.cyc & ~self.bus.ack)
276+
self.sync += self.bus.ack.eq(self.bus.cyc & self.bus.stb & (~self.bus.ack | adr_burst))
194277

195278
if init != []:
196279
self.add_init(init)

0 commit comments

Comments
 (0)