diff --git a/coreblocks/func_blocks/csr/csr.py b/coreblocks/func_blocks/csr/csr.py
index a633a647f..75cd23d19 100644
--- a/coreblocks/func_blocks/csr/csr.py
+++ b/coreblocks/func_blocks/csr/csr.py
@@ -57,8 +57,8 @@ class CSRUnit(FuncBlock, Elaboratable):
     update: Method
         Method from standard RS interface. Receives announcements of computed register values.
     get_result: Method
-        `accept` method from standard FU interface. Used to receive instruction result and pass it
-        to the next pipeline stage.
+        Method from standard RS func block interface. Used to receive instruction result and pass
+        it to the next pipeline stage.
     """
 
     def __init__(self, gen_params: GenParams):
@@ -79,7 +79,7 @@ def __init__(self, gen_params: GenParams):
         self.select = Method(o=self.csr_layouts.rs.select_out)
         self.insert = Method(i=self.csr_layouts.rs.insert_in)
         self.update = Method(i=self.csr_layouts.rs.update_in)
-        self.get_result = Method(o=self.fu_layouts.accept)
+        self.get_result = Method(o=self.fu_layouts.push_result)
 
         self.regfile: dict[int, tuple[Method, Method]] = {}
 
diff --git a/coreblocks/func_blocks/fu/alu.py b/coreblocks/func_blocks/fu/alu.py
index c4da07fb3..9b0de68d7 100644
--- a/coreblocks/func_blocks/fu/alu.py
+++ b/coreblocks/func_blocks/fu/alu.py
@@ -3,7 +3,6 @@
 from amaranth import *
 
 from transactron import *
-from transactron.lib import FIFO
 from transactron.lib.metrics import *
 
 from coreblocks.arch import OpType, Funct3, Funct7
@@ -242,7 +241,7 @@ def __init__(self, gen_params: GenParams, alu_fn=AluFn()):
         layouts = gen_params.get(FuncUnitLayouts)
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
         self.perf_instr = TaggedCounter(
             "backend.fu.alu.instr",
@@ -256,13 +255,8 @@ def elaborate(self, platform):
         m.submodules += [self.perf_instr]
 
         m.submodules.alu = alu = Alu(self.gen_params, alu_fn=self.alu_fn)
-        m.submodules.fifo = fifo = FIFO(self.gen_params.get(FuncUnitLayouts).accept, 2)
         m.submodules.decoder = decoder = self.alu_fn.get_decoder(self.gen_params)
 
-        @def_method(m, self.accept)
-        def _():
-            return fifo.read(m)
-
         @def_method(m, self.issue)
         def _(arg):
             m.d.av_comb += decoder.exec_fn.eq(arg.exec_fn)
@@ -273,7 +267,7 @@ def _(arg):
 
             self.perf_instr.incr(m, decoder.decode_fn)
 
-            fifo.write(m, rob_id=arg.rob_id, result=alu.out, rp_dst=arg.rp_dst, exception=0)
+            self.push_result(m, rob_id=arg.rob_id, result=alu.out, rp_dst=arg.rp_dst, exception=0)
 
         return m
 
@@ -281,6 +275,7 @@ def _(arg):
 @dataclass(frozen=True)
 class ALUComponent(FunctionalComponentParams):
     _: KW_ONLY
+    result_fifo: bool = True
     zba_enable: bool = False
     zbb_enable: bool = False
     zicond_enable: bool = False
diff --git a/coreblocks/func_blocks/fu/common/rs_func_block.py b/coreblocks/func_blocks/fu/common/rs_func_block.py
index 3238c518e..545021e7b 100644
--- a/coreblocks/func_blocks/fu/common/rs_func_block.py
+++ b/coreblocks/func_blocks/fu/common/rs_func_block.py
@@ -6,7 +6,7 @@
 from coreblocks.scheduler.wakeup_select import WakeupSelect
 from transactron import Method, TModule
 from coreblocks.func_blocks.interface.func_protocols import FuncUnit, FuncBlock
-from transactron.lib import Collector
+from transactron.lib import FIFO, Collector, Connect
 from coreblocks.arch import OpType
 from coreblocks.interface.layouts import RSLayouts, FuncUnitLayouts
 
@@ -34,7 +34,7 @@ class RSFuncBlock(FuncBlock, Elaboratable):
     def __init__(
         self,
         gen_params: GenParams,
-        func_units: Iterable[tuple[FuncUnit, set[OpType]]],
+        func_units: Iterable[tuple[FuncUnit, set[OpType], bool]],
         rs_entries: int,
         rs_number: int,
         rs_type: type[RSBase],
@@ -65,7 +65,7 @@ def __init__(
         self.insert = Method(i=self.rs_layouts.rs.insert_in)
         self.select = Method(o=self.rs_layouts.rs.select_out)
         self.update = Method(i=self.rs_layouts.rs.update_in)
-        self.get_result = Method(o=self.fu_layouts.accept)
+        self.get_result = Method(o=self.fu_layouts.push_result)
 
     def elaborate(self, platform):
         m = TModule()
@@ -74,20 +74,29 @@ def elaborate(self, platform):
             gen_params=self.gen_params,
             rs_entries=self.rs_entries,
             rs_number=self.rs_number,
-            ready_for=(optypes for _, optypes in self.func_units),
+            ready_for=(optypes for _, optypes, _ in self.func_units),
         )
 
-        for n, (func_unit, _) in enumerate(self.func_units):
+        targets: list[Method] = []
+
+        for n, (func_unit, _, result_fifo) in enumerate(self.func_units):
             wakeup_select = WakeupSelect(
                 gen_params=self.gen_params,
                 get_ready=self.rs.get_ready_list[n],
                 take_row=self.rs.take,
                 issue=func_unit.issue,
             )
+            if result_fifo:
+                connector = FIFO(self.gen_params.get(FuncUnitLayouts).push_result, 2)
+            else:
+                connector = Connect(self.gen_params.get(FuncUnitLayouts).push_result)
             m.submodules[f"func_unit_{n}"] = func_unit
             m.submodules[f"wakeup_select_{n}"] = wakeup_select
+            m.submodules[f"connector_{n}"] = connector
+            func_unit.push_result.proxy(m, connector.write)
+            targets.append(connector.read)
 
-        m.submodules.collector = collector = Collector([func_unit.accept for func_unit, _ in self.func_units])
+        m.submodules.collector = collector = Collector(targets)
 
         self.insert.proxy(m, self.rs.insert)
         self.select.proxy(m, self.rs.select)
@@ -105,7 +114,7 @@ class RSBlockComponent(BlockComponentParams):
     rs_type: type[RSBase] = RS
 
     def get_module(self, gen_params: GenParams) -> FuncBlock:
-        modules = list((u.get_module(gen_params), u.get_optypes()) for u in self.func_units)
+        modules = list((u.get_module(gen_params), u.get_optypes(), u.result_fifo) for u in self.func_units)
         rs_unit = RSFuncBlock(
             gen_params=gen_params,
             func_units=modules,
diff --git a/coreblocks/func_blocks/fu/div_unit.py b/coreblocks/func_blocks/fu/div_unit.py
index c79a48d6f..492c52282 100644
--- a/coreblocks/func_blocks/fu/div_unit.py
+++ b/coreblocks/func_blocks/fu/div_unit.py
@@ -48,7 +48,7 @@ def __init__(self, gen_params: GenParams, ipc: int = 4, div_fn=DivFn()):
         layouts = gen_params.get(FuncUnitLayouts)
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
         self.clear = Method()
 
         self.div_fn = div_fn
@@ -56,7 +56,6 @@ def __init__(self, gen_params: GenParams, ipc: int = 4, div_fn=DivFn()):
     def elaborate(self, platform):
         m = TModule()
 
-        m.submodules.result_fifo = result_fifo = BasicFifo(self.gen_params.get(FuncUnitLayouts).accept, 2)
         m.submodules.params_fifo = params_fifo = FIFO(
             [
                 ("rob_id", self.gen_params.rob_entries_bits),
@@ -75,13 +74,8 @@ def elaborate(self, platform):
 
         @def_method(m, self.clear)
         def _():
-            result_fifo.clear(m)
             divider.clear(m)
 
-        @def_method(m, self.accept)
-        def _():
-            return result_fifo.read(m)
-
         @def_method(m, self.issue)
         def _(arg):
             m.d.av_comb += decoder.exec_fn.eq(arg.exec_fn)
@@ -132,7 +126,7 @@ def _abs(s: Value) -> Value:
             flip_sig = Mux(params.flip_sign, ~result[sign_bit], 0)
             sign_result = Mux(flip_sig, -result, result)
 
-            result_fifo.write(m, rob_id=params.rob_id, result=sign_result, rp_dst=params.rp_dst, exception=0)
+            self.push_result(m, rob_id=params.rob_id, result=sign_result, rp_dst=params.rp_dst, exception=0)
 
         return m
 
@@ -140,6 +134,7 @@ def _abs(s: Value) -> Value:
 @dataclass(frozen=True)
 class DivComponent(FunctionalComponentParams):
     _: KW_ONLY
+    result_fifo: bool = False  # last step is registered
     ipc: int = 3  # iterations per cycle
     decoder_manager: DivFn = DivFn()
 
diff --git a/coreblocks/func_blocks/fu/exception.py b/coreblocks/func_blocks/fu/exception.py
index 35c00d003..2875cb721 100644
--- a/coreblocks/func_blocks/fu/exception.py
+++ b/coreblocks/func_blocks/fu/exception.py
@@ -1,11 +1,10 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, KW_ONLY
 from typing import Sequence
 from amaranth import *
 from coreblocks.arch.isa_consts import PrivilegeLevel
 from transactron.utils.dependencies import DependencyContext
 
 from transactron import *
-from transactron.lib import FIFO
 
 from coreblocks.params import GenParams, FunctionalComponentParams
 from coreblocks.arch import OpType, Funct3, ExceptionCause
@@ -50,7 +49,7 @@ def __init__(self, gen_params: GenParams, unit_fn=ExceptionUnitFn()):
         layouts = gen_params.get(FuncUnitLayouts)
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
         self.dm = DependencyContext.get()
         self.report = self.dm.get_dependency(ExceptionReportKey())
@@ -58,13 +57,8 @@ def __init__(self, gen_params: GenParams, unit_fn=ExceptionUnitFn()):
     def elaborate(self, platform):
         m = TModule()
 
-        m.submodules.fifo = fifo = FIFO(self.gen_params.get(FuncUnitLayouts).accept, 2)
         m.submodules.decoder = decoder = self.fn.get_decoder(self.gen_params)
 
-        @def_method(m, self.accept)
-        def _():
-            return fifo.read(m)
-
         @def_method(m, self.issue)
         def _(arg):
             m.d.comb += decoder.exec_fn.eq(arg.exec_fn)
@@ -104,13 +98,15 @@ def _(arg):
 
             self.report(m, rob_id=arg.rob_id, cause=cause, pc=arg.pc, mtval=mtval)
 
-            fifo.write(m, result=0, exception=1, rob_id=arg.rob_id, rp_dst=arg.rp_dst)
+            self.push_result(m, result=0, exception=1, rob_id=arg.rob_id, rp_dst=arg.rp_dst)
 
         return m
 
 
 @dataclass(frozen=True)
 class ExceptionUnitComponent(FunctionalComponentParams):
+    _: KW_ONLY
+    result_fifo: bool = True
     decoder_manager: ExceptionUnitFn = ExceptionUnitFn()
 
     def get_module(self, gen_params: GenParams) -> FuncUnit:
diff --git a/coreblocks/func_blocks/fu/jumpbranch.py b/coreblocks/func_blocks/fu/jumpbranch.py
index 5cfb7a1e5..627468145 100644
--- a/coreblocks/func_blocks/fu/jumpbranch.py
+++ b/coreblocks/func_blocks/fu/jumpbranch.py
@@ -134,7 +134,7 @@ def __init__(self, gen_params: GenParams, jb_fn=JumpBranchFn()):
         layouts = gen_params.get(FuncUnitLayouts)
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
         self.fifo_branch_resolved = FIFO(self.gen_params.get(JumpBranchLayouts).verify_branch, 2)
 
@@ -181,8 +181,7 @@ def elaborate(self, platform):
         )
         m.submodules.instr_fifo = instr_fifo = BasicFifo(instr_fifo_layout, 2)
 
-        @def_method(m, self.accept)
-        def _():
+        with Transaction().body(m):
             instr = instr_fifo.read(m)
             target_prediction = jump_target_resp(m)
 
@@ -250,12 +249,13 @@ def _():
                     misprediction,
                 )
 
-            return {
-                "rob_id": instr.rob_id,
-                "result": instr.reg_res,
-                "rp_dst": instr.rp_dst,
-                "exception": exception,
-            }
+            self.push_result(
+                m,
+                rob_id=instr.rob_id,
+                result=instr.reg_res,
+                rp_dst=instr.rp_dst,
+                exception=exception,
+            )
 
         @def_method(m, self.issue)
         def _(arg):
diff --git a/coreblocks/func_blocks/fu/lsu/dummyLsu.py b/coreblocks/func_blocks/fu/lsu/dummyLsu.py
index 29ec58b4f..e2b7d06e7 100644
--- a/coreblocks/func_blocks/fu/lsu/dummyLsu.py
+++ b/coreblocks/func_blocks/fu/lsu/dummyLsu.py
@@ -45,7 +45,7 @@ def __init__(self, gen_params: GenParams, bus: BusMasterInterface) -> None:
         self.report = self.dependency_manager.get_dependency(ExceptionReportKey())
 
         self.issue = Method(i=self.fu_layouts.issue)
-        self.accept = Method(o=self.fu_layouts.accept)
+        self.push_result = Method(i=self.fu_layouts.push_result)
 
         self.bus = bus
 
@@ -121,8 +121,7 @@ def _(arg):
             results_noop.write(m, data=0, exception=0, cause=0, addr=0)
             issued_noop.write(m, arg)
 
-        @def_method(m, self.accept)
-        def _():
+        with Transaction().body(m):
             arg = Signal(self.fu_layouts.issue)
             res = Signal(self.lsu_layouts.accept)
             with condition(m) as branch:
@@ -138,12 +137,13 @@ def _():
 
             self.log.debug(m, 1, "accept rob_id={} result=0x{:08x} exception={}", arg.rob_id, res.data, res.exception)
 
-            return {
-                "rob_id": arg["rob_id"],
-                "rp_dst": arg["rp_dst"],
-                "result": res["data"],
-                "exception": res["exception"],
-            }
+            self.push_result(
+                m,
+                rob_id=arg["rob_id"],
+                rp_dst=arg["rp_dst"],
+                result=res["data"],
+                exception=res["exception"],
+            )
 
         with Transaction().body(m):
             precommit = self.dependency_manager.get_dependency(InstructionPrecommitKey())
diff --git a/coreblocks/func_blocks/fu/lsu/lsu_atomic_wrapper.py b/coreblocks/func_blocks/fu/lsu/lsu_atomic_wrapper.py
index fc17f6327..28303517f 100644
--- a/coreblocks/func_blocks/fu/lsu/lsu_atomic_wrapper.py
+++ b/coreblocks/func_blocks/fu/lsu/lsu_atomic_wrapper.py
@@ -3,7 +3,6 @@
 from dataclasses import dataclass
 
 from transactron.core import TModule, Method, Transaction, def_method
-from transactron.lib.connectors import Forwarder
 from transactron.utils import assign, layout_subset, AssignType
 
 from coreblocks.arch import Funct3, Funct7, OpType
@@ -34,7 +33,7 @@ def __init__(self, gen_params: GenParams, lsu: FuncUnit):
 
         self.fu_layouts = fu_layouts = gen_params.get(FuncUnitLayouts)
         self.issue = Method(i=fu_layouts.issue)
-        self.accept = Method(o=fu_layouts.accept)
+        self.push_result = Method(i=fu_layouts.push_result)
 
     def elaborate(self, platform):
         m = TModule()
@@ -80,8 +79,6 @@ def atomic_op_res(v1: Value, v2: Value):
 
         load_val = Signal(self.gen_params.isa.xlen)
 
-        accept_forwarder = Forwarder(self.fu_layouts.accept)
-
         @def_method(m, self.issue, ready=~atomic_in_progress)
         def _(arg):
             is_atomic = arg.exec_fn.op_type == OpType.ATOMIC_MEMORY_OP
@@ -100,32 +97,29 @@ def _(arg):
                 m.d.sync += atomic_in_progress.eq(1)
                 m.d.sync += assign(atomic_op, arg, fields=AssignType.LHS)
 
-        @def_method(m, self.accept)
-        def _():
-            return accept_forwarder.read(m)
-
         atomic_second_reqest = Signal()
         atomic_fin = Signal()
 
-        with Transaction().body(m):
-            res = self.lsu.accept(m)
+        push_result = Method(i=self.fu_layouts.push_result)
 
+        @def_method(m, push_result)
+        def _(arg):
             # 1st atomic result
-            with m.If((res.rob_id == atomic_op.rob_id) & atomic_in_progress & ~atomic_second_reqest & ~res.exception):
+            with m.If((arg.rob_id == atomic_op.rob_id) & atomic_in_progress & ~atomic_second_reqest & ~arg.exception):
                 # NOTE: This branch could be optimised by replacing Ifs with condition to be independent of
-                # accept.ready, but it causes combinational loop because of `rob_id` data dependency.
-                m.d.sync += load_val.eq(res.result)
+                # push_result.ready, but it causes combinational loop because of `rob_id` data dependency.
+                m.d.sync += load_val.eq(arg.result)
                 m.d.sync += atomic_second_reqest.eq(1)
-            with m.Elif((res.rob_id == atomic_op.rob_id) & atomic_in_progress & ~atomic_second_reqest & res.exception):
-                accept_forwarder.write(m, res)
+            with m.Elif((arg.rob_id == atomic_op.rob_id) & atomic_in_progress & ~atomic_second_reqest & arg.exception):
+                self.push_result(m, arg)
                 m.d.sync += atomic_in_progress.eq(0)
 
             # 2nd atomic result
             with m.Elif(atomic_in_progress & atomic_fin):
-                atomic_res = Signal(self.fu_layouts.accept)
-                m.d.av_comb += assign(atomic_res, res)
-                m.d.av_comb += atomic_res.result.eq(Mux(res.exception, 0, load_val))
-                accept_forwarder.write(m, atomic_res)
+                atomic_res = Signal(self.fu_layouts.push_result)
+                m.d.av_comb += assign(atomic_res, arg)
+                m.d.av_comb += atomic_res.result.eq(Mux(arg.exception, 0, load_val))
+                self.push_result(m, atomic_res)
 
                 m.d.sync += atomic_in_progress.eq(0)
                 m.d.sync += atomic_second_reqest.eq(0)
@@ -133,7 +127,9 @@ def _():
 
             # Non-atomic results
             with m.Else():
-                accept_forwarder.write(m, res)
+                self.push_result(m, arg)
+
+        self.lsu.push_result.proxy(m, push_result)
 
         with Transaction().body(m, request=atomic_in_progress & atomic_second_reqest & ~atomic_fin):
             atomic_store_op = Signal(self.fu_layouts.issue)
@@ -146,7 +142,6 @@ def _():
 
             m.d.sync += atomic_fin.eq(1)
 
-        m.submodules.accept_forwarder = accept_forwarder
         m.submodules.lsu = self.lsu
 
         return m
diff --git a/coreblocks/func_blocks/fu/mul_unit.py b/coreblocks/func_blocks/fu/mul_unit.py
index 07b935572..f47ebb5f2 100644
--- a/coreblocks/func_blocks/fu/mul_unit.py
+++ b/coreblocks/func_blocks/fu/mul_unit.py
@@ -87,8 +87,8 @@ class MulUnit(FuncUnit, Elaboratable):
     ----------
     issue: Method(i=gen.get(FuncUnitLayouts).issue)
         Method used for requesting computation.
-    accept: Method(i=gen.get(FuncUnitLayouts).accept)
-        Method used for getting result of requested computation.
+    push_result: Method(i=gen.get(FuncUnitLayouts).push_result)
+        Method called for pushing result of requested computation.
     """
 
     def __init__(self, gen_params: GenParams, mul_type: MulType, dsp_width: int = 32, mul_fn=MulFn()):
@@ -105,14 +105,13 @@ def __init__(self, gen_params: GenParams, mul_type: MulType, dsp_width: int = 32
         layouts = gen_params.get(FuncUnitLayouts)
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
         self.mul_fn = mul_fn
 
     def elaborate(self, platform):
         m = TModule()
 
-        m.submodules.result_fifo = result_fifo = FIFO(self.gen_params.get(FuncUnitLayouts).accept, 2)
         m.submodules.params_fifo = params_fifo = FIFO(
             [
                 ("rob_id", self.gen_params.rob_entries_bits),
@@ -139,10 +138,6 @@ def elaborate(self, platform):
         #
         # half_sign_bit = xlen // 2 - 1  # position of sign bit considering only half of input being used
 
-        @def_method(m, self.accept)
-        def _():
-            return result_fifo.read(m)
-
         @def_method(m, self.issue)
         def _(arg):
             m.d.av_comb += decoder.exec_fn.eq(arg.exec_fn)
@@ -204,7 +199,7 @@ def _(arg):
             sign_result = Mux(params.negative_res, -response.o, response.o)  # changing sign of result
             result = Mux(params.high_res, sign_result[xlen:], sign_result[:xlen])  # selecting upper or lower bits
 
-            result_fifo.write(m, rob_id=params.rob_id, result=result, rp_dst=params.rp_dst, exception=0)
+            self.push_result(m, rob_id=params.rob_id, result=result, rp_dst=params.rp_dst, exception=0)
 
         return m
 
@@ -213,6 +208,7 @@ def _(arg):
 class MulComponent(FunctionalComponentParams):
     mul_unit_type: MulType
     _: KW_ONLY
+    result_fifo: bool = False  # last step is registered
     dsp_width: int = 32
     decoder_manager: MulFn = MulFn()
 
diff --git a/coreblocks/func_blocks/fu/priv.py b/coreblocks/func_blocks/fu/priv.py
index addb31d11..755a73887 100644
--- a/coreblocks/func_blocks/fu/priv.py
+++ b/coreblocks/func_blocks/fu/priv.py
@@ -41,12 +41,11 @@ class Fn(IntFlag):
         FENCEI = auto()
         WFI = auto()
 
-    @classmethod
-    def get_instructions(cls) -> Sequence[tuple]:
-        return [(cls.Fn.MRET, OpType.MRET), (cls.Fn.FENCEI, OpType.FENCEI), (cls.Fn.WFI, OpType.WFI)]
+    def get_instructions(self) -> Sequence[tuple]:
+        return [(self.Fn.MRET, OpType.MRET), (self.Fn.FENCEI, OpType.FENCEI), (self.Fn.WFI, OpType.WFI)]
 
 
-class PrivilegedFuncUnit(Elaboratable):
+class PrivilegedFuncUnit(FuncUnit, Elaboratable):
     def __init__(self, gen_params: GenParams, priv_fn=PrivilegedFn()):
         self.gen_params = gen_params
         self.priv_fn = priv_fn
@@ -55,7 +54,7 @@ def __init__(self, gen_params: GenParams, priv_fn=PrivilegedFn()):
         self.dm = DependencyContext.get()
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
         self.fetch_resume_fifo = BasicFifo(self.gen_params.get(FetchLayouts).resume, 2)
 
@@ -128,8 +127,7 @@ def _(arg):
 
             m.d.sync += illegal_instruction.eq(illegal_wfi | illegal_mret)
 
-        @def_method(m, self.accept, ready=instr_valid & finished)
-        def _():
+        with Transaction().body(m, request=instr_valid & finished):
             m.d.sync += instr_valid.eq(0)
             m.d.sync += finished.eq(0)
 
@@ -181,12 +179,13 @@ def _():
                 # Unstall the fetch
                 self.fetch_resume_fifo.write(m, pc=ret_pc)
 
-            return {
-                "rob_id": instr_rob,
-                "exception": exception,
-                "rp_dst": 0,
-                "result": 0,
-            }
+            self.push_result(
+                m,
+                rob_id=instr_rob,
+                exception=exception,
+                rp_dst=0,
+                result=0,
+            )
 
         return m
 
diff --git a/coreblocks/func_blocks/fu/shift_unit.py b/coreblocks/func_blocks/fu/shift_unit.py
index cd6eb5799..a82cb3ab5 100644
--- a/coreblocks/func_blocks/fu/shift_unit.py
+++ b/coreblocks/func_blocks/fu/shift_unit.py
@@ -3,7 +3,6 @@
 from amaranth import *
 
 from transactron import *
-from transactron.lib import FIFO
 
 from coreblocks.params import GenParams, FunctionalComponentParams
 from coreblocks.arch import OpType, Funct3, Funct7
@@ -84,19 +83,14 @@ def __init__(self, gen_params: GenParams, shift_unit_fn=ShiftUnitFn()):
         layouts = gen_params.get(FuncUnitLayouts)
 
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
     def elaborate(self, platform):
         m = TModule()
 
         m.submodules.shift_alu = shift_alu = ShiftUnit(self.gen_params, shift_unit_fn=self.shift_unit_fn)
-        m.submodules.fifo = fifo = FIFO(self.gen_params.get(FuncUnitLayouts).accept, 2)
         m.submodules.decoder = decoder = self.shift_unit_fn.get_decoder(self.gen_params)
 
-        @def_method(m, self.accept)
-        def _():
-            return fifo.read(m)
-
         @def_method(m, self.issue)
         def _(arg):
             m.d.av_comb += decoder.exec_fn.eq(arg.exec_fn)
@@ -105,7 +99,7 @@ def _(arg):
             m.d.av_comb += shift_alu.in1.eq(arg.s1_val)
             m.d.av_comb += shift_alu.in2.eq(Mux(arg.imm, arg.imm, arg.s2_val))
 
-            fifo.write(m, rob_id=arg.rob_id, result=shift_alu.out, rp_dst=arg.rp_dst, exception=0)
+            self.push_result(m, rob_id=arg.rob_id, result=shift_alu.out, rp_dst=arg.rp_dst, exception=0)
 
         return m
 
@@ -113,6 +107,7 @@ def _(arg):
 @dataclass(frozen=True)
 class ShiftUnitComponent(FunctionalComponentParams):
     _: KW_ONLY
+    result_fifo: bool = True
     zbb_enable: bool = False
     decoder_manager: ShiftUnitFn = field(init=False)
 
diff --git a/coreblocks/func_blocks/fu/zbc.py b/coreblocks/func_blocks/fu/zbc.py
index 3c182f715..818989328 100644
--- a/coreblocks/func_blocks/fu/zbc.py
+++ b/coreblocks/func_blocks/fu/zbc.py
@@ -8,7 +8,7 @@
 from coreblocks.params import GenParams, FunctionalComponentParams
 from coreblocks.arch import OpType, Funct3
 from coreblocks.interface.layouts import FuncUnitLayouts
-from transactron import Method, def_method, TModule
+from transactron import Method, Transaction, def_method, TModule
 from transactron.lib import FIFO
 from transactron.utils import OneHotSwitch
 from coreblocks.func_blocks.interface.func_protocols import FuncUnit
@@ -149,7 +149,7 @@ def recursive_module(self):
         return m
 
 
-class ZbcUnit(Elaboratable):
+class ZbcUnit(FuncUnit, Elaboratable):
     """
     Module responsible for executing Zbc instructions (carry-less multiplication)
 
@@ -157,8 +157,8 @@ class ZbcUnit(Elaboratable):
     ----------
     issue: Method(i=FuncUnitLayouts.issue)
         Method used for requesting computation.
-    accept: Method(i=FuncUnitLayouts.accept)
-        Method used for getting result of requested computation.
+    push_result: Method(i=FuncUnitLayouts.push_result)
+        Method called for pushing result of requested computation.
     """
 
     def __init__(self, gen_params: GenParams, recursion_depth: int, zbc_fn: ZbcFn):
@@ -168,7 +168,7 @@ def __init__(self, gen_params: GenParams, recursion_depth: int, zbc_fn: ZbcFn):
         self.recursion_depth = recursion_depth
         self.gen_params = gen_params
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
     def elaborate(self, platform):
         m = TModule()
@@ -187,8 +187,7 @@ def elaborate(self, platform):
 
         m.d.comb += clmul.reset.eq(0)
 
-        @def_method(m, self.accept, ready=~clmul.busy)
-        def _():
+        with Transaction().body(m, request=~clmul.busy):
             xlen = self.gen_params.isa.xlen
 
             output = clmul.result
@@ -197,7 +196,7 @@ def _():
             result = Mux(params.high_res, output[xlen:], output[:xlen])
             reversed_result = Mux(params.rev_res, result[::-1], result)
 
-            return {"rob_id": params.rob_id, "rp_dst": params.rp_dst, "result": reversed_result, "exception": 0}
+            self.push_result(m, rob_id=params.rob_id, rp_dst=params.rp_dst, result=reversed_result, exception=0)
 
         @def_method(m, self.issue)
         def _(exec_fn, imm, s1_val, s2_val, rob_id, rp_dst, pc):
diff --git a/coreblocks/func_blocks/fu/zbs.py b/coreblocks/func_blocks/fu/zbs.py
index a17c7d923..683ac5dd1 100644
--- a/coreblocks/func_blocks/fu/zbs.py
+++ b/coreblocks/func_blocks/fu/zbs.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, KW_ONLY
 from enum import IntFlag, auto
 from typing import Sequence
 from amaranth import *
@@ -7,7 +7,6 @@
 from coreblocks.arch import OpType, Funct3, Funct7
 from coreblocks.interface.layouts import FuncUnitLayouts
 from transactron import Method, TModule, def_method
-from transactron.lib import FIFO
 from transactron.utils import OneHotSwitch
 from coreblocks.func_blocks.interface.func_protocols import FuncUnit
 
@@ -92,8 +91,8 @@ class ZbsUnit(FuncUnit, Elaboratable):
     ----------
     issue: Method(i=FuncUnitLayouts.issue)
         Method used for requesting computation.
-    accept: Method(i=FuncUnitLayouts.accept)
-        Method used for getting result of requested computation.
+    push_result: Method(i=FuncUnitLayouts.push_result)
+        Method called for pushing result of requested computation.
     """
 
     def __init__(self, gen_params: GenParams, zbs_fn=ZbsFunction()):
@@ -101,7 +100,7 @@ def __init__(self, gen_params: GenParams, zbs_fn=ZbsFunction()):
 
         self.gen_params = gen_params
         self.issue = Method(i=layouts.issue)
-        self.accept = Method(o=layouts.accept)
+        self.push_result = Method(i=layouts.push_result)
 
         self.zbs_fn = zbs_fn
 
@@ -109,13 +108,8 @@ def elaborate(self, platform):
         m = TModule()
 
         m.submodules.zbs = zbs = Zbs(self.gen_params, function=self.zbs_fn)
-        m.submodules.result_fifo = result_fifo = FIFO(self.gen_params.get(FuncUnitLayouts).accept, 2)
         m.submodules.decoder = decoder = self.zbs_fn.get_decoder(self.gen_params)
 
-        @def_method(m, self.accept)
-        def _(arg):
-            return result_fifo.read(m)
-
         @def_method(m, self.issue)
         def _(arg):
             m.d.av_comb += decoder.exec_fn.eq(arg.exec_fn)
@@ -124,14 +118,16 @@ def _(arg):
             m.d.av_comb += zbs.in1.eq(arg.s1_val)
             m.d.av_comb += zbs.in2.eq(Mux(arg.imm, arg.imm, arg.s2_val))
 
-            result_fifo.write(m, rob_id=arg.rob_id, result=zbs.result, rp_dst=arg.rp_dst, exception=0)
+            self.push_result(m, rob_id=arg.rob_id, result=zbs.result, rp_dst=arg.rp_dst, exception=0)
 
         return m
 
 
 @dataclass(frozen=True)
 class ZbsComponent(FunctionalComponentParams):
+    _: KW_ONLY
     decoder_manager: ZbsFunction = ZbsFunction()
+    result_fifo: bool = True
 
     def get_module(self, gen_params: GenParams) -> FuncUnit:
         return ZbsUnit(gen_params, self.decoder_manager)
diff --git a/coreblocks/func_blocks/interface/func_protocols.py b/coreblocks/func_blocks/interface/func_protocols.py
index 9024b0d7c..c8eaa0b1f 100644
--- a/coreblocks/func_blocks/interface/func_protocols.py
+++ b/coreblocks/func_blocks/interface/func_protocols.py
@@ -1,5 +1,5 @@
 from typing import Protocol
-from transactron import Method
+from transactron import Method, Provided, Required
 from transactron.utils._typing import HasElaborate
 
 
@@ -7,8 +7,8 @@
 
 
 class FuncUnit(HasElaborate, Protocol):
-    issue: Method
-    accept: Method
+    issue: Provided[Method]
+    push_result: Required[Method]
 
 
 class FuncBlock(HasElaborate, Protocol):
diff --git a/coreblocks/interface/layouts.py b/coreblocks/interface/layouts.py
index 048db5085..bb5cf217b 100644
--- a/coreblocks/interface/layouts.py
+++ b/coreblocks/interface/layouts.py
@@ -525,7 +525,7 @@ def __init__(self, gen_params: GenParams):
             fields.pc,
         )
 
-        self.accept = make_layout(
+        self.push_result = make_layout(
             fields.rob_id,
             self.result,
             fields.rp_dst,
diff --git a/coreblocks/params/fu_params.py b/coreblocks/params/fu_params.py
index e200e6854..0b5f8da8d 100644
--- a/coreblocks/params/fu_params.py
+++ b/coreblocks/params/fu_params.py
@@ -39,6 +39,7 @@ def get_rs_entry_count(self) -> int:
 @dataclass(frozen=True)
 class FunctionalComponentParams(ABC):
     _: KW_ONLY
+    result_fifo: bool = False
     decoder_manager: "DecoderManager" = field(init=False)
 
     def __post_init__(self):
diff --git a/scripts/synthesize.py b/scripts/synthesize.py
index de8d877d4..aa8e5cdcd 100755
--- a/scripts/synthesize.py
+++ b/scripts/synthesize.py
@@ -28,7 +28,7 @@
 from coreblocks.func_blocks.fu.zbc import ZbcComponent
 from coreblocks.func_blocks.fu.zbs import ZbsComponent
 from transactron import TransactionModule
-from transactron.lib import AdapterTrans
+from transactron.lib import Adapter, AdapterTrans
 from coreblocks.peripherals.wishbone import WishboneArbiter, WishboneInterface, WishboneSignature
 from constants.ecp5_platforms import (
     ResourceBuilder,
@@ -111,19 +111,19 @@ def unit_fu(unit_params: FunctionalComponentParams):
     def unit(gen_params: GenParams):
         fu = unit_params.get_module(gen_params)
         issue_adapter = AdapterTrans(fu.issue)
-        accept_adapter = AdapterTrans(fu.accept)
+        push_result_adapter = Adapter(fu.push_result)
 
         issue_connector, issue_resources = InterfaceConnector.with_resources(issue_adapter, "adapter", 0)
-        accept_connector, accept_resources = InterfaceConnector.with_resources(accept_adapter, "adapter", 1)
+        push_connector, push_resources = InterfaceConnector.with_resources(push_result_adapter, "adapter", 1)
 
-        resources = append_resources(issue_resources, accept_resources)
+        resources = append_resources(issue_resources, push_resources)
 
         module = ModuleConnector(
             fu=fu,
             issue_connector=issue_connector,
-            accept_connector=accept_connector,
+            accept_connector=push_connector,
             issue_adapter=issue_adapter,
-            accept_adapter=accept_adapter,
+            accept_adapter=push_result_adapter,
         )
 
         return resources, TransactionModule(module, dependency_manager=DependencyContext.get())
diff --git a/test/backend/test_annoucement.py b/test/backend/test_annoucement.py
index 5177f9f12..30a658fc3 100644
--- a/test/backend/test_annoucement.py
+++ b/test/backend/test_annoucement.py
@@ -21,7 +21,7 @@ def __init__(self, gen_params: GenParams, fu_count: int = 1):
     def elaborate(self, platform):
         m = Module()
 
-        self.lay_result = self.gen_params.get(FuncUnitLayouts).accept
+        self.lay_result = self.gen_params.get(FuncUnitLayouts).push_result
         self.lay_rob_mark_done = self.gen_params.get(ROBLayouts).mark_done_layout
         self.lay_rs_write = self.gen_params.get(
             RSLayouts, rs_entries_bits=self.gen_params.max_rs_entries_bits
diff --git a/test/func_blocks/fu/functional_common.py b/test/func_blocks/fu/functional_common.py
index 031893a7c..1c1380c89 100644
--- a/test/func_blocks/fu/functional_common.py
+++ b/test/func_blocks/fu/functional_common.py
@@ -168,7 +168,7 @@ def setup(self, fixture_initialize_testing_env):
     async def consumer(self, sim: TestbenchContext):
         while self.responses:
             expected = self.responses.pop()
-            result = await self.m.accept.call(sim)
+            result = await self.m.push_result.call(sim)
             assert expected == data_const_to_dict(result)
             await self.random_wait(sim, self.max_wait)
 
diff --git a/test/func_blocks/fu/test_jb_unit.py b/test/func_blocks/fu/test_jb_unit.py
index 84ab5603d..98e2abbb4 100644
--- a/test/func_blocks/fu/test_jb_unit.py
+++ b/test/func_blocks/fu/test_jb_unit.py
@@ -17,7 +17,7 @@
 from test.func_blocks.fu.functional_common import ExecFn, FunctionalUnitTestCase
 
 
-class JumpBranchWrapper(Elaboratable):
+class JumpBranchWrapper(FuncUnit, Elaboratable):
     def __init__(self, gen_params: GenParams, auipc_test: bool):
         self.gp = gen_params
         self.auipc_test = auipc_test
@@ -30,9 +30,9 @@ def __init__(self, gen_params: GenParams, auipc_test: bool):
 
         self.jb = JumpBranchFuncUnit(gen_params)
         self.issue = self.jb.issue
-        self.accept = Method(
-            o=StructLayout(
-                gen_params.get(FuncUnitLayouts).accept.members
+        self.push_result = Method(
+            i=StructLayout(
+                gen_params.get(FuncUnitLayouts).push_result.members
                 | (gen_params.get(JumpBranchLayouts).verify_branch.members if not auipc_test else {})
             )
         )
@@ -41,10 +41,9 @@ def elaborate(self, platform):
         m = TModule()
 
         m.submodules.jb_unit = self.jb
-        m.submodules.res_fifo = res_fifo = BasicFifo(self.gp.get(FuncUnitLayouts).accept, 2)
+        m.submodules.res_fifo = res_fifo = BasicFifo(self.gp.get(FuncUnitLayouts).push_result, 2)
 
-        with Transaction().body(m):
-            res_fifo.write(m, self.jb.accept(m))
+        self.jb.push_result.proxy(m, res_fifo.write)
 
         @def_method(m, self.target_pred_req)
         def _():
@@ -54,8 +53,7 @@ def _():
         def _(arg):
             return {"valid": 0, "cfi_target": 0}
 
-        @def_method(m, self.accept)
-        def _(arg):
+        with Transaction().body(m):
             res = res_fifo.read(m)
             ret = {
                 "result": res.result,
@@ -63,15 +61,15 @@ def _(arg):
                 "rp_dst": res.rp_dst,
                 "exception": res.exception,
             }
-            if self.auipc_test:
-                return ret
-
-            verify = self.jb.fifo_branch_resolved.read(m)
-            return ret | {
-                "next_pc": verify.next_pc,
-                "from_pc": verify.from_pc,
-                "misprediction": verify.misprediction,
-            }
+            if not self.auipc_test:
+                verify = self.jb.fifo_branch_resolved.read(m)
+                ret = ret | {
+                    "next_pc": verify.next_pc,
+                    "from_pc": verify.from_pc,
+                    "misprediction": verify.misprediction,
+                }
+
+            self.push_result(m, ret)
 
         return m
 
diff --git a/test/func_blocks/lsu/test_dummylsu.py b/test/func_blocks/lsu/test_dummylsu.py
index 2348be0a7..87d05352a 100644
--- a/test/func_blocks/lsu/test_dummylsu.py
+++ b/test/func_blocks/lsu/test_dummylsu.py
@@ -95,7 +95,7 @@ def elaborate(self, platform):
         m.submodules.func_unit = func_unit = LSUDummy(self.gen, self.bus_master_adapter)
 
         m.submodules.issue_mock = self.issue = TestbenchIO(AdapterTrans(func_unit.issue))
-        m.submodules.accept_mock = self.accept = TestbenchIO(AdapterTrans(func_unit.accept))
+        m.submodules.push_result_mock = self.push_result = TestbenchIO(Adapter(func_unit.push_result))
         m.submodules.bus_master_adapter = self.bus_master_adapter
         return m
 
@@ -231,7 +231,7 @@ async def inserter(self, sim: TestbenchContext):
 
     async def consumer(self, sim: TestbenchContext):
         for i in range(self.tests_number):
-            v = await self.test_module.accept.call(sim)
+            v = await self.test_module.push_result.call(sim)
             rob_id = v["rob_id"]
             assert rob_id not in self.free_rob_id
             self.free_rob_id.add(rob_id)
@@ -309,7 +309,7 @@ async def one_instr_test(self, sim: TestbenchContext):
         r, v = (
             await CallTrigger(sim)
             .call(self.test_module.bus_master_adapter.get_read_response_mock, data=data, err=0)
-            .call(self.test_module.accept)
+            .call(self.test_module.push_result)
         )
         assert r is not None and v is not None
         assert v["result"] == data
@@ -411,7 +411,7 @@ async def inserter(self, sim: TestbenchContext):
 
     async def get_resulter(self, sim: TestbenchContext):
         for i in range(self.tests_number):
-            v = await self.test_module.accept.call(sim)
+            v = await self.test_module.push_result.call(sim)
             rob_id = self.get_result_data.pop()
             assert v["rob_id"] == rob_id
             assert v["rp_dst"] == 0
@@ -445,7 +445,7 @@ def get_instr(self, exec_fn):
     async def push_one_instr(self, sim: TestbenchContext, instr):
         await self.test_module.issue.call(sim, instr)
 
-        v = await self.test_module.accept.call(sim)
+        v = await self.test_module.push_result.call(sim)
         if instr["exec_fn"]["op_type"] == OpType.LOAD:
             assert v.result == 1
 
diff --git a/test/func_blocks/lsu/test_lsu_atomic_wrapper.py b/test/func_blocks/lsu/test_lsu_atomic_wrapper.py
index e63bf7489..1ce4ff1ba 100644
--- a/test/func_blocks/lsu/test_lsu_atomic_wrapper.py
+++ b/test/func_blocks/lsu/test_lsu_atomic_wrapper.py
@@ -1,8 +1,8 @@
 from collections import deque
 import random
 from amaranth import *
-from transactron import TModule
-from transactron.lib import Adapter
+from transactron import Method, TModule
+from transactron.lib import Adapter, AdapterTrans
 from transactron.testing import MethodMock, SimpleTestCircuit, TestCaseWithSimulator, TestbenchIO, def_method_mock
 
 from coreblocks.arch.isa_consts import Funct3, Funct7
@@ -15,20 +15,20 @@
 
 
 class FuncUnitMock(FuncUnit, Elaboratable):
-    def __init__(self, gen_params):
+    def __init__(self, gen_params: GenParams):
         layouts = gen_params.get(FuncUnitLayouts)
 
-        self.issue_tb = TestbenchIO(Adapter.create(i=layouts.issue))
-        self.accept_tb = TestbenchIO(Adapter.create(o=layouts.accept))
+        self.issue = Method(i=layouts.issue)
+        self.push_result = Method(i=layouts.push_result)
 
-        self.issue = self.issue_tb.adapter.iface
-        self.accept = self.accept_tb.adapter.iface
+        self.issue_tb = TestbenchIO(Adapter(self.issue))
+        self.push_result_tb = TestbenchIO(AdapterTrans(self.push_result))
 
     def elaborate(self, platform):
         m = TModule()
 
         m.submodules.issue_tb = self.issue_tb
-        m.submodules.accept_tb = self.accept_tb
+        m.submodules.push_result_tb = self.push_result_tb
 
         return m
 
@@ -74,7 +74,7 @@ def _():
             )
 
     @def_method_mock(
-        lambda self: self.lsu.accept_tb, enable=lambda self: random.random() < 0.9 and len(self.lsu_res_q) > 0
+        lambda self: self.lsu.push_result_tb, enable=lambda self: random.random() < 0.9 and len(self.lsu_res_q) > 0
     )
     def lsu_accept_mock(self, arg):
         res = self.lsu_res_q[0]
@@ -185,7 +185,7 @@ async def issue_process(self, sim):
 
     async def accept_process(self, sim):
         for _ in range(self.inst_cnt):
-            res = await self.dut.accept.call(sim)
+            res = await self.dut.push_result.call(sim)
             assert res["exception"] == self.result_q[0]["exception"]
             assert res["result"] == self.result_q[0]["result"]
             assert res["rp_dst"] == self.result_q[0]["rp_dst"]
diff --git a/test/func_blocks/lsu/test_pma.py b/test/func_blocks/lsu/test_pma.py
index 831cf6137..c906325ac 100644
--- a/test/func_blocks/lsu/test_pma.py
+++ b/test/func_blocks/lsu/test_pma.py
@@ -75,7 +75,7 @@ def elaborate(self, platform):
         m.submodules.func_unit = func_unit = LSUDummy(self.gen, self.bus_master_adapter)
 
         m.submodules.issue_mock = self.issue = TestbenchIO(AdapterTrans(func_unit.issue))
-        m.submodules.accept_mock = self.accept = TestbenchIO(AdapterTrans(func_unit.accept))
+        m.submodules.push_result_mock = self.push_result = TestbenchIO(Adapter(func_unit.push_result))
         m.submodules.bus_master_adapter = self.bus_master_adapter
         return m
 
@@ -106,7 +106,7 @@ async def verify_region(self, sim: TestbenchContext, region: PMARegion):
             _, v = (
                 await CallTrigger(sim)
                 .call(self.test_module.bus_master_adapter.get_read_response_mock, data=addr << (addr % 4) * 8, err=0)
-                .call(self.test_module.accept)
+                .call(self.test_module.push_result)
                 .until_done()
             )
             assert v.result == addr