def remove_port_connection(source: Port, sink: Port):
    """! @brief Remove/Undo a connection between two Ports."""
    source.outgoing.remove(sink)
    sink.incoming = None
    source.glue_signal = None
    sink.glue_signal = None
    sink.set_connected(False)
    def __init__(self, name: str, parent: AsModule, sub_modules: list):
        super().__init__(name)
        self.assign_to(parent)
        if self.parent is not None:
            self.parent.modules.append(self)
        self.description = (
            "ASTERICS module group '{}' file generated by Automatics"
        ).format(self.name)
        self.signals = []
        self.constants = []
        self.vhdl_libraries = ["helpers"]
        self.modules = sub_modules
        self.static_code = {"signals": [], "body": []}
        self.dynamic_code_generators = [self.__generate_register_vhdl__]
        self.bundles = {"and": [], "or": [], "xor": [], "xnor": []}

        self.register_if = None
        self.reg_assign_map_control = {}
        self.reg_assign_map_status = {}
        self.register_count = 0
        self.register_config = dict()
        self.regmod = None

        # Add standard reset and clk signals and ports
        self.add_standard_port(Port("reset", port_type="external"))
        self.add_standard_port(Port("clk", port_type="external"))
        self.get_port("reset").overwrite_rule("external_port", "none")
Example #3
0
    def test_add_port_w_pre_suffix(self):
        LOG.debug("*UNITTEST* <running test_add_port_w_pre_suffix>")
        # Test with suffixes

        # Start with fresh regif for this test
        self.regif = SlaveRegisterInterface()
        testport_p = Port(
            code_name="right_slv_ctrl_reg_42",
            name="slv_ctrl_reg",
            data_type="slv_reg_data",
        )
        testport_n = Port(name="slv_reg_config",
                          direction="out",
                          data_type="slv_reg_config_table")

        # Add a port with suffix and prefix. This should work regardless
        self.assertTrue(self.regif.add_port(testport_p))
        testport_p = Port(
            code_name="right_slv_reg_modify_42",
            name="slv_reg_modify",
            data_type="std_logic_vector",
            direction="out",
        )
        # Add another port using the same fixes. This should work
        self.assertTrue(self.regif.add_port(testport_p))
        # Try to add a port without fixes.
        self.assertFalse(self.regif.add_port(testport_n))
        testport_n = Port(
            code_name="42_slv_reg_config_right",
            name="slv_reg_config",
            direction="out",
            data_type="slv_reg_config_table",
        )
        # Another negative test using the wrong fixes
        self.assertFalse(self.regif.add_port(testport_n))
 def define_signal(
     self,
     name: str,
     data_type: str = "std_logic",
     data_width: tuple = None,
     fixed_value=None,
 ) -> GenericSignal:
     """! @brief Define, create and add a signal object to this module group.
     @param name  The name for the signal to create
     @param data_type  The data type to set for the signal
     @param data_width  The data width to define for the data type (optional)
     @param fixed_value  (optional) Set a fixed value to assign to the signal
     """
     if data_width:
         data_width = Port.DataWidth(*data_width)
     else:
         data_width = Port.DataWidth(1, None, None)
     signal = GenericSignal(name, data_type=data_type, data_width=data_width)
     if fixed_value:
         glue = GlueSignal(
             name=fixed_value,
             code_name=fixed_value,
             port_type=signal.port_type,
             data_width=signal.data_width,
             optional=False,
         )
         glue.is_signal = False
         signal.glue_signal = glue
         signal.incoming.append(glue)
         glue.set_connected()
         signal.set_connected()
     # Assign signal to this module group and return it
     if self.add_signal(signal):
         return signal
     return None
Example #5
0
    def __init__(self):
        super().__init__("simple_ram_interface")

        self.add_port(Port("wr_en"))
        self.add_port(Port("wr_addr",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="ADDR_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
        self.add_port(Port("rd_addr",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="ADDR_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
        self.add_port(Port("din",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="DATA_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
        self.add_port(Port("dout",
                           direction="out",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="DATA_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
Example #6
0
 def test_add_port_wo_pre_suffix(self):
     LOG.debug("*UNITTEST* <running test_add_port_wo_pre_suffix>")
     # Test without pre-/suffixes
     testport_p = Port(name="slv_ctrl_reg", data_type="slv_reg_data")
     testport_n = Port(name="slv_reg_config",
                       direction="out",
                       data_type="slv_reg_config_table")
     #  self.regif.list_ports()
     self.assertTrue(self.regif.add_port(testport_p))
     self.assertFalse(self.regif.add_port(testport_p))
     self.assertFalse(self.regif.add_port(testport_n))
 def __init__(self):
     super().__init__("slv_reg_interface")
     self.add_port(Port("slv_ctrl_reg", data_type="slv_reg_data"))
     self.add_port(
         Port("slv_status_reg", direction="out", data_type="slv_reg_data"))
     self.add_port(
         Port("slv_reg_modify",
              direction="out",
              data_type="std_logic_vector"))
     self.add_port(
         Port("slv_reg_config",
              direction="out",
              data_type="slv_reg_config_table"))
 def test_get_ports(self):
     LOG.debug("*UNITTEST* <running test_get_ports>")
     # Get the port list
     ports = self.mut.get_port_list()
     # Checks for the found ports:
     # Check the number of ports, name, direction, data type and data width
     self.assertEqual(len(ports), 7)
     self.assertEqual(
         [port.code_name for port in ports],
         [
             "clk",
             "reset",
             "ready",
             "mem_out_data",
             "wideport",
             "invwideport",
             "expdatatest",
         ],
     )
     self.assertEqual(
         [port.direction for port in ports],
         ["in", "inout", "out", "out", "out", "in", "out"],
     )
     self.assertEqual(
         [port.data_type for port in ports],
         [
             "std_logic",
             "std_logic",
             "std_logic",
             "std_logic_vector",
             "bitvector",
             "vector",
             "anothervector",
         ],
     )
     sdwtemp = Port.DataWidth(1, None, None)
     self.assertEqual(
         [port.data_width for port in ports],
         [
             sdwtemp,
             sdwtemp,
             sdwtemp,
             Port.DataWidth("MEMORY_DATA_WIDTH - 1", "downto", 0),
             Port.DataWidth(1023, "downto", 0),
             Port.DataWidth(0, "to", "24 * 11 - 9 + MAX_REGS_PER_MODULE"),
             Port.DataWidth(65535, "downto", 0),
         ],
     )
Example #9
0
def parse_gwindow_type(width_str: str, generics: list) -> list:
    """Parse the generic_window custom VHDL data type."""
    gendict = {}
    for gen in generics:
        gendict[gen.code_name] = gen.get_value()

    out = []
    parens = width_str.lower().split(",")
    for par in parens:
        dt_pos = par.find(" downto ")
        to_pos = par.find(" to ")
        if dt_pos > -1:
            spliton = "downto"
        elif to_pos > -1:
            spliton = "to"
        else:
            continue

        values = par.split(spliton, 1)
        value0 = eval_vhdl_expr(values[0].strip().upper(), "data width",
                                gendict)
        value1 = eval_vhdl_expr(values[1].strip().upper(), "data width",
                                gendict)
        out.append(Port.DataWidth(a=value0, sep=spliton, b=value1))
    return out
Example #10
0
def resolve_data_width(port: Port) -> tuple:
    """Analyse the data width of port and replace generics
    in the data width with the value of matching generics
    found in the module the port belongs to."""
    # Is it already resolved?
    if is_data_width_resolved(port.data_width):
        return port.data_width
    # "Variable" dictionary for 'eval_data_width'
    gvals = {}
    for gen in port.generics:
        # Get value
        val = gen.get_value(top_default=False)
        # If no static value is available,
        # use the code name of the linked generic
        if val is None:
            val = getattr(gen.value, "code_name", None)
            # If that couldn't be fetched, skip this generic
            if val is None:
                continue
        gvals[gen.code_name] = val
    # Evaluate the data width
    new_data_width = as_help.eval_data_width(port, gvals)
    # If the evaluation could not complete
    if not is_data_width_resolved(new_data_width):
        LOG.info(
            ("Can't automatically resolve data width of '%s' in '%s'. "
             "Generic(-s) in '%s' have no value set or is(are) external!"),
            port.code_name,
            port.parent.name,
            port.data_width_to_string(port.data_width),
        )
        return port.data_width
    return new_data_width
Example #11
0
 def set_input(self, input_ref: AsConnectionRef):
     """Set the data input reference for this layer.
     Each layer's input reference should be @ (0,0), with the layer.offset
     signifying the layer's offset from the base layer."""
     port = input_ref.port
     # Check data widths if the port's data width is already fixed
     if is_data_width_resolved(port.data_width):
         port_data_width = Port.data_width_to_string(port.data_width)
         if self.data_width != port_data_width:
             LOG.error(
                 ("Incompatiple layer input detected! '%s'(%s) -> "
                  "'%s'(%s)"),
                 port.code_name,
                 port_data_width,
                 self.name,
                 self.data_width,
             )
             raise AsConnectionError(
                 "Layer and input port data widths differ!")
     if ((input_ref.row < self.parent.rows)
             and (input_ref.col < self.parent.columns)
             and (input_ref.row >= 0 and input_ref.col >= 0)):
         self.input = input_ref
         LOG.debug("Set input for layer '%s' to %s.", self.name,
                   str(input_ref))
     else:
         LOG.error("Input '%s' is out of bounds!", str(input_ref))
    def assign_port_to_register(
        self, register_num: int, port: Port, to_bit_index: int
    ) -> bool:
        """! @brief Assign a Port as a part of a register as a data sink.
        @param register_num  Define the number of the register to assign to
        @param port  The Port to assign to the register
        @param to_bit_index  The bit offset to assign to.
                             register bit map: (31 downto 0)
        """
        if to_bit_index > 31 or to_bit_index < 0:
            LOG.error("Index for register assignment is out of bounds!")
            raise ValueError(to_bit_index, "Out of bounds!", port)
        # If the register index does not have a register associated, add them
        while self.register_count <= register_num:
            if register_num == self.register_count:
                self.add_register(Register.status)
            else:  # Empty registers for empty spots
                self.add_register(Register.none)
        # Update register type if necessary
        if self.register_config[register_num] == "AS_REG_NONE":
            self.modify_register_type(register_num, Register.status)
        elif self.register_config[register_num] == "AS_REG_CONTROL":
            self.modify_register_type(register_num, Register.both)

        # Get or create the register assignment signal
        try:
            reg_signal = self.reg_assign_map_status[register_num]
        except KeyError:
            reg_signal = self.define_signal(
                "s_register_id{}_status".format(register_num),
                data_type="std_logic_vector",
                data_width=Port.DataWidth(31, "downto", 0),
            )
            self._assign_to_register(register_num, reg_signal)

        # Get or create the source signal
        if isinstance(port, GenericSignal):
            source = port
        else:
            self.__update_generics_list__()
            port.glue_signal = self.define_signal_based_on_port(port)
            self.chain.connect(port, port.glue_signal)
            source = port.glue_signal
        # Assign the source signal to the register assignment signal
        reg_signal.assign_to_this_vector(source, to_bit_index)
Example #13
0
 def setUp(self):
     self.regif = SlaveRegisterInterface()
     testports = [
         Port(name="slv_status_reg",
              data_type="slv_reg_data",
              direction="out"),
         Port(name="slv_reg_modify",
              data_type="std_logic_vector",
              direction="out"),
         Port(name="slv_reg_config",
              data_type="slv_reg_config_table",
              direction="out"),
     ]
     self.regif.ports = testports
     self.regif.config = Constant(
         name="slave_register_configuration",
         value='("11","11","01","01","01","10","10","00");',
     )
 def __init__(self):
     super().__init__(self.INTERFACE_TYPE_NAME)
     self.add_port(Port("slv_ctrl_reg", data_type="slv_reg_data"))
     self.add_port(
         Port("slv_status_reg", direction="out", data_type="slv_reg_data")
     )
     self.add_port(
         Port(
             "slv_reg_modify", direction="out", data_type="std_logic_vector"
         )
     )
     self.add_port(
         Port(
             "slv_reg_config",
             direction="out",
             data_type="slv_reg_config_table",
         )
     )
    def __get_constant__(self, file_obj) -> str:
        # Make sure the current line is the complete constant definition
        if ";" not in self.line:
            self.line = self.line.strip(" \n") + self.__next_clean_statement__(
                file_obj)
        # Clean current line, remove the 'constant' keyword and split on ':'
        words = self.line.replace("constant", "", 1).strip(" \n").split(":", 1)
        if len(words) > 1:  # Was there a ':' in this line?
            # If so, we can extract the constant's name
            name = words[0].strip()
            # Split on value assignment
            words = words[1].strip().split(":=", 1)
            if len(words) > 1:  # Was there a ':=' in this line?
                # If so, we can extract both the data type and value.
                data_type = words[0].strip()
                value = words[1].strip(" ;").upper()
                data_width = Port.DataWidth(1, None, None)
                # If the data type is a vector (contains a "(a to/downto b)")
                if "(" in data_type:
                    words = data_type.strip().split("(", maxsplit=1)
                    data_type = words[0].strip()
                    # Get the data width (remove closing bracket)
                    data_width = self.__get_data_width__(words[1][:-1])

                # That's all infos for this constant! Create and add it:
                self.found_constants.append(
                    Constant(
                        code_name=name,
                        data_type=data_type,
                        value=value,
                        data_width=data_width,
                    ))
                LOG.debug(
                    "Found constant '%s' of type '%s' with value '%s'",
                    name,
                    data_type,
                    value,
                )
                return ""

            LOG.error(
                ("Malformed 'constant' declaration: '%s' in '%s': "
                 "Missing ':='!"),
                self.line,
                file_obj.name,
            )
            return "malformed constant declaration"

        LOG.error(
            ("Malformed 'constant' declaration: '%s' in '%s': "
             "Missing ':'!"),
            self.line,
            file_obj.name,
        )
        return "malformed constant declaration"
Example #16
0
 def __init__(
         self,
         name: str = "",
         code_name: str = "",
         port_type: str = "glue_signal",
         data_type: str = "std_logic",
         optional: bool = False,
         data_width=Port.DataWidth(1, None, None),
 ):
     super().__init__(name, code_name, port_type, data_type, optional,
                      data_width)
def resolve_generic(port: Port) -> bool:
    """! @brief Make sure Generics within port's data width exist in its parent module.
    This method makes sure that the Generics in port's data width
    exist in the VDHL entity of port's entity. Port may also be a GlueSignal
    Process: 1. Extract Generic strings from port's data width
    2. Match those strings to Generic objects in Port and the parent module
    3. Check if the Generic value is set; Check for and match linked Generic
    4. If necessary, substitute the Generic(s) with a match in group module
    5. If possible, use the defined value of the Generic
    6. Update port's data width and try to evaluate it.
    @param port: The data width attribute of this port will be resolved.
    @return True if the resolve function ran, False if nothing was done."""
    port.data_width = __resolve_generic__(port.data_width, port)
    try:
        port.line_width = __resolve_generic__(port.line_width, port)
        return all(
            (dw.is_resolved() for dw in (port.data_width, port.line_width)))
    except AttributeError:
        pass
    return port.data_width.is_resolved()
Example #18
0
 def test_is_complete(self):
     LOG.debug("*UNITTEST* <running test_is_complete>")
     # setUp() adds all required ports except for one, this should fail
     self.assertFalse(self.regif.is_complete())
     # Manually (not using add_port()) add the missing port
     tport = REGIF_PORTS[1]
     self.regif.ports.append(
         Port(name=tport.name,
              direction=tport.direction,
              data_type=tport.data_type))
     # Now the regif should report itself as complete
     self.assertTrue(self.regif.is_complete())
def resolve_data_width(port: Port):
    """! @brief Resolves any equations and generic values in port's data width.
    Analyse the data width of port and replace generics
    in the data width with the value of matching generics
    found in the module the port belongs to."""
    if isinstance(port.data_width, list):
        return [__resolve_data_width__(dw, port) for dw in port.data_width]

    if getattr(port, "line_width", False):
        port.line_dw = __resolve_data_width__(port.line_width, port)

    return __resolve_data_width__(port.data_width, port)
 def __port_set_value__(self, port: Port, value: str):
     if (port.port_type + "_port") in Port.rule_conditions:
         port.add_rule(
             (port.port_type + "_port"), "set_value({})".format(value)
         )
     else:
         port.add_rule("source_present", "set_value({})".format(value))
     port.remove_condition("both_present")
     if port.direction == "in":
         port.in_entity = False
 def define_port(
     self,
     name: str,
     code_name: str = "",
     direction: str = "in",
     data_type: str = "std_logic",
     data_width: tuple = None,
     fixed_value: str = "",
 ) -> Port:
     """! @brief Add a port to this module group.
     @param name: The ports base name (without pre- or suffixes)
     @param code_name: The ports name as it appears in VHDL code. [name]
     @param direction: Direction or data ['in'], 'out' or 'inout'.
     @param data_type: The ports VHDL data type. [std_logic]
     @param data_width: The width of vector data types. Use a tuple to define.
                        Example: (7, 'downto', 0); [None]
     @param fixed_value: Optionally set a fixed value for the port. The value of
                         this parameter is directly copied into code!
     @return  The created GenericSignal object."""
     if not code_name:
         code_name = name
     if data_width:
         data_width = Port.DataWidth(*data_width)
     else:
         data_width = Port.DataWidth(1, None, None)
     port = Port(
         name,
         code_name,
         direction,
         port_type="external",
         data_type=data_type,
         optional=False,
         data_width=data_width,
     )
     if fixed_value:
         self.__port_set_value__(port, fixed_value)
     self.add_port(port)
     return port
    def _update_register_params(self):
        # Update config constant value
        self.register_if.config.value = (
            as_help.generate_register_config_value_string(self.register_config)
        )
        # Update register interface port's data width
        for port in ittls.chain(
            self.register_if.ports, [self.regmod, self.register_if.config]
        ):
            port.data_width = Port.DataWidth(0, "to", self.register_count - 1)

        # Update register interface parameters
        self.register_if.config_applied = False
        self.register_if.__decode_slvreg_table__()
Example #23
0
 def __init__(self):
     super().__init__("iic_interface")
     self.add_port(Port("scl_in", direction="in"))
     self.add_port(Port("scl_out", direction="out"))
     self.add_port(Port("scl_out_enable", direction="out"))
     self.add_port(Port("sda_in", direction="in"))
     self.add_port(Port("sda_out", direction="out"))
     self.add_port(Port("sda_out_enable", direction="out"))
     self.to_external = True
Example #24
0
def resolve_data_width(data_width: Port.DataWidth, generics: list) -> list:
    """! @brief Resolve data_width using a list of generics."""
    if data_width.is_resolved():
        return data_width

    gendict = {}
    for gen in generics:
        gendict[gen.code_name] = gen.get_value()

    spliton = data_width.sep
    value0 = eval_vhdl_expr(
        str(data_width.a).strip().upper(), "data width", gendict)
    value1 = eval_vhdl_expr(
        str(data_width.b).strip().upper(), "data width", gendict)
    return Port.DataWidth(a=value0, sep=spliton, b=value1)
Example #25
0
    def __get_data_width__(parens: str) -> str:
        parens = parens[1:-1]
        # Determine the "direction" of the data width assignment
        dt_pos = parens.find(" downto ")
        to_pos = parens.find(" to ")
        if dt_pos > -1:
            spliton = "downto"
        elif to_pos > -1:
            spliton = "to"
        else:
            return ""

        values = parens.split(spliton, 1)
        value0 = eval_vhdl_expr(values[0].strip().upper(), "data width")
        value1 = eval_vhdl_expr(values[1].strip().upper(), "data width")
        return Port.DataWidth(a=value0, sep=spliton, b=value1)
Example #26
0
 def __init__(
         self,
         name: str = "",
         code_name: str = "",
         port_type: str = "signal",
         data_type: str = "std_logic",
         optional: bool = False,
         data_width=Port.DataWidth(1, None, None),
 ):
     super().__init__(name, code_name, "inout", port_type, data_type,
                      optional, data_width)
     self.incoming = []
     self.is_signal = True
     self.vector_map_incoming = dict()
     self.vector_map_outgoing = dict()
     self.vector_assignment_tasks = []
    def build_inout_vectors(self) -> GenericSignal:
        # Get module ports
        mod_in_port = self.module.get_port("buff_in")
        mod_out_port = self.module.get_port("data_out")
        mod_line_port = self.module.get_port("line_out")

        foreach(self.module.get_full_port_list(), resolve_generic)

        # Create intermediate vector signals
        sig_name = self.name + "_data_"
        self.in_signal = self.pipe.define_signal(
            sig_name + "in",
            data_type="std_logic_vector",
            data_width=(self.bit_width_in - 1, "downto", 0),
        )
        self.out_signal = self.pipe.define_signal(
            sig_name + "out",
            data_type="std_logic_vector",
            data_width=(self.bit_width_in - 1, "downto", 0),
        )
        # Connect them to the buffers input and output
        self.pipe.chain.__connect__(self.in_signal, mod_in_port, top=self.pipe)
        self.pipe.chain.__connect__(mod_out_port,
                                    self.out_signal,
                                    top=self.pipe)
        # Define vector signal connections
        for source in self.inputs:
            self.in_signal.assign_to_this_vector(source.port,
                                                 source.start_index)
        for target in self.outputs:
            self.out_signal.assign_from_this_vector(target.port,
                                                    target.start_index)
        # Create line port signal
        self.line_signal = self.pipe.define_signal(
            self.name + "_line_data",
            data_type="t_generic_line",
            data_width=(self.bit_width_in - 1, "downto", 0),
        )
        setattr(
            self.line_signal,
            "line_width",
            Port.DataWidth(0, "to", self.window_width - 1),
        )
        # Connect to buffer module line port
        self.pipe.__connect__(self.line_signal, mod_line_port)
        return self.line_signal
 def __init__(self):
     super().__init__(self.INTERFACE_TYPE_NAME)
     self.add_port(Port("reset_n", direction="out"))
     self.add_port(Port("powerdown", direction="out"))
     self.add_port(Port("pixclk"))
     self.add_port(Port("frame_valid"))
     self.add_port(Port("line_valid"))
     self.add_port(
         Port(
             "data",
             data_type="std_logic_vector",
             data_width=Port.DataWidth("SENSOR_DATA_WIDTH - 1", "downto", 0),
         )
     )
     self.set_prefix_suffix("sensor_", "")
     self.to_external = True
Example #29
0
 def convert_window_port_to_vector(self) -> list:
     """! @brief Convert as_window to only use standard data types.
     If this module wrapper contains a window module, the window port's
     data type must be converted from t_generic_window to std_logic_vector.
     Generates the conversion code and adds the necessary signals within
     the wrapper VHDL file (conversion from vector to window type) and
     converts the port data type."""
     # If we wrap a window module, we need to convert t
     if not isinstance(self.modules[0], AsWindowModule):
         return None
     mod = self.modules[0]
     window_ports = []
     conversion_template = (
         "f_convert_vector_to_generic_window({vector_name}, {x}, {y})")
     # Xilinx Vivado OOC Synthesis can't deal with custom data types
     # For all window interfaces, take the window port using the
     # t_generic_window data type and convert it to a std_logic_vector
     # Within this wrapper, take the vectorized port and convert it back
     # to a t_generic_window port to pass to the filter module.
     # The conversion from window to vector is done in the 2D Pipeline class
     for winter in getattr(self, "window_interfaces"):
         wport = winter.window_port
         window_dims = winter.window
         window_elements = window_dims.x * window_dims.y
         new_vector_width = (window_elements *
                             wport.data_width.get_bit_width())
         wport.data_type = "std_logic_vector"
         wport.data_width = Port.DataWidth(new_vector_width - 1, "downto",
                                           0)
         mport = mod.get_port(wport.code_name, suppress_error=True)
         sig = self.define_signal(
             mport.code_name + "_reconv",
             data_type=mport.data_type,
             data_width=mport.data_width,
             fixed_value=conversion_template.format(
                 vector_name=wport.code_name,
                 x=window_dims.x,
                 y=window_dims.y,
             ),
         )
         sig.window_config = wport.window_config
         wport.window_config = None
         mport.incoming = sig
         window_ports.append(wport)
     return window_ports
    def assign_register_to_port(
        self, register_num: int, port: Port, from_bit_index: int
    ):
        """! @brief Assign part of a register as a data source to a Port.
        @param register_num  Define the number of the register to assign from
        @param port  The Port to assign the register value to
        @param from_bit_index  The bit offset to assign from.
                               register bit map: (31 downto 0)"""

        # If the register index does not have a register associated, add them
        while self.register_count <= register_num:
            if register_num == self.register_count:
                self.add_register(Register.control)
            else:  # Empty registers for empty spots
                self.add_register(Register.none)

        # Update register type if necessary
        if self.register_config[register_num] == "AS_REG_NONE":
            self.modify_register_type(register_num, Register.control)
        elif self.register_config[register_num] == "AS_REG_STATUS":
            self.modify_register_type(register_num, Register.both)

        # Get or create the register assignment signal
        try:
            reg_signal = self.reg_assign_map_control[register_num]
        except KeyError:
            reg_signal = self.define_signal(
                "s_register_id{}_control".format(register_num),
                data_type="std_logic_vector",
                data_width=Port.DataWidth(31, "downto", 0),
            )
            self._assign_from_register(register_num, reg_signal)

        self.__update_generics_list__()
        if isinstance(port, GenericSignal):
            target = port
        else:
            sig = self.define_signal_based_on_port(port)
            self.chain.connect(port, sig)
            target = sig

        # Assign from the register to the target signal
        reg_signal.assign_from_this_vector(target, from_bit_index)