Showing preview only (203K chars total). Download the full file or copy to clipboard to get everything.
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 <alex@alexforencich.com>
================================================
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_pha
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
SYMBOL INDEX (66 symbols across 14 files)
FILE: tb/axis_ep.py
class AXIStreamFrame (line 29) | class AXIStreamFrame(object):
method __init__ (line 30) | def __init__(self, data=b'', keep=None, id=None, dest=None, user=None,...
method build (line 82) | def build(self):
method parse (line 141) | def parse(self, tdata, tkeep, tid, tdest, tuser):
method __eq__ (line 177) | def __eq__(self, other):
method __repr__ (line 235) | def __repr__(self):
method __iter__ (line 245) | def __iter__(self):
class AXIStreamSource (line 249) | class AXIStreamSource(object):
method __init__ (line 250) | def __init__(self):
method send (line 254) | def send(self, frame):
method write (line 257) | def write(self, data):
method count (line 260) | def count(self):
method empty (line 263) | def empty(self):
method create_logic (line 266) | def create_logic(self,
class AXIStreamSink (line 372) | class AXIStreamSink(object):
method __init__ (line 373) | def __init__(self):
method recv (line 378) | def recv(self):
method read (line 383) | def read(self, count=-1):
method count (line 392) | def count(self):
method empty (line 395) | def empty(self):
method create_logic (line 398) | def create_logic(self,
FILE: tb/i2s_ep.py
function I2SControl (line 27) | def I2SControl(clk, rst,
function I2SSource (line 64) | def I2SSource(clk, rst,
function I2SSink (line 125) | def I2SSink(clk, rst,
FILE: tb/test_cic_decimator.py
function dut_cic_decimator (line 50) | def dut_cic_decimator(clk,
function bench (line 75) | def bench():
function cic_decimate (line 449) | def cic_decimate(y, N=2, M=1, R=2):
function contains (line 472) | def contains(small, big):
function test_bench (line 481) | def test_bench():
FILE: tb/test_cic_interpolator.py
function dut_cic_interpolator (line 50) | def dut_cic_interpolator(clk,
function bench (line 75) | def bench():
function cic_interpolate (line 372) | def cic_interpolate(y, N=2, M=1, R=2):
function contains (line 394) | def contains(small, big):
function test_bench (line 403) | def test_bench():
FILE: tb/test_dsp_iq_mult.py
function dut_dsp_iq_mult (line 47) | def dut_dsp_iq_mult(clk,
function bench (line 82) | def bench():
function test_bench (line 211) | def test_bench():
FILE: tb/test_dsp_mult.py
function dut_dsp_mult (line 47) | def dut_dsp_mult(clk,
function bench (line 76) | def bench():
function test_bench (line 199) | def test_bench():
FILE: tb/test_i2s_ctrl.py
function dut_i2s_ctrl (line 42) | def dut_i2s_ctrl(clk,
function bench (line 59) | def bench():
function test_bench (line 148) | def test_bench():
FILE: tb/test_i2s_rx.py
function dut_i2s_rx (line 48) | def dut_i2s_rx(clk,
function bench (line 73) | def bench():
function contains (line 233) | def contains(small, big):
function test_bench (line 242) | def test_bench():
FILE: tb/test_i2s_tx.py
function dut_i2s_tx (line 48) | def dut_i2s_tx(clk,
function bench (line 73) | def bench():
function contains (line 227) | def contains(small, big):
function test_bench (line 236) | def test_bench():
FILE: tb/test_iq_join.py
function dut_iq_join (line 47) | def dut_iq_join(clk,
function bench (line 78) | def bench():
function test_bench (line 354) | def test_bench():
FILE: tb/test_iq_split.py
function dut_iq_split (line 47) | def dut_iq_split(clk,
function bench (line 78) | def bench():
function test_bench (line 364) | def test_bench():
FILE: tb/test_phase_accumulator.py
function dut_phase_accumulator (line 47) | def dut_phase_accumulator(clk,
function bench (line 82) | def bench():
function test_bench (line 233) | def test_bench():
FILE: tb/test_sine_dds.py
function dut_sine_dds (line 51) | def dut_sine_dds(clk,
function bench (line 88) | def bench():
function test_bench (line 326) | def test_bench():
FILE: tb/test_sine_dds_lut.py
function dut_sine_dds_lut (line 49) | def dut_sine_dds_lut(clk,
function bench (line 78) | def bench():
function test_bench (line 244) | def test_bench():
Condensed preview — 43 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (205K chars).
[
{
"path": ".gitignore",
"chars": 33,
"preview": "*~\n*.lxt\n*.pyc\n*.vvp\n*.kate-swp\n\n"
},
{
"path": ".travis.yml",
"chars": 427,
"preview": "language: python\npython:\n - \"3.4\"\nbefore_install:\n - export d=`pwd`\n - export PYTHON_EXE=`which python`\n - sudo apt-"
},
{
"path": "AUTHORS",
"chars": 40,
"preview": "Alex Forencich <alex@alexforencich.com>\n"
},
{
"path": "COPYING",
"chars": 1059,
"preview": "Copyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this "
},
{
"path": "README.md",
"chars": 14,
"preview": "Verilog DSP\n\n\n"
},
{
"path": "rtl/cic_decimator.v",
"chars": 4819,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/cic_interpolator.v",
"chars": 4738,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/dsp_iq_mult.v",
"chars": 4007,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/dsp_mult.v",
"chars": 3025,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/i2s_ctrl.v",
"chars": 2258,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/i2s_rx.v",
"chars": 3292,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/i2s_tx.v",
"chars": 3137,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/iq_join.v",
"chars": 2794,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/iq_split.v",
"chars": 2771,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/phase_accumulator.v",
"chars": 2683,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/sine_dds.v",
"chars": 3277,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/sine_dds_lut.v",
"chars": 4705,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/axis_ep.py",
"chars": 17608,
"preview": "\"\"\"\n\nCopyright (c) 2014-2018 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
},
{
"path": "tb/i2s_ep.py",
"chars": 5156,
"preview": "\"\"\"\n\nCopyright (c) 2014 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "tb/test_cic_decimator.py",
"chars": 11964,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_cic_decimator.v",
"chars": 2340,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_cic_interpolator.py",
"chars": 10467,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_cic_interpolator.v",
"chars": 2371,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_dsp_iq_mult.py",
"chars": 7170,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_dsp_iq_mult.v",
"chars": 2766,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_dsp_mult.py",
"chars": 6426,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_dsp_mult.v",
"chars": 2405,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_i2s_ctrl.py",
"chars": 3891,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_i2s_ctrl.v",
"chars": 1732,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_i2s_rx.py",
"chars": 6486,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_i2s_rx.v",
"chars": 2074,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_i2s_tx.py",
"chars": 6293,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_i2s_tx.v",
"chars": 2063,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_iq_join.py",
"chars": 10789,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_iq_join.v",
"chars": 2504,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_iq_split.py",
"chars": 10979,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_iq_split.v",
"chars": 2517,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_phase_accumulator.py",
"chars": 7676,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_phase_accumulator.v",
"chars": 2817,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_sine_dds.py",
"chars": 10792,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_sine_dds.v",
"chars": 3026,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_sine_dds_lut.py",
"chars": 7898,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_sine_dds_lut.v",
"chars": 2519,
"preview": "/*\n\nCopyright (c) 2015 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
}
]
About this extraction
This page contains the full source code of the alexforencich/verilog-dsp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 43 files (191.2 KB), approximately 46.8k tokens, and a symbol index with 66 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.