ロジックデザインコースでは、たとえば、カルノーマップまたはQuine–McCluskeyアルゴリズムを使用することにより、ロジック関数を最小化することが可能であることを学びました。また、それを学んだ「Do n't Care」値が最小化の可能性を高める。
たとえば、レジスタファイルを取得します。するときの信号は本当に重要ではありません信号です。したがって、「Do n't Care」値を割り当てて、次のようなロジックでより最適化できるようにする必要があります。write_address
write_data
write_enable
'0'
これらの信号を駆動(レジスタファイル自体ではない)でます。
合成ツールで可能な最適化の余地を増やすために、VHDLでこのような「Do n't Care」値を指定する正しい方法は何ですか?
これまでのところ、次のような適切なものを見つけました。しかし、私はそれぞれのアプローチの長所と短所が何であるか本当にわかりません:
- 単に信号を割り当てない。これはうまくいくようです。ただし
record
、レコード定数を完全に指定する必要があるため(少なくともModelsimでそう指示されているため)、何らかのタイプの「何もしない定数」を定義する場合は機能しないことがわかりました。 std_logic_1164
パッケージには、値定義'-' -- Don't care
のためにstd_ulogic
。これは、明示的な「ドントケア」に対する意味的に正しい選択のように見えますが、どこでも使用されたことはありません(無関係なVHDL-2008case?
コンストラクトを除く)。- Modelsimはこの値
'X'
を使用して未定義の信号を表示します。しかし、合成ツールが明示的なものを理解しているかどうかはわかりません'X'
割り当てを「ドントケア」としてません。
わかりやすくするために過度に簡略化したコードスニペットを示します。ここでは、ドントケア信号を初期化しました。 '-'
ます。
ご覧のとおり、信号に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;
write_address
とwrite_data
?どのような最適化が行われますか?