1
14
15module avralu
16(
17
18 input [ 4:0] mode,
19 input [ 7:0] dst,
20 input [ 7:0] src,
21 input [15:0] src16,
22 input [ 7:0] si,
23
24
25 output reg [ 7:0] so,
26 output reg [ 7:0] resb,
27 output reg [15:0] resw
28);
29
30
31wire [7:0] sub = dst - src;
32wire [7:0] add = dst + src;
33wire [8:0] sbc = dst - src - si[0];
34wire [7:0] adc = dst + src + si[0];
35wire [7:0] lsr = { 1'b0, dst[7:1]};
36wire [7:0] ror = { si[0], dst[7:1]};
37wire [7:0] asr = {dst[7], dst[7:1]};
38wire [7:0] neg = -dst;
39wire [7:0] inc = dst + 1;
40wire [7:0] dec = dst - 1;
41wire [7:0] com = dst ^ 8'hFF;
42wire [7:0] swap = {dst[3:0], dst[7:4]};
43reg carry;
44
45
46wire [15:0] adiw = src16 + src;
47wire [15:0] sbiw = src16 - src;
48wire [15:0] mul = dst[7:0] * src[7:0];
49wire [15:0] mulsu = {{8{dst[7]}}, dst[7:0]} * src[7:0];
50wire [15:0] muls = {{8{dst[7]}}, dst[7:0]} * {{8{src[7]}}, src[7:0]};
51
52
53wire add_flag_v = (dst[7] & src[7] & !resb[7]) | (!dst[7] & !src[7] & resb[7]);
54wire sub_flag_v = (dst[7] & !src[7] & !resb[7]) | (!dst[7] & src[7] & resb[7]);
55wire neg_flag_v = (resb == 8'h80);
56
57
58wire add_flag_h = ( dst[3] & src[3]) | (src[3] & !resb[3]) | (!resb[3] & dst[3]);
59wire sub_flag_h = (!dst[3] & src[3]) | (src[3] & resb[3]) | ( resb[3] & !dst[3]);
60wire neg_flag_h = dst[3] | (dst[3] & resb[3]) | resb[3];
61
62
63wire adiw_v = !src16[15] & resw [15];
64wire adiw_c = !resw [15] & src16[15];
65
66
67wire [7:0] set_logic_flag = {
68
69 si[7],
70 si[6],
71 si[5],
72 resb[7],
73 1'b0,
74 resb[7],
75 resb[7:0] == 0,
76 si[0]
77};
78
79
80wire [7:0] set_subcarry_flag = {
81
82 si[7],
83 si[6],
84 sub_flag_h,
85 sub_flag_v ^ resb[7],
86 sub_flag_v,
87 resb[7],
88 (resb[7:0] == 0) & si[1],
89 sbc[8]
90};
91
92
93wire [7:0] set_subtract_flag = {
94
95 si[7],
96 si[6],
97 sub_flag_h,
98 sub_flag_v ^ resb[7],
99 sub_flag_v,
100 resb[7],
101 (resb[7:0] == 0),
102 dst < src
103};
104
105
106wire [7:0] set_com_flag = {
107
108 si[7],
109 si[6],
110 si[5],
111 resb[7],
112 1'b0,
113 resb[7],
114 (resb[7:0] == 0),
115 1'b1
116};
117
118
119wire [7:0] set_neg_flag = {
120
121 si[7],
122 si[6],
123 neg_flag_h,
124 neg_flag_v ^ resb[7],
125 neg_flag_v,
126 resb[7],
127 (resb[7:0] == 0),
128 dst != 0
129};
130
131
132wire [7:0] set_add_flag = {
133
134 si[7],
135 si[6],
136 add_flag_h,
137 add_flag_v ^ resb[7],
138 add_flag_v,
139 resb[7],
140 (resb[7:0] == 0),
141 dst + src + carry >= 9'h100
142};
143
144
145wire [7:0] set_lsr_flag = {
146
147 si[7],
148 si[6],
149 si[5],
150 dst[0],
151 resb[7] ^ dst[0],
152 resb[7],
153 (resb[7:0] == 0),
154 dst[0]
155};
156
157
158wire [7:0] set_inc_flag = {
159
160 si[7],
161 si[6],
162 si[5],
163 (resb == 8'h80) ^ resb[7],
164 (resb == 8'h80),
165 resb[7],
166 (resb[7:0] == 0),
167 si[0]
168};
169
170
171wire [7:0] set_dec_flag = {
172
173 si[7],
174 si[6],
175 si[5],
176 (resb == 8'h7F) ^ resb[7],
177 (resb == 8'h7F),
178 resb[7],
179 (resb[7:0] == 0),
180 si[0]
181};
182
183
184wire [7:0] set_adiw_flag = {
185
186 si[7],
187 si[6],
188 si[5],
189 adiw_v ^ resw[15],
190 adiw_v,
191 resw[15],
192 (resw[15:0] == 0),
193 adiw_c
194};
195
196
197wire [7:0] set_sbiw_flag = {
198
199 si[7],
200 si[6],
201 si[5],
202 adiw_v ^ resw[15],
203 adiw_v,
204 resw[15],
205 (resw[15:0] == 0),
206 adiw_v
207};
208
209
210wire [7:0] set_mul_flag = {
211
212 si[7],
213 si[6],
214 si[5],
215 si[7],
216 si[7],
217 si[7],
218 (mul[15:0] == 0),
219 mul[15]
220};
221
222always @(*) begin
223
224 so = si;
225 carry = 0;
226
227 case (mode)
228
229 0: begin resb = src; end
230 1: begin resb = sbc[7:0]; so = set_subcarry_flag; end
231 2: begin resb = sbc[7:0]; so = set_subcarry_flag; end
232 3: begin resb = add; so = set_add_flag; carry = 0; end
233 5: begin resb = sub; so = set_subtract_flag; end
234 6: begin resb = sub; so = set_subtract_flag; end
235 7: begin resb = adc; so = set_add_flag; carry = si[0]; end
236 8: begin resb = dst & src; so = set_logic_flag; end
237 9: begin resb = dst ^ src; so = set_logic_flag; end
238 10: begin resb = dst | src; so = set_logic_flag; end
239 11: begin so = src; end
240 12: begin resb = com; so = set_com_flag; end
241 13: begin resb = neg; so = set_neg_flag; end
242 14: begin resb = swap; end
243 15: begin resb = inc; so = set_inc_flag; end
244 16: begin resb = asr; so = set_lsr_flag; end
245 17: begin resb = lsr; so = set_lsr_flag; end
246 18: begin resb = ror; so = set_lsr_flag; end
247 19: begin resb = dec; so = set_dec_flag; end
248 20: begin resw = adiw; so = set_adiw_flag; end
249 21: begin resw = sbiw; so = set_sbiw_flag; end
250 22: case (src[2:0])
251
252 0: resb = {dst[7:1], si[6]};
253 1: resb = {dst[7:2], si[6], dst[ 0]};
254 2: resb = {dst[7:3], si[6], dst[1:0]};
255 3: resb = {dst[7:4], si[6], dst[2:0]};
256 4: resb = {dst[7:5], si[6], dst[3:0]};
257 5: resb = {dst[7:6], si[6], dst[4:0]};
258 6: resb = {dst[ 7], si[6], dst[5:0]};
259 7: resb = { si[6], dst[6:0]};
260
261 endcase
262 23: begin resw = mul; so = set_mul_flag; end
263 24: begin resw = muls; so = set_mul_flag; end
264 25: begin resw = mulsu; so = set_mul_flag; end
265
266 default: resb = 8'hFF;
267
268 endcase
269
270end
271
272endmodule