-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdds.sv
162 lines (146 loc) · 4.88 KB
/
dds.sv
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
160
161
162
module dds #(
parameter int PHASE_BITS = 24,
parameter int OUTPUT_WIDTH = 18,
parameter int QUANT_BITS = 8,
parameter int PARALLEL_SAMPLES = 4
) (
input wire clk, reset,
output logic pinc_change,
Axis_If.Master_Simple cos_out,
Axis_If.Slave_Simple phase_inc_in,
Axis_If.Slave_Simple cos_scale_in
);
localparam int LUT_ADDR_BITS = PHASE_BITS - QUANT_BITS;
localparam int LUT_DEPTH = 2**LUT_ADDR_BITS;
assign phase_inc_in.ready = 1'b1;
assign cos_scale_in.ready = 1'b1;
// generate LUT
localparam real PI = 3.14159265;
logic signed [OUTPUT_WIDTH-1:0] lut [LUT_DEPTH];
initial begin
for (int i = 0; i < LUT_DEPTH; i = i + 1) begin
lut[i] = signed'(int'($floor($cos(2*PI/(LUT_DEPTH)*i)*(2**(OUTPUT_WIDTH-1) - 0.5) - 0.5)));
end
end
// update phases
logic [PARALLEL_SAMPLES-1:0][PHASE_BITS-1:0] phase_inc;
logic [PHASE_BITS-1:0] cycle_phase;
logic [PARALLEL_SAMPLES-1:0][PHASE_BITS-1:0] sample_phase;
assign phase_inc_in.ready = 1'b1;
always @(posedge clk) begin
if (reset) begin
phase_inc <= '0;
cycle_phase <= '0;
sample_phase <= '0;
pinc_change <= 1'b0;
end else begin
// load new phase_inc
if (phase_inc_in.ready && phase_inc_in.valid) begin
pinc_change <= 1'b1;
for (int i = 0; i < PARALLEL_SAMPLES; i = i + 1) begin
phase_inc[i] <= phase_inc_in.data * (i + 1);
end
end else begin
pinc_change <= 1'b0;
end
if (cos_out.ready) begin
cycle_phase <= cycle_phase + phase_inc[PARALLEL_SAMPLES-1];
sample_phase[0] <= cycle_phase;
for (int i = 1; i < PARALLEL_SAMPLES; i = i + 1) begin
sample_phase[i] <= cycle_phase + phase_inc[i-1];
end
end
end
end
// dither LFSR
logic [PARALLEL_SAMPLES-1:0][15:0] lfsr;
lfsr16_parallel #(.PARALLEL_SAMPLES(PARALLEL_SAMPLES)) lfsr_i (
.clk,
.reset,
.enable(cos_out.ready),
.data_out(lfsr)
);
logic [PARALLEL_SAMPLES-1:0][PHASE_BITS-1:0] phase_dithered;
logic [PARALLEL_SAMPLES-1:0][LUT_ADDR_BITS-1:0] phase_quant;
// delay data_valid to match phase increment + LUT latency
logic [3:0] data_valid;
assign cos_out.valid = data_valid[3];
// this isn't working right --- need to fix sign extension, and a bunch of samples are getting zeroed out
logic signed [OUTPUT_WIDTH-1:0] data_out_full_scale [PARALLEL_SAMPLES];
logic [$clog2(OUTPUT_WIDTH)-1:0] cos_scale;
genvar i;
generate
for (i = 0; i < PARALLEL_SAMPLES; i = i + 1) begin
if (QUANT_BITS > 16) begin
assign phase_dithered[i] = {lfsr[i], {(QUANT_BITS - 16){1'b0}}} + sample_phase[i];
end else begin
assign phase_dithered[i] = lfsr[i][QUANT_BITS-1:0] + sample_phase[i];
end
always @(posedge clk) begin
cos_out.data[OUTPUT_WIDTH*i+:OUTPUT_WIDTH] <= data_out_full_scale[i] >>> cos_scale;
if (reset) begin
data_out_full_scale[i] <= '0;
phase_quant[i] <= '0;
end else begin
if (cos_out.ready) begin
phase_quant[i] <= phase_dithered[i][PHASE_BITS-1:QUANT_BITS];
data_out_full_scale[i] <= lut[phase_quant[i]];
end
end
end
end
endgenerate
always @(posedge clk) begin
if (reset) begin
cos_scale <= '0;
data_valid <= '0;
end else begin
if (cos_scale_in.valid) begin
cos_scale <= cos_scale_in.data;
end
data_valid[0] <= 1'b1;
for (int j = 1; j < 4; j++) begin
data_valid[j] <= data_valid[j-1];
end
end
end
endmodule
module dds_sv_wrapper #(
parameter int PHASE_BITS = 24,
parameter int OUTPUT_WIDTH = 18,
parameter int QUANT_BITS = 8,
parameter int PARALLEL_SAMPLES = 4
) (
input wire clk, reset,
output logic pinc_change,
output logic [PARALLEL_SAMPLES*OUTPUT_WIDTH-1:0] cos_out_data,
output logic cos_out_valid,
input logic cos_out_ready,
input logic [PHASE_BITS-1:0] phase_inc_in_data,
input logic phase_inc_in_valid,
output logic phase_inc_in_ready,
input logic [$clog2(OUTPUT_WIDTH)-1:0] cos_scale_in_data,
input logic cos_scale_in_valid,
output logic cos_scale_in_ready
);
Axis_If #(.DWIDTH(PHASE_BITS)) phase_inc_if();
Axis_If #(.DWIDTH($clog2(OUTPUT_WIDTH))) cos_scale_if();
Axis_If #(.DWIDTH(PARALLEL_SAMPLES*OUTPUT_WIDTH)) cos_out_if();
assign phase_inc_if.data = phase_inc_in_data;
assign phase_inc_if.valid = phase_inc_in_valid;
assign phase_inc_in_ready = phase_inc_if.ready;
assign cos_scale_if.data = cos_scale_in_data;
assign cos_scale_if.valid = cos_scale_in_valid;
assign cos_scale_in_ready = cos_scale_if.ready;
assign cos_out_data = cos_out_if.data;
assign cos_out_valid = cos_out_if.valid;
assign cos_out_if.ready = cos_out_ready;
dds #(.PHASE_BITS(PHASE_BITS), .OUTPUT_WIDTH(OUTPUT_WIDTH), .QUANT_BITS(QUANT_BITS), .PARALLEL_SAMPLES(PARALLEL_SAMPLES)) dds_i (
.clk,
.reset,
.pinc_change,
.cos_out(cos_out_if),
.phase_inc_in(phase_inc_if),
.cos_scale_in(cos_scale_if)
);
endmodule