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

Subversion Repositories psg16

[/] [psg16/] [trunk/] [rtl/] [verilog/] [PSG32.v] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4
//   \\__/ o\    (C) 2007-2017  Robert Finch, Waterloo
5
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch<remove>@finitron.ca
7
//       ||
8
//
9
// PSG32.v
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
//
25
//      Registers
26
//  00      -------- ffffffff ffffffff ffffffff     freq [23:0]
27
//  04      -------- -------- pppppppp pppppppp     pulse width
28 5 robfinch
//      08          -------- -------- trsg-efo vvvvvv--         test, ringmod, sync, gate, filter, output, voice type
29
//  0C      -------- aaaaaaaa aaaaaaaa aaaaaaaa     attack
30
//  10      -------- dddddddd dddddddd dddddddd     decay
31
//  14      -------- -------- -------- ssssssss     sustain
32
//  18      -------- rrrrrrrr rrrrrrrr rrrrrrrr     release
33
//  1C      -------- -------- --aaaaaa aaaaaaa-     wave table base address
34 4 robfinch
//                                                                                      vvvvv
35
//                                                                                      wnpst
36 5 robfinch
//  20-3C   Voice #2
37
//  40-5C   Voice #3
38
//  60-7C   Voice #4
39 4 robfinch
//
40
//      ...
41 5 robfinch
//      B0      -------- -------- -------- ----vvvv   volume (0-255)
42 4 robfinch
//      B4      nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn   osc3 oscillator 3
43
//      B8      -------- -------- -------- nnnnnnnn   env3 envelope 3
44 5 robfinch
//  BC      -------- -------- -sss-sss -sss-sss   env state
45 4 robfinch
//
46
//  C0-DC   -------- -------- s---kkkk kkkkkkkk   filter coefficients
47
//  E0-FC   -------- -------- -------- --------   reserved for more filter coefficients
48
//
49
//=============================================================================
50
 
51
module PSG32(rst_i, clk_i, cs_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i, dat_o,
52
        m_adr_o, m_dat_i, o
53
);
54
parameter pClkDivide = 37;
55
 
56
// WISHBONE SYSCON
57
input rst_i;
58
input clk_i;                    // system clock
59
// NON-WISHBONE
60
input cs_i;             // circuit select
61
// WISHBONE SLAVE
62
input cyc_i;                    // cycle valid
63
input stb_i;                    // circuit select
64
output ack_o;
65
input we_i;                             // write
66
input [7:0] adr_i;               // address input
67
input [31:0] dat_i;              // data input
68
output [31:0] dat_o;     // data output
69
 
70
// WISHBONE MASTER
71
output [13:0] m_adr_o;   // wave table address
72
input  [11:0] m_dat_i;   // wave table data input
73
 
74
output [17:0] o;
75
 
76
// I/O registers
77
reg [31:0] dat_o;
78
reg [13:0] m_adr_o;
79
 
80
reg [3:0] test;                          // test (enable note generator)
81 5 robfinch
reg [5:0] vt [3:0];                       // voice type
82 4 robfinch
reg [23:0] freq0, freq1, freq2, freq3;   // frequency control
83
reg [15:0] pw0, pw1, pw2, pw3;                   // pulse width control
84
reg [3:0] gate;
85 5 robfinch
reg [23:0] attack0, attack1, attack2, attack3;
86
reg [23:0] decay0, decay1, decay2, decay3;
87 4 robfinch
reg [7:0] sustain0, sustain1, sustain2, sustain3;
88 5 robfinch
reg [23:0] relese0, relese1, relese2, relese3;
89 4 robfinch
reg [13:0] wtadr0, wtadr1, wtadr2, wtadr3;
90
reg [3:0] sync;
91
reg [3:0] ringmod;
92
reg [3:0] outctrl;
93 5 robfinch
reg [3:0] filt;                 // 1 = output goes to filter
94
reg [3:0] eg;                   // 1 = output goes through envelope generator
95 4 robfinch
wire [31:0] acc0, acc1, acc2, acc3;
96 5 robfinch
reg [3:0] volume;        // master volume
97 4 robfinch
wire [11:0] tg1_o,tg2_o,tg3_o,tg4_o;    // tone generator output
98
wire [7:0] env;          // envelope generator output
99 5 robfinch
wire [7:0] env0, env1, env2, env3;
100 4 robfinch
wire [19:0] out0,out1,out2,out3;
101
wire [2:0] es0,es1,es2,es3;
102
wire [29:0] out4;
103
reg [21:0] sum,fsum;
104
reg [21:0] sum2;
105
wire [21:0] filtin1;     // FIR filter input
106
wire [37:0] filt_o;              // FIR filter output
107
reg [1:0] cnt;
108
reg [1:0] cnt1,cnt2,cnt3;
109
 
110
// channel select signal
111
wire [1:0] sel = cnt[1:0];
112
 
113
and(cs, cyc_i, stb_i, cs_i);
114
reg ack1,ack2;
115
always @(posedge clk_i)
116
        ack1 <= cs;
117
always @(posedge clk_i)
118
    ack2 <= ack1 & cs;
119
assign ack_o = cs ? (we_i ? 1'b1 : ack2) : 1'b0;
120
 
121
// Register shadow ram for register readback
122
reg [15:0] reg_shadow [63:0];
123
reg [8:0] radr;
124
always @(posedge clk_i)
125
    if (cs & we_i)  reg_shadow[adr_i[7:2]] <= dat_i[15:0];
126
always @(posedge clk_i)
127
    radr <= adr_i[7:2];
128
wire [15:0] reg_shadow_o = reg_shadow[radr];
129
 
130
// write to registers
131
always @(posedge clk_i)
132
begin
133
        if (rst_i) begin
134
                freq0 <= 0;
135
                freq1 <= 0;
136
                freq2 <= 0;
137
                freq3 <= 0;
138
                pw0 <= 0;
139
                pw1 <= 0;
140
                pw2 <= 0;
141
                pw3 <= 0;
142
                test <= 0;
143
                vt[0] <= 0;
144
                vt[1] <= 0;
145
                vt[2] <= 0;
146
                vt[3] <= 0;
147
                gate <= 0;
148
                outctrl <= 0;
149
                filt <= 0;
150
                attack0 <= 0;
151
                attack1 <= 0;
152
                attack2 <= 0;
153
                attack3 <= 0;
154
                decay0 <= 0;
155
                sustain0 <= 0;
156
                relese0 <= 0;
157
                decay1 <= 0;
158
                sustain1 <= 0;
159
                relese1 <= 0;
160
                decay2 <= 0;
161
                sustain2 <= 0;
162
                relese2 <= 0;
163
                decay3 <= 0;
164
                sustain3 <= 0;
165
                relese3 <= 0;
166
                sync <= 0;
167
                ringmod <= 0;
168
                volume <= 0;
169
        end
170
        else begin
171
                if (cs & we_i) begin
172
                        case(adr_i[7:2])
173
                        //---------------------------------------------------------
174
                        6'd00:  freq0 <= dat_i[23:0];
175
                        6'd01:  pw0 <= dat_i[15:0];
176
                        6'd02:  begin
177 5 robfinch
                                                vt[0] <= dat_i[7:2];
178 4 robfinch
                                                outctrl[0] <= dat_i[8];
179
                                                filt[0] <= dat_i[9];
180 5 robfinch
                                                eg[0] <= dat_i[10];
181 4 robfinch
                                                gate[0] <= dat_i[12];
182
                                                sync[0] <= dat_i[13];
183
                                                ringmod[0] <= dat_i[14];
184
                                                test[0] <= dat_i[15];
185
                                        end
186 5 robfinch
                        6'd03:  attack0 <= dat_i[23:0];
187
                        6'd04:  decay0 <= dat_i[23:0];
188
                    6'd05:  sustain0 <= dat_i[7:0];
189
                        6'd06:  relese0 <= dat_i[23:0];
190
            6'd07:  wtadr0 <= {dat_i[13:1],1'b0};
191 4 robfinch
 
192
                        //---------------------------------------------------------
193 5 robfinch
                        6'd08:  freq1 <= dat_i[23:0];
194
                        6'd09:  pw1 <= dat_i[15:0];
195
                        6'd10:  begin
196
                                                vt[1] <= dat_i[7:2];
197 4 robfinch
                                                outctrl[1] <= dat_i[8];
198
                                                filt[1] <= dat_i[9];
199 5 robfinch
                                                eg[1] <= dat_i[10];
200 4 robfinch
                                                gate[1] <= dat_i[12];
201
                                                sync[1] <= dat_i[13];
202
                                                ringmod[1] <= dat_i[14];
203
                                                test[1] <= dat_i[15];
204
                                        end
205 5 robfinch
                        6'd11:  attack1 <= dat_i[23:0];
206
            6'd12:  decay1 <= dat_i[23:0];
207
            6'd13:  sustain1 <= dat_i[7:0];
208
            6'd14:  relese1 <= dat_i[23:0];
209
            6'd15:  wtadr1 <= {dat_i[13:1],1'b0};
210 4 robfinch
 
211
                        //---------------------------------------------------------
212 5 robfinch
                        6'd16:  freq2 <= dat_i[23:0];
213
                        6'd17:  pw2 <= dat_i[15:0];
214
                        6'd18:  begin
215
                                                vt[2] <= dat_i[7:2];
216 4 robfinch
                                                outctrl[2] <= dat_i[8];
217
                                                filt[2] <= dat_i[9];
218 5 robfinch
                                                eg[2] <= dat_i[10];
219 4 robfinch
                                                gate[2] <= dat_i[12];
220
                                                sync[2] <= dat_i[5];
221
                                                outctrl[0] <= dat_i[13];
222
                                                ringmod[2] <= dat_i[14];
223
                                                test[2] <= dat_i[15];
224
                                        end
225 5 robfinch
                        6'd19:  attack2 <= dat_i[23:0];
226
            6'd20:  decay2 <= dat_i[23:0];
227
            6'd21:  sustain2 <= dat_i[7:0];
228
            6'd22:  relese2 <= dat_i[23:0];
229
            6'd23:  wtadr2 <= {dat_i[13:1],1'b0};
230 4 robfinch
 
231
                        //---------------------------------------------------------
232 5 robfinch
                        6'd24:  freq3 <= dat_i[23:0];
233
                        6'd25:  pw3 <= dat_i[15:0];
234
                        6'd26:  begin
235
                                                vt[3] <= dat_i[7:2];
236 4 robfinch
                                                outctrl[3] <= dat_i[8];
237
                                                filt[3] <= dat_i[9];
238 5 robfinch
                                                eg[3] <= dat_i[10];
239 4 robfinch
                                                gate[3] <= dat_i[12];
240
                                                sync[3] <= dat_i[13];
241
                                                ringmod[3] <= dat_i[14];
242
                                                test[3] <= dat_i[15];
243
                                        end
244 5 robfinch
                        6'd27:  attack3 <= dat_i[23:0];
245
            6'd28:  decay3 <= dat_i[23:0];
246
            6'd29:  sustain3 <= dat_i[7:0];
247
            6'd30:  relese3 <= dat_i[23:0];
248
            6'd31:  wtadr3 <= {dat_i[13:1],1'b0};
249 4 robfinch
 
250
                        //---------------------------------------------------------
251 5 robfinch
                        6'd44:  volume <= dat_i[3:0];
252 4 robfinch
 
253
                        default:        ;
254
                        endcase
255
                end
256
        end
257
end
258
 
259
 
260
always @(posedge clk_i)
261
    case(adr_i[7:2])
262
    6'd45:      begin
263
            dat_o <= acc3;
264
            end
265 5 robfinch
    6'd46:      begin
266 4 robfinch
            dat_o <= {24'h0,env3};
267
            end
268 5 robfinch
    6'd47:  dat_o <= {17'h0,es3,1'b0,es2,1'b0,es1,1'b0,es0};
269 4 robfinch
    default: begin
270
            dat_o <= reg_shadow_o;
271
            end
272
    endcase
273
 
274
wire [13:0] madr;
275
mux4to1 #(12) u11
276
(
277
        .e(1'b1),
278
        .s(cnt),
279
        .i0(wtadr0 + {acc0[27:17],1'b0}),
280
        .i1(wtadr1 + {acc1[27:17],1'b0}),
281
        .i2(wtadr2 + {acc2[27:17],1'b0}),
282
        .i3(wtadr3 + {acc3[27:17],1'b0}),
283
        .z(madr)
284
);
285
always @(posedge clk_i)
286
    m_adr_o <= madr;
287 5 robfinch
wire [11:0] wave_i = m_dat_i;
288 4 robfinch
 
289
// This counter controls channel multiplexing for the wave table
290
always @(posedge clk_i)
291
if (rst_i)
292
    cnt <= 2'd0;
293
else
294
    cnt <= cnt + 2'd1;
295
 
296
// note generator - multi-channel
297
PSGToneGenerator u1a
298
(
299
    .rst(rst_i),
300
    .clk(clk_i),
301
    .ack(cnt==2'b11),
302
    .test(test[0]),
303
    .vt(vt[0]),
304
    .freq(freq0),
305
    .pw(pw0),
306
    .acc(acc0),
307
    .prev_acc(acc3),
308
    .wave(wave_i),
309
    .sync(sync[0]),
310
    .ringmod(ringmod[0]),
311
    .o(tg1_o)
312
);
313
 
314
PSGToneGenerator u1b
315
(
316
    .rst(rst_i),
317
    .clk(clk_i),
318
    .ack(cnt==2'b00),
319
    .test(test[1]),
320
    .vt(vt[1]),
321
    .freq(freq1),
322
    .pw(pw1),
323
    .acc(acc1),
324
    .prev_acc(acc0),
325
    .wave(wave_i),
326
    .sync(sync[1]),
327
    .ringmod(ringmod[1]),
328
    .o(tg2_o)
329
);
330
 
331
PSGToneGenerator u1c
332
(
333
    .rst(rst_i),
334
    .clk(clk_i),
335
    .ack(cnt==2'b01),
336
    .test(test[2]),
337
    .vt(vt[2]),
338
    .freq(freq2),
339
    .pw(pw2),
340
    .acc(acc2),
341
    .prev_acc(acc1),
342
    .wave(wave_i),
343
    .sync(sync[2]),
344
    .ringmod(ringmod[2]),
345
    .o(tg3_o)
346
);
347
 
348
PSGToneGenerator u1d
349
(
350
    .rst(rst_i),
351
    .clk(clk_i),
352
    .ack(cnt==2'b10),
353
    .test(test[3]),
354
    .vt(vt[3]),
355
    .freq(freq3),
356
    .pw(pw3),
357
    .acc(acc3),
358
    .prev_acc(acc2),
359
    .wave(wave_i),
360
    .sync(sync[3]),
361
    .ringmod(ringmod[3]),
362
    .o(tg4_o)
363
);
364
 
365
PSGEnvelopeGenerator u2a
366
(
367
    .rst(rst_i),
368
    .clk(clk_i),
369
    .gate(gate[0]),
370
    .attack(attack0),
371
    .decay(decay0),
372
    .sustain(sustain0),
373
    .relese(relese0),
374
    .o(env0),
375
    .envState(es0)
376
);
377
 
378
PSGEnvelopeGenerator u2b
379
(
380
    .rst(rst_i),
381
    .clk(clk_i),
382
    .gate(gate[1]),
383
    .attack(attack1),
384
    .decay(decay1),
385
    .sustain(sustain1),
386
    .relese(relese1),
387
    .o(env1),
388
    .envState(es1)
389
);
390
 
391
PSGEnvelopeGenerator u2c
392
(
393
    .rst(rst_i),
394
    .clk(clk_i),
395
    .gate(gate[2]),
396
    .attack(attack2),
397
    .decay(decay2),
398
    .sustain(sustain2),
399
    .relese(relese2),
400
    .o(env2),
401
    .envState(es2)
402
);
403
 
404
PSGEnvelopeGenerator u2d
405
(
406
    .rst(rst_i),
407
    .clk(clk_i),
408
    .gate(gate[3]),
409
    .attack(attack3),
410
    .decay(decay3),
411
    .sustain(sustain3),
412
    .relese(relese3),
413
    .o(env3),
414
    .envState(es3)
415
);
416
 
417
// shape output according to envelope
418
PSGShaper u5a
419
(
420
        .clk_i(clk_i),
421
        .ce(1'b1),
422
        .tgi(tg1_o),
423 5 robfinch
        .env(eg[0] ? env0 : 8'hFF),
424 4 robfinch
        .o(out0)
425
);
426
 
427
PSGShaper u5b
428
(
429
        .clk_i(clk_i),
430
        .ce(1'b1),
431
        .tgi(tg2_o),
432 5 robfinch
        .env(eg[1] ? env1 : 8'hFF),
433 4 robfinch
        .o(out1)
434
);
435
 
436
PSGShaper u5c
437
(
438
        .clk_i(clk_i),
439
        .ce(1'b1),
440
        .tgi(tg3_o),
441 5 robfinch
        .env(eg[2] ? env2 : 8'hFF),
442 4 robfinch
        .o(out2)
443
);
444
 
445
PSGShaper u5d
446
(
447
        .clk_i(clk_i),
448
        .ce(1'b1),
449
        .tgi(tg4_o),
450 5 robfinch
        .env(eg[3] ? env3 : 8'hFF),
451 4 robfinch
        .o(out3)
452
);
453
 
454
always @(posedge clk_i)
455
        cnt1 <= cnt;
456
always @(posedge clk_i)
457
        cnt2 <= cnt1;
458
always @(posedge clk_i)
459
        cnt3 <= cnt2;
460
 
461
// Sum the channels not going to the filter
462
always @(posedge clk_i)
463
sum <=
464
    {2'd0,(out0 & {20{outctrl[0]}})} +
465
    {2'd0,(out1 & {20{outctrl[1]}})} +
466
    {2'd0,(out2 & {20{outctrl[2]}})} +
467
    {2'd0,(out3 & {20{outctrl[3]}})};
468
 
469
// Sum the channels going to the filter
470
always @(posedge clk_i)
471
fsum <=
472
    {2'd0,(out0 & {20{filt[0]}})} +
473
    {2'd0,(out1 & {20{filt[1]}})} +
474
    {2'd0,(out2 & {20{filt[2]}})} +
475
    {2'd0,(out3 & {20{filt[3]}})};
476
 
477
// The FIR filter
478
PSGFilter2 u8
479
(
480
        .rst(rst_i),
481
        .clk(clk_i),
482
        .cnt(cnt2),
483
        .wr(we_i && stb_i && adr_i[7:6]==3'b11),
484
    .adr(adr_i[5:2]),
485
    .din({dat_i[15],dat_i[11:0]}),
486
    .i(fsum),
487
    .o(filt_o)
488
);
489
 
490
// Sum the filtered and unfiltered output
491
always @(posedge clk_i)
492
        sum2 <= sum + filt_o[37:16];
493
 
494
// Last stage:
495
// Adjust output according to master volume
496
PSGVolumeControl u10
497
(
498
        .rst_i(rst_i),
499
        .clk_i(clk_i),
500
        .i(sum2),
501
        .volume(volume),
502
        .o(out4)
503
);
504
 
505
assign o = out4[29:12];
506
 
507
endmodule

powered by: WebSVN 2.1.0

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