diff options
Diffstat (limited to 'fpga/usrp3/sim/axi/sim_axis_lib.svh')
-rw-r--r-- | fpga/usrp3/sim/axi/sim_axis_lib.svh | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/fpga/usrp3/sim/axi/sim_axis_lib.svh b/fpga/usrp3/sim/axi/sim_axis_lib.svh new file mode 100644 index 000000000..bdee113de --- /dev/null +++ b/fpga/usrp3/sim/axi/sim_axis_lib.svh @@ -0,0 +1,219 @@ +// +// Copyright 2016 Ettus Research +// +`ifndef INCLUDED_SIM_AXIS_LIB +`define INCLUDED_SIM_AXIS_LIB + +interface axis_t #(parameter DWIDTH = 32, parameter NUM_STREAMS = 1)(input clk); + logic [NUM_STREAMS*DWIDTH-1:0] tdata; + logic [NUM_STREAMS-1:0] tvalid; + logic [NUM_STREAMS-1:0] tlast; + logic [NUM_STREAMS-1:0] tready; + + modport master ( + output tdata, + output tvalid, + output tlast, + input tready); + + modport slave ( + input tdata, + input tvalid, + input tlast, + output tready); +endinterface + +// Interface to push data onto a master AXI-stream bus +interface axis_master #(parameter DWIDTH = 32, parameter NUM_STREAMS = 1)(input clk); + axis_t #(.DWIDTH(DWIDTH), .NUM_STREAMS(NUM_STREAMS)) axis(.clk(clk)); + + // Check that stream is actually in use + function void check_stream(int stream); + assert (stream < NUM_STREAMS) else + $error("axis_master::check_stream(): Tried to perform operation on unused stream %0d", stream); + endfunction + + // Reset signals / properties used by this interface + task automatic reset; + begin + axis.tvalid = 0; + axis.tlast = 0; + axis.tdata = 0; + end + endtask + + // Push a word onto the AXI-Stream bus and wait for it to transfer + // Args: + // - word: The data to push onto the bus + // - eop (optional): End of packet (asserts tlast) + // - stream: Stream to use (Optional) + task automatic push_word ( + input logic [DWIDTH-1:0] word, + input logic eop = 1'b0, + input int stream = 0); + begin + check_stream(stream); + if (clk) @(negedge clk); // Align with negative edge + axis.tvalid[stream] = 1; + axis.tlast[stream] = eop; + axis.tdata[DWIDTH*stream +: DWIDTH] = word; + @(posedge clk); // Put sample on data bus + while(~axis.tready[stream]) @(posedge clk); // Wait until receiver ready + @(negedge clk); // Put sample on data bus + axis.tvalid[stream] = 0; + axis.tlast[stream] = 0; + end + endtask + + // Push a bubble cycle onto the AXI-Stream bus + // Args: + // - stream: Stream to use (Optional) + task automatic push_bubble (input int stream = 0); + begin + check_stream(stream); + axis.tvalid[stream] = 0; + @(negedge clk); + end + endtask + + // Push a packet with random data onto to the AXI Stream bus + // Args: + // - num_samps: Packet size. + task automatic push_rand_pkt ( + input int num_samps, + input int stream = 0); + begin + check_stream(stream); + if (clk) @(negedge clk); + repeat(num_samps-1) begin + push_word({(((DWIDTH-1)/32)+1){$random}}, 0, stream); + end + push_word({(((DWIDTH-1)/32)+1){$random}}, 1, stream); + end + endtask + + // Push a packet with a ramp on to the AXI Stream bus + // Args: + // - num_samps: Packet size. + // - ramp_start: Start value for the ramp + // - ramp_inc: Increment per clock cycle + // - stream: Stream to use (Optional) + task automatic push_ramp_pkt ( + input integer num_samps, + input [DWIDTH-1:0] ramp_start, + input [DWIDTH-1:0] ramp_inc, + input int stream = 0); + begin + automatic integer counter = 0; + check_stream(stream); + if (clk) @(negedge clk); + repeat(num_samps-1) begin + push_word(ramp_start+(counter*ramp_inc), 0, stream); + counter = counter + 1; + end + push_word(ramp_start+(counter*ramp_inc), 1, stream); + end + endtask + +endinterface + + +// Interface to push data onto a master AXI-stream bus +interface axis_slave #(parameter DWIDTH = 32, parameter NUM_STREAMS = 1)(input clk); + axis_t #(.DWIDTH(DWIDTH), .NUM_STREAMS(NUM_STREAMS)) axis(.clk(clk)); + + // Check that stream is actually in use + function void check_stream(int stream); + assert (stream < NUM_STREAMS) else + $error("axis_slave::check_stream(): Tried to perform operation on unused stream %0d", stream); + endfunction + + // Reset signals / properties used by this interface + task automatic reset; + begin + axis.tready = 0; + end + endtask + + // Pull a word from the AXI Stream bus and + // return the data and last + // Args: + // - word: The data pulled from the bus + // - eop: End of packet (tlast) + // - stream: Stream to use (Optional) + task automatic pull_word ( + output logic [DWIDTH-1:0] word, + output logic eop, + input int stream = 0); + begin + check_stream(stream); + if (clk) @(negedge clk); + axis.tready[stream] = 1; + while(~axis.tvalid[stream]) @(posedge clk); + word = axis.tdata[DWIDTH*stream +: DWIDTH]; + eop = axis.tlast[stream]; + @(negedge clk); + axis.tready[stream] = 0; + end + endtask + + // Wait for a sample to be transferred on the AXI Stream + // bus and return the data and last. Note, this task only + // observes the bus and does not affect the AXI control + // signals. + // Args: + // - word: The data pulled from the bus + // - eop: End of packet (tlast) + // - stream: Stream to use (Optional) + task automatic copy_word ( + output logic [DWIDTH-1:0] word, + output logic eop, + input int stream = 0); + begin + check_stream(stream); + while(~(axis.tready[stream]&axis.tvalid[stream])) @(posedge clk); // Wait until sample is transferred + word = axis.tdata[DWIDTH*stream +: DWIDTH]; + eop = axis.tlast[stream]; + @(negedge clk); + end + endtask + + // Wait for a bubble cycle on the AXI Stream bus + // Args: + // - stream: Stream to use (Optional) + task automatic wait_for_bubble ( + input int stream = 0); + begin + check_stream(stream); + while(axis.tready[stream]&axis.tvalid[stream]) @(posedge clk); + @(negedge clk); + end + endtask + + // Wait for a packet to finish on the bus + // Args: + // - stream: Stream to use (Optional) + task automatic wait_for_pkt ( + input int stream = 0); + begin + check_stream(stream); + while(~(axis.tready[stream]&axis.tvalid[stream]&axis.tlast[stream])) @(posedge clk); + @(negedge clk); + end + endtask + + // Drop a word on the bus + // Args: + // - stream: Stream to use (Optional) + task automatic drop_word ( + input int stream = 0); + begin + logic [DWIDTH-1:0] dropped_word; + logic dropped_eop; + pull_word(dropped_word, dropped_eop, stream); + end + endtask + +endinterface + +`endif
\ No newline at end of file |