URL
https://opencores.org/ocsvn/astron_wb_fft/astron_wb_fft/trunk
Subversion Repositories astron_wb_fft
[/] [astron_wb_fft/] [trunk/] [fft_wide_unit_control.vhd] - Rev 3
Go to most recent revision | Compare with Previous | Blame | View Log
------------------------------------------------------------------------------- -- -- Copyright 2020 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- ------------------------------------------------------------------------------- -- 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_pkg_lib, common_ram_lib, common_fifo_lib, dp_pkg_lib; use IEEE.std_logic_1164.ALL; use IEEE.numeric_std.ALL; use common_pkg_lib.common_pkg.ALL; use common_ram_lib.common_ram_pkg.ALL; use dp_pkg_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_fifo_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_fifo_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_fifo_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_fifo_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;
Go to most recent revision | Compare with Previous | Blame | View Log