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.

237 lines
6.7 KiB

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