`timescale 1ns / 1ps /* This file is part of JT12. JT12 program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JT12 program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JT12. If not, see . Author: Jose Tejada Gomez. Twitter: @topapate Version: 1.0 Date: 14-2-2017 */ module jt12_reg( input rst, input clk, input [7:0] din, input [2:0] ch, input [1:0] op, input csm, input flag_A, input overflow_A, input up_keyon, input up_alg, input up_block, input up_fnumlo, input up_pms, input up_dt1, input up_tl, input up_ks_ar, input up_amen_d1r, input up_d2r, input up_d1l, input up_ssgeg, output busy, output reg ch6op, // 1 when the operator belongs to CH6 // CH3 Effect-mode operation input effect, input [10:0] fnum_ch3op2, input [10:0] fnum_ch3op3, input [10:0] fnum_ch3op1, input [ 2:0] block_ch3op2, input [ 2:0] block_ch3op3, input [ 2:0] block_ch3op1, // Pipeline order output reg zero, output s1_enters, output s2_enters, output s3_enters, output s4_enters, // Operator output use_prevprev1, output use_internal_x, output use_internal_y, output use_prev2, output use_prev1, // PG output [10:0] fnum_I, output [ 2:0] block_I, // channel configuration output [1:0] rl, output reg [2:0] fb_II, output [2:0] alg, // Operator multiplying output [ 3:0] mul_V, // Operator detuning output [ 2:0] dt1_II, // EG output [4:0] ar_II, // attack rate output [4:0] d1r_II, // decay rate output [4:0] d2r_II, // sustain rate output [3:0] rr_II, // release rate output [3:0] d1l, // sustain level output [1:0] ks_III, // key scale output ssg_en_II, output [2:0] ssg_eg_II, output [6:0] tl_VII, output [2:0] pms, output [1:0] ams_VII, output amsen_VII, // envelope operation output keyon_II ); reg [4:0] cnt; reg [1:0] next_op, cur_op; reg [2:0] next_ch, cur_ch; assign s1_enters = cur_op == 2'b00; assign s3_enters = cur_op == 2'b01; assign s2_enters = cur_op == 2'b10; assign s4_enters = cur_op == 2'b11; wire [4:0] next = { next_op, next_ch }; wire [4:0] cur = { cur_op, cur_ch }; wire [2:0] fb_I; always @(posedge clk) begin fb_II <= fb_I; ch6op <= next_ch==3'd6; end // FNUM and BLOCK wire [10:0] fnum_I_raw; wire [ 2:0] block_I_raw; wire effect_on = effect && (cur_ch==3'd2); wire effect_on_s1 = effect_on && (cur_op == 2'd0 ); wire effect_on_s3 = effect_on && (cur_op == 2'd1 ); wire effect_on_s2 = effect_on && (cur_op == 2'd2 ); wire noeffect = ~|{effect_on_s1, effect_on_s3, effect_on_s2}; assign fnum_I = ( {11{effect_on_s1}} & fnum_ch3op1 ) | ( {11{effect_on_s2}} & fnum_ch3op2 ) | ( {11{effect_on_s3}} & fnum_ch3op3 ) | ( {11{noeffect}} & fnum_I_raw ); assign block_I =( {3{effect_on_s1}} & block_ch3op1 ) | ( {3{effect_on_s2}} & block_ch3op2 ) | ( {3{effect_on_s3}} & block_ch3op3 ) | ( {3{noeffect}} & block_I_raw ); wire [2:0] ch_II, ch_III, ch_IV, ch_V, ch_VI; wire [4:0] req_opch_I = { op, ch }; wire [4:0] req_opch_II, req_opch_III, req_opch_IV, req_opch_V, req_opch_VI; jt12_sumch u_opch_II ( .chin(req_opch_I ), .chout(req_opch_II) ); jt12_sumch u_opch_III( .chin(req_opch_II ), .chout(req_opch_III) ); jt12_sumch u_opch_IV ( .chin(req_opch_III), .chout(req_opch_IV) ); jt12_sumch u_opch_V ( .chin(req_opch_IV ), .chout(req_opch_V) ); jt12_sumch u_opch_VI ( .chin(req_opch_V ), .chout(req_opch_VI) ); wire update_op_I = cur == req_opch_I; wire update_op_II = cur == req_opch_II; wire update_op_III= cur == req_opch_III; // wire update_op_IV = cur == opch_IV; wire update_op_V = cur == req_opch_V; // wire update_op_VI = cur == opch_VI; wire [2:0] op_plus1 = op+2'd1; wire update_op_VII= cur == { op_plus1[1:0], ch }; // key on/off wire [3:0] keyon_op = din[7:4]; wire [2:0] keyon_ch = din[2:0]; // channel data wire [1:0] rl_in = din[7:6]; wire [2:0] fb_in = din[5:3]; wire [2:0] alg_in = din[2:0]; wire [2:0] pms_in = din[2:0]; wire [1:0] ams_in = din[5:4]; wire [2:0] block_in= din[5:3]; wire [2:0] fnhi_in = din[2:0]; wire [7:0] fnlo_in = din; // operator data wire [2:0] dt1_in = din[6:4]; wire [3:0] mul_in = din[3:0]; wire [6:0] tl_in = din[6:0]; wire [1:0] ks_in = din[7:6]; wire [4:0] ar_in = din[4:0]; wire amen_in = din[7]; wire [4:0] d1r_in = din[4:0]; wire [4:0] d2r_in = din[4:0]; wire [3:0] d1l_in = din[7:4]; wire [3:0] rr_in = din[3:0]; wire [3:0] ssg_in = din[3:0]; wire [3:0] ssg; reg last; wire update_ch_I = cur_ch == ch; wire up_alg_ch = up_alg & update_ch_I; wire up_block_ch= up_block & update_ch_I; wire up_fnumlo_ch=up_fnumlo & update_ch_I; wire up_pms_ch = up_pms & update_ch_I; // DT1 & MUL wire up_dt1_op = up_dt1 & update_op_II; wire up_mul_op = up_dt1 & update_op_V; // TL wire up_tl_op = up_tl & update_op_VII; // KS & AR wire up_ks_op = up_ks_ar & update_op_III; wire up_ar_op = up_ks_ar & update_op_II; // AM ON, D1R wire up_amen_op = up_amen_d1r & update_op_VII; wire up_d1r_op = up_amen_d1r & update_op_II; // Sustain Rate (D2R) wire up_d2r_op = up_d2r & update_op_II; // D1L & RR wire up_d1l_op = up_d1l & update_op_I; wire up_rr_op = up_d1l & update_op_II; // SSG //wire up_ssgen_op = up_ssgeg & update_op_I; wire up_ssg_op = up_ssgeg & update_op_II; wire up = up_alg | up_block | up_fnumlo | up_pms | up_dt1 | up_tl | up_ks_ar | up_amen_d1r | up_d2r | up_d1l | up_ssgeg | up_keyon; always @(*) begin // next <= cur==5'd23 ? 5'd0 : cur +1'b1; next_op <= cur_ch==3'd6 ? cur_op+1'b1 : cur_op; next_ch <= cur_ch[1:0]==2'b10 ? cur_ch+2'd2 : cur_ch+1'd1; end reg busy_op; reg up_keyon_long; assign busy = busy_op; always @(posedge clk) begin : up_counter if( rst ) begin cnt <= 5'h0; last <= 1'b0; zero <= 1'b1; busy_op <= 1'b0; up_keyon_long <= 1'b0; cur_op <= 2'd0; cur_ch <= 3'd0; end else begin { cur_op, cur_ch } <= { next_op, next_ch }; zero <= next == 5'd0; last <= up; if( up && !last ) begin cnt <= cur; busy_op <= 1'b1; up_keyon_long <= up_keyon; end else if( cnt == cur ) begin busy_op <= 1'b0; up_keyon_long <= 1'b0; end end end jt12_kon u_kon( .rst ( rst ), .clk ( clk ), .keyon_op ( keyon_op ), .keyon_ch ( keyon_ch ), .cur_op ( cur_op ), .cur_ch ( cur_ch ), .up_keyon ( up_keyon_long ), .csm ( csm ), .flag_A ( flag_A ), .overflow_A ( overflow_A), .keyon_II ( keyon_II ) ); jt12_mod u_mod( .alg_I ( alg ), .s1_enters ( s1_enters ), .s3_enters ( s3_enters ), .s2_enters ( s2_enters ), .s4_enters ( s4_enters ), .use_prevprev1 ( use_prevprev1 ), .use_internal_x( use_internal_x ), .use_internal_y( use_internal_y ), .use_prev2 ( use_prev2 ), .use_prev1 ( use_prev1 ) ); // memory for OP registers parameter regop_width=44; wire [regop_width-1:0] regop_in, regop_out; jt12_opram u_opram( .clk ( clk ), .wr_addr ( cur ), .rd_addr ( next ), .data ( regop_in ), .q ( regop_out ) ); assign regop_in = { up_tl_op ? tl_in : tl_VII, // 7 up_dt1_op ? dt1_in : dt1_II, // 3 up_mul_op ? mul_in : mul_V, // 4 - 7 up_ks_op ? ks_in : ks_III, // 2 - 16 up_ar_op ? ar_in : ar_II, // 5 - 21 up_amen_op ? amen_in: amsen_VII,// 1 - 22 up_d1r_op ? d1r_in : d1r_II, // 5 - 25 up_d2r_op ? d2r_in : d2r_II, // 5 - 30 up_d1l_op ? d1l_in : d1l, // 4 - 34 up_rr_op ? rr_in : rr_II, // 4 - 38 up_ssg_op ? ssg_in[3] : ssg_en_II, // 1 - 39 up_ssg_op ? ssg_in[2:0] : ssg_eg_II // 3 - 42 }; assign { tl_VII, dt1_II, mul_V, ks_III, ar_II, amsen_VII, d1r_II, d2r_II, d1l, rr_II, ssg_en_II, ssg_eg_II } = regop_out; wire [2:0] block_latch, fnum_latch; // memory for CH registers // Block/fnum data is latched until fnum low byte is written to // Trying to synthesize this memory as M-9K RAM in Altera devices // turns out worse in terms of resource utilization. Probably because // this memory is already very small. It is better to leave it as it is. parameter regch_width=31; wire [regch_width-1:0] regch_out; wire [regch_width-1:0] regch_in = { up_block_ch ? { block_in, fnhi_in } : { block_latch, fnum_latch }, // 3+3 up_fnumlo_ch? { block_latch, fnum_latch, fnlo_in } : { block_I_raw, fnum_I_raw }, // 14 up_alg_ch ? { fb_in, alg_in } : { fb_I, alg },//3+3 up_pms_ch ? { ams_in, pms_in } : { ams_VII, pms }//2+2+3 }; assign { block_latch, fnum_latch, block_I_raw, fnum_I_raw, fb_I, alg, ams_VII, pms } = regch_out; jt12_sh #(.width(regch_width),.stages(6)) u_regch( .clk ( clk ), //.rst ( rst ), .din ( regch_in ), .drop ( regch_out ) ); // RL is on a different register to // have the reset to 1 jt12_sh_rst #(.width(2),.stages(6),.rstval(1'b1)) u_regch_rl( .clk ( clk ), // .rst ( rst ), .din ( up_pms_ch ? rl_in : rl ), .drop ( rl ) ); endmodule