1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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
|