OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [ao486/] [pipeline/] [execute_divide.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.