SURF  1.0
AxiStreamDmaRead.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiStreamDmaRead.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-04-25
5 -- Last update: 2016-10-27
6 -------------------------------------------------------------------------------
7 -- Description:
8 -- Block to transfer a single AXI Stream frame from memory using an AXI
9 -- interface.
10 -------------------------------------------------------------------------------
11 -- This file is part of 'SLAC Firmware Standard Library'.
12 -- It is subject to the license terms in the LICENSE.txt file found in the
13 -- top-level directory of this distribution and at:
14 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
15 -- No part of 'SLAC Firmware Standard Library', including this file,
16 -- may be copied, modified, propagated, or distributed except according to
17 -- the terms contained in the LICENSE.txt file.
18 -------------------------------------------------------------------------------
19 
20 library ieee;
21 use ieee.std_logic_1164.all;
22 use ieee.std_logic_arith.all;
23 use ieee.std_logic_unsigned.all;
24 
25 use work.StdRtlPkg.all;
26 use work.AxiStreamPkg.all;
27 use work.AxiPkg.all;
28 use work.AxiDmaPkg.all;
29 
30 --! @see entity
31  --! @ingroup axi
33  generic (
34  TPD_G : time := 1 ns;
35  AXIS_READY_EN_G : boolean := false;
38  AXI_BURST_G : slv(1 downto 0) := "01";
39  AXI_CACHE_G : slv(3 downto 0) := "1111";
40  SW_CACHE_EN_G : boolean := false;
41  PIPE_STAGES_G : natural := 1;
42  PEND_THRESH_G : natural := 0; -- In units of bytes
43  BYP_SHIFT_G : boolean := false);
44  port (
45  -- Clock/Reset
46  axiClk : in sl;
47  axiRst : in sl;
48  -- DMA Control Interface
51  swCache : in slv(3 downto 0) := "0000";
52  -- Streaming Interface
56  -- AXI Interface
59 end AxiStreamDmaRead;
60 
61 architecture rtl of AxiStreamDmaRead is
62 
63  constant DATA_BYTES_C : integer := AXIS_CONFIG_G.TDATA_BYTES_C;
64  constant ADDR_LSB_C : integer := bitSize(DATA_BYTES_C-1);
65  constant ARLEN_C : slv(7 downto 0) := getAxiLen(AXI_CONFIG_G, 4096);
66 
67  type ReqStateType is (
68  IDLE_S,
69  FIRST_S,
70  NEXT_S);
71 
72  type StateType is (
73  IDLE_S,
74  MOVE_S,
75  LAST_S,
76  DONE_S,
77  BLOWOFF_S);
78 
79  type RegType is record
80  pendBytes : slv(31 downto 0);
81  size : slv(31 downto 0);
82  reqSize : slv(31 downto 0);
83  reqCnt : slv(31 downto 0);
84  ackCnt : slv(31 downto 0);
87  shift : slv(3 downto 0);
88  shiftEn : sl;
89  first : sl;
90  leftovers : sl;
91  rMaster : AxiReadMasterType;
92  sMaster : AxiStreamMasterType;
93  reqState : ReqStateType;
94  state : StateType;
95  end record RegType;
96 
97  constant REG_INIT_C : RegType := (
98  pendBytes => (others => '0'),
99  size => (others => '0'),
100  reqSize => (others => '0'),
101  reqCnt => (others => '0'),
102  ackCnt => (others => '0'),
105  shift => (others => '0'),
106  shiftEn => '0',
107  first => '0',
108  leftovers => '0',
109  rMaster => axiReadMasterInit(AXI_CONFIG_G, AXI_BURST_G, AXI_CACHE_G),
110  sMaster => axiStreamMasterInit(AXIS_CONFIG_G),
111  reqState => IDLE_S,
112  state => IDLE_S);
113 
114  signal r : RegType := REG_INIT_C;
115  signal rin : RegType;
116  signal pause : sl;
117  signal sSlave : AxiStreamSlaveType;
118  signal pipeMaster : AxiStreamMasterType;
119  signal pipeSlave : AxiStreamSlaveType;
120  signal mMaster : AxiStreamMasterType;
121  signal mSlave : AxiStreamSlaveType;
122 
123  -- attribute dont_touch : string;
124  -- attribute dont_touch of r : signal is "TRUE";
125 
126 begin
127 
129  report "AXIS (" & integer'image(AXIS_CONFIG_G.TDATA_BYTES_C) & ") and AXI ("
130  & integer'image(AXI_CONFIG_G.DATA_BYTES_C) & ") must have equal data widths" severity failure;
131 
132  pause <= '0' when (AXIS_READY_EN_G) else axisCtrl.pause;
133 
134  comb : process (axiReadSlave, axiRst, dmaReq, mMaster, mSlave, pause, r, sSlave, swCache) is
135  variable v : RegType;
136  variable readSize : integer;
137  variable reqLen : natural;
138  variable pending : boolean;
139  begin
140  -- Latch the current value
141  v := r;
142 
143  -- Set cache value if enabled in software
144  if SW_CACHE_EN_G then
145  v.rMaster.arcache := swCache;
146  end if;
147 
148  -- Reset strobing Signals
149  v.rMaster.rready := '0';
150  v.shiftEn := '0';
151  if (axiReadSlave.arready = '1') then
152  v.rMaster.arvalid := '0';
153  end if;
154  if (sSlave.tReady = '1') then
155  v.sMaster.tValid := '0';
156  v.sMaster.tLast := '0';
157  v.sMaster.tUser := (others => '0');
158  v.sMaster.tKeep := (others => '1');
159  v.sMaster.tStrb := (others => '1');
160  end if;
161 
162  -- Calculate the pending bytes
163  v.pendBytes := r.reqCnt - r.ackCnt;
164 
165  -- Update variables
166  reqLen := 0;
167  pending := true;
168  -- Check for the threshold = zero case
169  if (PEND_THRESH_G = 0) then
170  if (r.pendBytes = 0) then
171  pending := false;
172  end if;
173  else
174  if (r.pendBytes < PEND_THRESH_G) then
175  pending := false;
176  end if;
177  end if;
178 
179  -- Track read status
180  if (axiReadSlave.rvalid = '1') and (axiReadSlave.rresp /= 0) and (axiReadSlave.rlast = '1') then
181  -- Error Detected
182  v.dmaAck.readError := '1';
184  end if;
185 
186  -- Check for handshaking
187  if (dmaReq.request = '0') and (r.dmaAck.done = '1') then
188  -- Reset the flags
189  v.dmaAck.done := '0';
190  end if;
191 
192  -- Memory Request State machine
193  case r.reqState is
194  ----------------------------------------------------------------------
195  when IDLE_S =>
196  -- Update the variables
197  v.dmaReq := dmaReq;
198  -- Reset the counters
199  v.shift := (others => '0');
200  v.reqCnt := (others => '0');
201  v.ackCnt := (others => '0');
202  -- Align shift and address to transfer size
203  if (DATA_BYTES_C /= 1) then
204  v.dmaReq.address(ADDR_LSB_C-1 downto 0) := (others => '0');
205  v.shift(ADDR_LSB_C-1 downto 0) := dmaReq.address(ADDR_LSB_C-1 downto 0);
206  end if;
207  -- Check for DMA request
208  if (dmaReq.request = '1') then
209  -- Reset the flags and counters
210  v.dmaAck.readError := '0';
211  v.dmaAck.errorValue := (others => '0');
212  -- Set the flags
213  v.shiftEn := '1';
214  v.first := '1';
215  -- Latch the value
216  v.size := dmaReq.size;
217  v.reqSize := dmaReq.size;
218  v.sMaster.tDest := dmaReq.dest;
219  v.sMaster.tId := dmareq.id;
220  -- Next state
221  v.reqState := FIRST_S;
222  end if;
223  ----------------------------------------------------------------------
224  when FIRST_S =>
225  -- Check if ready to make memory request
226  if (r.rMaster.arvalid = '0') then
227  -- Set the memory address
228  v.rMaster.araddr(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := r.dmaReq.address(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0);
229  -- Determine transfer size to align address to 16-transfer boundaries
230  -- This initial alignment will ensure that we never cross a 4k boundary
231  if (ARLEN_C > 0) then
232  -- Set the burst length
233  v.rMaster.arlen := ARLEN_C - r.dmaReq.address(ADDR_LSB_C+AXI_CONFIG_G.LEN_BITS_C-1 downto ADDR_LSB_C);
234  -- Limit read burst size
235  if (r.reqSize(31 downto ADDR_LSB_C) < v.rMaster.arlen) then
236  v.rMaster.arlen := resize(r.reqSize(ADDR_LSB_C+AXI_CONFIG_G.LEN_BITS_C-1 downto ADDR_LSB_C)-1, 8);
237  end if;
238  end if;
239  -- There is enough room in the FIFO for a burst
240  if (pause = '0') then
241  -- Set the flag
242  v.rMaster.arvalid := '1';
243  -- Update the request size
244  reqLen := DATA_BYTES_C*(conv_integer(v.rMaster.arlen) + 1);
245  v.reqCnt := toSlv(reqLen, 32) - conv_integer(r.shift);
246  v.reqSize := r.reqSize - reqLen;
247  -- Update next address
248  v.dmaReq.address := r.dmaReq.address + reqLen;
249  v.dmaReq.address(ADDR_LSB_C-1 downto 0) := (others => '0');
250  -- Next state
251  v.reqState := NEXT_S;
252  v.state := MOVE_S;
253  end if;
254  end if;
255  ----------------------------------------------------------------------
256  when NEXT_S =>
257  -- Check if ready to make memory request
258  if (r.rMaster.arvalid = '0') then
259  -- Set the memory address
260  v.rMaster.araddr(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := r.dmaReq.address(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0);
261  -- Bursts after the FIRST are guaranteed to be aligned
262  v.rMaster.arlen := ARLEN_C;
263  -- Limit read burst size
264  if (r.reqSize(31 downto ADDR_LSB_C) < v.rMaster.arlen) then
265  v.rMaster.arlen := resize(r.reqSize(ADDR_LSB_C+AXI_CONFIG_G.LEN_BITS_C-1 downto ADDR_LSB_C)-1, 8);
266  end if;
267  -- Check for the following:
268  -- 1) There is enough room in the FIFO for a burst
269  -- 2) pending flag
270  -- 3) Last transaction already completed
271  if (pause = '0') and (pending = false) and (r.reqCnt < r.dmaReq.size) then
272  -- Set the flag
273  v.rMaster.arvalid := '1';
274  -- Update the request size
275  reqLen := DATA_BYTES_C*(conv_integer(v.rMaster.arlen) + 1);
276  v.reqCnt := r.reqCnt + reqLen;
277  v.reqSize := r.reqSize - reqLen;
278  -- Update next address
279  v.dmaReq.address := r.dmaReq.address + reqLen;
280  v.dmaReq.address(ADDR_LSB_C-1 downto 0) := (others => '0');
281  end if;
282  end if;
283  ----------------------------------------------------------------------
284  end case;
285 
286  -- Data Collection State machine
287  case r.state is
288  ----------------------------------------------------------------------
289  when IDLE_S =>
290  -- Blowoff any out-of-phase data (should never happen)
291  v.rMaster.rready := '1';
292  ----------------------------------------------------------------------
293  when MOVE_S =>
294  -- Check if ready to move data
295  if (v.sMaster.tValid = '0') and (axiReadSlave.rvalid = '1') then
296  -- Accept the data
297  v.rMaster.rready := '1';
298  -- Move the data
299  v.sMaster.tValid := '1';
300  v.sMaster.tData((DATA_BYTES_C*8)-1 downto 0) := axiReadSlave.rdata((DATA_BYTES_C*8)-1 downto 0);
301  -- Check the flag
302  if r.first = '1' then
303  -- Reset the flag
304  v.first := '0';
305  -- Set the tUser for the first byte transferred
306  axiStreamSetUserField(
308  v.sMaster,
309  r.dmaReq.
311  conv_integer(r.shift));
312  end if;
313  -- Calculate the read size
314  readSize := DATA_BYTES_C - ite(r.first = '1', conv_integer(r.shift), 0);
315  -- Check the read size
316  if (readSize > r.size) then
317  -- Bottom out at 0
318  v.size := (others => '0');
319  -- Top out at dma.size
320  v.ackCnt := r.dmaReq.size;
321  else
322  -- Decrement the counter
323  v.size := r.size - readSize;
324  -- Increment the counter
325  v.ackCnt := r.ackCnt + readSize;
326  end if;
327  -- Check for completion
328  if (v.size = 0) then
329  -- Terminate the frame
330  v.sMaster.tLast := '1';
331  v.sMaster.tKeep := genTKeep(conv_integer(r.size(4 downto 0)));
332  v.sMaster.tStrb := genTKeep(conv_integer(r.size(4 downto 0)));
333  -- Check for first transfer
334  if (r.first = '1') then
335  -- Compensate the tKeep and tStrb via shift module
336  v.sMaster.tKeep := shl(v.sMaster.tKeep, r.shift);
337  v.sMaster.tStrb := shl(v.sMaster.tStrb, r.shift);
338  end if;
339  -- Set the flags
340  v.dmaAck.done := '1';
341  v.leftovers := not(axiReadSlave.rlast);
342  -- Next state
343  v.state := LAST_S;
344  end if;
345  end if;
346  ----------------------------------------------------------------------
347  when LAST_S =>
348  -- Hold until last transfer (required for Remap_mAxisMaster process)
349  if (mMaster.tValid = '1') and (mMaster.tLast = '1') and (mSlave.tReady = '1') then
350  -- Next state
351  v.state := DONE_S;
352  end if;
353  ----------------------------------------------------------------------
354  when DONE_S =>
355  -- Check for ACK completion
356  if (r.dmaAck.done = '0')then
357  -- Reset the flag
358  v.leftovers := '0';
359  -- Check if no leftover memory request data
360  if r.leftovers = '0' then
361  -- Next states
362  v.reqState := IDLE_S;
363  v.state := IDLE_S;
364  else
365  -- Next state
366  v.state := BLOWOFF_S;
367  end if;
368  end if;
369  ----------------------------------------------------------------------
370  when BLOWOFF_S =>
371  -- Blowoff the data
372  v.rMaster.rready := '1';
373  -- Check for last transfer
374  if (axiReadSlave.rvalid = '1') and (axiReadSlave.rlast = '1') then
375  -- Next states
376  v.reqState := IDLE_S;
377  v.state := IDLE_S;
378  end if;
379  ----------------------------------------------------------------------
380  end case;
381 
382  -- Forward the state of the state machine
383  if v.state = IDLE_S then
384  -- Set the flag
385  v.dmaAck.idle := '1';
386  else
387  -- Reset the flag
388  v.dmaAck.idle := '0';
389  end if;
390 
391  -- Reset
392  if (axiRst = '1') then
393  v := REG_INIT_C;
394  end if;
395 
396  -- Register the variable for next clock cycle
397  rin <= v;
398 
399  -- Outputs
400  dmaAck <= r.dmaAck;
401  axiReadMaster <= r.rMaster;
402  axiReadMaster.rready <= v.rMaster.rready;
403 
404  end process comb;
405 
406  seq : process (axiClk) is
407  begin
408  if (rising_edge(axiClk)) then
409  r <= rin after TPD_G;
410  end if;
411  end process seq;
412 
413  U_Pipeline : entity work.AxiStreamPipeline
414  generic map (
415  TPD_G => TPD_G,
417  port map (
418  axisClk => axiClk,
419  axisRst => axiRst,
420  sAxisMaster => r.sMaster,
421  sAxisSlave => sSlave,
422  mAxisMaster => pipeMaster,
423  mAxisSlave => pipeSlave);
424 
425  U_AxiStreamShift : entity work.AxiStreamShift
426  generic map (
427  TPD_G => TPD_G,
431  port map (
432  axisClk => axiClk,
433  axisRst => axiRst,
434  axiStart => r.shiftEn,
435  axiShiftDir => '1',
436  axiShiftCnt => r.shift,
437  sAxisMaster => pipeMaster,
438  sAxisSlave => pipeSlave,
439  mAxisMaster => mMaster,
440  mAxisSlave => mSlave);
441 
442  Remap_mAxisMaster : process (mMaster, r) is
443  variable tmp : AxiStreamMasterType;
444  begin
445  -- Latch the current value
446  tmp := mMaster;
447  -- Check for tLast
448  if mMaster.tLast = '1' then
449  axiStreamSetUserField (AXIS_CONFIG_G, tmp, r.dmaReq.lastUser(AXIS_CONFIG_G.TUSER_BITS_C-1 downto 0));
450  -- Note: This is done here (instead of "comb" process) to prevent a crazy long logic chain
451  -- Note: For the "1 byte" case, lastUser will overwrite the firstUser value.
452  end if;
453  -- Outputs
454  axisMaster <= tmp;
455  end process;
456 
458 
459 end rtl;
slv( 7 downto 0) tId
PIPE_STAGES_Gnatural range 0 to 16:= 0
slv( 7 downto 0) arlen
Definition: AxiPkg.vhd:37
slv( 63 downto 0) address
Definition: AxiDmaPkg.vhd:49
slv( 1023 downto 0) rdata
Definition: AxiPkg.vhd:83
sl rready
Definition: AxiPkg.vhd:46
slv( 7 downto 0) dest
Definition: AxiDmaPkg.vhd:78
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
slv( 1 downto 0) rresp
Definition: AxiPkg.vhd:87
sl readError
Definition: AxiDmaPkg.vhd:136
_library_ ieeeieee
AXI_CACHE_Gslv( 3 downto 0) := "1111"
slv( 7 downto 0) firstUser
Definition: AxiDmaPkg.vhd:76
out sAxisSlaveAxiStreamSlaveType
sl rvalid
Definition: AxiPkg.vhd:85
std_logic sl
Definition: StdRtlPkg.vhd:28
in dmaReqAxiReadDmaReqType
slv( 7 downto 0) id
Definition: AxiDmaPkg.vhd:79
in sAxisMasterAxiStreamMasterType
out sAxisSlaveAxiStreamSlaveType
slv( 15 downto 0) tStrb
slv( 3 downto 0) arcache
Definition: AxiPkg.vhd:42
slv( 15 downto 0) tKeep
sl arready
Definition: AxiPkg.vhd:81
PIPE_STAGES_Gnatural := 1
natural range 1 to 16 TDATA_BYTES_C
in mAxisSlaveAxiStreamSlaveType
in axiShiftCntslv( 3 downto 0)
in swCacheslv( 3 downto 0) := "0000"
out axiReadMasterAxiReadMasterType
positive range 12 to 64 ADDR_WIDTH_C
Definition: AxiPkg.vhd:214
AxiReadSlaveType
Definition: AxiPkg.vhd:79
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
in axiReadSlaveAxiReadSlaveType
TPD_Gtime := 1 ns
SW_CACHE_EN_Gboolean := false
slv( 7 downto 0) lastUser
Definition: AxiDmaPkg.vhd:77
AXI_BURST_Gslv( 1 downto 0) := "01"
out dmaAckAxiReadDmaAckType
slv( 127 downto 0) tData
in axisCtrlAxiStreamCtrlType
out mAxisMasterAxiStreamMasterType
BYP_SHIFT_Gboolean := false
in sAxisMasterAxiStreamMasterType
BYP_SHIFT_Gboolean := false
slv( 63 downto 0) araddr
Definition: AxiPkg.vhd:35
PEND_THRESH_Gnatural := 0
AxiConfigType
Definition: AxiPkg.vhd:213
AxiReadDmaReqType :=(request => '0',address =>( others => '0'),size =>( others => '0'),firstUser =>( others => '0'),lastUser =>( others => '0'),dest =>( others => '0'),id =>( others => '0')) AXI_READ_DMA_REQ_INIT_C
Definition: AxiDmaPkg.vhd:115
slv( 127 downto 0) tUser
AXIS_READY_EN_Gboolean := false
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
in axisSlaveAxiStreamSlaveType
AxiStreamConfigType :=(TSTRB_EN_C => false,TDATA_BYTES_C => 16,TDEST_BITS_C => 4,TID_BITS_C => 0,TKEEP_MODE_C => TKEEP_NORMAL_C,TUSER_BITS_C => 4,TUSER_MODE_C => TUSER_NORMAL_C) AXI_STREAM_CONFIG_INIT_C
slv( 7 downto 0) tDest
AxiReadDmaAckType :=(idle => '1',done => '0',readError => '0',errorValue => "00") AXI_READ_DMA_ACK_INIT_C
Definition: AxiDmaPkg.vhd:141
positive range 1 to 128 DATA_BYTES_C
Definition: AxiPkg.vhd:215
slv( 31 downto 0) size
Definition: AxiDmaPkg.vhd:72
slv( 1 downto 0) errorValue
Definition: AxiDmaPkg.vhd:75
in mAxisSlaveAxiStreamSlaveType
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
PIPE_STAGES_Ginteger range 0 to 16:= 0
sl rlast
Definition: AxiPkg.vhd:84
sl request
Definition: AxiDmaPkg.vhd:47
AxiConfigType :=axiConfig(ADDR_WIDTH_C => 32,DATA_BYTES_C => 4,ID_BITS_C => 12,LEN_BITS_C => 4) AXI_CONFIG_INIT_C
Definition: AxiPkg.vhd:227
AxiReadMasterType
Definition: AxiPkg.vhd:32
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
sl arvalid
Definition: AxiPkg.vhd:34
natural range 0 to 8 LEN_BITS_C
Definition: AxiPkg.vhd:217
out axisMasterAxiStreamMasterType