diff --git a/.gitignore b/.gitignore index a5d9fd67..c2ee534a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .bender -tmp \ No newline at end of file +tmp +xilinx/scripts/add_sources.artyz720.tcl +xilinx/scripts/add_sources.genesys2.tcl +xilinx/scripts/add_sources.zyboz720.tcl diff --git a/Bender.yml b/Bender.yml index d312c3fe..ab82ed47 100644 --- a/Bender.yml +++ b/Bender.yml @@ -68,6 +68,14 @@ sources: - xilinx/hw/croc_xilinx.sv - xilinx/hw/fan_ctrl.sv + - target: artyz720 + files: + - xilinx/hw/croc_xilinx.sv + + - target: zyboz720 + files: + - xilinx/hw/croc_xilinx.sv + vendor_package: ################################# # commonly used building blocks # diff --git a/rtl/common_cells/fifo_v3.sv b/rtl/common_cells/fifo_v3.sv index a15b8cf6..6b5b856e 100644 --- a/rtl/common_cells/fifo_v3.sv +++ b/rtl/common_cells/fifo_v3.sv @@ -140,13 +140,16 @@ module fifo_v3 #( end `ifndef COMMON_CELLS_ASSERTS_OFF + `ifndef SYNTHESIS `ASSERT_INIT(depth_0, DEPTH > 0, "DEPTH must be greater than 0.") - - `ASSERT(full_write, full_o |-> ~push_i, clk_i, !rst_ni, - "Trying to push new data although the FIFO is full.") - - `ASSERT(empty_read, empty_o |-> ~pop_i, clk_i, !rst_ni, - "Trying to pop data although the FIFO is empty.") + `ASSERT(full_write, full_o |-> ~push_i, clk_i, !rst_ni, "Trying to push new data although the FIFO is full.") + `ASSERT(empty_read, empty_o |-> ~pop_i, clk_i, !rst_ni, "Trying to pop data although the FIFO is empty.") + `else + `ASSERT_INIT(depth_0, DEPTH > 0) + `ASSERT(full_write, full_o |-> ~push_i, clk_i, !rst_ni) + `ASSERT(empty_read, empty_o |-> ~pop_i, clk_i, !rst_ni) + `endif `endif + endmodule // fifo_v3 diff --git a/rtl/common_cells/lzc.sv b/rtl/common_cells/lzc.sv index eccc31a5..4e2ecd56 100644 --- a/rtl/common_cells/lzc.sv +++ b/rtl/common_cells/lzc.sv @@ -41,10 +41,18 @@ module lzc #( localparam int unsigned NumLevels = $clog2(WIDTH); + + `ifndef COMMON_CELLS_ASSERTS_OFF - `ASSERT_INIT(width_0, WIDTH > 0, "input must be at least one bit wide") + `ifndef SYNTHESIS + `ASSERT_INIT(width_0, WIDTH > 0, "input must be at least one bit wide") + `else + `ASSERT_INIT(width_0, WIDTH > 0) + `endif `endif + + logic [WIDTH-1:0][NumLevels-1:0] index_lut; logic [2**NumLevels-1:0] sel_nodes; logic [2**NumLevels-1:0][NumLevels-1:0] index_nodes; @@ -99,8 +107,14 @@ module lzc #( end : gen_lzc + `ifndef COMMON_CELLS_ASSERTS_OFF - `ASSERT_INIT(width_0, WIDTH >= 1, "The WIDTH must at least be one bit wide!") + `ifndef SYNTHESIS + `ASSERT_INIT(width_0, WIDTH >= 1, "The WIDTH must at least be one bit wide!") + `else + `ASSERT_INIT(width_0, WIDTH >= 1) + `endif `endif + endmodule : lzc diff --git a/rtl/common_cells/rr_arb_tree.sv b/rtl/common_cells/rr_arb_tree.sv index dd07f0c7..06b21280 100644 --- a/rtl/common_cells/rr_arb_tree.sv +++ b/rtl/common_cells/rr_arb_tree.sv @@ -160,18 +160,36 @@ module rr_arb_tree #( end end end - + `ifndef COMMON_CELLS_ASSERTS_OFF - `ASSERT(lock, req_o && (!gnt_i && !flush_i) |=> idx_o == $past(idx_o), - clk_i, !rst_ni || flush_i, - "Lock implies same arbiter decision in next cycle if output is not ready.") - - logic [NumIn-1:0] req_tmp; - assign req_tmp = req_q & req_i; - `ASSUME(lock_req, lock_d |=> req_tmp == req_q, clk_i, !rst_ni || flush_i, - "It is disallowed to deassert unserved request signals when LockIn is enabled.") + `ifndef SYNTHESIS + `ASSERT(lock, + req_o && (!gnt_i && !flush_i) |=> idx_o == $past(idx_o), + clk_i, !rst_ni || flush_i, + "Lock implies same arbiter decision in next cycle if output is not ready.") + + logic [NumIn-1:0] req_tmp; + assign req_tmp = req_q & req_i; + + `ASSUME(lock_req, + lock_d |=> req_tmp == req_q, + clk_i, !rst_ni || flush_i, + "It is disallowed to deassert unserved request signals when LockIn is enabled.") + `else + `ASSERT(lock, + req_o && (!gnt_i && !flush_i) |=> idx_o == $past(idx_o), + clk_i, !rst_ni || flush_i) + + logic [NumIn-1:0] req_tmp; + assign req_tmp = req_q & req_i; + + `ASSUME(lock_req, + lock_d |=> req_tmp == req_q, + clk_i, !rst_ni || flush_i) + `endif `endif + always_ff @(posedge clk_i or negedge rst_ni) begin : p_req_regs if (!rst_ni) begin req_q <= '0; @@ -293,27 +311,48 @@ module rr_arb_tree #( ////////////////////////////////////////////////////////////// end end - + `ifndef COMMON_CELLS_ASSERTS_OFF - `ASSERT_INIT(numin_0, NumIn, "Input must be at least one element wide.") - `ASSERT_INIT(lockin_and_extprio, !(LockIn && ExtPrio), - "Cannot use LockIn feature together with external ExtPrio.") + `ifndef SYNTHESIS + `ASSERT_INIT(numin_0, NumIn, "Input must be at least one element wide.") + `ASSERT_INIT(lockin_and_extprio, !(LockIn && ExtPrio), + "Cannot use LockIn feature together with external ExtPrio.") + + `ASSERT(hot_one, $onehot0(gnt_o), clk_i, !rst_ni || flush_i, + "Grant signal must be hot1 or zero.") + + `ASSERT(gnt0, |gnt_o |-> gnt_i, clk_i, !rst_ni || flush_i, + "Grant out implies grant in.") - `ASSERT(hot_one, $onehot0(gnt_o), clk_i, !rst_ni || flush_i, - "Grant signal must be hot1 or zero.") + `ASSERT(gnt1, req_o |-> gnt_i |-> |gnt_o, clk_i, !rst_ni || flush_i, + "Req out and grant in implies grant out.") - `ASSERT(gnt0, |gnt_o |-> gnt_i, clk_i, !rst_ni || flush_i, "Grant out implies grant in.") + `ASSERT(gnt_idx, req_o |-> gnt_i |-> gnt_o[idx_o], clk_i, !rst_ni || flush_i, + "Idx_o / gnt_o do not match.") - `ASSERT(gnt1, req_o |-> gnt_i |-> |gnt_o, clk_i, !rst_ni || flush_i, - "Req out and grant in implies grant out.") + `ASSERT(req0, |req_i |-> req_o, clk_i, !rst_ni || flush_i, + "Req in implies req out.") - `ASSERT(gnt_idx, req_o |-> gnt_i |-> gnt_o[idx_o], clk_i, !rst_ni || flush_i, - "Idx_o / gnt_o do not match.") + `ASSERT(req1, req_o |-> |req_i, clk_i, !rst_ni || flush_i, + "Req out implies req in.") + `else + `ASSERT_INIT(numin_0, NumIn) + `ASSERT_INIT(lockin_and_extprio, !(LockIn && ExtPrio)) - `ASSERT(req0, |req_i |-> req_o, clk_i, !rst_ni || flush_i, "Req in implies req out.") + `ASSERT(hot_one, $onehot0(gnt_o), clk_i, !rst_ni || flush_i) - `ASSERT(req1, req_o |-> |req_i, clk_i, !rst_ni || flush_i, "Req out implies req in.") + `ASSERT(gnt0, |gnt_o |-> gnt_i, clk_i, !rst_ni || flush_i) + + `ASSERT(gnt1, req_o |-> gnt_i |-> |gnt_o, clk_i, !rst_ni || flush_i) + + `ASSERT(gnt_idx, req_o |-> gnt_i |-> gnt_o[idx_o], clk_i, !rst_ni || flush_i) + + `ASSERT(req0, |req_i |-> req_o, clk_i, !rst_ni || flush_i) + + `ASSERT(req1, req_o |-> |req_i, clk_i, !rst_ni || flush_i) + `endif `endif + end endmodule : rr_arb_tree diff --git a/rtl/common_cells/spill_register_flushable.sv b/rtl/common_cells/spill_register_flushable.sv index 7d07adc5..e82eed31 100644 --- a/rtl/common_cells/spill_register_flushable.sv +++ b/rtl/common_cells/spill_register_flushable.sv @@ -95,9 +95,13 @@ module spill_register_flushable #( // We empty the spill register before the slice register. assign data_o = b_full_q ? b_data_q : a_data_q; - `ifndef COMMON_CELLS_ASSERTS_OFF - `ASSERT(flush_valid, flush_i |-> ~valid_i, clk_i, !rst_ni, + `ifndef COMMON_CELLS_ASSERTS_OFF + `ifndef SYNTHESIS + `ASSERT(flush_valid, flush_i |-> ~valid_i, clk_i, !rst_ni, "Trying to flush and feed the spill register simultaneously. You will lose data!") - `endif + `else + `ASSERT(flush_valid, flush_i |-> ~valid_i, clk_i, !rst_ni) + `endif + `endif end endmodule diff --git a/xilinx/hw/croc_xilinx.sv b/xilinx/hw/croc_xilinx.sv index a9c5485c..239eb257 100644 --- a/xilinx/hw/croc_xilinx.sv +++ b/xilinx/hw/croc_xilinx.sv @@ -8,6 +8,7 @@ // Yann Picod // Paul Scheffler // Philippe Sauter +// Felix Niederer `ifdef TARGET_GENESYS2 `define USE_RESETN @@ -17,8 +18,27 @@ `define USE_LEDS `define USE_FAN `define USE_VIO + `define USE_DIFF_CLK + +`endif + +`ifdef TARGET_ARTYZ720 + `define USE_RESET + `define USE_STATUS + `define USE_SWITCHES + `define USE_LEDS + `define USE_VIO +`endif + +`ifdef TARGET_ZYBOZ720 + `define USE_RESET + `define USE_STATUS + `define USE_SWITCHES + `define USE_LEDS + `define USE_VIO `endif + `define ila(__name, __signal) \ (* dont_touch = "yes" *) (* mark_debug = "true" *) logic [$bits(__signal)-1:0] __name; \ assign __name = __signal; @@ -27,8 +47,11 @@ module croc_xilinx import croc_pkg::*; #( localparam int unsigned GpioCount = 4 ) ( input logic sys_clk_p, - input logic sys_clk_n, +`ifdef USE_DIFF_CLK + input logic sys_clk_n, +`endif + `ifdef USE_RESET input logic sys_reset, `endif @@ -77,6 +100,8 @@ module croc_xilinx import croc_pkg::*; #( wire sys_clk; wire soc_clk; + +`ifdef USE_DIFF_CLK IBUFDS #( .IBUF_LOW_PWR ("FALSE") ) i_bufds_sys_clk ( @@ -84,6 +109,15 @@ module croc_xilinx import croc_pkg::*; #( .IB ( sys_clk_n ), .O ( sys_clk ) ); +`endif + +`ifndef USE_DIFF_CLK + IBUF i_buf_sys_clk ( + .I ( sys_clk_p ), + .O ( sys_clk ) + ); +`endif + clkwiz i_clkwiz ( .clk_in1 ( sys_clk ), diff --git a/xilinx/implement.sh b/xilinx/implement.sh old mode 100644 new mode 100755 index 4ca25157..05c104f4 --- a/xilinx/implement.sh +++ b/xilinx/implement.sh @@ -1,20 +1,53 @@ -bender script vivado -t fpga -t rtl -t genesys2 > scripts/add_sources.genesys2.tcl -mkdir -p build/genesys2.clkwiz -cd build/genesys2.clkwiz && \ - vitis-2022.1 vivado -mode batch -log ../genesys2.clkwiz.log -jou ../genesys2.clkwiz.jou \ +#!/bin/bash + +# Default board is genesys2 +BOARD="genesys2" + +# Parse command line arguments +while getopts "b:" opt; do + case ${opt} in + b ) + BOARD=$OPTARG + ;; + \? ) + echo "Usage: $0 [-b board_type]" + echo "Supported boards: genesys2, artyz720, zyboz720" + exit 1 + ;; + esac +done + +# Validate board selection +if [[ "$BOARD" != "genesys2" && "$BOARD" != "artyz720" && "$BOARD" != "zyboz720" ]]; then + echo "Error: Unsupported board type '$BOARD'" + echo "Supported boards: genesys2, artyz720, zyboz720" + exit 1 +fi + +# Generate the TCL script +bender script vivado -t fpga -t rtl -t $BOARD > scripts/add_sources.$BOARD.tcl + +# Build Clkwiz +mkdir -p build/$BOARD.clkwiz +cd build/$BOARD.clkwiz && \ + vitis-2022.1 vivado -mode batch -log ../$BOARD.clkwiz.log -jou ../$BOARD.clkwiz.jou \ -source ../../scripts/impl_ip.tcl \ - -tclargs genesys2 clkwiz \ + -tclargs $BOARD clkwiz \ && cd ../.. -mkdir -p build/genesys2.vio -cd build/genesys2.vio && - vitis-2022.1 vivado -mode batch -log ../genesys2.vio.log -jou ../genesys2.vio.jou \ + +# Build VIO +mkdir -p build/$BOARD.vio +cd build/$BOARD.vio && \ + vitis-2022.1 vivado -mode batch -log ../$BOARD.vio.log -jou ../$BOARD.vio.jou \ -source ../../scripts/impl_ip.tcl \ - -tclargs genesys2 vio\ + -tclargs $BOARD vio \ && cd ../.. -mkdir -p build/genesys2.croc -cd build/genesys2.croc && \ - vitis-2022.1 vivado -mode batch -log ../croc.genesys2.log -jou ../croc.genesys2.jou \ + +# Build top croc module +mkdir -p build/$BOARD.croc +cd build/$BOARD.croc && \ + vitis-2022.1 vivado -mode batch -log ../croc.$BOARD.log -jou ../croc.$BOARD.jou \ -source ../../scripts/impl_sys.tcl \ - -tclargs genesys2 croc \ - ../genesys2.clkwiz/out.xci \ - ../genesys2.vio/out.xci + -tclargs $BOARD croc \ + ../$BOARD.clkwiz/out.xci \ + ../$BOARD.vio/out.xci \ No newline at end of file diff --git a/xilinx/scripts/clkwiz/clkwiz_artyz720.tcl b/xilinx/scripts/clkwiz/clkwiz_artyz720.tcl new file mode 100644 index 00000000..2c70c607 --- /dev/null +++ b/xilinx/scripts/clkwiz/clkwiz_artyz720.tcl @@ -0,0 +1,24 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 +# +# Florian Zaruba +# Cyril Koenig +# Paul Scheffler +# Felix Niederer + +create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name $proj +set_property -dict [list \ + CONFIG.PRIM_SOURCE {No_buffer} \ + CONFIG.PRIM_IN_FREQ {125.000} \ + CONFIG.CLKOUT1_USED {true} \ + CONFIG.CLK_OUT1_PORT {clk_20} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {20.000} \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {8.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {8.000} \ + CONFIG.MMCM_CLKOUT1_DIVIDE {50} \ + CONFIG.NUM_OUT_CLKS {1} \ + CONFIG.CLKOUT1_JITTER {155.330} \ + CONFIG.CLKOUT1_PHASE_ERROR {89.971} \ +] [get_ips $proj] diff --git a/xilinx/scripts/clkwiz/clkwiz_genesys2.tcl b/xilinx/scripts/clkwiz/clkwiz_genesys2.tcl new file mode 100644 index 00000000..f06a3a70 --- /dev/null +++ b/xilinx/scripts/clkwiz/clkwiz_genesys2.tcl @@ -0,0 +1,23 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 +# +# Florian Zaruba +# Cyril Koenig +# Paul Scheffler + +create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name $proj +set_property -dict [list \ + CONFIG.PRIM_SOURCE {No_buffer} \ + CONFIG.PRIM_IN_FREQ {200.000} \ + CONFIG.CLKOUT1_USED {true} \ + CONFIG.CLK_OUT1_PORT {clk_20} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {20.000} \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {6.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ + CONFIG.MMCM_CLKOUT1_DIVIDE {60} \ + CONFIG.NUM_OUT_CLKS {1} \ + CONFIG.CLKOUT1_JITTER {155.330} \ + CONFIG.CLKOUT1_PHASE_ERROR {89.971} \ + ] [get_ips $proj] diff --git a/xilinx/scripts/clkwiz/clkwiz_zyboz720.tcl b/xilinx/scripts/clkwiz/clkwiz_zyboz720.tcl new file mode 100644 index 00000000..2c70c607 --- /dev/null +++ b/xilinx/scripts/clkwiz/clkwiz_zyboz720.tcl @@ -0,0 +1,24 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 +# +# Florian Zaruba +# Cyril Koenig +# Paul Scheffler +# Felix Niederer + +create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name $proj +set_property -dict [list \ + CONFIG.PRIM_SOURCE {No_buffer} \ + CONFIG.PRIM_IN_FREQ {125.000} \ + CONFIG.CLKOUT1_USED {true} \ + CONFIG.CLK_OUT1_PORT {clk_20} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {20.000} \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {8.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {8.000} \ + CONFIG.MMCM_CLKOUT1_DIVIDE {50} \ + CONFIG.NUM_OUT_CLKS {1} \ + CONFIG.CLKOUT1_JITTER {155.330} \ + CONFIG.CLKOUT1_PHASE_ERROR {89.971} \ +] [get_ips $proj] diff --git a/xilinx/scripts/common.tcl b/xilinx/scripts/common.tcl index d49816b2..04231f88 100644 --- a/xilinx/scripts/common.tcl +++ b/xilinx/scripts/common.tcl @@ -9,6 +9,16 @@ set bpart(genesys2) "digilentinc.com:genesys2:part0:1.1" set fpart(genesys2) "xc7k325tffg900-2" set hwdev(genesys2) "xc7k325t_0" +# artyz720 board params +set bpart(artyz720) "digilentinc.com:arty-z7-20:part0:1.1" +set fpart(artyz720) "xc7z020clg400-1" +set hwdev(artyz720) "xc7z020c" + +# zyboz720 board params +set bpart(zyboz720) "digilentinc.com:zybo-z7-20:part0:1.2" +set fpart(zyboz720) "xc7z020clg400-1" +set hwdev(zyboz720) "xc7z020c" + # vcu128 board params set bpart(vcu128) "xilinx.com:vcu128:part0:1.0" set fpart(vcu128) "xcvu37p-fsvh2892-2L-e" diff --git a/xilinx/scripts/impl_ip.tcl b/xilinx/scripts/impl_ip.tcl index 5914548e..cfca3dba 100644 --- a/xilinx/scripts/impl_ip.tcl +++ b/xilinx/scripts/impl_ip.tcl @@ -5,33 +5,34 @@ # Florian Zaruba # Cyril Koenig # Paul Scheffler +# Felix Niederer + # Initialize implementation set xilinx_root [file dirname [file dirname [file normalize [info script]]]] source ${xilinx_root}/scripts/common.tcl init_impl $xilinx_root $argc $argv +# Get board type from first argument +if {$argc > 0} { + set board_type [lindex $argv 0] +} else { + puts "Error: No board type specified" + exit 1 +} + # Create and configure selected IP switch $proj { - clkwiz { - create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name $proj - set_property -dict [list \ - CONFIG.PRIM_SOURCE {No_buffer} \ - CONFIG.PRIM_IN_FREQ {200.000} \ - CONFIG.CLKOUT1_USED {true} \ - CONFIG.CLK_OUT1_PORT {clk_20} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {20.000} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.MMCM_CLKFBOUT_MULT_F {6.000} \ - CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ - CONFIG.MMCM_CLKOUT1_DIVIDE {60} \ - CONFIG.NUM_OUT_CLKS {1} \ - CONFIG.CLKOUT1_JITTER {155.330} \ - CONFIG.CLKOUT1_PHASE_ERROR {89.971} \ - ] [get_ips $proj] + # Source the board-specific clkwiz configuration + set clkwiz_config_file "${xilinx_root}/scripts/clkwiz/clkwiz_${board_type}.tcl" + if {[file exists $clkwiz_config_file]} { + source $clkwiz_config_file + } else { + puts "Error: clkwiz configuration for board '$board_type' not found at $clkwiz_config_file" + exit 1 + } } - vio { create_ip -name vio -vendor xilinx.com -library ip -version 3.0 -module_name $proj set_property -dict [list \ @@ -42,7 +43,7 @@ switch $proj { CONFIG.C_PROBE_OUT1_WIDTH {2} \ CONFIG.C_EN_PROBE_IN_ACTIVITY {0} \ CONFIG.C_NUM_PROBE_IN {0} \ - ] [get_ips $proj] + ] [get_ips $proj] } } diff --git a/xilinx/src/artyz720.xdc b/xilinx/src/artyz720.xdc new file mode 100644 index 00000000..1b3496ce --- /dev/null +++ b/xilinx/src/artyz720.xdc @@ -0,0 +1,147 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 +# Felix Niederer + + +# -------------------------------------------------------------------------------------------------- +# Clock Source +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { sys_clk_p }]; #IO_L12P_T1_MRCC_35 Sch=sysclk +create_clock -add -name sys_clk -period 8.00 -waveform {0 4} [get_ports { sys_clk_p }]; + +# SoC clock is generated by clock wizard and its constraints +set SOC_TCK 50.0 +set soc_clk [get_clocks -of_objects [get_pins i_clkwiz/clk_20]] + + +# -------------------------------------------------------------------------------------------------- +# Switches +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN M20 IOSTANDARD LVCMOS33 } [get_ports { fetch_en_i }]; #IO_L19N_T3_VREF_35 Sch=sw[0] +set_property -dict { PACKAGE_PIN M19 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[0] }]; #IO_L24P_T3_34 Sch=sw[1] + + +# set_false_path -from [get_ports {fetch_en_i}] -to * +# set_input_delay -clock sys_clk 0.0 [get_ports {fetch_en_i}] + +set_false_path -from [get_ports {gpio_i*}] -to * +set_input_delay -clock sys_clk 0.0 [get_ports {gpio_i*}] + +# -------------------------------------------------------------------------------------------------- +# Buttons +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN D19 IOSTANDARD LVCMOS33 } [get_ports { sys_reset }]; #IO_L12N_T1_MRCC_35 Sch=btn[0] +set_property -dict { PACKAGE_PIN D20 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[1] }]; #IO_L4N_T0_35 Sch=BTN1 +set_property -dict { PACKAGE_PIN L20 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[2] }]; #IO_L9N_T1_DQS_AD3N_35 Sch=BTN2 +set_property -dict { PACKAGE_PIN L19 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[3] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=BTN3 + + +# -------------------------------------------------------------------------------------------------- +# LEDs +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { status_o }]; #IO_L6N_T0_VREF_34 Sch=LED0 +set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[0] }]; #IO_L6P_T0_34 Sch=LED1 +set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[1] }]; #IO_L21N_T3_DQS_AD14N_35 Sch=LED2 +set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[2] }]; #IO_L23P_T3_35 Sch=LED3 +set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[3] }]; #IO_L16P_T2_35 Sch=LED4_G + +set_false_path -from * -to [get_ports {status_o}] +set_output_delay -clock sys_clk 0.0 [get_ports {status_o}] + +set_false_path -from * -to [get_ports {gpio_o*}] +set_output_delay -clock sys_clk 0.0 [get_ports {gpio_o*}] + + +# -------------------------------------------------------------------------------------------------- +# Pmod Header JB +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { jtag_tms_i }]; #IO_L15P_T2_DQS_13 Sch=jb_p[1] +set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdi_i }]; #IO_L15N_T2_DQS_13 Sch=jb_n[1] +set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdo_o }]; #IO_L11P_T1_SRCC_13 Sch=jb_p[2] +set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { jtag_tck_i }]; #IO_L11N_T1_SRCC_13 Sch=jb_n[2] + +# -------------------------------------------------------------------------------------------------- +# Pmod Header JA +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { uart_rx_i }]; #IO_L10P_T1_34 Sch=jc_p[1] +set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { uart_tx_o }]; #IO_L10N_T1_34 Sch=jc_n[1] + + +############ +# Switches # +############ + +set_input_delay -min -clock $soc_clk [expr { $SOC_TCK * 0.10 }] [ \ + get_ports {fetch_en_i}] +set_input_delay -max -clock $soc_clk [expr { $SOC_TCK * 0.35 }] [ \ + get_ports {fetch_en_i}] + +set_max_delay [expr { 2 * $SOC_TCK }] -from [get_ports {fetch_en_i}] +set_false_path -hold -from [get_ports {fetch_en_i}] + +################# +# Clock routing # +################# + +# JTAG is on non-clock-capable GPIOs (if not using BSCANE) +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports jtag_tck_i]] +set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports jtag_tck_i]] + +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports sys_reset*]] +set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports sys_reset*]] + +# Remove avoid tc_clk_mux2 to use global clock routing +set all_in_mux [get_nets -of [ get_pins -filter { DIRECTION == IN } -of \ + [get_cells -hier -filter { ORIG_REF_NAME == tc_clk_mux2 || REF_NAME == tc_clk_mux2 }]]] +set_property CLOCK_DEDICATED_ROUTE FALSE $all_in_mux +set_property CLOCK_BUFFER_TYPE NONE $all_in_mux + +######## +# JTAG # +######## + +# 10 MHz (max) JTAG clock +set JTAG_TCK 100.0 + +# JTAG Clock +create_clock -period $JTAG_TCK -name clk_jtag [get_ports jtag_tck_i] +set_input_jitter clk_jtag 1.000 + +# JTAG Clock is asynchronous to all other clocks +set_clock_groups -name jtag_async -asynchronous -group {clk_jtag} + +set_input_delay -min -clock clk_jtag [expr { 0.10 * $JTAG_TCK }] [get_ports {jtag_tdi_i jtag_tms_i}] +set_input_delay -max -clock clk_jtag [expr { 0.20 * $JTAG_TCK }] [get_ports {jtag_tdi_i jtag_tms_i}] + +set_output_delay -min -clock clk_jtag [expr { 0.10 * $JTAG_TCK }] [get_ports jtag_tdo_o] +set_output_delay -max -clock clk_jtag [expr { 0.20 * $JTAG_TCK }] [get_ports jtag_tdo_o] + + +######## +# UART # +######## + +# UART speed is at most 5 Mb/s +set UART_IO_SPEED 200.0 + +set_max_delay [expr { $UART_IO_SPEED * 0.35 }] -from [get_ports uart_rx_i] +set_false_path -hold -from [get_ports uart_rx_i] + +set_max_delay [expr { $UART_IO_SPEED * 0.35 }] -to [get_ports uart_tx_o] +set_false_path -hold -to [get_ports uart_tx_o] + +######## +# CDCs # +######## + +# Disable hold checks on CDCs +set_property KEEP_HIERARCHY SOFT [get_cells -hier \ + -filter {ORIG_REF_NAME=="sync" || REF_NAME=="sync"}] +set_false_path -hold -through [get_pins -of_objects [get_cells -hier \ + -filter {ORIG_REF_NAME=="sync" || REF_NAME=="sync"}] -filter {NAME=~*serial_i}] + +set_false_path -hold -through [get_pins -of_objects [get_cells -hier \ + -filter {ORIG_REF_NAME =~ cdc_*src* || REF_NAME =~ cdc_*src*}] -filter {NAME =~ *async*}] +set_false_path -hold -through [get_pins -of_objects [get_cells -hier \ + -filter {ORIG_REF_NAME =~ cdc_*dst* || REF_NAME =~ cdc_*dst*}] -filter {NAME =~ *async*}] diff --git a/xilinx/src/zyboz720.xdc b/xilinx/src/zyboz720.xdc new file mode 100644 index 00000000..ea33b896 --- /dev/null +++ b/xilinx/src/zyboz720.xdc @@ -0,0 +1,148 @@ +# -------------------------------------------------------------------------------------------------- +# Constraint File for the Zybo-Z7 20 Board +# -------------------------------------------------------------------------------------------------- + +# -------------------------------------------------------------------------------------------------- +# Clock Source +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { sys_clk_p }]; #IO_L12P_T1_MRCC_35 Sch=sysclk +create_clock -add -name sys_clk -period 8.00 -waveform {0 4} [get_ports { sys_clk_p }]; + + +# SoC clock is generated by clock wizard and its constraints +set SOC_TCK 50.0 +set soc_clk [get_clocks -of_objects [get_pins i_clkwiz/clk_20]] + +# -------------------------------------------------------------------------------------------------- +# Switches +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { fetch_en_i }]; #IO_L19N_T3_VREF_35 Sch=sw[0] +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[0] }]; #IO_L24P_T3_34 Sch=sw[1] +set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[1] }]; #IO_L4N_T0_34 Sch=sw[2] +set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[2] }]; #IO_L9P_T1_DQS_34 Sch=sw[3] + +# set_false_path -from [get_ports {fetch_en_i}] -to * +# set_input_delay -clock sys_clk 0.0 [get_ports {fetch_en_i}] + +set_false_path -from [get_ports {gpio_i*}] -to * +set_input_delay -clock sys_clk 0.0 [get_ports {gpio_i*}] + +# -------------------------------------------------------------------------------------------------- +# Buttons +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { sys_reset }]; #IO_L12N_T1_MRCC_35 Sch=btn[0] +set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { gpio_i[3] }]; #IO_L24N_T3_34 Sch=btn[1] + + +# -------------------------------------------------------------------------------------------------- +# LEDs +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { status_o }]; #IO_L23P_T3_35 Sch=led[0] +set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[0] }]; #IO_L23N_T3_35 Sch=led[1] +set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[1] }]; #IO_0_35 Sch=led[2] +set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[2] }]; #IO_L3N_T0_DQS_AD1N_35 Sch=led[3] +set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[3] }]; #IO_L6N_T0_VREF_35 Sch=led6_g + +set_false_path -from * -to [get_ports {status_o}] +set_output_delay -clock sys_clk 0.0 [get_ports {status_o}] + +set_false_path -from * -to [get_ports {gpio_o*}] +set_output_delay -clock sys_clk 0.0 [get_ports {gpio_o*}] + + + +# -------------------------------------------------------------------------------------------------- +# Pmod Header JB (Zybo Z7-20 only) +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { jtag_tms_i }]; #IO_L15P_T2_DQS_13 Sch=jb_p[1] +set_property -dict { PACKAGE_PIN W8 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdi_i }]; #IO_L15N_T2_DQS_13 Sch=jb_n[1] +set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdo_o }]; #IO_L11P_T1_SRCC_13 Sch=jb_p[2] +set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { jtag_tck_i }]; #IO_L11N_T1_SRCC_13 Sch=jb_n[2] + +# -------------------------------------------------------------------------------------------------- +# Pmod Header JC +# -------------------------------------------------------------------------------------------------- +set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { uart_rx_i }]; #IO_L10P_T1_34 Sch=jc_p[1] +set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { uart_tx_o }]; #IO_L10N_T1_34 Sch=jc_n[1] + + + +############ +# Switches # +############ + +set_input_delay -min -clock $soc_clk [expr { $SOC_TCK * 0.10 }] [ \ + get_ports {fetch_en_i}] +set_input_delay -max -clock $soc_clk [expr { $SOC_TCK * 0.35 }] [ \ + get_ports {fetch_en_i}] + +set_max_delay [expr { 2 * $SOC_TCK }] -from [get_ports {fetch_en_i}] +set_false_path -hold -from [get_ports {fetch_en_i}] + +################# +# Clock routing # +################# + +# JTAG is on non-clock-capable GPIOs (if not using BSCANE) +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports jtag_tck_i]] +set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports jtag_tck_i]] + +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets -of [get_ports sys_reset*]] +set_property CLOCK_BUFFER_TYPE NONE [get_nets -of [get_ports sys_reset*]] + +# Remove avoid tc_clk_mux2 to use global clock routing +set all_in_mux [get_nets -of [ get_pins -filter { DIRECTION == IN } -of \ + [get_cells -hier -filter { ORIG_REF_NAME == tc_clk_mux2 || REF_NAME == tc_clk_mux2 }]]] +set_property CLOCK_DEDICATED_ROUTE FALSE $all_in_mux +set_property CLOCK_BUFFER_TYPE NONE $all_in_mux + +######## +# JTAG # +######## + +# 10 MHz (max) JTAG clock +set JTAG_TCK 100.0 + +# JTAG Clock +create_clock -period $JTAG_TCK -name clk_jtag [get_ports jtag_tck_i] +set_input_jitter clk_jtag 1.000 + +# JTAG Clock is asynchronous to all other clocks +set_clock_groups -name jtag_async -asynchronous -group {clk_jtag} + +set_input_delay -min -clock clk_jtag [expr { 0.10 * $JTAG_TCK }] [get_ports {jtag_tdi_i jtag_tms_i}] +set_input_delay -max -clock clk_jtag [expr { 0.20 * $JTAG_TCK }] [get_ports {jtag_tdi_i jtag_tms_i}] + +set_output_delay -min -clock clk_jtag [expr { 0.10 * $JTAG_TCK }] [get_ports jtag_tdo_o] +set_output_delay -max -clock clk_jtag [expr { 0.20 * $JTAG_TCK }] [get_ports jtag_tdo_o] + +# set_max_delay -from [get_ports jtag_trst_ni] $JTAG_TCK +# set_false_path -hold -from [get_ports jtag_trst_ni] + +######## +# UART # +######## + +# UART speed is at most 5 Mb/s +set UART_IO_SPEED 200.0 + +set_max_delay [expr { $UART_IO_SPEED * 0.35 }] -from [get_ports uart_rx_i] +set_false_path -hold -from [get_ports uart_rx_i] + +set_max_delay [expr { $UART_IO_SPEED * 0.35 }] -to [get_ports uart_tx_o] +set_false_path -hold -to [get_ports uart_tx_o] + +######## +# CDCs # +######## + +# Disable hold checks on CDCs +set_property KEEP_HIERARCHY SOFT [get_cells -hier \ + -filter {ORIG_REF_NAME=="sync" || REF_NAME=="sync"}] +set_false_path -hold -through [get_pins -of_objects [get_cells -hier \ + -filter {ORIG_REF_NAME=="sync" || REF_NAME=="sync"}] -filter {NAME=~*serial_i}] + +set_false_path -hold -through [get_pins -of_objects [get_cells -hier \ + -filter {ORIG_REF_NAME =~ cdc_*src* || REF_NAME =~ cdc_*src*}] -filter {NAME =~ *async*}] +set_false_path -hold -through [get_pins -of_objects [get_cells -hier \ + -filter {ORIG_REF_NAME =~ cdc_*dst* || REF_NAME =~ cdc_*dst*}] -filter {NAME =~ *async*}] \ No newline at end of file