เมื่อคุณสร้างส่วนประกอบบล็อกการออกแบบหรือ HDL ที่สามารถนํากลับมาใช้ใหม่ได้ในหลายๆ การออกแบบ คุณอาจจําเป็นต้องสร้างข้อจํากัดของ SDC เพื่อใช้งาน การจะสร้างข้อจํากัดที่ไม่จําเป็นต้องแก้ไขโดยผู้ออกแบบนําส่วนประกอบไปใช้ใหม่จะเป็นประโยชน์มาก ข้อจํากัดควรเป็นแบบทั่วไป ดังนั้นข้อจํากัดจึงทํางานโดยไม่คํานึงว่าบล็อกจะถูกสร้างอินสแตนซ์ใดในลําดับชั้นการออกแบบและแบบไดนามิกเพื่อให้ทํางานโดยไม่คํานึงว่าบล็อกการออกแบบถูกเชื่อมต่ออย่างไร หากต้องแก้ไขข้อจํากัดด้วยตนเองเพื่อแสดงถึงการเปลี่ยนแปลงการออกแบบ ข้อจํากัดเหล่านั้นจะไม่ซิงค์ถ้านักออกแบบทําการเปลี่ยนแปลงการออกแบบโดยไม่อัปเดตข้อจํากัดด้วย
ตัวอย่างการออกแบบนี้ครอบคลุมเทคนิคการสร้างข้อจํากัด SDC แบบไดนามิกที่จัดการกับปัญหาสองประการต่อไปนี้:
- การกําหนดชื่อของ I/O ระดับสูงสุดที่เชื่อมต่อโดยตรงกับโมดูลระดับต่ํา
- การสร้างนาฬิกาที่สร้างขึ้นบนตรรกะในโมดูลระดับต่ํา
แผนผังในรูปภาพที่ 1 แสดงการออกแบบที่เรียบง่ายมากสําหรับตัวอย่างนี้ ซึ่งประกอบด้วยบล็อกการออกแบบที่นํากลับมาใช้ใหม่ได้สองอินสแตนซ์ที่มีชื่อว่า reusable_block ที่แสดงเป็นสีเหลือง รูปภาพที่ 2 แสดงเนื้อหาของการออกแบบreusable_block reusable_blockทําหน้าที่เป็นสัญญาณนาฬิกาอัตราข้อมูลสองเท่าสําหรับบัสเอาต์พุตซิงโครนัสต้นทาง เอาต์พุตต้องเชื่อมต่อกับเอาต์พุตระดับสูงสุด ข้อจํากัดสําหรับreusable_blockต้องรวมนาฬิกาที่สร้างขึ้น เนื่องจากฟังก์ชันเอาต์พุตเป็นสัญญาณนาฬิกาซิงโครนัสต้นทาง
การระบุชื่อ I/O ระดับสูงสุด
ข้อจํากัดสําหรับreusable_blockต้องรองรับการเปลี่ยนแปลงชื่อ I/O ระดับสูงสุด ดังนั้น ต้องกําหนดชื่อ I/O ระดับสูงสุดในระหว่างการคอมไพล์หรือการวิเคราะห์เวลา คําสั่ง get_fanouts Tcl จะส่งคืนชุดข้อมูลของ ID ที่แสดงถึงพอร์ตหรือการลงทะเบียนที่เป็นส่วนหนึ่งในชื่อที่ระบุ คําสั่ง get_fanouts Tcl ใช้ Netlist กําหนดเวลาที่มีอยู่ในระหว่างการคอมไพล์หรือการวิเคราะห์เวลา จึงกําหนดการเชื่อมต่อแบบไดนามิกโดยไม่คํานึงชื่อของโหนดพัดลม รหัส Tcl ต่อไปนี้แสดงวิธีใช้get_fanoutsเพื่อรับผลลัพธ์ระดับสูงสุดซึ่งเป็นความคับคั่งโดยตรงของการลงทะเบียนระดับต่ํา
foreach_in_collection fanout_id [get_fanouts $low_level_register_name] { break } set top_level_io_name [get_node_info -name $fanout_id]
ไม่จําเป็นต้องทราบชื่อลําดับชั้นทั้งหมดของการลงทะเบียนระดับต่ํา เนื่องจากคุณสามารถใช้สัญลักษณ์ตัวแทนและส่วนที่รู้จักของลําดับชั้นที่มีอยู่ใน Design Block ที่นํากลับมาใช้ใหม่ได้เพื่อให้ตรงกัน ตัวอย่างรหัสสุดท้ายในหน้านี้แสดงตัวอย่างวิธีการจับคู่ชื่อการลงทะเบียนระดับต่ํา
ในการออกแบบในรูปภาพที่ 1 พินเอาต์พุตโมดูลระดับต่ําจะถูกเชื่อมต่อโดยตรงกับเอาต์พุตระดับสูงสุดหนึ่งตัว Tcl code ต่อไปนี้เพิ่มการตรวจสอบข้อผิดพลาดเพื่อให้แน่ใจว่าพัดลมลงทะเบียนระดับต่ําออกไปเพียงตําแหน่งเดียวและตําแหน่งพัดลมเป็นพอร์ตเอาต์พุต โค้ด Tcl นี้ควรเป็นส่วนหนึ่งของไฟล์ SDC ที่มีข้อจํากัดreusable_block
# รับแฟนๆ ของชุดลงทะเบียนระดับต่ํา fanout_collection [get_fanouts $low_level_register_name] # ตรวจสอบให้แน่ใจว่ามีnum_fanoutsชุดพัดลมเพียงชุดเดียว [get_collection_size $fanout_collection] หาก { 1 != $num_fanouts } { ข้อผิดพลาดในการส่งคืนรหัส "$low_level_register_name fans ออกไปยัง$num_fanouts \ โหนด แต่ต้องออกเป็นหนึ่งโหนด" } # รับชื่อของโหนด fanout foreach_in_collection fanout_id $fanout_collection { break } set fanout_name [get_node_info -name $fanout_id] # ตรวจสอบว่าโหนด fanout เป็นพอร์ตเอาต์พุตหาก { get_port_info -is_output_port $fanout_id } is_output] } { # มีข้อผิดพลาด - ไม่ได้ทําให้พอร์ต ส่งคืน -code error "$low_level_register_name fans out to $fanout_name \ ซึ่งไม่ใช่พอร์ต" } อื่นๆ { ! $is_ เอาต์พุต } { # ไม่มีข้อผิดพลาด แต่พอร์ตไม่ใช่ข้อผิดพลาดในการส่งคืนพอร์ตเอาต์พุต -code "$fanout_name ไม่ใช่พอร์ตเอาต์พุต" } อีกอย่าง { set top_level_io_name $fanout_name } # top_level_io_nameเป็นพอร์ตเอาต์พุตเพียงพอร์ตเดียวของ low_level_register_name และเป็น # พอร์ตเอาต์พุต
การสร้างนาฬิกาที่สร้างขึ้น
ต้องกําหนดให้สัญญาณนาฬิกาเอาต์พุตซิงโครนัสต้นทางเป็นนาฬิกาที่สร้างขึ้น โดยยึดตามนาฬิกาที่ป้อนการลงทะเบียนเอาต์พุตอัตราข้อมูลสองตัว ต้องสร้างนาฬิกาที่สร้างขึ้นโดยไม่มีการป้อนข้อมูลใดๆ เกี่ยวกับนาฬิกาในการออกแบบด้วยตนเอง เนื่องจากบล็อกการออกแบบสามารถสร้างอินสแตนซ์ในการออกแบบใดๆ ด้วยรูปแบบการนาฬิกาใดๆ
คําสั่ง SDC ต่อไปนี้แสดงวิธีง่ายๆ ในการสร้างนาฬิกาที่สร้างขึ้นสําหรับสัญญาณนาฬิกาเอาต์พุตซิงโครนัสต้นทางสําหรับการออกแบบในรูปภาพที่ 1 เมื่อไม่ทราบตําแหน่งในลําดับชั้น
create_generated_clock -name reusable_generated -source [get_pins \ *|reusable_block_clock_out|altddio_out_component|auto_generated|ddio_outa[0]|muxsel] \ $top_level_io_name
ซึ่งเป็นวิธีการที่ตรงไปตรงมาที่ทํางานได้กับการสร้างอินสแตนซ์เดียวของreusable_blockที่ใดก็ได้ในลําดับชั้นการออกแบบ แต่ไม่สามารถจัดการกับสถานการณ์การสร้างอินสแตนซ์หรือมัลติคล็อกหลายสถานการณ์ได้ เมื่อไม่ทราบรูปแบบการนาฬิกา ข้อจํากัดนาฬิกาที่สร้างขึ้นจะสามารถจัดการกับสถานการณ์ที่มีการกําหนดสัญญาณนาฬิกาหลายครั้งบนสัญญาณนาฬิกาเดียวที่ป้อนบล็อกการออกแบบ สัญญาณนาฬิกาหลายสัญญาณมักจะมีอยู่ในการออกแบบที่รองรับความเร็วโปรโตคอล I/O ที่แตกต่างกัน หรือการออกแบบที่รองรับการสลับสัญญาณนาฬิกาเพื่อความซ้ําซ้อน ตัวอย่างสัญญาณนาฬิกาที่สร้างขึ้นอย่างง่ายด้านบนล้มเหลวในสถานการณ์มัลติคล็อกเนื่องจากไม่มีตัวเลือก -master_clock ในการแบ่งระหว่างนาฬิกาต้นทางหลายตัว
ในการจัดการการสร้างอินสแตนซ์หลายครั้ง ให้ใช้ลูปเพื่อสร้างนาฬิกาที่สร้างขึ้นเฉพาะสําหรับการสร้างอินสแตนซ์แต่ละครั้ง ในการจัดการสถานการณ์แบบมัลติคล็อก ให้ใช้ขั้นตอนแบบกําหนดเองที่เรียกว่า get_clocks_driving_pin ที่อธิบายไว้ในตัวอย่างการออกแบบ พินการป้อนสัญญาณนาฬิกา ในการใช้ขั้นตอนแบบกําหนดเอง คุณต้องคัดลอกจากหน้าตัวอย่างการออกแบบ พิน คุณสามารถบันทึกเป็นไฟล์ SDC แยกต่างหากที่เพิ่มเข้าในโครงการ หรือคัดลอกและวางลงในไฟล์ SDC เดียวโดยมีข้อจํากัดอื่นๆ ทั้งหมดที่มีข้อจํากัดของบล็อกที่นํากลับมาใช้ใหม่ได้ หากคุณบันทึกเป็นไฟล์ SDC ที่เพิ่มเข้าในโครงการ ตรวจสอบให้แน่ใจว่าไฟล์ดังกล่าวอยู่ก่อนหน้าไฟล์ SDC ใดๆ ที่ใช้ขั้นตอนกําหนดเองget_clocks_driving_pin
รหัส Tcl ต่อไปนี้แสดงวิธีสร้างข้อจํากัดนาฬิกาที่สร้างขึ้นบนเอาต์พุตระดับสูงสุดที่ขับเคลื่อนด้วยการลงทะเบียนระดับต่ําในการออกแบบที่แสดงในรูปภาพที่ 1 สัญญาณนาฬิกาที่สร้างขึ้นจะใช้เอาต์พุตระดับสูงสุดเป็นเป้าหมาย และพิน muxsel ของaltddio_outputรีจิสเตอร์เป็นแหล่งข้อมูล รหัสนี้ใช้ลูปเพื่อทําซ้ําการสร้างอินสแตนซ์ทั้งหมดของreusable_blockในการออกแบบ และลูปที่ซ้อนกันเพื่อจัดการกับสถานการณ์การล็อกหลายตัวด้วยขั้นตอนแบบกําหนดเองของget_clocks_driving_pin จะถือว่ามีการกําหนดขั้นตอนget_clocks_driving_pinไว้แล้ว
# get_pins ส่งกลับหนึ่งพิน muxsel สําหรับการสร้างอินสแตนซ์แต่ละreusable_block # foreach_in_collectionซ้ําforeach_in_collection pin_idพิน muxsel แต่ละตัว [get_pins -compatibility_mode \ *|reusable_block_clock_out|altddio_out_component|auto_generated|ddio_outa[0]|muxsel] { # pin_name มีลําดับชั้นการออกแบบเต็มรูปแบบของพิน muxsel สําหรับ การสร้างอินสแตนซ์ชุดreusable_blockหนึ่งpin_name [get_node_info -name $pin_id] # ใช้รหัสที่แสดงด้านบนโดยไม่มีการตรวจสอบข้อผิดพลาด เพื่อรับ ชื่อของforeach_in_collection port_idเอาต์พุตระดับสูงสุด [get_fanouts $pin_name] { break } ตั้งค่าport_name [get_node_info -name $port_id] # อาจมีนาฬิกาหลายตัวที่ป้อนaltddio_outputลงทะเบียน # นาฬิกาที่สร้างขึ้นหนึ่งตัวสําหรับแต่ละนาฬิกาที่ป้อน # พิน muxsel แต่ละนาฬิกาที่ป้อนพิน muxsel เป็นนาฬิกา หลัก foreach master_clock [get_clocks_feeding_pin $pin_name] { post_message "การสร้างนาฬิกาที่สร้างขึ้นบน $port_name ที่ป้อนโดย $pin_name" # สร้างนาฬิกาที่สร้างขึ้นด้วยนาฬิกา หลักที่เหมาะสม # แหล่งที่มาคือพิน muxsel ของเซลล์ altddio_output ใน # การสร้างอินสแตนซ์ปัจจุบันของreusable_block # ชื่อคือการรวมกันของนาฬิกาหลักและ ชื่อลําดับชั้นแบบเต็ม # ของพิน muxsel # เป้าหมายคือพอร์ตระดับบนสุดที่เป็นส่วนสําคัญของพิน muxsel create_generated_clock -add -master_clock $master_clock \ -source [get_pins $pin_name] -name ${master_clock}-${pin_name} \ [get_ports $port_name] }
ด้วยรหัสนี้ในไฟล์ SDC ที่รวมอยู่ในโครงการ การสร้างอินสแตนซ์ทั้งหมดของreusable_blockจะมีข้อจํากัดโดยอัตโนมัติกับนาฬิกาที่สร้างขึ้น นาฬิกาที่สร้างขึ้นจะมีความถูกต้องและเป็นปัจจุบันเสมอ แม้ในสถานการณ์ต่อไปนี้:
- reusable_blockจะสร้างอินสแตนซ์หรือย้ายไปยังจุดอื่นๆ ในลําดับชั้นของการออกแบบ
- I/O ระดับสูงสุดจะถูกเปลี่ยนชื่อ
- ตัวออกแบบใช้คําจํากัดความนาฬิกาหลายคําในการออกแบบ