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