Why are you using a truth table, if there are predefined VHDL mechanisms...?
B <= "000" when (disable = '1') else A;
C <= "000" when (disable = '1') else not A;
OR if needed as integer result
B <= 0 when (disable = '1') else to_integer(unsigned(A));
C <= 0 when (disable = '1') else to_integer(unsigned(not A));
Improvement 1:
You can write a function mux(...) or call it ite(...) (short for if-then-else) like this:
function ite(condition : boolean; a : std_logic_vector; b : std_logic_vector) return std_logic_vector is
begin
if (cond = true) then
return a;
else
return b;
end if;
end function;
Now you can write the statements above a bit shorter:
B <= ite((disable = '1'), "000", A);
C <= ite((disable = '1'), "000", not A);
Improvement 2:
Calculate the result with basic boolean operations. You can blow-up your disable signal to as many bits as A is wide and then use the conjunction operator. (This is also called 'A is gated by disable' or gate circuit).
B <= (A'range => disable) and A;
C <= (A'range => disable) and not A;
My examples use now type conversion (your example has std_logic_vector as in- and outputs).
if needed feel free to add conversion functions like unsigned(..) or to_integer(..).
Truth Tables / ROMs
If you really want to implement a truth table, I would advise to use a ROM. So define a constant, whose content is (pre-)calculated by es function. Then use your input as ROM address and the selected output as result.
Here an example which uses integers as result
subtype t_uint3 : integer range 0 to 7;
type t_uint3_vector is array (natural range <>) of t_uint3;
constant B_TRUTH_TABLE : t_uint3_vector(7 downto 0) := (0, 1, 2, 3, 4, 5, 6, 7);
constant C_TRUTH_TABLE : t_uint3_vector(7 downto 0) := (7, 6, 5, 4, 3, 2, 1, 0);
B <= B_TRUTH_TABLE(to_integer(unsigned(A)));
C <= C_TRUTH_TABLE(to_integer(unsigned(A)));
This example has now disable functionality. To add this, use the ROM in combination with one of the statements above.
Precalculation with a function:
Replace the element list (0, 1, ..., 7) with a function like this:
function precalc_B_ROM return t_uint3_vector is
variable result : t_uint3_vector(7 downto 0);
begin
for i in result'range loop
result(i) := i;
end loop;
return result;
end function;
function precalc_C_ROM return t_uint3_vector is
variable result : t_uint3_vector(7 downto 0);
begin
for i in result'range loop
result(i) := result'high - i; -- reverse numbers
end loop;
return result;
end function;
constant B_TRUTH_TABLE : t_uint3_vector(7 downto 0) := precalc_B_ROM;
constant C_TRUTH_TABLE : t_uint3_vector(7 downto 0) := precalc_C_ROM;
Edit 1
A combinatorial process which calculates several results.
process(inA, inB, ...)
begin
-- default assignments
outX <= '0';
outY <= '0';
outZ <= '0';
case (inA & inB) is
when "00" =>
outY <= '1';
outZ <= '1';
when "01" =>
outX <= '1';
outY <= '1';
[...]
when others =>
outZ <= '1';
end case;
end process;
(Default assignments reduce lines of code in a when statement and in a clocked process hinder the synthesis to generate latches.)
So it's a question of coding if you return a record and split the result into sub-results or if you use a case with multiple assignments.
addendum
The presented ROM can also return a record. => 1) define a record of your result; 2) pack this record in a new array/vector type; 3) define a ROM of this new type; 4) access a ROMs entry by address -> the result is your requested record.