mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-28 05:29:33 +00:00
113 lines
2.9 KiB
Verilog
113 lines
2.9 KiB
Verilog
|
|
`include "hvsync_generator.v"
|
|
`include "lfsr.v"
|
|
|
|
/*
|
|
Sound generator module.
|
|
This module has a square-wave oscillator (VCO) which can
|
|
be modulated by a low-frequency oscillator (LFO) and also
|
|
mixed with a LFSR noise source.
|
|
*/
|
|
|
|
module sound_generator(clk, reset, spkr,
|
|
lfo_freq,noise_freq, vco_freq,
|
|
vco_select, noise_select, lfo_shift, mixer);
|
|
|
|
input clk, reset;
|
|
output reg spkr = 0; // module output
|
|
|
|
input [9:0] lfo_freq; // LFO frequency (10 bits)
|
|
input [11:0] noise_freq; // noise frequency (12 bits)
|
|
input [11:0] vco_freq; // VCO frequency (12 bits)
|
|
input vco_select; // 1 = LFO modulates VCO
|
|
input noise_select; // 1 = LFO modulates Noise
|
|
input [2:0] lfo_shift; // LFO modulation depth
|
|
input [2:0] mixer; // mix enable {LFO, Noise, VCO}
|
|
|
|
reg [3:0] div16; // divide-by-16 counter
|
|
reg [17:0] lfo_count; // LFO counter (18 bits)
|
|
reg lfo_state; // LFO output
|
|
reg [12:0] noise_count; // Noise counter (13 bits)
|
|
reg noise_state; // Noise output
|
|
reg [12:0] vco_count; // VCO counter (12 bits)
|
|
reg vco_state; // VCO output
|
|
|
|
reg [15:0] lfsr; // LFSR output
|
|
|
|
LFSR #(16'b1000000001011,0) lfsr_gen(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.enable(div16 == 0 && noise_count == 0),
|
|
.lfsr(lfsr)
|
|
);
|
|
|
|
// create triangle waveform from LFO
|
|
wire [11:0] lfo_triangle = lfo_count[17] ? ~lfo_count[17:6] : lfo_count[17:6];
|
|
wire [11:0] vco_delta = lfo_triangle >> lfo_shift;
|
|
|
|
always @(posedge clk) begin
|
|
// divide clock by 64
|
|
div16 <= div16 + 1;
|
|
if (div16 == 0) begin
|
|
// VCO oscillator
|
|
if (reset || vco_count == 0) begin
|
|
vco_state <= ~vco_state;
|
|
if (vco_select)
|
|
vco_count <= vco_freq + vco_delta;
|
|
else
|
|
vco_count <= vco_freq + 0;
|
|
end else
|
|
vco_count <= vco_count - 1;
|
|
// LFO oscillator
|
|
if (reset || lfo_count == 0) begin
|
|
lfo_state <= ~lfo_state;
|
|
lfo_count <= {lfo_freq, 8'b0};
|
|
end else
|
|
lfo_count <= lfo_count - 1;
|
|
// Noise oscillator
|
|
if (reset || noise_count == 0) begin
|
|
if (lfsr[0])
|
|
noise_state <= ~noise_state;
|
|
if (noise_select)
|
|
noise_count <= noise_freq + vco_delta;
|
|
else
|
|
noise_count <= noise_freq + 0;
|
|
end else
|
|
noise_count <= noise_count - 1;
|
|
// Mixer
|
|
spkr <= (lfo_state | ~mixer[2])
|
|
& (noise_state | ~mixer[1])
|
|
& (vco_state | ~mixer[0]);
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
module test_snchip_top(clk, reset, hsync, vsync, rgb, spkr);
|
|
|
|
input clk, reset;
|
|
output hsync;
|
|
output vsync;
|
|
output spkr;
|
|
output [2:0] rgb;
|
|
|
|
// don't output a valid sync signal
|
|
assign hsync = 0;
|
|
assign vsync = 0;
|
|
assign rgb = {spkr,1'b0,1'b0};
|
|
|
|
sound_generator sndgen(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.spkr(spkr),
|
|
.lfo_freq(1000),
|
|
.noise_freq(90),
|
|
.vco_freq(250),
|
|
.vco_select(1),
|
|
.noise_select(1),
|
|
.lfo_shift(1),
|
|
.mixer(3)
|
|
);
|
|
|
|
endmodule
|