Here is a data source in Verilog RTL for LocalLink that generates a stream of packets containing arbitrary data with arbitrary gaps.
module LocalLinkSrc(
input reset,
input clk,
output [7:0] src_data,
output src_sof_n,
output src_eof_n,
output src_src_rdy_n,
input src_dst_rdy_n);
// The source generates 'random' data using a pseudo random sequence generator (prbs).
// The source also makes gaps in its data using bit[9] of the generator.
reg [14:0] prbs;
reg started;
assign src_data = (!src_src_rdy_n) ? prbs[7:0] : 0;
assign src_src_rdy_n = !(prbs[9]);
// The end of packet is arbitrarily generated when bits 14:12 have a particular value.
assign src_eof_n = !(!src_src_rdy_n && prbs[14:12]==2);
// A start of frame must be flagged during the first new word after the previous frame has ended.
assign src_sof_n = !(!src_src_rdy_n && !started);
always @(posedge clk) begin
started <= (reset) ? 0: (!src_eof_n) ? 0 : (!src_sof_n) ? 1 : started;
prbs <= (reset) ? 100: (src_dst_rdy_n) ? prbs: (prbs << 1) | (prbs[14] != prbs[13]);
end
endmodule
And here is a corresponding data sink:
module LocalLinkSink(
input reset,
input clk,
input [7:0] sink_data,
input sink_sof_n,
input sink_eof_n,
output sink_src_rdy_n,
input sink_dst_rdy_n);
// The sink also maintains a prbs to make it go busy or not on an arbitrary basis.
reg [14:0] prbs;
assign sink_dst_rdy_n = prbs[0];
always @(posedge clk) begin
if (!sink_dst_rdy_n && !sink_src_rdy_n) $display(
"%m LocalLinkSink sof_n=%d eof_n=%d data=0x%h", sink_sof_n, sink_eof_n, sink_data);
// Put a blank line between packets on the console.
if (!sink_dst_rdy_n && !sink_src_rdy_n && !sink_eof_n) $display("\n\n");
prbs <= (reset) ? 200: (prbs << 1) | (prbs[14] != prbs[13]);
end
endmodule // LocalLinkSrc
And here is a testbench that wires them together:
module SIMSYS();
reg reset;
reg clk;
wire [7:0] data;
wire sof_n;
wire eof_n;
wire ack_n;
wire req_n;
// Instance of the src
LocalLinkSrc src (.reset(reset),
.clk(clk),
.src_data(data),
.src_sof_n(sof_n),
.src_eof_n(eof_n),
.src_src_rdy_n(req_n),
.src_dst_rdy_n(ack_n));
// Instance of the sink
LocalLinkSink sink (.reset(reset),
.clk(clk),
.sink_data(data),
.sink_sof_n(sof_n),
.sink_eof_n(eof_n),
.sink_src_rdy_n(req_n),
.sink_dst_rdy_n(ack_n)
);
initial begin clk =0; forever #50 clk = !clk; end
initial begin reset = 1; #130 reset=0; end
endmodule // SIMSYS
| 34: (C) 2012-17, DJ Greaves, University of Cambridge, Computer Laboratory. |