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

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [rtl/] [verilog/] [mult_div.v] - Blame information for rev 35

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2013  Robert Finch, Stratford
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@opencores.org
6
//       ||
7
//
8
// rtf65002.v
9
//  - 32 bit CPU multiplier/divider
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
// ============================================================================
25
//
26 32 robfinch
`include "rtf65002_defines.v"
27 30 robfinch
 
28 32 robfinch
module mult_div(rst, clk, ld, op, fn, a, b, p, q, r, done);
29 12 robfinch
parameter IDLE=3'd0;
30 35 robfinch
parameter MULT1=3'd1;
31
parameter MULT2=3'd2;
32
parameter MULT3=3'd3;
33
parameter FIX_SIGN=3'd4;
34
parameter DIV=3'd5;
35 12 robfinch
input rst;
36
input clk;
37
input ld;
38 32 robfinch
input [8:0] op;
39
input [3:0] fn;
40 12 robfinch
input [31:0] a;
41
input [31:0] b;
42
output reg [63:0] p;
43
output reg [31:0] q;
44
output reg [31:0] r;
45
output done;
46
 
47
reg [31:0] aa, bb;
48
reg res_sgn;
49
 
50
reg [2:0] state;
51
 
52
assign done = state==IDLE;
53
wire [31:0] diff = r - bb;
54
wire [31:0] pa = a[31] ? -a : a;
55 35 robfinch
wire [63:0] p1 = aa * bb;
56 12 robfinch
reg [5:0] cnt;
57
 
58
always @(posedge clk)
59
if (rst)
60
state <= IDLE;
61
else begin
62
case(state)
63
IDLE:
64
        if (ld) begin
65
                cnt <= 6'd32;
66
                case(op)
67 32 robfinch
                `MUL_IMM8,`MUL_IMM16,`MUL_IMM32:
68 12 robfinch
                        begin
69
                                aa <= a;
70
                                bb <= b;
71
                                res_sgn <= 1'b0;
72 35 robfinch
                                state <= MULT1;
73 12 robfinch
                        end
74 30 robfinch
`ifdef SUPPORT_DIVMOD
75 32 robfinch
                `DIV_IMM8,`DIV_IMM16,`DIV_IMM32,
76
                `MOD_IMM8,`MOD_IMM16,`MOD_IMM32:
77 12 robfinch
                        begin
78
                                aa <= a;
79
                                bb <= b;
80
                                q <= a[30:0];
81
                                r <= a[31];
82
                                res_sgn <= 1'b0;
83
                                state <= DIV;
84
                        end
85 30 robfinch
`endif
86 32 robfinch
                `RR:
87
                        case(fn)
88
                        `MUL_RR:
89
                                begin
90
                                        aa <= a;
91
                                        bb <= b;
92
                                        res_sgn <= 1'b0;
93 35 robfinch
                                        state <= MULT1;
94 32 robfinch
                                end
95
                        `MULS_RR:
96
                                begin
97
                                        aa <= a[31] ? -a : a;
98
                                        bb <= b[31] ? -b : b;
99
                                        res_sgn <= a[31] ^ b[31];
100 35 robfinch
                                        state <= MULT1;
101 32 robfinch
                                end
102
`ifdef SUPPORT_DIVMOD
103
                        `DIV_RR,`MOD_RR:
104
                                begin
105
                                        aa <= a;
106
                                        bb <= b;
107
                                        q <= a[30:0];
108
                                        r <= a[31];
109
                                        res_sgn <= 1'b0;
110
                                        state <= DIV;
111
                                end
112
                        `DIVS_RR,`MODS_RR:
113
                                begin
114
                                        aa <= a[31] ? -a : a;
115
                                        bb <= b[31] ? -b : b;
116
                                        q <= pa[30:0];
117
                                        r <= pa[31];
118
                                        res_sgn <= a[31] ^ b[31];
119
                                        state <= DIV;
120
                                end
121
`endif
122
                        default:
123
                                state <= IDLE;
124
                        endcase
125 12 robfinch
                endcase
126
        end
127 35 robfinch
// Three waut states for the multiply to take effect. These are needed at
128
// higher clock frequencies. The multipler is a multi-cycle path that
129
// requires a timing constraint.
130
MULT1:  state <= MULT2;
131
MULT2:  state <= MULT3;
132
MULT3:  begin
133
                        p <= p1;
134
                        state <= res_sgn ? FIX_SIGN : IDLE;
135
                end
136
 
137 30 robfinch
`ifdef SUPPORT_DIVMOD
138 12 robfinch
DIV:
139
        begin
140
                q <= {q[30:0],~diff[31]};
141
                if (cnt==6'd0) begin
142
                        state <= res_sgn ? FIX_SIGN : IDLE;
143
                        if (diff[31])
144
                                r <= r[30:0];
145
                        else
146
                                r <= diff[30:0];
147
                end
148
                else begin
149
                        if (diff[31])
150
                                r <= {r[30:0],q[31]};
151
                        else
152
                                r <= {diff[30:0],q[31]};
153
                end
154
                cnt <= cnt - 6'd1;
155
        end
156 30 robfinch
`endif
157 12 robfinch
 
158
FIX_SIGN:
159
        begin
160
                state <= IDLE;
161
                if (res_sgn) begin
162
                        p <= -p;
163
                        q <= -q;
164
                        r <= -r;
165
                end
166
        end
167
default:        state <= IDLE;
168
endcase
169
end
170
 
171
endmodule
172
 
173
module multdiv_tb();
174
reg rst;
175
reg clk;
176
reg ld;
177
 
178
initial begin
179
        #0 clk = 1'b0;
180
        #0 rst = 1'b0;
181
        #10 rst = 1'b1;
182
        #10 rst = 1'b0;
183
        #10 ld = 1'b1;
184
        #20 ld = 1'b0;
185
end
186
 
187
always #10 clk = ~clk;
188
 
189
mult_div umd1 (
190
        .rst(rst),
191
        .clk(clk),
192
        .ld(ld),
193 32 robfinch
        .op(`RR),
194
        .fn(`DIV_RR),
195 12 robfinch
        .a(32'h12345678),
196
        .b(32'd10),
197
        .p(),
198
        .q(),
199
        .r(),
200
        .done()
201
);
202
 
203
endmodule

powered by: WebSVN 2.1.0

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