Commit 7aa41220 authored by Christian Fibich's avatar Christian Fibich
Browse files

initial

parents
module usynth (input wire clock,
input wire ce25,
input wire reset,
input wire play_note,
input wire [15:0] freq,
output wire out,
input wire [15:0] a,
input wire [15:0] d,
input wire [15:0] s,
input wire [15:0] r,
input wire envelope);
wire ce_sample;
wire ce_envelope;
wire ce_pwm;
wire [15:0] sample;
clken ce (.clock(clock),.reset(reset),
.ce25(ce25),
.ce_envelope(ce_envelope),
.ce_sample(ce_sample),
.ce_pwm(ce_pwm));
voice v (.clock(clock), .reset(reset),
.ce_sample(ce_sample), .ce_timing(ce_envelope),
.freq(freq),
.a(a),.d(d),.s(s),.r(r),
.play_note(play_note), .sample(sample),
.envelope_enable(envelope));
pwm p (.clock(clock), .reset(reset),
.ce_pwm(ce_pwm), .sample(sample[15:8]),
.out(out));
endmodule
module clken (input wire clock,
input wire reset,
input wire ce25,
output reg ce_envelope,
output reg ce_sample,
output reg ce_pwm);
reg [11:0] sample_count;
reg [3:0] envelope_count;
wire ce_envelope_int;
wire ce_sample_int;
wire ce_pwm_int;
localparam SAMPLE_RELOAD = 12'hBD0;
localparam ENVELOPE_RELOAD = 4'b1111;
assign ce_pwm_int = ce25;
assign ce_sample_int = ce25 & ce_pwm_int & (sample_count == 12'b0) ? 1'b1 : 1'b0;
always @ (posedge clock or posedge reset)
begin
if (reset == 1'b1) begin
sample_count <= SAMPLE_RELOAD;
end else if (ce_pwm_int) begin
sample_count <= sample_count - 1;
if (sample_count == 12'b0) begin
sample_count <= SAMPLE_RELOAD;
end
end
end
assign ce_envelope_int = ce25 & ce_pwm_int & ce_sample_int & (envelope_count == 8'b0) ? 1'b1 : 1'b0;
always @ (posedge clock or posedge reset)
begin
if (reset == 1'b1) begin
envelope_count <= ENVELOPE_RELOAD;
end else if (ce_sample_int) begin
envelope_count <= envelope_count - 1;
if (envelope_count == 4'b0) begin
envelope_count <= ENVELOPE_RELOAD;
end
end
end
always @(posedge clock or posedge reset)
begin
if (reset == 1'b1) begin
ce_envelope <= 1'b0;
ce_sample <= 1'b0;
ce_pwm <= 1'b0;
end else begin
ce_envelope <= ce_envelope_int;
ce_sample <= ce_sample_int;
ce_pwm <= ce_pwm_int;
end
end
endmodule
module envelope_generator (input wire clock,
input wire reset,
input wire ce,
input wire [15:0] a, // attack
input wire [15:0] d, // decay
input wire [15:0] s, // sustain
input wire [15:0] r, // release
input wire gate,
output wire [15:0] out);
reg [15:0] acc;
reg [15:0] a_sampled;
reg [15:0] d_sampled;
reg [15:0] s_sampled;
reg [15:0] r_sampled;
reg [4:0] adsr_state;
localparam IDLE = 5'b00001,
ATTACK = 5'b00010,
DECAY = 5'b00100,
SUSTAIN = 5'b01000,
RELEASE = 5'b10000;
always @ (posedge(clock) or posedge(reset))
begin
if (reset) begin
a_sampled <= 16'b0;
d_sampled <= 16'b0;
s_sampled <= 16'b0;
r_sampled <= 16'b0;
acc <= 16'b0;
adsr_state <= IDLE;
end else if (ce == 1'b1) begin
case (adsr_state)
IDLE : begin
if (gate == 1'b1) begin
adsr_state <= ATTACK;
a_sampled <= a;
d_sampled <= d;
s_sampled <= s;
r_sampled <= r;
end
end
ATTACK: begin
if (acc == 16'hffff)
adsr_state <= DECAY;
else
acc <= (a_sampled > (16'hffff - acc)) ? 16'hffff : acc + a_sampled;
end
DECAY: begin
if (acc == s_sampled)
adsr_state <= SUSTAIN;
else
acc <= ((acc - d_sampled) < s_sampled) ? s_sampled : acc - d_sampled;
end
SUSTAIN: begin
if (gate == 1'b0) begin
adsr_state <= RELEASE;
end
end
RELEASE: begin
if (acc == 16'h0000)
adsr_state <= IDLE;
else
acc <= (acc < r_sampled) ? 16'h0000 : acc - r_sampled;
end
default: begin
acc <= acc;
end
endcase
end
end
assign out = acc;
endmodule
`timescale 1ns/100ps
module synth_basys3 (input wire clock100, input wire reset,
input wire key, output wire pwm, input wire [15:0] sw);
reg [1:0] key_sync;
reg [15:0] sw_sync_0;
reg [15:0] sw_sync_1;
reg [1:0] ce25_count;
reg ce25;
reg [9:0] key_debounce_count;
reg reg_key;
synth s (.clock(clock100), .ce25(ce25), .reset(reset),
.play_note(reg_key), .out(pwm), .freq(sw_sync_1), .envelope(sw[15]),
.a(16'h0800),.d(16'h0800),.s(16'hC000),.r(16'h1000));
always @ (posedge clock100 or posedge reset)
begin
if (reset == 1'b1) begin
ce25_count <= 2'b11;
ce25 <= 1'b0;
end else begin
ce25 <= 1'b0;
ce25_count <= ce25_count - 2'b01;
if (ce25_count == 2'b00) begin
ce25 <= 1'b1;
end
end
end
always @ (posedge clock100 or posedge reset)
begin
if (reset == 1'b1) begin
key_sync <= 2'b0;
key_debounce_count <= 10'b0;
sw_sync_0 <= 16'b0;
sw_sync_1 <= 16'b0;
reg_key <= 1'b0;
end else begin
key_sync <= {key_sync[0], key};
sw_sync_1 <= sw_sync_0;
if (ce25 == 1'b1) begin
key_debounce_count <= key_debounce_count + 1'b1;
if (key_debounce_count[9] == 1'b1) begin
key_debounce_count <= 10'b0;
reg_key <= key_sync[1];
sw_sync_0 <= sw;
end
end
end
end
endmodule
module mixer (input wire clock, input wire reset,
input wire ce, input wire [15:0] tone,
input wire [15:0] envelope, output wire [15:0] out);
reg [31:0] sample;
always @ (posedge clock or posedge reset)
begin
if (reset)
sample <= 32'b0;
else if (ce) begin
sample <= tone * envelope;
$display("%d", sample[31:16]);
end
end
assign out = sample[31:16];
endmodule
module pwm (input wire clock,
input wire reset,
input wire ce_pwm,
input wire [7:0] sample,
output wire out);
reg [7:0] pwm_cnt;
reg pwm_out;
reg [7:0] sample_reg;
always @ (posedge clock or posedge reset)
begin
if (reset == 1'b1) begin
pwm_cnt <= 8'b0;
pwm_out <= 1'b0;
sample_reg <= 8'b0;
end else if (ce_pwm == 1'b1) begin
pwm_cnt <= pwm_cnt + 1;
if (pwm_cnt == 0)
sample_reg <= sample;
if (pwm_cnt >= sample)
pwm_out <= 1'b0;
else
pwm_out <= 1'b1;
end
end
assign out = pwm_out;
endmodule
module tone_generator (input wire clock,
input wire reset,
input wire ce,
input wire [15:0] freq,
output wire [15:0] out);
reg [12:0] phacc;
reg [7:0] wavetable [8191:0];
reg [15:0] wave_out;
always @(posedge clock or posedge reset)
begin
if (reset) begin
phacc <= 13'b0;
end else if (ce) begin
phacc <= phacc + {1'b0, freq[11:0]}; // Don't allow increments > 1/2
end
end
initial begin
$readmemh("wavetable.mem",wavetable);
end
always @(posedge clock)
wave_out <= {wavetable[phacc], 8'b0};
assign out = wave_out;
endmodule
module voice (input wire clock,
input wire ce_sample,
input wire ce_timing,
input wire reset,
input wire [15:0] freq,
input wire [15:0] a, // attack
input wire [15:0] d, // decay
input wire [15:0] s, // sustain
input wire [15:0] r, // release
input wire play_note,
output wire [15:0] sample,
input wire envelope_enable);
wire [15:0] tone;
wire [15:0] envelope;
wire [15:0] sample_envelope;
tone_generator tg (.clock(clock), .reset(reset), .freq(freq),
.ce(ce_sample), .out(tone));
envelope_generator eg ( .clock(clock), .reset(reset),
.ce(ce_timing),
.a(a),.d(d),.s(s),.r(r),
.gate(play_note),
.out(envelope));
mixer mix (.clock(clock), .reset(reset), .ce(ce_sample),
.tone(tone), .envelope(envelope), .out(sample_envelope));
assign sample = (envelope_enable) ? sample_envelope : tone;
endmodule
This diff is collapsed.
`timescale 1ns/100ps
module synth_basys3_tb ();
reg clock100;
reg reset;
reg key;
wire pwm;
reg [15:0] sw;
synth_basys3 dut (.clock100(clock100), .reset(reset),
.key(key), .pwm(pwm), .sw(sw));
initial begin
clock100 = 1'b0;
reset = 1'b1;
key = 1'b0;
sw = 16'h01;
#5;
reset = 1'b0;
#100;
key = 1'b1;
#20000000;
#20000000;
key = 1'b0;
#20000000;
#20000000;
end
always
#5 clock100 = ~clock100;
endmodule
`timescale 1ns/100ps
module tb_synth ();
reg play_note;
reg clock;
reg ce25;
reg reset;
wire out;
synth dut (.clock(clock), .ce25(ce25), .reset(reset),
.play_note(play_note), .out(out));
initial begin
clock = 1'b0;
ce25 = 1'b0;
play_note = 1'b0;
reset = 1'b1;
#15;
reset = 1'b0;
#35;
play_note = 1'b1;
#(976380*64)
play_note = 1'b0;
#(976380*64)
$finish;
end
always
#5 clock = ~clock;
always
#20 ce25 = ~ce25;
endmodule
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment