]> AND Private Git Repository - blast.git/blob - boxfilter_3x3.vhd
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
correct bug with clkrstgen
[blast.git] / boxfilter_3x3.vhd
1 -------------------------------------------------------------------------------
2 --
3 --  File          : boxfilter_3x3.vhd
4 --  Related files : 
5 --
6 --  Author(s)     : stephane Domas (sdomas@univ-fcomte.fr)
7 --
8 --  Creation Date : 2017/10/16
9 --
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
13 --
14 --  Note          :
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
19 --
20 -------------------------------------------------------------------------------
21
22 library IEEE;
23 use IEEE.std_logic_1164.all;
24 use IEEE.numeric_std.all;
25
26 entity boxfilter_3x3 is
27   generic(
28     img_width     : natural := 128;
29     img_height    : natural := 128;
30     dsp_in_width  : natural := 18;
31     dsp_out_width : natural := 36
32     );
33   port(
34     clk         : in  std_logic;
35     reset       : in  std_logic;
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
40     );
41 end boxfilter_3x3;
42
43
44 architecture rtl of boxfilter_3x3 is
45
46   component ram_dp_1024x8
47     port (
48       clka  : in  std_logic;
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);
53       clkb  : in  std_logic;
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)
58       );
59   end component;
60
61   -- Signals
62
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);
66
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  
72
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);
77
78   signal addra_w   : std_logic_vector(9 downto 0);
79   signal addra_w_s : unsigned (9 downto 0);
80   signal wea       : std_logic;
81
82
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
85
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);
89
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
95
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;
103
104   -- for doing sums
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);
109
110   -- for doing total
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;
116
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);
123
124
125 begin
126
127   img_row_0 : ram_dp_1024x8
128     port map (
129       clka  => clk,
130       wea   => wea_0,
131       addra => addra_w,
132       dina  => dina_0,
133       clkb  => clk,
134       web   => (others => '0'),
135       addrb => addrb_r,
136       dinb  => (others => '0'),
137       doutb => doutb_0
138       );
139   img_row_1 : ram_dp_1024x8
140     port map (
141       clka  => clk,
142       wea   => wea_1,
143       addra => addra_w,
144       dina  => dina_1,
145       clkb  => clk,
146       web   => (others => '0'),
147       addrb => addrb_r,
148       dinb  => (others => '0'),
149       doutb => doutb_1
150       );
151   img_row_2 : ram_dp_1024x8
152     port map (
153       clka  => clk,
154       wea   => wea_2,
155       addra => addra_w,
156       dina  => dina_2,
157       clkb  => clk,
158       web   => (others => '0'),
159       addrb => addrb_r,
160       dinb  => (others => '0'),
161       doutb => doutb_2
162       );
163
164
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);
168
169   addra_w <= std_logic_vector(addra_w_s);
170   addrb_r <= std_logic_vector(addrb_r_s);
171
172   wea_0 <= "1" when ((sel_mem = 0 or first_row_w = '1') and wea = '1') else
173            "0";
174   wea_1 <= "1" when (sel_mem = 1 and wea = '1') else
175            "0";
176   wea_2 <= "1" when (sel_mem = 2 and wea = '1') else
177            "0";
178
179   dina_0 <= (others => '0') when (first_row_w = '1') else
180             dina;
181
182   dina_1 <= dina;
183   dina_2 <= dina;
184
185   store_row_process : process (clk, reset)
186   begin
187     if reset = '1' then
188
189       sel_mem   <= to_unsigned(0, 2);
190       addra_w_s <= to_unsigned(img_width-1, 10);
191       dina      <= (others => '0');
192
193       wea         <= '0';
194       count_row_w <= to_unsigned(0, 11);
195
196       start_read     <= '0';
197       first_row_w    <= '1';
198       store_last_pix <= '0';
199       all_pix_stored <= '0';
200
201     elsif rising_edge(clk) then
202
203       wea            <= '0';
204       start_read     <= '0';
205       dina           <= (others => '0');
206       store_last_pix <= '0';
207
208       -- reset all when filter has ended
209       if end_filter = '1' then
210
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);
214         first_row_w    <= '1';
215         all_pix_stored <= '0';
216
217       elsif store_last_pix = '1' then
218         addra_w_s <= to_unsigned(0, 10);
219         -- select next ram
220         if sel_mem = 2 then
221           sel_mem <= to_unsigned(0, 2);
222         else
223           sel_mem <= sel_mem + 1;
224         end if;
225         all_pix_stored <= '1';          -- all pixels are stored        
226
227       elsif pix_in_enb = '1' then
228
229         -- prepare to write
230         wea  <= '1';
231         -- take input
232         dina <= pix_in;
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';
236         end if;
237         -- if at line end
238         if addra_w_s = img_width-1 then
239           -- back to 0
240           addra_w_s <= to_unsigned(0, 10);
241           -- select next ram
242           if sel_mem = 2 then
243             sel_mem <= to_unsigned(0, 2);
244           else
245             sel_mem <= sel_mem + 1;
246           end if;
247           -- end of first line to store
248           if count_row_w = 1 then
249             first_row_w <= '0';
250             start_read  <= '1';
251           end if;
252           count_row_w <= count_row_w + 1;
253         else
254           addra_w_s <= addra_w_s + 1;
255         end if;
256       end if;
257     end if;
258
259   end process store_row_process;
260
261   read_rows_process : process (clk, reset)
262   begin
263     if reset = '1' then
264
265       addrb_r_s <= to_unsigned(0, 10);
266       do_read   <= '0';
267       wea_dly   <= '0';
268
269       count_row_r <= to_unsigned(0, 11);
270       end_read    <= '0';
271
272       do_sum <= '0';
273
274     elsif rising_edge(clk) then
275
276       wea_dly  <= wea;
277       do_sum   <= '0';
278       end_read <= '0';
279
280       if end_read = '1' then
281         do_sum <= '1';
282       end if;
283
284       if start_read = '1' then
285         do_read <= '1';
286
287       elsif do_read = '1' and (all_pix_stored = '1' or wea_dly = '1') then
288
289         do_sum <= '1';
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);
295             do_read     <= '0';
296             end_read    <= '1';
297           else
298             count_row_r <= count_row_r+1;
299           end if;
300         else
301           addrb_r_s <= addrb_r_s + 1;
302         end if;
303       end if;
304     end if;
305
306   end process read_rows_process;
307
308   sum_process : process (clk, reset)
309   begin
310     if reset = '1' then
311
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);
316       do_total        <= '0';
317
318     elsif rising_edge(clk) then
319
320       do_total        <= '0';
321       count_row_r_dly <= count_row_r;
322
323       if end_filter = '1' then
324         sum1 <= to_unsigned(0, 10);
325         sum2 <= to_unsigned(0, 10);
326         sum3 <= to_unsigned(0, 10);
327       end if;
328       if do_sum = '1' then
329
330         sum3 <= sum2;
331         sum2 <= sum1;
332         if count_row_r_dly = img_height-1 then
333           if sel_mem = 0 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);
339           end if;
340         else
341           sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1) + unsigned("00" & doutb_2);
342         end if;
343         do_total <= '1';
344       end if;
345     end if;
346
347   end process sum_process;
348
349   total_process : process (clk, reset)
350   begin
351     if reset = '1' then
352
353       sum <= to_unsigned(0, dsp_in_width);
354
355       jump_first_sum  <= '0';
356       count_row_total <= to_unsigned(0, 11);
357       count_col_total <= to_unsigned(0, 11);
358       do_div          <= '0';
359       end_filter      <= '0';
360
361     elsif rising_edge(clk) then
362
363       do_div     <= '0';
364       end_filter <= '0';
365
366       if do_total = '1' then
367
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
374               end_filter      <= '1';
375               count_row_total <= to_unsigned(0, 11);
376               jump_first_sum  <= '0';
377             else
378               count_row_total <= count_row_total + 1;
379             end if;
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);
384           else
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;
387           end if;
388           do_div <= '1';
389         else
390           jump_first_sum <= '1';
391         end if;
392       end if;
393
394
395     end if;
396
397   end process total_process;
398
399   final_div_process : process (clk, reset)
400   begin
401     if reset = '1' then
402
403       mult_result <= to_unsigned(0, dsp_out_width);
404       do_out      <= '0';
405
406     elsif rising_edge(clk) then
407
408       do_out <= '0';
409
410       if do_div = '1' then
411         mult_result <= sum * cst_mult;
412         do_out      <= '1';
413       end if;
414     end if;
415   end process final_div_process;
416
417   pix_out     <= std_logic_vector(mult_result(24 downto 17));
418   pix_out_enb <= do_out;
419
420 end rtl;
421