@@ -429,8 +429,8 @@ def __init__(self, jtag=None, device=None, data_width=8, clock_domain="sys", cha
429429
430430
431431 # JTAG TAP ---------------------------------------------------------------------------------
432+ jtag_tdi_delay = 0
432433 if jtag is None :
433- jtag_tdi_delay = 0
434434 # Xilinx.
435435 if XilinxJTAG .get_primitive (device ) is not None :
436436 jtag = XilinxJTAG (primitive = XilinxJTAG .get_primitive (device ), chain = chain )
@@ -504,15 +504,6 @@ def __init__(self, jtag=None, device=None, data_width=8, clock_domain="sys", cha
504504 # via sync.jtag outside the FSM, it only resets on the clock domain reset.
505505 ready = Signal ()
506506 update_ready = Signal ()
507- ready_value = Signal ()
508-
509- # TDO timing fix: The JTAGG primitive samples JTDO1 on the FALLING edge of TCK,
510- # but the FSM state changes on the RISING edge. By the falling edge, the FSM
511- # has already transitioned to the next state, so the wrong TDO value would be
512- # sampled. We use a registered TDO output that captures the value on the rising
513- # edge, so it's stable when sampled on the falling edge.
514- tdo_reg = Signal (reset = 1 ) # Start with ready=1 assumption
515- self .comb += jtag_tdo .eq (tdo_reg )
516507
517508 # Detect shift falling edge (transition from Shift-DR to Exit1-DR)
518509 # This is when the valid bit (bit9) is available but jtag.shift is already 0
@@ -526,68 +517,76 @@ def __init__(self, jtag=None, device=None, data_width=8, clock_domain="sys", cha
526517 fsm = ResetInserter ()(fsm )
527518 self .submodules += fsm
528519
529- # Only reset FSM on jtag.reset, NOT jtag.capture.
530- # Resetting on capture clears 'ready' before it can be shifted out.
531- self .comb += fsm .reset .eq (jtag .reset )
520+ # Reset FSM on both jtag.reset and jtag.capture to ensure the FSM
521+ # starts in XFER-READY at the beginning of each DR scan. The 'ready'
522+ # signal is updated outside the FSM (via sync.jtag), so it survives
523+ # FSM resets and is correctly output via combinational TDO.
524+ self .comb += fsm .reset .eq (jtag .reset | jtag .capture )
532525
533526 fsm .act ("XFER-READY" ,
534- If (jtag .capture ,
535- # On capture, prepare to output ready on next shift
536- NextValue (tdo_reg , ready ),
537- ),
527+ jtag_tdo .eq (ready ),
538528 If (jtag .shift ,
539529 sink .ready .eq (jtag_tdi ),
540530 NextValue (valid , sink .valid ),
541531 NextValue (data , sink .data ),
542532 NextValue (count , 0 ),
543- # Update tdo_reg to output ready (will be sampled on falling edge)
544- NextValue (tdo_reg , ready ),
545533 NextState ("XFER-DATA" )
546534 )
547535 )
548536 fsm .act ("XFER-DATA" ,
537+ jtag_tdo .eq (data [0 ]),
549538 If (jtag .shift ,
550539 NextValue (count , count + 1 ),
551- # Update tdo_reg to output current data bit BEFORE shifting
552- NextValue (tdo_reg , data [0 ]),
553540 NextValue (data , Cat (data [1 :], jtag_tdi )),
554- If (count == data_width ,
555- # After outputting all data bits, transition to XFER-VALID.
556- # The valid bit is output on the NEXT shift cycle.
557- # NOTE: We need data_width + 3 shift cycles total for the
558- # data_width + 2 bit wire format because the JTAGG primitive
559- # only captures TDO on falling edge in Shift-DR, and the last
560- # falling edge is in Exit1-DR (doesn't capture).
561- NextValue (tdo_reg , valid ),
541+ If (count == (data_width - 1 ),
562542 NextState ("XFER-VALID" )
563543 )
564544 )
565545 )
566546 fsm .act ("XFER-VALID" ,
567- # Stay in this state for one shift cycle to output valid bit.
568- # Then on the next shift, output padding bit (repeat of valid).
569- # The actual valid bit from host arrives on shift_falling when TAP exits Shift-DR.
547+ jtag_tdo .eq (valid ),
570548 If (jtag .shift ,
571- # We're still in Shift-DR, output padding (valid repeated)
572- NextValue (tdo_reg , valid ),
549+ NextValue (rx_valid_in , jtag_tdi ),
573550 NextState ("XFER-PADDING" )
574551 )
575552 )
576553 fsm .act ("XFER-PADDING" ,
577- # The valid bit arrives when jtag.shift goes low (TAP exits Shift-DR).
578- # We use the falling edge of shift to capture the valid bit from jtag_tdi.
554+ # Padding cycle: finalize the current word and return to XFER-READY.
555+ # rx_valid_in was registered in XFER-VALID; data holds the 8 RX bits.
556+ # Handle both concatenated scans (jtag.shift stays high) and individual
557+ # scans (shift_falling fires when TAP exits Shift-DR).
558+ If (jtag .shift ,
559+ update_rx .eq (1 ),
560+ update_ready .eq (1 ),
561+ NextState ("XFER-READY" )
562+ ),
579563 If (shift_falling ,
580- # Capture RX valid bit for update_rx trigger (combinatorial)
581- rx_valid_in .eq (jtag_tdi ),
582- # Trigger rx_valid/rx_data update (handled outside FSM)
583564 update_rx .eq (1 ),
584- # Update tdo_reg to output valid
585- NextValue (tdo_reg , valid ),
586- update_ready .eq (1 ), # Trigger ready update (outside FSM)
565+ update_ready .eq (1 ),
587566 NextState ("XFER-READY" )
588567 )
589568 )
590569
570+ # RX path - connect to CDC FIFO write side.
571+ self .comb += [
572+ source .valid .eq (rx_valid ),
573+ source .data .eq (rx_data ),
574+ ]
575+
576+ # Update ready from FIFO writable (outside FSM, survives resets).
577+ self .sync .jtag += If (update_ready , ready .eq (source .ready ))
578+
579+ # Update RX registers (outside FSM, survives resets).
580+ # Clear rx_valid after FIFO accepts the data to prevent duplicates.
581+ self .sync .jtag += [
582+ If (update_rx ,
583+ rx_valid .eq (rx_valid_in ),
584+ rx_data .eq (data ),
585+ ).Elif (source .valid & source .ready ,
586+ rx_valid .eq (0 ),
587+ )
588+ ]
589+
591590# ECP5 JTAG PHY (Verilog + AsyncFIFO) -----------------------------------------------------------------
592591
593592class ECP5JTAGPHY (LiteXModule ):
0 commit comments