Skip to content

Commit 8889903

Browse files
committed
wip: entire script of bee movie
1 parent 635ae2b commit 8889903

2 files changed

Lines changed: 4229 additions & 169 deletions

File tree

software/glasgow/gateware/hyperram.py

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,12 @@ class PHYx1(wiring.Component):
9090
"o": Out(StreamSignature(data.StructLayout({
9191
"mode": PHYMode,
9292
"data": 16,
93-
"mask": 2
93+
"mask": 2,
94+
"last": 1
9495
}))),
9596
"i": In(StreamSignature(data.StructLayout({
96-
"data": 16
97+
"data": 16,
98+
"last": 1 # o.last looped back
9799
})))
98100
})
99101

@@ -260,11 +262,13 @@ def elaborate(self, platform):
260262
pins_rwds_i_regl.eq(pins_rwds.i),
261263
]
262264
m.d.comb += [
265+
self.i.p.last.eq(o_p_reg.last),
263266
self.i.p.data.eq(Cat(pins_dq.i, pins_dq_i_regh)),
264267
self.i.valid.eq( Cat(pins_rwds.i, pins_rwds_i_regh) == 0b10),
265268
]
266269
with m.Else():
267270
m.d.comb += [
271+
self.i.p.last.eq(o_p_reg.last),
268272
self.i.p.data.eq(Cat(pins_dq_i_regl, pins_dq_i_regh)),
269273
self.i.valid.eq( Cat(pins_rwds_i_regl, pins_rwds_i_regh) == 0b10),
270274
]
@@ -290,7 +294,7 @@ def elaborate(self, platform):
290294
pins.ck_p.o1.eq(0),
291295
]
292296

293-
return m
297+
return ResetInserter(self.rst)(m)
294298

295299

296300
class Operation(enum.Enum, shape=1):
@@ -330,18 +334,19 @@ def __init__(self, phy):
330334
self.phy = phy
331335

332336
super().__init__(Signature({
333-
"control" : In(StreamSignature(data.StructLayout({
334-
"select" : range(self.phy.cs_count + 1),
335-
"cmd_addr" : CommandAddress,
336-
"latency" : range(3, 17),
337-
# "length" : range(TODO)
337+
"ctl": In(StreamSignature(data.StructLayout({
338+
"select" : range(self.phy.cs_count + 1),
339+
"cmd_addr" : CommandAddress,
340+
"latency" : range(0, 16 + 1)
341+
}))),
342+
"o": In(StreamSignature(data.StructLayout({
343+
"data" : 16,
344+
"mask" : 2,
345+
"last" : 1
338346
}))),
339-
"write" : In(StreamSignature(data.StructLayout({
340-
"data" : 16,
341-
"en" : 2,
342-
}), reset={"en": 0b11})),
343-
"read" : Out(StreamSignature(data.StructLayout({
344-
"data" : 16,
347+
"i": Out(StreamSignature(data.StructLayout({
348+
"data" : 16,
349+
"last" : 1
345350
})))
346351
}))
347352

@@ -352,39 +357,33 @@ def elaborate(self, platform):
352357
# The cycle counter performs double duty: it is used to time the Command/Address phase as
353358
# well as the Latency phase after it. The counting of latency cycles starts from the third
354359
# cycle of the Command/Address phase, so the counter starts at -1 to simplify comparisons.
355-
cycle = Signal(range(-1, 33), reset=-1)
360+
cycle = Signal(range(-1, 16 << 1 + 1), reset=-1)
356361

357362
# The latency must be doubled if RWDS is high after CS# assertion.
358-
latency = Signal.like(self.control.p.latency)
363+
latency = Signal.like(self.ctl.p.latency)
359364

360365
# The command/address word is latched and shifted.
361366
cmd_addr = Signal(48)
362367

363-
leds_o = Cat(platform.request("led", i).o for i in range(5))
364-
leds = Signal(5, reset_less=True)
365-
m.d.comb += leds_o.eq(leds)
366-
367368
with m.FSM():
368369
with m.State("Select"):
369370
m.d.comb += [
370371
phy.o.p.mode.eq(PHYMode.Select),
371-
phy.o.p.data.eq(self.control.p.select),
372-
phy.o.valid.eq(self.control.valid),
372+
phy.o.p.data.eq(self.ctl.p.select),
373+
phy.o.valid.eq(self.ctl.valid),
373374
]
374375
m.d.sync += [
375376
cycle.eq(cycle.reset),
376-
latency.eq(self.control.p.latency),
377-
cmd_addr.eq(self.control.p.cmd_addr),
377+
latency.eq(self.ctl.p.latency),
378+
cmd_addr.eq(self.ctl.p.cmd_addr),
378379
]
379-
with m.If(phy.o.ready & self.control.valid):
380+
with m.If(phy.o.ready & self.ctl.valid):
380381
m.next = "Latency"
381382

382383
with m.State("Latency"):
383384
m.d.comb += phy.i.ready.eq(1)
384385
with m.If(phy.i.valid):
385386
# If RWDS is asserted by the memory when it's selected, latency is doubled.
386-
with m.If(self.control.p.cmd_addr.operation == Operation.Write):
387-
m.d.sync += leds.eq(Cat(phy.i.p.data[0], leds))
388387
m.d.sync += latency.eq(Mux(phy.i.p.data[0], latency << 1, latency))
389388
m.next = "Command/Address"
390389

@@ -400,19 +399,26 @@ def elaborate(self, platform):
400399
cmd_addr.eq(Cat(C(0, 16), cmd_addr)),
401400
]
402401
with m.If(cycle == 1):
403-
with m.If(self.control.p.cmd_addr.operation == Operation.Write):
404-
with m.If(latency != 0):
405-
m.next = "Latency-Write"
406-
with m.Else():
407-
m.d.comb += self.control.ready.eq(1)
408-
m.next = "Write"
409-
with m.Else():
410-
# Although reads also have initial latency, it is not necessary to know
411-
# it in advance because toggling of RWDS unambiguously delimits data.
412-
# In addition it is also often not possible to know it in advance
413-
# because a read from the register with the initial latency value has
414-
# the same initial latency as any other read.
402+
m.d.comb += self.ctl.ready.eq(1) # Done processing the command.
403+
with m.If(self.ctl.p.cmd_addr.operation == Operation.Read):
404+
# Although reads have initial latency, it is not necessary to know it
405+
# in advance because toggling of RWDS unambiguously delimits data.
406+
# In addition, it is also not possible to know it in advance for reads
407+
# from the register space because the default value for the initial
408+
# latency value is not fixed, and there is no way to find it out other
409+
# than by reading CR0.
415410
m.next = "Latency-Read"
411+
with m.Elif(self.ctl.p.cmd_addr.address_space == AddressSpace.Memory):
412+
# Memory space writes generally have non-zero latency. Although
413+
# the HyperBus specification allows memory space writes with zero
414+
# latency, this is not generally used.
415+
m.next = "Latency-Write"
416+
with m.Else():
417+
# Register space writes generally have zero latency. Although
418+
# the HyperBus specification allows register space writes with non-zero
419+
# latency, this is not generally used, and writes to CR0 must have zero
420+
# latency or it would not be possible to set the initial latency value.
421+
m.next = "Write"
416422

417423
with m.State("Latency-Write"):
418424
m.d.comb += [
@@ -427,20 +433,19 @@ def elaborate(self, platform):
427433
with m.If(phy.o.ready):
428434
m.d.sync += cycle.eq(cycle + 1)
429435
with m.If(cycle == latency):
430-
m.d.comb += self.control.ready.eq(1)
431436
m.next = "Write"
432437

433438
with m.State("Write"):
434439
m.d.comb += [
435440
# Drive RWDS only if there was a turnaround time; do not drive it during
436441
# a zero-latency write.
437442
phy.o.p.mode.eq(Mux(latency != 0, PHYMode.Write, PHYMode.CmdAddr)),
438-
phy.o.p.data.eq(self.write.p.data),
439-
phy.o.p.mask.eq(~self.write.p.en),
440-
phy.o.valid.eq(1),
441-
self.write.ready.eq(phy.o.ready),
443+
phy.o.p.data.eq(self.o.p.data),
444+
phy.o.p.mask.eq(self.o.p.mask),
445+
phy.o.valid.eq(self.o.valid),
446+
self.o.ready.eq(phy.o.ready),
442447
]
443-
with m.If(self.control.valid):
448+
with m.If(self.o.valid & self.o.ready & self.o.p.last):
444449
m.next = "Deselect"
445450

446451
with m.State("Latency-Read"):
@@ -456,16 +461,23 @@ def elaborate(self, platform):
456461
# initial latency, there will be a 'high, low' transition at the beginning
457462
# that does not indicate a data word being read.
458463
with m.If(cycle == 3):
459-
m.d.comb += self.control.ready.eq(1)
460464
m.next = "Read"
461465

462466
with m.State("Read"):
467+
# `last` added and removed here
463468
m.d.comb += [
464469
phy.o.p.mode.eq(PHYMode.Read),
465-
phy.o.valid.eq(1),
470+
phy.o.p.last.eq(self.o.p.last),
471+
phy.o.valid.eq(self.o.valid),
472+
self.o.ready.eq(phy.o.ready),
473+
]
474+
m.d.comb += [
475+
self.i.p.data.eq(phy.i.p.data),
476+
self.i.p.last.eq(phy.i.p.last),
477+
self.i.valid.eq(phy.i.valid),
478+
phy.i.ready.eq(self.i.ready),
466479
]
467-
wiring.connect(m, wiring.flipped(self.read), phy.i)
468-
with m.If(self.control.valid):
480+
with m.If(self.i.valid & self.i.ready & self.i.p.last):
469481
m.next = "Deselect"
470482

471483
with m.State("Deselect"):

0 commit comments

Comments
 (0)