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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [soc/] [rtl/] [altera_ddr_ctrl/] [altera_ddr_phy_report_timing.tcl] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 xianfeng
##
2
##Legal Notice: (C)2007 Altera Corporation. All rights reserved. Your
3
##use of Altera Corporation's design tools, logic functions and other
4
##software and tools, and its AMPP partner logic functions, and any
5
##output files any of the foregoing (including device programming or
6
##simulation files), and any associated documentation or information are
7
##expressly subject to the terms and conditions of the Altera Program
8
##License Subscription Agreement or other applicable license agreement,
9
##including, without limitation, that your use is for the sole purpose
10
##of programming logic devices manufactured by Altera and sold by Altera
11
##or its authorized distributors. Please refer to the applicable
12
##agreement for further details.
13
 
14
if { ![info exists quartus(nameofexecutable)] || $quartus(nameofexecutable) != "quartus_sta" } {
15
        puts "Restarting in quartus_sta..."
16
 
17
        set cmd quartus_sta
18
        if { [info exists quartus(binpath)] } {
19
                set cmd [file join $quartus(binpath) $cmd]
20
        }
21
 
22
        set res [catch { exec $cmd -t [info script] batch } output]
23
 
24
        # This procedure is 'clever' in that it will write a message using
25
        # post_message if available and refert to puts otherwise.
26
        # if post_message fails, this procedure changes itself into one that
27
        # uses a simple 'puts' and continues.
28
        proc out { msg } {
29
                set type info
30
                regexp {^\W*(Info|Extra Info|Warning|Critical Warning|Error): (.*)$} $msg x type msg
31
                regsub " " $type _ type
32
                if { [catch { post_message -type $type $msg } res] } {
33
                        proc out { msg } {puts $msg}
34
                        out $msg
35
                }
36
        }
37
 
38
        foreach line [split $output \n] {
39
                out $line
40
        }
41
        return 0
42
}
43
 
44
set scriptname [info script]
45
if { ! [regexp (.*)_report_timing.tcl $scriptname _ corename] } {
46
        error "Couldn't determine corename from $scriptname"
47
}
48
 
49
if {[namespace which -variable ::argv] != "" && [lindex $::argv 0] == "batch" } {
50
        post_message -type info "Running in batch mode"
51
 
52
        set proj_name [glob *.qpf]
53
        project_open -revision [get_current_revision $proj_name] $proj_name
54
 
55
        catch {delete_timing_netlist }
56
        create_timing_netlist
57
        read_sdc
58
 
59
        set opcs [list]
60
        foreach_in_collection op [get_available_operating_conditions] {
61
                lappend opcs $op
62
        }
63
 
64
        update_timing_netlist
65
} else {
66
        set opcs [list ""]
67
}
68
 
69
set fpga_tREAD_CAPTURE_SETUP_ERROR 0
70
set fpga_tREAD_CAPTURE_HOLD_ERROR 0
71
set fpga_RESYNC_SETUP_ERROR 0
72
set fpga_RESYNC_HOLD_ERROR 0
73
set fpga_PA_DQS_SETUP_ERROR 0
74
set fpga_PA_DQS_HOLD_ERROR 0
75
set WR_DQS_DQ_SETUP_ERROR 0
76
set WR_DQS_DQ_HOLD_ERROR 0
77
set fpga_tCK_ADDR_CTRL_SETUP_ERROR 0
78
set fpga_tCK_ADDR_CTRL_HOLD_ERROR 0
79
set fpga_tDQSS_SETUP_ERROR 0
80
set fpga_tDQSS_HOLD_ERROR 0
81
set fpga_tDSSH_SETUP_ERROR 0
82
set fpga_tDSSH_HOLD_ERROR 0
83
set write_deskew_mode "none"
84
set read_deskew_mode "none"
85
set write_deskew_t10 0
86
set write_deskew_t9i 0
87
set write_deskew_t9ni 0
88
set write_deskew_range 0
89
 
90
set period 6.666
91
 
92
load_package atoms
93
read_atom_netlist
94
 
95
proc traverse_atom_path {atom_id atom_oport_id path} {
96
        # Return list of {atom oterm_id} pairs by tracing the atom netlist starting from the given atom_id through the given path
97
        # Path consists of list of {atom_type fanin|fanout|end <port_type> <-optional>}
98
        set result [list]
99
        if {[llength $path] > 0} {
100
                set path_point [lindex $path 0]
101
                set atom_type [lindex $path_point 0]
102
                set next_direction [lindex $path_point 1]
103
                set port_type [lindex $path_point 2]
104
                set atom_optional [lindex $path_point 3]
105
                if {[get_atom_node_info -key type -node $atom_id] == $atom_type} {
106
                        if {$next_direction == "end"} {
107
                                if {[get_atom_port_info -key type -node $atom_id -port_id $atom_oport_id -type oport] == $port_type} {
108
                                        lappend result [list $atom_id $atom_oport_id]
109
                                }
110
                        } elseif {$next_direction == "fanin"} {
111
                                set atom_iport [get_atom_iport_by_type -node $atom_id -type $port_type]
112
                                if {$atom_iport != -1} {
113
                                        set iport_fanin [get_atom_port_info -key fanin -node $atom_id -port_id $atom_iport -type iport]
114
                                        set source_atom [lindex $iport_fanin 0]
115
                                        set source_oterm [lindex $iport_fanin 1]
116
                                        set result [traverse_atom_path $source_atom $source_oterm [lrange $path 1 end]]
117
                                }
118
                        } elseif {$next_direction == "fanout"} {
119
                                set atom_oport [get_atom_oport_by_type -node $atom_id -type $port_type]
120
                                if {$atom_oport != -1} {
121
                                        set oport_fanout [get_atom_port_info -key fanout -node $atom_id -port_id $atom_oport -type oport]
122
                                        foreach dest $oport_fanout {
123
                                                set dest_atom [lindex $dest 0]
124
                                                set dest_iterm [lindex $dest 1]
125
                                                set fanout_result_list [traverse_atom_path $dest_atom -1 [lrange $path 1 end]]
126
                                                foreach fanout_result $fanout_result_list {
127
                                                        if {[lsearch $result $fanout_result] == -1} {
128
                                                                lappend result $fanout_result
129
                                                        }
130
                                                }
131
                                        }
132
                                }
133
                        } else {
134
                                error "Unexpected path"
135
                        }
136
                } elseif {$atom_optional == "-optional"} {
137
                        set result [traverse_atom_path $atom_id $atom_oport_id [lrange $path 1 end]]
138
                }
139
        }
140
        return $result
141
}
142
 
143
# Get the fitter name of the PLL output driving the given pin
144
proc traverse_to_ddio_out_pll_clock {pin msg_list_name} {
145
        upvar 1 $msg_list_name msg_list
146
        set result ""
147
        if {$pin != ""} {
148
                set pin_id [get_atom_node_by_name -name $pin]
149
                set pin_to_pll_path [list {IO_PAD fanin PADIN} {IO_OBUF fanin I} {PSEUDO_DIFF_OUT fanin I -optional} {DDIO_OUT fanin CLKHI -optional} {CLKBUF fanin INCLK -optional} {PLL end CLK}]
150
                set pll_id_list [traverse_atom_path $pin_id -1 $pin_to_pll_path]
151
                if {[llength $pll_id_list] == 1} {
152
                        set atom_oterm_pair [lindex $pll_id_list 0]
153
                        set result [get_atom_port_info -key name -node [lindex $atom_oterm_pair 0] -port_id [lindex $atom_oterm_pair 1] -type oport]
154
                } else {
155
                        lappend msg_list "Error: PLL clock not found for $pin"
156
                }
157
        }
158
        return $result
159
}
160
 
161
proc verify_high_performance_timing_assumptions {instname pin_array_name write_deskew_t10} {
162
        upvar 1 $pin_array_name pins
163
        set num_errors 0
164
        load_package verify_ddr
165
        set ck_pins [lsort $pins(ck_p)]
166
        set ckn_pins [lsort $pins(ck_n)]
167
        set ck_ckn_pairs [list]
168
        set failed_assumptions [list]
169
 
170
        if {[llength $ck_pins] > 0 && [llength $ck_pins] == [llength $ckn_pins]} {
171
                for {set ck_index 0} {$ck_index != [llength $ck_pins]} {incr ck_index} {
172
                lappend ck_ckn_pairs [list [lindex $ck_pins $ck_index] [lindex $ckn_pins $ck_index]]
173
                }
174
        } else {
175
                incr num_errors
176
                lappend failed_assumptions "Error: Could not locate same number of CK pins as CK# pins"
177
        }
178
 
179
        set read_pins_list [list]
180
        set write_pins_list [list]
181
        foreach dqsgroup $pins(dqsgroup) {
182
                set dqs [lindex $dqsgroup 0]
183
                set dq_list [lindex $dqsgroup 2]
184
                lappend read_pins_list [list $dqs $dq_list]
185
                set dm_list [lindex $dqsgroup 1]
186
                lappend write_pins_list [list $dqs [concat $dq_list $dm_list]]
187
        }
188
        set all_write_dqs_list [get_all_dqs_pins $pins(dqsgroup)]
189
        set all_d_list [get_all_dq_pins $pins(dqsgroup)]
190
        if {[llength $pins(dqsgroup)] == 0} {
191
                incr num_errors
192
                lappend failed_assumptions "Error: Could not locate DQS pins"
193
        }
194
 
195
        if {$num_errors == 0} {
196
                set msg_list [list]
197
                set clk_to_write_d [traverse_to_ddio_out_pll_clock [lindex $all_d_list 0] msg_list]
198
                set clk_to_write_clock [traverse_to_ddio_out_pll_clock [lindex $all_write_dqs_list 0] msg_list]
199
                set clk_to_ck_ckn [traverse_to_ddio_out_pll_clock [lindex $ck_pins 0] msg_list]
200
 
201
                foreach msg $msg_list {
202
                        set verify_assumptions_exception 1
203
                        incr num_errors
204
                        lappend failed_assumptions $msg
205
                }
206
 
207
                if {$num_errors == 0} {
208
                        #puts "calling verify_assumptions -memory_type ddr -read_pins_list $read_pins_list -write_pins_list $write_pins_list -ck_ckn_pairs $ck_ckn_pairs -clk_to_write_d $clk_to_write_d -clk_to_write_clock $clk_to_write_clock -clk_to_ck_ckn $clk_to_ck_ckn -mimic_pin [lindex $ck_pins 0]  "
209
                        set verify_assumptions_exception 0
210
                        set verify_assumptions_result {0}
211
                        set verify_assumptions_exception [catch {verify_assumptions -memory_type ddr -read_pins_list $read_pins_list -write_pins_list $write_pins_list -ck_ckn_pairs $ck_ckn_pairs -clk_to_write_d $clk_to_write_d -clk_to_write_clock $clk_to_write_clock -clk_to_ck_ckn $clk_to_ck_ckn -mimic_pin [lindex $ck_pins 0]  } verify_assumptions_result]
212
                        if {$verify_assumptions_exception == 0} {
213
                                incr num_errors [lindex $verify_assumptions_result 0]
214
                                set failed_assumptions [concat $failed_assumptions [lrange $verify_assumptions_result 1 end]]
215
                        }
216
                }
217
                if {$verify_assumptions_exception != 0} {
218
                        lappend failed_assumptions "Error: Macro timing assumptions could not be verified"
219
                        incr num_errors
220
                }
221
        }
222
 
223
        if {$num_errors != 0} {
224
                for {set i 0} {$i != [llength $failed_assumptions]} {incr i} {
225
                        set raw_msg [lindex $failed_assumptions $i]
226
                        if {[regexp {^\W*(Info|Extra Info|Warning|Critical Warning|Error): (.*)$} $raw_msg -- msg_type msg]} {
227
                                regsub " " $msg_type _ msg_type
228
                                if {$msg_type == "Error"} {
229
                                        set msg_type "critical_warning"
230
                                }
231
                                post_message -type $msg_type $msg
232
                        } else {
233
                                post_message -type info $raw_msg
234
                        }
235
                }
236
                post_message -type critical_warning "Read Capture and Write timing analyses may not be valid due to violated timing model assumptions"
237
        }
238
        return [expr $num_errors == 0]
239
}
240
 
241
proc ddr_pin {n pin pin_array_name} {
242
        upvar 1 $pin_array_name pins
243
        lappend pins($n) $pin
244
}
245
 
246
load_package report
247
load_report
248
 
249
if { ! [timing_netlist_exist] } {
250
        post_message -type error "Timing Netlist has not been created. Run the 'Update Timing Netlist' task first."
251
        return
252
}
253
 
254
source "${corename}_ddr_pins.tcl"
255
 
256
set corename [file tail $corename]
257
set instance_names [get_core_full_instance_list $corename]
258
 
259
for {set inst_index 0} {$inst_index != [llength $instance_names]} {incr inst_index} {
260
        set full_instance_name [lindex $instance_names $inst_index]
261
        set instance_name [get_timequest_name $full_instance_name]
262
        set instname "${instance_name}|${corename}"
263
 
264
        global TimeQuestInfo
265
        set family $TimeQuestInfo(family)
266
 
267
        set pins(ck_p) [list]
268
        set pins(ck_n) [list]
269
        set pins(addrcmd) [list]
270
        set pins(addrcmd_2t) [list]
271
        set pins(dqsgroup) [list]
272
        set pins(dgroup) [list]
273
        get_ddr_pins $instname pins
274
        # Find all the DQ pins
275
        set alldqpins [list]
276
        set alldqdmpins [list]
277
        set alldqspins [list]
278
        foreach dqsgroup $pins(dqsgroup) {
279
                set alldqpins [concat $alldqpins [lindex $dqsgroup 2]]
280
                set alldqdmpins [concat $alldqdmpins [lindex $dqsgroup 2] [lindex $dqsgroup 1]]
281
                lappend alldqspins [lindex $dqsgroup 0]
282
        }
283
 
284
        set summary [list]
285
        foreach opc $opcs {
286
                if {$opc != "" } {
287
                        set_operating_conditions $opc
288
                        update_timing_netlist
289
                }
290
 
291
                set opcname [get_operating_conditions_info [get_operating_conditions] -display_name]
292
                set opcname [string trim $opcname]
293
 
294
                if {$altera_ddr_phy_use_high_performance_timing && $family != "HardCopy III" && $family != "HardCopy IV"} {
295
                        set assumptions_valid [verify_high_performance_timing_assumptions $instname pins $write_deskew_t10]
296
                }
297
                # endif altera_ddr_phy_use_high_performance_timing
298
 
299
                if {!$altera_ddr_phy_use_high_performance_timing} {
300
# Write
301
set res_0 [report_timing -detail full_path -to [get_ports $alldqdmpins] -npaths 100 -panel_name "$instname Write \u0028setup\u0029" -setup]
302
set res_1 [report_timing -detail full_path -to [get_ports $alldqdmpins] -npaths 100 -panel_name "$instname Write \u0028hold\u0029" -hold]
303
lappend summary [list $opcname 0 "Write ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
304
 
305
                }
306
                # endif !altera_ddr_phy_use_high_performance_timing
307
 
308
# Address Command
309
set res_0 [report_timing -detail full_path -to $pins(addrcmd) -npaths 100 -panel_name "$instname Address Command \u0028setup\u0029" -setup]
310
set res_1 [report_timing -detail full_path -to $pins(addrcmd) -npaths 100 -panel_name "$instname Address Command \u0028hold\u0029" -hold]
311
lappend summary [list $opcname 0 "Address Command ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
312
 
313
# DQS vs CK
314
set res_0 [report_timing -detail full_path -to [get_ports $alldqspins] -npaths 100 -panel_name "$instname DQS vs CK \u0028setup\u0029" -setup]
315
set res_1 [report_timing -detail full_path -to [get_ports $alldqspins] -npaths 100 -panel_name "$instname DQS vs CK \u0028hold\u0029" -hold]
316
lappend summary [list $opcname 0 "DQS vs CK ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
317
 
318
                if {!$altera_ddr_phy_use_high_performance_timing} {
319
# Read Capture
320
set res_0 [report_timing -detail full_path -from [get_ports $alldqpins] -to [all_registers] -npaths 100 -panel_name "$instname Read Capture \u0028setup\u0029" -setup]
321
set res_1 [report_timing -detail full_path -from [get_ports $alldqpins] -to [all_registers] -npaths 100 -panel_name "$instname Read Capture \u0028hold\u0029" -hold]
322
lappend summary [list $opcname 0 "Read Capture ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
323
 
324
                }
325
                # endif !altera_ddr_phy_use_high_performance_timing
326
 
327
# Phy
328
set res_0 [report_timing -detail full_path -to [get_registers  "$full_instance_name|*" ] -npaths 100 -panel_name "$instname Phy \u0028setup\u0029" -setup]
329
set res_1 [report_timing -detail full_path -to [get_registers  "$full_instance_name|*" ] -npaths 100 -panel_name "$instname Phy \u0028hold\u0029" -hold]
330
lappend summary [list $opcname 0 "Phy ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
331
 
332
# Phy Reset
333
set res_0 [report_timing -detail full_path -to [get_registers  "$full_instance_name|*" ] -npaths 100 -panel_name "$instname Phy Reset \u0028recovery\u0029" -recovery]
334
set res_1 [report_timing -detail full_path -to [get_registers  "$full_instance_name|*" ] -npaths 100 -panel_name "$instname Phy Reset \u0028removal\u0029" -removal]
335
lappend summary [list $opcname 0 "Phy Reset ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
336
 
337
# Mimic
338
set res_1 [list xxx ""]
339
set res_0 [report_timing -detail full_path -from $pins(ck_p) -to * -npaths 100 -panel_name "$instname Mimic \u0028setup\u0029" -setup]
340
lappend summary [list $opcname 0 "Mimic ($opcname)" [lindex $res_0 1] [lindex $res_1 1]]
341
 
342
}
343
set opcname "All Conditions"
344
set tDCD_total 0.250
345
 
346
if {$altera_ddr_phy_use_high_performance_timing} {
347
set board_skew 0.020
348
set tmin_additional_dqs_variation 0.000
349
set tmax_additional_dqs_variation 0.000
350
set tDS 0.400
351
set tDH 0.400
352
set tDQSQ 0.400
353
set tQHS 0.500
354
set tAC 0.700
355
set all_read_dqs_list [get_all_dqs_pins $pins(dqsgroup)]
356
set all_write_dqs_list $all_read_dqs_list
357
set all_d_list [get_all_dq_pins $pins(dqsgroup)]
358
set mem_if_memtype "DDR SDRAM"
359
set dqs_phase 60.000
360
# Write capture
361
set msg_list [list]
362
set dqs_pll_output_id [get_output_clock_id $all_write_dqs_list "DQS output" msg_list]
363
set dqs_pll_clock ""
364
sett_collection dqs_pll_clock_id [get_clocks [get_pin_info -name $dqs_pll_output_id]]
365
set dqs_output_phase [get_clock_info -phase $dqs_pll_clock_id]
366
set dq_pll_output_id [get_output_clock_id $all_d_list "DQ output" msg_list]
367
set dq_pll_clock ""
368
sett_collection dq_pll_clock_id [get_clocks [get_pin_info -name $dq_pll_output_id]]
369
set dq_output_phase [get_clock_info -phase $dq_pll_clock_id]
370
set dq2dqs_output_phase_offset [expr $dqs_output_phase - $dq_output_phase]
371
if {$dq2dqs_output_phase_offset < 0} {
372
  set dq2dqs_output_phase_offset [expr $dq2dqs_output_phase_offset + 360.0]
373
}
374
set tccs [get_tccs $mem_if_memtype $all_write_dqs_list $period]
375
set write_board_skew $board_skew
376
set su   [round_3dp [expr {$period*$dq2dqs_output_phase_offset/360.0 - $write_board_skew - [lindex $tccs 0]/1000.0 - $tDS}]]
377
set hold [round_3dp [expr {$period*(0.5 - $dq2dqs_output_phase_offset/360.0) - $tDCD_total - $write_board_skew - [lindex $tccs 1]/1000.0 - $tDH}]]
378
lappend summary [list $opcname 0 "Write ($opcname)" $su $hold]
379
# Read capture
380
set tsw [get_tsw $mem_if_memtype $all_read_dqs_list $period]
381
 
382
################################################################################
383
# Cyclone III uses a Macro Timing Methodology for the write and capture paths.
384
# The read data is captured using a PLL phase which is calibrated and tracked
385
# with the sequencer. The PHY will automatically calibrate the phase of a
386
# dedicated PLL read clock to center it within the read data valid window
387
# presented to all DQ capture registers.  The DQS read strobes are ignored, so
388
# postamble is not an issue. The phase of the read clock is adjusted to account
389
# for VT variations seen in the mimic path. Also, the exact length of the DQ
390
# and CK traces don't affect the timing analysis. Note that the read data
391
# resync to the PHY system clock domain is done through a dual-clock FIFO, so
392
# no resync timing analysis is needed for that transfer.
393
################################################################################
394
set su   [round_3dp [expr {0.25*$period - 0.5*$tDCD_total - $tAC - [lindex $tsw 0]/1000.0 - 0.5 * $board_skew}]]
395
set hold [round_3dp [expr {0.25*$period - 0.5*$tDCD_total - $tAC - [lindex $tsw 1]/1000.0 - 0.5 * $board_skew}]]
396
lappend summary [list $opcname 0 "Read Capture ($opcname)" $su $hold]
397
 
398
}
399
# endif altera_ddr_phy_use_high_performance_timing
400
proc sort_proc {a b} {
401
        set idxs [list 1 2 0]
402
        foreach i $idxs {
403
                set ai [lindex $a $i]
404
                set bi [lindex $b $i]
405
                if {$ai > $bi} {
406
                        return 1
407
                } elseif { $ai < $bi } {
408
                        return -1
409
                }
410
        }
411
        return 0
412
}
413
 
414
set summary [lsort -command sort_proc $summary]
415
if {[llength $instance_names] <= 1} {
416
        set f [open "${corename}_summary.csv" w]
417
} else {
418
        set f [open "${corename}${inst_index}_summary.csv" w]
419
}
420
puts $f "#Path, Setup Margin, Hold Margin"
421
post_message -type info "                                                         setup  hold"
422
set panel_name "$instname"
423
set root_folder_name [get_current_timequest_report_folder]
424
if { ! [string match "${root_folder_name}*" $panel_name] } {
425
        set panel_name "${root_folder_name}||$panel_name"
426
}
427
# Create the root if it doesn't yet exist
428
if {[get_report_panel_id $root_folder_name] == -1} {
429
        set panel_id [create_report_panel -folder $root_folder_name]
430
}
431
 
432
# Delete any pre-existing summary panel
433
set panel_id [get_report_panel_id $panel_name]
434
if {$panel_id != -1} {
435
        delete_report_panel -id $panel_id
436
}
437
 
438
# Create summary panel
439
set panel_id [create_report_panel -table $panel_name]
440
add_row_to_table -id $panel_id [list "Path" "Operating Condition" "Setup Slack" "Hold Slack"]
441
foreach summary_line $summary {
442
        foreach {corner order path su hold} $summary_line { }
443
                if { $su < 0 || ($hold!="" && $hold < 0) } {
444
                        set type warning
445
                        set offset 50
446
                } else {
447
                        set type info
448
                        set offset 53
449
                }
450
                set su [format %.3f $su]
451
                if {$hold != ""} {
452
                        set hold [format %.3f $hold]
453
                }
454
                post_message -type $type [format "%-${offset}s | %6s %6s" $path $su $hold]
455
                puts $f [format "\"%s\",%s,%s" $path $su $hold]
456
                set fg_colours [list black black]
457
                if { $su < 0 } {
458
                        lappend fg_colours red
459
                } else {
460
                        lappend fg_colours black
461
                }
462
                if { $hold != "" && $hold < 0 } {
463
                        lappend fg_colours red
464
                } else {
465
                        lappend fg_colours black
466
                }
467
                add_row_to_table -id $panel_id -fcolors $fg_colours [list $path $corner $su $hold]
468
        }
469
        close $f
470
}
471
write_timing_report

powered by: WebSVN 2.1.0

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