OpenCores
URL https://opencores.org/ocsvn/wbpwmaudio/wbpwmaudio/trunk

Subversion Repositories wbpwmaudio

[/] [wbpwmaudio/] [trunk/] [demo-rtl/] [toplevel.v] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    toplevel.v
4
//
5
// Project:     A Wishbone Controlled PWM (audio) controller
6
//
7
// Purpose:     This is the top level file in Verilog demonstration illustrating
8
//              the differences between a traditional PWM generated audio
9
//      output signal, generated by traditionalpwm.v, and a less conventional
10
//      PWM generation method more appropriately termed PDM provided by
11
//      wbpwmaudio.v.
12
//
13
// Creator:     Dan Gisselquist, Ph.D.
14
//              Gisselquist Technology, LLC
15
//
16
////////////////////////////////////////////////////////////////////////////////
17
//
18
// Copyright (C) 2017, Gisselquist Technology, LLC
19
//
20
// This program is free software (firmware): you can redistribute it and/or
21
// modify it under the terms of the GNU General Public License as published
22
// by the Free Software Foundation, either version 3 of the License, or (at
23
// your option) any later version.
24
//
25
// This program is distributed in the hope that it will be useful, but WITHOUT
26
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
27
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
28
// for more details.
29
//
30
// You should have received a copy of the GNU General Public License along
31
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
32
// target there if the PDF file isn't present.)  If not, see
33
// <http://www.gnu.org/licenses/> for a copy.
34
//
35
// License:     GPL, v3, as defined and found on www.gnu.org,
36
//              http://www.gnu.org/licenses/gpl.html
37
//
38
//
39
////////////////////////////////////////////////////////////////////////////////
40
//
41
//
42
`default_nettype        none
43
//
44
module  toplevel(i_clk, i_sw, o_led, o_shutdown_n, o_gain, o_pwm);
45
        input   wire    i_clk, i_sw;
46
        output  wire    o_led;
47
        output  wire    o_shutdown_n, o_gain;
48
        output  reg     o_pwm;
49
 
50
        // 8 second repeating test sequence
51
        //
52
        // 0: Off
53
        // 1: Off
54
        // 2: 440 Hz
55
        // 3: 440 Hz (continued)
56
        // 4: off
57
        // 5: Sweep, starting at 110Hz
58
        // 6: Sweep (continued)
59
        // 7: Sweep continued, but with a small discontinuity
60
        reg     [36:0]   test_params [0:7];
61
        reg     [36:0]   params;
62
        initial begin
63
                // Sweep starts from 110 Hz
64
                test_params[0] = { 2'b11,
65
                        // Start at 110 Hz
66
                        34'd18_898,     // 0x49d2
67
                        // Sweep
68
                        1'b1 };
69
                test_params[1] = { 2'b11, 34'd158_1398, 1'b1 };
70
                test_params[2] = { 2'b11, 34'd314_3898, 1'b1 };
71
                // One second of silence
72
                test_params[3] = { 2'b00, 34'd0, 1'b0 };
73
                // 440 Hz tone for two seconds
74
                test_params[4] = { 2'b11,
75
                        // 440Hz Tone frequency / 100MHz clock rate * 2^34
76
                        34'd75_591,
77
                        // No sweep rate
78
                        1'b0 };
79
                test_params[5] = { 2'b11, 34'd75_591, 1'b0 };
80
                // Off again for two seconds prior to the next step
81
                test_params[6] = { 2'b00, 34'd0, 1'b0 };
82
                test_params[7] = { 2'b00, 34'd0, 1'b0 };
83
        end
84
 
85
        reg             seq_sweep;
86
        reg     [1:0]    seq_aux;
87
        reg     [33:0]   seq_step;
88
        reg     [31:0]   sub_second_counter;
89
        reg             next_second;
90
 
91
 
92
        // We'll step through the sequence once per second.  Hence, our
93
        // full test-sequence will take 8-seconds.
94
        //
95
        // Artificially start just before the top of a second
96
        initial next_second = 0;
97
        initial sub_second_counter = 32'hffff_fff0;
98
        always @(posedge i_clk)
99
                // 32'd43 is taken from 2^32 / CLOCK_FREQUENCY and then rounded
100
                // to the nearest integer.  Overflows set next_second for one
101
                // clock period only.
102
                { next_second, sub_second_counter }
103
                        <= sub_second_counter + 32'd43;
104
 
105
        // Artificially start at the beginning of the frequency sweep.
106
        reg             test_reset;
107
        reg     [2:0]    test_state;
108
        initial test_state = 3'b000;
109
        always @(posedge i_clk)
110
                // Advance the test on the top of each second
111
                if (next_second)
112
                        test_state <= test_state + 1'b1;
113
 
114
        // At the top of the last second, apply a reset to everything, so we
115
        // know we come back to the same values.  In reality, all this signal
116
        // is going to do is to make sure our two components under test start
117
        // in the exact same configuration.
118
        always @(posedge i_clk)
119
                test_reset <= (next_second)&&(test_state == 3'h7);
120
 
121
        // Read our parameters for the next test.  These will be applied at the
122
        // top of the next second.
123
        always @(posedge i_clk)
124
                params <= test_params[test_state];
125
 
126
        reg     sub_sweep_overflow;
127
        reg     [5:0]    sub_sweep;
128
        initial sub_sweep = 0;
129
        initial sub_sweep_overflow = 0;
130
        always @(posedge i_clk)
131
                if (next_second)
132
                begin
133
                        // seq_aux controls the gain and shutdown values
134
                        seq_aux   <= params[36:35];
135
                        // seq_step controls our output frequency.  It's
136
                        // defined as a step in phase
137
                        seq_step  <= params[34:1];
138
                        // seq_sweep is a single bit indicating whether or not
139
                        // we are sweeping or not.
140
                        seq_sweep <= params[0];
141
                end else begin
142
                        // At each second, add one to the frequency if our
143
                        // sweep step counter overflowed.
144
                        seq_step <= seq_step + {{(33){1'b0}}, sub_sweep_overflow};
145
 
146
                        // Calculate a sweep step counter.  This is a six
147
                        // bit counter (0...63).  When it overflows, we'll
148
                        // increase our phase step amount (seq_step)
149
                        { sub_sweep_overflow, sub_sweep } <= sub_sweep + { {(5){1'b0}}, (seq_sweep) };
150
                end
151
 
152
        // Generating either a tone or a swept tone requires a phase, which we
153
        // can then use to calculate a sin() and cos().  The change in this
154
        // phase value is proportional to the frequency of this phase.
155
        reg     [33:0]   test_phase;
156
        always @(posedge i_clk)
157
                test_phase <= test_phase + seq_step;
158
 
159
        // We're not going to use all of the capabilities of our CORDIC
160
        // sin() and cos() generator.  In particular, we're going to ignore
161
        // the sin() output and the aux synchronization output.  Since
162
        // V*rilator will otherwise complain about this if we turn -Wall on
163
        // (Thank you, verilator), we'll tell it during the definition of
164
        // these values that we aren't going to use them.
165
        //
166
        // verilator lint_off UNUSED
167
        wire            ignore_aux;
168
        wire    [15:0]   geny;
169
        // verilator lint_on  UNUSED
170
 
171
        // The result we want from the cordic, though, is the cos() result.
172
        // this will be used.
173
        wire    signed [15:0]    signal;
174
 
175
        // Here's a straight CORDIC.  The inputs to this should be fairly
176
        // self-explanatory, with the exception of the 16'h6de0.  This value
177
        // is the gain necessary to cause the CORDIC to produce a full-range
178
        // output value.  This gain is calculated internal to the CORDIC
179
        // core generator, but can also be found within the cordic.v code
180
        // following the cordic_angle[] array initialization.  In our case,
181
        // we've taken the top 15-bits of the gain annihilator, prepended
182
        // a zero sign bit, and used that for our value here.  See the
183
        // discussion on CORDIC's, and the CORDIC file for more info.
184
        //
185
        // The value was dropped from 16'h6dec to 16'h6de8 to provide some
186
        // cushion against overflow.
187
        localparam      [15:0]   FULL_SCALE = 16'h6de8,
188
                                SMALL_SCALE= 16'h006e;
189
        localparam      [15:0]   ACTUAL_SCALE = SMALL_SCALE;
190
        cordic  gentone(i_clk, test_reset, 1'b1, ACTUAL_SCALE, 16'h0,
191
                        test_phase[33:9], 1'b0, signal, geny, ignore_aux);
192
 
193
        // Our goal is to calculate two outputs: one from the PDM, one from
194
        // the PWM.
195
        wire    pdm_out, pwm_out;
196
 
197
        // verilator lint_off UNUSED
198
        wire            ignore_ack, ignore_stall, ignore_int,
199
                        trad_ack,   trad_stall,   trad_int;
200
        wire    [31:0]   ignore_data, trad_data;
201
        wire            ignore_pwm_aux, trad_pwm_aux;
202
        // verilator lint_on  UNUSED
203
 
204
        // Here's our component under test.
205
        //
206
        // DEFAULT_RELOAD of 3125 comes from a request to do 32kHz sampling.
207
        //      100e6/32e3 = 3125
208
        // VARIABLE_RATE(0) keeps us from needing to adjust (or set) this
209
        //      sampling rate for this test
210
        // The NAUX value is normally used to control the shutdown and gain
211
        // pins.  Since we're handling theses via another fashion, we'll just
212
        // set this to (1) and ignore the aux pins.
213
        //
214
        // As for the wishbone interface, if all we do is set CYC, STB, and WE
215
        // then the component will accept a value anytime it is ready for the
216
        // next sample.  This allows us to ignore the rest of the wishbone
217
        // interface (ack, stall, data, etc.)  Finally, we'll also ignore the
218
        // interrupt output from the core simply because we don't need it for
219
        // this test setup.
220
        //
221
        localparam signed [15:0] DR_44_1KHZ = 16'd2268,
222
                                        DR_32KHZ = 16'd3125,
223
                                        DR_8KHZ = 16'd12500;
224
        localparam      [15:0]   DEF_RELOAD = DR_8KHZ;
225
        localparam signed [15:0] HALF_DR = DEF_RELOAD[15:1] - 3;
226
 
227
        wbpwmaudio #(.DEFAULT_RELOAD(DEF_RELOAD),
228
                        .VARIABLE_RATE(0),
229
                        .NAUX(1))
230
                genpwm(i_clk, test_reset, 1'b1, 1'b1, 1'b1, 1'b0,
231
                        { 16'h0, signal[14:0], 1'b0 },
232
                        ignore_ack, ignore_stall, ignore_data,
233
                        pdm_out, ignore_pwm_aux, ignore_int);
234
 
235
        //
236
        // Now for the control.
237
        //
238
        // The hypothesis under test is that the waveform above will more
239
        // faithfully generate an audio signal (tone or swept tone) than this
240
        // control signal does.  To make this claim, we need to compare it
241
        // against something.  Hence, our traditional PWM component.
242
 
243
        // One of the difficulties of traditional PWM signals is that they
244
        // can only handle values between zero and the number of clocks in
245
        // their period.  Hence, we'll multiply this by just less than half
246
        // of 3125 to get us into the range of -3125/2 to 3125/2.  Inside the
247
        // component, 3125/2 will be added to the value.  Because 3125/2 isn't
248
        // an integer, this will produce a DC bias.
249
        reg     signed [31:0]    scaled_signal;
250
        always @(posedge i_clk)
251
                scaled_signal <= signal * HALF_DR;
252
 
253
        // Since we're only going to use the top 16-bits, let's tell V*rilator
254
        // that the bottom sixteen bits are unused.
255
        //
256
        // Well, ... not quite.  We're only using bits 29:14.  Hence we need
257
        // to tell Verilator that the other bits are unused.  Since adjusting
258
        // for the scale factor, the number of "unused" bits declared below is a
259
        // touch more than the actual unused bits, but this should just allow
260
        // us to modify things without Verilator complaining at us.
261
        //
262
        // verilator lint_off UNUSED
263
        wire    [17:0]   unused;
264
        assign  unused = { scaled_signal[31:30], scaled_signal[15:0] };
265
        // verilator lint_on  UNUSED
266
 
267
        //
268
        // Here's the traditional PWM component.  It's interface is nearly
269
        // identical to the component above.
270
        traditionalpwm #(.DEFAULT_RELOAD(DEF_RELOAD),
271
                        .VARIABLE_RATE(0), .NAUX(1))
272
                regpwm(i_clk, test_reset, 1'b1, 1'b1, 1'b1, 1'b0,
273
                        { 16'h0, scaled_signal[29:14] },
274
                        trad_ack, trad_stall, trad_data,
275
                        pwm_out, trad_pwm_aux, trad_int);
276
 
277
 
278
        // As a last step, use the switch to control which value actually goes
279
        // out the output port.
280
        always @(posedge i_clk)
281
                if (i_sw)
282
                        o_pwm <= pdm_out;
283
                else
284
                        o_pwm <= pwm_out;
285
 
286
        // Turn the LED "on" if we are producing the improved signal, leave
287
        // it off otherwise.
288
        assign  o_led = i_sw;
289
 
290
        // Finally, use the seq_aux values to control the two audio control
291
        // pins. 
292
        assign  o_shutdown_n = seq_aux[1];
293
        assign  o_gain       = seq_aux[0];
294
 
295
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.