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

Subversion Repositories pcie_ds_dma

[/] [pcie_ds_dma/] [trunk/] [core/] [ds_dma64/] [pcie_src/] [pcie_core64_m1/] [source_virtex6/] [axi_basic_rx_null_gen.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dsmv
-------------------------------------------------------------------------------
2
--
3
-- (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved.
4
--
5
-- This file contains confidential and proprietary information
6
-- of Xilinx, Inc. and is protected under U.S. and
7
-- international copyright and other intellectual property
8
-- laws.
9
--
10
-- DISCLAIMER
11
-- This disclaimer is not a license and does not grant any
12
-- rights to the materials distributed herewith. Except as
13
-- otherwise provided in a valid license issued to you by
14
-- Xilinx, and to the maximum extent permitted by applicable
15
-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
16
-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
17
-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
18
-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
19
-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
20
-- (2) Xilinx shall not be liable (whether in contract or tort,
21
-- including negligence, or under any other theory of
22
-- liability) for any loss or damage of any kind or nature
23
-- related to, arising under or in connection with these
24
-- materials, including for any direct, or any indirect,
25
-- special, incidental, or consequential loss or damage
26
-- (including loss of data, profits, goodwill, or any type of
27
-- loss or damage suffered as a result of any action brought
28
-- by a third party) even if such damage or loss was
29
-- reasonably foreseeable or Xilinx had been advised of the
30
-- possibility of the same.
31
--
32
-- CRITICAL APPLICATIONS
33
-- Xilinx products are not designed or intended to be fail-
34
-- safe, or for use in any application requiring fail-safe
35
-- performance, such as life-support or safety devices or
36
-- systems, Class III medical devices, nuclear facilities,
37
-- applications related to the deployment of airbags, or any
38
-- other applications that could lead to death, personal
39
-- injury, or severe property or environmental damage
40
-- (individually and collectively, "Critical
41
-- Applications"). Customer assumes the sole risk and
42
-- liability of any use of Xilinx products in Critical
43
-- Applications, subject only to applicable laws and
44
-- regulations governing limitations on product liability.
45
--
46
-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
47
-- PART OF THIS FILE AT ALL TIMES.
48
--
49
-------------------------------------------------------------------------------
50
-- Project    : Virtex-6 Integrated Block for PCI Express
51
-- File       : axi_basic_rx_null_gen.vhd
52
-- Version    : 2.3
53
--
54
-- Description:
55
-- TRN to AXI RX null generator. Generates null packets for use in discontinue situations.
56
--
57
-- Notes:
58
--   Optional notes section.
59
--
60
--   Hierarchical:
61
--     axi_basic_top
62
--       axi_basic_rx
63
--         axi_basic_rx_null_gen
64
--------------------------------------------------------------------------------
65
-- Library Declarations
66
--------------------------------------------------------------------------------
67
LIBRARY ieee;
68
   USE ieee.std_logic_1164.all;
69
   USE ieee.std_logic_unsigned.all;
70
 
71
ENTITY axi_basic_rx_null_gen IS
72
   GENERIC (
73
      C_DATA_WIDTH              : INTEGER := 128; -- RX/TX interface data width
74
      TCQ                       : INTEGER := 1;   --  Clock to Q time
75
 
76
      C_STRB_WIDTH              : INTEGER := 4   --TSTRB width
77
   );
78
   PORT (
79
      -- AXI RX
80
      M_AXIS_RX_TDATA           : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) :=(OTHERS=>'0'); -- RX data to user
81
      M_AXIS_RX_TVALID          : IN STD_LOGIC                                   :='0';           -- RX data is valid
82
      M_AXIS_RX_TREADY          : IN STD_LOGIC                                   :='0';           -- RX ready for data
83
      M_AXIS_RX_TLAST           : IN STD_LOGIC                                   :='0';           -- RX data is last
84
      M_AXIS_RX_TUSER           : IN STD_LOGIC_VECTOR(21 DOWNTO 0)               :=(OTHERS=>'0'); -- RX user signals
85
 
86
      -- Null Inputs
87
      NULL_RX_TVALID            : OUT STD_LOGIC                                  ;           -- NULL generated tvalid
88
      NULL_RX_TLAST             : OUT STD_LOGIC                                  ;           -- NULL generated tlast
89
      NULL_RX_TSTRB             : OUT STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0); -- NULL generated tstrb
90
      NULL_RDST_RDY             : OUT STD_LOGIC                                  ;           -- NULL generated rdst_rdy
91
      NULL_IS_EOF               : OUT STD_LOGIC_VECTOR(4 DOWNTO 0)               ; -- NULL generated is_eof
92
 
93
      -- System
94
      USER_CLK                  : IN STD_LOGIC                                   :='0';
95
      USER_RST                  : IN STD_LOGIC                                   :='0'
96
   );
97
END axi_basic_rx_null_gen;
98
 
99
------------------------------------------------------------------------------//
100
-- NULL packet gnereator state machine                                        //
101
-- This state machine shadows the TRN RX interface, tracking each packet as   //
102
-- it's passed to the AXI user. When a disountine is detected, the rx data    //
103
-- pipeline switches to a NULL packet and clocks that out instead. It does so //
104
-- by asserting null_mux_sel, which the rx pipeline uses to mux in NULL vals. //
105
------------------------------------------------------------------------------//
106
 
107
ARCHITECTURE TRANS OF axi_basic_rx_null_gen IS
108
 
109
   --   INTERFACE_WIDTH_DWORDS = (C_DATA_WIDTH == 128) ? 11'd4 : (C_DATA_WIDTH == 64) ? 11'd2 : 11'd1;
110
   function if_wdt_dw (
111
     constant wdt   : integer)
112
     return integer is
113
      variable dw : integer := 1;
114
   begin  -- if_wdt_dw
115
 
116
     if (wdt = 128) then
117
       dw := 4;
118
     elsif (wdt = 64) then
119
       dw := 2;
120
     else
121
       dw := 1;
122
     end if;
123
     return dw;
124
   end if_wdt_dw;
125
 
126
   constant INTERFACE_WIDTH_DWORDS : integer := if_wdt_dw(C_DATA_WIDTH);
127
   constant IDLE : std_logic := '0';
128
   constant IN_PACKET : std_logic := '1';
129
 
130
   -- Signals for tracking a packet on the AXI interface
131
   SIGNAL reg_pkt_len_counter   : STD_LOGIC_VECTOR(11 DOWNTO 0);
132
   SIGNAL pkt_len_counter       : STD_LOGIC_VECTOR(11 DOWNTO 0);
133
   SIGNAL pkt_len_counter_dec   : STD_LOGIC_VECTOR(11 DOWNTO 0);
134
   SIGNAL pkt_done              : STD_LOGIC;
135
 
136
   SIGNAL new_pkt_len           : STD_LOGIC_VECTOR(11 DOWNTO 0);
137
   SIGNAL payload_len           : STD_LOGIC_VECTOR(9 DOWNTO 0);
138
   SIGNAL payload_len_tmp       : STD_LOGIC_VECTOR(9 DOWNTO 0) := (others => '0');
139
   SIGNAL packet_fmt            : STD_LOGIC_VECTOR(1 DOWNTO 0);
140
   SIGNAL packet_td             : STD_LOGIC;
141
   SIGNAL packet_overhead       : STD_LOGIC_VECTOR(3 DOWNTO 0);
142
   -- X-HDL generated signals`
143
 
144
   SIGNAL xhdl2                 : STD_LOGIC_VECTOR(2 DOWNTO 0);
145
   SIGNAL reg_is_eof            : STD_LOGIC_VECTOR(4 DOWNTO 0);
146
   SIGNAL xhdl5                 : STD_LOGIC_VECTOR(1 DOWNTO 0);
147
   SIGNAL xhdl7                 : STD_LOGIC_VECTOR(1 DOWNTO 0);
148
   --State machine variables and states
149
   SIGNAL next_state            : STD_LOGIC;
150
   SIGNAL cur_state             : STD_LOGIC;
151
 
152
   -- Declare intermediate signals for referenced outputs
153
   SIGNAL null_rx_tlast_xhdl0   : STD_LOGIC;
154
 
155
   -- Misc.
156
   SIGNAL eof_tstrb             : STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0);
157
   SIGNAL straddle_sof          : STD_LOGIC;
158
   SIGNAL eof                   : STD_LOGIC;
159
 
160
BEGIN
161
 
162
    -- Create signals to detect sof and eof situations. These signals vary depending
163
    -- on the data width.
164
    eof <= M_AXIS_RX_TUSER(21);
165
    SOF_EOF_128 : IF (C_DATA_WIDTH = 128) GENERATE
166
       straddle_sof <= '1' WHEN (M_AXIS_RX_TUSER(14 DOWNTO 13) = "11") ELSE '0';
167
    END GENERATE;
168
 
169
    SOF_EOF_64_32 : IF (C_DATA_WIDTH /= 128) GENERATE
170
       straddle_sof <= '0';
171
    END GENERATE;
172
 
173
    ------------------------------------------------------------------------------//
174
    -- Calculate the length of the packet being presented on the RX interface. To //
175
    -- do so, we need the relevent packet fields that impact total packet length. //
176
    -- These are:                                                                 //
177
    --   - Header length: obtained from bit 1 of FMT field in 1st DWORD of header //
178
    --   - Payload length: obtained from LENGTH field in 1st DWORD of header      //
179
    --   - TLP digist: obtained from TD field in 1st DWORD of header              //
180
    --   - Current data: the number of bytes that have already been presented     //
181
    --                   on the data interface                                    //
182
    --                                                                            //
183
    -- packet length = header + payload + tlp digest - # of DWORDS already        //
184
    --                 transmitted                                                //
185
    --                                                                            //
186
    -- packet_overhead is where we calculate everything except payload.           //
187
    ------------------------------------------------------------------------------//
188
 
189
    -- Drive referenced outputs
190
    NULL_RX_TLAST <= null_rx_tlast_xhdl0;
191
 
192
    XHDL1 : IF (C_DATA_WIDTH = 128) GENERATE
193
       packet_fmt   <= M_AXIS_RX_TDATA(94 DOWNTO 93) WHEN ((straddle_sof) = '1') ELSE  M_AXIS_RX_TDATA(30 DOWNTO 29);
194
       packet_td    <= M_AXIS_RX_TDATA(79) WHEN (straddle_sof = '1') ELSE M_AXIS_RX_TDATA(15);
195
       payload_len_tmp  <= M_AXIS_RX_TDATA(73 DOWNTO 64) WHEN (straddle_sof = '1') ELSE M_AXIS_RX_TDATA(9 DOWNTO 0);
196
       payload_len  <= payload_len_tmp WHEN ((packet_fmt(1)) = '1') ELSE  (others => '0');
197
 
198
       xhdl2 <= packet_fmt(0) & packet_td & straddle_sof;
199
       -- In 128-bit mode, the amount of data currently on the interface
200
       -- depends on whether we're straddling or not. If so, 2 DWORDs have been
201
       -- seen. If not, 4 DWORDs.
202
       PROCESS (xhdl2)
203
       BEGIN
204
               CASE xhdl2 IS
205
                       WHEN "000" =>
206
                               packet_overhead <= "0011" + "0000" - "0100";
207
                       WHEN "001" =>
208
                               packet_overhead <= "0011" + "0000" - "0010";
209
                       WHEN "010" =>
210
                               packet_overhead <= "0011" + "0001" - "0100";
211
                       WHEN "011" =>
212
                               packet_overhead <= "0011" + "0001" - "0010";
213
                       WHEN "100" =>
214
                               packet_overhead <= "0100" + "0000" - "0100";
215
                       WHEN "101" =>
216
                               packet_overhead <= "0100" + "0000" - "0010";
217
                       WHEN "110" =>
218
                               packet_overhead <= "0100" + "0001" - "0100";
219
                       WHEN "111" =>
220
                               packet_overhead <= "0100" + "0001" - "0010";
221
                       WHEN OTHERS =>
222
                               packet_overhead <= "0000" + "0000" - "0000";
223
               END CASE;
224
       END PROCESS;
225
       END GENERATE;
226
 
227
      XHDL4 : IF (C_DATA_WIDTH = 64) GENERATE
228
              packet_fmt <= M_AXIS_RX_TDATA(30 DOWNTO 29);
229
              packet_td <= M_AXIS_RX_TDATA(15);
230
              payload_len <= M_AXIS_RX_TDATA(9 DOWNTO 0) WHEN ((packet_fmt(1)) = '1') ELSE  "0000000000";
231
 
232
              xhdl5 <= packet_fmt(0) & packet_td;
233
              --  64-bit mode: no straddling, so always 2 DWORDs
234
              PROCESS (packet_fmt, packet_td,xhdl5)
235
              BEGIN
236
                      CASE xhdl5 IS
237
                                                      -- Header +   TD   - Data currently on interface
238
                              WHEN "00" =>
239
                                      packet_overhead <= "0011" + "0000" - "0010";
240
                              WHEN "01" =>
241
                                      packet_overhead <= "0011" + "0001" - "0010";
242
                              WHEN "10" =>
243
                                      packet_overhead <= "0100" + "0000" - "0010";
244
                              WHEN "11" =>
245
                                      packet_overhead <= "0100" + "0001" - "0010";
246
                              WHEN OTHERS =>
247
                                      packet_overhead <= "0000" + "0000" - "0000";
248
                      END CASE;
249
              END PROCESS;
250
      END GENERATE;
251
 
252
    XHDL6 : IF (C_DATA_WIDTH = 32) GENERATE
253
            packet_fmt <= M_AXIS_RX_TDATA(30 DOWNTO 29);
254
            packet_td <= M_AXIS_RX_TDATA(15);
255
            payload_len <= M_AXIS_RX_TDATA(9 DOWNTO 0) WHEN ((packet_fmt(1)) = '1') ELSE "0000000000";
256
 
257
            xhdl7 <= packet_fmt(0) & packet_td;
258
            -- 32-bit mode: no straddling, so always 1 DWORD
259
            PROCESS (packet_fmt, packet_td,xhdl7)
260
            BEGIN
261
                    CASE xhdl7 IS
262
                            WHEN "00" =>
263
                                    packet_overhead <= "0011" + "0000" - "0001";
264
                            WHEN "01" =>
265
                                    packet_overhead <= "0011" + "0001" - "0001";
266
                            WHEN "10" =>
267
                                    packet_overhead <= "0100" + "0000" - "0001";
268
                            WHEN "11" =>
269
                                    packet_overhead <= "0100" + "0001" - "0001";
270
                            WHEN OTHERS =>
271
                                    packet_overhead <= "0000" + "0000" - "0000";
272
                    END CASE;
273
            END PROCESS;
274
    END GENERATE;
275
    --END GENERATE;
276
    -- Now calculate actual packet length, adding the packet overhead and the
277
    -- payload length. This is signed math, so sign-extend packet_overhead.
278
    -- NOTE: a payload length of zero means 1024 DW in the PCIe spec, but this behavior isn't supported in our block.
279
 
280
    new_pkt_len <= (packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(2 DOWNTO 0)) + ("00" & payload_len);
281
 
282
 
283
    -- Math signals needed in the state machine below. These are seperate wires to
284
    -- help ensure synthesis tools are smart about optimizing them.
285
    pkt_len_counter_dec <= reg_pkt_len_counter - INTERFACE_WIDTH_DWORDS;
286
    pkt_done <= '1' WHEN (reg_pkt_len_counter <= INTERFACE_WIDTH_DWORDS) ELSE '0';
287
 
288
 
289
    PROCESS (cur_state, M_AXIS_RX_TVALID, M_AXIS_RX_TREADY, eof, new_pkt_len, reg_pkt_len_counter, pkt_len_counter_dec)
290
    BEGIN
291
 
292
       CASE cur_state IS
293
          -- IDLE state: the interface is IDLE and we're waiting for a packet to
294
          -- start. If a packet starts, move to state IN_PACKET and begin tracking it as long as it's NOT
295
          -- a signle cycle packet (indicated by assertion of eof at packet start)
296
               WHEN IDLE =>
297
                       IF ((M_AXIS_RX_TVALID = '1') and (M_AXIS_RX_TREADY = '1') and (eof = '0')) THEN next_state <= IN_PACKET;
298
                       ELSE
299
                               next_state <= IDLE;
300
                       END IF;
301
                       pkt_len_counter <= new_pkt_len;
302
                       -- IN_PACKET: a multi -cycle packet is in progress and we're tracking it. We are
303
                       -- in lock-step with the AXI interface decrementing our packet length
304
                       -- tracking reg, and waiting for the packet to finish.
305
                       -- If packet finished and a new one starts, this is a straddle situation.
306
                       -- Next state is IN_PACKET (128-bit only).
307
                       -- If the current packet is done, next state is IDLE.
308
                       -- Otherwise, next state is IN_PACKET.
309
               WHEN IN_PACKET =>
310
                       -- Straddle packet
311
                       IF ((C_DATA_WIDTH = 128) AND straddle_sof = '1' AND M_AXIS_RX_TVALID = '1') THEN
312
                              pkt_len_counter <= new_pkt_len;
313
                              next_state <= IN_PACKET;
314
                               -- Current packet finished
315
                       ELSIF (M_AXIS_RX_TREADY = '1' AND pkt_done = '1') THEN
316
                              pkt_len_counter <= new_pkt_len;
317
                              next_state <= IDLE ;
318
 
319
                       ELSE
320
                              IF (M_AXIS_RX_TREADY = '1') THEN
321
                                    -- Packet in progress
322
                                    pkt_len_counter <= pkt_len_counter_dec;
323
                              ELSE
324
                                    -- Throttled
325
                                    pkt_len_counter <= reg_pkt_len_counter;
326
                              END IF;
327
 
328
                              next_state <= IN_PACKET;
329
                       END IF;
330
             WHEN OTHERS =>
331
                     pkt_len_counter <= reg_pkt_len_counter;
332
                     next_state <= IDLE ;
333
     END CASE;
334
     END PROCESS;
335
 
336
    --Synchronous NULL packet generator state machine logic
337
    PROCESS (USER_CLK)
338
    BEGIN
339
       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
340
               IF (USER_RST = '1') THEN
341
                       cur_state <= IDLE  AFTER (TCQ)*1 ps;
342
                       reg_pkt_len_counter <= (others => '0')  AFTER (TCQ)*1 ps;
343
               ELSE
344
                       cur_state <= next_state AFTER (TCQ)*1 ps;
345
                       reg_pkt_len_counter <= pkt_len_counter  AFTER (TCQ)*1 ps;
346
               END IF;
347
       END IF;
348
       END PROCESS;
349
 
350
    --Generate TSTRB/is_eof for an end-of-packet situation.
351
    XHDL8 : IF (C_DATA_WIDTH = 128) GENERATE
352
            -- Assign null_is_eof depending on how many DWORDs are left in the packet.
353
            PROCESS (pkt_len_counter)
354
            BEGIN
355
                    CASE pkt_len_counter IS
356
                            WHEN "000000000001" =>
357
                                    null_is_eof <= "10011";
358
                            WHEN "000000000010" =>
359
                                    null_is_eof <= "10111";
360
                            WHEN "000000000011" =>
361
                                    null_is_eof <= "11011";
362
                            WHEN "000000000100" =>
363
                                    null_is_eof <= "11111";
364
                            WHEN OTHERS =>
365
                                    null_is_eof <= "00011";
366
                    END CASE;
367
            END PROCESS;
368
 
369
            --TSTRB not used in 128-bit interface
370
            eof_tstrb <= (others => '0') ; --'0' & '0' & '0' & '0';
371
    END GENERATE;
372
 
373
    XHDL9 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
374
       XHDL10 : IF (C_DATA_WIDTH = 64) GENERATE
375
            -- Assign null_is_eof depending on how many DWORDs are left in the packet.
376
            PROCESS (pkt_len_counter)
377
            BEGIN
378
                    CASE pkt_len_counter IS
379
                            WHEN "000000000001" =>
380
                                    null_is_eof <= "10011";
381
                            WHEN "000000000010" =>
382
                                    null_is_eof <= "10111";
383
                            WHEN OTHERS =>
384
                                    null_is_eof <= "00011";
385
                    END CASE;
386
            END PROCESS;
387
 
388
               -- Assign TSTRB to 0xFF or 0x0F depending on how many DWORDs are left in the current packet.
389
               eof_tstrb <= X"FF" WHEN (pkt_len_counter = "000000000010") ELSE X"0F";
390
       END GENERATE;
391
 
392
       XHDL11 : IF (NOT(C_DATA_WIDTH = 64)) GENERATE
393
            PROCESS (pkt_len_counter)
394
            BEGIN
395
                    --is_eof is either on or off in 32-bit interface
396
                    IF (pkt_len_counter = "000000000001") THEN
397
                            null_is_eof <= "10011";
398
                    ELSE
399
                            null_is_eof <= "10011";
400
                    END IF;
401
            END PROCESS;
402
 
403
               --The entire DWORD is always valid in 32-bit mode, so TSTRB is always 0xF
404
               eof_tstrb <= "1111";
405
       END GENERATE;
406
       END GENERATE;
407
 
408
    --Finally, use everything we've generated to calculate our NULL outputs
409
       NULL_RX_TVALID <= '1';
410
       null_rx_tlast_xhdl0 <= '1' WHEN (pkt_len_counter <= INTERFACE_WIDTH_DWORDS) ELSE '0' ;
411
       NULL_RX_TSTRB <= eof_tstrb WHEN (null_rx_tlast_xhdl0 = '1') ELSE  (others => '1');
412
       NULL_RDST_RDY <= null_rx_tlast_xhdl0 ;
413
END TRANS;
414
 
415
 

powered by: WebSVN 2.1.0

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