Files
b210-k7-fpga/lib/rfnoc/sine_tone.v
T
Wade Fife 2eb71626fb fpga: rfnoc: Add Signal Generator RFNoC block
Original-commit: 1e94f85b8bafc3f9acab7ef35d2675fa7e61f6f4
2020-07-30 12:51:41 -05:00

160 lines
4.8 KiB
Verilog

//
// 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