@@ -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
296300class 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