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 |