]>
Commit | Line | Data |
---|---|---|
5b3daee2 JW |
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, | |
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 | 33 | endmodule |
07fbfa80 JW |
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 | |
879a3986 CL |
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 |