diff options
author | Wade Fife <wade.fife@ettus.com> | 2020-06-19 15:40:12 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-07-30 12:51:41 -0500 |
commit | 1e94f85b8bafc3f9acab7ef35d2675fa7e61f6f4 (patch) | |
tree | 12ba30a59c8057e355971797d5cc7bf6910f520b /fpga/usrp3/lib/rfnoc/sine_tone.v | |
parent | b0b3849a18e1f2d3cb255a507b01ac5e7a9416a0 (diff) | |
download | uhd-1e94f85b8bafc3f9acab7ef35d2675fa7e61f6f4.tar.gz uhd-1e94f85b8bafc3f9acab7ef35d2675fa7e61f6f4.tar.bz2 uhd-1e94f85b8bafc3f9acab7ef35d2675fa7e61f6f4.zip |
fpga: rfnoc: Add Signal Generator RFNoC block
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/sine_tone.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/sine_tone.v | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/sine_tone.v b/fpga/usrp3/lib/rfnoc/sine_tone.v new file mode 100644 index 000000000..a687472eb --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/sine_tone.v @@ -0,0 +1,159 @@ +// +// Copyright 2020 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: sine_tone +// +// Description: +// +// Sine tone generator. This block uses the Xilinx CORDIC IP configured to +// perform the rotate function in units of scaled radians. See the CORDIC IP +// Product Guide (PG105) for details. +// +// The SR_PHASE_INC register controls the phase increment, in scaled +// radians, for the sine waveform generator. It is a 16-bit signed +// fixed-point phase value with 3 integer bits and 13 fractional bits. This +// is the amount by which REG_CARTESIAN is rotated each clock cycle. In +// other words, it controls the rate of rotation, or the frequency, of the +// sine wave. In scaled radians, the phase value range -1 to +1 corresponds +// to -Pi to Pi in radians. +// +// The SR_CARTESIAN register sets the sets the (X,Y) Cartesian coordinate +// that will be rotated to generate the sine output. Both X and Y are 16-bit +// signed fixed-point values with 2 integer bits and 14 fractional bits. Y +// is in the upper 16-bits and X is in the lower 16-bits. +// +// In addition to rotation, the SR_CARTESIAN input vector is also scaled by +// a "CORDIC scale factor" that equals about 1.1644 (that is, the product of +// sqrt(1 + 2^(-2i)) for i = 1 to n, where n = 14, the number of fractional +// bits). +// +// Parameters: +// +// SR_PHASE_INC_ADDR : The address to use for SR_PHASE_INC. +// SR_CARTESIAN_ADDR : The address to use for SR_CARTESIAN. +// + + +module sine_tone #( + parameter WIDTH = 32, + parameter SR_PHASE_INC_ADDR = 129, + parameter SR_CARTESIAN_ADDR = 130 +) ( + input clk, + input reset, + input clear, + input enable, + + // Settings bus + input set_stb, + input [WIDTH-1:0] set_data, + input [ 7:0] set_addr, + + // Output sinusoid + output [WIDTH-1:0] o_tdata, + output o_tlast, + output o_tvalid, + input o_tready +); + + wire [15:0] phase_in_tdata; + wire phase_in_tlast; + wire phase_in_tvalid; + wire phase_in_tready; + + wire [15:0] phase_out_tdata; + wire phase_out_tlast; + wire phase_out_tvalid; + wire phase_out_tready; + + wire [WIDTH-1:0] cartesian_tdata; + wire cartesian_tlast; + wire cartesian_tvalid; + wire cartesian_tready; + + wire [WIDTH-1:0] sine_out_tdata; + wire sine_out_tlast; + wire sine_out_tvalid; + wire sine_out_tready; + + // AXI settings bus for phase values + axi_setting_reg #( + .ADDR (SR_PHASE_INC_ADDR), + .AWIDTH (8), + .WIDTH (16), + .STROBE_LAST (1), + .REPEATS (1) + ) set_phase_acc ( + .clk (clk), + .reset (reset), + .error_stb (), + .set_stb (set_stb), + .set_addr (set_addr), + .set_data (set_data), + .o_tdata (phase_in_tdata), + .o_tlast (phase_in_tlast), + .o_tvalid (phase_in_tvalid), + .o_tready (phase_in_tready & enable) + ); + + // AXI settings bus for Cartesian values + axi_setting_reg #( + .ADDR (SR_CARTESIAN_ADDR), + .AWIDTH (8), + .WIDTH (32), + .REPEATS (1) + ) set_axis_cartesian ( + .clk (clk), + .reset (reset), + .error_stb (), + .set_stb (set_stb), + .set_addr (set_addr), + .set_data (set_data), + .o_tdata (cartesian_tdata), + .o_tlast (), + .o_tvalid (cartesian_tvalid), + .o_tready (cartesian_tready & enable) + ); + + assign cartesian_tlast = 1; + + // Phase accumulator + phase_accum phase_acc ( + .clk (clk), + .reset (reset), + .clear (clear), + .i_tdata (phase_in_tdata), + .i_tlast (phase_in_tlast), + .i_tvalid (1'b1), + .i_tready (phase_in_tready), + .o_tdata (phase_out_tdata), + .o_tlast (phase_out_tlast), + .o_tvalid (phase_out_tvalid), + .o_tready (phase_out_tready & enable) + ); + + // CORDIC + cordic_rotator cordic_inst ( + .aclk (clk), + .aresetn (~(reset|clear)), + .s_axis_phase_tdata (phase_out_tdata), + .s_axis_phase_tvalid (phase_out_tvalid & cartesian_tvalid & enable), + .s_axis_phase_tready (phase_out_tready), + .s_axis_cartesian_tdata (cartesian_tdata), + .s_axis_cartesian_tlast (cartesian_tlast), + .s_axis_cartesian_tvalid (phase_out_tvalid & cartesian_tvalid & enable), + .s_axis_cartesian_tready (cartesian_tready), + .m_axis_dout_tdata (sine_out_tdata), + .m_axis_dout_tlast (sine_out_tlast), + .m_axis_dout_tvalid (sine_out_tvalid), + .m_axis_dout_tready (sine_out_tready & enable) + ); + + assign o_tdata = sine_out_tdata; + assign o_tlast = sine_out_tlast; + assign o_tvalid = sine_out_tvalid; + assign sine_out_tready = o_tready; + +endmodule // sine_tone |