Library of reusable VHDL components
vhdl
osvvm
fpga
ghdl
testbenches
psl
coverage

QueueP.vhd 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. package QueueP is
  4. generic (
  5. type QUEUE_TYPE;
  6. MAX_LEN : natural := 64;
  7. function to_string(d : in QUEUE_TYPE) return string
  8. );
  9. -- simple queue interface
  10. type t_simple_queue is protected
  11. procedure push (data : in QUEUE_TYPE);
  12. procedure pop (data : out QUEUE_TYPE);
  13. procedure init (logging : in boolean := false);
  14. impure function is_empty return boolean;
  15. impure function is_full return boolean;
  16. impure function fillstate return natural;
  17. end protected t_simple_queue;
  18. -- linked list queue interface
  19. type t_list_queue is protected
  20. procedure push (data : in QUEUE_TYPE);
  21. procedure pop (data : out QUEUE_TYPE);
  22. procedure init (logging : in boolean := false);
  23. impure function is_empty return boolean;
  24. impure function is_full return boolean;
  25. impure function fillstate return natural;
  26. end protected t_list_queue;
  27. end package QueueP;
  28. package body QueueP is
  29. -- simple queue implementation
  30. -- inspired by noasic article http://noasic.com/blog/a-simple-fifo-using-vhdl-protected-types/
  31. type t_simple_queue is protected body
  32. type t_queue_array is array (0 to MAX_LEN-1) of QUEUE_TYPE;
  33. variable v_queue : t_queue_array;
  34. variable v_count : natural range 0 to t_queue_array'length := 0;
  35. variable v_head : natural range 0 to t_queue_array'high := 0;
  36. variable v_tail : natural range 0 to t_queue_array'high := 0;
  37. variable v_logging : boolean := false;
  38. -- write one entry into queue
  39. procedure push (data : in QUEUE_TYPE) is
  40. begin
  41. assert not(is_full)
  42. report "push into full queue -> discarded"
  43. severity failure;
  44. v_queue(v_head) := data;
  45. v_head := (v_head + 1) mod t_queue_array'length;
  46. v_count := v_count + 1;
  47. if v_logging then
  48. report t_simple_queue'instance_name & " pushed 0x" & to_string(data) & " into queue";
  49. end if;
  50. end procedure push;
  51. -- read one entry from queue
  52. procedure pop (data : out QUEUE_TYPE) is
  53. variable v_data : QUEUE_TYPE;
  54. begin
  55. assert not(is_empty)
  56. report "pop from empty queue -> discarded"
  57. severity failure;
  58. v_data := v_queue(v_tail);
  59. v_tail := (v_tail + 1) mod t_queue_array'length;
  60. v_count := v_count - 1;
  61. if v_logging then
  62. report t_simple_queue'instance_name & " popped 0x" & to_string(v_data) & " from queue";
  63. end if;
  64. data := v_data;
  65. end procedure pop;
  66. -- returns true if queue is empty, false otherwise
  67. impure function is_empty return boolean is
  68. begin
  69. return v_count = 0;
  70. end function is_empty;
  71. -- returns true if queue is full, false otherwise
  72. impure function is_full return boolean is
  73. begin
  74. return v_count = t_queue_array'length;
  75. end function is_full;
  76. -- returns number of filled slots in queue
  77. impure function fillstate return natural is
  78. begin
  79. return v_count;
  80. end function fillstate;
  81. -- returns number of free slots in queue
  82. impure function freeslots return natural is
  83. begin
  84. return t_queue_array'length - v_count;
  85. end function freeslots;
  86. procedure init (logging : in boolean := false) is
  87. begin
  88. v_logging := logging;
  89. end procedure init;
  90. end protected body t_simple_queue;
  91. -- linked liste queue implementation
  92. type t_list_queue is protected body
  93. type t_entry;
  94. type t_entry_ptr is access t_entry;
  95. type t_data_ptr is access QUEUE_TYPE;
  96. type t_entry is record
  97. data : t_data_ptr;
  98. last_entry : t_entry_ptr;
  99. next_entry : t_entry_ptr;
  100. end record t_entry;
  101. variable v_head : t_entry_ptr;
  102. variable v_tail : t_entry_ptr;
  103. variable v_count : natural := 0;
  104. variable v_logging : boolean := false;
  105. -- write one entry into queue by
  106. -- creating new entry at head of list
  107. procedure push (data : in QUEUE_TYPE) is
  108. variable v_entry : t_entry_ptr;
  109. begin
  110. if (not(is_full)) then
  111. if (v_count /= 0) then
  112. v_entry := new t_entry;
  113. v_entry.data := new QUEUE_TYPE'(data);
  114. v_entry.last_entry := v_head;
  115. v_entry.next_entry := null;
  116. v_head := v_entry;
  117. v_head.last_entry.next_entry := v_head;
  118. else
  119. v_head := new t_entry;
  120. v_head.data := new QUEUE_TYPE'(data);
  121. v_head.last_entry := null;
  122. v_head.next_entry := null;
  123. v_tail := v_head;
  124. end if;
  125. v_count := v_count + 1;
  126. if v_logging then
  127. report t_list_queue'instance_name & " pushed 0x" & to_string(data) & " into queue";
  128. end if;
  129. else
  130. assert false
  131. report "Push to full queue -> discared"
  132. severity warning;
  133. end if;
  134. end procedure push;
  135. -- read one entry from queue at tail of list and
  136. -- delete that entry from list after read
  137. procedure pop (data : out QUEUE_TYPE) is
  138. variable v_entry : t_entry_ptr := v_tail;
  139. variable v_data : QUEUE_TYPE;
  140. begin
  141. assert not(is_empty)
  142. report "pop from empty queue -> discarded"
  143. severity failure;
  144. v_data := v_tail.data.all;
  145. v_tail := v_tail.next_entry;
  146. deallocate(v_entry.data);
  147. deallocate(v_entry);
  148. v_count := v_count - 1;
  149. if v_logging then
  150. report t_list_queue'instance_name & " popped 0x" & to_string(v_data) & " from queue";
  151. end if;
  152. data := v_data;
  153. end procedure pop;
  154. procedure init (logging : in boolean := false) is
  155. begin
  156. v_logging := logging;
  157. end procedure init;
  158. -- returns true if queue is full, false otherwise
  159. impure function is_full return boolean is
  160. begin
  161. return v_count = MAX_LEN;
  162. end function is_full;
  163. -- returns true if queue is empty, false otherwise
  164. impure function is_empty return boolean is
  165. begin
  166. return v_tail = null;
  167. end function is_empty;
  168. -- returns number of filled slots in queue
  169. impure function fillstate return natural is
  170. begin
  171. return v_count;
  172. end function fillstate;
  173. end protected body t_list_queue;
  174. end package body QueueP;