litedram: l2: Latency improvements
[microwatt.git] / dram_tb.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.common.all;
7 use work.wishbone_types.all;
8
9 entity dram_tb is
10 generic (
11 DRAM_INIT_FILE : string := "";
12 DRAM_INIT_SIZE : natural := 0
13 );
14 end dram_tb;
15
16 architecture behave of dram_tb is
17 signal clk, rst: std_logic;
18 signal clk_in, soc_rst : std_ulogic;
19
20 -- testbench signals
21 constant clk_period : time := 10 ns;
22
23 -- Sim DRAM
24 signal wb_in : wishbone_master_out;
25 signal wb_out : wishbone_slave_out;
26 signal wb_ctrl_in : wb_io_master_out;
27
28 subtype addr_t is std_ulogic_vector(wb_in.adr'left downto 0);
29 subtype data_t is std_ulogic_vector(wb_in.dat'left downto 0);
30 subtype sel_t is std_ulogic_vector(wb_in.sel'left downto 0);
31
32 -- Counter for acks
33 signal acks : integer := 0;
34 signal reset_acks : std_ulogic;
35
36 -- Read data fifo
37 signal rd_ready : std_ulogic := '0';
38 signal rd_valid : std_ulogic;
39 signal rd_data : data_t;
40 begin
41
42 dram: entity work.litedram_wrapper
43 generic map(
44 DRAM_ABITS => 24,
45 DRAM_ALINES => 1,
46 PAYLOAD_FILE => DRAM_INIT_FILE,
47 PAYLOAD_SIZE => DRAM_INIT_SIZE
48 )
49 port map(
50 clk_in => clk_in,
51 rst => rst,
52 system_clk => clk,
53 system_reset => soc_rst,
54 core_alt_reset => open,
55 pll_locked => open,
56
57 wb_in => wb_in,
58 wb_out => wb_out,
59 wb_ctrl_in => wb_ctrl_in,
60 wb_ctrl_out => open,
61 wb_ctrl_is_csr => '0',
62 wb_ctrl_is_init => '0',
63
64 init_done => open,
65 init_error => open,
66
67 ddram_a => open,
68 ddram_ba => open,
69 ddram_ras_n => open,
70 ddram_cas_n => open,
71 ddram_we_n => open,
72 ddram_cs_n => open,
73 ddram_dm => open,
74 ddram_dq => open,
75 ddram_dqs_p => open,
76 ddram_dqs_n => open,
77 ddram_clk_p => open,
78 ddram_clk_n => open,
79 ddram_cke => open,
80 ddram_odt => open,
81 ddram_reset_n => open
82 );
83
84 clk_process: process
85 begin
86 clk_in <= '0';
87 wait for clk_period/2;
88 clk_in <= '1';
89 wait for clk_period/2;
90 end process;
91
92 rst_process: process
93 begin
94 rst <= '1';
95 wait for 10*clk_period;
96 rst <= '0';
97 wait;
98 end process;
99
100 wb_ctrl_in.cyc <= '0';
101 wb_ctrl_in.stb <= '0';
102
103 -- Read data receive queue
104 data_queue: entity work.sync_fifo
105 generic map (
106 DEPTH => 16,
107 WIDTH => rd_data'length
108 )
109 port map (
110 clk => clk,
111 reset => soc_rst or reset_acks,
112 rd_ready => rd_ready,
113 rd_valid => rd_valid,
114 rd_data => rd_data,
115 wr_ready => open,
116 wr_valid => wb_out.ack,
117 wr_data => wb_out.dat
118 );
119
120 recv_acks: process(clk)
121 begin
122 if rising_edge(clk) then
123 if rst = '1' or reset_acks = '1' then
124 acks <= 0;
125 elsif wb_out.ack = '1' then
126 acks <= acks + 1;
127 -- report "WB ACK ! DATA=" & to_hstring(wb_out.dat);
128 end if;
129 end if;
130 end process;
131
132 sim: process
133 procedure wb_write(addr: addr_t; data: data_t; sel: sel_t) is
134 begin
135 wb_in.adr <= addr;
136 wb_in.sel <= sel;
137 wb_in.dat <= data;
138 wb_in.we <= '1';
139 wb_in.stb <= '1';
140 wb_in.cyc <= '1';
141 loop
142 wait until rising_edge(clk);
143 if wb_out.stall = '0' then
144 wb_in.stb <= '0';
145 exit;
146 end if;
147 end loop;
148 end procedure;
149
150 procedure wb_read(addr: addr_t) is
151 begin
152 wb_in.adr <= addr;
153 wb_in.sel <= x"ff";
154 wb_in.we <= '0';
155 wb_in.stb <= '1';
156 wb_in.cyc <= '1';
157 loop
158 wait until rising_edge(clk);
159 if wb_out.stall = '0' then
160 wb_in.stb <= '0';
161 exit;
162 end if;
163 end loop;
164 end procedure;
165
166 procedure wait_acks(count: integer) is
167 begin
168 wait until acks = count;
169 wait until rising_edge(clk);
170 end procedure;
171
172 procedure clr_acks is
173 begin
174 reset_acks <= '1';
175 wait until rising_edge(clk);
176 reset_acks <= '0';
177 end procedure;
178
179 procedure read_data(data: out data_t) is
180 begin
181 assert rd_valid = '1' report "No data to read" severity failure;
182 rd_ready <= '1';
183 wait until rising_edge(clk);
184 rd_ready <= '0';
185 data := rd_data;
186 end procedure;
187
188 function add_off(a: addr_t; off: integer) return addr_t is
189 begin
190 return addr_t(unsigned(a) + off);
191 end function;
192
193 function make_pattern(num : integer) return data_t is
194 variable r : data_t;
195 variable t,b : integer;
196 begin
197 for i in 0 to (data_t'length/8)-1 loop
198 t := (i+1)*8-1;
199 b := i*8;
200 r(t downto b) := std_ulogic_vector(to_unsigned(num+1, 8));
201 end loop;
202 return r;
203 end function;
204
205 procedure check_data(p: data_t) is
206 variable d : data_t;
207 begin
208 read_data(d);
209 assert d = p report "bad data, want " & to_hstring(p) &
210 " got " & to_hstring(d) severity failure;
211 end procedure;
212
213 variable a : addr_t := (others => '0');
214 variable d : data_t := (others => '0');
215 variable d1 : data_t := (others => '0');
216 begin
217 reset_acks <= '0';
218 rst <= '1';
219 wait until rising_edge(clk_in);
220 wait until rising_edge(clk_in);
221 wait until rising_edge(clk_in);
222 wait until rising_edge(clk_in);
223 wait until rising_edge(clk_in);
224 rst <= '0';
225 wait until rising_edge(clk_in);
226 wait until soc_rst = '0';
227 wait until rising_edge(clk);
228
229 report "Simple write miss...";
230 clr_acks;
231 wb_write(a, x"0123456789abcdef", x"ff");
232 wait_acks(1);
233
234 report "Simple read miss...";
235 clr_acks;
236 wb_read(a);
237 wait_acks(1);
238 read_data(d);
239 assert d = x"0123456789abcdef" report "bad data, got " & to_hstring(d) severity failure;
240
241 report "Simple read hit...";
242 clr_acks;
243 wb_read(a);
244 wait_acks(1);
245 read_data(d);
246 assert d = x"0123456789abcdef" report "bad data, got " & to_hstring(d) severity failure;
247
248 report "Back to back 4 stores 4 reads on hit...";
249 clr_acks;
250 for i in 0 to 3 loop
251 wb_write(add_off(a, i*8), make_pattern(i), x"ff");
252 end loop;
253 for i in 0 to 3 loop
254 wb_read(add_off(a, i*8));
255 end loop;
256 wait_acks(8);
257 for i in 0 to 7 loop
258 if i < 4 then
259 read_data(d);
260 else
261 check_data(make_pattern(i-4));
262 end if;
263 end loop;
264
265 report "Back to back 4 stores 4 reads on miss...";
266 a(10) := '1';
267 clr_acks;
268 for i in 0 to 3 loop
269 wb_write(add_off(a, i*8), make_pattern(i), x"ff");
270 end loop;
271 for i in 0 to 3 loop
272 wb_read(add_off(a, i*8));
273 end loop;
274 wait_acks(8);
275 for i in 0 to 7 loop
276 if i < 4 then
277 read_data(d);
278 else
279 check_data(make_pattern(i-4));
280 end if;
281 end loop;
282
283 report "Back to back interleaved 4 stores 4 reads on hit...";
284 a(10) := '1';
285 clr_acks;
286 for i in 0 to 3 loop
287 wb_write(add_off(a, i*8), make_pattern(i), x"ff");
288 wb_read(add_off(a, i*8));
289 end loop;
290 wait_acks(8);
291 for i in 0 to 3 loop
292 read_data(d);
293 check_data(make_pattern(i));
294 end loop;
295
296 report "Pre-fill a line";
297 a(11) := '1';
298 clr_acks;
299 wb_write(add_off(a, 0), x"1111111100000000", x"ff");
300 wb_write(add_off(a, 8), x"3333333322222222", x"ff");
301 wb_write(add_off(a, 16), x"5555555544444444", x"ff");
302 wb_write(add_off(a, 24), x"7777777766666666", x"ff");
303 wb_write(add_off(a, 32), x"9999999988888888", x"ff");
304 wb_write(add_off(a, 40), x"bbbbbbbbaaaaaaaa", x"ff");
305 wb_write(add_off(a, 48), x"ddddddddcccccccc", x"ff");
306 wb_write(add_off(a, 56), x"ffffffffeeeeeeee", x"ff");
307 wb_write(add_off(a, 64), x"1111111100000000", x"ff");
308 wb_write(add_off(a, 72), x"3333333322222222", x"ff");
309 wb_write(add_off(a, 80), x"5555555544444444", x"ff");
310 wb_write(add_off(a, 88), x"7777777766666666", x"ff");
311 wb_write(add_off(a, 96), x"9999999988888888", x"ff");
312 wb_write(add_off(a,104), x"bbbbbbbbaaaaaaaa", x"ff");
313 wb_write(add_off(a,112), x"ddddddddcccccccc", x"ff");
314 wb_write(add_off(a,120), x"ffffffffeeeeeeee", x"ff");
315 wait_acks(16);
316
317 report "Scattered from middle of line...";
318 clr_acks;
319 wb_read(add_off(a,24));
320 wb_read(add_off(a,32));
321 wb_read(add_off(a, 0));
322 wb_read(add_off(a,16));
323 wait_acks(4);
324 read_data(d);
325 assert d = x"7777777766666666" report "bad data (24), got " & to_hstring(d) severity failure;
326 read_data(d);
327 assert d = x"9999999988888888" report "bad data (32), got " & to_hstring(d) severity failure;
328 read_data(d);
329 assert d = x"1111111100000000" report "bad data (0), got " & to_hstring(d) severity failure;
330 read_data(d);
331 assert d = x"5555555544444444" report "bad data (16), got " & to_hstring(d) severity failure;
332
333 std.env.finish;
334 end process;
335 end architecture;