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

Subversion Repositories aoocs

[/] [aoocs/] [trunk/] [rtl/] [terasic_de2_70/] [drv_audio.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright 2010, Aleksander Osman, alfik@poczta.fm. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without modification, are
5
 * permitted provided that the following conditions are met:
6
 *
7
 *  1. Redistributions of source code must retain the above copyright notice, this list of
8
 *     conditions and the following disclaimer.
9
 *
10
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list
11
 *     of conditions and the following disclaimer in the documentation and/or other materials
12
 *     provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
 
25
/*! \file
26
 * \brief WM8731 audio codec driver for stereo audio output.
27
 */
28
 
29
/*! \brief \copybrief drv_audio.v
30
*/
31
module drv_audio(
32
        //% \name Clock and reset
33
    //% @{
34
        input       clk_12,
35
        input       reset_n,
36
        //% @}
37
 
38
        //% \name drv_audio interface
39
    //% @{
40
    input [5:0] volume0,
41
    input [5:0] volume1,
42
    input [5:0] volume2,
43
    input [5:0] volume3,
44
    input [7:0] sample0,
45
    input [7:0] sample1,
46
    input [7:0] sample2,
47
    input [7:0] sample3,
48
        //% @}
49
 
50
        //% \name WM8731 audio codec hardware interface
51
        //% @{
52
        output      ac_sclk,
53
        inout       ac_sdat,
54
        output      ac_xclk,
55
        output reg  ac_bclk,
56
        output      ac_dat,
57
        output reg  ac_lr
58
        //% @}
59
);
60
 
61
//clock domain switch
62
reg [5:0] volume0a;
63
reg [5:0] volume1a;
64
reg [5:0] volume2a;
65
reg [5:0] volume3a;
66
reg [7:0] sample0a;
67
reg [7:0] sample1a;
68
reg [7:0] sample2a;
69
reg [7:0] sample3a;
70
 
71
always @(posedge clk_12) begin
72
    volume0a <= volume0;
73
    volume1a <= volume1;
74
    volume2a <= volume2;
75
    volume3a <= volume3;
76
    sample0a <= sample0;
77
    sample1a <= sample1;
78
    sample2a <= sample2;
79
    sample3a <= sample3;
80
end
81
 
82
reg [5:0] volume0f;
83
reg [5:0] volume1f;
84
reg [5:0] volume2f;
85
reg [5:0] volume3f;
86
reg [7:0] sample0f;
87
reg [7:0] sample1f;
88
reg [7:0] sample2f;
89
reg [7:0] sample3f;
90
 
91
always @(posedge clk_12) begin
92
    volume0f <= volume0a;
93
    volume1f <= volume1a;
94
    volume2f <= volume2a;
95
    volume3f <= volume3a;
96
    sample0f <= sample0a;
97
    sample1f <= sample1a;
98
    sample2f <= sample2a;
99
    sample3f <= sample3a;
100
end
101
 
102
 
103
assign ac_dat = left_right_sample[31];
104
assign ac_xclk = clk_12;
105
 
106
// left MSB-LSB, right MSB-LSB
107
reg [31:0] left_right_sample;
108
reg [7:0] data_counter;
109
 
110
wire [13:0] mult_left_1;
111
assign mult_left_1 =
112
    ((volume1f[0] == 1'b1)? { {6{sample1f[7]}}, sample1f[7:0] } : 14'd0) +
113
    ((volume1f[1] == 1'b1)? { {5{sample1f[7]}}, sample1f[7:0], 1'b0 } : 14'd0) +
114
    ((volume1f[2] == 1'b1)? { {4{sample1f[7]}}, sample1f[7:0], 2'b0 } : 14'd0) +
115
    ((volume1f[3] == 1'b1)? { {3{sample1f[7]}}, sample1f[7:0], 3'b0 } : 14'd0) +
116
    ((volume1f[4] == 1'b1)? { {2{sample1f[7]}}, sample1f[7:0], 4'b0 } : 14'd0) +
117
    ((volume1f[5] == 1'b1)? { {1{sample1f[7]}}, sample1f[7:0], 5'b0 } : 14'd0);
118
 
119
wire [13:0] mult_left_2;
120
assign mult_left_2 =
121
    ((volume2f[0] == 1'b1)? { {6{sample2f[7]}}, sample2f[7:0] } : 14'd0) +
122
    ((volume2f[1] == 1'b1)? { {5{sample2f[7]}}, sample2f[7:0], 1'b0 } : 14'd0) +
123
    ((volume2f[2] == 1'b1)? { {4{sample2f[7]}}, sample2f[7:0], 2'b0 } : 14'd0) +
124
    ((volume2f[3] == 1'b1)? { {3{sample2f[7]}}, sample2f[7:0], 3'b0 } : 14'd0) +
125
    ((volume2f[4] == 1'b1)? { {2{sample2f[7]}}, sample2f[7:0], 4'b0 } : 14'd0) +
126
    ((volume2f[5] == 1'b1)? { {1{sample2f[7]}}, sample2f[7:0], 5'b0 } : 14'd0);
127
 
128
wire [13:0] mult_right_0;
129
assign mult_right_0 =
130
    ((volume0f[0] == 1'b1)? { {6{sample0f[7]}}, sample0f[7:0] } : 14'd0) +
131
    ((volume0f[1] == 1'b1)? { {5{sample0f[7]}}, sample0f[7:0], 1'b0 } : 14'd0) +
132
    ((volume0f[2] == 1'b1)? { {4{sample0f[7]}}, sample0f[7:0], 2'b0 } : 14'd0) +
133
    ((volume0f[3] == 1'b1)? { {3{sample0f[7]}}, sample0f[7:0], 3'b0 } : 14'd0) +
134
    ((volume0f[4] == 1'b1)? { {2{sample0f[7]}}, sample0f[7:0], 4'b0 } : 14'd0) +
135
    ((volume0f[5] == 1'b1)? { {1{sample0f[7]}}, sample0f[7:0], 5'b0 } : 14'd0);
136
 
137
wire [13:0] mult_right_3;
138
assign mult_right_3 =
139
    ((volume3f[0] == 1'b1)? { {6{sample3f[7]}}, sample3f[7:0] } : 14'd0) +
140
    ((volume3f[1] == 1'b1)? { {5{sample3f[7]}}, sample3f[7:0], 1'b0 } : 14'd0) +
141
    ((volume3f[2] == 1'b1)? { {4{sample3f[7]}}, sample3f[7:0], 2'b0 } : 14'd0) +
142
    ((volume3f[3] == 1'b1)? { {3{sample3f[7]}}, sample3f[7:0], 3'b0 } : 14'd0) +
143
    ((volume3f[4] == 1'b1)? { {2{sample3f[7]}}, sample3f[7:0], 4'b0 } : 14'd0) +
144
    ((volume3f[5] == 1'b1)? { {1{sample3f[7]}}, sample3f[7:0], 5'b0 } : 14'd0);
145
 
146
wire [14:0] left_channel;
147
assign left_channel = { mult_left_1[13], mult_left_1 } + { mult_left_2[13], mult_left_2 };
148
 
149
wire [14:0] right_channel;
150
assign right_channel = { mult_right_0[13], mult_right_0 } + { mult_right_3[13], mult_right_3 };
151
 
152
/* Butterworth second order low-pass filter, cut-off = 3.3 kHz, sampling rate = 48 kHz
153
    y_n =
154
            1.4014      y_n1
155
            -0.5432     y_n2
156
            0.0354      x_n
157
            0.0709      x_n1
158
            0.0354      x_n2
159
    Coefficients * 2^14:
160
            1.4014  ->  22961           =   1.01100110110001
161
            -0.5432 ->  -8900           =  -0.10001011000100
162
            0.0354  ->  580             =   0.10010001000000
163
            0.0709  ->  1162            =   0.10010001010000
164
            0.0354  ->  580             =   0.10010001000000
165
*/
166
 
167
wire [31:0] lx_n;
168
assign lx_n = { {3{left_channel[14]}}, left_channel, 14'd0 };
169
 
170
wire [31:0] rx_n;
171
assign rx_n = { {3{right_channel[14]}}, right_channel, 14'd0 };
172
 
173
reg [31:0] ly_n1;
174
reg [31:0] ly_n2;
175
reg [31:0] lx_n1;
176
reg [31:0] lx_n2;
177
 
178
reg [31:0] ry_n1;
179
reg [31:0] ry_n2;
180
reg [31:0] rx_n1;
181
reg [31:0] rx_n2;
182
 
183
wire [31:0] minus_ly_n2;
184
assign minus_ly_n2 = -ly_n2;
185
 
186
wire [31:0] ly_n;
187
assign ly_n =
188
    ly_n1 +
189
    { {2{ly_n1[31]}}, ly_n1[31:2] } +
190
    { {3{ly_n1[31]}}, ly_n1[31:3] } +
191
    { {6{ly_n1[31]}}, ly_n1[31:6] } +
192
    { {7{ly_n1[31]}}, ly_n1[31:7] } +
193
    { {9{ly_n1[31]}}, ly_n1[31:9] } +
194
    { {10{ly_n1[31]}}, ly_n1[31:10] } +
195
    { {14{ly_n1[31]}}, ly_n1[31:14] } +
196
 
197
    { {1{minus_ly_n2[31]}}, minus_ly_n2[31:1] } +
198
    { {5{minus_ly_n2[31]}}, minus_ly_n2[31:5] } +
199
    { {7{minus_ly_n2[31]}}, minus_ly_n2[31:7] } +
200
    { {8{minus_ly_n2[31]}}, minus_ly_n2[31:8] } +
201
    { {13{minus_ly_n2[31]}}, minus_ly_n2[31:13] } +
202
    { {14{minus_ly_n2[31]}}, minus_ly_n2[31:14] } +
203
 
204
    { {5{lx_n[31]}}, lx_n[31:5] } +
205
    { {8{lx_n[31]}}, lx_n[31:8] } +
206
    { {12{lx_n[31]}}, lx_n[31:12] } +
207
    { {14{lx_n[31]}}, lx_n[31:14] } +
208
 
209
    { {4{lx_n1[31]}}, lx_n1[31:4] } +
210
    { {7{lx_n1[31]}}, lx_n1[31:7] } +
211
    { {11{lx_n1[31]}}, lx_n1[31:11] } +
212
    { {14{lx_n1[31]}}, lx_n1[31:14] } +
213
 
214
    { {5{lx_n2[31]}}, lx_n2[31:5] } +
215
    { {8{lx_n2[31]}}, lx_n2[31:8] } +
216
    { {12{lx_n2[31]}}, lx_n2[31:12] } +
217
    { {14{lx_n2[31]}}, lx_n2[31:14] };
218
 
219
wire [31:0] minus_ry_n2;
220
assign minus_ry_n2 = -ry_n2;
221
 
222
wire [31:0] ry_n;
223
assign ry_n =
224
    ry_n1 +
225
    { {2{ry_n1[31]}}, ry_n1[31:2] } +
226
    { {3{ry_n1[31]}}, ry_n1[31:3] } +
227
    { {6{ry_n1[31]}}, ry_n1[31:6] } +
228
    { {7{ry_n1[31]}}, ry_n1[31:7] } +
229
    { {9{ry_n1[31]}}, ry_n1[31:9] } +
230
    { {10{ry_n1[31]}}, ry_n1[31:10] } +
231
    { {14{ry_n1[31]}}, ry_n1[31:14] } +
232
 
233
    { {1{minus_ry_n2[31]}}, minus_ry_n2[31:1] } +
234
    { {5{minus_ry_n2[31]}}, minus_ry_n2[31:5] } +
235
    { {7{minus_ry_n2[31]}}, minus_ry_n2[31:7] } +
236
    { {8{minus_ry_n2[31]}}, minus_ry_n2[31:8] } +
237
    { {13{minus_ry_n2[31]}}, minus_ry_n2[31:13] } +
238
    { {14{minus_ry_n2[31]}}, minus_ry_n2[31:14] } +
239
 
240
    { {5{rx_n[31]}}, rx_n[31:5] } +
241
    { {8{rx_n[31]}}, rx_n[31:8] } +
242
    { {12{rx_n[31]}}, rx_n[31:12] } +
243
    { {14{rx_n[31]}}, rx_n[31:14] } +
244
 
245
    { {4{rx_n1[31]}}, rx_n1[31:4] } +
246
    { {7{rx_n1[31]}}, rx_n1[31:7] } +
247
    { {11{rx_n1[31]}}, rx_n1[31:11] } +
248
    { {14{rx_n1[31]}}, rx_n1[31:14] } +
249
 
250
    { {5{rx_n2[31]}}, rx_n2[31:5] } +
251
    { {8{rx_n2[31]}}, rx_n2[31:8] } +
252
    { {12{rx_n2[31]}}, rx_n2[31:12] } +
253
    { {14{rx_n2[31]}}, rx_n2[31:14] };
254
 
255
always @(posedge clk_12 or negedge reset_n) begin
256
    if(reset_n == 1'b0) begin
257
        data_counter        <= 8'd0;
258
        left_right_sample   <= 32'd0;
259
        ac_bclk             <= 1'b0;
260
        ac_lr               <= 1'b0;
261
 
262
        ly_n1 <= 30'd0;
263
        ly_n2 <= 30'd0;
264
        lx_n1 <= 30'd0;
265
        lx_n2 <= 30'd0;
266
        ry_n1 <= 30'd0;
267
        ry_n2 <= 30'd0;
268
        rx_n1 <= 30'd0;
269
        rx_n2 <= 30'd0;
270
    end
271
    else if(data_counter == 8'd0 && state == S_READY) begin
272
        data_counter <= data_counter + 8'd1;
273
        left_right_sample <= { ly_n[29:14],  ry_n[29:14] };
274
        ac_bclk <= 1'b0;
275
        ac_lr <= 1'b1;
276
 
277
        ly_n1 <= ly_n;
278
        ly_n2 <= ly_n1;
279
        lx_n1 <= lx_n;
280
        lx_n2 <= lx_n1;
281
        ry_n1 <= ry_n;
282
        ry_n2 <= ry_n1;
283
        rx_n1 <= rx_n;
284
        rx_n2 <= rx_n1;
285
 
286
    end
287
    else if(data_counter == 8'd1) begin
288
        data_counter <= data_counter + 8'd1;
289
        ac_bclk <= 1'b1;
290
        ac_lr <= 1'b1;
291
    end
292
    else if(data_counter >= 8'd127 && data_counter <= 8'd248) begin
293
        data_counter <= data_counter + 8'd1;
294
        left_right_sample <= { left_right_sample[30:0], 1'b0 };
295
        ac_bclk <= 1'b0;
296
        ac_lr <= 1'b0;
297
    end
298
    else if(data_counter == 8'd249) begin
299
        data_counter <= 8'd0;
300
        ac_bclk <= 1'b0;
301
        ac_lr <= 1'b0;
302
    end
303
    else if(data_counter[1:0] == 2'b11) begin
304
        data_counter <= data_counter + 8'd1;
305
        left_right_sample <= { left_right_sample[30:0], 1'b0 };
306
        ac_bclk <= 1'b0;
307
        ac_lr <= 1'b0;
308
    end
309
    else if(data_counter[1:0] == 2'b01) begin
310
        data_counter <= data_counter + 8'd1;
311
        ac_bclk <= 1'b1;
312
        ac_lr <= 1'b0;
313
    end
314
    else if(data_counter != 8'd0 && state == S_READY) begin
315
        data_counter <= data_counter + 8'd1;
316
    end
317
end
318
 
319
reg i2c_start;
320
reg [15:0] i2c_data;
321
reg [3:0] state;
322
 
323
parameter [3:0]
324
    S_IDLE      = 4'd0,
325
    S_RESET     = 4'd1,
326
    S_POWER     = 4'd2,
327
    S_OUTPUT    = 4'd3,
328
    S_SIDE      = 4'd4,
329
    S_EMPH      = 4'd5,
330
    S_FORMAT    = 4'd6,
331
    S_SAMPLING  = 4'd7,
332
    S_ACTIVATE  = 4'd8,
333
    S_READY     = 4'd9;
334
 
335
wire i2c_ready;
336
 
337
i2c_send i2c_send_inst(
338
    .clk_12(clk_12),
339
    .reset_n(reset_n),
340
 
341
    .start(i2c_start),
342
    .data(i2c_data),
343
    .ready(i2c_ready),
344
 
345
    .sclk(ac_sclk),
346
    .sdat(ac_sdat)
347
);
348
 
349
always @(posedge clk_12 or negedge reset_n) begin
350
    if(reset_n == 1'b0) begin
351
        i2c_start <= 1'b0;
352
        i2c_data <= 16'd0;
353
        state <= S_IDLE;
354
    end
355
    else begin
356
        if(state == S_IDLE) begin
357
            i2c_start <= 1'b1;
358
            i2c_data <= 16'b0001111_000000000;
359
            state <= S_RESET;
360
        end
361
        else if(state == S_RESET && i2c_ready == 1'b1) begin
362
            i2c_start <= 1'b1;
363
            i2c_data <= 16'b0000110_001100111; // power down unused parts
364
            state <= S_POWER;
365
        end
366
        else if(state == S_POWER && i2c_ready == 1'b1) begin
367
            i2c_start <= 1'b1;
368
            i2c_data <= 16'b0000010_101111001; // 0dB headphone output
369
            state <= S_OUTPUT;
370
        end
371
        else if(state == S_OUTPUT && i2c_ready == 1'b1) begin
372
            i2c_start <= 1'b1;
373
            i2c_data <= 16'b0000100_011010010; // DAC select
374
            state <= S_SIDE;
375
        end
376
        else if(state == S_SIDE && i2c_ready == 1'b1) begin
377
            i2c_start <= 1'b1;
378
            i2c_data <= 16'b0000101_000000011; // disable mute, 32kHz de-emphasis
379
            state <= S_EMPH;
380
        end
381
        else if(state == S_EMPH && i2c_ready == 1'b1) begin
382
            i2c_start <= 1'b1;
383
            i2c_data <= 16'b0000111_000000011; // DSP mode
384
            state <= S_FORMAT;
385
        end
386
        else if(state == S_FORMAT && i2c_ready == 1'b1) begin
387
            i2c_start <= 1'b1;
388
            i2c_data <= 16'b0001000_000000001; // USB mode, 12MHz, 48 kHz
389
            state <= S_SAMPLING;
390
        end
391
        else if(state == S_SAMPLING && i2c_ready == 1'b1) begin
392
            i2c_start <= 1'b1;
393
            i2c_data <= 16'b0001001_000000001;
394
            state <= S_ACTIVATE;
395
        end
396
        else if(state == S_ACTIVATE && i2c_ready == 1'b1) begin
397
            state <= S_READY;
398
        end
399
        else begin
400
            i2c_start <= 1'b0;
401
        end
402
    end
403
end
404
 
405
endmodule
406
 
407
/*! \brief I2C write helper module.
408
 */
409
module i2c_send(
410
    input clk_12,
411
    input reset_n,
412
 
413
    input start,
414
    input [15:0] data,
415
    output ready,
416
 
417
    output reg sclk,
418
    inout sdat
419
);
420
 
421
assign ready = (state == S_IDLE && start == 1'b0);
422
assign sdat = (sdat_oe == 1'b0)? 1'bZ : sdat_o;
423
 
424
reg sdat_oe;
425
reg sdat_o;
426
reg [7:0] dat_byte;
427
reg [1:0] part;
428
reg [2:0] counter;
429
reg [3:0] state;
430
parameter [3:0]
431
    S_IDLE      = 4'd0,
432
    S_SEND_0    = 4'd1,
433
    S_SEND_1    = 4'd2,
434
    S_SEND_2    = 4'd3,
435
    S_SEND_3    = 4'd4,
436
    S_SEND_4    = 4'd5,
437
    S_END_0     = 4'd6,
438
    S_END_1     = 4'd7,
439
    S_END_2     = 4'd8;
440
 
441
always @(posedge clk_12 or negedge reset_n) begin
442
    if(reset_n == 1'b0) begin
443
        sclk <= 1'b1;
444
        sdat_oe <= 1'b0;
445
        sdat_o <= 1'b1;
446
        dat_byte <= 8'd0;
447
        part <= 2'b0;
448
        counter <= 3'd0;
449
        state <= S_IDLE;
450
    end
451
    else if(state == S_IDLE && start == 1'b1) begin
452
        // start
453
        sdat_oe <= 1'b1;
454
        sdat_o <= 1'b0;
455
        sclk <= 1'b1;
456
 
457
        part <= 2'b0;
458
        dat_byte <= 8'b0011010_0;
459
        counter <= 3'd7;
460
        state <= S_SEND_0;
461
    end
462
    else if(state == S_SEND_0) begin
463
        sdat_oe <= 1'b1;
464
        sdat_o <= dat_byte[7];
465
        sclk <= 1'b0;
466
        state <= S_SEND_1;
467
    end
468
    else if(state == S_SEND_1) begin
469
        sclk <= 1'b1;
470
 
471
        if(counter == 3'd0) state <= S_SEND_2;
472
        else begin
473
            dat_byte <= { dat_byte[6:0], 1'b0 };
474
            counter <= counter - 3'd1;
475
            state <= S_SEND_0;
476
        end
477
    end
478
    else if(state == S_SEND_2) begin
479
        sdat_oe <= 1'b0;
480
        sclk <= 1'b0;
481
        state <= S_SEND_3;
482
    end
483
    else if(state == S_SEND_3) begin
484
        sclk <= 1'b1;
485
        state <= S_SEND_4;
486
    end
487
    else if(state == S_SEND_4 && sdat == 1'b0) begin
488
        sclk <= 1'b0;
489
        part <= part + 2'b1;
490
        counter <= 3'd7;
491
 
492
        if(part == 2'd0)        dat_byte <= data[15:8];
493
        else if(part == 2'd1)   dat_byte <= data[7:0];
494
 
495
        if(part == 2'd0 || part == 2'd1)    state <= S_SEND_0;
496
        else                                state <= S_END_0;
497
    end
498
    else if(state == S_END_0) begin
499
        sdat_oe <= 1'b1;
500
        sdat_o <= 1'b0;
501
        sclk <= 1'b0;
502
        state <= S_END_1;
503
    end
504
    else if(state == S_END_1) begin
505
        sclk <= 1'b1;
506
        state <= S_END_2;
507
    end
508
    else if(state == S_END_2) begin
509
        // end
510
        sdat_oe <= 1'b0;
511
        state <= S_IDLE;
512
    end
513
end
514
 
515
endmodule

powered by: WebSVN 2.1.0

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