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_artix7/] [cl_a7pcie_x4_axi_basic_rx_null_gen.vhd] - Blame information for rev 48

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

Line No. Rev Author Line
1 46 dsmv
-------------------------------------------------------------------------------
2
--
3
-- (c) Copyright 2010-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    : Series-7 Integrated Block for PCI Express
51
-- File       : cl_a7pcie_x4_axi_basic_rx_null_gen.vhd
52 48 dsmv
-- Version    : 1.10
53 46 dsmv
--
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 cl_a7pcie_x4_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
  );
77
  PORT (
78
    -- AXI RX
79
    M_AXIS_RX_TDATA           : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) :=(OTHERS=>'0'); -- RX data to user
80
    M_AXIS_RX_TVALID          : IN STD_LOGIC                                   :='0';           -- RX data is valid
81
    M_AXIS_RX_TREADY          : IN STD_LOGIC                                   :='0';           -- RX ready for data
82
    M_AXIS_RX_TLAST           : IN STD_LOGIC                                   :='0';           -- RX data is last
83
    M_AXIS_RX_TUSER           : IN STD_LOGIC_VECTOR(21 DOWNTO 0)               :=(OTHERS=>'0'); -- RX user signals
84
 
85
    -- Null Inputs
86
    NULL_RX_TVALID            : OUT STD_LOGIC                                  ;           -- NULL generated tvalid
87
    NULL_RX_TLAST             : OUT STD_LOGIC                                  ;           -- NULL generated tlast
88
    NULL_RX_tkeep             : OUT STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0); -- NULL generated tkeep
89
    NULL_RDST_RDY             : OUT STD_LOGIC                                  ;           -- NULL generated rdst_rdy
90
    NULL_IS_EOF               : OUT STD_LOGIC_VECTOR(4 DOWNTO 0)               ; -- NULL generated is_eof
91
 
92
    -- System
93
    USER_CLK                  : IN STD_LOGIC                                   :='0';
94
    USER_RST                  : IN STD_LOGIC                                   :='0'
95
  );
96
END cl_a7pcie_x4_axi_basic_rx_null_gen;
97
 
98
------------------------------------------------------------------------------//
99
-- NULL packet gnereator state machine                                        //
100
-- This state machine shadows the TRN RX interface, tracking each packet as   //
101
-- it's passed to the AXI user. When a disountine is detected, the rx data    //
102
-- pipeline switches to a NULL packet and clocks that out instead. It does so //
103
-- by asserting null_mux_sel, which the rx pipeline uses to mux in NULL vals. //
104
------------------------------------------------------------------------------//
105
 
106
ARCHITECTURE TRANS OF cl_a7pcie_x4_axi_basic_rx_null_gen IS
107
 
108
  --   INTERFACE_WIDTH_DWORDS = (C_DATA_WIDTH == 128) ? 11'd4 : (C_DATA_WIDTH == 64) ? 11'd2 : 11'd1;
109
  function if_wdt_dw (
110
    constant wdt   : integer)
111
    return integer is
112
     variable dw : integer := 1;
113
  begin  -- if_wdt_dw
114
 
115
    if (wdt = 128) then
116
      dw := 4;
117
    elsif (wdt = 64) then
118
      dw := 2;
119
    else
120
      dw := 1;
121
    end if;
122
    return dw;
123
  end if_wdt_dw;
124
 
125
  constant INTERFACE_WIDTH_DWORDS : integer := if_wdt_dw(C_DATA_WIDTH);
126
  constant IDLE : std_logic := '0';
127
  constant IN_PACKET : std_logic := '1';
128
 
129
  -- Signals for tracking a packet on the AXI interface
130
  SIGNAL reg_pkt_len_counter   : STD_LOGIC_VECTOR(11 DOWNTO 0);
131
  SIGNAL pkt_len_counter       : STD_LOGIC_VECTOR(11 DOWNTO 0);
132
  SIGNAL pkt_len_counter_dec   : STD_LOGIC_VECTOR(11 DOWNTO 0);
133
  SIGNAL pkt_done              : STD_LOGIC;
134
 
135
  SIGNAL new_pkt_len           : STD_LOGIC_VECTOR(11 DOWNTO 0);
136
  SIGNAL payload_len           : STD_LOGIC_VECTOR(9 DOWNTO 0);
137
  SIGNAL payload_len_tmp       : STD_LOGIC_VECTOR(9 DOWNTO 0) := (others => '0');
138
  SIGNAL packet_fmt            : STD_LOGIC_VECTOR(1 DOWNTO 0);
139
  SIGNAL packet_td             : STD_LOGIC;
140
  SIGNAL packet_overhead       : STD_LOGIC_VECTOR(3 DOWNTO 0);
141
  -- X-HDL generated signals`
142
 
143
  SIGNAL xhdl2                 : STD_LOGIC_VECTOR(2 DOWNTO 0);
144
  SIGNAL reg_is_eof            : STD_LOGIC_VECTOR(4 DOWNTO 0);
145
  SIGNAL xhdl5                 : STD_LOGIC_VECTOR(1 DOWNTO 0);
146
  SIGNAL xhdl7                 : STD_LOGIC_VECTOR(1 DOWNTO 0);
147
  --State machine variables and states
148
  SIGNAL next_state            : STD_LOGIC;
149
  SIGNAL cur_state             : STD_LOGIC;
150
 
151
  -- Declare intermediate signals for referenced outputs
152
  SIGNAL null_rx_tlast_xhdl0   : STD_LOGIC;
153
 
154
  -- Misc.
155
  SIGNAL eof_tkeep             : STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0);
156
  SIGNAL straddle_sof          : STD_LOGIC;
157
  SIGNAL eof                   : STD_LOGIC;
158
 
159
BEGIN
160
 
161
  -- Create signals to detect sof and eof situations. These signals vary depending
162
  -- on the data width.
163
  eof <= M_AXIS_RX_TUSER(21);
164
  SOF_EOF_128 : IF (C_DATA_WIDTH = 128) GENERATE
165
    straddle_sof <= '1' WHEN (M_AXIS_RX_TUSER(14 DOWNTO 13) = "11") ELSE '0';
166
  END GENERATE;
167
 
168
  SOF_EOF_64_32 : IF (C_DATA_WIDTH /= 128) GENERATE
169
    straddle_sof <= '0';
170
  END GENERATE;
171
 
172
  ------------------------------------------------------------------------------//
173
  -- Calculate the length of the packet being presented on the RX interface. To //
174
  -- do so, we need the relevent packet fields that impact total packet length. //
175
  -- These are:                                                                 //
176
  --   - Header length: obtained from bit 1 of FMT field in 1st DWORD of header //
177
  --   - Payload length: obtained from LENGTH field in 1st DWORD of header      //
178
  --   - TLP digist: obtained from TD field in 1st DWORD of header              //
179
  --   - Current data: the number of bytes that have already been presented     //
180
  --                   on the data interface                                    //
181
  --                                                                            //
182
  -- packet length = header + payload + tlp digest - # of DWORDS already        //
183
  --                 transmitted                                                //
184
  --                                                                            //
185
  -- packet_overhead is where we calculate everything except payload.           //
186
  ------------------------------------------------------------------------------//
187
 
188
  -- Drive referenced outputs
189
  NULL_RX_TLAST <= null_rx_tlast_xhdl0;
190
 
191
  XHDL1 : IF (C_DATA_WIDTH = 128) GENERATE
192
    packet_fmt   <= M_AXIS_RX_TDATA(94 DOWNTO 93) WHEN ((straddle_sof) = '1') ELSE  M_AXIS_RX_TDATA(30 DOWNTO 29);
193
    packet_td    <= M_AXIS_RX_TDATA(79) WHEN (straddle_sof = '1') ELSE M_AXIS_RX_TDATA(15);
194
    payload_len_tmp  <= M_AXIS_RX_TDATA(73 DOWNTO 64) WHEN (straddle_sof = '1') ELSE M_AXIS_RX_TDATA(9 DOWNTO 0);
195
    payload_len  <= payload_len_tmp WHEN ((packet_fmt(1)) = '1') ELSE  (others => '0');
196
 
197
    xhdl2 <= packet_fmt(0) & packet_td & straddle_sof;
198
    -- In 128-bit mode, the amount of data currently on the interface
199
    -- depends on whether we're straddling or not. If so, 2 DWORDs have been
200
    -- seen. If not, 4 DWORDs.
201
    PROCESS (xhdl2)
202
    BEGIN
203
      CASE xhdl2 IS
204
        WHEN "000" =>
205
          packet_overhead <= "0011" + "0000" - "0100";
206
        WHEN "001" =>
207
          packet_overhead <= "0011" + "0000" - "0010";
208
        WHEN "010" =>
209
          packet_overhead <= "0011" + "0001" - "0100";
210
        WHEN "011" =>
211
          packet_overhead <= "0011" + "0001" - "0010";
212
        WHEN "100" =>
213
          packet_overhead <= "0100" + "0000" - "0100";
214
        WHEN "101" =>
215
          packet_overhead <= "0100" + "0000" - "0010";
216
        WHEN "110" =>
217
          packet_overhead <= "0100" + "0001" - "0100";
218
        WHEN "111" =>
219
          packet_overhead <= "0100" + "0001" - "0010";
220
        WHEN OTHERS =>
221
          packet_overhead <= "0000" + "0000" - "0000";
222
      END CASE;
223
    END PROCESS;
224
  END GENERATE;
225
 
226
  XHDL4 : IF (C_DATA_WIDTH = 64) GENERATE
227
    packet_fmt <= M_AXIS_RX_TDATA(30 DOWNTO 29);
228
    packet_td <= M_AXIS_RX_TDATA(15);
229
    payload_len <= M_AXIS_RX_TDATA(9 DOWNTO 0) WHEN ((packet_fmt(1)) = '1') ELSE  "0000000000";
230
 
231
    xhdl5 <= packet_fmt(0) & packet_td;
232
    --  64-bit mode: no straddling, so always 2 DWORDs
233
    PROCESS (packet_fmt, packet_td,xhdl5)
234
    BEGIN
235
      CASE xhdl5 IS
236
        -- Header +   TD   - Data currently on interface
237
        WHEN "00" =>
238
          packet_overhead <= "0011" + "0000" - "0010";
239
        WHEN "01" =>
240
          packet_overhead <= "0011" + "0001" - "0010";
241
        WHEN "10" =>
242
          packet_overhead <= "0100" + "0000" - "0010";
243
        WHEN "11" =>
244
          packet_overhead <= "0100" + "0001" - "0010";
245
        WHEN OTHERS =>
246
          packet_overhead <= "0000" + "0000" - "0000";
247
      END CASE;
248
    END PROCESS;
249
  END GENERATE;
250
 
251
  XHDL6 : IF (C_DATA_WIDTH = 32) GENERATE
252
    packet_fmt <= M_AXIS_RX_TDATA(30 DOWNTO 29);
253
    packet_td <= M_AXIS_RX_TDATA(15);
254
    payload_len <= M_AXIS_RX_TDATA(9 DOWNTO 0) WHEN ((packet_fmt(1)) = '1') ELSE "0000000000";
255
 
256
    xhdl7 <= packet_fmt(0) & packet_td;
257
    -- 32-bit mode: no straddling, so always 1 DWORD
258
    PROCESS (packet_fmt, packet_td,xhdl7)
259
    BEGIN
260
      CASE xhdl7 IS
261
        WHEN "00" =>
262
          packet_overhead <= "0011" + "0000" - "0001";
263
        WHEN "01" =>
264
          packet_overhead <= "0011" + "0001" - "0001";
265
        WHEN "10" =>
266
          packet_overhead <= "0100" + "0000" - "0001";
267
        WHEN "11" =>
268
          packet_overhead <= "0100" + "0001" - "0001";
269
        WHEN OTHERS =>
270
          packet_overhead <= "0000" + "0000" - "0000";
271
      END CASE;
272
    END PROCESS;
273
  END GENERATE;
274
 
275
  -- Now calculate actual packet length, adding the packet overhead and the
276
  -- payload length. This is signed math, so sign-extend packet_overhead.
277
  -- NOTE: a payload length of zero means 1024 DW in the PCIe spec, but this behavior isn't supported in our block.
278
 
279
    new_pkt_len <= (packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) &
280
                    packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(2 DOWNTO 0))
281
                   + ("00" & payload_len);
282
 
283
 
284
  -- Math signals needed in the state machine below. These are seperate wires to
285
  -- help ensure synthesis tools are smart about optimizing them.
286
  pkt_len_counter_dec <= reg_pkt_len_counter - INTERFACE_WIDTH_DWORDS;
287
  pkt_done <= '1' WHEN (reg_pkt_len_counter <= INTERFACE_WIDTH_DWORDS) ELSE '0';
288
 
289
 
290
  PROCESS (cur_state, M_AXIS_RX_TVALID, M_AXIS_RX_TREADY, eof, new_pkt_len, reg_pkt_len_counter,
291
           pkt_len_counter_dec, straddle_sof, pkt_done)
292
  BEGIN
293
 
294
    CASE cur_state IS
295
      -- IDLE state: the interface is IDLE and we're waiting for a packet to
296
      -- start. If a packet starts, move to state IN_PACKET and begin tracking it as long as it's NOT
297
      -- a signle cycle packet (indicated by assertion of eof at packet start)
298
      WHEN IDLE =>
299
        IF ((M_AXIS_RX_TVALID = '1') and (M_AXIS_RX_TREADY = '1') and (eof = '0')) THEN next_state <= IN_PACKET;
300
        ELSE
301
                next_state <= IDLE;
302
        END IF;
303
        pkt_len_counter <= new_pkt_len;
304
      -- IN_PACKET: a multi -cycle packet is in progress and we're tracking it. We are
305
      -- in lock-step with the AXI interface decrementing our packet length
306
      -- tracking reg, and waiting for the packet to finish.
307
      -- If packet finished and a new one starts, this is a straddle situation.
308
      -- Next state is IN_PACKET (128-bit only).
309
      -- If the current packet is done, next state is IDLE.
310
      -- Otherwise, next state is IN_PACKET.
311
      WHEN IN_PACKET =>
312
        -- Straddle packet
313
        IF ((C_DATA_WIDTH = 128) AND straddle_sof = '1' AND M_AXIS_RX_TVALID = '1') THEN
314
          pkt_len_counter <= new_pkt_len;
315
          next_state <= IN_PACKET;
316
        -- Current packet finished
317
        ELSIF (M_AXIS_RX_TREADY = '1' AND pkt_done = '1') THEN
318
          pkt_len_counter <= new_pkt_len;
319
          next_state <= IDLE ;
320
 
321
        ELSE
322
          IF (M_AXIS_RX_TREADY = '1') THEN
323
            -- Packet in progress
324
            pkt_len_counter <= pkt_len_counter_dec;
325
          ELSE
326
            -- Throttled
327
            pkt_len_counter <= reg_pkt_len_counter;
328
          END IF;
329
 
330
          next_state <= IN_PACKET;
331
        END IF;
332
      WHEN OTHERS =>
333
        pkt_len_counter <= reg_pkt_len_counter;
334
        next_state <= IDLE ;
335
    END CASE;
336
  END PROCESS;
337
 
338
  --Synchronous NULL packet generator state machine logic
339
  PROCESS (USER_CLK)
340
  BEGIN
341
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
342
      IF (USER_RST = '1') THEN
343
        cur_state <= IDLE  AFTER (TCQ)*1 ps;
344
        reg_pkt_len_counter <= (others => '0')  AFTER (TCQ)*1 ps;
345
      ELSE
346
        cur_state <= next_state AFTER (TCQ)*1 ps;
347
        reg_pkt_len_counter <= pkt_len_counter  AFTER (TCQ)*1 ps;
348
      END IF;
349
    END IF;
350
  END PROCESS;
351
 
352
  --Generate tkeep/is_eof for an end-of-packet situation.
353
  XHDL8 : IF (C_DATA_WIDTH = 128) GENERATE
354
    -- Assign null_is_eof depending on how many DWORDs are left in the packet.
355
    PROCESS (pkt_len_counter)
356
    BEGIN
357
      CASE pkt_len_counter IS
358
        WHEN "000000000001" =>
359
          null_is_eof <= "10011";
360
        WHEN "000000000010" =>
361
          null_is_eof <= "10111";
362
        WHEN "000000000011" =>
363
          null_is_eof <= "11011";
364
        WHEN "000000000100" =>
365
          null_is_eof <= "11111";
366
        WHEN OTHERS =>
367
          null_is_eof <= "00011";
368
      END CASE;
369
    END PROCESS;
370
 
371
    --tkeep not used in 128-bit interface
372
    eof_tkeep <= (others => '0') ; --'0' & '0' & '0' & '0';
373
  END GENERATE;
374
 
375
  XHDL9 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
376
    XHDL10 : IF (C_DATA_WIDTH = 64) GENERATE
377
      -- Assign null_is_eof depending on how many DWORDs are left in the packet.
378
      PROCESS (pkt_len_counter)
379
      BEGIN
380
        CASE pkt_len_counter IS
381
          WHEN "000000000001" =>
382
            null_is_eof <= "10011";
383
          WHEN "000000000010" =>
384
            null_is_eof <= "10111";
385
          WHEN OTHERS =>
386
            null_is_eof <= "00011";
387
        END CASE;
388
      END PROCESS;
389
 
390
      -- Assign tkeep to 0xFF or 0x0F depending on how many DWORDs are left in the current packet.
391
      eof_tkeep <= X"FF" WHEN (pkt_len_counter = "000000000010") ELSE X"0F";
392
    END GENERATE;
393
 
394
    XHDL11 : IF (NOT(C_DATA_WIDTH = 64)) GENERATE
395
      PROCESS (pkt_len_counter)
396
      BEGIN
397
        --is_eof is either on or off in 32-bit interface
398
        IF (pkt_len_counter = "000000000001") THEN
399
          null_is_eof <= "10011";
400
        ELSE
401
          null_is_eof <= "10011";
402
        END IF;
403
      END PROCESS;
404
 
405
      --The entire DWORD is always valid in 32-bit mode, so tkeep is always 0xF
406
      eof_tkeep <= "1111";
407
    END GENERATE;
408
  END GENERATE;
409
 
410
  --Finally, use everything we've generated to calculate our NULL outputs
411
  NULL_RX_TVALID <= '1';
412
  null_rx_tlast_xhdl0 <= '1' WHEN (pkt_len_counter <= INTERFACE_WIDTH_DWORDS) ELSE '0' ;
413
  NULL_RX_tkeep <= eof_tkeep WHEN (null_rx_tlast_xhdl0 = '1') ELSE  (others => '1');
414
  NULL_RDST_RDY <= null_rx_tlast_xhdl0 ;
415
END TRANS;

powered by: WebSVN 2.1.0

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