Subversion Repositories ngs

Rev

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