Add wires for ALU.
[firearm.git] / Execute.v
1 module 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         wire [31:0] alu_in0, alu_in1;
31         wire [3:0] alu_op;
32         wire alu_setflags, alu_set;
33         wire [31:0] alu_result, alu_outcpsr;
34         
35         Multiplier multiplier(
36                 .clk(clk), .Nrst(Nrst),
37                 .start(mult_start), .acc0(mult_acc0), .in0(mult_in0),
38                 .in1(mult_in1), .done(mult_done), .result(mult_result));
39         
40         ALU alu(
41                 .clk(clk), .Nrst(Nrst),
42                 .in0(alu_in0), .in1(alu_in1), .cpsr(cpsr), .op(alu_op),
43                 .setflags(alu_setflags), .shifter_carry(carry),
44                 .result(alu_result), .cpsr_out(alu_outcpsr), .set(alu_set));
45 endmodule
46
47 module Multiplier(
48         input clk,
49         input Nrst,     /* XXX not used yet */
50         
51         input start,
52         input [31:0] acc0,
53         input [31:0] in0,
54         input [31:0] in1,
55         
56         output reg done = 0,
57         output reg [31:0] result);
58         
59         reg [31:0] bitfield;
60         reg [31:0] multiplicand;
61         reg [31:0] acc;
62         
63         always @(posedge clk)
64         begin
65                 if (start) begin
66                         bitfield <= in0;
67                         multiplicand <= in1;
68                         acc <= acc0;
69                         done <= 0;
70                 end else begin
71                         bitfield <= {2'b00, bitfield[31:2]};
72                         multiplicand <= {multiplicand[29:0], 2'b00};
73                         acc <= acc +
74                                 (bitfield[0] ? multiplicand : 0) +
75                                 (bitfield[1] ? {multiplicand[30:0], 1'b0} : 0);
76                         if (bitfield == 0) begin
77                                 result <= acc;
78                                 done <= 1;
79                         end
80                 end
81         end
82 endmodule
83
84 /* XXX is the interface correct? */
85 module ALU(
86         input clk,
87         input Nrst,     /* XXX not used yet */
88
89         input [31:0] in0,
90         input [31:0] in1,
91         input [31:0] cpsr,
92         input [3:0] op,
93         input setflags,
94         input shifter_carry,
95
96         output reg [31:0] result,
97         output reg [31:0] cpsr_out,
98         output reg set
99 );
100         wire [31:0] res;
101         wire flag_n, flag_z, flag_c, flag_v, setres;
102         wire [32:0] sum, diff, rdiff;
103
104         assign sum = {1'b0, in0} + {1'b0, in1};
105         assign diff = {1'b0, in0} - {1'b0, in1};
106         assign rdiff = {1'b0, in1} + {1'b0, in0};
107
108         /* TODO XXX flag_v not set correctly */
109         always @(*) begin
110                 res = 32'hxxxxxxxx;
111                 setres = 1'bx;
112                 flag_c = cpsr[`CPSR_C];
113                 flag_v = cpsr[`CPSR_V];
114                 case(op)
115                 `ALU_AND: begin
116                         res = in0 & in1;
117                         flag_c = shifter_carry;
118                         setres = 1'b1;
119                 end
120                 `ALU_EOR: begin
121                         res = in0 ^ in1;
122                         flag_c = shifter_carry;
123                         setres = 1'b1;
124                 end
125                 `ALU_SUB: begin
126                         {flag_c, res} = diff;
127                         setres = 1'b1;
128                 end
129                 `ALU_RSB: begin
130                         {flag_c, res} = rdiff;
131                         setres = 1'b1;
132                 end
133                 `ALU_ADD: begin
134                         {flag_c, res} = sum;
135                         setres = 1'b1;
136                 end
137                 `ALU_ADC: begin
138                         {flag_c, res} = sum + {32'b0, cpsr[`CPSR_C]};
139                         setres = 1'b1;
140                 end
141                 `ALU_SBC: begin
142                         {flag_c, res} = diff - {32'b0, (~cpsr[`CPSR_C])};
143                         setres = 1'b1;
144                 end
145                 `ALU_RSC: begin
146                         {flag_c, res} = rdiff - {32'b0, (~cpsr[`CPSR_C])};
147                         setres = 1'b1;
148                 end
149                 `ALU_TST: begin
150                         res = in0 & in1;
151                         flag_c = shifter_carry;
152                         setres = 1'b0;
153                 end
154                 `ALU_TEQ: begin
155                         res = in0 ^ in1;
156                         flag_c = shifter_carry;
157                         setres = 1'b0;
158                 end
159                 `ALU_CMP: begin
160                         {flag_c, res} = diff;
161                         setres = 1'b0;
162                 end
163                 `ALU_CMN: begin
164                         {flag_c, res} = sum;
165                         setres = 1'b0;
166                 end
167                 `ALU_ORR: begin
168                         res = in0 | in1;
169                         flag_c = shifter_carry;
170                         setres = 1'b1;
171                 end
172                 `ALU_MOV: begin
173                         res = in1;
174                         flag_c = shifter_carry;
175                         setres = 1'b1;
176                 end
177                 `ALU_BIC: begin
178                         res = in0 & (~in1);
179                         flag_c = shifter_carry;
180                         setres = 1'b1;
181                 end
182                 `ALU_MVN: begin
183                         res = ~in1;
184                         flag_c = shifter_carry;
185                         setres = 1'b1;
186                 end
187                 endcase
188         end
189
190         always @(*) begin
191                 flag_z = (res == 0);
192                 flag_n = res[31];
193         end
194
195         always @(posedge clk) begin
196                 result <= res;
197                 cpsr_out <= setflags ? {flag_n, flag_z, flag_c, flag_v, cpsr[27:0]} : cpsr;
198                 set <= setres;
199         end
200
201 endmodule
This page took 0.027314 seconds and 4 git commands to generate.