From 2bf15706cd876415f56b5c8e74445ceb29899d20 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 24 Oct 2018 18:23:14 -0700 Subject: [PATCH] Convert generated mux to verilog parametrized mux --- rtl/axis_mux.py | 354 -------------------------------------- rtl/axis_mux.v | 253 +++++++++++++++++++++++++++ rtl/axis_mux_4.v | 363 --------------------------------------- tb/test_axis_mux_4.py | 276 +++++++++++------------------ tb/test_axis_mux_4.v | 174 ++++++------------- tb/test_axis_mux_4_64.py | 276 +++++++++++------------------ tb/test_axis_mux_4_64.v | 174 ++++++------------- 7 files changed, 549 insertions(+), 1321 deletions(-) delete mode 100755 rtl/axis_mux.py create mode 100644 rtl/axis_mux.v delete mode 100644 rtl/axis_mux_4.v diff --git a/rtl/axis_mux.py b/rtl/axis_mux.py deleted file mode 100755 index e327e21f..00000000 --- a/rtl/axis_mux.py +++ /dev/null @@ -1,354 +0,0 @@ -#!/usr/bin/env python -""" -Generates an AXI Stream mux with the specified number of ports -""" - -from __future__ import print_function - -import argparse -import math -from jinja2 import Template - -def main(): - parser = argparse.ArgumentParser(description=__doc__.strip()) - parser.add_argument('-p', '--ports', type=int, default=4, help="number of ports") - parser.add_argument('-n', '--name', type=str, help="module name") - parser.add_argument('-o', '--output', type=str, help="output file name") - - args = parser.parse_args() - - try: - generate(**args.__dict__) - except IOError as ex: - print(ex) - exit(1) - -def generate(ports=4, name=None, output=None): - if name is None: - name = "axis_mux_{0}".format(ports) - - if output is None: - output = name + ".v" - - print("Opening file '{0}'...".format(output)) - - output_file = open(output, 'w') - - print("Generating {0} port AXI Stream mux {1}...".format(ports, name)) - - select_width = int(math.ceil(math.log(ports, 2))) - - t = Template(u"""/* - -Copyright (c) 2014-2018 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 {{n}} port multiplexer - */ -module {{name}} # -( - parameter DATA_WIDTH = 8, - parameter KEEP_ENABLE = (DATA_WIDTH>8), - parameter KEEP_WIDTH = (DATA_WIDTH/8), - parameter ID_ENABLE = 0, - parameter ID_WIDTH = 8, - parameter DEST_ENABLE = 0, - parameter DEST_WIDTH = 8, - parameter USER_ENABLE = 1, - parameter USER_WIDTH = 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI inputs - */ -{%- for p in ports %} - input wire [DATA_WIDTH-1:0] input_{{p}}_axis_tdata, - input wire [KEEP_WIDTH-1:0] input_{{p}}_axis_tkeep, - input wire input_{{p}}_axis_tvalid, - output wire input_{{p}}_axis_tready, - input wire input_{{p}}_axis_tlast, - input wire [ID_WIDTH-1:0] input_{{p}}_axis_tid, - input wire [DEST_WIDTH-1:0] input_{{p}}_axis_tdest, - input wire [USER_WIDTH-1:0] input_{{p}}_axis_tuser, -{% endfor %} - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] output_axis_tdata, - output wire [KEEP_WIDTH-1:0] output_axis_tkeep, - output wire output_axis_tvalid, - input wire output_axis_tready, - output wire output_axis_tlast, - output wire [ID_WIDTH-1:0] output_axis_tid, - output wire [DEST_WIDTH-1:0] output_axis_tdest, - output wire [USER_WIDTH-1:0] output_axis_tuser, - - /* - * Control - */ - input wire enable, - input wire [{{w-1}}:0] select -); - -reg [{{w-1}}:0] select_reg = {{w}}'d0, select_next; -reg frame_reg = 1'b0, frame_next; -{% for p in ports %} -reg input_{{p}}_axis_tready_reg = 1'b0, input_{{p}}_axis_tready_next; -{%- endfor %} - -// internal datapath -reg [DATA_WIDTH-1:0] output_axis_tdata_int; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; -reg output_axis_tvalid_int; -reg output_axis_tready_int_reg = 1'b0; -reg output_axis_tlast_int; -reg [ID_WIDTH-1:0] output_axis_tid_int; -reg [DEST_WIDTH-1:0] output_axis_tdest_int; -reg [USER_WIDTH-1:0] output_axis_tuser_int; -wire output_axis_tready_int_early; -{% for p in ports %} -assign input_{{p}}_axis_tready = input_{{p}}_axis_tready_reg; -{%- endfor %} - -// mux for start of packet detection -reg selected_input_tvalid; -always @* begin - case (select) -{%- for p in ports %} - {{w}}'d{{p}}: selected_input_tvalid = input_{{p}}_axis_tvalid; -{%- endfor %} - default: selected_input_tvalid = 1'b0; - endcase -end - -// mux for incoming packet -reg [DATA_WIDTH-1:0] current_input_tdata; -reg [KEEP_WIDTH-1:0] current_input_tkeep; -reg current_input_tvalid; -reg current_input_tready; -reg current_input_tlast; -reg [ID_WIDTH-1:0] current_input_tid; -reg [DEST_WIDTH-1:0] current_input_tdest; -reg [USER_WIDTH-1:0] current_input_tuser; -always @* begin - case (select_reg) -{%- for p in ports %} - {{w}}'d{{p}}: begin - current_input_tdata = input_{{p}}_axis_tdata; - current_input_tkeep = input_{{p}}_axis_tkeep; - current_input_tvalid = input_{{p}}_axis_tvalid; - current_input_tready = input_{{p}}_axis_tready; - current_input_tlast = input_{{p}}_axis_tlast; - current_input_tid = input_{{p}}_axis_tid; - current_input_tdest = input_{{p}}_axis_tdest; - current_input_tuser = input_{{p}}_axis_tuser; - end -{%- endfor %} - default: begin - current_input_tdata = {DATA_WIDTH{1'b0}}; - current_input_tkeep = {KEEP_WIDTH{1'b0}}; - current_input_tvalid = 1'b0; - current_input_tready = 1'b0; - current_input_tlast = 1'b0; - current_input_tid = {ID_WIDTH{1'b0}}; - current_input_tdest = {DEST_WIDTH{1'b0}}; - current_input_tuser = {USER_WIDTH{1'b0}}; - end - endcase -end - -always @* begin - select_next = select_reg; - frame_next = frame_reg; -{% for p in ports %} - input_{{p}}_axis_tready_next = 1'b0; -{%- endfor %} - - if (current_input_tvalid & current_input_tready) begin - // end of frame detection - if (current_input_tlast) begin - frame_next = 1'b0; - end - end - - if (~frame_reg & enable & selected_input_tvalid) begin - // start of frame, grab select value - frame_next = 1'b1; - select_next = select; - end - - // generate ready signal on selected port - case (select_next) -{%- for p in ports %} - {{w}}'d{{p}}: input_{{p}}_axis_tready_next = output_axis_tready_int_early & frame_next; -{%- endfor %} - endcase - - // pass through selected packet data - output_axis_tdata_int = current_input_tdata; - output_axis_tkeep_int = current_input_tkeep; - output_axis_tvalid_int = current_input_tvalid & current_input_tready & frame_reg; - output_axis_tlast_int = current_input_tlast; - output_axis_tid_int = current_input_tid; - output_axis_tdest_int = current_input_tdest; - output_axis_tuser_int = current_input_tuser; -end - -always @(posedge clk) begin - if (rst) begin - select_reg <= {{w}}'d0; - frame_reg <= 1'b0; -{%- for p in ports %} - input_{{p}}_axis_tready_reg <= 1'b0; -{%- endfor %} - end else begin - select_reg <= select_next; - frame_reg <= frame_next; -{%- for p in ports %} - input_{{p}}_axis_tready_reg <= input_{{p}}_axis_tready_next; -{%- endfor %} - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; -reg output_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] output_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] output_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] output_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; -reg temp_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] temp_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] temp_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] temp_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign output_axis_tdata = output_axis_tdata_reg; -assign output_axis_tkeep = KEEP_ENABLE ? output_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign output_axis_tvalid = output_axis_tvalid_reg; -assign output_axis_tlast = output_axis_tlast_reg; -assign output_axis_tid = ID_ENABLE ? output_axis_tid_reg : {ID_WIDTH{1'b0}}; -assign output_axis_tdest = DEST_ENABLE ? output_axis_tdest_reg : {DEST_WIDTH{1'b0}}; -assign output_axis_tuser = USER_ENABLE ? output_axis_tuser_reg : {USER_WIDTH{1'b0}}; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); - -always @* begin - // transfer sink ready state to source - output_axis_tvalid_next = output_axis_tvalid_reg; - temp_axis_tvalid_next = temp_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (output_axis_tready_int_reg) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tvalid_next = output_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_axis_tvalid_next = output_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tvalid_next = temp_axis_tvalid_reg; - temp_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - output_axis_tvalid_reg <= 1'b0; - output_axis_tready_int_reg <= 1'b0; - temp_axis_tvalid_reg <= 1'b0; - end else begin - output_axis_tvalid_reg <= output_axis_tvalid_next; - output_axis_tready_int_reg <= output_axis_tready_int_early; - temp_axis_tvalid_reg <= temp_axis_tvalid_next; - end - - // datapath - if (store_axis_int_to_output) begin - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tid_reg <= output_axis_tid_int; - output_axis_tdest_reg <= output_axis_tdest_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tid_reg <= temp_axis_tid_reg; - output_axis_tdest_reg <= temp_axis_tdest_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tid_reg <= output_axis_tid_int; - temp_axis_tdest_reg <= output_axis_tdest_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end -end - -endmodule - -""") - - output_file.write(t.render( - n=ports, - w=select_width, - name=name, - ports=range(ports) - )) - - print("Done") - -if __name__ == "__main__": - main() - diff --git a/rtl/axis_mux.v b/rtl/axis_mux.v new file mode 100644 index 00000000..fcec2467 --- /dev/null +++ b/rtl/axis_mux.v @@ -0,0 +1,253 @@ +/* + +Copyright (c) 2014-2018 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 multiplexer + */ +module axis_mux # +( + parameter S_COUNT = 4, + parameter DATA_WIDTH = 8, + parameter KEEP_ENABLE = (DATA_WIDTH>8), + parameter KEEP_WIDTH = (DATA_WIDTH/8), + parameter ID_ENABLE = 0, + parameter ID_WIDTH = 8, + parameter DEST_ENABLE = 0, + parameter DEST_WIDTH = 8, + parameter USER_ENABLE = 1, + parameter USER_WIDTH = 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI inputs + */ + input wire [S_COUNT*DATA_WIDTH-1:0] s_axis_tdata, + input wire [S_COUNT*KEEP_WIDTH-1:0] s_axis_tkeep, + input wire [S_COUNT-1:0] s_axis_tvalid, + output wire [S_COUNT-1:0] s_axis_tready, + input wire [S_COUNT-1:0] s_axis_tlast, + input wire [S_COUNT*ID_WIDTH-1:0] s_axis_tid, + input wire [S_COUNT*DEST_WIDTH-1:0] s_axis_tdest, + input wire [S_COUNT*USER_WIDTH-1:0] s_axis_tuser, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire [KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire [ID_WIDTH-1:0] m_axis_tid, + output wire [DEST_WIDTH-1:0] m_axis_tdest, + output wire [USER_WIDTH-1:0] m_axis_tuser, + + /* + * Control + */ + input wire enable, + input wire [$clog2(S_COUNT)-1:0] select +); + +parameter CL_S_COUNT = $clog2(S_COUNT); + +reg [CL_S_COUNT-1:0] select_reg = 2'd0, select_next; +reg frame_reg = 1'b0, frame_next; + +reg [S_COUNT-1:0] s_axis_tready_reg = 0, s_axis_tready_next; + +// internal datapath +reg [DATA_WIDTH-1:0] m_axis_tdata_int; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; +reg m_axis_tvalid_int; +reg m_axis_tready_int_reg = 1'b0; +reg m_axis_tlast_int; +reg [ID_WIDTH-1:0] m_axis_tid_int; +reg [DEST_WIDTH-1:0] m_axis_tdest_int; +reg [USER_WIDTH-1:0] m_axis_tuser_int; +wire m_axis_tready_int_early; + +assign s_axis_tready = s_axis_tready_reg; + +// mux for incoming packet +wire [DATA_WIDTH-1:0] current_s_tdata = s_axis_tdata[select_reg*DATA_WIDTH +: DATA_WIDTH]; +wire [KEEP_WIDTH-1:0] current_s_tkeep = s_axis_tkeep[select_reg*KEEP_WIDTH +: KEEP_WIDTH]; +wire current_s_tvalid = s_axis_tvalid[select_reg]; +wire current_s_tready = s_axis_tready[select_reg]; +wire current_s_tlast = s_axis_tlast[select_reg]; +wire [ID_WIDTH-1:0] current_s_tid = s_axis_tid[select_reg*ID_WIDTH +: ID_WIDTH]; +wire [DEST_WIDTH-1:0] current_s_tdest = s_axis_tdest[select_reg*DEST_WIDTH +: DEST_WIDTH]; +wire [USER_WIDTH-1:0] current_s_tuser = s_axis_tuser[select_reg*USER_WIDTH +: USER_WIDTH]; + +always @* begin + select_next = select_reg; + frame_next = frame_reg; + + s_axis_tready_next = 0; + + if (current_s_tvalid & current_s_tready) begin + // end of frame detection + if (current_s_tlast) begin + frame_next = 1'b0; + end + end + + if (~frame_reg && enable && (s_axis_tvalid & (1 << select))) begin + // start of frame, grab select value + frame_next = 1'b1; + select_next = select; + end + + // generate ready signal on selected port + s_axis_tready_next = (m_axis_tready_int_early && frame_next) << select_next; + + // pass through selected packet data + m_axis_tdata_int = current_s_tdata; + m_axis_tkeep_int = current_s_tkeep; + m_axis_tvalid_int = current_s_tvalid && current_s_tready && frame_reg; + m_axis_tlast_int = current_s_tlast; + m_axis_tid_int = current_s_tid; + m_axis_tdest_int = current_s_tdest; + m_axis_tuser_int = current_s_tuser; +end + +always @(posedge clk) begin + if (rst) begin + select_reg <= 0; + frame_reg <= 1'b0; + s_axis_tready_reg <= 0; + end else begin + select_reg <= select_next; + frame_reg <= frame_next; + s_axis_tready_reg <= s_axis_tready_next; + end +end + +// output datapath logic +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; +reg m_axis_tlast_reg = 1'b0; +reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; +reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; +reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + +reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; +reg temp_m_axis_tlast_reg = 1'b0; +reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; +reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; +reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; +assign m_axis_tvalid = m_axis_tvalid_reg; +assign m_axis_tlast = m_axis_tlast_reg; +assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; +assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; +assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign m_axis_tready_int_early = m_axis_tready | (~temp_m_axis_tvalid_reg & (~m_axis_tvalid_reg | ~m_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + m_axis_tvalid_next = m_axis_tvalid_reg; + temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (m_axis_tready_int_reg) begin + // input is ready + if (m_axis_tready | ~m_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (m_axis_tready) begin + // input is not ready, but output is ready + m_axis_tvalid_next = temp_m_axis_tvalid_reg; + temp_m_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + m_axis_tvalid_reg <= 1'b0; + m_axis_tready_int_reg <= 1'b0; + temp_m_axis_tvalid_reg <= 1'b0; + end else begin + m_axis_tvalid_reg <= m_axis_tvalid_next; + m_axis_tready_int_reg <= m_axis_tready_int_early; + temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; + end + + // datapath + if (store_axis_int_to_output) begin + m_axis_tdata_reg <= m_axis_tdata_int; + m_axis_tkeep_reg <= m_axis_tkeep_int; + m_axis_tlast_reg <= m_axis_tlast_int; + m_axis_tid_reg <= m_axis_tid_int; + m_axis_tdest_reg <= m_axis_tdest_int; + m_axis_tuser_reg <= m_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + m_axis_tdata_reg <= temp_m_axis_tdata_reg; + m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; + m_axis_tlast_reg <= temp_m_axis_tlast_reg; + m_axis_tid_reg <= temp_m_axis_tid_reg; + m_axis_tdest_reg <= temp_m_axis_tdest_reg; + m_axis_tuser_reg <= temp_m_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_m_axis_tdata_reg <= m_axis_tdata_int; + temp_m_axis_tkeep_reg <= m_axis_tkeep_int; + temp_m_axis_tlast_reg <= m_axis_tlast_int; + temp_m_axis_tid_reg <= m_axis_tid_int; + temp_m_axis_tdest_reg <= m_axis_tdest_int; + temp_m_axis_tuser_reg <= m_axis_tuser_int; + end +end + +endmodule diff --git a/rtl/axis_mux_4.v b/rtl/axis_mux_4.v deleted file mode 100644 index dea78aca..00000000 --- a/rtl/axis_mux_4.v +++ /dev/null @@ -1,363 +0,0 @@ -/* - -Copyright (c) 2014-2018 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 4 port multiplexer - */ -module axis_mux_4 # -( - parameter DATA_WIDTH = 8, - parameter KEEP_ENABLE = (DATA_WIDTH>8), - parameter KEEP_WIDTH = (DATA_WIDTH/8), - parameter ID_ENABLE = 0, - parameter ID_WIDTH = 8, - parameter DEST_ENABLE = 0, - parameter DEST_WIDTH = 8, - parameter USER_ENABLE = 1, - parameter USER_WIDTH = 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI inputs - */ - input wire [DATA_WIDTH-1:0] input_0_axis_tdata, - input wire [KEEP_WIDTH-1:0] input_0_axis_tkeep, - input wire input_0_axis_tvalid, - output wire input_0_axis_tready, - input wire input_0_axis_tlast, - input wire [ID_WIDTH-1:0] input_0_axis_tid, - input wire [DEST_WIDTH-1:0] input_0_axis_tdest, - input wire [USER_WIDTH-1:0] input_0_axis_tuser, - - input wire [DATA_WIDTH-1:0] input_1_axis_tdata, - input wire [KEEP_WIDTH-1:0] input_1_axis_tkeep, - input wire input_1_axis_tvalid, - output wire input_1_axis_tready, - input wire input_1_axis_tlast, - input wire [ID_WIDTH-1:0] input_1_axis_tid, - input wire [DEST_WIDTH-1:0] input_1_axis_tdest, - input wire [USER_WIDTH-1:0] input_1_axis_tuser, - - input wire [DATA_WIDTH-1:0] input_2_axis_tdata, - input wire [KEEP_WIDTH-1:0] input_2_axis_tkeep, - input wire input_2_axis_tvalid, - output wire input_2_axis_tready, - input wire input_2_axis_tlast, - input wire [ID_WIDTH-1:0] input_2_axis_tid, - input wire [DEST_WIDTH-1:0] input_2_axis_tdest, - input wire [USER_WIDTH-1:0] input_2_axis_tuser, - - input wire [DATA_WIDTH-1:0] input_3_axis_tdata, - input wire [KEEP_WIDTH-1:0] input_3_axis_tkeep, - input wire input_3_axis_tvalid, - output wire input_3_axis_tready, - input wire input_3_axis_tlast, - input wire [ID_WIDTH-1:0] input_3_axis_tid, - input wire [DEST_WIDTH-1:0] input_3_axis_tdest, - input wire [USER_WIDTH-1:0] input_3_axis_tuser, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] output_axis_tdata, - output wire [KEEP_WIDTH-1:0] output_axis_tkeep, - output wire output_axis_tvalid, - input wire output_axis_tready, - output wire output_axis_tlast, - output wire [ID_WIDTH-1:0] output_axis_tid, - output wire [DEST_WIDTH-1:0] output_axis_tdest, - output wire [USER_WIDTH-1:0] output_axis_tuser, - - /* - * Control - */ - input wire enable, - input wire [1:0] select -); - -reg [1:0] select_reg = 2'd0, select_next; -reg frame_reg = 1'b0, frame_next; - -reg input_0_axis_tready_reg = 1'b0, input_0_axis_tready_next; -reg input_1_axis_tready_reg = 1'b0, input_1_axis_tready_next; -reg input_2_axis_tready_reg = 1'b0, input_2_axis_tready_next; -reg input_3_axis_tready_reg = 1'b0, input_3_axis_tready_next; - -// internal datapath -reg [DATA_WIDTH-1:0] output_axis_tdata_int; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_int; -reg output_axis_tvalid_int; -reg output_axis_tready_int_reg = 1'b0; -reg output_axis_tlast_int; -reg [ID_WIDTH-1:0] output_axis_tid_int; -reg [DEST_WIDTH-1:0] output_axis_tdest_int; -reg [USER_WIDTH-1:0] output_axis_tuser_int; -wire output_axis_tready_int_early; - -assign input_0_axis_tready = input_0_axis_tready_reg; -assign input_1_axis_tready = input_1_axis_tready_reg; -assign input_2_axis_tready = input_2_axis_tready_reg; -assign input_3_axis_tready = input_3_axis_tready_reg; - -// mux for start of packet detection -reg selected_input_tvalid; -always @* begin - case (select) - 2'd0: selected_input_tvalid = input_0_axis_tvalid; - 2'd1: selected_input_tvalid = input_1_axis_tvalid; - 2'd2: selected_input_tvalid = input_2_axis_tvalid; - 2'd3: selected_input_tvalid = input_3_axis_tvalid; - default: selected_input_tvalid = 1'b0; - endcase -end - -// mux for incoming packet -reg [DATA_WIDTH-1:0] current_input_tdata; -reg [KEEP_WIDTH-1:0] current_input_tkeep; -reg current_input_tvalid; -reg current_input_tready; -reg current_input_tlast; -reg [ID_WIDTH-1:0] current_input_tid; -reg [DEST_WIDTH-1:0] current_input_tdest; -reg [USER_WIDTH-1:0] current_input_tuser; -always @* begin - case (select_reg) - 2'd0: begin - current_input_tdata = input_0_axis_tdata; - current_input_tkeep = input_0_axis_tkeep; - current_input_tvalid = input_0_axis_tvalid; - current_input_tready = input_0_axis_tready; - current_input_tlast = input_0_axis_tlast; - current_input_tid = input_0_axis_tid; - current_input_tdest = input_0_axis_tdest; - current_input_tuser = input_0_axis_tuser; - end - 2'd1: begin - current_input_tdata = input_1_axis_tdata; - current_input_tkeep = input_1_axis_tkeep; - current_input_tvalid = input_1_axis_tvalid; - current_input_tready = input_1_axis_tready; - current_input_tlast = input_1_axis_tlast; - current_input_tid = input_1_axis_tid; - current_input_tdest = input_1_axis_tdest; - current_input_tuser = input_1_axis_tuser; - end - 2'd2: begin - current_input_tdata = input_2_axis_tdata; - current_input_tkeep = input_2_axis_tkeep; - current_input_tvalid = input_2_axis_tvalid; - current_input_tready = input_2_axis_tready; - current_input_tlast = input_2_axis_tlast; - current_input_tid = input_2_axis_tid; - current_input_tdest = input_2_axis_tdest; - current_input_tuser = input_2_axis_tuser; - end - 2'd3: begin - current_input_tdata = input_3_axis_tdata; - current_input_tkeep = input_3_axis_tkeep; - current_input_tvalid = input_3_axis_tvalid; - current_input_tready = input_3_axis_tready; - current_input_tlast = input_3_axis_tlast; - current_input_tid = input_3_axis_tid; - current_input_tdest = input_3_axis_tdest; - current_input_tuser = input_3_axis_tuser; - end - default: begin - current_input_tdata = {DATA_WIDTH{1'b0}}; - current_input_tkeep = {KEEP_WIDTH{1'b0}}; - current_input_tvalid = 1'b0; - current_input_tready = 1'b0; - current_input_tlast = 1'b0; - current_input_tid = {ID_WIDTH{1'b0}}; - current_input_tdest = {DEST_WIDTH{1'b0}}; - current_input_tuser = {USER_WIDTH{1'b0}}; - end - endcase -end - -always @* begin - select_next = select_reg; - frame_next = frame_reg; - - input_0_axis_tready_next = 1'b0; - input_1_axis_tready_next = 1'b0; - input_2_axis_tready_next = 1'b0; - input_3_axis_tready_next = 1'b0; - - if (current_input_tvalid & current_input_tready) begin - // end of frame detection - if (current_input_tlast) begin - frame_next = 1'b0; - end - end - - if (~frame_reg & enable & selected_input_tvalid) begin - // start of frame, grab select value - frame_next = 1'b1; - select_next = select; - end - - // generate ready signal on selected port - case (select_next) - 2'd0: input_0_axis_tready_next = output_axis_tready_int_early & frame_next; - 2'd1: input_1_axis_tready_next = output_axis_tready_int_early & frame_next; - 2'd2: input_2_axis_tready_next = output_axis_tready_int_early & frame_next; - 2'd3: input_3_axis_tready_next = output_axis_tready_int_early & frame_next; - endcase - - // pass through selected packet data - output_axis_tdata_int = current_input_tdata; - output_axis_tkeep_int = current_input_tkeep; - output_axis_tvalid_int = current_input_tvalid & current_input_tready & frame_reg; - output_axis_tlast_int = current_input_tlast; - output_axis_tid_int = current_input_tid; - output_axis_tdest_int = current_input_tdest; - output_axis_tuser_int = current_input_tuser; -end - -always @(posedge clk) begin - if (rst) begin - select_reg <= 2'd0; - frame_reg <= 1'b0; - input_0_axis_tready_reg <= 1'b0; - input_1_axis_tready_reg <= 1'b0; - input_2_axis_tready_reg <= 1'b0; - input_3_axis_tready_reg <= 1'b0; - end else begin - select_reg <= select_next; - frame_reg <= frame_next; - input_0_axis_tready_reg <= input_0_axis_tready_next; - input_1_axis_tready_reg <= input_1_axis_tready_next; - input_2_axis_tready_reg <= input_2_axis_tready_next; - input_3_axis_tready_reg <= input_3_axis_tready_next; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] output_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] output_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next; -reg output_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] output_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] output_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] output_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -reg [DATA_WIDTH-1:0] temp_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_axis_tvalid_reg = 1'b0, temp_axis_tvalid_next; -reg temp_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] temp_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] temp_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] temp_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign output_axis_tdata = output_axis_tdata_reg; -assign output_axis_tkeep = KEEP_ENABLE ? output_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign output_axis_tvalid = output_axis_tvalid_reg; -assign output_axis_tlast = output_axis_tlast_reg; -assign output_axis_tid = ID_ENABLE ? output_axis_tid_reg : {ID_WIDTH{1'b0}}; -assign output_axis_tdest = DEST_ENABLE ? output_axis_tdest_reg : {DEST_WIDTH{1'b0}}; -assign output_axis_tuser = USER_ENABLE ? output_axis_tuser_reg : {USER_WIDTH{1'b0}}; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign output_axis_tready_int_early = output_axis_tready | (~temp_axis_tvalid_reg & (~output_axis_tvalid_reg | ~output_axis_tvalid_int)); - -always @* begin - // transfer sink ready state to source - output_axis_tvalid_next = output_axis_tvalid_reg; - temp_axis_tvalid_next = temp_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (output_axis_tready_int_reg) begin - // input is ready - if (output_axis_tready | ~output_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - output_axis_tvalid_next = output_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_axis_tvalid_next = output_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (output_axis_tready) begin - // input is not ready, but output is ready - output_axis_tvalid_next = temp_axis_tvalid_reg; - temp_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - output_axis_tvalid_reg <= 1'b0; - output_axis_tready_int_reg <= 1'b0; - temp_axis_tvalid_reg <= 1'b0; - end else begin - output_axis_tvalid_reg <= output_axis_tvalid_next; - output_axis_tready_int_reg <= output_axis_tready_int_early; - temp_axis_tvalid_reg <= temp_axis_tvalid_next; - end - - // datapath - if (store_axis_int_to_output) begin - output_axis_tdata_reg <= output_axis_tdata_int; - output_axis_tkeep_reg <= output_axis_tkeep_int; - output_axis_tlast_reg <= output_axis_tlast_int; - output_axis_tid_reg <= output_axis_tid_int; - output_axis_tdest_reg <= output_axis_tdest_int; - output_axis_tuser_reg <= output_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - output_axis_tdata_reg <= temp_axis_tdata_reg; - output_axis_tkeep_reg <= temp_axis_tkeep_reg; - output_axis_tlast_reg <= temp_axis_tlast_reg; - output_axis_tid_reg <= temp_axis_tid_reg; - output_axis_tdest_reg <= temp_axis_tdest_reg; - output_axis_tuser_reg <= temp_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_axis_tdata_reg <= output_axis_tdata_int; - temp_axis_tkeep_reg <= output_axis_tkeep_int; - temp_axis_tlast_reg <= output_axis_tlast_int; - temp_axis_tid_reg <= output_axis_tid_int; - temp_axis_tdest_reg <= output_axis_tdest_int; - temp_axis_tuser_reg <= output_axis_tuser_int; - end -end - -endmodule diff --git a/tb/test_axis_mux_4.py b/tb/test_axis_mux_4.py index 04dbcb7f..4d469375 100755 --- a/tb/test_axis_mux_4.py +++ b/tb/test_axis_mux_4.py @@ -28,8 +28,8 @@ import os import axis_ep -module = 'axis_mux_4' -testbench = 'test_%s' % module +module = 'axis_mux' +testbench = 'test_%s_4' % module srcs = [] @@ -43,6 +43,7 @@ build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) def bench(): # Parameters + S_COUNT = 4 DATA_WIDTH = 8 KEEP_ENABLE = (DATA_WIDTH>8) KEEP_WIDTH = (DATA_WIDTH/8) @@ -58,142 +59,81 @@ def bench(): rst = Signal(bool(0)) current_test = Signal(intbv(0)[8:]) - input_0_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_0_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_0_axis_tvalid = Signal(bool(0)) - input_0_axis_tlast = Signal(bool(0)) - input_0_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_0_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_0_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) - input_1_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_1_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_1_axis_tvalid = Signal(bool(0)) - input_1_axis_tlast = Signal(bool(0)) - input_1_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_1_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_1_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) - input_2_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_2_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_2_axis_tvalid = Signal(bool(0)) - input_2_axis_tlast = Signal(bool(0)) - input_2_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_2_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_2_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) - input_3_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_3_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_3_axis_tvalid = Signal(bool(0)) - input_3_axis_tlast = Signal(bool(0)) - input_3_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_3_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_3_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) + s_axis_tdata_list = [Signal(intbv(0)[DATA_WIDTH:]) for i in range(S_COUNT)] + s_axis_tkeep_list = [Signal(intbv(1)[KEEP_WIDTH:]) for i in range(S_COUNT)] + s_axis_tvalid_list = [Signal(bool(0)) for i in range(S_COUNT)] + s_axis_tlast_list = [Signal(bool(0)) for i in range(S_COUNT)] + s_axis_tid_list = [Signal(intbv(0)[ID_WIDTH:]) for i in range(S_COUNT)] + s_axis_tdest_list = [Signal(intbv(0)[DEST_WIDTH:]) for i in range(S_COUNT)] + s_axis_tuser_list = [Signal(intbv(0)[USER_WIDTH:]) for i in range(S_COUNT)] - output_axis_tready = Signal(bool(0)) + s_axis_tdata = ConcatSignal(*reversed(s_axis_tdata_list)) + s_axis_tkeep = ConcatSignal(*reversed(s_axis_tkeep_list)) + s_axis_tvalid = ConcatSignal(*reversed(s_axis_tvalid_list)) + s_axis_tlast = ConcatSignal(*reversed(s_axis_tlast_list)) + s_axis_tid = ConcatSignal(*reversed(s_axis_tid_list)) + s_axis_tdest = ConcatSignal(*reversed(s_axis_tdest_list)) + s_axis_tuser = ConcatSignal(*reversed(s_axis_tuser_list)) + + m_axis_tready = Signal(bool(0)) enable = Signal(bool(0)) select = Signal(intbv(0)[2:]) # Outputs - input_0_axis_tready = Signal(bool(0)) - input_1_axis_tready = Signal(bool(0)) - input_2_axis_tready = Signal(bool(0)) - input_3_axis_tready = Signal(bool(0)) + s_axis_tready = Signal(intbv(0)[S_COUNT:]) - output_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - output_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - output_axis_tvalid = Signal(bool(0)) - output_axis_tlast = Signal(bool(0)) - output_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - output_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - output_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) + s_axis_tready_list = [s_axis_tready(i) for i in range(S_COUNT)] + + m_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) + m_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) + m_axis_tvalid = Signal(bool(0)) + m_axis_tlast = Signal(bool(0)) + m_axis_tid = Signal(intbv(0)[ID_WIDTH:]) + m_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) + m_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) # sources and sinks - source_0_pause = Signal(bool(0)) - source_1_pause = Signal(bool(0)) - source_2_pause = Signal(bool(0)) - source_3_pause = Signal(bool(0)) + source_pause_list = [] + source_list = [] + source_logic_list = [] sink_pause = Signal(bool(0)) - source_0 = axis_ep.AXIStreamSource() + for k in range(S_COUNT): + s = axis_ep.AXIStreamSource() + p = Signal(bool(0)) - source_0_logic = source_0.create_logic( - clk, - rst, - tdata=input_0_axis_tdata, - tkeep=input_0_axis_tkeep, - tvalid=input_0_axis_tvalid, - tready=input_0_axis_tready, - tlast=input_0_axis_tlast, - tid=input_0_axis_tid, - tdest=input_0_axis_tdest, - tuser=input_0_axis_tuser, - pause=source_0_pause, - name='source_0' - ) + source_list.append(s) + source_pause_list.append(p) - source_1 = axis_ep.AXIStreamSource() - - source_1_logic = source_1.create_logic( - clk, - rst, - tdata=input_1_axis_tdata, - tkeep=input_1_axis_tkeep, - tvalid=input_1_axis_tvalid, - tready=input_1_axis_tready, - tlast=input_1_axis_tlast, - tid=input_1_axis_tid, - tdest=input_1_axis_tdest, - tuser=input_1_axis_tuser, - pause=source_1_pause, - name='source_1' - ) - - source_2 = axis_ep.AXIStreamSource() - - source_2_logic = source_2.create_logic( - clk, - rst, - tdata=input_2_axis_tdata, - tkeep=input_2_axis_tkeep, - tvalid=input_2_axis_tvalid, - tready=input_2_axis_tready, - tlast=input_2_axis_tlast, - tid=input_2_axis_tid, - tdest=input_2_axis_tdest, - tuser=input_2_axis_tuser, - pause=source_2_pause, - name='source_2' - ) - - source_3 = axis_ep.AXIStreamSource() - - source_3_logic = source_3.create_logic( - clk, - rst, - tdata=input_3_axis_tdata, - tkeep=input_3_axis_tkeep, - tvalid=input_3_axis_tvalid, - tready=input_3_axis_tready, - tlast=input_3_axis_tlast, - tid=input_3_axis_tid, - tdest=input_3_axis_tdest, - tuser=input_3_axis_tuser, - pause=source_3_pause, - name='source_3' - ) + source_logic_list.append(s.create_logic( + clk, + rst, + tdata=s_axis_tdata_list[k], + tkeep=s_axis_tkeep_list[k], + tvalid=s_axis_tvalid_list[k], + tready=s_axis_tready_list[k], + tlast=s_axis_tlast_list[k], + tid=s_axis_tid_list[k], + tdest=s_axis_tdest_list[k], + tuser=s_axis_tuser_list[k], + pause=p, + name='source_%d' % k + )) sink = axis_ep.AXIStreamSink() sink_logic = sink.create_logic( clk, rst, - tdata=output_axis_tdata, - tkeep=output_axis_tkeep, - tvalid=output_axis_tvalid, - tready=output_axis_tready, - tlast=output_axis_tlast, - tid=output_axis_tid, - tdest=output_axis_tdest, - tuser=output_axis_tuser, + tdata=m_axis_tdata, + tkeep=m_axis_tkeep, + tvalid=m_axis_tvalid, + tready=m_axis_tready, + tlast=m_axis_tlast, + tid=m_axis_tid, + tdest=m_axis_tdest, + tuser=m_axis_tuser, pause=sink_pause, name='sink' ) @@ -208,47 +148,23 @@ def bench(): rst=rst, current_test=current_test, - input_0_axis_tdata=input_0_axis_tdata, - input_0_axis_tkeep=input_0_axis_tkeep, - input_0_axis_tvalid=input_0_axis_tvalid, - input_0_axis_tready=input_0_axis_tready, - input_0_axis_tlast=input_0_axis_tlast, - input_0_axis_tid=input_0_axis_tid, - input_0_axis_tdest=input_0_axis_tdest, - input_0_axis_tuser=input_0_axis_tuser, - input_1_axis_tdata=input_1_axis_tdata, - input_1_axis_tkeep=input_1_axis_tkeep, - input_1_axis_tvalid=input_1_axis_tvalid, - input_1_axis_tready=input_1_axis_tready, - input_1_axis_tlast=input_1_axis_tlast, - input_1_axis_tid=input_1_axis_tid, - input_1_axis_tdest=input_1_axis_tdest, - input_1_axis_tuser=input_1_axis_tuser, - input_2_axis_tdata=input_2_axis_tdata, - input_2_axis_tkeep=input_2_axis_tkeep, - input_2_axis_tvalid=input_2_axis_tvalid, - input_2_axis_tready=input_2_axis_tready, - input_2_axis_tlast=input_2_axis_tlast, - input_2_axis_tid=input_2_axis_tid, - input_2_axis_tdest=input_2_axis_tdest, - input_2_axis_tuser=input_2_axis_tuser, - input_3_axis_tdata=input_3_axis_tdata, - input_3_axis_tkeep=input_3_axis_tkeep, - input_3_axis_tvalid=input_3_axis_tvalid, - input_3_axis_tready=input_3_axis_tready, - input_3_axis_tlast=input_3_axis_tlast, - input_3_axis_tid=input_3_axis_tid, - input_3_axis_tdest=input_3_axis_tdest, - input_3_axis_tuser=input_3_axis_tuser, + s_axis_tdata=s_axis_tdata, + s_axis_tkeep=s_axis_tkeep, + s_axis_tvalid=s_axis_tvalid, + s_axis_tready=s_axis_tready, + s_axis_tlast=s_axis_tlast, + s_axis_tid=s_axis_tid, + s_axis_tdest=s_axis_tdest, + s_axis_tuser=s_axis_tuser, - output_axis_tdata=output_axis_tdata, - output_axis_tkeep=output_axis_tkeep, - output_axis_tvalid=output_axis_tvalid, - output_axis_tready=output_axis_tready, - output_axis_tlast=output_axis_tlast, - output_axis_tid=output_axis_tid, - output_axis_tdest=output_axis_tdest, - output_axis_tuser=output_axis_tuser, + m_axis_tdata=m_axis_tdata, + m_axis_tkeep=m_axis_tkeep, + m_axis_tvalid=m_axis_tvalid, + m_axis_tready=m_axis_tready, + m_axis_tlast=m_axis_tlast, + m_axis_tid=m_axis_tid, + m_axis_tdest=m_axis_tdest, + m_axis_tuser=m_axis_tuser, enable=enable, select=select @@ -287,7 +203,7 @@ def bench(): dest=1 ) - source_0.send(test_frame) + source_list[0].send(test_frame) yield sink.wait() rx_frame = sink.recv() @@ -311,7 +227,7 @@ def bench(): dest=1 ) - source_1.send(test_frame) + source_list[1].send(test_frame) yield sink.wait() rx_frame = sink.recv() @@ -343,8 +259,8 @@ def bench(): dest=2 ) - source_0.send(test_frame1) - source_0.send(test_frame2) + source_list[0].send(test_frame1) + source_list[0].send(test_frame2) yield sink.wait() rx_frame = sink.recv() @@ -381,11 +297,11 @@ def bench(): dest=2 ) - source_1.send(test_frame1) - source_2.send(test_frame2) + source_list[1].send(test_frame1) + source_list[2].send(test_frame2) yield clk.posedge - while input_0_axis_tvalid or input_1_axis_tvalid or input_2_axis_tvalid or input_3_axis_tvalid: + while s_axis_tvalid: yield clk.posedge select.next = 2 @@ -424,22 +340,22 @@ def bench(): dest=2 ) - source_1.send(test_frame1) - source_2.send(test_frame2) + source_list[1].send(test_frame1) + source_list[2].send(test_frame2) yield clk.posedge - while input_0_axis_tvalid or input_1_axis_tvalid or input_2_axis_tvalid or input_3_axis_tvalid: - source_0_pause.next = True - source_1_pause.next = True - source_2_pause.next = True - source_3_pause.next = True + while s_axis_tvalid: + source_pause_list[0].next = True + source_pause_list[1].next = True + source_pause_list[2].next = True + source_pause_list[3].next = True yield clk.posedge yield clk.posedge yield clk.posedge - source_0_pause.next = False - source_1_pause.next = False - source_2_pause.next = False - source_3_pause.next = False + source_pause_list[0].next = False + source_pause_list[1].next = False + source_pause_list[2].next = False + source_pause_list[3].next = False yield clk.posedge select.next = 2 @@ -478,11 +394,11 @@ def bench(): dest=2 ) - source_1.send(test_frame1) - source_2.send(test_frame2) + source_list[1].send(test_frame1) + source_list[2].send(test_frame2) yield clk.posedge - while input_0_axis_tvalid or input_1_axis_tvalid or input_2_axis_tvalid or input_3_axis_tvalid: + while s_axis_tvalid: sink_pause.next = True yield clk.posedge yield clk.posedge diff --git a/tb/test_axis_mux_4.v b/tb/test_axis_mux_4.v index ca434582..a72c2444 100644 --- a/tb/test_axis_mux_4.v +++ b/tb/test_axis_mux_4.v @@ -27,11 +27,12 @@ THE SOFTWARE. `timescale 1ns / 1ps /* - * Testbench for axis_mux_4 + * Testbench for axis_mux */ module test_axis_mux_4; // Parameters +parameter S_COUNT = 4; parameter DATA_WIDTH = 8; parameter KEEP_ENABLE = (DATA_WIDTH>8); parameter KEEP_WIDTH = (DATA_WIDTH/8); @@ -47,53 +48,29 @@ reg clk = 0; reg rst = 0; reg [7:0] current_test = 0; -reg [DATA_WIDTH-1:0] input_0_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_0_axis_tkeep = 0; -reg input_0_axis_tvalid = 0; -reg input_0_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_0_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_0_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_0_axis_tuser = 0; -reg [DATA_WIDTH-1:0] input_1_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_1_axis_tkeep = 0; -reg input_1_axis_tvalid = 0; -reg input_1_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_1_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_1_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_1_axis_tuser = 0; -reg [DATA_WIDTH-1:0] input_2_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_2_axis_tkeep = 0; -reg input_2_axis_tvalid = 0; -reg input_2_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_2_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_2_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_2_axis_tuser = 0; -reg [DATA_WIDTH-1:0] input_3_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_3_axis_tkeep = 0; -reg input_3_axis_tvalid = 0; -reg input_3_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_3_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_3_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_3_axis_tuser = 0; +reg [S_COUNT*DATA_WIDTH-1:0] s_axis_tdata = 0; +reg [S_COUNT*KEEP_WIDTH-1:0] s_axis_tkeep = 0; +reg [S_COUNT-1:0] s_axis_tvalid = 0; +reg [S_COUNT-1:0] s_axis_tlast = 0; +reg [S_COUNT*ID_WIDTH-1:0] s_axis_tid = 0; +reg [S_COUNT*DEST_WIDTH-1:0] s_axis_tdest = 0; +reg [S_COUNT*USER_WIDTH-1:0] s_axis_tuser = 0; -reg output_axis_tready = 0; +reg m_axis_tready = 0; reg enable = 0; reg [1:0] select = 0; // Outputs -wire input_0_axis_tready; -wire input_1_axis_tready; -wire input_2_axis_tready; -wire input_3_axis_tready; +wire [S_COUNT-1:0] s_axis_tready; -wire [DATA_WIDTH-1:0] output_axis_tdata; -wire [KEEP_WIDTH-1:0] output_axis_tkeep; -wire output_axis_tvalid; -wire output_axis_tlast; -wire [ID_WIDTH-1:0] output_axis_tid; -wire [DEST_WIDTH-1:0] output_axis_tdest; -wire [USER_WIDTH-1:0] output_axis_tuser; +wire [DATA_WIDTH-1:0] m_axis_tdata; +wire [KEEP_WIDTH-1:0] m_axis_tkeep; +wire m_axis_tvalid; +wire m_axis_tlast; +wire [ID_WIDTH-1:0] m_axis_tid; +wire [DEST_WIDTH-1:0] m_axis_tdest; +wire [USER_WIDTH-1:0] m_axis_tuser; initial begin // myhdl integration @@ -101,50 +78,26 @@ initial begin clk, rst, current_test, - input_0_axis_tdata, - input_0_axis_tkeep, - input_0_axis_tvalid, - input_0_axis_tlast, - input_0_axis_tid, - input_0_axis_tdest, - input_0_axis_tuser, - input_1_axis_tdata, - input_1_axis_tkeep, - input_1_axis_tvalid, - input_1_axis_tlast, - input_1_axis_tid, - input_1_axis_tdest, - input_1_axis_tuser, - input_2_axis_tdata, - input_2_axis_tkeep, - input_2_axis_tvalid, - input_2_axis_tlast, - input_2_axis_tid, - input_2_axis_tdest, - input_2_axis_tuser, - input_3_axis_tdata, - input_3_axis_tkeep, - input_3_axis_tvalid, - input_3_axis_tlast, - input_3_axis_tid, - input_3_axis_tdest, - input_3_axis_tuser, - output_axis_tready, + s_axis_tdata, + s_axis_tkeep, + s_axis_tvalid, + s_axis_tlast, + s_axis_tid, + s_axis_tdest, + s_axis_tuser, + m_axis_tready, enable, select ); $to_myhdl( - input_0_axis_tready, - input_1_axis_tready, - input_2_axis_tready, - input_3_axis_tready, - output_axis_tdata, - output_axis_tkeep, - output_axis_tvalid, - output_axis_tlast, - output_axis_tid, - output_axis_tdest, - output_axis_tuser + s_axis_tready, + m_axis_tdata, + m_axis_tkeep, + m_axis_tvalid, + m_axis_tlast, + m_axis_tid, + m_axis_tdest, + m_axis_tuser ); // dump file @@ -152,7 +105,8 @@ initial begin $dumpvars(0, test_axis_mux_4); end -axis_mux_4 #( +axis_mux #( + .S_COUNT(S_COUNT), .DATA_WIDTH(DATA_WIDTH), .KEEP_ENABLE(KEEP_ENABLE), .KEEP_WIDTH(KEEP_WIDTH), @@ -167,47 +121,23 @@ UUT ( .clk(clk), .rst(rst), // AXI inputs - .input_0_axis_tdata(input_0_axis_tdata), - .input_0_axis_tkeep(input_0_axis_tkeep), - .input_0_axis_tvalid(input_0_axis_tvalid), - .input_0_axis_tready(input_0_axis_tready), - .input_0_axis_tlast(input_0_axis_tlast), - .input_0_axis_tid(input_0_axis_tid), - .input_0_axis_tdest(input_0_axis_tdest), - .input_0_axis_tuser(input_0_axis_tuser), - .input_1_axis_tdata(input_1_axis_tdata), - .input_1_axis_tkeep(input_1_axis_tkeep), - .input_1_axis_tvalid(input_1_axis_tvalid), - .input_1_axis_tready(input_1_axis_tready), - .input_1_axis_tlast(input_1_axis_tlast), - .input_1_axis_tid(input_1_axis_tid), - .input_1_axis_tdest(input_1_axis_tdest), - .input_1_axis_tuser(input_1_axis_tuser), - .input_2_axis_tdata(input_2_axis_tdata), - .input_2_axis_tkeep(input_2_axis_tkeep), - .input_2_axis_tvalid(input_2_axis_tvalid), - .input_2_axis_tready(input_2_axis_tready), - .input_2_axis_tlast(input_2_axis_tlast), - .input_2_axis_tid(input_2_axis_tid), - .input_2_axis_tdest(input_2_axis_tdest), - .input_2_axis_tuser(input_2_axis_tuser), - .input_3_axis_tdata(input_3_axis_tdata), - .input_3_axis_tkeep(input_3_axis_tkeep), - .input_3_axis_tvalid(input_3_axis_tvalid), - .input_3_axis_tready(input_3_axis_tready), - .input_3_axis_tlast(input_3_axis_tlast), - .input_3_axis_tid(input_3_axis_tid), - .input_3_axis_tdest(input_3_axis_tdest), - .input_3_axis_tuser(input_3_axis_tuser), + .s_axis_tdata(s_axis_tdata), + .s_axis_tkeep(s_axis_tkeep), + .s_axis_tvalid(s_axis_tvalid), + .s_axis_tready(s_axis_tready), + .s_axis_tlast(s_axis_tlast), + .s_axis_tid(s_axis_tid), + .s_axis_tdest(s_axis_tdest), + .s_axis_tuser(s_axis_tuser), // AXI output - .output_axis_tdata(output_axis_tdata), - .output_axis_tkeep(output_axis_tkeep), - .output_axis_tvalid(output_axis_tvalid), - .output_axis_tready(output_axis_tready), - .output_axis_tlast(output_axis_tlast), - .output_axis_tid(output_axis_tid), - .output_axis_tdest(output_axis_tdest), - .output_axis_tuser(output_axis_tuser), + .m_axis_tdata(m_axis_tdata), + .m_axis_tkeep(m_axis_tkeep), + .m_axis_tvalid(m_axis_tvalid), + .m_axis_tready(m_axis_tready), + .m_axis_tlast(m_axis_tlast), + .m_axis_tid(m_axis_tid), + .m_axis_tdest(m_axis_tdest), + .m_axis_tuser(m_axis_tuser), // Control .enable(enable), .select(select) diff --git a/tb/test_axis_mux_4_64.py b/tb/test_axis_mux_4_64.py index de7b1e01..0b9d8a47 100755 --- a/tb/test_axis_mux_4_64.py +++ b/tb/test_axis_mux_4_64.py @@ -28,8 +28,8 @@ import os import axis_ep -module = 'axis_mux_4' -testbench = 'test_%s_64' % module +module = 'axis_mux' +testbench = 'test_%s_4_64' % module srcs = [] @@ -43,6 +43,7 @@ build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) def bench(): # Parameters + S_COUNT = 4 DATA_WIDTH = 64 KEEP_ENABLE = (DATA_WIDTH>8) KEEP_WIDTH = (DATA_WIDTH/8) @@ -58,142 +59,81 @@ def bench(): rst = Signal(bool(0)) current_test = Signal(intbv(0)[8:]) - input_0_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_0_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_0_axis_tvalid = Signal(bool(0)) - input_0_axis_tlast = Signal(bool(0)) - input_0_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_0_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_0_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) - input_1_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_1_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_1_axis_tvalid = Signal(bool(0)) - input_1_axis_tlast = Signal(bool(0)) - input_1_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_1_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_1_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) - input_2_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_2_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_2_axis_tvalid = Signal(bool(0)) - input_2_axis_tlast = Signal(bool(0)) - input_2_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_2_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_2_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) - input_3_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - input_3_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - input_3_axis_tvalid = Signal(bool(0)) - input_3_axis_tlast = Signal(bool(0)) - input_3_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - input_3_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - input_3_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) + s_axis_tdata_list = [Signal(intbv(0)[DATA_WIDTH:]) for i in range(S_COUNT)] + s_axis_tkeep_list = [Signal(intbv(1)[KEEP_WIDTH:]) for i in range(S_COUNT)] + s_axis_tvalid_list = [Signal(bool(0)) for i in range(S_COUNT)] + s_axis_tlast_list = [Signal(bool(0)) for i in range(S_COUNT)] + s_axis_tid_list = [Signal(intbv(0)[ID_WIDTH:]) for i in range(S_COUNT)] + s_axis_tdest_list = [Signal(intbv(0)[DEST_WIDTH:]) for i in range(S_COUNT)] + s_axis_tuser_list = [Signal(intbv(0)[USER_WIDTH:]) for i in range(S_COUNT)] - output_axis_tready = Signal(bool(0)) + s_axis_tdata = ConcatSignal(*reversed(s_axis_tdata_list)) + s_axis_tkeep = ConcatSignal(*reversed(s_axis_tkeep_list)) + s_axis_tvalid = ConcatSignal(*reversed(s_axis_tvalid_list)) + s_axis_tlast = ConcatSignal(*reversed(s_axis_tlast_list)) + s_axis_tid = ConcatSignal(*reversed(s_axis_tid_list)) + s_axis_tdest = ConcatSignal(*reversed(s_axis_tdest_list)) + s_axis_tuser = ConcatSignal(*reversed(s_axis_tuser_list)) + + m_axis_tready = Signal(bool(0)) enable = Signal(bool(0)) select = Signal(intbv(0)[2:]) # Outputs - input_0_axis_tready = Signal(bool(0)) - input_1_axis_tready = Signal(bool(0)) - input_2_axis_tready = Signal(bool(0)) - input_3_axis_tready = Signal(bool(0)) + s_axis_tready = Signal(intbv(0)[S_COUNT:]) - output_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) - output_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) - output_axis_tvalid = Signal(bool(0)) - output_axis_tlast = Signal(bool(0)) - output_axis_tid = Signal(intbv(0)[ID_WIDTH:]) - output_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) - output_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) + s_axis_tready_list = [s_axis_tready(i) for i in range(S_COUNT)] + + m_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) + m_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) + m_axis_tvalid = Signal(bool(0)) + m_axis_tlast = Signal(bool(0)) + m_axis_tid = Signal(intbv(0)[ID_WIDTH:]) + m_axis_tdest = Signal(intbv(0)[DEST_WIDTH:]) + m_axis_tuser = Signal(intbv(0)[USER_WIDTH:]) # sources and sinks - source_0_pause = Signal(bool(0)) - source_1_pause = Signal(bool(0)) - source_2_pause = Signal(bool(0)) - source_3_pause = Signal(bool(0)) + source_pause_list = [] + source_list = [] + source_logic_list = [] sink_pause = Signal(bool(0)) - source_0 = axis_ep.AXIStreamSource() + for k in range(S_COUNT): + s = axis_ep.AXIStreamSource() + p = Signal(bool(0)) - source_0_logic = source_0.create_logic( - clk, - rst, - tdata=input_0_axis_tdata, - tkeep=input_0_axis_tkeep, - tvalid=input_0_axis_tvalid, - tready=input_0_axis_tready, - tlast=input_0_axis_tlast, - tid=input_0_axis_tid, - tdest=input_0_axis_tdest, - tuser=input_0_axis_tuser, - pause=source_0_pause, - name='source_0' - ) + source_list.append(s) + source_pause_list.append(p) - source_1 = axis_ep.AXIStreamSource() - - source_1_logic = source_1.create_logic( - clk, - rst, - tdata=input_1_axis_tdata, - tkeep=input_1_axis_tkeep, - tvalid=input_1_axis_tvalid, - tready=input_1_axis_tready, - tlast=input_1_axis_tlast, - tid=input_1_axis_tid, - tdest=input_1_axis_tdest, - tuser=input_1_axis_tuser, - pause=source_1_pause, - name='source_1' - ) - - source_2 = axis_ep.AXIStreamSource() - - source_2_logic = source_2.create_logic( - clk, - rst, - tdata=input_2_axis_tdata, - tkeep=input_2_axis_tkeep, - tvalid=input_2_axis_tvalid, - tready=input_2_axis_tready, - tlast=input_2_axis_tlast, - tid=input_2_axis_tid, - tdest=input_2_axis_tdest, - tuser=input_2_axis_tuser, - pause=source_2_pause, - name='source_2' - ) - - source_3 = axis_ep.AXIStreamSource() - - source_3_logic = source_3.create_logic( - clk, - rst, - tdata=input_3_axis_tdata, - tkeep=input_3_axis_tkeep, - tvalid=input_3_axis_tvalid, - tready=input_3_axis_tready, - tlast=input_3_axis_tlast, - tid=input_3_axis_tid, - tdest=input_3_axis_tdest, - tuser=input_3_axis_tuser, - pause=source_3_pause, - name='source_3' - ) + source_logic_list.append(s.create_logic( + clk, + rst, + tdata=s_axis_tdata_list[k], + tkeep=s_axis_tkeep_list[k], + tvalid=s_axis_tvalid_list[k], + tready=s_axis_tready_list[k], + tlast=s_axis_tlast_list[k], + tid=s_axis_tid_list[k], + tdest=s_axis_tdest_list[k], + tuser=s_axis_tuser_list[k], + pause=p, + name='source_%d' % k + )) sink = axis_ep.AXIStreamSink() sink_logic = sink.create_logic( clk, rst, - tdata=output_axis_tdata, - tkeep=output_axis_tkeep, - tvalid=output_axis_tvalid, - tready=output_axis_tready, - tlast=output_axis_tlast, - tid=output_axis_tid, - tdest=output_axis_tdest, - tuser=output_axis_tuser, + tdata=m_axis_tdata, + tkeep=m_axis_tkeep, + tvalid=m_axis_tvalid, + tready=m_axis_tready, + tlast=m_axis_tlast, + tid=m_axis_tid, + tdest=m_axis_tdest, + tuser=m_axis_tuser, pause=sink_pause, name='sink' ) @@ -208,47 +148,23 @@ def bench(): rst=rst, current_test=current_test, - input_0_axis_tdata=input_0_axis_tdata, - input_0_axis_tkeep=input_0_axis_tkeep, - input_0_axis_tvalid=input_0_axis_tvalid, - input_0_axis_tready=input_0_axis_tready, - input_0_axis_tlast=input_0_axis_tlast, - input_0_axis_tid=input_0_axis_tid, - input_0_axis_tdest=input_0_axis_tdest, - input_0_axis_tuser=input_0_axis_tuser, - input_1_axis_tdata=input_1_axis_tdata, - input_1_axis_tkeep=input_1_axis_tkeep, - input_1_axis_tvalid=input_1_axis_tvalid, - input_1_axis_tready=input_1_axis_tready, - input_1_axis_tlast=input_1_axis_tlast, - input_1_axis_tid=input_1_axis_tid, - input_1_axis_tdest=input_1_axis_tdest, - input_1_axis_tuser=input_1_axis_tuser, - input_2_axis_tdata=input_2_axis_tdata, - input_2_axis_tkeep=input_2_axis_tkeep, - input_2_axis_tvalid=input_2_axis_tvalid, - input_2_axis_tready=input_2_axis_tready, - input_2_axis_tlast=input_2_axis_tlast, - input_2_axis_tid=input_2_axis_tid, - input_2_axis_tdest=input_2_axis_tdest, - input_2_axis_tuser=input_2_axis_tuser, - input_3_axis_tdata=input_3_axis_tdata, - input_3_axis_tkeep=input_3_axis_tkeep, - input_3_axis_tvalid=input_3_axis_tvalid, - input_3_axis_tready=input_3_axis_tready, - input_3_axis_tlast=input_3_axis_tlast, - input_3_axis_tid=input_3_axis_tid, - input_3_axis_tdest=input_3_axis_tdest, - input_3_axis_tuser=input_3_axis_tuser, + s_axis_tdata=s_axis_tdata, + s_axis_tkeep=s_axis_tkeep, + s_axis_tvalid=s_axis_tvalid, + s_axis_tready=s_axis_tready, + s_axis_tlast=s_axis_tlast, + s_axis_tid=s_axis_tid, + s_axis_tdest=s_axis_tdest, + s_axis_tuser=s_axis_tuser, - output_axis_tdata=output_axis_tdata, - output_axis_tkeep=output_axis_tkeep, - output_axis_tvalid=output_axis_tvalid, - output_axis_tready=output_axis_tready, - output_axis_tlast=output_axis_tlast, - output_axis_tid=output_axis_tid, - output_axis_tdest=output_axis_tdest, - output_axis_tuser=output_axis_tuser, + m_axis_tdata=m_axis_tdata, + m_axis_tkeep=m_axis_tkeep, + m_axis_tvalid=m_axis_tvalid, + m_axis_tready=m_axis_tready, + m_axis_tlast=m_axis_tlast, + m_axis_tid=m_axis_tid, + m_axis_tdest=m_axis_tdest, + m_axis_tuser=m_axis_tuser, enable=enable, select=select @@ -287,7 +203,7 @@ def bench(): dest=1 ) - source_0.send(test_frame) + source_list[0].send(test_frame) yield sink.wait() rx_frame = sink.recv() @@ -311,7 +227,7 @@ def bench(): dest=1 ) - source_1.send(test_frame) + source_list[1].send(test_frame) yield sink.wait() rx_frame = sink.recv() @@ -343,8 +259,8 @@ def bench(): dest=2 ) - source_0.send(test_frame1) - source_0.send(test_frame2) + source_list[0].send(test_frame1) + source_list[0].send(test_frame2) yield sink.wait() rx_frame = sink.recv() @@ -381,11 +297,11 @@ def bench(): dest=2 ) - source_1.send(test_frame1) - source_2.send(test_frame2) + source_list[1].send(test_frame1) + source_list[2].send(test_frame2) yield clk.posedge - while input_0_axis_tvalid or input_1_axis_tvalid or input_2_axis_tvalid or input_3_axis_tvalid: + while s_axis_tvalid: yield clk.posedge select.next = 2 @@ -424,22 +340,22 @@ def bench(): dest=2 ) - source_1.send(test_frame1) - source_2.send(test_frame2) + source_list[1].send(test_frame1) + source_list[2].send(test_frame2) yield clk.posedge - while input_0_axis_tvalid or input_1_axis_tvalid or input_2_axis_tvalid or input_3_axis_tvalid: - source_0_pause.next = True - source_1_pause.next = True - source_2_pause.next = True - source_3_pause.next = True + while s_axis_tvalid: + source_pause_list[0].next = True + source_pause_list[1].next = True + source_pause_list[2].next = True + source_pause_list[3].next = True yield clk.posedge yield clk.posedge yield clk.posedge - source_0_pause.next = False - source_1_pause.next = False - source_2_pause.next = False - source_3_pause.next = False + source_pause_list[0].next = False + source_pause_list[1].next = False + source_pause_list[2].next = False + source_pause_list[3].next = False yield clk.posedge select.next = 2 @@ -478,11 +394,11 @@ def bench(): dest=2 ) - source_1.send(test_frame1) - source_2.send(test_frame2) + source_list[1].send(test_frame1) + source_list[2].send(test_frame2) yield clk.posedge - while input_0_axis_tvalid or input_1_axis_tvalid or input_2_axis_tvalid or input_3_axis_tvalid: + while s_axis_tvalid: sink_pause.next = True yield clk.posedge yield clk.posedge diff --git a/tb/test_axis_mux_4_64.v b/tb/test_axis_mux_4_64.v index ad62fd3d..a8d9c280 100644 --- a/tb/test_axis_mux_4_64.v +++ b/tb/test_axis_mux_4_64.v @@ -27,11 +27,12 @@ THE SOFTWARE. `timescale 1ns / 1ps /* - * Testbench for axis_mux_4 + * Testbench for axis_mux */ module test_axis_mux_4_64; // Parameters +parameter S_COUNT = 4; parameter DATA_WIDTH = 64; parameter KEEP_ENABLE = (DATA_WIDTH>8); parameter KEEP_WIDTH = (DATA_WIDTH/8); @@ -47,53 +48,29 @@ reg clk = 0; reg rst = 0; reg [7:0] current_test = 0; -reg [DATA_WIDTH-1:0] input_0_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_0_axis_tkeep = 0; -reg input_0_axis_tvalid = 0; -reg input_0_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_0_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_0_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_0_axis_tuser = 0; -reg [DATA_WIDTH-1:0] input_1_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_1_axis_tkeep = 0; -reg input_1_axis_tvalid = 0; -reg input_1_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_1_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_1_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_1_axis_tuser = 0; -reg [DATA_WIDTH-1:0] input_2_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_2_axis_tkeep = 0; -reg input_2_axis_tvalid = 0; -reg input_2_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_2_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_2_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_2_axis_tuser = 0; -reg [DATA_WIDTH-1:0] input_3_axis_tdata = 0; -reg [KEEP_WIDTH-1:0] input_3_axis_tkeep = 0; -reg input_3_axis_tvalid = 0; -reg input_3_axis_tlast = 0; -reg [ID_WIDTH-1:0] input_3_axis_tid = 0; -reg [DEST_WIDTH-1:0] input_3_axis_tdest = 0; -reg [USER_WIDTH-1:0] input_3_axis_tuser = 0; +reg [S_COUNT*DATA_WIDTH-1:0] s_axis_tdata = 0; +reg [S_COUNT*KEEP_WIDTH-1:0] s_axis_tkeep = 0; +reg [S_COUNT-1:0] s_axis_tvalid = 0; +reg [S_COUNT-1:0] s_axis_tlast = 0; +reg [S_COUNT*ID_WIDTH-1:0] s_axis_tid = 0; +reg [S_COUNT*DEST_WIDTH-1:0] s_axis_tdest = 0; +reg [S_COUNT*USER_WIDTH-1:0] s_axis_tuser = 0; -reg output_axis_tready = 0; +reg m_axis_tready = 0; reg enable = 0; reg [1:0] select = 0; // Outputs -wire input_0_axis_tready; -wire input_1_axis_tready; -wire input_2_axis_tready; -wire input_3_axis_tready; +wire [S_COUNT-1:0] s_axis_tready; -wire [DATA_WIDTH-1:0] output_axis_tdata; -wire [KEEP_WIDTH-1:0] output_axis_tkeep; -wire output_axis_tvalid; -wire output_axis_tlast; -wire [ID_WIDTH-1:0] output_axis_tid; -wire [DEST_WIDTH-1:0] output_axis_tdest; -wire [USER_WIDTH-1:0] output_axis_tuser; +wire [DATA_WIDTH-1:0] m_axis_tdata; +wire [KEEP_WIDTH-1:0] m_axis_tkeep; +wire m_axis_tvalid; +wire m_axis_tlast; +wire [ID_WIDTH-1:0] m_axis_tid; +wire [DEST_WIDTH-1:0] m_axis_tdest; +wire [USER_WIDTH-1:0] m_axis_tuser; initial begin // myhdl integration @@ -101,50 +78,26 @@ initial begin clk, rst, current_test, - input_0_axis_tdata, - input_0_axis_tkeep, - input_0_axis_tvalid, - input_0_axis_tlast, - input_0_axis_tid, - input_0_axis_tdest, - input_0_axis_tuser, - input_1_axis_tdata, - input_1_axis_tkeep, - input_1_axis_tvalid, - input_1_axis_tlast, - input_1_axis_tid, - input_1_axis_tdest, - input_1_axis_tuser, - input_2_axis_tdata, - input_2_axis_tkeep, - input_2_axis_tvalid, - input_2_axis_tlast, - input_2_axis_tid, - input_2_axis_tdest, - input_2_axis_tuser, - input_3_axis_tdata, - input_3_axis_tkeep, - input_3_axis_tvalid, - input_3_axis_tlast, - input_3_axis_tid, - input_3_axis_tdest, - input_3_axis_tuser, - output_axis_tready, + s_axis_tdata, + s_axis_tkeep, + s_axis_tvalid, + s_axis_tlast, + s_axis_tid, + s_axis_tdest, + s_axis_tuser, + m_axis_tready, enable, select ); $to_myhdl( - input_0_axis_tready, - input_1_axis_tready, - input_2_axis_tready, - input_3_axis_tready, - output_axis_tdata, - output_axis_tkeep, - output_axis_tvalid, - output_axis_tlast, - output_axis_tid, - output_axis_tdest, - output_axis_tuser + s_axis_tready, + m_axis_tdata, + m_axis_tkeep, + m_axis_tvalid, + m_axis_tlast, + m_axis_tid, + m_axis_tdest, + m_axis_tuser ); // dump file @@ -152,7 +105,8 @@ initial begin $dumpvars(0, test_axis_mux_4_64); end -axis_mux_4 #( +axis_mux #( + .S_COUNT(S_COUNT), .DATA_WIDTH(DATA_WIDTH), .KEEP_ENABLE(KEEP_ENABLE), .KEEP_WIDTH(KEEP_WIDTH), @@ -167,47 +121,23 @@ UUT ( .clk(clk), .rst(rst), // AXI inputs - .input_0_axis_tdata(input_0_axis_tdata), - .input_0_axis_tkeep(input_0_axis_tkeep), - .input_0_axis_tvalid(input_0_axis_tvalid), - .input_0_axis_tready(input_0_axis_tready), - .input_0_axis_tlast(input_0_axis_tlast), - .input_0_axis_tid(input_0_axis_tid), - .input_0_axis_tdest(input_0_axis_tdest), - .input_0_axis_tuser(input_0_axis_tuser), - .input_1_axis_tdata(input_1_axis_tdata), - .input_1_axis_tkeep(input_1_axis_tkeep), - .input_1_axis_tvalid(input_1_axis_tvalid), - .input_1_axis_tready(input_1_axis_tready), - .input_1_axis_tlast(input_1_axis_tlast), - .input_1_axis_tid(input_1_axis_tid), - .input_1_axis_tdest(input_1_axis_tdest), - .input_1_axis_tuser(input_1_axis_tuser), - .input_2_axis_tdata(input_2_axis_tdata), - .input_2_axis_tkeep(input_2_axis_tkeep), - .input_2_axis_tvalid(input_2_axis_tvalid), - .input_2_axis_tready(input_2_axis_tready), - .input_2_axis_tlast(input_2_axis_tlast), - .input_2_axis_tid(input_2_axis_tid), - .input_2_axis_tdest(input_2_axis_tdest), - .input_2_axis_tuser(input_2_axis_tuser), - .input_3_axis_tdata(input_3_axis_tdata), - .input_3_axis_tkeep(input_3_axis_tkeep), - .input_3_axis_tvalid(input_3_axis_tvalid), - .input_3_axis_tready(input_3_axis_tready), - .input_3_axis_tlast(input_3_axis_tlast), - .input_3_axis_tid(input_3_axis_tid), - .input_3_axis_tdest(input_3_axis_tdest), - .input_3_axis_tuser(input_3_axis_tuser), + .s_axis_tdata(s_axis_tdata), + .s_axis_tkeep(s_axis_tkeep), + .s_axis_tvalid(s_axis_tvalid), + .s_axis_tready(s_axis_tready), + .s_axis_tlast(s_axis_tlast), + .s_axis_tid(s_axis_tid), + .s_axis_tdest(s_axis_tdest), + .s_axis_tuser(s_axis_tuser), // AXI output - .output_axis_tdata(output_axis_tdata), - .output_axis_tkeep(output_axis_tkeep), - .output_axis_tvalid(output_axis_tvalid), - .output_axis_tready(output_axis_tready), - .output_axis_tlast(output_axis_tlast), - .output_axis_tid(output_axis_tid), - .output_axis_tdest(output_axis_tdest), - .output_axis_tuser(output_axis_tuser), + .m_axis_tdata(m_axis_tdata), + .m_axis_tkeep(m_axis_tkeep), + .m_axis_tvalid(m_axis_tvalid), + .m_axis_tready(m_axis_tready), + .m_axis_tlast(m_axis_tlast), + .m_axis_tid(m_axis_tid), + .m_axis_tdest(m_axis_tdest), + .m_axis_tuser(m_axis_tuser), // Control .enable(enable), .select(select)