如何从 VHDL 中的实体变量创建子信号/子变量?

How to create a subsignal / subvariable from an entity variable in VHDL?

我目前正在用 VHDL 实现 MIPS 处理器。系统组件(将 ALU、寄存器文件、控制单元等粘合在一起)具有以下实体描述:

entity system is
    port (
                 reset : in std_logic;
                 sys_clk : in std_logic;
                 instruction : in std_logic_vector(15 downto 0);
                 sys_mem_dump : in std_logic := '0'
         );
end system;

在这个系统的架构部分,我正在尝试创建 "subvariables" 指令变量,对应于正在使用的操作码和寄存器。

architecture Behavioral of system is
        instruction_opcode : std_logic_vector(3 downto 0) := instruction(15 downto 12);
        instruction_rd : std_logic_vector(3 downto 0) := instruction(11 downto 8); -- destination register
        instruction_rs : std_logic_vector(3 downto 0) := instruction(7 downto 4); -- source register
        instruction_rt : std_logic_vector(3 downto 0) := instruction(3 downto 0); -- target register
        -- a bunch of signals
begin 
    -- a bunch of port maps
end Behavioral

我试过signalvariableshared_variableconstant,但是这些导致当我移植映射一时寄存器文件的地址没有被初始化这些变量。我也试过将这些变量放在系统实体端口中,但这也不起作用。我也不想将系统实体端口中的 instruction 变量拆分为这四个变量。

同意 paebles 的观点:您似乎缺乏基本的 VHDL 知识,应该在您的书中寻找这些知识。

你至少应该知道这个方法:

architecture Behavioral of system is
    signal instruction_opcode : std_logic_vector(3 downto 0);
begin
    instruction_opcode <= instruction(15 downto 12);
end architecture;

但实际上你可以使用别名:

architecture Behavioral of system is
    alias instruction_opcode : std_logic_vector(3 downto 0) is instruction(15 downto 12);
begin
end architecture;

反映您的评论的常见话题

@Paebbels Is it simply not possible to do this in VHDL? I have looked at the synario manual and some other websites, and none of the data object types match this use case.

是你使用的参考文献不充分

除了 JH Bonarius 的回答中描述的中间信号和对象别名之外,还有一种方法使用声明为子类型的索引范围:

library ieee;
use ieee.std_logic_1164.all;

entity field is
    port (
        fourbitfield:   in  std_logic_vector (3 downto 0)
    );
end entity;

architecture foo of field is 
begin
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity system is
    port (
        reset:          in  std_logic;
        sys_clk:        in  std_logic;
        instruction:    in  std_logic_vector(15 downto 0);
        sys_mem_dump:   in  std_logic := '0'
    );
end entity system;

architecture foo of system is
    subtype opcode is integer range 15 downto 12;
    subtype rd is integer range 11 downto 8;
    subtype rs is integer range 7 downto 4;
    subtype rt is integer range 3 downto 0;
begin
U1: 
    entity work.field port map (instruction(opcode));

U2: 
    entity work.field port map (instruction(rd));

U3: 
    entity work.field port map (instruction(rs));

U4: 
    entity work.field port map (instruction(rt));
end architecture;

这分析、阐述和模拟(在证明缺乏边界错误时实际上没有做任何事情)。

实体是一个独立的设计单元,自然允许抽象(在详细说明组件实例化期间,端口名称与端口映射中的实际信号相关联)。所有其他形式的名称或使用中间对象都是旨在提高可读性的抽象形式,并由样式决定。

在上面的 instruction(opcode) 中,切片名称(IEEE Std 1076-2008 8.5 切片名称)以整数子类型的形式提供离散范围。您同样可以直接使用具有离散范围(例如 15 到 12)的切片名称作为关联列表中的实际值,而无需声明子类型:

U1:
    entity work.field port map (fourbitfield => instruction(15 downto 12));

在此处显示的正式端口和实际信号之间使用命名关联可以排除进一步抽象的需要。指示抽象会影响 VHDL 标准不需要的样式。

您对子信号或变量的想法与 VHDL 中的切片名称对齐就像使用中间信号一样容易。别名只是命名实体(包括对象切片)的其他名称。

您使用哪种额外的抽象方法可能取决于预期 reader 的复杂程度。

如果有人在 Whosebug 上彻底搜索 标签,您会找到所有这三种方法的示例。狡猾的 reader 可以编辑您的问题以符合 VHDL 语法并将其作为副本提交。