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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [sound/] [sound.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
module sound(
28
    input               clk,
29
    input               rst_n,
30
 
31
    output              irq,
32
 
33
    //speaker input
34
    input               speaker_enable,
35
    input               speaker_out,
36
 
37
    //io slave 220h-22Fh
38
    input       [3:0]   io_address,
39
    input               io_read,
40
    output reg  [7:0]   io_readdata,
41
    input               io_write,
42
    input       [7:0]   io_writedata,
43
 
44
    //fm music io slave 388h-389h
45
    input               fm_address,
46
    input               fm_read,
47
    output      [7:0]   fm_readdata,
48
    input               fm_write,
49
    input       [7:0]   fm_writedata,
50
 
51
    //dma
52
    output              dma_soundblaster_req,
53
    input               dma_soundblaster_ack,
54
    input               dma_soundblaster_terminal,
55
    input       [7:0]   dma_soundblaster_readdata,
56
    output      [7:0]   dma_soundblaster_writedata,
57
 
58
    //sound interface master
59
    output      [2:0]   avm_address,
60
    input               avm_waitrequest,
61
    output              avm_write,
62
    output      [31:0]  avm_writedata,
63
 
64
    //mgmt slave
65
    /*
66
    0-255.[15:0]: cycles in period
67
    256.[12:0]:  cycles in 80us
68
    257.[9:0]:   cycles in 1 sample: 96000 Hz
69
    */
70
    input       [8:0]   mgmt_address,
71
    input               mgmt_write,
72
    input       [31:0]  mgmt_writedata
73
);
74
 
75
//------------------------------------------------------------------------------
76
 
77
//------------------------------------------------------------------------------ dsp
78
 
79
wire [7:0] io_readdata_from_dsp;
80
 
81
wire       sample_from_dsp_disabled;
82
wire       sample_from_dsp_do;
83
wire [7:0] sample_from_dsp_value;
84
 
85
sound_dsp sound_dsp_inst(
86
    .clk                        (clk),
87
    .rst_n                      (rst_n),
88
 
89
    .irq                        (irq),                          //output
90
 
91
    //io slave 220h-22Fh
92
    .io_address                 (io_address),                   //input [3:0]
93
    .io_read                    (io_read),                      //input
94
    .io_readdata_from_dsp       (io_readdata_from_dsp),         //output [7:0]
95
    .io_write                   (io_write),                     //input
96
    .io_writedata               (io_writedata),                 //input [7:0]
97
 
98
    //dma
99
    .dma_soundblaster_req       (dma_soundblaster_req),         //output
100
    .dma_soundblaster_ack       (dma_soundblaster_ack),         //input
101
    .dma_soundblaster_terminal  (dma_soundblaster_terminal),    //input
102
    .dma_soundblaster_readdata  (dma_soundblaster_readdata),    //input [7:0]
103
    .dma_soundblaster_writedata (dma_soundblaster_writedata),   //output [7:0]
104
 
105
    //sample
106
    .sample_from_dsp_disabled   (sample_from_dsp_disabled),     //output
107
    .sample_from_dsp_do         (sample_from_dsp_do),           //output
108
    .sample_from_dsp_value      (sample_from_dsp_value),        //output [7:0] unsigned
109
 
110
    //mgmt slave
111
    /*
112
    0-255.[15:0]: cycles in period
113
    */
114
    .mgmt_address               (mgmt_address),                 //input [8:0]
115
    .mgmt_write                 (mgmt_write),                   //input
116
    .mgmt_writedata             (mgmt_writedata)                //input [31:0]
117
);
118
 
119
//------------------------------------------------------------------------------ opl2
120
 
121
wire [7:0] sb_readdata_from_opl2;
122
 
123
wire        sample_from_opl2;
124
wire [15:0] sample_from_opl2_value;
125
 
126
sound_opl2 sound_opl2_inst(
127
    .clk                        (clk),
128
    .rst_n                      (rst_n),
129
 
130
    //sb slave 220h-22Fh
131
    .sb_address                 (io_address),               //input [3:0]
132
    .sb_read                    (io_read),                  //input
133
    .sb_readdata_from_opl2      (sb_readdata_from_opl2),    //output [7:0]
134
    .sb_write                   (io_write),                 //input
135
    .sb_writedata               (io_writedata),             //input [7:0]
136
 
137
 
138
    //fm music io slave 388h-389h
139
    .fm_address                 (fm_address),               //input
140
    .fm_read                    (fm_read),                  //input
141
    .fm_readdata                (fm_readdata),              //output [7:0]
142
    .fm_write                   (fm_write),                 //input
143
    .fm_writedata               (fm_writedata),             //input [7:0]
144
 
145
    //sample
146
    .sample_from_opl2           (sample_from_opl2),         //output
147
    .sample_from_opl2_value     (sample_from_opl2_value),   //output [15:0]
148
 
149
    //mgmt slave
150
    /*
151
    256.[12:0]:  cycles in 80us
152
    257.[9:0]:   cycles in 1 sample: 96000 Hz
153
    */
154
    .mgmt_address               (mgmt_address),   //input [8:0]
155
    .mgmt_write                 (mgmt_write),     //input
156
    .mgmt_writedata             (mgmt_writedata)  //input [31:0]
157
);
158
 
159
//------------------------------------------------------------------------------ io_readdata
160
 
161
wire [7:0] io_readdata_next =
162
    (io_address == 4'h8 || io_address == 4'h9)?     sb_readdata_from_opl2 :
163
                                                    io_readdata_from_dsp;
164
 
165
always @(posedge clk or negedge rst_n) begin
166
    if(rst_n == 1'b0)   io_readdata <= 8'd0;
167
    else                io_readdata <= io_readdata_next;
168
end
169
 
170
//------------------------------------------------------------------------------ speaker
171
 
172
reg [15:0] speaker_value;
173
always @(posedge clk or negedge rst_n) begin
174
    if(rst_n == 1'b0)                               speaker_value <= 16'd0;
175
    else if(speaker_enable && speaker_out == 1'b0)  speaker_value <= 16'd16384;
176
    else if(speaker_enable && speaker_out == 1'b1)  speaker_value <= 16'd49152;
177
    else                                            speaker_value <= 16'd0;
178
end
179
 
180
//------------------------------------------------------------------------------
181
 
182
reg [15:0] sample_dsp;
183
always @(posedge clk or negedge rst_n) begin
184
    if(rst_n == 1'b0)                   sample_dsp <= 16'd0;
185
    else if(sample_from_dsp_disabled)   sample_dsp <= 16'd0;
186
    else if(sample_from_dsp_do)         sample_dsp <= { sample_from_dsp_value, 8'd0 } - 16'd32768; //unsigned to signed
187
end
188
 
189
reg [15:0] sample_opl2;
190
always @(posedge clk or negedge rst_n) begin
191
    if(rst_n == 1'b0)           sample_opl2 <= 16'd0;
192
    else if(sample_from_opl2)   sample_opl2 <= sample_from_opl2_value; //already signed
193
end
194
 
195
wire [15:0] sample_sum_1 = sample_dsp + sample_opl2;
196
 
197
wire [15:0] sample_next_1 = (sample_dsp[15] == 1'b0 && sample_opl2[15] == 1'b0 && sample_sum_1[15] == 1'b1)?   16'd32767 :
198
                            (sample_dsp[15] == 1'b1 && sample_opl2[15] == 1'b1 && sample_sum_1[15] == 1'b0)?   16'd32768 :
199
                                                                                                               sample_sum_1[15:0];
200
reg [15:0] sample_sum_1_reg;
201
always @(posedge clk or negedge rst_n) begin
202
    if(rst_n == 1'b0)               sample_sum_1_reg <= 16'd0;
203
    else if(state == STATE_LOAD_1)  sample_sum_1_reg <= sample_next_1;
204
end
205
 
206
wire [15:0] sample_sum_2 = sample_sum_1_reg + speaker_value;
207
 
208
wire [15:0] sample_next_2 = (sample_sum_1_reg[15] == 1'b0 && speaker_value[15] == 1'b0 && sample_sum_2[15] == 1'b1)?    16'd32767 :
209
                            (sample_sum_1_reg[15] == 1'b1 && speaker_value[15] == 1'b1 && sample_sum_2[15] == 1'b0)?    16'd32768 :
210
                                                                                                                        sample_sum_2[15:0];
211
 
212
//------------------------------------------------------------------------------
213
 
214
localparam [1:0] STATE_IDLE   = 2'd0;
215
localparam [1:0] STATE_LOAD_1 = 2'd1;
216
localparam [1:0] STATE_LOAD_2 = 2'd2;
217
localparam [1:0] STATE_WRITE  = 2'd3;
218
 
219
reg [1:0] state;
220
 
221
reg [15:0] sample_sum_2_reg;
222
always @(posedge clk or negedge rst_n) begin
223
    if(rst_n == 1'b0)               sample_sum_2_reg <= 16'd0;
224
    else if(state == STATE_LOAD_2)  sample_sum_2_reg <= sample_next_2;
225
end
226
 
227
assign avm_address   = 3'd0;
228
assign avm_writedata = { 16'd0, sample_sum_2_reg }; //signed
229
assign avm_write     = state == STATE_WRITE;
230
 
231
always @(posedge clk or negedge rst_n) begin
232
    if(rst_n == 1'b0)                                   state <= STATE_IDLE;
233
    else if(state == STATE_IDLE && sample_from_opl2)    state <= STATE_LOAD_1;
234
    else if(state == STATE_LOAD_1)                      state <= STATE_LOAD_2;
235
    else if(state == STATE_LOAD_2)                      state <= STATE_WRITE;
236
    else if(state == STATE_WRITE && ~(avm_waitrequest)) state <= STATE_IDLE;
237
end
238
 
239
//------------------------------------------------------------------------------
240
 
241
endmodule

powered by: WebSVN 2.1.0

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