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

Subversion Repositories mkjpeg

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

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
        cmp_max            : in  std_logic_vector(1 downto 0);
59
 
60
        -- RLE
61
        rle_buf_sel        : out std_logic;
62
        rd_en              : out std_logic;
63
        runlength          : in  std_logic_vector(3 downto 0);
64
        VLI_size           : in  std_logic_vector(3 downto 0);
65
        VLI                : in  std_logic_vector(11 downto 0);
66
        d_val              : in  std_logic;
67
        rle_fifo_empty     : in  std_logic;
68
 
69
        -- Byte Stuffer
70
        bs_buf_sel         : in  std_logic;
71
        bs_fifo_empty      : out std_logic;
72
        bs_rd_req          : in  std_logic;
73
        bs_packed_byte     : out std_logic_vector(7 downto 0)
74
    );
75
end entity Huffman;
76
 
77
-------------------------------------------------------------------------------
78
-------------------------------------------------------------------------------
79
----------------------------------- ARCHITECTURE ------------------------------
80
-------------------------------------------------------------------------------
81
-------------------------------------------------------------------------------
82
architecture RTL of Huffman is
83
 
84
  type T_STATE is (IDLE, RUN_VLC, RUN_VLI, PAD);
85
 
86
  constant C_M             : integer := 23;
87
  constant BLK_SIZE        : integer := 64;
88
 
89
  signal state             : T_STATE;
90
  signal rle_buf_sel_s     : std_logic;
91
  signal first_rle_word    : std_logic;
92
  signal word_reg          : unsigned(C_M-1 downto 0);
93
  signal bit_ptr           : unsigned(4 downto 0);
94
  signal num_fifo_wrs      : unsigned(1 downto 0);
95
  signal VLI_ext           : unsigned(15 downto 0);
96
  signal VLI_ext_size      : unsigned(4 downto 0);
97
  signal ready_HFW         : std_logic;
98
  signal fifo_wbyte        : std_logic_vector(7 downto 0);
99
  signal fifo_wrt_cnt      : unsigned(1 downto 0);
100
  signal fifo_wren         : std_logic;
101
  signal last_block        : std_logic;
102
  signal image_area_size   : unsigned(33 downto 0);
103
  signal block_cnt         : unsigned(27 downto 0);
104
  signal VLC_size          : unsigned(4 downto 0);
105
  signal VLC               : unsigned(15 downto 0);
106
  signal VLC_DC_size       : std_logic_vector(3 downto 0);
107
  signal VLC_DC            : unsigned(8 downto 0);
108
  signal VLC_AC_size       : unsigned(4 downto 0);
109
  signal VLC_AC            : unsigned(15 downto 0);
110
  signal vlc_vld           : std_logic;
111
  signal d_val_d1          : std_logic;
112
  signal d_val_d2          : std_logic;
113
  signal d_val_d3          : std_logic;
114
  signal d_val_d4          : std_logic;
115
  signal VLI_size_d        : std_logic_vector(3 downto 0);
116
  signal VLI_d             : std_logic_vector(11 downto 0);
117
  signal VLI_size_d1       : std_logic_vector(3 downto 0);
118
  signal VLI_d1            : std_logic_vector(11 downto 0);
119
  signal HFW_running       : std_logic;
120
  signal runlength_r       : std_logic_vector(3 downto 0);
121
  signal VLI_size_r        : std_logic_vector(3 downto 0);
122
  signal VLI_r             : std_logic_vector(11 downto 0);
123
  signal rd_en_s           : std_logic;
124
  signal pad_byte          : std_logic_vector(7 downto 0);
125
  signal pad_reg           : std_logic;
126 36 mikel262
  signal VLC_CR_DC_size    : std_logic_vector(3 downto 0);
127
  signal VLC_CR_DC         : unsigned(10 downto 0);
128
  signal VLC_CR_AC_size    : unsigned(4 downto 0);
129
  signal VLC_CR_AC         : unsigned(15 downto 0);
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
        if huf_sm_settings.cmp_idx = 0 then
260
          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
        if huf_sm_settings.cmp_idx = 0 then
271
          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
      image_area_size <= unsigned(cmp_max)*
292
                         unsigned(img_size_x)*unsigned(img_size_y);
293
 
294
      if sof = '1' then
295
        block_cnt <= (others => '0');
296
      elsif start_pb = '1' then
297
        block_cnt <= block_cnt + 1;
298
      end if;
299
 
300
      if block_cnt = image_area_size(33 downto 6) then
301
        last_block <= '1';
302
      else
303
        last_block <= '0';
304
      end if;
305
 
306
    end if;
307
  end process;
308
 
309
  VLI_ext      <= unsigned("0000" & VLI_d1);
310
  VLI_ext_size <= unsigned('0' & VLI_size_d1);
311
 
312
  -------------------------------------------------------------------
313
  -- delay line
314
  -------------------------------------------------------------------
315
  p_vli_dly : process(CLK, RST)
316
  begin
317
    if RST = '1' then
318
      VLI_d       <= (others => '0');
319
      VLI_size_d  <= (others => '0');
320
      VLI_d1      <= (others => '0');
321
      VLI_size_d1 <= (others => '0');
322
      d_val_d1    <= '0';
323
      d_val_d2    <= '0';
324
      d_val_d3    <= '0';
325
      d_val_d4    <= '0';
326
    elsif CLK'event and CLK = '1' then
327
      VLI_d1      <= VLI_r;
328
      VLI_size_d1 <= VLI_size_r;
329
 
330
      VLI_d       <= VLI_d1;
331
      VLI_size_d  <= VLI_size_d1;
332
 
333
      d_val_d1   <= d_val;
334
      d_val_d2   <= d_val_d1;
335
      d_val_d3   <= d_val_d2;
336
      d_val_d4   <= d_val_d3;
337
    end if;
338
  end process;
339
 
340
  -------------------------------------------------------------------
341
  -- HandleFifoWrites
342
  -------------------------------------------------------------------
343
  p_HandleFifoWrites : process(CLK, RST)
344
  begin
345
    if RST = '1' then
346
      ready_HFW    <= '0';
347
      fifo_wrt_cnt <= (others => '0');
348
      fifo_wren    <= '0';
349
      fifo_wbyte   <= (others => '0');
350
      rd_en_s      <= '0';
351
    elsif CLK'event and CLK = '1' then
352
      fifo_wren <= '0';
353
      ready_HFW <= '0';
354
      rd_en_s   <= '0';
355
 
356
      if start_pb = '1' then
357
        rd_en_s     <= '1';
358
      end if;
359
 
360
      if HFW_running = '1' and ready_HFW = '0' then
361
        -- there is no at least one integer byte to write this time
362
        if num_fifo_wrs = 0 then
363
          ready_HFW    <= '1';
364
          if state = RUN_VLI then
365
            rd_en_s      <= '1';
366
          end if;
367
        -- single byte write to FIFO
368
        else
369
          fifo_wrt_cnt <= fifo_wrt_cnt + 1;
370
          fifo_wren    <= '1';
371
          -- last byte write
372
          if fifo_wrt_cnt + 1 = num_fifo_wrs then
373
            ready_HFW    <= '1';
374
            if state = RUN_VLI then
375
              rd_en_s      <= '1';
376
            end if;
377
            fifo_wrt_cnt <= (others => '0');
378
          end if;
379
        end if;
380
      end if;
381
 
382
      case fifo_wrt_cnt is
383
        when "00" =>
384
          fifo_wbyte <= std_logic_vector(word_reg(C_M-1 downto C_M-8));
385
        when "01" =>
386
          fifo_wbyte <= std_logic_vector(word_reg(C_M-8-1 downto C_M-16));
387
        when others =>
388
          fifo_wbyte <= (others => '0');
389
      end case;
390
      if pad_reg = '1' then
391
        fifo_wbyte <= pad_byte;
392
      end if;
393
 
394
 
395
    end if;
396
  end process;
397
 
398
  -- divide by 8
399
  num_fifo_wrs <= bit_ptr(4 downto 3);
400
 
401
  -------------------------------------------------------------------
402
  -- Variable Length Processor FSM
403
  -------------------------------------------------------------------
404
  p_vlp : process(CLK, RST)
405
  begin
406
    if RST = '1' then
407
      ready_pb     <= '0';
408
      first_rle_word <= '0';
409
      state        <= IDLE;
410
      word_reg     <= (others => '0');
411
      bit_ptr      <= (others => '0');
412
      HFW_running  <= '0';
413
      pad_reg      <= '0';
414
      pad_byte     <= (others => '0');
415
    elsif CLK'event and CLK = '1' then
416
      ready_pb  <= '0';
417
 
418
      case state is
419
 
420
        when IDLE =>
421
          if start_pb = '1' then
422
            first_rle_word <= '1';
423
            state       <= RUN_VLC;
424
          end if;
425
 
426
        when RUN_VLC =>
427
          -- data valid DC or data valid AC
428
          if (d_val_d2 = '1' and first_rle_word = '1') or
429
             (d_val = '1' and first_rle_word = '0') then
430
            for i in 0 to C_M-1 loop
431
              if i < to_integer(VLC_size) then
432
                word_reg(C_M-1-to_integer(bit_ptr)-i) <= VLC(to_integer(VLC_size)-1-i);
433
              end if;
434
            end loop;
435
            bit_ptr <= bit_ptr + resize(VLC_size,bit_ptr'length);
436
 
437
            -- HandleFifoWrites
438
            HFW_running  <= '1';
439
          -- HandleFifoWrites completed
440
          elsif HFW_running = '1' and
441
                (num_fifo_wrs = 0 or fifo_wrt_cnt + 1 = num_fifo_wrs) then
442
            -- shift word reg left to skip bytes already written to FIFO
443
            word_reg <= shift_left(word_reg, to_integer(num_fifo_wrs & "000"));
444
            -- adjust bit pointer after some bytes were written to FIFO
445
            -- modulo 8 operation
446
            bit_ptr <= bit_ptr - (num_fifo_wrs & "000");
447
            HFW_running     <= '0';
448
            first_rle_word  <= '0';
449
            state           <= RUN_VLI;
450
          end if;
451
 
452
        when RUN_VLI =>
453
          if HFW_running = '0' then
454
 
455
            for i in 0 to C_M-1 loop
456
              if i < to_integer(VLI_ext_size) then
457
                word_reg(C_M-1-to_integer(bit_ptr)-i)
458
                  <= VLI_ext(to_integer(VLI_ext_size)-1-i);
459
              end if;
460
            end loop;
461
 
462
            bit_ptr <= bit_ptr + resize(VLI_ext_size,bit_ptr'length);
463
 
464
            -- HandleFifoWrites
465
            HFW_running <= '1';
466
          -- HandleFifoWrites completed
467
          elsif HFW_running = '1' and
468
                (num_fifo_wrs = 0 or fifo_wrt_cnt + 1 = num_fifo_wrs) then
469
            -- shift word reg left to skip bytes already written to FIFO
470
            word_reg <= shift_left(word_reg, to_integer(num_fifo_wrs & "000"));
471
            -- adjust bit pointer after some bytes were written to FIFO
472
            -- modulo 8 operation
473
            bit_ptr <= bit_ptr - (num_fifo_wrs & "000");
474
            HFW_running <= '0';
475
 
476
            -- end of block
477
            if rle_fifo_empty = '1' then
478
              -- end of segment
479
              if bit_ptr - (num_fifo_wrs & "000") /= 0 and last_block = '1' then
480
                state <= PAD;
481
              else
482
                ready_pb <= '1';
483
                state    <= IDLE;
484
              end if;
485
            else
486
              state          <= RUN_VLC;
487
            end if;
488
          end if;
489
 
490
        -- end of segment which requires bit padding
491
        when PAD =>
492
          if HFW_running = '0' then
493
            -- 1's bit padding to integer number of bytes
494
            for i in 0 to 7 loop
495
              if i < bit_ptr then
496
                pad_byte(7-i) <= word_reg(C_M-1-i);
497
              else
498
                pad_byte(7-i) <= '1';
499
              end if;
500
            end loop;
501
            pad_reg <= '1';
502
 
503
            bit_ptr <= to_unsigned(8, bit_ptr'length);
504
 
505
            -- HandleFifoWrites
506
            HFW_running <= '1';
507
         elsif HFW_running = '1' and
508
                (num_fifo_wrs = 0 or fifo_wrt_cnt + 1 = num_fifo_wrs) then
509
           bit_ptr      <= (others => '0');
510
           HFW_running  <= '0';
511
           pad_reg      <= '0';
512
 
513
           ready_pb <= '1';
514
           state <= IDLE;
515
         end if;
516
 
517
        when others =>
518
 
519
      end case;
520
 
521
      if sof = '1' then
522
        bit_ptr <= (others => '0');
523
      end if;
524
 
525
    end if;
526
  end process;
527
 
528
 
529
end architecture RTL;
530
-------------------------------------------------------------------------------
531
-- Architecture: end
532
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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