Este artículo analiza los casos de uso y los beneficios del árbitro con una implementación de un árbitro de prioridad simple en VHDL.

El arbitraje es una parte importante de cualquier sistema informático moderno. Desde el arbitraje de bus en protocolos de comunicación como yo.2C y CAN, para el arbitraje de memoria en sistemas multiprocesador, los árbitros se pueden encontrar en cualquier lugar donde se necesite compartir un recurso.

Los árbitros pueden ser síncronos (es decir, sincronizados) o asíncronos, y funcionan al ingresar solicitudes y otorgar acceso a los recursos en función de esas solicitudes.

En el mundo incrustado, los recursos son siempre limitados. El uso de un árbitro puede simplificar el control de recursos y agregar prioridad a los subsistemas de la competencia, al mismo tiempo que aumenta el rendimiento y la solidez del sistema.

Los basicos

¿Qué es un árbitro?

En su forma más básica, un árbitro es un dispositivo que toma como N las solicitudes de entrada, y genera una única concesión, en forma de un solo caliente. A one-hot es un grupo de bits de tamaño arbitrario que consta de todos los ceros excepto uno; es decir, un bit es lógico alto, o "caliente". De esta manera, el árbitro mira su conjunto de entradas y permite que un solo dispositivo acceda al recurso.

Ejemplo de un árbitro en acción

Digamos que tenemos tres dispositivos, cada uno con una señal de solicitud vinculada a un árbitro. "Dispositivo" aquí se usa como un término general para cualquier solicitante. El solicitante podría ser una cola FIFO (primero en entrar, primero en salir), una CPU, una máquina de estados, etc. Cuando el dispositivo necesita acceso a un recurso, simplemente establece su señal de solicitud alta. El árbitro comprueba sus entradas y concede acceso.

La figura 1 muestra un diagrama de bloques con una tabla de verdad debajo. En este ejemplo, la señal de concesión no se utiliza de ninguna manera específica. La forma en que la señal de concesión da acceso al recurso depende de la aplicación y la implementación.

Figura 1. Árbitro con señales de petición y concesión.

La Figura 1 muestra el caso cuando cada dispositivo hace una solicitud de forma independiente.

Pero ¿qué pasa cuando dos o más dispositivos hacen una solicitud simultáneamente? Para resolver este problema, podemos crear prioridad en nuestro árbitro.

Cómo construir prioridad en un árbitro

La Figura 2 muestra una tabla de verdad modificada que da prioridad según la solicitud. Dev3, con la solicitud R3, tiene prioridad sobre Dev2 (con R2) y Dev1 (con R1). Dev2, con la solicitud R2, tiene prioridad sobre Dev1 (con R1). Tenga en cuenta de nuevo que la salida de concesión es siempre de un solo calor. Esto es esencial para evitar que múltiples dispositivos obtengan acceso al mismo recurso al mismo tiempo.

Figura 2. Tabla de verdad del árbitro con prioridad de solicitud y señales de concesión.

Implementando Arbiters en Diseño

Ahora conocemos la idea básica detrás del árbitro y cuál es el comportamiento lógico. A partir de aquí, podemos comenzar a implementar nuestro diseño.

Hay diferentes formas de implementar la misma funcionalidad. Podría simplificar la tabla de verdad anterior utilizando un mapa de Karnaugh o comenzar su implementación en un lenguaje de descripción de hardware.

Personalmente, me gusta dibujar el diagrama lógico si no es demasiado complicado. La capacidad de visualizar las puertas lógicas junto con la tabla de verdad solo lo hace más fácil cuando llega el momento de construir.

Arbitro en Logisim

Logisim es un simulador lógico de código abierto para diseñadores digitales, aficionados y estudiantes. Es completamente gráfico y le permite al usuario construir y probar diseños simples utilizando todos los bloques lógicos cotidianos, incluyendo compuertas AND, multiplexores, sumadores, flip-flops, registros e incluso memoria de acceso aleatorio (RAM).

La Figura 3 y la Figura 4, a continuación, muestran un árbitro de prioridad de tres bits. Las etiquetas con las letras 'a' y 'b' se llaman túneles y significa que los puntos con la misma letra están conectados aunque no haya un cable físico entre ellos. Las rutas verdes brillantes representan señales lógicas altas o VERDADERAS.

Figura 3. Un árbitro de tres entradas simulado en Logisim

Para empezar, observe que la primera entrada de la compuerta AND superior (A1) se mantiene alta. Esta lógica alta obtiene ANDed en A2, con el complemento de la solicitud R3. La salida de A2 obtiene ANDed en A4, con el complemento de la solicitud R2. La salida de A4 determina si la solicitud R1 se concede.

De esta manera, puede ver que esta lógica inicial alta se ondula a través del árbitro. Si alguna solicitud es alta, su complemento pasa al árbitro, lo que garantiza que no se conceda ninguna solicitud por debajo de ella. Así es como creamos una prioridad de árbitro. La Figura 3 muestra que aunque el árbitro recibe dos solicitudes, R1 y R3, solo se emite una única concesión (G3).

La Figura 4 muestra una situación similar, excepto que ahora se solicita R1 y R2 compite por acceder a un recurso.

Figura 4

La solicitud R2 tiene una prioridad más alta que R1, por lo tanto, la señal de concesión que pasa a nivel alto es G2. Podemos ver que esta alta prioridad proviene del hecho de que la solicitud R2 se complementa en la puerta A4, evitando que la salida de A5 (es decir, la concesión de G1) se convierta en alta.

La simulación de pequeños diagramas lógicos, como los de arriba, es ideal para una rápida prueba de concepto. Cuando se necesita construir algo grande, se debe utilizar una herramienta más sofisticada.

Arbitro en VHDL

Para implementar nuestro árbitro en VHDL, usé Xilinx ISE. Otras herramientas como Quartus II o Active-HDL también funcionarán.

El Listado 1, a continuación, muestra una implementación de un árbitro de prioridad de tres entradas.

                    - Listado 1: Árbitro

biblioteca IEEE;
use IEEE.STD_LOGIC_1164.ALL;

árbitro de entidad es
Puerto(
R: en STD_LOGIC_VECTOR (3 abajo a 1);
G: out STD_LOGIC_VECTOR (3 abajo a 1));

árbitro final

La concesión de arquitectura del árbitro es
empezar

 sol 
                  

Listado 1. Árbitro implementado en VHDL

Observe el uso de std_logic_vector en el bloque de entidad para construir la solicitud y otorgar puertos.

El vector R representa las tres solicitudes de entrada y G se usa para las concesiones de salida. En lo que respecta a la arquitectura, solo estamos usando lógica combinacional, por lo que no ve ningún proceso.

La primera línea, una vez que comienza la arquitectura, establece G en '100' cuando R (3) es alto, ignorando el resto de las entradas. A continuación, si R (3) es bajo, verificamos R (2) y configuramos G igual a '010' si R (2) es alto. Note que todavía ignoramos R (1). Si tanto R (3) como R (2) son bajos, verificamos R (1). Si R (1) es alto, G obtiene '001'. Por último, usamos la instrucción else para asegurarnos de que G se establece en '000' si todas las entradas son bajas. Esta es una forma sencilla de implementar nuestro esquema de prioridad en VHDL.

Probando un árbitro VHDL en Testbench

Ahora para probar nuestro código. El Listado 2 muestra un banco de pruebas simple que podemos usar para instanciar y probar nuestro nuevo diseño.

                    - Listado 2: Arbiter TestBench

biblioteca ieee;
use ieee.std_logic_1164.all;
 
entidad arbitrerTest es
end arbitrerTest;
 
comportamiento de la arquitectura de la prueba de árbitro es
 
   - Declaración del componente para la unidad bajo prueba (UUT)
   árbitro componente
   Puerto(
         R: en std_logic_vector (3 abajo a 1);
         G: out std_logic_vector (3 abajo a 1)
        );
   componente final
    
   --Inputs
   señal r: std_logic_vector (3 abajo a 1): = (otros => '0');

   --Salidas
   señal g: std_logic_vector (3 abajo a 1);
 
empezar
 
   - Crear una instancia de la unidad bajo prueba (UUT)
   uut: mapa del puerto del árbitro (
          r => R,
          g => G
        );
 

   - Proceso de estímulo.
   stim_proc: proceso
   empezar

     r 
                  

Listado 2. Arbiter testbench implementado en VHDL

Si bien el diseño de testbench está fuera del alcance de este artículo, a continuación se ofrece una breve explicación.

Esencialmente, declaro el componente de árbitro junto con las señales de prueba, r y g. Luego, hago una instancia del componente de árbitro como mi unidad bajo prueba y mapeo las señales de prueba a sus puertos. Luego ejecuto las ocho combinaciones de entrada, esperando un nanosegundo entre cada una. He ordenado que coincidan con la tabla de verdad de la Figura 2. La última parte del banco de pruebas establece las entradas igual a '000' y luego espera para siempre. Si bien hay formas más elegantes de probar todas las combinaciones de entrada, esta parece ser la implementación más simple y directa.

Para ver cómo se comporta el árbitro dentro de este banco de pruebas, simulé el banco de pruebas en ISE y produje un diagrama de tiempo, que se muestra en la Figura 5.

Figura 5. Diagrama de tiempo del banco de pruebas del árbitro

La barra superior es nuestro vector de solicitud, mientras que la segunda barra es el vector de concesión.

Este vector de concesión se ha expandido para que podamos ver G3, G2 y G1. Observe que cuando la solicitud R3 (el bit más significativo del vector de solicitud) es alta, la concesión G3 también es alta, independientemente del estado de las otras entradas. Cuando la solicitud R2 es alta y R3 es baja, G2 es alta. G1 es alto solo cuando todas las solicitudes, excepto R1, son bajas. A través de este diagrama de tiempo, podemos ver que nuestro árbitro se está comportando como se espera.

El árbitro de prioridad simple es, como su nombre lo indica, simple. Hay formas mejores y más eficientes de implementar un árbitro. Un problema con el árbitro de prioridad es que las solicitudes de baja prioridad nunca se pueden conceder. Una forma de resolverlo es con un árbitro de round-robin, que le da a cada solicitante acceso al recurso por un corto tiempo. Se puede combinar un árbitro de round-robin y de prioridad para obtener lo mejor de ambas implementaciones. Estos diseños pueden ser explorados en un artículo futuro.

Conclusión

Este artículo introdujo al árbitro, con una implementación de un árbitro de prioridad simple en VHDL. El árbitro es un mediador entre diferentes componentes del sistema y recursos del sistema. Estos podrían ser dos núcleos de CPU que necesitan acceder a la memoria compartida o dos microcontroladores que intentan tomar el control de un bus de comunicación. Cualquiera que sea la aplicación, el árbitro es una solución de bajo costo y relativamente simple para un problema a menudo complejo.

LEAVE A REPLY

Please enter your comment!
Please enter your name here