SURF  1.0
AxiMemTester.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiMemTester.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-07-28
5 -- Last update: 2017-05-09
6 -------------------------------------------------------------------------------
7 -- Description: General Purpose AXI4 memory tester
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_arith.all;
21 use ieee.std_logic_unsigned.all;
22 
23 use work.StdRtlPkg.all;
24 use work.AxiLitePkg.all;
25 use work.AxiPkg.all;
26 
27 --! @see entity
28  --! @ingroup axi
29 entity AxiMemTester is
30  generic (
31  TPD_G : time := 1 ns;
33  START_ADDR_G : slv := X"00000000";
34  STOP_ADDR_G : slv := X"FFFFFFFF";
35  BURST_LEN_G : positive range 1 to 4096 := 4096;
37  port (
38  -- AXI-Lite Interface
39  axilClk : in sl;
40  axilRst : in sl;
45  memReady : out sl;
46  memError : out sl;
47  -- DDR Memory Interface
48  axiClk : in sl;
49  axiRst : in sl;
50  start : in sl;
55 end AxiMemTester;
56 
57 architecture rtl of AxiMemTester is
58 
59  constant START_C : slv(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := START_ADDR_G(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0);
60  constant START_ADDR_C : slv(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := START_C(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 12) & x"000";
61  constant STOP_C : slv(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := STOP_ADDR_G(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0);
62  constant STOP_ADDR_C : slv(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := STOP_C(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 12) & x"000";
63 
64  constant DATA_BITS_C : natural := 8*AXI_CONFIG_G.DATA_BYTES_C;
65  constant AXI_LEN_C : slv(7 downto 0) := getAxiLen(AXI_CONFIG_G, BURST_LEN_G);
66 
67 
68  constant PRBS_TAPS_C : NaturalArray := (0 => 1023, 1 => 257, 2 => 113, 3 => 61, 4 => 29, 5 => 17, 6 => 7);
69  constant PRBS_SEED_C : slv(1023 downto 0) := x"AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55AA55";
70 
71  type StateType is (
72  IDLE_S,
73  WRITE_ADDR_S,
74  WRITE_DATA_S,
75  WRITE_RESP_S,
76  READ_ADDR_S,
77  READ_DATA_S,
78  DONE_S,
79  ERROR_S);
80 
81  type RegType is record
82  done : sl;
83  error : sl;
84  wErrResp : sl;
85  rErrResp : sl;
86  rErrData : sl;
87  wTimerEn : sl;
88  rTimerEn : sl;
89  wTimer : slv(31 downto 0);
90  rTimer : slv(31 downto 0);
91  len : slv(7 downto 0);
92  address : slv(63 downto 0);
93  randomData : slv(1023 downto 0);
94  state : StateType;
97  end record;
98 
99  constant REG_INIT_C : RegType := (
100  done => '0',
101  error => '0',
102  wErrResp => '0',
103  rErrResp => '0',
104  rErrData => '0',
105  wTimerEn => '0',
106  rTimerEn => '0',
107  wTimer => (others => '0'),
108  rTimer => (others => '0'),
109  len => AXI_LEN_C,
110  address => (others => '0'),
111  randomData => PRBS_SEED_C,
112  state => IDLE_S,
115 
116  signal r : RegType := REG_INIT_C;
117  signal rin : RegType;
118 
119  signal done : sl;
120  signal error : sl;
121  signal wTimer : slv(31 downto 0);
122  signal rTimer : slv(31 downto 0);
123 
124  type RegLiteType is record
125  memReady : sl;
126  memError : sl;
129  end record;
130 
131  constant REG_LITE_INIT_C : RegLiteType := (
132  memReady => '0',
133  memError => '0',
136 
137  signal rLite : RegLiteType := REG_LITE_INIT_C;
138  signal rinLite : RegLiteType;
139 
140  -- attribute dont_touch : string;
141  -- attribute dont_touch of r : signal is "true";
142  -- attribute dont_touch of rLite : signal is "true";
143 
144 begin
145 
146  comb : process (axiReadSlave, axiRst, axiWriteSlave, r, start) is
147  variable v : RegType;
148  begin
149  -- Latch the current value
150  v := r;
151 
152  -- Update output registers
153  if axiWriteSlave.awready = '1' then
154  v.axiWriteMaster.awvalid := '0';
155  end if;
156  if axiWriteSlave.wready = '1' then
157  v.axiWriteMaster.wvalid := '0';
158  v.axiWriteMaster.wlast := '0';
159  end if;
160  if axiReadSlave.arready = '1' then
161  v.axiReadMaster.arvalid := '0';
162  end if;
163 
164  -- Check the flags
165  if (r.wTimerEn = '1') and (r.wTimer /= x"FFFFFFFF") then
166  v.wTimer := r.wTimer + 1;
167  end if;
168  if (r.rTimerEn = '1') and (r.rTimer /= x"FFFFFFFF") then
169  v.rTimer := r.rTimer + 1;
170  end if;
171 
172  -- State Machine
173  case (r.state) is
174 
175  ----------------------------------------------------------------------
176  when IDLE_S =>
177  -- Check calibration to complete
178  if start = '1' then
179  -- Set the flags
180  v.wTimerEn := '1';
181  v.rTimerEn := '0';
182  -- Latch the generator seed
183  v.randomData := PRBS_SEED_C;
184  -- Set the start address
185  v.address(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := START_ADDR_C;
186  -- Next State
187  v.state := WRITE_ADDR_S;
188  end if;
189  ----------------------------------------------------------------------
190  when WRITE_ADDR_S =>
191  if (v.axiWriteMaster.awvalid = '0') and (axiReadSlave.rvalid = '0') then
192  -- Write Address channel
193  v.axiWriteMaster.awvalid := '1';
194  v.axiWriteMaster.awaddr := r.address;
195  -- Next State
196  v.state := WRITE_DATA_S;
197  end if;
198  ----------------------------------------------------------------------
199  when WRITE_DATA_S =>
200  if (v.axiWriteMaster.awvalid = '0') and (v.axiWriteMaster.wvalid = '0') then
201  -- Write Data channel
202  v.axiWriteMaster.wvalid := '1';
203  v.axiWriteMaster.wdata(DATA_BITS_C-1 downto 0) := r.randomData(DATA_BITS_C-1 downto 0);
204  -- Generate next random word
205  v.randomData := lfsrShift(r.randomData, PRBS_TAPS_C);
206  -- Increment the counter
207  v.len := r.len - 1;
208  -- Check that all txns are done
209  if r.len = 0 then
210  -- Reset the counter
211  v.len := AXI_LEN_C;
212  -- Set the flag
213  v.axiWriteMaster.wlast := '1';
214  -- Next State
215  v.state := WRITE_RESP_S;
216  end if;
217  end if;
218  ----------------------------------------------------------------------
219  when WRITE_RESP_S =>
220  -- Wait for the response
221  if axiWriteSlave.bvalid = '1' then
222  -- Check for "OKAY" response
223  if axiWriteSlave.bresp = "00" then
224  -- Check for max. address
225  if r.address = STOP_ADDR_C then
226  -- Reset the start address
227  v.address := (others => '0');
228  v.address(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 0) := START_ADDR_C;
229  -- Set the flags
230  v.wTimerEn := '0';
231  v.rTimerEn := '1';
232  -- Latch the generator seed
233  v.randomData := PRBS_SEED_C;
234  -- Next State
235  v.state := READ_ADDR_S;
236  else
237  -- Increment the counter
238  v.address := r.address + BURST_LEN_G;
239  -- Next State
240  v.state := WRITE_ADDR_S;
241  end if;
242  else
243  -- Set the flag
244  v.wErrResp := '1';
245  -- Next State
246  v.state := ERROR_S;
247  end if;
248  end if;
249  ----------------------------------------------------------------------
250  when READ_ADDR_S =>
251  if (v.axiReadMaster.arvalid = '0') and (axiReadSlave.rvalid = '0') then
252  -- Write Address channel
253  v.axiReadMaster.arvalid := '1';
254  v.axiReadMaster.araddr := r.address;
255  -- Next State
256  v.state := READ_DATA_S;
257  end if;
258  ----------------------------------------------------------------------
259  when READ_DATA_S =>
260  if (v.axiReadMaster.arvalid = '0') and (axiReadSlave.rvalid = '1') then
261  -- Compare the data
262  if r.randomData(DATA_BITS_C-1 downto 0) /= axiReadSlave.rdata(DATA_BITS_C-1 downto 0) then
263  -- Set the flag
264  v.rErrData := '1';
265  -- Next State
266  v.state := ERROR_S;
267  end if;
268  -- Generate next random word
269  v.randomData := lfsrShift(r.randomData, PRBS_TAPS_C);
270  -- Check for last transfer
271  if axiReadSlave.rlast = '1' then
272  if axiReadSlave.rresp = "00" then
273  -- Check for max. address
274  if r.address = STOP_ADDR_C then
275  report "AxiMemTester: Passed Test!";
276  report "wTimer = " & integer'image(conv_integer(v.wTimer));
277  report "rTimer = " & integer'image(conv_integer(v.rTimer));
278  -- Next State
279  v.state := DONE_S;
280  else
281  -- Increment the counter
282  v.address := r.address + BURST_LEN_G;
283  -- Next State
284  v.state := READ_ADDR_S;
285  end if;
286  else
287  -- Set the flag
288  v.rErrResp := '1';
289  -- Next State
290  v.state := ERROR_S;
291  end if;
292  end if;
293  end if;
294  ----------------------------------------------------------------------
295  when DONE_S =>
296  v.done := '1';
297  v.error := '0';
298  v.wTimerEn := '0';
299  v.rTimerEn := '0';
300  ----------------------------------------------------------------------
301  when ERROR_S =>
302  v.done := '0';
303  v.error := '1';
304  v.wTimerEn := '0';
305  v.rTimerEn := '0';
306  ----------------------------------------------------------------------
307  end case;
308 
309  -- Reset
310  if axiRst = '1' then
311  v := REG_INIT_C;
312  end if;
313 
314  -- Write Address Constants
315  v.axiWriteMaster.awid := (others => '0');
316  v.axiWriteMaster.awlen := AXI_LEN_C;
317  v.axiWriteMaster.awsize := toSlv(log2(AXI_CONFIG_G.DATA_BYTES_C), 3);
318  v.axiWriteMaster.awburst := "01"; -- Burst type = "INCR"
319  v.axiWriteMaster.awlock := (others => '0');
320  v.axiWriteMaster.awprot := (others => '0');
321  v.axiWriteMaster.awcache := "1111"; -- Write-back Read and Write-allocate
322  v.axiWriteMaster.awqos := (others => '0');
323  v.axiWriteMaster.bready := '1';
324  v.axiWriteMaster.wstrb := (others => '1');
325 
326  -- Read Address Constants (copied from Write Constants)
336 
337  -- Register the variable for next clock cycle
338  rin <= v;
339 
340  -- Outputs
343 
344  end process comb;
345 
346  seq : process (axiClk) is
347  begin
348  if rising_edge(axiClk) then
349  r <= rin after TPD_G;
350  end if;
351  end process seq;
352 
353  Sync_0 : entity work.Synchronizer
354  generic map (
355  TPD_G => TPD_G)
356  port map (
357  clk => axilClk,
358  dataIn => r.done,
359  dataOut => done);
360 
361  Sync_1 : entity work.Synchronizer
362  generic map (
363  TPD_G => TPD_G)
364  port map (
365  clk => axilClk,
366  dataIn => r.error,
367  dataOut => error);
368 
369  Sync_2 : entity work.SynchronizerFifo
370  generic map (
371  TPD_G => TPD_G,
372  DATA_WIDTH_G => 32)
373  port map (
374  -- Write Ports (wr_clk domain)
375  wr_clk => axiClk,
376  din => r.wTimer,
377  -- Read Ports (rd_clk domain)
378  rd_clk => axilClk,
379  dout => wTimer);
380 
381  Sync_3 : entity work.SynchronizerFifo
382  generic map (
383  TPD_G => TPD_G,
384  DATA_WIDTH_G => 32)
385  port map (
386  -- Write Ports (wr_clk domain)
387  wr_clk => axiClk,
388  din => r.rTimer,
389  -- Read Ports (rd_clk domain)
390  rd_clk => axilClk,
391  dout => rTimer);
392 
393  combLite : process (axilReadMaster, axilRst, axilWriteMaster, done, error, rLite, rTimer, wTimer) is
394  variable v : RegLiteType;
395  variable regCon : AxiLiteEndPointType;
396  begin
397  -- Latch the current value
398  v := rLite;
399 
400  -- Determine the transaction type
401  axiSlaveWaitTxn(regCon, axilWriteMaster, axilReadMaster, v.axilWriteSlave, v.axilReadSlave);
402 
403  -- Map the registers
404  axiSlaveRegisterR(regCon, x"100", 0, rLite.memReady);
405  axiSlaveRegisterR(regCon, x"104", 0, rLite.memError);
406  axiSlaveRegisterR(regCon, x"108", 0, wTimer);
407  axiSlaveRegisterR(regCon, x"10C", 0, rTimer);
408  if (AXI_CONFIG_G.ADDR_WIDTH_C <= 32) then
409  axiSlaveRegisterR(regCon, x"110", 0, START_C);
410  axiSlaveRegisterR(regCon, x"114", 0, x"00000000");
411  axiSlaveRegisterR(regCon, x"118", 0, STOP_C);
412  axiSlaveRegisterR(regCon, x"11C", 0, x"00000000");
413  else
414  axiSlaveRegisterR(regCon, x"110", 0, START_C(31 downto 0));
415  axiSlaveRegisterR(regCon, x"114", 0, START_C(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 32));
416  axiSlaveRegisterR(regCon, x"118", 0, STOP_C(31 downto 0));
417  axiSlaveRegisterR(regCon, x"11C", 0, STOP_C(AXI_CONFIG_G.ADDR_WIDTH_C-1 downto 32));
418  end if;
419  axiSlaveRegisterR(regCon, x"120", 0, toSlv(AXI_CONFIG_G.ADDR_WIDTH_C, 32));
420  axiSlaveRegisterR(regCon, x"124", 0, toSlv(AXI_CONFIG_G.DATA_BYTES_C, 32));
421  axiSlaveRegisterR(regCon, x"128", 0, toSlv(AXI_CONFIG_G.ID_BITS_C, 32));
422 
423  -- Closeout the transaction
424  axiSlaveDefault(regCon, v.axilWriteSlave, v.axilReadSlave, AXI_ERROR_RESP_G);
425 
426  -- Latch the values from Synchronizers
427  v.memReady := done;
428  v.memError := error;
429 
430  -- Synchronous Reset
431  if (axilRst = '1') then
432  v := REG_LITE_INIT_C;
433  end if;
434 
435  -- Register the variable for next clock cycle
436  rinLite <= v;
437 
438  -- Outputs
440  axilReadSlave <= rLite.axilReadSlave;
441  memReady <= rLite.memReady;
442  memError <= rLite.memError;
443 
444  end process combLite;
445 
446  seqLite : process (axilClk) is
447  begin
448  if (rising_edge(axilClk)) then
449  rLite <= rinLite after TPD_G;
450  end if;
451  end process seqLite;
452 
453 end rtl;
slv( 2 downto 0) arprot
Definition: AxiLitePkg.vhd:62
out axilReadSlaveAxiLiteReadSlaveType
slv( 7 downto 0) arlen
Definition: AxiPkg.vhd:37
in axilWriteMasterAxiLiteWriteMasterType
AxiReadMasterType :=(arvalid => '0',araddr =>( others => '0'),arid =>( others => '0'),arlen =>( others => '0'),arsize =>( others => '0'),arburst =>( others => '0'),arlock =>( others => '0'),arprot =>( others => '0'),arcache =>( others => '0'),arqos =>( others => '0'),arregion =>( others => '0'),rready => '0') AXI_READ_MASTER_INIT_C
Definition: AxiPkg.vhd:49
out axiReadMasterAxiReadMasterType
slv( 1 downto 0) rresp
Definition: AxiLitePkg.vhd:90
slv( 1 downto 0) awlock
Definition: AxiPkg.vhd:116
AxiLiteWriteMasterType
Definition: AxiLitePkg.vhd:111
std_logic sl
Definition: StdRtlPkg.vhd:28
out memReadysl
_library_ ieeeieee
sl wlast
Definition: AxiPkg.vhd:123
in dinslv( DATA_WIDTH_G- 1 downto 0)
slv( 7 downto 0) awlen
Definition: AxiPkg.vhd:113
START_ADDR_Gslv := X"00000000"
slv( 2 downto 0) awsize
Definition: AxiPkg.vhd:114
slv( 31 downto 0) rdata
Definition: AxiLitePkg.vhd:89
slv( 3 downto 0) arcache
Definition: AxiPkg.vhd:42
STOP_ADDR_Gslv := X"FFFFFFFF"
in axiReadSlaveAxiReadSlaveType
slv( 3 downto 0) awqos
Definition: AxiPkg.vhd:119
slv( 31 downto 0) wdata
Definition: AxiLitePkg.vhd:117
out dataOutsl
out doutslv( DATA_WIDTH_G- 1 downto 0)
positive range 12 to 64 ADDR_WIDTH_C
Definition: AxiPkg.vhd:214
AxiReadSlaveType
Definition: AxiPkg.vhd:79
AxiWriteMasterType
Definition: AxiPkg.vhd:108
TPD_Gtime := 1 ns
slv( 3 downto 0) arqos
Definition: AxiPkg.vhd:43
slv( 1 downto 0) := "11" AXI_RESP_DECERR_C
Definition: AxiLitePkg.vhd:49
slv( 31 downto 0) arid
Definition: AxiPkg.vhd:36
array(natural range <> ) of natural NaturalArray
Definition: StdRtlPkg.vhd:34
slv( 2 downto 0) awprot
Definition: AxiLitePkg.vhd:114
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
slv( 31 downto 0) awaddr
Definition: AxiLitePkg.vhd:113
out axiWriteMasterAxiWriteMasterType
AxiConfigType
Definition: AxiPkg.vhd:213
TPD_Gtime := 1 ns
slv( 2 downto 0) arsize
Definition: AxiPkg.vhd:38
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:95
in axilReadMasterAxiLiteReadMasterType
slv( 1 downto 0) bresp
Definition: AxiLitePkg.vhd:150
AxiWriteSlaveType
Definition: AxiPkg.vhd:171
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
slv( 1 downto 0) awburst
Definition: AxiPkg.vhd:115
slv( 1 downto 0) arburst
Definition: AxiPkg.vhd:39
out axilWriteSlaveAxiLiteWriteSlaveType
slv( 3 downto 0) awcache
Definition: AxiPkg.vhd:118
out memErrorsl
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
positive range 1 to 128 DATA_BYTES_C
Definition: AxiPkg.vhd:215
slv( 31 downto 0) araddr
Definition: AxiLitePkg.vhd:61
sl rlast
Definition: AxiPkg.vhd:84
slv( 1 downto 0) arlock
Definition: AxiPkg.vhd:40
slv( 3 downto 0) wstrb
Definition: AxiLitePkg.vhd:118
slv( 31 downto 0) awid
Definition: AxiPkg.vhd:112
BURST_LEN_Gpositive range 1 to 4096:= 4096
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
positive range 1 to 32 ID_BITS_C
Definition: AxiPkg.vhd:216
AxiWriteMasterType :=(awvalid => '0',awaddr =>( others => '0'),awid =>( others => '0'),awlen =>( others => '0'),awsize =>( others => '0'),awburst =>( others => '0'),awlock =>( others => '0'),awprot =>( others => '0'),awcache =>( others => '0'),awqos =>( others => '0'),awregion =>( others => '0'),wdata =>( others => '0'),wlast => '0',wvalid => '0',wid =>( others => '0'),wstrb =>( others => '0'),bready => '0') AXI_WRITE_MASTER_INIT_C
Definition: AxiPkg.vhd:131
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:156
AXI_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_DECERR_C
AxiReadMasterType
Definition: AxiPkg.vhd:32
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in axiWriteSlaveAxiWriteSlaveType