1 |
2 |
alfik |
/*
|
2 |
|
|
* Copyright (c) 2014, Aleksander Osman
|
3 |
|
|
* All rights reserved.
|
4 |
|
|
*
|
5 |
|
|
* Redistribution and use in source and binary forms, with or without
|
6 |
|
|
* modification, are permitted provided that the following conditions are met:
|
7 |
|
|
*
|
8 |
|
|
* * Redistributions of source code must retain the above copyright notice, this
|
9 |
|
|
* list of conditions and the following disclaimer.
|
10 |
|
|
*
|
11 |
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
12 |
|
|
* this list of conditions and the following disclaimer in the documentation
|
13 |
|
|
* and/or other materials provided with the distribution.
|
14 |
|
|
*
|
15 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16 |
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18 |
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
19 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
21 |
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
22 |
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
23 |
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
24 |
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25 |
|
|
*/
|
26 |
|
|
|
27 |
|
|
`include "defines.v"
|
28 |
|
|
|
29 |
|
|
module execute_divide(
|
30 |
|
|
input clk,
|
31 |
|
|
input rst_n,
|
32 |
|
|
|
33 |
|
|
input exe_reset,
|
34 |
|
|
input exe_ready,
|
35 |
|
|
|
36 |
|
|
input exe_is_8bit,
|
37 |
|
|
input exe_operand_16bit,
|
38 |
|
|
input exe_operand_32bit,
|
39 |
|
|
input [6:0] exe_cmd,
|
40 |
|
|
|
41 |
|
|
input [31:0] eax,
|
42 |
|
|
input [31:0] edx,
|
43 |
|
|
|
44 |
|
|
input [31:0] src,
|
45 |
|
|
|
46 |
|
|
//output
|
47 |
|
|
output div_busy,
|
48 |
|
|
|
49 |
|
|
output exe_div_exception,
|
50 |
|
|
|
51 |
|
|
output [31:0] div_result_quotient,
|
52 |
|
|
output [31:0] div_result_remainder
|
53 |
|
|
);
|
54 |
|
|
|
55 |
|
|
//------------------------------------------------------------------------------ IDIV, DIV, AAM
|
56 |
|
|
|
57 |
|
|
wire div_start;
|
58 |
|
|
wire div_working;
|
59 |
|
|
|
60 |
|
|
wire div_exception_min_int;
|
61 |
|
|
wire div_exception_zero;
|
62 |
|
|
|
63 |
|
|
reg div_overflow_waiting;
|
64 |
|
|
|
65 |
|
|
reg [5:0] div_counter;
|
66 |
|
|
reg div_one_time;
|
67 |
|
|
|
68 |
|
|
wire [64:0] div_numer;
|
69 |
|
|
wire [32:0] div_denom;
|
70 |
|
|
|
71 |
|
|
wire [32:0] div_denom_neg;
|
72 |
|
|
|
73 |
|
|
wire [64:0] div_diff;
|
74 |
|
|
|
75 |
|
|
reg [63:0] div_dividend;
|
76 |
|
|
reg [63:0] div_divisor;
|
77 |
|
|
|
78 |
|
|
reg [32:0] div_quotient;
|
79 |
|
|
|
80 |
|
|
wire div_quotient_neg;
|
81 |
|
|
wire div_remainder_neg;
|
82 |
|
|
|
83 |
|
|
wire div_overflow_8bit;
|
84 |
|
|
wire div_overflow_16bit;
|
85 |
|
|
wire div_overflow_32bit;
|
86 |
|
|
wire div_overflow;
|
87 |
|
|
|
88 |
|
|
//------------------------------------------------------------------------------
|
89 |
|
|
|
90 |
|
|
assign exe_div_exception = div_exception_zero || div_exception_min_int || div_overflow_waiting;
|
91 |
|
|
|
92 |
|
|
assign div_start = ~(exe_div_exception) && ~(div_one_time) && div_counter == 6'd0 && (exe_cmd == `CMD_IDIV || exe_cmd == `CMD_DIV || exe_cmd == `CMD_AAM);
|
93 |
|
|
assign div_working= div_counter > 6'd1;
|
94 |
|
|
assign div_busy = div_counter != 6'd0 || ~(div_one_time);
|
95 |
|
|
//div_end condition: div_counter == 6'd1 && ~(exe_div_exception)
|
96 |
|
|
|
97 |
|
|
always @(posedge clk or negedge rst_n) begin
|
98 |
|
|
if(rst_n == 1'b0) div_one_time <= `FALSE;
|
99 |
|
|
else if(exe_reset) div_one_time <= `FALSE;
|
100 |
|
|
else if(exe_ready) div_one_time <= `FALSE;
|
101 |
|
|
else if(div_counter > 6'd1) div_one_time <= `TRUE;
|
102 |
|
|
end
|
103 |
|
|
|
104 |
|
|
assign div_exception_min_int = div_counter == 6'd0 && exe_cmd == `CMD_IDIV && (
|
105 |
|
|
( exe_is_8bit && eax[15:0] == 16'h8000) ||
|
106 |
|
|
((~exe_is_8bit) && exe_operand_16bit && edx[15:0] == 16'h8000 && eax[15:0] == 16'h0000) ||
|
107 |
|
|
((~exe_is_8bit) && exe_operand_32bit && edx == 32'h80000000 && eax == 32'h00000000));
|
108 |
|
|
|
109 |
|
|
assign div_exception_zero = div_counter == 6'd0 && (exe_cmd == `CMD_IDIV || exe_cmd == `CMD_DIV || exe_cmd == `CMD_AAM) && (
|
110 |
|
|
(exe_is_8bit && src[7:0] == 8'd0) ||
|
111 |
|
|
(exe_operand_16bit && src[15:0] == 16'd0) ||
|
112 |
|
|
(exe_operand_32bit && src == 32'd0) );
|
113 |
|
|
|
114 |
|
|
always @(posedge clk or negedge rst_n) begin
|
115 |
|
|
if(rst_n == 1'b0) div_overflow_waiting <= `FALSE;
|
116 |
|
|
else if(exe_reset) div_overflow_waiting <= `FALSE;
|
117 |
|
|
else if(div_counter == 6'd1 && div_overflow) div_overflow_waiting <= `TRUE;
|
118 |
|
|
end
|
119 |
|
|
|
120 |
|
|
always @(posedge clk or negedge rst_n) begin
|
121 |
|
|
if(rst_n == 1'b0) div_counter <= 6'd0;
|
122 |
|
|
else if(exe_reset) div_counter <= 6'd0;
|
123 |
|
|
else if(div_start && exe_is_8bit) div_counter <= 6'd10;
|
124 |
|
|
else if(div_start && exe_operand_16bit) div_counter <= 6'd18;
|
125 |
|
|
else if(div_start && exe_operand_32bit) div_counter <= 6'd34;
|
126 |
|
|
else if(div_counter != 6'd0) div_counter <= div_counter - 6'd1;
|
127 |
|
|
end
|
128 |
|
|
|
129 |
|
|
assign div_numer =
|
130 |
|
|
(exe_cmd == `CMD_AAM)? { 57'd0, eax[7:0] } :
|
131 |
|
|
(exe_is_8bit)? { {49{(exe_cmd == `CMD_IDIV) & eax[15]}}, eax[15:0] } :
|
132 |
|
|
(exe_operand_16bit)? { {33{(exe_cmd == `CMD_IDIV) & edx[15]}}, edx[15:0], eax[15:0] } :
|
133 |
|
|
{ ((exe_cmd == `CMD_IDIV) & edx[31]), edx, eax };
|
134 |
|
|
|
135 |
|
|
assign div_denom =
|
136 |
|
|
(exe_is_8bit)? { {25{(exe_cmd == `CMD_IDIV) & src[7]}}, src[7:0] } :
|
137 |
|
|
(exe_operand_16bit)? { {17{(exe_cmd == `CMD_IDIV) & src[15]}}, src[15:0] } :
|
138 |
|
|
{ ((exe_cmd == `CMD_IDIV) & src[31]), src };
|
139 |
|
|
|
140 |
|
|
assign div_denom_neg = -div_denom;
|
141 |
|
|
|
142 |
|
|
assign div_diff = div_dividend - div_divisor;
|
143 |
|
|
|
144 |
|
|
always @(posedge clk or negedge rst_n) begin
|
145 |
|
|
if(rst_n == 1'b0) div_dividend <= 64'd0;
|
146 |
|
|
else if(div_start && div_numer[64] == 1'b0) div_dividend <= div_numer[63:0];
|
147 |
|
|
else if(div_start && div_numer[64] == 1'b1) div_dividend <= -div_numer[63:0];
|
148 |
|
|
else if(div_working && div_diff[64] == 1'b0) div_dividend <= div_diff[63:0];
|
149 |
|
|
end
|
150 |
|
|
|
151 |
|
|
always @(posedge clk or negedge rst_n) begin
|
152 |
|
|
if(rst_n == 1'b0) div_divisor <= 64'd0;
|
153 |
|
|
else if(div_start && div_denom[32] == 1'b0 && exe_is_8bit) div_divisor <= { 48'd0, div_denom [7:0], 8'd0 };
|
154 |
|
|
else if(div_start && div_denom[32] == 1'b1 && exe_is_8bit) div_divisor <= { 48'd0, div_denom_neg[7:0], 8'd0 };
|
155 |
|
|
else if(div_start && div_denom[32] == 1'b0 && exe_operand_16bit) div_divisor <= { 32'd0, div_denom [15:0],16'd0 };
|
156 |
|
|
else if(div_start && div_denom[32] == 1'b1 && exe_operand_16bit) div_divisor <= { 32'd0, div_denom_neg[15:0],16'd0 };
|
157 |
|
|
else if(div_start && div_denom[32] == 1'b0 && exe_operand_32bit) div_divisor <= { div_denom [31:0],32'd0 };
|
158 |
|
|
else if(div_start && div_denom[32] == 1'b1 && exe_operand_32bit) div_divisor <= { div_denom_neg[31:0],32'd0 };
|
159 |
|
|
else if(div_working) div_divisor <= { 1'b0, div_divisor[63:1] };
|
160 |
|
|
end
|
161 |
|
|
|
162 |
|
|
always @(posedge clk or negedge rst_n) begin
|
163 |
|
|
if(rst_n == 1'b0) div_quotient <= 33'd0;
|
164 |
|
|
else if(div_start) div_quotient <= 33'd0;
|
165 |
|
|
else if(div_working && div_diff[64] == 1'b0) div_quotient <= { div_quotient[31:0], 1'b1 };
|
166 |
|
|
else if(div_working && div_diff[64] == 1'b1) div_quotient <= { div_quotient[31:0], 1'b0 };
|
167 |
|
|
end
|
168 |
|
|
|
169 |
|
|
assign div_quotient_neg = div_numer[64] ^ div_denom[32];
|
170 |
|
|
assign div_remainder_neg = div_numer[64];
|
171 |
|
|
|
172 |
|
|
assign div_overflow_8bit =
|
173 |
|
|
(exe_cmd == `CMD_IDIV && ( (~(div_quotient_neg) && div_quotient[8:7] != 2'b00) || (div_quotient_neg && div_quotient[8:0] > 9'h80) )) ||
|
174 |
|
|
(exe_cmd != `CMD_IDIV && div_quotient[8]);
|
175 |
|
|
|
176 |
|
|
assign div_overflow_16bit =
|
177 |
|
|
(exe_cmd == `CMD_IDIV && ( (~(div_quotient_neg) && div_quotient[16:15] != 2'b00) || (div_quotient_neg && div_quotient[16:0] > 17'h8000) )) ||
|
178 |
|
|
(exe_cmd != `CMD_IDIV && div_quotient[16]);
|
179 |
|
|
|
180 |
|
|
assign div_overflow_32bit =
|
181 |
|
|
(exe_cmd == `CMD_IDIV && ( (~(div_quotient_neg) && div_quotient[32:31] != 2'b00) || (div_quotient_neg && div_quotient[32:0] > 33'h80000000) )) ||
|
182 |
|
|
(exe_cmd != `CMD_IDIV && div_quotient[32]);
|
183 |
|
|
|
184 |
|
|
assign div_overflow = (exe_cmd == `CMD_IDIV || exe_cmd == `CMD_DIV) && (
|
185 |
|
|
(exe_is_8bit && div_overflow_8bit) ||
|
186 |
|
|
(exe_operand_16bit && div_overflow_16bit) ||
|
187 |
|
|
(exe_operand_32bit && div_overflow_32bit));
|
188 |
|
|
|
189 |
|
|
assign div_result_quotient = (div_quotient_neg)? -div_quotient[31:0] : div_quotient[31:0];
|
190 |
|
|
assign div_result_remainder = (div_remainder_neg)? -div_dividend[31:0] : div_dividend[31:0];
|
191 |
|
|
|
192 |
|
|
//------------------------------------------------------------------------------
|
193 |
|
|
|
194 |
|
|
//------------------------------------------------------------------------------
|
195 |
|
|
|
196 |
|
|
// synthesis translate_off
|
197 |
|
|
wire _unused_ok = &{ 1'b0, div_denom_neg[32], 1'b0 };
|
198 |
|
|
// synthesis translate_on
|
199 |
|
|
|
200 |
|
|
//------------------------------------------------------------------------------
|
201 |
|
|
|
202 |
|
|
endmodule
|