Subversion Repositories ngs

Rev

Rev 6 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // part of NeoGS project (c) 2007-2008 NedoPC
  2. //
  3. // sound_mulacc is a serial multiplier-accumulator for volume and sound data value.
  4. // Input data is: volume (6bit unsigned) and sound data (8bit signed with sign bit inverted,
  5. //  thus compatible with unsigned data centered at $7f-$80), and clr_sum bit.
  6. // Input data is read and multiply-add starts after 1-clock positive pulse on load pin,
  7. //  when ready becomes 1, operation is finished, output is defined and another load pulse could be accepted.
  8. // If clr_sum is read to be 1, sum is also cleared (and the output will be just result of multiply), otherwise
  9. //  output will be the sum of previous result with current multiplication result.
  10. //
  11. // clock number          XX |  00 |  01 |  02 |  || |  14 |  15 |  16 |
  12. // clock            __/``\__/``\__/``\__/``\__/``||_/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``
  13. // load       _________/`````\___________________||______________________________________________
  14. // inputs are read here --> *                    ||
  15. // ready      ```````````````\___________________||______________/```````````````````````````````
  16. // data out               old data |XXXXXXXXXXXXX||XXXXXXXXXXXXXX| new data ready
  17.  
  18. module sound_mulacc(
  19.  
  20.         clock,   // input clock (24 MHz)
  21.  
  22.         vol_in,  // input volume (6 bit unsigned)
  23.         dat_in,  // input sound data (8 bit signed with sign bit inverted)
  24.  
  25.         mode_inv7b, // whether to invert 7th bit of dat_in
  26.  
  27.         load,    // load pulse input
  28.         clr_sum, // clear sum input
  29.  
  30.         ready,   // ready output
  31.         sum_out  // 16-bit sum output
  32. );
  33.  
  34.         input clock;
  35.  
  36.         input [5:0] vol_in;
  37.         input [7:0] dat_in;
  38.  
  39.         input mode_inv7b;
  40.  
  41.         input load;
  42.         input clr_sum;
  43.  
  44.         output reg ready;
  45.  
  46.         output reg [15:0] sum_out;
  47.  
  48.  
  49.  
  50.         wire [5:0] add_data;
  51.         wire [6:0] sum_unreg;
  52.         reg [6:0] sum_reg;
  53.         reg [7:0] shifter;
  54.         reg [5:0] adder;
  55.         wire   mul_out;
  56.  
  57.  
  58.  
  59.         reg [3:0] counter;
  60.  
  61.  
  62.         reg clr_sum_reg;
  63.         wire [1:0] temp_sum;
  64.         wire carry_in;
  65.         wire old_data_in;
  66.         reg old_carry;
  67.  
  68.  
  69.  
  70.  
  71.         // control section
  72.         //
  73.         always @(posedge clock)
  74.         begin
  75.  
  76.                 if( load )
  77.                         ready <= 1'b0;
  78.  
  79.                 if( counter[3:0] == 4'd15 )
  80.                         ready <= 1'b1;
  81.  
  82.                 if( load )
  83.                         counter <= 4'd0;
  84.                 else
  85.                         counter <= counter + 4'd1;
  86.  
  87.         end
  88.  
  89.  
  90.  
  91.         // serial multiplier section
  92.         //
  93.         assign add_data = ( shifter[0] ) ? adder : 6'd0; // data to be added controlled by LSB of shifter
  94.  
  95.         assign sum_unreg[6:0] = sum_reg[6:1] + add_data[5:0]; // sum of two values
  96.  
  97.         assign mul_out = sum_unreg[0];
  98.  
  99.         always @(posedge clock)
  100.         begin
  101.  
  102.                 if( !load ) // normal addition
  103.                 begin
  104.                         sum_reg[6:0] <= sum_unreg[6:0];
  105.                         shifter[6:0] <= shifter[7:1];
  106.                 end
  107.  
  108.                 else // load==1
  109.  
  110.                 begin
  111.                         sum_reg[6:0] <= 7'd0;
  112.  
  113.                         shifter[7]   <= ~(mode_inv7b^dat_in[7]);   // convert to signed data (we need signed result), invert 7th bit if needed
  114.                         shifter[6:0] <=  dat_in[6:0];
  115.  
  116.                         adder <= vol_in;
  117.  
  118.                 end
  119.         end
  120.  
  121.  
  122.  
  123.  
  124.         // serial adder section
  125.         //
  126.         always @(posedge clock)
  127.         begin
  128.                 if( load )
  129.                         clr_sum_reg <= clr_sum;
  130.         end
  131.  
  132.         assign carry_in = (counter==4'd0) ? 1'b0 : old_carry;
  133.  
  134.         assign old_data_in = (clr_sum_reg) ? 1'b0 : sum_out[0];
  135.  
  136.         assign temp_sum[1:0] = carry_in + mul_out + old_data_in;
  137.  
  138.         always @(posedge clock)
  139.         begin
  140.                 if( !ready )
  141.                 begin
  142.                         sum_out[15:0] <= { temp_sum[0], sum_out[15:1] };
  143.                         old_carry <= temp_sum[1];
  144.                 end
  145.         end
  146.  
  147.  
  148.  
  149. endmodule
  150.  
  151.