Implementación de BZFAD usando VHDL

Soy novato en la codificación vhdl. Estoy implementando BZFAD , que es un multiplicador de baja potencia.

En el diagrama de bloques, como se muestra a continuación, tengo un bloque de transistores (M1) cuya entrada se controla desde el contador de anillo. Estoy confundido en cuanto a cómo se pueden implementar estos transistores usando VHDL.ingrese la descripción de la imagen aquí

Estoy usando la herramienta Xlinx ISE para implementar lo mismo.

¿Cuál es tu pregunta específica?
No sé mucho sobre VHDL o Xilinx, pero dudo que puedas acceder a los transistores directamente en Xilinx. Acabo de echar un vistazo al papel, y creo que su mejor opción puede ser implementar la lógica del multiplexor directamente usando una declaración if o una declaración case. Su resultado no estará tan optimizado como el de ellos, pero será más sólidamente implementable que lo que tienen. Creo que ese tipo de multiplexor tendría problemas de temporización relacionados con la fuerza de la unidad si se hiciera incorrectamente y necesitaría un dimensionamiento cuidadoso de todas las puertas para que funcione a velocidad incluso en un flujo ASIC.
Más específicamente diciendo cómo implementar el bloque M1 como se muestra en el esquema.
¿Qué sucede si coloca los FET fuera del FPGA?
Creo que es poco probable que su multiplicador de "baja potencia" sea tan bajo como los duros en los bloques DSP48 ... ¡pero los datos que dicen lo contrario serían muy interesantes!

Respuestas (1)

M1 es un multiplexor k-1 ancho a 1 con habilitaciones individuales impulsadas desde el contador de anillo. Donde la señal READY fuerza la salida a '0'. M2 es un selector 1:k-1 con habilitaciones individuales expulsadas del contador de anillo. El contador de anillos tiene k etapas. MUX1 es un multiplexor 2:1 de ancho k+1 con una única entrada de selección.

Modelo M1, M2 y MUX1 desde el punto de vista del comportamiento, no tiene acceso a los transistores en el entorno de software integrado de la tecnología de síntesis de Xilinx. En el mejor de los casos, puede emularlo en un FPGA.

M1_out <= reduce_or (B(32 downto 1) and Ring_Counter(31 downto 0)) 
              when Ready = '0' else 
          '0' when Ready = '1';`

Listo es Ring_Counter(31).

Donde en una implementación de nivel de transistor, la reducción O es en realidad un cable O. Dependiendo de los paquetes y la versión de VHDL, es posible que ya tenga una reducción O disponible como una función o un operador.

Lo especial de la arquitectura es la capacidad de usar pestillos para P en lugar de un registro de desplazamiento a la derecha de cambio de carga paralelo y ahorrar energía al reducir la cantidad de redes que cambian con el reloj.

Podría escribir modelos de comportamiento de transistores, pero no lo acercará más a los transistores reales.

Apéndice

"¿Podemos escribir un modelo estructural en lugar del modelo de comportamiento..."

Estructural en este caso es el nivel del transistor. No podemos modelar transistores con precisión sin simulación analógica, VHDL no sabe nada sobre transistores. Podemos hacer un modelo lógico digital estructural.

Se utilizan dos tipos de transistores, ambos mostrados incidentalmente en MUX1, que es un multiplexor 2: 1 de ancho k + 1:

MUX1 dos tipos de transistores

Llame a la conexión superior al transistor source, la conexión inferior drainy la conexión de burbuja o sin burbuja del medio (derecha) gate.

La siguiente no es la única forma de modelar transistores aquí. Modelar transistores es algo que es mejor dejar para el dominio analógico.

Modelamos los dos transistores de manera diferente según la burbuja:

library ieee;
use ieee.std_logic_1164.all;

entity trans is
    port (
        source:     in  std_logic;
        gate:       in  std_logic;
        drain:      out std_logic
    );
end entity;

architecture func of trans is

begin
    drain <= source  when gate = '1' else
             'Z'     when gate = '0' else
             'X';
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity trans_bubble is
    port (
        source:     in  std_logic;
        gate:       in  std_logic;
        drain:      out std_logic
    );
end entity;

architecture func of trans_bubble is

begin
    drain <= source  when gate = '0' else
             'Z'     when gate = '1' else
             'X';
end architecture;

Sin simulación analógica, lo único diferente que podríamos hacer sería modelar la fuente y el drenaje como modo inouty resolver ambas salidas. Parece mucho trabajo para algo que no puede ser realmente preciso de todos modos.

Un modelo MUX1 simple que usa transistores:

library ieee;
use ieee.std_logic_1164.all;

entity MUX1 is
    generic (
        k: natural :=32  -- k width
    );
    port (
        a:      in  std_logic_vector (k downto 0);  -- width is k+1
        b:      in  std_logic_vector (k downto 0);
        sel:    in  std_logic;
        outp:   out std_logic_vector (k downto 0)
    );
end entity;

architecture func of MUX1 is
    signal wire_ab:     std_logic_vector (k downto 0);
begin
MUX_1:
    for i in outp'range generate
    MUX1A:
        entity work.trans_bubble 
            port map (source => a(i), gate => sel, drain => wire_ab(i));
    MUX1B:
        entity work.trans 
            port map (source => b(i), gate => sel, drain => wire_ab(i));
    end generate;
WIRED_OR:
    outp <= wire_ab;

arquitectura final;

Las declaraciones de generación producen una matriz de 32 transistores con burbujas para el lado a del multiplexor y 32 transistores sin burbujas para el lado b. Las salidas de los transistores o cables OR juntan el valor de salida contando con la resolución std_logic. Un transistor está encendido o apagado. En estos modelos, la entrada de la fuente se expulsa al drenaje cuando la compuerta se habilita; de lo contrario, la salida es 'Z' (alta impedancia).

Escribiendo un banco de pruebas simple para MUX1:

library ieee;
use ieee.std_logic_1164.all;

entity mux1_tb is
    generic 
        ( k:  natural := 32 );
end entity;

architecture foo of mux1_tb is

    signal a:       std_logic_vector(k downto 0) := ('0' & X"FEEDFACE");
    signal b:       std_logic_vector(k downto 0) := ('1' & X"DEADBEEF");
    signal outp:    std_logic_vector(k downto 0);
    signal sel:     std_logic;
begin
DUT:
    entity work.mux1
        generic map (
            k => k
        )
        port map (
            a => a,
            b => b,
            sel => sel,
            outp => outp
        );

STIMULUS:
    process 
    begin
        wait for 10 ns;
        sel <= '0';
        wait for 10 ns;
        sel <= '1';
        wait for 10 ns;
        wait;
    end process;
end architecture;

Nos da:

Banco de pruebas MUX1

Lo que muestra que MUX1 funciona. Además, si echara un vistazo a la jerarquía, encontraría 32 pares de transistores (MUX_1[0-32]/MUX1A y MUX_1[0-32]/MUX1B o alguna variación, donde MUX1As son trans_bubble y MUX1Bs son trans).

M1 y M2 requieren acceso individual a las entradas de la puerta y tienen un riel común para la fuente (M2) o el drenaje (M1), consulte la Figura 2 del documento. Tenga en cuenta que en ninguna parte del multiplexor MUX1, selector M1 o decodificador M2 hay más de un transistor habilitado a la vez.

Debido a que el Ring Counter también proporciona una señal READY, también impulsa la salida del selector M1 a '0'través del transistor debajo del drenaje común. En lugar de usar funciones de resolución, simplemente puede invertir las conexiones para que el drenaje del transistor único esté en la parte superior del símbolo esquemático. Podemos hacer esto porque todas las habilitaciones de transistores son mutuamente excluyentes. La intención es tener siempre algo conduciendo una red. Esto evita el bloqueo y otros fenómenos desagradables en implementaciones reales. El suelo puede ser reemplazado por un '0'.

¿Podemos escribir un modelo estructural en lugar del modelo de comportamiento como lo escribió usted?