source: sandbox/MultiChannelUSB/average.v@ 168

Last change on this file since 168 was 116, checked in by demin, 14 years ago

fix sign conversion

File size: 7.9 KB
Line 
1module average
2 #(
3 parameter size = 1, // number of channels
4 parameter width = 16 // bit width of the input data
5 )
6 (
7 input wire clock, frame, reset,
8 input wire [3*size*6-1:0] del_data,
9 input wire [3*size*width-1:0] inp_data,
10 output wire [3*size*width2-1:0] out_data
11 );
12
13 localparam width1 = width + 1;
14 localparam width2 = width + 6 + 1;
15
16 reg int_wren_reg, int_wren_next;
17 reg [1:0] int_chan_reg, int_chan_next;
18 reg [2:0] int_case_reg, int_case_next;
19 reg [7:0] int_addr_reg, int_addr_next;
20
21 reg [5:0] del_addr_reg, del_addr_next;
22 wire [5:0] del_addr_wire;
23 wire [7:0] int_addr_wire;
24
25 reg [size*width2-1:0] acc_data_reg [3:0], acc_data_next [3:0];
26 wire [size*width2-1:0] acc_data_wire;
27
28 reg [size*width1-1:0] sub_data_reg [3:0], sub_data_next [3:0];
29 wire [size*width1-1:0] sub_data_wire;
30
31 reg [size*width-1:0] inp_data_reg [2:0], inp_data_next [2:0];
32 wire [size*width-1:0] inp_data_wire [3:0];
33
34 integer i;
35 genvar j;
36
37 generate
38 for (j = 0; j < size; j = j + 1)
39 begin : INT_DATA
40 assign inp_data_wire[0][j*width+width-1:j*width] = inp_data[(3*j+0)*width+width-1:(3*j+0)*width];
41 assign inp_data_wire[1][j*width+width-1:j*width] = inp_data[(3*j+1)*width+width-1:(3*j+1)*width];
42 assign inp_data_wire[2][j*width+width-1:j*width] = inp_data[(3*j+2)*width+width-1:(3*j+2)*width];
43
44 lpm_mux #(
45 .lpm_size(3),
46 .lpm_type("LPM_MUX"),
47 .lpm_width(8),
48 .lpm_widths(2)) mux_unit_1 (
49 .sel(int_chan_next),
50 .data({
51 2'd2, del_data[(3*j+2)*6+6-1:(3*j+2)*6],
52 2'd1, del_data[(3*j+1)*6+6-1:(3*j+1)*6],
53 2'd0, del_data[(3*j+0)*6+6-1:(3*j+0)*6]}),
54 .result(int_addr_wire));
55
56 lpm_add_sub #(
57 .lpm_direction("SUB"),
58 .lpm_hint("ONE_INPUT_IS_CONSTANT=NO,CIN_USED=NO"),
59 .lpm_representation("UNSIGNED"),
60 .lpm_type("LPM_ADD_SUB"),
61 .lpm_width(6)) add_unit_1 (
62 .dataa(del_addr_reg),
63 .datab(int_addr_wire[5:0]),
64 .result(del_addr_wire));
65
66 lpm_add_sub #(
67 .lpm_direction("SUB"),
68 .lpm_hint("ONE_INPUT_IS_CONSTANT=NO,CIN_USED=NO"),
69 .lpm_representation("SIGNED"),
70 .lpm_type("LPM_ADD_SUB"),
71 .lpm_width(width1)) sub_unit_1 (
72 .dataa({{(width1-width){1'b0}}, inp_data_reg[0][j*width+width-1:j*width]}),
73 .datab({{(width1-width){1'b0}}, inp_data_wire[3][j*width+width-1:j*width]}),
74 .result(sub_data_wire[j*width1+width1-1:j*width1]));
75
76 lpm_add_sub #(
77 .lpm_direction("ADD"),
78 .lpm_hint("ONE_INPUT_IS_CONSTANT=NO,CIN_USED=NO"),
79 .lpm_representation("SIGNED"),
80 .lpm_type("LPM_ADD_SUB"),
81 .lpm_width(width2)) acc_unit_1 (
82 .dataa({{(width2-width1+1){sub_data_reg[0][j*width1+width1-1]}}, sub_data_reg[0][j*width1+width1-2:j*width1]}),
83 .datab(acc_data_reg[0][j*width2+width2-1:j*width2]),
84 .result(acc_data_wire[j*width2+width2-1:j*width2]));
85
86 end
87 endgenerate
88
89
90 altsyncram #(
91 .address_aclr_b("NONE"),
92 .address_reg_b("CLOCK0"),
93 .clock_enable_input_a("BYPASS"),
94 .clock_enable_input_b("BYPASS"),
95 .clock_enable_output_b("BYPASS"),
96 .intended_device_family("Cyclone III"),
97 .lpm_type("altsyncram"),
98 .numwords_a(256),
99 .numwords_b(256),
100 .operation_mode("DUAL_PORT"),
101 .outdata_aclr_b("NONE"),
102 .outdata_reg_b("CLOCK0"),
103 .power_up_uninitialized("FALSE"),
104 .read_during_write_mode_mixed_ports("DONT_CARE"),
105 .widthad_a(8),
106 .widthad_b(8),
107 .width_a(size*width),
108 .width_b(size*width),
109 .width_byteena_a(1)) ram_unit_1 (
110 .wren_a(int_wren_reg),
111 .clock0(clock),
112 .address_a(int_addr_reg),
113 .address_b({int_addr_wire[7:6], del_addr_wire}),
114 .data_a(inp_data_reg[0]),
115 .q_b(inp_data_wire[3]),
116 .aclr0(1'b0),
117 .aclr1(1'b0),
118 .addressstall_a(1'b0),
119 .addressstall_b(1'b0),
120 .byteena_a(1'b1),
121 .byteena_b(1'b1),
122 .clock1(1'b1),
123 .clocken0(1'b1),
124 .clocken1(1'b1),
125 .clocken2(1'b1),
126 .clocken3(1'b1),
127 .data_b({(size*width){1'b1}}),
128 .eccstatus(),
129 .q_a(),
130 .rden_a(1'b1),
131 .rden_b(1'b1),
132 .wren_b(1'b0));
133
134 always @(posedge clock)
135 begin
136 if (reset)
137 begin
138 int_wren_reg <= 1'b1;
139 int_chan_reg <= 2'd0;
140 int_case_reg <= 3'd0;
141 del_addr_reg <= 6'd0;
142 int_addr_reg <= 8'd0;
143 for(i = 0; i <= 2; i = i + 1)
144 begin
145 inp_data_reg[i] <= {(size*width){1'b0}};
146 end
147 for(i = 0; i <= 3; i = i + 1)
148 begin
149 sub_data_reg[i] <= {(size*width1){1'b0}};
150 acc_data_reg[i] <= {(size*width2){1'b0}};
151 end
152 end
153 else
154 begin
155 int_wren_reg <= int_wren_next;
156 int_chan_reg <= int_chan_next;
157 int_case_reg <= int_case_next;
158 del_addr_reg <= del_addr_next;
159 int_addr_reg <= int_addr_next;
160 for(i = 0; i <= 2; i = i + 1)
161 begin
162 inp_data_reg[i] <= inp_data_next[i];
163 end
164 for(i = 0; i <= 3; i = i + 1)
165 begin
166 sub_data_reg[i] <= sub_data_next[i];
167 acc_data_reg[i] <= acc_data_next[i];
168 end
169 end
170 end
171
172 always @*
173 begin
174 int_wren_next = int_wren_reg;
175 int_chan_next = int_chan_reg;
176 int_case_next = int_case_reg;
177 del_addr_next = del_addr_reg;
178 int_addr_next = int_addr_reg;
179 for(i = 0; i <= 2; i = i + 1)
180 begin
181 inp_data_next[i] = inp_data_reg[i];
182 end
183 for(i = 0; i <= 3; i = i + 1)
184 begin
185 sub_data_next[i] = sub_data_reg[i];
186 acc_data_next[i] = acc_data_reg[i];
187 end
188
189 case (int_case_reg)
190 0:
191 begin
192 // write zeros
193 int_wren_next = 1'b1;
194 del_addr_next = 6'd0;
195 int_addr_next = 8'd0;
196 for(i = 0; i <= 2; i = i + 1)
197 begin
198 inp_data_next[i] = {(size*width){1'b0}};
199 end
200 for(i = 0; i <= 3; i = i + 1)
201 begin
202 sub_data_next[i] = {(size*width1){1'b0}};
203 acc_data_next[i] = {(size*width2){1'b0}};
204 end
205
206 int_case_next = 3'd1;
207 end
208 1:
209 begin
210 // write zeros
211 int_addr_next = int_addr_reg + 8'd1;
212 if (&int_addr_reg)
213 begin
214 int_wren_next = 1'b0;
215 int_chan_next = 2'd0;
216 int_case_next = 3'd2;
217 end
218 end
219 2: // frame
220 begin
221 if (frame)
222 begin
223 int_wren_next = 1'b1;
224
225 int_addr_next[7:6] = 2'd0;
226
227 // set read addr for 2nd pipeline
228 int_chan_next = 2'd1;
229
230 // register input data for 2nd and 3rd sums
231 inp_data_next[1] = inp_data_wire[1];
232 inp_data_next[2] = inp_data_wire[2];
233
234 // prepare registers for 1st sum
235 inp_data_next[0] = inp_data_wire[0];
236
237 sub_data_next[0] = sub_data_reg[1];
238 acc_data_next[0] = acc_data_reg[1];
239
240 int_case_next = 3'd3;
241 end
242
243 end
244 3: // 1st sum
245 begin
246 int_addr_next[7:6] = 2'd1;
247
248 // set read addr for 3rd pipeline
249 int_chan_next = 2'd2;
250
251 // prepare registers for 2nd sum
252 inp_data_next[0] = inp_data_reg[1];
253
254 sub_data_next[0] = sub_data_reg[2];
255 acc_data_next[0] = acc_data_reg[2];
256
257 // register 1st sum
258 sub_data_next[1] = sub_data_wire;
259 acc_data_next[1] = acc_data_wire;
260
261 int_case_next = 3'd4;
262 end
263 4: // 2nd sum
264 begin
265 int_addr_next[7:6] = 2'd2;
266
267 // prepare registers for 3rd sum
268 inp_data_next[0] = inp_data_reg[2];
269
270 sub_data_next[0] = sub_data_reg[3];
271 acc_data_next[0] = acc_data_reg[3];
272
273 // register 2nd sum
274 sub_data_next[2] = sub_data_wire;
275 acc_data_next[2] = acc_data_wire;
276
277 del_addr_next = del_addr_reg + 6'd1;
278
279 int_case_next = 3'd5;
280 end
281 5: // 3rd sum
282 begin
283 int_wren_next = 1'b0;
284
285 // set read addr for 1st pipeline
286 int_chan_next = 2'd0;
287
288 // register 3rd sum
289 sub_data_next[3] = sub_data_wire;
290 acc_data_next[3] = acc_data_wire;
291
292 int_addr_next[5:0] = del_addr_reg;
293
294 int_case_next = 3'd2;
295 end
296 default:
297 begin
298 int_case_next = 3'd0;
299 end
300 endcase
301 end
302
303 assign out_data = {acc_data_reg[3], acc_data_reg[2], acc_data_reg[1]};
304
305endmodule
Note: See TracBrowser for help on using the repository browser.