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_tx_thrtl_ctl.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_tx_thrtl_ctl.vhd
52
-- Version    : 2.3
53
--
54
-- Description:
55
--    TX throttle controller. Anticipates back-pressure from PCIe block and
56
--      preemptively back-pressures user design (packet boundary throttling).
57
--
58
--      Notes:
59
--      Optional notes section.
60
--
61
--      Hierarchical:
62
--        axi_basic_top
63
--          axi_basic_tx
64
--            axi_basic_tx_thrtl_ctl
65
--------------------------------------------------------------------------------
66
-- Library Declarations
67
--------------------------------------------------------------------------------
68
 
69
LIBRARY ieee;
70
   USE ieee.std_logic_1164.all;
71
   USE ieee.std_logic_unsigned.all;
72
 
73
 
74
ENTITY axi_basic_tx_thrtl_ctl IS
75
   GENERIC (
76
      C_DATA_WIDTH              : INTEGER := 128;      -- RX/TX interface data width
77
      C_FAMILY                  : STRING := "X7";      -- Targeted FPGA family
78
      C_ROOT_PORT               : BOOLEAN := FALSE;   -- PCIe block is in root port mode
79
      TCQ                       : INTEGER := 1         -- Clock to Q time
80
   );
81
   PORT (
82
     -- AXI TX
83
     -------------
84
      S_AXIS_TX_TDATA           : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX data from user
85
      S_AXIS_TX_TVALID          : IN STD_LOGIC                     := '0';    -- TX data is valid
86
      S_AXIS_TX_TUSER           : IN STD_LOGIC_VECTOR(3 DOWNTO 0)  := "0000"; -- TX user signals
87
      S_AXIS_TX_TLAST           : IN STD_LOGIC                     := '0';    -- TX data is last
88
 
89
     -- User Misc.
90
     -------------
91
      USER_TURNOFF_OK           : IN STD_LOGIC                     := '0';    -- Turnoff OK from user
92
      USER_TCFG_GNT             : IN STD_LOGIC                     := '0';    -- Send cfg OK from user
93
 
94
     -- TRN TX
95
     -------------
96
      TRN_TBUF_AV               : IN STD_LOGIC_VECTOR(5 DOWNTO 0)  := "000000"; -- TX buffers available
97
      TRN_TDST_RDY              : IN STD_LOGIC                     := '0';     -- TX destination ready
98
 
99
     -- TRN Misc.
100
     -------------
101
      TRN_TCFG_REQ              : IN STD_LOGIC                     := '0';     -- TX config request
102
      TRN_TCFG_GNT              : OUT STD_LOGIC                    ;--:= '0';     -- RX config grant
103
      TRN_LNK_UP                : IN STD_LOGIC                     := '0';     -- PCIe link up
104
 
105
     -- 7 Series/Virtex6 PM
106
     -------------
107
      CFG_PCIE_LINK_STATE       : IN STD_LOGIC_VECTOR(2 DOWNTO 0)  := "000";    -- Encoded PCIe link state
108
 
109
     -- Virtex6 PM
110
     -------------
111
      CFG_PM_SEND_PME_TO        : IN STD_LOGIC                     := '0';              -- PM send PME turnoff msg
112
      CFG_PMCSR_POWERSTATE      : IN STD_LOGIC_VECTOR(1 DOWNTO 0)  := "00";             -- PMCSR power state
113
      TRN_RDLLP_DATA            : IN STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00000000";      -- RX DLLP data
114
      TRN_RDLLP_SRC_RDY         : IN STD_LOGIC                     := '0';              -- RX DLLP source ready
115
 
116
     -- Virtex6/Spartan6 PM
117
     -------------
118
      CFG_TO_TURNOFF            : IN STD_LOGIC                     := '0';    -- Turnoff request
119
      CFG_TURNOFF_OK            : OUT STD_LOGIC                    ;--:= '0';    -- Turnoff grant
120
 
121
     -- System
122
     -------------
123
      TREADY_THRTL              : OUT STD_LOGIC                    ;--:= '0';   -- TREADY to pipeline
124
      USER_CLK                  : IN STD_LOGIC                     := '0';   -- user clock from block
125
      USER_RST                  : IN STD_LOGIC                     := '0'    -- user reset from block
126
   );
127
END axi_basic_tx_thrtl_ctl;
128
 
129
ARCHITECTURE trans OF axi_basic_tx_thrtl_ctl IS
130
 
131
   function tbuf_av_min_fn (
132
     constant wdt   : integer)
133
     return integer is
134
      variable buf_min : integer := 1;
135
   begin  -- tbuf_av_min_fn
136
 
137
     if (wdt = 128) then
138
       buf_min := 5;
139
     elsif (wdt = 64) then
140
       buf_min := 1;
141
     else
142
       buf_min := 0;
143
     end if;
144
     return buf_min;
145
   end tbuf_av_min_fn;
146
 
147
   function tbuf_gap_time_fn (
148
     constant wdt   : integer)
149
     return integer is
150
      variable gap_time : integer := 1;
151
   begin  -- tbuf_gap_time_fn
152
 
153
     if (wdt = 128) then
154
       gap_time := 4;
155
     else
156
       gap_time := 1;
157
     end if;
158
     return gap_time;
159
   end tbuf_gap_time_fn;
160
 
161
   -- Thrtl user when TBUF hits this val
162
   CONSTANT TBUF_AV_MIN               : INTEGER :=  tbuf_av_min_fn(C_DATA_WIDTH);
163
 
164
   -- Pause user when TBUF hits this val
165
   CONSTANT TBUF_AV_GAP               : INTEGER :=  TBUF_AV_MIN + 1;
166
 
167
   -- GAP pause time - the latency from the time a packet is accepted on the TRN
168
   -- interface to the time trn_tbuf_av from the Block will decrement.
169
   CONSTANT TBUF_GAP_TIME             : INTEGER :=  tbuf_gap_time_fn(C_DATA_WIDTH);
170
 
171
   -- Latency time from when tcfg_gnt is asserted to when PCIe block will throttle
172
   CONSTANT TCFG_LATENCY_TIME         : INTEGER :=  2;
173
 
174
   CONSTANT LINKSTATE_L0              : INTEGER := 0;
175
   CONSTANT LINKSTATE_PPM_L1          : INTEGER := 1;
176
   CONSTANT LINKSTATE_PPM_L1_TRANS    : INTEGER := 5;
177
   CONSTANT LINKSTATE_PPM_L23R_TRANS  : INTEGER := 6;
178
   CONSTANT PM_ENTER_L1               : INTEGER := 32;
179
   CONSTANT POWERSTATE_D0             : INTEGER := 0;
180
 
181
   SIGNAL lnk_up_thrtl           : STD_LOGIC;
182
   SIGNAL lnk_up_trig            : STD_LOGIC;
183
   SIGNAL lnk_up_exit            : STD_LOGIC;
184
   SIGNAL tbuf_av_min_thrtl      : STD_LOGIC;
185
   SIGNAL tbuf_av_min_trig       : STD_LOGIC;
186
   SIGNAL tbuf_av_gap_thrtl      : STD_LOGIC;
187
   SIGNAL tbuf_gap_cnt           : STD_LOGIC_VECTOR(2 DOWNTO 0);
188
   SIGNAL tbuf_gap_cnt_t         : STD_LOGIC_VECTOR(2 DOWNTO 0);
189
   SIGNAL tbuf_av_gap_trig       : STD_LOGIC;
190
   SIGNAL tbuf_av_gap_exit       : STD_LOGIC;
191
   SIGNAL gap_trig_tlast         : STD_LOGIC;
192
   SIGNAL gap_trig_tlast_1       : STD_LOGIC;
193
   SIGNAL gap_trig_decr          : STD_LOGIC;
194
   SIGNAL gap_trig_decr_1        : STD_LOGIC;
195
   SIGNAL gap_trig_decr_2        : STD_LOGIC;
196
   SIGNAL tbuf_av_d              : STD_LOGIC_VECTOR(5 DOWNTO 0);
197
   SIGNAL tcfg_req_thrtl         : STD_LOGIC;
198
   SIGNAL tcfg_req_cnt           : STD_LOGIC_VECTOR(1 DOWNTO 0);
199
   SIGNAL trn_tdst_rdy_d         : STD_LOGIC;
200
   SIGNAL tcfg_req_trig          : STD_LOGIC;
201
   SIGNAL tcfg_req_exit          : STD_LOGIC;
202
   SIGNAL pre_throttle           : STD_LOGIC;
203
   SIGNAL reg_throttle           : STD_LOGIC;
204
   SIGNAL exit_crit              : STD_LOGIC;
205
   SIGNAL reg_tcfg_gnt           : STD_LOGIC;
206
   SIGNAL trn_tcfg_req_d         : STD_LOGIC;
207
   SIGNAL tcfg_gnt_pending       : STD_LOGIC;
208
   SIGNAL wire_to_turnoff        : STD_LOGIC;
209
   SIGNAL reg_turnoff_ok         : STD_LOGIC;
210
   SIGNAL tready_thrtl_mux       : STD_LOGIC;
211
   SIGNAL ppm_L1_thrtl           : STD_LOGIC;
212
   SIGNAL ppm_L1_trig            : STD_LOGIC;
213
   SIGNAL ppm_L1_exit            : STD_LOGIC;
214
   SIGNAL cfg_pcie_link_state_d  : STD_LOGIC_VECTOR(2 DOWNTO 0);
215
   SIGNAL trn_rdllp_src_rdy_d    : STD_LOGIC;
216
   SIGNAL ppm_L23_thrtl          : STD_LOGIC;
217
   SIGNAL ppm_L23_trig           : STD_LOGIC;
218
   SIGNAL cfg_turnoff_ok_pending : STD_LOGIC;
219
   SIGNAL reg_tlast              : STD_LOGIC;
220
   SIGNAL cur_state              : STD_LOGIC;
221
   SIGNAL next_state             : STD_LOGIC;
222
 
223
   SIGNAL reg_axi_in_pkt         : STD_LOGIC;
224
   SIGNAL axi_in_pkt             : STD_LOGIC;
225
   SIGNAL axi_pkt_ending         : STD_LOGIC;
226
   SIGNAL axi_throttled          : STD_LOGIC;
227
   SIGNAL axi_thrtl_ok           : STD_LOGIC;
228
   SIGNAL tx_ecrc_pause          : STD_LOGIC;
229
 
230
   SIGNAL gap_trig_tcfg          : STD_LOGIC;
231
   SIGNAL reg_to_turnoff         : STD_LOGIC;
232
   SIGNAL reg_tx_ecrc_pkt        : STD_LOGIC;
233
 
234
   SIGNAL tx_ecrc_pkt            : STD_LOGIC;
235
   SIGNAL packet_fmt             : STD_LOGIC_VECTOR(1 DOWNTO 0);
236
   SIGNAL packet_td              : STD_LOGIC;
237
   SIGNAL header_len             : STD_LOGIC_VECTOR(2 DOWNTO 0);
238
   SIGNAL payload_len            : STD_LOGIC_VECTOR(9 DOWNTO 0);
239
   SIGNAL packet_len             : STD_LOGIC_VECTOR(13 DOWNTO 0);
240
   SIGNAL pause_needed           : STD_LOGIC;
241
 
242
   -- Declare intermediate signals for referenced outputs
243
   SIGNAL trn_tcfg_gnt_xhdl2     : STD_LOGIC;
244
   SIGNAL cfg_turnoff_ok_xhdl0   : STD_LOGIC;
245
   SIGNAL tready_thrtl_xhdl1     : STD_LOGIC;
246
--   TYPE T_STATE is  (IDLE_A,THROTTLE);
247
--   SIGNAL CUR_STATE_A, NEXT_STATE_A : T_STATE;
248
   SIGNAL CUR_STATE_A, NEXT_STATE_A : STD_LOGIC;
249
 
250
   constant IDLE : std_logic := '0';
251
   constant THROTTLE : std_logic := '1';
252
 
253
BEGIN
254
   -- Drive referenced outputs
255
   TRN_TCFG_GNT     <= trn_tcfg_gnt_xhdl2;
256
   CFG_TURNOFF_OK   <= cfg_turnoff_ok_xhdl0;
257
   TREADY_THRTL     <= tready_thrtl_xhdl1;
258
    --------------------------------------------------------------------------------
259
    -- THROTTLE REASON: PCIe link is down                                         --
260
    --   - When to throttle: trn_lnk_up deasserted                                --
261
    --   - When to stop: trn_tdst_rdy assesrted                                   --
262
    --------------------------------------------------------------------------------
263
   lnk_up_trig      <= NOT(TRN_LNK_UP);
264
   lnk_up_exit      <= TRN_TDST_RDY;
265
 
266
   PROCESS (USER_CLK)
267
   BEGIN
268
           IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
269
                   IF (USER_RST = '1') THEN
270
                           lnk_up_thrtl <= '1'  AFTER (TCQ)*1 ps;
271
                   ELSE
272
                           IF (lnk_up_trig = '1') THEN
273
                                   lnk_up_thrtl <= '1'   AFTER (TCQ)*1 ps;
274
                           ELSIF (lnk_up_exit = '1') THEN
275
                                   lnk_up_thrtl <= '0'   AFTER (TCQ)*1 ps;
276
                           END IF;
277
                   END IF;
278
           END IF;
279
   END PROCESS;
280
 
281
  --------------------------------------------------------------------------------
282
  -- THROTTLE REASON: Transmit buffers depleted                                 --
283
  --   - When to throttle: trn_tbuf_av falls to 0                               --
284
  --   - When to stop: trn_tbuf_av rises above 0 again                          --
285
  --------------------------------------------------------------------------------
286
   tbuf_av_min_trig <= '1' WHEN (TRN_TBUF_AV <= TBUF_AV_MIN) ELSE '0';
287
 
288
   PROCESS (USER_CLK)
289
   BEGIN
290
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
291
              IF (USER_RST = '1') THEN
292
                      tbuf_av_min_thrtl <= '0'   AFTER (TCQ)*1 ps;
293
              ELSE
294
                      IF (tbuf_av_min_trig = '1') THEN
295
                              tbuf_av_min_thrtl <= '1'  AFTER (TCQ)*1 ps;
296
                      -- The exit condition for tbuf_av_min_thrtl is !tbuf_av_min_trig
297
                      ELSE
298
                              tbuf_av_min_thrtl <= '0'  AFTER (TCQ)*1 ps;
299
                      END IF;
300
              END IF;
301
      END IF;
302
   END PROCESS;
303
 
304
   ------------------------------------------------------------------------------//
305
   -- THROTTLE REASON: Transmit buffers getting low                              //
306
   --   - When to throttle: trn_tbuf_av falls below "gap" threshold TBUF_AV_GAP  //
307
   --   - When to stop: after TBUF_GAP_TIME cycles elapse                        //
308
   --                                                                            //
309
   -- If we're about to run out of transmit buffers, throttle the user for a     //
310
   -- few clock cycles to give the PCIe block time to catch up. This is          //
311
   -- needed to compensate for latency in decrementing trn_tbuf_av in the PCIe   //
312
   -- Block transmit path.                                                       //
313
   ------------------------------------------------------------------------------//
314
 
315
   -- Detect two different scenarios for buffers getting low:
316
   -- 1) If we see a TLAST. a new packet has been inserted into the buffer, and
317
   --    we need to pause and let that packet "soak in"
318
   gap_trig_tlast_1 <=  '1' WHEN (TRN_TBUF_AV <= TBUF_AV_GAP) ELSE '0';
319
   gap_trig_tlast   <=  (gap_trig_tlast_1 AND S_AXIS_TX_TVALID AND tready_thrtl_xhdl1 AND S_AXIS_TX_TLAST );
320
 
321
   -- 2) Any time tbug_avail decrements to the TBUF_AV_GAP threshold, we need to
322
   --    pause and make sure no other packets are about to soak in and cause the
323
   --    buffer availability to drop further.
324
   gap_trig_decr_1    <=  '1' WHEN ( TRN_TBUF_AV = TBUF_AV_GAP) ELSE '0' ;
325
   gap_trig_decr_2  <=  '1' WHEN (tbuf_av_d = TBUF_AV_GAP + 1) ELSE '0' ;
326
 
327
   gap_trig_decr    <= ( gap_trig_decr_1 AND gap_trig_decr_2);
328
 
329
   gap_trig_tcfg    <= ((tcfg_req_thrtl AND tcfg_req_exit));
330
   tbuf_av_gap_trig <= (gap_trig_tlast OR gap_trig_decr OR gap_trig_tcfg) ;
331
   tbuf_av_gap_exit <= '1' WHEN (tbuf_gap_cnt = "000") ELSE '0' ;
332
   tbuf_gap_cnt_t   <= "100" WHEN (C_DATA_WIDTH = 128) ELSE "001";
333
   PROCESS (USER_CLK)
334
   BEGIN
335
           IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
336
                   IF (USER_RST = '1') THEN
337
                           tbuf_av_gap_thrtl <= '0'       AFTER (TCQ)*1 ps;
338
                           tbuf_gap_cnt      <= "000"     AFTER (TCQ)*1 ps;
339
                           tbuf_av_d         <= "000000"  AFTER (TCQ)*1 ps;
340
                   ELSE
341
                           IF (tbuf_av_gap_trig = '1') THEN
342
                                   tbuf_av_gap_thrtl <= '1'   AFTER (TCQ)*1 ps;
343
                           ELSIF (tbuf_av_gap_exit = '1') THEN
344
                                   tbuf_av_gap_thrtl <= '0'   AFTER (TCQ)*1 ps;
345
                           END IF;
346
                           -- tbuf gap counter:
347
                           -- This logic controls the length of the throttle condition when tbufs are
348
                           -- getting low.
349
                           IF (tbuf_av_gap_thrtl = '1' AND (CUR_STATE_A = THROTTLE)) THEN
350
                                   IF (tbuf_gap_cnt > "000") THEN
351
                                           tbuf_gap_cnt <= tbuf_gap_cnt - "001"  AFTER (TCQ)*1 ps;
352
                                   END IF;
353
                           ELSE
354
                                   tbuf_gap_cnt <= tbuf_gap_cnt_t AFTER (TCQ)*1 ps;
355
                           END IF;
356
                           tbuf_av_d <= TRN_TBUF_AV  AFTER (TCQ)*1 ps;
357
                   END IF;
358
           END IF;
359
   END PROCESS;
360
 
361
   ------------------------------------------------------------------------------
362
   -- THROTTLE REASON: Block needs to send a CFG response
363
   --   - When to throttle: trn_tcfg_req and user_tcfg_gnt asserted
364
   --   - When to stop: after trn_tdst_rdy transitions to unasserted
365
   --
366
   -- If the block needs to send a response to a CFG packet, this will cause
367
   -- the subsequent deassertion of trn_tdst_rdy. When the user design permits,
368
   -- grant permission to the block to service request and throttle the user.
369
   ------------------------------------------------------------------------------
370
 
371
   tcfg_req_trig <= (TRN_TCFG_REQ AND reg_tcfg_gnt);
372
   tcfg_req_exit <= '1' WHEN (tcfg_req_cnt = "00" AND trn_tdst_rdy_d = '0' AND  TRN_TDST_RDY ='1') ELSE '0';
373
 
374
   PROCESS (USER_CLK)
375
   BEGIN
376
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
377
              IF (USER_RST = '1') THEN
378
                      tcfg_req_thrtl   <= '0'   AFTER (TCQ)*1 ps;
379
                      trn_tcfg_req_d   <= '0'   AFTER (TCQ)*1 ps;
380
                      trn_tdst_rdy_d   <= '1'   AFTER (TCQ)*1 ps;
381
                      reg_tcfg_gnt     <= '0'   AFTER (TCQ)*1 ps;
382
                      tcfg_req_cnt     <= "00"  AFTER (TCQ)*1 ps;
383
                      tcfg_gnt_pending <= '0'   AFTER (TCQ)*1 ps;
384
              ELSE
385
                      IF (tcfg_req_trig = '1') THEN
386
                              tcfg_req_thrtl <= '1'  AFTER (TCQ)*1 ps;
387
                      ELSIF (tcfg_req_exit = '1') THEN
388
                              tcfg_req_thrtl <= '0'  AFTER (TCQ)*1 ps;
389
                      END IF;
390
                      -- We need to wait the appropriate amount of time for the tcfg_gnt to
391
                      -- "sink in" to the PCIe block. After that, we know that the PCIe block will
392
                      -- not reassert trn_tdst_rdy until the CFG request has been serviced. If a
393
                      -- new request is being service (trn_tcfg_gnt == 1), then reset the timer.
394
                      IF ((NOT(trn_tcfg_req_d = '1' ) AND TRN_TCFG_REQ = '1' ) OR tcfg_gnt_pending = '1') THEN
395
                              -- As TCFG_LATENCY_TIME value is 2
396
                              tcfg_req_cnt <= "10"  AFTER (TCQ)*1 ps;
397
                      ELSE
398
                              IF (tcfg_req_cnt > "00") THEN
399
                                      tcfg_req_cnt <= tcfg_req_cnt - "01"  AFTER (TCQ)*1 ps;
400
                              END IF;
401
                      END IF;
402
                      -- Make sure trn_tcfg_gnt pulses once for one clock cycle for every
403
                      -- cfg packet request.
404
                      IF (TRN_TCFG_REQ = '1' AND NOT(trn_tcfg_req_d = '1' )) THEN
405
                              tcfg_gnt_pending   <= '1' AFTER (TCQ)*1 ps;
406
                      ELSIF (trn_tcfg_gnt_xhdl2 = '1') THEN
407
                              tcfg_gnt_pending   <= '0' AFTER (TCQ)*1 ps;
408
                      END IF;
409
 
410
                      trn_tcfg_req_d   <= TRN_TCFG_REQ   AFTER (TCQ)*1 ps;
411
                      trn_tdst_rdy_d   <= TRN_TDST_RDY   AFTER (TCQ)*1 ps;
412
                      reg_tcfg_gnt     <= USER_TCFG_GNT  AFTER (TCQ)*1 ps;
413
              END IF;
414
      END IF;
415
   END PROCESS;
416
 
417
   ------------------------------------------------------------------------------
418
   -- THROTTLE REASON: Block needs to transition to low power state PPM L1
419
   --   - When to throttle: appropriate low power state signal asserted
420
   --     (architecture dependent)
421
   --   - When to stop: cfg_pcie_link_state goes to proper value (C_ROOT_PORT
422
   --     dependent)
423
   --
424
   -- If the block needs to transition to PM state PPM L1, we need to finish
425
   -- up what we're doing and throttle immediately.
426
   ------------------------------------------------------------------------------
427
   xhdl3 : IF ((C_FAMILY = "X7") AND (C_ROOT_PORT)) GENERATE
428
           -- PPM L1 signals for 7 Series in RC mode
429
           ppm_L1_trig <=  '1' WHEN ((cfg_pcie_link_state_d = "000") AND (CFG_PCIE_LINK_STATE = "101")) ELSE '0';
430
           ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "001") ELSE '0';
431
   END GENERATE;
432
 
433
  -- PPM L1 signals for 7 Series in EP mode
434
   xhdl4 : IF (NOT((C_FAMILY = ("X7")) AND (C_ROOT_PORT))) GENERATE
435
           xhdl5 : IF ((C_FAMILY = ("X7")) AND (NOT(C_ROOT_PORT))) GENERATE
436
                   ppm_L1_trig <= '1' WHEN ((cfg_pcie_link_state_d = "000") AND (CFG_PCIE_LINK_STATE = "101")) ELSE '0';
437
                   ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "000") ELSE '0';
438
           END GENERATE;
439
      -- PPM L1 signals for V6 in RC mode
440
           xhdl6 : IF (NOT((C_FAMILY = ("X7")) AND (NOT(C_ROOT_PORT)))) GENERATE
441
                   xhdl7 : IF ((C_FAMILY = ("V6")) AND (C_ROOT_PORT)) GENERATE
442
                           ppm_L1_trig <= '1' WHEN ((TRN_RDLLP_DATA(31 DOWNTO 24) = x"20") AND TRN_RDLLP_SRC_RDY = '1' AND trn_rdllp_src_rdy_d = '0') ELSE '0';
443
                           ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "001") ELSE '0';
444
                   END GENERATE;
445
         -- PPM L1 signals for V6 in EP mode
446
                   xhdl8 : IF (NOT((C_FAMILY = ("V6")) AND (C_ROOT_PORT))) GENERATE
447
                           xhdl9 : IF ((C_FAMILY = ("V6")) AND (NOT(C_ROOT_PORT))) GENERATE
448
                                   ppm_L1_trig <= '1' WHEN (CFG_PMCSR_POWERSTATE /= "000") ELSE '0';
449
                                   ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "000") ELSE '0';
450
                           END GENERATE;
451
            -- PPM L1 detection not supported for S6
452
                           xhdl10 : IF (NOT((C_FAMILY = ("V6")) AND (NOT(C_ROOT_PORT)))) GENERATE
453
                                   ppm_L1_trig <= '0';
454
                                   ppm_L1_exit <= '1';
455
                           END GENERATE;
456
                   END GENERATE;
457
           END GENERATE;
458
   END GENERATE;
459
 
460
   PROCESS (USER_CLK)
461
   BEGIN
462
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
463
              IF (USER_RST = '1') THEN
464
                      ppm_L1_thrtl          <= '0'   AFTER (TCQ)*1 ps;
465
                      cfg_pcie_link_state_d <= "000" AFTER (TCQ)*1 ps;
466
                      trn_rdllp_src_rdy_d   <= '0'   AFTER (TCQ)*1 ps;
467
              ELSE
468
                      IF (ppm_L1_trig = '1') THEN
469
                              ppm_L1_thrtl  <= '1'   AFTER (TCQ)*1 ps;
470
                      ELSIF (ppm_L1_exit = '1') THEN
471
                              ppm_L1_thrtl  <= '0'   AFTER (TCQ)*1 ps;
472
                      END IF;
473
                      cfg_pcie_link_state_d <= CFG_PCIE_LINK_STATE  AFTER (TCQ)*1 ps;
474
                      trn_rdllp_src_rdy_d <= TRN_RDLLP_SRC_RDY      AFTER (TCQ)*1 ps;
475
              END IF;
476
      END IF;
477
   END PROCESS;
478
 
479
    ------------------------------------------------------------------------------
480
    -- THROTTLE REASON: Block needs to transition to low power state PPM L2/3
481
    --   - When to throttle: appropriate PM signal indicates a transition to
482
    --     L2/3 is pending or in progress (family and role dependent)
483
    --   - When to stop: never (the only path out of L2/3 is a full reset)
484
    --
485
    -- If the block needs to transition to PM state PPM L2/3, we need to finish
486
    -- up what we're doing and throttle when the user gives permission.
487
    ------------------------------------------------------------------------------
488
    -- PPM L2/3 signals for 7 Series in RC mode
489
   xhdl11 : IF ((C_FAMILY = ("X7")) AND (C_ROOT_PORT)) GENERATE
490
           ppm_L23_trig <= '1' WHEN (cfg_pcie_link_state_d = "110") ELSE '0';
491
           wire_to_turnoff <= '0';
492
   END GENERATE;
493
 
494
   -- PPM L2/3 signals for V6 in RC mode
495
   xhdl12 : IF (NOT((C_FAMILY = ("X7")) AND (C_ROOT_PORT))) GENERATE
496
           xhdl13 : IF ((C_FAMILY = ("V6")) AND (C_ROOT_PORT)) GENERATE
497
                   ppm_L23_trig <= CFG_PM_SEND_PME_TO;
498
                   wire_to_turnoff <= '0';
499
           END GENERATE;
500
            -- PPM L2/3 signals in EP mode
501
           xhdl14 : IF (NOT((C_FAMILY = ("V6")) AND (C_ROOT_PORT))) GENERATE
502
                   ppm_L23_trig <= (wire_to_turnoff AND reg_turnoff_ok);
503
                    -- PPM L2/3 signals for 7 Series in EP mode
504
                    -- For 7 Series, cfg_to_turnoff pulses once when a turnoff request is
505
                    -- outstanding, so we need a "sticky" register that grabs the request.
506
                   xhdl15 : IF (C_FAMILY = ("X7")) GENERATE
507
                           PROCESS (USER_CLK)
508
                           BEGIN
509
                                   IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
510
                                           IF (USER_RST = '1') THEN
511
                                                   reg_to_turnoff <= '0' AFTER (TCQ)*1 ps;
512
                                           ELSE
513
                                                   IF (CFG_TO_TURNOFF = '1') THEN
514
                                                           reg_to_turnoff <= '1' AFTER (TCQ)*1 ps;
515
                                                   END IF;
516
                                           END IF;
517
                                   END IF;
518
                           END PROCESS;
519
                           wire_to_turnoff <= reg_to_turnoff;
520
                   END GENERATE;
521
                    -- PPM L2/3 signals for V6/S6 in EP mode
522
                    -- In V6 and S6, the to_turnoff signal asserts and remains asserted until
523
                    -- turnoff_ok is asserted, so a sticky reg is not necessary.
524
                   xhdl16 : IF (NOT(C_FAMILY = ("X7"))) GENERATE
525
                           wire_to_turnoff <= CFG_TO_TURNOFF;
526
                   END GENERATE;
527
                   PROCESS (USER_CLK)
528
                   BEGIN
529
                           IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
530
                                   IF (USER_RST = '1') THEN
531
                                           reg_turnoff_ok <= '0' AFTER (TCQ)*1 ps;
532
                                   ELSE
533
                                           reg_turnoff_ok <= USER_TURNOFF_OK AFTER (TCQ)*1 ps;
534
                                   END IF;
535
                           END IF;
536
                   END PROCESS;
537
           END GENERATE;
538
   END GENERATE;
539
 
540
   PROCESS (USER_CLK)
541
   BEGIN
542
           IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
543
                   IF (USER_RST = '1') THEN
544
                           ppm_L23_thrtl <= '0' AFTER (TCQ)*1 ps;
545
                           cfg_turnoff_ok_pending <= '0' AFTER (TCQ)*1 ps;
546
                   ELSE
547
                   -- Make sure cfg_turnoff_ok pulses once for one clock cycle for every
548
                   -- turnoff request.
549
                           IF (ppm_L23_trig = '1') THEN
550
                                   ppm_L23_thrtl <= '1' AFTER (TCQ)*1 ps;
551
                           END IF;
552
                           IF (ppm_L23_trig = '1' AND (ppm_L23_thrtl = '0')) THEN
553
                                   cfg_turnoff_ok_pending <= '1' AFTER (TCQ)*1 ps;
554
                           ELSIF (cfg_turnoff_ok_xhdl0 = '1') THEN
555
                                   cfg_turnoff_ok_pending <= '0' AFTER (TCQ)*1 ps;
556
                           END IF;
557
                   END IF;
558
           END IF;
559
   END PROCESS;
560
 
561
   --------------------------------------------------------------------------------
562
   -- Create axi_thrtl_ok. This signal determines if it's OK to throttle the     --
563
   -- user design on the AXI interface. Since TREADY is registered, this signal  --
564
   -- needs to assert on the cycle ~before~ we actually intend to throttle.      --
565
   -- The only time it's OK to throttle when TVALID is asserted is on the first  --
566
   -- beat of a new packet. Therefore, assert axi_thrtl_ok if one of the         --
567
   -- is true:                                                                   --
568
   --    1) The user is not in a packet and is not starting one                  --
569
   --    2) The user is just finishing a packet                                  --
570
   --    3) We're already throttled, so it's OK to continue throttling           --
571
   --------------------------------------------------------------------------------
572
 
573
   PROCESS (USER_CLK)
574
   BEGIN
575
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
576
              IF (USER_RST = '1') THEN
577
                      reg_axi_in_pkt <= '0' AFTER (TCQ)*1 ps;
578
              ELSE
579
                      IF (S_AXIS_TX_TVALID = '1' AND S_AXIS_TX_TLAST  = '1') THEN
580
                              reg_axi_in_pkt <= '0' AFTER (TCQ)*1 ps;
581
                      ELSIF (tready_thrtl_xhdl1  = '1'  AND S_AXIS_TX_TVALID  = '1') THEN
582
                              reg_axi_in_pkt <= '1' AFTER (TCQ)*1 ps;
583
                      END IF;
584
              END IF;
585
      END IF;
586
   END PROCESS;
587
 
588
   axi_in_pkt     <= (S_AXIS_TX_TVALID OR reg_axi_in_pkt);
589
   axi_pkt_ending <= (S_AXIS_TX_TVALID AND S_AXIS_TX_TLAST);
590
   axi_throttled  <= NOT(tready_thrtl_xhdl1);
591
   axi_thrtl_ok   <= (NOT(axi_in_pkt) OR axi_pkt_ending OR axi_throttled);
592
   --------------------------------------------------------------------------------
593
   -- Throttle CTL State Machine:                                                --
594
   -- Throttle user design when a throttle trigger (or triggers) occur.          --
595
   -- Keep user throttled until all exit criteria have been met.                 --
596
   --------------------------------------------------------------------------------
597
 
598
   -- Immediate throttle signal. Used to "pounce" on a throttle opportunity when
599
   -- we're seeking one
600
   pre_throttle <= (tbuf_av_min_trig OR tbuf_av_gap_trig OR lnk_up_trig OR tcfg_req_trig OR ppm_L1_trig OR ppm_L23_trig);
601
 
602
   -- Registered throttle signals. Used to control throttle state machine
603
   reg_throttle <= (tbuf_av_min_thrtl OR tbuf_av_gap_thrtl OR lnk_up_thrtl OR tcfg_req_thrtl OR ppm_L1_thrtl OR ppm_L23_thrtl);
604
   exit_crit <= (NOT(tbuf_av_min_thrtl) AND NOT(tbuf_av_gap_thrtl) AND (NOT(lnk_up_thrtl)) AND (NOT(tcfg_req_thrtl)) AND (NOT(ppm_L1_thrtl)) AND (NOT(ppm_L23_thrtl)));
605
 
606
   PROCESS (CUR_STATE_A,reg_throttle, axi_thrtl_ok, tcfg_req_thrtl, tcfg_gnt_pending, cfg_turnoff_ok_pending, pre_throttle, exit_crit)
607
   BEGIN
608
      CASE CUR_STATE_A IS
609
         -- IDLE: in this state we're waiting for a trigger event to occur. As
610
         -- soon as an event occurs and the user isn't transmitting a packet, we
611
         -- throttle the PCIe block and the user and next state is THROTTLE.
612
              WHEN (IDLE) =>
613
                      IF(reg_throttle = '1' AND axi_thrtl_ok = '1') THEN
614
                              tready_thrtl_mux <= '0';
615
                              NEXT_STATE_A   <= (THROTTLE);
616
                              -- Assert appropriate grant signal depending on the throttle type.
617
                              IF (tcfg_req_thrtl  = '1') THEN
618
                                      trn_tcfg_gnt_xhdl2    <= '1';   -- For cfg request, grant the request
619
                                      cfg_turnoff_ok_xhdl0  <= '0'; --
620
                              ELSIF (ppm_L23_thrtl = '1') THEN
621
                                      trn_tcfg_gnt_xhdl2    <= '0';    --
622
                                      cfg_turnoff_ok_xhdl0  <= '1';  -- For PM request, permit transition
623
                              ELSE
624
                                      trn_tcfg_gnt_xhdl2    <= '0';  -- Otherwise do nothing
625
                                      cfg_turnoff_ok_xhdl0  <= '0';--
626
                              END IF;
627
                      ELSE
628
                             -- If there's not throttle event, do nothing
629
                             -- Throttle user as soon as possible
630
                              tready_thrtl_mux <= (NOT((axi_thrtl_ok AND pre_throttle)));
631
                              NEXT_STATE_A <= IDLE;
632
                              trn_tcfg_gnt_xhdl2 <= '0';
633
                              cfg_turnoff_ok_xhdl0 <= '0';
634
                      END IF;
635
              -- THROTTLE: in this state the user is throttle and we're waiting for
636
              -- exit criteria, which tells us that the throttle event is over. When
637
              -- the exit criteria is satisfied, de-throttle the user and next state
638
              WHEN (THROTTLE) =>
639
                      IF (exit_crit = '1') THEN
640
                              -- Dethrottle user
641
                              tready_thrtl_mux <= (NOT(pre_throttle));
642
                              NEXT_STATE_A   <= IDLE;
643
                      ELSE
644
                              -- Throttle user
645
                              tready_thrtl_mux <= '0';
646
                              NEXT_STATE_A   <= (THROTTLE);
647
                      END IF;
648
                       -- Assert appropriate grant signal depending on the throttle type.
649
                      IF (tcfg_req_thrtl = '1' AND tcfg_gnt_pending = '1') THEN
650
                              trn_tcfg_gnt_xhdl2     <= '1';   -- For cfg request, grant the request
651
                              cfg_turnoff_ok_xhdl0   <= '0'; --
652
                      ELSIF (cfg_turnoff_ok_pending = '1') THEN
653
                              trn_tcfg_gnt_xhdl2     <= '0';   --
654
                              cfg_turnoff_ok_xhdl0   <= '1'; -- For PM request, permit transition
655
                      ELSE
656
                              trn_tcfg_gnt_xhdl2     <= '0';   -- Otherwise do nothing
657
                              cfg_turnoff_ok_xhdl0   <= '0'; --
658
                      END IF;
659
              WHEN OTHERS =>
660
                      tready_thrtl_mux     <= '0';
661
                      NEXT_STATE_A         <= (IDLE);
662
                      trn_tcfg_gnt_xhdl2   <= '0' ;
663
                      cfg_turnoff_ok_xhdl0 <= '0';
664
      END CASE;
665
   END PROCESS;
666
 
667
 
668
-- Synchronous logic
669
   PROCESS (USER_CLK)
670
   BEGIN
671
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
672
              IF (USER_RST = '1') THEN
673
                      -- Throttle user by default until link comes up
674
                      CUR_STATE_A        <= (THROTTLE) AFTER (TCQ)*1 ps;
675
                      reg_tlast          <= '0' AFTER (TCQ)*1 ps;
676
                      tready_thrtl_xhdl1 <= '0' AFTER (TCQ)*1 ps;
677
              ELSE
678
                      CUR_STATE_A        <= NEXT_STATE_A AFTER (TCQ)*1 ps;
679
                      tready_thrtl_xhdl1 <= (tready_thrtl_mux AND NOT(tx_ecrc_pause)) AFTER (TCQ)*1 ps;
680
                      reg_tlast          <= S_AXIS_TX_TLAST AFTER (TCQ)*1 ps;
681
              END IF;
682
      END IF;
683
   END PROCESS;
684
 
685
 
686
   -- For X7, the PCIe block will generate the ECRC for a packet if trn_tecrc_gen
687
   -- is asserted at SOF. In this case, the Block needs an extra data beat to
688
   -- calculate the ECRC, but only if the following conditions are met:
689
   --  1) there is no empty DWORDS at the end of the packet
690
   --     (i.e. packet length % C_DATA_WIDTH == 0)
691
   --
692
   --  2) There isn't a ECRC in the TLP already, as indicated by the TD bit in the
693
   --     TLP header
694
   --
695
   -- If both conditions are met, the Block will stall the TRN interface for one
696
   -- data beat after EOF. We need to predict this stall and preemptively stall the
697
   -- User for one beat.
698
   xhdl17 : IF (C_FAMILY = ("X7")) GENERATE
699
 
700
      -- Grab necessary packet fields
701
      packet_fmt <= S_AXIS_TX_TDATA(30 DOWNTO 29);
702
      packet_td  <= S_AXIS_TX_TDATA(15);
703
 
704
      -- Calculate total packet length
705
      header_len <= "100" WHEN packet_fmt(0) = '1' ELSE "011";
706
      payload_len <= S_AXIS_TX_TDATA(9 DOWNTO 0) WHEN packet_fmt(1) = '1' ELSE "0000000000";
707
      packet_len  <= ("0000000000" & header_len) + ("0000" & payload_len);
708
 
709
      -- Determine if an ECRC pause is needed
710
      PACKET_LEN_CHECK_128 : IF (C_DATA_WIDTH = 128) GENERATE
711
              pause_needed <= '1' WHEN (packet_len(1 DOWNTO 0) = "00" AND packet_td = '0') ELSE '0';
712
      END GENERATE;
713
 
714
      PACKET_LEN_CHECK_64 : IF (C_DATA_WIDTH /= 128) GENERATE
715
              pause_needed <= '1' WHEN (packet_len(0) = '0' AND packet_td = '0') ELSE '0';
716
      END GENERATE;
717
 
718
      -- Create flag to alert TX pipeline to insert a stall
719
      tx_ecrc_pkt <= S_AXIS_TX_TUSER(0) AND pause_needed AND tready_thrtl_xhdl1 AND S_AXIS_TX_TVALID AND not(reg_axi_in_pkt);
720
 
721
      PROCESS (USER_CLK)
722
      BEGIN
723
              IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
724
                      IF (USER_RST = '1') THEN
725
                              reg_tx_ecrc_pkt <= '0' AFTER (TCQ)*1 ps;
726
                      ELSE
727
                              IF (tx_ecrc_pkt  = '1' AND S_AXIS_TX_TLAST = '0') THEN
728
                                      reg_tx_ecrc_pkt <= '1' AFTER (TCQ)*1 ps;
729
                              ELSIF (tready_thrtl_xhdl1 = '1' AND S_AXIS_TX_TVALID = '1' AND S_AXIS_TX_TLAST = '1') THEN
730
                                      reg_tx_ecrc_pkt <= '0' AFTER (TCQ)*1 ps;
731
                              END IF;
732
                      END IF;
733
              END IF;
734
      END PROCESS;
735
 
736
--      tx_ecrc_pkt <= (S_AXIS_TX_TUSER(0) AND tready_thrtl_xhdl1 AND S_AXIS_TX_TVALID AND (NOT(reg_axi_in_pkt)));
737
      tx_ecrc_pause <= (((tx_ecrc_pkt OR reg_tx_ecrc_pkt) AND S_AXIS_TX_TLAST AND S_AXIS_TX_TVALID AND tready_thrtl_xhdl1));
738
   END GENERATE;
739
 
740
   xhdl18 : IF (NOT(C_FAMILY = ("X7"))) GENERATE
741
           tx_ecrc_pause <= '0';
742
   END GENERATE;
743
END trans;

powered by: WebSVN 2.1.0

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