rlm@8: // The MIT License rlm@8: rlm@8: // Copyright (c) 2009 Massachusetts Institute of Technology rlm@8: rlm@8: // Permission is hereby granted, free of charge, to any person obtaining a copy rlm@8: // of this software and associated documentation files (the "Software"), to deal rlm@8: // in the Software without restriction, including without limitation the rights rlm@8: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell rlm@8: // copies of the Software, and to permit persons to whom the Software is rlm@8: // furnished to do so, subject to the following conditions: rlm@8: rlm@8: // The above copyright notice and this permission notice shall be included in rlm@8: // all copies or substantial portions of the Software. rlm@8: rlm@8: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR rlm@8: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, rlm@8: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE rlm@8: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER rlm@8: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, rlm@8: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN rlm@8: // THE SOFTWARE. rlm@8: rlm@8: // Author: Kermin Fleming kfleming@mit.edu rlm@8: rlm@8: import Connectable::*; rlm@8: import GetPut::*; rlm@8: import ClientServer::*; rlm@8: import FIFO::*; rlm@8: import FixedPoint::*; rlm@8: import Vector::*; rlm@8: rlm@8: //AWB includes. These import the structure whcih allow us to communicate rlm@8: // with the outside world, and are part of the AWB library code rlm@8: rlm@8: `include "asim/provides/soft_connections.bsh" rlm@8: `include "asim/provides/common_services.bsh" rlm@8: rlm@8: // Local includes. Look for the correspondingly named .awb files rlm@8: // workspace/labs/src/mit-6.375/modules/bluespec/mit-6.375/common/ rlm@8: // to find the actual Bluespec files which are used to generate rlm@8: // these includes. These files are specific to this audio processing rlm@8: // pipeline rlm@8: rlm@8: `include "asim/provides/audio_pipeline_types.bsh" rlm@8: `include "asim/provides/audio_processor_types.bsh" rlm@8: rlm@8: typedef 8 Taps; rlm@8: rlm@8: module [Connected_Module] mkFIRFilter (FIRFilter); rlm@8: rlm@8: rlm@8: // instantiate an input FIFO and an Output FIFO rlm@8: // mkFIFO returns a fifo of length 2 (by default) rlm@8: // AudioProcessorUnit is the name given to the packets rlm@8: // of DATA processed by our audio pipeline. For their rlm@8: // definition, look in the file rlm@8: // workspace/labs/src/mit-6.375/modules/bluespec/mit-6.375/common/AudioProcessorTypes.bsv rlm@8: rlm@8: FIFO#(AudioProcessorUnit) infifo <- mkFIFO; rlm@8: FIFO#(AudioProcessorUnit) outfifo <- mkFIFO; rlm@8: rlm@8: rlm@8: // an alternate syntax for instantiating the samples vector rlm@8: // would have been as follows: rlm@8: // rlm@8: // Vector#(Taps,Reg#(Sample)) samples <- replicateM(mkReg(0)); rlm@8: // rlm@8: // we have used an explicit loop here, to demonstrate how rlm@8: // vectors can be instantiated during the static elaboration rlm@8: // phase, even though replicateM is far more concise. rlm@8: rlm@8: Vector#(Taps,Reg#(Sample)) samples = newVector(); rlm@8: for(Integer i = 0; i < valueof(Taps); i=i+1) rlm@8: samples[i] <- mkReg(0); rlm@8: rlm@8: Vector#(9,Reg#(FixedPoint#(16,16))) pr <- replicateM(mkReg(0)); rlm@8: rlm@8: rlm@8: // fromReal takes a Real number and converts it to a FixedPoint rlm@8: // representation. The compiler is smart enough to infer the rlm@8: // type (bit width) of the fixed point (in this case, we have 16 rlm@8: // bits of integer, and 16 bits of fraction. rlm@8: rlm@8: FixedPoint#(16,16) firCoefs [9] = {fromReal(-0.0124), rlm@8: fromReal(0.0), rlm@8: fromReal(-0.0133), rlm@8: fromReal(0.0), rlm@8: fromReal(0.8181), rlm@8: fromReal(0.0), rlm@8: fromReal(-0.0133), rlm@8: fromReal(0.0), rlm@8: fromReal(-0.0124)}; rlm@8: rlm@8: rlm@8: // This rule implements a fir filter. We do the fir computations in rlm@8: // 16.16 fixed point. This preserves the magnitude of the input rlm@8: // pcm. This code was implemented using for loops so as to be more rlm@8: // clear. Using the functions map, fold, readVReg, and writeVReg rlm@8: // would have been more concise. rlm@8: rlm@8: rule process (infifo.first matches tagged Sample .sample); rlm@8: rlm@8: // Advance the fir filter, by shifting all the elements rlm@8: // down the Vector of registers (like a shift register) rlm@8: rlm@8: samples[0] <= sample; rlm@8: for(Integer i = 0; i < valueof(Taps) - 1; i = i + 1) rlm@8: begin rlm@8: samples[i+1] <= samples[i]; rlm@8: end rlm@8: rlm@8: // Filter the values, using an inefficient adder chain. You will rlm@8: // need to shorten the combinatorial path, by pipelining this logic. rlm@8: rlm@8: FixedPoint#(16,16) accumulate= firCoefs[0] * fromInt(sample); rlm@8: for(Integer i = 0; i < valueof(Taps); i = i + 1) rlm@8: begin rlm@8: accumulate = accumulate + firCoefs[1+i] * fromInt(samples[i]); rlm@8: end rlm@8: rlm@8: outfifo.enq(tagged Sample fxptGetInt(accumulate)); rlm@8: rlm@8: infifo.deq; rlm@8: endrule rlm@8: rlm@8: // Handle the end of stream condition. Look at the two rule guards, rlm@8: // these are obviously mutually exclusive. The definition of rlm@8: // AudioProcessorUnit shows that it can be tagged only as a Sample, or rlm@8: // EndOfFile; nothing else! rlm@8: rlm@8: rule endOfFile (infifo.first matches tagged EndOfFile); rlm@8: rlm@8: $display("FIR got end of file"); rlm@8: rlm@8: // Reset state for next invocation rlm@8: for(Integer i = 0; i < valueof(Taps); i = i + 1) rlm@8: begin rlm@8: samples[i] <= 0; rlm@8: pr[i] <= 0; rlm@8: end rlm@8: rlm@8: // pass the end-of-file token down the pipeline, eventually this will rlm@8: // make it back to the software side, to notify it that the stream rlm@8: // has been processed completely rlm@8: rlm@8: outfifo.enq(infifo.first); rlm@8: infifo.deq; rlm@8: endrule rlm@8: rlm@8: rlm@8: // this section connects the fifos instantiated internally to the rlm@8: // externally visible interface rlm@8: rlm@8: interface sampleInput = fifoToPut(infifo); rlm@8: interface sampleOutput = fifoToGet(outfifo); rlm@8: rlm@8: endmodule