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;