- // part of NeoGS project (c) 2007-2008 NedoPC 
- // 
- // sound_mulacc is a serial multiplier-accumulator for volume and sound data value. 
- // Input data is: volume (6bit unsigned) and sound data (8bit signed with sign bit inverted, 
- //  thus compatible with unsigned data centered at $7f-$80), and clr_sum bit. 
- // Input data is read and multiply-add starts after 1-clock positive pulse on load pin, 
- //  when ready becomes 1, operation is finished, output is defined and another load pulse could be accepted. 
- // If clr_sum is read to be 1, sum is also cleared (and the output will be just result of multiply), otherwise 
- //  output will be the sum of previous result with current multiplication result. 
- // 
- // clock number          XX |  00 |  01 |  02 |  || |  14 |  15 |  16 | 
- // clock            __/``\__/``\__/``\__/``\__/``||_/``\__/``\__/``\__/``\__/``\__/``\__/``\__/`` 
- // load       _________/`````\___________________||______________________________________________ 
- // inputs are read here --> *                    || 
- // ready      ```````````````\___________________||______________/``````````````````````````````` 
- // data out               old data |XXXXXXXXXXXXX||XXXXXXXXXXXXXX| new data ready 
-   
- module sound_mulacc( 
-   
-         clock,   // input clock (24 MHz) 
-   
-         vol_in,  // input volume (6 bit unsigned) 
-         dat_in,  // input sound data (8 bit signed with sign bit inverted) 
-   
-         mode_inv7b, // whether to invert 7th bit of dat_in 
-   
-         load,    // load pulse input 
-         clr_sum, // clear sum input 
-   
-         ready,   // ready output 
-         sum_out  // 16-bit sum output 
- ); 
-   
-         input clock; 
-   
-         input [5:0] vol_in; 
-         input [7:0] dat_in; 
-   
-         input mode_inv7b; 
-   
-         input load; 
-         input clr_sum; 
-   
-         output reg ready; 
-   
-         output reg [15:0] sum_out; 
-   
-   
-   
-         wire [5:0] add_data; 
-         wire [6:0] sum_unreg; 
-         reg [6:0] sum_reg; 
-         reg [7:0] shifter; 
-         reg [5:0] adder; 
-         wire   mul_out; 
-   
-   
-   
-         reg [3:0] counter; 
-   
-   
-         reg clr_sum_reg; 
-         wire [1:0] temp_sum; 
-         wire carry_in; 
-         wire old_data_in; 
-         reg old_carry; 
-   
-   
-   
-   
-         // control section 
-         // 
-         always @(posedge clock) 
-         begin 
-   
-                 if( load ) 
-                         ready <= 1'b0; 
-   
-                 if( counter[3:0] == 4'd15 ) 
-                         ready <= 1'b1; 
-   
-                 if( load ) 
-                         counter <= 4'd0; 
-                 else 
-                         counter <= counter + 4'd1; 
-   
-         end 
-   
-   
-   
-         // serial multiplier section 
-         // 
-         assign add_data = ( shifter[0] ) ? adder : 6'd0; // data to be added controlled by LSB of shifter 
-   
-         assign sum_unreg[6:0] = sum_reg[6:1] + add_data[5:0]; // sum of two values 
-   
-         assign mul_out = sum_unreg[0]; 
-   
-         always @(posedge clock) 
-         begin 
-   
-                 if( !load ) // normal addition 
-                 begin 
-                         sum_reg[6:0] <= sum_unreg[6:0]; 
-                         shifter[6:0] <= shifter[7:1]; 
-                 end 
-   
-                 else // load==1 
-   
-                 begin 
-                         sum_reg[6:0] <= 7'd0; 
-   
-                         shifter[7]   <= ~(mode_inv7b^dat_in[7]);   // convert to signed data (we need signed result), invert 7th bit if needed 
-                         shifter[6:0] <=  dat_in[6:0]; 
-   
-                         adder <= vol_in; 
-   
-                 end 
-         end 
-   
-   
-   
-   
-         // serial adder section 
-         // 
-         always @(posedge clock) 
-         begin 
-                 if( load ) 
-                         clr_sum_reg <= clr_sum; 
-         end 
-   
-         assign carry_in = (counter==4'd0) ? 1'b0 : old_carry; 
-   
-         assign old_data_in = (clr_sum_reg) ? 1'b0 : sum_out[0]; 
-   
-         assign temp_sum[1:0] = carry_in + mul_out + old_data_in; 
-   
-         always @(posedge clock) 
-         begin 
-                 if( !ready ) 
-                 begin 
-                         sum_out[15:0] <= { temp_sum[0], sum_out[15:1] }; 
-                         old_carry <= temp_sum[1]; 
-                 end 
-         end 
-   
-   
-   
- endmodule 
-   
-