OpenCores
URL https://opencores.org/ocsvn/lzrw1-compressor-core/lzrw1-compressor-core/trunk

Subversion Repositories lzrw1-compressor-core

[/] [lzrw1-compressor-core/] [trunk/] [hw/] [HDL/] [LZRWcompressor.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 habicht
--/**************************************************************************************************************
2
--*
3
--*    L Z R W 1   E N C O D E R   C O R E
4
--*
5
--*  A high throughput loss less data compression core.
6
--* 
7
--* Copyright 2012-2013   Lukas Schrittwieser (LS)
8
--*
9
--*    This program is free software: you can redistribute it and/or modify
10
--*    it under the terms of the GNU General Public License as published by
11
--*    the Free Software Foundation, either version 2 of the License, or
12
--*    (at your option) any later version.
13
--*
14
--*    This program is distributed in the hope that it will be useful,
15
--*    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
--*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
--*    GNU General Public License for more details.
18
--*
19
--*    You should have received a copy of the GNU General Public License
20
--*    along with this program; if not, write to the Free Software
21
--*    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22
--*    Or see <http://www.gnu.org/licenses/>
23
--*
24
--***************************************************************************************************************
25
--*
26
--* Change Log:
27
--*
28
--* Version 1.0 - 2012/6/17 - LS
29
--*   started file
30
--*
31
--* Version 1.0 - 2013/04/05 - LS
32
--*   release
33
--*
34
--***************************************************************************************************************
35
--*
36
--* Naming convention:  http://dz.ee.ethz.ch/en/information/hdl-help/vhdl-naming-conventions.html
37
--*
38
--***************************************************************************************************************
39
--* 
40
--* This is the main file of the compression core. It connects several
41
--* sub-cores in a pipeline. Data IO is bytewise.
42
--*
43
--***************************************************************************************************************
44
library IEEE;
45
use IEEE.STD_LOGIC_1164.all;
46
use IEEE.NUMERIC_STD.all;
47
 
48
library UNISIM;
49
use UNISIM.VComponents.all;
50
 
51
entity LZRWcompressor is
52
  port (
53
    ClkxCI         : in  std_logic;
54
    RstxRI         : in  std_logic;
55
    DataInxDI      : in  std_logic_vector(7 downto 0);  -- uncompressed data input
56
    StrobexSI      : in  std_logic;     -- strobe for input data
57
    FlushBufxSI    : in  std_logic;
58
    BusyxSO        : out std_logic;  -- data can only be strobed in if this is low
59
    DonexSO        : out std_logic;  -- flush is done, all data has been processed
60
    BufOutxDO      : out std_logic_vector(7 downto 0);
61
    OutputValidxSO : out std_logic;
62
    RdStrobexSI    : in  std_logic;
63
    LengthxDO      : out integer range 0 to 1024
64
    );
65
end LZRWcompressor;
66
 
67
architecture Behavioral of LZRWcompressor is
68
 
69
 
70
  component HashTable
71
    generic (
72
      entryBitWidth : integer);
73
    port (
74
      ClkxCI      : in  std_logic;
75
      RstxRI      : in  std_logic;
76
      NewEntryxDI : in  std_logic_vector(entryBitWidth-1 downto 0);
77
      EnWrxSI     : in  std_logic;
78
      Key0xDI     : in  std_logic_vector(7 downto 0);
79
      Key1xDI     : in  std_logic_vector(7 downto 0);
80
      Key2xDI     : in  std_logic_vector(7 downto 0);
81
      OldEntryxDO : out std_logic_vector(entryBitWidth-1 downto 0));
82
  end component;
83
 
84
  component historyBuffer
85
    port (
86
      ClkxCI          : in  std_logic;
87
      RstxRI          : in  std_logic;
88
      WriteInxDI      : in  std_logic_vector(7 downto 0);
89
      WExSI           : in  std_logic;
90
      NextWrAdrxDO    : out std_logic_vector(11 downto 0);
91
      RExSI           : in  std_logic;
92
      ReadBackAdrxDI  : in  std_logic_vector(11 downto 2);
93
      ReadBackxDO     : out std_logic_vector(16*8-1 downto 0);
94
      ReadBackDonexSO : out std_logic);
95
  end component;
96
 
97
  component comparator
98
    port (
99
      LookAheadxDI    : in  std_logic_vector(16*8-1 downto 0);
100
      LookAheadLenxDI : in  integer range 0 to 16;
101
      CandidatexDI    : in  std_logic_vector(16*8-1 downto 0);
102
      CandidateLenxDI : in  integer range 0 to 16;
103
      MatchLenxDO     : out integer range 0 to 16);
104
  end component;
105
 
106
  component outputEncoder
107
    generic (
108
      frameSize   : integer;
109
      minMatchLen : integer;
110
      maxMatchLen : integer);
111
    port (
112
      ClkxCI          : in  std_logic;
113
      RstxRI          : in  std_logic;
114
      OffsetxDI       : in  std_logic_vector(11 downto 0);
115
      MatchLengthxDI  : in  integer range 0 to maxMatchLen;
116
      EnxSI           : in  std_logic;
117
      EndOfDataxSI    : in  std_logic;
118
      LiteralxDI      : in  std_logic_vector(7 downto 0);
119
      BodyStrobexSO   : out std_logic;
120
      BodyOutxDO      : out std_logic_vector(7 downto 0);
121
      HeaderStrobexSO : out std_logic;
122
      HeaderOutxDO    : out std_logic_vector(frameSize-1 downto 0);
123
      DonexSO         : out std_logic);
124
  end component;
125
 
126
  component outputFIFO
127
    generic (
128
      frameSize : integer);
129
    port (
130
      ClkxCI          : in  std_logic;
131
      RstxRI          : in  std_logic;
132
      BodyDataxDI     : in  std_logic_vector(7 downto 0);
133
      BodyStrobexSI   : in  std_logic;
134
      HeaderDataxDI   : in  std_logic_vector(frameSize-1 downto 0);
135
      HeaderStrobexSI : in  std_logic;
136
      BuffersEmptyxSO : out std_logic;
137
      BufOutxDO       : out std_logic_vector(7 downto 0);
138
      OutputValidxSO  : out std_logic;
139
      RdStrobexSI     : in  std_logic;
140
      LengthxDO       : out integer range 0 to 1024);
141
  end component;
142
 
143
  constant HIST_BUF_LEN   : integer := 4096;  -- length of the history buffer in bytes (DO NOT CHANGE!!)
144
  constant LOOK_AHEAD_LEN : integer := 16;  -- length of the look ahead buffer in bytes (DO NOT CHANGE!!)
145
  constant OUT_FIFO_THR   : integer := 1000;  -- output length at which we set busy high. Should be at least one max frame size below 1024
146
 
147
  type lookAheadBufType is array (LOOK_AHEAD_LEN-1 downto 0) of std_logic_vector(7 downto 0);
148
  type ctrlFSMType is (ST_FILL_LOOK_AHEAD, ST_RUN, ST_DRAIN_LOOK_AHEAD, ST_DONE);
149
 
150
  signal LookAheadBufxDN, LookAheadBufxDP     : lookAheadBufType                  := (others => (others => '0'));
151
  signal LookAheadLenxDN, LookAheadLenxDP     : integer range 0 to LOOK_AHEAD_LEN := 0;
152
  signal ShiftLookAheadxSN, ShiftLookAheadxSP : std_logic                         := '0';
153
  signal Strobe0xSN, Strobe0xSP               : std_logic                         := '0';
154
  signal HistBufLen0xDN, HistBufLen0xDP       : integer range 0 to HIST_BUF_LEN   := 0;  -- count history buffer length at startup
155
  signal HistBufOutxD                         : std_logic_vector(LOOK_AHEAD_LEN*8-1 downto 0);
156
  signal EndOfData0xSN, EndOfData0xSP         : std_logic                         := '0';
157
  signal DataIn0xDN, DataIn0xDP               : std_logic_vector(7 downto 0)      := x"00";
158
  signal WrHistBufxS                          : std_logic;
159
  signal LookAheadPtr0xD                      : std_logic_vector(11 downto 0);
160
  signal NextWrAdrxD                          : std_logic_vector(11 downto 0);
161
  signal BusyxSN, BusyxSP                     : std_logic                         := '0';
162
  signal StatexSN, StatexSP                   : ctrlFSMType                       := ST_FILL_LOOK_AHEAD;
163
 
164
  signal HashTableEntryxD                   : std_logic_vector(11 downto 0);  -- entry found by the hash table
165
  signal LookAheadLen1xDN, LookAheadLen1xDP : integer range 0 to LOOK_AHEAD_LEN := 0;
166
  signal Strobe1xSN, Strobe1xSP             : std_logic                         := '0';
167
  signal HistBufLen1xDN, HistBufLen1xDP     : integer range 0 to HIST_BUF_LEN   := 0;
168
  signal EndOfData1xSN, EndOfData1xSP       : std_logic                         := '0';
169
  signal LookAheadBuf1xDN, LookAheadBuf1xDP : lookAheadBufType                  := (others => (others => '0'));
170
  signal WrAdr1xDN, WrAdr1xDP               : std_logic_vector(11 downto 0)     := (others => '0');
171
  signal LookAheadPtr1xDN, LookAheadPtr1xDP : std_logic_vector(11 downto 0)     := (others => '0');
172
  signal CandAddr1xDN, CandAddr1xDP         : std_logic_vector(11 downto 0)     := (others => '0');
173
 
174
  signal LookAheadLen2xDN, LookAheadLen2xDP     : integer range 0 to LOOK_AHEAD_LEN             := 0;
175
  signal LookAheadBuf2xDN, LookAheadBuf2xDP     : lookAheadBufType                              := (others => (others => '0'));
176
  signal Strobe2xSN, Strobe2xSP                 : std_logic                                     := '0';
177
  signal HistBufLen2xDN, HistBufLen2xDP         : integer range 0 to HIST_BUF_LEN               := 0;
178
  signal Candidate2xDN, Candidate2xDP           : std_logic_vector(LOOK_AHEAD_LEN*8-1 downto 0) := (others => '0');
179
  signal NextWrAdr2xDN, NextWrAdr2xDP           : integer range 0 to LOOK_AHEAD_LEN             := 0;
180
  signal CandAddr2xDN, CandAddr2xDP             : std_logic_vector(11 downto 0)                 := (others => '0');
181
  signal CandLen2xD                             : integer range 0 to LOOK_AHEAD_LEN;
182
  signal EndOfData2xSN, EndOfData2xSP           : std_logic                                     := '0';
183
  signal OffsetIntxD                            : integer range -HIST_BUF_LEN to HIST_BUF_LEN;
184
  signal OffsetxD                               : std_logic_vector(11 downto 0);
185
  signal HashTableEntry2xDN, HashTableEntry2xDP : std_logic_vector(11 downto 0)                 := (others => '0');
186
  signal MaxCandLenxD                           : integer range 0 to LOOK_AHEAD_LEN;
187
 
188
  signal MatchLenxD, MatchLenLimitedxD      : integer range 0 to LOOK_AHEAD_LEN := 0;
189
  signal LookAheadPtr2xDN, LookAheadPtr2xDP : std_logic_vector(11 downto 0)     := (others => '0');
190
  signal CompLAIn3xD                        : std_logic_vector(LOOK_AHEAD_LEN*8-1 downto 0);
191
  signal HeaderStrobexS                     : std_logic;
192
  signal HeaderDataxD                       : std_logic_vector(7 downto 0);
193
  signal BodyStrobexS                       : std_logic;
194
  signal BodyDataxD                         : std_logic_vector(7 downto 0);
195
  signal FifoBuffersEmptyxS                 : std_logic;
196
  signal OutFIFOLengthxD                    : integer range 0 to 1024;
197
  signal EncDonexS                          : std_logic;
198
  signal Done3xSN, Done3xSP                 : std_logic                         := '0';
199
 
200
begin
201
 
202
  -----------------------------------------------------------------------------
203
  -- Pipeline stage 0
204
  -----------------------------------------------------------------------------
205
 
206
  -- control FSM for look ahead buffer
207
  process (DataIn0xDP, DataInxDI, FlushBufxSI, LookAheadLenxDP,
208
           OutFIFOLengthxD, StatexSP, Strobe0xSP, StrobexSI)
209
  begin
210
    StatexSN          <= StatexSP;
211
    ShiftLookAheadxSN <= '0';
212
    WrHistBufxS       <= '0';
213
    Strobe0xSN        <= '0';
214
    EndOfData0xSN     <= '0';
215
    DataIn0xDN        <= DataIn0xDP;
216
    BusyxSN           <= '0';
217
 
218
    case StatexSP is
219
      when ST_FILL_LOOK_AHEAD =>
220
        -- don't shift here, we are still loading data
221
        --ShiftLookAheadxSN <= StrobexSI;  -- the shift is delayed by one cycle because we have to process the byte first
222
        WrHistBufxS       <= StrobexSI;
223
        DataIn0xDN        <= DataInxDI;
224
        if FlushBufxSI='1' then
225
          StatexSN <= ST_DRAIN_LOOK_AHEAD;
226
        elsif LookAheadLenxDP = LOOK_AHEAD_LEN-1 then
227
          -- this byte is number look_ahead_len-1, so it is the last one before the buffer is full
228
          -- the buffer will be full with the next incoming byte, so the next
229
          -- one can be processed regularely
230
          StatexSN <= ST_RUN;
231
        end if;
232
 
233
      when ST_RUN =>
234
        ShiftLookAheadxSN <= StrobexSI;
235
        Strobe0xSN        <= StrobexSI;  -- pass on strobe to pipeline
236
        WrHistBufxS       <= StrobexSI;
237
        DataIn0xDN        <= DataInxDI;
238
        if FlushBufxSI = '1' then
239
          StatexSN <= ST_DRAIN_LOOK_AHEAD;
240
        end if;
241
 
242
      when ST_DRAIN_LOOK_AHEAD =>
243
        -- create a strobe every second cycle
244
        if LookAheadLenxDP > 0 and Strobe0xSP = '0' then
245
          ShiftLookAheadxSN <= '1';
246
          Strobe0xSN        <= '1';
247
        end if;
248
        if LookAheadLenxDP = 0 then
249
          EndOfData0xSN <= '1';
250
          StatexSN      <= ST_DONE;
251
        end if;
252
 
253
      when ST_DONE => null;
254
 
255
      when others => StatexSN <= ST_DONE;  -- fail save, just block
256
    end case;
257
 
258
    if OutFIFOLengthxD > OUT_FIFO_THR then
259
      BusyxSN <= '1';                   -- request stop of data input if output FIFO is full
260
    end if;
261
  end process;
262
 
263
  -- we can accept data only every second clock cycle -> feed strobe back as
264
  -- busy signal
265
  BusyxSO <= BusyxSP or StrobexSI;
266
 
267
  -- implement a shift register for the look ahead buffer
268
  lookAheadProc : process (DataInxDI, ShiftLookAheadxSP, StatexSP, StrobexSI,
269
                           lookAheadBufxDP, lookAheadLenxDP)
270
  begin  -- process lookAheadProc
271
    lookAheadLenxDN <= lookAheadLenxDP;
272
 
273
    if StrobexSI = '1' then
274
      -- load new data into MSB
275
      --lookAheadBufxDN(LOOK_AHEAD_LEN-1) <= DataInxDI;
276
      -- increase length counter if it is below the top 
277
      if lookAheadLenxDP < LOOK_AHEAD_LEN then
278
        lookAheadLenxDN <= lookAheadLenxDP + 1;
279
      end if;
280
    end if;
281
 
282
    if ShiftLookAheadxSP = '1' then
283
      -- decrease buffer length counter if there is no valid input data
284
      if lookAheadLenxDP > 0 and StrobexSI = '0' and StatexSP /= ST_FILL_LOOK_AHEAD then
285
        lookAheadLenxDN <= lookAheadLenxDP - 1;
286
      end if;
287
    end if;
288
 
289
  end process lookAheadProc;
290
 
291
  -- implement actual shift register
292
  lookAheadShiftReg : for i in 0 to LOOK_AHEAD_LEN-2 generate
293
    process (DataInxDI, LookAheadLenxDP, ShiftLookAheadxSP, StrobexSI,
294
             lookAheadBufxDP)
295
    begin  -- process
296
      lookAheadBufxDN(i) <= lookAheadBufxDP(i);  -- default: do nothing
297
      if ShiftLookAheadxSP = '1' then
298
        lookAheadBufxDN(i) <= lookAheadBufxDP(i+1);  -- shift done one entry
299
      elsif LookAheadLenxDP = i and StrobexSI = '1' then
300
        lookAheadBufxDN(i) <= DataInxDI;  -- load new byte into shift register
301
      end if;
302
    end process;
303
  end generate lookAheadShiftReg;
304
  -- implement the top most byte of the shift register
305
  lookAheadBufxDN(LOOK_AHEAD_LEN-1) <= DataInxDI when lookAheadLenxDP >= LOOK_AHEAD_LEN-1 and StrobexSI = '1' else lookAheadBufxDP(LOOK_AHEAD_LEN-1);
306
 
307
  HashTableInst : HashTable
308
    generic map (
309
      entryBitWidth => 12)
310
    port map (
311
      ClkxCI      => ClkxCI,
312
      RstxRI      => RstxRI,
313
      NewEntryxDI => LookAheadPtr0xD,
314
      EnWrxSI     => Strobe0xSP,  -- delay write by one cycle because we have to read first
315
      Key0xDI     => lookAheadBufxDP(0),
316
      Key1xDI     => lookAheadBufxDP(1),
317
      Key2xDI     => lookAheadBufxDP(2),
318
      OldEntryxDO => HashTableEntryxD);
319
 
320
  historyBufferInst : historyBuffer
321
    port map (
322
      ClkxCI          => ClkxCI,
323
      RstxRI          => RstxRI,
324
      WriteInxDI      => DataInxDI,
325
      WExSI           => WrHistBufxS,
326
      NextWrAdrxDO    => NextWrAdrxD,
327
      RExSI           => Strobe0xSP,  -- delay read by one cycle (we write first)
328
      ReadBackAdrxDI  => HashTableEntryxD(11 downto 2),
329
      ReadBackxDO     => HistBufOutxD,
330
      ReadBackDonexSO => open);
331
 
332
-- calculate a pointer to the beginning of the look ahead section in the
333
-- history buffer
334
  process (LookAheadLenxDP, NextWrAdrxD)
335
  begin  -- process
336
    if LookAheadLenxDP <= to_integer(unsigned(NextWrAdrxD)) then
337
      -- this is the regular case, write index is bigger than look ahead len ->
338
      -- no wrap around in buffer
339
      LookAheadPtr0xD <= std_logic_vector(to_unsigned(to_integer(unsigned(NextWrAdrxD))-LookAheadLenxDP, 12));
340
    else
341
      -- wrap around -> add history buffer length to get a pos value
342
      LookAheadPtr0xD <= std_logic_vector(to_unsigned(HIST_BUF_LEN + to_integer(unsigned(NextWrAdrxD)) - LookAheadLenxDP, 12));
343
    end if;
344
  end process;
345
 
346
 
347
-- count the number of bytes in the history buffer. Note that we only count
348
-- the _history_ so only bytes which have already been processed.
349
  process (HistBufLen0xDP, Strobe0xSP)
350
  begin
351
    HistBufLen0xDN <= HistBufLen0xDP;
352
    -- count the number of processed bytes
353
    if Strobe0xSP = '1' then
354
      if HistBufLen0xDP < HIST_BUF_LEN - LOOK_AHEAD_LEN then
355
        HistBufLen0xDN <= HistBufLen0xDP + 1;
356
      end if;
357
    end if;
358
  end process;
359
 
360
 
361
-----------------------------------------------------------------------------
362
-- pipeline stage 1
363
--
364
-- wait for data from histroy buffer
365
-----------------------------------------------------------------------------
366
 
367
  process (CandAddr1xDP, HashTableEntryxD, HistBufLen0xDP, HistBufLen1xDP,
368
           LookAheadBuf1xDP, LookAheadLen1xDP, LookAheadPtr0xD,
369
           LookAheadPtr1xDP, Strobe0xSP, lookAheadBufxDP, lookAheadLenxDP)
370
  begin
371
    LookAheadLen1xDN <= LookAheadLen1xDP;
372
    LookAheadBuf1xDN <= LookAheadBuf1xDP;
373
    LookAheadPtr1xDN <= LookAheadPtr1xDP;
374
    HistBufLen1xDN   <= HistBufLen1xDP;
375
    CandAddr1xDN     <= CandAddr1xDP;
376
 
377
    if Strobe0xSP = '1' then
378
      LookAheadLen1xDN <= lookAheadLenxDP;
379
      LookAheadBuf1xDN <= lookAheadBufxDP;
380
      CandAddr1xDN     <= HashTableEntryxD;
381
      LookAheadPtr1xDN <= LookAheadPtr0xD;
382
      HistBufLen1xDN   <= HistBufLen0xDP;
383
    end if;
384
 
385
  end process;
386
 
387
-- signals to be passed on
388
  Strobe1xSN    <= Strobe0xSP;
389
  EndOfData1xSN <= EndOfData0xSP;
390
 
391
 
392
 
393
-----------------------------------------------------------------------------
394
-- pipeline stage 2
395
--
396
-- shift history buffer output
397
-----------------------------------------------------------------------------
398
 
399
-- limit the max candidate length
400
  MaxCandLenxD <= LOOK_AHEAD_LEN;
401
 
402
-- use a shifter to implement the last two bytes of the address
403
  process (CandAddr1xDP, CandAddr2xDP, Candidate2xDP, HistBufLen1xDP,
404
           HistBufLen2xDP, HistBufOutxD, LookAheadBuf1xDP, LookAheadBuf2xDP,
405
           LookAheadLen1xDP, LookAheadLen2xDP, LookAheadPtr1xDP, MaxCandLenxD,
406
           Strobe1xSP)
407
  begin
408
    Candidate2xDN    <= Candidate2xDP;
409
    LookAheadBuf2xDN <= LookAheadBuf2xDP;
410
    LookAheadLen2xDN <= LookAheadLen2xDP;
411
    CandAddr2xDN     <= CandAddr2xDP;
412
    HistBufLen2xDN   <= HistBufLen2xDP;
413
 
414
    if Strobe1xSP = '1' then
415
      case CandAddr1xDP(1 downto 0) is
416
        when "00" => Candidate2xDN <= HistBufOutxD;  -- no shifting
417
                     CandLen2xD <= MaxCandLenxD;
418
        when "01" => Candidate2xDN <= x"00" & HistBufOutxD(LOOK_AHEAD_LEN*8-1 downto 8);  -- shift one byte
419
                     CandLen2xD <= MaxCandLenxD-1;  -- we shifted one byte out -> candidate is one byte shorter
420
        when "10" => Candidate2xDN <= x"0000" & HistBufOutxD(LOOK_AHEAD_LEN*8-1 downto 16);  -- shift 2 bytes
421
                     CandLen2xD <= MaxCandLenxD-2;
422
        when "11" => Candidate2xDN <= x"000000" & HistBufOutxD(LOOK_AHEAD_LEN*8-1 downto 24);  -- shift 3 bytes
423
                     CandLen2xD <= MaxCandLenxD-3;
424
        when others => null;
425
      end case;
426
 
427
      LookAheadBuf2xDN <= LookAheadBuf1xDP;
428
      LookAheadLen2xDN <= LookAheadLen1xDP;
429
      CandAddr2xDN     <= CandAddr1xDP;
430
      --   NextWrAdr2xDN    <= NextWrAdr1xDP;
431
      LookAheadPtr2xDN <= LookAheadPtr1xDP;
432
      HistBufLen2xDN   <= HistBufLen1xDP;
433
    end if;
434
  end process;
435
 
436
-- signals to be passed on to next stage
437
  HashTableEntry2xDN <= HashTableEntryxD;
438
  Strobe2xSN         <= Strobe1xSP;
439
  EndOfData2xSN      <= EndOfData1xSP;
440
 
441
 
442
-------------------------------------------------------------------------------
443
-- Pipeline Stage 3
444
--
445
-- Comparator, Offset Calculation and Data Output
446
-------------------------------------------------------------------------------
447
 
448
-- reformat two dimensional look ahead buffer into one dimensional array
449
-- not nice, I know. We should have a package defining proper types and use
450
-- them consistently...
451
  arrayReformatter : for i in 0 to LOOK_AHEAD_LEN-1 generate
452
    CompLAIn3xD((i+1)*8-1 downto i*8) <= LookAheadBuf2xDP(i);
453
  end generate arrayReformatter;
454
 
455
  comparatorInst : comparator
456
    port map (
457
      LookAheadxDI    => CompLAIn3xD,
458
      LookAheadLenxDI => LookAheadLen2xDP,
459
      CandidatexDI    => Candidate2xDP,
460
      CandidateLenxDI => CandLen2xD,
461
      MatchLenxDO     => MatchLenxD);
462
 
463
  -- calculate the offset
464
  process (CandAddr2xDP, LookAheadPtr2xDP, OffsetIntxD)
465
  begin
466
    OffsetIntxD <= -1;                  -- default: illegal offset
467
    if to_integer(unsigned(LookAheadPtr2xDP)) > to_integer(unsigned(CandAddr2xDP)) then
468
      -- this is the regular case, the candidate address is smaller (ie in the
469
      -- past) than the byte to be encoded (which is at index given by lookAheadPtr)
470
      OffsetIntxD <= to_integer(unsigned(LookAheadPtr2xDP)) - to_integer(unsigned(CandAddr2xDP)) - 1;
471
    elsif to_integer(unsigned(LookAheadPtr2xDP)) < to_integer(unsigned(CandAddr2xDP)) then
472
      -- there is a buffer wrap around between the two pointers, the offset
473
      -- would be negative -> add buffer length
474
      OffsetIntxD <= HIST_BUF_LEN + to_integer(unsigned(LookAheadPtr2xDP)) - to_integer(unsigned(CandAddr2xDP)) - 1;
475
    else
476
      -- this means that the candidate and the history buffer (byte to be
477
      -- encoded) are on the same location. This is invalid as the candidate can't be
478
      -- in the future -> create an illeagal negative offset to invalidate this match
479
      OffsetIntxD <= -1;
480
    end if;
481
    OffsetxD <= std_logic_vector(to_unsigned(OffsetIntxD, 12));
482
  end process;
483
 
484
  Done3xSN <= EncDonexS and FifoBuffersEmptyxS;
485
 
486
  -- note: the offset can't be longer than the history buffer length 
487
  -- if the offset is too long we disable the match by setting the length to 0
488
  -- we also check for illegal negative offsets
489
  MatchLenLimitedxD <= MatchLenxD when OffsetIntxD < (HistBufLen2xDP) and OffsetIntxD >= 0 else 0;
490
 
491
  outputEncoderInst : outputEncoder
492
    generic map (
493
      frameSize   => 8,
494
      minMatchLen => 3,
495
      maxMatchLen => LOOK_AHEAD_LEN)
496
    port map (
497
      ClkxCI          => ClkxCI,
498
      RstxRI          => RstxRI,
499
      OffsetxDI       => OffsetxD,
500
      MatchLengthxDI  => MatchLenLimitedxD,
501
      EnxSI           => Strobe2xSP,
502
      EndOfDataxSI    => EndOfData2xSP,
503
      LiteralxDI      => LookAheadBuf2xDP(0),
504
      BodyStrobexSO   => BodyStrobexS,
505
      BodyOutxDO      => BodyDataxD,
506
      HeaderStrobexSO => HeaderStrobexS,
507
      HeaderOutxDO    => HeaderDataxD,
508
      DonexSO         => EncDonexS);
509
 
510
 
511
  outputFIFOInst : outputFIFO
512
    generic map (
513
      frameSize => 8)  -- number of elements (pairs or literals) per frame
514
    port map (
515
      ClkxCI          => ClkxCI,
516
      RstxRI          => RstxRI,
517
      BodyDataxDI     => BodyDataxD,
518
      BodyStrobexSI   => BodyStrobexS,
519
      HeaderDataxDI   => HeaderDataxD,
520
      HeaderStrobexSI => HeaderStrobexS,
521
      BuffersEmptyxSO => FifoBuffersEmptyxS,
522
      BufOutxDO       => BufOutxDO,
523
      OutputValidxSO  => OutputValidxSO,
524
      RdStrobexSI     => RdStrobexSI,
525
      LengthxDO       => OutFIFOLengthxD);
526
 
527
  LengthxDO <= OutFIFOLengthxD;
528
  DonexSO   <= Done3xSP;
529
 
530
  -----------------------------------------------------------------------------
531
  -- GENERAL STUFF
532
  -----------------------------------------------------------------------------
533
 
534
  registers : process (ClkxCI)
535
  begin  -- process registers
536
    if ClkxCI'event and ClkxCI = '1' then
537
      if RstxRI = '1' then
538
        StatexSP          <= ST_FILL_LOOK_AHEAD;
539
        BusyxSP           <= '0';
540
        ShiftLookAheadxSP <= '0';
541
        lookAheadLenxDP   <= 0;
542
        Strobe0xSP        <= '0';
543
        LookAheadLen1xDP  <= 0;
544
        Strobe1xSP        <= '0';
545
        WrAdr1xDP         <= (others => '0');
546
        LookAheadLen2xDP  <= 0;
547
        Strobe2xSP        <= '0';
548
        HistBufLen0xDP    <= 0;
549
        EndOfData0xSP     <= '0';
550
        EndOfData1xSP     <= '0';
551
        EndOfData2xSP     <= '0';
552
        Done3xSP          <= '0';
553
      else
554
        StatexSP           <= StatexSN;
555
        BusyxSP            <= BusyxSN;
556
        ShiftLookAheadxSP  <= ShiftLookAheadxSN;
557
        lookAheadLenxDP    <= lookAheadLenxDN;
558
        lookAheadBufxDP    <= lookAheadBufxDN;
559
        Strobe0xSP         <= Strobe0xSN;
560
        HistBufLen0xDP     <= HistBufLen0xDN;
561
        DataIn0xDP         <= DataIn0xDN;
562
        lookAheadLen1xDP   <= lookAheadLen1xDN;
563
        Strobe1xSP         <= Strobe1xSN;
564
        HistBufLen1xDP     <= HistBufLen1xDN;
565
        WrAdr1xDP          <= WrAdr1xDN;
566
        LookAheadPtr1xDP   <= LookAheadPtr1xDN;
567
        LookAheadBuf1xDP   <= LookAheadBuf1xDN;
568
        LookAheadLen2xDP   <= LookAheadLen2xDN;
569
        LookAheadBuf2xDP   <= LookAheadBuf2xDN;
570
        CandAddr1xDP       <= CandAddr1xDN;
571
        Strobe2xSP         <= Strobe2xSN;
572
        HistBufLen2xDP     <= HistBufLen2xDN;
573
        NextWrAdr2xDP      <= NextWrAdr2xDN;
574
        LookAheadPtr2xDP   <= LookAheadPtr2xDN;
575
        CandAddr2xDP       <= CandAddr2xDN;
576
        Candidate2xDP      <= Candidate2xDN;
577
        HashTableEntry2xDP <= HashTableEntry2xDN;
578
        EndOfData0xSP      <= EndOfData0xSN;
579
        EndOfData1xSP      <= EndOfData1xSN;
580
        EndOfData2xSP      <= EndOfData2xSN;
581
        Done3xSP           <= Done3xSN;
582
 
583
      end if;
584
    end if;
585
  end process registers;
586
 
587
end Behavioral;
588
 

powered by: WebSVN 2.1.0

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