diff --git a/b_asic/resources.py b/b_asic/resources.py
index 8977b3b31e1610def27c42781ee0d1ba59f17fae..ad7a3744b2acd80b0c3b426bb5646171af4694f0 100644
--- a/b_asic/resources.py
+++ b/b_asic/resources.py
@@ -8,7 +8,7 @@ from matplotlib.axes import Axes
 from matplotlib.ticker import MaxNLocator
 
 from b_asic._preferences import LATENCY_COLOR
-from b_asic.process import Process
+from b_asic.process import MemoryVariable, PlainMemoryVariable, Process
 
 # Default latency coloring RGB tuple
 _LATENCY_COLOR = tuple(c / 255 for c in LATENCY_COLOR)
@@ -34,6 +34,53 @@ def _sorted_nicely(to_be_sorted: Iterable[_T]) -> List[_T]:
     return sorted(to_be_sorted, key=alphanum_key)
 
 
+def _sanitize_port_option(
+    read_ports: Optional[int] = None,
+    write_ports: Optional[int] = None,
+    total_ports: Optional[int] = None,
+) -> Tuple[int, int, int]:
+    """
+    General port sanitization function, to test if a port specification makes sense.
+    Raises ValueError if the port specification is in-proper.
+
+    Parameters
+    ----------
+    read_ports : int, optional
+        The number of read ports.
+    write_ports : int, optional
+        The number of write ports.
+    total_ports : int, optional
+        The total number of ports
+
+    Returns
+    -------
+    Returns a triple int tuple (read_ports, write_ports, total_ports) equal to the input, or sanitized if one of the input equals None.
+    If total_ports is set to None at the input, it is set to read_ports+write_ports at the output.
+    If read_ports or write_ports is set to None at the input, it is set to total_ports at the output.
+
+    """
+    if total_ports is None:
+        if read_ports is None or write_ports is None:
+            raise ValueError(
+                "If total_ports is unset, both read_ports and write_ports"
+                " must be provided."
+            )
+        else:
+            total_ports = read_ports + write_ports
+    else:
+        read_ports = total_ports if read_ports is None else read_ports
+        write_ports = total_ports if write_ports is None else write_ports
+    if total_ports < read_ports:
+        raise ValueError(
+            f'Total ports ({total_ports}) less then read ports ({read_ports})'
+        )
+    if total_ports < write_ports:
+        raise ValueError(
+            f'Total ports ({total_ports}) less then write ports ({write_ports})'
+        )
+    return (read_ports, write_ports, total_ports)
+
+
 def draw_exclusion_graph_coloring(
     exclusion_graph: nx.Graph,
     color_dict: Dict[Process, int],
@@ -75,6 +122,7 @@ def draw_exclusion_graph_coloring(
         '#0000ff',
         '#ff00aa',
         '#ffaa00',
+        '#ffffff',
         '#00ffaa',
         '#aaff00',
         '#aa00ff',
@@ -85,6 +133,7 @@ def draw_exclusion_graph_coloring(
         '#aaaa00',
         '#aa00aa',
         '#00aaaa',
+        '#666666',
     ]
     if color_list is None:
         node_color_dict = {k: COLOR_LIST[v] for k, v in color_dict.items()}
@@ -288,17 +337,9 @@ class ProcessCollection:
         nx.Graph
 
         """
-        if total_ports is None:
-            if read_ports is None or write_ports is None:
-                raise ValueError(
-                    "If total_ports is unset, both read_ports and write_ports"
-                    " must be provided."
-                )
-            else:
-                total_ports = read_ports + write_ports
-        else:
-            read_ports = total_ports if read_ports is None else read_ports
-            write_ports = total_ports if write_ports is None else write_ports
+        read_ports, write_ports, total_ports = _sanitize_port_option(
+            read_ports, write_ports, total_ports
+        )
 
         # Guard for proper read/write port settings
         if read_ports != 1 or write_ports != 1:
@@ -359,13 +400,37 @@ class ProcessCollection:
                     t1 = set(
                         range(
                             process1.start_time,
-                            process1.start_time + process1.execution_time,
+                            min(
+                                process1.start_time + process1.execution_time,
+                                self._schedule_time,
+                            ),
+                        )
+                    ).union(
+                        set(
+                            range(
+                                0,
+                                process1.start_time
+                                + process1.execution_time
+                                - self._schedule_time,
+                            )
                         )
                     )
                     t2 = set(
                         range(
                             process2.start_time,
-                            process2.start_time + process2.execution_time,
+                            min(
+                                process2.start_time + process2.execution_time,
+                                self._schedule_time,
+                            ),
+                        )
+                    ).union(
+                        set(
+                            range(
+                                0,
+                                process2.start_time
+                                + process2.execution_time
+                                - self._schedule_time,
+                            )
                         )
                     )
                     if t1.intersection(t2):
@@ -448,17 +513,9 @@ class ProcessCollection:
         -------
         A set of new ProcessCollection objects with the process splitting.
         """
-        if total_ports is None:
-            if read_ports is None or write_ports is None:
-                raise ValueError(
-                    "If total_ports is unset, both read_ports and write_ports"
-                    " must be provided."
-                )
-            else:
-                total_ports = read_ports + write_ports
-        else:
-            read_ports = total_ports if read_ports is None else read_ports
-            write_ports = total_ports if write_ports is None else write_ports
+        read_ports, write_ports, total_ports = _sanitize_port_option(
+            read_ports, write_ports, total_ports
+        )
         if heuristic == "graph_color":
             return self._split_ports_graph_color(read_ports, write_ports, total_ports)
         else:
@@ -554,15 +611,18 @@ class ProcessCollection:
         self,
         coloring_strategy: str = "saturation_largest_first",
     ) -> Dict[int, "ProcessCollection"]:
-        """graph_color_cell_assignment.
+        """
+        Perform cell assignment of the processes in this collection using graph coloring with networkx.coloring.greedy_color.
+        Two or more processes can share a single cell if, and only if, they have no overlaping time alive.
 
         Parameters
         ----------
-
+        coloring_strategy : str, default: "saturation_largest_first"
+            Graph coloring strategy passed to networkx.coloring.greedy_color().
 
         Returns
         -------
-        Dict[int, "ProcessCollection"]
+        Dict[int, ProcessCollection]
 
         """
         cell_assignment: Dict[int, ProcessCollection] = dict()
@@ -570,15 +630,22 @@ class ProcessCollection:
         coloring: Dict[Process, int] = nx.coloring.greedy_color(
             exclusion_graph, strategy=coloring_strategy
         )
+        for process, cell in coloring.items():
+            try:
+                cell_assignment[cell].add_process(process)
+            except:
+                cell_assignment[cell] = ProcessCollection(set(), self._schedule_time)
+                cell_assignment[cell].add_process(process)
         return cell_assignment
 
     def left_edge_cell_assignment(self) -> Dict[int, "ProcessCollection"]:
         """
-        Perform left edge cell assignment of this process collection.
+        Perform cell assignment of the processes in this collection using the left-edge algorithm.
+        Two or more processes can share a single cell if, and only if, they have no overlaping time alive.
 
         Returns
         -------
-        Dict[Process, int]
+        Dict[int, ProcessCollection]
         """
         next_empty_cell = 0
         cell_assignment: Dict[int, ProcessCollection] = dict()
@@ -613,6 +680,9 @@ class ProcessCollection:
     def generate_memory_based_storage_vhdl(
         self,
         filename: str,
+        read_ports: Optional[int] = None,
+        write_ports: Optional[int] = None,
+        total_ports: Optional[int] = None,
     ):
         """
         Generate VHDL code for memory based storage of processes (MemoryVariables).
@@ -621,7 +691,53 @@ class ProcessCollection:
         ----------
         filename : str
             Filename of output file.
+        read_ports : int, optional
+            The number of read ports used when splitting process collection based on
+            memory variable access. If total ports in unset, this parameter has to be set
+            and total_ports is assumed to be read_ports + write_ports.
+        write_ports : int, optional
+            The number of write ports used when splitting process collection based on
+            memory variable access. If total ports is unset, this parameter has to be set
+            and total_ports is assumed to be read_ports + write_ports.
+        total_ports : int, optional
+            The total number of ports used when splitting process collection based on
+            memory variable access.
         """
 
-        # Check that hardware can be generated for the ProcessCollection...
-        raise NotImplementedError("Not implemented yet!")
+        # Check that this is a ProcessCollection of (Plain)MemoryVariables
+        is_memory_variable = all(
+            isinstance(process, MemoryVariable) for process in self._collection
+        )
+        is_plain_memory_variable = all(
+            isinstance(process, PlainMemoryVariable) for process in self._collection
+        )
+        if not (is_memory_variable or is_plain_memory_variable):
+            raise ValueError(
+                "HDL can only be generated for ProcessCollection of"
+                " (Plain)MemoryVariables"
+            )
+
+        # Sanitize port settings
+        read_ports, write_ports, total_ports = _sanitize_port_option(
+            read_ports, write_ports, total_ports
+        )
+
+        # Make sure that concurrent reads/writes do not surpass the port setting
+        for mv in self:
+            filter_write = lambda p: p.start_time == mv.start_time
+            filter_read = (
+                lambda p: (p.start_time + p.execution_time) & self._schedule_time
+                == mv.start_time + mv.execution_time % self._schedule_time
+            )
+            if len(list(filter(filter_write, self))) > write_ports + 1:
+                raise ValueError(
+                    f'More than {write_ports} write ports needed to generate HDL for'
+                    ' this ProcessCollection'
+                )
+            if len(list(filter(filter_read, self))) > read_ports + 1:
+                raise ValueError(
+                    f'More than {read_ports} read ports needed to generate HDL for this'
+                    ' ProcessCollection'
+                )
+
+        # raise NotImplementedError("Not implemented yet!")
diff --git a/test/test_resources.py b/test/test_resources.py
index 48a5589846d53836ddc73f58142f9e5e30ec1d3f..3008e9bfdeec1c248494f23a1828a1ddd8bd1099 100644
--- a/test/test_resources.py
+++ b/test/test_resources.py
@@ -3,11 +3,12 @@ import pickle
 import matplotlib.pyplot as plt
 import pytest
 
+from b_asic.process import PlainMemoryVariable
 from b_asic.research.interleaver import (
     generate_matrix_transposer,
     generate_random_interleaver,
 )
-from b_asic.resources import ProcessCollection
+from b_asic.resources import ProcessCollection, draw_exclusion_graph_coloring
 
 
 class TestProcessCollectionPlainMemoryVariable:
@@ -33,11 +34,20 @@ class TestProcessCollectionPlainMemoryVariable:
     def test_left_edge_cell_assignment(self, simple_collection: ProcessCollection):
         fig, ax = plt.subplots(1, 2)
         assignment = simple_collection.left_edge_cell_assignment()
-        for cell in assignment.keys():
+        for cell in assignment:
             assignment[cell].plot(ax=ax[1], row=cell)
         simple_collection.plot(ax[0])
         return fig
 
+    def test_cell_assignment_matrix_transposer(self):
+        collection = generate_matrix_transposer(4, min_lifetime=5)
+        assignment_left_edge = collection.left_edge_cell_assignment()
+        assignment_graph_color = collection.graph_color_cell_assignment(
+            coloring_strategy='saturation_largest_first'
+        )
+        assert len(assignment_left_edge.keys()) == 18
+        assert len(assignment_graph_color.keys()) == 16
+
     # Issue: #175
     def test_interleaver_issue175(self):
         with open('test/fixtures/interleaver-two-port-issue175.p', 'rb') as f: