blob: a496c5b5a3b63bd657713bec0538ece266793ee8 [file] [log] [blame]
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Wenting Zhang
//
// Create Date: 21:19:04 04/08/2018
// Module Name: sound_noise
// Project Name: VerilogBoy
// Description:
//
// Dependencies:
//
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module sound_noise(
input rst, // Sync reset
input clk, // CPU Clock
input clk_length_ctr, // Length control clock
input clk_vol_env, // Volume Envelope clock
input [5:0] length, // Length = (64-t1)*(1/256) second, used iff single is set
input [3:0] initial_volume, // Initial volume of envelope 0 = no sound
input envelope_increasing, // 0 = decrease, 1 = increase
input [2:0] num_envelope_sweeps, // number of envelope sweep 0 = stop
input [3:0] shift_clock_freq, // shift clock prescaler (s)
input counter_width, // 0 = 15 bits, 1 = 7 bits
input [2:0] freq_dividing_ratio, // shift clock divider 0 -> 1MHz, 1 -> 512kHz (r)
input start, // Restart sound
input single, // If set, output would stop upon reaching the length specified
output [3:0] level,
output enable
);
wire start_posedge;
edgedet start_edgedet (
.clk(clk),
.i(start),
.o(start_posedge)
);
// Dividing ratio from 4MHz is (r * 8), for the divier to work, the comparator shoud
// compare with (dividing_factor / 2 - 1), so it becomes (r * 4 - 1)
reg [5:0] adjusted_freq_dividing_ratio;
reg [3:0] latched_shift_clock_freq;
wire [3:0] target_vol;
wire clk_shift;
reg [5:0] clk_divider = 6'b0; // First stage
reg [13:0] clk_shifter = 14'b0; // Second stage
always @(posedge clk)
begin
if (clk_divider == adjusted_freq_dividing_ratio) begin
clk_shifter <= clk_shifter + 1'b1;
clk_divider <= 0;
end
else
clk_divider <= clk_divider + 1'b1;
end
assign clk_shift = clk_shifter[latched_shift_clock_freq];
reg [14:0] lfsr = {15{1'b1}};
wire target_freq_out = ~lfsr[0];
wire [14:0] lfsr_next =
(counter_width == 0) ? ({(lfsr[0] ^ lfsr[1]), lfsr[14:1]}) :
({8'b0, (lfsr[0] ^ lfsr[1]), lfsr[6:1]});
wire clk_shift_posedge;
edgedet clk_shift_edgedet (
.clk(clk),
.i(clk_shift),
.o(clk_shift_posedge)
);
always @(posedge clk)
begin
if (start_posedge) begin
adjusted_freq_dividing_ratio <=
(freq_dividing_ratio == 3'b0) ? (6'd1) : ((freq_dividing_ratio * 8) - 1);
latched_shift_clock_freq <= shift_clock_freq;
end
end
always @(posedge clk)
begin
if (start_posedge) begin
lfsr <= {15{1'b1}};
end
else if (clk_shift_posedge) begin
lfsr <= lfsr_next;
end
end
sound_vol_env sound_vol_env(
.clk(clk),
.clk_vol_env(clk_vol_env),
.start(start_posedge),
.initial_volume(initial_volume),
.envelope_increasing(envelope_increasing),
.num_envelope_sweeps(num_envelope_sweeps),
.target_vol(target_vol)
);
sound_length_ctr #(6) sound_length_ctr(
.clk(clk),
.rst(rst),
.clk_length_ctr(clk_length_ctr),
.start(start_posedge),
.single(single),
.length(length),
.enable(enable)
);
sound_channel_mix sound_channel_mix(
.enable(enable),
.modulate(target_freq_out),
.target_vol(target_vol),
.level(level)
);
endmodule