I've spent a rather confusing couple of hours trying to diagnose behaviour that I'm seeing in OpenTitan. There, we have a frontdoor agent that does DMI transactions as follows:
- Do a JTAG write to the
dmi register with the operation required.
- Wait a short time
- Do a JTAG write to the
dmi register with op set to zero (a "nop").
- Check the response. If it is equal to 3 ("operation in progress") then write over JTAG to the
dmireset field in dtmcs to clear the flag, then go back to the previous step.
- If the response is not 3 then the response can be treated as the result of a DMI register read (if needed) and we are done.
The "short time" that is currently in the agent is 10 TCK cycles. But this is not really enough. Specifically, the CDC component (i_dmi_cdc in dap) takes a reasonable time for the dmi_resp_i signal to be synchronised to dmi_resp in dmi_jtag.sv. This timing depends on the implementation of prim_fifo_async_simple.
In an example test that I've just run, the time from the end of the first JTAG transaction to when dmi_resp_valid goes high in dmi_jtag is 13 TCK cycles. Here's a screenshot of waves that show this:

Unfortunately, the OpenTitan frontdoor didn't wait long enough (because of the 10 TCK cycles above). The result is that the "nop" JTAG transaction starts too early and the CaptureDr JTAG state happens a cycle before the response comes back. The end result is that our frontdoor agent thinks the DMI operation is complete, but then gets rather confused when it sees a "busy" response in the next JTAG transaction it sends.
There's a trivial short-term workaround: to increase the "short time" that we wait in the DV agent. (I'm going to do that). But I'm a bit confused: is there a minimum number of clk/TCK cycles between request and reading the response? (And is it described anywhere?) If not, maybe it makes sense to make things a bit more robust by treating an operation as being in progress from when the req goes out to when the response comes back.
I've spent a rather confusing couple of hours trying to diagnose behaviour that I'm seeing in OpenTitan. There, we have a frontdoor agent that does DMI transactions as follows:
dmiregister with the operation required.dmiregister withopset to zero (a "nop").dmiresetfield indtmcsto clear the flag, then go back to the previous step.The "short time" that is currently in the agent is 10 TCK cycles. But this is not really enough. Specifically, the CDC component (
i_dmi_cdcindap) takes a reasonable time for thedmi_resp_isignal to be synchronised todmi_respindmi_jtag.sv. This timing depends on the implementation ofprim_fifo_async_simple.In an example test that I've just run, the time from the end of the first JTAG transaction to when

dmi_resp_validgoes high indmi_jtagis 13 TCK cycles. Here's a screenshot of waves that show this:Unfortunately, the OpenTitan frontdoor didn't wait long enough (because of the 10 TCK cycles above). The result is that the "nop" JTAG transaction starts too early and the
CaptureDrJTAG state happens a cycle before the response comes back. The end result is that our frontdoor agent thinks the DMI operation is complete, but then gets rather confused when it sees a "busy" response in the next JTAG transaction it sends.There's a trivial short-term workaround: to increase the "short time" that we wait in the DV agent. (I'm going to do that). But I'm a bit confused: is there a minimum number of clk/TCK cycles between request and reading the response? (And is it described anywhere?) If not, maybe it makes sense to make things a bit more robust by treating an operation as being in progress from when the req goes out to when the response comes back.