URL
https://opencores.org/ocsvn/raytrac/raytrac/trunk
Subversion Repositories raytrac
Compare Revisions
- This comparison shows the changes necessary to convert path
/raytrac/branches/fp
- from Rev 144 to Rev 145
- ↔ Reverse comparison
Rev 144 → Rev 145
/sm.vhd
32,24 → 32,37
width : integer := 32; |
widthadmemblock : integer := 9 |
--!external_readable_widthad : |
) |
); |
port ( |
|
clk,rst:in std_logic; |
--! Señales normales de secuencia. |
clk,rst: in std_logic; |
|
adda,addb:out std_logic_vector (widthadmemblock-1 downto 0); |
sync_chain_d:out std_logic; |
--! ENTRADAS DE CONTROL DE SINCRONIZACION. |
--! Señales de sincronización de recursos. |
--! Las siguientes entradas tienen relevancia y son sensibles en los estados EXECUTE_INSTRUCTION y VERMEER_EXECUTE. |
|
|
|
--! ENTRADAS |
|
|
|
--! Instruction Q, instruction. |
instrQq:in std_logic_vector(width-1 downto 0); |
instrQ_empty:in std_logic; |
|
|
adda,addb:out std_logic_vector (widthadmemblock-1 downto 0); |
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. |
|
|
--! apempty, arithmetical pipeline empty. |
arithPbusy, instrQempty ,resultQfull: in std_logic; |
|
|
--! DataPath Control uca code. |
dpc_uca : out std_logic_vector (2 downto 0); |
dpc_uca : out std_logic_vector (2 downto 0) |
|
|
); |
57,82 → 70,205
|
architecture sm_arch of sm is |
|
type macState is (FLUSH_TO_NEXT_INSTRUCTION,EXECUTE_INSTRUCTION); |
type macState is (LOAD_INSTRUCTION,FLUSH_ARITH_PIPELINE,EXECUTE_INSTRUCTION); |
--! 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. |
--! 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. |
|
signal state : macState; |
constant rstMasterValue : std_logic:='0'; |
|
component customCounter |
generic ( |
width : integer |
EOBFLAG : string ; |
ZEROFLAG : string ; |
BACKWARDS : string ; |
EQUALFLAG : string ; |
subwidth : integer; |
width : integer |
|
); |
port ( |
clk,rst,go,set : in std_logic; |
setValue : in std_Logic_vector(width-1 downto 0); |
setValue,cmpBlockValue : in std_Logic_vector(width-1 downto subwidth); |
zero_flag,eob_flag,eq_flag : out std_logic; |
count : out std_logic_vector(width-1 downto 0) |
) |
); |
end component; |
|
signal addt0_blocka,addt0_blockb,set_Value_A,set_Value_B : std_logic_vector(widthadmemblock-1 downto 0); |
signal add_condition_a, add_condition_b,set_a,set_b : std_logic; |
signal s_dpc_uca, s_instrQ_uca : std_logic_vector(2 downto 0); |
signal s_block_start_a, s_block_start_b, s_block_end_a, s_block_end_b : std_logic_vector(4 downto 0); |
|
|
|
signal s_instr_uca: std_logic_vector(2 downto 0); |
signal s_dpc_uca: std_logic_vector(2 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_end_a: std_logic_vector(4 downto 0); |
signal s_block_end_b: std_logic_vector(4 downto 0); |
signal s_combinatory: std_logic; |
signal s_delay_field: std_logic_vector(7 downto 0); |
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_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_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_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_eb_b,s_eb_a: std_logic; --! Indica que se está leyendo en memoria el último operando del bloque actual, b o a, respectivamente. |
|
begin |
--! 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; |
|
--! Bloques asignados |
|
--! Bloques asignados en la instrucci´øn |
s_block_start_a <= instrQq(width-4 downto width-8); |
s_block_start_b <= instrQq(width-14 downto width-18); |
s_block_end_a <= instrQq(width-9 downto width-13); |
s_block_end_b <= instrQq(width-19 downto width-) |
|
s_block_start_b <= instrQq(width-14 downto width-18); |
s_block_end_b <= instrQq(width-19 downto width-23); |
|
--! Campo que define si la instrucción es combinatoria |
s_combinatory <= instrQq(width-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. |
s_delay_field <= instrQq(width-25 downto width-32); |
|
--! UCA code, código con la instrucción a ejecutar. |
s_instr_uca <= instrQq(31 downto 29); |
|
--! Address Counters |
counterA:customCounter |
port map (clk,rst,add_condition_a,set_a,instrQq(width-4 downto width-8)&x"0",addt0_blocka); |
generic map ("YES","NO","NO","YES",4,9) |
port map (clk,rst,s_go_a,s_set_a,s_block_start_a,s_block_end_a,open,s_eb_a,s_eq_a,adda); |
counterB:customCounter |
port map (clk,rst,add_condition_b,set_b,instrQq(width-9 downto width-12)&x"0",addt0_blockb); |
adda <= addt0_blocka; |
addb <= addt0_blockb; |
generic map ("YES","NO","NO","YES",4,9) |
port map (clk,rst,s_go_b,s_set_b,s_block_start_b,s_block_end_b,open,s_eb_b,s_eq_b,addb); |
counterDly:customCounter |
generic map("NO","YES","YES","NO",0,5) |
port map (clk,rst,s_go_delay,s_set_dly,s_delay_field(4 downto 0),"00000",s_zeroFlag_delay,open,open,open); |
|
--! uca code |
s_instrQ_uca <= instrQq(31 downto 29); |
|
sm_comb: |
process (state, full_r,s_eb_b,s_combinatory,s_zeroFlag_delay,s_eq_b,s_eb_a,s_eq_a,instrQ_empty) |
begin |
--!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); |
|
--!Señal de play/pause del contador de direcciones para el parámetro A/C. |
if s_combinatory='0' then |
s_go_a <= not(full_r and s_eb_b); |
|
else |
s_go_a <= not(full_r) and s_eb_b and s_eq_b; |
end if; |
|
--!Señal de play/pause del contador del arithmetic pipeline flush counter. |
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. |
if s_eb_b='1' and s_eq_b='1' and s_eb_a='1' and s_eq_a='1' and state=EXECUTE_INSTRUCTION then |
instrRdAckd <= '1'; |
else |
instrRdAckd <= '0'; |
end if; |
|
if (s_eb_a='1' and s_eq_a='1') or state=LOAD_INSTRUCTION or state=FLUSH_ARITH_PIPELINE then |
s_set_a <= '1'; |
else |
s_set_a <= '0'; |
end if; |
|
|
|
if (s_eb_b='1' and s_eq_b='1') or state=LOAD_INSTRUCTION or state=FLUSH_ARITH_PIPELINE then |
s_set_b <= '1'; |
else |
s_set_b <= '0'; |
end if; |
|
end process; |
|
sm_proc: |
process (clk,rst) |
process (clk,rst,state, full_r,s_eb_b,s_combinatory,s_zeroFlag_delay,s_eq_b,s_eb_a,s_eq_a,instrQ_empty) |
begin |
|
if rst=rstMasterValue then |
state <= IDLE; |
ird_ack <= '0'; |
|
state <= LOAD_INSTRUCTION; |
s_set_dly <= '1'; |
sync_chain_0 <= '0'; |
s_dpc_uca <= (others => '0'); |
|
|
elsif clk='1' and clk'event then |
|
case state is |
when FLUSH_TO_NEXT_INSTRUCTION => |
|
--! Chequear si hay una instruccion en la salida de la cola de instruccioens. |
if instrQempty='0' then |
--! Cargar la siguiente instrucción. |
when LOAD_INSTRUCTION => |
|
if instrQ_empty='0' and full_r='0' then |
|
--! Chequear si la cola de resultados tiene espacio. |
if resultQfull='0' then |
--! Siguiente estado: Ejecutar la instrucción. |
state <= EXECUTE_INSTRUCTION; |
|
--! Asignar el código UCA para que comience la decodificación. |
s_dpc_uca <= s_instr_uca; |
|
--! Validar el siguiente dato dentro del pipeline aritmético. |
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. |
s_set_dly <= '1'; |
|
|
|
end if; |
|
--! Ejecución de la instruccion |
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 |
|
--!Ya no ingresaran mas datos al pipeline aritmético, invalidar. |
sync_chain_0 <= '0'; |
|
if s_zeroFlag_delay='1' then |
|
state <= LOAD_INSTRUCTION; |
s_set_dly <= '1'; |
|
--! Si el codigo de instruccion (uca) que se encuentra en el DPC es igual al que se encuentra en la instruccion de la salida de la cola de instrucciones, entonces no hay mas validaciones que hacer. |
|
else |
|
state <= FLUSH_ARITH_PIPELINE; |
s_set_dly <= '0'; |
|
|
--! Now check that arithmetic pipline is not busy |
if arithPbusy='0' then |
|
|
when EXECUTE_INSTRUCTION => |
if addt1_blockb(4 downto 0)=x"1f" and addt1_blocka=x"1f" then |
if addt1_blockb(8 downto ) |
end if; |
|
--! Invalidar/validar datos dentro del pipeline aritmético. |
elsif s_eb_b='1' and full_r='1' then |
--! Invalidar el siguiente dato dentro del pipeline aritmético. |
sync_chain_0 <= '0'; |
else |
sync_chain_0 <= '1'; |
end if; |
|
--! Ejecución de la instrucción |
when FLUSH_ARITH_PIPELINE => |
--! Este estado permanece así hasta que, haya una instrucción |
if s_zeroFlag_delay='1' then |
|
end if; |
state <= LOAD_INSTRUCTION; |
s_set_dly <= '1'; |
|
|
end if; |
|
when others => null; |
|
end case; |
end if; |
end process; |
|
nxtadda_proc: |
process () |
end architecture; |
/dpc.vhd
37,7 → 37,7
fifo32x23_q : in std_logic_vector (03*width-1 downto 0); --! Salida de la cola intermedia. |
fifo32x09_q : in std_logic_vector (02*width-1 downto 0); --! Salida de las colas de producto punto. |
unary,crossprod,addsub : in std_logic; --! Bit con el identificador del bloque AB vs CD e identificador del sub bloque (A/B) o (C/D). |
sync_chain_d : in std_logic; --! Señal de dato valido que se va por toda la cadena de sincronizacion. |
sync_chain_0 : in std_logic; --! Señal de dato valido que se va por toda la cadena de sincronizacion. |
sqr32blki,inv32blki : out std_logic_vector (width-1 downto 0); --! Salidas de las 2 raices cuadradas y los 2 inversores. |
fifo32x26_d : out std_logic_vector (03*width-1 downto 0); --! Entrada a la cola intermedia para la normalización. |
fifo32x09_d : out std_logic_vector (02*width-1 downto 0); --! Entrada a las colas intermedias del producto punto. |
95,14 → 95,13
begin |
|
--! Cadena de sincronización: 29 posiciones. |
ssync_chain_d <= sync_chain_d; |
ssync_chain(0) <= sync_chain_0; |
sync_chain_proc: |
process(clk,rst) |
begin |
if rst=rstMasterValue then |
ssync_chain <= (others => '0'); |
ssync_chain(28 downto 1) <= (others => '0'); |
elsif clk'event and clk='1' then |
ssync_chain(0) <= ssync_chain_d; |
for i in 28 downto 1 loop |
ssync_chain(i) <= ssync_chain(i-1); |
end loop; |
/customCounter.vhd
28,11 → 28,17
|
entity customCounter is |
generic ( |
width : integer := 9 |
) |
EOBFLAG : string := "NO"; |
ZEROFLAG : string := "YES"; |
BACKWARDS : string := "YES"; |
EQUALFLAG : string := "NO"; |
subwidth : integer := 0; |
width : integer := 5 |
); |
port ( |
clk,rst,go,set : in std_logic; |
setValue : in std_logic_vector(width - 1 downto 0); |
setValue, cmpBlockValue : in std_logic_vector (width-1 downto subwidth); --! Los 5 bits de arriba. |
zero_flag,eob_flag, eq_flag : out std_logic; |
count : out std_logic_vector (width - 1 downto 0) |
); |
end entity; |
42,17 → 48,111
architecture customCounter_arch of customCounter is |
|
constant rstMasterValue : std_logic := '0'; |
signal scount_d, scount_q : std_logic_vector(width-1 downto 0); |
|
signal scount_d, scount_q, sgo : std_logic_vector(width-1 downto 0); |
signal seob_flag : std_logic; |
|
begin |
|
--!Compara los bits superiores solamente, si subwidth es 4 y width es 9 comparara los 9-4=5 bits superiores. |
steadyEqualFlag: |
if EQUALFLAG/="YES" generate |
eq_flag <= '0'; |
end generate steadyEqualFlag; |
equalFlagsProcess: |
if EQUALFLAG="YES" generate |
process (scount_d(width-1 downto subwidth),cmpBlockValue,clk,rst) |
begin |
if rst=rstMasterValue then |
eq_flag <= '0'; |
elsif clk'event and clk='1' then |
if scount_d(width-1 downto subwidth)=cmpBlockValue then |
eq_flag <= '1'; |
else |
eq_flag <= '0'; |
end if; |
end if; |
end process; |
end generate equalFlagsProcess; |
|
--Backwards or Forwards. |
forwardGenerator: |
if BACKWARDS="NO" generate |
sgo(width-1 downto 1) <= (others => '0'); |
sgo(0) <= go; |
end generate forwardGenerator; |
|
backwardGenerator: |
if BACKWARDS="YES" generate |
sgo(width-1 downto 0) <= (others => go); |
end generate backwardGenerator; |
|
|
--! Si en los parámetros no se encuentra especificado que detecte el zero entonces la salida zero_flag estará en cero siempre. |
steadyZeroFlag: |
if ZEROFLAG/="YES" generate |
zero_flag <= '0'; |
end generate steadyZeroFlag; |
|
--! Si el parámetro para la bandera de cero se especifica, entonces se instancia un proceso que depende del valor del conteo. |
zeroFlagProcess: |
if ZEROFLAG="YES" generate |
--! Proceso para calcular la bandera de cero, en el conteo. |
process (scount_d,clk,rst) |
begin |
if rst=rstMasterValue then |
zero_flag <= '0'; |
elsif clk'event and clk='1' then |
zero_flag <= '1'; |
for i in width-1 downto 0 loop |
if scount_d(i) = '1' then |
zero_flag <= '0'; |
exit;--the loop; |
end if; |
end loop; |
end if; |
end process; |
end generate zeroFlagProcess; |
|
|
--! Proceso para controlar la salida de la bandera de fin de bloque. Se colocará en uno lógico cuando el conteo vaya en multiplo de 32 menos 1. |
steadyEobFlag: |
if EOBFLAG/="YES" generate |
eob_flag <= '0'; |
end generate steadyEobFlag; |
eobFlagProcess: |
if EOBFLAG="YES" generate |
process (scount_d(subwidth-1 downto 0),clk,rst) |
begin |
if rst=rstMasterValue then |
eob_flag <= '0'; |
elsif clk'event and clk='1' then |
eob_flag <= '1'; |
for i in subwidth-1 downto 0 loop |
if scount_d(i) /= '1' then |
eob_flag <= '0'; |
exit;--the loop |
end if; |
end loop; |
end if; |
end process; |
end generate eobFlagProcess; |
|
--! Salida combinatoria del contador. |
count <= scount_d; |
|
--! Proceso de control del conteo. |
add_proc: |
process (scount_q,go,set,setValue) |
process (scount_q,sgo,set,setValue) |
begin |
case set is |
when '1' => scount_d <= setValue; |
when others => scount_d <= scount_q+go; |
case set is |
--! Si subwidth es cero, p.ej. cuando se quiere hacer un contador simple y no detectar el final de bloques de 4 bits de ancho, el compilador ignora el statement con la expresión por fuera del rango. |
when '1' => scount_d(subwidth-1 downto 0) <= (others => '0');scount_d(width-1 downto subwidth) <= setValue; |
|
--! Strange, but yet true. Esto se puede hacer, es practicamente una compilacion condicional pero posiblemente coste una cuantas celdas logicas. |
-- if subwidth>0 then |
-- scount_d(subwidth-1 downto 0) <= (others => '0'); |
-- end if; |
when others => scount_d <= scount_q+sgo; |
end case; |
end process; |
|