--! @file sm.vhd
|
--! @file sm.vhd
|
--! @brief Maquina de Estados. Controla la operación interna y genera los mecanismos de sincronización con el exterior (interrupciones).
|
--! @brief Maquina de Estados. Controla la operación interna y genera los mecanismos de sincronización con el exterior (interrupciones).
|
--! @author Julián Andrés Guarín Reyes
|
--! @author Julián Andrés Guarín Reyes
|
--------------------------------------------------------------
|
--------------------------------------------------------------
|
-- RAYTRAC
|
-- RAYTRAC
|
-- Author Julian Andres Guarin
|
-- Author Julian Andres Guarin
|
-- sm.vhd
|
-- sm.vhd
|
-- This file is part of raytrac.
|
-- This file is part of raytrac.
|
--
|
--
|
-- raytrac is free software: you can redistribute it and/or modify
|
-- raytrac is free software: you can redistribute it and/or modify
|
-- it under the terms of the GNU General Public License as published by
|
-- it under the terms of the GNU General Public License as published by
|
-- the Free Software Foundation, either version 3 of the License, or
|
-- the Free Software Foundation, either version 3 of the License, or
|
-- (at your option) any later version.
|
-- (at your option) any later version.
|
--
|
--
|
-- raytrac is distributed in the hope that it will be useful,
|
-- raytrac is distributed in the hope that it will be useful,
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
-- GNU General Public License for more details.
|
-- GNU General Public License for more details.
|
--
|
--
|
-- You should have received a copy of the GNU General Public License
|
-- You should have received a copy of the GNU General Public License
|
-- along with raytrac. If not, see <http://www.gnu.org/licenses/>.
|
-- along with raytrac. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_unsigned.all;
|
|
|
use work.arithpack.all;
|
use work.arithpack.all;
|
|
|
entity sm is
|
entity sm is
|
port (
|
port (
|
|
|
--! Señales normales de secuencia.
|
--! Señales normales de secuencia.
|
clk,rst: in std_logic;
|
clk,rst: in std_logic;
|
--! Vector con las instrucción codficada
|
--! Vector con las instrucción codficada
|
instrQq:in std_logic_vector(floatwidth-1 downto 0);
|
instrQq:in std_logic_vector(floatwidth-1 downto 0);
|
--! Señal de cola vacia.
|
--! Señal de cola vacia.
|
instrQ_empty:in std_logic;
|
instrQ_empty:in std_logic;
|
|
|
|
|
adda,addb:out std_logic_vector (widthadmemblock-1 downto 0);
|
adda,addb:out std_logic_vector (widthadmemblock-1 downto 0);
|
sync_chain_0,instrRdAckd:out std_logic;
|
sync_chain_0,instrRdAckd:out std_logic;
|
|
|
|
|
full_r: in std_logic; --! Indica que la cola de resultados no puede aceptar mas de 32 elementos.
|
full_r: in std_logic; --! Indica que la cola de resultados no puede aceptar mas de 32 elementos.
|
|
|
|
|
--! End Of Instruction Event
|
--! End Of Instruction Event
|
eoi : out std_logic;
|
eoi : out std_logic;
|
|
|
--! State Exposed for testbench purposes.
|
--! State Exposed for testbench purposes.
|
state : out macState;
|
state : out macState;
|
|
|
--! DataPath Control uca code.
|
--! DataPath Control uca code.
|
dpc_uca : out std_logic_vector (2 downto 0)
|
dpc_uca : out std_logic_vector (2 downto 0)
|
|
|
|
|
);
|
);
|
end entity;
|
end entity;
|
|
|
architecture sm_arch of sm is
|
architecture sm_arch of sm is
|
|
|
|
|
--! LOAD_INSTRUCTION: Estado en el que se espera que en la cola de instrucciones haya una instrucción para ejecutar.
|
--! LOAD_INSTRUCTION: Estado en el que se espera que en la cola de instrucciones haya una instrucción para ejecutar.
|
--! EXECUTE_INSTRUCTION: Estado en el que se ejecuta la instrucción de la cola de instrucciones.
|
--! EXECUTE_INSTRUCTION: Estado en el que se ejecuta la instrucción de la cola de instrucciones.
|
--! FLUSH_ARITH_PIPELINE: Estado en el que se espera un número específico de ciclos de reloj, para que se desocupe el pipeline aritmético.
|
--! FLUSH_ARITH_PIPELINE: Estado en el que se espera un número específico de ciclos de reloj, para que se desocupe el pipeline aritmético.
|
|
|
|
--!TBXSTART:STATE
|
signal s_state : macState;
|
signal s_state : macState;
|
|
--!TBXEND
|
|
|
|
|
|
--!TBXSTART:INS_BLKS
|
signal s_instr_uca: std_logic_vector(2 downto 0);
|
|
signal s_dpc_uca: std_logic_vector(2 downto 0);
|
signal s_dpc_uca: std_logic_vector(2 downto 0);
|
|
signal s_instr_uca : std_logic_vector(2 downto 0);
|
signal s_block_start_a: std_logic_vector(4 downto 0);
|
signal s_block_start_a: std_logic_vector(4 downto 0);
|
signal s_block_start_b: std_logic_vector(4 downto 0);
|
signal s_block_start_b : std_logic_vector(4 downto 0);
|
signal s_block_end_a: std_logic_vector(4 downto 0);
|
signal s_block_end_a : std_logic_vector(4 downto 0);
|
signal s_block_end_b: std_logic_vector(4 downto 0);
|
signal s_block_end_b : std_logic_vector(4 downto 0);
|
signal s_combinatory: std_logic;
|
signal s_combinatory : std_logic;
|
signal s_delay_field: std_logic_vector(7 downto 0);
|
signal s_delay_field: std_logic_vector(7 downto 0);
|
|
--!TBXEND
|
|
|
|
--!TBXEND:CNT_SIGNLS
|
signal s_set_b: std_logic; --! Señal para colocar un valor arbitrario en el contador B.
|
signal s_set_b: std_logic; --! Señal para colocar un valor arbitrario en el contador B.
|
signal s_set_a: std_logic;
|
signal s_set_a: std_logic;
|
signal s_set_dly: std_logic;
|
signal s_set_dly: std_logic;
|
signal s_go_b: std_logic; --! Salida para controlar la pausa(0) o marcha(1) del contador de direcciones del operando B/D.
|
signal s_go_b: std_logic; --! Salida para controlar la pausa(0) o marcha(1) del contador de direcciones del operando B/D.
|
signal s_go_a: std_logic; --! Salida para controlar la pausa(0) o marcha(1) del contador de direcciones del operando A/C.
|
signal s_go_a: std_logic; --! Salida para controlar la pausa(0) o marcha(1) del contador de direcciones del operando A/C.
|
signal s_go_delay: std_logic; --! Salida para controlar la pausa(0) o marcha(1) del contador de delay, para el flush del pipeline aritmético.
|
signal s_go_delay: std_logic; --! Salida para controlar la pausa(0) o marcha(1) del contador de delay, para el flush del pipeline aritmético.
|
signal s_zeroFlag_delay:std_logic; --! Bandera de cero del contador delay.
|
signal s_zeroFlag_delay:std_logic; --! Bandera de cero del contador delay.
|
signal s_eq_b,s_eq_a: std_logic; --! Indica cuando se está leyendo el último bloque de memoria con operandos de entrada de a y de b respectivamente.
|
signal s_eq_b,s_eq_a: std_logic; --! Indica cuando se está leyendo el último bloque de memoria con operandos de entrada de a y de b respectivamente.
|
signal s_eb_b,s_eb_a: std_logic; --! Indica que se está leyendo en memoria el último operando del bloque actual, b o a, respectivamente.
|
signal s_eb_b,s_eb_a: std_logic; --! Indica que se está leyendo en memoria el último operando del bloque actual, b o a, respectivamente.
|
|
--!TBXEND
|
begin
|
begin
|
|
|
state <= s_state;
|
state <= s_state;
|
|
|
--! Código UCA, pero en la etapa DPC: La diferencia es que UCA en la etapa DPC, decodifica el datapath dentro del pipeline aritmético.
|
--! Código UCA, pero en la etapa DPC: La diferencia es que UCA en la etapa DPC, decodifica el datapath dentro del pipeline aritmético.
|
dpc_uca <= s_dpc_uca;
|
dpc_uca <= s_dpc_uca;
|
|
|
|
|
--! Bloques asignados en la instrucci´øn
|
--! Bloques asignados en la instrucción
|
s_block_start_a <= instrQq(floatwidth-4 downto floatwidth-8);
|
s_block_start_a <= instrQq(floatwidth-4 downto floatwidth-8);
|
s_block_end_a <= instrQq(floatwidth-9 downto floatwidth-13);
|
s_block_end_a <= instrQq(floatwidth-9 downto floatwidth-13);
|
|
|
s_block_start_b <= instrQq(floatwidth-14 downto floatwidth-18);
|
s_block_start_b <= instrQq(floatwidth-14 downto floatwidth-18);
|
s_block_end_b <= instrQq(floatwidth-19 downto floatwidth-23);
|
s_block_end_b <= instrQq(floatwidth-19 downto floatwidth-23);
|
|
|
--! Campo que define si la instrucción es combinatoria
|
--! Campo que define si la instrucción es combinatoria
|
s_combinatory <= instrQq(floatwidth-24);
|
s_combinatory <= instrQq(floatwidth-24);
|
|
|
--! Campo que define cuantos clocks debe esperar el sistema, despues de que se ejecuta una instrucción, para que el pipeline aritmético quede vacio.
|
--! Campo que define cuantos clocks debe esperar el sistema, despues de que se ejecuta una instrucción, para que el pipeline aritmético quede vacio.
|
s_delay_field <= instrQq(floatwidth-25 downto floatwidth-32);
|
s_delay_field <= instrQq(floatwidth-25 downto floatwidth-32);
|
|
|
--! UCA code, código con la instrucción a ejecutar.
|
--! UCA code, código con la instrucción a ejecutar.
|
s_instr_uca <= instrQq(31 downto 29);
|
s_instr_uca <= instrQq(31 downto 29);
|
|
|
--! Address Counters
|
--! Address Counters
|
--!TBXINSTANCESTART
|
--!TBXINSTANCESTART
|
counterA:customCounter
|
counterA:customCounter
|
generic map (
|
generic map (
|
EOBFLAG => "YES",
|
EOBFLAG => "YES",
|
ZEROFLAG => "NO",
|
ZEROFLAG => "NO",
|
BACKWARDS => "NO",
|
BACKWARDS => "NO",
|
EQUALFLAG => "YES",
|
EQUALFLAG => "YES",
|
subwidth => 4,
|
subwidth => 4,
|
width => 9
|
width => 9
|
)
|
)
|
port map (
|
port map (
|
clk => clk,
|
clk => clk,
|
rst => rst,
|
rst => rst,
|
go => s_go_a,
|
go => s_go_a,
|
set => s_set_a,
|
set => s_set_a,
|
setValue => s_block_start_a,
|
setValue => s_block_start_a,
|
cmpBlockValue => s_block_end_a,
|
cmpBlockValue => s_block_end_a,
|
zero_flag => open,
|
zero_flag => open,
|
eob_flag => s_eb_a,
|
eob_flag => s_eb_a,
|
eq_flag => s_eq_a,
|
eq_flag => s_eq_a,
|
count => adda
|
count => adda
|
);
|
);
|
--!TBXINSTANCEEND
|
--!TBXINSTANCEEND
|
--!TBXINSTANCESTART
|
--!TBXINSTANCESTART
|
counterB:customCounter
|
counterB:customCounter
|
generic map (
|
generic map (
|
EOBFLAG => "YES",
|
EOBFLAG => "YES",
|
ZEROFLAG => "NO",
|
ZEROFLAG => "NO",
|
BACKWARDS => "NO",
|
BACKWARDS => "NO",
|
EQUALFLAG => "YES",
|
EQUALFLAG => "YES",
|
subwidth => 4,
|
subwidth => 4,
|
width => 9
|
width => 9
|
)
|
)
|
port map (
|
port map (
|
clk => clk,
|
clk => clk,
|
rst => rst,
|
rst => rst,
|
go => s_go_b,
|
go => s_go_b,
|
set => s_set_b,
|
set => s_set_b,
|
setValue => s_block_start_b,
|
setValue => s_block_start_b,
|
cmpBlockValue => s_block_end_b,
|
cmpBlockValue => s_block_end_b,
|
zero_flag => open,
|
zero_flag => open,
|
eob_flag => s_eb_b,
|
eob_flag => s_eb_b,
|
eq_flag => s_eq_b,
|
eq_flag => s_eq_b,
|
count => addb
|
count => addb
|
);
|
);
|
--!TBXINSTANCEEND
|
--!TBXINSTANCEEND
|
--!TBXINSTANCESTART
|
--!TBXINSTANCESTART
|
counterDly:customCounter
|
counterDly:customCounter
|
generic map(
|
generic map(
|
EOBFLAG => "NO",
|
EOBFLAG => "NO",
|
ZEROFLAG => "YES",
|
ZEROFLAG => "YES",
|
BACKWARDS => "YES",
|
BACKWARDS => "YES",
|
EQUALFLAG => "NO",
|
EQUALFLAG => "NO",
|
width => 5,
|
width => 5,
|
subwidth => 0
|
subwidth => 0
|
|
|
)
|
)
|
port map (
|
port map (
|
clk => clk,
|
clk => clk,
|
rst => rst,
|
rst => rst,
|
go => s_go_delay,
|
go => s_go_delay,
|
set => s_set_dly,
|
set => s_set_dly,
|
setValue => s_delay_field(4 downto 0),
|
setValue => s_delay_field(4 downto 0),
|
cmpBlockValue => "00000",
|
cmpBlockValue => "00000",
|
zero_flag => s_zeroFlag_delay,
|
zero_flag => s_zeroFlag_delay,
|
eob_flag => open,
|
eob_flag => open,
|
eq_flag => open,
|
eq_flag => open,
|
count => open
|
count => open
|
);
|
);
|
--!TBXINSTANCEEND
|
--!TBXINSTANCEEND
|
|
|
sm_comb:
|
sm_comb:
|
process (s_state, full_r,s_eb_b,s_combinatory,s_zeroFlag_delay,s_eq_b,s_eb_a,s_eq_a,instrQ_empty)
|
process (s_state, full_r,s_eb_b,s_combinatory,s_zeroFlag_delay,s_eq_b,s_eb_a,s_eq_a,instrQ_empty)
|
begin
|
begin
|
--!Señal de play/pause del contador de direcciones para el parámetro B/D.
|
--!Señal de play/pause del contador de direcciones para el parámetro B/D.
|
s_go_b <= not(full_r and s_eb_b);
|
s_go_b <= not(full_r and s_eb_b);
|
|
|
--!Señal de play/pause del contador de direcciones para el parámetro A/C.
|
--!Señal de play/pause del contador de direcciones para el parámetro A/C.
|
if s_combinatory='0' then
|
if s_combinatory='0' then
|
s_go_a <= not(full_r and s_eb_b);
|
s_go_a <= not(full_r and s_eb_b);
|
|
|
else
|
else
|
s_go_a <= not(full_r) and s_eb_b and s_eq_b;
|
s_go_a <= not(full_r) and s_eb_b and s_eq_b;
|
end if;
|
end if;
|
|
|
--!Señal de play/pause del contador del arithmetic pipeline flush counter.
|
--!Señal de play/pause del contador del arithmetic pipeline flush counter.
|
s_go_delay <= not(s_zeroFlag_delay);
|
s_go_delay <= not(s_zeroFlag_delay);
|
|
|
--! Si estamos en el final de la instrucción, "descargamos" esta de la máquina de estados con acknowledge read.
|
--! Si estamos en el final de la instrucción, "descargamos" esta de la máquina de estados con acknowledge read.
|
if s_eb_b='1' and s_eq_b='1' and s_eb_a='1' and s_eq_a='1' and s_state=EXECUTE_INSTRUCTION then
|
if s_eb_b='1' and s_eq_b='1' and s_eb_a='1' and s_eq_a='1' and s_state=EXECUTE_INSTRUCTION then
|
instrRdAckd <= '1';
|
instrRdAckd <= '1';
|
else
|
else
|
instrRdAckd <= '0';
|
instrRdAckd <= '0';
|
end if;
|
end if;
|
|
|
if (s_eb_a='1' and s_eq_a='1') or s_state=LOAD_INSTRUCTION or s_state=FLUSH_ARITH_PIPELINE then
|
if (s_eb_a='1' and s_eq_a='1') or s_state=LOAD_INSTRUCTION or s_state=FLUSH_ARITH_PIPELINE then
|
s_set_a <= '1';
|
s_set_a <= '1';
|
else
|
else
|
s_set_a <= '0';
|
s_set_a <= '0';
|
end if;
|
end if;
|
|
|
|
|
|
|
if (s_eb_b='1' and s_eq_b='1') or s_state=LOAD_INSTRUCTION or s_state=FLUSH_ARITH_PIPELINE then
|
if (s_eb_b='1' and s_eq_b='1') or s_state=LOAD_INSTRUCTION or s_state=FLUSH_ARITH_PIPELINE then
|
s_set_b <= '1';
|
s_set_b <= '1';
|
else
|
else
|
s_set_b <= '0';
|
s_set_b <= '0';
|
end if;
|
end if;
|
|
|
end process;
|
end process;
|
|
|
sm_proc:
|
sm_proc:
|
process (clk,rst,s_state, full_r,s_eb_b,s_combinatory,s_zeroFlag_delay,s_eq_b,s_eb_a,s_eq_a,instrQ_empty)
|
process (clk,rst,s_state, full_r,s_eb_b,s_combinatory,s_zeroFlag_delay,s_eq_b,s_eb_a,s_eq_a,instrQ_empty)
|
begin
|
begin
|
|
|
if rst=rstMasterValue then
|
if rst=rstMasterValue then
|
|
|
s_state <= LOAD_INSTRUCTION;
|
s_state <= LOAD_INSTRUCTION;
|
s_set_dly <= '1';
|
s_set_dly <= '1';
|
sync_chain_0 <= '0';
|
sync_chain_0 <= '0';
|
eoi<='0';
|
eoi<='0';
|
s_dpc_uca <= (others => '0');
|
s_dpc_uca <= (others => '0');
|
|
|
|
|
elsif clk='1' and clk'event then
|
elsif clk='1' and clk'event then
|
|
|
case s_state is
|
case s_state is
|
|
|
--! Cargar la siguiente instrucción.
|
--! Cargar la siguiente instrucción.
|
when LOAD_INSTRUCTION =>
|
when LOAD_INSTRUCTION =>
|
|
|
eoi <= '0';
|
eoi <= '0';
|
|
|
if instrQ_empty='0' and full_r='0' then
|
if instrQ_empty='0' and full_r='0' then
|
|
|
--! Siguiente estado: Ejecutar la instrucción.
|
--! Siguiente estado: Ejecutar la instrucción.
|
s_state <= EXECUTE_INSTRUCTION;
|
s_state <= EXECUTE_INSTRUCTION;
|
|
|
--! Asignar el código UCA para que comience la decodificación.
|
--! Asignar el código UCA para que comience la decodificación.
|
s_dpc_uca <= s_instr_uca;
|
s_dpc_uca <= s_instr_uca;
|
|
|
--! Validar el siguiente dato dentro del pipeline aritmético.
|
--! Validar el siguiente dato dentro del pipeline aritmético.
|
sync_chain_0 <= '1';
|
sync_chain_0 <= '1';
|
|
|
--! En el estado EXECUTE, el valor del contador de delay se debe mantener fijo, y puesto en el valor de delay que contiene la instruccion.
|
--! En el estado EXECUTE, el valor del contador de delay se debe mantener fijo, y puesto en el valor de delay que contiene la instruccion.
|
s_set_dly <= '1';
|
s_set_dly <= '1';
|
|
|
|
|
|
|
end if;
|
end if;
|
|
|
--! Ejecución de la instruccion
|
--! Ejecución de la instruccion
|
when EXECUTE_INSTRUCTION =>
|
when EXECUTE_INSTRUCTION =>
|
|
|
|
|
if s_eb_b='1'and s_eq_b='1' and s_eb_a='1' and s_eq_a='1' then --! Revisar si es el fin de la instruccion
|
if s_eb_b='1'and s_eq_b='1' and s_eb_a='1' and s_eq_a='1' then --! Revisar si es el fin de la instruccion
|
|
|
|
|
--!Ya no ingresaran mas datos al pipeline aritmético, invalidar.
|
--!Ya no ingresaran mas datos al pipeline aritmético, invalidar.
|
sync_chain_0 <= '0';
|
sync_chain_0 <= '0';
|
|
|
if s_zeroFlag_delay='1' then
|
if s_zeroFlag_delay='1' then
|
|
|
--! Notificar fin de procesamiento de la instruccion (End Of Instruction)
|
--! Notificar fin de procesamiento de la instruccion (End Of Instruction)
|
eoi <= '1';
|
eoi <= '1';
|
s_state <= LOAD_INSTRUCTION;
|
s_state <= LOAD_INSTRUCTION;
|
s_set_dly <= '1';
|
s_set_dly <= '1';
|
|
|
|
|
else
|
else
|
|
|
s_state <= FLUSH_ARITH_PIPELINE;
|
s_state <= FLUSH_ARITH_PIPELINE;
|
s_set_dly <= '0';
|
s_set_dly <= '0';
|
|
|
end if;
|
end if;
|
|
|
--! Invalidar/validar datos dentro del pipeline aritmético.
|
--! Invalidar/validar datos dentro del pipeline aritmético.
|
elsif s_eb_b='1' and full_r='1' then
|
elsif s_eb_b='1' and full_r='1' then
|
--! Invalidar el siguiente dato dentro del pipeline aritmético.
|
--! Invalidar el siguiente dato dentro del pipeline aritmético.
|
sync_chain_0 <= '0';
|
sync_chain_0 <= '0';
|
else
|
else
|
sync_chain_0 <= '1';
|
sync_chain_0 <= '1';
|
end if;
|
end if;
|
|
|
--! Ejecución de la instrucción
|
--! Ejecución de la instrucción
|
when FLUSH_ARITH_PIPELINE =>
|
when FLUSH_ARITH_PIPELINE =>
|
--! Este estado permanece así hasta que, haya una instrucción
|
--! Este estado permanece así hasta que, haya una instrucción
|
if s_zeroFlag_delay='1' then
|
if s_zeroFlag_delay='1' then
|
|
|
--! Notificar fin de procesamiento de la instruccion (End Of Instruction)
|
--! Notificar fin de procesamiento de la instruccion (End Of Instruction)
|
eoi <= '1';
|
eoi <= '1';
|
s_state <= LOAD_INSTRUCTION;
|
s_state <= LOAD_INSTRUCTION;
|
s_set_dly <= '1';
|
s_set_dly <= '1';
|
|
|
end if;
|
end if;
|
|
|
when others => null;
|
when others => null;
|
|
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
end architecture;
|
end architecture;
|
|
|