From 62f4f13a9af6ce2ab7039f0ffabcb0e421c02cb3 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 20 Sep 2020 12:54:07 +0100 Subject: [PATCH] first version code-morph on dmi2jtag --- src/soc/debug/dmi2jtag.py | 285 ++++++++++++++++++ src/soc/experiment/dmi_dtm_xilinx.py | 417 --------------------------- 2 files changed, 285 insertions(+), 417 deletions(-) create mode 100644 src/soc/debug/dmi2jtag.py delete mode 100644 src/soc/experiment/dmi_dtm_xilinx.py diff --git a/src/soc/debug/dmi2jtag.py b/src/soc/debug/dmi2jtag.py new file mode 100644 index 00000000..7459150e --- /dev/null +++ b/src/soc/debug/dmi2jtag.py @@ -0,0 +1,285 @@ +"""JTAGToDMI + +based on Anton Blanchard microwatt dmi_dtm_xilinx.vhdl + +""" + +from enum import Enum, unique +from nmigen import (Module, Signal, Elaboratable, Cat, Signal) +from nmigen.cli import main +from nmigen.cli import rtlil +from nmutil.iocontrol import RecordObject +from nmutil.byterev import byte_reverse +from nmutil.mask import Mask +from nmigen.util import log2_int + +# -- Xilinx internal JTAG to DMI interface +# -- +# -- DMI bus +# -- +# -- req : ____/------------\_____ +# -- addr: xxxx< >xxxxx +# -- dout: xxxx< >xxxxx +# -- wr : xxxx< >xxxxx +# -- din : xxxxxxxxxxxx< >xxx +# -- ack : ____________/------\___ +# -- +# -- * addr/dout set along with req, can be latched on same cycle by slave +# -- * ack & din remain up until req is dropped by master, the slave must +# -- provide a stable output on din on reads during that time. +# -- * req remains low at until at least one sysclk after ack seen down. +# -- +# -- JTAG (tck) DMI (sys_clk) +# -- +# -- * jtag_req = 1 +# -- (jtag_req_0) * +# -- (jtag_req_1) -> * dmi_req = 1 > +# -- *.../... +# -- * dmi_ack = 1 < +# -- * (dmi_ack_0) +# -- * <- (dmi_ack_1) +# -- * jtag_req = 0 (and latch dmi_din) +# -- (jtag_req_0) * +# -- (jtag_req_1) -> * dmi_req = 0 > +# -- * dmi_ack = 0 < +# -- * (dmi_ack_0) +# -- * <- (dmi_ack_1) +# -- +# -- jtag_req can go back to 1 when jtag_rsp_1 is 0 +# -- +# -- Questions/TODO: +# -- - I use 2 flip fops for sync, is that enough ? +# -- - I treat the jtag_reset as an async reset, is that necessary ? +# -- - Dbl check reset situation since we have two different resets +# -- each only resetting part of the logic... +# -- - Look at optionally removing the synchronizer on the ack path, +# -- assuming JTAG is always slow enough that ack will have been +# -- stable long enough by the time CAPTURE comes in. +# -- - We could avoid the latched request by not shifting while a +# -- request is in progress (and force TDO to 1 to return a busy +# -- status). +# -- +# -- WARNING: This isn't the real DMI JTAG protocol (at least not yet). +# -- a command while busy will be ignored. A response of "11" +# -- means the previous command is still going, try again. +# -- As such We don't implement the DMI "error" status, and +# -- we don't implement DTMCS yet... This may still all change +# -- but for now it's easier that way as the real DMI protocol +# -- requires for a command to work properly that enough TCK +# -- are sent while IDLE and I'm having trouble getting that +# -- working with UrJtag and the Xilinx BSCAN2 for now. + + +# ** Constants ** +DMI_REQ_NOP = Const(0b00, 2) +DMI_REQ_RD = Const(0b01, 2) +DMI_REQ_WR = Const(0b10, 2) +DMI_RSP_OK = Const(0b00, 2) +DMI_RSP_BSY = Const(0b11, 2) + + +class JTAGToDMI(Elaboratable): + def __init__(self, ABITS=8, DBITS=32): + self.ABITS = ABITS + self.DBITS = DBITS + self.sys_clk = Signal() + self.sys_reset = Signal() + self.dmi_addr = Signal(ABITS) + self.dmi_din = Signal(DBITS) + self.dmi_dout = Signal(DBITS) + self.dmi_req = Signal() + self.dmi_wr = Signal() + self.dmi_ack = Signal() + self.dmi_err = Signal() + + # DMI req synchronization + def dmi_req_sync(self, m, jtag_req): + + # Syncrhonizer for jtag_req (jtag clk -> sys clk) + jtag_req_0 = Signal() + jtag_req_1 = Signal() + + sync = m.d.SYS_sync + + with m.If(sys_reset): + sync += jtag_req_0.eq(0) + sync += jtag_req_1.eq(0) + + with m.Else(): + sync += jtag_req_0.eq(jtag_req) + sync += jtag_req_1.eq(jtag_req_0) + comb += self.dmi_req.eq(jtag_req_1) + + # DMI ack synchronization + def dmi_ack_sync(self, m, dmi_ack_1): + comb = m.d.comb + sync = m.d.JTAG_sync + + dmi_ack_0 = Signal() + + # -- jtag_reset is async (see comments) + with m.If(jtag_reset): + comb += dmi_ack_0.eq(0) + comb += dmi_ack_1.eq(0) + + sync += dmi_ack_0.eq(self.dmi_ack) + sync += dmi_ack_1.eq(dmi_ack_0) + + def elaborate(self, platform): + m = Module() + + comb = m.d.comb + sync = m.d.sync + + # Signal coming out of the BSCANE2 block + jtag_reset = Signal() + capture = Signal() + update = Signal() + drck = Signal() + jtag_clk = Signal() + sel = Signal() + shift = Signal() + tdi = Signal() + tdo = Signal() + tck = Signal() + + # ** JTAG clock domain ** + + # Shift register + shiftr = Signal(self.ABITS + self.DBITS) + + # Latched request + request = Signal(ABITS + DBITS) + + dmi_ack_1 = Signal() + + # A request is present + jtag_req = Signal() + + # ** SYS clock domain + + # combination signals + jtag_bsy = Signal() + op_valid = Signal() + rsp_op = Signal(2) + + # attribute ASYNC_REG : string; + # attribute ASYNC_REG of jtag_req_0: signal is "TRUE"; + # attribute ASYNC_REG of jtag_req_1: signal is "TRUE"; + # attribute ASYNC_REG of dmi_ack_0: signal is "TRUE"; + # attribute ASYNC_REG of dmi_ack_1: signal is "TRUE"; + # TODO nmigen attributes + # attribute ASYNC_REG : string; + # attribute ASYNC_REG of jtag_req_0: signal is "TRUE"; + # attribute ASYNC_REG of jtag_req_1: signal is "TRUE"; + # attribute ASYNC_REG of dmi_ack_0: signal is "TRUE"; + # attribute ASYNC_REG of dmi_ack_1: signal is "TRUE"; + + +# begin +# +# -- Implement the Xilinx bscan2 for series 7 devices (TODO: use PoC +# -- to wrap this if compatibility is required with older devices). +# bscan : BSCANE2 +# generic map ( +# JTAG_CHAIN => 2 +# ) +# port map ( +# CAPTURE => capture, +# DRCK => drck, +# RESET => jtag_reset, +# RUNTEST => open, +# SEL => sel, +# SHIFT => shift, +# TCK => tck, +# TDI => tdi, +# TMS => open, +# UPDATE => update, +# TDO => tdo +# ); +# +# -- Some examples out there suggest buffering the clock so it's +# -- treated as a proper clock net. This is probably needed when using +# -- drck (the gated clock) but I'm using the real tck here to avoid +# -- missing the update phase so maybe not... +# -- +# clkbuf : BUFG +# port map ( +# -- I => drck, +# I => tck, +# O => jtag_clk +# ); +# + # jtag_bsy indicates whether we can start a new request, + # we can when we aren't already processing one (jtag_req) + # and the synchronized ack of the previous one is 0. + comb += jtag_bsy.eq(jtag_req | dmi_ack_1) + + # -- decode request type in shift register + with m.Switch(shitr[:2]): + with m.Case(DMI_REQ_RD): comb += op_valid.eq(1) + with m.Case(DMI_REQ_WR): comb += op_valid.eq(1) + + # -- encode response op + with m.If(jtag_bsy): + comb += rsp_op.eq(DMI_RSP_BSY) + with m.Else(): + comb += rsp_op.eq(DMI_RSP_OK) + + # Some DMI out signals are directly driven from the request register + # dmi_addr <= request(ABITS + DBITS + 1 downto DBITS + 2); + # dmi_dout <= request(DBITS + 1 downto 2); + # dmi_wr <= '1' when request(1 downto 0) = DMI_REQ_WR else '0'; + comb += dmi_addr.eq(request[DBITS + 2:ABITS + DBITS + 2]) + comb += dmi_dout.eq(request[2:DBITS]) + + with m.If(request[:2] == DMI_REQ_WR): + comb += dmi_wr.eq(1) + + # TDO is wired to shift register bit 0 + comb += tdo.eq(shiftr[0]) + + # Main state machine. Handles shift registers, request latch and + # jtag_req latch. Could be split into 3 processes but it's probably + # not worthwhile. + def shifter(self, m, jtag_clk, jtag_reset) + comb = m.d.comb + sync = m.d.JTAG_sync + + with m.If(jtag_reset): + comb += shiftr.eq(0) + comb += jtag_req.eq(0) + + # Handle jtag "commands" when sel is 1 + with m.Elif(sel): + # Shift state, rotate the register + with m.If(shift): + sync += shiftr.eq(Cat(shiftr[1:ABITS + DBITS], tdi)) + + # Update state (trigger) + # Latch the request if we aren't already processing + # one and it has a valid command opcode. + with m.If(update & op_valid): + with m.If(~jtag_bsy): + sync += request.eq(shiftr) + sync += jtag_req.eq(1) + # Set the shift register "op" to "busy". This will prevent + # us from re-starting the command on the next update if + # the command completes before that. + sync += shiftr[:2].eq(DMI_RSP_BSY) + + # Request completion. + # Capture the response data for reads and clear request flag. + # Note: We clear req (and thus dmi_req) here which + # relies on tck ticking and sel set. This means we + # are stuck with dmi_req up if the jtag interface stops. + # Slaves must be resilient to this. + with m.If(jtag_rq & dmi_ack): + sync += jtag_req.eq(0) + with m.If(request[:2] == DMI_REQ_RD): + sync += request[2:DBITS].eq(dmi_din) + + # Capture state, grab latch content with updated status + with m.If(capture): + sync += shiftr.eq(Cat(rsp_op, request[2:ABITS + DBITS])) + diff --git a/src/soc/experiment/dmi_dtm_xilinx.py b/src/soc/experiment/dmi_dtm_xilinx.py deleted file mode 100644 index ab80eade..00000000 --- a/src/soc/experiment/dmi_dtm_xilinx.py +++ /dev/null @@ -1,417 +0,0 @@ -"""JTAGToDMI - -based on Anton Blanchard microwatt dmi_dtm_xilinx.vhdl - -""" - -from enum import Enum, unique -from nmigen import (Module, Signal, Elaboratable, Cat, Signal) -from nmigen.cli import main -from nmigen.cli import rtlil -from nmutil.iocontrol import RecordObject -from nmutil.byterev import byte_reverse -from nmutil.mask import Mask -from nmigen.util import log2_int - -# -- Xilinx internal JTAG to DMI interface -# -- -# -- DMI bus -# -- -# -- req : ____/------------\_____ -# -- addr: xxxx< >xxxxx -# -- dout: xxxx< >xxxxx -# -- wr : xxxx< >xxxxx -# -- din : xxxxxxxxxxxx< >xxx -# -- ack : ____________/------\___ -# -- -# -- * addr/dout set along with req, can be latched on same cycle by slave -# -- * ack & din remain up until req is dropped by master, the slave must -# -- provide a stable output on din on reads during that time. -# -- * req remains low at until at least one sysclk after ack seen down. -# -- -# -- JTAG (tck) DMI (sys_clk) -# -- -# -- * jtag_req = 1 -# -- (jtag_req_0) * -# -- (jtag_req_1) -> * dmi_req = 1 > -# -- *.../... -# -- * dmi_ack = 1 < -# -- * (dmi_ack_0) -# -- * <- (dmi_ack_1) -# -- * jtag_req = 0 (and latch dmi_din) -# -- (jtag_req_0) * -# -- (jtag_req_1) -> * dmi_req = 0 > -# -- * dmi_ack = 0 < -# -- * (dmi_ack_0) -# -- * <- (dmi_ack_1) -# -- -# -- jtag_req can go back to 1 when jtag_rsp_1 is 0 -# -- -# -- Questions/TODO: -# -- - I use 2 flip fops for sync, is that enough ? -# -- - I treat the jtag_reset as an async reset, is that necessary ? -# -- - Dbl check reset situation since we have two different resets -# -- each only resetting part of the logic... -# -- - Look at optionally removing the synchronizer on the ack path, -# -- assuming JTAG is always slow enough that ack will have been -# -- stable long enough by the time CAPTURE comes in. -# -- - We could avoid the latched request by not shifting while a -# -- request is in progress (and force TDO to 1 to return a busy -# -- status). -# -- -# -- WARNING: This isn't the real DMI JTAG protocol (at least not yet). -# -- a command while busy will be ignored. A response of "11" -# -- means the previous command is still going, try again. -# -- As such We don't implement the DMI "error" status, and -# -- we don't implement DTMCS yet... This may still all change -# -- but for now it's easier that way as the real DMI protocol -# -- requires for a command to work properly that enough TCK -# -- are sent while IDLE and I'm having trouble getting that -# -- working with UrJtag and the Xilinx BSCAN2 for now. -# -# library ieee; -# use ieee.std_logic_1164.all; -# use ieee.math_real.all; -# -# library work; -# use work.wishbone_types.all; -# -# library unisim; -# use unisim.vcomponents.all; -# -# entity dmi_dtm is -# generic(ABITS : INTEGER:=8; -# DBITS : INTEGER:=32); -# -# port(sys_clk : in std_ulogic; -# sys_reset : in std_ulogic; -# dmi_addr : out std_ulogic_vector(ABITS - 1 downto 0); -# dmi_din : in std_ulogic_vector(DBITS - 1 downto 0); -# dmi_dout : out std_ulogic_vector(DBITS - 1 downto 0); -# dmi_req : out std_ulogic; -# dmi_wr : out std_ulogic; -# dmi_ack : in std_ulogic -# -- dmi_err : in std_ulogic TODO: Add error response -# ); -# end entity dmi_dtm; -class JTAGToDMI(Elaboratable): - def __init__(self): - self.sys_clk = Signal() - self.sys_reset = Signal() - self.dmi_addr = Signal(ABITS) - self.dmi_din = Signal(DBITS) - self.dmi_dout = Signal(DBITS) - self.dmi_req = Signal() - self.dmi_wr = Signal() - self.dmi_ack = Signal() - self.dmi_err = Signal() - -# architecture behaviour of dmi_dtm is - def elaborate(self, platform): - m = Module() - - comb = m.d.comb - sync = m.d.sync - -# -- Signals coming out of the BSCANE2 block -# signal jtag_reset : std_ulogic; -# signal capture : std_ulogic; -# signal update : std_ulogic; -# signal drck : std_ulogic; -# signal jtag_clk : std_ulogic; -# signal sel : std_ulogic; -# signal shift : std_ulogic; -# signal tdi : std_ulogic; -# signal tdo : std_ulogic; -# signal tck : std_ulogic; - # Signal coming out of the BSCANE2 block - jtag_reset = Signal() - capture = Signal() - update = Signal() - drck = Signal() - jtag_clk = Signal() - sel = Signal() - shift = Signal() - tdi = Signal() - tdo = Signal() - tck = Signal() - -# -- ** JTAG clock domain ** - # ** JTAG clock domain ** - -# -- Shift register -# signal shiftr : std_ulogic_vector(ABITS + DBITS + 1 downto 0); - # Shift register - shiftr = Signal(ABITS + DBITS) - -# -- Latched request -# signal request : std_ulogic_vector(ABITS + DBITS + 1 downto 0); - # Latched request - request = Signal(ABITS + DBITS) - -# -- A request is present -# signal jtag_req : std_ulogic; - # A request is present - jtag_req = Signal() - -# -- Synchronizer for jtag_rsp (sys clk -> jtag_clk) -# signal dmi_ack_0 : std_ulogic; -# signal dmi_ack_1 : std_ulogic; - # Synchronizer for jtag_rsp (sys clk -> jtag_clk) - dmi_ack_0 = Signal() - dmi_ack_1 = Signal() - -# -- ** sys clock domain ** - # ** SYS clock domain - -# -- Synchronizer for jtag_req (jtag clk -> sys clk) -# signal jtag_req_0 : std_ulogic; -# signal jtag_req_1 : std_ulogic; - # Syncrhonizer for jtag_req (jtag clk -> sys clk) - jtag_req_0 = Signal() - jtag_req_1 = Signal() - -# -- ** combination signals -# signal jtag_bsy : std_ulogic; -# signal op_valid : std_ulogic; -# signal rsp_op : std_ulogic_vector(1 downto 0); - # combination signals - jtag_bsy = Signal() - op_valid = Signal() - rsp_op = Signal(2) - -# -- ** Constants ** -# constant DMI_REQ_NOP : std_ulogic_vector(1 downto 0) := "00"; -# constant DMI_REQ_RD : std_ulogic_vector(1 downto 0) := "01"; -# constant DMI_REQ_WR : std_ulogic_vector(1 downto 0) := "10"; -# constant DMI_RSP_OK : std_ulogic_vector(1 downto 0) := "00"; -# constant DMI_RSP_BSY : std_ulogic_vector(1 downto 0) := "11"; - # ** Constants ** - DMI_REQ_NOP = Const(0b00, 2) - DMI_REQ_RD = Const(0b01, 2) - DMI_REQ_WR = Const(0b10, 2) - DMI_RSP_OK = Const(0b00, 2) - DMI_RSP_BSY = Const(0b11, 2) - - -# attribute ASYNC_REG : string; -# attribute ASYNC_REG of jtag_req_0: signal is "TRUE"; -# attribute ASYNC_REG of jtag_req_1: signal is "TRUE"; -# attribute ASYNC_REG of dmi_ack_0: signal is "TRUE"; -# attribute ASYNC_REG of dmi_ack_1: signal is "TRUE"; - # TODO nmigen attributes - # attribute ASYNC_REG : string; - # attribute ASYNC_REG of jtag_req_0: signal is "TRUE"; - # attribute ASYNC_REG of jtag_req_1: signal is "TRUE"; - # attribute ASYNC_REG of dmi_ack_0: signal is "TRUE"; - # attribute ASYNC_REG of dmi_ack_1: signal is "TRUE"; - - -# begin -# -# -- Implement the Xilinx bscan2 for series 7 devices (TODO: use PoC -# -- to wrap this if compatibility is required with older devices). -# bscan : BSCANE2 -# generic map ( -# JTAG_CHAIN => 2 -# ) -# port map ( -# CAPTURE => capture, -# DRCK => drck, -# RESET => jtag_reset, -# RUNTEST => open, -# SEL => sel, -# SHIFT => shift, -# TCK => tck, -# TDI => tdi, -# TMS => open, -# UPDATE => update, -# TDO => tdo -# ); -# -# -- Some examples out there suggest buffering the clock so it's -# -- treated as a proper clock net. This is probably needed when using -# -- drck (the gated clock) but I'm using the real tck here to avoid -# -- missing the update phase so maybe not... -# -- -# clkbuf : BUFG -# port map ( -# -- I => drck, -# I => tck, -# O => jtag_clk -# ); -# -# -- dmi_req synchronization -# dmi_req_sync : process(sys_clk) -# begin -# -- sys_reset is synchronous -# if rising_edge(sys_clk) then -# if (sys_reset = '1') then -# jtag_req_0 <= '0'; -# jtag_req_1 <= '0'; -# else -# jtag_req_0 <= jtag_req; -# jtag_req_1 <= jtag_req_0; -# end if; -# end if; -# end process; -# dmi_req <= jtag_req_1; - # DMI req synchronization - def dmi_req_sync(self, m, jtag_req, jtag_req_0, jtag_req_1): - sync = m.d.SYS_sync - - with m.If(sys_reset): - sync += jtag_req_0.eq(0) - sync += jtag_req_1.eq(0) - - with m.Else(): - sync += jtag_req_0.eq(jtag_req) - sync += jtag_req_1.eq(jtag_req_0) - -# -- dmi_ack synchronization -# dmi_ack_sync: process(jtag_clk, jtag_reset) -# begin -# -- jtag_reset is async (see comments) -# if jtag_reset = '1' then -# dmi_ack_0 <= '0'; -# dmi_ack_1 <= '0'; -# elsif rising_edge(jtag_clk) then -# dmi_ack_0 <= dmi_ack; -# dmi_ack_1 <= dmi_ack_0; -# end if; -# end process; - # DMI ack synchronization - def dmi_ack_sync(self, dmi_ack, dmi_ack_0, dmi_ack_1): - comb = m.d.comb - sync = m.d.JTAG_sync - - with m.If(jtag_reset): - comb += dmi_ack_0.eq(0) - comb += dmi_ack_1.eq(0) - - sync += dmi_ack_0.eq(dmi_ack) - sync += dmi_ack_1.eq(dmi_ack_0) - -# -- jtag_bsy indicates whether we can start a new request, -# -- we can when we aren't already processing one (jtag_req) -# -- and the synchronized ack of the previous one is 0. -# -- -# jtag_bsy <= jtag_req or dmi_ack_1; - comb += jtag_bsy.eq(jtag_req | dmi_ack_1) - -# -- decode request type in shift register -# with shiftr(1 downto 0) select op_valid <= -# '1' when DMI_REQ_RD, -# '1' when DMI_REQ_WR, -# '0' when others; - with m.Switch(shitr[:2]): - with m.Case(DMI_REQ_RD): comb += op_valid.eq(1) - with m.Case(DMI_REQ_WR): comb += op_valid.eq(1) - with m.Default(): comb += op_valid.eq(0) - -# -- encode response op -# rsp_op <= DMI_RSP_BSY when jtag_bsy = '1' else DMI_RSP_OK; - with m.If(jtag_bsy): - comb += rsp_op.eq(DMI_RSP_BSY) - - with m.Else(): - comb += rsp_op.eq(DMI_RSP_OK) - -# -- Some DMI out signals are directly driven from the request register -# dmi_addr <= request(ABITS + DBITS + 1 downto DBITS + 2); -# dmi_dout <= request(DBITS + 1 downto 2); -# dmi_wr <= '1' when request(1 downto 0) = DMI_REQ_WR else '0'; - comb += dmi_addr.eq(request[DBITS + 2:ABITS + DBITS + 2]) - comb += dmi_dout.eq(request[2:DBITS]) - - with m.If(request[:2] == DMI_REQ_WR): - comb += dmi_wr.eq(1) - - with m.Else(): - comb += dmi_wr.eq(0) - -# -- TDO is wired to shift register bit 0 -# tdo <= shiftr(0); - comb += tdo.eq(shiftr[0]) - -# -- Main state machine. Handles shift registers, request latch and -# -- jtag_req latch. Could be split into 3 processes but it's probably -# -- not worthwhile. -# -- -# shifter: process(jtag_clk, jtag_reset) - def shifter(self, m, jtag_clk, jtag_reset) - comb = m.d.comb - sync = m.d.JTAG_sync -# begin -# if jtag_reset = '1' then -# shiftr <= (others => '0'); -# jtag_req <= '0'; - with m.If(jtag_reset): - comb += shiftr.eq(~1) - comb += jtag_req.eq(0) - -# elsif rising_edge(jtag_clk) then -# -- Handle jtag "commands" when sel is 1 -# if sel = '1' then - with m.If(sel): -# -- Shift state, rotate the register -# if shift = '1' then - with m.If(shift): -# shiftr <= tdi & shiftr(ABITS + DBITS + 1 downto 1); - sync += shiftr.eq(Cat(shiftr[1:ABITS + DBITS], tdi)) -# end if; -# -# -- Update state (trigger) -# -- -# -- Latch the request if we aren't already processing -# -- one and it has a valid command opcode. -# -- -# if update = '1' and op_valid = '1' then - with m.If(update & op_valid): -# if jtag_bsy = '0' then - with m.If(~jtag_bsy): -# request <= shiftr; -# jtag_req <= '1'; - sync += request.eq(shiftr) - sync += jtag_req.eq(1) -# end if; -# -- Set the shift register "op" to "busy". -# -- This will prevent us from re-starting -# -- the command on the next update if -# -- the command completes before that. -# shiftr(1 downto 0) <= DMI_RSP_BSY; - sync += shiftr[:2].eq(DMI_RSP_BSY) -# end if; -# -# -- Request completion. -# -- -# -- Capture the response data for reads and -# -- clear request flag. -# -- -# -- Note: We clear req (and thus dmi_req) here which -# -- relies on tck ticking and sel set. This means we -# -- are stuck with dmi_req up if the jtag interface stops. -# -- Slaves must be resilient to this. -# -- -# if jtag_req = '1' and dmi_ack_1 = '1' then - with m.If(jtag_rq & dmi_ack): -# jtag_req <= '0'; - sync += jtag_req.eq(0) -# if request(1 downto 0) = DMI_REQ_RD then -# request(DBITS + 1 downto 2) <= dmi_din; - with m.If(request[:2] == DMI_REQ_RD): - sync += request[2:DBITS].eq(dmi_din) -# end if; -# end if; -# -# -- Capture state, grab latch content with updated status -# if capture = '1' then -# shiftr <= request(ABITS + DBITS + 1 downto 2) & rsp_op; - with m.If(capture): - sync += shiftr.eq(Cat(rsp_op, request[2:ABITS + DBITS])) -# end if; -# -# end if; -# end if; -# end process; -# end architecture behaviour; -- 2.30.2