OpenCores
URL https://opencores.org/ocsvn/mkjpeg/mkjpeg/trunk

Subversion Repositories mkjpeg

[/] [mkjpeg/] [trunk/] [design/] [huffman/] [Huffman.vhd] - Blame information for rev 25

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 mikel262
-------------------------------------------------------------------------------
2
-- File Name :  Huffman.vhd
3
--
4
-- Project   : JPEG_ENC
5
--
6
-- Module    : Huffman
7
--
8
-- Content   : Huffman Encoder
9
--
10
-- Description : Huffman encoder core
11
--
12
-- Spec.     : 
13
--
14
-- Author    : Michal Krepa
15
--
16
-------------------------------------------------------------------------------
17
-- History :
18
-- 20090228: (MK): Initial Creation.
19
-------------------------------------------------------------------------------
20
 
21
-------------------------------------------------------------------------------
22
-------------------------------------------------------------------------------
23
----------------------------------- LIBRARY/PACKAGE ---------------------------
24
-------------------------------------------------------------------------------
25
-------------------------------------------------------------------------------
26
 
27
-------------------------------------------------------------------------------
28
-- generic packages/libraries:
29
-------------------------------------------------------------------------------
30
library ieee;
31
  use ieee.std_logic_1164.all;
32
  use ieee.numeric_std.all;
33
 
34
-------------------------------------------------------------------------------
35
-- user packages/libraries:
36
-------------------------------------------------------------------------------
37
 
38
-------------------------------------------------------------------------------
39
-------------------------------------------------------------------------------
40
----------------------------------- ENTITY ------------------------------------
41
-------------------------------------------------------------------------------
42
-------------------------------------------------------------------------------
43
entity Huffman is
44
  port
45
  (
46
        CLK                : in  std_logic;
47
        RST                : in  std_logic;
48
        -- CTRL
49
        start_pb           : in  std_logic;
50
        ready_pb           : out std_logic;
51
 
52
        -- HOST IF
53
        sof                : in  std_logic;
54
        img_size_x         : in  std_logic_vector(15 downto 0);
55
        img_size_y         : in  std_logic_vector(15 downto 0);
56
        cmp_max            : in  std_logic_vector(1 downto 0);
57
 
58
        -- RLE
59
        rle_buf_sel        : out std_logic;
60
        rd_en              : out std_logic;
61
        runlength          : in  std_logic_vector(3 downto 0);
62
        VLI_size           : in  std_logic_vector(3 downto 0);
63
        VLI                : in  std_logic_vector(11 downto 0);
64
        d_val              : in  std_logic;
65
        rle_fifo_empty     : in  std_logic;
66
 
67
        -- Byte Stuffer
68
        bs_buf_sel         : in  std_logic;
69
        bs_fifo_empty      : out std_logic;
70
        bs_rd_req          : in  std_logic;
71
        bs_packed_byte     : out std_logic_vector(7 downto 0)
72
    );
73
end entity Huffman;
74
 
75
-------------------------------------------------------------------------------
76
-------------------------------------------------------------------------------
77
----------------------------------- ARCHITECTURE ------------------------------
78
-------------------------------------------------------------------------------
79
-------------------------------------------------------------------------------
80
architecture RTL of Huffman is
81
 
82
  type T_STATE is (IDLE, RUN_VLC, RUN_VLI, PAD);
83
 
84
  constant C_M             : integer := 23;
85
  constant BLK_SIZE        : integer := 64;
86
 
87
  signal state             : T_STATE;
88
  signal rle_buf_sel_s     : std_logic;
89
  signal first_rle_word    : std_logic;
90
  signal word_reg          : unsigned(C_M-1 downto 0);
91
  signal bit_ptr           : unsigned(4 downto 0);
92
  signal num_fifo_wrs      : unsigned(1 downto 0);
93
  signal VLI_ext           : unsigned(15 downto 0);
94
  signal VLI_ext_size      : unsigned(4 downto 0);
95
  signal ready_HFW         : std_logic;
96
  signal fifo_wbyte        : std_logic_vector(7 downto 0);
97
  signal fifo_wrt_cnt      : unsigned(1 downto 0);
98
  signal fifo_wren         : std_logic;
99
  signal last_block        : std_logic;
100
  signal image_area_size   : unsigned(33 downto 0);
101
  signal block_cnt         : unsigned(27 downto 0);
102
  signal VLC_size          : unsigned(4 downto 0);
103
  signal VLC               : unsigned(15 downto 0);
104
  signal VLC_DC_size       : std_logic_vector(3 downto 0);
105
  signal VLC_DC            : unsigned(8 downto 0);
106
  signal VLC_AC_size       : unsigned(4 downto 0);
107
  signal VLC_AC            : unsigned(15 downto 0);
108
  signal vlc_vld           : std_logic;
109
  signal d_val_d1          : std_logic;
110
  signal d_val_d2          : std_logic;
111
  signal d_val_d3          : std_logic;
112
  signal d_val_d4          : std_logic;
113
  signal VLI_size_d        : std_logic_vector(3 downto 0);
114
  signal VLI_d             : std_logic_vector(11 downto 0);
115
  signal VLI_size_d1       : std_logic_vector(3 downto 0);
116
  signal VLI_d1            : std_logic_vector(11 downto 0);
117
  signal HFW_running       : std_logic;
118
  signal runlength_r       : std_logic_vector(3 downto 0);
119
  signal VLI_size_r        : std_logic_vector(3 downto 0);
120
  signal VLI_r             : std_logic_vector(11 downto 0);
121
  signal rd_en_s           : std_logic;
122
  signal pad_byte          : std_logic_vector(7 downto 0);
123
  signal pad_reg           : std_logic;
124
 
125
-------------------------------------------------------------------------------
126
-- Architecture: begin
127
-------------------------------------------------------------------------------
128
begin
129
 
130
  rle_buf_sel <= rle_buf_sel_s;
131
 
132
  rd_en   <= rd_en_s;
133
  vlc_vld <= rd_en_s;
134
 
135
  -------------------------------------------------------------------
136
  -- latch FIFO Q
137
  -------------------------------------------------------------------
138
  p_latch_fifo : process(CLK, RST)
139
  begin
140
    if RST = '1' then
141
      VLI_size_r  <= (others => '0');
142
      VLI_r       <= (others => '0');
143
    elsif CLK'event and CLK = '1' then
144
      if d_val = '1' then
145
        VLI_size_r  <= VLI_size;
146
        VLI_r       <= VLI;
147
      end if;
148
    end if;
149
  end process;
150
 
151
  -------------------------------------------------------------------
152
  -- DC_ROM
153
  -------------------------------------------------------------------
154
  U_DC_ROM : entity work.DC_ROM
155
  port map
156
  (
157
        CLK                => CLK,
158
        RST                => RST,
159
        VLI_size           => VLI_size,
160
 
161
        VLC_DC_size        => VLC_DC_size,
162
        VLC_DC             => VLC_DC
163
  );
164
 
165
  -------------------------------------------------------------------
166
  -- AC_ROM
167
  -------------------------------------------------------------------
168
  U_AC_ROM : entity work.AC_ROM
169
  port map
170
  (
171
        CLK                => CLK,
172
        RST                => RST,
173
        runlength          => runlength,
174
        VLI_size           => VLI_size,
175
 
176
        VLC_AC_size        => VLC_AC_size,
177
        VLC_AC             => VLC_AC
178
    );
179
 
180
  -------------------------------------------------------------------
181
  -- Double Fifo
182
  -------------------------------------------------------------------
183
  U_DoubleFifo : entity work.DoubleFifo
184
  port map
185
  (
186
        CLK                => CLK,
187
        RST                => RST,
188
        -- HUFFMAN
189
        data_in            => fifo_wbyte,
190
        wren               => fifo_wren,
191
        -- BYTE STUFFER
192
        buf_sel            => bs_buf_sel,
193
        rd_req             => bs_rd_req,
194
        fifo_empty         => bs_fifo_empty,
195
        data_out           => bs_packed_byte
196
    );
197
 
198
  -------------------------------------------------------------------
199
  -- RLE buf_sel
200
  -------------------------------------------------------------------
201
  p_rle_buf_sel : process(CLK, RST)
202
  begin
203
    if RST = '1' then
204
      rle_buf_sel_s   <= '0';
205
    elsif CLK'event and CLK = '1' then
206
      if start_pb = '1' then
207
        rle_buf_sel_s <= not rle_buf_sel_s;
208
      end if;
209
    end if;
210
  end process;
211
 
212
  -------------------------------------------------------------------
213
  -- mux for DC/AC ROM
214
  -------------------------------------------------------------------
215
  p_mux : process(CLK, RST)
216
  begin
217
    if RST = '1' then
218
      VLC_size <= (others => '0');
219
      VLC      <= (others => '0');
220
    elsif CLK'event and CLK = '1' then
221
      if first_rle_word = '1' then
222
        VLC_size <= unsigned('0' & VLC_DC_size);
223
        VLC      <= resize(VLC_DC, VLC'length);
224
      else
225
        VLC_size <= VLC_AC_size;
226
        VLC      <= VLC_AC;
227
      end if;
228
    end if;
229
  end process;
230
 
231
  -------------------------------------------------------------------
232
  -- Block Counter / Last Block detector
233
  -------------------------------------------------------------------
234
  p_blk_cnt : process(CLK, RST)
235
  begin
236
    if RST = '1' then
237
      image_area_size <= (others => '0');
238
      last_block      <= '0';
239
    elsif CLK'event and CLK = '1' then
240
      image_area_size <= unsigned(cmp_max)*
241
                         unsigned(img_size_x)*unsigned(img_size_y);
242
 
243
      if sof = '1' then
244
        block_cnt <= (others => '0');
245
      elsif start_pb = '1' then
246
        block_cnt <= block_cnt + 1;
247
      end if;
248
 
249
      if block_cnt = image_area_size(33 downto 6) then
250
        last_block <= '1';
251
      else
252
        last_block <= '0';
253
      end if;
254
 
255
    end if;
256
  end process;
257
 
258
  VLI_ext      <= unsigned("0000" & VLI_d1);
259
  VLI_ext_size <= unsigned('0' & VLI_size_d1);
260
 
261
  -------------------------------------------------------------------
262
  -- delay line
263
  -------------------------------------------------------------------
264
  p_vli_dly : process(CLK, RST)
265
  begin
266
    if RST = '1' then
267
      VLI_d       <= (others => '0');
268
      VLI_size_d  <= (others => '0');
269
      VLI_d1      <= (others => '0');
270
      VLI_size_d1 <= (others => '0');
271
      d_val_d1    <= '0';
272
      d_val_d2    <= '0';
273
      d_val_d3    <= '0';
274
      d_val_d4    <= '0';
275
    elsif CLK'event and CLK = '1' then
276
      VLI_d1      <= VLI_r;
277
      VLI_size_d1 <= VLI_size_r;
278
 
279
      VLI_d       <= VLI_d1;
280
      VLI_size_d  <= VLI_size_d1;
281
 
282
      d_val_d1   <= d_val;
283
      d_val_d2   <= d_val_d1;
284
      d_val_d3   <= d_val_d2;
285
      d_val_d4   <= d_val_d3;
286
    end if;
287
  end process;
288
 
289
  -------------------------------------------------------------------
290
  -- HandleFifoWrites
291
  -------------------------------------------------------------------
292
  p_HandleFifoWrites : process(CLK, RST)
293
  begin
294
    if RST = '1' then
295
      ready_HFW    <= '0';
296
      fifo_wrt_cnt <= (others => '0');
297
      fifo_wren    <= '0';
298
      fifo_wbyte   <= (others => '0');
299
      rd_en_s      <= '0';
300
    elsif CLK'event and CLK = '1' then
301
      fifo_wren <= '0';
302
      ready_HFW <= '0';
303
      rd_en_s   <= '0';
304
 
305
      if start_pb = '1' then
306
        rd_en_s     <= '1';
307
      end if;
308
 
309
      if HFW_running = '1' and ready_HFW = '0' then
310
        -- there is no at least one integer byte to write this time
311
        if num_fifo_wrs = 0 then
312
          ready_HFW    <= '1';
313
          if state = RUN_VLI then
314
            rd_en_s      <= '1';
315
          end if;
316
        -- single byte write to FIFO
317
        else
318
          fifo_wrt_cnt <= fifo_wrt_cnt + 1;
319
          fifo_wren    <= '1';
320
          -- last byte write
321
          if fifo_wrt_cnt + 1 = num_fifo_wrs then
322
            ready_HFW    <= '1';
323
            if state = RUN_VLI then
324
              rd_en_s      <= '1';
325
            end if;
326
            fifo_wrt_cnt <= (others => '0');
327
          end if;
328
        end if;
329
      end if;
330
 
331
      case fifo_wrt_cnt is
332
        when "00" =>
333
          fifo_wbyte <= std_logic_vector(word_reg(C_M-1 downto C_M-8));
334
        when "01" =>
335
          fifo_wbyte <= std_logic_vector(word_reg(C_M-8-1 downto C_M-16));
336
        when others =>
337
          fifo_wbyte <= (others => '0');
338
      end case;
339
      if pad_reg = '1' then
340
        fifo_wbyte <= pad_byte;
341
      end if;
342
 
343
 
344
    end if;
345
  end process;
346
 
347
  -- divide by 8
348
  num_fifo_wrs <= bit_ptr(4 downto 3);
349
 
350
  -------------------------------------------------------------------
351
  -- Variable Length Processor FSM
352
  -------------------------------------------------------------------
353
  p_vlp : process(CLK, RST)
354
  begin
355
    if RST = '1' then
356
      ready_pb     <= '0';
357
      first_rle_word <= '0';
358
      state        <= IDLE;
359
      word_reg     <= (others => '0');
360
      bit_ptr      <= (others => '0');
361
      HFW_running  <= '0';
362
      pad_reg      <= '0';
363
      pad_byte     <= (others => '0');
364
    elsif CLK'event and CLK = '1' then
365
      ready_pb  <= '0';
366
 
367
      case state is
368
 
369
        when IDLE =>
370
          if start_pb = '1' then
371
            first_rle_word <= '1';
372
            state       <= RUN_VLC;
373
          end if;
374
 
375
        when RUN_VLC =>
376
          -- data valid DC or data valid AC
377
          if (d_val_d2 = '1' and first_rle_word = '1') or
378
             (d_val = '1' and first_rle_word = '0') then
379
            for i in 0 to C_M-1 loop
380
              if i < to_integer(VLC_size) then
381
                word_reg(C_M-1-to_integer(bit_ptr)-i) <= VLC(to_integer(VLC_size)-1-i);
382
              end if;
383
            end loop;
384
            bit_ptr <= bit_ptr + resize(VLC_size,bit_ptr'length);
385
 
386
            -- HandleFifoWrites
387
            HFW_running  <= '1';
388
          -- HandleFifoWrites completed
389
          elsif HFW_running = '1' and
390
                (num_fifo_wrs = 0 or fifo_wrt_cnt + 1 = num_fifo_wrs) then
391
            -- shift word reg left to skip bytes already written to FIFO
392
            word_reg <= shift_left(word_reg, to_integer(num_fifo_wrs & "000"));
393
            -- adjust bit pointer after some bytes were written to FIFO
394
            -- modulo 8 operation
395
            bit_ptr <= bit_ptr - (num_fifo_wrs & "000");
396
            HFW_running     <= '0';
397
            first_rle_word  <= '0';
398
            state           <= RUN_VLI;
399
          end if;
400
 
401
        when RUN_VLI =>
402
          if HFW_running = '0' then
403
 
404
            for i in 0 to C_M-1 loop
405
              if i < to_integer(VLI_ext_size) then
406
                word_reg(C_M-1-to_integer(bit_ptr)-i)
407
                  <= VLI_ext(to_integer(VLI_ext_size)-1-i);
408
              end if;
409
            end loop;
410
 
411
            bit_ptr <= bit_ptr + resize(VLI_ext_size,bit_ptr'length);
412
 
413
            -- HandleFifoWrites
414
            HFW_running <= '1';
415
          -- HandleFifoWrites completed
416
          elsif HFW_running = '1' and
417
                (num_fifo_wrs = 0 or fifo_wrt_cnt + 1 = num_fifo_wrs) then
418
            -- shift word reg left to skip bytes already written to FIFO
419
            word_reg <= shift_left(word_reg, to_integer(num_fifo_wrs & "000"));
420
            -- adjust bit pointer after some bytes were written to FIFO
421
            -- modulo 8 operation
422
            bit_ptr <= bit_ptr - (num_fifo_wrs & "000");
423
            HFW_running <= '0';
424
 
425
            -- end of block
426
            if rle_fifo_empty = '1' then
427
              -- end of segment
428
              if bit_ptr - (num_fifo_wrs & "000") /= 0 and last_block = '1' then
429
                state <= PAD;
430
              else
431
                ready_pb <= '1';
432
                state    <= IDLE;
433
              end if;
434
            else
435
              state          <= RUN_VLC;
436
            end if;
437
          end if;
438
 
439
        -- end of segment which requires bit padding
440
        when PAD =>
441
          if HFW_running = '0' then
442
            -- 1's bit padding to integer number of bytes
443
            for i in 0 to 7 loop
444
              if i < bit_ptr then
445
                pad_byte(7-i) <= word_reg(C_M-1-i);
446
              else
447
                pad_byte(7-i) <= '1';
448
              end if;
449
            end loop;
450
            pad_reg <= '1';
451
 
452
            bit_ptr <= to_unsigned(8, bit_ptr'length);
453
 
454
            -- HandleFifoWrites
455
            HFW_running <= '1';
456
         elsif HFW_running = '1' and
457
                (num_fifo_wrs = 0 or fifo_wrt_cnt + 1 = num_fifo_wrs) then
458
           bit_ptr      <= (others => '0');
459
           HFW_running  <= '0';
460
           pad_reg      <= '0';
461
 
462
           ready_pb <= '1';
463
           state <= IDLE;
464
         end if;
465
 
466
        when others =>
467
 
468
      end case;
469
 
470
      if sof = '1' then
471
        bit_ptr <= (others => '0');
472
      end if;
473
 
474
    end if;
475
  end process;
476
 
477
 
478
end architecture RTL;
479
-------------------------------------------------------------------------------
480
-- Architecture: end
481
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.