--synopsys synthesis_off ---------------------------------------------------------------------------- -- -- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. -- -- This program is proprietary and confidential information of -- Synopsys, Inc. and may be used and disclosed only as authorized -- in a license agreement controlling such use and disclosure. -- -- Package name: qe.vhd -- -- Purpose: This file contains examples showing the use of the queues -- Declared in vhdlq.vhd and vhdlzq.vhd. -- -- Author: PH -- ---------------------------------------------------------------------------- -- -- This file contains examples of how to use queues. -- EX1: Producer-consumer relationship in the same architecture. -- EX2: Producer-consumer relationship in different architectures. -- EX3: Array of queues. -- -- -- EX1: Producer-consumer relationship between processes in the same -- architecture. -- -- We are using PUT and GET here, so notice how the consumer initially -- waits for 2 time units. This ensures that the PUT will have happened -- before the corresponding GET. -- entity EX1 is end; use WORK.INTEGER_QUEUES; architecture A of EX1 is signal IQ: INTEGER_QUEUES.QTYPE; begin PRODUCER: process begin for I in 10 to 20 loop INTEGER_QUEUES.PUT(I, IQ); wait for 10 ns; end loop; wait; end process; CONSUMER: process variable V: integer; begin wait for 2 ns; loop INTEGER_QUEUES.GET(V, IQ); wait for 10 ns; end loop; end process; end; -- -- EX2: Producer-consumer relationship between processes in different -- architectures. -- -- Things to notice: -- 1. The entities are "connected" via a queue. Alternately, we could -- have declared the queue in a package and referenced it globally, -- but this keeps us from having multiple instances of the producer- -- consumer pairs. -- 2. We are using zero length queues. As a consequence, we are using -- using the SEND and RECEIVE procedures. -- 3. We are explicitly passing the priority for queue operations. This -- is not necessary for this example, but is shown here for form. -- 4. We only advance time in the consumer process. We let the -- synchronization functionality of SEND/RECEIVE take care of -- proper ordering of the operations. -- entity EX2 is end; use WORK.INTEGER_ZQUEUES; entity EX2_P is port (Q: inout INTEGER_ZQUEUES.QTYPE); end; architecture A of EX2_P is begin PRODUCER: process begin for I in 10 to 20 loop INTEGER_ZQUEUES.SEND(I, Q); end loop; wait; end process; end; use WORK.INTEGER_ZQUEUES; entity EX2_C is port (Q: inout INTEGER_ZQUEUES.QTYPE); end; architecture A of EX2_C is begin CONSUMER: process variable V: integer; begin loop INTEGER_ZQUEUES.RECEIVE(V, Q); wait for 1 ns; end loop; end process; end; use WORK.INTEGER_ZQUEUES; architecture A of EX2 is signal IZQ: INTEGER_ZQUEUES.QTYPE; component EX2_P port (Q: inout INTEGER_ZQUEUES.QTYPE); end component; component EX2_C port (Q: inout INTEGER_ZQUEUES.QTYPE); end component; for all: EX2_P use entity WORK.EX2_P(A); for all: EX2_C use entity WORK.EX2_C(A); begin PRODUCER: EX2_P port map (IZQ); CONSUMER: EX2_C port map (IZQ); end; -- -- EX3: array of queues. Here we have multiple producers, each writing into -- their own queue. A single consumer polls the queues. -- -- Things of interest: -- 1. VHDL's requirement that we pass a static signal name to a subprogram -- makes this model rather ugly. -- entity EX3 is end; use WORK.INTEGER_QUEUES; architecture A of EX3 is -- QA_ISTYPE must have an ascending range. subtype QA_ISTYPE is positive range 1 to 10; type QA_TYPE is array (QA_ISTYPE) of INTEGER_QUEUES.QTYPE; signal IQA: QA_TYPE; begin G: for I in QA_ISTYPE generate PRODUCER: process begin for J in 10 to 20 loop INTEGER_QUEUES.SEND(J, IQA(I)); end loop; wait; end process; end generate; CONSUMER: process variable V: integer; variable NQ: QA_ISTYPE; -- keeps things fair function NON_EMPTY_Q(signal X: QA_TYPE) return boolean is variable R: boolean; begin for I in X'range loop R := R or not INTEGER_QUEUES.EMPTY(X(I)); end loop; return R; end; begin wait on IQA; while NON_EMPTY_Q(IQA) loop if not INTEGER_QUEUES.EMPTY(IQA(NQ)) then -- -- Here is the ugly case statement, required -- because VHDL will not let us say: -- GET(V, IQA(NQ), 1); -- directly. -- case NQ is when 1 => INTEGER_QUEUES.GET(V, IQA(1), 1); when 2 => INTEGER_QUEUES.GET(V, IQA(2), 1); when 3 => INTEGER_QUEUES.GET(V, IQA(3), 1); when 4 => INTEGER_QUEUES.GET(V, IQA(4), 1); when 5 => INTEGER_QUEUES.GET(V, IQA(5), 1); when 6 => INTEGER_QUEUES.GET(V, IQA(6), 1); when 7 => INTEGER_QUEUES.GET(V, IQA(7), 1); when 8 => INTEGER_QUEUES.GET(V, IQA(8), 1); when 9 => INTEGER_QUEUES.GET(V, IQA(9), 1); when 10 => INTEGER_QUEUES.GET(V, IQA(10), 1); when others => assert false report "Need another CONSUMER case" severity FAILURE; end case; -- -- process new element here. -- wait for 1 ns; -- -- next here makes us process more elements -- in the same queue. Removing it makes -- us go on to the next queue. -- next; end if; if NQ = QA_ISTYPE'right then NQ := QA_ISTYPE'left; else NQ := QA_ISTYPE'SUCC(NQ); end if; end loop; end process; end; --synopsys synthesis_on