Forum Discussion
cjak
New Contributor
1 hour ago p_filter_fsm : process (clk) is
begin
if rising_edge(clk) then
if (rst = '1') then
coef_addr_cnt <= i_config_filterlength_reg(coef_addr_cnt'range) - 1;
decimation_cnt <= (others => '0');
accRAM_addr_in <= i_config_q_factor_reg(accRAM_addr_in'range) - 1;
prev_accRAM_addr_in <= i_config_q_factor_reg(accRAM_addr_in'range) - 1;
accRAM_addr_out <= i_config_q_factor_reg(accRAM_addr_out'range) - 1;
prev_accRAM_addr_out <= i_config_q_factor_reg(accRAM_addr_out'range) - 1;
run_filter_cnt <= (others => '0');
we_accRAM <= '0';
accRAM_Re_out_add <= (others => '0');
accRAM_Im_out_add <= (others => '0');
filtered_accRAM_addr_out <= (others => '0');
o_filtered_sample.tvalid <= '0';
o_filtered_sample.tlast <= '0';
state_filter <= NEXT_SAMPLE;
else
-- Defaults
accRAM_Re_out_add <= accRAM_Re_out;
accRAM_Im_out_add <= accRAM_Im_out;
we_accRAM <= '0';
o_filtered_sample.tdata(4*GC_CH_DATA_WIDTH-1 downto 0) <= (others => '0');
o_filtered_sample.tvalid <= '0';
o_filtered_sample.tlast <= '0';
-- FSM
case state_filter is
-------------------------------------------------------------------
when NEXT_SAMPLE =>
accRAM_addr_in <= prev_accRAM_addr_in;
accRAM_addr_out <= prev_accRAM_addr_out;
run_filter_cnt <= (others => '0');
we_accRAM <= '0';
if (sample_tvalid_posedge = '1') then
sample_in <= sample_s1.tdata(GC_CH_DATA_WIDTH-1 downto 0);
coef_addr_cnt <= coef_addr_cnt - to_integer(i_config_d_factor_reg);
decimation_cnt <= decimation_cnt + 1;
state_filter <= FILTERING;
end if;
-------------------------------------------------------------------
when FILTERING =>
mult_Re <= std_logic_vector(resize(signed(sample_in) * signed(i_coef_data(2*GC_COEF_DATA_WIDTH-1 downto GC_COEF_DATA_WIDTH)), mult_Re'length));
mult_Im <= std_logic_vector(resize(signed(sample_in) * signed(i_coef_data(GC_COEF_DATA_WIDTH-1 downto 0)), mult_Im'length));
mult_Re_ext <= std_logic_vector(resize(signed(mult_Re), mult_Re_ext'length));
mult_Im_ext <= std_logic_vector(resize(signed(mult_Im), mult_Im_ext'length));
-- Truncate number of bits defined in 'config_lsb_prod_reg'
case i_config_lsb_prod_reg(2 downto 0) is
when b"000" =>
add_Re_in <= mult_Re_ext(GC_ADDER_WIDTH-1 downto 0); -- (35:0)
add_Im_in <= mult_Im_ext(GC_ADDER_WIDTH-1 downto 0);
when b"001" =>
add_Re_in <= mult_Re_ext(GC_ADDER_WIDTH downto 1); -- (36:1)
add_Im_in <= mult_Im_ext(GC_ADDER_WIDTH downto 1);
when b"010" =>
add_Re_in <= mult_Re_ext(GC_ADDER_WIDTH+1 downto 2); -- (37:2)
add_Im_in <= mult_Im_ext(GC_ADDER_WIDTH+1 downto 2);
when b"011" =>
add_Re_in <= mult_Re_ext(GC_ADDER_WIDTH+2 downto 3); -- (38:3)
add_Im_in <= mult_Im_ext(GC_ADDER_WIDTH+2 downto 3);
when b"100" =>
add_Re_in <= mult_Re_ext(GC_ADDER_WIDTH+3 downto 4); -- (39:4)
add_Im_in <= mult_Im_ext(GC_ADDER_WIDTH+3 downto 4);
when others =>
add_Re_in <= mult_Re_ext(GC_ADDER_WIDTH-1 downto 0); -- same as (b"000")
add_Im_in <= mult_Im_ext(GC_ADDER_WIDTH-1 downto 0);
end case;
-- Counter for controlling length of Filtering-state
run_filter_cnt <= run_filter_cnt + 1;
-- Read previous sum from accRAM
if (run_filter_cnt > i_config_q_factor_reg-1) then
accRAM_addr_out <= filtered_accRAM_addr_out;
elsif (run_filter_cnt > 0) then
-- Rotating accRAM-address counter for reading from accRAM
if (accRAM_addr_out = 0) then
accRAM_addr_out <= i_config_q_factor_reg(accRAM_addr_out'range) - 1;
else
accRAM_addr_out <= accRAM_addr_out - 1;
end if;
end if;
-- Add new sum and store in accRAM
if (run_filter_cnt > C_START_WRITING_NEW_SUM+i_config_q_factor_reg) then
we_accRAM <= '0';
elsif (run_filter_cnt > C_START_WRITING_NEW_SUM) then
we_accRAM <= '1';
accRAM_Re_in <= std_logic_vector(signed(add_Re_in) + signed(accRAM_Re_out_add));
accRAM_Im_in <= std_logic_vector(signed(add_Im_in) + signed(accRAM_Im_out_add));
if (run_filter_cnt > C_START_WRITING_NEW_SUM+1) then
-- Rotating accRAM-address counter for writing to accRAM
if (accRAM_addr_in = 0 and we_accRAM = '1') then
accRAM_addr_in <= i_config_q_factor_reg(accRAM_addr_in'range) - 1;
else
accRAM_addr_in <= accRAM_addr_in - 1;
end if;
end if;
end if;
-- Update address-counter for coef-RAM, until last overlap is reached
if (run_filter_cnt < i_config_q_factor_reg-1) then
if (coef_addr_cnt < i_config_d_factor_reg) then
coef_addr_cnt <= i_config_filterlength_reg(coef_addr_cnt'range) - 1;
else
coef_addr_cnt <= coef_addr_cnt - to_integer(i_config_d_factor_reg);
end if;
end if;
-- Control length of FILTERING-state
if (run_filter_cnt = i_config_q_factor_reg+8) then
if (decimation_cnt < i_config_d_factor_reg) then
coef_addr_cnt <= i_config_filterlength_reg(coef_addr_cnt'range) -1 -decimation_cnt; -- coef in first overlap
state_filter <= NEXT_SAMPLE;
elsif (decimation_cnt = i_config_d_factor_reg) then
state_filter <= FILTER_OUTPUT;
end if;
end if;
-------------------------------------------------------------------
when FILTER_OUTPUT =>
o_filtered_sample.tdata <= accRAM_Re_Out & accRAM_Im_out;
o_filtered_sample.tvalid <= '1';
o_filtered_sample.tlast <= '0';
if (i_config_q_factor_reg = 1) then
filtered_accRAM_addr_out <= (others => '0');
elsif (filtered_accRAM_addr_out > i_config_q_factor_reg-2) then
filtered_accRAM_addr_out <= (others => '0');
else
filtered_accRAM_addr_out <= filtered_accRAM_addr_out + 1;
end if;
-- Flush cell which is read, in accRAM
we_accRAM <= '1';
accRAM_addr_in <= filtered_accRAM_addr_out;
accRAM_Re_in <= (others => '0');
accRAM_Im_in <= (others => '0');
-- Update coefficient for next sample
coef_addr_cnt <= i_config_filterlength_reg(coef_addr_cnt'range) - 1;
-- Reset decimation counter
decimation_cnt <= (others => '0');
-- Store accRAM-address value for next round of filtering before
-- changing state
prev_accRAM_addr_in <= accRAM_addr_in;
prev_accRAM_addr_out <= accRAM_addr_out;
state_filter <= NEXT_SAMPLE;
when others => state_filter <= NEXT_SAMPLE;
end case;
end if;
end if;
end process p_filter_fsm;Here are the filter statemachin which uses the config_q_factor: