Bluepsec Examples
Avalon Streaming Interface
Overview
This package provides an Avalon Streaming interface which is compliant (though I don't make any guarantees!) with Altera's Avalon interconnect system used by their SOPC Builder tool. It effectively allows Get and Put interfaces within Bluespec to be passed to the SOPC Builder system allowing these communication channels to be hooked together using the SOPC Builder GUI environment. Flow-control is preserved. Some examples are also provided at the end of this page.
Avalon Streaming Interface Code
/***************************************************************************** AvalonStreaming =============== Simon Moore, May 2010 This library provides Bluespec wrappers for Altera's Avalon Streaming interface. * Names - SOPC Builder expects the following names to be used for streaming interfaces (i.e. these are the names you should use in the top-level interface): * aso - Avalon-ST source * asi - Avalon-ST sink *****************************************************************************/ package AvalonStreaming; import GetPut::*; import FIFOF::*; /***************************************************************************** Source Stream *****************************************************************************/ // Avalon-ST source physical interface. Note that names of modules // match SOPC's expectations. (* always_ready, always_enabled *) interface AvalonStreamSourcePhysicalIfc#(numeric type dataT_width); method Bit#(dataT_width) stream_out_data; method Bool stream_out_valid; method Action stream_out(Bool ready); endinterface interface AvalonStreamSourceVerboseIfc#(type dataT, numeric type dataT_width); interface Put#(dataT) tx; interface AvalonStreamSourcePhysicalIfc#(dataT_width) physical; endinterface typedef AvalonStreamSourceVerboseIfc#(dataT,SizeOf#(dataT)) AvalonStreamSourceIfc#(type dataT); module mkPut2AvalonStreamSource(AvalonStreamSourceVerboseIfc#(dataT,dataT_width)) provisos(Bits#(dataT,dataT_width)); Wire#(Maybe#(Bit#(dataT_width))) data_dw <- mkDWire(tagged Invalid); Wire#(Bool) ready_w <- mkBypassWire; interface Put tx; method Action put(dataT d) if(ready_w); data_dw <= tagged Valid pack(d); endmethod endinterface interface AvalonStreamSourcePhysicalIfc physical; method Bit#(dataT_width) stream_out_data; return fromMaybe(0,data_dw); endmethod method Bool stream_out_valid; return isValid(data_dw); endmethod method Action stream_out(Bool ready); ready_w <= ready; endmethod endinterface endmodule /***************************************************************************** Sink Stream *****************************************************************************/ // Avalon-ST sink physical interface. Note that names of modules // match SOPC's expectations. (* always_ready, always_enabled *) interface AvalonStreamSinkPhysicalIfc#(type dataT_width); method Action stream_in(Bit#(dataT_width) data, Bool valid); method Bool stream_in_ready; endinterface interface AvalonStreamSinkVerboseIfc#(type dataT, numeric type dataT_width); interface Get#(dataT) rx; interface AvalonStreamSinkPhysicalIfc#(dataT_width) physical; endinterface typedef AvalonStreamSinkVerboseIfc#(dataT,SizeOf#(dataT)) AvalonStreamSinkIfc#(type dataT); module mkAvalonStreamSink2Get(AvalonStreamSinkVerboseIfc#(dataT,dataT_width)) provisos(Bits#(dataT,dataT_width)); FIFOF#(dataT) f <- mkLFIFOF; Wire#(Maybe#(dataT)) d_dw <- mkDWire(tagged Invalid); rule push_data_into_fifo (isValid(d_dw)); f.enq(fromMaybe(?,d_dw)); endrule interface Get rx = toGet(f); interface AvalonStreamSinkPhysicalIfc physical; // method to receive data. Note that the data should be held // until stream_in_ready is True, i.e. there is room in the internal // FIFO - f - so we should never loose data from our d_dw DWire method Action stream_in(Bit#(dataT_width) data, Bool valid); if(valid) d_dw <= tagged Valid unpack(data); endmethod method Bool stream_in_ready; return f.notFull; endmethod endinterface endmodule endpackage
Link to the AvalonStreaming.bsv source
Example Test Code
/***************************************************************************** Test AvalonStreaming ==================== Simon Moore, May 2010 This produces three simple Avalon Stream devices to test the AvalonStreaming library: * simple counter source * a stream doubler (i.e. reads from input stream and outputs the input*2) * a stream jitter inserter (i.e. randomly pauses stream. Useful to test that back pressure is working correctly These devices can be imported into SOPC builder simply and only require that the data width be set to 32-bits. *****************************************************************************/ import GetPut::*; import FIFO::*; import AvalonStreaming::*; import Clocks::*; import LFSR::*; typedef UInt#(32) TestT; interface OneSourceIfc; interface AvalonStreamSourcePhysicalIfc#(SizeOf#(TestT)) aso; endinterface interface SinkAndSourceIfc; interface AvalonStreamSinkPhysicalIfc#(SizeOf#(TestT)) asi; interface AvalonStreamSourcePhysicalIfc#(SizeOf#(TestT)) aso; endinterface (* synthesize, reset_prefix = "csi_clockreset_reset_n", clock_prefix = "csi_clockreset_clk" *) module mkCountingAvalonSource(OneSourceIfc); Reg#(TestT) ctr <- mkReg(0); AvalonStreamSourceIfc#(TestT) src <- mkPut2AvalonStreamSource; rule inc_ctr_put; src.tx.put(ctr); ctr <= ctr+1; endrule interface aso = src.physical; endmodule (* synthesize, reset_prefix = "csi_clockreset_reset_n", clock_prefix = "csi_clockreset_clk" *) module mkDoubleAvalonStream(SinkAndSourceIfc); AvalonStreamSinkIfc#(TestT) rx <- mkAvalonStreamSink2Get; AvalonStreamSourceIfc#(TestT) tx <- mkPut2AvalonStreamSource; rule double; let d <- rx.rx.get(); tx.tx.put(d<<1); endrule interface asi = rx.physical; interface aso = tx.physical; endmodule (* synthesize, reset_prefix = "csi_clockreset_reset_n", clock_prefix = "csi_clockreset_clk" *) module mkJitterAvalonStream(SinkAndSourceIfc); LFSR#(Bit#(32)) random <- mkLFSR_32; let stop = (random.value & 32'hf) == 0; AvalonStreamSinkIfc#(TestT) rx <- mkAvalonStreamSink2Get; AvalonStreamSourceIfc#(TestT) tx <- mkPut2AvalonStreamSource; rule forward (!stop); let d <- rx.rx.get(); tx.tx.put(d); endrule rule next_random; random.next; endrule interface asi = rx.physical; interface aso = tx.physical; endmodule
Link to the TestAvalonST.bsv source