Skip to content

Commit

Permalink
cores/vco: fix and modularize vco example (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
schnommus committed Sep 17, 2023
1 parent 052d6b0 commit b033f23
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 37 deletions.
25 changes: 12 additions & 13 deletions gateware/cores/util/wavetable_osc.sv
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
module wavetable_osc #(
parameter W = 16,
parameter FRAC_BITS = 10,
parameter WAVETABLE_PATH = "cores/util/vco/wavetable.hex",
parameter WAVETABLE_SIZE = 256,
parameter WAVETABLE_SIZE = 256
)(
input rst,
input sample_clk,
input [31:0] wavetable_inc,
output signed [W-1:0] out,
output logic signed [W-1:0] out
);

logic [W-1:0] wavetable [0:WAVETABLE_SIZE-1];
initial $readmemh(WAVETABLE_PATH, wavetable);

logic [31:0] wavetable_pos = 32'h0;
// Position in wavetable - N.F fixed-point where BIT_START is size of F.
logic [31:0] wavetable_pos = 0;

always_ff @(posedge sample_clk) begin
// TODO: linear interpolation between frequencies, silence oscillator
// whenever we are outside the LUT bounds.
wavetable_pos <= wavetable_pos + wavetable_inc;
if (rst) begin
wavetable_pos <= 0;
end else begin
wavetable_pos <= wavetable_pos + wavetable_inc;
// Take top N bits of wavetable_pos as output.
out <= wavetable[wavetable_pos[FRAC_BITS+$clog2(WAVETABLE_SIZE)-1:FRAC_BITS]];
end
end

// Top 8 bits of the N.F fixed-point representation are index into wavetable.
localparam BIT_START = 10;
wire [$clog2(WAVETABLE_SIZE)-1:0] wavetable_idx =
wavetable_pos[BIT_START+$clog2(WAVETABLE_SIZE)-1:BIT_START];

assign out = wavetable[wavetable_idx];

endmodule
43 changes: 21 additions & 22 deletions gateware/cores/vco.sv
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// Mapping:
// - Input 0: V/Oct input, C3 is +3V
// - Output 0-3: VCO output (from wavetable) phased at 0, 90, 120, 270deg.
// - Output 0: VCO output (from wavetable)

module vco #(
parameter W = 16,
Expand Down Expand Up @@ -35,31 +35,30 @@ module vco #(
logic [W-1:0] v_oct_lut [0:V_OCT_LUT_SIZE-1];
initial $readmemh(V_OCT_LUT_PATH, v_oct_lut);

logic [W-1:0] wavetable [0:WAVETABLE_SIZE-1];
initial $readmemh(WAVETABLE_PATH, wavetable);

// For < 0V input, clamp to bottom note.
logic signed [W-1:0] lut_index;
logic [$clog2(V_OCT_LUT_SIZE)-1:0] lut_index_clamped;
logic [31:0] wavetable_pos = 32'h0;

assign lut_index = sample_in0 >>> 6;
assign lut_index_clamped = $clog2(V_OCT_LUT_SIZE)'(lut_index < 0 ? W'(0) : lut_index);
logic signed [W-1:0] lut_index = 0;
logic signed [W-1:0] lut_index_clamp_lo = 0;

always_ff @(posedge sample_clk) begin
// TODO: linear interpolation between frequencies, silence oscillator
// whenever we are outside the LUT bounds.
wavetable_pos <= wavetable_pos + 32'(v_oct_lut[lut_index_clamped]);
if (rst) begin
lut_index <= 0;
lut_index_clamp_lo <= 0;
end else begin
lut_index <= sample_in0 >>> 6;
lut_index_clamp_lo <= lut_index < 0 ? 0 : lut_index;
end
end

// Top 8 bits of the N.F fixed-point representation are index into wavetable.
localparam BIT_START = 10 + FDIV;
wire [$clog2(WAVETABLE_SIZE)-1:0] wavetable_idx =
wavetable_pos[BIT_START+$clog2(WAVETABLE_SIZE)-1:BIT_START];

assign sample_out0 = wavetable[wavetable_idx];
assign sample_out1 = wavetable[wavetable_idx+WAVETABLE_SIZE/4];
assign sample_out2 = wavetable[wavetable_idx+WAVETABLE_SIZE/2];
assign sample_out3 = wavetable[wavetable_idx+WAVETABLE_SIZE/2+WAVETABLE_SIZE/4];
wavetable_osc #(
.W(W),
.FRAC_BITS(10),
.WAVETABLE_PATH(WAVETABLE_PATH),
.WAVETABLE_SIZE(WAVETABLE_SIZE)
) osc_0 (
.rst(rst),
.sample_clk(sample_clk),
.wavetable_inc(32'(v_oct_lut[$clog2(V_OCT_LUT_SIZE)'(lut_index_clamp_lo)])),
.out(sample_out0)
);

endmodule
3 changes: 2 additions & 1 deletion gateware/mk/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ SRC_COMMON = eurorack_pmod.sv \
cores/util/transpose.sv \
cores/util/echo.sv \
cores/util/delayline.sv \
cores/util/dc_block.sv
cores/util/dc_block.sv \
cores/util/wavetable_osc.sv
3 changes: 2 additions & 1 deletion gateware/scripts/verilator_lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ verilator --lint-only -Icores clkdiv.sv
verilator --lint-only -Icores sampler.sv
verilator --lint-only -Icores seqswitch.sv
verilator --lint-only -Icores vca.sv
verilator --lint-only -Icores vco.sv
verilator --lint-only -Icores -Icores/util vco.sv
verilator --lint-only cores/util/filter/karlsen_lpf.sv
verilator --lint-only cores/util/filter/karlsen_lpf_pipelined.sv
verilator --lint-only -Icores -Icores/util/filter filter.sv
verilator --lint-only -Icores -Icores/util pitch_shift.sv
verilator --lint-only -Icores -Icores/util stereo_echo.sv
verilator --lint-only -Icores -Icores/util dc_block.sv
verilator --lint-only -Icores -Icores/util wavetable_osc.sv

0 comments on commit b033f23

Please sign in to comment.