Execute: most of an ALU, ARM_Constants: RBC -> RSC
[firearm.git] / Execute.v
CommitLineData
5b3daee2
JW
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,
3f5cefe1
JW
12 input [31:0] op0,
13 input [31:0] op1,
14 input [31:0] op2,
15 input carry,
5b3daee2
JW
16
17 output reg outstall = 0,
bc572c5f
JW
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
5b3daee2 22 );
5b3daee2 23
bc572c5f
JW
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));
5b3daee2 33endmodule
07fbfa80
JW
34
35module 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
70endmodule
879a3986
CL
71
72/* XXX is the interface correct? */
73module 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
189endmodule
This page took 0.032863 seconds and 4 git commands to generate.