OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [mor1kx-5.0/] [rtl/] [verilog/] [pfpu32/] [pfpu32_rnd.v] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 alirezamon
/////////////////////////////////////////////////////////////////////
2
//                                                                 //
3
//    pfpu32_rnd                                                   //
4
//    32-bit common rounding module for FPU                        //
5
//                                                                 //
6
//    This file is part of the mor1kx project                      //
7
//    https://github.com/openrisc/mor1kx                           //
8
//                                                                 //
9
//    Author: Andrey Bacherov                                      //
10
//            avbacherov@opencores.org                             //
11
//                                                                 //
12
/////////////////////////////////////////////////////////////////////
13
//                                                                 //
14
//   Copyright (C) 2014 Andrey Bacherov                            //
15
//                      avbacherov@opencores.org                   //
16
//                                                                 //
17
//   This source file may be used and distributed without          //
18
//   restriction provided that this copyright statement is not     //
19
//   removed from the file and that any derivative work contains   //
20
//   the original copyright notice and the associated disclaimer.  //
21
//                                                                 //
22
//       THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY       //
23
//   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED     //
24
//   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS     //
25
//   FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR        //
26
//   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,           //
27
//   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES      //
28
//   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE     //
29
//   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR          //
30
//   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    //
31
//   LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT    //
32
//   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT    //
33
//   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           //
34
//   POSSIBILITY OF SUCH DAMAGE.                                   //
35
//                                                                 //
36
/////////////////////////////////////////////////////////////////////
37
 
38
`include "mor1kx-defines.v"
39
 
40
module pfpu32_rnd
41
(
42
  // clocks, resets and other controls
43
  input        clk,
44
  input        rst,
45
  input        flush_i,  // flush pipe
46
  input        adv_i,    // advance pipe
47
  input  [1:0] rmode_i,  // rounding mode
48
  // input from add/sub
49
  input        add_rdy_i,       // add/sub is ready
50
  input        add_sign_i,      // add/sub signum
51
  input        add_sub_0_i,     // flag that actual substruction is performed and result is zero
52
  input  [4:0] add_shl_i,       // do left shift in align stage
53
  input  [9:0] add_exp10shl_i,  // exponent for left shift align
54
  input  [9:0] add_exp10sh0_i,  // exponent for no shift in align
55
  input [27:0] add_fract28_i,   // fractional with appended {r,s} bits
56
  input        add_inv_i,       // add/sub invalid operation flag
57
  input        add_inf_i,       // add/sub infinity input
58
  input        add_snan_i,      // add/sub signaling NaN input
59
  input        add_qnan_i,      // add/sub quiet NaN input
60
  input        add_anan_sign_i, // add/sub signum for output nan
61
  // input from mul
62
  input        mul_rdy_i,       // mul is ready
63
  input        mul_sign_i,      // mul signum
64
  input  [4:0] mul_shr_i,       // do right shift in align stage
65
  input  [9:0] mul_exp10shr_i,  // exponent for right shift align
66
  input        mul_shl_i,       // do left shift in align stage
67
  input  [9:0] mul_exp10shl_i,  // exponent for left shift align
68
  input  [9:0] mul_exp10sh0_i,  // exponent for no shift in align
69
  input [27:0] mul_fract28_i,   // fractional with appended {r,s} bits
70
  input        mul_inv_i,       // mul invalid operation flag
71
  input        mul_inf_i,       // mul infinity input
72
  input        mul_snan_i,      // mul signaling NaN input
73
  input        mul_qnan_i,      // mul quiet NaN input
74
  input        mul_anan_sign_i, // mul signum for output nan
75
  // input from div
76
  input        div_op_i,        // MUL/DIV output is division
77
  input        div_sign_rmnd_i, // signum or reminder for IEEE compliant rounding
78
  input        div_dbz_i,       // division by zero flag
79
  // input from i2f
80
  input        i2f_rdy_i,       // i2f is ready
81
  input        i2f_sign_i,      // i2f signum
82
  input  [3:0] i2f_shr_i,
83
  input  [7:0] i2f_exp8shr_i,
84
  input  [4:0] i2f_shl_i,
85
  input  [7:0] i2f_exp8shl_i,
86
  input  [7:0] i2f_exp8sh0_i,
87
  input [31:0] i2f_fract32_i,
88
  // input from f2i
89
  input        f2i_rdy_i,       // f2i is ready
90
  input        f2i_sign_i,      // f2i signum
91
  input [23:0] f2i_int24_i,     // f2i fractional
92
  input  [4:0] f2i_shr_i,       // f2i required shift right value
93
  input  [3:0] f2i_shl_i,       // f2i required shift left value   
94
  input        f2i_ovf_i,       // f2i overflow flag
95
  input        f2i_snan_i,      // f2i signaling NaN input
96
  // input from cmp
97
  input        cmp_rdy_i,       // cmp is ready
98
  input        cmp_res_i,       // cmp result
99
  input        cmp_inv_i,       // cmp invalid flag
100
  input        cmp_inf_i,       // cmp infinity flag
101
  // outputs
102
  //  arithmetic part's outputs
103
  output reg                  [31:0] fpu_result_o,
104
  output reg                         fpu_arith_valid_o,
105
  //  comparator's outputs 
106
  output reg                         fpu_cmp_flag_o,
107
  output reg                         fpu_cmp_valid_o,
108
  //  common output
109
  output reg [`OR1K_FPCSR_WIDTH-1:0] fpcsr_o
110
);
111
 
112
  localparam INF  = 31'b1111111100000000000000000000000;
113
  localparam QNAN = 31'b1111111110000000000000000000000;
114
  localparam SNAN = 31'b1111111101111111111111111111111;
115
 
116
  // rounding mode isn't require pipelinization
117
  wire rm_nearest = (rmode_i==2'b00);
118
  wire rm_to_zero = (rmode_i==2'b01);
119
  wire rm_to_infp = (rmode_i==2'b10);
120
  wire rm_to_infm = (rmode_i==2'b11);
121
 
122
  /*
123
     Any stage's output is registered.
124
     Definitions:
125
       s??o_name - "S"tage number "??", "O"utput
126
       s??t_name - "S"tage number "??", "T"emporary (internally)
127
  */
128
 
129
  /* Stage #1: common align */
130
 
131
  wire        s1t_sign;
132
  wire [34:0] s1t_fract35;
133
  wire        s1t_inv;
134
  wire        s1t_inf;
135
  wire        s1t_snan;
136
  wire        s1t_qnan;
137
  wire        s1t_anan_sign;
138
  wire  [4:0] s1t_shr;
139
  wire  [4:0] s1t_shl;
140
 
141
  // multiplexer for signums and flags
142
  wire s1t_add_sign = add_sub_0_i ? rm_to_infm : add_sign_i;
143
 
144
  assign {s1t_sign,s1t_inv,s1t_inf,s1t_snan,s1t_qnan,s1t_anan_sign} =
145
    ({6{add_rdy_i}} & {s1t_add_sign,add_inv_i,add_inf_i,add_snan_i,add_qnan_i,add_anan_sign_i}) |
146
    ({6{mul_rdy_i}} & {mul_sign_i,mul_inv_i,mul_inf_i,mul_snan_i,mul_qnan_i,mul_anan_sign_i}) |
147
    ({6{f2i_rdy_i}} & {f2i_sign_i,1'b0,1'b0,f2i_snan_i,1'b0,f2i_sign_i}) |
148
    ({6{i2f_rdy_i}} & {i2f_sign_i,1'b0,1'b0,1'b0,1'b0,1'b0});
149
 
150
  // multiplexer for fractionals
151
  assign s1t_fract35 =
152
    ({35{add_rdy_i}} & {7'd0, add_fract28_i}) |
153
    ({35{mul_rdy_i}} & {7'd0, mul_fract28_i}) |
154
    ({35{f2i_rdy_i}} & {8'd0, f2i_int24_i, 3'd0}) |
155
    ({35{i2f_rdy_i}} & {i2f_fract32_i,3'd0});
156
 
157
  // overflow bit for add/mul
158
  wire s1t_addmul_carry = (add_rdy_i & add_fract28_i[27]) |
159
                          (mul_rdy_i & mul_fract28_i[27]);
160
 
161
  // multiplexer for shift values
162
  wire [4:0] s1t_shr_t;
163
  assign {s1t_shr_t, s1t_shl} =
164
    ({10{add_rdy_i}} & {5'd0, add_shl_i}) |
165
    ({10{mul_rdy_i}} & {mul_shr_i, {4'd0,mul_shl_i}}) |
166
    ({10{f2i_rdy_i}} & {f2i_shr_i, {1'b0,f2i_shl_i}}) |
167
    ({10{i2f_rdy_i}} & {{1'b0,i2f_shr_i}, i2f_shl_i});
168
 
169
  assign s1t_shr = (|s1t_shr_t) ? s1t_shr_t : {4'd0,s1t_addmul_carry};
170
 
171
  // align
172
  wire [34:0] s1t_fract35sh =
173
    (|s1t_shr) ? (s1t_fract35 >> s1t_shr) :
174
                 (s1t_fract35 << s1t_shl);
175
 
176
  // update sticky bit for right shift case.
177
  // maximum right shift value is :
178
  //    27 for mul/div
179
  //     8 for i2f
180
  reg s1r_sticky;
181
  always @(s1t_fract35 or s1t_shr) begin
182
    case (s1t_shr)
183
      5'd0   : s1r_sticky = |s1t_fract35[ 1:0];
184
      5'd1   : s1r_sticky = |s1t_fract35[ 2:0];
185
      5'd2   : s1r_sticky = |s1t_fract35[ 3:0];
186
      5'd3   : s1r_sticky = |s1t_fract35[ 4:0];
187
      5'd4   : s1r_sticky = |s1t_fract35[ 5:0];
188
      5'd5   : s1r_sticky = |s1t_fract35[ 6:0];
189
      5'd6   : s1r_sticky = |s1t_fract35[ 7:0];
190
      5'd7   : s1r_sticky = |s1t_fract35[ 8:0];
191
      5'd8   : s1r_sticky = |s1t_fract35[ 9:0];
192
      5'd9   : s1r_sticky = |s1t_fract35[10:0];
193
      5'd10  : s1r_sticky = |s1t_fract35[11:0];
194
      5'd11  : s1r_sticky = |s1t_fract35[12:0];
195
      5'd12  : s1r_sticky = |s1t_fract35[13:0];
196
      5'd13  : s1r_sticky = |s1t_fract35[14:0];
197
      5'd14  : s1r_sticky = |s1t_fract35[15:0];
198
      5'd15  : s1r_sticky = |s1t_fract35[16:0];
199
      5'd16  : s1r_sticky = |s1t_fract35[17:0];
200
      5'd17  : s1r_sticky = |s1t_fract35[18:0];
201
      5'd18  : s1r_sticky = |s1t_fract35[19:0];
202
      5'd19  : s1r_sticky = |s1t_fract35[20:0];
203
      5'd20  : s1r_sticky = |s1t_fract35[21:0];
204
      5'd21  : s1r_sticky = |s1t_fract35[22:0];
205
      5'd22  : s1r_sticky = |s1t_fract35[23:0];
206
      5'd23  : s1r_sticky = |s1t_fract35[24:0];
207
      5'd24  : s1r_sticky = |s1t_fract35[25:0];
208
      5'd25  : s1r_sticky = |s1t_fract35[26:0];
209
      default: s1r_sticky = |s1t_fract35[27:0];
210
    endcase
211
  end // always
212
 
213
  // update sticky bit for left shift case.
214
  reg s1l_sticky;
215
  always @(s1t_fract35 or s1t_shl) begin
216
    case (s1t_shl)
217
      5'd0   : s1l_sticky = |s1t_fract35[1:0];
218
      5'd1   : s1l_sticky =  s1t_fract35[0];
219
      default: s1l_sticky = 1'b0;
220
    endcase
221
  end // always
222
 
223
  wire s1t_sticky = (|s1t_shr) ? s1r_sticky : s1l_sticky;
224
 
225
  // two stage multiplexer for exponents
226
  wire [9:0] s1t_exp10shr;
227
  wire [9:0] s1t_exp10shl;
228
  wire [9:0] s1t_exp10sh0;
229
  assign {s1t_exp10shr, s1t_exp10shl, s1t_exp10sh0} =
230
    ({30{add_rdy_i}} & {add_exp10sh0_i, add_exp10shl_i, add_exp10sh0_i}) |
231
    ({30{mul_rdy_i}} & {mul_exp10shr_i, mul_exp10shl_i, mul_exp10sh0_i}) |
232
    ({30{f2i_rdy_i}} & {10'd0, 10'd0, 10'd0}) |
233
    ({30{i2f_rdy_i}} & {{2'd0,i2f_exp8shr_i},{2'd0,i2f_exp8shl_i},{2'd0,i2f_exp8sh0_i}});
234
 
235
  wire [9:0] s1t_exp10 =
236
    (|s1t_shr_t)  ? s1t_exp10shr :
237
    (~(|s1t_shl)) ? (s1t_exp10sh0 + {9'd0,s1t_addmul_carry}) :
238
                    s1t_exp10shl;
239
 
240
  // output of align stage 
241
  reg        s1o_sign;
242
  reg  [9:0] s1o_exp10;
243
  reg [31:0] s1o_fract32;
244
  reg  [1:0] s1o_rs;
245
  reg        s1o_inv;
246
  reg        s1o_inf;
247
  reg        s1o_snan_i;
248
  reg        s1o_qnan_i;
249
  reg        s1o_anan_sign_i;
250
  reg        s1o_div_op, s1o_div_sign_rmnd, s1o_div_dbz;
251
  reg        s1o_f2i_ovf, s1o_f2i;
252
  // registering
253
  always @(posedge clk) begin
254
    if(adv_i) begin
255
      s1o_sign    <= s1t_sign;
256
      s1o_exp10   <= s1t_exp10;
257
      s1o_fract32 <= s1t_fract35sh[34:3];
258
      s1o_rs      <= {s1t_fract35sh[2],s1t_sticky};
259
      // various flags:
260
      s1o_inv         <= s1t_inv;
261
      s1o_inf         <= s1t_inf;
262
      s1o_snan_i      <= s1t_snan;
263
      s1o_qnan_i      <= s1t_qnan;
264
      s1o_anan_sign_i <= s1t_anan_sign;
265
      // DIV specials
266
      s1o_div_op        <= mul_rdy_i & div_op_i;
267
      s1o_div_sign_rmnd <= div_sign_rmnd_i;
268
      s1o_div_dbz       <= div_dbz_i;
269
      // I2F specials
270
      s1o_f2i_ovf <= f2i_ovf_i;
271
      s1o_f2i     <= f2i_rdy_i;
272
    end // advance
273
  end // posedge clock
274
 
275
  // ready is special case
276
  reg s1o_ready;
277
  always @(posedge clk `OR_ASYNC_RST) begin
278
    if (rst)
279
      s1o_ready <= 1'b0;
280
    else if(flush_i)
281
      s1o_ready <= 1'b0;
282
    else if(adv_i)
283
      s1o_ready <= (add_rdy_i | mul_rdy_i | f2i_rdy_i | i2f_rdy_i);
284
  end // posedge clock
285
 
286
 
287
  /* Stage #2: rounding */
288
 
289
 
290
  wire s2t_dbz  = s1o_div_dbz;
291
 
292
  wire s2t_g    = s1o_fract32[0];
293
  wire s2t_r    = s1o_rs[1];
294
  wire s2t_s    = s1o_rs[0];
295
  wire s2t_lost = s2t_r | s2t_s;
296
 
297
  wire s2t_rnd_up = (rm_nearest & s2t_r & s2t_s) |
298
                    (rm_nearest & s2t_g & s2t_r & (~s2t_s)) |
299
                    (rm_to_infp & (~s1o_sign) & s2t_lost) |
300
                    (rm_to_infm &   s1o_sign  & s2t_lost);
301
 
302
  // IEEE compliance rounding for qutient
303
  wire s2t_div_rnd_up =
304
    (rm_nearest & s2t_r & s2t_s & (~s1o_div_sign_rmnd)) |
305
    ( ((rm_to_infp & (~s1o_sign)) | (rm_to_infm & s1o_sign)) &
306
      ((s2t_r & s2t_s) | ((~s2t_r) & s2t_s & (~s1o_div_sign_rmnd))) );
307
  wire s2t_div_rnd_dn = (~s2t_r) & s2t_s & s1o_div_sign_rmnd &
308
    ( (rm_to_infp &   s1o_sign)  |
309
      (rm_to_infm & (~s1o_sign)) |
310
       rm_to_zero );
311
 
312
  // set resulting direction of rounding
313
  //  a) normalized quotient is rounded by quotient related rules
314
  //  b) de-normalized quotient is rounded by common rules
315
  wire s2t_rnd_n_qtnt = s1o_div_op & s1o_fract32[23]; // normalized quotient
316
  wire s2t_set_rnd_up = s2t_rnd_n_qtnt ? s2t_div_rnd_up : s2t_rnd_up;
317
  wire s2t_set_rnd_dn = s2t_rnd_n_qtnt ? s2t_div_rnd_dn : 1'b0;
318
 
319
  // define value for rounding adder
320
  wire [31:0] s2t_rnd_v32 =
321
    s2t_set_rnd_up ? 32'd1        : // +1
322
    s2t_set_rnd_dn ? 32'hFFFFFFFF : // -1
323
                     32'd0;         // no rounding
324
  // rounded fractional
325
  wire [31:0] s2t_fract32_rnd = s1o_fract32 + s2t_rnd_v32;
326
 
327
 
328
  // floating point output
329
  wire s2t_f32_shr = s2t_fract32_rnd[24];
330
  // update exponent and fraction
331
  wire [9:0]  s2t_f32_exp10   = s1o_exp10 + {9'd0,s2t_f32_shr};
332
  wire [23:0] s2t_f32_fract24 = s2t_f32_shr ? s2t_fract32_rnd[24:1] :
333
                                              s2t_fract32_rnd[23:0];
334
   // denormalized or zero
335
  wire s2t_f32_fract24_dn = ~s2t_f32_fract24[23];
336
 
337
 
338
  // integer output (f2i)
339
  wire s2t_i32_carry_rnd = s1o_fract32[31];
340
  wire s2t_i32_inv = ((~s1o_sign) & s2t_i32_carry_rnd) | s1o_f2i_ovf;
341
  // two's complement for negative number
342
  wire [31:0] s2t_i32_int32 = (s1o_fract32 ^ {32{s1o_sign}}) + {31'd0,s1o_sign};
343
  // zero
344
  wire s2t_i32_int32_00 = (~s2t_i32_inv) & (~(|s2t_i32_int32));
345
  // int32 output
346
  wire [31:0] s2t_i32_opc;
347
  assign s2t_i32_opc =
348
    s2t_i32_inv ? (32'h7fffffff ^ {32{s1o_sign}}) : s2t_i32_int32;
349
 
350
 
351
   // Generate result and flags
352
  wire s2t_ine, s2t_ovf, s2t_inf, s2t_unf, s2t_zer;
353
  wire [31:0] s2t_opc;
354
  assign {s2t_opc,s2t_ine,s2t_ovf,s2t_inf,s2t_unf,s2t_zer} =
355
    // f2i
356
    s1o_f2i ?       //  ine  ovf  inf  unf              zer
357
      {s2t_i32_opc,s2t_lost,1'b0,1'b0,1'b0,s2t_i32_int32_00} :
358
    // qnan output
359
    (s1o_snan_i | s1o_qnan_i) ? // ine  ovf  inf  unf  zer
360
      {{s1o_anan_sign_i,QNAN},    1'b0,1'b0,1'b0,1'b0,1'b0} :
361
    // snan output
362
    s1o_inv ?        // ine  ovf  inf  unf  zer
363
      {{s1o_sign,SNAN},1'b0,1'b0,1'b0,1'b0,1'b0} :
364
    // overflow and infinity
365
    ((s2t_f32_exp10 > 10'd254) | s1o_inf | s2t_dbz) ? // ine                       ovf  inf  unf  zer
366
      {{s1o_sign,INF},((s2t_lost | (~s1o_inf)) & (~s2t_dbz)),((~s1o_inf) & (~s2t_dbz)),1'b1,1'b0,1'b0} :
367
    // denormalized or zero
368
    (s2t_f32_fract24_dn) ?                     // ine  ovf  inf 
369
      {{s1o_sign,8'd0,s2t_f32_fract24[22:0]},s2t_lost,1'b0,1'b0,
370
                                // unf        zer
371
       (s2t_lost & s2t_f32_fract24_dn),~(|s2t_f32_fract24)} :
372
    // normal result                                          ine  ovf  inf  unf  zer
373
    {{s1o_sign,s2t_f32_exp10[7:0],s2t_f32_fract24[22:0]},s2t_lost,1'b0,1'b0,1'b0,1'b0};
374
 
375
 
376
  // Output Register
377
  always @(posedge clk `OR_ASYNC_RST) begin
378
    if (rst) begin
379
        // arithmetic results
380
      fpu_result_o      <= 32'd0;
381
      fpu_arith_valid_o <=  1'b0;
382
        // comparison specials
383
      fpu_cmp_flag_o  <= 1'b0;
384
      fpu_cmp_valid_o <= 1'b0;
385
        // exeptions
386
      fpcsr_o         <= {`OR1K_FPCSR_WIDTH{1'b0}};
387
    end
388
    else if(flush_i) begin
389
        // arithmetic results
390
      fpu_result_o      <= 32'd0;
391
      fpu_arith_valid_o <=  1'b0;
392
        // comparison specials
393
      fpu_cmp_flag_o  <= 1'b0;
394
      fpu_cmp_valid_o <= 1'b0;
395
        // exeptions
396
      fpcsr_o         <= {`OR1K_FPCSR_WIDTH{1'b0}};
397
    end
398
    else if(adv_i) begin
399
        // arithmetic results
400
      fpu_result_o      <= s2t_opc;
401
      fpu_arith_valid_o <= s1o_ready;
402
        // comparison specials
403
      fpu_cmp_flag_o  <= cmp_res_i;
404
      fpu_cmp_valid_o <= cmp_rdy_i;
405
        // exeptions
406
      fpcsr_o[`OR1K_FPCSR_OVF] <= s2t_ovf;
407
      fpcsr_o[`OR1K_FPCSR_UNF] <= s2t_unf;
408
      fpcsr_o[`OR1K_FPCSR_SNF] <= s1o_inv | (s1o_snan_i & s1o_f2i);
409
      fpcsr_o[`OR1K_FPCSR_QNF] <= s1o_qnan_i;
410
      fpcsr_o[`OR1K_FPCSR_ZF]  <= s2t_zer;
411
      fpcsr_o[`OR1K_FPCSR_IXF] <= s2t_ine;
412
      fpcsr_o[`OR1K_FPCSR_IVF] <= (s1o_inv | (s2t_i32_inv & s1o_f2i) | s1o_snan_i) |
413
                                  (cmp_inv_i & cmp_rdy_i);
414
      fpcsr_o[`OR1K_FPCSR_INF] <= s2t_inf |
415
                                  (cmp_inf_i & cmp_rdy_i);
416
      fpcsr_o[`OR1K_FPCSR_DZF] <= s2t_dbz;
417
    end
418
  end // posedge clock
419
 
420
endmodule // pfpu32_rnd

powered by: WebSVN 2.1.0

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