In reply to James Ferris:
This is just TLM purism, usually defended with “the methodology says that scoreboards have to be fed transactions”, etc. It’s a similar situation to what I once saw: clock transaction that gets sent whenever a clock tick is seen. The TB writer wanted to implement some cycle accurate modeling of something (a whole different discussion in itself) and didn’t use an interface that contained the clock, because in UVM everything has to be transactions.
In my interpretation, transactions are only useful when you can abstract the behavior of multiple signals over time. For example, for an APB transfer I don’t care that there’s are PSEL, PENABLE, PREADY signals or that data is driven on either PWDATA or PRDATA. In high level code I just care that there is data and whether it’s a read or a write. Aside from the obvious advantage of making things easier to reason about, it’s also more efficient to work with transactions (from a simulation speed point of view). All of this falls apart if you don’t have signal protocols and you’re trying to shoehorn transaction where they don’t belong (see the clock transaction example above - no added abstraction and obviously slower).
In your case, maybe you could get the first benefit (abstraction) if you don’t think in terms of signal changes, but assign semantic meaning to those changes. For control signals this means something like “do_command_X” instead of “drive signal ‘cmd’ high for one cycle”. For status signals you would have something like “design responds with X” instead of “‘rsp_valid’ signal goes high and ‘rsp’ signal is driven to X”.