--------------------------------------------------------------------------------
---
--- File : boxfilter_3x3.vhd
--- Related files :
---
--- Author(s) : stephane Domas (sdomas@univ-fcomte.fr)
---
--- Creation Date : 2017/10/16
---
--- Description : This IP does a box (i.e. average) filter with a 3x3 mask
--- on a grayscale image. The width of the image must be <= 1024.
--- Image size must be provided via generics
---
--- Note :
--- CP = 1{$img_width*$img_height}
--- PP = 0{$img_width+7}1{$img_width*$img_height}
--- PC = {$img_width+2:$img_width*$img_height-($img_width+2):1},{$img_width*$img_height:$img_width+2,0}
--- delta = $img_width*$img_height
---
--------------------------------------------------------------------------------
-
-library IEEE;
-use IEEE.std_logic_1164.all;
-use IEEE.numeric_std.all;
-
-entity boxfilter_3x3 is
- generic(
- img_width : natural := 128;
- img_height : natural := 128;
- dsp_in_width : natural := 18;
- dsp_out_width : natural := 36
- );
- port(
- clk : in std_logic;
- reset : in std_logic;
- pix_in : in std_logic_vector(7 downto 0);
- pix_in_enb : in std_logic;
- pix_out : out std_logic_vector(7 downto 0);
- pix_out_enb : out std_logic
- );
-end boxfilter_3x3;
-
-
-architecture rtl of boxfilter_3x3 is
-
- component ram_dp_1024x8
- port (
- clka : in std_logic;
- wea : in std_logic_vector(0 downto 0);
- addra : in std_logic_vector(9 downto 0);
- dina : in std_logic_vector(7 downto 0);
- douta : out std_logic_vector(7 downto 0);
- clkb : in std_logic;
- web : in std_logic_vector(0 downto 0);
- addrb : in std_logic_vector(9 downto 0);
- dinb : in std_logic_vector(7 downto 0);
- doutb : out std_logic_vector(7 downto 0)
- );
- end component;
-
- -- Signals
-
- -- constant signal set tup to img limits
- signal count_col_end : unsigned (9 downto 0);
- signal count_row_end : unsigned (9 downto 0);
-
- -- for storing image rows
- signal sel_mem : unsigned (1 downto 0); -- the current memorize row
- signal wea_0 : std_logic_vector(0 downto 0); -- we for memorized row 0
- signal wea_1 : std_logic_vector(0 downto 0); -- we for memorized row 1
- signal wea_2 : std_logic_vector(0 downto 0); -- we for memorized row 2
-
- signal dina_0 : std_logic_vector(7 downto 0);
- signal dina_1 : std_logic_vector(7 downto 0);
- signal dina_2 : std_logic_vector(7 downto 0);
- signal dina : std_logic_vector(7 downto 0);
-
- signal addra_w : std_logic_vector(9 downto 0);
- signal addra_w_s : unsigned (9 downto 0);
- signal wea : std_logic;
-
-
- signal addrb_r : std_logic_vector(9 downto 0); -- addr where to store
- signal addrb_r_s : unsigned (9 downto 0); -- addr where to store
-
- signal doutb_0 : std_logic_vector(7 downto 0);
- signal doutb_1 : std_logic_vector(7 downto 0);
- signal doutb_2 : std_logic_vector(7 downto 0);
-
- signal count_row_w : unsigned (10 downto 0); -- row counter while storing
- signal store_last_pix : std_logic; -- to be sure that last pixel is stored
- signal first_row_w : std_logic; -- '1' when the first row is read so that
- -- mem_0 is filled with zeroes
- signal all_pix_stored : std_logic; -- '1' when all pixels have been stored
-
- -- for reading image rows
- signal start_read : std_logic;
- signal do_read : std_logic;
- signal count_row_r : unsigned (10 downto 0);
- signal count_row_r_dly : unsigned (10 downto 0);
- signal wea_dly : std_logic;
- signal end_read : std_logic;
-
- -- for doing sums
- signal do_sum : std_logic;
- signal sum1 : unsigned (9 downto 0);
- signal sum2 : unsigned (9 downto 0);
- signal sum3 : unsigned (9 downto 0);
-
- -- for doing total
- signal do_total : std_logic;
- signal sum : unsigned (dsp_in_width-1 downto 0);
- signal count_col_total : unsigned (10 downto 0);
- signal count_row_total : unsigned (10 downto 0);
- signal jump_first_sum : std_logic;
-
- -- for doing final division
- signal do_div : std_logic;
- signal do_out : std_logic;
- signal end_filter : std_logic;
- signal cst_mult : unsigned(dsp_in_width-1 downto 0); -- eq. 14564 (=2^17/9)
- signal mult_result : unsigned (dsp_out_width-1 downto 0);
-
-
-begin
-
- img_row_0 : ram_dp_1024x8
- port map (
- clka => clk,
- wea => wea_0,
- addra => addra_w,
- dina => dina_0,
- clkb => clk,
- web => (others => '0'),
- addrb => addrb_r,
- dinb => (others => '0'),
- doutb => doutb_0
- );
- img_row_1 : ram_dp_1024x8
- port map (
- clka => clk,
- wea => wea_1,
- addra => addra_w,
- dina => dina_1,
- clkb => clk,
- web => (others => '0'),
- addrb => addrb_r,
- dinb => (others => '0'),
- doutb => doutb_1
- );
- img_row_2 : ram_dp_1024x8
- port map (
- clka => clk,
- wea => wea_2,
- addra => addra_w,
- dina => dina_2,
- clkb => clk,
- web => (others => '0'),
- addrb => addrb_r,
- dinb => (others => '0'),
- doutb => doutb_2
- );
-
-
- cst_mult <= to_unsigned(14564, dsp_in_width);
- count_col_end <= to_unsigned(img_width-1, 10);
- count_row_end <= to_unsigned(img_height-1, 10);
-
- addra_w <= std_logic_vector(addra_w_s);
- addrb_r <= std_logic_vector(addrb_r_s);
-
- wea_0 <= "1" when ((sel_mem = 0 or first_row_w = '1') and wea = '1') else
- "0";
- wea_1 <= "1" when (sel_mem = 1 and wea = '1') else
- "0";
- wea_2 <= "1" when (sel_mem = 2 and wea = '1') else
- "0";
-
- dina_0 <= (others => '0') when (first_row_w = '1') else
- dina;
-
- dina_1 <= dina;
- dina_2 <= dina;
-
- store_row_process : process (clk, reset)
- begin
- if reset = '1' then
-
- sel_mem <= to_unsigned(0, 2);
- addra_w_s <= to_unsigned(img_width-1, 10);
- dina <= (others => '0');
-
- wea <= '0';
- count_row_w <= to_unsigned(0, 11);
-
- start_read <= '0';
- first_row_w <= '1';
- store_last_pix <= '0';
- all_pix_stored <= '0';
-
- elsif rising_edge(clk) then
-
- wea <= '0';
- start_read <= '0';
- dina <= (others => '0');
- store_last_pix <= '0';
-
- -- reset all when filter has ended
- if end_filter = '1' then
-
- count_row_w <= to_unsigned(0, 11);
- sel_mem <= to_unsigned(0, 2);
- addra_w_s <= to_unsigned(img_width-1, 10);
- first_row_w <= '1';
- all_pix_stored <= '0';
-
- elsif store_last_pix = '1' then
- addra_w_s <= to_unsigned(0, 10);
- -- select next ram
- if sel_mem = 2 then
- sel_mem <= to_unsigned(0, 2);
- else
- sel_mem <= sel_mem + 1;
- end if;
- all_pix_stored <= '1'; -- all pixels are stored
-
- elsif pix_in_enb = '1' then
-
- -- prepare to write
- wea <= '1';
- -- take input
- dina <= pix_in;
- -- check if this is the last pixel
- if addra_w_s = img_width-2 and count_row_w = img_height then
- store_last_pix <= '1';
- end if;
- -- if at line end
- if addra_w_s = img_width-1 then
- -- back to 0
- addra_w_s <= to_unsigned(0, 10);
- -- select next ram
- if sel_mem = 2 then
- sel_mem <= to_unsigned(0, 2);
- else
- sel_mem <= sel_mem + 1;
- end if;
- -- end of first line to store
- if count_row_w = 1 then
- first_row_w <= '0';
- start_read <= '1';
- end if;
- count_row_w <= count_row_w + 1;
- else
- addra_w_s <= addra_w_s + 1;
- end if;
- end if;
- end if;
-
- end process store_row_process;
-
- read_rows_process : process (clk, reset)
- begin
- if reset = '1' then
-
- addrb_r_s <= to_unsigned(0, 10);
- do_read <= '0';
- wea_dly <= '0';
-
- count_row_r <= to_unsigned(0, 11);
- end_read <= '0';
-
- do_sum <= '0';
-
- elsif rising_edge(clk) then
-
- wea_dly <= wea;
- do_sum <= '0';
- end_read <= '0';
-
- if end_read = '1' then
- do_sum <= '1';
- end if;
-
- if start_read = '1' then
- do_read <= '1';
-
- elsif do_read = '1' and (all_pix_stored = '1' or wea_dly = '1') then
-
- do_sum <= '1';
- -- whatever the case inc addr if not at end
- if addrb_r_s = img_width-1 then
- addrb_r_s <= to_unsigned(0, 10);
- if count_row_r = img_height-1 then
- count_row_r <= to_unsigned(0, 11);
- do_read <= '0';
- end_read <= '1';
- else
- count_row_r <= count_row_r+1;
- end if;
- else
- addrb_r_s <= addrb_r_s + 1;
- end if;
- end if;
- end if;
-
- end process read_rows_process;
-
- sum_process : process (clk, reset)
- begin
- if reset = '1' then
-
- sum1 <= to_unsigned(0, 10);
- sum2 <= to_unsigned(0, 10);
- sum3 <= to_unsigned(0, 10);
- count_row_r_dly <= to_unsigned(0, 11);
- do_total <= '0';
-
- elsif rising_edge(clk) then
-
- do_total <= '0';
- count_row_r_dly <= count_row_r;
-
- if end_filter = '1' then
- sum1 <= to_unsigned(0, 10);
- sum2 <= to_unsigned(0, 10);
- sum3 <= to_unsigned(0, 10);
- end if;
- if do_sum = '1' then
-
- sum3 <= sum2;
- sum2 <= sum1;
- if count_row_r_dly = img_height-1 then
- if sel_mem = 0 then
- sum1 <= unsigned("00" & doutb_1) + unsigned("00" & doutb_2);
- elsif sel_mem = 1 then
- sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_2);
- elsif sel_mem = 2 then
- sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1);
- end if;
- else
- sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1) + unsigned("00" & doutb_2);
- end if;
- do_total <= '1';
- end if;
- end if;
-
- end process sum_process;
-
- total_process : process (clk, reset)
- begin
- if reset = '1' then
-
- sum <= to_unsigned(0, dsp_in_width);
-
- jump_first_sum <= '0';
- count_row_total <= to_unsigned(0, 11);
- count_col_total <= to_unsigned(0, 11);
- do_div <= '0';
- end_filter <= '0';
-
- elsif rising_edge(clk) then
-
- do_div <= '0';
- end_filter <= '0';
-
- if do_total = '1' then
-
- if jump_first_sum = '1' then
- -- sum for the end of the line
- if count_col_total = img_width-1 then
- sum <= resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width);
- count_col_total <= to_unsigned(0, 11);
- if count_row_total = img_height-1 then
- end_filter <= '1';
- count_row_total <= to_unsigned(0, 11);
- jump_first_sum <= '0';
- else
- count_row_total <= count_row_total + 1;
- end if;
- -- sum for the begining of the line
- elsif count_col_total = 0 then
- sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width);
- count_col_total <= to_unsigned(1, 11);
- else
- sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width);
- count_col_total <= count_col_total + 1;
- end if;
- do_div <= '1';
- else
- jump_first_sum <= '1';
- end if;
- end if;
-
-
- end if;
-
- end process total_process;
-
- final_div_process : process (clk, reset)
- begin
- if reset = '1' then
-
- mult_result <= to_unsigned(0, dsp_out_width);
- do_out <= '0';
-
- elsif rising_edge(clk) then
-
- do_out <= '0';
-
- if do_div = '1' then
- mult_result <= sum * cst_mult;
- do_out <= '1';
- end if;
- end if;
- end process final_div_process;
-
- pix_out <= std_logic_vector(mult_result(24 downto 17));
- pix_out_enb <= do_out;
-
-end rtl;
-