diff --git a/README.md b/README.md index fcca6a9..96e4dea 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ # jt12 -FM sound source written in Verilog, fully compatible with YM2612 + +FM sound source written in Verilog, fully compatible with YM2612 and YM2203. + +The implementation tries to be as close to original hardware as possible. Low usage of FPGA resources has also been a design goal. Except in the operator section (jt12_op) where an exact replica of the original circuit is done. This could be done in less space with a different style but because this piece of the circuit was reversed engineered by Sauraen, I decided to use that knowledge. + +Directories: + +hdl -> all relevant RTL files, written in verilog +ver -> test benches +ver/verilator -> test bench that can play vgm files + +Usage: + +YM2612: top level file "jt12.v". Use jt12.qip to automatically get all relevant files in Quartus. + YM2612 should have parameters set like: + use_lfo = 1 + use_psg = 0 + +YM2203: top level file "jt12.v". Use jt03.qip to automatically get all relevant files in Quartus. + YM2203 should have parameters set like: + use_lfo = 0 + use_psg = 1 + diff --git a/hdl/jt03.qip b/hdl/jt03.qip new file mode 100644 index 0000000..d3ff87e --- /dev/null +++ b/hdl/jt03.qip @@ -0,0 +1,36 @@ +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) jt12.vhd ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_step.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_pure.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_final.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_ctrl.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_limitamp.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_opram.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_inc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_dt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_sum.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_phrom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49.h ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_div.h ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_eg.h ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_exp.h ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_noise.h ] diff --git a/hdl/jt03.v b/hdl/jt03.v deleted file mode 100644 index f950d1e..0000000 --- a/hdl/jt03.v +++ /dev/null @@ -1,85 +0,0 @@ -/* This file is part of JT12. - - JT12 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 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-2016 - - - - YM2203 clone, based upon JT12 (YM2612) and JT49 (YM2149) - - - */ - - - -module jt03 ( - input rst, // rst should be at least 6 clk&cen cycles long - input clk, // CPU clock - input cen, // optional clock enable, it not needed leave as 1'b1 - input [7:0] din, - input [1:0] addr, - input cs_n, - input wr_n, - input limiter_en, - - output [7:0] dout, - output irq_n, - // combined output - output signed [11:0] snd_right, - output signed [11:0] snd_left, - output snd_sample, - // multiplexed output - output signed [8:0] mux_right, - output signed [8:0] mux_left, - output mux_sample -); - - -jt12 u_fm( - .rst ( rst ), // rst should be at least 6 clk&cen cycles long - .clk ( clk ), // CPU clock - .cen ( cen ), // optional clock enable, it not needed leave as 1'b1 - .din ( din ), - .addr ( addr ), - .cs_n ( cs_n ), - .wr_n ( wr_n ), - .limiter_en ( limiter_en ), - .dout ( dout ), - .irq_n ( irq_n ), - .snd_right ( snd_right ), - .snd_left ( snd_left ), - .snd_sample ( snd_sample), - .mux_right ( mux_right ), - .mux_left ( mux_left ), - .mux_sample ( mux_sample) -); - -wire [9:0] ssg_sound; - -jt49 u_ssg( // note that input ports are not multiplexed - .rst_n ( ~rst ), - .clk ( clk ), // signal on positive edge - .cen ( cen ), // clock enable on negative edge - .addr ( addr ), - .cs_n ( cs_n ), - .wr_n ( wr_n ), // write - .din ( din ), - .sound ( sound ), -); - - -endmodule // jt03 \ No newline at end of file diff --git a/hdl/jt12.v b/hdl/jt12.v index 59df565..06a0093 100644 --- a/hdl/jt12.v +++ b/hdl/jt12.v @@ -315,7 +315,8 @@ jt12_sh #(.width(10),.stages(4)) u_egpad( .drop ( eg_IX ) ); -wire [8:0] op_result; +wire [ 8:0] op_result; +wire [13:0] full_result; jt12_op u_op( .rst ( rst ), @@ -336,7 +337,8 @@ jt12_op u_op( .use_prev2 ( use_prev2 ), .use_prev1 ( use_prev1 ), .zero ( zero ), - .op_result ( op_result ) + .op_result ( op_result ), + .full_result ( full_result ) ); wire signed [11:0] fm_snd_left, fm_snd_right; diff --git a/hdl/jt12_op.v b/hdl/jt12_op.v index cdd2c46..58205be 100644 --- a/hdl/jt12_op.v +++ b/hdl/jt12_op.v @@ -4,125 +4,127 @@ /* 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 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. + 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 . + You should have received a copy of the GNU General Public License + along with JT12. If not, see . - Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. + Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. - Author: Jose Tejada Gomez. Twitter: @topapate - Version: 1.0 - Date: 27-1-2017 + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 */ module jt12_op( - input rst, - input clk, - input clk_en, - input [9:0] pg_phase_VIII, - input [9:0] eg_atten_IX, // output from envelope generator - input [2:0] fb_II, // voice feedback - input use_prevprev1, - input use_internal_x, - input use_internal_y, - input use_prev2, - input use_prev1, - input test_214, - - input s1_enters, - input s2_enters, - input s3_enters, - input s4_enters, - input zero, + input rst, + input clk, + input clk_en, + input [9:0] pg_phase_VIII, + input [9:0] eg_atten_IX, // output from envelope generator + input [2:0] fb_II, // voice feedback + input use_prevprev1, + input use_internal_x, + input use_internal_y, + input use_prev2, + input use_prev1, + input test_214, - output signed [8:0] op_result + input s1_enters, + input s2_enters, + input s3_enters, + input s4_enters, + input zero, + + output signed [ 8:0] op_result, + output signed [13:0] full_result ); -/* enters exits - S1 S2 - S3 S4 - S2 S1 - S4 S3 +/* enters exits + S1 S2 + S3 S4 + S2 S1 + S4 S3 */ -reg [13:0] op_result_internal, op_XII; -reg [11:0] atten_internal_IX; +reg [13:0] op_result_internal, op_XII; +reg [11:0] atten_internal_IX; -assign op_result = op_result_internal[13:5]; +assign op_result = op_result_internal[13:5]; +assign full_result = op_result_internal; parameter NUM_VOICES = 6; -reg signbit_IX, signbit_X, signbit_XI; -reg [11:0] totalatten_X; +reg signbit_IX, signbit_X, signbit_XI; +reg [11:0] totalatten_X; -wire [13:0] prev1, prevprev1, prev2; +wire [13:0] prev1, prevprev1, prev2; jt12_sh #( .width(14), .stages(NUM_VOICES)) prev1_buffer( -// .rst ( rst ), - .clk ( clk ), - .clk_en ( clk_en), - .din ( s2_enters ? op_result_internal : prev1 ), - .drop ( prev1 ) +// .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en), + .din ( s2_enters ? op_result_internal : prev1 ), + .drop ( prev1 ) ); jt12_sh #( .width(14), .stages(NUM_VOICES)) prevprev1_buffer( -// .rst ( rst ), - .clk ( clk ), - .clk_en ( clk_en), - .din ( s2_enters ? prev1 : prevprev1 ), - .drop ( prevprev1 ) +// .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en), + .din ( s2_enters ? prev1 : prevprev1 ), + .drop ( prevprev1 ) ); jt12_sh #( .width(14), .stages(NUM_VOICES)) prev2_buffer( -// .rst ( rst ), - .clk ( clk ), - .clk_en ( clk_en), - .din ( s1_enters ? op_result_internal : prev2 ), - .drop ( prev2 ) +// .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en), + .din ( s1_enters ? op_result_internal : prev2 ), + .drop ( prev2 ) ); -reg [18:0] stb; -reg [10:0] stf, stg; -reg [11:0] logsin; -reg [10:0] subtresult; +reg [18:0] stb; +reg [10:0] stf, stg; +reg [11:0] logsin; +reg [10:0] subtresult; -reg [12:0] etb; -reg [ 9:0] etf, mantissa_XI; -reg [ 2:0] etg; -reg [ 3:0] exponent_XI; +reg [12:0] etb; +reg [ 9:0] etf, mantissa_XI; +reg [ 2:0] etg; +reg [ 3:0] exponent_XI; -reg [12:0] shifter, shifter_2, shifter_3; +reg [12:0] shifter, shifter_2, shifter_3; // REGISTER/CYCLE 1 // Creation of phase modulation (FM) feedback signal, before shifting reg [13:0] x, y; -reg [14:0] xs, ys, pm_preshift_II; -reg s1_II; +reg [14:0] xs, ys, pm_preshift_II; +reg s1_II; always @(*) begin - x = ( {14{use_prevprev1}} & prevprev1 ) | - ( {14{use_internal_x}} & op_result_internal ) | + x = ( {14{use_prevprev1}} & prevprev1 ) | + ( {14{use_internal_x}} & op_result_internal ) | ( {14{use_prev2}} & prev2 ); - y = ( {14{use_prev1}} & prev1 ) | - ( {14{use_internal_y}} & op_result_internal ); - xs = { x[13], x }; // sign-extend - ys = { y[13], y }; // sign-extend + y = ( {14{use_prev1}} & prev1 ) | + ( {14{use_internal_y}} & op_result_internal ); + xs = { x[13], x }; // sign-extend + ys = { y[13], y }; // sign-extend end always @(posedge clk) if( clk_en ) begin - pm_preshift_II <= xs + ys; // carry is discarded + pm_preshift_II <= xs + ys; // carry is discarded s1_II <= s1_enters; end @@ -133,61 +135,61 @@ end are 6 cycles worth of registers between the generated (non-registered) phasemod_II signal and the input to add_pg_phase. */ -reg [9:0] phasemod_II; -wire [9:0] phasemod_VIII; +reg [9:0] phasemod_II; +wire [9:0] phasemod_VIII; always @(*) begin - // Shift FM feedback signal - if (!s1_II ) // Not S1 - phasemod_II = pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used - else // S1 - case( fb_II ) - 3'd0: phasemod_II = 10'd0; - 3'd1: phasemod_II = { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] }; - 3'd2: phasemod_II = { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] }; - 3'd3: phasemod_II = { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] }; - 3'd4: phasemod_II = { pm_preshift_II[14], pm_preshift_II[14:6] }; - 3'd5: phasemod_II = pm_preshift_II[14:5]; - 3'd6: phasemod_II = pm_preshift_II[13:4]; - 3'd7: phasemod_II = pm_preshift_II[12:3]; - endcase + // Shift FM feedback signal + if (!s1_II ) // Not S1 + phasemod_II = pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used + else // S1 + case( fb_II ) + 3'd0: phasemod_II = 10'd0; + 3'd1: phasemod_II = { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] }; + 3'd2: phasemod_II = { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] }; + 3'd3: phasemod_II = { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] }; + 3'd4: phasemod_II = { pm_preshift_II[14], pm_preshift_II[14:6] }; + 3'd5: phasemod_II = pm_preshift_II[14:5]; + 3'd6: phasemod_II = pm_preshift_II[13:4]; + 3'd7: phasemod_II = pm_preshift_II[12:3]; + endcase end // REGISTER/CYCLE 2-7 jt12_sh #( .width(10), .stages(NUM_VOICES)) phasemod_sh( - .clk ( clk ), - .clk_en ( clk_en), - .din ( phasemod_II ), - .drop ( phasemod_VIII ) + .clk ( clk ), + .clk_en ( clk_en), + .din ( phasemod_II ), + .drop ( phasemod_VIII ) ); // REGISTER/CYCLE 8 -reg [ 9:0] phase; +reg [ 9:0] phase; // Sets the maximum number of fanouts for a register or combinational // cell. The Quartus II software will replicate the cell and split // the fanouts among the duplicates until the fanout of each cell // is below the maximum. -reg [ 7:0] phaselo_IX, aux_VIII; +reg [ 7:0] phaselo_IX, aux_VIII; always @(*) begin - phase = phasemod_VIII + pg_phase_VIII; - aux_VIII= phase[7:0] ^ {8{~phase[8]}}; + phase = phasemod_VIII + pg_phase_VIII; + aux_VIII= phase[7:0] ^ {8{~phase[8]}}; end always @(posedge clk) if( clk_en ) begin - phaselo_IX <= aux_VIII; - signbit_IX <= phase[9]; + phaselo_IX <= aux_VIII; + signbit_IX <= phase[9]; end wire [45:0] sta_IX; jt12_phrom u_phrom( - .clk ( clk ), - .clk_en ( clk_en ), - .addr ( aux_VIII[5:1] ), - .ph ( sta_IX ) + .clk ( clk ), + .clk_en ( clk_en ), + .addr ( aux_VIII[5:1] ), + .ph ( sta_IX ) ); // REGISTER/CYCLE 9 @@ -196,57 +198,57 @@ jt12_phrom u_phrom( always @(*) begin - //sta_IX <= sinetable[ phaselo_IX[5:1] ]; - // 2-bit row chooser - case( phaselo_IX[7:6] ) - 2'b00: stb = { 10'b0, sta_IX[29], sta_IX[25], 2'b0, sta_IX[18], - sta_IX[14], 1'b0, sta_IX[7] , sta_IX[3] }; - 2'b01: stb = { 6'b0 , sta_IX[37], sta_IX[34], 2'b0, sta_IX[28], - sta_IX[24], 2'b0, sta_IX[17], sta_IX[13], sta_IX[10], sta_IX[6], sta_IX[2] }; - 2'b10: stb = { 2'b0, sta_IX[43], sta_IX[41], 2'b0, sta_IX[36], - sta_IX[33], 2'b0, sta_IX[27], sta_IX[23], 1'b0, sta_IX[20], + //sta_IX <= sinetable[ phaselo_IX[5:1] ]; + // 2-bit row chooser + case( phaselo_IX[7:6] ) + 2'b00: stb = { 10'b0, sta_IX[29], sta_IX[25], 2'b0, sta_IX[18], + sta_IX[14], 1'b0, sta_IX[7] , sta_IX[3] }; + 2'b01: stb = { 6'b0 , sta_IX[37], sta_IX[34], 2'b0, sta_IX[28], + sta_IX[24], 2'b0, sta_IX[17], sta_IX[13], sta_IX[10], sta_IX[6], sta_IX[2] }; + 2'b10: stb = { 2'b0, sta_IX[43], sta_IX[41], 2'b0, sta_IX[36], + sta_IX[33], 2'b0, sta_IX[27], sta_IX[23], 1'b0, sta_IX[20], sta_IX[16], sta_IX[12], sta_IX[9], sta_IX[5], sta_IX[1] }; - default: stb = { - sta_IX[45], sta_IX[44], sta_IX[42], sta_IX[40] - , sta_IX[39], sta_IX[38], sta_IX[35], sta_IX[32] - , sta_IX[31], sta_IX[30], sta_IX[26], sta_IX[22] - , sta_IX[21], sta_IX[19], sta_IX[15], sta_IX[11] - , sta_IX[8], sta_IX[4], sta_IX[0] }; - endcase - // Fixed value to sum - stf = { stb[18:15], stb[12:11], stb[8:7], stb[4:3], stb[0] }; - // Gated value to sum; bit 14 is indeed used twice - if( phaselo_IX[0] ) - stg = { 2'b0, stb[14], stb[14:13], stb[10:9], stb[6:5], stb[2:1] }; - else - stg = 11'd0; - // Sum to produce final logsin value - logsin = stf + stg; // Carry-out of 11-bit addition becomes 12th bit - // Invert-subtract logsin value from EG attenuation value, with inverted carry - // In the actual chip, the output of the above logsin sum is already inverted. - // The two LSBs go through inverters (so they're non-inverted); the eg_atten_IX signal goes through inverters. - // The adder is normal except the carry-in is 1. It's a 10-bit adder. - // The outputs are inverted outputs, including the carry bit. - //subtresult = not (('0' & not eg_atten_IX) - ('1' & logsin([11:2]))); - // After a little pencil-and-paper, turns out this is equivalent to a regular adder! - subtresult = eg_atten_IX + logsin[11:2]; - // Place all but carry bit into result; also two LSBs of logsin - // If addition overflowed, make it the largest value (saturate) - atten_internal_IX = { subtresult[9:0], logsin[1:0] } | {12{subtresult[10]}}; + default: stb = { + sta_IX[45], sta_IX[44], sta_IX[42], sta_IX[40] + , sta_IX[39], sta_IX[38], sta_IX[35], sta_IX[32] + , sta_IX[31], sta_IX[30], sta_IX[26], sta_IX[22] + , sta_IX[21], sta_IX[19], sta_IX[15], sta_IX[11] + , sta_IX[8], sta_IX[4], sta_IX[0] }; + endcase + // Fixed value to sum + stf = { stb[18:15], stb[12:11], stb[8:7], stb[4:3], stb[0] }; + // Gated value to sum; bit 14 is indeed used twice + if( phaselo_IX[0] ) + stg = { 2'b0, stb[14], stb[14:13], stb[10:9], stb[6:5], stb[2:1] }; + else + stg = 11'd0; + // Sum to produce final logsin value + logsin = stf + stg; // Carry-out of 11-bit addition becomes 12th bit + // Invert-subtract logsin value from EG attenuation value, with inverted carry + // In the actual chip, the output of the above logsin sum is already inverted. + // The two LSBs go through inverters (so they're non-inverted); the eg_atten_IX signal goes through inverters. + // The adder is normal except the carry-in is 1. It's a 10-bit adder. + // The outputs are inverted outputs, including the carry bit. + //subtresult = not (('0' & not eg_atten_IX) - ('1' & logsin([11:2]))); + // After a little pencil-and-paper, turns out this is equivalent to a regular adder! + subtresult = eg_atten_IX + logsin[11:2]; + // Place all but carry bit into result; also two LSBs of logsin + // If addition overflowed, make it the largest value (saturate) + atten_internal_IX = { subtresult[9:0], logsin[1:0] } | {12{subtresult[10]}}; end wire [44:0] exp_X; jt12_exprom u_exprom( - .clk ( clk ), - .clk_en ( clk_en ), - .addr ( atten_internal_IX[5:1] ), - .exp ( exp_X ) + .clk ( clk ), + .clk_en ( clk_en ), + .addr ( atten_internal_IX[5:1] ), + .exp ( exp_X ) ); always @(posedge clk) if( clk_en ) begin - totalatten_X <= atten_internal_IX; - signbit_X <= signbit_IX; + totalatten_X <= atten_internal_IX; + signbit_X <= signbit_IX; end //wire [1:0] et_sel = totalatten_X[7:6]; @@ -256,62 +258,62 @@ end // Exponential table // Main sine table body always @(*) begin - //eta <= explut_jt51[ totalatten_X[5:1] ]; - // 2-bit row chooser - case( totalatten_X[7:6] ) - 2'b00: begin - etf = { 1'b1, exp_X[44:36] }; - etg = { 1'b1, exp_X[35:34] }; - end - 2'b01: begin - etf = exp_X[33:24]; - etg = { 2'b10, exp_X[23] }; - end - 2'b10: begin - etf = { 1'b0, exp_X[22:14] }; - etg = exp_X[13:11]; - end - 2'b11: begin - etf = { 2'b00, exp_X[10:3] }; - etg = exp_X[2:0]; - end - - endcase + //eta <= explut_jt51[ totalatten_X[5:1] ]; + // 2-bit row chooser + case( totalatten_X[7:6] ) + 2'b00: begin + etf = { 1'b1, exp_X[44:36] }; + etg = { 1'b1, exp_X[35:34] }; + end + 2'b01: begin + etf = exp_X[33:24]; + etg = { 2'b10, exp_X[23] }; + end + 2'b10: begin + etf = { 1'b0, exp_X[22:14] }; + etg = exp_X[13:11]; + end + 2'b11: begin + etf = { 2'b00, exp_X[10:3] }; + etg = exp_X[2:0]; + end + + endcase end always @(posedge clk) if( clk_en ) begin //RESULT - mantissa_XI <= etf + { 7'd0, ( totalatten_X[0] ? 3'd0 : etg )}; //carry-out discarded - exponent_XI <= totalatten_X[11:8]; - signbit_XI <= signbit_X; + mantissa_XI <= etf + { 7'd0, ( totalatten_X[0] ? 3'd0 : etg )}; //carry-out discarded + exponent_XI <= totalatten_X[11:8]; + signbit_XI <= signbit_X; end // REGISTER/CYCLE 11 // Introduce test bit as MSB, 2's complement & Carry-out discarded always @(*) begin - // Floating-point to integer, and incorporating sign bit - // Two-stage shifting of mantissa_XI by exponent_XI - shifter = { 3'b001, mantissa_XI }; - case( ~exponent_XI[1:0] ) - 2'b00: shifter_2 = { 1'b0, shifter[12:1] }; // LSB discarded - 2'b01: shifter_2 = shifter; - 2'b10: shifter_2 = { shifter[11:0], 1'b0 }; - 2'b11: shifter_2 = { shifter[10:0], 2'b0 }; - endcase - case( ~exponent_XI[3:2] ) - 2'b00: shifter_3 = {12'b0, shifter_2[12] }; - 2'b01: shifter_3 = { 8'b0, shifter_2[12:8] }; - 2'b10: shifter_3 = { 4'b0, shifter_2[12:4] }; - 2'b11: shifter_3 = shifter_2; - endcase + // Floating-point to integer, and incorporating sign bit + // Two-stage shifting of mantissa_XI by exponent_XI + shifter = { 3'b001, mantissa_XI }; + case( ~exponent_XI[1:0] ) + 2'b00: shifter_2 = { 1'b0, shifter[12:1] }; // LSB discarded + 2'b01: shifter_2 = shifter; + 2'b10: shifter_2 = { shifter[11:0], 1'b0 }; + 2'b11: shifter_2 = { shifter[10:0], 2'b0 }; + endcase + case( ~exponent_XI[3:2] ) + 2'b00: shifter_3 = {12'b0, shifter_2[12] }; + 2'b01: shifter_3 = { 8'b0, shifter_2[12:8] }; + 2'b10: shifter_3 = { 4'b0, shifter_2[12:4] }; + 2'b11: shifter_3 = shifter_2; + endcase end always @(posedge clk) if( clk_en ) begin - // REGISTER CYCLE 11 - op_XII <= ({ test_214, shifter_3 } ^ {14{signbit_XI}}) + {13'd0,signbit_XI}; - // REGISTER CYCLE 12 - // Extra register, take output after here + // REGISTER CYCLE 11 + op_XII <= ({ test_214, shifter_3 } ^ {14{signbit_XI}}) + {13'd0,signbit_XI}; + // REGISTER CYCLE 12 + // Extra register, take output after here op_result_internal <= op_XII; end @@ -320,228 +322,228 @@ end reg [4:0] sep24_cnt; wire signed [13:0] op_ch0s1, op_ch1s1, op_ch2s1, op_ch3s1, - op_ch4s1, op_ch5s1, op_ch0s2, op_ch1s2, - op_ch2s2, op_ch3s2, op_ch4s2, op_ch5s2, - op_ch0s3, op_ch1s3, op_ch2s3, op_ch3s3, - op_ch4s3, op_ch5s3, op_ch0s4, op_ch1s4, - op_ch2s4, op_ch3s4, op_ch4s4, op_ch5s4; + op_ch4s1, op_ch5s1, op_ch0s2, op_ch1s2, + op_ch2s2, op_ch3s2, op_ch4s2, op_ch5s2, + op_ch0s3, op_ch1s3, op_ch2s3, op_ch3s3, + op_ch4s3, op_ch5s3, op_ch0s4, op_ch1s4, + op_ch2s4, op_ch3s4, op_ch4s4, op_ch5s4; always @(posedge clk ) if( clk_en ) begin - sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0; + sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0; end sep24 #( .width(14), .pos0(13)) opsep ( - .clk ( clk ), - .clk_en ( clk_en ), - .mixed ( op_result_internal ), - .mask ( 24'd0 ), - .cnt ( sep24_cnt ), - - .ch0s1 (op_ch0s1), - .ch1s1 (op_ch1s1), - .ch2s1 (op_ch2s1), - .ch3s1 (op_ch3s1), - .ch4s1 (op_ch4s1), - .ch5s1 (op_ch5s1), - - .ch0s2 (op_ch0s2), - .ch1s2 (op_ch1s2), - .ch2s2 (op_ch2s2), - .ch3s2 (op_ch3s2), - .ch4s2 (op_ch4s2), - .ch5s2 (op_ch5s2), - - .ch0s3 (op_ch0s3), - .ch1s3 (op_ch1s3), - .ch2s3 (op_ch2s3), - .ch3s3 (op_ch3s3), - .ch4s3 (op_ch4s3), - .ch5s3 (op_ch5s3), - - .ch0s4 (op_ch0s4), - .ch1s4 (op_ch1s4), - .ch2s4 (op_ch2s4), - .ch3s4 (op_ch3s4), - .ch4s4 (op_ch4s4), - .ch5s4 (op_ch5s4) + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( op_result_internal ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (op_ch0s1), + .ch1s1 (op_ch1s1), + .ch2s1 (op_ch2s1), + .ch3s1 (op_ch3s1), + .ch4s1 (op_ch4s1), + .ch5s1 (op_ch5s1), + + .ch0s2 (op_ch0s2), + .ch1s2 (op_ch1s2), + .ch2s2 (op_ch2s2), + .ch3s2 (op_ch3s2), + .ch4s2 (op_ch4s2), + .ch5s2 (op_ch5s2), + + .ch0s3 (op_ch0s3), + .ch1s3 (op_ch1s3), + .ch2s3 (op_ch2s3), + .ch3s3 (op_ch3s3), + .ch4s3 (op_ch4s3), + .ch5s3 (op_ch5s3), + + .ch0s4 (op_ch0s4), + .ch1s4 (op_ch1s4), + .ch2s4 (op_ch2s4), + .ch3s4 (op_ch3s4), + .ch4s4 (op_ch4s4), + .ch5s4 (op_ch5s4) ); wire signed [8:0] acc_ch0s1, acc_ch1s1, acc_ch2s1, acc_ch3s1, - acc_ch4s1, acc_ch5s1, acc_ch0s2, acc_ch1s2, - acc_ch2s2, acc_ch3s2, acc_ch4s2, acc_ch5s2, - acc_ch0s3, acc_ch1s3, acc_ch2s3, acc_ch3s3, - acc_ch4s3, acc_ch5s3, acc_ch0s4, acc_ch1s4, - acc_ch2s4, acc_ch3s4, acc_ch4s4, acc_ch5s4; + acc_ch4s1, acc_ch5s1, acc_ch0s2, acc_ch1s2, + acc_ch2s2, acc_ch3s2, acc_ch4s2, acc_ch5s2, + acc_ch0s3, acc_ch1s3, acc_ch2s3, acc_ch3s3, + acc_ch4s3, acc_ch5s3, acc_ch0s4, acc_ch1s4, + acc_ch2s4, acc_ch3s4, acc_ch4s4, acc_ch5s4; sep24 #( .width(9), .pos0(13)) accsep ( - .clk ( clk ), - .clk_en ( clk_en ), - .mixed ( op_result_internal[13:5] ), - .mask ( 24'd0 ), - .cnt ( sep24_cnt ), - - .ch0s1 (acc_ch0s1), - .ch1s1 (acc_ch1s1), - .ch2s1 (acc_ch2s1), - .ch3s1 (acc_ch3s1), - .ch4s1 (acc_ch4s1), - .ch5s1 (acc_ch5s1), - - .ch0s2 (acc_ch0s2), - .ch1s2 (acc_ch1s2), - .ch2s2 (acc_ch2s2), - .ch3s2 (acc_ch3s2), - .ch4s2 (acc_ch4s2), - .ch5s2 (acc_ch5s2), - - .ch0s3 (acc_ch0s3), - .ch1s3 (acc_ch1s3), - .ch2s3 (acc_ch2s3), - .ch3s3 (acc_ch3s3), - .ch4s3 (acc_ch4s3), - .ch5s3 (acc_ch5s3), - - .ch0s4 (acc_ch0s4), - .ch1s4 (acc_ch1s4), - .ch2s4 (acc_ch2s4), - .ch3s4 (acc_ch3s4), - .ch4s4 (acc_ch4s4), - .ch5s4 (acc_ch5s4) + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( op_result_internal[13:5] ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (acc_ch0s1), + .ch1s1 (acc_ch1s1), + .ch2s1 (acc_ch2s1), + .ch3s1 (acc_ch3s1), + .ch4s1 (acc_ch4s1), + .ch5s1 (acc_ch5s1), + + .ch0s2 (acc_ch0s2), + .ch1s2 (acc_ch1s2), + .ch2s2 (acc_ch2s2), + .ch3s2 (acc_ch3s2), + .ch4s2 (acc_ch4s2), + .ch5s2 (acc_ch5s2), + + .ch0s3 (acc_ch0s3), + .ch1s3 (acc_ch1s3), + .ch2s3 (acc_ch2s3), + .ch3s3 (acc_ch3s3), + .ch4s3 (acc_ch4s3), + .ch5s3 (acc_ch5s3), + + .ch0s4 (acc_ch0s4), + .ch1s4 (acc_ch1s4), + .ch2s4 (acc_ch2s4), + .ch3s4 (acc_ch3s4), + .ch4s4 (acc_ch4s4), + .ch5s4 (acc_ch5s4) ); wire signed [9:0] pm_ch0s1, pm_ch1s1, pm_ch2s1, pm_ch3s1, - pm_ch4s1, pm_ch5s1, pm_ch0s2, pm_ch1s2, - pm_ch2s2, pm_ch3s2, pm_ch4s2, pm_ch5s2, - pm_ch0s3, pm_ch1s3, pm_ch2s3, pm_ch3s3, - pm_ch4s3, pm_ch5s3, pm_ch0s4, pm_ch1s4, - pm_ch2s4, pm_ch3s4, pm_ch4s4, pm_ch5s4; + pm_ch4s1, pm_ch5s1, pm_ch0s2, pm_ch1s2, + pm_ch2s2, pm_ch3s2, pm_ch4s2, pm_ch5s2, + pm_ch0s3, pm_ch1s3, pm_ch2s3, pm_ch3s3, + pm_ch4s3, pm_ch5s3, pm_ch0s4, pm_ch1s4, + pm_ch2s4, pm_ch3s4, pm_ch4s4, pm_ch5s4; sep24 #( .width(10), .pos0( 18 ) ) pmsep ( - .clk ( clk ), - .clk_en ( clk_en ), - .mixed ( phasemod_VIII ), - .mask ( 24'd0 ), - .cnt ( sep24_cnt ), - - .ch0s1 (pm_ch0s1), - .ch1s1 (pm_ch1s1), - .ch2s1 (pm_ch2s1), - .ch3s1 (pm_ch3s1), - .ch4s1 (pm_ch4s1), - .ch5s1 (pm_ch5s1), - - .ch0s2 (pm_ch0s2), - .ch1s2 (pm_ch1s2), - .ch2s2 (pm_ch2s2), - .ch3s2 (pm_ch3s2), - .ch4s2 (pm_ch4s2), - .ch5s2 (pm_ch5s2), - - .ch0s3 (pm_ch0s3), - .ch1s3 (pm_ch1s3), - .ch2s3 (pm_ch2s3), - .ch3s3 (pm_ch3s3), - .ch4s3 (pm_ch4s3), - .ch5s3 (pm_ch5s3), - - .ch0s4 (pm_ch0s4), - .ch1s4 (pm_ch1s4), - .ch2s4 (pm_ch2s4), - .ch3s4 (pm_ch3s4), - .ch4s4 (pm_ch4s4), - .ch5s4 (pm_ch5s4) + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( phasemod_VIII ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (pm_ch0s1), + .ch1s1 (pm_ch1s1), + .ch2s1 (pm_ch2s1), + .ch3s1 (pm_ch3s1), + .ch4s1 (pm_ch4s1), + .ch5s1 (pm_ch5s1), + + .ch0s2 (pm_ch0s2), + .ch1s2 (pm_ch1s2), + .ch2s2 (pm_ch2s2), + .ch3s2 (pm_ch3s2), + .ch4s2 (pm_ch4s2), + .ch5s2 (pm_ch5s2), + + .ch0s3 (pm_ch0s3), + .ch1s3 (pm_ch1s3), + .ch2s3 (pm_ch2s3), + .ch3s3 (pm_ch3s3), + .ch4s3 (pm_ch4s3), + .ch5s3 (pm_ch5s3), + + .ch0s4 (pm_ch0s4), + .ch1s4 (pm_ch1s4), + .ch2s4 (pm_ch2s4), + .ch3s4 (pm_ch3s4), + .ch4s4 (pm_ch4s4), + .ch5s4 (pm_ch5s4) ); wire [9:0] phase_ch0s1, phase_ch1s1, phase_ch2s1, phase_ch3s1, - phase_ch4s1, phase_ch5s1, phase_ch0s2, phase_ch1s2, - phase_ch2s2, phase_ch3s2, phase_ch4s2, phase_ch5s2, - phase_ch0s3, phase_ch1s3, phase_ch2s3, phase_ch3s3, - phase_ch4s3, phase_ch5s3, phase_ch0s4, phase_ch1s4, - phase_ch2s4, phase_ch3s4, phase_ch4s4, phase_ch5s4; + phase_ch4s1, phase_ch5s1, phase_ch0s2, phase_ch1s2, + phase_ch2s2, phase_ch3s2, phase_ch4s2, phase_ch5s2, + phase_ch0s3, phase_ch1s3, phase_ch2s3, phase_ch3s3, + phase_ch4s3, phase_ch5s3, phase_ch0s4, phase_ch1s4, + phase_ch2s4, phase_ch3s4, phase_ch4s4, phase_ch5s4; sep24 #( .width(10), .pos0( 18 ) ) phsep ( - .clk ( clk ), - .clk_en ( clk_en ), - .mixed ( phase ), - .mask ( 24'd0 ), - .cnt ( sep24_cnt ), - - .ch0s1 (phase_ch0s1), - .ch1s1 (phase_ch1s1), - .ch2s1 (phase_ch2s1), - .ch3s1 (phase_ch3s1), - .ch4s1 (phase_ch4s1), - .ch5s1 (phase_ch5s1), - - .ch0s2 (phase_ch0s2), - .ch1s2 (phase_ch1s2), - .ch2s2 (phase_ch2s2), - .ch3s2 (phase_ch3s2), - .ch4s2 (phase_ch4s2), - .ch5s2 (phase_ch5s2), - - .ch0s3 (phase_ch0s3), - .ch1s3 (phase_ch1s3), - .ch2s3 (phase_ch2s3), - .ch3s3 (phase_ch3s3), - .ch4s3 (phase_ch4s3), - .ch5s3 (phase_ch5s3), - - .ch0s4 (phase_ch0s4), - .ch1s4 (phase_ch1s4), - .ch2s4 (phase_ch2s4), - .ch3s4 (phase_ch3s4), - .ch4s4 (phase_ch4s4), - .ch5s4 (phase_ch5s4) + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( phase ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (phase_ch0s1), + .ch1s1 (phase_ch1s1), + .ch2s1 (phase_ch2s1), + .ch3s1 (phase_ch3s1), + .ch4s1 (phase_ch4s1), + .ch5s1 (phase_ch5s1), + + .ch0s2 (phase_ch0s2), + .ch1s2 (phase_ch1s2), + .ch2s2 (phase_ch2s2), + .ch3s2 (phase_ch3s2), + .ch4s2 (phase_ch4s2), + .ch5s2 (phase_ch5s2), + + .ch0s3 (phase_ch0s3), + .ch1s3 (phase_ch1s3), + .ch2s3 (phase_ch2s3), + .ch3s3 (phase_ch3s3), + .ch4s3 (phase_ch4s3), + .ch5s3 (phase_ch5s3), + + .ch0s4 (phase_ch0s4), + .ch1s4 (phase_ch1s4), + .ch2s4 (phase_ch2s4), + .ch3s4 (phase_ch3s4), + .ch4s4 (phase_ch4s4), + .ch5s4 (phase_ch5s4) ); wire [9:0] eg_ch0s1, eg_ch1s1, eg_ch2s1, eg_ch3s1, eg_ch4s1, eg_ch5s1, - eg_ch0s2, eg_ch1s2, eg_ch2s2, eg_ch3s2, eg_ch4s2, eg_ch5s2, - eg_ch0s3, eg_ch1s3, eg_ch2s3, eg_ch3s3, eg_ch4s3, eg_ch5s3, - eg_ch0s4, eg_ch1s4, eg_ch2s4, eg_ch3s4, eg_ch4s4, eg_ch5s4; + eg_ch0s2, eg_ch1s2, eg_ch2s2, eg_ch3s2, eg_ch4s2, eg_ch5s2, + eg_ch0s3, eg_ch1s3, eg_ch2s3, eg_ch3s3, eg_ch4s3, eg_ch5s3, + eg_ch0s4, eg_ch1s4, eg_ch2s4, eg_ch3s4, eg_ch4s4, eg_ch5s4; sep24 #( .width(10), .pos0(17) ) egsep ( - .clk ( clk ), - .clk_en ( clk_en ), - .mixed ( eg_atten_IX ), - .mask ( 24'd0 ), - .cnt ( sep24_cnt ), - - .ch0s1 (eg_ch0s1), - .ch1s1 (eg_ch1s1), - .ch2s1 (eg_ch2s1), - .ch3s1 (eg_ch3s1), - .ch4s1 (eg_ch4s1), - .ch5s1 (eg_ch5s1), - - .ch0s2 (eg_ch0s2), - .ch1s2 (eg_ch1s2), - .ch2s2 (eg_ch2s2), - .ch3s2 (eg_ch3s2), - .ch4s2 (eg_ch4s2), - .ch5s2 (eg_ch5s2), - - .ch0s3 (eg_ch0s3), - .ch1s3 (eg_ch1s3), - .ch2s3 (eg_ch2s3), - .ch3s3 (eg_ch3s3), - .ch4s3 (eg_ch4s3), - .ch5s3 (eg_ch5s3), - - .ch0s4 (eg_ch0s4), - .ch1s4 (eg_ch1s4), - .ch2s4 (eg_ch2s4), - .ch3s4 (eg_ch3s4), - .ch4s4 (eg_ch4s4), - .ch5s4 (eg_ch5s4) + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( eg_atten_IX ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (eg_ch0s1), + .ch1s1 (eg_ch1s1), + .ch2s1 (eg_ch2s1), + .ch3s1 (eg_ch3s1), + .ch4s1 (eg_ch4s1), + .ch5s1 (eg_ch5s1), + + .ch0s2 (eg_ch0s2), + .ch1s2 (eg_ch1s2), + .ch2s2 (eg_ch2s2), + .ch3s2 (eg_ch3s2), + .ch4s2 (eg_ch4s2), + .ch5s2 (eg_ch5s2), + + .ch0s3 (eg_ch0s3), + .ch1s3 (eg_ch1s3), + .ch2s3 (eg_ch2s3), + .ch3s3 (eg_ch3s3), + .ch4s3 (eg_ch4s3), + .ch5s3 (eg_ch5s3), + + .ch0s4 (eg_ch0s4), + .ch1s4 (eg_ch1s4), + .ch2s4 (eg_ch2s4), + .ch3s4 (eg_ch3s4), + .ch4s4 (eg_ch4s4), + .ch5s4 (eg_ch5s4) ); /* verilator lint_on PINMISSING */ `endif