Nos cursos de Design Lógico, todos aprendemos que é possível minimizar uma função lógica, por exemplo, usando um mapa de Karnaugh ou o algoritmo Quine – McCluskey . Também aprendemos que os valores "Não me importo" aumentam o potencial de minimização.
Por exemplo, pegue um arquivo de registro. Os sinais write_address
e write_data
realmente não importam quando o write_enable
sinal é '0'
. Portanto, eles devem receber um valor "Não se importam" para permitir mais otimizações na lógica que está direcionando esses sinais (ou seja, não no próprio arquivo de registro).
Qual é a maneira correta de especificar esses valores "Não me importo" em VHDL para permitir que a ferramenta de síntese tenha mais espaço para possíveis otimizações?
Até agora, encontrei as seguintes coisas que podem ser adequadas. Mas não tenho muita certeza de quais são os prós e os contras de cada abordagem:
- Simplesmente não atribuindo o sinal. Parece que poderia funcionar. No entanto, descobri que não funciona quando você deseja definir um tipo "não faça constante" de algum
record
tipo, pois as constantes de registro precisam ser totalmente especificadas (pelo menos o Modelsim me diz isso). - O
std_logic_1164
pacote define o valor'-' -- Don't care
parastd_ulogic
. Parece que é a escolha semanticamente correta para um "não se importe" explícito, mas nunca o vi usado em nenhum lugar (exceto nascase?
construções não relacionadas do VHDL-2008 ). - Modelsim usa o valor
'X'
para exibir sinais indefinidos. No entanto, não tenho certeza se as ferramentas de síntese entendem uma'X'
atribuição explícita como "não me importo".
Aqui está um trecho de código simplificado demais para esclarecimentos, onde eu inicializei os sinais de não se importar '-'
.
Como você pode ver, o sinal control.reg_write_address
pode ter 3 valores diferentes: "----"
, instruction(11 downto 8);
e instruction(3 downto 0);
. Agora, eu espero que isso seja sintetizado em um multiplexador de 2 entradas se '-'
for interpretado como "não me importo". Se eu tivesse inicializado o sinal com, em (others => '0')
vez de '-'
, a ferramenta teria que gerar um multiplexador de 3 entradas.
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
ewrite_data
? Qual otimização você espera que ocorra?