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

Subversion Repositories jt51

[/] [jt51/] [trunk/] [jt51/] [jt51_lfo.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 gryzor
/*  This file is part of JT51.
2
 
3
    JT51 is free software: you can redistribute it and/or modify
4
    it under the terms of the GNU General Public License as published by
5
    the Free Software Foundation, either version 3 of the License, or
6
    (at your option) any later version.
7
 
8
    JT51 is distributed in the hope that it will be useful,
9
    but WITHOUT ANY WARRANTY; without even the implied warranty of
10
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
    GNU General Public License for more details.
12
 
13
    You should have received a copy of the GNU General Public License
14
    along with JT51.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
        Author: Jose Tejada Gomez. Twitter: @topapate
17
        Version: 1.0
18
        Date: 27-10-2016
19
        */
20
 
21
`timescale 1ns / 1ps
22
 
23
/*
24
 
25
        tab size 4
26
 
27
*/
28
 
29
module jt51_lfo(
30
        input                           rst,
31
        input                           clk,
32
        input                           zero,
33
        input                           lfo_rst,
34
        input           [7:0]    lfo_freq,
35
        input           [6:0]    lfo_amd,
36
        input           [6:0]    lfo_pmd,
37
        input           [1:0]    lfo_w,
38
        output  reg     [6:0]    am,
39
        output  reg     [7:0]    pm_u
40
);
41
 
42
reg     signed [7:0] pm;
43
 
44
always @(*) begin: signed_to_unsigned
45
        if( pm[7] ) begin
46
                pm_u[7] <= pm[7];
47
                pm_u[6:0] <= ~pm[6:0];
48
        end
49
        else pm_u <= pm;
50
end
51
 
52
wire [6:0] noise_am;
53
wire [7:0] noise_pm;
54
 
55
parameter b0=3;
56
reg [15+b0:0] base;
57
 
58
always @(posedge clk) begin : base_counter
59
        if( rst ) begin
60
                base    <= {b0+15{1'b0}};
61
        end
62
        else begin
63
                if( zero ) base <= base + 1'b1;
64
        end
65
end
66
 
67
reg sel_base;
68
reg [4:0] freq_sel;
69
 
70
always @(*) begin : base_mux
71
        freq_sel <= lfo_freq[7:4]
72
                + ( lfo_w==2'd2 ? 1'b1 : 1'b0 );
73
        case( freq_sel )
74
                5'h10: sel_base <= base[b0-1];
75
                5'hf: sel_base <= base[b0+0];
76
                5'he: sel_base <= base[b0+1];
77
                5'hd: sel_base <= base[b0+2];
78
                5'hc: sel_base <= base[b0+3];
79
                5'hb: sel_base <= base[b0+4];
80
                5'ha: sel_base <= base[b0+5];
81
                5'h9: sel_base <= base[b0+6];
82
                5'h8: sel_base <= base[b0+7];
83
                5'h7: sel_base <= base[b0+8];
84
                5'h6: sel_base <= base[b0+9];
85
                5'h5: sel_base <= base[b0+10];
86
                5'h4: sel_base <= base[b0+11];
87
                5'h3: sel_base <= base[b0+12];
88
                5'h2: sel_base <= base[b0+13];
89
                5'h1: sel_base <= base[b0+14];
90
                5'h0: sel_base <= base[b0+15];
91
                default: sel_base <= base[b0-1];
92
        endcase
93
end
94
 
95
reg [7:0] cnt, cnt_lim;
96
 
97
reg signed [10:0] am_bresenham;
98
reg signed [ 9:0] pm_bresenham;
99
 
100
always @(*) begin : counter_limit
101
        case( lfo_freq[3:0] )
102
                4'hf: cnt_lim <= 8'd66;
103
                4'he: cnt_lim <= 8'd68;
104
                4'hd: cnt_lim <= 8'd70;
105
                4'hc: cnt_lim <= 8'd73;
106
                4'hb: cnt_lim <= 8'd76;
107
                4'ha: cnt_lim <= 8'd79;
108
                4'h9: cnt_lim <= 8'd82;
109
                4'h8: cnt_lim <= 8'd85;
110
                4'h7: cnt_lim <= 8'd89;
111
                4'h6: cnt_lim <= 8'd93;
112
                4'h5: cnt_lim <= 8'd98;
113
                4'h4: cnt_lim <= 8'd102;
114
                4'h3: cnt_lim <= 8'd108;
115
                4'h2: cnt_lim <= 8'd114;
116
                4'h1: cnt_lim <= 8'd120;
117
                4'h0: cnt_lim <= 8'd128;
118
        endcase
119
end
120
 
121
wire signed [7:0] pmd_min = (~{1'b0, lfo_pmd[6:0]})+8'b1;
122
 
123
reg lfo_clk, last_base, am_up, pm_up;
124
 
125
always @(posedge clk) begin : modulator
126
        if( rst || lfo_rst ) begin
127
                last_base       <= 1'd0;
128
                lfo_clk         <= 1'b0;
129
                cnt                     <= 8'd0;
130
                am                      <= 7'd0;
131
                pm                      <= 8'd0;
132
                am_up           <= 1'b1;
133
                pm_up           <= 1'b1;
134
                am_bresenham <= 11'd0;
135
                pm_bresenham <= 10'd0;
136
        end
137
        else begin
138
                last_base <= sel_base;
139
                if( last_base != sel_base ) begin
140
                        case( lfo_w )
141
                        2'd0: begin // AM sawtooth
142
                                if( am_bresenham > 0 ) begin
143
                                        if( am == lfo_amd ) begin
144
                                                am <= 7'd0;
145
                                                am_bresenham <= 11'd0;
146
                                        end
147
                                        else begin
148
                                                am <= am + 1'b1;
149
                                                am_bresenham <= am_bresenham
150
                                                - { cnt_lim, 1'b0} + lfo_amd;
151
                                        end
152
                                end
153
                                else am_bresenham <= am_bresenham + lfo_amd;
154
 
155
                                if( pm_bresenham > 0 ) begin
156
                                        if( pm == { 1'b0, lfo_pmd } ) begin
157
                                                pm <= pmd_min;
158
                                                pm_bresenham <= 10'd0;
159
                                        end
160
                                        else begin
161
                                                pm <= pm + 1'b1;
162
                                                pm_bresenham <= pm_bresenham
163
                                                - cnt_lim + lfo_pmd;
164
                                        end
165
                                end
166
                                else pm_bresenham <= pm_bresenham + lfo_pmd;
167
                                end
168
                        2'd1: // AM square waveform
169
                                if( cnt == cnt_lim ) begin
170
                                        cnt <= 8'd0;
171
                                        lfo_clk <= ~lfo_clk;
172
                                        am <= lfo_clk ? lfo_amd : 7'd0;
173
                                        pm <= lfo_clk ? {1'b0, lfo_pmd } : pmd_min;
174
                                end
175
                                else cnt <= cnt + 1'd1;
176
                        2'd2:  begin // AM triangle
177
                                if( am_bresenham > 0 ) begin
178
                                        if( am == lfo_amd && am_up) begin
179
                                                am_up <= 1'b0;
180
                                                am_bresenham <= 11'd0;
181
                                        end
182
                                        else if( am == 8'd0 && !am_up) begin
183
                                                am_up <= 1'b1;
184
                                                am_bresenham <= 11'd0;
185
                                        end
186
                                        else begin
187
                                                am <= am_up ? am+1'b1 : am-1'b1;
188
                                                am_bresenham <= am_bresenham
189
                                                - { cnt_lim, 1'b0} + lfo_amd;
190
                                        end
191
                                end
192
                                else am_bresenham <= am_bresenham + lfo_amd;
193
 
194
                                if( pm_bresenham > 0 ) begin
195
                                        if( pm == {1'b0, lfo_pmd} && pm_up) begin
196
                                                pm_up <= 1'b0;
197
                                                pm_bresenham <= 10'd0;
198
                                        end
199
                                        else if( pm == pmd_min && !pm_up) begin
200
                                                pm_up <= 1'b1;
201
                                                pm_bresenham <= 10'd0;
202
                                        end
203
                                        else begin
204
                                                pm <= pm_up ? pm+1'b1 : pm-1'b1;
205
                                                pm_bresenham <= pm_bresenham
206
                                                - cnt_lim + lfo_pmd;
207
                                        end
208
                                end
209
                                else pm_bresenham <= pm_bresenham + lfo_pmd;
210
                                end
211
                        2'd3: begin
212
                                casex( lfo_amd ) // same as real chip
213
                                        7'b1xxxxxx: am <= noise_am[6:0];
214
                                        7'b01xxxxx: am <= { 1'b0, noise_am[5:0] };
215
                                        7'b001xxxx: am <= { 2'b0, noise_am[4:0] };
216
                                        7'b0001xxx: am <= { 3'b0, noise_am[3:0] };
217
                                        7'b00001xx: am <= { 4'b0, noise_am[2:0] };
218
                                        7'b000001x: am <= { 5'b0, noise_am[1:0] };
219
                                        7'b0000001: am <= { 6'b0, noise_am[0]   };
220
                                        default:    am <= 7'd0;
221
                                endcase
222
                                casex( lfo_pmd )
223
                                        7'b1xxxxxx: pm <= noise_pm;
224
                                        7'b01xxxxx: pm <= { {2{noise_pm[7]}}, noise_pm[5:0] };
225
                                        7'b001xxxx: pm <= { {3{noise_pm[7]}}, noise_pm[4:0] };
226
                                        7'b0001xxx: pm <= { {4{noise_pm[7]}}, noise_pm[3:0] };
227
                                        7'b00001xx: pm <= { {5{noise_pm[7]}}, noise_pm[2:0] };
228
                                        7'b000001x: pm <= { {6{noise_pm[7]}}, noise_pm[1:0] };
229
                                        7'b0000001: pm <= { {7{noise_pm[7]}}, noise_pm[0]   };
230
                                        default:    pm <= 8'd0;
231
                                endcase
232
                                end
233
                        endcase
234
                end
235
        end
236
end
237
 
238
genvar aux;
239
generate
240
        for( aux=0; aux<7; aux=aux+1 ) begin : amnoise
241
                jt51_lfo_lfsr #(.init(aux*aux+aux) ) u_noise_am(
242
                        .rst( rst ),
243
                        .clk( clk ),
244
                        .base(sel_base),
245
                        .out( noise_am[aux] )
246
                );
247
        end
248
        for( aux=0; aux<8; aux=aux+1 ) begin : pmnoise
249
                jt51_lfo_lfsr #(.init(4*aux*aux-3*aux+40) ) u_noise_pm(
250
                        .rst( rst ),
251
                        .clk( clk ),
252
                        .base(sel_base),
253
                        .out( noise_pm[aux] )
254
                );
255
        end
256
endgenerate
257
 
258
endmodule

powered by: WebSVN 2.1.0

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