macro pre(x) = abs((+x-1) % size); macro suc(x) = abs((+x+1) % size); macro numBits = 4; macro size = 4; module FIFO(event ?put,!ackPut, event ?get,!ackGet, event bv{numBits} ?dataIn, event bv{numBits} !dataOut) { // local variables to implement the buffer [size]bv{numBits} buf; nat{size} hd; nat{size} tl; bool isEmpty; isEmpty = true; always{ case (put & !get) do // enqueue dataIn -> buf[tl] if(isEmpty) { // FIFO is empty next(buf[tl]) = dataIn; emit next(ackPut); next(isEmpty) = false; } else if(hd==tl) { // FIFO is full nothing; } else { // FIFO is neither empty nor full next(buf[tl]) = dataIn; emit next(ackPut); next(isEmpty) = false; next(tl) = suc(tl); } (!put & get) do // dequeue buf[hd] -> dataOut if(isEmpty) { // FIFO is empty nothing; } else if(hd==tl) { // FIFO is full next(dataOut) = buf[hd]; emit next(ackGet); next(isEmpty) = true; } else { // FIFO is neither empty nor full next(dataOut) = buf[hd]; emit next(ackGet); next(hd) = suc(hd); } (put & get) do // parallel enqueue and dequeue if(isEmpty) { // FIFO is empty next(dataOut) = dataIn; emit next(ackPut); emit next(ackGet); } else if(hd==tl) { // FIFO is full next(dataOut) = buf[hd]; next(buf[tl]) = dataIn; emit next(ackPut); emit next(ackGet); } else { // FIFO is neither empty nor full next(dataOut) = buf[hd]; next(buf[tl]) = dataIn; emit next(ackPut); emit next(ackGet); next(hd) = suc(hd); next(tl) = suc(tl); } default nothing; } }