SURF  1.0
AxiStreamDmaV2Read.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiStreamDmaV2Read.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2017-02-02
5 -- Last update: 2017-02-02
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  PIPE_STAGES_G : natural := 1;
39  BURST_BYTES_G : integer range 1 to 4096 := 4096;
40  PEND_THRESH_G : natural := 0); -- In units of bytes
41  port (
42  -- Clock/Reset
43  axiClk : in sl;
44  axiRst : in sl;
45  -- DMA Control Interface
50  -- Config and status
51  dmaRdIdle : out sl;
52  axiCache : in slv(3 downto 0);
53  -- Streaming Interface
57  -- AXI Interface
60 end AxiStreamDmaV2Read;
61 
62 architecture rtl of AxiStreamDmaV2Read is
63 
64  constant DATA_BYTES_C : integer := AXIS_CONFIG_G.TDATA_BYTES_C;
65  constant ADDR_LSB_C : integer := bitSize(DATA_BYTES_C-1);
66 
67  type ReqStateType is (
68  IDLE_S,
69  ADDR_S,
70  NEXT_S);
71 
72  type StateType is (
73  IDLE_S,
74  MOVE_S,
75  DONE_S,
76  BLOWOFF_S);
77 
78  type RegType is record
79  idle : sl;
80  --pendBytes : slv(31 downto 0);
81  size : slv(31 downto 0); -- Decrementing counter used in data collection engine
82  reqSize : slv(31 downto 0); -- Decrementing counter used in request engine
83  reqCnt : slv(31 downto 0); -- Total bytes requested
84  ackCnt : slv(31 downto 0); -- Total bytes received
86  dmaRdDescAck : sl;
88  first : sl;
89  leftovers : sl;
90  rMaster : AxiReadMasterType;
91  sMaster : AxiStreamMasterType;
92  reqState : ReqStateType;
93  state : StateType;
94  end record RegType;
95 
96  constant REG_INIT_C : RegType := (
97  idle => '0',
98  --pendBytes => (others => '0'),
99  size => (others => '0'),
100  reqSize => (others => '0'),
101  reqCnt => (others => '0'),
102  ackCnt => (others => '0'),
104  dmaRdDescAck => '0',
106  first => '0',
107  leftovers => '0',
108  rMaster => axiReadMasterInit(AXI_CONFIG_G, "01", "0000"),
109  sMaster => axiStreamMasterInit(AXIS_CONFIG_G),
110  reqState => IDLE_S,
111  state => IDLE_S);
112 
113  signal r : RegType := REG_INIT_C;
114  signal rin : RegType;
115  signal pause : sl;
116  signal sSlave : AxiStreamSlaveType;
117  signal mSlave : AxiStreamSlaveType;
118 
119  attribute dont_touch : string;
120  attribute dont_touch of r : signal is "TRUE";
121 
122 begin
123 
125  report "AXIS (" & integer'image(AXIS_CONFIG_G.TDATA_BYTES_C) & ") and AXI ("
126  & integer'image(AXI_CONFIG_G.DATA_BYTES_C) & ") must have equal data widths" severity failure;
127 
128  pause <= '0' when (AXIS_READY_EN_G) else axisCtrl.pause;
129 
130  comb : process (axiReadSlave, axiRst, dmaRdDescReq, dmaRdDescRetAck, pause, r, sSlave, axiCache) is
131  variable v : RegType;
132  variable pendBytes: natural;
133  variable pending : boolean;
134  begin
135  -- Latch the current value
136  v := r;
137 
138  -- AXI Cache Setting
139  v.rMaster.arcache := axiCache;
140 
141  -- Reset strobing Signals
142  v.rMaster.rready := '0';
143  if (axiReadSlave.arready = '1') then
144  v.rMaster.arvalid := '0';
145  end if;
146  if (sSlave.tReady = '1') then
147  v.sMaster.tValid := '0';
148  v.sMaster.tLast := '0';
149  v.sMaster.tUser := (others => '0');
150  v.sMaster.tKeep := (others => '1');
151  v.sMaster.tStrb := (others => '1');
152  end if;
153 
154  -- Calculate the pending bytes
155  --v.pendBytes := r.reqCnt - r.ackCnt;
156  pendBytes := conv_integer(r.reqCnt - r.ackCnt);
157 
158  -- Update variables
159  pending := true;
160 
161  -- Check for the threshold = zero case
162  if (PEND_THRESH_G = 0) then
163  --if (r.pendBytes = 0) then
164  if (pendBytes = 0) then
165  pending := false;
166  end if;
167  else
168  --if (r.pendBytes < PEND_THRESH_G) then
169  if (pendBytes < PEND_THRESH_G) then
170  pending := false;
171  end if;
172  end if;
173 
174  -- Track read status
175  if (axiReadSlave.rvalid = '1') and (axiReadSlave.rresp /= 0) and (axiReadSlave.rlast = '1') then
176  -- Error Detected
177  v.dmaRdDescRet.result(1 downto 0) := axiReadSlave.rresp;
178  end if;
179 
180  -- Clear descriptor handshake
181  if dmaRdDescRetAck = '1' then
182  v.dmaRdDescRet.valid := '0';
183  end if;
184  v.dmaRdDescAck := '0';
185 
186  -- Memory Request State machine
187  case r.reqState is
188  ----------------------------------------------------------------------
189  when IDLE_S =>
190  -- Update the variables
192  -- Init return
193  v.dmaRdDescRet.valid := '0';
195  v.dmaRdDescRet.result := (others=>'0');
196  -- Force address alignment
197  v.dmaRdDescReq.address(ADDR_LSB_C-1 downto 0) := (others => '0');
198  -- Reset the counters
199  v.reqCnt := (others => '0');
200  v.ackCnt := (others => '0');
201  -- Check for DMA request
202  if dmaRdDescReq.valid = '1' then
203  v.dmaRdDescAck := '1';
204  -- Set the flags
205  v.first := '1';
206  -- Latch the value
207  v.size := dmaRdDescReq.size;
208  v.reqSize := dmaRdDescReq.size;
209  v.sMaster.tDest := dmaRdDescReq.dest;
210  v.sMaster.tId := dmaRdDescReq.id;
211  -- Next state
212  v.reqState := ADDR_S;
213  end if;
214  ----------------------------------------------------------------------
215  when ADDR_S =>
216  -- Check if ready to make memory request
217  if (r.rMaster.arvalid = '0') then
218  -- Set the memory address
219  v.rMaster.araddr(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := r.dmaRdDescReq.address(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0);
220  -- Determine transfer size aligned to 4k boundaries
221  v.rMaster.arlen := getAxiLen(AXI_CONFIG_G,BURST_BYTES_G,r.reqSize,r.dmaRdDescReq.address);
222  -- Check for the following:
223  -- 1) There is enough room in the FIFO for a burst
224  -- 2) pending flag
225  -- 3) Last transaction already completed
226  if (pause = '0') and (pending = false) and (r.reqCnt < r.dmaRdDescReq.size) then
227  -- Set the flag
228  v.rMaster.arvalid := '1';
229  -- Next state
230  v.state := MOVE_S;
231  v.reqState := NEXT_S;
232  end if;
233  end if;
234  ----------------------------------------------------------------------
235  when NEXT_S =>
236  -- Update the request size
237  v.reqCnt := r.reqCnt + getAxiReadBytes(AXI_CONFIG_G,r.rMaster);
238  v.reqSize := r.reqSize - getAxiReadBytes(AXI_CONFIG_G,r.rMaster);
239  -- Update next address
240  v.dmaRdDescReq.address := r.dmaRdDescReq.address + getAxiReadBytes(AXI_CONFIG_G,r.rMaster);
241  -- Back to address state
242  v.reqState := ADDR_S;
243  ----------------------------------------------------------------------
244  end case;
245 
246  -- Data Collection State machine
247  case r.state is
248  ----------------------------------------------------------------------
249  when IDLE_S =>
250  -- Blowoff any out-of-phase data (should never happen)
251  v.rMaster.rready := '1';
252  ----------------------------------------------------------------------
253  when MOVE_S =>
254 
255  -- Flow control
256  if (v.sMaster.tValid = '0') then
257  v.rMaster.rready := '1';
258  end if;
259 
260  -- Check if ready to move data
261  if (v.sMaster.tValid = '0') and (axiReadSlave.rvalid = '1') then
262  -- Move the data
263  v.sMaster.tValid := '1';
264  v.sMaster.tData((DATA_BYTES_C*8)-1 downto 0) := axiReadSlave.rdata((DATA_BYTES_C*8)-1 downto 0);
265  -- Check the flag
266  if r.first = '1' then
267  -- Reset the flag
268  v.first := '0';
269  -- Set the tUser for the first byte transferred
270  axiStreamSetUserField(
272  v.sMaster,
274  end if;
275  -- Check the read size
276  if (DATA_BYTES_C > r.size) then
277  -- Bottom out at 0
278  v.size := (others => '0');
279  -- Top out at dma.size
280  v.ackCnt := r.dmaRdDescReq.size;
281  else
282  -- Decrement the counter
283  v.size := r.size - DATA_BYTES_C;
284  -- Increment the counter
285  v.ackCnt := r.ackCnt + DATA_BYTES_C;
286  end if;
287  -- Check for completion
288  if (v.size = 0) then
289  -- Terminate the frame
290  v.sMaster.tLast := not r.dmaRdDescReq.continue;
291  v.sMaster.tKeep := genTKeep(conv_integer(r.size(4 downto 0)));
292  v.sMaster.tStrb := genTKeep(conv_integer(r.size(4 downto 0)));
293  -- Set last user field
294  axiStreamSetUserField (AXIS_CONFIG_G, v.sMaster, r.dmaRdDescReq.lastUser(AXIS_CONFIG_G.TUSER_BITS_C-1 downto 0));
295  -- Set the flags
296  v.dmaRdDescRet.valid := '1';
297  v.leftovers := not(axiReadSlave.rlast);
298  -- Next state
299  v.state := DONE_S;
300  end if;
301  end if;
302  ----------------------------------------------------------------------
303  when DONE_S =>
304  -- Check for ACK completion
305  if (r.dmaRdDescRet.valid = '0')then
306  -- Reset the flag
307  v.leftovers := '0';
308  -- Check if no leftover memory request data
309  if r.leftovers = '0' then
310  -- Next states
311  v.reqState := IDLE_S;
312  v.state := IDLE_S;
313  else
314  -- Next state
315  v.state := BLOWOFF_S;
316  end if;
317  end if;
318  ----------------------------------------------------------------------
319  when BLOWOFF_S =>
320  -- Blowoff the data
321  v.rMaster.rready := '1';
322  -- Check for last transfer
323  if (axiReadSlave.rvalid = '1') and (axiReadSlave.rlast = '1') then
324  -- Next states
325  v.reqState := IDLE_S;
326  v.state := IDLE_S;
327  end if;
328  ----------------------------------------------------------------------
329  end case;
330 
331  -- Forward the state of the state machine
332  if v.state = IDLE_S then
333  -- Set the flag
334  v.idle := '1';
335  else
336  -- Reset the flag
337  v.idle := '0';
338  end if;
339 
340  -- Reset
341  if (axiRst = '1') then
342  v := REG_INIT_C;
343  end if;
344 
345  -- Register the variable for next clock cycle
346  rin <= v;
347 
348  -- Outputs
349  dmaRdIdle <= r.idle;
352  axiReadMaster <= r.rMaster;
353  axiReadMaster.rready <= v.rMaster.rready;
354 
355  end process comb;
356 
357  seq : process (axiClk) is
358  begin
359  if (rising_edge(axiClk)) then
360  r <= rin after TPD_G;
361  end if;
362  end process seq;
363 
364  U_Pipeline : entity work.AxiStreamPipeline
365  generic map (
366  TPD_G => TPD_G,
368  port map (
369  axisClk => axiClk,
370  axisRst => axiRst,
371  sAxisMaster => r.sMaster,
372  sAxisSlave => sSlave,
374  mAxisSlave => mSlave);
375 
377 
378 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
out dmaRdDescRetAxiReadDmaDescRetType
slv( 1023 downto 0) rdata
Definition: AxiPkg.vhd:83
sl rready
Definition: AxiPkg.vhd:46
slv( 7 downto 0) dest
Definition: AxiDmaPkg.vhd:78
slv( 1 downto 0) rresp
Definition: AxiPkg.vhd:87
in dmaRdDescReqAxiReadDmaDescReqType
AxiReadDmaDescRetType :=(valid => '0',buffId =>( others => '0'),result =>( others => '0')) AXI_READ_DMA_DESC_RET_INIT_C
Definition: AxiDmaPkg.vhd:330
slv( 7 downto 0) firstUser
Definition: AxiDmaPkg.vhd:76
in axisSlaveAxiStreamSlaveType
sl rvalid
Definition: AxiPkg.vhd:85
std_logic sl
Definition: StdRtlPkg.vhd:28
AXIS_READY_EN_Gboolean := false
slv( 7 downto 0) id
Definition: AxiDmaPkg.vhd:79
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
slv( 15 downto 0) buffId
Definition: AxiDmaPkg.vhd:188
natural range 1 to 16 TDATA_BYTES_C
in mAxisSlaveAxiStreamSlaveType
slv( 2 downto 0) result
Definition: AxiDmaPkg.vhd:219
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
positive range 12 to 64 ADDR_WIDTH_C
Definition: AxiPkg.vhd:214
AxiReadSlaveType
Definition: AxiPkg.vhd:79
slv( 7 downto 0) lastUser
Definition: AxiDmaPkg.vhd:77
slv( 127 downto 0) tData
in sAxisMasterAxiStreamMasterType
AxiReadDmaDescReqType :=(valid => '0',address =>( others => '0'),buffId =>( others => '0'),firstUser =>( others => '0'),lastUser =>( others => '0'),size =>( others => '0'),continue => '0',id =>( others => '0'),dest =>( others => '0')) AXI_READ_DMA_DESC_REQ_INIT_C
Definition: AxiDmaPkg.vhd:300
slv( 63 downto 0) araddr
Definition: AxiPkg.vhd:35
AxiConfigType
Definition: AxiPkg.vhd:213
slv( 127 downto 0) tUser
out axiReadMasterAxiReadMasterType
in axiCacheslv( 3 downto 0)
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
AxiReadDmaDescReqType
Definition: AxiDmaPkg.vhd:288
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
positive range 1 to 128 DATA_BYTES_C
Definition: AxiPkg.vhd:215
slv( 31 downto 0) size
Definition: AxiDmaPkg.vhd:72
in axisCtrlAxiStreamCtrlType
in axiReadSlaveAxiReadSlaveType
out axisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
sl rlast
Definition: AxiPkg.vhd:84
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
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
AxiReadMasterType
Definition: AxiPkg.vhd:32
AxiReadDmaDescRetType
Definition: AxiDmaPkg.vhd:324
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
sl arvalid
Definition: AxiPkg.vhd:34
BURST_BYTES_Ginteger range 1 to 4096:= 4096