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

Subversion Repositories rtf68ksys

[/] [rtf68ksys/] [trunk/] [rtl/] [verilog/] [PSG16.v] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
//=============================================================================
2
//      2007,2010  Robert Finch
3
//      robfinch@FPGAfield.ca
4
//
5
//      PSG16.v 
6
//              4 Channel ADSR sound generator
7
//
8
//      This source code is available only for veiwing, testing and evaluation
9
//      purposes. Any commercial use requires a license. This copyright
10
//      statement and disclaimer must remain present in the file.
11
//
12
//
13
//      NO WARRANTY.
14
//  THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER
15
//      EXPRESS OR IMPLIED. The user must assume the entire risk of using the
16
//      Work.
17
//
18
//      IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
19
//  INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO
20
//  THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR.
21
//
22
//      IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK
23
//      IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN
24
//      REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN
25
//      LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU
26
//      AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR
27
//      LOSSES RELATING TO SUCH UNAUTHORIZED USE.
28
//
29
//
30
//      Registers
31
//      0            ffffffff ffffffff   freq [15:0]
32
//      1           ----pppp pppppppp   pulse width [11:0]
33
//      2           trsg--fo -vvvvv--   test, ringmod, sync, gate, filter, output, voice type
34
//                                                                                      vvvvv
35
//                                                                                      wnpst
36
//      3           -------- --------   reserved
37
//      4           aaaaaaaa aaaaaaaa   attack
38
//      5           ----dddd dddddddd   decay
39
//      6           -------- ssssssss   sustain
40
//      7           ----rrrr rrrrrrrr   release
41
//      ...
42
//      64      -------- ----vvvv   volume (0-15)
43
//      65      nnnnnnnn nnnnnnnn   osc3 oscillator 3
44
//      66      -------- nnnnnnnn   env3 envelope 3
45
//      67
46
//      68      aa------ --------   wave table address a15-14
47
//      69      aaaaaaaa aaaaaaaa   wave table address a31-16
48
//
49
//  80-87   s---kkkk kkkkkkkk   filter coefficients
50
//  88-96   -------- --------   reserved for more filter coefficients
51
//
52
//
53
//      Spartan3
54
//      Webpack 12.3  xc3s1200e-4fg320
55
//      1290 LUTs / 893 slices / 69.339 MHz
56
//      1 Multipliers
57
//=============================================================================
58
 
59
module PSG16(rst_i, clk_i, cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o,
60
        vol_o, bg,
61
        m_cyc_o, m_stb_o, m_ack_i, m_we_o, m_sel_o, m_adr_o, m_dat_i, o
62
);
63
parameter pClkDivide = 66;
64
 
65
// WISHBONE SYSCON
66
input rst_i;
67
input clk_i;                    // system clock
68
// WISHBONE SLAVE
69
input cyc_i;                    // cycle valid
70
input stb_i;                    // circuit select
71
output ack_o;
72
input we_i;                             // write
73
input  [1:0] sel_i;              // byte selects
74
input [43:0] adr_i;              // address input
75
input [15:0] dat_i;              // data input
76
output [15:0] dat_o;     // data output
77
// WISHBONE MASTER
78
output m_cyc_o;                 // bus request
79
output m_stb_o;                 // strobe output
80
input m_ack_i;
81
output m_we_o;                  // write enable (always inactive)
82
output [ 1:0] m_sel_o;   // byte lane selects
83
output [43:0] m_adr_o;   // wave table address
84
input  [11:0] m_dat_i;   // wave table data input
85
 
86
output vol_o;
87
 
88
input bg;                               // bus grant
89
 
90
output [11:0] o;
91
 
92
// I/O registers
93
reg [15:0] dat_o;
94
reg vol_o;
95
reg [43:0] m_adr_o;
96
 
97
reg [3:0] test;                          // test (enable note generator)
98
reg [4:0] vt [3:0];                       // voice type
99
reg [15:0] freq0, freq1, freq2, freq3;   // frequency control
100
reg [11:0] pw0, pw1, pw2, pw3;                   // pulse width control
101
reg [3:0] gate;
102
reg [15:0] attack0, attack1, attack2, attack3;
103
reg [11:0] decay0, decay1, decay2, decay3;
104
reg [7:0] sustain0, sustain1, sustain2, sustain3;
105
reg [11:0] relese0, relese1, relese2, relese3;
106
reg [3:0] sync;
107
reg [3:0] ringmod;
108
reg [3:0] outctrl;
109
reg [3:0] filt;                // 1 = output goes to filter
110
wire [23:0] acc0, acc1, acc2, acc3;
111
reg [3:0] volume;        // master volume
112
wire [11:0] ngo; // not generator output
113
wire [7:0] env;          // envelope generator output
114
wire [7:0] env3;
115
wire [7:0] ibr;
116
wire [7:0] ibg;
117
wire [21:0] out1;
118
wire [21:0] out3;
119
wire [19:0] out4;
120
wire [21:0] filtin1;     // FIR filter input
121
wire [14:0] filt_o;              // FIR filter output
122
 
123
wire cs = cyc_i && stb_i && (adr_i[43:8]==36'hFFF_FFD4_00);
124
assign m_cyc_o = |ibr & ~bg;
125
assign m_stb_o = m_cyc_o;
126
assign m_we_o  = 1'b0;
127
assign m_sel_o = {m_cyc_o,m_cyc_o};
128
assign ack_o = cs;
129
wire my_ack = m_ack_i;
130
 
131
// write to registers
132
always @(posedge clk_i)
133
begin
134
        if (rst_i) begin
135
                freq0 <= 0;
136
                freq1 <= 0;
137
                freq2 <= 0;
138
                freq3 <= 0;
139
                pw0 <= 0;
140
                pw1 <= 0;
141
                pw2 <= 0;
142
                pw3 <= 0;
143
                test <= 0;
144
                vt[0] <= 0;
145
                vt[1] <= 0;
146
                vt[2] <= 0;
147
                vt[3] <= 0;
148
                gate <= 0;
149
                outctrl <= 0;
150
                filt <= 0;
151
                attack0 <= 0;
152
                attack1 <= 0;
153
                attack2 <= 0;
154
                attack3 <= 0;
155
                decay0 <= 0;
156
                sustain0 <= 0;
157
                relese0 <= 0;
158
                decay1 <= 0;
159
                sustain1 <= 0;
160
                relese1 <= 0;
161
                decay2 <= 0;
162
                sustain2 <= 0;
163
                relese2 <= 0;
164
                decay3 <= 0;
165
                sustain3 <= 0;
166
                relese3 <= 0;
167
                sync <= 0;
168
                ringmod <= 0;
169
                volume <= 0;
170
                m_adr_o[31:14] <= 18'b0000_0000_0000_0011_10;   // 00038000
171
        end
172
        else begin
173
                if (ack_o & we_i) begin
174
                        case(adr_i[7:1])
175
                        7'd0:
176
                                        begin
177
                                                if (sel_i[0]) freq0[ 7:0] <= dat_i[ 7:0];
178
                                                if (sel_i[1]) freq0[15:8] <= dat_i[15:8];
179
                                        end
180
                        7'd1:
181
                                        begin
182
                                                if (sel_i[0]) pw0[ 7:0] <= dat_i[ 7:0];
183
                                                if (sel_i[1]) pw0[11:8] <= dat_i[11:8];
184
                                        end
185
                        7'd2:   begin
186
                                                if (sel_i[0]) vt[0] <= dat_i[6:2];
187
                                                if (sel_i[1]) begin
188
                                                        outctrl[0] <= dat_i[8];
189
                                                        filt[0] <= dat_i[9];
190
                                                        gate[0] <= dat_i[12];
191
                                                        sync[0] <= dat_i[13];
192
                                                        ringmod[0] <= dat_i[14];
193
                                                        test[0] <= dat_i[15];
194
                                                end
195
                                        end
196
                        7'd3:   ;
197
                        7'd4:   attack0 <= dat_i;
198
                        7'd5:   decay0 <= dat_i;
199
                        7'd6:   if (sel_i[0]) sustain0 <= dat_i;
200
                        7'd7:   relese0 <= dat_i;
201
 
202
                        7'd8:
203
                                        begin
204
                                                if (sel_i[0]) freq1[ 7:0] <= dat_i[ 7:0];
205
                                                if (sel_i[1]) freq1[15:8] <= dat_i[15:8];
206
                                        end
207
                        7'd9:
208
                                        begin
209
                                                if (sel_i[0]) pw1[ 7:0] <= dat_i[ 7:0];
210
                                                if (sel_i[1]) pw1[11:8] <= dat_i[11:8];
211
                                        end
212
                        7'd10:  begin
213
                                                if (sel_i[0]) vt[1] <= dat_i[6:2];
214
                                                if (sel_i[1]) begin
215
                                                        outctrl[1] <= dat_i[8];
216
                                                        filt[1] <= dat_i[9];
217
                                                        gate[1] <= dat_i[12];
218
                                                        sync[1] <= dat_i[13];
219
                                                        ringmod[1] <= dat_i[14];
220
                                                        test[1] <= dat_i[15];
221
                                                end
222
                                        end
223
                        7'd11: ;
224
                        7'd12:  attack1 <= dat_i;
225
                        7'd13:  decay1 <= dat_i;
226
                        7'd14:  if (sel_i[0]) sustain1 <= dat_i;
227
                        7'd15:  relese1 <= dat_i;
228
 
229
                        7'd16:
230
                                        begin
231
                                                if (sel_i[0]) freq2[ 7:0] <= dat_i[ 7:0];
232
                                                if (sel_i[1]) freq2[15:8] <= dat_i[15:8];
233
                                        end
234
                        7'd17:
235
                                        begin
236
                                                if (sel_i[0]) pw2[ 7:0] <= dat_i[ 7:0];
237
                                                if (sel_i[1]) pw2[11:8] <= dat_i[11:8];
238
                                        end
239
                        7'd18:  begin
240
                                                if (sel_i[0]) vt[2] <= dat_i[6:2];
241
                                                if (sel_i[1]) begin
242
                                                        outctrl[2] <= dat_i[8];
243
                                                        filt[2] <= dat_i[9];
244
                                                        gate[2] <= dat_i[12];
245
                                                        sync[2] <= dat_i[5];
246
                                                        outctrl[0] <= dat_i[13];
247
                                                        ringmod[2] <= dat_i[14];
248
                                                        test[2] <= dat_i[15];
249
                                                end
250
                                        end
251
                        7'd19: ;
252
                        7'd20:  attack2 <= dat_i;
253
                        7'd21:  decay2 <= dat_i;
254
                        7'd22:  if (sel_i[0]) sustain2 <= dat_i;
255
                        7'd23:  relese2 <= dat_i;
256
 
257
                        7'd24:
258
                                        begin
259
                                                if (sel_i[0]) freq3[ 7:0] <= dat_i[ 7:0];
260
                                                if (sel_i[1]) freq3[15:8] <= dat_i[15:8];
261
                                        end
262
                        7'd25:
263
                                        begin
264
                                                if (sel_i[0]) pw3[ 7:0] <= dat_i[ 7:0];
265
                                                if (sel_i[1]) pw3[11:8] <= dat_i[11:8];
266
                                        end
267
                        7'd26:  begin
268
                                                if (sel_i[0]) vt[3] <= dat_i[6:2];
269
                                                if (sel_i[1]) begin
270
                                                        outctrl[3] <= dat_i[8];
271
                                                        filt[3] <= dat_i[9];
272
                                                        gate[3] <= dat_i[12];
273
                                                        sync[3] <= dat_i[13];
274
                                                        ringmod[3] <= dat_i[14];
275
                                                        test[3] <= dat_i[15];
276
                                                end
277
                                        end
278
                        7'd27: ;
279
                        7'd28:  attack3 <= dat_i;
280
                        7'd29:  decay3 <= dat_i;
281
                        7'd30:  if (sel_i[0]) sustain3 <= dat_i;
282
                        7'd31:  relese3 <= dat_i;
283
 
284
                        7'd64:  if (sel_i[0]) volume <= dat_i[3:0];
285
 
286
                        7'd68:  begin
287
                                                if (sel_i[1]) m_adr_o[15:14] <= dat_i[15:14];
288
                                        end
289
                        7'd69:
290
                                        begin
291
                                                if (sel_i[0]) m_adr_o[23:16] <= dat_i[ 7:0];
292
                                                if (sel_i[1]) m_adr_o[31:24] <= dat_i[15:8];
293
                                        end
294
                        7'd70:  begin
295
                                                if (sel_i[0]) m_adr_o[39:32] <= dat_i[ 7:0];
296
                                                if (sel_i[1]) m_adr_o[43:40] <= dat_i[11:8];
297
                                        end
298
                        default:        ;
299
                        endcase
300
                end
301
        end
302
end
303
 
304
 
305
always @(adr_i or acc3 or env3 or cs)
306
begin
307
        if (cs) begin
308
                case(adr_i[6:0])
309
                7'd65:  begin
310
                                vol_o <= 1'b1;
311
                                dat_o <= acc3[23:8];
312
                                end
313
                7'd66:  begin
314
                                vol_o <= 1'b1;
315
                                dat_o <= env3;
316
                                end
317
                default: begin
318
                                dat_o <= env3;
319
                                vol_o <= 1'b0;
320
                                end
321
                endcase
322
        end
323
        else begin
324
                dat_o <= 16'b0;
325
                vol_o <= 1'b0;
326
        end
327
end
328
 
329
wire [3:0] ibg1 = ibg & {4{bg}};
330
wire [11:0] alow;
331
 
332
// set wave table output address
333
always @(ibg1 or acc1 or acc0 or acc2 or acc3 or alow)
334
begin
335
        m_adr_o[13:12] <= {ibg1[2]|ibg1[3],ibg1[1]|ibg1[3]};
336
        m_adr_o[11:0] <= alow;
337
end
338
 
339
mux4to1 #(12) u11
340
(
341
        .e(1'b1),
342
        .s(m_adr_o[13:12]),
343
        .i0({acc0[23:13],1'b0}),
344
        .i1({acc1[23:13],1'b0}),
345
        .i2({acc2[23:13],1'b0}),
346
        .i3({acc3[23:13],1'b0}),
347
        .z(alow)
348
);
349
 
350
// This counter controls channel multiplexing and the base
351
// operating frequency.
352
wire [7:0] cnt;
353
counter #(8) u1
354
(
355
        .rst(rst_i),
356
        .clk(clk_i),
357
        .ce(1'b1),
358
        .ld(cnt!=pClkDivide),
359
        .d(8'd1),
360
        .q(cnt)
361
);
362
 
363
// channel select signal
364
wire [1:0] sel = cnt[1:0];
365
 
366
 
367
// bus arbitrator for wave table access
368
wire [2:0] bgn;
369
PSGBusArb u2
370
(
371
        .rst(rst_i),
372
        .clk(clk_i),
373
        .ce(1'b1),
374
        .ack(1'b1), .seln(bgn),
375
        .req0(ibr[0]), .req1(ibr[1]), .req2(ibr[2]), .req3(ibr[3]),
376
        .sel0(ibg[0]), .sel1(ibg[1]), .sel2(ibg[2]), .sel3(ibg[3]),
377
        .req4(1'b0), .req5(1'b0), .req6(1'b0), .req7(1'b0),
378
        .sel4(), .sel5(), .sel6(), .sel7()
379
);
380
 
381
// note generator - multi-channel
382
PSGNoteGen u3
383
(
384
        .rst(rst_i), .clk(clk_i),
385
        .cnt(cnt), .br(ibr), .bg(ibg1), .ack(my_ack), .bgn(bgn),
386
        .test(test),
387
        .vt0(vt[0]), .vt1(vt[1]), .vt2(vt[2]), .vt3(vt[3]),
388
        .freq0(freq0), .freq1(freq1), .freq2(freq2), .freq3(freq3),
389
        .pw0(pw0), .pw1(pw1), .pw2(pw2), .pw3(pw3),
390
        .acc0(acc0), .acc1(acc1), .acc2(acc2), .acc3(acc3),
391
        .wave(m_dat_i),
392
        .sync(sync),
393
        .ringmod(ringmod),
394
        .o(ngo)
395
);
396
 
397
// envelope generator - multi-channel
398
PSGEnvGen u4
399
(
400
        .rst(rst_i),
401
        .clk(clk_i),
402
        .cnt(cnt),
403
        .gate(gate),
404
        .attack0(attack0), .attack1(attack1), .attack2(attack2), .attack3(attack3),
405
        .decay0(decay0), .decay1(decay1), .decay2(decay2), .decay3(decay3),
406
        .sustain0(sustain0), .sustain1(sustain1), .sustain2(sustain2), .sustain3(sustain3),
407
        .relese0(relese0), .relese1(relese1), .relese2(relese2), .relese3(relese3),
408
        .o(env)
409
);
410
 
411
// shape output according to envelope
412
PSGShaper u5
413
(
414
        .clk_i(clk_i),
415
        .ce(1'b1),
416
        .tgi(ngo),
417
        .env(env),
418
        .o(out2)
419
);
420
 
421
// Sum the channels not going to the filter
422
PSGChannelSummer u6
423
(
424
        .clk_i(clk_i),
425
        .cnt(cnt),
426
        .outctrl(outctrl),
427
        .tmc_i(out2),
428
        .o(out1)
429
);
430
 
431
// Sum the channels going to the filter
432
PSGChannelSummer u7
433
(
434
        .clk_i(clk_i),
435
        .cnt(cnt),
436
        .outctrl(filt),
437
        .tmc_i(out2),
438
        .o(filtin1)
439
);
440
 
441
// The FIR filter
442
PSGFilter u8
443
(
444
        .rst(rst_i),
445
        .clk(clk_i),
446
        .cnt(cnt),
447
        .wr(we_i && stb_i && adr_i[6:4]==3'b101),
448
    .adr(adr_i[3:0]),
449
    .din({dat_i[15],dat_i[11:0]}),
450
    .i(filtin1[21:7]),
451
    .o(filt_o)
452
);
453
 
454
// Sum the filtered and unfiltered output
455
PSGOutputSummer u9
456
(
457
        .clk_i(clk_i),
458
        .cnt(cnt),
459
        .ufi(out1),
460
        .fi({filt_o,7'b0}),
461
        .o(out3)
462
);
463
 
464
// Last stage:
465
// Adjust output according to master volume
466
PSGMasterVolumeControl u10
467
(
468
        .rst_i(rst_i),
469
        .clk_i(clk_i),
470
        .i(out3[21:6]),
471
        .volume(volume),
472
        .o(out4)
473
);
474
 
475
assign o = out4[19:8];
476
 
477
endmodule
478
 

powered by: WebSVN 2.1.0

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