Select Git revision
SKAMaster_test.py
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
fft_wide_unit_control.vhd 12.62 KiB
-------------------------------------------------------------------------------
--
-- Copyright (C) 2009
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program 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.
--
-- This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Purpose: Composition of the SOSI output streams for the fft_wide_unit.
--
-- Description: This unit monitors the in_val signal. Based on the assertion of the
-- in_val signal it will compose the output sosi streams. The packet-
-- size equals g_fft.nof_points/g_fft.wb_factor.
-- Both the incoming bsn and err fields are written to a fifo. When
-- the output is composed the bsn and err field will be read from the
-- fifo's.
-- Incoming syncs will be detected and the bsn that accompanies the sync
-- will be stored. When the bsn that is read from the fifo is the same
-- as the stored one, the sync will be asserted to the output.
--
-- Remarks: .The sync interval must be larger that the total amount of pipeline
-- stages in the FFT. In other words: the fft_wide_unit_control unit
-- is not capable of handling more than one sync pulse at a time.
--
--
library IEEE, common_lib, dp_lib;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
use common_lib.common_pkg.ALL;
use common_lib.common_mem_pkg.ALL;
use dp_lib.dp_stream_pkg.ALL;
use work.fft_pkg.ALL;
entity fft_wide_unit_control is
generic (
g_fft : t_fft := c_fft;
g_nof_ffts : natural := 1
);
port (
rst : in std_logic := '0';
clk : in std_logic;
in_re_arr : in t_fft_slv_arr(g_nof_ffts*g_fft.wb_factor-1 downto 0);
in_im_arr : in t_fft_slv_arr(g_nof_ffts*g_fft.wb_factor-1 downto 0);
in_val : in std_logic;
ctrl_sosi : in t_dp_sosi; -- Inputrecord for tapping off the sync, bsn and err.
out_sosi_arr : out t_dp_sosi_arr(g_nof_ffts*g_fft.wb_factor-1 downto 0) -- Streaming output interface
);
end fft_wide_unit_control;
architecture rtl of fft_wide_unit_control is
constant c_pipe_data : natural := 3; -- Delay depth for the data
constant c_pipe_ctrl : natural := c_pipe_data-1; -- Delay depth for the control signals
constant c_packet_size : natural := (2**g_fft.nof_chan)*g_fft.nof_points/g_fft.wb_factor; -- Definition of the packet size
constant c_ctrl_fifo_depth : natural := 16; -- Depth of the bsn and err fifo.
type t_fft_slv_arr2 is array (integer range <>) of t_fft_slv_arr(g_nof_ffts*g_fft.wb_factor-1 downto 0); type state_type is (s_idle, s_run, s_hold);
type reg_type is record
out_sosi_arr : t_dp_sosi_arr(g_nof_ffts*g_fft.wb_factor-1 downto 0); -- Register that holds the streaming interface
in_re_arr2_dly : t_fft_slv_arr2(c_pipe_data -1 downto 0); -- Input registers for the real data
in_im_arr2_dly : t_fft_slv_arr2(c_pipe_data -1 downto 0); -- Input registers for the imag data
val_dly : std_logic_vector(c_pipe_ctrl -1 downto 0); -- Delay-register for the valid signal
sop_dly : std_logic_vector(c_pipe_ctrl -1 downto 0); -- Delay-register for the sop signal
eop_dly : std_logic_vector(c_pipe_ctrl -1 downto 0); -- Delay-register for the eop signal
sync_detected : std_logic; -- Register used to detect and pass the sync pulse.
packet_cnt : integer; -- Counter to create the packets.
state : state_type; -- The state machine.
end record;
signal r, rin : reg_type;
signal bsn : std_logic_vector(c_dp_stream_bsn_w -1 downto 0);
signal sync_bsn : std_logic_vector(c_dp_stream_bsn_w -1 downto 0);
signal err : std_logic_vector(c_dp_stream_error_w-1 downto 0);
signal rd_req : std_logic;
signal rd_req_i : std_logic;
signal rd_dat_i : std_logic_vector(c_dp_stream_bsn_w -1 downto 0);
signal rd_val_i : std_logic;
begin
---------------------------------------------------------------
-- INPUT FIFO FOR BSN
---------------------------------------------------------------
u_bsn_fifo : entity common_lib.common_fifo_sc
generic map (
g_use_lut => TRUE, -- Make this FIFO in logic, since it's only 4 words deep.
g_reset => FALSE,
g_init => FALSE,
g_dat_w => c_dp_stream_bsn_w,
g_nof_words => c_ctrl_fifo_depth
)
port map (
rst => rst,
clk => clk,
wr_dat => ctrl_sosi.bsn,
wr_req => ctrl_sosi.sop,
wr_ful => open ,
rd_dat => bsn,
rd_req => r.sop_dly(0),
rd_emp => open ,
rd_val => open ,
usedw => open
);
---------------------------------------------------------------
-- INPUT FIFO FOR ERR
---------------------------------------------------------------
u_error_fifo : entity common_lib.common_fifo_sc
generic map (
g_use_lut => TRUE, -- Make this FIFO in logic, since it's only 4 words deep.
g_reset => FALSE,
g_init => FALSE,
g_dat_w => c_dp_stream_error_w,
g_nof_words => c_ctrl_fifo_depth
)
port map (
rst => rst,
clk => clk,
wr_dat => ctrl_sosi.err,
wr_req => ctrl_sosi.sop,
wr_ful => open ,
rd_dat => err,
rd_req => r.sop_dly(1),
rd_emp => open ,
rd_val => open , usedw => open
);
---------------------------------------------------------------
-- FIFO FOR SYNC-BSN
---------------------------------------------------------------
u_sync_bsn_fifo : entity common_lib.common_fifo_sc
generic map (
g_use_lut => TRUE, -- Make this FIFO in logic, since it's only 4 words deep.
g_reset => FALSE,
g_init => FALSE,
g_dat_w => c_dp_stream_bsn_w,
g_nof_words => 2
)
port map (
rst => rst,
clk => clk,
wr_dat => ctrl_sosi.bsn,
wr_req => ctrl_sosi.sync,
wr_ful => open ,
rd_dat => rd_dat_i,
rd_req => rd_req_i,
rd_emp => open,
rd_val => rd_val_i,
usedw => open
);
---------------------------------------------------------------
-- CREATE READ-AHEAD FIFO INTERFACE FOR SYNC-BSN
---------------------------------------------------------------
u_fifo_adapter : entity common_lib.common_fifo_rd
generic map (
g_dat_w => c_dp_stream_bsn_w
)
port map(
rst => rst,
clk => clk,
-- ST sink: RL = 1
fifo_req => rd_req_i,
fifo_dat => rd_dat_i,
fifo_val => rd_val_i,
-- ST source: RL = 0
rd_req => rd_req,
rd_dat => sync_bsn,
rd_val => open
);
rd_req <= r.out_sosi_arr(0).sync; -- (r.sync_detected and not(rd_emp)) or r.rd_first;
---------------------------------------------------------------
-- PROCESS THAT COMPOSES THE SOSI OUTPUT ARRAYS
---------------------------------------------------------------
comb : process(r, rst, ctrl_sosi, in_re_arr, in_im_arr, in_val, sync_bsn, bsn, err)
variable v : reg_type;
begin
v := r;
v.val_dly(0) := '0'; -- Some defaults, before entering the state machine.
v.sop_dly(0) := '0';
v.eop_dly(0) := '0';
for I in g_nof_ffts*g_fft.wb_factor-1 downto 0 loop
v.out_sosi_arr(I).sync := '0';
end loop;
v.in_re_arr2_dly(0) := in_re_arr; -- Latch the data into the input registers.
v.in_im_arr2_dly(0) := in_im_arr; -- Latch the data into the input registers.
v.in_re_arr2_dly(c_pipe_data-1 downto 1) := r.in_re_arr2_dly(c_pipe_data-2 downto 0); -- Shift the delay registers v.in_im_arr2_dly(c_pipe_data-1 downto 1) := r.in_im_arr2_dly(c_pipe_data-2 downto 0); -- Shift the delay registers
v.val_dly(c_pipe_ctrl-1 downto 1) := r.val_dly(c_pipe_ctrl-2 downto 0); -- Shift the delay registers
v.sop_dly(c_pipe_ctrl-1 downto 1) := r.sop_dly(c_pipe_ctrl-2 downto 0); -- Shift the delay registers
v.eop_dly(c_pipe_ctrl-1 downto 1) := r.eop_dly(c_pipe_ctrl-2 downto 0); -- Shift the delay registers
for I in g_nof_ffts*g_fft.wb_factor-1 downto 0 loop
v.out_sosi_arr(I).sop := r.sop_dly(c_pipe_ctrl-1); -- Assign the output of the shiftregisters to the "real" signals
v.out_sosi_arr(I).eop := r.eop_dly(c_pipe_ctrl-1); -- Assign the output of the shiftregisters to the "real" signals
v.out_sosi_arr(I).valid := r.val_dly(c_pipe_ctrl-1); -- Assign the output of the shiftregisters to the "real" signals
v.out_sosi_arr(I).bsn := bsn; -- The bsn is read from the FIFO
v.out_sosi_arr(I).err := err; -- The err is read from the FIFO
v.out_sosi_arr(I).re := RESIZE_SVEC(r.in_re_arr2_dly(c_pipe_data-1)(I), c_dp_stream_dsp_data_w); -- Data input is latched-in
v.out_sosi_arr(I).im := RESIZE_SVEC(r.in_im_arr2_dly(c_pipe_data-1)(I), c_dp_stream_dsp_data_w); -- Data input is latched-in
end loop;
if(ctrl_sosi.sync = '1') then -- Check which bsn accompanies the sync
v.sync_detected := '1';
end if;
if(sync_bsn = bsn and r.sop_dly(1) = '1' and r.sync_detected = '1') then -- When the next bsn equals the stored bsn
for I in g_fft.wb_factor-1 downto 0 loop -- a sync pulse will be generated that
v.out_sosi_arr(I).sync := '1'; -- preceeds the sop
end loop;
v.sync_detected := '0';
end if;
case r.state is
when s_idle =>
if(in_val = '1') then -- Wait for the first data to arrive
v.packet_cnt := 0; -- Reset the packet counter
v.state := s_run;
end if;
when s_run =>
v.val_dly(0) := '1'; -- Assert the valid signal (Stream starts)
v.packet_cnt := r.packet_cnt + 1; -- Increment the packet-counter when in s_run-state
if(r.packet_cnt = 0) then -- First sample marks
v.sop_dly(0) :='1'; -- the start of a packet
elsif(r.packet_cnt = c_packet_size-1) then -- Last address marks
v.eop_dly(0) :='1'; -- the end of a packet
v.packet_cnt := 0; -- Reset the counter
end if;
if(in_val = '0') then -- If there is no more data:
v.state := s_hold; -- go wait in the s_hold state
end if;
when s_hold =>
if(in_val = '1') then -- Wait until new valid data arrives
v.state := s_run;
end if;
when others =>
v.state := s_idle;
end case;
if(rst = '1') then
v.out_sosi_arr := (others => c_dp_sosi_rst);
v.val_dly := (others => '0');
v.sop_dly := (others => '0');
v.eop_dly := (others => '0');
v.sync_detected := '0';
v.packet_cnt := 0;
v.state := s_idle;
end if;
rin <= v;
end process comb;
regs : process(clk)
begin
if rising_edge(clk) then
r <= rin;
end if;
end process;
-- Connect to the outside world
gen_output : for I in g_nof_ffts*g_fft.wb_factor-1 downto 0 generate
out_sosi_arr(I) <= r.out_sosi_arr(I);
end generate;
end rtl;