Skip to content

Commit

Permalink
Fix 4-op modulation connections (#32)
Browse files Browse the repository at this point in the history
* modulation cnt fix

* added 1 cycle delay to fb/cnt register read

* fix 4 op modulation connections
  • Loading branch information
gtaylormb authored Apr 18, 2024
1 parent 5adbe31 commit a787ebb
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 45 deletions.
141 changes: 102 additions & 39 deletions fpga/modules/channels/src/control_operators.sv
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ module control_operators
logic [REG_FNUM_WIDTH-1:0] fnum; // f-number (scale data within the octave)
logic [REG_BLOCK_WIDTH-1:0] block; // octave data
logic kon; // key-on (sound generation on/off)
logic [REG_FB_WIDTH-1:0] fb; // feedback (modulation for slot 1 FM feedback)
logic cnt; // operator connection
logic cnt_p1 = 0;
logic [REG_FB_WIDTH-1:0] fb_p1; // feedback (modulation for slot 1 FM feedback)
logic cnt0_p1; // operator connection
logic cnt1_p1; // operator connection
logic [$clog2('h9)-1:0] kon_block_fnum_channel_mem_rd_address;
logic [$clog2('h9)-1:0] fb_cnt_channel_mem_rd_address;
logic [$clog2('h9)-1:0] fb_cnt0_channel_mem_rd_address;
logic [$clog2('h9)-1:0] cnt1_channel_mem_rd_address;

logic nts = 0; // keyboard split selection
logic dvb = 0; // vibrato depth
Expand Down Expand Up @@ -237,60 +238,70 @@ module control_operators
.dob(ws)
);

always_comb
always_comb begin
cnt1_channel_mem_rd_address = 0;

unique case (op_num)
0, 3: begin
kon_block_fnum_channel_mem_rd_address = 0;
fb_cnt_channel_mem_rd_address = 0;
fb_cnt0_channel_mem_rd_address = 0;
end
1, 4: begin
kon_block_fnum_channel_mem_rd_address = 1;
fb_cnt_channel_mem_rd_address = 1;
fb_cnt0_channel_mem_rd_address = 1;
end
2, 5: begin
kon_block_fnum_channel_mem_rd_address = 2;
fb_cnt_channel_mem_rd_address = 2;
fb_cnt0_channel_mem_rd_address = 2;
end
6, 9:
6, 9: begin
cnt1_channel_mem_rd_address = 3;
if (bank_num == 0) begin
kon_block_fnum_channel_mem_rd_address = connection_sel[0] ? 0 : 3;
fb_cnt_channel_mem_rd_address = 3;
fb_cnt0_channel_mem_rd_address = connection_sel[0] ? 0 : 3;
end
else begin
kon_block_fnum_channel_mem_rd_address = connection_sel[3] ? 0 : 3;
fb_cnt_channel_mem_rd_address = 3;
fb_cnt0_channel_mem_rd_address = connection_sel[3] ? 0 : 3;
end
7, 10:
end
7, 10: begin
cnt1_channel_mem_rd_address = 4;
if (bank_num == 0) begin
kon_block_fnum_channel_mem_rd_address = connection_sel[1] ? 1 : 4;
fb_cnt_channel_mem_rd_address = 4;
fb_cnt0_channel_mem_rd_address = connection_sel[1] ? 1 : 4;
end
else begin
kon_block_fnum_channel_mem_rd_address = connection_sel[4] ? 1 : 4;
fb_cnt_channel_mem_rd_address = 4;
fb_cnt0_channel_mem_rd_address = connection_sel[4] ? 1 : 4;
cnt1_channel_mem_rd_address = 4;
end
8, 11:
end
8, 11: begin
cnt1_channel_mem_rd_address = 5;
if (bank_num == 0) begin
kon_block_fnum_channel_mem_rd_address = connection_sel[2] ? 2 : 5;
fb_cnt_channel_mem_rd_address = 5;
fb_cnt0_channel_mem_rd_address = connection_sel[2] ? 2 : 5;
end
else begin
kon_block_fnum_channel_mem_rd_address = connection_sel[5] ? 2 : 5;
fb_cnt_channel_mem_rd_address = 5;
fb_cnt0_channel_mem_rd_address = connection_sel[2] ? 2 : 5;
end
end
12, 15: begin
kon_block_fnum_channel_mem_rd_address = 6;
fb_cnt_channel_mem_rd_address = 6;
fb_cnt0_channel_mem_rd_address = 6;
end
13, 16: begin
kon_block_fnum_channel_mem_rd_address = 7;
fb_cnt_channel_mem_rd_address = 7;
fb_cnt0_channel_mem_rd_address = 7;
end
14, 17: begin
kon_block_fnum_channel_mem_rd_address = 8;
fb_cnt_channel_mem_rd_address = 8;
fb_cnt0_channel_mem_rd_address = 8;
end
endcase
end

wire [$clog2('h9)-1:0] fnum_low_mem_wr_address = opl3_reg_wr.address - 'hA0;

Expand Down Expand Up @@ -334,24 +345,44 @@ module control_operators
);

wire [$clog2('h9)-1:0] fb_cnt_mem_wr_address = opl3_reg_wr.address - 'hC0;
localparam fb_cnt_mem_width = $bits(fb) + $bits(cnt);
localparam fb_cnt_mem_width = $bits(fb_p1) + $bits(cnt0_p1);

mem_multi_bank #(
.DATA_WIDTH(fb_cnt_mem_width),
.DEPTH('h9),
.OUTPUT_DELAY(0),
.OUTPUT_DELAY(1),
.DEFAULT_VALUE(0),
.NUM_BANKS(NUM_BANKS)
) fb_cnt_mem (
) fb_cnt0_mem (
.clk,
.wea(opl3_reg_wr.valid && opl3_reg_wr.address >= 'hC0 && opl3_reg_wr.address <= 'hC8),
.reb(op_sample_clk_en),
.banka(opl3_reg_wr.bank_num),
.addra(fb_cnt_mem_wr_address),
.bankb(bank_num),
.addrb(fb_cnt_channel_mem_rd_address),
.addrb(fb_cnt0_channel_mem_rd_address),
.dia(opl3_reg_wr.data[fb_cnt_mem_width-1:0]),
.dob({fb, cnt})
.dob({fb_p1, cnt0_p1})
);

// used for 4 op connections, need both cnt0 and cnt1 simultaneously
localparam cnt_mem_width = $bits(cnt1_p1);
mem_multi_bank #(
.DATA_WIDTH(cnt_mem_width),
.DEPTH('h9),
.OUTPUT_DELAY(1),
.DEFAULT_VALUE(0),
.NUM_BANKS(NUM_BANKS)
) fb_cnt1_mem (
.clk,
.wea(opl3_reg_wr.valid && opl3_reg_wr.address >= 'hC0 && opl3_reg_wr.address <= 'hC8),
.reb(op_sample_clk_en),
.banka(opl3_reg_wr.bank_num),
.addra(fb_cnt_mem_wr_address),
.bankb(bank_num),
.addrb(cnt1_channel_mem_rd_address),
.dia(opl3_reg_wr.data[cnt_mem_width-1:0]),
.dob(cnt1_p1)
);

always_ff @(posedge clk)
Expand Down Expand Up @@ -383,7 +414,6 @@ module control_operators
end

always_ff @(posedge clk) begin
cnt_p1 <= cnt;
bank_num_p1 <= bank_num;
connection_sel_p1 <= connection_sel;
ryt_p1 <= ryt;
Expand All @@ -392,19 +422,52 @@ module control_operators

always_comb
unique case (op_num_p1)
0, 1, 2, 12, 13, 14: modulation_p1 = 0;
3, 4, 5, 9, 10, 11, 15: modulation_p1 = cnt_p1 ? 0 : modulation_out_p1;
6: if ((bank_num_p1 == 0 && connection_sel_p1[0]) || (bank_num_p1 == 1 && connection_sel_p1[3]))
modulation_p1 = cnt ? 0 : modulation_out_p1;
else modulation_p1 = 0;
7: if ((bank_num_p1 == 0 && connection_sel_p1[1]) || (bank_num_p1 == 1 && connection_sel_p1[4]))
modulation_p1 = cnt_p1 ? 0 : modulation_out_p1;
else modulation_p1 = 0;
8: if ((bank_num_p1 == 0 && connection_sel_p1[2]) || (bank_num_p1 == 1 && connection_sel_p1[5]))
modulation_p1 = cnt_p1 ? 0 : modulation_out_p1;
else modulation_p1 = 0;
16: modulation_p1 = cnt_p1 || (ryt_p1 && bank_num_p1 == 0) ? 0 : modulation_out_p1; // aka snare drum operator in bank 0
17: modulation_p1 = cnt_p1 || (ryt_p1 && bank_num_p1 == 0) ? 0 : modulation_out_p1; // aka top cymbal operator in bank 0
0, 1, 2, 12, 13, 14: modulation_p1 = 0;
3, 4, 5, 15: modulation_p1 = cnt0_p1 ? 0 : modulation_out_p1;
6:
if ((bank_num_p1 == 0 && connection_sel_p1[0]) || (bank_num_p1 == 1 && connection_sel_p1[3]))
unique case ({cnt0_p1, cnt1_p1}) // 4 op mode
'b00, 'b10, 'b11: modulation_p1 = modulation_out_p1;
'b01: modulation_p1 = 0;
endcase
else modulation_p1 = 0;
7:
if ((bank_num_p1 == 0 && connection_sel_p1[1]) || (bank_num_p1 == 1 && connection_sel_p1[4]))
unique case ({cnt0_p1, cnt1_p1}) // 4 op mode
'b00, 'b10, 'b11: modulation_p1 = modulation_out_p1;
'b01: modulation_p1 = 0;
endcase
else modulation_p1 = 0;
8:
if ((bank_num_p1 == 0 && connection_sel_p1[2]) || (bank_num_p1 == 1 && connection_sel_p1[5]))
unique case ({cnt0_p1, cnt1_p1}) // 4 op mode
'b00, 'b10, 'b11: modulation_p1 = modulation_out_p1;
'b01: modulation_p1 = 0;
endcase
else modulation_p1 = 0;
9:
if ((bank_num_p1 == 0 && connection_sel_p1[0]) || (bank_num_p1 == 1 && connection_sel_p1[3]))
unique case ({cnt0_p1, cnt1_p1}) // 4 op mode
'b00, 'b01, 'b10: modulation_p1 = modulation_out_p1;
'b11: modulation_p1 = 0;
endcase
else modulation_p1 = cnt0_p1 ? 0 : modulation_out_p1;
10:
if ((bank_num_p1 == 0 && connection_sel_p1[1]) || (bank_num_p1 == 1 && connection_sel_p1[4]))
unique case ({cnt0_p1, cnt1_p1}) // 4 op mode
'b00, 'b01, 'b10: modulation_p1 = modulation_out_p1;
'b11: modulation_p1 = 0;
endcase
else modulation_p1 = cnt0_p1 ? 0 : modulation_out_p1;
11:
if ((bank_num_p1 == 0 && connection_sel_p1[2]) || (bank_num_p1 == 1 && connection_sel_p1[5]))
unique case ({cnt0_p1, cnt1_p1}) // 4 op mode
'b00, 'b01, 'b10: modulation_p1 = modulation_out_p1;
'b11: modulation_p1 = 0;
endcase
else modulation_p1 = cnt0_p1 ? 0 : modulation_out_p1;
16: modulation_p1 = cnt0_p1 || (ryt_p1 && bank_num_p1 == 0) ? 0 : modulation_out_p1; // aka snare drum operator in bank 0
17: modulation_p1 = cnt0_p1 || (ryt_p1 && bank_num_p1 == 0) ? 0 : modulation_out_p1; // aka top cymbal operator in bank 0
endcase

always_ff @(posedge clk)
Expand Down
6 changes: 1 addition & 5 deletions fpga/modules/operator/src/operator.sv
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ module operator
input wire tc,
input wire hh,
input wire use_feedback_p1,
input wire [REG_FB_WIDTH-1:0] fb,
input wire [REG_FB_WIDTH-1:0] fb_p1,
input wire signed [OP_OUT_WIDTH-1:0] modulation_p1,
input var operator_t op_type,
output logic signed [OP_OUT_WIDTH-1:0] out_p6
Expand All @@ -100,7 +100,6 @@ module operator
logic [1:0] [OP_OUT_WIDTH-1:0] feedback_p1;
logic [1:0] [OP_OUT_WIDTH-1:0] feedback_p6;
logic [PIPELINE_DELAY:2] [1:0] [OP_OUT_WIDTH-1:0] feedback_p;
logic [REG_FB_WIDTH-1:0] fb_p1 = 0;

pipeline_sr #(
.ENDING_CYCLE(PIPELINE_DELAY)
Expand Down Expand Up @@ -256,9 +255,6 @@ module operator
.out(feedback_p)
);

always_ff @(posedge clk)
fb_p1 <= fb;

always_comb begin
// used signed casts because signed on packed 2D array in Verilog doesn't apply individually to inner array, only the outer array
feedback_result_tmp_p1 = fb_p1 == 0 ? 0 : (signed'(feedback_p1[0]) + signed'(feedback_p1[1])) <<< fb_p1;
Expand Down
1 change: 0 additions & 1 deletion fpga/modules/timers/src/timer.sv
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ module timer
logic tick_pulse = 0;
logic [REG_TIMER_WIDTH-1:0] timer = 0;
logic start_timer_set_pulse;
logic [REG_TIMER_WIDTH-1:0] timer_p1 = 0;

/*
* Detect when start_timer is initially set, use it to reset the timer value
Expand Down

0 comments on commit a787ebb

Please sign in to comment.