
1. 说明XCKU5P 流水灯 · 单文件纯 TCL 版 使用说明led_blink_all_in_one.tcl—— 一个文件包含全部内容Verilog 源码、XDC 约束、Testbench 均以 here-doc 内嵌由 TCL 自动写出并跑完「建工程 → 综合 → 实现 → 比特流 → 报告」全流程。工具链Vivado 2024.1 Ubuntu 22.04 XCKU5PKintex UltraScale1.1. 快速开始source/tools/Xilinx/Vivado/2024.1/settings64.sh vivado-modebatch-sourceled_blink_all_in_one.tcl成功后在脚本同级目录生成led_blink_xcku5p/ ├── led_blink.v ← TCL 写出的 RTL差分时钟 双向流水 ├── led_blink.xdc ← TCL 写出的约束 ├── tb_led_blink.v ← TCL 写出的仿真平台 ├── led_blink.bit ← 最终比特流从 runs 目录拷贝而来 ├── reports/ ← timing / utilization / power / drc 报告 ├── led_blink_xcku5p.xpr ← 工程文件可 GUI 打开 └── led_blink_xcku5p.runs/ ← 综合实现中间产物脚本可重复执行每次运行先删除旧工程目录从头重建结果可复现。1.2. 硬件约束与板卡对应关系信号管脚电平说明clk_pT24DIFF_SSTL12差分晶振 P 端N 端自动配对不约束rst_nK9LVCMOS33复位按键低有效led[0]H9LVCMOS33LED1高电平点亮led[1]J9LVCMOS33LED2led[2]G11LVCMOS33LED3led[3]H11LVCMOS33LED4功能双向流水每 2 秒切换一次H9 → J9 → G11 → H11 → G11 → J9 → H9 → ...到两端自动折返1.3. 与参考脚本相比的差异点本版本按实际板卡约束做了以下修正时钟改为差分晶振参考脚本用 50 MHz 单端时钟K25/LVCMOS18本版用 T24 差分晶振 IBUFDS原语DIFF_SSTL12只绑 P 端默认 200 MHz电平标准统一为 LVCMOS33LED 与复位与 spec 给的约束一致Testbench 改为差分时钟激励clk_p/clk_n相位相反并通过参数覆盖把分频计数缩小到 1000仿真可在 50 µs 内看到完整往返修复报告生成问题参考脚本在launch_runs后直接report_*batch 模式下没有打开的设计会报错本版先open_run impl_1再出报告SPIx4 配置改为可选注释CONFIG_MODE SPIx4依赖板载 Flash 硬件默认只保留比特流压缩需要烧 Flash 时再取消注释。1.4. 常见修改点需求修改位置都在led_blink_all_in_one.tcl内器件型号不符第 0 节set PART可用get_parts *ku5p*查询晶振不是 200 MHz① 内嵌 Verilog 参数CLK_FREQ_HZ② 内嵌 XDC 的create_clock -period如 156.25 MHz → 6.400切换间隔内嵌 Verilog 参数SWITCH_SEC改成单向循环流水把移位逻辑中的折返分支去掉到顶/到底后直接回到4b0001或改用{led_reg[2:0], led_reg[3]}循环移位板子 LED 低电平点亮初值改4b1110并将移位方向取反需要烧写 QSPI Flash取消 XDC 末尾SPI_BUSWIDTH/CONFIG_MODE两行注释再用write_cfgmem生成 .mcs1.5. 仿真验证可选流程跑完后vivado-modetclopen_project led_blink_xcku5p/led_blink_xcku5p.xpr launch_simulation ;# 打开 xsim GUI已配置 log_all_signals控制台会打印 LED 变化序列应为0001 → 0010 → 0100 → 1000 → 0100 → 0010 → 0001 → 0010 → 0100共 9 次状态一个完整往返与双向流水逻辑一致。1.6. 常见问题is not a valid partPART与板卡丝印不一致在vivado -mode tcl中执行get_parts *ku5p*选对应型号如xcku5p-ffvb676-2-i。给clk_n加约束报错差分对只需约束 P 端T24N 端由工具自动配对不要为clk_n写PACKAGE_PIN。CFGBVS / CONFIG_VOLTAGE DRC 警告按原理图 Bank0 的 VCCO 电压在 XDC 中补set_property CFGBVS与CONFIG_VOLTAGE。下载比特流在led_blink_xcku5p/led_blink.bit可用 Hardware Manager 或上一版项目的program.tcl下载上板现象为 2 秒间隔的双向流水按住 K9 复位回 H9。2. 项目脚本led_blink_all_in_one.tcl# # led_blink_all_in_one.tcl # # XCKU5P 流水灯 —— 单文件纯 TCL 全流程脚本 # Verilog 源码 / XDC 约束 / Testbench 全部内嵌在本文件中 # 由 TCL 自动写出 - 建工程 - 综合 - 实现 - 比特流 - 报告。 # # 功能 : 4 个 LED 双向流水 1-2-3-4-3-2-1 ...每 2 秒切换 # 器件 : xcku5p-ffvb676-2-e按板卡丝印修改下方 PART # 时钟 : 差分晶振P 端 T24DIFF_SSTL12默认 200 MHz # 复位 : K9LVCMOS33低有效 # LED : H9 / J9 / G11 / H11LVCMOS33高电平点亮三极管基极 # # 用法Ubuntu 22.04 Vivado 2024.1: # source /tools/Xilinx/Vivado/2024.1/settings64.sh # vivado -mode batch -source led_blink_all_in_one.tcl # # 可选流程结束后在 TCL 控制台运行仿真 # vivado -mode tcl - open_project led_blink_xcku5p/led_blink_xcku5p.xpr # - launch_simulation # #--------------------------------------------------------------- # 0. 用户配置区需要改的地方都在这里 #--------------------------------------------------------------- set PROJECT_NAME led_blink_xcku5p set PART xcku5p-ffvb676-2-e ;# 器件型号查询命令: get_parts *ku5p* set JOBS 8 ;# 编译并行线程数按 CPU 核数调整 set SCRIPT_DIR [file dirname [file normalize [info script]]] set PROJECT_DIR $SCRIPT_DIR/$PROJECT_NAME puts puts XCKU5P 4-LED 双向流水灯 (单文件 TCL 全流程) puts Project : $PROJECT_NAME puts Part : $PART puts Dir : $PROJECT_DIR puts #--------------------------------------------------------------- # 1. 创建工程已存在则先删除保证可重复执行 #--------------------------------------------------------------- if {[file exists $PROJECT_DIR]} { file delete -force $PROJECT_DIR } create_project $PROJECT_NAME $PROJECT_DIR -part $PART set_property target_language Verilog [current_project] set_property simulator_language Verilog [current_project] #--------------------------------------------------------------- # 2. 内嵌 Verilog 源码并写出 # 差分晶振 - IBUFDS - 计数分频(2s) - 双向流水移位 #--------------------------------------------------------------- set verilog_content { timescale 1ns / 1ps // // led_blink.v // XCKU5P 4-LED 双向流水灯 // 时钟: 差分晶振 - IBUFDS - 单端 (默认 200 MHz) // 复位: rst_n 低有效, 异步复位 // LED : 高电平点亮 (FPGA 管脚 - 三极管基极) // module led_blink #( parameter integer CLK_FREQ_HZ 200_000_000, // 差分晶振频率(Hz) parameter integer SWITCH_SEC 2 // 每个灯点亮时长(秒) )( input wire clk_p, // 差分晶振 P 端 - T24 input wire clk_n, // 差分晶振 N 端 (差分对自动配对, 无需约束) input wire rst_n, // 复位按键 - K9, 低有效 output wire [3:0] led // 4 个 LED - H9/J9/G11/H11 ); //---------------------------------------------------------- // 1. 差分时钟转单端 (UltraScale 原语) //---------------------------------------------------------- wire clk; IBUFDS #( .DIFF_TERM (FALSE), .IBUF_LOW_PWR (TRUE), .IOSTANDARD (DEFAULT) ) u_ibufds ( .O (clk), .I (clk_p), .IB (clk_n) ); //---------------------------------------------------------- // 2. 定时计数器: 数满 CLK_FREQ_HZ*SWITCH_SEC 个周期 2 秒 // 200 MHz x 2 s 400_000_000, 32 位计数器足够 //---------------------------------------------------------- localparam integer CNT_MAX CLK_FREQ_HZ * SWITCH_SEC; reg [31:0] cnt; reg [3:0] led_reg; reg dir; // 0: 向高位流动 1: 向低位流动 wire tick (cnt CNT_MAX - 1); always (posedge clk or negedge rst_n) begin if (!rst_n) cnt 32d0; else if (tick) cnt 32d0; else cnt cnt 1b1; end //---------------------------------------------------------- // 3. 双向流水: 0001-0010-0100-1000-0100-0010-0001-... //---------------------------------------------------------- always (posedge clk or negedge rst_n) begin if (!rst_n) begin led_reg 4b0001; // 初始: LED1(H9) 亮 dir 1b0; end else if (tick) begin if (dir 1b0) begin // 向高位流动 1-2-3-4 if (led_reg 4b1000) begin dir 1b1; led_reg 4b0100; // 到顶后折返 end else begin led_reg {led_reg[2:0], 1b0}; end end else begin // 向低位流动 4-3-2-1 if (led_reg 4b0001) begin dir 1b0; led_reg 4b0010; // 到底后折返 end else begin led_reg {1b0, led_reg[3:1]}; end end end end assign led led_reg; endmodule } set src_file [open $PROJECT_DIR/led_blink.v w] puts $src_file $verilog_content close $src_file add_files $PROJECT_DIR/led_blink.v #--------------------------------------------------------------- # 3. 内嵌 XDC 约束并写出 #--------------------------------------------------------------- set xdc_content { # # led_blink.xdc - XCKU5P 4-LED 流水灯约束 # # ---- 差分晶振 (默认 200 MHz) ---- # 差分对只约束 P 端, N 端由工具按差分对自动配对, clk_n 不要再写 PACKAGE_PIN set_property PACKAGE_PIN T24 [get_ports clk_p] set_property IOSTANDARD DIFF_SSTL12 [get_ports clk_p] create_clock -name sys_clk -period 5.000 [get_ports clk_p] # ---- 复位按键 (低有效) ---- set_property PACKAGE_PIN K9 [get_ports rst_n] set_property IOSTANDARD LVCMOS33 [get_ports rst_n] set_property PULLUP true [get_ports rst_n] set_false_path -from [get_ports rst_n] # ---- 4 个 LED (LVCMOS33, 高电平点亮, 驱动三极管基极) ---- set_property PACKAGE_PIN H9 [get_ports {led[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] set_property DRIVE 12 [get_ports {led[0]}] set_property SLEW FAST [get_ports {led[0]}] set_property PACKAGE_PIN J9 [get_ports {led[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] set_property DRIVE 12 [get_ports {led[1]}] set_property SLEW FAST [get_ports {led[1]}] set_property PACKAGE_PIN G11 [get_ports {led[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}] set_property DRIVE 12 [get_ports {led[2]}] set_property SLEW FAST [get_ports {led[2]}] set_property PACKAGE_PIN H11 [get_ports {led[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}] set_property DRIVE 12 [get_ports {led[3]}] set_property SLEW FAST [get_ports {led[3]}] # LED 为低速输出, 不做时序分析 set_false_path -to [get_ports {led[*]}] # ---- 比特流设置 ---- set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] # 以下两项与板载 QSPI Flash 有关, 需要烧写 Flash 时按原理图取消注释: # set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] # set_property CONFIG_MODE SPIx4 [current_design] } set xdc_file [open $PROJECT_DIR/led_blink.xdc w] puts $xdc_file $xdc_content close $xdc_file add_files -fileset constrs_1 $PROJECT_DIR/led_blink.xdc #--------------------------------------------------------------- # 4. 内嵌 Testbench 并写出差分时钟激励, 缩小计数器加速仿真 #--------------------------------------------------------------- set tb_content { timescale 1ns / 1ps // // tb_led_blink.v - 双向流水灯仿真平台 // 差分时钟激励: clk_p / clk_n 相位相反 // 例化时把 CLK_FREQ_HZ 改为 1000, 即每 1000 个时钟切换一次, 加速仿真 // module tb_led_blink; localparam real CLK_PERIOD 5.0; // 200 MHz reg clk_p; reg clk_n; reg rst_n; wire [3:0] led; // 被测模块: 参数覆盖, 加速仿真 led_blink #( .CLK_FREQ_HZ (1000), .SWITCH_SEC (1) ) uut ( .clk_p (clk_p), .clk_n (clk_n), .rst_n (rst_n), .led (led) ); // 差分时钟激励: P/N 初值相反, 各自翻转 initial begin clk_p 1b0; forever #(CLK_PERIOD/2.0) clk_p ~clk_p; end initial begin clk_n 1b1; forever #(CLK_PERIOD/2.0) clk_n ~clk_n; end // LED 变化打印 always (led) begin $display([%0t ns] LED %b, $time, led); end // 测试序列 initial begin $display(); $display( tb_led_blink: XCKU5P 4-LED 双向流水); $display( 期望序列: 0001 0010 0100 1000 0100 0010 0001 ...); $display(); rst_n 1b0; #(CLK_PERIOD * 20); rst_n 1b1; $display([%0t ns] 复位释放, $time); // 观察 9 次切换 (覆盖一个完整的往返) #(CLK_PERIOD * 1000 * 9 500); $display(); $display( 仿真结束, 最终 LED %b, led); $display(); $finish; end // 波形转储 initial begin $dumpfile(tb_led_blink.vcd); $dumpvars(0, tb_led_blink); end endmodule } set tb_file [open $PROJECT_DIR/tb_led_blink.v w] puts $tb_file $tb_content close $tb_file add_files -fileset sim_1 $PROJECT_DIR/tb_led_blink.v #--------------------------------------------------------------- # 5. 设置顶层与仿真属性 #--------------------------------------------------------------- set_property top led_blink [current_fileset] set_property top tb_led_blink [get_filesets sim_1] set_property xsim.simulate.runtime 50us [get_filesets sim_1] set_property xsim.simulate.log_all_signals true [get_filesets sim_1] update_compile_order -fileset sources_1 #--------------------------------------------------------------- # 6. 综合 #--------------------------------------------------------------- puts \[1/3\] Synthesis ... launch_runs synth_1 -jobs $JOBS wait_on_run synth_1 if {[get_property PROGRESS [get_runs synth_1]] ! 100%} { puts ERROR: Synthesis FAILED, see $PROJECT_DIR/$PROJECT_NAME.runs/synth_1/runme.log exit 1 } puts Synthesis OK. #--------------------------------------------------------------- # 7. 实现 生成比特流 #--------------------------------------------------------------- puts \[2/3\] Implementation (to write_bitstream) ... launch_runs impl_1 -to_step write_bitstream -jobs $JOBS wait_on_run impl_1 if {[get_property PROGRESS [get_runs impl_1]] ! 100%} { puts ERROR: Implementation FAILED, see $PROJECT_DIR/$PROJECT_NAME.runs/impl_1/runme.log exit 1 } puts Implementation OK. #--------------------------------------------------------------- # 8. 打开实现结果, 导出报告 #--------------------------------------------------------------- puts \[3/3\] Reports ... open_run impl_1 set RPT_DIR $PROJECT_DIR/reports file mkdir $RPT_DIR report_timing_summary -file $RPT_DIR/timing_summary.rpt report_utilization -file $RPT_DIR/utilization.rpt report_power -file $RPT_DIR/power.rpt report_drc -file $RPT_DIR/drc.rpt #--------------------------------------------------------------- # 9. 拷贝比特流到工程根目录 #--------------------------------------------------------------- set bitstream_file [get_property DIRECTORY [get_runs impl_1]]/led_blink.bit if {[file exists $bitstream_file]} { file copy -force $bitstream_file $PROJECT_DIR/led_blink.bit puts BITSTREAM: $PROJECT_DIR/led_blink.bit } else { puts ERROR: 找不到比特流文件! exit 1 } #--------------------------------------------------------------- # 10. 总结 #--------------------------------------------------------------- puts puts 全流程完成! puts 工程目录 : $PROJECT_DIR puts 比特流 : $PROJECT_DIR/led_blink.bit puts 报告目录 : $RPT_DIR puts 流水序列 : H9 - J9 - G11 - H11 - G11 - J9 - H9 ... puts 切换间隔 : 2 秒 puts 运行仿真 : open_project $PROJECT_DIR/$PROJECT_NAME.xpr puts launch_simulation puts close_project exit 03. 运行结果通过执行构建命令$ vivado-modebatch-sourceled_blink_all_in_one.tcl由一个tcl文件生成了一大堆文件这里的这里的 led_blink.v tb_led_blink.v 都是通过tcl脚本生成的verilog文件。内容如下供参考led_blink.vtimescale 1ns / 1ps // // led_blink.v // XCKU5P 4-LED 双向流水灯 // 时钟: 差分晶振 - IBUFDS - 单端 (默认 200 MHz) // 复位: rst_n 低有效, 异步复位 // LED : 高电平点亮 (FPGA 管脚 - 三极管基极) // module led_blink #( parameter integer CLK_FREQ_HZ 200_000_000, // 差分晶振频率(Hz) parameter integer SWITCH_SEC 2 // 每个灯点亮时长(秒) )( input wire clk_p, // 差分晶振 P 端 - T24 input wire clk_n, // 差分晶振 N 端 (差分对自动配对, 无需约束) input wire rst_n, // 复位按键 - K9, 低有效 output wire [3:0] led // 4 个 LED - H9/J9/G11/H11 ); //---------------------------------------------------------- // 1. 差分时钟转单端 (UltraScale 原语) //---------------------------------------------------------- wire clk; IBUFDS #( .DIFF_TERM (FALSE), .IBUF_LOW_PWR (TRUE), .IOSTANDARD (DEFAULT) ) u_ibufds ( .O (clk), .I (clk_p), .IB (clk_n) ); //---------------------------------------------------------- // 2. 定时计数器: 数满 CLK_FREQ_HZ*SWITCH_SEC 个周期 2 秒 // 200 MHz x 2 s 400_000_000, 32 位计数器足够 //---------------------------------------------------------- localparam integer CNT_MAX CLK_FREQ_HZ * SWITCH_SEC; reg [31:0] cnt; reg [3:0] led_reg; reg dir; // 0: 向高位流动 1: 向低位流动 wire tick (cnt CNT_MAX - 1); always (posedge clk or negedge rst_n) begin if (!rst_n) cnt 32d0; else if (tick) cnt 32d0; else cnt cnt 1b1; end //---------------------------------------------------------- // 3. 双向流水: 0001-0010-0100-1000-0100-0010-0001-... //---------------------------------------------------------- always (posedge clk or negedge rst_n) begin if (!rst_n) begin led_reg 4b0001; // 初始: LED1(H9) 亮 dir 1b0; end else if (tick) begin if (dir 1b0) begin // 向高位流动 1-2-3-4 if (led_reg 4b1000) begin dir 1b1; led_reg 4b0100; // 到顶后折返 end else begin led_reg {led_reg[2:0], 1b0}; end end else begin // 向低位流动 4-3-2-1 if (led_reg 4b0001) begin dir 1b0; led_reg 4b0010; // 到底后折返 end else begin led_reg {1b0, led_reg[3:1]}; end end end end assign led led_reg; endmoduletb_led_blink.vtimescale 1ns / 1ps // // tb_led_blink.v - 双向流水灯仿真平台 // 差分时钟激励: clk_p / clk_n 相位相反 // 例化时把 CLK_FREQ_HZ 改为 1000, 即每 1000 个时钟切换一次, 加速仿真 // module tb_led_blink; localparam real CLK_PERIOD 5.0; // 200 MHz reg clk_p; reg clk_n; reg rst_n; wire [3:0] led; // 被测模块: 参数覆盖, 加速仿真 led_blink #( .CLK_FREQ_HZ (1000), .SWITCH_SEC (1) ) uut ( .clk_p (clk_p), .clk_n (clk_n), .rst_n (rst_n), .led (led) ); // 差分时钟激励: P/N 初值相反, 各自翻转 initial begin clk_p 1b0; forever #(CLK_PERIOD/2.0) clk_p ~clk_p; end initial begin clk_n 1b1; forever #(CLK_PERIOD/2.0) clk_n ~clk_n; end // LED 变化打印 always (led) begin $display([%0t ns] LED %b, $time, led); end // 测试序列 initial begin $display(); $display( tb_led_blink: XCKU5P 4-LED 双向流水); $display( 期望序列: 0001 0010 0100 1000 0100 0010 0001 ...); $display(); rst_n 1b0; #(CLK_PERIOD * 20); rst_n 1b1; $display([%0t ns] 复位释放, $time); // 观察 9 次切换 (覆盖一个完整的往返) #(CLK_PERIOD * 1000 * 9 500); $display(); $display( 仿真结束, 最终 LED %b, led); $display(); $finish; end // 波形转储 initial begin $dumpfile(tb_led_blink.vcd); $dumpvars(0, tb_led_blink); end endmodule