jtagstream: fix JTAGPHY and JTAGUART for reliable operation#2410
Open
chiralitie wants to merge 3 commits intoenjoy-digital:masterfrom
Open
jtagstream: fix JTAGPHY and JTAGUART for reliable operation#2410chiralitie wants to merge 3 commits intoenjoy-digital:masterfrom
chiralitie wants to merge 3 commits intoenjoy-digital:masterfrom
Conversation
Two issues were causing JTAGBone to fail on ECP5 devices: Issue 1: TDO Timing ------------------- The JTAGG primitive samples JTDO1 on the FALLING edge of TCK, but the FSM state changes on the RISING edge. By the falling edge, the FSM has already transitioned to the next state, so the wrong TDO value was being sampled. Fix: Use a registered TDO output (tdo_reg) that captures the value on the rising edge, so it's stable when sampled on the falling edge. Issue 2: Ready Signal Persistence --------------------------------- The FSM was being reset on jtag.capture, which cleared the ready signal before it could be shifted out. Additionally, NextValue registers are cleared by ResetInserter when the JTAG TAP goes through Test-Logic-Reset. Fix: Only reset FSM on jtag.reset (not jtag.capture), and update ready via sync.jtag outside the FSM so it survives FSM resets. Testing ------- Tested on ECP5-VIP board (LFE5UM-85F) and LimeSDR Mini v2 (LFE5U-45F): Before fix: > drscan ecp5.tap 10 0x000 0000 # rx_ready=0 (always zero) After fix: > drscan ecp5.tap 10 0x000 0001 # rx_ready=1 (correct) CSR reads via litex_cli work correctly after the fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f5a3506 to
2eef758
Compare
Author
Update: Added TDO Timing FixI've updated this PR with an additional critical fix for the TDO timing issue. The ProblemThe JTAGG primitive samples JTDO1 on the falling edge of TCK, but the FSM state changes on the rising edge. By the falling edge, the FSM has already transitioned to the next state, so the wrong TDO value was being sampled. The FixUse a registered TDO output ( tdo_reg = Signal(reset=1)
self.comb += jtag_tdo.eq(tdo_reg)
# In FSM states, use NextValue to update tdo_reg:
NextValue(tdo_reg, ready) # In XFER-READY
NextValue(tdo_reg, data[0]) # In XFER-DATA
NextValue(tdo_reg, valid) # In XFER-VALIDTestingVerified working on ECP5-VIP board (LFE5UM-85F):
The branch has been force-pushed with the complete fix. |
- litex_term.py: Add error handling for TCP connection failures - Raise ConnectionError if OpenOCD jtagstream connection fails - Handle ConnectionResetError, BrokenPipeError, OSError in pty2tcp/tcp2pty - Properly close TCP socket and PTY in close() method - Check for empty reads to detect connection closure - openocd.py: Fix jtagstream for background operation - Remove stdin readable callback that caused immediate exit when running in background - Use 11-bit wire format (was incorrectly documented as 10-bit) - Handle newline-separated drscan output in newer OpenOCD versions - Add get_openocd_cmd() to respect OPENOCD environment variable These fixes allow litex_server --jtag to work reliably when spawned as a background process or from a daemon thread. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use data_width + 3 shift cycles for data_width + 2 bits of information (JTAGG only captures TDO on falling edge in Shift-DR, last falling edge is in Exit1-DR which doesn't capture) - Add XFER-PADDING state to handle the extra shift cycle - Capture RX valid bit on shift falling edge (transition from Shift-DR to Exit1-DR) - Update rx_valid/rx_data via sync.jtag instead of NextValue to survive FSM resets - Fix documentation to reflect actual wire format This fixes the issue where the JTAGPHY would miss the valid bit from the host because it was being captured at the wrong time in the JTAG state machine. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes several issues with the JTAGPHY and JTAG UART functionality:
Problem 1: rx_ready always zero
The JTAGPHY
rx_readysignal (bit 0 of Target-to-Host response) was always returning 0 on ECP5 devices, even when the CDC FIFO was writable. This broke JTAGBone CSR access.Root Cause
Two issues in the current implementation:
FSM reset on capture:
jtag.captureevent fires at the start of every drscan, triggeringResetInserterwhich clears ALLNextValueregisters, includingready.NextValue cleared by FSM reset: The JTAG TAP transitions through Test-Logic-Reset between drscans, asserting
jtag.resetand clearingready.Solution
jtag.reset, notjtag.capturereadyupdate outside FSM control using a separatesync.jtagstatementProblem 2: litex_server --jtag crashes in background
When running
litex_server --jtagas a background process, it would crash with:Root Cause
stdin readablecallback in jtagstream_serve caused immediate exit when stdin was closedSolution
stdin readablecallback from jtagstream_serveProblem 3: Wire format timing issues
The wire format documentation was incorrect (10 bits instead of 11), and the RX valid bit was being captured at the wrong time.
Solution
data_width + 3shift cycles fordata_width + 2bitsXFER-PADDINGstate to handle the extra shift cycleChanges
litex/soc/cores/jtag.py
jtag.reset, notjtag.capturereadyupdate outside FSM controldata_width + 3shift cyclesXFER-PADDINGstate for extra shift cyclelitex/build/openocd.py
stdin readablecallback from jtagstream_serveget_openocd_cmd()to respect OPENOCD environment variablelitex/tools/litex_term.py
Testing
Tested on ECP5-VIP board with FT2232H JTAG adapter:
litex_server --jtagnow starts and listens on both ports (1234 and 20000)tcp2ptyexceptions when running in backgroundCompatibility
These changes should be backwards compatible. The FSM behavior is unchanged except:
readyandrx_validregisters survive FSM resets (expected behavior)