w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
tb_tst_serloop.vhd
Go to the documentation of this file.
1-- $Id: tb_tst_serloop.vhd 1181 2019-07-08 17:00:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2011-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: tb_tst_serloop - sim
7-- Description: Generic test bench for sys_tst_serloop_xx
8--
9-- Dependencies: vlib/simlib/simclkcnt
10-- vlib/serport/serport_uart_rxtx_tb
11-- vlib/serport/serport_xontx_tb
12--
13-- To test: sys_tst_serloop_xx
14--
15-- Target Devices: generic
16--
17-- Revision History:
18-- Date Rev Version Comment
19-- 2016-09-03 805 1.2.2 remove CLK_STOP logic (simstop via report)
20-- 2016-08-18 799 1.2.1 remove 'assert false' from report statements
21-- 2016-04-23 764 1.2 use serport/tb/serport_(uart_rxtx|xontx)_tb
22-- use assert to halt simulation
23-- 2011-12-23 444 1.1 use new simclkcnt
24-- 2011-11-13 425 1.0 Initial version
25-- 2011-11-06 420 0.5 First draft
26------------------------------------------------------------------------------
27
28library ieee;
29use ieee.std_logic_1164.all;
30use ieee.numeric_std.all;
31use ieee.std_logic_textio.all;
32use std.textio.all;
33
34use work.slvtypes.all;
35use work.simlib.all;
36use work.simbus.all;
37use work.serportlib_tb.all;
38
40 port (
41 CLKS : in slbit; -- clock for serport
42 CLKH : in slbit; -- clock for humanio
43 P0_RXD : out slbit; -- port 0 receive data (board view)
44 P0_TXD : in slbit; -- port 0 transmit data (board view)
45 P0_RTS_N : in slbit; -- port 0 rts_n
46 P0_CTS_N : out slbit; -- port 0 cts_n
47 P1_RXD : out slbit; -- port 1 receive data (board view)
48 P1_TXD : in slbit; -- port 1 transmit data (board view)
49 P1_RTS_N : in slbit; -- port 1 rts_n
50 P1_CTS_N : out slbit; -- port 1 cts_n
51 SWI : out slv8; -- hio switches
52 BTN : out slv4 -- hio buttons
53 );
55
56architecture sim of tb_tst_serloop is
57
58 signal CLK_CYCLE : integer := 0;
59
60 signal UART_RESET : slbit := '0';
61 signal UART_RXD : slbit := '1';
62 signal UART_TXD : slbit := '1';
63 signal CTS_N : slbit := '0';
64 signal RTS_N : slbit := '0';
65
66 signal CLKDIV : slv13 := (others=>'0');
67 signal RXDATA : slv8 := (others=>'0');
68 signal RXVAL : slbit := '0';
69 signal RXERR : slbit := '0';
70 signal RXACT : slbit := '0';
71 signal TXDATA : slv8 := (others=>'0');
72 signal TXENA : slbit := '0';
73 signal TXBUSY : slbit := '0';
74
75 signal UART_TXDATA : slv8 := (others=>'0');
76 signal UART_TXENA : slbit := '0';
77 signal UART_TXBUSY : slbit := '0';
78
79 signal ACTPORT : slbit := '0';
80 signal BREAK : slbit := '0';
81
82 signal CTS_CYCLE : integer := 0;
83 signal CTS_FRACT : integer := 0;
84 signal XON_CYCLE : integer := 0;
85 signal XON_FRACT : integer := 0;
86
87 signal S2M_ACTIVE : slbit := '0';
88 signal S2M_SIZE : integer := 0;
89 signal S2M_ENAESC : slbit := '0';
90 signal S2M_ENAXON : slbit := '0';
91
92 signal M2S_XONSEEN : slbit := '0';
93 signal M2S_XOFFSEEN : slbit := '0';
94
95 signal R_XONRXOK : slbit := '1';
96 signal R_XONTXOK : slbit := '1';
97
98begin
99
100 CLKCNT : simclkcnt port map (CLK => CLKS, CLK_CYCLE => CLK_CYCLE);
101
102 UART : entity work.serport_uart_rxtx_tb
103 generic map (
104 CDWIDTH => 13)
105 port map (
106 CLK => CLKS,
107 RESET => UART_RESET,
108 CLKDIV => CLKDIV,
109 RXSD => UART_RXD,
110 RXDATA => RXDATA,
111 RXVAL => RXVAL,
112 RXERR => RXERR,
113 RXACT => RXACT,
114 TXSD => UART_TXD,
116 TXENA => UART_TXENA,
118 );
119
120 XONTX : entity work.serport_xontx_tb
121 port map (
122 CLK => CLKS,
123 RESET => UART_RESET,
129 TXDATA => TXDATA,
130 TXENA => TXENA,
131 TXBUSY => TXBUSY,
132 RXOK => R_XONRXOK,
133 TXOK => R_XONTXOK
134 );
135
136 proc_port_mux: process (ACTPORT, BREAK, UART_TXD, CTS_N,
138 variable eff_txd : slbit := '0';
139 begin
140
141 if BREAK = '0' then -- if no break active
142 eff_txd := UART_TXD; -- send uart
143 else -- otherwise
144 eff_txd := '0'; -- force '0'
145 end if;
146
147 if ACTPORT = '0' then -- use port 0
148 P0_RXD <= eff_txd; -- write port 0 inputs
149 P0_CTS_N <= CTS_N;
150 UART_RXD <= P0_TXD; -- get port 0 outputs
151 RTS_N <= P0_RTS_N;
152 P1_RXD <= '1'; -- port 1 inputs to idle state
153 P1_CTS_N <= '0';
154 else -- use port 1
155 P1_RXD <= eff_txd; -- write port 1 inputs
156 P1_CTS_N <= CTS_N;
157 UART_RXD <= P1_TXD; -- get port 1 outputs
158 RTS_N <= P1_RTS_N;
159 P0_RXD <= '1'; -- port 0 inputs to idle state
160 P0_CTS_N <= '0';
161 end if;
162 end process proc_port_mux;
163
164 proc_cts: process(CLKS)
165 variable cts_timer : integer := 0;
166 begin
167
168 if rising_edge(CLKS) then
169 if CTS_CYCLE = 0 then -- if cts throttle off
170 CTS_N <= '0'; -- cts permanently asserted
171
172 else -- otherwise determine throttling
173
174 if cts_timer>0 and cts_timer<CTS_CYCLE then -- unless beyond ends
175 cts_timer := cts_timer - 1; -- decrement
176 else
177 cts_timer := CTS_CYCLE-1; -- otherwise reload
178 end if;
179
180 if cts_timer < cts_fract then -- if in lower 'fract' counts
181 CTS_N <= '1'; -- throttle: deassert CTS
182 else -- otherwise
183 CTS_N <= '0'; -- let go: assert CTS
184 end if;
185
186 end if;
187 end if;
188
189 end process proc_cts;
190
191 proc_xonrxok: process(CLKS)
192 variable xon_timer : integer := 0;
193 begin
194 if rising_edge(CLKS) then
195 if XON_CYCLE = 0 then -- if xon throttle off
196 R_XONRXOK <= '1'; -- xonrxok permanently asserted
197
198 else -- otherwise determine throttling
199
200 if xon_timer>0 and xon_timer<XON_CYCLE then -- unless beyond ends
201 xon_timer := xon_timer - 1; -- decrement
202 else
203 xon_timer := XON_CYCLE-1; -- otherwise reload
204 end if;
205
206 if xon_timer < xon_fract then -- if in lower 'fract' counts
207 R_XONRXOK <= '0'; -- throttle: deassert xonrxok
208 else -- otherwise
209 R_XONRXOK <= '1'; -- let go: assert xonrxok
210 end if;
211
212 end if;
213 end if;
214 end process proc_xonrxok;
215
216 proc_xontxok: process(CLKS)
217 begin
218 if rising_edge(CLKS) then
219 if M2S_XONSEEN = '1' then
220 R_XONTXOK <= '1';
221 elsif M2S_XOFFSEEN = '1' then
222 R_XONTXOK <= '0';
223 end if;
224 end if;
225 end process proc_xontxok;
226
227 proc_stim: process
228 file fstim : text open read_mode is "tb_tst_serloop_stim";
229 variable iline : line;
230 variable oline : line;
231 variable idelta : integer := 0;
232 variable iactport : slbit := '0';
233 variable iswi : slv8 := (others=>'0');
234 variable btn_num : integer := 0;
235 variable i_cycle : integer := 0;
236 variable i_fract : integer := 0;
237 variable nbyte : integer := 0;
238 variable enaesc : slbit := '0';
239 variable enaxon : slbit := '0';
240 variable bcnt : integer := 0;
241 variable itxdata : slv8 := (others=>'0');
242 variable ok : boolean;
243 variable dname : string(1 to 6) := (others=>' ');
244
245 procedure waitclk(ncyc : in integer) is
246 begin
247 for i in 1 to ncyc loop
248 wait until rising_edge(CLKS);
249 end loop; -- i
250 end procedure waitclk;
251
252 begin
253
254 -- initialize some top level out signals
255 SWI <= (others=>'0');
256 BTN <= (others=>'0');
257
258 wait until rising_edge(CLKS);
259
260 file_loop: while not endfile(fstim) loop
261
262 readline (fstim, iline);
263
264 readcomment(iline, ok);
265 next file_loop when ok;
266
267 readword(iline, dname, ok);
268 if ok then
269 case dname is
270 when "wait " => -- wait
271 read_ea(iline, idelta);
272 writetimestamp(oline, CLK_CYCLE, ": wait ");
273 write(oline, idelta, right, 5);
274 writeline(output, oline);
275 waitclk(idelta);
276
277 when "port " => -- switch rs232 port
278 read_ea(iline, iactport);
279 ACTPORT <= iactport;
280 writetimestamp(oline, CLK_CYCLE, ": port ");
281 write(oline, iactport, right, 5);
282 writeline(output, oline);
283
284 when "cts " => -- setup cts throttling
285 read_ea(iline, i_cycle);
286 read_ea(iline, i_fract);
287 CTS_CYCLE <= i_cycle;
288 CTS_FRACT <= i_fract;
289 writetimestamp(oline, CLK_CYCLE, ": cts ");
290 write(oline, i_cycle, right, 5);
291 write(oline, i_fract, right, 5);
292 writeline(output, oline);
293
294 when "xon " => -- setup xon throttling
295 read_ea(iline, i_cycle);
296 read_ea(iline, i_fract);
297 XON_CYCLE <= i_cycle;
298 XON_FRACT <= i_fract;
299 writetimestamp(oline, CLK_CYCLE, ": cts ");
300 write(oline, i_cycle, right, 5);
301 write(oline, i_fract, right, 5);
302 writeline(output, oline);
303
304 when "swi " => -- new SWI settings
305 read_ea(iline, iswi);
306 read_ea(iline, idelta);
307 writetimestamp(oline, CLK_CYCLE, ": swi ");
308 write(oline, iswi, right, 10);
309 write(oline, idelta, right, 5);
310 writeline(output, oline);
311 wait until rising_edge(CLKH);
312 SWI <= iswi;
313 wait until rising_edge(CLKS);
314 waitclk(idelta);
315
316 when "btn " => -- BTN push (3 cyc down + 3 cyc wait)
317 read_ea(iline, btn_num);
318 read_ea(iline, idelta);
319 if btn_num>=0 and btn_num<=3 then
320 writetimestamp(oline, CLK_CYCLE, ": btn ");
321 write(oline, btn_num, right, 5);
322 write(oline, idelta, right, 5);
323 writeline(output, oline);
324 wait until rising_edge(CLKH);
325 BTN(btn_num) <= '1'; -- 3 cycle BTN pulse
326 wait until rising_edge(CLKH);
327 wait until rising_edge(CLKH);
328 wait until rising_edge(CLKH);
329 BTN(btn_num) <= '0';
330 wait until rising_edge(CLKH);
331 wait until rising_edge(CLKH);
332 wait until rising_edge(CLKH);
333 wait until rising_edge(CLKS);
334 waitclk(idelta);
335 else
336 write(oline, string'("!! btn: btn number out of range"));
337 writeline(output, oline);
338 end if;
339
340 when "expect" => -- expect n bytes data
341 read_ea(iline, nbyte);
342 read_ea(iline, enaesc);
343 read_ea(iline, enaxon);
344 writetimestamp(oline, CLK_CYCLE, ": expect");
345 write(oline, nbyte, right, 5);
346 write(oline, enaesc, right, 3);
347 write(oline, enaxon, right, 3);
348 writeline(output, oline);
349
350 if nbyte > 0 then
351 S2M_ACTIVE <= '1';
352 S2M_SIZE <= nbyte;
353 else
354 S2M_ACTIVE <= '0';
355 end if;
356 S2M_ENAESC <= enaesc;
357 S2M_ENAXON <= enaxon;
358 wait until rising_edge(CLKS);
359
360 when "send " => -- send n bytes data
361 read_ea(iline, nbyte);
362 read_ea(iline, enaesc);
363 read_ea(iline, enaxon);
364 writetimestamp(oline, CLK_CYCLE, ": send ");
365 write(oline, nbyte, right, 5);
366 write(oline, enaesc, right, 3);
367 write(oline, enaxon, right, 3);
368 writeline(output, oline);
369 bcnt := 0;
370 itxdata := (others=>'0');
371
372 wait until falling_edge(CLKS);
373 while bcnt < nbyte loop
374 while TXBUSY='1' or RTS_N='1' loop
375 wait until falling_edge(CLKS);
376 end loop;
377
378 TXDATA <= itxdata;
379 itxdata := slv(unsigned(itxdata) + 1);
380 bcnt := bcnt + 1;
381
382 TXENA <= '1';
383 wait until falling_edge(CLKS);
384 TXENA <= '0';
385 wait until falling_edge(CLKS);
386 end loop;
387 while TXBUSY='1' or RTS_N='1' loop -- wait till last char send...
388 wait until falling_edge(CLKS);
389 end loop;
390 wait until rising_edge(CLKS);
391
392 when "break " => -- send a break for n cycles
393 read_ea(iline, idelta);
394 writetimestamp(oline, CLK_CYCLE, ": break ");
395 write(oline, idelta, right, 5);
396 writeline(output, oline);
397 -- send break for n cycles
398 BREAK <= '1';
399 waitclk(idelta);
400 BREAK <= '0';
401 -- wait for 3 bit cell width
402 waitclk(3*to_integer(unsigned(CLKDIV)+1));
403 -- send 'sync' character
404 wait until falling_edge(CLKS);
405 TXDATA <= "10000000";
406 TXENA <= '1';
407 wait until falling_edge(CLKS);
408 TXENA <= '0';
409 wait until rising_edge(CLKS);
410
411 when "clkdiv" => -- set new clock divider
412 read_ea(iline, idelta);
413 writetimestamp(oline, CLK_CYCLE, ": clkdiv");
414 write(oline, idelta, right, 5);
415 writeline(output, oline);
416 CLKDIV <= slv(to_unsigned(idelta, CLKDIV'length));
417 UART_RESET <= '1';
418 wait until rising_edge(CLKS);
419 UART_RESET <= '0';
420
421 when others => -- unknown command
422 write(oline, string'("?? unknown command: "));
423 write(oline, dname);
424 writeline(output, oline);
425 report "aborting" severity failure;
426 end case;
427
428 else
429 report "failed to find command" severity failure;
430
431 end if;
432
433 testempty_ea(iline);
434 end loop; -- file_loop
435
436 -- extra wait for at least two character times (20 bit times)
437 -- to allow tx and rx of the last character
438 waitclk(20*(to_integer(unsigned(CLKDIV))+1));
439
440 writetimestamp(oline, CLK_CYCLE, ": DONE ");
441 writeline(output, oline);
442
443 SB_SIMSTOP <= '1'; -- signal simulation stop
444 wait for 100 ns; -- monitor grace time
445 report "Simulation Finished" severity failure; -- end simulation
446
447 end process proc_stim;
448
449 proc_moni: process
450 variable oline : line;
451 variable dclk : integer := 0;
452 variable active_1 : slbit := '0';
453 variable irxdata : slv8 := (others=>'0');
454 variable irxeff : slv8 := (others=>'0');
455 variable irxval : slbit := '0';
456 variable doesc : slbit := '0';
457 variable bcnt : integer := 0;
458 variable xseen : slbit := '0';
459 begin
460
461 loop
462 wait until falling_edge(CLKS);
463
464 M2S_XONSEEN <= '0';
465 M2S_XOFFSEEN <= '0';
466
467 if S2M_ACTIVE='1' and active_1='0' then -- start expect message
468 irxdata := (others=>'0');
469 bcnt := 0;
470 end if;
471
472 if S2M_ACTIVE='0' and active_1='1' then -- end expect message
473 if bcnt = S2M_SIZE then
474 writetimestamp(oline, CLK_CYCLE, ": OK: message seen");
475 else
476 writetimestamp(oline, CLK_CYCLE, ": FAIL: missing chars, seen=");
477 write(oline, bcnt, right, 5);
478 write(oline, string'(" expect="));
479 write(oline, S2M_SIZE, right, 5);
480 end if;
481 writeline(output, oline);
482 end if;
483
484 active_1 := S2M_ACTIVE;
485
486 if RXVAL = '1' then
487 writetimestamp(oline, CLK_CYCLE, ": char: ");
488 write(oline, RXDATA, right, 10);
489 write(oline, string'(" ("));
490 writeoct(oline, RXDATA, right, 3);
491 write(oline, string'(") dt="));
492 write(oline, dclk, right, 4);
493
494 irxeff := RXDATA;
495 irxval := '1';
496 if doesc = '1' then
497 irxeff := not RXDATA;
498 irxval := '1';
499 doesc := '0';
500 write(oline, string'(" eff="));
501 write(oline, irxeff, right, 10);
502 write(oline, string'(" ("));
503 writeoct(oline, irxeff, right, 3);
504 write(oline, string'(")"));
505 elsif S2M_ENAESC='1' and RXDATA=c_serport_xesc then
506 doesc := '1';
507 irxval := '0';
508 write(oline, string'(" XESC seen"));
509 end if;
510
511 xseen := '0';
512 if S2M_ENAXON = '1' then
513 if RXDATA = c_serport_xon then
514 write(oline, string'(" XON seen"));
515 M2S_XONSEEN <= '1';
516 xseen := '1';
517 elsif RXDATA = c_serport_xoff then
518 write(oline, string'(" XOFF seen"));
519 M2S_XOFFSEEN <= '1';
520 xseen := '1';
521 end if;
522 end if;
523
524 if S2M_ACTIVE='1' and irxval='1' and xseen='0' then
525 if irxeff = irxdata then
526 write(oline, string'(" OK"));
527 else
528 write(oline, string'(" FAIL: expect="));
529 write(oline, irxdata, right, 10);
530 end if;
531 irxdata := slv(unsigned(irxdata) + 1);
532 bcnt := bcnt + 1;
533 end if;
534
535 writeline(output, oline);
536 dclk := 0;
537
538 end if;
539
540 if RXERR = '1' then
541 writetimestamp(oline, CLK_CYCLE, ": FAIL: RXERR='1'");
542 writeline(output, oline);
543 end if;
544
545 dclk := dclk + 1;
546
547 end loop;
548
549 end process proc_moni;
550
551end sim;
in CLKDIV slv( CDWIDTH- 1 downto 0)
out CLK_CYCLE integer
Definition: simclkcnt.vhd:29
in CLK slbit
Definition: simclkcnt.vhd:27
std_logic_vector( 12 downto 0) slv13
Definition: slvtypes.vhd:45
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector( 7 downto 0) slv8
Definition: slvtypes.vhd:40
std_logic_vector slv
Definition: slvtypes.vhd:31
slbit := '0' BREAK
slbit := '0' RXERR
slv8 :=( others => '0') UART_TXDATA
integer := 0 CTS_FRACT
integer := 0 XON_FRACT
slbit := '0' S2M_ENAESC
integer := 0 CTS_CYCLE
slbit := '0' S2M_ACTIVE
slbit := '0' S2M_ENAXON
slbit := '1' R_XONTXOK
slbit := '1' UART_RXD
slbit := '0' TXENA
integer := 0 XON_CYCLE
slv8 :=( others => '0') RXDATA
slbit := '1' UART_TXD
slbit := '0' ACTPORT
slbit := '1' R_XONRXOK
slbit := '0' UART_RESET
slbit := '0' RXACT
slbit := '0' RXVAL
slbit := '0' CTS_N
slbit := '0' UART_TXENA
integer := 0 CLK_CYCLE
slv13 :=( others => '0') CLKDIV
slbit := '0' RTS_N
slbit := '0' M2S_XONSEEN
slbit := '0' TXBUSY
slbit := '0' UART_TXBUSY
slv8 :=( others => '0') TXDATA
slbit := '0' M2S_XOFFSEEN
integer := 0 S2M_SIZE
out P0_RXD slbit
in P1_RTS_N slbit
in P1_TXD slbit
in P0_TXD slbit
out P0_CTS_N slbit
out P1_RXD slbit
in P0_RTS_N slbit
out P1_CTS_N slbit