SURF  1.0
AxiStreamDmaRingRead.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiStreamDmaRingRead.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-09-29
5 -- Last update: 2016-08-02
6 -------------------------------------------------------------------------------
7 -- Description: AXI Stream to DMA Ring Buffer Read Module
8 -------------------------------------------------------------------------------
9 -- This file is part of 'SLAC Firmware Standard Library'.
10 -- It is subject to the license terms in the LICENSE.txt file found in the
11 -- top-level directory of this distribution and at:
12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
13 -- No part of 'SLAC Firmware Standard Library', including this file,
14 -- may be copied, modified, propagated, or distributed except according to
15 -- the terms contained in the LICENSE.txt file.
16 -------------------------------------------------------------------------------
17 
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.std_logic_unsigned.all;
21 use ieee.std_logic_arith.all;
22 
23 use work.StdRtlPkg.all;
24 use work.AxiStreamPkg.all;
25 use work.SsiPkg.all;
26 use work.AxiLitePkg.all;
27 use work.AxiLiteMasterPkg.all;
28 use work.AxiPkg.all;
29 use work.AxiDmaPkg.all;
30 use work.AxiStreamDmaRingPkg.all;
31 
32 --! @see entity
33  --! @ingroup axi
35 
36  generic (
37  TPD_G : time := 1 ns;
38  BUFFERS_G : natural range 2 to 64 := 64;
39  BURST_SIZE_BYTES_G : natural range 4 to 2**17 := 4096;
40  SSI_OUTPUT_G : boolean := false;
41  AXIL_BASE_ADDR_G : slv(31 downto 0) := (others => '0');
42  AXI_STREAM_READY_EN_G : boolean := true;
43  AXI_STREAM_CONFIG_G : AxiStreamConfigType := ssiAxiStreamConfig(8);
44  AXI_READ_CONFIG_G : AxiConfigType := axiConfig(32, 8, 1, 8));
45  port (
46  -- AXI-Lite Interface for local registers
47  axilClk : in sl;
48  axilRst : in sl;
53 
54  -- Status stream
55  statusClk : in sl;
56  statusRst : in sl;
59 
60  -- DMA Stream
61 -- dataClk : in sl;
62 -- dataRst : in sl;
66 
67  -- AXI4 Interface for RAM
68  axiClk : in sl;
69  axiRst : in sl;
72 
73 end entity AxiStreamDmaRingRead;
74 
75 architecture rtl of AxiStreamDmaRingRead is
76 
77  constant DMA_ADDR_LOW_C : integer := log2(BURST_SIZE_BYTES_G);
78 
79  type StateType is (
80  START_LOW_S,
81  START_HIGH_S,
82  END_LOW_S,
83  END_HIGH_S,
84  MODE_S,
85  DMA_REQ_S,
86  CLEAR_HIGH_S,
87  CLEAR_LOW_S);
88 
89  type RegType is record
90  startAddr : slv(63 downto 0);
91  endAddr : slv(63 downto 0);
92  mode : slv(31 downto 0);
93  state : StateType;
94  axilReq : AxiLiteMasterReqType;
95  dmaReq : AxiReadDmaReqType;
96  intStatusSlave : AxiStreamSlaveType;
97  end record RegType;
98 
99  constant REG_INIT_C : RegType := (
100  startAddr => (others => '0'),
101  endAddr => (others => '0'),
102  mode => (others => '0'),
103  state => START_LOW_S,
104  axilReq => AXI_LITE_MASTER_REQ_INIT_C,
105  dmaReq => AXI_READ_DMA_REQ_INIT_C,
106  intStatusSlave => AXI_STREAM_SLAVE_INIT_C);
107 
108  signal r : RegType := REG_INIT_C;
109  signal rin : RegType;
110 
111  signal intStatusMaster : AxiStreamMasterType;
112 
113  signal axilAck : AxiLiteMasterAckType;
114  signal dmaAck : AxiReadDmaAckType;
115 
116 
117  -- axiClk signals
118  signal dmaReqAxi : AxiReadDmaReqType;
119  signal dmaAckAxi : AxiReadDmaAckType;
120 
121 
122 begin
123  -- Assert that stream config has enough tdest bits for the number of buffers being tracked
124 
125 
126  -- Axi Lite Bus master
127  U_AxiLiteMaster_1 : entity work.AxiLiteMaster
128  generic map (
129  TPD_G => TPD_G)
130  port map (
131  axilClk => axilClk, -- [in]
132  axilRst => axilRst, -- [in]
133  req => r.axilReq, -- [in]
134  ack => axilAck, -- [out]
135  axilWriteMaster => axilWriteMaster, -- [out]
136  axilWriteSlave => axilWriteSlave, -- [in]
137  axilReadMaster => axilReadMaster, -- [out]
138  axilReadSlave => axilReadSlave); -- [in]
139 
140  -- DMA Write block
141  U_AxiStreamDmaRead_1 : entity work.AxiStreamDmaRead
142  generic map (
143  TPD_G => TPD_G,
147  AXI_BURST_G => "01", -- INCR
148  AXI_CACHE_G => "0011") -- Cacheable
149  port map (
150  axiClk => axiClk, -- [in]
151  axiRst => axiRst, -- [in]
152  dmaReq => dmaReqAxi, -- [in]
153  dmaAck => dmaAckAxi, -- [out]
154  axisMaster => dataMaster, -- [out]
155  axisSlave => dataSlave, -- [in]
156  axisCtrl => dataCtrl, --[in]
157  axiReadMaster => axiReadMaster, -- [out]
158  axiReadSlave => axiReadSlave); -- [in]
159 
160  -- Main logic runs on AXI-Lite clk, which may be different from the DMA AXI clk
161  -- Synchronize the request/ack bus if necessary
162  U_Synchronizer_Req : entity work.Synchronizer
163  generic map (
164  TPD_G => TPD_G,
165  STAGES_G => 4,
166  BYPASS_SYNC_G => false)
167  port map (
168  clk => axiClk, -- [in]
169  rst => axiRst, -- [in]
170  dataIn => r.dmaReq.request, -- [in]
171  dataOut => dmaReqAxi.request); -- [out]
172 
173  U_SynchronizerFifo_ReqData : entity work.SynchronizerVector
174  generic map (
175  TPD_G => TPD_G,
176  BYPASS_SYNC_G => false,
177  STAGES_G => 2,
178  WIDTH_G => 128)
179  port map (
180  clk => axiClk, -- [in]
181  rst => axiRst, -- [in]
182  dataIn(63 downto 0) => r.dmaReq.address,
183  dataIn(95 downto 64) => r.dmaReq.size,
184  dataIn(103 downto 96) => r.dmaReq.firstUser,
185  dataIn(111 downto 104) => r.dmaReq.lastUser,
186  dataIn(119 downto 112) => r.dmaReq.dest,
187  dataIn(127 downto 120) => r.dmaReq.id,
188  dataOut(63 downto 0) => dmaReqAxi.address,
189  dataOut(95 downto 64) => dmaReqAxi.size,
190  dataOut(103 downto 96) => dmaReqAxi.firstUser,
191  dataOut(111 downto 104) => dmaReqAxi.lastUser,
192  dataOut(119 downto 112) => dmaReqAxi.dest,
193  dataOut(127 downto 120) => dmaReqAxi.id);
194 
195  U_Synchronizer_Ack : entity work.Synchronizer
196  generic map (
197  TPD_G => TPD_G,
198  STAGES_G => 4,
199  BYPASS_SYNC_G => false)
200  port map (
201  clk => axilClk, -- [in]
202  rst => axilRst, -- [in]
203  dataIn => dmaAckAxi.done, -- [in]
204  dataOut => dmaAck.done); -- [out]
205 
206  U_SynchronizerFifo_Ack : entity work.SynchronizerVector
207  generic map (
208  TPD_G => TPD_G,
209  BYPASS_SYNC_G => false,
210  STAGES_G => 2,
211  WIDTH_G => 3)
212  port map (
213  clk => axilClk, -- [in]
214  rst => axilRst, -- [in]
215  dataIn(0) => dmaAckAxi.readError, -- [in]
216  dataIn(2 downto 1) => dmaAckAxi.errorValue, -- [in]
217  dataOut(0) => dmaAck.readError, -- [out]
218  dataOut(2 downto 1) => dmaAck.errorValue); -- [out]
219 
220  U_AxiStreamFifo_Status : entity work.AxiStreamFifoV2
221  generic map (
222  TPD_G => TPD_G,
223  PIPE_STAGES_G => 1,
224  SLAVE_READY_EN_G => true,
225  VALID_THOLD_G => 1,
226  BRAM_EN_G => false,
227  USE_BUILT_IN_G => false,
228  GEN_SYNC_FIFO_G => false,
229  FIFO_ADDR_WIDTH_G => 6,
230  FIFO_FIXED_THRESH_G => true,
231  FIFO_PAUSE_THRESH_G => 15,
234  port map (
235  sAxisClk => statusClk, -- [in]
236  sAxisRst => statusRst, -- [in]
237  sAxisMaster => statusMaster, -- [in]
238  sAxisSlave => statusSlave, -- [out]
239  mAxisClk => axilClk, -- [in]
240  mAxisRst => axilRst, -- [in]
241  mAxisMaster => intStatusMaster, -- [out]
242  mAxisSlave => r.intStatusSlave); -- [in]
243 
244  comb : process (axilAck, axilRst, dmaAck, intStatusMaster, r) is
245  variable v : RegType;
246  variable buf : slv(5 downto 0);
247  begin
248  v := r;
249 
250  buf := intStatusMaster.tData(5 downto 0);
251 
252  v.intStatusSlave.tReady := '0';
253 
254  -- Automatically issue new read requests when a status message is ready
255  v.axilReq.rnw := '1';
256  if (axilAck.done = '0' and r.intStatusSlave.tReady = '0') then
257  v.axilReq.request := intStatusMaster.tValid;
258  end if;
259 
260  case r.state is
261  when START_LOW_S =>
262  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, START_AXIL_C, buf, '0');
263 
264  if (r.axilReq.request = '1' and axilAck.done = '1') then
265  v.axilReq.request := '0';
266  v.startAddr(31 downto 0) := axilAck.rdData;
267  v.state := START_HIGH_S;
268  end if;
269 
270  when START_HIGH_S =>
271  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, START_AXIL_C, buf, '1');
272 
273  if (r.axilReq.request = '1' and axilAck.done = '1') then
274  v.axilReq.request := '0';
275  v.startAddr(63 downto 32) := axilAck.rdData;
276  v.state := END_LOW_S;
277  end if;
278 
279  when END_LOW_S =>
280  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, END_AXIL_C, buf, '0');
281 
282  if (r.axilReq.request = '1' and axilAck.done = '1') then
283  v.axilReq.request := '0';
284  v.endAddr(31 downto 0) := axilAck.rdData;
285  v.state := END_HIGH_S;
286  end if;
287 
288  when END_HIGH_S =>
289  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, END_AXIL_C, buf, '1');
290 
291  if (r.axilReq.request = '1' and axilAck.done = '1') then
292  v.axilReq.request := '0';
293  v.endAddr(63 downto 32) := axilAck.rdData;
294  v.state := DMA_REQ_S;
295  end if;
296 
297  when DMA_REQ_S =>
298  v.axilReq.request := '0';
299 
300  v.dmaReq.request := '1';
301  v.dmaReq.address := r.startAddr;
302  -- Optimization. Start address will always be on a BURST_SIZE boundary
303  v.dmaReq.address(DMA_ADDR_LOW_C-1 downto 0) := (others => '0');
304  v.dmaReq.size := resize(r.endAddr-r.startAddr, 32);
305  v.dmaReq.dest := resize(buf, 8);
306  v.dmaReq.firstUser := ite(SSI_OUTPUT_G, X"02", X"00");
307  if (dmaAck.done = '1') then
308  v.dmaReq.request := '0';
309  v.state := MODE_S;
310  end if;
311 
312  when MODE_S =>
313  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, MODE_AXIL_C, buf, '0');
314  v.axilReq.request := '1';
315  v.axilReq.rnw := '1';
316  if (r.axilReq.request = '1' and axilAck.done = '1') then
317  v.axilReq.request := '0';
318  v.mode := axilAck.rdData;
319  v.state := CLEAR_HIGH_S;
320  end if;
321 
322  when CLEAR_HIGH_S =>
323  -- Clear the buffer after reading it out
324  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, MODE_AXIL_C, buf, '0');
325  v.axilReq.wrData := r.mode;
326  v.axilReq.wrData(INIT_C) := '1';
327  v.axilReq.request := '1';
328  v.axilReq.rnw := '0';
329  if (r.axilReq.request = '1' and axilAck.done = '1') then
330  v.axilReq.request := '0';
331  v.state := CLEAR_LOW_S;
332  end if;
333 
334  when CLEAR_LOW_S =>
335  v.axilReq.address := getBufferAddr(AXIL_BASE_ADDR_G, MODE_AXIL_C, buf, '0');
336  v.axilReq.wrData := r.mode;
337  v.axilReq.wrData(INIT_C) := '0';
338  v.axilReq.request := '1';
339  v.axilReq.rnw := '0';
340  if (r.axilReq.request = '1' and axilAck.done = '1') then
341  v.axilReq.request := '0';
342  v.intStatusSlave.tready := '1';
343  v.state := START_LOW_S;
344  end if;
345 
346 
347  end case;
348 
349  ----------------------------------------------------------------------------------------------
350  -- Reset and output assignment
351  ----------------------------------------------------------------------------------------------
352  if (axilRst = '1') then
353  v := REG_INIT_C;
354  end if;
355 
356  rin <= v;
357 
358 
359  end process comb;
360 
361  seq : process (axilClk) is
362  begin
363  if (rising_edge(axilClk)) then
364  r <= rin after TPD_G;
365  end if;
366  end process seq;
367 
368 end architecture rtl;
369 
in statusMasterAxiStreamMasterType
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
AxiLiteMasterReqType :=(request => '0',rnw => '1',address =>( others => '0'),wrData =>( others => '0')) AXI_LITE_MASTER_REQ_INIT_C
in axilReadSlaveAxiLiteReadSlaveType
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
BUFFERS_Gnatural range 2 to 64:= 64
AXI_CACHE_Gslv( 3 downto 0) := "1111"
AXI_STREAM_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 8)
out axilWriteMasterAxiLiteWriteMasterType
PIPE_STAGES_Gnatural range 0 to 16:= 1
slv( 7 downto 0) firstUser
Definition: AxiDmaPkg.vhd:76
out axilReadMasterAxiLiteReadMasterType
AxiLiteWriteMasterType
Definition: AxiLitePkg.vhd:111
std_logic sl
Definition: StdRtlPkg.vhd:28
in rstsl :=not RST_POLARITY_G
BYPASS_SYNC_Gboolean := false
in axilWriteSlaveAxiLiteWriteSlaveType
AXI_READ_CONFIG_GAxiConfigType := axiConfig( 32, 8, 1, 8)
in reqAxiLiteMasterReqType
BYPASS_SYNC_Gboolean := false
in dmaReqAxiReadDmaReqType
out ackAxiLiteMasterAckType
in axilWriteSlaveAxiLiteWriteSlaveType
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
BURST_SIZE_BYTES_Gnatural range 4 to 2** 17:= 4096
STAGES_Gpositive := 2
out statusSlaveAxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C
slv( 31 downto 0) rdData
SLAVE_READY_EN_Gboolean := true
FIFO_FIXED_THRESH_Gboolean := true
GEN_SYNC_FIFO_Gboolean := false
out axiReadMasterAxiReadMasterType
out dataOutsl
AxiStreamConfigType :=(TSTRB_EN_C => false,TDATA_BYTES_C => 1,TDEST_BITS_C => 0,TID_BITS_C => 0,TKEEP_MODE_C => TKEEP_FIXED_C,TUSER_BITS_C => 1,TUSER_MODE_C => TUSER_NONE_C) DMA_RING_STATUS_CONFIG_C
AxiReadSlaveType
Definition: AxiPkg.vhd:79
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
in axiReadSlaveAxiReadSlaveType
AXI_BURST_Gslv( 1 downto 0) := "01"
out dmaAckAxiReadDmaAckType
slv( 127 downto 0) tData
in axisCtrlAxiStreamCtrlType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
BRAM_EN_Gboolean := true
out axilWriteMasterAxiLiteWriteMasterType
AxiConfigType
Definition: AxiPkg.vhd:213
TPD_Gtime := 1 ns
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
AXIS_READY_EN_Gboolean := false
TPD_Gtime := 1 ns
out axilReadMasterAxiLiteReadMasterType
in axiReadSlaveAxiReadSlaveType
slv( SSI_TDEST_BITS_C- 1 downto 0) dest
Definition: SsiPkg.vhd:70
out sAxisSlaveAxiStreamSlaveType
in axilReadSlaveAxiLiteReadSlaveType
in dataCtrlAxiStreamCtrlType := AXI_STREAM_CTRL_UNUSED_C
in axisSlaveAxiStreamSlaveType
slv( 31 downto 0) wrData
AxiStreamCtrlType :=(pause => '0',overflow => '0',idle => '1') AXI_STREAM_CTRL_UNUSED_C
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
slv( 31 downto 0) size
Definition: AxiDmaPkg.vhd:72
slv( 31 downto 0) address
in sAxisMasterAxiStreamMasterType
out mAxisMasterAxiStreamMasterType
SSI_OUTPUT_Gboolean := false
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
in dataSlaveAxiStreamSlaveType
in mAxisSlaveAxiStreamSlaveType
USE_BUILT_IN_Gboolean := false
in rstsl :=not RST_POLARITY_G
FIFO_PAUSE_THRESH_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
out axiReadMasterAxiReadMasterType
out dataMasterAxiStreamMasterType
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
TPD_Gtime := 1 ns
AxiReadMasterType
Definition: AxiPkg.vhd:32
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
out axisMasterAxiStreamMasterType
AXIL_BASE_ADDR_Gslv( 31 downto 0) :=( others => '0')
AXI_STREAM_READY_EN_Gboolean := true