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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_fpu.v] - Blame information for rev 249

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 185 julius
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  OR1200's FPU Wrapper                                        ////
4
////                                                              ////
5
////  This file is part of the OpenRISC 1200 project              ////
6
////  http://opencores.org/project,or1k                           ////
7
////                                                              ////
8
////  Description                                                 ////
9
////  Wrapper for floating point unit.                            ////
10
////  Interface based on MULT/MAC unit.                           ////
11
////                                                              ////
12
////  To Do:                                                      ////
13
////   - remainder instruction implementation                     ////
14
////   - registering in/around compare unit                       ////
15
////                                                              ////
16
////  Author(s):                                                  ////
17
////      - Julius Baxter, julius@opencores.org                   ////
18
////                                                              ////
19
//////////////////////////////////////////////////////////////////////
20
////                                                              ////
21
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
22
////                                                              ////
23
//// This source file may be used and distributed without         ////
24
//// restriction provided that this copyright statement is not    ////
25
//// removed from the file and that any derivative work contains  ////
26
//// the original copyright notice and the associated disclaimer. ////
27
////                                                              ////
28
//// This source file is free software; you can redistribute it   ////
29
//// and/or modify it under the terms of the GNU Lesser General   ////
30
//// Public License as published by the Free Software Foundation; ////
31
//// either version 2.1 of the License, or (at your option) any   ////
32
//// later version.                                               ////
33
////                                                              ////
34
//// This source is distributed in the hope that it will be       ////
35
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
36
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
37
//// PURPOSE.  See the GNU Lesser General Public License for more ////
38
//// details.                                                     ////
39
////                                                              ////
40
//// You should have received a copy of the GNU Lesser General    ////
41
//// Public License along with this source; if not, download it   ////
42
//// from http://www.opencores.org/lgpl.shtml                     ////
43
////                                                              ////
44
//////////////////////////////////////////////////////////////////////
45
 
46
// synopsys translate_off
47
`include "timescale.v"
48
// synopsys translate_on
49
`include "or1200_defines.v"
50
 
51
module or1200_fpu(
52
                  // Clock and reset
53
                  clk, rst,
54
 
55
                  // FPU interface
56
                  ex_freeze, a, b, fpu_op, result,
57
 
58
                  // Flag controls
59
                  flagforw, flag_we,
60
 
61
                  // Exception signal
62
                  sig_fp, except_started,
63
 
64
                  // SPR interface
65
                  fpcsr_we, fpcsr,
66
                  spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
67
                  );
68
 
69
   parameter width = `OR1200_OPERAND_WIDTH;
70
 
71
   //
72
   // I/O
73
   //
74
 
75
   //
76
   // Clock and reset
77
   //
78
   input                                clk;
79
   input                                rst;
80
 
81
   //
82
   // FPU interface
83
   //
84
   input                                ex_freeze;
85
   input [width-1:0]                     a;
86
   input [width-1:0]                     b;
87
   input [`OR1200_FPUOP_WIDTH-1:0]       fpu_op;
88
   output [width-1:0]                    result;
89
 
90
   //
91
   // Flag signals
92
   //
93
   output                               flagforw;
94
   output                               flag_we;
95
 
96
 
97
   //
98
   // FPCSR interface
99
   //  
100
   input                                fpcsr_we;
101
   output [`OR1200_FPCSR_WIDTH-1:0]      fpcsr;
102
 
103
   //
104
   // Exception signal
105
   //   
106
   output                               sig_fp;
107
   input                                except_started;
108
 
109
 
110
   //
111
   // SPR interface
112
   //
113
   input                                spr_cs;
114
   input                                spr_write;
115
   input [31:0]                  spr_addr;
116
   input [31:0]                  spr_dat_i;
117
   output [31:0]                         spr_dat_o;
118
 
119 186 julius
 
120
`ifndef OR1200_FPU_IMPLEMENTED
121
 
122
   // No FPU needed
123
   assign result = 0;
124
   assign flagforw  = 0;
125
   assign flag_we = 0;
126
   assign sig_fp = 0;
127
   assign spr_dat_o = 0;
128
 
129
`else
130
 
131
 
132 185 julius
   //
133
   // Internals
134
   //
135
   reg [2:0]                             fpu_op_count;
136
   reg [`OR1200_FPUOP_WIDTH:0]           fpu_op_r;
137
   reg [`OR1200_FPCSR_WIDTH-1:0]         fpcsr_r;
138
   reg                                  fpu_latch_operand;
139
   wire                                 fpu_check_op;
140
   wire                                 fpu_latch_op;
141
   wire                                 inf, snan, qnan, ine, overflow,
142
                                        underflow, zero, div_by_zero;
143
   wire                                 fpu_op_is_comp, fpu_op_r_is_comp;
144
   wire                                 altb, blta, aeqb, cmp_inf, cmp_zero,
145
                                        unordered ;
146
   reg                                  flag;
147 186 julius
 
148 185 julius
 
149
   assign fpcsr = fpcsr_r;
150
 
151
   assign sig_fp = fpcsr_r[`OR1200_FPCSR_FPEE]
152
            & (|fpcsr_r[`OR1200_FPCSR_WIDTH-1:`OR1200_FPCSR_OVF]);
153
 
154
   // Generate signals to latch fpu_op from decode instruction, then latch 
155
   // operands when they appear during execute stage
156
 
157
   assign fpu_check_op = (!ex_freeze & fpu_op[`OR1200_FPUOP_WIDTH-1]);
158
 
159
   assign fpu_op_is_comp = fpu_op[3];
160
 
161
   assign fpu_op_r_is_comp = fpu_op_r[3];
162
 
163
   assign fpu_latch_op = fpu_check_op & !fpu_op_is_comp;
164
 
165
   always @(posedge clk)
166
     fpu_latch_operand <= fpu_check_op & !fpu_op_is_comp;
167
 
168
   // Register fpu_op on comparisons, clear otherwise, remove top bit
169
   always @(posedge clk)
170
     fpu_op_r <= (fpu_check_op & fpu_op_is_comp) ?
171
                 {1'b0,fpu_op[`OR1200_FPUOP_WIDTH-2:0]} : !ex_freeze ?
172
 
173
 
174
   //
175
   // Counter for each FPU operation
176
   // Loaded at start, counts down
177
   //
178
   always @(posedge clk or posedge rst) begin
179
      if (rst)
180
        fpu_op_count <= 0;
181
      else
182
        if (|fpu_op_count)
183
          fpu_op_count <= fpu_op_count - 1;
184
        else if(fpu_check_op)
185
          fpu_op_count <= 5;
186
   end
187
 
188
   //
189
   // FPCSR register
190
   //   
191
   always @(posedge clk or posedge rst) begin
192
      if (rst)
193
        fpcsr_r <= 0;
194
      else
195
        begin
196
           if (fpcsr_we)
197
             fpcsr_r <= b[`OR1200_FPCSR_WIDTH-1:0];
198
           else if (fpu_op_count == 1)
199
             begin
200
                fpcsr_r[`OR1200_FPCSR_OVF] <= overflow;
201
                fpcsr_r[`OR1200_FPCSR_UNF] <= underflow;
202
                fpcsr_r[`OR1200_FPCSR_SNF] <= snan;
203
                fpcsr_r[`OR1200_FPCSR_QNF] <= qnan;
204
                fpcsr_r[`OR1200_FPCSR_ZF]  <= zero |
205
                                              (cmp_zero & fpu_op_r_is_comp);
206
                fpcsr_r[`OR1200_FPCSR_IXF] <= ine;
207
                fpcsr_r[`OR1200_FPCSR_IVF] <= 0; // Not used by this FPU
208
                fpcsr_r[`OR1200_FPCSR_INF] <= inf |
209
                                              (cmp_inf & fpu_op_r_is_comp);
210
                fpcsr_r[`OR1200_FPCSR_DZF] <= div_by_zero;
211
             end // if (fpu_op_count == 1)
212
           if (except_started)
213
             fpcsr_r[`OR1200_FPCSR_FPEE] <= 0;
214
        end // else: !if(rst)
215
   end // always @ (posedge clk or posedge rst)
216
 
217
   //
218
   // Comparison flag generation
219
   //
220
   always@(posedge clk)
221
     begin
222
        if (fpu_op_r_is_comp)
223
          begin
224
             case(fpu_op_r)
225
               `OR1200_FPCOP_SFEQ: begin
226
                  flag <= aeqb;
227
               end
228
               `OR1200_FPCOP_SFNE: begin
229
                  flag <= !aeqb;
230
               end
231
               `OR1200_FPCOP_SFGT: begin
232
                  flag <= blta & !aeqb;
233
               end
234
               `OR1200_FPCOP_SFGE: begin
235
                  flag <= blta | aeqb;
236
               end
237
               `OR1200_FPCOP_SFLT: begin
238
                  flag <= altb & !aeqb;
239
               end
240
               `OR1200_FPCOP_SFLE: begin
241
                  flag <= altb | aeqb;
242
               end
243
               default: begin
244
                  flag <= 0;
245
               end
246
             endcase // case (fpu_op_r)
247
          end // if (fpu_op_r_is_comp)
248
        else
249
          flag <= 0;
250
     end // always@ (posedge clk)
251
 
252
   assign flagforw = flag;
253
 
254
   // Determine here where we do the write, ie how much we pipeline the 
255
   // comparison   
256
   assign flag_we = fpu_op_r_is_comp & (fpu_op_count == 2);
257
 
258
   // FP arithmetic module
259
   fpu fpu0
260
     (
261
       .clk(clk),
262
       .rmode(fpcsr_r[`OR1200_FPCSR_RM]),
263
       .fpu_op(fpu_op[2:0]),
264
       .opa(a),
265
       .opb(b),
266
       .out(result),
267
       .latch_operand(fpu_latch_operand),
268
       .latch_op(fpu_latch_op),
269
       .inf(inf),
270
       .snan(snan),
271
       .qnan(qnan),
272
       .ine(ine),
273
       .overflow(overflow),
274
       .underflow(underflow),
275
       .zero(zero),
276
       .div_by_zero(div_by_zero)
277
       );
278
 
279
   // FP comparator
280
   fcmp fcmp0
281
     (
282
      .opa(a),
283
      .opb(b),
284
      .unordered(unordered),
285
      // I am convinced the comparison logic is wrong way around in this 
286
      // module, simplest to swap them on output -- julius
287
 
288
      .altb(blta),
289
      .blta(altb),
290
      .aeqb(aeqb),
291
      .inf(cmp_inf),
292
      .zero(cmp_zero));
293
 
294 186 julius
`endif // !`ifndef OR1200_FPU_IMPLEMENTED
295
 
296 185 julius
endmodule // or1200_fpu

powered by: WebSVN 2.1.0

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