[
  {
    "path": ".gitignore",
    "content": "*~\n*.lxt\n*.pyc\n*.vvp\n*.kate-swp\n\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: python\npython:\n  - \"3.4\"\nbefore_install:\n  - export d=`pwd`\n  - export PYTHON_EXE=`which python`\n  - sudo apt-get update -qq\n  - sudo apt-get install -y iverilog\n  - git clone https://github.com/jandecaluwe/myhdl.git\n  - cd $d/myhdl && sudo $PYTHON_EXE setup.py install\n  - cd $d/myhdl/cosimulation/icarus && make && sudo install -m 0755 -D ./myhdl.vpi /usr/lib/ivl/myhdl.vpi\n  - cd $d\nscript:\n  - cd tb && py.test\n\n\n"
  },
  {
    "path": "AUTHORS",
    "content": "Alex Forencich <alex@alexforencich.com>\n"
  },
  {
    "path": "COPYING",
    "content": "Copyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\n"
  },
  {
    "path": "README.md",
    "content": "Verilog DSP\n\n\n"
  },
  {
    "path": "rtl/cic_decimator.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Cascaded integrator-comb (CIC) Decimator\n */\nmodule cic_decimator #(\n    parameter WIDTH = 16,\n    parameter RMAX = 2,\n    parameter M = 1,\n    parameter N = 2,\n    parameter REG_WIDTH = WIDTH+$clog2((RMAX*M)**N)\n)\n(\n    input  wire                      clk,\n    input  wire                      rst,\n\n    /*\n     * AXI stream input\n     */\n    input  wire [WIDTH-1:0]          input_tdata,\n    input  wire                      input_tvalid,\n    output wire                      input_tready,\n\n    /*\n     * AXI stream output\n     */\n    output wire [REG_WIDTH-1:0]      output_tdata,\n    output wire                      output_tvalid,\n    input  wire                      output_tready,\n\n    /*\n     * Configuration\n     */\n    input  wire [$clog2(RMAX+1)-1:0] rate\n);\n\n/*\n * CIC decimator architecture\n *\n *                       ,---.\n * IN -->(+)--------+--->| V |----+------->(-)--- OUT\n *        ^         |    `---'    |         ^\n *        |         |             |         |\n *        +-- z-1 --+             +-- z-M --+\n *\n *       \\___________/           \\___________/\n *             N                       N\n *\n *         Integrate    Decimate     Comb\n *\n */\n\nreg [$clog2(RMAX+1)-1:0] cycle_reg = 0;\n\nreg [REG_WIDTH-1:0] int_reg[N-1:0];\n\nwire [REG_WIDTH-1:0] int_reg_0 = int_reg[0];\nwire [REG_WIDTH-1:0] int_reg_1 = int_reg[1];\n\nreg [REG_WIDTH-1:0] comb_reg[N-1:0];\n\nwire [REG_WIDTH-1:0] comb_reg_0 = comb_reg[0];\nwire [REG_WIDTH-1:0] comb_reg_1 = comb_reg[1];\n\nassign input_tready = output_tready | (cycle_reg != 0);\n\nassign output_tdata = comb_reg[N-1];\nassign output_tvalid = input_tvalid & cycle_reg == 0;\n\ngenvar k;\ninteger i;\n\ninitial begin\n    for (i = 0; i < N; i = i + 1) begin\n        int_reg[i] <= 0;\n        comb_reg[i] <= 0;\n    end\nend\n\n// integrator stages\ngenerate\n\nfor (k = 0; k < N; k = k + 1) begin : integrator\n    always @(posedge clk) begin\n        if (rst) begin\n            int_reg[k] <= 0;\n        end else begin\n            if (input_tready & input_tvalid) begin\n                if (k == 0) begin\n                    int_reg[k] <= $signed(int_reg[k]) + $signed(input_tdata);\n                end else begin\n                    int_reg[k] <= $signed(int_reg[k]) + $signed(int_reg[k-1]);\n                end\n            end\n        end\n    end\nend\n\nendgenerate\n\n// comb stages\ngenerate\n\nfor (k = 0; k < N; k = k + 1) begin : comb\n    reg [REG_WIDTH-1:0] delay_reg[M-1:0];\n\n    initial begin\n        for (i = 0; i < M; i = i + 1) begin\n            delay_reg[i] <= 0;\n        end\n    end\n\n    always @(posedge clk) begin\n        if (rst) begin\n            for (i = 0; i < M; i = i + 1) begin\n                delay_reg[i] <= 0;\n            end\n            comb_reg[k] <= 0;\n        end else begin\n            if (output_tready & output_tvalid) begin\n                if (k == 0) begin\n                    delay_reg[0] <= $signed(int_reg[N-1]);\n                    comb_reg[k] <= $signed(int_reg[N-1]) - $signed(delay_reg[M-1]);\n                end else begin\n                    delay_reg[0] <= $signed(comb_reg[k-1]);\n                    comb_reg[k] <= $signed(comb_reg[k-1]) - $signed(delay_reg[M-1]);\n                end\n\n                for (i = 0; i < M-1; i = i + 1) begin\n                    delay_reg[i+1] <= delay_reg[i];\n                end\n            end\n        end\n    end\nend\n\nendgenerate\n\nalways @(posedge clk) begin\n    if (rst) begin\n        cycle_reg <= 0;\n    end else begin\n        if (input_tready & input_tvalid) begin\n            if (cycle_reg < RMAX - 1 && cycle_reg < rate - 1) begin\n                cycle_reg <= cycle_reg + 1;\n            end else begin\n                cycle_reg <= 0;\n            end\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/cic_interpolator.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Cascaded integrator-comb (CIC) Interpolator\n */\nmodule cic_interpolator #(\n    parameter WIDTH = 16,\n    parameter RMAX = 2,\n    parameter M = 1,\n    parameter N = 2,\n    parameter REG_WIDTH = WIDTH+$max(N, $clog2(((RMAX*M)**N)/RMAX))\n)\n(\n    input  wire                      clk,\n    input  wire                      rst,\n\n    /*\n     * AXI stream input\n     */\n    input  wire [WIDTH-1:0]          input_tdata,\n    input  wire                      input_tvalid,\n    output wire                      input_tready,\n\n    /*\n     * AXI stream output\n     */\n    output wire [REG_WIDTH-1:0]      output_tdata,\n    output wire                      output_tvalid,\n    input  wire                      output_tready,\n\n    /*\n     * Configuration\n     */\n    input  wire [$clog2(RMAX+1)-1:0] rate\n);\n\n/*\n * CIC interpolator architecture\n *\n *                       ,---.\n * IN ----+------->(-)-->| ^ |-->(+)--------+---- OUT\n *        |         ^    `---'    ^         |\n *        |         |             |         |\n *        +-- z-M --+             +-- z-1 --+\n *\n *       \\___________/           \\___________/\n *             N                       N\n *\n *           Comb      Upconvert   Integrate\n *\n */\n\nreg [$clog2(RMAX+1)-1:0] cycle_reg = 0;\n\nreg [REG_WIDTH-1:0] comb_reg[N-1:0];\n\nreg [REG_WIDTH-1:0] int_reg[N-1:0];\n\nassign input_tready = output_tready & (cycle_reg == 0);\n\nassign output_tdata = int_reg[N-1];\nassign output_tvalid = input_tvalid | (cycle_reg != 0);\n\ngenvar k;\ninteger i;\n\ninitial begin\n    for (i = 0; i < N; i = i + 1) begin\n        comb_reg[i] <= 0;\n        int_reg[i] <= 0;\n    end\nend\n\n// comb stages\ngenerate\n\nfor (k = 0; k < N; k = k + 1) begin : comb\n    reg [REG_WIDTH-1:0] delay_reg[M-1:0];\n\n    initial begin\n        for (i = 0; i < M; i = i + 1) begin\n            delay_reg[i] <= 0;\n        end\n    end\n\n    always @(posedge clk) begin\n        if (rst) begin\n            for (i = 0; i < M; i = i + 1) begin\n                delay_reg[i] <= 0;\n            end\n            comb_reg[k] <= 0;\n        end else begin\n            if (input_tready & input_tvalid) begin\n                if (k == 0) begin\n                    delay_reg[0] <= $signed(input_tdata);\n                    comb_reg[k] <= $signed(input_tdata) - $signed(delay_reg[M-1]);\n                end else begin\n                    delay_reg[0] <= $signed(comb_reg[k-1]);\n                    comb_reg[k] <= $signed(comb_reg[k-1]) - $signed(delay_reg[M-1]);\n                end\n\n                for (i = 0; i < M-1; i = i + 1) begin\n                    delay_reg[i+1] <= delay_reg[i];\n                end\n            end\n        end\n    end\nend\n\nendgenerate\n\n// integrator stages\ngenerate\n\nfor (k = 0; k < N; k = k + 1) begin : integrator\n    always @(posedge clk) begin\n        if (rst) begin\n            int_reg[k] <= 0;\n        end else begin\n            if (output_tready & output_tvalid) begin\n                if (k == 0) begin\n                    if (cycle_reg == 0) begin\n                        int_reg[k] <= $signed(int_reg[k]) + $signed(comb_reg[N-1]);\n                    end\n                end else begin\n                    int_reg[k] <= $signed(int_reg[k]) + $signed(int_reg[k-1]);\n                end\n            end\n        end\n    end\nend\n\nendgenerate\n\nalways @(posedge clk) begin\n    if (rst) begin\n        cycle_reg <= 0;\n    end else begin\n        if (output_tready & output_tvalid) begin\n            if (cycle_reg < RMAX - 1 && cycle_reg < rate - 1) begin\n                cycle_reg <= cycle_reg + 1;\n            end else begin\n                cycle_reg <= 0;\n            end\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/dsp_iq_mult.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * IQ Multiplier - computes a*b\n */\nmodule dsp_iq_mult #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire                  clk,\n    input  wire                  rst,\n\n    /*\n     * AXI stream inputs\n     */\n    input  wire [WIDTH-1:0]      input_a_i_tdata,\n    input  wire [WIDTH-1:0]      input_a_q_tdata,\n    input  wire                  input_a_tvalid,\n    output wire                  input_a_tready,\n\n    input  wire [WIDTH-1:0]      input_b_i_tdata,\n    input  wire [WIDTH-1:0]      input_b_q_tdata,\n    input  wire                  input_b_tvalid,\n    output wire                  input_b_tready,\n\n    /*\n     * AXI stream output\n     */\n    output wire [(WIDTH*2)-1:0]  output_i_tdata,\n    output wire [(WIDTH*2)-1:0]  output_q_tdata,\n    output wire                  output_tvalid,\n    input  wire                  output_tready\n);\n\nreg [WIDTH-1:0] input_a_i_reg_0 = 0;\nreg [WIDTH-1:0] input_a_q_reg_0 = 0;\nreg [WIDTH-1:0] input_a_i_reg_1 = 0;\nreg [WIDTH-1:0] input_a_q_reg_1 = 0;\n\nreg [WIDTH-1:0] input_b_i_reg_0 = 0;\nreg [WIDTH-1:0] input_b_q_reg_0 = 0;\nreg [WIDTH-1:0] input_b_i_reg_1 = 0;\nreg [WIDTH-1:0] input_b_q_reg_1 = 0;\n\nreg [(WIDTH*2)-1:0] output_i_reg_0 = 0;\nreg [(WIDTH*2)-1:0] output_q_reg_0 = 0;\nreg [(WIDTH*2)-1:0] output_i_reg_1 = 0;\nreg [(WIDTH*2)-1:0] output_q_reg_1 = 0;\n\nwire transfer = input_a_tvalid & input_b_tvalid & output_tready;\n\nassign input_a_tready = input_b_tvalid & output_tready;\nassign input_b_tready = input_a_tvalid & output_tready;\n\nassign output_i_tdata = output_i_reg_1;\nassign output_q_tdata = output_q_reg_1;\nassign output_tvalid = input_a_tvalid & input_b_tvalid;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        input_a_i_reg_0 <= 0;\n        input_a_q_reg_0 <= 0;\n        input_a_i_reg_1 <= 0;\n        input_a_q_reg_1 <= 0;\n\n        input_b_i_reg_0 <= 0;\n        input_b_q_reg_0 <= 0;\n        input_b_i_reg_1 <= 0;\n        input_b_q_reg_1 <= 0;\n\n        output_i_reg_0 <= 0;\n        output_q_reg_0 <= 0;\n        output_i_reg_1 <= 0;\n        output_q_reg_1 <= 0;\n    end else begin\n        if (transfer) begin\n            // pipeline for Xilinx DSP slice\n\n            // register\n            input_a_i_reg_0 <= input_a_i_tdata;\n            input_a_q_reg_0 <= input_a_q_tdata;\n            input_b_i_reg_0 <= input_b_i_tdata;\n            input_b_q_reg_0 <= input_b_q_tdata;\n\n            // pipeline\n            input_a_i_reg_1 <= input_a_i_reg_0;\n            input_a_q_reg_1 <= input_a_q_reg_0;\n            input_b_i_reg_1 <= input_b_i_reg_0;\n            input_b_q_reg_1 <= input_b_q_reg_0;\n\n            // multiply\n            output_i_reg_0 <= $signed(input_a_i_reg_1) * $signed(input_b_i_reg_1);\n            output_q_reg_0 <= $signed(input_a_q_reg_1) * $signed(input_b_q_reg_1);\n\n            // pipeline\n            output_i_reg_1 <= output_i_reg_0;\n            output_q_reg_1 <= output_q_reg_0;\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/dsp_mult.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Multiplier - computes a*b\n */\nmodule dsp_mult #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire                  clk,\n    input  wire                  rst,\n\n    /*\n     * AXI stream inputs\n     */\n    input  wire [WIDTH-1:0]      input_a_tdata,\n    input  wire                  input_a_tvalid,\n    output wire                  input_a_tready,\n\n    input  wire [WIDTH-1:0]      input_b_tdata,\n    input  wire                  input_b_tvalid,\n    output wire                  input_b_tready,\n\n    /*\n     * AXI stream output\n     */\n    output wire [(WIDTH*2)-1:0]  output_tdata,\n    output wire                  output_tvalid,\n    input  wire                  output_tready\n);\n\nreg [WIDTH-1:0] input_a_reg_0 = 0;\nreg [WIDTH-1:0] input_a_reg_1 = 0;\n\nreg [WIDTH-1:0] input_b_reg_0 = 0;\nreg [WIDTH-1:0] input_b_reg_1 = 0;\n\nreg [(WIDTH*2)-1:0] output_reg_0 = 0;\nreg [(WIDTH*2)-1:0] output_reg_1 = 0;\n\nwire transfer = input_a_tvalid & input_b_tvalid & output_tready;\n\nassign input_a_tready = input_b_tvalid & output_tready;\nassign input_b_tready = input_a_tvalid & output_tready;\n\nassign output_tdata = output_reg_1;\nassign output_tvalid = input_a_tvalid & input_b_tvalid;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        input_a_reg_0 <= 0;\n        input_a_reg_1 <= 0;\n\n        input_b_reg_0 <= 0;\n        input_b_reg_1 <= 0;\n\n        output_reg_0 <= 0;\n        output_reg_1 <= 0;\n    end else begin\n        if (transfer) begin\n            // pipeline for Xilinx DSP slice\n\n            // register\n            input_a_reg_0 <= input_a_tdata;\n            input_b_reg_0 <= input_b_tdata;\n\n            // pipeline\n            input_a_reg_1 <= input_a_reg_0;\n            input_b_reg_1 <= input_b_reg_0;\n\n            // multiply\n            output_reg_0 <= $signed(input_a_reg_1) * $signed(input_b_reg_1);\n\n            // pipeline\n            output_reg_1 <= output_reg_0;\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/i2s_ctrl.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * I2S control\n */\nmodule i2s_ctrl #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire              clk,\n    input  wire              rst,\n\n    /*\n     * I2S interface\n     */\n    output wire              sck,\n    output wire              ws,\n\n    /*\n     * Configuration\n     */\n    input  wire [15:0]       prescale\n);\n\nreg [15:0] prescale_cnt = 0;\nreg [$clog2(WIDTH)-1:0] ws_cnt = 0;\n\nreg sck_reg = 0;\nreg ws_reg = 0;\n\nassign sck = sck_reg;\nassign ws = ws_reg;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        prescale_cnt <= 0;\n        ws_cnt <= 0;\n        sck_reg <= 0;\n        ws_reg <= 0;\n    end else begin\n        if (prescale_cnt > 0) begin\n            prescale_cnt <= prescale_cnt - 1;\n        end else begin\n            prescale_cnt <= prescale;\n            if (sck_reg) begin\n                sck_reg <= 0;\n                if (ws_cnt > 0) begin\n                    ws_cnt <= ws_cnt - 1;\n                end else begin\n                    ws_cnt <= WIDTH-1;\n                    ws_reg <= ~ws_reg;\n                end\n            end else begin\n                sck_reg <= 1;\n            end\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/i2s_rx.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * I2S RX\n */\nmodule i2s_rx #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire              clk,\n    input  wire              rst,\n\n    /*\n     * I2S interface\n     */\n    input  wire              sck,\n    input  wire              ws,\n    input  wire              sd,\n\n    /*\n     * AXI stream output\n     */\n    output wire [WIDTH-1:0]  output_l_tdata,\n    output wire [WIDTH-1:0]  output_r_tdata,\n    output wire              output_tvalid,\n    input  wire              output_tready\n);\n\nreg [WIDTH-1:0] l_data_reg = 0;\nreg [WIDTH-1:0] r_data_reg = 0;\n\nreg l_data_valid_reg = 0;\nreg r_data_valid_reg = 0;\n\nreg [WIDTH-1:0] sreg = 0;\n\nreg [$clog2(WIDTH)-1:0] bit_cnt = 0;\n\nreg last_sck = 0;\nreg last_ws = 0;\nreg last_ws2 = 0;\n\nassign output_l_tdata = l_data_reg;\nassign output_r_tdata = r_data_reg;\nassign output_tvalid = l_data_valid_reg & r_data_valid_reg;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        l_data_reg <= 0;\n        r_data_reg <= 0;\n        l_data_valid_reg <= 0;\n        r_data_valid_reg <= 0;\n        sreg <= 0;\n        bit_cnt <= 0;\n        last_sck <= 0;\n        last_ws <= 0;\n        last_ws2 <= 0;\n    end else begin\n        if (output_tready & output_tvalid) begin\n            l_data_valid_reg <= 0;\n            r_data_valid_reg <= 0;\n        end\n\n        last_sck <= sck;\n\n        if (~last_sck & sck) begin\n            // rising edge sck\n            last_ws <= ws;\n            last_ws2 <= last_ws;\n\n            if (last_ws2 != last_ws) begin\n                bit_cnt <= WIDTH-1;\n                sreg <= {{WIDTH-1{1'b0}}, sd};\n            end else begin\n                if (bit_cnt > 0) begin\n                    bit_cnt <= bit_cnt - 1;\n                    if (bit_cnt > 1) begin\n                        sreg <= {sreg[WIDTH-2:0], sd};\n                    end else if (last_ws2) begin\n                        r_data_reg <= {sreg[WIDTH-2:0], sd};\n                        r_data_valid_reg <= l_data_valid_reg;\n                    end else begin\n                        l_data_reg <= {sreg[WIDTH-2:0], sd};\n                        l_data_valid_reg <= 1;\n                    end\n                end\n            end\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/i2s_tx.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * I2S TX\n */\nmodule i2s_tx #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire              clk,\n    input  wire              rst,\n\n    /*\n     * AXI stream input\n     */\n    input  wire [WIDTH-1:0]  input_l_tdata,\n    input  wire [WIDTH-1:0]  input_r_tdata,\n    input  wire              input_tvalid,\n    output wire              input_tready,\n\n    /*\n     * I2S interface\n     */\n    input  wire              sck,\n    input  wire              ws,\n    output wire              sd\n);\n\nreg [WIDTH-1:0] l_data_reg = 0;\nreg [WIDTH-1:0] r_data_reg = 0;\n\nreg l_data_valid_reg = 0;\nreg r_data_valid_reg = 0;\n\nreg [WIDTH-1:0] sreg = 0;\n\nreg [$clog2(WIDTH+1)-1:0] bit_cnt = 0;\n\nreg last_sck = 0;\nreg last_ws = 0;\nreg sd_reg = 0;\n\nassign input_tready = ~l_data_valid_reg & ~r_data_valid_reg;\n\nassign sd = sd_reg;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        l_data_reg <= 0;\n        r_data_reg <= 0;\n        l_data_valid_reg <= 0;\n        r_data_valid_reg <= 0;\n        sreg <= 0;\n        bit_cnt <= 0;\n        last_sck <= 0;\n        last_ws <= 0;\n        sd_reg <= 0;\n    end else begin\n        if (input_tready & input_tvalid) begin\n            l_data_reg <= input_l_tdata;\n            r_data_reg <= input_r_tdata;\n            l_data_valid_reg <= 1;\n            r_data_valid_reg <= 1;\n        end\n\n        last_sck <= sck;\n\n        if (~last_sck & sck) begin\n            // rising edge sck\n            last_ws <= ws;\n\n            if (last_ws != ws) begin\n                bit_cnt <= WIDTH;\n                if (ws) begin\n                    sreg <= r_data_reg;\n                    r_data_valid_reg <= 0;\n                end else begin\n                    sreg <= l_data_reg;\n                    l_data_valid_reg <= 0;\n                end\n            end\n        end\n\n        if (last_sck & ~sck) begin\n            // falling edge sck\n            if (bit_cnt > 0) begin\n                bit_cnt <= bit_cnt - 1;\n                {sd_reg, sreg} <= {sreg[WIDTH-1:0], 1'b0};\n            end\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/iq_join.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * IQ joiner\n */\nmodule iq_join #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire              clk,\n    input  wire              rst,\n\n    /*\n     * AXI stream inputs\n     */\n    input  wire [WIDTH-1:0]  input_i_tdata,\n    input  wire              input_i_tvalid,\n    output wire              input_i_tready,\n\n    input  wire [WIDTH-1:0]  input_q_tdata,\n    input  wire              input_q_tvalid,\n    output wire              input_q_tready,\n\n    /*\n     * AXI stream output\n     */\n    output wire [WIDTH-1:0]  output_i_tdata,\n    output wire [WIDTH-1:0]  output_q_tdata,\n    output wire              output_tvalid,\n    input  wire              output_tready\n);\n\nreg [WIDTH-1:0] i_data_reg = 0;\nreg [WIDTH-1:0] q_data_reg = 0;\n\nreg i_valid_reg = 0;\nreg q_valid_reg = 0;\n\nassign input_i_tready = ~i_valid_reg | (output_tready & output_tvalid);\nassign input_q_tready = ~q_valid_reg | (output_tready & output_tvalid);\n\nassign output_i_tdata = i_data_reg;\nassign output_q_tdata = q_data_reg;\nassign output_tvalid = i_valid_reg & q_valid_reg;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        i_data_reg <= 0;\n        q_data_reg <= 0;\n        i_valid_reg <= 0;\n        q_valid_reg <= 0;\n    end else begin\n        if (input_i_tready & input_i_tvalid) begin\n            i_data_reg <= input_i_tdata;\n            i_valid_reg <= 1;\n        end else if (output_tready & output_tvalid) begin\n            i_valid_reg <= 0;\n        end\n        if (input_q_tready & input_q_tvalid) begin\n            q_data_reg <= input_q_tdata;\n            q_valid_reg <= 1;\n        end else if (output_tready & output_tvalid) begin\n            q_valid_reg <= 0;\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/iq_split.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * IQ splitter\n */\nmodule iq_split #\n(\n    parameter WIDTH = 16\n)\n(\n    input  wire              clk,\n    input  wire              rst,\n\n    /*\n     * AXI stream input\n     */\n    input  wire [WIDTH-1:0]  input_i_tdata,\n    input  wire [WIDTH-1:0]  input_q_tdata,\n    input  wire              input_tvalid,\n    output wire              input_tready,\n\n    /*\n     * AXI stream outputs\n     */\n    output wire [WIDTH-1:0]  output_i_tdata,\n    output wire              output_i_tvalid,\n    input  wire              output_i_tready,\n\n    output wire [WIDTH-1:0]  output_q_tdata,\n    output wire              output_q_tvalid,\n    input  wire              output_q_tready\n);\n\nreg [WIDTH-1:0] i_data_reg = 0;\nreg [WIDTH-1:0] q_data_reg = 0;\n\nreg i_valid_reg = 0;\nreg q_valid_reg = 0;\n\nassign input_tready = (~i_valid_reg | (output_i_tready & output_i_tvalid)) & (~q_valid_reg | (output_q_tready & output_q_tvalid));\n\nassign output_i_tdata = i_data_reg;\nassign output_i_tvalid = i_valid_reg;\n\nassign output_q_tdata = q_data_reg;\nassign output_q_tvalid = q_valid_reg;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        i_data_reg <= 0;\n        q_data_reg <= 0;\n        i_valid_reg <= 0;\n        q_valid_reg <= 0;\n    end else begin\n        if (input_tready & input_tvalid) begin\n            i_data_reg <= input_i_tdata;\n            q_data_reg <= input_q_tdata;\n            i_valid_reg <= 1;\n            q_valid_reg <= 1;\n        end else begin\n            if (output_i_tready) begin\n                i_valid_reg <= 0;\n            end\n            if (output_q_tready) begin\n                q_valid_reg <= 0;\n            end\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/phase_accumulator.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Phase accumulator\n */\nmodule phase_accumulator #\n(\n    parameter WIDTH = 32,\n    parameter INITIAL_PHASE = 0,\n    parameter INITIAL_PHASE_STEP = 0\n)\n(\n    input  wire             clk,\n    input  wire             rst,\n\n    /*\n     * AXI stream phase input\n     */\n    input  wire [WIDTH-1:0] input_phase_tdata,\n    input  wire             input_phase_tvalid,\n    output wire             input_phase_tready,\n\n    /*\n     * AXI stream phase step input\n     */\n    input  wire [WIDTH-1:0] input_phase_step_tdata,\n    input  wire             input_phase_step_tvalid,\n    output wire             input_phase_step_tready,\n\n    /*\n     * AXI stream phase output\n     */\n    output wire [WIDTH-1:0] output_phase_tdata,\n    output wire             output_phase_tvalid,\n    input  wire             output_phase_tready\n);\n\nreg [WIDTH-1:0] phase_reg = INITIAL_PHASE;\nreg [WIDTH-1:0] phase_step_reg = INITIAL_PHASE_STEP;\n\nassign input_phase_tready = output_phase_tready;\nassign input_phase_step_tready = 1;\nassign output_phase_tdata = phase_reg;\nassign output_phase_tvalid = 1;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        phase_reg <= INITIAL_PHASE;\n        phase_step_reg <= INITIAL_PHASE_STEP;\n    end else begin\n        if (input_phase_tready & input_phase_tvalid) begin\n            phase_reg <= input_phase_tdata;\n        end else if (output_phase_tready) begin\n            phase_reg <= phase_reg + phase_step_reg;\n        end\n\n        if (input_phase_step_tvalid) begin\n            phase_step_reg <= input_phase_step_tdata;\n        end\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "rtl/sine_dds.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Sine DDS\n */\nmodule sine_dds #\n(\n    parameter PHASE_WIDTH = 32,\n    parameter OUTPUT_WIDTH = 16,\n    parameter INITIAL_PHASE = 0,\n    parameter INITIAL_PHASE_STEP = 0\n)\n(\n    input  wire                    clk,\n    input  wire                    rst,\n\n    /*\n     * AXI stream phase input\n     */\n    input  wire [PHASE_WIDTH-1:0]  input_phase_tdata,\n    input  wire                    input_phase_tvalid,\n    output wire                    input_phase_tready,\n\n    /*\n     * AXI stream phase step input\n     */\n    input  wire [PHASE_WIDTH-1:0]  input_phase_step_tdata,\n    input  wire                    input_phase_step_tvalid,\n    output wire                    input_phase_step_tready,\n\n    /*\n     * AXI stream sample output\n     */\n    output wire [OUTPUT_WIDTH-1:0] output_sample_i_tdata,\n    output wire [OUTPUT_WIDTH-1:0] output_sample_q_tdata,\n    output wire                    output_sample_tvalid,\n    input  wire                    output_sample_tready\n);\n\nwire [PHASE_WIDTH-1:0] phase_tdata;\nwire phase_tvalid;\nwire phase_tready;\n\nphase_accumulator #(\n    .WIDTH(PHASE_WIDTH),\n    .INITIAL_PHASE(INITIAL_PHASE),\n    .INITIAL_PHASE_STEP(INITIAL_PHASE_STEP)\n)\nphase_accumulator_inst (\n    .clk(clk),\n    .rst(rst),\n    \n    .input_phase_tdata(input_phase_tdata),\n    .input_phase_tvalid(input_phase_tvalid),\n    .input_phase_tready(input_phase_tready),\n\n    .input_phase_step_tdata(input_phase_step_tdata),\n    .input_phase_step_tvalid(input_phase_step_tvalid),\n    .input_phase_step_tready(input_phase_step_tready),\n\n    .output_phase_tdata(phase_tdata),\n    .output_phase_tvalid(phase_tvalid),\n    .output_phase_tready(phase_tready)\n);\n\nsine_dds_lut #(\n    .INPUT_WIDTH(OUTPUT_WIDTH+2),\n    .OUTPUT_WIDTH(OUTPUT_WIDTH)\n)\nsine_dds_inst (\n    .clk(clk),\n    .rst(rst),\n\n    .input_phase_tdata(phase_tdata[PHASE_WIDTH-1:PHASE_WIDTH-OUTPUT_WIDTH-2]),\n    .input_phase_tvalid(phase_tvalid),\n    .input_phase_tready(phase_tready),\n\n    .output_sample_i_tdata(output_sample_i_tdata),\n    .output_sample_q_tdata(output_sample_q_tdata),\n    .output_sample_tvalid(output_sample_tvalid),\n    .output_sample_tready(output_sample_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "rtl/sine_dds_lut.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Sine DDS look up table\n */\nmodule sine_dds_lut #\n(\n    parameter OUTPUT_WIDTH = 16,\n    parameter INPUT_WIDTH = OUTPUT_WIDTH+2\n)\n(\n    input  wire                    clk,\n    input  wire                    rst,\n\n    /*\n     * AXI stream phase input\n     */\n    input  wire [INPUT_WIDTH-1:0]  input_phase_tdata,\n    input  wire                    input_phase_tvalid,\n    output wire                    input_phase_tready,\n\n    /*\n     * AXI stream sample output\n     */\n    output wire [OUTPUT_WIDTH-1:0] output_sample_i_tdata,\n    output wire [OUTPUT_WIDTH-1:0] output_sample_q_tdata,\n    output wire                    output_sample_tvalid,\n    input  wire                    output_sample_tready\n);\n\nlocalparam W = (INPUT_WIDTH-2)/2;\n\nreg [INPUT_WIDTH-1:0] phase_reg = 0;\n\ninteger i;\n\n// coarse sine and cosine LUTs\nreg [OUTPUT_WIDTH-1:0] coarse_c_lut[2**(W+1)-1:0];\nreg [OUTPUT_WIDTH-1:0] coarse_s_lut[2**(W+1)-1:0];\n\ninitial begin\n    for (i = 0; i < 2**(W+1); i = i + 1) begin\n        coarse_c_lut[i] = $cos(2*3.1415926535*i/2**(W+2))*(2**(OUTPUT_WIDTH-1)-1);\n        coarse_s_lut[i] = $sin(2*3.1415926535*i/2**(W+2))*(2**(OUTPUT_WIDTH-1)-1);\n    end\nend\n\n// fine sine LUT\nreg [(OUTPUT_WIDTH/2)-1:0] fine_s_lut[2**W-1:0];\n\ninitial begin\n    for (i = 0; i < 2**W; i = i + 1) begin\n        fine_s_lut[i] = $sin(2*3.1415926535*(i-2**(W-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1);\n    end\nend\n\nreg [OUTPUT_WIDTH-1:0] sample_i_reg = 0;\nreg [OUTPUT_WIDTH-1:0] sample_q_reg = 0;\n\nwire SIGN = phase_reg[INPUT_WIDTH-1];\nwire SLOPE = phase_reg[INPUT_WIDTH-2];\nwire [W:0] A = phase_reg[INPUT_WIDTH-2:W];\nwire [W-1:0] B = phase_reg[W-1:0];\n\nreg sign_reg_1 = 0;\nreg sign_reg_2 = 0;\nreg sign_reg_3 = 0;\nreg sign_reg_4 = 0;\n\nreg [OUTPUT_WIDTH-1:0] ccs_reg_1 = 0, ccs_reg_2 = 0, ccs_reg_3 = 0;\nreg [OUTPUT_WIDTH-1:0] css_reg_1 = 0, css_reg_2 = 0, css_reg_3 = 0;\nreg [(OUTPUT_WIDTH/2)-1:0] fss_reg_1 = 0, fss_reg_2 = 0;\n\nreg [(OUTPUT_WIDTH*2)-1:0] cp_reg_1 = 0;\nreg [(OUTPUT_WIDTH*2)-1:0] sp_reg_1 = 0;\n\nreg [OUTPUT_WIDTH-1:0] cs_reg_1 = 0;\nreg [OUTPUT_WIDTH-1:0] ss_reg_1 = 0;\n\nassign input_phase_tready = output_sample_tready;\nassign output_sample_i_tdata = sample_i_reg;\nassign output_sample_q_tdata = sample_q_reg;\nassign output_sample_tvalid = input_phase_tvalid;\n\nalways @(posedge clk) begin\n    if (rst) begin\n        phase_reg <= 0;\n    end else begin\n        if (input_phase_tready & input_phase_tvalid) begin\n            phase_reg <= input_phase_tdata;\n        end\n    end\n\n    if (input_phase_tready & input_phase_tvalid) begin\n        // pipeline sits primarily in DSP slice\n        // sin(A+B) = sin(A) + cos(A)*sin(B)\n        // cos(A+B) = cos(A) - sin(A)*sin(B)\n        \n        // read samples\n        sign_reg_1 <= SIGN;\n        ccs_reg_1 <= coarse_c_lut[A];\n        css_reg_1 <= coarse_s_lut[A];\n        fss_reg_1 <= fine_s_lut[B];\n\n        // pipeline\n        sign_reg_2 <= sign_reg_1;\n        ccs_reg_2 <= ccs_reg_1;\n        css_reg_2 <= css_reg_1;\n        fss_reg_2 <= fss_reg_1;\n\n        // multiply\n        sign_reg_3 <= sign_reg_2;\n        ccs_reg_3 <= ccs_reg_2;\n        css_reg_3 <= css_reg_2;\n        cp_reg_1 <= $signed(css_reg_2) * $signed(fss_reg_2);\n        sp_reg_1 <= $signed(ccs_reg_2) * $signed(fss_reg_2);\n\n        // add\n        sign_reg_4 <= sign_reg_3;\n        cs_reg_1 <= ccs_reg_3 - (cp_reg_1 >> (OUTPUT_WIDTH-1));\n        ss_reg_1 <= css_reg_3 + (sp_reg_1 >> (OUTPUT_WIDTH-1));\n\n        // negate output samples\n        sample_i_reg <= sign_reg_4 ? -cs_reg_1 : cs_reg_1;\n        sample_q_reg <= sign_reg_4 ? -ss_reg_1 : ss_reg_1;\n    end\nend\n\nendmodule\n"
  },
  {
    "path": "tb/axis_ep.py",
    "content": "\"\"\"\n\nCopyright (c) 2014-2018 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\n\nskip_asserts = False\n\nclass AXIStreamFrame(object):\n    def __init__(self, data=b'', keep=None, id=None, dest=None, user=None, last_cycle_user=None):\n        self.B = 0\n        self.N = 8\n        self.M = 1\n        self.WL = 8\n        self.data = b''\n        self.keep = None\n        self.id = 0\n        self.dest = 0\n        self.user = None\n        self.last_cycle_user = None\n\n        if type(data) in (bytes, bytearray):\n            self.data = bytearray(data)\n            self.keep = keep\n            self.id = id\n            self.dest = dest\n            self.user = user\n            self.last_cycle_user = last_cycle_user\n        elif type(data) is AXIStreamFrame:\n            self.N = data.N\n            self.WL = data.WL\n            if type(data.data) is bytearray:\n                self.data = bytearray(data.data)\n            else:\n                self.data = list(data.data)\n            if data.keep is not None:\n                self.keep = list(data.keep)\n            if data.id is not None:\n                if type(data.id) in (int, bool):\n                    self.id = data.id\n                else:\n                    self.id = list(data.id)\n            if data.dest is not None:\n                if type(data.dest) in (int, bool):\n                    self.dest = data.dest\n                else:\n                    self.dest = list(data.dest)\n            if data.user is not None:\n                if type(data.user) in (int, bool):\n                    self.user = data.user\n                else:\n                    self.user = list(data.user)\n            self.last_cycle_user = data.last_cycle_user\n        else:\n            self.data = list(data)\n            self.keep = keep\n            self.id = id\n            self.dest = dest\n            self.user = user\n            self.last_cycle_user = last_cycle_user\n\n    def build(self):\n        if self.data is None:\n            return\n\n        f = list(self.data)\n        tdata = []\n        tkeep = []\n        tid = []\n        tdest = []\n        tuser = []\n        i = 0\n\n        while len(f) > 0:\n            if self.B == 0:\n                data = 0\n                keep = 0\n                for j in range(self.M):\n                    data = data | (f.pop(0) << (j*self.WL))\n                    keep = keep | (1 << j)\n                    if len(f) == 0: break\n                tdata.append(data)\n\n                if self.keep is None:\n                    tkeep.append(keep)\n                else:\n                    tkeep.append(self.keep[i])\n            else:\n                # multiple tdata signals\n                data = 0\n                tdata.append(f.pop(0))\n                tkeep.append(0)\n\n            if self.id is None:\n                tid.append(0)\n            elif type(self.id) is int:\n                tid.append(self.id)\n            else:\n                tid.append(self.id[i])\n\n            if self.dest is None:\n                tdest.append(0)\n            elif type(self.dest) is int:\n                tdest.append(self.dest)\n            else:\n                tdest.append(self.dest[i])\n\n            if self.user is None:\n                tuser.append(0)\n            elif type(self.user) is int:\n                tuser.append(self.user)\n            else:\n                tuser.append(self.user[i])\n            i += 1\n\n        if self.last_cycle_user:\n            tuser[-1] = self.last_cycle_user\n\n        return tdata, tkeep, tid, tdest, tuser\n\n    def parse(self, tdata, tkeep, tid, tdest, tuser):\n        if tdata is None or tkeep is None or tuser is None:\n            return\n        if len(tdata) != len(tkeep) or len(tdata) != len(tid) or len(tdata) != len(tdest) or len(tdata) != len(tuser):\n            raise Exception(\"Invalid data\")\n\n        self.data = []\n        self.keep = []\n        self.id = []\n        self.dest = []\n        self.user = []\n\n        if self.B == 0:\n            mask = 2**self.WL-1\n\n            for i in range(len(tdata)):\n                for j in range(self.M):\n                    if tkeep[i] & (1 << j):\n                        self.data.append((tdata[i] >> (j*self.WL)) & mask)\n                self.keep.append(tkeep[i])\n                self.id.append(tid[i])\n                self.dest.append(tdest[i])\n                self.user.append(tuser[i])\n        else:\n            for i in range(len(tdata)):\n                self.data.append(tdata[i])\n                self.keep.append(tkeep[i])\n                self.id.append(tid[i])\n                self.dest.append(tdest[i])\n                self.user.append(tuser[i])\n\n        if self.WL == 8:\n            self.data = bytearray(self.data)\n\n        self.last_cycle_user = self.user[-1]\n\n    def __eq__(self, other):\n        if not isinstance(other, AXIStreamFrame):\n            return False\n        if self.data != other.data:\n            return False\n        if self.keep is not None and other.keep is not None:\n            if self.keep != other.keep:\n                return False\n        if self.id is not None and other.id is not None:\n            if type(self.id) in (int, bool) and type(other.id) is list:\n                for k in other.id:\n                    if self.id != k:\n                        return False\n            elif type(other.id) in (int, bool) and type(self.id) is list:\n                for k in self.id:\n                    if other.id != k:\n                        return False\n            elif self.id != other.id:\n                return False\n        if self.dest is not None and other.dest is not None:\n            if type(self.dest) in (int, bool) and type(other.dest) is list:\n                for k in other.dest:\n                    if self.dest != k:\n                        return False\n            elif type(other.dest) in (int, bool) and type(self.dest) is list:\n                for k in self.dest:\n                    if other.dest != k:\n                        return False\n            elif self.dest != other.dest:\n                return False\n        if self.last_cycle_user is not None and other.last_cycle_user is not None:\n            if self.last_cycle_user != other.last_cycle_user:\n                return False\n            if self.user is not None and other.user is not None:\n                if type(self.user) in (int, bool) and type(other.user) is list:\n                    for k in other.user[:-1]:\n                        if self.user != k:\n                            return False\n                elif type(other.user) in (int, bool) and type(self.user) is list:\n                    for k in self.user[:-1]:\n                        if other.user != k:\n                            return False\n                elif self.user != other.user:\n                    return False\n        else:\n            if self.user is not None and other.user is not None:\n                if type(self.user) in (int, bool) and type(other.user) is list:\n                    for k in other.user:\n                        if self.user != k:\n                            return False\n                elif type(other.user) in (int, bool) and type(self.user) is list:\n                    for k in self.user:\n                        if other.user != k:\n                            return False\n                elif self.user != other.user:\n                    return False\n        return True\n\n    def __repr__(self):\n        return (\n                ('AXIStreamFrame(data=%s, ' % repr(self.data)) +\n                ('keep=%s, ' % repr(self.keep)) +\n                ('id=%s, ' % repr(self.id)) +\n                ('dest=%s, ' % repr(self.dest)) +\n                ('user=%s, ' % repr(self.user)) +\n                ('last_cycle_user=%s)' % repr(self.last_cycle_user))\n            )\n\n    def __iter__(self):\n        return self.data.__iter__()\n\n\nclass AXIStreamSource(object):\n    def __init__(self):\n        self.has_logic = False\n        self.queue = []\n\n    def send(self, frame):\n        self.queue.append(AXIStreamFrame(frame))\n\n    def write(self, data):\n        self.send(data)\n\n    def count(self):\n        return len(self.queue)\n\n    def empty(self):\n        return self.count() == 0\n\n    def create_logic(self,\n                clk,\n                rst,\n                tdata=None,\n                tkeep=Signal(bool(True)),\n                tvalid=Signal(bool(False)),\n                tready=Signal(bool(True)),\n                tlast=Signal(bool(False)),\n                tid=Signal(intbv(0)),\n                tdest=Signal(intbv(0)),\n                tuser=Signal(intbv(0)),\n                pause=0,\n                name=None\n            ):\n\n        assert not self.has_logic\n\n        self.has_logic = True\n\n        tready_int = Signal(bool(False))\n        tvalid_int = Signal(bool(False))\n\n        @always_comb\n        def pause_logic():\n            tready_int.next = tready and not pause\n            tvalid.next = tvalid_int and not pause\n\n        @instance\n        def logic():\n            frame = AXIStreamFrame()\n            data = []\n            keep = []\n            id = []\n            dest = []\n            user = []\n            B = 0\n            N = len(tdata)\n            M = len(tkeep)\n            WL = int((len(tdata)+M-1)/M)\n\n            if type(tdata) is list or type(tdata) is tuple:\n                # multiple tdata signals\n                B = len(tdata)\n                N = [len(b) for b in tdata]\n                M = 1\n                WL = [1]*B\n\n            while True:\n                yield clk.posedge, rst.posedge\n\n                if rst:\n                    if B > 0:\n                        for s in tdata:\n                            s.next = 0\n                    else:\n                        tdata.next = 0\n                    tkeep.next = 0\n                    tid.next = 0\n                    tdest.next = 0\n                    tuser.next = False\n                    tvalid_int.next = False\n                    tlast.next = False\n                else:\n                    if tready_int and tvalid:\n                        if len(data) > 0:\n                            if B > 0:\n                                l = data.pop(0)\n                                for i in range(B):\n                                    tdata[i].next = l[i]\n                            else:\n                                tdata.next = data.pop(0)\n                            tkeep.next = keep.pop(0)\n                            tid.next = id.pop(0)\n                            tdest.next = dest.pop(0)\n                            tuser.next = user.pop(0)\n                            tvalid_int.next = True\n                            tlast.next = len(data) == 0\n                        else:\n                            tvalid_int.next = False\n                            tlast.next = False\n                    if (tlast and tready_int and tvalid) or not tvalid_int:\n                        if len(self.queue) > 0:\n                            frame = self.queue.pop(0)\n                            frame.B = B\n                            frame.N = N\n                            frame.M = M\n                            frame.WL = WL\n                            data, keep, id, dest, user = frame.build()\n                            if name is not None:\n                                print(\"[%s] Sending frame %s\" % (name, repr(frame)))\n                            if B > 0:\n                                l = data.pop(0)\n                                for i in range(B):\n                                    tdata[i].next = l[i]\n                            else:\n                                tdata.next = data.pop(0)\n                            tkeep.next = keep.pop(0)\n                            tid.next = id.pop(0)\n                            tdest.next = dest.pop(0)\n                            tuser.next = user.pop(0)\n                            tvalid_int.next = True\n                            tlast.next = len(data) == 0\n\n        return instances()\n\n\nclass AXIStreamSink(object):\n    def __init__(self):\n        self.has_logic = False\n        self.queue = []\n        self.read_queue = []\n\n    def recv(self):\n        if len(self.queue) > 0:\n            return self.queue.pop(0)\n        return None\n\n    def read(self, count=-1):\n        while len(self.queue) > 0:\n            self.read_queue.extend(self.queue.pop(0).data)\n        if count < 0:\n            count = len(self.read_queue)\n        data = self.read_queue[:count]\n        del self.read_queue[:count]\n        return data\n\n    def count(self):\n        return len(self.queue)\n\n    def empty(self):\n        return self.count() == 0\n\n    def create_logic(self,\n                clk,\n                rst,\n                tdata=None,\n                tkeep=Signal(bool(True)),\n                tvalid=Signal(bool(False)),\n                tready=Signal(bool(True)),\n                tlast=Signal(bool(True)),\n                tid=Signal(intbv(0)),\n                tdest=Signal(intbv(0)),\n                tuser=Signal(intbv(0)),\n                pause=0,\n                name=None\n            ):\n\n        assert not self.has_logic\n\n        self.has_logic = True\n\n        tready_int = Signal(bool(False))\n        tvalid_int = Signal(bool(False))\n\n        @always_comb\n        def pause_logic():\n            tready.next = tready_int and not pause\n            tvalid_int.next = tvalid and not pause\n\n        @instance\n        def logic():\n            frame = AXIStreamFrame()\n            data = []\n            keep = []\n            id = []\n            dest = []\n            user = []\n            B = 0\n            N = len(tdata)\n            M = len(tkeep)\n            WL = int((len(tdata)+M-1)/M)\n            first = True\n\n            if type(tdata) is list or type(tdata) is tuple:\n                # multiple tdata signals\n                B = len(tdata)\n                N = [len(b) for b in tdata]\n                M = 1\n                WL = [1]*B\n\n            while True:\n                yield clk.posedge, rst.posedge\n\n                if rst:\n                    tready_int.next = False\n                    frame = AXIStreamFrame()\n                    data = []\n                    keep = []\n                    id = []\n                    dest = []\n                    user = []\n                    first = True\n                else:\n                    tready_int.next = True\n\n                    if tvalid_int:\n\n                        if not skip_asserts:\n                            # zero tkeep not allowed\n                            assert int(tkeep) != 0\n                            # tkeep must be contiguous\n                            # i.e. 0b00011110 allowed, but 0b00011010 not allowed\n                            b = int(tkeep)\n                            while b & 1 == 0:\n                                b = b >> 1\n                            while b & 1 == 1:\n                                b = b >> 1\n                            assert b == 0\n                            # tkeep must not have gaps across cycles\n                            if not first:\n                                # not first cycle; lowest bit must be set\n                                assert int(tkeep) & 1\n                            if not tlast:\n                                # not last cycle; highest bit must be set\n                                assert int(tkeep) & (1 << len(tkeep)-1)\n\n                        if B > 0:\n                            l = []\n                            for i in range(B):\n                                l.append(int(tdata[i]))\n                            data.append(l)\n                        else:\n                            data.append(int(tdata))\n                        keep.append(int(tkeep))\n                        id.append(int(tid))\n                        dest.append(int(tdest))\n                        user.append(int(tuser))\n                        first = False\n                        if tlast:\n                            frame.B = B\n                            frame.N = N\n                            frame.M = M\n                            frame.WL = WL\n                            frame.parse(data, keep, id, dest, user)\n                            self.queue.append(frame)\n                            if name is not None:\n                                print(\"[%s] Got frame %s\" % (name, repr(frame)))\n                            frame = AXIStreamFrame()\n                            data = []\n                            keep = []\n                            id = []\n                            dest = []\n                            user = []\n                            first = True\n\n        return instances()\n\n"
  },
  {
    "path": "tb/i2s_ep.py",
    "content": "\"\"\"\n\nCopyright (c) 2014 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\n\ndef I2SControl(clk, rst,\n               sck=None,\n               ws=None,\n               width=16,\n               prescale=2):\n    \n    @instance\n    def logic():\n        prescale_cnt = 0\n        ws_cnt = 0\n\n        while True:\n            yield clk.posedge\n\n            if rst:\n                sck.next = 0\n                ws.next = 0\n                prescale_cnt = 0\n                ws_cnt = 0\n            else:\n                if prescale_cnt > 0:\n                    prescale_cnt = prescale_cnt - 1;\n                else:\n                    prescale_cnt = prescale;\n                    if sck:\n                        sck.next = False\n                        if ws_cnt > 0:\n                            ws_cnt = ws_cnt - 1\n                        else:\n                            ws_cnt = width-1\n                            ws.next = not ws\n                    else:\n                        sck.next = True\n\n    return instances()\n\n\ndef I2SSource(clk, rst,\n              sck=None,\n              ws=None,\n              sd=None,\n              width=16,\n              fifo=None,\n              name=None):\n    \n    @instance\n    def logic():\n        lst = None\n        r_data = 0\n        bit_cnt = 0\n        last_sck = 0\n        last_ws = 0\n        sreg = 0\n\n        while True:\n            yield clk.posedge\n\n            if rst:\n                sd.next = 0\n                r_data = 0\n                bit_cnt = 0\n                last_sck = 0\n                last_ws = 0\n                sreg = 0\n            else:\n                if not last_sck and sck:\n                    if last_ws != ws:\n                        bit_cnt = width\n\n                        if ws:\n                            sreg = r_data\n                        else:\n                            d = (0,0)\n                            if lst is None or len(lst) == 0:\n                                if not fifo.empty():\n                                    d = fifo.get(False)\n                                if type(d) is list:\n                                    lst = d\n                                    d = lst.pop(0)\n                            else:\n                                d = lst.pop(0)\n                            sreg, r_data = d\n                            if name is not None:\n                                print(\"[%s] Sending I2S data (%d, %d)\" % (name, sreg, r_data))\n\n                    last_ws = int(ws)\n\n                if last_sck and not sck:\n                    if bit_cnt > 0:\n                        bit_cnt = bit_cnt - 1\n                        sd.next = sreg & (1 << bit_cnt) != 0\n\n                last_sck = int(sck)\n\n\n    return logic\n\n\ndef I2SSink(clk, rst,\n            sck=None,\n            ws=None,\n            sd=None,\n            width=16,\n            fifo=None,\n            name=None):\n    \n    @instance\n    def logic():\n        l_data = 0\n        bit_cnt = 0\n        last_sck = 0\n        last_ws = 0\n        last_ws2 = 0\n        sreg = 0\n\n        while True:\n            yield clk.posedge\n\n            if rst:\n                l_data = 0\n                bit_cnt = 0\n                last_sck = 0\n                last_ws = 0\n                last_ws2 = 0\n                sreg = 0\n            else:\n                if not last_sck and sck:\n                    if last_ws2 != last_ws:\n                        bit_cnt = width-1\n                        sreg = int(sd)\n                    elif bit_cnt > 0:\n                        if bit_cnt > 1:\n                            sreg = (sreg << 1) | int(sd)\n                        elif last_ws2:\n                            d = (sreg << 1) | int(sd)\n                            fifo.put((l_data, d))\n                            if name is not None:\n                                print(\"[%s] Got I2S data (%d, %d)\" % (name, l_data, d))\n                        else:\n                            l_data = (sreg << 1) | int(sd)\n\n                        bit_cnt = bit_cnt - 1\n\n                    last_ws2 = last_ws\n                    last_ws = int(ws)\n\n                last_sck = int(sck)\n\n    return instances()\n\n"
  },
  {
    "path": "tb/test_cic_decimator.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport numpy as np\nimport math\n\nimport axis_ep\n\nmodule = 'cic_decimator'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_cic_decimator(clk,\n                      rst,\n                      current_test,\n                      input_tdata,\n                      input_tvalid,\n                      input_tready,\n                      output_tdata,\n                      output_tvalid,\n                      output_tready,\n                      rate):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_tdata=input_tdata,\n                input_tvalid=input_tvalid,\n                input_tready=input_tready,\n                output_tdata=output_tdata,\n                output_tvalid=output_tvalid,\n                output_tready=output_tready,\n                rate=rate)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n    RMAX = 4\n    M = 1\n    N = 2\n    REG_WIDTH = WIDTH+math.ceil(math.log10((RMAX*M)**N)/math.log10(2))\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_tdata = Signal(intbv(0)[WIDTH:])\n    input_tvalid = Signal(bool(0))\n    output_tready = Signal(bool(0))\n    rate = Signal(intbv(0)[math.ceil(math.log10(RMAX+1)/math.log10(2)):])\n\n    # Outputs\n    input_tready = Signal(bool(0))\n    output_tdata = Signal(intbv(0)[REG_WIDTH:])\n    output_tvalid = Signal(bool(0))\n\n    # sources and sinks\n    input_source_queue = Queue()\n    input_source_pause = Signal(bool(0))\n    output_sink_queue = Queue()\n    output_sink_pause = Signal(bool(0))\n    \n    input_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_tdata,\n                                           tvalid=input_tvalid,\n                                           tready=input_tready,\n                                           fifo=input_source_queue,\n                                           pause=input_source_pause,\n                                           name='input_source')\n\n    output_sink = axis_ep.AXIStreamSink(clk,\n                                        rst,\n                                        tdata=output_tdata,\n                                        tvalid=output_tvalid,\n                                        tready=output_tready,\n                                        fifo=output_sink_queue,\n                                        pause=output_sink_pause,\n                                        name='output_sink')\n\n    # DUT\n    dut = dut_cic_decimator(clk,\n                            rst,\n                            current_test,\n                            input_tdata,\n                            input_tvalid,\n                            input_tready,\n                            output_tdata,\n                            output_tvalid,\n                            output_tready,\n                            rate)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        rate.next = 2\n\n        yield clk.posedge\n        print(\"test 1: impulse response\")\n        current_test.next = 1\n\n        y = [1, 0, 0, 0, 0]\n        ref = cic_decimate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*10\n\n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: ramp\")\n        current_test.next = 2\n\n        # reset integrator\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        y = list(range(100)) + [0,0,0,0,0]\n        ref = cic_decimate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*10\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 3: source pause\")\n        current_test.next = 3\n\n        # reset integrator\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        y = list(range(100)) + [0,0,0,0,0]\n        ref = cic_decimate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*10\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            input_source_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            input_source_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 4: sink pause\")\n        current_test.next = 4\n\n        # reset integrator\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        y = list(range(100)) + [0,0,0,0,0]\n        ref = cic_decimate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*10\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            output_sink_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            output_sink_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 5: sinewave\")\n        current_test.next = 5\n\n        # reset integrator\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        x = np.arange(0,100)\n        y = np.r_[(np.sin(2*np.pi*x/50)*1024).astype(int), [0,0,0,0]]\n        ref = cic_decimate(y, N, M, rate)\n\n        ys = y\n        ys[y < 0] += 2**WIDTH\n\n        refs = ref\n        refs[ref < 0] += 2**REG_WIDTH\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(map(int, ys)) + [0]*10\n\n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 6: rate of 4\")\n        current_test.next = 6\n\n        # reset integrator\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        rate.next = 4\n\n        yield clk.posedge\n\n        x = np.arange(0,100)\n        y = np.r_[(np.sin(2*np.pi*x/50)*1024).astype(int), [0]*10]\n        ref = cic_decimate(y, N, M, rate)\n\n        ys = y\n        ys[y < 0] += 2**WIDTH\n\n        refs = ref\n        refs[ref < 0] += 2**REG_WIDTH\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(map(int, ys)) + [0]*10\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 7: DC\")\n        current_test.next = 7\n\n        # reset integrator\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        rate.next = 2\n\n        yield clk.posedge\n\n        y = np.r_[np.ones(1000).astype(int)*1000, [0]*10]\n        ref = cic_decimate(y, N, M, rate)\n\n        ys = y\n        ys[y < 0] += 2**WIDTH\n\n        refs = ref\n        refs[ref < 0] += 2**REG_WIDTH\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(map(int, ys)) + [0]*10\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef cic_decimate(y, N=2, M=1, R=2):\n    y = np.array(y)\n\n    # integrate\n    for i in range(N):\n        s = 0\n        for j in range(len(y)):\n            s += y[j]\n            y[j] = s\n\n    # pipeline delay\n    y = np.r_[[0]*N, y]\n\n    # upconvert\n    y = y[0::R]\n\n    # comb stage\n    for i in range(N):\n        for j in range(len(y)-1, M-1, -1):\n            y[j] = y[j] - y[j-M]\n\n    return y\n\ndef contains(small, big):\n    for i in range(len(big)-len(small)+1):\n        for j in range(len(small)):\n            if big[i+j] != small[j]:\n                break\n        else:\n            return i, i+len(small)\n    return False\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_cic_decimator.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for cic_decimator\n */\nmodule test_cic_decimator;\n\n// Parameters\nparameter WIDTH = 16;\nparameter RMAX = 4;\nparameter M = 1;\nparameter N = 2;\nparameter REG_WIDTH = WIDTH+$clog2((RMAX*M)**N);\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_tdata = 0;\nreg input_tvalid = 0;\nreg output_tready = 0;\nreg [$clog2(RMAX+1)-1:0] rate = 0;\n\n// Outputs\nwire input_tready;\nwire [REG_WIDTH-1:0] output_tdata;\nwire output_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_tdata,\n                input_tvalid,\n                output_tready,\n                rate);\n    $to_myhdl(input_tready,\n              output_tdata,\n              output_tvalid);\n\n    // dump file\n    $dumpfile(\"test_cic_decimator.lxt\");\n    $dumpvars(0, test_cic_decimator);\nend\n\ncic_decimator #(\n    .WIDTH(WIDTH),\n    .RMAX(RMAX),\n    .M(M),\n    .N(N)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_tdata(input_tdata),\n    .input_tvalid(input_tvalid),\n    .input_tready(input_tready),\n    .output_tdata(output_tdata),\n    .output_tvalid(output_tvalid),\n    .output_tready(output_tready),\n    .rate(rate)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_cic_interpolator.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport numpy as np\nimport math\n\nimport axis_ep\n\nmodule = 'cic_interpolator'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_cic_interpolator(clk,\n                         rst,\n                         current_test,\n                         input_tdata,\n                         input_tvalid,\n                         input_tready,\n                         output_tdata,\n                         output_tvalid,\n                         output_tready,\n                         rate):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_tdata=input_tdata,\n                input_tvalid=input_tvalid,\n                input_tready=input_tready,\n                output_tdata=output_tdata,\n                output_tvalid=output_tvalid,\n                output_tready=output_tready,\n                rate=rate)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n    RMAX = 4\n    M = 1\n    N = 2\n    REG_WIDTH = WIDTH+max(N, math.ceil(math.log10(((RMAX*M)**N)/RMAX)/math.log10(2)))\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_tdata = Signal(intbv(0)[WIDTH:])\n    input_tvalid = Signal(bool(0))\n    output_tready = Signal(bool(0))\n    rate = Signal(intbv(0)[math.ceil(math.log10(RMAX+1)/math.log10(2)):])\n\n    # Outputs\n    input_tready = Signal(bool(0))\n    output_tdata = Signal(intbv(0)[REG_WIDTH:])\n    output_tvalid = Signal(bool(0))\n\n    # sources and sinks\n    input_source_queue = Queue()\n    input_source_pause = Signal(bool(0))\n    output_sink_queue = Queue()\n    output_sink_pause = Signal(bool(0))\n    \n    input_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_tdata,\n                                           tvalid=input_tvalid,\n                                           tready=input_tready,\n                                           fifo=input_source_queue,\n                                           pause=input_source_pause,\n                                           name='input_source')\n\n    output_sink = axis_ep.AXIStreamSink(clk,\n                                        rst,\n                                        tdata=output_tdata,\n                                        tvalid=output_tvalid,\n                                        tready=output_tready,\n                                        fifo=output_sink_queue,\n                                        pause=output_sink_pause,\n                                        name='output_sink')\n\n    # DUT\n    dut = dut_cic_interpolator(clk,\n                               rst,\n                               current_test,\n                               input_tdata,\n                               input_tvalid,\n                               input_tready,\n                               output_tdata,\n                               output_tvalid,\n                               output_tready,\n                               rate)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        rate.next = 2\n\n        yield clk.posedge\n        print(\"test 1: impulse response\")\n        current_test.next = 1\n\n        y = [1, 0, 0, 0, 0]\n        ref = cic_interpolate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*5\n\n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: ramp\")\n        current_test.next = 2\n\n        y = list(range(100)) + [0,0]\n        ref = cic_interpolate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*5\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 3: source pause\")\n        current_test.next = 3\n\n        y = list(range(100)) + [0,0]\n        ref = cic_interpolate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*5\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            input_source_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            input_source_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 4: sink pause\")\n        current_test.next = 4\n\n        y = list(range(100)) + [0,0]\n        ref = cic_interpolate(y, N, M, rate)\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = y + [0]*5\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            output_sink_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            output_sink_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 5: sinewave\")\n        current_test.next = 5\n\n        x = np.arange(0,100)\n        y = np.r_[(np.sin(2*np.pi*x/50)*1024).astype(int), [0,0]]\n        ref = cic_interpolate(y, N, M, rate)\n\n        ys = y\n        ys[y < 0] += 2**WIDTH\n\n        refs = ref\n        refs[ref < 0] += 2**REG_WIDTH\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(map(int, ys)) + [0]*5\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 6: rate of 4\")\n        current_test.next = 6\n\n        rate.next = 4\n\n        yield clk.posedge\n\n        x = np.arange(0,100)\n        y = np.r_[(np.sin(2*np.pi*x/50)*1024).astype(int), [0,0]]\n        ref = cic_interpolate(y, N, M, rate)\n\n        ys = y\n        ys[y < 0] += 2**WIDTH\n\n        refs = ref\n        refs[ref < 0] += 2**REG_WIDTH\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(map(int, ys)) + [0]*5\n        \n        input_source_queue.put(test_frame)\n        \n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        print(lst)\n        print(ref)\n        assert contains(ref, lst)\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef cic_interpolate(y, N=2, M=1, R=2):\n    y = np.array(y)\n\n    # comb stage\n    for i in range(N):\n        for j in range(len(y)-1, M-1, -1):\n            y[j] = y[j] - y[j-M]\n\n    # upconvert\n    y2 = np.zeros(y.shape[0]*R, dtype=y.dtype)\n    y2[0::R] = y\n    y = y2\n\n    # integrate\n    for i in range(N):\n        s = 0\n        for j in range(len(y)):\n            s += y[j]\n            y[j] = s\n\n    return y\n\ndef contains(small, big):\n    for i in range(len(big)-len(small)+1):\n        for j in range(len(small)):\n            if big[i+j] != small[j]:\n                break\n        else:\n            return i, i+len(small)\n    return False\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_cic_interpolator.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for cic_interpolator\n */\nmodule test_cic_interpolator;\n\n// Parameters\nparameter WIDTH = 16;\nparameter RMAX = 4;\nparameter M = 1;\nparameter N = 2;\nparameter REG_WIDTH = WIDTH+$max(N, $clog2(((RMAX*M)**N)/RMAX));\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_tdata = 0;\nreg input_tvalid = 0;\nreg output_tready = 0;\nreg [$clog2(RMAX+1)-1:0] rate = 0;\n\n// Outputs\nwire input_tready;\nwire [REG_WIDTH-1:0] output_tdata;\nwire output_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_tdata,\n                input_tvalid,\n                output_tready,\n                rate);\n    $to_myhdl(input_tready,\n              output_tdata,\n              output_tvalid);\n\n    // dump file\n    $dumpfile(\"test_cic_interpolator.lxt\");\n    $dumpvars(0, test_cic_interpolator);\nend\n\ncic_interpolator #(\n    .WIDTH(WIDTH),\n    .RMAX(RMAX),\n    .M(M),\n    .N(N)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_tdata(input_tdata),\n    .input_tvalid(input_tvalid),\n    .input_tready(input_tready),\n    .output_tdata(output_tdata),\n    .output_tvalid(output_tvalid),\n    .output_tready(output_tready),\n    .rate(rate)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_dsp_iq_mult.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\n\nmodule = 'dsp_iq_mult'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_dsp_iq_mult(clk,\n                    rst,\n                    current_test,\n                    input_a_i_tdata,\n                    input_a_q_tdata,\n                    input_a_tvalid,\n                    input_a_tready,\n                    input_b_i_tdata,\n                    input_b_q_tdata,\n                    input_b_tvalid,\n                    input_b_tready,\n                    output_i_tdata,\n                    output_q_tdata,\n                    output_tvalid,\n                    output_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_a_i_tdata=input_a_i_tdata,\n                input_a_q_tdata=input_a_q_tdata,\n                input_a_tvalid=input_a_tvalid,\n                input_a_tready=input_a_tready,\n                input_b_i_tdata=input_b_i_tdata,\n                input_b_q_tdata=input_b_q_tdata,\n                input_b_tvalid=input_b_tvalid,\n                input_b_tready=input_b_tready,\n                output_i_tdata=output_i_tdata,\n                output_q_tdata=output_q_tdata,\n                output_tvalid=output_tvalid,\n                output_tready=output_tready)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_a_i_tdata = Signal(intbv(0)[WIDTH:])\n    input_a_q_tdata = Signal(intbv(0)[WIDTH:])\n    input_a_tvalid = Signal(bool(0))\n    input_b_i_tdata = Signal(intbv(0)[WIDTH:])\n    input_b_q_tdata = Signal(intbv(0)[WIDTH:])\n    input_b_tvalid = Signal(bool(0))\n    output_tready = Signal(bool(0))\n\n    # Outputs\n    input_a_tready = Signal(bool(0))\n    input_b_tready = Signal(bool(0))\n    output_i_tdata = Signal(intbv(0)[WIDTH*2:])\n    output_q_tdata = Signal(intbv(0)[WIDTH*2:])\n    output_tvalid = Signal(bool(0))\n\n    # sources and sinks\n    input_a_source_queue = Queue()\n    input_a_source_pause = Signal(bool(0))\n    input_b_source_queue = Queue()\n    input_b_source_pause = Signal(bool(0))\n    output_sink_queue = Queue()\n    output_sink_pause = Signal(bool(0))\n\n    input_a_source = axis_ep.AXIStreamSource(clk,\n                                             rst,\n                                             tdata=(input_a_i_tdata, input_a_q_tdata),\n                                             tvalid=input_a_tvalid,\n                                             tready=input_a_tready,\n                                             fifo=input_a_source_queue,\n                                             pause=input_a_source_pause,\n                                             name='input_a_source')\n\n    input_b_source = axis_ep.AXIStreamSource(clk,\n                                             rst,\n                                             tdata=(input_b_i_tdata, input_b_q_tdata),\n                                             tvalid=input_b_tvalid,\n                                             tready=input_b_tready,\n                                             fifo=input_b_source_queue,\n                                             pause=input_b_source_pause,\n                                             name='input_b_source')\n\n    output_sink = axis_ep.AXIStreamSink(clk,\n                                       rst,\n                                       tdata=(output_i_tdata, output_q_tdata),\n                                       tvalid=output_tvalid,\n                                       tready=output_tready,\n                                       fifo=output_sink_queue,\n                                       pause=output_sink_pause,\n                                       name='output_sink')\n\n    # DUT\n    dut = dut_dsp_iq_mult(clk,\n                          rst,\n                          current_test,\n                          input_a_i_tdata,\n                          input_a_q_tdata,\n                          input_a_tvalid,\n                          input_a_tready,\n                          input_b_i_tdata,\n                          input_b_q_tdata,\n                          input_b_tvalid,\n                          input_b_tready,\n                          output_i_tdata,\n                          output_q_tdata,\n                          output_tvalid,\n                          output_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test multiplier\")\n        current_test.next = 1\n\n        test_frame1 = axis_ep.AXIStreamFrame()\n        test_frame1.data = [[12, 56]] + [[0,0]]*4\n        test_frame2 = axis_ep.AXIStreamFrame()\n        test_frame2.data = [[34, 78]] + [[0,0]]*4\n\n        input_a_source_queue.put(test_frame1)\n        input_b_source_queue.put(test_frame2)\n\n        yield clk.posedge\n        yield clk.posedge\n        yield clk.posedge\n        yield clk.posedge\n\n        while output_sink_queue.empty():\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        for i in range(4):\n            rx_frame = output_sink_queue.get(False)\n\n        rx_frame = output_sink_queue.get(False)\n        assert rx_frame.data[0] == [12*34,56*78]\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_dsp_iq_mult.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for dsp_iq_mult\n */\nmodule test_dsp_iq_mult;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_a_i_tdata = 0;\nreg [WIDTH-1:0] input_a_q_tdata = 0;\nreg input_a_tvalid = 0;\nreg [WIDTH-1:0] input_b_i_tdata = 0;\nreg [WIDTH-1:0] input_b_q_tdata = 0;\nreg input_b_tvalid = 0;\nreg output_tready = 0;\n\n// Outputs\nwire input_a_tready;\nwire input_b_tready;\nwire [(WIDTH*2)-1:0] output_i_tdata;\nwire [(WIDTH*2)-1:0] output_q_tdata;\nwire output_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_a_i_tdata,\n                input_a_q_tdata,\n                input_a_tvalid,\n                input_b_i_tdata,\n                input_b_q_tdata,\n                input_b_tvalid,\n                output_tready);\n    $to_myhdl(input_a_tready,\n              input_b_tready,\n              output_i_tdata,\n              output_q_tdata,\n              output_tvalid);\n\n    // dump file\n    $dumpfile(\"test_dsp_iq_mult.lxt\");\n    $dumpvars(0, test_dsp_iq_mult);\nend\n\ndsp_iq_mult #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_a_i_tdata(input_a_i_tdata),\n    .input_a_q_tdata(input_a_q_tdata),\n    .input_a_tvalid(input_a_tvalid),\n    .input_a_tready(input_a_tready),\n    .input_b_i_tdata(input_b_i_tdata),\n    .input_b_q_tdata(input_b_q_tdata),\n    .input_b_tvalid(input_b_tvalid),\n    .input_b_tready(input_b_tready),\n    .output_i_tdata(output_i_tdata),\n    .output_q_tdata(output_q_tdata),\n    .output_tvalid(output_tvalid),\n    .output_tready(output_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_dsp_mult.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\n\nmodule = 'dsp_mult'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_dsp_mult(clk,\n                 rst,\n                 current_test,\n                 input_a_tdata,\n                 input_a_tvalid,\n                 input_a_tready,\n                 input_b_tdata,\n                 input_b_tvalid,\n                 input_b_tready,\n                 output_tdata,\n                 output_tvalid,\n                 output_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_a_tdata=input_a_tdata,\n                input_a_tvalid=input_a_tvalid,\n                input_a_tready=input_a_tready,\n                input_b_tdata=input_b_tdata,\n                input_b_tvalid=input_b_tvalid,\n                input_b_tready=input_b_tready,\n                output_tdata=output_tdata,\n                output_tvalid=output_tvalid,\n                output_tready=output_tready)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_a_tdata = Signal(intbv(0)[WIDTH:])\n    input_a_tvalid = Signal(bool(0))\n    input_b_tdata = Signal(intbv(0)[WIDTH:])\n    input_b_tvalid = Signal(bool(0))\n    output_tready = Signal(bool(0))\n\n    # Outputs\n    input_a_tready = Signal(bool(0))\n    input_b_tready = Signal(bool(0))\n    output_tdata = Signal(intbv(0)[WIDTH*2:])\n    output_tvalid = Signal(bool(0))\n\n    # sources and sinks\n    input_a_source_queue = Queue()\n    input_a_source_pause = Signal(bool(0))\n    input_b_source_queue = Queue()\n    input_b_source_pause = Signal(bool(0))\n    output_sink_queue = Queue()\n    output_sink_pause = Signal(bool(0))\n\n    input_a_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_a_tdata,\n                                           tvalid=input_a_tvalid,\n                                           tready=input_a_tready,\n                                           fifo=input_a_source_queue,\n                                           pause=input_a_source_pause,\n                                           name='input_a_source')\n\n    input_b_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_b_tdata,\n                                           tvalid=input_b_tvalid,\n                                           tready=input_b_tready,\n                                           fifo=input_b_source_queue,\n                                           pause=input_b_source_pause,\n                                           name='input_b_source')\n\n    output_sink = axis_ep.AXIStreamSink(clk,\n                                       rst,\n                                       tdata=output_tdata,\n                                       tvalid=output_tvalid,\n                                       tready=output_tready,\n                                       fifo=output_sink_queue,\n                                       pause=output_sink_pause,\n                                       name='output_sink')\n\n    # DUT\n    dut = dut_dsp_mult(clk,\n                       rst,\n                       current_test,\n                       input_a_tdata,\n                       input_a_tvalid,\n                       input_a_tready,\n                       input_b_tdata,\n                       input_b_tvalid,\n                       input_b_tready,\n                       output_tdata,\n                       output_tvalid,\n                       output_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test multiplier\")\n        current_test.next = 1\n\n        test_frame1 = axis_ep.AXIStreamFrame()\n        test_frame1.data = [123] + [0]*4\n        test_frame2 = axis_ep.AXIStreamFrame()\n        test_frame2.data = [456] + [0]*4\n\n        input_a_source_queue.put(test_frame1)\n        input_b_source_queue.put(test_frame2)\n\n        yield clk.posedge\n        yield clk.posedge\n        yield clk.posedge\n        yield clk.posedge\n\n        while output_sink_queue.empty():\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        for i in range(4):\n            rx_frame = output_sink_queue.get(False)\n\n        rx_frame = output_sink_queue.get(False)\n        assert rx_frame.data[0] == 123*456\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_dsp_mult.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for dsp_mult\n */\nmodule test_dsp_mult;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_a_tdata = 0;\nreg input_a_tvalid = 0;\nreg [WIDTH-1:0] input_b_tdata = 0;\nreg input_b_tvalid = 0;\nreg output_tready = 0;\n\n// Outputs\nwire input_a_tready;\nwire input_b_tready;\nwire [(WIDTH*2)-1:0] output_tdata;\nwire output_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_a_tdata,\n                input_a_tvalid,\n                input_b_tdata,\n                input_b_tvalid,\n                output_tready);\n    $to_myhdl(input_a_tready,\n              input_b_tready,\n              output_tdata,\n              output_tvalid);\n\n    // dump file\n    $dumpfile(\"test_dsp_mult.lxt\");\n    $dumpvars(0, test_dsp_mult);\nend\n\ndsp_mult #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_a_tdata(input_a_tdata),\n    .input_a_tvalid(input_a_tvalid),\n    .input_a_tready(input_a_tready),\n    .input_b_tdata(input_b_tdata),\n    .input_b_tvalid(input_b_tvalid),\n    .input_b_tready(input_b_tready),\n    .output_tdata(output_tdata),\n    .output_tvalid(output_tvalid),\n    .output_tready(output_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_i2s_ctrl.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nimport i2s_ep\n\nmodule = 'i2s_ctrl'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_i2s_ctrl(clk,\n                 rst,\n                 current_test,\n                 sck,\n                 ws,\n                 prescale):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                sck=sck,\n                ws=ws,\n                prescale=prescale)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    prescale = Signal(intbv(0)[16:])\n\n    # Outputs\n    sck = Signal(bool(0))\n    ws = Signal(bool(0))\n\n    sck_check = Signal(bool(0))\n    ws_check = Signal(bool(0))\n\n    i2s_ctrl = i2s_ep.I2SControl(clk,\n                                 rst,\n                                 sck=sck_check,\n                                 ws=ws_check,\n                                 width=WIDTH,\n                                 prescale=prescale)\n\n    # DUT\n    dut = dut_i2s_ctrl(clk,\n                       rst,\n                       current_test,\n                       sck,\n                       ws,\n                       prescale)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: no prescaler\")\n        current_test.next = 1\n\n        for i in range(100):\n            print(sck, ws, sck_check, ws_check)\n            assert sck == sck_check\n            assert ws == ws_check\n            yield clk.posedge\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: prescaler of 4\")\n        current_test.next = 2\n\n        prescale.next = 4\n\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        for i in range(100):\n            print(sck, ws, sck_check, ws_check)\n            assert sck == sck_check\n            assert ws == ws_check\n            yield clk.posedge\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_i2s_ctrl.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for i2s_ctrl\n */\nmodule test_i2s_ctrl;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [15:0] prescale = 0;\n\n// Outputs\nwire sck;\nwire ws;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                prescale);\n    $to_myhdl(sck,\n              ws);\n\n    // dump file\n    $dumpfile(\"test_i2s_ctrl.lxt\");\n    $dumpvars(0, test_i2s_ctrl);\nend\n\ni2s_ctrl #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .sck(sck),\n    .ws(ws),\n    .prescale(prescale)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_i2s_rx.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\nimport i2s_ep\n\nmodule = 'i2s_rx'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_i2s_rx(clk,\n               rst,\n               current_test,\n               sck,\n               ws,\n               sd,\n               output_l_tdata,\n               output_r_tdata,\n               output_tvalid,\n               output_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                sck=sck,\n                ws=ws,\n                sd=sd,\n                output_l_tdata=output_l_tdata,\n                output_r_tdata=output_r_tdata,\n                output_tvalid=output_tvalid,\n                output_tready=output_tready)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    i2s_ctrl_width = Signal(intbv(WIDTH))\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    sck = Signal(bool(0))\n    ws = Signal(bool(0))\n    sd = Signal(bool(0))\n    output_tready = Signal(bool(0))\n\n    # Outputs\n    output_l_tdata = Signal(intbv(0)[WIDTH:])\n    output_r_tdata = Signal(intbv(0)[WIDTH:])\n    output_tvalid = Signal(bool(0))\n\n    # Sources and sinks\n    input_source_queue = Queue()\n    output_sink_queue = Queue()\n    output_sink_pause = Signal(bool(0))\n\n    i2s_ctrl = i2s_ep.I2SControl(clk,\n                                 rst,\n                                 sck=sck,\n                                 ws=ws,\n                                 width=i2s_ctrl_width,\n                                 prescale=2)\n\n    i2s_source = i2s_ep.I2SSource(clk,\n                                  rst,\n                                  sck=sck,\n                                  ws=ws,\n                                  sd=sd,\n                                  width=WIDTH,\n                                  fifo=input_source_queue,\n                                  name='source')\n\n    output_sink = axis_ep.AXIStreamSink(clk,\n                                        rst,\n                                        tdata=(output_l_tdata, output_r_tdata),\n                                        tvalid=output_tvalid,\n                                        tready=output_tready,\n                                        fifo=output_sink_queue,\n                                        pause=output_sink_pause,\n                                        name='output_sink')\n\n    # DUT\n    dut = dut_i2s_rx(clk,\n                     rst,\n                     current_test,\n                     sck,\n                     ws,\n                     sd,\n                     output_l_tdata,\n                     output_r_tdata,\n                     output_tvalid,\n                     output_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test ramp\")\n        current_test.next = 1\n\n        y_l = list(range(0,4096,128))\n        y_r = list(range(4096-128,-128,-128))\n        y = list(zip(y_l, y_r))\n\n        for p in y:\n            input_source_queue.put(p)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not input_source_queue.empty():\n            yield clk.posedge\n\n        yield clk.posedge\n\n        yield delay(3000)\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        lst = [tuple(p) for p in lst]\n\n        assert contains(y, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: trailing zeros\")\n        current_test.next = 2\n\n        i2s_ctrl_width.next = 24\n\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        y_l = list(range(0,4096,128))\n        y_r = list(range(4096-128,-128,-128))\n        y = list(zip(y_l, y_r))\n\n        for p in y:\n            input_source_queue.put(p)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not input_source_queue.empty():\n            yield clk.posedge\n\n        yield clk.posedge\n\n        yield delay(5000)\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        lst = [tuple(p) for p in lst]\n\n        assert contains(y, lst)\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef contains(small, big):\n    for i in range(len(big)-len(small)+1):\n        for j in range(len(small)):\n            if big[i+j] != small[j]:\n                break\n        else:\n            return i, i+len(small)\n    return False\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_i2s_rx.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for i2s_rx\n */\nmodule test_i2s_rx;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg sck = 0;\nreg ws = 0;\nreg sd = 0;\nreg output_tready = 0;\n\n// Outputs\nwire [WIDTH-1:0] output_l_tdata;\nwire [WIDTH-1:0] output_r_tdata;\nwire output_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                sck,\n                ws,\n                sd,\n                output_tready);\n    $to_myhdl(output_l_tdata,\n              output_r_tdata,\n              output_tvalid);\n\n    // dump file\n    $dumpfile(\"test_i2s_rx.lxt\");\n    $dumpvars(0, test_i2s_rx);\nend\n\ni2s_rx #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .sck(sck),\n    .ws(ws),\n    .sd(sd),\n    .output_l_tdata(output_l_tdata),\n    .output_r_tdata(output_r_tdata),\n    .output_tvalid(output_tvalid),\n    .output_tready(output_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_i2s_tx.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\nimport i2s_ep\n\nmodule = 'i2s_tx'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_i2s_tx(clk,\n               rst,\n               current_test,\n               input_l_tdata,\n               input_r_tdata,\n               input_tvalid,\n               input_tready,\n               sck,\n               ws,\n               sd):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_l_tdata=input_l_tdata,\n                input_r_tdata=input_r_tdata,\n                input_tvalid=input_tvalid,\n                input_tready=input_tready,\n                sck=sck,\n                ws=ws,\n                sd=sd)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    i2s_ctrl_width = Signal(intbv(WIDTH))\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_l_tdata = Signal(intbv(0)[WIDTH:])\n    input_r_tdata = Signal(intbv(0)[WIDTH:])\n    input_tvalid = Signal(bool(0))\n    sck = Signal(bool(0))\n    ws = Signal(bool(0))\n\n    # Outputs\n    input_tready = Signal(bool(0))\n    sd = Signal(bool(0))\n\n    # Sources and sinks\n    input_source_queue = Queue()\n    input_source_pause = Signal(bool(0))\n    output_sink_queue = Queue()\n\n    input_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=(input_l_tdata, input_r_tdata),\n                                           tvalid=input_tvalid,\n                                           tready=input_tready,\n                                           fifo=input_source_queue,\n                                           pause=input_source_pause,\n                                           name='input_source')\n\n    i2s_ctrl = i2s_ep.I2SControl(clk,\n                                 rst,\n                                 sck=sck,\n                                 ws=ws,\n                                 width=i2s_ctrl_width,\n                                 prescale=2)\n\n    i2s_sink = i2s_ep.I2SSink(clk,\n                              rst,\n                              sck=sck,\n                              ws=ws,\n                              sd=sd,\n                              width=WIDTH,\n                              fifo=output_sink_queue,\n                              name='sink')\n\n    # DUT\n    dut = dut_i2s_tx(clk,\n                     rst,\n                     current_test,\n                     input_l_tdata,\n                     input_r_tdata,\n                     input_tvalid,\n                     input_tready,\n                     sck,\n                     ws,\n                     sd)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test ramp\")\n        current_test.next = 1\n\n        y_l = list(range(0,4096,128))\n        y_r = list(range(4096-128,-128,-128))\n        y = list(zip(y_l, y_r))\n\n        input_source_queue.put(y)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        yield delay(3000)\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst.append(output_sink_queue.get(False))\n\n        assert contains(y, lst)\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: trailing zeros\")\n        current_test.next = 2\n\n        i2s_ctrl_width.next = 24\n\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        y_l = list(range(0,4096,128))\n        y_r = list(range(4096-128,-128,-128))\n        y = list(zip(y_l, y_r))\n\n        input_source_queue.put(y)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n\n        yield delay(5000)\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst.append(output_sink_queue.get(False))\n\n        assert contains(y, lst)\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef contains(small, big):\n    for i in range(len(big)-len(small)+1):\n        for j in range(len(small)):\n            if big[i+j] != small[j]:\n                break\n        else:\n            return i, i+len(small)\n    return False\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_i2s_tx.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for i2s_tx\n */\nmodule test_i2s_tx;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_l_tdata = 0;\nreg [WIDTH-1:0] input_r_tdata = 0;\nreg input_tvalid = 0;\nreg sck = 0;\nreg ws = 0;\n\n// Outputs\nwire input_tready;\nwire sd;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_l_tdata,\n                input_r_tdata,\n                input_tvalid,\n                sck,\n                ws);\n    $to_myhdl(input_tready,\n              sd);\n\n    // dump file\n    $dumpfile(\"test_i2s_tx.lxt\");\n    $dumpvars(0, test_i2s_tx);\nend\n\ni2s_tx #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_l_tdata(input_l_tdata),\n    .input_r_tdata(input_r_tdata),\n    .input_tvalid(input_tvalid),\n    .input_tready(input_tready),\n    .sck(sck),\n    .ws(ws),\n    .sd(sd)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_iq_join.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\n\nmodule = 'iq_join'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_iq_join(clk,\n                rst,\n                current_test,\n                input_i_tdata,\n                input_i_tvalid,\n                input_i_tready,\n                input_q_tdata,\n                input_q_tvalid,\n                input_q_tready,\n                output_i_tdata,\n                output_q_tdata,\n                output_tvalid,\n                output_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_i_tdata=input_i_tdata,\n                input_i_tvalid=input_i_tvalid,\n                input_i_tready=input_i_tready,\n                input_q_tdata=input_q_tdata,\n                input_q_tvalid=input_q_tvalid,\n                input_q_tready=input_q_tready,\n                output_i_tdata=output_i_tdata,\n                output_q_tdata=output_q_tdata,\n                output_tvalid=output_tvalid,\n                output_tready=output_tready)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_i_tdata = Signal(intbv(0)[WIDTH:])\n    input_i_tvalid = Signal(bool(0))\n    input_q_tdata = Signal(intbv(0)[WIDTH:])\n    input_q_tvalid = Signal(bool(0))\n    output_tready = Signal(bool(0))\n\n    # Outputs\n    input_i_tready = Signal(bool(0))\n    input_q_tready = Signal(bool(0))\n    output_i_tdata = Signal(intbv(0)[WIDTH:])\n    output_q_tdata = Signal(intbv(0)[WIDTH:])\n    output_tvalid = Signal(bool(0))\n\n    # Sources and sinks\n    input_i_source_queue = Queue()\n    input_i_source_pause = Signal(bool(0))\n    input_q_source_queue = Queue()\n    input_q_source_pause = Signal(bool(0))\n    output_sink_queue = Queue()\n    output_sink_pause = Signal(bool(0))\n\n    input_i_source = axis_ep.AXIStreamSource(clk,\n                                             rst,\n                                             tdata=input_i_tdata,\n                                             tvalid=input_i_tvalid,\n                                             tready=input_i_tready,\n                                             fifo=input_i_source_queue,\n                                             pause=input_i_source_pause,\n                                             name='input_i_source')\n\n    input_q_source = axis_ep.AXIStreamSource(clk,\n                                             rst,\n                                             tdata=input_q_tdata,\n                                             tvalid=input_q_tvalid,\n                                             tready=input_q_tready,\n                                             fifo=input_q_source_queue,\n                                             pause=input_q_source_pause,\n                                             name='input_q_source')\n\n    output_sink = axis_ep.AXIStreamSink(clk,\n                                       rst,\n                                       tdata=(output_i_tdata, output_q_tdata),\n                                       tvalid=output_tvalid,\n                                       tready=output_tready,\n                                       fifo=output_sink_queue,\n                                       pause=output_sink_pause,\n                                       name='output_sink')\n\n    # DUT\n    dut = dut_iq_join(clk,\n                      rst,\n                      current_test,\n                      input_i_tdata,\n                      input_i_tvalid,\n                      input_i_tready,\n                      input_q_tdata,\n                      input_q_tvalid,\n                      input_q_tready,\n                      output_i_tdata,\n                      output_q_tdata,\n                      output_tvalid,\n                      output_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test sequence\")\n        current_test.next = 1\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame_i = axis_ep.AXIStreamFrame(i_data)\n        test_frame_q = axis_ep.AXIStreamFrame(q_data)\n\n        input_i_source_queue.put(test_frame_i)\n        input_q_source_queue.put(test_frame_q)\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_i_tvalid or input_q_tvalid or output_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        assert lst == [list(f) for f in zip(i_data, q_data)]\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: pause source\")\n        current_test.next = 2\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame_i = axis_ep.AXIStreamFrame(i_data)\n        test_frame_q = axis_ep.AXIStreamFrame(q_data)\n\n        input_i_source_queue.put(test_frame_i)\n        input_q_source_queue.put(test_frame_q)\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_i_tvalid or input_q_tvalid or output_tvalid:\n            input_i_source_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            input_i_source_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        assert lst == [list(f) for f in zip(i_data, q_data)]\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 3: pause both sources\")\n        current_test.next = 3\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame_i = axis_ep.AXIStreamFrame(i_data)\n        test_frame_q = axis_ep.AXIStreamFrame(q_data)\n\n        input_i_source_queue.put(test_frame_i)\n        input_q_source_queue.put(test_frame_q)\n        yield clk.posedge\n        yield clk.posedge\n\n        input_q_source_pause.next = True\n\n        while input_i_tvalid or input_q_tvalid or output_tvalid:\n            input_i_source_pause.next = True\n            yield clk.posedge\n            input_q_source_pause.next = False\n            yield clk.posedge\n            input_q_source_pause.next = True\n            yield clk.posedge\n            input_i_source_pause.next = False\n            yield clk.posedge\n\n        input_q_source_pause.next = False\n\n        yield clk.posedge\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        assert lst == [list(f) for f in zip(i_data, q_data)]\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 4: pause sink\")\n        current_test.next = 4\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame_i = axis_ep.AXIStreamFrame(i_data)\n        test_frame_q = axis_ep.AXIStreamFrame(q_data)\n\n        input_i_source_queue.put(test_frame_i)\n        input_q_source_queue.put(test_frame_q)\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_i_tvalid or input_q_tvalid or output_tvalid:\n            output_sink_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            output_sink_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        assert lst == [list(f) for f in zip(i_data, q_data)]\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 5: pause source and sink\")\n        current_test.next = 4\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame_i = axis_ep.AXIStreamFrame(i_data)\n        test_frame_q = axis_ep.AXIStreamFrame(q_data)\n\n        input_i_source_queue.put(test_frame_i)\n        input_q_source_queue.put(test_frame_q)\n        yield clk.posedge\n        yield clk.posedge\n\n        input_q_source_pause.next = True\n    \n        while input_i_tvalid or input_q_tvalid or output_tvalid:\n            output_sink_pause.next = True\n            yield clk.posedge\n            input_q_source_pause.next = False\n            yield clk.posedge\n            input_q_source_pause.next = True\n            yield clk.posedge\n            output_sink_pause.next = False\n            yield clk.posedge\n        \n        input_q_source_pause.next = False\n\n        yield clk.posedge\n        yield clk.posedge\n\n        lst = []\n\n        while not output_sink_queue.empty():\n            lst += output_sink_queue.get(False).data\n\n        assert lst == [list(f) for f in zip(i_data, q_data)]\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_iq_join.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for iq_join\n */\nmodule test_iq_join;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_i_tdata = 0;\nreg input_i_tvalid = 0;\nreg [WIDTH-1:0] input_q_tdata = 0;\nreg input_q_tvalid = 0;\nreg output_tready = 0;\n\n// Outputs\nwire input_i_tready;\nwire input_q_tready;\nwire [WIDTH-1:0] output_i_tdata;\nwire [WIDTH-1:0] output_q_tdata;\nwire output_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_i_tdata,\n                input_i_tvalid,\n                input_q_tdata,\n                input_q_tvalid,\n                output_tready);\n    $to_myhdl(input_i_tready,\n              input_q_tready,\n              output_i_tdata,\n              output_q_tdata,\n              output_tvalid);\n\n    // dump file\n    $dumpfile(\"test_iq_join.lxt\");\n    $dumpvars(0, test_iq_join);\nend\n\niq_join #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_i_tdata(input_i_tdata),\n    .input_i_tvalid(input_i_tvalid),\n    .input_i_tready(input_i_tready),\n    .input_q_tdata(input_q_tdata),\n    .input_q_tvalid(input_q_tvalid),\n    .input_q_tready(input_q_tready),\n    .output_i_tdata(output_i_tdata),\n    .output_q_tdata(output_q_tdata),\n    .output_tvalid(output_tvalid),\n    .output_tready(output_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_iq_split.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\n\nmodule = 'iq_split'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_iq_split(clk,\n                 rst,\n                 current_test,\n                 input_i_tdata,\n                 input_q_tdata,\n                 input_tvalid,\n                 input_tready,\n                 output_i_tdata,\n                 output_i_tvalid,\n                 output_i_tready,\n                 output_q_tdata,\n                 output_q_tvalid,\n                 output_q_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n                input_i_tdata=input_i_tdata,\n                input_q_tdata=input_q_tdata,\n                input_tvalid=input_tvalid,\n                input_tready=input_tready,\n                output_i_tdata=output_i_tdata,\n                output_i_tvalid=output_i_tvalid,\n                output_i_tready=output_i_tready,\n                output_q_tdata=output_q_tdata,\n                output_q_tvalid=output_q_tvalid,\n                output_q_tready=output_q_tready)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 16\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_i_tdata = Signal(intbv(0)[WIDTH:])\n    input_q_tdata = Signal(intbv(0)[WIDTH:])\n    input_tvalid = Signal(bool(0))\n    output_i_tready = Signal(bool(0))\n    output_q_tready = Signal(bool(0))\n\n    # Outputs\n    input_tready = Signal(bool(0))\n    output_i_tdata = Signal(intbv(0)[WIDTH:])\n    output_i_tvalid = Signal(bool(0))\n    output_q_tdata = Signal(intbv(0)[WIDTH:])\n    output_q_tvalid = Signal(bool(0))\n\n    # Sources and sinks\n    input_source_queue = Queue()\n    input_source_pause = Signal(bool(0))\n    output_i_sink_queue = Queue()\n    output_i_sink_pause = Signal(bool(0))\n    output_q_sink_queue = Queue()\n    output_q_sink_pause = Signal(bool(0))\n\n    input_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=(input_i_tdata, input_q_tdata),\n                                           tvalid=input_tvalid,\n                                           tready=input_tready,\n                                           fifo=input_source_queue,\n                                           pause=input_source_pause,\n                                           name='input_source')\n\n    output_i_sink = axis_ep.AXIStreamSink(clk,\n                                          rst,\n                                          tdata=output_i_tdata,\n                                          tvalid=output_i_tvalid,\n                                          tready=output_i_tready,\n                                          fifo=output_i_sink_queue,\n                                          pause=output_i_sink_pause,\n                                          name='output_i_sink')\n\n    output_q_sink = axis_ep.AXIStreamSink(clk,\n                                          rst,\n                                          tdata=output_q_tdata,\n                                          tvalid=output_q_tvalid,\n                                          tready=output_q_tready,\n                                          fifo=output_q_sink_queue,\n                                          pause=output_q_sink_pause,\n                                          name='output_q_sink')\n\n    # DUT\n    dut = dut_iq_split(clk,\n                       rst,\n                       current_test,\n                       input_i_tdata,\n                       input_q_tdata,\n                       input_tvalid,\n                       input_tready,\n                       output_i_tdata,\n                       output_i_tvalid,\n                       output_i_tready,\n                       output_q_tdata,\n                       output_q_tvalid,\n                       output_q_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test sequence\")\n        current_test.next = 1\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame = axis_ep.AXIStreamFrame(zip(i_data, q_data))\n\n        input_source_queue.put(test_frame)\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid or output_i_tvalid or output_q_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        i_lst = []\n        q_lst = []\n\n        while not output_i_sink_queue.empty():\n            i_lst += output_i_sink_queue.get(False).data\n        while not output_q_sink_queue.empty():\n            q_lst += output_q_sink_queue.get(False).data\n\n        assert i_data == i_lst\n        assert q_data == q_lst\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: pause source\")\n        current_test.next = 2\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame = axis_ep.AXIStreamFrame(zip(i_data, q_data))\n\n        input_source_queue.put(test_frame)\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid or output_i_tvalid or output_q_tvalid:\n            input_source_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            input_source_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        i_lst = []\n        q_lst = []\n\n        while not output_i_sink_queue.empty():\n            i_lst += output_i_sink_queue.get(False).data\n        while not output_q_sink_queue.empty():\n            q_lst += output_q_sink_queue.get(False).data\n\n        assert i_data == i_lst\n        assert q_data == q_lst\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 3: pause sink\")\n        current_test.next = 3\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame = axis_ep.AXIStreamFrame(zip(i_data, q_data))\n\n        input_source_queue.put(test_frame)\n        yield clk.posedge\n        yield clk.posedge\n\n        while input_tvalid or output_i_tvalid or output_q_tvalid:\n            output_i_sink_pause.next = True\n            yield clk.posedge\n            yield clk.posedge\n            yield clk.posedge\n            output_i_sink_pause.next = False\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        i_lst = []\n        q_lst = []\n\n        while not output_i_sink_queue.empty():\n            i_lst += output_i_sink_queue.get(False).data\n        while not output_q_sink_queue.empty():\n            q_lst += output_q_sink_queue.get(False).data\n\n        assert i_data == i_lst\n        assert q_data == q_lst\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 4: pause both sinks\")\n        current_test.next = 4\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame = axis_ep.AXIStreamFrame(zip(i_data, q_data))\n\n        input_source_queue.put(test_frame)\n        yield clk.posedge\n        yield clk.posedge\n\n        output_q_sink_pause.next = True\n\n        while input_tvalid or output_i_tvalid or output_q_tvalid:\n            output_i_sink_pause.next = True\n            yield clk.posedge\n            output_q_sink_pause.next = False\n            yield clk.posedge\n            output_q_sink_pause.next = True\n            yield clk.posedge\n            output_i_sink_pause.next = False\n            yield clk.posedge\n\n        output_q_sink_pause.next = False\n\n        yield clk.posedge\n        yield clk.posedge\n\n        i_lst = []\n        q_lst = []\n\n        while not output_i_sink_queue.empty():\n            i_lst += output_i_sink_queue.get(False).data\n        while not output_q_sink_queue.empty():\n            q_lst += output_q_sink_queue.get(False).data\n\n        assert i_data == i_lst\n        assert q_data == q_lst\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 5: pause source and sink\")\n        current_test.next = 5\n\n        i_data = list(range(20))\n        q_data = list(range(20,40))\n\n        test_frame = axis_ep.AXIStreamFrame(zip(i_data, q_data))\n\n        input_source_queue.put(test_frame)\n        yield clk.posedge\n        yield clk.posedge\n\n        output_q_sink_pause.next = True\n\n        while input_tvalid or output_i_tvalid or output_q_tvalid:\n            input_source_pause.next = True\n            yield clk.posedge\n            output_q_sink_pause.next = False\n            yield clk.posedge\n            output_q_sink_pause.next = True\n            yield clk.posedge\n            input_source_pause.next = False\n            yield clk.posedge\n\n        output_q_sink_pause.next = False\n\n        yield clk.posedge\n        yield clk.posedge\n\n        i_lst = []\n        q_lst = []\n\n        while not output_i_sink_queue.empty():\n            i_lst += output_i_sink_queue.get(False).data\n        while not output_q_sink_queue.empty():\n            q_lst += output_q_sink_queue.get(False).data\n\n        assert i_data == i_lst\n        assert q_data == q_lst\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_iq_split.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for iq_split\n */\nmodule test_iq_split;\n\n// Parameters\nparameter WIDTH = 16;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_i_tdata = 0;\nreg [WIDTH-1:0] input_q_tdata = 0;\nreg input_tvalid = 0;\nreg output_i_tready = 0;\nreg output_q_tready = 0;\n\n// Outputs\nwire input_tready;\nwire [WIDTH-1:0] output_i_tdata;\nwire output_i_tvalid;\nwire [WIDTH-1:0] output_q_tdata;\nwire output_q_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_i_tdata,\n                input_q_tdata,\n                input_tvalid,\n                output_i_tready,\n                output_q_tready);\n    $to_myhdl(input_tready,\n              output_i_tdata,\n              output_i_tvalid,\n              output_q_tdata,\n              output_q_tvalid);\n\n    // dump file\n    $dumpfile(\"test_iq_split.lxt\");\n    $dumpvars(0, test_iq_split);\nend\n\niq_split #(\n    .WIDTH(WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_i_tdata(input_i_tdata),\n    .input_q_tdata(input_q_tdata),\n    .input_tvalid(input_tvalid),\n    .input_tready(input_tready),\n    .output_i_tdata(output_i_tdata),\n    .output_i_tvalid(output_i_tvalid),\n    .output_i_tready(output_i_tready),\n    .output_q_tdata(output_q_tdata),\n    .output_q_tvalid(output_q_tvalid),\n    .output_q_tready(output_q_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_phase_accumulator.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport axis_ep\n\nmodule = 'phase_accumulator'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_phase_accumulator(clk,\n                          rst,\n                          current_test,\n\n                          input_phase_tdata,\n                          input_phase_tvalid,\n                          input_phase_tready,\n\n                          input_phase_step_tdata,\n                          input_phase_step_tvalid,\n                          input_phase_step_tready,\n\n                          output_phase_tdata,\n                          output_phase_tvalid,\n                          output_phase_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n\n                input_phase_tdata=input_phase_tdata,\n                input_phase_tvalid=input_phase_tvalid,\n                input_phase_tready=input_phase_tready,\n\n                input_phase_step_tdata=input_phase_step_tdata,\n                input_phase_step_tvalid=input_phase_step_tvalid,\n                input_phase_step_tready=input_phase_step_tready,\n\n                output_phase_tdata=output_phase_tdata,\n                output_phase_tvalid=output_phase_tvalid,\n                output_phase_tready=output_phase_tready)\n\ndef bench():\n\n    # Parameters\n    WIDTH = 32\n    INITIAL_PHASE = 0\n    INITIAL_PHASE_STEP = 0\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_phase_tdata = Signal(intbv(0)[WIDTH:])\n    input_phase_tvalid = Signal(bool(0))\n    input_phase_step_tdata = Signal(intbv(0)[WIDTH:])\n    input_phase_step_tvalid = Signal(bool(0))\n    output_phase_tready = Signal(bool(0))\n\n    # Outputs\n    input_phase_tready = Signal(bool(1))\n    input_phase_step_tready = Signal(bool(1))\n    output_phase_tdata = Signal(intbv(0)[WIDTH:])\n    output_phase_tvalid = Signal(bool(1))\n\n    # sources and sinks\n    phase_source_queue = Queue()\n    phase_source_pause = Signal(bool(0))\n    phase_step_source_queue = Queue()\n    phase_step_source_pause = Signal(bool(0))\n    phase_sink_queue = Queue()\n    phase_sink_pause = Signal(bool(0))\n\n    phase_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_phase_tdata,\n                                           tvalid=input_phase_tvalid,\n                                           tready=input_phase_tready,\n                                           fifo=phase_source_queue,\n                                           pause=phase_source_pause,\n                                           name='phase_source')\n\n    phase_step_source = axis_ep.AXIStreamSource(clk,\n                                                rst,\n                                                tdata=input_phase_step_tdata,\n                                                tvalid=input_phase_step_tvalid,\n                                                tready=input_phase_step_tready,\n                                                fifo=phase_step_source_queue,\n                                                pause=phase_step_source_pause,\n                                                name='phase_step_source')\n\n    phase_sink = axis_ep.AXIStreamSink(clk,\n                                       rst,\n                                       tdata=output_phase_tdata,\n                                       tvalid=output_phase_tvalid,\n                                       tready=output_phase_tready,\n                                       fifo=phase_sink_queue,\n                                       pause=phase_sink_pause,\n                                       name='phase_sink')\n\n    # DUT\n    dut = dut_phase_accumulator(clk,\n                                rst,\n                                current_test,\n\n                                input_phase_tdata,\n                                input_phase_tvalid,\n                                input_phase_tready,\n\n                                input_phase_step_tdata,\n                                input_phase_step_tvalid,\n                                input_phase_step_tready,\n\n                                output_phase_tdata,\n                                output_phase_tvalid,\n                                output_phase_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: initial phase\")\n        current_test.next = 1\n\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = [123456]\n\n        phase_source_queue.put(test_frame)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not phase_sink_queue.empty():\n            phase_sink_queue.get(False)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        rx_frame = phase_sink_queue.get(False)\n        assert rx_frame.data[0] == 123456\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: phase step\")\n        current_test.next = 2\n\n        test_frame1 = axis_ep.AXIStreamFrame()\n        test_frame1.data = [10000]\n        test_frame2 = axis_ep.AXIStreamFrame()\n        test_frame2.data = [5000]\n\n        phase_source_queue.put(test_frame1)\n        phase_step_source_queue.put(test_frame2)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not phase_sink_queue.empty():\n            phase_sink_queue.get(False)\n\n        yield clk.posedge\n        yield clk.posedge\n        yield clk.posedge\n\n        rx_frame = phase_sink_queue.get(False)\n        assert rx_frame.data[0] == 10000\n        rx_frame = phase_sink_queue.get(False)\n        assert rx_frame.data[0] == 15000\n        rx_frame = phase_sink_queue.get(False)\n        assert rx_frame.data[0] == 20000\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_phase_accumulator.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for phase_accumulator\n */\nmodule test_phase_accumulator;\n\n// Parameters\nparameter WIDTH = 32;\nparameter INITIAL_PHASE = 0;\nparameter INITIAL_PHASE_STEP = 0;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [WIDTH-1:0] input_phase_tdata = 0;\nreg input_phase_tvalid = 0;\nreg [WIDTH-1:0] input_phase_step_tdata = 0;\nreg input_phase_step_tvalid = 0;\nreg output_phase_tready = 0;\n\n// Outputs\nwire input_phase_tready;\nwire input_phase_step_tready;\nwire [WIDTH-1:0] output_phase_tdata;\nwire output_phase_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_phase_tdata,\n                input_phase_tvalid,\n                input_phase_step_tdata,\n                input_phase_step_tvalid,\n                output_phase_tready);\n    $to_myhdl(input_phase_tready,\n              input_phase_step_tready,\n              output_phase_tdata,\n              output_phase_tvalid);\n\n    // dump file\n    $dumpfile(\"test_phase_accumulator.lxt\");\n    $dumpvars(0, test_phase_accumulator);\nend\n\nphase_accumulator #(\n    .WIDTH(WIDTH),\n    .INITIAL_PHASE(INITIAL_PHASE),\n    .INITIAL_PHASE_STEP(INITIAL_PHASE_STEP)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_phase_tdata(input_phase_tdata),\n    .input_phase_tvalid(input_phase_tvalid),\n    .input_phase_tready(input_phase_tready),\n    .input_phase_step_tdata(input_phase_step_tdata),\n    .input_phase_step_tvalid(input_phase_step_tvalid),\n    .input_phase_step_tready(input_phase_step_tready),\n    .output_phase_tdata(output_phase_tdata),\n    .output_phase_tvalid(output_phase_tvalid),\n    .output_phase_tready(output_phase_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_sine_dds.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport numpy as np\n\nimport axis_ep\n\nmodule = 'sine_dds'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/phase_accumulator.v\")\nsrcs.append(\"../rtl/sine_dds_lut.v\")\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_sine_dds(clk,\n                 rst,\n                 current_test,\n\n                 input_phase_tdata,\n                 input_phase_tvalid,\n                 input_phase_tready,\n\n                 input_phase_step_tdata,\n                 input_phase_step_tvalid,\n                 input_phase_step_tready,\n\n                 output_sample_i_tdata,\n                 output_sample_q_tdata,\n                 output_sample_tvalid,\n                 output_sample_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n\n                input_phase_tdata=input_phase_tdata,\n                input_phase_tvalid=input_phase_tvalid,\n                input_phase_tready=input_phase_tready,\n\n                input_phase_step_tdata=input_phase_step_tdata,\n                input_phase_step_tvalid=input_phase_step_tvalid,\n                input_phase_step_tready=input_phase_step_tready,\n\n                output_sample_i_tdata=output_sample_i_tdata,\n                output_sample_q_tdata=output_sample_q_tdata,\n                output_sample_tvalid=output_sample_tvalid,\n                output_sample_tready=output_sample_tready)\n\ndef bench():\n\n    # Parameters\n    PHASE_WIDTH = 32\n    OUTPUT_WIDTH = 16\n    INITIAL_PHASE = 0\n    INITIAL_PHASE_STEP = 0\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_phase_tdata = Signal(intbv(0)[PHASE_WIDTH:])\n    input_phase_tvalid = Signal(bool(0))\n    input_phase_step_tdata = Signal(intbv(0)[PHASE_WIDTH:])\n    input_phase_step_tvalid = Signal(bool(0))\n    output_sample_tready = Signal(bool(0))\n\n    # Outputs\n    input_phase_tready = Signal(bool(0))\n    input_phase_step_tready = Signal(bool(1))\n    output_sample_i_tdata = Signal(intbv(0)[OUTPUT_WIDTH:])\n    output_sample_q_tdata = Signal(intbv(0)[OUTPUT_WIDTH:])\n    output_sample_tvalid = Signal(bool(1))\n\n    # sources and sinks\n    phase_source_queue = Queue()\n    phase_source_pause = Signal(bool(0))\n    phase_step_source_queue = Queue()\n    phase_step_source_pause = Signal(bool(0))\n    sample_sink_queue = Queue()\n    sample_sink_pause = Signal(bool(0))\n\n    phase_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_phase_tdata,\n                                           tvalid=input_phase_tvalid,\n                                           tready=input_phase_tready,\n                                           fifo=phase_source_queue,\n                                           pause=phase_source_pause,\n                                           name='phase_source')\n\n    phase_step_source = axis_ep.AXIStreamSource(clk,\n                                                rst,\n                                                tdata=input_phase_step_tdata,\n                                                tvalid=input_phase_step_tvalid,\n                                                tready=input_phase_step_tready,\n                                                fifo=phase_step_source_queue,\n                                                pause=phase_step_source_pause,\n                                                name='phase_step_source')\n\n    sample_sink = axis_ep.AXIStreamSink(clk,\n                                        rst,\n                                        tdata=(output_sample_i_tdata, output_sample_q_tdata),\n                                        tvalid=output_sample_tvalid,\n                                        tready=output_sample_tready,\n                                        fifo=sample_sink_queue,\n                                        pause=sample_sink_pause,\n                                        name='sample_sink')\n\n    # DUT\n    dut = dut_sine_dds(clk,\n                       rst,\n                       current_test,\n\n                       input_phase_tdata,\n                       input_phase_tvalid,\n                       input_phase_tready,\n\n                       input_phase_step_tdata,\n                       input_phase_step_tvalid,\n                       input_phase_step_tready,\n\n                       output_sample_i_tdata,\n                       output_sample_q_tdata,\n                       output_sample_tvalid,\n                       output_sample_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: high frequency\")\n        current_test.next = 1\n\n        fcw = int(2**PHASE_WIDTH / 100)\n        offset = 0\n\n        test_frame1 = axis_ep.AXIStreamFrame()\n        test_frame1.data = [offset]\n        test_frame2 = axis_ep.AXIStreamFrame()\n        test_frame2.data = [fcw]\n\n        phase_source_queue.put(test_frame1)\n        phase_step_source_queue.put(test_frame2)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not sample_sink_queue.empty():\n            sample_sink_queue.get(False)\n\n        yield delay(1000)\n\n        for j in range(6):\n            sample_sink_queue.get(False)\n\n        for j in range(100):\n            rx_frame = sample_sink_queue.get(False)\n            INPUT_WIDTH = OUTPUT_WIDTH+2\n            x = int((fcw*j + offset) / 2**(PHASE_WIDTH-INPUT_WIDTH))\n            c, s = rx_frame.data[0]\n\n            # sign bit\n            if c >= 2**(OUTPUT_WIDTH-1):\n                c -= 2**OUTPUT_WIDTH\n            if s >= 2**(OUTPUT_WIDTH-1):\n                s -= 2**OUTPUT_WIDTH\n\n            # reference sine and cosine\n            rc = int(np.cos(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n            rs = int(np.sin(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n\n            # assert error of two counts or less\n            assert abs(c-rc) <= 2\n            assert abs(s-rs) <= 2\n\n        yield clk.posedge\n        print(\"test 2: low frequency\")\n        current_test.next = 2\n\n        fcw = int(2**PHASE_WIDTH / 10000)\n        offset = 0\n\n        test_frame1 = axis_ep.AXIStreamFrame()\n        test_frame1.data = [offset]\n        test_frame2 = axis_ep.AXIStreamFrame()\n        test_frame2.data = [fcw]\n\n        phase_source_queue.put(test_frame1)\n        phase_step_source_queue.put(test_frame2)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not sample_sink_queue.empty():\n            sample_sink_queue.get(False)\n\n        yield delay(1000)\n\n        for j in range(6):\n            sample_sink_queue.get(False)\n\n        for j in range(100):\n            rx_frame = sample_sink_queue.get(False)\n            INPUT_WIDTH = OUTPUT_WIDTH+2\n            x = int((fcw*j + offset) / 2**(PHASE_WIDTH-INPUT_WIDTH))\n            c, s = rx_frame.data[0]\n\n            # sign bit\n            if c >= 2**(OUTPUT_WIDTH-1):\n                c -= 2**OUTPUT_WIDTH\n            if s >= 2**(OUTPUT_WIDTH-1):\n                s -= 2**OUTPUT_WIDTH\n\n            # reference sine and cosine\n            rc = int(np.cos(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n            rs = int(np.sin(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n\n            # assert error of two counts or less\n            assert abs(c-rc) <= 2\n            assert abs(s-rs) <= 2\n\n        yield clk.posedge\n        print(\"test 3: phase offset\")\n        current_test.next = 3\n\n        fcw = int(2**PHASE_WIDTH / 10000)\n        offset = 2**(PHASE_WIDTH-2)\n\n        test_frame1 = axis_ep.AXIStreamFrame()\n        test_frame1.data = [offset]\n        test_frame2 = axis_ep.AXIStreamFrame()\n        test_frame2.data = [fcw]\n\n        phase_source_queue.put(test_frame1)\n        phase_step_source_queue.put(test_frame2)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not sample_sink_queue.empty():\n            sample_sink_queue.get(False)\n\n        yield delay(1000)\n\n        for j in range(6):\n            sample_sink_queue.get(False)\n\n        for j in range(100):\n            rx_frame = sample_sink_queue.get(False)\n            INPUT_WIDTH = OUTPUT_WIDTH+2\n            x = int((fcw*j + offset) / 2**(PHASE_WIDTH-INPUT_WIDTH))\n            c, s = rx_frame.data[0]\n\n            # sign bit\n            if c >= 2**(OUTPUT_WIDTH-1):\n                c -= 2**OUTPUT_WIDTH\n            if s >= 2**(OUTPUT_WIDTH-1):\n                s -= 2**OUTPUT_WIDTH\n\n            # reference sine and cosine\n            rc = int(np.cos(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n            rs = int(np.sin(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n\n            # assert error of two counts or less\n            assert abs(c-rc) <= 2\n            assert abs(s-rs) <= 2\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_sine_dds.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for sine_dds\n */\nmodule test_sine_dds;\n\n// Parameters\nparameter PHASE_WIDTH = 32;\nparameter OUTPUT_WIDTH = 16;\nparameter INITIAL_PHASE = 0;\nparameter INITIAL_PHASE_STEP = 0;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [PHASE_WIDTH-1:0] input_phase_tdata = 0;\nreg input_phase_tvalid = 0;\nreg [PHASE_WIDTH-1:0] input_phase_step_tdata = 0;\nreg input_phase_step_tvalid = 0;\nreg output_sample_tready = 0;\n\n// Outputs\nwire input_phase_tready;\nwire input_phase_step_tready;\nwire [OUTPUT_WIDTH-1:0] output_sample_i_tdata;\nwire [OUTPUT_WIDTH-1:0] output_sample_q_tdata;\nwire output_sample_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_phase_tdata,\n                input_phase_tvalid,\n                input_phase_step_tdata,\n                input_phase_step_tvalid,\n                output_sample_tready);\n    $to_myhdl(input_phase_tready,\n              input_phase_step_tready,\n              output_sample_i_tdata,\n              output_sample_q_tdata,\n              output_sample_tvalid);\n\n    // dump file\n    $dumpfile(\"test_sine_dds.lxt\");\n    $dumpvars(0, test_sine_dds);\nend\n\nsine_dds #(\n    .PHASE_WIDTH(PHASE_WIDTH),\n    .OUTPUT_WIDTH(OUTPUT_WIDTH),\n    .INITIAL_PHASE(INITIAL_PHASE),\n    .INITIAL_PHASE_STEP(INITIAL_PHASE_STEP)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_phase_tdata(input_phase_tdata),\n    .input_phase_tvalid(input_phase_tvalid),\n    .input_phase_tready(input_phase_tready),\n    .input_phase_step_tdata(input_phase_step_tdata),\n    .input_phase_step_tvalid(input_phase_step_tvalid),\n    .input_phase_step_tready(input_phase_step_tready),\n    .output_sample_i_tdata(output_sample_i_tdata),\n    .output_sample_q_tdata(output_sample_q_tdata),\n    .output_sample_tvalid(output_sample_tvalid),\n    .output_sample_tready(output_sample_tready)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_sine_dds_lut.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\ntry:\n    from queue import Queue\nexcept ImportError:\n    from Queue import Queue\n\nimport numpy as np\n\nimport axis_ep\n\nmodule = 'sine_dds_lut'\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"test_%s.v\" % module)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o test_%s.vvp %s\" % (module, src)\n\ndef dut_sine_dds_lut(clk,\n                     rst,\n                     current_test,\n\n                     input_phase_tdata,\n                     input_phase_tvalid,\n                     input_phase_tready,\n\n                     output_sample_i_tdata,\n                     output_sample_q_tdata,\n                     output_sample_tvalid,\n                     output_sample_tready):\n\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    return Cosimulation(\"vvp -m myhdl test_%s.vvp -lxt2\" % module,\n                clk=clk,\n                rst=rst,\n                current_test=current_test,\n\n                input_phase_tdata=input_phase_tdata,\n                input_phase_tvalid=input_phase_tvalid,\n                input_phase_tready=input_phase_tready,\n\n                output_sample_i_tdata=output_sample_i_tdata,\n                output_sample_q_tdata=output_sample_q_tdata,\n                output_sample_tvalid=output_sample_tvalid,\n                output_sample_tready=output_sample_tready)\n\ndef bench():\n\n    # Parameters\n    OUTPUT_WIDTH = 16\n    INPUT_WIDTH = OUTPUT_WIDTH+2\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    input_phase_tdata = Signal(intbv(0)[INPUT_WIDTH:])\n    input_phase_tvalid = Signal(bool(0))\n    output_sample_tready = Signal(bool(0))\n\n    # Outputs\n    input_phase_tready = Signal(bool(0))\n    output_sample_i_tdata = Signal(intbv(0)[OUTPUT_WIDTH:])\n    output_sample_q_tdata = Signal(intbv(0)[OUTPUT_WIDTH:])\n    output_sample_tvalid = Signal(bool(0))\n\n    # sources and sinks\n    phase_source_queue = Queue()\n    phase_source_pause = Signal(bool(0))\n    sample_sink_queue = Queue()\n    sample_sink_pause = Signal(bool(0))\n\n    phase_source = axis_ep.AXIStreamSource(clk,\n                                           rst,\n                                           tdata=input_phase_tdata,\n                                           tvalid=input_phase_tvalid,\n                                           tready=input_phase_tready,\n                                           fifo=phase_source_queue,\n                                           pause=phase_source_pause,\n                                           name='phase_source')\n\n    sample_sink = axis_ep.AXIStreamSink(clk,\n                                        rst,\n                                        tdata=(output_sample_i_tdata, output_sample_q_tdata),\n                                        tvalid=output_sample_tvalid,\n                                        tready=output_sample_tready,\n                                        fifo=sample_sink_queue,\n                                        pause=sample_sink_pause,\n                                        name='sample_sink')\n\n    # DUT\n    dut = dut_sine_dds_lut(clk,\n                           rst,\n                           current_test,\n\n                           input_phase_tdata,\n                           input_phase_tvalid,\n                           input_phase_tready,\n\n                           output_sample_i_tdata,\n                           output_sample_q_tdata,\n                           output_sample_tvalid,\n                           output_sample_tready)\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: coarse check\")\n        current_test.next = 1\n\n        # check single cycle\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(range(0,2**18,2**10)) + [0]*6\n\n        phase_source_queue.put(test_frame)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not phase_source_queue.empty() or input_phase_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        # pipeline delay\n        for j in range(6):\n            sample_sink_queue.get(False)\n\n        for j in range(len(test_frame.data)-6):\n            rx_frame = sample_sink_queue.get(False)\n            x = test_frame.data[j]\n            c, s = rx_frame.data[0]\n\n            # sign bit\n            if c >= 2**(OUTPUT_WIDTH-1):\n                c -= 2**OUTPUT_WIDTH\n            if s >= 2**(OUTPUT_WIDTH-1):\n                s -= 2**OUTPUT_WIDTH\n            \n            # reference sine and cosine\n            rc = int(np.cos(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n            rs = int(np.sin(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n\n            # assert error of two counts or less\n            assert abs(c-rc) <= 2\n            assert abs(s-rs) <= 2\n\n        yield clk.posedge\n        print(\"test 2: fine check\")\n        current_test.next = 2\n\n        # check two zero crossing regions\n        test_frame = axis_ep.AXIStreamFrame()\n        test_frame.data = list(range(2**18-2**8,2**18-1)) + list(range(0,2**8)) + list(range(2**16-2**8, 2**16+2**8)) + [0]*6\n\n        phase_source_queue.put(test_frame)\n\n        yield clk.posedge\n        yield clk.posedge\n\n        while not phase_source_queue.empty() or input_phase_tvalid:\n            yield clk.posedge\n\n        yield clk.posedge\n        yield clk.posedge\n\n        # pipeline delay\n        for j in range(6):\n            sample_sink_queue.get(False)\n\n        for j in range(len(test_frame.data)-6):\n            rx_frame = sample_sink_queue.get(False)\n            x = test_frame.data[j]\n            c, s = rx_frame.data[0]\n\n            # sign bit\n            if c >= 2**(OUTPUT_WIDTH-1):\n                c -= 2**OUTPUT_WIDTH\n            if s >= 2**(OUTPUT_WIDTH-1):\n                s -= 2**OUTPUT_WIDTH\n            \n            # reference sine and cosine\n            rc = int(np.cos(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n            rs = int(np.sin(2*np.pi*(x-2**((INPUT_WIDTH-2)/2-1))/2**INPUT_WIDTH)*(2**(OUTPUT_WIDTH-1)-1))\n\n            # assert error of two counts or less\n            assert abs(c-rc) <= 2\n            assert abs(s-rs) <= 2\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_sine_dds_lut.v",
    "content": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for sine_dds_lut\n */\nmodule test_sine_dds_lut;\n\n// Parameters\nparameter OUTPUT_WIDTH = 16;\nparameter INPUT_WIDTH = OUTPUT_WIDTH+2;\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [INPUT_WIDTH-1:0] input_phase_tdata = 0;\nreg input_phase_tvalid = 0;\nreg output_sample_tready = 0;\n\n// Outputs\nwire input_phase_tready;\nwire [OUTPUT_WIDTH-1:0] output_sample_i_tdata;\nwire [OUTPUT_WIDTH-1:0] output_sample_q_tdata;\nwire output_sample_tvalid;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(clk,\n                rst,\n                current_test,\n                input_phase_tdata,\n                input_phase_tvalid,\n                output_sample_tready);\n    $to_myhdl(input_phase_tready,\n              output_sample_i_tdata,\n              output_sample_q_tdata,\n              output_sample_tvalid);\n\n    // dump file\n    $dumpfile(\"test_sine_dds_lut.lxt\");\n    $dumpvars(0, test_sine_dds_lut);\nend\n\nsine_dds_lut #(\n    .OUTPUT_WIDTH(OUTPUT_WIDTH),\n    .INPUT_WIDTH(INPUT_WIDTH)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .input_phase_tdata(input_phase_tdata),\n    .input_phase_tvalid(input_phase_tvalid),\n    .input_phase_tready(input_phase_tready),\n    .output_sample_i_tdata(output_sample_i_tdata),\n    .output_sample_q_tdata(output_sample_q_tdata),\n    .output_sample_tvalid(output_sample_tvalid),\n    .output_sample_tready(output_sample_tready)\n);\n\nendmodule\n"
  }
]