Library of reusable VHDL components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

851 lines
29 KiB

  1. --
  2. -- File Name: TbUtilPkg.vhd
  3. -- Design Unit Name: TbUtilPkg
  4. -- Revision: STANDARD VERSION
  5. --
  6. -- Maintainer: Jim Lewis email: jim@SynthWorks.com
  7. -- Contributor(s):
  8. -- Jim Lewis email: jim@SynthWorks.com
  9. --
  10. -- Package Defines
  11. --
  12. -- Developed for:
  13. -- SynthWorks Design Inc.
  14. -- VHDL Training Classes
  15. -- 11898 SW 128th Ave. Tigard, Or 97223
  16. -- http://www.SynthWorks.com
  17. --
  18. -- Revision History:
  19. -- Date Version Description
  20. -- 11/1999: 0.1 Initial revision
  21. -- Numerous revisions for VHDL Testbenches and Verification
  22. -- 10/2013 2013.10 Split out Text Utilities
  23. -- 11/2016 2016.11 First Public Release Version
  24. -- Updated naming for consistency.
  25. --
  26. --
  27. -- Copyright (c) 1999 - 2016 by SynthWorks Design Inc. All rights reserved.
  28. --
  29. -- Verbatim copies of this source file may be used and
  30. -- distributed without restriction.
  31. --
  32. -- This source file is free software; you can redistribute it
  33. -- and/or modify it under the terms of the ARTISTIC License
  34. -- as published by The Perl Foundation; either version 2.0 of
  35. -- the License, or (at your option) any later version.
  36. --
  37. -- This source is distributed in the hope that it will be
  38. -- useful, but WITHOUT ANY WARRANTY; without even the implied
  39. -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  40. -- PURPOSE. See the Artistic License for details.
  41. --
  42. -- You should have received a copy of the license with this source.
  43. -- If not download it from,
  44. -- http://www.perlfoundation.org/artistic_license_2_0
  45. --
  46. library ieee ;
  47. use ieee.std_logic_1164.all ;
  48. library osvvm ;
  49. use osvvm.AlertLogPkg.all ;
  50. use osvvm.TranscriptPkg.all ;
  51. package TbUtilPkg is
  52. constant CLK_ACTIVE : std_logic := '1' ;
  53. constant t_sim_resolution : time := std.env.resolution_limit ; -- VHDL-2008
  54. -- constant t_sim_resolution : time := 1 ns ; -- for non VHDL-2008 simulators
  55. ------------------------------------------------------------
  56. -- ZeroOneHot, OneHot
  57. -- OneHot: return true if exactly one value is 1
  58. -- ZeroOneHot: return false when more than one value is a 1
  59. ------------------------------------------------------------
  60. function OneHot ( constant A : in std_logic_vector ) return boolean ;
  61. function ZeroOneHot ( constant A : in std_logic_vector ) return boolean ;
  62. ------------------------------------------------------------
  63. -- RequestTransaction
  64. -- Transaction initiation side of handshaking
  65. -- Pairs with WaitForTransaction or one of its variations
  66. ------------------------------------------------------------
  67. procedure RequestTransaction (
  68. signal Rdy : Out std_logic ;
  69. signal Ack : In std_logic
  70. ) ;
  71. ------------------------------------------------------------
  72. -- WaitForTransaction
  73. -- Model side of handshaking
  74. -- Pairs with RequestTransaction
  75. ------------------------------------------------------------
  76. procedure WaitForTransaction (
  77. signal Clk : In std_logic ;
  78. signal Rdy : In std_logic ;
  79. signal Ack : Out std_logic
  80. ) ;
  81. -- Variation for model that stops waiting when TimeOut is asserted
  82. -- Intended for models that need to switch between instruction streams
  83. -- such as a CPU when interrupt is pending
  84. procedure WaitForTransaction (
  85. signal Clk : In std_logic ;
  86. signal Rdy : In std_logic ;
  87. signal Ack : Out std_logic ;
  88. signal TimeOut : In std_logic ;
  89. constant Polarity : In std_logic := '1'
  90. ) ;
  91. -- Set Ack to Model starting value
  92. procedure StartTransaction ( signal Ack : Out std_logic ) ;
  93. -- Set Ack to Model finishing value
  94. procedure FinishTransaction ( signal Ack : Out std_logic ) ;
  95. -- If a transaction is pending, return true
  96. function TransactionPending ( signal Rdy : In std_logic ) return boolean ;
  97. -- Variation for clockless models
  98. procedure WaitForTransaction (
  99. signal Rdy : In std_logic ;
  100. signal Ack : Out std_logic
  101. ) ;
  102. ------------------------------------------------------------
  103. -- Toggle, WaitForToggle
  104. -- Used for communicating between processes
  105. ------------------------------------------------------------
  106. procedure Toggle (
  107. signal Sig : InOut std_logic ;
  108. constant DelayVal : time
  109. ) ;
  110. procedure Toggle ( signal Sig : InOut std_logic ) ;
  111. procedure ToggleHS ( signal Sig : InOut std_logic ) ;
  112. function IsToggle ( signal Sig : In std_logic ) return boolean ;
  113. procedure WaitForToggle ( signal Sig : In std_logic ) ;
  114. -- Bit type versions
  115. procedure Toggle ( signal Sig : InOut bit ; constant DelayVal : time ) ;
  116. procedure Toggle ( signal Sig : InOut bit ) ;
  117. procedure ToggleHS ( signal Sig : InOut bit ) ;
  118. function IsToggle ( signal Sig : In bit ) return boolean ;
  119. procedure WaitForToggle ( signal Sig : In bit ) ;
  120. ------------------------------------------------------------
  121. -- WaitForBarrier
  122. -- Barrier Synchronization
  123. -- Multiple processes call it, it finishes when all have called it
  124. ------------------------------------------------------------
  125. procedure WaitForBarrier ( signal Sig : InOut std_logic ) ;
  126. procedure WaitForBarrier ( signal Sig : InOut std_logic ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') ;
  127. procedure WaitForBarrier ( signal Sig : InOut std_logic ; constant TimeOut : time ) ;
  128. -- resolved_barrier : summing resolution used in conjunction with integer based barriers
  129. function resolved_barrier ( s : integer_vector ) return integer ;
  130. subtype integer_barrier is resolved_barrier integer ;
  131. -- Usage of integer barriers requires resolved_barrier. Initialization to 1 recommended, but not required
  132. -- signal barrier1 : resolved_barrier integer := 1 ; -- using the resolution function
  133. -- signal barrier2 : integer_barrier := 1 ; -- using the subtype that already applies the resolution function
  134. procedure WaitForBarrier ( signal Sig : InOut integer ) ;
  135. procedure WaitForBarrier ( signal Sig : InOut integer ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') ;
  136. procedure WaitForBarrier ( signal Sig : InOut integer ; constant TimeOut : time ) ;
  137. -- Using separate signals
  138. procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncIn : in std_logic ) ;
  139. procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncInV : in std_logic_vector ) ;
  140. ------------------------------------------------------------
  141. -- WaitForClock
  142. -- Sync to Clock - after a delay, after a number of clocks
  143. ------------------------------------------------------------
  144. procedure WaitForClock ( signal Clk : in std_logic ; constant Delay : in time ) ;
  145. procedure WaitForClock ( signal Clk : in std_logic ; constant NumberOfClocks : in integer := 1) ;
  146. procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in boolean ) ;
  147. procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in std_logic ; constant Polarity : std_logic := '1' ) ;
  148. ------------------------------------------------------------
  149. -- WaitForLevel
  150. -- Find a signal at a level
  151. ------------------------------------------------------------
  152. procedure WaitForLevel ( signal A : in boolean ) ;
  153. procedure WaitForLevel ( signal A : in std_logic ; Polarity : std_logic := '1' ) ;
  154. ------------------------------------------------------------
  155. -- CreateClock, CreateReset
  156. -- Note these do not exit
  157. ------------------------------------------------------------
  158. procedure CreateClock (
  159. signal Clk : inout std_logic ;
  160. constant Period : time ;
  161. constant DutyCycle : real := 0.5
  162. ) ;
  163. procedure CheckClockPeriod (
  164. constant AlertLogID : AlertLogIDType ;
  165. signal Clk : in std_logic ;
  166. constant Period : time ;
  167. constant ClkName : string := "Clock" ;
  168. constant HowMany : integer := 5
  169. ) ;
  170. procedure CheckClockPeriod (
  171. signal Clk : in std_logic ;
  172. constant Period : time ;
  173. constant ClkName : string := "Clock" ;
  174. constant HowMany : integer := 5
  175. ) ;
  176. procedure CreateReset (
  177. signal Reset : out std_logic ;
  178. constant ResetActive : in std_logic ;
  179. signal Clk : in std_logic ;
  180. constant Period : time ;
  181. constant tpd : time
  182. ) ;
  183. procedure LogReset (
  184. constant AlertLogID : AlertLogIDType ;
  185. signal Reset : in std_logic ;
  186. constant ResetActive : in std_logic ;
  187. constant ResetName : in string := "Reset" ;
  188. constant LogLevel : in LogType := ALWAYS
  189. ) ;
  190. procedure LogReset (
  191. signal Reset : in std_logic ;
  192. constant ResetActive : in std_logic ;
  193. constant ResetName : in string := "Reset" ;
  194. constant LogLevel : in LogType := ALWAYS
  195. ) ;
  196. ------------------------------------------------------------
  197. -- Deprecated subprogram names
  198. -- Maintaining backward compatibility using aliases
  199. ------------------------------------------------------------
  200. -- History of RequestTransaction / WaitForTransaction
  201. alias RequestAction is RequestTransaction [std_logic, std_logic] ;
  202. alias WaitForRequest is WaitForTransaction [std_logic, std_logic, std_logic] ;
  203. -- History of WaitForToggle
  204. alias WaitOnToggle is WaitForToggle [std_logic] ;
  205. -- History of WaitForBarrier
  206. alias WayPointBlock is WaitForBarrier [std_logic] ;
  207. alias SyncTo is WaitForBarrier2[std_logic, std_logic] ;
  208. alias SyncTo is WaitForBarrier2[std_logic, std_logic_vector] ;
  209. -- Backward compatible name
  210. alias SyncToClk is WaitForClock [std_logic, time] ;
  211. ------------------------------------------------------------
  212. -- Deprecated
  213. -- subsumed by WaitForTransaction with Ack and TimeOut.
  214. -- TimeOut works exactly like IntReq
  215. ------------------------------------------------------------
  216. procedure WaitForTransactionOrIrq (
  217. signal Clk : In std_logic ;
  218. signal Rdy : In std_logic ;
  219. signal IntReq : In std_logic
  220. ) ;
  221. ------------------------------------------------------------
  222. -- Deprecated
  223. -- WaitForAck, StrobeAck
  224. -- Replaced by WaitForToggle and Toggle
  225. ------------------------------------------------------------
  226. procedure WaitForAck ( signal Ack : In std_logic ) ;
  227. procedure StrobeAck ( signal Ack : Out std_logic ) ;
  228. end TbUtilPkg ;
  229. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  230. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  231. package body TbUtilPkg is
  232. ------------------------------------------------------------
  233. -- ZeroOneHot, OneHot
  234. -- OneHot: return true if exactly one value is 1
  235. -- ZeroOneHot: return false when more than one value is a 1
  236. ------------------------------------------------------------
  237. function OneHot ( constant A : in std_logic_vector ) return boolean is
  238. variable found_one : boolean := FALSE ;
  239. begin
  240. for i in A'range loop
  241. if A(i) = '1' or A(i) = 'H' then
  242. if found_one then
  243. return FALSE ;
  244. end if ;
  245. found_one := TRUE ;
  246. end if ;
  247. end loop ;
  248. return found_one ; -- found a one
  249. end function OneHot ;
  250. function ZeroOneHot ( constant A : in std_logic_vector ) return boolean is
  251. variable found_one : boolean := FALSE ;
  252. begin
  253. for i in A'range loop
  254. if A(i) = '1' or A(i) = 'H' then
  255. if found_one then
  256. return FALSE ;
  257. end if ;
  258. found_one := TRUE ;
  259. end if ;
  260. end loop ;
  261. return TRUE ; -- all zero or found a one
  262. end function ZeroOneHot ;
  263. ------------------------------------------------------------
  264. -- RequestTransaction
  265. -- Transaction initiation side of handshaking
  266. -- Pairs with WaitForTransaction or one of its variations
  267. ------------------------------------------------------------
  268. procedure RequestTransaction (
  269. signal Rdy : Out std_logic ;
  270. signal Ack : In std_logic
  271. ) is
  272. begin
  273. -- Record contains new transaction
  274. Rdy <= '1' ;
  275. -- Find Ack low = '0'
  276. wait until Ack = '0' ;
  277. -- Prepare for Next Transaction
  278. Rdy <= '0' ;
  279. -- Transaction Done
  280. wait until Ack = '1' ;
  281. end procedure ;
  282. ------------------------------------------------------------
  283. -- WaitForTransaction
  284. -- Model side of handshaking
  285. -- Pairs with RequestTransaction
  286. ------------------------------------------------------------
  287. procedure WaitForTransaction (
  288. signal Clk : In std_logic ;
  289. signal Rdy : In std_logic ;
  290. signal Ack : Out std_logic
  291. ) is
  292. variable AckTime : time ;
  293. begin
  294. -- End of Previous Cycle. Signal Done
  295. Ack <= '1' ; -- #6
  296. AckTime := NOW ;
  297. -- Find Start of Transaction
  298. if Rdy /= '1' then -- #2
  299. wait until Rdy = '1' ;
  300. else
  301. wait for 0 ns ; -- allow Ack to update
  302. end if ;
  303. -- align to clock if needed (not back-to-back transactions)
  304. if NOW /= AckTime then
  305. wait until Clk = CLK_ACTIVE ;
  306. end if ;
  307. -- Model active and owns the record
  308. Ack <= '0' ; -- #3
  309. end procedure ;
  310. -- Variation for model that stops waiting when TimeOut is asserted
  311. -- Intended for models that need to switch between instruction streams
  312. -- such as a CPU when interrupt is pending
  313. procedure WaitForTransaction (
  314. signal Clk : In std_logic ;
  315. signal Rdy : In std_logic ;
  316. signal Ack : Out std_logic ;
  317. signal TimeOut : In std_logic ;
  318. constant Polarity : In std_logic := '1'
  319. ) is
  320. variable AckTime : time ;
  321. variable FoundRdy : boolean ;
  322. begin
  323. -- End of Previous Cycle. Signal Done
  324. Ack <= '1' ; -- #6
  325. AckTime := NOW ;
  326. -- Find Ready or Time out
  327. if (Rdy /= '1' and TimeOut /= Polarity) then
  328. wait until Rdy = '1' or TimeOut = Polarity ;
  329. else
  330. wait for 0 ns ; -- allow Ack to update
  331. end if ;
  332. FoundRdy := Rdy = '1' ;
  333. -- align to clock if Rdy or TimeOut does not happen within delta cycles from Ack
  334. if NOW /= AckTime then
  335. wait until Clk = CLK_ACTIVE ;
  336. end if ;
  337. if FoundRdy then
  338. -- Model active and owns the record
  339. Ack <= '0' ; -- #3
  340. end if ;
  341. end procedure ;
  342. -- Set Ack to Model starting value
  343. -- Pairs with WaitForTransactionOrIrq above
  344. procedure StartTransaction ( signal Ack : Out std_logic ) is
  345. begin
  346. Ack <= '0' ;
  347. end procedure ;
  348. -- Set Ack to Model finishing value
  349. -- Pairs with WaitForTransactionOrIrq above
  350. procedure FinishTransaction ( signal Ack : Out std_logic ) is
  351. begin
  352. -- End of Cycle
  353. Ack <= '1' ;
  354. end procedure ;
  355. -- If a transaction is pending, return true
  356. -- Used to detect presence of transaction stream,
  357. -- such as an interrupt handler
  358. function TransactionPending (
  359. signal Rdy : In std_logic
  360. ) return boolean is
  361. begin
  362. return Rdy = '1' ;
  363. end function ;
  364. -- Variation for clockless models
  365. procedure WaitForTransaction (
  366. signal Rdy : In std_logic ;
  367. signal Ack : Out std_logic
  368. ) is
  369. variable AckTime : time ;
  370. begin
  371. -- End of Previous Cycle. Signal Done
  372. Ack <= '1' ; -- #6
  373. -- Find Start of Transaction
  374. if Rdy /= '1' then -- #2
  375. wait until Rdy = '1' ;
  376. else
  377. wait for 0 ns ; -- allow Ack to update
  378. end if ;
  379. -- Model active and owns the record
  380. Ack <= '0' ; -- #3
  381. end procedure ;
  382. ------------------------------------------------------------
  383. -- Toggle, WaitForToggle
  384. -- Used for communicating between processes
  385. ------------------------------------------------------------
  386. type stdulogic_indexby_stdulogic is array (std_ulogic) of std_ulogic;
  387. constant toggle_sl_table : stdulogic_indexby_stdulogic := (
  388. '0' => '1',
  389. 'L' => '1',
  390. others => '0'
  391. );
  392. procedure Toggle (
  393. signal Sig : InOut std_logic ;
  394. constant DelayVal : time
  395. ) is
  396. variable iDelayVal : time ;
  397. begin
  398. iDelayVal := DelayVal ;
  399. if iDelayVal > t_sim_resolution then
  400. iDelayVal := iDelayVal - t_sim_resolution ;
  401. end if ;
  402. Sig <= toggle_sl_table(Sig) after iDelayVal ;
  403. end procedure ;
  404. procedure Toggle ( signal Sig : InOut std_logic ) is
  405. begin
  406. Sig <= toggle_sl_table(Sig) ;
  407. end procedure ;
  408. procedure ToggleHS ( signal Sig : InOut std_logic ) is
  409. begin
  410. Sig <= toggle_sl_table(Sig) ;
  411. wait for 0 ns ; -- Sig toggles
  412. wait for 0 ns ; -- new values updated into record
  413. end procedure ;
  414. function IsToggle ( signal Sig : In std_logic ) return boolean is
  415. begin
  416. return Sig'event ;
  417. end function ;
  418. procedure WaitForToggle ( signal Sig : In std_logic ) is
  419. begin
  420. wait on Sig ;
  421. end procedure ;
  422. -- Bit type versions
  423. procedure Toggle ( signal Sig : InOut bit ; constant DelayVal : time ) is
  424. variable iDelayVal : time ;
  425. begin
  426. iDelayVal := DelayVal ;
  427. if iDelayVal > t_sim_resolution then
  428. iDelayVal := iDelayVal - t_sim_resolution ;
  429. end if ;
  430. Sig <= not Sig after iDelayVal ;
  431. end procedure ;
  432. procedure Toggle ( signal Sig : InOut bit ) is
  433. begin
  434. Sig <= not Sig ;
  435. end procedure ;
  436. procedure ToggleHS ( signal Sig : InOut bit ) is
  437. begin
  438. Sig <= not Sig ;
  439. wait for 0 ns ; -- Sig toggles
  440. wait for 0 ns ; -- new values updated into record
  441. end procedure ;
  442. function IsToggle ( signal Sig : In bit ) return boolean is
  443. begin
  444. return Sig'event ;
  445. end function ;
  446. procedure WaitForToggle ( signal Sig : In bit ) is
  447. begin
  448. wait on Sig ;
  449. end procedure ;
  450. ------------------------------------------------------------
  451. -- WaitForBarrier
  452. -- Barrier Synchronization
  453. -- Multiple processes call it, it finishes when all have called it
  454. ------------------------------------------------------------
  455. procedure WaitForBarrier ( signal Sig : InOut std_logic ) is
  456. begin
  457. Sig <= 'H' ;
  458. -- Wait until all processes set Sig to H
  459. -- Level check not necessary since last value /= H yet
  460. wait until Sig = 'H' ;
  461. -- Deactivate and propagate to allow back to back calls
  462. Sig <= '0' ;
  463. wait for 0 ns ;
  464. end procedure WaitForBarrier ;
  465. procedure WaitForBarrier ( signal Sig : InOut std_logic ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') is
  466. begin
  467. Sig <= 'H' ;
  468. -- Wait until all processes set Sig to H
  469. -- Level check not necessary since last value /= H yet
  470. wait until Sig = 'H' or TimeOut = Polarity ;
  471. -- Deactivate and propagate to allow back to back calls
  472. Sig <= '0' ;
  473. wait for 0 ns ;
  474. end procedure WaitForBarrier ;
  475. procedure WaitForBarrier ( signal Sig : InOut std_logic ; constant TimeOut : time ) is
  476. begin
  477. Sig <= 'H' ;
  478. -- Wait until all processes set Sig to H
  479. -- Level check not necessary since last value /= H yet
  480. wait until Sig = 'H' for TimeOut ;
  481. -- Deactivate and propagate to allow back to back calls
  482. Sig <= '0' ;
  483. wait for 0 ns ;
  484. end procedure WaitForBarrier ;
  485. ------------------------------------------------------------
  486. -- resolved_barrier
  487. -- summing resolution used in conjunction with integer based barriers
  488. function resolved_barrier ( s : integer_vector ) return integer is
  489. variable result : integer := 0 ;
  490. begin
  491. for i in s'RANGE loop
  492. if s(i) /= integer'left then
  493. result := s(i) + result;
  494. else
  495. return integer'left ; -- removes the initialization requirement
  496. end if ;
  497. end loop ;
  498. return result ;
  499. end function resolved_barrier ;
  500. -- Usage of integer barriers requires resolved_barrier. Initialization to 1 recommended, but not required
  501. -- signal barrier1 : resolved_barrier integer := 1 ; -- using the resolution function
  502. -- signal barrier2 : integer_barrier := 1 ; -- using the subtype that already applies the resolution function
  503. procedure WaitForBarrier ( signal Sig : InOut integer ) is
  504. begin
  505. Sig <= 0 ;
  506. -- Wait until all processes set Sig to 0
  507. -- Level check not necessary since last value /= 0 yet
  508. wait until Sig = 0 ;
  509. -- Deactivate and propagate to allow back to back calls
  510. Sig <= 1 ;
  511. wait for 0 ns ;
  512. end procedure WaitForBarrier ;
  513. procedure WaitForBarrier ( signal Sig : InOut integer ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') is
  514. begin
  515. Sig <= 0 ;
  516. -- Wait until all processes set Sig to 0
  517. -- Level check not necessary since last value /= 0 yet
  518. wait until Sig = 0 or TimeOut = Polarity ;
  519. -- Deactivate and propagate to allow back to back calls
  520. Sig <= 1 ;
  521. wait for 0 ns ;
  522. end procedure WaitForBarrier ;
  523. procedure WaitForBarrier ( signal Sig : InOut integer ; constant TimeOut : time ) is
  524. begin
  525. Sig <= 0 ;
  526. -- Wait until all processes set Sig to 0
  527. -- Level check not necessary since last value /= 0 yet
  528. wait until Sig = 0 for TimeOut ;
  529. -- Deactivate and propagate to allow back to back calls
  530. Sig <= 1 ;
  531. wait for 0 ns ;
  532. end procedure WaitForBarrier ;
  533. -- Using separate signals
  534. procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncIn : in std_logic ) is
  535. begin
  536. -- Activate Rdy
  537. SyncOut <= '1' ;
  538. -- Make sure our Rdy is seen
  539. wait for 0 ns ;
  540. -- Wait until other process' Rdy is at level 1
  541. if SyncIn /= '1' then
  542. wait until SyncIn = '1' ;
  543. end if ;
  544. -- Deactivate Rdy
  545. SyncOut <= '0' ;
  546. end procedure WaitForBarrier2 ;
  547. procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncInV : in std_logic_vector ) is
  548. constant ALL_ONE : std_logic_vector(SyncInV'Range) := (others => '1');
  549. begin
  550. -- Activate Rdy
  551. SyncOut <= '1' ;
  552. -- Make sure our Rdy is seen
  553. wait for 0 ns ;
  554. -- Wait until all other process' Rdy is at level 1
  555. if SyncInV /= ALL_ONE then
  556. wait until SyncInV = ALL_ONE ;
  557. end if ;
  558. -- Deactivate Rdy
  559. SyncOut <= '0' ;
  560. end procedure WaitForBarrier2 ;
  561. ------------------------------------------------------------
  562. -- WaitForClock
  563. -- Sync to Clock - after a delay, after a number of clocks
  564. ------------------------------------------------------------
  565. procedure WaitForClock ( signal Clk : in std_logic ; constant Delay : in time ) is
  566. begin
  567. if delay > t_sim_resolution then
  568. wait for delay - t_sim_resolution ;
  569. end if ;
  570. wait until Clk = CLK_ACTIVE ;
  571. end procedure WaitForClock ;
  572. procedure WaitForClock ( signal Clk : in std_logic ; constant NumberOfClocks : in integer := 1) is
  573. begin
  574. for i in 1 to NumberOfClocks loop
  575. wait until Clk = CLK_ACTIVE ;
  576. end loop ;
  577. end procedure WaitForClock ;
  578. procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in boolean ) is
  579. begin
  580. wait on Clk until Clk = CLK_ACTIVE and Enable ;
  581. end procedure WaitForClock ;
  582. procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in std_logic ; constant Polarity : std_logic := '1' ) is
  583. begin
  584. wait on Clk until Clk = CLK_ACTIVE and Enable = Polarity ;
  585. end procedure WaitForClock ;
  586. ------------------------------------------------------------
  587. -- WaitForLevel
  588. -- Find a signal at a level
  589. ------------------------------------------------------------
  590. procedure WaitForLevel ( signal A : in boolean ) is
  591. begin
  592. if not A then
  593. wait until A ;
  594. end if ;
  595. end procedure WaitForLevel ;
  596. procedure WaitForLevel ( signal A : in std_logic ; Polarity : std_logic := '1' ) is
  597. begin
  598. if A /= Polarity then
  599. -- wait on A until A = Polarity ;
  600. if Polarity = '1' then
  601. wait until A = '1' ;
  602. else
  603. wait until A = '0' ;
  604. end if ;
  605. end if ;
  606. end procedure WaitForLevel ;
  607. ------------------------------------------------------------
  608. -- CreateClock, CreateReset
  609. -- Note these do not exit
  610. ------------------------------------------------------------
  611. procedure CreateClock (
  612. signal Clk : inout std_logic ;
  613. constant Period : time ;
  614. constant DutyCycle : real := 0.5
  615. ) is
  616. constant HIGH_TIME : time := Period * DutyCycle ;
  617. constant LOW_TIME : time := Period - HIGH_TIME ;
  618. begin
  619. if HIGH_TIME = LOW_TIME then
  620. loop
  621. Clk <= toggle_sl_table(Clk) after HIGH_TIME ;
  622. wait on Clk ;
  623. end loop ;
  624. else
  625. -- Schedule s.t. all assignments after the first occur on delta cycle 0
  626. Clk <= '0', '1' after LOW_TIME ;
  627. wait for period - 1 ns ; -- allows after on future Clk <= '0'
  628. loop
  629. Clk <= '0' after 1 ns, '1' after LOW_TIME + 1 ns ;
  630. wait for period ;
  631. end loop ;
  632. end if ;
  633. end procedure CreateClock ;
  634. procedure CheckClockPeriod (
  635. constant AlertLogID : AlertLogIDType ;
  636. signal Clk : in std_logic ;
  637. constant Period : time ;
  638. constant ClkName : string := "Clock" ;
  639. constant HowMany : integer := 5
  640. ) is
  641. variable LastLogTime, ObservedPeriod : time ;
  642. begin
  643. wait until Clk = CLK_ACTIVE ;
  644. LastLogTime := now ;
  645. -- Check First HowMany clocks
  646. for i in 1 to HowMany loop
  647. wait until Clk = CLK_ACTIVE ;
  648. ObservedPeriod := now - LastLogTime ;
  649. AffirmIf(AlertLogID, ObservedPeriod = Period,
  650. "CheckClockPeriod: " & ClkName & " Period: " & to_string(ObservedPeriod) &
  651. " = Expected " & to_string(Period)) ;
  652. LastLogTime := now ;
  653. end loop ;
  654. wait ;
  655. end procedure CheckClockPeriod ;
  656. procedure CheckClockPeriod (
  657. signal Clk : in std_logic ;
  658. constant Period : time ;
  659. constant ClkName : string := "Clock" ;
  660. constant HowMany : integer := 5
  661. ) is
  662. begin
  663. CheckClockPeriod (
  664. AlertLogID => ALERTLOG_DEFAULT_ID,
  665. Clk => Clk,
  666. Period => Period,
  667. ClkName => ClkName,
  668. HowMany => HowMany
  669. ) ;
  670. end procedure CheckClockPeriod ;
  671. procedure CreateReset (
  672. signal Reset : out std_logic ;
  673. constant ResetActive : in std_logic ;
  674. signal Clk : in std_logic ;
  675. constant Period : time ;
  676. constant tpd : time
  677. ) is
  678. begin
  679. wait until Clk = CLK_ACTIVE ;
  680. Reset <= ResetActive after tpd ;
  681. wait for Period - t_sim_resolution ;
  682. wait until Clk = CLK_ACTIVE ;
  683. Reset <= not ResetActive after tpd ;
  684. wait ;
  685. end procedure CreateReset ;
  686. procedure LogReset (
  687. constant AlertLogID : AlertLogIDType ;
  688. signal Reset : in std_logic ;
  689. constant ResetActive : in std_logic ;
  690. constant ResetName : in string := "Reset" ;
  691. constant LogLevel : in LogType := ALWAYS
  692. ) is
  693. begin
  694. -- Does not log the value of Reset at time 0.
  695. for_ever : loop
  696. wait on Reset ;
  697. if Reset = ResetActive then
  698. LOG(AlertLogID, ResetName & " now active", INFO) ;
  699. print("") ;
  700. elsif Reset = not ResetActive then
  701. LOG(AlertLogID, ResetName & " now inactive", INFO) ;
  702. print("") ;
  703. else
  704. LOG(AlertLogID, ResetName & " = " & to_string(Reset), INFO) ;
  705. print("") ;
  706. end if ;
  707. end loop for_ever ;
  708. end procedure LogReset ;
  709. procedure LogReset (
  710. signal Reset : in std_logic ;
  711. constant ResetActive : in std_logic ;
  712. constant ResetName : in string := "Reset" ;
  713. constant LogLevel : in LogType := ALWAYS
  714. ) is
  715. begin
  716. LogReset (
  717. AlertLogID => ALERTLOG_DEFAULT_ID,
  718. Reset => Reset,
  719. ResetActive => ResetActive,
  720. ResetName => ResetName,
  721. LogLevel => LogLevel
  722. ) ;
  723. end procedure LogReset ;
  724. ------------------------------------------------------------
  725. -- Deprecated
  726. -- subsumed by WaitForTransaction with Ack and TimeOut.
  727. -- TimeOut works exactly like IntReq
  728. ------------------------------------------------------------
  729. procedure WaitForTransactionOrIrq (
  730. signal Clk : In std_logic ;
  731. signal Rdy : In std_logic ;
  732. signal IntReq : In std_logic
  733. ) is
  734. variable AckTime : time ;
  735. constant POLARITY : std_logic := '1' ;
  736. begin
  737. AckTime := NOW ;
  738. -- Find Ready or Time out
  739. if (Rdy /= '1' and IntReq /= POLARITY) then
  740. wait until Rdy = '1' or IntReq = POLARITY ;
  741. else
  742. wait for 0 ns ; -- allow Ack to update
  743. end if ;
  744. -- align to clock if Rdy or IntReq does not happen within delta cycles from Ack
  745. if NOW /= AckTime then
  746. wait until Clk = CLK_ACTIVE ;
  747. end if ;
  748. end procedure ;
  749. ------------------------------------------------------------
  750. -- Deprecated
  751. -- WaitForAck, StrobeAck
  752. -- Replaced by WaitForToggle and Toggle
  753. ------------------------------------------------------------
  754. procedure WaitForAck ( signal Ack : In std_logic ) is
  755. begin
  756. -- Wait for Model to be done
  757. wait until Ack = '1' ;
  758. end procedure ;
  759. procedure StrobeAck ( signal Ack : Out std_logic ) is
  760. begin
  761. -- Model done, drive rising edge on Ack
  762. Ack <= '0' ;
  763. wait for 0 ns ;
  764. Ack <= '1' ;
  765. end procedure ;
  766. end TbUtilPkg ;