Line 1... |
Line 1... |
--! @file raytrac.vhd
|
library ieee;
|
--! @brief Archivo con el RTL que describe al RayTrac en su totalidad.
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
--! @author Julián Andrés Guarín Reyes
|
library altera_mf;
|
--------------------------------------------------------------
|
use altera_mf.altera_mf_components.all;
|
-- RAYTRAC
|
|
-- Author Julian Andres Guarin
|
|
-- Rytrac.vhd
|
|
-- This file is part of raytrac.
|
|
--
|
|
-- raytrac is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- raytrac is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with raytrac. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
library lpm;
|
|
use lpm.lpm_components.all;
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.arithpack.all;
|
|
|
|
entity raytrac is
|
entity slave_template is
|
|
generic (
|
|
wd : integer := 32;
|
|
sl : integer := 5; --! Arith Sync Chain Long 2**sl
|
|
ln : integer := 12; --! Max Transfer Length = 2**ln = n_outputbuffers * 256
|
|
fd : integer := 8; --! Result Fifo Depth = 2**fd =256
|
|
mb : integer := 4; --! Max Burst Length = 2**mb
|
|
nr : integer := 4 --! Number of Registers = 2**nr
|
|
);
|
port (
|
port (
|
|
|
clk : in std_logic;
|
clk : in std_logic;
|
rst : in std_logic;
|
rst : in std_logic;
|
|
|
|
--! Avalon MM Slave
|
|
slave_address : in std_logic_vector(3 downto 0);
|
|
slave_read : in std_logic;
|
|
slave_write : in std_logic;
|
|
slave_readdata : out std_logic_vector(31 downto 0);
|
|
slave_writedata : in std_logic_vector(31 downto 0);
|
|
|
|
--! Avalon MM Master (Read & Write common signals)
|
|
master_address : out std_logic_vector(31 downto 0);
|
|
master_burstcount : out std_logic_vector(4 downto 0);
|
|
master_waitrequest : in std_logic;
|
|
|
|
--! Avalon MM Master (Read Stage)
|
|
master_read : out std_logic;
|
|
master_readdata : in std_logic_vector(31 downto 0);
|
|
master_readdatavalid : in std_logic;
|
|
|
|
--! Avalon MM Master (Write Stage)
|
|
master_write : out std_logic;
|
|
master_writedata : out std_logic_vector(31 downto 0);
|
|
|
--! Interface Avalon Master
|
--! Avalon IRQ
|
address_master : out std_logic_vector(31 downto 0);
|
|
begintransfer : out std_logic;
|
|
read_master : out std_logic;
|
|
readdata_master : in std_logic_vector (31 downto 0);
|
|
write_master : out std_logic;
|
|
writedata_master: out std_logic_vector (31 downto 0);
|
|
waitrequest : in std_logic_vector;
|
|
readdatavalid_m : in std_logic_vector;
|
|
|
|
--! Interface Avalon Slave
|
|
address_slave : in std_logic_vector(3 downto 0);
|
|
read_slave : in std_logic;
|
|
readdata_slave : in std_logic_vector(31 downto 0);
|
|
write_slave : in std_logic;
|
|
writedata_slave : in std_logic_vector(31 downto 0);
|
|
readdatavalid_s : out std_logic;
|
|
|
|
--! Interface Interrupt Sender
|
|
irq : out std_logic
|
irq : out std_logic
|
|
|
|
|
|
|
);
|
);
|
end entity;
|
end entity;
|
|
|
architecture raytrac_arch of raytrac is
|
|
|
|
--!Señales de State Machine -> Memblock
|
architecture slave_template_arch of slave_template is
|
--!TBXSTART:SM
|
|
signal s_adda : std_logic_vector (8 downto 0);
|
|
signal s_addb : std_logic_vector (8 downto 0);
|
|
signal s_iq_rd_ack : std_logic;
|
|
--!Señales de State Machine -> DataPathControl
|
|
signal s_dpc_uca : std_logic_vector(2 downto 0);
|
|
signal s_eoi : std_logic;
|
|
signal s_sign : std_logic;
|
|
--!TBXEND
|
|
|
|
--!TBXSTART:MBLK
|
|
--!Señales de Memblock -> State Machine
|
|
signal sqresult_e : std_logic_vector(3 downto 0);
|
|
signal sqparams_e : std_logic;
|
|
--!Señales de Memblock -> DPC.
|
|
signal sparaminput : vectorblock06;
|
|
signal sqresult_q : vectorblock04;
|
|
--!Señales de Memblock -> DPC.
|
|
signal s_sync_chain_0 : std_logic;
|
|
--!TBXEND
|
|
|
|
--!TXBXSTART:DPC
|
|
--! Señ que va desde DPC -> Memblock
|
|
signal sqresult_d : vectorblock04;
|
|
signal sqresult_w : std_logic_vector (3 downto 0);
|
|
signal sqresult_rdec : std_logic_vector (3 downto 0);
|
|
|
|
--! Señales de DPC a ArithBlock
|
|
signal sprd32blki : vectorblock12;
|
|
signal sadd32blki : vectorblock06;
|
|
|
|
--!TBXEND
|
|
|
|
--!TBXSTART:ARITHBLOCK
|
|
--! Señales de Arithblock a DPC
|
|
signal sadd32blko : vectorblock03;
|
|
signal sprd32blko : vectorblock06;
|
|
signal ssq32o : xfloat32;
|
|
signal sinv32o : xfloat32;
|
|
--!TBXEND
|
|
|
|
--!TBXSTART:SM
|
|
--! Señales de State Machine a DPC
|
|
signal sqresult_sel : std_logic_vector(1 downto 0);
|
|
signal sdataread : std_logic;
|
|
signal sd : std_logic;
|
|
signal sc : std_logic;
|
|
signal ss : std_logic;
|
|
|
|
--! Señales de State Machine a Memblock
|
|
signal sgo : std_logic;
|
|
signal scomb : std_logic;
|
|
signal sload : std_logic;
|
|
signal sload_chain : std_logic_vector(1 downto 0);
|
|
--!TBXEND
|
|
|
|
|
--! Altera Compiler Directive, to avoid m9k autoinferring thanks to the guys at http://www.alteraforum.com/forum/archive/index.php/t-30784.html ....
|
|
attribute altera_attribute : string;
|
|
attribute altera_attribute of slave_template_arch : architecture is "-name AUTO_SHIFT_REGISTER_RECOGNITION OFF";
|
|
|
|
|
|
subtype xfloat32 is std_logic_vector(wd-1 downto 0);
|
|
type registerblock is array ((2**nr)-1 downto 0) of xfloat32;
|
|
type transferState is (IDLE,SINK,SOURCE);
|
|
|
|
constant rstMasterValue : std_logic :='0';
|
|
|
|
|
|
constant reg_ctrl : integer:=00;
|
|
constant reg_vz : integer:=01;
|
|
constant reg_vy : integer:=02;
|
|
constant reg_vx : integer:=03;
|
|
constant reg_scalar : integer:=04;
|
|
constant reg_scratch00 : integer:=05;
|
|
constant reg_outputcounter : integer:=06;
|
|
constant reg_inputcounter : integer:=07;
|
|
constant reg_fetchstart : integer:=08;
|
|
constant reg_sinkstart : integer:=09;
|
|
constant reg_ax : integer:=10;
|
|
constant reg_ay : integer:=11;
|
|
constant reg_az : integer:=12;
|
|
constant reg_bx : integer:=13;
|
|
constant reg_by : integer:=14;
|
|
constant reg_bz : integer:=15;
|
|
|
|
|
|
|
|
constant reg_ctrl_cmb : integer:=00; --! CMB bit : Combinatorial Instruction.
|
|
constant reg_ctrl_s : integer:=01; --! S bit of the DCS field.
|
|
constant reg_ctrl_c : integer:=02; --! C bit of the DCS field.
|
|
constant reg_ctrl_d : integer:=03; --! D bit of the DCS field.
|
|
|
|
constant reg_ctrl_sc : integer:=04; --! SC bit of the VTSC field.
|
|
constant reg_ctrl_vt : integer:=05; --! VT bit of the VTSC field.
|
|
constant reg_ctrl_flags_ae : integer:=06; --! Almost Empty Flag.
|
|
constant reg_ctrl_flags_fc : integer:=07; --! Flood Condition Flag.
|
|
|
|
constant reg_ctrl_flags_dc : integer:=08; --! Drain Condition Flag.
|
|
constant reg_ctrl_flags_wp : integer:=09; --! Write on Memory Pending Flag.
|
|
constant reg_ctrl_flags_pp : integer:=10; --! Pipeline Pending Flag.
|
|
constant reg_ctrl_flags_pl : integer:=11; --! Load Parameter Pending Flag.
|
|
|
|
constant reg_ctrl_flags_dp : integer:=12; --! Data Pending flag.
|
|
constant reg_ctrl_flags_ap : integer:=13; --! Address Pending Flag.
|
|
constant reg_ctrl_rlsc : integer:=14; --! RLSC bit : Reload Load Sync Chain.
|
|
constant reg_ctrl_rom : integer:=15; --! ROM bit : Read Only Mode bit.
|
|
|
|
constant reg_ctrl_nfetch_low : integer:=16; --! NFETCH_LOW : Lower bit to program the number of addresses to load in the interconnection.
|
|
constant reg_ctrl_nfetch_high : integer:=30; --! NFETCH_HIGH : Higher bit to program the number of addresses to load in the interconnection.
|
|
constant reg_ctrl_irq : integer:=31; --! IRQ bit : Interrupt Request Signal.
|
|
|
|
|
|
--! Avalon MM Slave
|
|
signal sreg_block : registerblock;
|
|
signal sslave_read : std_logic;
|
|
signal sslave_write : std_logic;
|
|
signal sslave_writedata : xfloat32;
|
|
signal sslave_address : std_logic_vector (nr-1 downto 0);
|
|
signal sslave_waitrequest : std_logic;
|
|
--! Avalon MM Master
|
|
signal smaster_write : std_logic;
|
|
signal smaster_read : std_logic;
|
|
|
|
|
|
--! State Machine and event signaling
|
|
signal sm : transferState;
|
|
|
|
signal sres_ack : std_logic;
|
|
signal soutb_ack : std_logic;
|
|
|
|
signal sres_q : std_logic_vector(4*wd-1 downto 0);
|
|
|
|
signal sres_d : std_logic_vector(4*wd-1 downto 0);
|
|
signal soutb_d : std_logic_vector(wd-1 downto 0);
|
|
|
|
|
|
signal sres_w : std_logic;
|
|
signal soutb_w : std_logic;
|
|
|
|
signal sres_e : std_logic;
|
|
signal soutb_e : std_logic;
|
|
signal soutb_ae : std_logic;
|
|
signal soutb_af : std_logic;
|
|
|
|
signal soutb_usedw : std_logic_vector(fd-1 downto 0);
|
|
|
|
signal ssync_chain_1 : std_logic;
|
|
signal ssync_chain_pending : std_logic;
|
|
signal sfetch_data_pending : std_logic;
|
|
signal sload_add_pending : std_logic;
|
|
signal spipeline_pending : std_logic;
|
|
signal swrite_pending : std_logic;
|
|
signal sparamload_pending : std_logic;
|
|
signal sZeroTransit : std_logic;
|
|
|
|
|
|
--!Unload Control
|
|
type upload_chain is (VX,VY,VZ,SC);
|
|
signal supload_chain : upload_chain;
|
|
signal supload_start : upload_chain;
|
|
|
|
--!Señales de apoyo:
|
|
signal zero : std_logic_vector(31 downto 0);
|
|
|
|
--!High Register Bank Control Signals or AKA Load Sync Chain Control
|
|
type download_chain is (AX,AY,AZ,BX,BY,BZ,AXBX,AYBY,AZBZ);
|
|
signal sdownload_chain : download_chain;
|
|
signal sdownload_start : download_chain;
|
|
signal srestart_chain : std_logic;
|
|
--!State Machine Hysteresis Control Signals
|
|
signal sdrain_condition : std_logic;
|
|
signal sdrain_burstcount : std_logic_vector(mb downto 0);
|
|
signal sdata_fetch_counter : std_logic_vector(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low);
|
|
signal sburstcount_sink : std_logic_vector(mb downto 0);
|
|
|
|
signal sflood_condition : std_logic;
|
|
signal sflood_burstcount : std_logic_vector(mb downto 0);
|
|
|
|
|
begin
|
begin
|
--!TBXINSTANCESTART
|
|
state_machine : raytrac_control
|
|
port map (
|
|
clk => clk,
|
|
rst => rst,
|
|
adda => s_adda,
|
|
addb => s_addb,
|
|
sync_chain_0 => s_sync_chain_0,
|
|
instrRdAckd => s_iq_rd_ack,
|
|
full_r => s_full_r,
|
|
eoi => s_eoi,
|
|
dpc_uca => s_dpc_uca,
|
|
state => s_smState
|
|
|
|
);
|
--! Unos y ceros
|
--!TBXINSTANCEEND
|
zero <= (others => '0');
|
|
|
--!TBXINSTANCESTART
|
--! Salidas no asignadas
|
MemoryBlock : memblock
|
|
port map (
|
|
clk => clk,
|
|
rst => rst,
|
|
go => sgo,
|
|
comb => scomb,
|
|
load => sload,
|
|
|
|
readdatavalid => readdatavalid,
|
|
readdata_master => readdata_master,
|
|
qparams_e => sqparams_e,
|
|
qresult_d => sqresult_d,
|
|
paraminput => sparaminput,
|
|
sync_chain_0 => s_sync_chain_0,
|
|
qresult_e => sqresult_e,
|
|
qresult_w => sqresult_w,
|
|
qresult_rdec => sqresult_rdec
|
|
|
|
);
|
--! Mientras tanto
|
--!TBXINSTANCEEND
|
ssync_chain_pending <= ssync_chain_1;
|
|
sres_d ((wd*1)-1 downto wd*0)<= sreg_block(reg_bz) ;
|
|
sres_d ((wd*2)-1 downto wd*1)<= sreg_block(reg_by) ;
|
|
sres_d ((wd*3)-1 downto wd*2)<= sreg_block(reg_bx) ;
|
|
sres_d ((wd*4)-1 downto wd*3)<= sreg_block(reg_ax) ;
|
|
sres_w <= ssync_chain_1;
|
|
|
--! Instanciar el bloque DPC
|
|
--!TBXINSTANCESTART
|
|
DataPathControl_And_Syncronization_Block: dpc
|
|
port map (
|
|
|
|
clk => clk,
|
|
rst => rst,
|
|
|
|
paraminput => sparaminput,
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! AVALON MEMORY MAPPED MASTER INTERFACE BEGIN => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => =>
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! ******************************************************************************************************************************************************
|
|
--! TRANSFER CONTROL RTL CODE
|
|
--! ******************************************************************************************************************************************************
|
|
TRANSFER_CONTROL:
|
|
process(clk,rst,master_waitrequest,soutb_ae,soutb_usedw,spipeline_pending,soutb_e,zero,soutb_af,sfetch_data_pending,sreg_block,sslave_write,sslave_address,sslave_writedata,ssync_chain_pending,sres_e,smaster_read,smaster_write,sdata_fetch_counter,sload_add_pending,swrite_pending,sdownload_chain)
|
|
begin
|
|
|
prd32blko => sprd32blko,
|
--! Conexióln a señales externas.
|
add32blko => sadd32blko,
|
irq <= sreg_block(reg_ctrl)(reg_ctrl_irq);
|
inv32blko => sinv32o,
|
master_read <= smaster_read;
|
sqr32blko => ssq32o,
|
master_write <= smaster_write;
|
|
|
|
|
|
--! ZERO_TRANSIT: Cuando todos los elementos de sincronización están en cero menos la cola de sincronización de carga de parametros.
|
|
sZeroTransit <= not(sload_add_pending or sfetch_data_pending or spipeline_pending or swrite_pending);
|
|
|
|
--! ELEMENTO DE SINCRONIZACION OUT QUEUE: Datos pendientes por cargar a la memoria a través de la interconexión
|
|
swrite_pending <= not(soutb_e);
|
|
|
|
--! ELEMENTO DE SINCRONIZACION ARITH PIPELINE: Hay datos transitando por el pipeline aritmético.
|
|
if ssync_chain_pending='1' or sres_e='0' then
|
|
spipeline_pending <= '1';
|
|
else
|
|
spipeline_pending <= '0';
|
|
end if;
|
|
|
|
--! ELEMENTO DE SINCRONIZACION DESCARGA DE DATOS: Hay datos pendientes por descargar desde la memoria a través de la interconexión.
|
|
if sdata_fetch_counter=zero(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low) then
|
|
sfetch_data_pending <= '0';
|
|
else
|
|
sfetch_data_pending <= '1';
|
|
end if;
|
|
|
|
--! ELEMENTO DE SINCRONIZACION CARGA DE DIRECCIONES: Hay direcciones pendientes por cargar a la interconexión?
|
|
if sreg_block(reg_ctrl)(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low)=zero(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low) then
|
|
sload_add_pending <= '0';
|
|
else
|
|
sload_add_pending <= '1';
|
|
end if;
|
|
|
|
--! ELEMENTO DE SINCRONIZACION CARGA DE OPERANDOS: Se están cargando los operandos que serán operados en el pipeline aritmético.
|
|
if sdownload_chain /= AX and sdownload_chain /= AXBX then
|
|
sparamload_pending <= '1';
|
|
else
|
|
sparamload_pending <= '0';
|
|
end if;
|
|
|
|
--! Se debe iniciar una transacción de descarga de datos desde la memoria externa?
|
|
if soutb_af='0' and sload_add_pending='1' then
|
|
--! Flow Control : La saturación de la cola de resultados continuará si no está tan llena y además hay pendientes datos por ser descargados.
|
|
sflood_condition <= '1';
|
|
else
|
|
--! Flow Control : La saturación de la cola de resultados debe parar porque está casí llena.
|
|
sflood_condition <= '0';
|
|
end if;
|
|
if sreg_block(reg_ctrl)(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low+mb)/=zero(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low+mb) then
|
|
--! Flow Control: Si el número de descargas pendientes es mayor o igual al max burst length, entonces cargar max burst en el contador.
|
|
sflood_burstcount <= '1'&zero(mb-1 downto 0);
|
|
else
|
|
--! Flow Control: Si le número de descargas pendientes es inferior a Max Burst Count entonces cargar los bits menos significativos del registro de descargas pendientes.
|
|
sflood_burstcount <= '0'&sreg_block(reg_ctrl)(reg_ctrl_nfetch_low+mb-1 downto reg_ctrl_nfetch_low);
|
|
end if;
|
|
|
|
--! Se debe iniciar una transacción de carga de datos hacia la memoria externa?
|
|
if soutb_ae='1' then
|
|
--! Flow Control : Cuando se esté drenando la cola de resultados, si la cola está casí vac&iaute;a, la longitud del burst serán los bits menos significativos del contador de la cola.
|
|
sdrain_burstcount <= soutb_usedw(mb downto 0);
|
|
--! Flow Control: El drenado de datos continuará si el número de datos en la cola bajo y no hay datos transitando por el pipeline, ni datos pendientes por cargar desde la memoria.
|
|
sdrain_condition <= not(sload_add_pending) and not(sfetch_data_pending) and not(spipeline_pending) and swrite_pending;
|
|
else
|
|
--! Flow Control: Cuando se esté drenando la cola de resultados, si la cola de tiene una cantidad de datos mayor al burst count entonces se hará una transacción de longitud equivalente al burst count.
|
|
sdrain_burstcount <= '1'&zero(mb-1 downto 0);
|
|
--! Flow Control: El drenado de datos continuará si el número de datos en la cola es mayor o igual a 2**mb O si hay muy pocos datos y no hay datos transitando por el pipeline.
|
|
sdrain_condition <= '1';
|
|
end if;
|
|
|
|
--! Restart param load chain
|
|
srestart_chain <= sreg_block(reg_ctrl)(reg_ctrl_irq) and sreg_block(reg_ctrl)(reg_ctrl_rlsc);
|
|
|
|
--! Data dumpster: Dump data once the interconeection has loaded the data to write.
|
|
if sm=SINK and master_waitrequest='0' and smaster_write='1' then
|
|
soutb_ack <= '1';
|
|
else
|
|
soutb_ack <= '0';
|
|
end if;
|
|
|
|
--! Flow Control State Machine.
|
|
if rst=rstMasterValue then
|
|
|
|
--! State Machine
|
|
sm <= IDLE;
|
|
|
|
|
|
--! Master Write & Read Common Signals Reset Value
|
|
master_burstcount <= (others => '0');
|
|
master_address <= (others => '0');
|
|
sdata_fetch_counter <= (others => '0');
|
|
sburstcount_sink <= (others => '0');
|
|
|
|
--! Master Read Only Signals Reset Value
|
|
smaster_read <= '0';
|
|
|
|
--! Master Write Only Signals
|
|
smaster_write <= '0';
|
|
|
|
--! Reg Ctrl & Fetch address and writeaddress
|
|
--! Sinking address
|
|
sreg_block(reg_sinkstart) <= (others => '0');
|
|
--! Sourcing address
|
|
sreg_block(reg_fetchstart) <= (others => '0');
|
|
--! Control and Status Register
|
|
sreg_block(reg_ctrl) <= (others => '0');
|
|
--! Contador Overall
|
|
sreg_block(reg_inputcounter) <= (others => '0');
|
|
sreg_block(reg_outputcounter) <= (others => '0');
|
|
|
|
|
|
elsif clk'event and clk='1' then
|
|
|
|
--! Nevermind the State, discount the incoming valid data counter.
|
|
sdata_fetch_counter <= sdata_fetch_counter-master_readdatavalid;
|
|
|
|
--! Debug Counter.
|
|
sreg_block(reg_inputcounter) <= sreg_block(reg_inputcounter) + master_readdatavalid;
|
|
sreg_block(reg_outputcounter) <= sreg_block(reg_outputcounter) + soutb_ack;
|
|
|
|
--! Flags
|
|
|
|
|
|
case sm is
|
|
when SOURCE =>
|
|
--! ******************************************************************************************************************************************************
|
|
--! Flooding the pipeline ........
|
|
--! ******************************************************************************************************************************************************
|
|
if smaster_read='0' then
|
|
if sflood_condition = '1' then
|
|
--! Flow Control: Hay suficiente espacio en el buffer de salida y hay descargas pendientes por hacer
|
|
smaster_read <= '1';
|
|
master_address <= sreg_block(reg_fetchstart);
|
|
master_burstcount <= sflood_burstcount;
|
|
sdata_fetch_counter <= sdata_fetch_counter+sflood_burstcount-master_readdatavalid;
|
|
--! Context Saving:
|
|
sreg_block(reg_fetchstart) <= sreg_block(reg_fetchstart) + (sflood_burstcount&"00");
|
|
sreg_block(reg_ctrl)(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low) <= sreg_block(reg_ctrl)(reg_ctrl_nfetch_high downto reg_ctrl_nfetch_low) - sflood_burstcount;
|
|
else
|
|
--! Flow Control : Cambiar al estado SINK, porque o está muy llena la cola de salida o no hay descargas pendientes por realizar.
|
|
sm <= SINK;
|
|
end if;
|
|
else --master_read=1;
|
|
if master_waitrequest='0' then
|
|
--! Las direcciones de lectura están cargadas. Terminar la transferencia.
|
|
smaster_read <= '0';
|
|
end if;
|
|
end if;
|
|
when SINK =>
|
|
|
|
--! ******************************************************************************************************************************************************
|
|
--! Draining the pipeline ........
|
|
--! ******************************************************************************************************************************************************
|
|
if smaster_write='0' then
|
|
|
|
if sdrain_condition='1' then
|
|
--! Flow Control : Hay muchos datos aun en la cola de resultados Ó la cola de resultados está casí vacía y no hay datos transitando en el pipeline aritm&eetico.
|
|
smaster_write <= '1';
|
|
master_address <= sreg_block(reg_sinkstart);
|
|
master_burstcount <= sdrain_burstcount;
|
|
|
|
--!Context Saving
|
|
sreg_block(reg_sinkstart) <= sreg_block(reg_sinkstart) + (sdrain_burstcount&"00");
|
|
sburstcount_sink <= sdrain_burstcount-1;
|
|
else
|
|
--! Flow Control: Son muy pocos los datos que hay en el buffer de salida y existen aun datos transitando en el resto del pipe ir al estado SOURCE.
|
|
if sZeroTransit='1' then
|
|
|
|
--! Flow Control: Finalizada la instrucción, generar una interrupción e ir al estado IDLE.
|
|
sm <= IDLE;
|
|
sreg_block(reg_ctrl)(reg_ctrl_irq) <= '1';
|
|
sreg_block(reg_ctrl)(reg_ctrl_rom) <= '0';
|
|
sreg_block(reg_ctrl)(reg_ctrl_flags_dc downto reg_ctrl_flags_ae) <= sdrain_condition & sflood_condition & soutb_ae;
|
|
sreg_block(reg_ctrl)(reg_ctrl_flags_ap downto reg_ctrl_flags_wp) <= sload_add_pending & sfetch_data_pending & sparamload_pending & spipeline_pending & swrite_pending;
|
|
|
|
else
|
|
|
|
--! Flow Control: Cambiar a Source porque aun hay elementos transitando.
|
|
sm <= SOURCE;
|
|
end if;
|
|
|
|
end if;
|
|
else --!smaster_write=1
|
|
if master_waitrequest = '0' then
|
|
|
|
--! Descartar datos : revisar antes de este proceso secuencial la parte combinatoria (Data Dumpster).
|
|
|
|
|
|
if sburstcount_sink/=zero(mb downto 0) then
|
|
|
|
--! Datos pendientes por transmitir aun en el burst. Restar uno
|
|
sburstcount_sink <= sburstcount_sink-1;
|
|
else
|
|
|
|
--! No escribir mas. Finalizar la transmisión
|
|
smaster_write <= '0';
|
|
|
|
--! Si no hay transito de dato se con terminada la instrucción siempre que el estado de control de flujo esté sidera
|
|
if sZeroTransit='1' then
|
|
|
|
--! Flow Control: Finalizada la instrucción, generar una interrupción e ir al estado IDLE.
|
|
sm <= IDLE;
|
|
sreg_block(reg_ctrl)(reg_ctrl_irq) <= '1';
|
|
sreg_block(reg_ctrl)(reg_ctrl_rom) <= '0';
|
|
sreg_block(reg_ctrl)(reg_ctrl_flags_dc downto reg_ctrl_flags_ae) <= sdrain_condition & sflood_condition & soutb_ae;
|
|
sreg_block(reg_ctrl)(reg_ctrl_flags_ap downto reg_ctrl_flags_wp) <= sload_add_pending & sfetch_data_pending & sparamload_pending & spipeline_pending & swrite_pending;
|
|
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
when IDLE =>
|
|
--! ******************************************************************************************************************************************************
|
|
--! Programming the pipeline
|
|
--! ******************************************************************************************************************************************************
|
|
--! El registro de control en sus campos fetch e irq, es escribile solo cuando estamos en estado IDLE.
|
|
if sslave_write='1' then
|
|
case sslave_address is
|
|
when x"0" =>
|
|
--! Solo se permitira escribir en el registro de control si no hay una interrupción activa o si la hay solamente si se esta intentando desactivar la interrupci´n
|
|
if sreg_block(reg_ctrl)(reg_ctrl_irq)='0' or sslave_writedata(reg_ctrl_irq)='0' then
|
|
sreg_block(reg_ctrl)(reg_ctrl_irq downto reg_ctrl_nfetch_low) <= sslave_writedata(reg_ctrl_irq downto reg_ctrl_nfetch_low);
|
|
sreg_block(reg_ctrl)(reg_ctrl_flags_wp-1 downto reg_ctrl_cmb) <= sslave_writedata(reg_ctrl_flags_wp-1 downto reg_ctrl_cmb);
|
|
end if;
|
|
when x"6" => sreg_block(reg_outputcounter) <= sslave_writedata;
|
|
when x"7" => sreg_block(reg_inputcounter) <= sslave_writedata;
|
|
when x"8" => sreg_block(reg_fetchstart) <= sslave_writedata;
|
|
when x"9" => sreg_block(reg_sinkstart) <= sslave_writedata;
|
|
when others => null;
|
|
end case;
|
|
else
|
|
|
|
if sZeroTransit='0' then
|
|
|
|
|
|
--! Flow Control: Existe un número de descargas programadas por el sistema, comenzar a realizarlas.
|
|
--! Ir al estado Source.
|
|
sm <= SOURCE;
|
|
sreg_block(reg_ctrl)(reg_ctrl_rom) <= '1';
|
|
|
|
end if;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end process;
|
|
--! ******************************************************************************************************************************************************
|
|
--! FLOW CONTROL RTL CODE
|
|
--! ******************************************************************************************************************************************************
|
|
--! Colas de resultados y buffer de salida
|
|
--! ******************************************************************************************************************************************************
|
|
res:scfifo
|
|
generic map (lpm_numwords => 2**fd, lpm_showahead => "ON", lpm_width => 128, lpm_widthu => fd, overflow_checking => "ON", underflow_checking => "ON", use_eab => "ON")
|
|
port map (rdreq => sres_ack, aclr => '0', empty => sres_e, clock => clk, q => sres_q, wrreq => sres_w, data => sres_d);
|
|
output_buffer:scfifo
|
|
generic map (almost_empty_value => 2**mb,almost_full_value => (2**fd)-52, lpm_widthu => fd, lpm_numwords => 2**fd, lpm_showahead => "ON", lpm_width => 32, overflow_checking => "ON", underflow_checking => "ON", use_eab => "ON")
|
|
port map (empty => soutb_e, aclr => '0', clock => clk, rdreq => soutb_ack, wrreq => soutb_w, q => master_writedata, usedw => soutb_usedw, almost_full => soutb_af, almost_empty => soutb_ae, data => soutb_d);
|
|
--! ******************************************************************************************************************************************************
|
|
--! PROCESO DE CONTROL DE FLUJO ENTRE EL BUFFER DE RESULTADOS Y EL BUFFER DE SALIDA
|
|
--! ******************************************************************************************************************************************************
|
|
|
d => sd,
|
FLOW_CONTROL_OUTPUT_STAGE:
|
c => sc,
|
process (clk,rst,sres_e,sreg_block(reg_ctrl)(reg_ctrl_vt downto reg_ctrl_sc),sm,supload_chain,zero,ssync_chain_pending,sres_q,supload_start)
|
s => ss,
|
begin
|
|
|
sync_chain_0 => s_sync_chain_0,
|
|
|
|
qresult_q => sqresult_q,
|
--! Compute initial State.
|
qresult_sel => sqresult_sel,
|
|
qresult_rdec => sqresult_rdec,
|
|
qresult_w => sqresult_w,
|
|
qresult_d => sqresult_d,
|
|
|
|
dataread => sdataread,
|
--! Escribir en el output buffer.
|
|
soutb_w <= not(sres_e);
|
|
|
|
--! Control de lectura de la cola de resultados.
|
|
if sres_e='0' then
|
|
--!Hay datos en la cola de resultados.
|
|
if (supload_chain=VZ and sreg_block(reg_ctrl)(reg_ctrl_sc)='0') or supload_chain=SC then
|
|
--!Se transfiere el ultimo componente vectorial y no se estan cargando resultados escalares.
|
|
sres_ack <= '1';
|
|
end if;
|
|
else
|
|
sres_ack <= '0';
|
|
end if;
|
|
|
|
--! Decodificar que salida de la cola de resultados se conecta a la entrada del otput buffer
|
|
case supload_chain is
|
|
when VX =>
|
|
soutb_d <= sres_q ((wd*1)-1 downto wd*0);
|
|
when VY =>
|
|
soutb_d <= sres_q ((wd*2)-1 downto wd*1);
|
|
when VZ =>
|
|
soutb_d <= sres_q ((wd*3)-1 downto wd*2);
|
|
when SC =>
|
|
soutb_d <= sres_q ((wd*4)-1 downto wd*3);
|
|
end case;
|
|
|
|
|
|
case sreg_block(reg_ctrl)(reg_ctrl_vt downto reg_ctrl_sc) is
|
|
when "01" =>
|
|
supload_start <= SC;
|
|
when others =>
|
|
supload_start <= VX;
|
|
end case;
|
|
|
|
|
|
--! Máquina de estados para el width adaptation RES(128) -> OUTPUTBUFFER(32).
|
|
if rst=rstMasterValue then
|
|
supload_chain <= VX;
|
|
elsif clk'event and clk='1' then
|
|
case supload_chain is
|
|
when VX =>
|
|
if sres_e='1' then
|
|
supload_chain <= supload_start;
|
|
else
|
|
supload_chain <= VY;
|
|
end if;
|
|
when VY =>
|
|
supload_chain <= VZ;
|
|
when VZ =>
|
|
if sreg_block(reg_ctrl)(reg_ctrl_sc)='0' then
|
|
supload_chain <= VX;
|
|
else
|
|
supload_chain <= SC;
|
|
end if;
|
|
when SC =>
|
|
supload_chain <= supload_start;
|
|
end case;
|
|
end if;
|
|
|
|
|
|
end process;
|
|
--! ******************************************************************************************************************************************************
|
|
--! PROCESO DE CONTROL DE FLUJO ENTRE LA ENTRADA DESDE LA INTERCONEXI&OACUTE;N Y LOS PARAMETROS DE ENTRADA EN EL PIPELINE ARITMETICO
|
|
--! ******************************************************************************************************************************************************
|
|
FLOW_CONTROL_INPUT_STAGE:
|
|
process(clk,rst,master_readdatavalid,master_readdata,sreg_block(reg_ctrl)(reg_ctrl_d downto reg_ctrl_s),sslave_write,sslave_address)
|
|
begin
|
|
--! Está ocurriendo un evento de transición del estado TX al estado FETCH: Programar el enganche de parámetros que vienen de la interconexión.
|
|
--! Mirar como es la carga inicial. Si es Normalizacion o Magnitud (dcs=110) entonces cargar AXBX de lo contrario solo AX.
|
|
case sreg_block(reg_ctrl)(reg_ctrl_d downto reg_ctrl_s) is
|
|
when "110" | "100" => sdownload_start <= AXBX;
|
|
when others => sdownload_start <= AX;
|
|
end case;
|
|
if rst=rstMasterValue then
|
|
ssync_chain_1 <= '0';
|
|
sdownload_chain <= AX;
|
|
for i in reg_bz downto reg_ax loop
|
|
sreg_block(i) <= (others => '0');
|
|
end loop;
|
|
elsif clk'event and clk='1' then
|
|
ssync_chain_1 <= '0';
|
|
if master_readdatavalid='1' then
|
|
--! El dato en la interconexión es valido, se debe enganchar.
|
|
case sdownload_chain is
|
|
when AX | AXBX =>
|
|
--! Cargar el operando correspondiente al componente "X" del vector "A"
|
|
ssync_chain_1 <= '0';
|
|
sreg_block(reg_ax) <= master_readdata;
|
|
if sdownload_start = AXBX then
|
|
--! Operación Unaria por ejemplo magnitud de un vector
|
|
--! Escribir en el registro bx adicionalmente.
|
|
sreg_block(reg_bx) <= master_readdata;
|
|
--! El siguiente estado es cargar el componente "Y" de del operando a ejecutar.
|
|
sdownload_chain <= AYBY;
|
|
else
|
|
--! Operación de dos operandos. Por ejemplo Producto Cruz.
|
|
--! El siguiente estado es cargar el vector "Y" del operando "A".
|
|
sdownload_chain <= AY;
|
|
end if;
|
|
when AY | AYBY =>
|
|
sreg_block(reg_ay) <= master_readdata;
|
|
ssync_chain_1 <= '0';
|
|
if sdownload_chain = AYBY then
|
|
sreg_block(reg_by) <= master_readdata;
|
|
sdownload_chain <= AZBZ;
|
|
else
|
|
sdownload_chain <= AZ;
|
|
end if;
|
|
when AZ | AZBZ =>
|
|
sreg_block(reg_az) <= master_readdata;
|
|
if sdownload_chain=AZBZ then
|
|
ssync_chain_1 <= '1';
|
|
sreg_block(reg_bz) <= master_readdata;
|
|
sdownload_chain <= AXBX;
|
|
else
|
|
ssync_chain_1 <= '0';
|
|
sdownload_chain <= BX;
|
|
end if;
|
|
when BX =>
|
|
ssync_chain_1 <= '0';
|
|
sreg_block(reg_bx) <= master_readdata;
|
|
sdownload_chain <= BY;
|
|
when BY =>
|
|
ssync_chain_1 <= '0';
|
|
sreg_block(reg_by) <= master_readdata;
|
|
sdownload_chain <= BZ;
|
|
when BZ =>
|
|
sreg_block(reg_bz) <= master_readdata;
|
|
ssync_chain_1 <= '1';
|
|
if sreg_block(reg_ctrl)(reg_ctrl_cmb)='1' then
|
|
sdownload_chain <= BX;
|
|
else
|
|
sdownload_chain <= AX;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
|
|
if srestart_chain='1' then
|
|
sdownload_chain <= sdownload_start;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
end process;
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! AVALON MEMORY MAPPED MASTER FINISHED
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! AVALON MEMORY MAPPED SLAVE BEGINS => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => =>
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! Master Slave Process: Proceso para la escritura y lectura de registros desde el NIOS II.
|
|
low_register_bank:
|
|
process (clk,rst,sreg_block)
|
|
begin
|
|
if rst=rstMasterValue then
|
|
for i in reg_scratch00 downto reg_vz loop
|
|
sreg_block(i) <= (others => '0');
|
|
end loop;
|
|
|
|
slave_readdata <= (others => '0');
|
|
sslave_address <= (others => '0');
|
|
sslave_writedata <= (others => '0');
|
|
sslave_write <= '0';
|
|
sslave_read <= '0';
|
|
elsif clk'event and clk='1' then
|
|
|
|
|
|
sslave_address <= slave_address;
|
|
sslave_write <= slave_write;
|
|
sslave_read <= slave_read;
|
|
sslave_writedata <= slave_writedata;
|
|
for i in reg_scratch00 downto reg_vz loop
|
|
if sslave_address=i then
|
|
if sslave_write='1' then
|
|
sreg_block(i) <= sslave_writedata;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
for i in 15 downto 0 loop
|
|
if sslave_address=i then
|
|
if sslave_read='1' then
|
|
slave_readdata <= sreg_block(i);
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end process;
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
--! AVALON MEMORY MAPPED SLAVE FINISHED
|
|
--! *************************************************************************************************************************************************************************************************************************************************************
|
|
|
prd32blki => sprd32blki,
|
|
add32blki => sadd32blki,
|
|
|
|
dataout => writedata_master
|
|
|
|
|
|
);
|
|
--!TBXINSTANCEEND
|
|
--! Instanciar el bloque aritmético.
|
|
--!TBXINSTANCESTART
|
|
arithmetic_block : arithblock
|
|
port map (
|
|
clk => clk,
|
|
rst => rst,
|
|
sign => ss,
|
|
prd32blki => sprd32blki,
|
|
add32blki => sadd32blki,
|
|
add32blko => sadd32blko,
|
|
prd32blko => sprd32blko,
|
|
sq32o => ssq32o,
|
|
inv32o => sinv32o
|
|
);
|
|
--!TBXINSTANCEEND
|
|
|
|
--!Instanciar la maquina de estados
|
|
|
|
|
|
end architecture;
|
end architecture;
|
|
|
No newline at end of file
|
No newline at end of file
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------
|
|
--! Control Register (cr) BASE_ADDRESS + 0x0 |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------
|
|
--! Bit No. | Nombre | Descripción |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------
|
|
--! 0 | cmb (rw) | 1: La operación es combinatoria, por lo tanto solo se cargan vectores en el operando B. |
|
|
--! | | 0: La operación no es combinatoria, se cargan vectores en los operandos A y B. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! | | Configuración del Datapath, Interconexión del Pipeline Aritmético y Cadena de Carga |
|
|
--! | | Dependiendo del valor de estos 3 bits se configura la operación a ejecutar. |
|
|
--! | | |
|
|
--! [3:1] | dcs (rw) | 011: Producto Cruz |
|
|
--! | | 000: Suma Vectorial |
|
|
--! | | 001: Resta Vectorial |
|
|
--! | | 110: Normalización Vectorial y cálculo de Magnitud Vectorial |
|
|
--! | | 100: Producto Punto |
|
|
--! | | 111: Producto Simple |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! | | En el caso de que dcs sea 110 (Normalización y Magnitud Vectorial) este par de bits indica que resultados |
|
|
--! | | escribir. Si dcs tiene un valor diferente a 110 se ignora este campo. |
|
|
--! | | |
|
|
--! [5:4] | vtsc (rw) | 00: Solo leer los resultados vectoriales. |
|
|
--! | | 01: Solo leer los resultados escalares. |
|
|
--! | | 10: Solo leer los resultados vectoriales. |
|
|
--! | | 11: Leer los resultados escalares y vectoriales. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! 14 | rlsc (rw) | 1: El sistema está configurado para resetear la recarga sincronizada de parámetros una vez |
|
|
--! | | concluya la instrucción |
|
|
--! | | |
|
|
--! | | 0: El sistema está configurado para no resetear la cadena de sincronización de carga. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! 15 | rom (r) | 1: Los registros solo se pueden leer no se pueden escribir. |
|
|
--! | | 0: Los registros se pueden leer y escribir. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! [30:16] | nfetch(rw)| Cantidad de direcciones a cargar en la interconexón para realizar la posterior descarga de datos de la |
|
|
--! | | memoria al RayTrac.
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! 31 | irq | 1: Evento de interrupción. El usuario debe hacer clear de este bit para dar la interrupci&o;n por |
|
|
--! | | por atendida. Este bit se pone en uno cuando el sistema pasa de estado TX a FETCH o FETCH a TX. |
|
|
--! | | |
|
|
--! | | 0: El RayTrac se encuentra en operación Normal. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------
|
|
--! Start Parameter Address (psadd) BASE_ADDRESS + 0x4 |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! [31:0] | sadd (rw) | Dirección de memoria donde se encuentra el primer parámetro de entrada. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! Start Result Address (rsadd) BASE_ADDRESS + 0x8 |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! [31:0] | rsadd (rw)| Dirección de memoria donde se encuentra el primer parámetro de entrada. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! Scratch Register (screg) BASE_ADDRESS + 0x1C |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
--! [31:0] | screg (rw)| Dirección de memoria donde se pueden escribir y leer valores de 32 bits. |
|
|
--!---------|-----------|-------------------------------------------------------------------------------------------------------------------|
|
|
|
No newline at end of file
|
No newline at end of file
|