Subversion Repositories ngs

Rev

Rev 3 | 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.         load,    // load pulse input
  26.         clr_sum, // clear sum input
  27.  
  28.         ready,   // ready output
  29.         sum_out  // 16-bit sum output
  30. );
  31.  
  32.         input clock;
  33.  
  34.         input [5:0] vol_in;
  35.         input [7:0] dat_in;
  36.  
  37.         input load;
  38.         input clr_sum;
  39.  
  40.         output reg ready;
  41.  
  42.         output reg [15:0] sum_out;
  43.  
  44.  
  45.  
  46.         wire [5:0] add_data;
  47.         wire [6:0] sum_unreg;
  48.         reg [6:0] sum_reg;
  49.         reg [7:0] shifter;
  50.         reg [5:0] adder;
  51.         wire   mul_out;
  52.  
  53.  
  54.  
  55.         reg [3:0] counter;
  56.  
  57.  
  58.         reg clr_sum_reg;
  59.         wire [1:0] temp_sum;
  60.         wire carry_in;
  61.         wire old_data_in;
  62.         reg old_carry;
  63.  
  64.  
  65.  
  66.  
  67.         // control section
  68.         //
  69.         always @(posedge clock)
  70.         begin
  71.  
  72.                 if( load )
  73.                         ready <= 1'b0;
  74.  
  75.                 if( counter[3:0] == 4'd15 )
  76.                         ready <= 1'b1;
  77.  
  78.                 if( load )
  79.                         counter <= 4'd0;
  80.                 else
  81.                         counter <= counter + 4'd1;
  82.  
  83.         end
  84.  
  85.  
  86.  
  87.         // serial multiplier section
  88.         //
  89.         assign add_data = ( shifter[0] ) ? adder : 6'd0; // data to be added controlled by LSB of shifter
  90.  
  91.         assign sum_unreg[6:0] = sum_reg[6:1] + add_data[5:0]; // sum of two values
  92.  
  93.         assign mul_out = sum_unreg[0];
  94.  
  95.         always @(posedge clock)
  96.         begin
  97.  
  98.                 if( !load ) // normal addition
  99.                 begin
  100.                         sum_reg[6:0] <= sum_unreg[6:0];
  101.                         shifter[6:0] <= shifter[7:1];
  102.                 end
  103.  
  104.                 else // load==1
  105.  
  106.                 begin
  107.                         sum_reg[6:0] <= 7'd0;
  108.  
  109.                         shifter[7]   <= ~dat_in[7];   // convert to signed data (we need signed result)
  110.                         shifter[6:0] <=  dat_in[6:0];
  111.  
  112.                         adder <= vol_in;
  113.  
  114.                 end
  115.         end
  116.  
  117.  
  118.  
  119.  
  120.         // serial adder section
  121.         //
  122.         always @(posedge clock)
  123.         begin
  124.                 if( load )
  125.                         clr_sum_reg <= clr_sum;
  126.         end
  127.  
  128.         assign carry_in = (counter==4'd0) ? 1'b0 : old_carry;
  129.  
  130.         assign old_data_in = (clr_sum_reg) ? 1'b0 : sum_out[0];
  131.  
  132.         assign temp_sum[1:0] = carry_in + mul_out + old_data_in;
  133.  
  134.         always @(posedge clock)
  135.         begin
  136.                 if( !ready )
  137.                 begin
  138.                         sum_out[15:0] <= { temp_sum[0], sum_out[15:1] };
  139.                         old_carry <= temp_sum[1];
  140.                 end
  141.         end
  142.  
  143.  
  144.  
  145. endmodule
  146.  
  147.