1 |
13 |
wfjm |
-- $Id: rbd_rbmon.vhd 427 2011-11-19 21:04:11Z mueller $
|
2 |
10 |
wfjm |
--
|
3 |
|
|
-- Copyright 2010-2011 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
4 |
|
|
--
|
5 |
|
|
-- This program is free software; you may redistribute and/or modify it under
|
6 |
|
|
-- the terms of the GNU General Public License as published by the Free
|
7 |
|
|
-- Software Foundation, either version 2, or at your option any later version.
|
8 |
|
|
--
|
9 |
|
|
-- This program is distributed in the hope that it will be useful, but
|
10 |
|
|
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
11 |
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
12 |
|
|
-- for complete details.
|
13 |
|
|
--
|
14 |
|
|
------------------------------------------------------------------------------
|
15 |
|
|
-- Module Name: rbd_rbmon - syn
|
16 |
|
|
-- Description: rbus dev: rbus monitor
|
17 |
|
|
--
|
18 |
|
|
-- Dependencies: memlib/ram_1swsr_wfirst_gen
|
19 |
|
|
--
|
20 |
|
|
-- Test bench: rlink/tb/tb_rlink_tba_ttcombo
|
21 |
|
|
--
|
22 |
|
|
-- Target Devices: generic
|
23 |
13 |
wfjm |
-- Tool versions: xst 12.1, 13.1; ghdl 0.29
|
24 |
10 |
wfjm |
--
|
25 |
|
|
-- Synthesized (xst):
|
26 |
|
|
-- Date Rev ise Target flop lutl lutm slic t peri
|
27 |
|
|
-- 2010-12-27 349 12.1 M53d xc3s1000-4 95 228 - 154 s 10.4
|
28 |
|
|
--
|
29 |
|
|
-- Revision History:
|
30 |
|
|
-- Date Rev Version Comment
|
31 |
13 |
wfjm |
-- 2011-11-19 427 1.0.3 now numeric_std clean
|
32 |
10 |
wfjm |
-- 2011-03-27 374 1.0.2 rename ncyc -> nbusy because it counts busy cycles
|
33 |
|
|
-- 2010-12-31 352 1.0.1 simplify irb_ack logic
|
34 |
|
|
-- 2010-12-27 349 1.0 Initial version
|
35 |
|
|
------------------------------------------------------------------------------
|
36 |
|
|
--
|
37 |
12 |
wfjm |
-- Address Bits Name r/w/f Function
|
38 |
|
|
-- bbbbbb00 cntl r/w/f Control register
|
39 |
|
|
-- 00 go r/w/f writing 1 clears add
|
40 |
|
|
-- bbbbbb01 alim r/w/- Address limit register
|
41 |
|
|
-- 15:08 hilim r/w/- upper address limit (def: ff)
|
42 |
|
|
-- 07:00 lolim r/w/- lower address limit (def: 00)
|
43 |
|
|
-- bbbbbb10 addr r/w/- Address register
|
44 |
|
|
-- 15 wrap r/0/- line address wrapped (cleared on write)
|
45 |
|
|
-- *:02 laddr r/w/- line address
|
46 |
|
|
-- 01:00 waddr r/w/- word address
|
47 |
|
|
-- bbbbbb11 data r/w/- Data register
|
48 |
10 |
wfjm |
--
|
49 |
|
|
-- data format:
|
50 |
|
|
-- word 3 15 : ack
|
51 |
|
|
-- 14 : busy
|
52 |
|
|
-- 13 : err
|
53 |
|
|
-- 12 : nak
|
54 |
|
|
-- 11 : tout
|
55 |
|
|
-- 09 : init
|
56 |
|
|
-- 08 : we
|
57 |
|
|
-- 07:00 : addr
|
58 |
|
|
-- word 2 data
|
59 |
|
|
-- word 1 15:00 : delay to prev (lsb's)
|
60 |
|
|
-- word 0 15:12 : delay to prev (msb's)
|
61 |
|
|
-- 11:00 : number of busy cycles
|
62 |
|
|
--
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
library ieee;
|
66 |
|
|
use ieee.std_logic_1164.all;
|
67 |
13 |
wfjm |
use ieee.numeric_std.all;
|
68 |
10 |
wfjm |
|
69 |
|
|
use work.slvtypes.all;
|
70 |
|
|
use work.memlib.all;
|
71 |
|
|
use work.rblib.all;
|
72 |
|
|
|
73 |
|
|
entity rbd_rbmon is -- rbus dev: rbus monitor
|
74 |
|
|
generic (
|
75 |
13 |
wfjm |
RB_ADDR : slv8 := slv(to_unsigned(2#11111100#,8));
|
76 |
10 |
wfjm |
AWIDTH : positive := 9);
|
77 |
|
|
port (
|
78 |
|
|
CLK : in slbit; -- clock
|
79 |
|
|
RESET : in slbit; -- reset
|
80 |
|
|
RB_MREQ : in rb_mreq_type; -- rbus: request
|
81 |
|
|
RB_SRES : out rb_sres_type; -- rbus: response
|
82 |
|
|
RB_SRES_SUM : in rb_sres_type -- rbus: response (sum for monitor)
|
83 |
|
|
);
|
84 |
|
|
end entity rbd_rbmon;
|
85 |
|
|
|
86 |
|
|
|
87 |
|
|
architecture syn of rbd_rbmon is
|
88 |
|
|
|
89 |
|
|
constant rbaddr_cntl : slv2 := "00"; -- cntl address offset
|
90 |
|
|
constant rbaddr_alim : slv2 := "01"; -- alim address offset
|
91 |
|
|
constant rbaddr_addr : slv2 := "10"; -- addr address offset
|
92 |
|
|
constant rbaddr_data : slv2 := "11"; -- data address offset
|
93 |
|
|
|
94 |
|
|
constant cntl_rbf_go : integer := 0;
|
95 |
|
|
subtype alim_rbf_hilim is integer range 15 downto 8;
|
96 |
|
|
subtype alim_rbf_lolim is integer range 7 downto 0;
|
97 |
|
|
constant addr_rbf_wrap : integer := 15;
|
98 |
|
|
subtype addr_rbf_laddr is integer range 2+AWIDTH-1 downto 2;
|
99 |
|
|
subtype addr_rbf_waddr is integer range 1 downto 0;
|
100 |
|
|
|
101 |
|
|
constant dat3_rbf_ack : integer := 15;
|
102 |
|
|
constant dat3_rbf_busy : integer := 14;
|
103 |
|
|
constant dat3_rbf_err : integer := 13;
|
104 |
|
|
constant dat3_rbf_nak : integer := 12;
|
105 |
|
|
constant dat3_rbf_tout : integer := 11;
|
106 |
|
|
constant dat3_rbf_init : integer := 9;
|
107 |
|
|
constant dat3_rbf_we : integer := 8;
|
108 |
|
|
subtype dat3_rbf_addr is integer range 7 downto 0;
|
109 |
|
|
subtype dat0_rbf_ndlymsb is integer range 15 downto 12;
|
110 |
|
|
subtype dat0_rbf_nbusy is integer range 11 downto 0;
|
111 |
|
|
|
112 |
|
|
type regs_type is record -- state registers
|
113 |
|
|
rbsel : slbit; -- rbus select
|
114 |
|
|
go : slbit; -- go flag
|
115 |
|
|
hilim : slv8; -- upper address limit
|
116 |
|
|
lolim : slv8; -- lower address limit
|
117 |
|
|
wrap : slbit; -- laddr wrap flag
|
118 |
|
|
laddr : slv(AWIDTH-1 downto 0); -- line address
|
119 |
|
|
waddr : slv2; -- word address
|
120 |
|
|
rbtake_1 : slbit; -- rb capture active in last cycle
|
121 |
|
|
rbaddr : slv8; -- rbus trace: addr
|
122 |
|
|
rbinit : slbit; -- rbus trace: init
|
123 |
|
|
rbwe : slbit; -- rbus trace: we
|
124 |
|
|
rback : slbit; -- rbus trace: ack seen
|
125 |
|
|
rbbusy : slbit; -- rbus trace: busy seen
|
126 |
|
|
rberr : slbit; -- rbus trace: err seen
|
127 |
|
|
rbnak : slbit; -- rbus trace: nak detected
|
128 |
|
|
rbtout : slbit; -- rbus trace: tout detected
|
129 |
|
|
rbdata : slv16; -- rbus trace: data
|
130 |
|
|
rbnbusy : slv12; -- rbus number of busy cycles
|
131 |
|
|
rbndly : slv20; -- rbus delay to prev. access
|
132 |
|
|
end record regs_type;
|
133 |
|
|
|
134 |
|
|
constant laddrzero : slv(AWIDTH-1 downto 0) := (others=>'0');
|
135 |
|
|
constant laddrlast : slv(AWIDTH-1 downto 0) := (others=>'1');
|
136 |
|
|
|
137 |
|
|
constant regs_init : regs_type := (
|
138 |
|
|
'0', -- rbsel
|
139 |
|
|
'0', -- go (default is off)
|
140 |
|
|
(others=>'1'), -- hilim (def: ff)
|
141 |
|
|
(others=>'0'), -- lolim (def: 00)
|
142 |
|
|
'0', -- wrap
|
143 |
|
|
laddrzero, -- laddr
|
144 |
|
|
"00", -- waddr
|
145 |
|
|
'0', -- rbtake_1
|
146 |
|
|
(others=>'0'), -- rbaddr
|
147 |
|
|
'0','0','0','0','0', -- rbinit,rbwe,rback,rbbusy,rberr
|
148 |
|
|
'0','0', -- rbnak,rbtout
|
149 |
|
|
(others=>'0'), -- rbdata
|
150 |
|
|
(others=>'0'), -- rbnbusy
|
151 |
|
|
(others=>'0') -- rbndly
|
152 |
|
|
);
|
153 |
|
|
|
154 |
|
|
constant rbnbusylast : slv12 := (others=>'1');
|
155 |
|
|
constant rbndlylast : slv20 := (others=>'1');
|
156 |
|
|
|
157 |
|
|
signal R_REGS : regs_type := regs_init;
|
158 |
|
|
signal N_REGS : regs_type := regs_init;
|
159 |
|
|
|
160 |
|
|
signal BRAM_EN : slbit := '0';
|
161 |
|
|
signal BRAM_WE : slbit := '0';
|
162 |
|
|
signal BRAM0_DI : slv32 := (others=>'0');
|
163 |
|
|
signal BRAM1_DI : slv32 := (others=>'0');
|
164 |
|
|
signal BRAM0_DO : slv32 := (others=>'0');
|
165 |
|
|
signal BRAM1_DO : slv32 := (others=>'0');
|
166 |
|
|
|
167 |
|
|
begin
|
168 |
|
|
|
169 |
|
|
assert AWIDTH<=13
|
170 |
|
|
report "assert(AWIDTH<=13): max address width supported"
|
171 |
|
|
severity failure;
|
172 |
|
|
|
173 |
|
|
BRAM1 : ram_1swsr_wfirst_gen
|
174 |
|
|
generic map (
|
175 |
|
|
AWIDTH => AWIDTH,
|
176 |
|
|
DWIDTH => 32)
|
177 |
|
|
port map (
|
178 |
|
|
CLK => CLK,
|
179 |
|
|
EN => BRAM_EN,
|
180 |
|
|
WE => BRAM_WE,
|
181 |
|
|
ADDR => R_REGS.laddr,
|
182 |
|
|
DI => BRAM1_DI,
|
183 |
|
|
DO => BRAM1_DO
|
184 |
|
|
);
|
185 |
|
|
|
186 |
|
|
BRAM0 : ram_1swsr_wfirst_gen
|
187 |
|
|
generic map (
|
188 |
|
|
AWIDTH => AWIDTH,
|
189 |
|
|
DWIDTH => 32)
|
190 |
|
|
port map (
|
191 |
|
|
CLK => CLK,
|
192 |
|
|
EN => BRAM_EN,
|
193 |
|
|
WE => BRAM_WE,
|
194 |
|
|
ADDR => R_REGS.laddr,
|
195 |
|
|
DI => BRAM0_DI,
|
196 |
|
|
DO => BRAM0_DO
|
197 |
|
|
);
|
198 |
|
|
|
199 |
|
|
proc_regs: process (CLK)
|
200 |
|
|
begin
|
201 |
13 |
wfjm |
if rising_edge(CLK) then
|
202 |
10 |
wfjm |
if RESET = '1' then
|
203 |
|
|
R_REGS <= regs_init;
|
204 |
|
|
else
|
205 |
|
|
R_REGS <= N_REGS;
|
206 |
|
|
end if;
|
207 |
|
|
end if;
|
208 |
|
|
end process proc_regs;
|
209 |
|
|
|
210 |
|
|
proc_next : process (R_REGS, RB_MREQ, RB_SRES_SUM, BRAM0_DO, BRAM1_DO)
|
211 |
|
|
variable r : regs_type := regs_init;
|
212 |
|
|
variable n : regs_type := regs_init;
|
213 |
|
|
variable irb_ack : slbit := '0';
|
214 |
|
|
variable irb_busy : slbit := '0';
|
215 |
|
|
variable irb_err : slbit := '0';
|
216 |
|
|
variable irb_dout : slv16 := (others=>'0');
|
217 |
|
|
variable irbena : slbit := '0';
|
218 |
|
|
variable ibramen : slbit := '0';
|
219 |
|
|
variable ibramwe : slbit := '0';
|
220 |
|
|
variable rbtake : slbit := '0';
|
221 |
|
|
variable laddr_inc : slbit := '0';
|
222 |
|
|
variable idat0 : slv16 := (others=>'0');
|
223 |
|
|
variable idat1 : slv16 := (others=>'0');
|
224 |
|
|
variable idat2 : slv16 := (others=>'0');
|
225 |
|
|
variable idat3 : slv16 := (others=>'0');
|
226 |
|
|
begin
|
227 |
|
|
|
228 |
|
|
r := R_REGS;
|
229 |
|
|
n := R_REGS;
|
230 |
|
|
|
231 |
|
|
irb_ack := '0';
|
232 |
|
|
irb_busy := '0';
|
233 |
|
|
irb_err := '0';
|
234 |
|
|
irb_dout := (others=>'0');
|
235 |
|
|
|
236 |
|
|
irbena := RB_MREQ.re or RB_MREQ.we;
|
237 |
|
|
|
238 |
|
|
ibramen := '0';
|
239 |
|
|
ibramwe := '0';
|
240 |
|
|
|
241 |
|
|
laddr_inc := '0';
|
242 |
|
|
|
243 |
|
|
-- rbus address decoder
|
244 |
|
|
n.rbsel := '0';
|
245 |
|
|
if RB_MREQ.aval='1' and RB_MREQ.addr(7 downto 2)=RB_ADDR(7 downto 2) then
|
246 |
|
|
n.rbsel := '1';
|
247 |
|
|
ibramen := '1';
|
248 |
|
|
end if;
|
249 |
|
|
|
250 |
|
|
-- rbus transactions
|
251 |
|
|
if r.rbsel = '1' then
|
252 |
|
|
|
253 |
|
|
irb_ack := irbena; -- ack all accesses
|
254 |
|
|
|
255 |
|
|
case RB_MREQ.addr(1 downto 0) is
|
256 |
|
|
|
257 |
|
|
when rbaddr_cntl =>
|
258 |
|
|
if RB_MREQ.we = '1' then
|
259 |
|
|
n.go := RB_MREQ.din(cntl_rbf_go);
|
260 |
|
|
if RB_MREQ.din(cntl_rbf_go)='1' then
|
261 |
|
|
n.wrap := '0';
|
262 |
|
|
n.laddr := laddrzero;
|
263 |
|
|
n.waddr := "00";
|
264 |
|
|
end if;
|
265 |
|
|
end if;
|
266 |
|
|
|
267 |
|
|
when rbaddr_alim =>
|
268 |
|
|
if RB_MREQ.we = '1' then
|
269 |
|
|
n.hilim := RB_MREQ.din(alim_rbf_hilim);
|
270 |
|
|
n.lolim := RB_MREQ.din(alim_rbf_lolim);
|
271 |
|
|
end if;
|
272 |
|
|
|
273 |
|
|
when rbaddr_addr =>
|
274 |
|
|
if RB_MREQ.we = '1' then
|
275 |
|
|
n.go := '0';
|
276 |
|
|
n.wrap := '0';
|
277 |
|
|
n.laddr := RB_MREQ.din(addr_rbf_laddr);
|
278 |
|
|
n.waddr := RB_MREQ.din(addr_rbf_waddr);
|
279 |
|
|
end if;
|
280 |
|
|
|
281 |
|
|
when rbaddr_data =>
|
282 |
|
|
if r.go='1' or RB_MREQ.we='1' then
|
283 |
|
|
irb_err := '1';
|
284 |
|
|
end if;
|
285 |
|
|
if RB_MREQ.re = '1' then
|
286 |
13 |
wfjm |
n.waddr := slv(unsigned(r.waddr) + 1);
|
287 |
10 |
wfjm |
if r.waddr = "11" then
|
288 |
|
|
laddr_inc := '1';
|
289 |
|
|
end if;
|
290 |
|
|
end if;
|
291 |
|
|
|
292 |
|
|
when others => null;
|
293 |
|
|
end case;
|
294 |
|
|
end if;
|
295 |
|
|
|
296 |
|
|
-- rbus output driver
|
297 |
|
|
if r.rbsel = '1' then
|
298 |
|
|
case RB_MREQ.addr(1 downto 0) is
|
299 |
|
|
when rbaddr_cntl =>
|
300 |
|
|
irb_dout(cntl_rbf_go) := r.go;
|
301 |
|
|
when rbaddr_alim =>
|
302 |
|
|
irb_dout(alim_rbf_hilim) := r.hilim;
|
303 |
|
|
irb_dout(alim_rbf_lolim) := r.lolim;
|
304 |
|
|
when rbaddr_addr =>
|
305 |
|
|
irb_dout(addr_rbf_wrap) := r.wrap;
|
306 |
|
|
irb_dout(addr_rbf_laddr) := r.laddr;
|
307 |
|
|
irb_dout(addr_rbf_waddr) := r.waddr;
|
308 |
|
|
when rbaddr_data =>
|
309 |
|
|
case r.waddr is
|
310 |
|
|
when "11" => irb_dout := BRAM1_DO(31 downto 16);
|
311 |
|
|
when "10" => irb_dout := BRAM1_DO(15 downto 0);
|
312 |
|
|
when "01" => irb_dout := BRAM0_DO(31 downto 16);
|
313 |
|
|
when "00" => irb_dout := BRAM0_DO(15 downto 0);
|
314 |
|
|
when others => null;
|
315 |
|
|
end case;
|
316 |
|
|
when others => null;
|
317 |
|
|
end case;
|
318 |
|
|
end if;
|
319 |
|
|
|
320 |
|
|
-- rbus monitor
|
321 |
|
|
-- a rbus transaction are captured if the address is in alim window
|
322 |
|
|
-- and the access is not refering to rbd_rbmon itself
|
323 |
|
|
|
324 |
|
|
rbtake := '0';
|
325 |
|
|
if RB_MREQ.aval='1' and irbena='1' then -- aval and (re or we)
|
326 |
|
|
if unsigned(RB_MREQ.addr)>=unsigned(r.lolim) and -- and in addr window
|
327 |
|
|
unsigned(RB_MREQ.addr)<=unsigned(r.hilim) and
|
328 |
|
|
r.rbsel='0' then -- and not self
|
329 |
|
|
rbtake := '1';
|
330 |
|
|
end if;
|
331 |
|
|
end if;
|
332 |
|
|
if RB_MREQ.init = '1' then -- also take init's
|
333 |
|
|
rbtake := '1';
|
334 |
|
|
end if;
|
335 |
|
|
|
336 |
|
|
if rbtake = '1' then -- if capture active
|
337 |
|
|
n.rbaddr := RB_MREQ.addr; -- keep track of some state
|
338 |
|
|
n.rbinit := RB_MREQ.init;
|
339 |
|
|
n.rbwe := RB_MREQ.we;
|
340 |
|
|
if RB_MREQ.init='1' or RB_MREQ.we='1' then -- for write/init of din
|
341 |
|
|
n.rbdata := RB_MREQ.din;
|
342 |
|
|
else -- for read of dout
|
343 |
|
|
n.rbdata := RB_SRES_SUM.dout;
|
344 |
|
|
end if;
|
345 |
|
|
|
346 |
|
|
if r.rbtake_1 = '0' then -- if initial cycle of a transaction
|
347 |
|
|
n.rback := RB_SRES_SUM.ack;
|
348 |
|
|
n.rbbusy := RB_SRES_SUM.busy;
|
349 |
|
|
n.rberr := RB_SRES_SUM.err;
|
350 |
|
|
n.rbnbusy := (others=>'0');
|
351 |
|
|
else -- if non-initial cycles
|
352 |
|
|
if RB_SRES_SUM.err = '1' then -- keep track of err flags
|
353 |
|
|
n.rberr := '1';
|
354 |
|
|
end if;
|
355 |
|
|
if r.rbnbusy /= rbnbusylast then -- and count
|
356 |
13 |
wfjm |
n.rbnbusy := slv(unsigned(r.rbnbusy) + 1);
|
357 |
10 |
wfjm |
end if;
|
358 |
|
|
end if;
|
359 |
|
|
n.rbnak := not RB_SRES_SUM.ack;
|
360 |
|
|
n.rbtout := RB_SRES_SUM.busy;
|
361 |
|
|
|
362 |
|
|
else -- if capture not active
|
363 |
|
|
if r.go='1' and r.rbtake_1='1' then -- active and transaction just ended
|
364 |
|
|
ibramen := '1';
|
365 |
|
|
ibramwe := '1';
|
366 |
|
|
laddr_inc := '1';
|
367 |
|
|
end if;
|
368 |
|
|
if r.rbtake_1 = '1' then -- rbus transaction just ended
|
369 |
|
|
n.rbndly := (others=>'0'); -- clear delay counter
|
370 |
|
|
else -- just idle
|
371 |
|
|
if r.rbndly /= rbndlylast then -- count cycles
|
372 |
13 |
wfjm |
n.rbndly := slv(unsigned(r.rbndly) + 1);
|
373 |
10 |
wfjm |
end if;
|
374 |
|
|
end if;
|
375 |
|
|
end if;
|
376 |
|
|
|
377 |
|
|
if laddr_inc = '1' then
|
378 |
13 |
wfjm |
n.laddr := slv(unsigned(r.laddr) + 1);
|
379 |
10 |
wfjm |
if r.go='1' and r.laddr=laddrlast then
|
380 |
|
|
n.wrap := '1';
|
381 |
|
|
end if;
|
382 |
|
|
end if;
|
383 |
|
|
|
384 |
|
|
idat3 := (others=>'0');
|
385 |
|
|
idat3(dat3_rbf_ack) := r.rback;
|
386 |
|
|
idat3(dat3_rbf_busy) := r.rbbusy;
|
387 |
|
|
idat3(dat3_rbf_err) := r.rberr;
|
388 |
|
|
idat3(dat3_rbf_nak) := r.rbnak;
|
389 |
|
|
idat3(dat3_rbf_tout) := r.rbtout;
|
390 |
|
|
idat3(dat3_rbf_init) := r.rbinit;
|
391 |
|
|
idat3(dat3_rbf_we) := r.rbwe;
|
392 |
|
|
idat3(dat3_rbf_addr) := r.rbaddr;
|
393 |
|
|
idat2 := r.rbdata;
|
394 |
|
|
idat1 := r.rbndly(15 downto 0);
|
395 |
|
|
idat0(dat0_rbf_ndlymsb) := r.rbndly(19 downto 16);
|
396 |
|
|
idat0(dat0_rbf_nbusy) := r.rbnbusy;
|
397 |
|
|
|
398 |
|
|
n.rbtake_1 := rbtake;
|
399 |
|
|
|
400 |
|
|
N_REGS <= n;
|
401 |
|
|
|
402 |
|
|
BRAM_EN <= ibramen;
|
403 |
|
|
BRAM_WE <= ibramwe;
|
404 |
|
|
|
405 |
|
|
BRAM1_DI <= idat3 & idat2;
|
406 |
|
|
BRAM0_DI <= idat1 & idat0;
|
407 |
|
|
|
408 |
|
|
RB_SRES.dout <= irb_dout;
|
409 |
|
|
RB_SRES.ack <= irb_ack;
|
410 |
|
|
RB_SRES.err <= irb_err;
|
411 |
|
|
RB_SRES.busy <= irb_busy;
|
412 |
|
|
|
413 |
|
|
end process proc_next;
|
414 |
|
|
|
415 |
|
|
end syn;
|