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

Subversion Repositories lzrw1-compressor-core

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

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/7/22 - 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
--* Descrambles encoded data output into proper data stream and buffers data in an FIFO.
41
--* Note: This unit can accept simulatinous input of body and header data.
42
--* However there must not be too much data input. The minimum is 16 cycles between
43
--* two assertions of HeaderStrobexSI. This is due to internal bandwidth
44
--* limitations. The only exception to this rule is the very last frame. However
45
--* no additional data is permitted after it until the reset signal was applied
46
--*
47
--***************************************************************************************************************
48
 
49
library IEEE;
50
use IEEE.STD_LOGIC_1164.all;
51
use IEEE.NUMERIC_STD.all;
52
 
53
library UNISIM;
54
use UNISIM.VComponents.all;
55
 
56
 
57
entity outputFIFO is
58
 
59
  generic (
60
    frameSize : integer := 8);          -- must be a multiple of 8
61
 
62
  port (
63
    ClkxCI          : in  std_logic;
64
    RstxRI          : in  std_logic;    -- active high
65
    BodyDataxDI     : in  std_logic_vector(7 downto 0);
66
    BodyStrobexSI   : in  std_logic;    -- strobe signal for data
67
    HeaderDataxDI   : in  std_logic_vector(frameSize-1 downto 0);
68
    HeaderStrobexSI : in  std_logic;
69
    BuffersEmptyxSO : out std_logic;  -- indicates that the internal data buffers are empty
70
    BufOutxDO       : out std_logic_vector(7 downto 0);
71
    OutputValidxSO  : out std_logic;
72
    RdStrobexSI     : in  std_logic;    -- read next word
73
    LengthxDO       : out integer range 0 to 1024);  -- number of bytes in the FIFO
74
 
75
end outputFIFO;
76
 
77
architecture Behavorial of outputFIFO is
78
 
79
  constant ADR_BIT_LEN : integer := 10;  -- fifo memory address bus width in bits (for byte addressing)
80
  constant DEPTH       : integer := 2**ADR_BIT_LEN;  -- Has to match value for range in LengthxDO and the BRam!
81
 
82
  constant TRANS_BUF_LEN : integer := (frameSize*2)+(frameSize/8);  -- we need frameSize/8 bytes for the
83
                                                                    -- header, plus frameSize*2 for the body
84
 
85
  type inBufType is array (0 to (frameSize*2)-1) of std_logic_vector(7 downto 0);  -- *2 because we can have two bytes per entry
86
  signal InputBufxDN, InputBufxDP         : inBufType                          := (others => (others => '0'));
87
  type transBufType is array (0 to TRANS_BUF_LEN-1) of std_logic_vector(7 downto 0);
88
  signal TransBufxDN, TransBufxDP         : transBufType                       := (others => (others => '0'));
89
  signal InBufCntxDN, InBufCntxDP         : integer range 0 to (frameSize*2)+1 := 0;  -- number of _bytes_ in buffer
90
  signal TransBufLenxDN, TransBufLenxDP   : integer range 0 to (frameSize*2)+1 := 0;
91
  signal TransBufBusyxS                   : std_logic;
92
  signal CopyReqxSN, CopyReqxSP           : std_logic                          := '0';
93
  signal HeaderInBufxDN, HeaderInBufxDP   : std_logic_vector(7 downto 0)       := x"00";
94
  signal BuffersEmptyxSN, BuffersEmptyxSP : std_logic                          := '0';
95
 
96
  signal BRamWexS    : std_logic_vector(3 downto 0);
97
  signal BRamWrInxD  : std_logic_vector(31 downto 0);
98
  signal BRamWrAdrxD : std_logic_vector(13 downto 0);
99
  signal BRamRdAdrxD : std_logic_vector(13 downto 0);
100
  signal BRamDOutxD  : std_logic_vector(31 downto 0);
101
 
102
  signal DoReadxS, DoWritexS            : std_logic;
103
  signal ReadLenxS, WriteLenxS          : integer range 0 to 3;  -- 0 -> 1 byte, 1 -> 2 bytes, ...
104
  signal LengthxDN, LengthxDP           : integer range 0 to DEPTH := 0;  -- count the number of bytes in the FIFO
105
  signal ReadPtrxDN, ReadPtrxDP         : integer range 0 to DEPTH := 0;
106
  signal WrPtrxDN, WrPtrxDP             : integer range 0 to DEPTH := 0;
107
  signal FifoInxD                       : std_logic_vector(15 downto 0);  -- data input to fifo
108
  signal FifoInSelxD                    : std_logic_vector(1 downto 0);  -- byte select for fifo data input
109
  signal OutputValidxSN, OutputValidxSP : std_logic                := '0';
110
 
111
  type transferFSMType is (ST_IDLE, ST_FIRST_SINGLE_BYTE, ST_COPY, ST_LAST_SINGLE_BYTE);
112
  signal StatexSN, StatexSP : transferFSMType := ST_IDLE;
113
 
114
 
115
begin  -- Behavorial
116
 
117
  -- implement data input buffer
118
  inBufPrcs : process (BodyDataxDI, BodyStrobexSI, CopyReqxSP, HeaderDataxDI,
119
                       HeaderInBufxDP, HeaderStrobexSI, InBufCntxDP,
120
                       InputBufxDP, StatexSP, TransBufBusyxS)
121
  begin
122
    InBufCntxDN    <= InBufCntxDP;
123
    InputBufxDN    <= InputBufxDP;
124
    CopyReqxSN     <= CopyReqxSP and TransBufBusyxS;
125
    HeaderInBufxDN <= HeaderInBufxDP;
126
    if BodyStrobexSI = '1' then
127
      if InBufCntxDP < (frameSize*2) then
128
        InBufCntxDN              <= InBufCntxDP + 1;
129
        InputBufxDN(InBufCntxDP) <= BodyDataxDI;
130
      else
131
        assert false report "Buffer overflow in data input buffer of output FIFO" severity error;
132
      end if;
133
    end if;
134
    if HeaderStrobexSI = '1' then
135
      if TransBufBusyxS = '0' then
136
        InBufCntxDN <= 0;               -- reset for next frame
137
      else
138
        CopyReqxSN     <= '1';  -- can't copy right now, remember to do that
139
        HeaderInBufxDN <= HeaderDataxDI;
140
      end if;
141
    end if;
142
    if StatexSP = ST_IDLE and CopyReqxSP = '1' then
143
      -- the requested copy operation starts now, reset counter
144
      InBufCntxDN <= 0;
145
    end if;
146
  end process inBufPrcs;
147
 
148
  -- purpose: implement transfer buffer (shift reg) and the state machine which copies the
149
  -- data into the fifo.
150
  transBufPrcs : process (BodyStrobexSI, CopyReqxSP, HeaderDataxDI,
151
                          HeaderInBufxDP, HeaderStrobexSI, InBufCntxDP,
152
                          InputBufxDP, LengthxDP, StatexSP, TransBufLenxDP,
153
                          TransBufxDP, WrPtrxDP)
154
  begin
155
    TransBufxDN    <= TransBufxDP;
156
    TransBufLenxDN <= TransBufLenxDP;
157
    StatexSN       <= StatexSP;         -- default: keep current state
158
    DoWritexS      <= '0';              -- default: do nothing
159
    FifoInxD       <= (others => '-');
160
    FifoInSelxD    <= "00";
161
    WriteLenxS     <= 0;
162
    TransBufBusyxS <= '0';
163
 
164
    case StatexSP is
165
      when ST_IDLE =>
166
        if (HeaderStrobexSI = '1' or CopyReqxSP = '1') and InBufCntxDP > 1 then
167
          -- we must have at least one data byte in the frame
168
          -- assert InBufCntxDN > 0 report "Transfer FSM: Atempted illegal transfer of frame without data" severity warning;
169
          -- copy data from the input buffer into transfer buffer
170
          for i in 1 to TRANS_BUF_LEN-1 loop
171
            TransBufxDN(i) <= InputBufxDP(i-1);
172
          end loop;  -- i
173
          if HeaderStrobexSI = '1' then
174
            -- the header is coming in right now -> copy from input signal
175
            TransBufxDN(0) <= HeaderDataxDI;
176
          else
177
            -- this must be an transfer requested earlier -> copy header from buffer
178
            TransBufxDN(0) <= HeaderInBufxDP;
179
          end if;
180
          if BodyStrobexSI = '0' then
181
            TransBufLenxDN <= InBufCntxDP + (frameSize/8);  -- frameSize / 8 is the header length
182
          else
183
            TransBufLenxDN <= InBufCntxDP + (frameSize/8) + 1;  -- frameSize / 8 is the header length
184
          end if;
185
          -- Note: we know we have at least two bytes (header + data) therefore
186
          -- it is save to move to ST_COPY
187
          if WrPtrxDP mod 2 = 1 then
188
            -- we have an odd byte location -> transfer single byte first
189
            StatexSN <= ST_FIRST_SINGLE_BYTE;
190
          else
191
            StatexSN <= ST_COPY;
192
          end if;
193
        end if;
194
 
195
      when ST_FIRST_SINGLE_BYTE =>
196
        TransBufBusyxS <= '1';
197
        if LengthxDP < DEPTH-1 then  -- make sure we have enough space for 2 bytes in fifo
198
          -- copy one byte from the transfer buffer to the fifo
199
          FifoInxD    <= TransBufxDP(0) & x"00";
200
          FifoInSelxD <= "10";
201
          DoWritexS   <= '1';
202
          WriteLenxS  <= 1;
203
          if TransBufLenxDP > 2 then
204
            StatexSN <= ST_COPY;  -- we have more than one byte left, do dual byte copy
205
          else
206
            StatexSN <= ST_LAST_SINGLE_BYTE;  -- only one byte left in frame
207
          end if;
208
          -- shift the transfer buffer one byte
209
          for i in 0 to TRANS_BUF_LEN-2 loop
210
            TransBufxDN(i) <= TransBufxDP(i+1);
211
          end loop;  -- i
212
          TransBufxDN(TRANS_BUF_LEN-1) <= x"00";  -- to make simulation look nice :)
213
          TransBufLenxDN               <= TransBufLenxDP - 1;
214
        end if;
215
 
216
      when ST_COPY =>
217
        TransBufBusyxS <= '1';
218
        if LengthxDP < DEPTH-1 then  -- make sure we have enough space for 2 bytes in fifo
219
          assert TransBufLenxDP >= 2 report "ST_COPY: not enough data in transfer buffer to perform copy operation" severity error;
220
          FifoInxD       <= TransBufxDP(1) & TransBufxDP(0);
221
          FifoInSelxD    <= "11";
222
          DoWritexS      <= '1';
223
          WriteLenxS     <= 2;
224
          TransBufLenxDN <= TransBufLenxDP - 2;  -- we copy two bytes here
225
          for i in 0 to TRANS_BUF_LEN-3 loop
226
            -- shift buffer two bytes 
227
            TransBufxDN(i) <= TransBufxDP(i+2);
228
          end loop;  -- i
229
          if TransBufLenxDP = 2 then
230
            StatexSN <= ST_IDLE;  -- this were the last two bytes -> we are done
231
          elsif TransBufLenxDP = 3 then
232
            StatexSN <= ST_LAST_SINGLE_BYTE;  -- handle last byte as special case
233
          end if;
234
        end if;
235
 
236
      when ST_LAST_SINGLE_BYTE =>
237
        TransBufBusyxS <= '1';
238
        if LengthxDP < DEPTH-1 then  -- make sure we have enough space for 2 bytes in fifo
239
          assert TransBufLenxDP = 1 report "ST_LAST_SINGLE_BYTE: TransBufLenxDP is not 1" severity error;
240
          FifoInxD       <= x"00" & TransBufxDP(0);  -- copy last byte
241
          FifoInSelxD    <= "01";
242
          TransBufLenxDN <= 0;
243
          DoWritexS      <= '1';
244
          WriteLenxS     <= 1;
245
          StatexSN       <= ST_IDLE;    -- transfer is done
246
        end if;
247
      when others => null;
248
    end case;
249
  end process transBufPrcs;
250
 
251
  BuffersEmptyxSN <= '1' when InBufCntxDP = 0 and TransBufLenxDP = 0 else '0';
252
  BuffersEmptyxSO <= BuffersEmptyxSP;
253
 
254
  -- implement write pointer counter
255
  wrPortDemuxPrcs : process (DoWritexS, FifoInSelxD, FifoInxD, WrPtrxDP,
256
                             WriteLenxS)
257
  begin
258
    WrPtrxDN    <= WrPtrxDP;
259
    BRamWrInxD  <= x"0000" & FifoInxD;
260
    BRamWrAdrxD <= "0" & std_logic_vector(to_unsigned(WrPtrxDP/2, ADR_BIT_LEN-1)) & "0000";
261
    BRamWexS    <= "00" & FifoInSelxD;
262
    -- implement a write pointer that overflows when we reach the end of the fifo memory
263
    if DoWritexS = '1' then
264
      if (WrPtrxDP + WriteLenxS) < DEPTH then
265
        WrPtrxDN <= WrPtrxDP + WriteLenxS;
266
      else
267
        WrPtrxDN <= WrPtrxDP + WriteLenxS - DEPTH;
268
      end if;
269
    end if;
270
  end process wrPortDemuxPrcs;
271
 
272
 
273
  -- purpose: implement read port related logic
274
  readPrcs : process (LengthxDP, RdStrobexSI, ReadPtrxDP)
275
  begin
276
    ReadPtrxDN     <= ReadPtrxDP;
277
    DoReadxS       <= '0';
278
    ReadLenxS      <= 0;
279
    OutputValidxSN <= '0';
280
    BRamRdAdrxD    <= "0" & std_logic_vector(to_unsigned(ReadPtrxDP, ADR_BIT_LEN)) & "000";
281
    -- suppress illeagal read attempts (when the fifo is empty)
282
    if RdStrobexSI = '1' and LengthxDP > 0 then
283
      DoReadxS       <= '1';
284
      ReadLenxS      <= 1;
285
      OutputValidxSN <= '1';            -- read takes one cycle
286
      -- implement read pointer
287
      if ReadPtrxDP < DEPTH-1 then
288
        ReadPtrxDN <= ReadPtrxDP + 1;
289
      else
290
        ReadPtrxDN <= 0;
291
      end if;
292
    end if;
293
  end process readPrcs;
294
 
295
  -- purpose: Count the number of _bytes_ currently stored in the FIFO
296
  lenCntPrcs : process (DoReadxS, DoWritexS, LengthxDP, ReadLenxS, WriteLenxS)
297
  begin  -- process LenCntPrcs
298
    LengthxDN <= LengthxDP;             -- default: do nothing
299
    if DoReadxS = '1' and DoWritexS = '0' and LengthxDP > 0 then
300
      LengthxDN <= LengthxDP - ReadLenxS;
301
      -- byte -> different encoding for ReadLen, see signal definition
302
    end if;
303
    if DoReadxS = '0' and DoWritexS = '1' and LengthxDP < DEPTH then
304
      LengthxDN <= LengthxDP + WriteLenxS;
305
    end if;
306
    if DoReadxS = '1' and DoWritexS = '1' then
307
      LengthxDN <= LengthxDP + WriteLenxS - ReadLenxS;
308
    end if;
309
 
310
  end process LenCntPrcs;
311
 
312
  BufOutxDO      <= BRamDOutxD(7 downto 0);
313
  LengthxDO      <= LengthxDP;
314
  OutputValidxSO <= OutputValidxSP;
315
  --SelxSO    <= ReadSelxS;
316
 
317
 
318
  -- purpose: implement the registers
319
  -- type   : sequential
320
  process (ClkxCI, RstxRI)
321
  begin  -- process
322
    if ClkxCI'event and ClkxCI = '1' then  -- rising clock edge then
323
      if RstxRI = '1' then
324
 
325
        InBufCntxDP     <= 0;
326
        LengthxDP       <= 0;
327
        TransBufLenxDP  <= 0;
328
        CopyReqxSP      <= '0';
329
        LengthxDP       <= 0;
330
        WrPtrxDP        <= 0;
331
        ReadPtrxDP      <= 0;
332
        OutputValidxSP  <= '0';
333
        BuffersEmptyxSP <= '0';
334
        StatexSP        <= ST_IDLE;
335
      else
336
        InputBufxDP     <= InputBufxDN;
337
        InBufCntxDP     <= InBufCntxDN;
338
        TransBufxDP     <= TransBufxDN;
339
        TransBufLenxDP  <= TransBufLenxDN;
340
        CopyReqxSP      <= CopyReqxSN;
341
        HeaderInBufxDP  <= HeaderInBufxDN;
342
        LengthxDP       <= LengthxDN;
343
        WrPtrxDP        <= WrPtrxDN;
344
        ReadPtrxDP      <= ReadPtrxDN;
345
        OutputValidxSP  <= OutputValidxSN;
346
        BuffersEmptyxSP <= BuffersEmptyxSN;
347
        StatexSP        <= StatexSN;
348
      end if;
349
    end if;
350
  end process;
351
 
352
 
353
  FifoBRam : RAMB16BWER
354
    generic map (
355
      -- DATA_WIDTH_A/DATA_WIDTH_B: 0, 1, 2, 4, 9, 18, or 36
356
      DATA_WIDTH_A        => 18,
357
      DATA_WIDTH_B        => 9,
358
      -- DOA_REG/DOB_REG: Optional output register (0 or 1)
359
      DOA_REG             => 0,
360
      DOB_REG             => 0,
361
      -- EN_RSTRAM_A/EN_RSTRAM_B: Enable/disable RST
362
      EN_RSTRAM_A         => true,
363
      EN_RSTRAM_B         => true,
364
      -- INIT_A/INIT_B: Initial values on output port
365
      INIT_A              => X"000000000",
366
      INIT_B              => X"000000000",
367
      -- INIT_FILE: Optional file used to specify initial RAM contents
368
      INIT_FILE           => "NONE",
369
      -- RSTTYPE: "SYNC" or "ASYNC" 
370
      RSTTYPE             => "SYNC",
371
      -- RST_PRIORITY_A/RST_PRIORITY_B: "CE" or "SR" 
372
      RST_PRIORITY_A      => "CE",
373
      RST_PRIORITY_B      => "CE",
374
      -- SIM_COLLISION_CHECK: Collision check enable "ALL", "WARNING_ONLY", "GENERATE_X_ONLY" or "NONE" 
375
      SIM_COLLISION_CHECK => "ALL",
376
      -- SIM_DEVICE: Must be set to "SPARTAN6" for proper simulation behavior
377
      SIM_DEVICE          => "SPARTAN6",
378
      -- SRVAL_A/SRVAL_B: Set/Reset value for RAM output
379
      SRVAL_A             => X"000000000",
380
      SRVAL_B             => X"000000000",
381
      -- WRITE_MODE_A/WRITE_MODE_B: "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE" 
382
      WRITE_MODE_A        => "WRITE_FIRST",
383
      WRITE_MODE_B        => "WRITE_FIRST"
384
      )
385
    port map (
386
      -- Port A Data: 32-bit (each) Port A data
387
      DOA    => open,                   -- 32-bit A port data output
388
      DOPA   => open,                   -- 4-bit A port parity output
389
      -- Port B Data: 32-bit (each) Port B data
390
      DOB    => BRamDOutxD,             -- 32-bit B port data output
391
      DOPB   => open,                   -- 4-bit B port parity output
392
      -- Port A Address/Control Signals: 14-bit (each) Port A address and control signals
393
      ADDRA  => BRamWrAdrxD,            -- 14-bit A port address input
394
      CLKA   => ClkxCI,                 -- 1-bit A port clock input
395
      ENA    => DoWritexS,              -- 1-bit A port enable input
396
      REGCEA => '1',          -- 1-bit A port register clock enable input
397
      RSTA   => RstxRI,       -- 1-bit A port register set/reset input
398
      WEA    => BRamWexS,     -- 4-bit Port A byte-wide write enable input
399
      -- Port A Data: 32-bit (each) Port A data
400
      DIA    => BRamWrInxD,             -- 32-bit A port data input
401
      DIPA   => "0000",                 -- 4-bit A port parity input
402
      -- Port B Address/Control Signals: 14-bit (each) Port B address and control signals
403
      ADDRB  => BRamRdAdrxD,            -- 14-bit B port address input
404
      CLKB   => ClkxCI,                 -- 1-bit B port clock input
405
      ENB    => DoReadxS,               -- 1-bit B port enable input
406
      REGCEB => '1',          -- 1-bit B port register clock enable input
407
      RSTB   => RstxRI,       -- 1-bit B port register set/reset input
408
      WEB    => "0000",       -- 4-bit Port B byte-wide write enable input
409
      -- Port B Data: 32-bit (each) Port B data
410
      DIB    => x"00000000",            -- 32-bit B port data input
411
      DIPB   => "0000"                  -- 4-bit B port parity input
412
      );
413
 
414
 
415
end Behavorial;

powered by: WebSVN 2.1.0

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