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

Subversion Repositories mkjpeg

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

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

powered by: WebSVN 2.1.0

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