VHDL: registro multifunción con carga, reseteo, desplazamiento y rotación

VHDL registro multifunción con carga desplazamiento y rotación
VHDL registro multifunción con carga desplazamiento y rotación.

Otro code-kata a traer vengo de nuevo continuando con el post anterior sobre registros. Los registros se usan para varias tareas como almacenamiento de valores, direccionar a la memoria, el contador de programa, códigos de operación, lo que haga falta.. así que añadiendo funcionalidades al registro simple del post anterior, llegamos al registro multifunción.

Es decir, los registros multifunción son como los simples, pero añaden más señales de entrada, para hacer operaciones simples con el dato que les llega, valga la redundancia. Por ejemplo las señales y operaciones pueden ser:

  • Precarga o carga en paralelo.
  • Desplazamiento a la izquierda o derecha con bit extra de desplazamiento.
  • Rotación a la izquierda o derecha.

Sin demasiadas explicaciones, la carga en paralelo activa en la salida la entrada sólo si la señal de carga está activada. El reset pone a ceros la salida. Un desplazamiento convierte por ejemplo una entrada de la forma “00001111” con entrada a 0 en “00011110”. Y en la rotación no tenemos entrada extra, si no que por ejemplo, una rotación a la derecha de “00001111” quedaría en “10000111”.

Al grano, el código del registro multifunción

library IEEE;
use IEEE.std_logic_1164.all;

entity eightBitsRegister is
    port (
        valueOut : out std_logic_vector (7 downto 0);
        valueIn : in std_logic_vector (7 downto 0);
        reset, clock, load : in std_logic;
        shiftLeft, shiftLeftValueIn, shiftRight, shiftRightValueIn : in std_logic;
        rotateLeft, rotateRight : in std_logic
    );
end entity;

architecture arch_eightBitsRegister of eightBitsRegister is

    signal auxValueOut : std_logic_vector (7 downto 0);

begin

    valueOut <= auxValueOut;

    identifier : process (clock)
    begin
        if rising_edge(clock) then
            if reset = '1' then
                auxValueOut <= "00000000";
            elsif load = '1' then
                auxValueOut <= valueIn;
            elsif shiftLeft = '1' then
                auxValueOut(0) <= shiftLeftValueIn;
                for i in 1 to 7 loop
                    auxValueOut(i) <= valueIn(i-1);
                end loop;
            elsif shiftRight = '1' then
                for i in 0 to 6 loop
                    auxValueOut(i) <= valueIn(i+1);
                end loop;
                auxValueOut(7) <= shiftRightValueIn;
            elsif rotateLeft = '1' then
                auxValueOut(0) <= valueIn(7);
                for i in 1 to 7 loop
                    auxValueOut(i) <= valueIn(i-1);
                end loop;
            elsif rotateRight = '1' then
                for i in 0 to 6 loop
                    auxValueOut(i) <= valueIn(i+1);
                end loop;
                auxValueOut(7) <= valueIn(0);
            end if;
        end if;
    end process;

end architecture;

El banco de pruebas

library IEEE;
use IEEE.std_logic_1164.all;

entity eightBitsRegister_tb is
end entity;

architecture arch_eightBitsRegister_tb of eightBitsRegister_tb is

    component eightBitsRegister is
        port (
            valueOut : out std_logic_vector (7 downto 0);
            valueIn : in std_logic_vector (7 downto 0);
            reset, clock, load : in std_logic;
            shiftLeft, shiftLeftValueIn, shiftRight, shiftRightValueIn : in std_logic;
            rotateLeft, rotateRight : in std_logic
        );
    end component;

    signal testReset, testClock : std_logic := '0';
    signal testValueOut, testValueIn : std_logic_vector (7 downto 0);
    signal tics : integer := 0;
    signal testLoad, testShiftLeft, testShiftLeftValueIn, testShiftRight, testShiftRightValueIn, testRotateLeft, testRotateRight : std_logic;

begin

    testing_unit: eightBitsRegister port map (
        valueOut => testValueOut,
        valueIn => testValueIn,
        reset => testReset,
        clock => testClock,
        load => testLoad,
        shiftLeft => testShiftLeft,
        shiftLeftValueIn => testShiftLeftValueIn,
        shiftRight => testShiftRight,
        shiftRightValueIn => testShiftRightValueIn,
        rotateLeft => testRotateLeft,
        rotateRight => testRotateRight
    );

    generate_100Mhzs_clock : process
    begin

        report "Tic tac..";
        testClock <= not testClock;
        wait for 5 ns; -- Tiempo de espera en un flanco de reloj.

        if testClock = '1' then tics <= tics + 1; end if;
        if tics >= 25 then wait; end if;

    end process;

    generate_signals : process
    begin

        wait for 5 ns;
        testReset <= '1'; wait for 10 ns;
        testReset <= '0'; wait for 10 ns;
        testLoad <= '1'; wait for 10 ns;

        testValueIn <= "00001101"; wait for 10 ns;
        testValueIn <= "00001110"; wait for 10 ns;
        testValueIn <= "00001111"; wait for 10 ns;

        testLoad <= '0'; wait for 10 ns;

        testReset <= '1'; wait for 10 ns;
        testReset <= '0'; wait for 10 ns;

        testShiftLeftValueIn <= '1'; wait for 10 ns;
        testShiftLeft <= '1'; wait for 10 ns;
        testShiftLeftValueIn <= '0'; testShiftLeft <= '0'; wait for 10 ns;

        testShiftRightValueIn <= '1'; wait for 10 ns;
        testShiftRight <= '1'; wait for 10 ns;
        testShiftRightValueIn <= '0'; testShiftRight <= '0'; wait for 10 ns;

        testRotateLeft <= '1'; wait for 10 ns;
        testRotateLeft <= '0'; wait for 10 ns;
        testRotateRight <= '1'; wait for 10 ns;
        testRotateRight <= '0'; wait for 10 ns;

        wait;

    end process;

end architecture;

Si todo va bien, en la simulación se tiene que ver algo como lo de la imagen del principio.

Compartir..

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *