]> Joshua Wise's Git repositories - firearm.git/blame_incremental - Execute.v
Execute.v: Wire up the ALU.
[firearm.git] / Execute.v
... / ...
CommitLineData
1module Execute(
2 input clk,
3 input Nrst, /* XXX not used yet */
4
5 input stall,
6 input flush,
7
8 input inbubble,
9 input [31:0] pc,
10 input [31:0] insn,
11 input [31:0] cpsr,
12 input [31:0] op0,
13 input [31:0] op1,
14 input [31:0] op2,
15 input carry,
16
17 output reg outstall = 0,
18 output reg outbubble = 1,
19 output reg [31:0] outcpsr = 0,
20 output reg write_reg = 1'bx,
21 output reg [3:0] write_num = 4'bxxxx,
22 output reg [31:0] write_data = 32'hxxxxxxxx
23 );
24
25 reg mult_start;
26 reg [31:0] mult_acc0, mult_in0, mult_in1;
27 wire mult_done;
28 wire [31:0] mult_result;
29
30 reg [31:0] alu_in0, alu_in1;
31 reg [3:0] alu_op;
32 reg alu_setflags;
33 wire [31:0] alu_result, alu_outcpsr;
34 wire alu_setres;
35
36 reg next_outbubble;
37 reg [31:0] next_outcpsr;
38 reg next_write_reg;
39 reg [3:0] next_write_num;
40 reg [31:0] next_write_data;
41
42 Multiplier multiplier(
43 .clk(clk), .Nrst(Nrst),
44 .start(mult_start), .acc0(mult_acc0), .in0(mult_in0),
45 .in1(mult_in1), .done(mult_done), .result(mult_result));
46
47 ALU alu(
48 .clk(clk), .Nrst(Nrst),
49 .in0(alu_in0), .in1(alu_in1), .cpsr(cpsr), .op(alu_op),
50 .setflags(alu_setflags), .shifter_carry(carry),
51 .result(alu_result), .cpsr_out(alu_outcpsr), .setres(alu_setres));
52
53 always @(posedge clk)
54 begin
55 if (!stall)
56 begin
57 outbubble <= next_outbubble;
58 outcpsr <= next_outcpsr;
59 write_reg <= next_write_reg;
60 write_num <= next_write_num;
61 write_data <= next_write_data;
62 end
63 end
64
65 always @(*)
66 begin
67 outstall = stall;
68 next_outbubble = inbubble;
69 next_outcpsr = cpsr;
70 next_write_reg = 0;
71 next_write_num = 4'hx;
72 next_write_data = 32'hxxxxxxxx;
73
74 alu_in0 = 32'hxxxxxxxx;
75 alu_in1 = 32'hxxxxxxxx;
76 alu_op = 4'hx; /* hax! */
77 alu_setflags = 1'bx;
78
79 casez (insn)
80 `DECODE_ALU_MULT, /* Multiply -- must come before ALU, because it pattern matches a specific case of ALU */
81// `DECODE_ALU_MUL_LONG, /* Multiply long */
82 `DECODE_ALU_MRS, /* MRS (Transfer PSR to register) */
83 `DECODE_ALU_MSR, /* MSR (Transfer register to PSR) */
84 `DECODE_ALU_MSR_FLAGS, /* MSR (Transfer register or immediate to PSR, flag bits only) */
85 `DECODE_ALU_SWP, /* Atomic swap */
86 `DECODE_ALU_BX, /* Branch */
87 `DECODE_ALU_HDATA_REG, /* Halfword transfer - register offset */
88 `DECODE_ALU_HDATA_IMM: /* Halfword transfer - immediate offset */
89 begin end
90 `DECODE_ALU: /* ALU */
91 begin
92 alu_in0 = op0;
93 alu_in1 = op1;
94 alu_op = insn[24:21];
95 alu_setflags = insn[20] /* I */;
96
97 if (alu_setres) begin
98 next_write_reg = 1;
99 next_write_num = insn[15:12] /* Rd */;
100 next_write_data = alu_result;
101 end
102
103 next_outcpsr = alu_outcpsr;
104 end
105 `DECODE_LDRSTR_UNDEFINED, /* Undefined. I hate ARM */
106 `DECODE_LDRSTR, /* Single data transfer */
107 `DECODE_LDMSTM, /* Block data transfer */
108 `DECODE_BRANCH, /* Branch */
109 `DECODE_LDCSTC, /* Coprocessor data transfer */
110 `DECODE_CDP, /* Coprocessor data op */
111 `DECODE_MRCMCR, /* Coprocessor register transfer */
112 `DECODE_SWI: /* SWI */
113 begin end
114 default: /* X everything else out */
115 begin end
116 endcase
117 end
118endmodule
119
120module Multiplier(
121 input clk,
122 input Nrst, /* XXX not used yet */
123
124 input start,
125 input [31:0] acc0,
126 input [31:0] in0,
127 input [31:0] in1,
128
129 output reg done = 0,
130 output reg [31:0] result);
131
132 reg [31:0] bitfield;
133 reg [31:0] multiplicand;
134 reg [31:0] acc;
135
136 always @(posedge clk)
137 begin
138 if (start) begin
139 bitfield <= in0;
140 multiplicand <= in1;
141 acc <= acc0;
142 done <= 0;
143 end else begin
144 bitfield <= {2'b00, bitfield[31:2]};
145 multiplicand <= {multiplicand[29:0], 2'b00};
146 acc <= acc +
147 (bitfield[0] ? multiplicand : 0) +
148 (bitfield[1] ? {multiplicand[30:0], 1'b0} : 0);
149 if (bitfield == 0) begin
150 result <= acc;
151 done <= 1;
152 end
153 end
154 end
155endmodule
156
157/* XXX is the interface correct? */
158module ALU(
159 input clk,
160 input Nrst, /* XXX not used yet */
161
162 input [31:0] in0,
163 input [31:0] in1,
164 input [31:0] cpsr,
165 input [3:0] op,
166 input setflags,
167 input shifter_carry,
168
169 output reg [31:0] result,
170 output reg [31:0] cpsr_out,
171 output reg setres
172);
173 wire [31:0] res;
174 wire flag_n, flag_z, flag_c, flag_v, setres;
175 wire [32:0] sum, diff, rdiff;
176
177 assign sum = {1'b0, in0} + {1'b0, in1};
178 assign diff = {1'b0, in0} - {1'b0, in1};
179 assign rdiff = {1'b0, in1} + {1'b0, in0};
180
181 /* TODO XXX flag_v not set correctly */
182 always @(*) begin
183 res = 32'hxxxxxxxx;
184 setres = 1'bx;
185 flag_c = cpsr[`CPSR_C];
186 flag_v = cpsr[`CPSR_V];
187 case(op)
188 `ALU_AND: begin
189 result = in0 & in1;
190 flag_c = shifter_carry;
191 setres = 1'b1;
192 end
193 `ALU_EOR: begin
194 result = in0 ^ in1;
195 flag_c = shifter_carry;
196 setres = 1'b1;
197 end
198 `ALU_SUB: begin
199 {flag_c, result} = diff;
200 setres = 1'b1;
201 end
202 `ALU_RSB: begin
203 {flag_c, result} = rdiff;
204 setres = 1'b1;
205 end
206 `ALU_ADD: begin
207 {flag_c, result} = sum;
208 setres = 1'b1;
209 end
210 `ALU_ADC: begin
211 {flag_c, result} = sum + {32'b0, cpsr[`CPSR_C]};
212 setres = 1'b1;
213 end
214 `ALU_SBC: begin
215 {flag_c, result} = diff - {32'b0, (~cpsr[`CPSR_C])};
216 setres = 1'b1;
217 end
218 `ALU_RSC: begin
219 {flag_c, result} = rdiff - {32'b0, (~cpsr[`CPSR_C])};
220 setres = 1'b1;
221 end
222 `ALU_TST: begin
223 result = in0 & in1;
224 flag_c = shifter_carry;
225 setres = 1'b0;
226 end
227 `ALU_TEQ: begin
228 result = in0 ^ in1;
229 flag_c = shifter_carry;
230 setres = 1'b0;
231 end
232 `ALU_CMP: begin
233 {flag_c, result} = diff;
234 setres = 1'b0;
235 end
236 `ALU_CMN: begin
237 {flag_c, result} = sum;
238 setres = 1'b0;
239 end
240 `ALU_ORR: begin
241 result = in0 | in1;
242 flag_c = shifter_carry;
243 setres = 1'b1;
244 end
245 `ALU_MOV: begin
246 result = in1;
247 flag_c = shifter_carry;
248 setres = 1'b1;
249 end
250 `ALU_BIC: begin
251 result = in0 & (~in1);
252 flag_c = shifter_carry;
253 setres = 1'b1;
254 end
255 `ALU_MVN: begin
256 result = ~in1;
257 flag_c = shifter_carry;
258 setres = 1'b1;
259 end
260 endcase
261
262 flag_z = (result == 0);
263 flag_n = result[31];
264
265 cpsr_out = setflags ? {flag_n, flag_z, flag_c, flag_v, cpsr[27:0]} : cpsr;
266 end
267endmodule
This page took 0.02422 seconds and 4 git commands to generate.