Optimización VHDL: registro de desplazamiento con salidas reconfigurables

0

Estoy buscando un consejo para optimizar el diseño de mi principiante. La lógica debe implementarse en un CPLD que sea capaz de:

  • reciba datos de 4 registros de desplazamiento de entrada / salida paralelos a través de 4 líneas de entrada serie (comparten el mismo reloj y líneas de control, no se encadenan para aumentar el rendimiento de datos)
  • recibir la configuración del puerto de salida desde un microcontrolador a través de una línea serie
  • aplique la configuración de salida y los puertos de salida de la unidad

La idea es construir un crosspoint switch personalizado, pero con una implementación diferente, ya que no "conecta" los puertos de entrada con los puertos de salida, sino que recibe 32 bits de datos del estado del puerto de entrada a través de 4 líneas serie y use una configuración de puerto de salida dinámica para controlar 32 puertos de salida. Debería haber una forma de enviar y "cargar" nuevas configuraciones de matriz de salida sobre la marcha.

Aquí está el código que escribí hasta ahora. Utiliza más de 1000 elementos lógicos, lo cual es demasiado para CPLD de nivel de entrada. Así que creo que soy yo quien creó un buen ejemplo de código VHDL incorrecto. De todos modos, aquí está.

Alguna información sobre las señales: si CE baja, los datos en serie están listos para leer. Cuando la CE es alta, el muestreo se lleva a cabo en los chips PISO, por lo que todos los datos deben recibirse.

CLK_LOAD es un reloj provisto por un microcontrolador para cargar la configuración de la matriz. La carga es alta durante la carga de la nueva configuración. CNFG es un solo impulso utilizado para "aplicar" la configuración cargada a la configuración en ejecución. RST se restablece y CBITS es el pin de configuración en serie. Mi idea fue enviar enteros de 32 x 5 bits, lo que dio como resultado un registro de 160 bits.

De hecho, la carga dinámica y la aplicación de la parte son las más difíciles para mí.

Cualquier pensamiento, sugerencia y consejo es bienvenido!

Gracias

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity top_entity is
port (clk:          in  STD_LOGIC; --clock line IN
        ce:         in      STD_LOGIC; -- clock enable signal
        sdi0:       in  STD_LOGIC; --serial line inputs 0-7
        sdi1:       in  STD_LOGIC; --serial line inputs 8-15
        sdi2:       in  STD_LOGIC; --serial line inputs 16-23
        sdi3:       in  STD_LOGIC; --serial line inputs 24-31
        port_out:   out STD_LOGIC_VECTOR(31 downto 0); --output pins

        clk_load:   in      STD_LOGIC; -- clock used for reading cbits
        load:           in      STD_LOGIC; -- high during config loading (active high)
        cnfg:           in      STD_LOGIC; -- single pulse applies loaded conf (active high)
        rst:            in      STD_LOGIC; -- resets configuration (all outputs to input 0) (active high)
        cbits:      in      STD_LOGIC  -- serial data_in for loading configuration bits
        );

end top_entity;

Architecture top_arch of top_entity is
signal port_reg:        STD_LOGIC_VECTOR(31 downto 0) :=  (others =>'0');   --signal for concatenated input port state  
signal conf_reg:        STD_LOGIC_VECTOR(159 downto 0) :=  (others =>'0'); --running configuration register (32 x 5 bits)
signal load_reg:        STD_LOGIC_VECTOR(159 downto 0) :=  (others =>'0'); --loaded configuration register (32 x 5 bits)

signal temp_a:          STD_LOGIC_VECTOR(7 downto 0) :=  (others =>'0');
signal temp_b:          STD_LOGIC_VECTOR(7 downto 0) :=  (others =>'0');
signal temp_c:          STD_LOGIC_VECTOR(7 downto 0) :=  (others =>'0');
signal temp_d:          STD_LOGIC_VECTOR(7 downto 0) :=  (others =>'0');

--32 element integer array to store 
type int_array is array(0 to 31) of integer;
signal channel_ints: int_array :=  (others => 0);

begin

    process (ce)        
        begin
        if (rising_edge(ce)) then --CE high, all bits received
                port_reg <= temp_a & temp_b & temp_c & temp_d; 

                --set output ports according to output matrix index
                for i in 0 to 31 loop
                    port_out(i) <= port_reg(channel_ints(i));
                end loop;

        end if;
    end process;


    process (clk) --receive serial input from 4 lines with shared clock
        begin

            if (rising_edge(clk)) then
                if (ce = '0') then
                    temp_a(7 downto 1) <= temp_a(6 downto 0);
                    temp_a(0) <= sdi0;
                    temp_b(7 downto 1) <= temp_b(6 downto 0);
                    temp_b(0) <= sdi1;
                    temp_c(7 downto 1) <= temp_c(6 downto 0);
                    temp_c(0) <= sdi2;
                    temp_d(7 downto 1) <= temp_d(6 downto 0);
                    temp_d(0) <= sdi3;
                else
                    temp_a <= (others =>'0');
                    temp_b <= (others =>'0');
                    temp_c <= (others =>'0');
                    temp_d <= (others =>'0');
                end if;
            end if;
    end process;


    process (cnfg)
        begin
            if (rising_edge(cnfg)) then 
                --cnfg is a single pulse. copy the loaded config into running config.
                conf_reg <= load_reg;

                --read individual port configuration
                channel_ints(0) <= to_integer(signed(conf_reg(159 downto 155)));
                channel_ints(1) <= to_integer(signed(conf_reg(154 downto 150)));
                channel_ints(2) <= to_integer(signed(conf_reg(149 downto 145)));
                channel_ints(3) <= to_integer(signed(conf_reg(144 downto 140)));
                channel_ints(4) <= to_integer(signed(conf_reg(139 downto 135)));
                channel_ints(5) <= to_integer(signed(conf_reg(134 downto 130)));
                channel_ints(6) <= to_integer(signed(conf_reg(129 downto 125)));
                channel_ints(7) <= to_integer(signed(conf_reg(124 downto 120)));
                channel_ints(8) <= to_integer(signed(conf_reg(119 downto 115)));
                channel_ints(9) <= to_integer(signed(conf_reg(114 downto 110)));
                channel_ints(10) <= to_integer(signed(conf_reg(109 downto 105)));
                channel_ints(11) <= to_integer(signed(conf_reg(104 downto 100)));
                channel_ints(12) <= to_integer(signed(conf_reg(99 downto 95)));
                channel_ints(13) <= to_integer(signed(conf_reg(94 downto 90)));
                channel_ints(14) <= to_integer(signed(conf_reg(89 downto 85)));
                channel_ints(15) <= to_integer(signed(conf_reg(84 downto 80)));
                channel_ints(16) <= to_integer(signed(conf_reg(79 downto 75)));
                channel_ints(17) <= to_integer(signed(conf_reg(74 downto 70)));
                channel_ints(18) <= to_integer(signed(conf_reg(69 downto 65)));
                channel_ints(19) <= to_integer(signed(conf_reg(64 downto 60)));
                channel_ints(20) <= to_integer(signed(conf_reg(59 downto 55)));
                channel_ints(21) <= to_integer(signed(conf_reg(54 downto 50)));
                channel_ints(22) <= to_integer(signed(conf_reg(49 downto 45)));
                channel_ints(23) <= to_integer(signed(conf_reg(44 downto 40)));
                channel_ints(24) <= to_integer(signed(conf_reg(39 downto 35)));
                channel_ints(25) <= to_integer(signed(conf_reg(34 downto 30)));
                channel_ints(26) <= to_integer(signed(conf_reg(29 downto 25)));
                channel_ints(27) <= to_integer(signed(conf_reg(24 downto 20)));
                channel_ints(28) <= to_integer(signed(conf_reg(19 downto 15)));
                channel_ints(29) <= to_integer(signed(conf_reg(14 downto 10)));
                channel_ints(30) <= to_integer(signed(conf_reg(9 downto 5)));
                channel_ints(31) <= to_integer(signed(conf_reg(4 downto 0)));
            end if;
    end process;

    --read serial port configuration and load into load_reg
    process (clk_load, rst)
        begin
            if (rst = '1') then
                load_reg <= (others =>'0');
            elsif (rising_edge(clk_load)) then              
                if (load = '1') then
                    load_reg(159 downto 1) <= load_reg(158 downto 0);
                    load_reg(0) <= cbits;

                end if;
        end if;

    end process;

end top_arch;
    
pregunta Peterstevens

0 respuestas

Lea otras preguntas en las etiquetas