diff --git a/rtl/axis_ll_bridge.v b/rtl/axis_ll_bridge.v new file mode 100644 index 000000000..06186aef7 --- /dev/null +++ b/rtl/axis_ll_bridge.v @@ -0,0 +1,79 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream to LocalLink bridge + */ +module axis_ll_bridge # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] axis_tdata, + input wire axis_tvalid, + output wire axis_tready, + input wire axis_tlast, + + /* + * LocalLink output + */ + output wire [DATA_WIDTH-1:0] ll_data_out, + output wire ll_sof_out_n, + output wire ll_eof_out_n, + output wire ll_src_rdy_out_n, + input wire ll_dst_rdy_in_n +); + +reg last_tlast = 1'b1; + +always @(posedge clk or posedge rst) begin + if (rst) begin + last_tlast = 1'b1; + end else begin + if (axis_tvalid & axis_tready) last_tlast = axis_tlast; + end +end + +// high for packet length 1 -> cannot set SOF and EOF in same cycle +// invalid packets are discarded +wire invalid = axis_tvalid & axis_tlast & last_tlast; + +assign axis_tready = ~ll_dst_rdy_in_n; + +assign ll_data_out = axis_tdata; +assign ll_sof_out_n = ~(last_tlast & axis_tvalid & ~invalid); +assign ll_eof_out_n = ~(axis_tlast & ~invalid); +assign ll_src_rdy_out_n = ~(axis_tvalid & ~invalid); + +endmodule diff --git a/rtl/ll_axis_bridge.v b/rtl/ll_axis_bridge.v new file mode 100644 index 000000000..99733536c --- /dev/null +++ b/rtl/ll_axis_bridge.v @@ -0,0 +1,64 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * LocalLink to AXI4-Stream bridge + */ +module ll_axis_bridge # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * LocalLink input + */ + input wire [DATA_WIDTH-1:0] ll_data_in, + input wire ll_sof_in_n, + input wire ll_eof_in_n, + input wire ll_src_rdy_in_n, + output wire ll_dst_rdy_out_n, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] axis_tdata, + output wire axis_tvalid, + input wire axis_tready, + output wire axis_tlast +); + +assign axis_tdata = ll_data_in; +assign axis_tvalid = ~ll_src_rdy_in_n; +assign axis_tlast = ~ll_eof_in_n; + +assign ll_dst_rdy_out_n = ~axis_tready; + +endmodule diff --git a/tb/ll_ep.py b/tb/ll_ep.py new file mode 100644 index 000000000..d69346be6 --- /dev/null +++ b/tb/ll_ep.py @@ -0,0 +1,123 @@ +""" + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +from myhdl import * + +def LocalLinkSource(clk, rst, + data_out, + sof_out_n, + eof_out_n, + src_rdy_out_n, + dst_rdy_in_n, + fifo, + pause=0, + name=None): + + src_rdy_out_n_int = Signal(bool(True)) + dst_rdy_in_n_int = Signal(bool(True)) + + @always_comb + def pause_logic(): + dst_rdy_in_n_int.next = dst_rdy_in_n or pause + src_rdy_out_n.next = src_rdy_out_n_int or pause + + @instance + def logic(): + frame = [] + + while True: + yield clk.posedge, rst.posedge + + if rst: + data_out.next = 0 + src_rdy_out_n_int.next = True + sof_out_n.next = True + eof_out_n.next = True + else: + if not dst_rdy_in_n_int and not src_rdy_out_n: + if len(frame) > 0: + data_out.next = frame.pop(0) + src_rdy_out_n_int.next = False + sof_out_n.next = True + eof_out_n.next = len(frame) != 0 + else: + src_rdy_out_n_int.next = True + eof_out_n.next = True + if (not eof_out_n and not dst_rdy_in_n_int and not src_rdy_out_n) or src_rdy_out_n_int: + if not fifo.empty(): + frame = fifo.get() + if name is not None: + print("[%s] Sending frame %s" % (name, repr(frame))) + data_out.next = frame.pop(0) + src_rdy_out_n_int.next = False + sof_out_n.next = False + eof_out_n.next = len(frame) != 0 + + return logic, pause_logic + + +def LocalLinkSink(clk, rst, + data_in, + sof_in_n, + eof_in_n, + src_rdy_in_n, + dst_rdy_out_n, + fifo=None, + pause=0, + name=None): + + src_rdy_in_n_int = Signal(bool(True)) + dst_rdy_out_n_int = Signal(bool(True)) + + @always_comb + def pause_logic(): + dst_rdy_out_n.next = dst_rdy_out_n_int or pause + src_rdy_in_n_int.next = src_rdy_in_n or pause + + @instance + def logic(): + frame = [] + + while True: + yield clk.posedge, rst.posedge + + if rst: + dst_rdy_out_n_int.next = True + frame = [] + else: + dst_rdy_out_n_int.next = False + + if not src_rdy_in_n_int: + if not sof_in_n: + frame = [] + frame.append(int(data_in)) + if not eof_in_n: + if fifo is not None: + fifo.put(frame) + if name is not None: + print("[%s] Got frame %s" % (name, repr(frame))) + frame = [] + + return logic, pause_logic + diff --git a/tb/test_axis_ll_bridge.py b/tb/test_axis_ll_bridge.py new file mode 100755 index 000000000..21e6d7a43 --- /dev/null +++ b/tb/test_axis_ll_bridge.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python2 +""" + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +from myhdl import * +import os +from Queue import Queue + +import axis_ep +import ll_ep + +module = 'axis_ll_bridge' + +srcs = [] + +srcs.append("../rtl/%s.v" % module) +srcs.append("test_%s.v" % module) + +src = ' '.join(srcs) + +build_cmd = "iverilog -o test_%s.vvp %s" % (module, src) + +def dut_axis_ll_bridge(clk, + rst, + current_test, + + axis_tdata, + axis_tvalid, + axis_tready, + axis_tlast, + + ll_data_out, + ll_sof_out_n, + ll_eof_out_n, + ll_src_rdy_out_n, + ll_dst_rdy_in_n): + + if os.system(build_cmd): + raise Exception("Error running build command") + return Cosimulation("vvp -m myhdl test_%s.vvp -lxt2" % module, + clk=clk, + rst=rst, + current_test=current_test, + + axis_tdata=axis_tdata, + axis_tvalid=axis_tvalid, + axis_tready=axis_tready, + axis_tlast=axis_tlast, + + ll_data_out=ll_data_out, + ll_sof_out_n=ll_sof_out_n, + ll_eof_out_n=ll_eof_out_n, + ll_src_rdy_out_n=ll_src_rdy_out_n, + ll_dst_rdy_in_n=ll_dst_rdy_in_n) + +def bench(): + + # Inputs + clk = Signal(bool(0)) + rst = Signal(bool(0)) + current_test = Signal(intbv(0)[8:]) + + axis_tdata = Signal(intbv(0)[8:]) + axis_tvalid = Signal(bool(0)) + axis_tlast = Signal(bool(0)) + ll_dst_rdy_in_n = Signal(bool(1)) + + # Outputs + ll_data_out = Signal(intbv(0)[8:]) + ll_sof_out_n = Signal(bool(1)) + ll_eof_out_n = Signal(bool(1)) + ll_src_rdy_out_n = Signal(bool(1)) + axis_tready = Signal(bool(0)) + + # sources and sinks + source_queue = Queue() + source_pause = Signal(bool(0)) + sink_queue = Queue() + sink_pause = Signal(bool(0)) + + source = axis_ep.AXIStreamSource(clk, + rst, + tdata=axis_tdata, + tvalid=axis_tvalid, + tready=axis_tready, + tlast=axis_tlast, + fifo=source_queue, + pause=source_pause, + name='source') + + sink = ll_ep.LocalLinkSink(clk, + rst, + data_in=ll_data_out, + sof_in_n=ll_sof_out_n, + eof_in_n=ll_eof_out_n, + src_rdy_in_n=ll_src_rdy_out_n, + dst_rdy_out_n=ll_dst_rdy_in_n, + fifo=sink_queue, + pause=sink_pause, + name='sink') + + # DUT + dut = dut_axis_ll_bridge(clk, + rst, + current_test, + + axis_tdata, + axis_tvalid, + axis_tready, + axis_tlast, + + ll_data_out, + ll_sof_out_n, + ll_eof_out_n, + ll_src_rdy_out_n, + ll_dst_rdy_in_n) + + @always(delay(4)) + def clkgen(): + clk.next = not clk + + @instance + def check(): + yield delay(100) + yield clk.posedge + rst.next = 1 + yield clk.posedge + rst.next = 0 + yield clk.posedge + yield delay(100) + yield clk.posedge + + yield clk.posedge + + yield clk.posedge + print("test 1: test packet") + current_test.next = 1 + + source_queue.put(bytearray(b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10')) + yield clk.posedge + + yield ll_eof_out_n.negedge + yield clk.posedge + yield clk.posedge + + rx_frame = None + if not sink_queue.empty(): + rx_frame = sink_queue.get() + + assert bytearray(rx_frame) == (b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10') + + yield delay(100) + + yield clk.posedge + print("test 2: test packet with pauses") + current_test.next = 2 + + source_queue.put(bytearray(b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10')) + yield clk.posedge + + yield delay(64) + yield clk.posedge + source_pause.next = True + yield delay(32) + yield clk.posedge + source_pause.next = False + + yield delay(64) + yield clk.posedge + sink_pause.next = True + yield delay(32) + yield clk.posedge + sink_pause.next = False + + yield ll_eof_out_n.negedge + yield clk.posedge + yield clk.posedge + + rx_frame = None + if not sink_queue.empty(): + rx_frame = sink_queue.get() + + assert bytearray(rx_frame) == (b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10') + + yield delay(100) + + raise StopSimulation + + return dut, source, sink, clkgen, check + +def test_bench(): + os.chdir(os.path.dirname(os.path.abspath(__file__))) + sim = Simulation(bench()) + sim.run() + +if __name__ == '__main__': + print("Running test...") + test_bench() + diff --git a/tb/test_axis_ll_bridge.v b/tb/test_axis_ll_bridge.v new file mode 100644 index 000000000..680b570b9 --- /dev/null +++ b/tb/test_axis_ll_bridge.v @@ -0,0 +1,85 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1 ns / 1 ps + +module test_axis_ll_bridge; + +// Inputs +reg clk = 0; +reg rst = 0; +reg [7:0] current_test = 0; + +reg [7:0] axis_tdata = 8'd0; +reg axis_tvalid = 1'b0; +reg axis_tlast = 1'b0; +reg ll_dst_rdy_in_n = 1'b1; + +// Outputs +wire [7:0] ll_data_out; +wire ll_sof_out_n; +wire ll_eof_out_n; +wire ll_src_rdy_out_n; +wire axis_tready; + +initial begin + // myhdl integration + $from_myhdl(clk, + rst, + current_test, + axis_tdata, + axis_tvalid, + axis_tlast, + ll_dst_rdy_in_n); + $to_myhdl(ll_data_out, + ll_sof_out_n, + ll_eof_out_n, + ll_src_rdy_out_n, + axis_tready); + + // dump file + $dumpfile("test_axis_ll_bridge.lxt"); + $dumpvars(0, test_axis_ll_bridge); +end + +axis_ll_bridge +UUT ( + .clk(clk), + .rst(rst), + // axi input + .axis_tdata(axis_tdata), + .axis_tvalid(axis_tvalid), + .axis_tready(axis_tready), + .axis_tlast(axis_tlast), + // locallink output + .ll_data_out(ll_data_out), + .ll_sof_out_n(ll_sof_out_n), + .ll_eof_out_n(ll_eof_out_n), + .ll_src_rdy_out_n(ll_src_rdy_out_n), + .ll_dst_rdy_in_n(ll_dst_rdy_in_n) +); + +endmodule diff --git a/tb/test_ll_axis_bridge.py b/tb/test_ll_axis_bridge.py new file mode 100755 index 000000000..7c6ca681d --- /dev/null +++ b/tb/test_ll_axis_bridge.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python2 +""" + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +from myhdl import * +import os +from Queue import Queue + +import axis_ep +import ll_ep + +module = 'll_axis_bridge' + +srcs = [] + +srcs.append("../rtl/%s.v" % module) +srcs.append("test_%s.v" % module) + +src = ' '.join(srcs) + +build_cmd = "iverilog -o test_%s.vvp %s" % (module, src) + +def dut_ll_axis_bridge(clk, + rst, + current_test, + + ll_data_in, + ll_sof_in_n, + ll_eof_in_n, + ll_src_rdy_in_n, + ll_dst_rdy_out_n, + + axis_tdata, + axis_tvalid, + axis_tready, + axis_tlast): + + os.system(build_cmd) + return Cosimulation("vvp -m myhdl test_%s.vvp -lxt2" % module, + clk=clk, + rst=rst, + current_test=current_test, + + ll_data_in=ll_data_in, + ll_sof_in_n=ll_sof_in_n, + ll_eof_in_n=ll_eof_in_n, + ll_src_rdy_in_n=ll_src_rdy_in_n, + ll_dst_rdy_out_n=ll_dst_rdy_out_n, + + axis_tdata=axis_tdata, + axis_tvalid=axis_tvalid, + axis_tready=axis_tready, + axis_tlast=axis_tlast) + +def bench(): + + # Inputs + clk = Signal(bool(0)) + rst = Signal(bool(0)) + current_test = Signal(intbv(0)[8:]) + + ll_data_in = Signal(intbv(0)[8:]) + ll_sof_in_n = Signal(bool(1)) + ll_eof_in_n = Signal(bool(1)) + ll_src_rdy_in_n = Signal(bool(1)) + axis_tready = Signal(bool(0)) + + # Outputs + axis_tdata = Signal(intbv(0)[8:]) + axis_tvalid = Signal(bool(0)) + axis_tlast = Signal(bool(0)) + ll_dst_rdy_out_n = Signal(bool(1)) + + # sources and sinks + source_queue = Queue() + source_pause = Signal(bool(0)) + sink_queue = Queue() + sink_pause = Signal(bool(0)) + + source = ll_ep.LocalLinkSource(clk, + rst, + data_out=ll_data_in, + sof_out_n=ll_sof_in_n, + eof_out_n=ll_eof_in_n, + src_rdy_out_n=ll_src_rdy_in_n, + dst_rdy_in_n=ll_dst_rdy_out_n, + fifo=source_queue, + pause=source_pause, + name='source') + + sink = axis_ep.AXIStreamSink(clk, + rst, + tdata=axis_tdata, + tvalid=axis_tvalid, + tready=axis_tready, + tlast=axis_tlast, + fifo=sink_queue, + pause=sink_pause, + name='sink') + + # DUT + dut = dut_ll_axis_bridge(clk, + rst, + current_test, + + ll_data_in, + ll_sof_in_n, + ll_eof_in_n, + ll_src_rdy_in_n, + ll_dst_rdy_out_n, + + axis_tdata, + axis_tvalid, + axis_tready, + axis_tlast) + + @always(delay(4)) + def clkgen(): + clk.next = not clk + + @instance + def check(): + yield delay(100) + yield clk.posedge + rst.next = 1 + yield clk.posedge + rst.next = 0 + yield clk.posedge + yield delay(100) + yield clk.posedge + + yield clk.posedge + + yield clk.posedge + print("test 1: test packet") + current_test.next = 1 + + source_queue.put(bytearray(b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10')) + yield clk.posedge + + yield axis_tlast.negedge + yield clk.posedge + yield clk.posedge + + rx_frame = None + if not sink_queue.empty(): + rx_frame = sink_queue.get() + + assert bytearray(rx_frame) == (b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10') + + yield delay(100) + + yield clk.posedge + print("test 2: test packet with pauses") + current_test.next = 2 + + source_queue.put(bytearray(b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10')) + yield clk.posedge + + yield delay(64) + yield clk.posedge + source_pause.next = True + yield delay(32) + yield clk.posedge + source_pause.next = False + + yield delay(64) + yield clk.posedge + sink_pause.next = True + yield delay(32) + yield clk.posedge + sink_pause.next = False + + yield axis_tlast.negedge + yield clk.posedge + yield clk.posedge + + rx_frame = None + if not sink_queue.empty(): + rx_frame = sink_queue.get() + + assert bytearray(rx_frame) == (b'\xDA\xD1\xD2\xD3\xD4\xD5' + + b'\x5A\x51\x52\x53\x54\x55' + + b'\x80\x00' + + b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10') + + yield delay(100) + + raise StopSimulation + + return dut, source, sink, clkgen, check + +def test_bench(): + os.chdir(os.path.dirname(os.path.abspath(__file__))) + sim = Simulation(bench()) + sim.run() + +if __name__ == '__main__': + print("Running test...") + test_bench() + diff --git a/tb/test_ll_axis_bridge.v b/tb/test_ll_axis_bridge.v new file mode 100644 index 000000000..573fec7c5 --- /dev/null +++ b/tb/test_ll_axis_bridge.v @@ -0,0 +1,85 @@ +/* + +Copyright (c) 2014 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1 ns / 1 ps + +module test_ll_axis_bridge; + +// Inputs +reg clk = 0; +reg rst = 0; +reg [7:0] current_test = 0; + +reg [7:0] ll_data_in = 0; +reg ll_sof_in_n = 1; +reg ll_eof_in_n = 1; +reg ll_src_rdy_in_n = 1; +reg axis_tready = 0; + +// Outputs +wire ll_dst_rdy_out_n; +wire [7:0] axis_tdata; +wire axis_tvalid; +wire axis_tlast; + +initial begin + // myhdl integration + $from_myhdl(clk, + rst, + current_test, + ll_data_in, + ll_sof_in_n, + ll_eof_in_n, + ll_src_rdy_in_n, + axis_tready); + $to_myhdl(axis_tdata, + axis_tvalid, + axis_tlast, + ll_dst_rdy_out_n); + + // dump file + $dumpfile("test_ll_axis_bridge.lxt"); + $dumpvars(0, test_ll_axis_bridge); +end + +ll_axis_bridge +UUT ( + .clk(clk), + .rst(rst), + // locallink input + .ll_data_in(ll_data_in), + .ll_sof_in_n(ll_sof_in_n), + .ll_eof_in_n(ll_eof_in_n), + .ll_src_rdy_in_n(ll_src_rdy_in_n), + .ll_dst_rdy_out_n(ll_dst_rdy_out_n), + // axi output + .axis_tdata(axis_tdata), + .axis_tvalid(axis_tvalid), + .axis_tready(axis_tready), + .axis_tlast(axis_tlast) +); + +endmodule