VHDL ¿cómo simplificar una declaración de caso redundante?

3

Estoy usando declaraciones de casos para verificar los bits de una palabra. ¿Hay alguna forma de escribir esto de forma más compacta, ya que usa mucho espacio (tengo otras señales en las que también quiero hacer esto)?

...
case a(1 downto 0) is
        when "00" =>
            r(3 downto 0) <= "0000";
        when "01" =>
            r(3 downto 0) <= "0001";
        when "10" =>
            r(3 downto 0) <= "1100";
        when "11" =>
            r(3 downto 0) <= "1101";
        when others =>
            null;
    case a(3 downto 2) is
        when "00" =>
            r(7 downto 4) <= "0000";
        when "01" =>
            r(7 downto 4) <= "0001";
        when "10" =>
            r(7 downto 4) <= "1100";
        when "11" =>
            r(7 downto 4) <= "1101";
        when others =>
            null;
    case a(5 downto 4) is
        when "00" =>
            r(11 downto 8) <= "0000";
        when "01" =>
            r(11 downto 8) <= "0001";
        when "10" =>
            r(11 downto 8) <= "1100";
        when "11" =>
            r(11 downto 8) <= "1101";
        when others =>
            null;
    case a(7 downto 6) is
        when "00" =>
            r(15 downto 12) <= "0000";
        when "01" =>
            r(15 downto 12) <= "0001";
        when "10" =>
            r(15 downto 12) <= "1100";
        when "11" =>
            r(15 downto 12) <= "1101";
        when others =>
            null;
        ...
    
pregunta gilianzz

2 respuestas

12

Básicamente, estás codificando una gran cantidad de multiplexores de 4 entradas, por lo que puedes escribir una función o crear un submódulo que creas para cada uno.

function map4 (sel: in std_logic_vector (1 downto 0);
               constant v0, v1, v2, v3 : in std_logic_vector (3 downto 0))
return std_logic_vector is
begin
  case sel is
  when "00" => return v0;
  when "01" => return v1;
  when "10" => return v2;
  when "11" => return v3;
  when others => return "XXXX";
  end case;
end map4;

...

r( 3 downto 0) <= map4 (a(1 downto 0), "0000", "0001", "1100", "1101");
r( 7 downto 4) <= map4 (a(3 downto 2), "0000", "0001", "1100", "1101");
r(11 downto 8) <= map4 (a(5 downto 4), "0000", "0001", "1100", "1101");

Si los valores del mapa son todos iguales, entonces no necesita pasarlos como parámetros.

Por supuesto, con la asignación específica que da como ejemplo, la lógica es trivial: el bit 0 de la salida es simplemente el bit 0 de la entrada, el bit 1 siempre es 0, y los bits 2 y 3 de la salida son bit 1 de la entrada.

    
respondido por el Dave Tweed
7

Puedes hacer bucles:

   FOR i IN 0 TO 3 LOOP
     CASE a(i*2+1 DOWNTO i*2) IS
       when "00" =>
         r(i*4+3 downto i*4) <= "0000";
       when "01" =>
         r(i*4+3 downto i*4) <= "0001";
       when "10" =>
         r(i*4+3 downto i*4) <= "1100";
       when "11" =>
         r(i*4+3 downto i*4) <= "1101";
       when others =>
         r(i*4+3 downto i*4) <= "XXXX";
       END CASE;
     END LOOP;

(Los bucles suelen ser sintetizables, especialmente cuando el número de iteraciones es fijo)

Si no necesita la cláusula "otros":

   FOR i IN 0 TO 3 LOOP
     CASE a(i*2+1 DOWNTO i*2) IS
       when "00" =>
         r(i*4+3 downto i*4) <= "0000";
       when "01" =>
         r(i*4+3 downto i*4) <= "0001";
       when "10" =>
         r(i*4+3 downto i*4) <= "1100";
       when others =>
         r(i*4+3 downto i*4) <= "1101";
       END CASE;
     END LOOP;

(Si no te importa el comportamiento cuando las entradas están en el estado 'X', 'Z', 'U' ...)

También puede crear una variable temporal para que el código sea aún más corto y fácil de leer:

  VARIABLE t : unsigned(3 DOWNTO 0);
  ...
  FOR i IN 0 TO 3 LOOP
    CASE a(i*2+1 DOWNTO i*2) IS
      when "00"   => t := "0000";
      when "01"   => t := "0001";
      when "10"   => t := "1100";
      when others => t := "1101";
    END CASE;
    r(i*4+3 downto i*4) <= t;
  END LOOP;

Puedes escribir directamente ecuaciones booleanas, aquí es bastante simple:

  FOR i IN 0 TO 3 LOOP
    r(i*4+3 downto i*4) <= a(i*2+1) & a(i*2+1) & '0' & a(i*2);
  END LOOP;
    
respondido por el TEMLIB

Lea otras preguntas en las etiquetas