在逻辑设计课程中,我们都知道可以最小化逻辑函数,例如使用卡诺图或Quine-McCluskey 算法。我们还了解到,“不关心”值增加了最小化的潜力。
例如拿一个寄存器文件。当信号为时, write_address
andwrite_data
信号并不重要。因此,应该为它们分配一个“无关”值,以允许在驱动这些信号的逻辑中进行更多优化(即不在寄存器文件本身中)。write_enable
'0'
为了让综合工具有更多空间进行可能的优化,在 VHDL 中指定此类“无关”值的正确方法是什么?
到目前为止,我发现了以下可能合适的东西。但我不太确定每种方法的优缺点是什么:
- 只是不分配信号。这似乎可以工作。但是我发现当你想定义某种类型的“什么都不做常量”时它不起作用
record
,因为需要完全指定记录常量(至少 Modelsim 告诉我)。 std_logic_1164
包定义了的'-' -- Don't care
值std_ulogic
。这看起来像是明确“不在乎”的语义正确选择,但我从未见过它在任何地方使用过(除了在不相关的 VHDL-2008case?
结构中)。- Modelsim 使用该值
'X'
来显示未定义的信号。但是我不确定综合工具是否将显式'X'
-assign 理解为“不关心”。
这是一个过于简化的代码片段,用于澄清,我在其中初始化了无关信号'-'
。
如您所见,信号control.reg_write_address
可以有 3 个不同的值"----"
:instruction(11 downto 8);
和instruction(3 downto 0);
。'-'
现在,如果被解释为“不关心”,我希望这将被合成到一个 2 输入多路复用器。(others => '0')
如果我用代替初始化信号'-'
,该工具将不得不生成一个 3 输入多路复用器。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package mytypes is
type control_signals_t is record
write_enable : std_logic;
write_address : std_ulogic_vector(3 downto 0);
read_address : std_ulogic_vector(3 downto 0);
end record;
-- All members of this constant must be fully specified.
-- So it's not possible to simply not assign a value.
constant CONTROL_NOP : control_signals_t := (
write_enable => '0',
write_address => (others => '-'),
read_address => (others => '-')
);
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library cfx;
use cfx.mytypes.all;
entity control_unit is
port(
instruction : in std_ulogic_vector(15 downto 0);
write_data : out std_ulogic_vector(15 downto 0);
ctrl : out control_signals_t
);
end entity;
architecture rtl of control_unit is
begin
decode_instruction : process(instruction) is
begin
-- Set sensible default values that do nothing.
-- Especially all "write_enable" signals should be '0'.
-- Everything else is mostly irrelevant (don't care).
ctrl <= CONTROL_NOP;
write_data <= (others => '-');
if instruction(15 downto 12) = "1100" then
-- Load 8 bit of data into the register file
ctrl.write_enable <= '1';
write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
ctrl.write_address <= instruction(11 downto 8);
elsif instruction(15 downto 8) = "11111001" then
-- Load 4 bit of data into the register file
write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
ctrl.write_address <= instruction(3 downto 0);
elsif instruction(15 downto 8) = "10110101" then
-- Read from the register file. Don't use the write signals at all.
ctrl.read_address <= instruction(3 downto 0);
end if;
end process;
end architecture;