# ============================================================================= # gen_ip.tcl -- create the Vivado IPs listed in rtl_ip/ip_manifest.tcl # usage: vivado -mode batch -source gen_ip.tcl -tclargs [part] # Managed-IP style: .xci + synthesis + simulation targets are generated so the # cores can be (a) added to the synthesis project and (b) compiled for xsim. # ============================================================================= set manifest [lindex $argv 0] set ipdir [file normalize [lindex $argv 1]] set part xc7z100ffg900-2 if {[llength $argv] > 2} { set part [lindex $argv 2] } file mkdir $ipdir create_project -in_memory -part $part set_property target_language Verilog [current_project] set ips {} source $manifest ;# fills $ips: list of {type {..} name {..} width {..} depth {..} coe {..} mode {..}} # manifest field with a default (older manifests do not carry the newer keys) proc opt {arrname key def} { upvar 1 $arrname c if {[info exists c($key)] && $c($key) ne {}} { return $c($key) } return $def } foreach ip $ips { array unset c; array set c $ip set name $c(name) if {[file exists $ipdir/$name/$name.xci]} { puts "###### SKIP $name (exists)" continue } switch -- $c(type) { dist_mem_gen { create_ip -name dist_mem_gen -vendor xilinx.com -library ip -version 8.0 \ -module_name $name -dir $ipdir set_property -dict [list \ CONFIG.memory_type {rom} \ CONFIG.data_width $c(width) \ CONFIG.depth $c(depth) \ CONFIG.coefficient_file $c(coe) \ ] [get_ips $name] } blk_mem_gen { # SDP, common clock, READ_FIRST on the write port, no output register, # ENA/ENB pins -- matches SimpleDualPortRAM_generic semantics exactly. create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 \ -module_name $name -dir $ipdir set_property -dict [list \ CONFIG.Memory_Type {Simple_Dual_Port_RAM} \ CONFIG.Assume_Synchronous_Clk {true} \ CONFIG.Use_Byte_Write_Enable {false} \ CONFIG.Write_Width_A $c(width) \ CONFIG.Write_Depth_A $c(depth) \ CONFIG.Read_Width_A $c(width) \ CONFIG.Write_Width_B $c(width) \ CONFIG.Read_Width_B $c(width) \ CONFIG.Operating_Mode_A {READ_FIRST} \ CONFIG.Enable_A {Use_ENA_Pin} \ CONFIG.Enable_B {Use_ENB_Pin} \ CONFIG.Register_PortB_Output_of_Memory_Primitives {false} \ CONFIG.Register_PortB_Output_of_Memory_Core {false} \ ] [get_ips $name] } fifo_generator { # guided: mode field carries standard|fwft; depth/width from manifest create_ip -name fifo_generator -vendor xilinx.com -library ip -version 13.2 \ -module_name $name -dir $ipdir set rm {Standard_FIFO} if {[info exists c(mode)] && $c(mode) eq "fwft"} { set rm {First_Word_Fall_Through} } set_property -dict [list \ CONFIG.Fifo_Implementation {Common_Clock_Block_RAM} \ CONFIG.Performance_Options $rm \ CONFIG.Input_Data_Width $c(width) \ CONFIG.Input_Depth $c(depth) \ CONFIG.Output_Data_Width $c(width) \ CONFIG.Output_Depth $c(depth) \ ] [get_ips $name] } cordic { # guided: Arc_Tan phase-seed kernel. Coarse rotation = full-quadrant atan2 # (bidirectional-adjustment principle: better than the FSM's RHP quirk); # Radians 3QN phase; Truncate rounding; ACLKEN so enb gating stays exact; # parallel/maximum pipelining -> latency ~input_width+4, well under the # 64-cycle commit budget. create_ip -name cordic -vendor xilinx.com -library ip -version 6.0 \ -module_name $name -dir $ipdir set_property -dict [list \ CONFIG.Functional_Selection {Arc_Tan} \ CONFIG.Input_Width $c(width) \ CONFIG.Output_Width $c(out_width) \ CONFIG.Data_Format {SignedFraction} \ CONFIG.Phase_Format {Radians} \ CONFIG.Coarse_Rotation {true} \ CONFIG.Round_Mode {Truncate} \ CONFIG.ACLKEN {true} \ CONFIG.Pipelining_Mode {Maximum} \ ] [get_ips $name] } fir_compiler { # guided (Task12 §六). Cycle-true-critical settings: # Integer_Coefficients : taps go in as integers, the IP must NOT re-quantise # Full_Precision output : truncation stays OUTSIDE, done the way the RTL did it # Input_Sample_Period/1 : one sample per clock, no hardware folding # -> the latency is a fixed number we can align to # ACLKEN : gated by enb exactly like the generated RTL # no TREADY / no input FIFO: pure pipeline, no variable-latency handshake create_ip -name fir_compiler -vendor xilinx.com -library ip -version 7.2 \ -module_name $name -dir $ipdir set_property -dict [list \ CONFIG.Filter_Type [opt c filter_type {Single_Rate}] \ CONFIG.CoefficientSource {COE_File} \ CONFIG.Coefficient_File $c(coe) \ CONFIG.Quantization {Integer_Coefficients} \ CONFIG.Coefficient_Width $c(coef_width) \ CONFIG.Coefficient_Fractional_Bits [opt c coef_frac 0] \ CONFIG.Coefficient_Sign {Signed} \ CONFIG.Coefficient_Structure [opt c coef_structure {Inferred}] \ CONFIG.Data_Width $c(width) \ CONFIG.Data_Fractional_Bits [opt c frac 0] \ CONFIG.Data_Sign {Signed} \ CONFIG.Output_Rounding_Mode {Full_Precision} \ CONFIG.RateSpecification {Input_Sample_Period} \ CONFIG.SamplePeriod 1 \ CONFIG.HardwareOversamplingRate 1 \ CONFIG.Interpolation_Rate [opt c interp 1] \ CONFIG.Decimation_Rate [opt c decim 1] \ CONFIG.Zero_Pack_Factor [opt c zero_pack 1] \ CONFIG.Number_Channels [opt c channels 1] \ CONFIG.Number_Paths [opt c paths 1] \ CONFIG.Coefficient_Reload [opt c reload {false}] \ CONFIG.Num_Reload_Slots [opt c reload_slots 1] \ CONFIG.Has_ACLKEN [opt c aclken {true}] \ CONFIG.Has_ARESETn [opt c aresetn {false}] \ CONFIG.M_DATA_Has_TREADY {false} \ CONFIG.S_DATA_Has_FIFO {false} \ ] [get_ips $name] } cic_compiler { # guided: only for large integer rate changes (CIC), fixed rate so the # decimation/interpolation cadence is static and comparable cycle by cycle. create_ip -name cic_compiler -vendor xilinx.com -library ip -version 4.0 \ -module_name $name -dir $ipdir set rate [opt c rate 1] set_property -dict [list \ CONFIG.Filter_Type [opt c filter_type {Decimation}] \ CONFIG.Number_Of_Stages [opt c stages 3] \ CONFIG.Differential_Delay [opt c diff_delay 1] \ CONFIG.Sample_Rate_Changes {Fixed} \ CONFIG.Fixed_Or_Initial_Rate $rate \ CONFIG.Minimum_Rate [opt c min_rate $rate] \ CONFIG.Maximum_Rate [opt c max_rate $rate] \ CONFIG.Input_Data_Width $c(width) \ CONFIG.Quantization {Full_Precision} \ CONFIG.RateSpecification {Sample_Period} \ CONFIG.SamplePeriod 1 \ CONFIG.Number_Of_Channels [opt c channels 1] \ CONFIG.Use_Xtreme_DSP_Slice {false} \ CONFIG.HAS_ACLKEN [opt c aclken {true}] \ CONFIG.HAS_ARESETN [opt c aresetn {false}] \ CONFIG.HAS_DOUT_TREADY {false} \ ] [get_ips $name] } default { puts "###### UNKNOWN IP TYPE: $c(type) ($name)"; continue } } generate_target {instantiation_template synthesis simulation} [get_ips $name] puts "###### GENERATED $name ($c(type))" } puts "###### DONE [llength $ips] ip(s) in $ipdir"