Skip to content
Snippets Groups Projects
Commit 98f207ac authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Added g_big_endian_wb_in/out. Improved index order description.

parent f397e7fd
No related branches found
No related tags found
No related merge requests found
...@@ -18,41 +18,77 @@ ...@@ -18,41 +18,77 @@
-- along with this program. If not, see <http://www.gnu.org/licenses/>. -- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- --
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Purpose: Performing a poly phase prefilter (PPF) function on one or multiple wideband data stream. -- Purpose: Performing a poly phase prefilter (PPF) function on one or more
-- wideband data stream.
-- --
-- Description: -- Description:
-- The poly phase prefilter function is applied on multiple inputs. The -- The poly phase prefilter function is applied on multiple inputs. In
-- incoming data must be divided over the inputs as shown in the -- array notation:
-- following example for nof_streams=1 and wb_factor is 4:
-- --
-- array stream wb time index -- parallel serial type
-- index index index -- in_dat_arr [wb_factor][nof_streams] [t][nof_channels] int
-- 3 0 0 : t0, t4, t8, t12, t16... -- out_dat_arr [wb_factor][nof_streams] [t][nof_channels] int
-- 2 0 1 : t1, t5, t9, t13, t17... --
-- 1 0 2 : t2, t6, t10, t14, t18... -- If g_big_endian_wb_*=true then the time t to wb_factor P mapping for the
-- 0 0 3 : t3, t7, t11, t15, t19... -- fil_ppf_wide is t[0,1,2,3] = P[3,2,1,0], else when it is false then the
-- mapping is t[3,2,1,0] = P[3,2,1,0]. The mapping can be selected
-- independently for the in_dat_arr and the out_dat_arr.
--
-- The incoming data must be divided over the inputs as shown in the
-- following example for nof_streams=1 and wb_factor is 4. The array
-- index I runs from [wb_factor*nof_streams-1:0].
--
-- array wb stream time index when g_big_endian_wb_*=true)
-- index index index
-- I P S t
-- 3 3 0 : 0, 4, 8, 12, 16, ...
-- 2 2 0 : 1, 5, 9, 13, 17, ...
-- 1 1 0 : 2, 6, 10, 14, 18, ...
-- 0 0 0 : 3, 7, 11, 15, 19, ...
-- ^
-- big endian
-- --
-- Every array input will be filtered by a fil_ppf_single instance. It is -- Every array input will be filtered by a fil_ppf_single instance. It is
-- also possible to offer multiple wideband input streams. Those wide -- also possible to offer multiple wideband input streams. Those wide
-- band input streams will share the filter coefficients. For a system with -- band input streams will share the filter coefficients. For a system with
-- nof_streams=2 and wb_factor=4 the array inputs become (s0t0 means wide -- nof_streams=2 and wb_factor=4 the array inputs become:
-- band stream 0, timestamp 0): --
-- array wb stream time index when g_big_endian_wb_*=true)
-- index index index
-- I P S t
-- 7 3 1 : 0, 4, 8, 12, 16, ...
-- 6 3 0 : 0, 4, 8, 12, 16, ...
-- 5 2 1 : 1, 5, 9, 13, 17, ...
-- 4 2 0 : 1, 5, 9, 13, 17, ...
-- 3 1 1 : 2, 6, 10, 14, 18, ...
-- 2 1 0 : 2, 6, 10, 14, 18, ...
-- 1 0 1 : 3, 7, 11, 15, 19, ...
-- 0 0 0 : 3, 7, 11, 15, 19, ...
-- ^
-- big endian
-- --
-- array stream wb time index -- Note that I, P and S all increment in the same direction and t increments
-- index index index -- in the opposite direction of P. This is the g_big_endian_wb_in=true and
-- 7 0 0 : s0t0, s0t4, s0t8, s0t12, s0t16... -- g_big_endian_wb_out=true format for the in_dat_arr and out_dat_arr.
-- 6 1 0 : s1t0, s1t4, s1t8, s1t12, s1t16...
-- 5 0 1 : s0t1, s0t5, s0t9, s0t13, s0t17...
-- 4 1 1 : s1t1, s1t5, s1t9, s1t13, s1t17...
-- 3 0 2 : s0t2, s0t6, s0t10, s0t14, s0t18...
-- 2 1 2 : s1t2, s1t6, s1t10, s1t14, s1t18...
-- 1 0 3 : s0t3, s0t7, s0t11, s0t15, s0t19...
-- 0 1 3 : s1t3, s1t7, s1t11, s1t15, s1t19...
-- --
-- For fil_ppf_wide with wb_factor > 1 the array index runs from -- If g_big_endian_wb_in=false and g_big_endian_wb_out=false for little endian
-- [wb_factor*nof_streams-1:0]. However per stream the wb_factor index -- format, then the time t increments in the same direction as P, for both
-- needs to run in big endian order from [0:wb_factor-1], so this needs to -- in_dat_arr and out_dat_arr, so then I, P and S all increment in the same
-- be accounted for when connecting wide band streams to fil_ppf_wide. -- direction:
--
-- array wb stream time index when g_big_endian_wb_*=false
-- index index index
-- I P S t
-- 7 3 1 : 3, 7, 11, 15, 19, ...
-- 6 3 0 : 3, 7, 11, 15, 19, ...
-- 5 2 1 : 2, 6, 10, 14, 18, ...
-- 4 2 0 : 2, 6, 10, 14, 18, ...
-- 3 1 1 : 1, 5, 9, 13, 17, ...
-- 2 1 0 : 1, 5, 9, 13, 17, ...
-- 1 0 1 : 0, 4, 8, 12, 16, ...
-- 0 0 0 : 0, 4, 8, 12, 16, ...
-- ^
-- little endian
-- --
-- With wb_factor > 1 and nof_streams > 1 the streams in in_dat_arr and -- With wb_factor > 1 and nof_streams > 1 the streams in in_dat_arr and
-- out_dat_arr are looped first and then the wb_factor is looped. This -- out_dat_arr are looped first and then the wb_factor is looped. This
...@@ -77,6 +113,8 @@ use work.fil_pkg.ALL; ...@@ -77,6 +113,8 @@ use work.fil_pkg.ALL;
entity fil_ppf_wide is entity fil_ppf_wide is
generic ( generic (
g_big_endian_wb_in : boolean := true;
g_big_endian_wb_out : boolean := true;
g_fil_ppf : t_fil_ppf := c_fil_ppf; g_fil_ppf : t_fil_ppf := c_fil_ppf;
g_fil_ppf_pipeline : t_fil_ppf_pipeline := c_fil_ppf_pipeline; g_fil_ppf_pipeline : t_fil_ppf_pipeline := c_fil_ppf_pipeline;
g_file_index_arr : t_nat_natural_arr := array_init(0, 128, 1); -- default use the instance index as file index 0, 1, 2, 3, 4 ... g_file_index_arr : t_nat_natural_arr := array_init(0, 128, 1); -- default use the instance index as file index 0, 1, 2, 3, 4 ...
...@@ -100,8 +138,9 @@ architecture rtl of fil_ppf_wide is ...@@ -100,8 +138,9 @@ architecture rtl of fil_ppf_wide is
type t_fil_ppf_arr is array(integer range <> ) of t_fil_ppf; -- An array of t_fil_ppf's generics. type t_fil_ppf_arr is array(integer range <> ) of t_fil_ppf; -- An array of t_fil_ppf's generics.
type t_nat_natural_arr2 is array(integer range <> ) of t_nat_natural_arr(127 downto 0); -- An array of arrays, used to point to the right .mif files for the coefficients type t_nat_natural_arr2 is array(integer range <> ) of t_nat_natural_arr(127 downto 0); -- An array of arrays, used to point to the right .mif files for the coefficients
type t_out_arr is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.out_dat_w -1 downto 0);
type t_in_arr is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.in_dat_w -1 downto 0); type t_streams_in_arr is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.in_dat_w -1 downto 0);
type t_streams_out_arr is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.out_dat_w -1 downto 0);
---------------------------------------------------------- ----------------------------------------------------------
-- This function creates an array of t_fil_ppf generics -- This function creates an array of t_fil_ppf generics
...@@ -115,22 +154,22 @@ architecture rtl of fil_ppf_wide is ...@@ -115,22 +154,22 @@ architecture rtl of fil_ppf_wide is
variable v_nof_bands : natural := input.nof_bands/input.wb_factor; -- The nof_bands for the single channel poly phase filters variable v_nof_bands : natural := input.nof_bands/input.wb_factor; -- The nof_bands for the single channel poly phase filters
variable v_return : t_fil_ppf_arr(input.wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values variable v_return : t_fil_ppf_arr(input.wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values
begin begin
for I in 0 to input.wb_factor-1 loop for P in 0 to input.wb_factor-1 loop
v_return(I).nof_bands := v_nof_bands; -- The new number of bands v_return(P).nof_bands := v_nof_bands; -- The new number of bands
end loop; end loop;
return v_return; return v_return;
end; end;
---------------------------------------------------------- ----------------------------------------------------------
-- Function that divids the input file index array into -- Function that divides the input file index array into
-- "wb_factor" new file index arrays. -- "wb_factor" new file index arrays.
---------------------------------------------------------- ----------------------------------------------------------
function func_create_file_index_array(input: t_nat_natural_arr; wb_factor: natural; nof_taps: natural) return t_nat_natural_arr2 is function func_create_file_index_array(input: t_nat_natural_arr; wb_factor: natural; nof_taps: natural) return t_nat_natural_arr2 is
variable v_return : t_nat_natural_arr2(wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values variable v_return : t_nat_natural_arr2(wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values
begin begin
for I in 0 to wb_factor-1 loop for P in 0 to wb_factor-1 loop
for J in 0 to nof_taps-1 loop for T in 0 to nof_taps-1 loop
v_return(I)(J) := input(I*nof_taps+J); v_return(P)(T) := input(P*nof_taps+T);
end loop; end loop;
end loop; end loop;
return v_return; return v_return;
...@@ -141,11 +180,12 @@ architecture rtl of fil_ppf_wide is ...@@ -141,11 +180,12 @@ architecture rtl of fil_ppf_wide is
constant c_mem_addr_w : natural := ceil_log2(g_fil_ppf.nof_bands * g_fil_ppf.nof_taps / g_fil_ppf.wb_factor); constant c_mem_addr_w : natural := ceil_log2(g_fil_ppf.nof_bands * g_fil_ppf.nof_taps / g_fil_ppf.wb_factor);
signal ram_coefs_mosi_arr : t_mem_mosi_arr(g_fil_ppf.wb_factor-1 downto 0); signal ram_coefs_mosi_arr : t_mem_mosi_arr(g_fil_ppf.wb_factor-1 downto 0);
signal ram_coefs_miso_arr : t_mem_miso_arr(g_fil_ppf.wb_factor-1 downto 0) := (others => c_mem_miso_rst); signal ram_coefs_miso_arr : t_mem_miso_arr(g_fil_ppf.wb_factor-1 downto 0) := (others => c_mem_miso_rst);
signal out_val_i : std_logic_vector(g_fil_ppf.wb_factor-1 downto 0);
signal out_arr_i : t_out_arr(g_fil_ppf.wb_factor-1 downto 0); signal streams_in_arr : t_streams_in_arr( g_fil_ppf.wb_factor-1 downto 0);
signal in_dat_vect_arr : t_in_arr(g_fil_ppf.wb_factor-1 downto 0); signal streams_out_arr : t_streams_out_arr(g_fil_ppf.wb_factor-1 downto 0);
signal streams_out_val_arr : std_logic_vector( g_fil_ppf.wb_factor-1 downto 0);
begin begin
--------------------------------------------------------------- ---------------------------------------------------------------
...@@ -165,22 +205,30 @@ begin ...@@ -165,22 +205,30 @@ begin
miso_arr => ram_coefs_miso_arr miso_arr => ram_coefs_miso_arr
); );
gen_in_vect_wb : for I in 0 to g_fil_ppf.wb_factor-1 generate p_wire_input : process(in_dat_arr)
gen_in_vect_streams : for J in 0 to g_fil_ppf.nof_streams-1 generate variable vP : natural;
--in_dat_vect_arr(I)((J+1)*g_fil_ppf.in_dat_w-1 downto J*g_fil_ppf.in_dat_w) <= in_dat_arr(J*g_fil_ppf.wb_factor+I)(g_fil_ppf.in_dat_w-1 downto 0); begin
in_dat_vect_arr(I)((J+1)*g_fil_ppf.in_dat_w-1 downto J*g_fil_ppf.in_dat_w) <= in_dat_arr(I*g_fil_ppf.nof_streams+J)(g_fil_ppf.in_dat_w-1 downto 0); for P in 0 to g_fil_ppf.wb_factor-1 loop
end generate; if g_big_endian_wb_in=true then
end generate; vP := P; -- big endian time [0,1,2,3] to P [3,2,1,0] index mapping
else
vP := g_fil_ppf.wb_factor-1-P; -- little endian time [0,1,2,3] to P [0,1,2,3] index mapping
end if;
for S in 0 to g_fil_ppf.nof_streams-1 loop
streams_in_arr(vP)((S+1)*g_fil_ppf.in_dat_w-1 downto S*g_fil_ppf.in_dat_w) <= in_dat_arr(P*g_fil_ppf.nof_streams+S)(g_fil_ppf.in_dat_w-1 downto 0);
end loop;
end loop;
end process;
--------------------------------------------------------------- ---------------------------------------------------------------
-- INSTANTIATE MULTIPLE SINGLE CHANNEL POLY PHASE FILTERS -- INSTANTIATE MULTIPLE SINGLE CHANNEL POLY PHASE FILTERS
--------------------------------------------------------------- ---------------------------------------------------------------
gen_ppf_singles : for I in 0 to g_fil_ppf.wb_factor-1 generate gen_fil_ppf_singles : for P in 0 to g_fil_ppf.wb_factor-1 generate
u_single_filter : entity work.fil_ppf_single u_fil_ppf_single : entity work.fil_ppf_single
generic map ( generic map (
g_fil_ppf => c_fil_ppf_arr(I), g_fil_ppf => c_fil_ppf_arr(P),
g_fil_ppf_pipeline => g_fil_ppf_pipeline, g_fil_ppf_pipeline => g_fil_ppf_pipeline,
g_file_index_arr => c_file_index_arr2(I), g_file_index_arr => c_file_index_arr2(P),
g_coefs_file_prefix => g_coefs_file_prefix g_coefs_file_prefix => g_coefs_file_prefix
) )
port map ( port map (
...@@ -188,18 +236,30 @@ begin ...@@ -188,18 +236,30 @@ begin
dp_rst => dp_rst, dp_rst => dp_rst,
mm_clk => mm_clk, mm_clk => mm_clk,
mm_rst => mm_rst, mm_rst => mm_rst,
ram_coefs_mosi => ram_coefs_mosi_arr(I), ram_coefs_mosi => ram_coefs_mosi_arr(P),
ram_coefs_miso => ram_coefs_miso_arr(I), ram_coefs_miso => ram_coefs_miso_arr(P),
in_dat => in_dat_vect_arr(I), in_dat => streams_in_arr(P),
in_val => in_val, in_val => in_val,
out_dat => out_arr_i(I), out_dat => streams_out_arr(P),
out_val => out_val_i(I) out_val => streams_out_val_arr(P)
); );
gen_in_vect_streams : for J in 0 to g_fil_ppf.nof_streams-1 generate
out_dat_arr(I*g_fil_ppf.nof_streams+J) <= RESIZE_SVEC(out_arr_i(I)((J+1)*g_fil_ppf.out_dat_w-1 downto J*g_fil_ppf.out_dat_w), out_dat_arr(I)'LENGTH);
end generate;
end generate; end generate;
out_val <= out_val_i(0); p_wire_output : process(streams_out_arr)
variable vP : natural;
begin
for P in 0 to g_fil_ppf.wb_factor-1 loop
if g_big_endian_wb_in=true then
vP := P; -- big endian time [0,1,2,3] to P [3,2,1,0] index mapping
else
vP := g_fil_ppf.wb_factor-1-P; -- little endian time [0,1,2,3] to P [0,1,2,3] index mapping
end if;
for S in 0 to g_fil_ppf.nof_streams-1 loop
out_dat_arr(vP*g_fil_ppf.nof_streams+S) <= RESIZE_SVEC_32(streams_out_arr(P)((S+1)*g_fil_ppf.out_dat_w-1 downto S*g_fil_ppf.out_dat_w));
end loop;
end loop;
end process;
out_val <= streams_out_val_arr(0);
end rtl; end rtl;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment