Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 3 | lvd | 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 |