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 3

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 3 habicht
  signal CandLen2xDN, CandLen2xDP               : integer range 0 to LOOK_AHEAD_LEN;
182 2 habicht
  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 3 habicht
    BusyxSN           <= '0';
217 2 habicht
 
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 3 habicht
        WrHistBufxS <= StrobexSI;
223
        DataIn0xDN  <= DataInxDI;
224
        if FlushBufxSI = '1' then
225 2 habicht
          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 3 habicht
      BusyxSN <= '1';  -- request stop of data input if output FIFO is full
260 2 habicht
    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 3 habicht
      lookAheadBufxDN(i) <= lookAheadBufxDP(i);      -- default: do nothing
297 2 habicht
      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 3 habicht
  process (CandAddr1xDP, CandAddr2xDP, CandLen2xDP, Candidate2xDP,
404
           HistBufLen1xDP, HistBufLen2xDP, HistBufOutxD, LookAheadBuf1xDP,
405
           LookAheadBuf2xDP, LookAheadLen1xDP, LookAheadLen2xDP,
406
           LookAheadPtr1xDP, LookAheadPtr2xDP, MaxCandLenxD, Strobe1xSP)
407 2 habicht
  begin
408
    Candidate2xDN    <= Candidate2xDP;
409
    LookAheadBuf2xDN <= LookAheadBuf2xDP;
410
    LookAheadLen2xDN <= LookAheadLen2xDP;
411
    CandAddr2xDN     <= CandAddr2xDP;
412 3 habicht
    LookAheadPtr2xDN <= LookAheadPtr2xDP;
413 2 habicht
    HistBufLen2xDN   <= HistBufLen2xDP;
414 3 habicht
    CandLen2xDN      <= CandLen2xDP;
415
    -- send data through pipeline when strobe is high
416 2 habicht
    if Strobe1xSP = '1' then
417 3 habicht
      -- note: the history buffer can't load data only from addresses where the
418
      -- last two bits are zero. If this was not the case we shift the candidate
419
      -- (which makes it shorter) to correct that
420 2 habicht
      case CandAddr1xDP(1 downto 0) is
421
        when "00" => Candidate2xDN <= HistBufOutxD;  -- no shifting
422 3 habicht
                     CandLen2xDN <= MaxCandLenxD;
423 2 habicht
        when "01" => Candidate2xDN <= x"00" & HistBufOutxD(LOOK_AHEAD_LEN*8-1 downto 8);  -- shift one byte
424 3 habicht
                     CandLen2xDN <= MaxCandLenxD-1;  -- we shifted one byte out -> candidate is one byte shorter
425 2 habicht
        when "10" => Candidate2xDN <= x"0000" & HistBufOutxD(LOOK_AHEAD_LEN*8-1 downto 16);  -- shift 2 bytes
426 3 habicht
                     CandLen2xDN <= MaxCandLenxD-2;
427 2 habicht
        when "11" => Candidate2xDN <= x"000000" & HistBufOutxD(LOOK_AHEAD_LEN*8-1 downto 24);  -- shift 3 bytes
428 3 habicht
                     CandLen2xDN <= MaxCandLenxD-3;
429 2 habicht
        when others => null;
430
      end case;
431
 
432
      LookAheadBuf2xDN <= LookAheadBuf1xDP;
433
      LookAheadLen2xDN <= LookAheadLen1xDP;
434
      CandAddr2xDN     <= CandAddr1xDP;
435
      --   NextWrAdr2xDN    <= NextWrAdr1xDP;
436
      LookAheadPtr2xDN <= LookAheadPtr1xDP;
437
      HistBufLen2xDN   <= HistBufLen1xDP;
438
    end if;
439
  end process;
440
 
441
-- signals to be passed on to next stage
442
  HashTableEntry2xDN <= HashTableEntryxD;
443
  Strobe2xSN         <= Strobe1xSP;
444
  EndOfData2xSN      <= EndOfData1xSP;
445
 
446
 
447
-------------------------------------------------------------------------------
448
-- Pipeline Stage 3
449
--
450
-- Comparator, Offset Calculation and Data Output
451
-------------------------------------------------------------------------------
452
 
453
-- reformat two dimensional look ahead buffer into one dimensional array
454
-- not nice, I know. We should have a package defining proper types and use
455
-- them consistently...
456
  arrayReformatter : for i in 0 to LOOK_AHEAD_LEN-1 generate
457
    CompLAIn3xD((i+1)*8-1 downto i*8) <= LookAheadBuf2xDP(i);
458
  end generate arrayReformatter;
459
 
460
  comparatorInst : comparator
461
    port map (
462
      LookAheadxDI    => CompLAIn3xD,
463
      LookAheadLenxDI => LookAheadLen2xDP,
464
      CandidatexDI    => Candidate2xDP,
465 3 habicht
      CandidateLenxDI => CandLen2xDP,
466 2 habicht
      MatchLenxDO     => MatchLenxD);
467
 
468
  -- calculate the offset
469
  process (CandAddr2xDP, LookAheadPtr2xDP, OffsetIntxD)
470
  begin
471
    OffsetIntxD <= -1;                  -- default: illegal offset
472
    if to_integer(unsigned(LookAheadPtr2xDP)) > to_integer(unsigned(CandAddr2xDP)) then
473
      -- this is the regular case, the candidate address is smaller (ie in the
474
      -- past) than the byte to be encoded (which is at index given by lookAheadPtr)
475
      OffsetIntxD <= to_integer(unsigned(LookAheadPtr2xDP)) - to_integer(unsigned(CandAddr2xDP)) - 1;
476
    elsif to_integer(unsigned(LookAheadPtr2xDP)) < to_integer(unsigned(CandAddr2xDP)) then
477
      -- there is a buffer wrap around between the two pointers, the offset
478
      -- would be negative -> add buffer length
479
      OffsetIntxD <= HIST_BUF_LEN + to_integer(unsigned(LookAheadPtr2xDP)) - to_integer(unsigned(CandAddr2xDP)) - 1;
480
    else
481
      -- this means that the candidate and the history buffer (byte to be
482
      -- encoded) are on the same location. This is invalid as the candidate can't be
483
      -- in the future -> create an illeagal negative offset to invalidate this match
484
      OffsetIntxD <= -1;
485
    end if;
486
    OffsetxD <= std_logic_vector(to_unsigned(OffsetIntxD, 12));
487
  end process;
488
 
489
  Done3xSN <= EncDonexS and FifoBuffersEmptyxS;
490
 
491
  -- note: the offset can't be longer than the history buffer length 
492
  -- if the offset is too long we disable the match by setting the length to 0
493
  -- we also check for illegal negative offsets
494
  MatchLenLimitedxD <= MatchLenxD when OffsetIntxD < (HistBufLen2xDP) and OffsetIntxD >= 0 else 0;
495
 
496
  outputEncoderInst : outputEncoder
497
    generic map (
498
      frameSize   => 8,
499
      minMatchLen => 3,
500
      maxMatchLen => LOOK_AHEAD_LEN)
501
    port map (
502
      ClkxCI          => ClkxCI,
503
      RstxRI          => RstxRI,
504
      OffsetxDI       => OffsetxD,
505
      MatchLengthxDI  => MatchLenLimitedxD,
506
      EnxSI           => Strobe2xSP,
507
      EndOfDataxSI    => EndOfData2xSP,
508
      LiteralxDI      => LookAheadBuf2xDP(0),
509
      BodyStrobexSO   => BodyStrobexS,
510
      BodyOutxDO      => BodyDataxD,
511
      HeaderStrobexSO => HeaderStrobexS,
512
      HeaderOutxDO    => HeaderDataxD,
513
      DonexSO         => EncDonexS);
514
 
515
 
516
  outputFIFOInst : outputFIFO
517
    generic map (
518
      frameSize => 8)  -- number of elements (pairs or literals) per frame
519
    port map (
520
      ClkxCI          => ClkxCI,
521
      RstxRI          => RstxRI,
522
      BodyDataxDI     => BodyDataxD,
523
      BodyStrobexSI   => BodyStrobexS,
524
      HeaderDataxDI   => HeaderDataxD,
525
      HeaderStrobexSI => HeaderStrobexS,
526
      BuffersEmptyxSO => FifoBuffersEmptyxS,
527
      BufOutxDO       => BufOutxDO,
528
      OutputValidxSO  => OutputValidxSO,
529
      RdStrobexSI     => RdStrobexSI,
530
      LengthxDO       => OutFIFOLengthxD);
531
 
532
  LengthxDO <= OutFIFOLengthxD;
533
  DonexSO   <= Done3xSP;
534
 
535
  -----------------------------------------------------------------------------
536
  -- GENERAL STUFF
537
  -----------------------------------------------------------------------------
538
 
539
  registers : process (ClkxCI)
540
  begin  -- process registers
541
    if ClkxCI'event and ClkxCI = '1' then
542
      if RstxRI = '1' then
543
        StatexSP          <= ST_FILL_LOOK_AHEAD;
544
        BusyxSP           <= '0';
545
        ShiftLookAheadxSP <= '0';
546
        lookAheadLenxDP   <= 0;
547
        Strobe0xSP        <= '0';
548
        LookAheadLen1xDP  <= 0;
549
        Strobe1xSP        <= '0';
550
        WrAdr1xDP         <= (others => '0');
551
        LookAheadLen2xDP  <= 0;
552
        Strobe2xSP        <= '0';
553
        HistBufLen0xDP    <= 0;
554
        EndOfData0xSP     <= '0';
555
        EndOfData1xSP     <= '0';
556
        EndOfData2xSP     <= '0';
557
        Done3xSP          <= '0';
558
      else
559
        StatexSP           <= StatexSN;
560
        BusyxSP            <= BusyxSN;
561
        ShiftLookAheadxSP  <= ShiftLookAheadxSN;
562
        lookAheadLenxDP    <= lookAheadLenxDN;
563
        lookAheadBufxDP    <= lookAheadBufxDN;
564
        Strobe0xSP         <= Strobe0xSN;
565
        HistBufLen0xDP     <= HistBufLen0xDN;
566
        DataIn0xDP         <= DataIn0xDN;
567
        lookAheadLen1xDP   <= lookAheadLen1xDN;
568
        Strobe1xSP         <= Strobe1xSN;
569
        HistBufLen1xDP     <= HistBufLen1xDN;
570
        WrAdr1xDP          <= WrAdr1xDN;
571
        LookAheadPtr1xDP   <= LookAheadPtr1xDN;
572
        LookAheadBuf1xDP   <= LookAheadBuf1xDN;
573
        LookAheadLen2xDP   <= LookAheadLen2xDN;
574
        LookAheadBuf2xDP   <= LookAheadBuf2xDN;
575
        CandAddr1xDP       <= CandAddr1xDN;
576
        Strobe2xSP         <= Strobe2xSN;
577
        HistBufLen2xDP     <= HistBufLen2xDN;
578
        NextWrAdr2xDP      <= NextWrAdr2xDN;
579
        LookAheadPtr2xDP   <= LookAheadPtr2xDN;
580
        CandAddr2xDP       <= CandAddr2xDN;
581
        Candidate2xDP      <= Candidate2xDN;
582 3 habicht
        CandLen2xDP        <= CandLen2xDN;
583 2 habicht
        HashTableEntry2xDP <= HashTableEntry2xDN;
584
        EndOfData0xSP      <= EndOfData0xSN;
585
        EndOfData1xSP      <= EndOfData1xSN;
586
        EndOfData2xSP      <= EndOfData2xSN;
587
        Done3xSP           <= Done3xSN;
588
 
589
      end if;
590
    end if;
591
  end process registers;
592
 
593
end Behavioral;
594
 

powered by: WebSVN 2.1.0

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