Skip to content

Commit b53aa72

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 0de371e commit b53aa72

File tree

1 file changed

+90
-3
lines changed

1 file changed

+90
-3
lines changed

soc/hps_lattice_nx.py

Lines changed: 90 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 = False
8283
assert width in [32, 64]
8384
self.width = width
8485
self.size = size
@@ -115,6 +116,85 @@ 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 &
186+
Cat(~adr_wrap_mask[self.bus.bte], Replicate(1, len(adr_offset_msb)-len(adr_offset_lsb)))
187+
),
188+
adr_next.eq(adr_offset_msb +
189+
Cat(adr_offset_lsb, Replicate(0, len(adr_next) - len(adr_offset_lsb)))
190+
)
191+
]
192+
193+
else: # bus_bursting = False
194+
self.comb += adr_burst.eq(0)
195+
196+
# # #
197+
118198
if dual_port:
119199
self.b_addrs = []
120200
self.b_douts = []
@@ -124,6 +204,7 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
124204
self.lram_blocks.append([])
125205
# Combine RAMs to increase Width.
126206
for w in range(self.width_cascading):
207+
address = Signal(self.width)
127208
datain = Signal(32)
128209
dataout = Signal(32)
129210
cs = Signal()
@@ -146,13 +227,19 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
146227
self.bus.dat_r[32*w:32*(w+1)].eq(dataout)
147228
]
148229

230+
self.comb += address.eq(self.bus.adr[adr_bits_start:adr_bits_start+14])
231+
if bus_bursting:
232+
self.comb += If(adr_burst & adr_latched,
233+
address.eq(adr_next[adr_bits_start:adr_bits_start+14]),
234+
)
235+
149236
if dual_port:
150237
b_addr = Signal(14)
151238
b_dout = Signal(32)
152239
lram_block = Instance("DPSC512K",
153240
p_ECC_BYTE_SEL = "BYTE_EN",
154241
i_DIA = datain,
155-
i_ADA = self.bus.adr[adr_bits_start:adr_bits_start+14],
242+
i_ADA = address,
156243
i_CLK = ClockSignal(),
157244
i_CEA = 0b1,
158245
i_WEA = wren,
@@ -177,7 +264,7 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
177264
lram_block = Instance("SP512K",
178265
p_ECC_BYTE_SEL = "BYTE_EN",
179266
i_DI = datain,
180-
i_AD = self.bus.adr[adr_bits_start:adr_bits_start+14],
267+
i_AD = address,
181268
i_CLK = ClockSignal(),
182269
i_CE = 0b1,
183270
i_WE = wren,
@@ -190,7 +277,7 @@ def __init__(self, width=32, size=128*kB, dual_port=False, init=[]):
190277
self.lram_blocks[d].append(lram_block)
191278
self.specials += lram_block
192279

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

195282
if init != []:
196283
self.add_init(init)

0 commit comments

Comments
 (0)