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