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

Subversion Repositories psg16

[/] [psg16/] [trunk/] [rtl/] [verilog/] [PSG16.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
`timescale 1ns / 1ps
2
//=============================================================================
3
//      (C) 2007,2010,2012  Robert Finch
4
//      robfinch<remove>@opencores.org
5
//
6
//      PSG16.v 
7
//              4 Channel ADSR sound generator
8
//
9
// This source file is free software: you can redistribute it and/or modify 
10
// it under the terms of the GNU Lesser General Public License as published 
11
// by the Free Software Foundation, either version 3 of the License, or     
12
// (at your option) any later version.                                      
13
//                                                                          
14
// This source file is distributed in the hope that it will be useful,      
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
17
// GNU General Public License for more details.                             
18
//                                                                          
19
// You should have received a copy of the GNU General Public License        
20
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
21
//
22
//
23
//      Registers
24
//      0            ffffffff ffffffff   freq [15:0]
25
//      1           ----pppp pppppppp   pulse width [11:0]
26
//      2           trsg--fo -vvvvv--   test, ringmod, sync, gate, filter, output, voice type
27
//                                                                                      vvvvv
28
//                                                                                      wnpst
29
//      3           ssssrrrr aaaadddd   sustain,release,attack,decay
30
//
31
//      ...
32
//      64      -------- ----vvvv   volume (0-15)
33
//      65      nnnnnnnn nnnnnnnn   osc3 oscillator 3
34
//      66      -------- nnnnnnnn   env3 envelope 3
35
//      67
36
//      68      aa------ --------   wave table address a15-14
37
//      69      aaaaaaaa aaaaaaaa   wave table address a31-16
38
//
39
//  80-87   s---kkkk kkkkkkkk   filter coefficients
40
//  88-96   -------- --------   reserved for more filter coefficients
41
//
42
//
43
//      Spartan3
44
//      Webpack 12.3  xc3s1200e-4fg320
45
//      1290 LUTs / 893 slices / 69.339 MHz
46
//      1 Multipliers
47
//=============================================================================
48
 
49
module PSG16(rst_i, clk_i, cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o,
50
        vol_o, bg,
51
        m_cyc_o, m_stb_o, m_ack_i, m_we_o, m_sel_o, m_adr_o, m_dat_i, o
52
);
53
parameter pClkDivide = 66;
54
 
55
// WISHBONE SYSCON
56
input rst_i;
57
input clk_i;                    // system clock
58
// WISHBONE SLAVE
59
input cyc_i;                    // cycle valid
60
input stb_i;                    // circuit select
61
output ack_o;
62
input we_i;                             // write
63
input  [1:0] sel_i;              // byte selects
64
input [63:0] adr_i;              // address input
65
input [15:0] dat_i;              // data input
66
output [15:0] dat_o;     // data output
67
// WISHBONE MASTER
68
output m_cyc_o;                 // bus request
69
output m_stb_o;                 // strobe output
70
input m_ack_i;
71
output m_we_o;                  // write enable (always inactive)
72
output [ 1:0] m_sel_o;   // byte lane selects
73
output [63:0] m_adr_o;   // wave table address
74
input  [11:0] m_dat_i;   // wave table data input
75
 
76
output vol_o;
77
 
78
input bg;                               // bus grant
79
 
80
output [17:0] o;
81
 
82
// I/O registers
83
reg [15:0] dat_o;
84
reg vol_o;
85
reg [43:0] m_adr_o;
86
 
87
reg [3:0] test;                          // test (enable note generator)
88
reg [4:0] vt [3:0];                       // voice type
89
reg [15:0] freq0, freq1, freq2, freq3;   // frequency control
90
reg [11:0] pw0, pw1, pw2, pw3;                   // pulse width control
91
reg [3:0] gate;
92
reg [3:0] attack0, attack1, attack2, attack3;
93
reg [3:0] decay0, decay1, decay2, decay3;
94
reg [3:0] sustain0, sustain1, sustain2, sustain3;
95
reg [3:0] relese0, relese1, relese2, relese3;
96
reg [3:0] sync;
97
reg [3:0] ringmod;
98
reg [3:0] outctrl;
99
reg [3:0] filt;                // 1 = output goes to filter
100
wire [23:0] acc0, acc1, acc2, acc3;
101
reg [3:0] volume;        // master volume
102
wire [11:0] ngo; // not generator output
103
wire [7:0] env;          // envelope generator output
104
wire [7:0] env3;
105
wire [7:0] ibr;
106
wire [7:0] ibg;
107
wire [21:0] out1;
108
reg [21:0] out1a;
109
wire [19:0] out2;
110
wire [21:0] out3;
111
wire [19:0] out4;
112
wire [21:0] filtin1;     // FIR filter input
113
wire [14:0] filt_o;              // FIR filter output
114
 
115
wire cs = cyc_i && stb_i && (adr_i[63:8]==56'hFFFF_FFFF_FFD5_00);
116
assign m_cyc_o = |ibg & !m_ack_i;
117
assign m_stb_o = m_cyc_o;
118
assign m_we_o  = 1'b0;
119
assign m_sel_o = {m_cyc_o,m_cyc_o};
120
reg ack1;
121
always @(posedge clk_i)
122
        ack1 <= cs & !ack1;
123
assign ack_o = cs ? (we_i ? 1'b1 : ack1) : 1'b0;
124
wire my_ack = m_ack_i;
125
 
126
// write to registers
127
always @(posedge clk_i)
128
begin
129
        if (rst_i) begin
130
                freq0 <= 0;
131
                freq1 <= 0;
132
                freq2 <= 0;
133
                freq3 <= 0;
134
                pw0 <= 0;
135
                pw1 <= 0;
136
                pw2 <= 0;
137
                pw3 <= 0;
138
                test <= 0;
139
                vt[0] <= 0;
140
                vt[1] <= 0;
141
                vt[2] <= 0;
142
                vt[3] <= 0;
143
                gate <= 0;
144
                outctrl <= 0;
145
                filt <= 0;
146
                attack0 <= 0;
147
                attack1 <= 0;
148
                attack2 <= 0;
149
                attack3 <= 0;
150
                decay0 <= 0;
151
                sustain0 <= 0;
152
                relese0 <= 0;
153
                decay1 <= 0;
154
                sustain1 <= 0;
155
                relese1 <= 0;
156
                decay2 <= 0;
157
                sustain2 <= 0;
158
                relese2 <= 0;
159
                decay3 <= 0;
160
                sustain3 <= 0;
161
                relese3 <= 0;
162
                sync <= 0;
163
                ringmod <= 0;
164
                volume <= 0;
165
                m_adr_o[47:14] <= 34'b00000000_00000000_0000_0000_0000_0011_10; // 00038000
166
        end
167
        else begin
168
                if (cs & we_i) begin
169
                        case(adr_i[7:1])
170
                        //---------------------------------------------------------
171
                        7'd0:
172
                                        begin
173
                                                if (sel_i[0]) freq0[ 7:0] <= dat_i[ 7:0];
174
                                                if (sel_i[1]) freq0[15:8] <= dat_i[15:8];
175
                                        end
176
                        7'd1:
177
                                        begin
178
                                                if (sel_i[0]) pw0[ 7:0] <= dat_i[ 7:0];
179
                                                if (sel_i[1]) pw0[11:8] <= dat_i[11:8];
180
                                        end
181
                        7'd2:   begin
182
                                                if (sel_i[0]) vt[0] <= dat_i[6:2];
183
                                                if (sel_i[1]) begin
184
                                                        outctrl[0] <= dat_i[8];
185
                                                        filt[0] <= dat_i[9];
186
                                                        gate[0] <= dat_i[12];
187
                                                        sync[0] <= dat_i[13];
188
                                                        ringmod[0] <= dat_i[14];
189
                                                        test[0] <= dat_i[15];
190
                                                end
191
                                        end
192
                        7'd3:   begin
193
                                        if (sel_i[0]) attack0 <= dat_i[7:4];
194
                                        if (sel_i[0]) decay0 <= dat_i[3:0];
195
                                        if (sel_i[1]) relese0 <= dat_i[11:8];
196
                                        if (sel_i[1]) sustain0 <= dat_i[15:12];
197
                                        end
198
 
199
                        //---------------------------------------------------------
200
                        7'd4:
201
                                        begin
202
                                                if (sel_i[0]) freq1[ 7:0] <= dat_i[ 7:0];
203
                                                if (sel_i[1]) freq1[15:8] <= dat_i[15:8];
204
                                        end
205
                        7'd5:
206
                                        begin
207
                                                if (sel_i[0]) pw1[ 7:0] <= dat_i[ 7:0];
208
                                                if (sel_i[1]) pw1[11:8] <= dat_i[11:8];
209
                                        end
210
                        7'd6:   begin
211
                                                if (sel_i[0]) vt[1] <= dat_i[6:2];
212
                                                if (sel_i[1]) begin
213
                                                        outctrl[1] <= dat_i[8];
214
                                                        filt[1] <= dat_i[9];
215
                                                        gate[1] <= dat_i[12];
216
                                                        sync[1] <= dat_i[13];
217
                                                        ringmod[1] <= dat_i[14];
218
                                                        test[1] <= dat_i[15];
219
                                                end
220
                                        end
221
                        7'd7:   begin
222
                                        if (sel_i[0]) attack1 <= dat_i[7:4];
223
                                        if (sel_i[0]) decay1 <= dat_i[3:0];
224
                                        if (sel_i[1]) relese1 <= dat_i[11:8];
225
                                        if (sel_i[1]) sustain1 <= dat_i[15:12];
226
                                        end
227
 
228
                        //---------------------------------------------------------
229
                        7'd8:
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'd9:
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'd10:  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'd11:  begin
252
                                        if (sel_i[0]) attack2 <= dat_i[7:4];
253
                                        if (sel_i[0]) decay2 <= dat_i[3:0];
254
                                        if (sel_i[1]) relese2 <= dat_i[11:8];
255
                                        if (sel_i[1]) sustain2 <= dat_i[15:12];
256
                                        end
257
 
258
                        //---------------------------------------------------------
259
                        7'd12:
260
                                        begin
261
                                                if (sel_i[0]) freq3[ 7:0] <= dat_i[ 7:0];
262
                                                if (sel_i[1]) freq3[15:8] <= dat_i[15:8];
263
                                        end
264
                        7'd13:
265
                                        begin
266
                                                if (sel_i[0]) pw3[ 7:0] <= dat_i[ 7:0];
267
                                                if (sel_i[1]) pw3[11:8] <= dat_i[11:8];
268
                                        end
269
                        7'd14:  begin
270
                                                if (sel_i[0]) vt[3] <= dat_i[6:2];
271
                                                if (sel_i[1]) begin
272
                                                        outctrl[3] <= dat_i[8];
273
                                                        filt[3] <= dat_i[9];
274
                                                        gate[3] <= dat_i[12];
275
                                                        sync[3] <= dat_i[13];
276
                                                        ringmod[3] <= dat_i[14];
277
                                                        test[3] <= dat_i[15];
278
                                                end
279
                                        end
280
                        7'd15:  begin
281
                                        if (sel_i[0]) attack3 <= dat_i[7:4];
282
                                        if (sel_i[0]) decay3 <= dat_i[3:0];
283
                                        if (sel_i[1]) relese3 <= dat_i[11:8];
284
                                        if (sel_i[1]) sustain3 <= dat_i[15:12];
285
                                        end
286
 
287
                        //---------------------------------------------------------
288
                        7'd64:  if (sel_i[0]) volume <= dat_i[3:0];
289
 
290
                        7'd68:  begin
291
                                                if (sel_i[1]) m_adr_o[15:14] <= dat_i[15:14];
292
                                        end
293
                        7'd69:
294
                                        begin
295
                                                if (sel_i[0]) m_adr_o[23:16] <= dat_i[ 7:0];
296
                                                if (sel_i[1]) m_adr_o[31:24] <= dat_i[15:8];
297
                                        end
298
                        7'd70:  begin
299
                                                if (sel_i[0]) m_adr_o[39:32] <= dat_i[ 7:0];
300
                                                if (sel_i[1]) m_adr_o[47:40] <= dat_i[15:8];
301
                                        end
302
                        default:        ;
303
                        endcase
304
                end
305
        end
306
end
307
 
308
 
309
always @(posedge clk_i)
310
        if (cs) begin
311
                case(adr_i[6:0])
312
                7'd65:  begin
313
                                vol_o <= 1'b1;
314
                                dat_o <= acc3[23:8];
315
                                end
316
                7'd66:  begin
317
                                vol_o <= 1'b1;
318
                                dat_o <= env3;
319
                                end
320
                default: begin
321
                                dat_o <= env3;
322
                                vol_o <= 1'b0;
323
                                end
324
                endcase
325
        end
326
        else begin
327
                dat_o <= 16'b0;
328
                vol_o <= 1'b0;
329
        end
330
 
331
wire [11:0] alow;
332
 
333
// set wave table output address
334
always @(ibg or acc1 or acc0 or acc2 or acc3 or alow)
335
begin
336
        m_adr_o[13:12] <= {ibg[2]|ibg[3],ibg[1]|ibg[3]};
337
        m_adr_o[11:0] <= alow;
338
end
339
 
340
mux4to1 #(12) u11
341
(
342
        .e(1'b1),
343
        .s(m_adr_o[13:12]),
344
        .i0({acc0[23:13],1'b0}),
345
        .i1({acc1[23:13],1'b0}),
346
        .i2({acc2[23:13],1'b0}),
347
        .i3({acc3[23:13],1'b0}),
348
        .z(alow)
349
);
350
 
351
// This counter controls channel multiplexing and the base
352
// operating frequency.
353
wire [7:0] cnt;
354
reg [7:0] cnt1,cnt2,cnt3;
355
counter #(8) u1
356
(
357
        .rst(rst_i),
358
        .clk(clk_i),
359
        .ce(1'b1),
360
        .ld(cnt==pClkDivide-1),
361
        .d(8'd0),
362
        .q(cnt)
363
);
364
 
365
// channel select signal
366
wire [1:0] sel = cnt[1:0];
367
 
368
 
369
// bus arbitrator for wave table access
370
wire [2:0] bgn;
371
PSGBusArb u2
372
(
373
        .rst(rst_i),
374
        .clk(clk_i),
375
        .ce(1'b1),
376
        .ack(1'b1),
377
        .seln(bgn),
378
        .req0(ibr[0]),
379
        .req1(ibr[1]),
380
        .req2(ibr[2]),
381
        .req3(ibr[3]),
382
        .req4(1'b0),
383
        .req5(1'b0),
384
        .req6(1'b0),
385
        .req7(1'b0),
386
        .sel0(ibg[0]),
387
        .sel1(ibg[1]),
388
        .sel2(ibg[2]),
389
        .sel3(ibg[3]),
390
        .sel4(),
391
        .sel5(),
392
        .sel6(),
393
        .sel7()
394
);
395
 
396
// note generator - multi-channel
397
PSGNoteGen u3
398
(
399
        .rst(rst_i),
400
        .clk(clk_i),
401
        .cnt(cnt),
402
        .br(ibr),
403
        .bg(ibg),
404
        .ack(m_ack_i),
405
        .bgn(bgn),
406
        .test(test),
407
        .vt0(vt[0]),
408
        .vt1(vt[1]),
409
        .vt2(vt[2]),
410
        .vt3(vt[3]),
411
        .freq0(freq0),
412
        .freq1(freq1),
413
        .freq2(freq2),
414
        .freq3(freq3),
415
        .pw0(pw0),
416
        .pw1(pw1),
417
        .pw2(pw2),
418
        .pw3(pw3),
419
        .acc0(acc0),
420
        .acc1(acc1),
421
        .acc2(acc2),
422
        .acc3(acc3),
423
        .wave(m_dat_i),
424
        .sync(sync),
425
        .ringmod(ringmod),
426
        .o(ngo)
427
);
428
 
429
// envelope generator - multi-channel
430
PSGEnvGen u4
431
(
432
        .rst(rst_i),
433
        .clk(clk_i),
434
        .cnt(cnt),
435
        .gate(gate),
436
        .attack0(attack0),
437
        .attack1(attack1),
438
        .attack2(attack2),
439
        .attack3(attack3),
440
        .decay0(decay0),
441
        .decay1(decay1),
442
        .decay2(decay2),
443
        .decay3(decay3),
444
        .sustain0(sustain0),
445
        .sustain1(sustain1),
446
        .sustain2(sustain2),
447
        .sustain3(sustain3),
448
        .relese0(relese0),
449
        .relese1(relese1),
450
        .relese2(relese2),
451
        .relese3(relese3),
452
        .o(env)
453
);
454
 
455
// shape output according to envelope
456
PSGShaper u5
457
(
458
        .clk_i(clk_i),
459
        .ce(1'b1),
460
        .tgi(ngo),
461
        .env(env),
462
        .o(out2)
463
);
464
 
465
always @(posedge clk_i)
466
        cnt1 <= cnt;
467
always @(posedge clk_i)
468
        cnt2 <= cnt1;
469
always @(posedge clk_i)
470
        cnt3 <= cnt2;
471
 
472
// Sum the channels not going to the filter
473
PSGChannelSummer u6
474
(
475
        .clk_i(clk_i),
476
        .cnt(cnt1),
477
        .outctrl(outctrl),
478
        .tmc_i(out2),
479
        .o(out1)
480
);
481
 
482
always @(posedge clk_i)
483
        out1a <= out1;
484
 
485
// Sum the channels going to the filter
486
PSGChannelSummer u7
487
(
488
        .clk_i(clk_i),
489
        .cnt(cnt1),
490
        .outctrl(filt),
491
        .tmc_i(out2),
492
        .o(filtin1)
493
);
494
 
495
// The FIR filter
496
PSGFilter u8
497
(
498
        .rst(rst_i),
499
        .clk(clk_i),
500
        .cnt(cnt2),
501
        .wr(we_i && stb_i && adr_i[6:4]==3'b101),
502
    .adr(adr_i[3:0]),
503
    .din({dat_i[15],dat_i[11:0]}),
504
    .i(filtin1[21:7]),
505
    .o(filt_o)
506
);
507
 
508
// Sum the filtered and unfiltered output
509
PSGOutputSummer u9
510
(
511
        .clk_i(clk_i),
512
        .cnt(cnt3),
513
        .ufi(out1a),
514
        .fi({filt_o,7'b0}),
515
        .o(out3)
516
);
517
 
518
// Last stage:
519
// Adjust output according to master volume
520
PSGMasterVolumeControl u10
521
(
522
        .rst_i(rst_i),
523
        .clk_i(clk_i),
524
        .i(out3[21:6]),
525
        .volume(volume),
526
        .o(out4)
527
);
528
 
529
assign o = out4[19:2];
530
 
531
endmodule
532
 

powered by: WebSVN 2.1.0

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