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

Subversion Repositories mkjpeg

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

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

powered by: WebSVN 2.1.0

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