1 -------------------------------------------------------------------------------
3 -- File : boxfilter_3x3.vhd
6 -- Author(s) : stephane Domas (sdomas@univ-fcomte.fr)
8 -- Creation Date : 2017/10/16
10 -- Description : This IP does a box (i.e. average) filter with a 3x3 mask
11 -- on a grayscale image. The width of the image must be <= 1024.
12 -- Image size must be provided via generics
15 -- CP = 1{$img_width*$img_height}
16 -- PP = 0{$img_width+7}1{$img_width*$img_height}
17 -- PC = {$img_width+2:$img_width*$img_height-($img_width+2):1},{$img_width*$img_height:$img_width+2,0}
18 -- delta = $img_width*$img_height
20 -------------------------------------------------------------------------------
23 use IEEE.std_logic_1164.all;
24 use IEEE.numeric_std.all;
26 entity boxfilter_3x3 is
28 img_width : natural := 128;
29 img_height : natural := 128;
30 dsp_in_width : natural := 18;
31 dsp_out_width : natural := 36
36 pix_in : in std_logic_vector(7 downto 0);
37 pix_in_enb : in std_logic;
38 pix_out : out std_logic_vector(7 downto 0);
39 pix_out_enb : out std_logic
44 architecture rtl of boxfilter_3x3 is
46 component ram_dp_1024x8
49 wea : in std_logic_vector(0 downto 0);
50 addra : in std_logic_vector(9 downto 0);
51 dina : in std_logic_vector(7 downto 0);
52 douta : out std_logic_vector(7 downto 0);
54 web : in std_logic_vector(0 downto 0);
55 addrb : in std_logic_vector(9 downto 0);
56 dinb : in std_logic_vector(7 downto 0);
57 doutb : out std_logic_vector(7 downto 0)
63 -- constant signal set tup to img limits
64 signal count_col_end : unsigned (9 downto 0);
65 signal count_row_end : unsigned (9 downto 0);
67 -- for storing image rows
68 signal sel_mem : unsigned (1 downto 0); -- the current memorize row
69 signal wea_0 : std_logic_vector(0 downto 0); -- we for memorized row 0
70 signal wea_1 : std_logic_vector(0 downto 0); -- we for memorized row 1
71 signal wea_2 : std_logic_vector(0 downto 0); -- we for memorized row 2
73 signal dina_0 : std_logic_vector(7 downto 0);
74 signal dina_1 : std_logic_vector(7 downto 0);
75 signal dina_2 : std_logic_vector(7 downto 0);
76 signal dina : std_logic_vector(7 downto 0);
78 signal addra_w : std_logic_vector(9 downto 0);
79 signal addra_w_s : unsigned (9 downto 0);
80 signal wea : std_logic;
83 signal addrb_r : std_logic_vector(9 downto 0); -- addr where to store
84 signal addrb_r_s : unsigned (9 downto 0); -- addr where to store
86 signal doutb_0 : std_logic_vector(7 downto 0);
87 signal doutb_1 : std_logic_vector(7 downto 0);
88 signal doutb_2 : std_logic_vector(7 downto 0);
90 signal count_row_w : unsigned (10 downto 0); -- row counter while storing
91 signal store_last_pix : std_logic; -- to be sure that last pixel is stored
92 signal first_row_w : std_logic; -- '1' when the first row is read so that
93 -- mem_0 is filled with zeroes
94 signal all_pix_stored : std_logic; -- '1' when all pixels have been stored
96 -- for reading image rows
97 signal start_read : std_logic;
98 signal do_read : std_logic;
99 signal count_row_r : unsigned (10 downto 0);
100 signal count_row_r_dly : unsigned (10 downto 0);
101 signal wea_dly : std_logic;
102 signal end_read : std_logic;
105 signal do_sum : std_logic;
106 signal sum1 : unsigned (9 downto 0);
107 signal sum2 : unsigned (9 downto 0);
108 signal sum3 : unsigned (9 downto 0);
111 signal do_total : std_logic;
112 signal sum : unsigned (dsp_in_width-1 downto 0);
113 signal count_col_total : unsigned (10 downto 0);
114 signal count_row_total : unsigned (10 downto 0);
115 signal jump_first_sum : std_logic;
117 -- for doing final division
118 signal do_div : std_logic;
119 signal do_out : std_logic;
120 signal end_filter : std_logic;
121 signal cst_mult : unsigned(dsp_in_width-1 downto 0); -- eq. 14564 (=2^17/9)
122 signal mult_result : unsigned (dsp_out_width-1 downto 0);
127 img_row_0 : ram_dp_1024x8
134 web => (others => '0'),
136 dinb => (others => '0'),
139 img_row_1 : ram_dp_1024x8
146 web => (others => '0'),
148 dinb => (others => '0'),
151 img_row_2 : ram_dp_1024x8
158 web => (others => '0'),
160 dinb => (others => '0'),
165 cst_mult <= to_unsigned(14564, dsp_in_width);
166 count_col_end <= to_unsigned(img_width-1, 10);
167 count_row_end <= to_unsigned(img_height-1, 10);
169 addra_w <= std_logic_vector(addra_w_s);
170 addrb_r <= std_logic_vector(addrb_r_s);
172 wea_0 <= "1" when ((sel_mem = 0 or first_row_w = '1') and wea = '1') else
174 wea_1 <= "1" when (sel_mem = 1 and wea = '1') else
176 wea_2 <= "1" when (sel_mem = 2 and wea = '1') else
179 dina_0 <= (others => '0') when (first_row_w = '1') else
185 store_row_process : process (clk, reset)
189 sel_mem <= to_unsigned(0, 2);
190 addra_w_s <= to_unsigned(img_width-1, 10);
191 dina <= (others => '0');
194 count_row_w <= to_unsigned(0, 11);
198 store_last_pix <= '0';
199 all_pix_stored <= '0';
201 elsif rising_edge(clk) then
205 dina <= (others => '0');
206 store_last_pix <= '0';
208 -- reset all when filter has ended
209 if end_filter = '1' then
211 count_row_w <= to_unsigned(0, 11);
212 sel_mem <= to_unsigned(0, 2);
213 addra_w_s <= to_unsigned(img_width-1, 10);
215 all_pix_stored <= '0';
217 elsif store_last_pix = '1' then
218 addra_w_s <= to_unsigned(0, 10);
221 sel_mem <= to_unsigned(0, 2);
223 sel_mem <= sel_mem + 1;
225 all_pix_stored <= '1'; -- all pixels are stored
227 elsif pix_in_enb = '1' then
233 -- check if this is the last pixel
234 if addra_w_s = img_width-2 and count_row_w = img_height then
235 store_last_pix <= '1';
238 if addra_w_s = img_width-1 then
240 addra_w_s <= to_unsigned(0, 10);
243 sel_mem <= to_unsigned(0, 2);
245 sel_mem <= sel_mem + 1;
247 -- end of first line to store
248 if count_row_w = 1 then
252 count_row_w <= count_row_w + 1;
254 addra_w_s <= addra_w_s + 1;
259 end process store_row_process;
261 read_rows_process : process (clk, reset)
265 addrb_r_s <= to_unsigned(0, 10);
269 count_row_r <= to_unsigned(0, 11);
274 elsif rising_edge(clk) then
280 if end_read = '1' then
284 if start_read = '1' then
287 elsif do_read = '1' and (all_pix_stored = '1' or wea_dly = '1') then
290 -- whatever the case inc addr if not at end
291 if addrb_r_s = img_width-1 then
292 addrb_r_s <= to_unsigned(0, 10);
293 if count_row_r = img_height-1 then
294 count_row_r <= to_unsigned(0, 11);
298 count_row_r <= count_row_r+1;
301 addrb_r_s <= addrb_r_s + 1;
306 end process read_rows_process;
308 sum_process : process (clk, reset)
312 sum1 <= to_unsigned(0, 10);
313 sum2 <= to_unsigned(0, 10);
314 sum3 <= to_unsigned(0, 10);
315 count_row_r_dly <= to_unsigned(0, 11);
318 elsif rising_edge(clk) then
321 count_row_r_dly <= count_row_r;
323 if end_filter = '1' then
324 sum1 <= to_unsigned(0, 10);
325 sum2 <= to_unsigned(0, 10);
326 sum3 <= to_unsigned(0, 10);
332 if count_row_r_dly = img_height-1 then
334 sum1 <= unsigned("00" & doutb_1) + unsigned("00" & doutb_2);
335 elsif sel_mem = 1 then
336 sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_2);
337 elsif sel_mem = 2 then
338 sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1);
341 sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1) + unsigned("00" & doutb_2);
347 end process sum_process;
349 total_process : process (clk, reset)
353 sum <= to_unsigned(0, dsp_in_width);
355 jump_first_sum <= '0';
356 count_row_total <= to_unsigned(0, 11);
357 count_col_total <= to_unsigned(0, 11);
361 elsif rising_edge(clk) then
366 if do_total = '1' then
368 if jump_first_sum = '1' then
369 -- sum for the end of the line
370 if count_col_total = img_width-1 then
371 sum <= resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width);
372 count_col_total <= to_unsigned(0, 11);
373 if count_row_total = img_height-1 then
375 count_row_total <= to_unsigned(0, 11);
376 jump_first_sum <= '0';
378 count_row_total <= count_row_total + 1;
380 -- sum for the begining of the line
381 elsif count_col_total = 0 then
382 sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width);
383 count_col_total <= to_unsigned(1, 11);
385 sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width);
386 count_col_total <= count_col_total + 1;
390 jump_first_sum <= '1';
397 end process total_process;
399 final_div_process : process (clk, reset)
403 mult_result <= to_unsigned(0, dsp_out_width);
406 elsif rising_edge(clk) then
411 mult_result <= sum * cst_mult;
415 end process final_div_process;
417 pix_out <= std_logic_vector(mult_result(24 downto 17));
418 pix_out_enb <= do_out;