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