diff --git a/bittware_xupvvh/src/rtl/bittware_xupvvh_top.sv b/bittware_xupvvh/src/rtl/bittware_xupvvh_top.sv index e69de29..7240820 100644 --- a/bittware_xupvvh/src/rtl/bittware_xupvvh_top.sv +++ b/bittware_xupvvh/src/rtl/bittware_xupvvh_top.sv @@ -0,0 +1,315 @@ +//************************************************************************** +//************* BittWare Incorporated ************* +//************* 45 S. Main Street, Concord, NH 03301 ************* +//************************************************************************** +// LEGAL NOTICE: +// Copyright (c) 2018 BittWare, Inc. +// The user is hereby granted a non-exclusive license to use and or +// modify this code provided that it runs on BittWare hardware. +// Usage of this code on non-BittWare hardware without the express +// written permission of BittWare is strictly prohibited. +// +// E-mail: support@bittware.com Tel: 603-226-0404 +//************************************************************************** + +//# Created by: Jeff Sanders +//# Date: 20 Jun 2018 +/// +//************************************************************************** +// pcie_base: Default PCIe-based design incorporating the following functionality: +// - PCIe Gen3x16 interface w/integrated PCIe-to-AXI4 conversion (within IPI subsystem) +// - SPI controller (within IPI subsystem) +// - I2C controller (within IPI subsystem) +// - 16550-compatible UART (within IPI subsystem) +// - STARTUPE3 primitive configured to allow writes to QSPI flash +// +// PCIe address map: (BAR0, 32-bit) +// 0x0000: CSR (0x0=Version(rd);LED[2:0](wr), 0x4=UAR timestamp(rd), 0x8=CSR(rd/wr)) +// 0x1100: SPI core +// 0x2200: I2C Core +// 0x3300: UART Core +// 0x4000: 4KB scratchpad BRAM +// +//************************************************************************** + +`timescale 1ps/1ps + +`define DEV_SEL_HI_BIT 11 +`define DEV_SEL_LO_BIT 8 +`define VERSION_REG 32'h00600000 + +module bittware_xupvvh_top ( + led_pins, + pcie_7x_mgt_rxn, + pcie_7x_mgt_rxp, + pcie_7x_mgt_txn, + pcie_7x_mgt_txp, + prog_b5_p, + prog_b5_n, + avr_rxd, + avr_txd, + usb_rxd, + usb_txd, + i2c_sda, + i2c_scl, + FPGA_I2C_MASTER_L, + QSFP_CTL_EN, + SAS_CTL_EN, + sys_clkp, + sys_clkn, + sys_reset_l); + + //####### Misc. Board-specific ####### + output [3:0]led_pins; // On-board LEDs 0-3 + output FPGA_I2C_MASTER_L; // Drive high to allow BMC to control QSFPs + output QSFP_CTL_EN; // Drive high for normal operation + output SAS_CTL_EN; // Drive high for normal operation + //####### PCIe Interface ####### + input [15:0]pcie_7x_mgt_rxn; + input [15:0]pcie_7x_mgt_rxp; + output [15:0]pcie_7x_mgt_txn; + output [15:0]pcie_7x_mgt_txp; + //####### I2C and UART I/F's ####### + input avr_txd; // Tx UART data from the AVR + output avr_rxd; // Rx UART data to the AVR + inout i2c_sda; // I2C biderectional data + inout i2c_scl; // I2C clock + input usb_uart_txd; // Tx UART data from the USB + output logic usb_uart_rxd; // Rx UART data to the USB + //####### Clocks & Reset ####### + input sys_clkp; // PCIe reference clock + input sys_clkn; + input prog_b5_p; + input prog_b5_n; + input sys_reset_l; // PCIe PERSTN + + + wire [3:0] spi_in; + wire [3:0] spi_out; + wire [3:0] spi_tri; + wire spi_sel; + wire spi_clk_o; + wire spi_clk_t; + reg spi_cs_l; + reg [31:0] clk_cnt; + reg [3:0] led_q; + wire [3:0] memtest_ok; + reg led_test_reg; + reg [3:0] qsfp_rst_reg; + reg [3:0] qsfp_lp_reg; + reg [3:0] qsfp_sel_oh; + reg [3:0] qsfp_i2c_ctri_vec; + reg [3:0] qsfp_i2c_dtri_vec; + reg [3:0] qsfp_i2c_cin_vec; + reg [3:0] qsfp_i2c_din_vec; + wire [31:0] CSR_awaddr; + wire [31:0] CSR_wdata; + wire [31:0] CSR_araddr; + reg [31:0] CSR_rdata; + reg CSR_rvalid; + reg CSR_awready; + reg CSR_arready; + reg CSR_wready; + reg CSR_bvalid; + wire CSR_wdecode; + wire CSR_rdecode; + wire csr_ren; + wire csr_wen; + wire sys_clk; + wire sys_clk_gt; + wire [31:0] UAR_DATA; + + + IBUFDS_GTE4 refclk_ibuf (.O(sys_clk_gt), .ODIV2(sys_clk), .I(sys_clkp), .CEB(1'b0), .IB(sys_clkn)); + + // STARTUPE3 block: Allows FPGA logic connections to dedicated config. pins + // From the UltraScale Configuration Guide: + // FCSBO: FPGA logic signal to external FCS_B configuration pin. FCSBO allows user + // control of FCS_B pin for Flash access. + // USRCCLKO (User CCLK input). USRCCLKO is an input from the FPGA logic. USERCCLKO drives a custom, + // FPGA-generated clock frequency onto the external FPGA CCLK pin. This is useful for + // post-configuration access of external SPI flash devices. + + // STARTUPE3: STARTUP Block + // UltraScale + // Xilinx HDL Libraries Guide, version 2014.4 + STARTUPE3 #( + .PROG_USR("FALSE") // Activate program event security feature. Requires encrypted bitstreams. + ) + STARTUPE3_inst ( + .CFGCLK(), // 1-bit output: Configuration main clock output + .CFGMCLK(), // 1-bit output: Configuration internal oscillator clock output + .DI(spi_in), // 4-bit output: Allow receiving on the D input pin + .EOS(), // 1-bit output: Active-High output signal indicating the End Of Startup + .PREQ(), // 1-bit output: PROGRAM request to fabric output + .DO({3'b000,spi_mosi}),// 4-bit input: Allows control of the D pin output + .DTS(4'b1110), // 4-bit input: Allows tristate of the D pin + .FCSBO(spi_cs_l), // 1-bit input: Contols the FCS_B pin for flash access + .FCSBTS(1'b0), // 1-bit input: Tristate the FCS_B pin + .GSR(), // 1-bit input: Global Set/Reset input (GSR cannot be used for the port) + .GTS(1'b0), // 1-bit input: Global 3-state input (GTS cannot be used for the port name) + .KEYCLEARB(), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM) + .PACK(), // 1-bit input: PROGRAM acknowledge input + .USRCCLKO(spi_sck_o), // 1-bit input: User CCLK input + .USRCCLKTS(1'b0), // 1-bit input: User CCLK 3-state enable input + .USRDONEO(1'b1), // 1-bit input: User DONE pin output control + .USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output + ); + + // + // PCIe IPI subsystem instantiation + // + pcie2axilite_sub pcie2axilite_sub_i( + .sys_clk(sys_clk), + .sys_clk_gt(sys_clk_gt), + .clk_100_clk_p(prog_b5_p), + .clk_100_clk_n(prog_b5_n), + .sys_reset_l(sys_reset_l), + .pcie_7x_mgt_rxn(pcie_7x_mgt_rxn), + .pcie_7x_mgt_rxp(pcie_7x_mgt_rxp), + .pcie_7x_mgt_txn(pcie_7x_mgt_txn), + .pcie_7x_mgt_txp(pcie_7x_mgt_txp), + .axi_aclk(axi_clk), + .user_link_up(rst_l), + .m00_axi_0_araddr(CSR_araddr), + .m00_axi_0_arprot(CSR_arprot), + .m00_axi_0_arready(CSR_arready), + .m00_axi_0_arvalid(CSR_arvalid), + .m00_axi_0_awaddr(CSR_awaddr), + .m00_axi_0_awprot(CSR_awprot), + .m00_axi_0_awready(CSR_awready), + .m00_axi_0_awvalid(CSR_awvalid), + .m00_axi_0_bready(CSR_bready), + .m00_axi_0_bresp(1'b0), + .m00_axi_0_bvalid(CSR_bvalid), + .m00_axi_0_rdata(CSR_rdata), + .m00_axi_0_rready(CSR_rready), + .m00_axi_0_rresp(1'b0), + .m00_axi_0_rvalid(CSR_rvalid), + .m00_axi_0_wdata(CSR_wdata), + .m00_axi_0_wready(CSR_wready), + .m00_axi_0_wstrb(CSR_wstrb), + .m00_axi_0_wvalid(CSR_wvalid), + .uart_0_baudoutn(), + .uart_0_ctsn(1'b0), + .uart_0_dcdn(1'b0), + .uart_0_ddis(), + .uart_0_dsrn(1'b0), + .uart_0_dtrn(), + .uart_0_out1n(), + .uart_0_out2n(), + .uart_0_ri(1'b0), + .uart_0_rtsn(), + .uart_0_rxd(avr_txd), + .uart_0_rxrdyn(), + .uart_0_txd(avr_rxd), + .uart_0_txrdyn(), + .iic_0_scl_i(i2c_cin), + .iic_0_scl_o(i2c_cout), + .iic_0_scl_t(i2c_ctri), + .iic_0_sda_i(i2c_din), + .iic_0_sda_o(i2c_dout), + .iic_0_sda_t(i2c_dtri), + .spi_0_io0_o(spi_io0_o), + .spi_0_io1_i(spi_io1_i), + .spi_0_sck_o(spi_sck_o), + .spi_0_ss_o(spi_ss_o_0), + .spi_0_ss_t(spi_ss_t) + ); + + assign spi_mosi = spi_io0_o; + assign spi_io1_i = spi_miso; + + always@(posedge axi_clk) begin + if (spi_ss_t == 0) + spi_cs_l <= spi_ss_o_0; + else + spi_cs_l <= 1'b1; + end + + //*************************************************************************** + // Buffers for I2C Tri-State I/O + //*************************************************************************** + IOBUF IOBUF_i2c_clk_inst ( + .O(i2c_cin), + .I(i2c_cout), + .IO(i2c_scl), + .T(i2c_ctri) + ); + + IOBUF IOBUF_i2c_data_inst ( + .O(i2c_din), + .I(i2c_dout), + .IO(i2c_sda), + .T(i2c_dtri) + ); + + USR_ACCESSE2 USR_ACCESSE2_inst ( + .CFGCLK(), // 1-bit output: Configuration Clock + .DATA(UAR_DATA), // 32-bit output: Configuration Data reflecting the contents of the AXSS register + .DATAVALID() // 1-bit output: Active High Data Valid + ); + + // decode CSR Transaction + assign CSR_wdecode = (CSR_awaddr[`DEV_SEL_HI_BIT:`DEV_SEL_LO_BIT] == 0) | (CSR_awaddr[`DEV_SEL_HI_BIT:`DEV_SEL_LO_BIT] > 3); // Decode 0x0 and out-of-range to CSR + assign CSR_rdecode = (CSR_araddr[`DEV_SEL_HI_BIT:`DEV_SEL_LO_BIT] == 0) | (CSR_araddr[`DEV_SEL_HI_BIT:`DEV_SEL_LO_BIT] > 3); // Decode 0x0 and out-of-range to CSR + assign csr_wen = CSR_awready & CSR_wdecode; + assign csr_ren = CSR_arready & CSR_rdecode; + + always@(posedge axi_clk or negedge(rst_l)) begin + if (rst_l == 1'b0) begin + CSR_awready <= 1'b0; + CSR_arready <= 1'b0; + clk_cnt <= 0; + led_q <= 0; + led_test_reg <= 1'b0; + qsfp_rst_reg <= 'h0; + qsfp_lp_reg <= 'h0; + qsfp_sel_oh <= 4'h0; + end + else begin + clk_cnt <= clk_cnt + 1; + led_q[3] <= clk_cnt[25]; + CSR_awready <= CSR_awvalid; + CSR_arready <= CSR_arvalid; + if (csr_wen & CSR_wvalid) begin + CSR_wready <= CSR_wvalid & ~(CSR_awvalid); + if (CSR_awaddr[`DEV_SEL_LO_BIT-1]) begin + qsfp_rst_reg <= CSR_wdata[19:16]; // AXI Write to addr 0x80 Config Reg, R/W + qsfp_lp_reg <= CSR_wdata[15:12]; + qsfp_sel_oh <= CSR_wdata[11:8]; + led_test_reg <= CSR_wdata[7]; + led_q[2:0] <= CSR_wdata[6:4]; + end + CSR_bvalid <= 1; + end + else if (csr_ren & CSR_rready) begin + CSR_rvalid <= CSR_rready & ~(CSR_arvalid); + // AXI Read: 0x80 reads config reg, 0x0 reads VERSION REG, 0x4 reads UAR. 0x0 and 0x4 are READ ONLY + CSR_rdata <= CSR_araddr[`DEV_SEL_LO_BIT-1] ? {12'h0, + qsfp_rst_reg, + qsfp_lp_reg, + qsfp_sel_oh, + led_test_reg, + led_q[2:0], + 4'b0000} : CSR_araddr[3] ? 32'h0 : (CSR_araddr[2] ? UAR_DATA : `VERSION_REG); + end + else begin + CSR_rvalid <= 0; + CSR_wready <= 0; + end + end + end + + assign spi_miso = spi_in[1]; + + assign led_pins = ~led_q; + assign FPGA_I2C_MASTER_L = 1'b1; // Change to 1'b0 to allow FPGA control of QSFP I2C bus + assign QSFP_CTL_EN = 1'b1; + assign SAS_CTL_EN = 1'b1; + + // User logic + + + +endmodule diff --git a/ip_cores/common/scripts/synchronizer.tcl b/ip_cores/common/scripts/synchronizer.tcl new file mode 100644 index 0000000..4d9fb85 --- /dev/null +++ b/ip_cores/common/scripts/synchronizer.tcl @@ -0,0 +1,30 @@ +# Find all the cdc_fifos and synchronizers set constraints for the cross clock domains. +# +# Copyright (C) 2019 Benjamin Devlin and Zcash Foundation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set synchronizer_instance [get_cells -hierarchical -filter { ORIG_REF_NAME =~ "synchronizer" || REF_NAME =~ "synchronizer" } ] +foreach child $synchronizer_instance { + + set name [get_property NAME $child] + + set cells [get_cells -hierarchical -filter "NAME =~ $name/* "] + set clock [get_clocks -of_objects [get_pins -filter { NAME =~ "*dat_reg[1]*C" } -of_objects $cells]] + set clock_period [get_property PERIOD $clock] + + set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects $cells] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects $cells] [expr $clock_period/2] + set_max_delay -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects $cells] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects $cells] -datapath_only [expr $clock_period/2] + +} \ No newline at end of file diff --git a/ip_cores/common/src/rtl/common_if.sv b/ip_cores/common/src/rtl/common_if.sv index a30d111..e08aab5 100644 --- a/ip_cores/common/src/rtl/common_if.sv +++ b/ip_cores/common/src/rtl/common_if.sv @@ -20,7 +20,7 @@ */ interface if_axi_stream # ( - parameter DAT_BYTS = 64, + parameter DAT_BYTS = 8, parameter DAT_BITS = DAT_BYTS*8, parameter CTL_BYTS = 1, parameter CTL_BITS = CTL_BYTS*8, diff --git a/ip_cores/fifo/scripts/cdc_fifo.tcl b/ip_cores/fifo/scripts/cdc_fifo.tcl index b98de7e..3725566 100644 --- a/ip_cores/fifo/scripts/cdc_fifo.tcl +++ b/ip_cores/fifo/scripts/cdc_fifo.tcl @@ -18,7 +18,6 @@ set cdc_fifo_instance [get_cells -hierarchical -filter { ORIG_REF_NAME =~ "cdc_fifo" || REF_NAME =~ "cdc_fifo" } ] foreach child $cdc_fifo_instance { - set using_bram [get_property USE_BRAM [get_cells $child]] set name [get_property NAME $child] set wr_ptr_cells [get_cells -hierarchical -filter "NAME =~ $name/synchronizer_wr_ptr/* "] diff --git a/zcash_fpga/src/rtl/control/control_top.sv b/zcash_fpga/src/rtl/control/control_top.sv index 43cc503..8ef3a72 100644 --- a/zcash_fpga/src/rtl/control/control_top.sv +++ b/zcash_fpga/src/rtl/control/control_top.sv @@ -26,7 +26,7 @@ module control_top parameter [63:0] BUILD_HOST = "test", parameter [63:0] BUILD_DATE = "20180311" )( - input i_clk_core, i_rst_core, + input i_clk_core, i_rst_core, i_rst_core_perm, // _perm reset is not effected by o_usr_rst input i_clk_if, i_rst_if, // User is able to reset custom logic on FPGA output logic o_usr_rst, @@ -43,6 +43,8 @@ module control_top localparam IN_DAT_BITS = IN_DAT_BYTS*8; localparam CORE_DAT_BITS = CORE_DAT_BYTS*8; +localparam MAX_BYT_MSG = 256; // Max bytes in a reply message + // When a command comes in it is put through a clock crossing, and then stored in a command // FIFO to be processed. There are two FIFOS - one for processing status / reset commands (msg_type == 0), // and one for everything else. This is so we can process these messages even if we are @@ -59,24 +61,31 @@ if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) rx_typ1_if (i_clk_core); if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) tx_arb_in_if [2] (i_clk_core); if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) tx_int_if (i_clk_core); -enum {TYP0_IDLE = 0, +typedef enum {TYP0_IDLE = 0, TYP0_SEND_STATUS = 1, TYP0_RESET_FPGA = 2, - TYP0_IGNORE = 3} typ0_msg_state; + TYP0_SEND_IGNORE = 3, + TYP0_IGNORE = 4} typ0_msg_state_t; + +typ0_msg_state_t typ0_msg_state; enum {TYP1_IDLE = 0, TYP1_VERIFY_EQUIHASH = 1, TYP1_IGNORE = 2} typ1_msg_state; header_t header, header0, header1, header0_l, header1_l; -fpga_status_rpl_t fpga_status_rpl; -fpga_reset_rpl_t fpga_reset_rpl; +//fpga_status_rpl_t fpga_status_rpl; +//fpga_reset_rpl_t fpga_reset_rpl; +//fpga_ignore_rpl_t fpga0_ignore_rpl; verify_equihash_rpl_t verify_equihash_rpl; -logic [7:0] typ0_wrd_cnt, typ1_wrd_cnt, reset_cnt; +logic [7:0] reset_cnt; +logic [$clog2(MAX_BYT_MSG) -1:0] typ0_wrd_cnt, typ1_wrd_cnt; +logic [MAX_BYT_MSG*8 -1:0] typ0_msg; logic [63:0] equihash_index; logic equihash_index_val, rx_typ1_if_rdy, verify_equihash_rpl_val; logic sop_l; +logic eop_typ0_l; fpga_state_t fpga_state; always_comb begin @@ -90,45 +99,54 @@ end // Logic for processing msg_type == 0 messages always_ff @ (posedge i_clk_core) begin - if (i_rst_core) begin + if (i_rst_core_perm ) begin rx_typ0_if.rdy <= 0; typ0_msg_state <= TYP0_IDLE; header0_l <= 0; tx_arb_in_if[0].reset_source(); - fpga_status_rpl <= 0; - fpga_reset_rpl <= 0; + // fpga_status_rpl <= 0; + // fpga_reset_rpl <= 0; +/// fpga0_ignore_rpl <= 0; typ0_wrd_cnt <= 0; o_usr_rst <= 0; reset_cnt <= 0; + eop_typ0_l <= 0; + typ0_msg <= 0; end else begin rx_typ0_if.rdy <= 1; case (typ0_msg_state) TYP0_IDLE: begin - fpga_status_rpl <= get_fpga_status_rpl(BUILD_HOST, BUILD_DATE, fpga_state); - fpga_reset_rpl <= get_fpga_reset_rpl(); + //fpga_status_rpl <= get_fpga_status_rpl(BUILD_HOST, BUILD_DATE, fpga_state); + //fpga_reset_rpl <= get_fpga_reset_rpl(); + //fpga0_ignore_rpl <= get_fpga_ignore_rpl(header0); if (rx_typ0_if.val && rx_typ0_if.rdy) begin header0_l <= header0; rx_typ0_if.rdy <= 0; case(header0.cmd) RESET_FPGA: begin + typ0_msg <= get_fpga_reset_rpl(); typ0_wrd_cnt <= $bits(fpga_reset_rpl_t)/8; typ0_msg_state <= TYP0_RESET_FPGA; o_usr_rst <= 1; reset_cnt <= -1; end FPGA_STATUS: begin + typ0_msg <= get_fpga_status_rpl(BUILD_HOST, BUILD_DATE, fpga_state); typ0_wrd_cnt <= $bits(fpga_status_rpl_t)/8; typ0_msg_state <= TYP0_SEND_STATUS; end - default: - if (~rx_typ0_if.eop) - typ0_msg_state <= TYP0_IGNORE; + default: begin + typ0_msg <= get_fpga_ignore_rpl(header0); + eop_typ0_l <= rx_typ0_if.eop; + typ0_msg_state <= TYP0_SEND_IGNORE; + end endcase end end TYP0_SEND_STATUS: begin + /* rx_typ0_if.rdy <= 0; if (~tx_arb_in_if[0].val || (tx_arb_in_if[0].rdy && tx_arb_in_if[0].val)) begin tx_arb_in_if[0].dat <= fpga_status_rpl; @@ -143,6 +161,8 @@ always_ff @ (posedge i_clk_core) begin typ0_msg_state <= TYP0_IDLE; end end + */ + send_typ0_message($bits(fpga_status_rpl_t)/8, typ0_msg, typ0_wrd_cnt); end TYP0_RESET_FPGA: begin rx_typ0_if.rdy <= 0; @@ -152,6 +172,8 @@ always_ff @ (posedge i_clk_core) begin reset_cnt <= reset_cnt - 1; if (~o_usr_rst) begin + send_typ0_message($bits(fpga_reset_rpl_t)/8, typ0_msg, typ0_wrd_cnt); + /* if (~tx_arb_in_if[0].val || (tx_arb_in_if[0].rdy && tx_arb_in_if[0].val)) begin tx_arb_in_if[0].dat <= fpga_reset_rpl; tx_arb_in_if[0].val <= 1; @@ -164,10 +186,27 @@ always_ff @ (posedge i_clk_core) begin tx_arb_in_if[0].val <= 0; typ0_msg_state <= TYP0_IDLE; end - end + end*/ end - end + TYP0_SEND_IGNORE: begin + send_typ0_message($bits(fpga0_ignore_rpl_t)/8, typ0_msg, typ0_wrd_cnt, eop_typ0_l ? TYP0_IDLE :TYP0_IGNORE); + /* + rx_typ0_if.rdy <= 0; + if (~tx_arb_in_if[0].val || (tx_arb_in_if[0].rdy && tx_arb_in_if[0].val)) begin + tx_arb_in_if[0].dat <= fpga_ignore_rpl; + tx_arb_in_if[0].val <= 1; + tx_arb_in_if[0].sop <= typ0_wrd_cnt == $bits(fpga0_ignore_rpl_t)/8; + tx_arb_in_if[0].eop <= typ0_wrd_cnt <= CORE_DAT_BYTS; + tx_arb_in_if[0].mod <= typ0_wrd_cnt < CORE_DAT_BYTS ? typ0_wrd_cnt : 0; + typ0_wrd_cnt <= (typ0_wrd_cnt > CORE_DAT_BYTS) ? (typ0_wrd_cnt - CORE_DAT_BYTS) : 0; + fpga_ignore_rpl <= fpga_ignore_rpl >> CORE_DAT_BITS; + if (typ0_wrd_cnt == 0) begin + tx_arb_in_if[0].val <= 0; + typ0_msg_state <= eop_typ0_l ? TYP0_IDLE :TYP0_IGNORE; + end + end*/ + end TYP0_IGNORE: begin rx_typ0_if.rdy <= 1; if (rx_typ0_if.rdy && rx_typ0_if.eop && rx_typ0_if.val) @@ -177,6 +216,24 @@ always_ff @ (posedge i_clk_core) begin end end +// Task to help build reply messages. Assume no message will be more than MAX_BYT_MSG bytes +task automatic send_typ0_message(input logic [$clog2(MAX_BYT_MSG)-1:0] msg_size, ref logic [MAX_BYT_MSG*8-1:0] msg, ref logic [$clog2(MAX_BYT_MSG)-1:0] byt_cnt, input typ0_msg_state_t nxt_state = TYP0_IDLE); + rx_typ0_if.rdy <= 0; + if (~tx_arb_in_if[0].val || (tx_arb_in_if[0].rdy && tx_arb_in_if[0].val)) begin + tx_arb_in_if[0].dat <= msg; + tx_arb_in_if[0].val <= 1; + tx_arb_in_if[0].sop <= byt_cnt == msg_size; + tx_arb_in_if[0].eop <= byt_cnt <= CORE_DAT_BYTS; + tx_arb_in_if[0].mod <= byt_cnt < CORE_DAT_BYTS ? byt_cnt : 0; + byt_cnt <= (byt_cnt > CORE_DAT_BYTS) ? (byt_cnt - CORE_DAT_BYTS) : 0; + msg <= msg >> CORE_DAT_BITS; + if (byt_cnt == 0) begin + tx_arb_in_if[0].val <= 0; + typ0_msg_state <= nxt_state; + end + end +endtask + always_comb begin case(typ1_msg_state) TYP1_IDLE: rx_typ1_if.rdy = rx_typ1_if_rdy; @@ -199,6 +256,7 @@ always_ff @ (posedge i_clk_core) begin equihash_index_val <= 0; sop_l <= 0; end else begin + // TODO add IGNORE type here case (typ1_msg_state) TYP1_IDLE: begin rx_typ1_if_rdy <= 1; @@ -303,7 +361,7 @@ always_comb begin end always_ff @ (posedge i_clk_core) begin - if (i_rst_core || o_usr_rst) begin + if (i_rst_core ) begin msg_type_l <= 0; end else begin if (rx_int_if.val && rx_int_if.rdy) begin @@ -321,7 +379,7 @@ axi_stream_fifo #( ) cmd_fifo0 ( .i_clk ( i_clk_core ), - .i_rst ( i_rst_core || o_usr_rst ), + .i_rst ( i_rst_core ), .i_axi ( rx_int0_if ), .o_axi ( rx_typ0_if ) ); @@ -332,7 +390,7 @@ axi_stream_fifo #( ) cmd_fifo1 ( .i_clk ( i_clk_core ), - .i_rst ( i_rst_core || o_usr_rst ), + .i_rst ( i_rst_core ), .i_axi ( rx_int1_if ), .o_axi ( rx_typ1_if ) ); @@ -346,9 +404,9 @@ width_change_cdc_fifo #( ) cdc_fifo_rx ( .i_clk_a ( i_clk_if ), - .i_rst_a ( i_rst_if || o_usr_rst ), + .i_rst_a ( i_rst_if ), .i_clk_b ( i_clk_core ), - .i_rst_b ( i_rst_core || o_usr_rst ), + .i_rst_b ( i_rst_core ), .i_axi_a ( rx_if ), .o_axi_b ( rx_int_if ) ); @@ -361,7 +419,7 @@ packet_arb # ( ) packet_arb_tx ( .i_clk ( i_clk_core ), - .i_rst ( i_rst_core || o_usr_rst ), + .i_rst ( i_rst_core ), .i_axi ( tx_arb_in_if ), .o_axi ( tx_int_if ) @@ -377,9 +435,9 @@ width_change_cdc_fifo #( ) cdc_fifo_tx ( .i_clk_a ( i_clk_core ), - .i_rst_a ( i_rst_core || o_usr_rst ), + .i_rst_a ( i_rst_core ), .i_clk_b ( i_clk_if ), - .i_rst_b ( i_rst_if || o_usr_rst ), + .i_rst_b ( i_rst_if ), .i_axi_a ( tx_int_if ), .o_axi_b ( tx_if ) ); diff --git a/zcash_fpga/src/rtl/secp256k1/secp256k1_mod.sv b/zcash_fpga/src/rtl/secp256k1/secp256k1_mod.sv new file mode 100644 index 0000000..135029b --- /dev/null +++ b/zcash_fpga/src/rtl/secp256k1/secp256k1_mod.sv @@ -0,0 +1,89 @@ +/* + This performs modular reduction using Algorithm 2.4 from + D. Hankerson, A. Menezes, S. Vanstone, “Guide to Elliptic Curve Cryptography” + but with data width 256, for the prime field used in secp256k1 + + p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 + + Implemented with 2 stages of 8x 256b adds and one final optional + subtract in the case we are >= p. + + returns o_dat = i_dat % p, where i_dat < p^2 + + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +module secp256k1_mod ( + input i_clk, i_rst, + // Input value + input [256*2-1:0] i_dat, + input i_val, + output logic o_rdy, + // output + output logic [255:0] o_dat, + input i_rdy, + output logic o_val +); + +import secp256k1_pkg::*; + +logic [256*2-1:0] b, a, a_; + +always_comb begin + a_ = (a << 32) + (a << 9) + (a << 8) + (a << 7) + (a << 6) + (a << 4) + a + b; +end + +enum {IDLE, S1, S2} state; + +always_ff @ (posedge i_clk) begin + if (i_rst) begin + a <= 0; + b <= 0; + state <= IDLE; + o_val <= 0; + o_rdy <= 0; + end else begin + o_rdy <= 0; + o_dat <= a_ >= p_eq ? (a_ - p_eq) : a_; + case(state) + IDLE: begin + o_rdy <= 1; + o_val <= 0; + if (i_val && o_rdy) begin + a <= i_dat[511:256]; + b <= i_dat[255:0]; + o_rdy <= 0; + state <= S1; + end + end + S1: begin + a <= a_[511:256]; + b <= a_[255:0]; + state <= S2; + end + S2: begin + o_val <= 1; + if (o_val && i_rdy) begin + state <=IDLE; + o_rdy <= 1; + o_val <= 0; + end + end + endcase + end +end + +endmodule \ No newline at end of file diff --git a/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv b/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv new file mode 100644 index 0000000..d2d0089 --- /dev/null +++ b/zcash_fpga/src/rtl/secp256k1/secp256k1_pkg.sv @@ -0,0 +1,33 @@ +/* + Package for the secp256k1 core + + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +package secp256k1_pkg; + + // TODO might have to flip these + parameter [255:0] p = 256'hFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFC2F; + parameter [255:0] a = 256'h0; + parameter [255:0] b = 256'h7; + parameter [255:0] Gx = 256'h79BE667E_F9DCBBAC_55A06295_CE870B07_029BFCDB_2DCE28D9_59F2815B_16F81798; + parameter [255:0] Gy = 256'h483ADA77_26A3C465_5DA4FBFC_0E1108A8_FD17B448_A6855419_9C47D08F_FB10D4B8; + parameter [255:0] n = 256'hFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_BAAEDCE6_AF48A03B_BFD25E8C_D0364141; + parameter [255:0] h = 256'h1; + + parameter [255:0] p_eq = (1 << 256) - (1 << 32) - (1 << 9) - (1 << 8) - (1 << 7) - (1 << 6) - (1 << 4) - 1; + +endpackage \ No newline at end of file diff --git a/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv b/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv new file mode 100644 index 0000000..89c110b --- /dev/null +++ b/zcash_fpga/src/rtl/secp256k1/secp256k1_top.sv @@ -0,0 +1,10 @@ +module secp256k1_top (); + + + // inversion + + // multiplication + + // addition + +endmodule \ No newline at end of file diff --git a/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv b/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv index 08c2948..5b2f0e0 100644 --- a/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv +++ b/zcash_fpga/src/rtl/top/zcash_fpga_pkg.sv @@ -21,9 +21,13 @@ package zcash_fpga_pkg; import equihash_pkg::equihash_bm_t; import equihash_pkg::cblockheader_sol_t; + import equihash_pkg::N; + import equihash_pkg::K; parameter FPGA_VERSION = 32'h0; - localparam [63:0] FPGA_CMD_CAP = 64'h0; + localparam [63:0] FPGA_CMD_CAP = {{62'd0}, + (equihash_pkg::N == 144 && equihash_pkg::K == 5), // N = 144, K = 5 for VERIFY_EQUIHASH command + (equihash_pkg::N == 200 && equihash_pkg::K == 9)}; // N = 200, K = 9 for VERIFY_EQUIHASH command // These are all the command types the FPGA supports // Reply messages from the FPGA to host all have the last @@ -36,6 +40,7 @@ package zcash_fpga_pkg; // Replies from the FPGA RESET_FPGA_RPL = 'h80_00_00_00, FPGA_STATUS_RPL = 'h80_00_00_01, + FPGA_IGNORE_RPL = 'h80_00_00_02, VERIFY_EQUIHASH_RPL = 'h80_00_01_00 } command_t; @@ -50,6 +55,11 @@ package zcash_fpga_pkg; header_t hdr; } fpga_reset_rpl_t; + typedef struct packed { + header_t hdr; + logic [63:0] ignore_hdr; + } fpga_ignore_rpl_t; + // These are registers we use for debug typedef struct packed { logic [3:0] padding; @@ -82,6 +92,10 @@ package zcash_fpga_pkg; function fpga_reset_rpl_t get_fpga_reset_rpl(); get_fpga_reset_rpl.hdr = '{cmd:RESET_FPGA_RPL, len:$bits(fpga_reset_rpl_t)/8}; endfunction + + function fpga_ignore_rpl_t get_fpga_ignore_rpl(header_t hdr); + get_fpga_ignore_rpl.hdr = '{cmd:FPGA_IGNORE_RPL, len:$bits(fpga_ignore_rpl_t)/8}; + endfunction function fpga_status_rpl_t get_fpga_status_rpl(input [63:0] build_host, build_date, fpga_state_t fpga_state); get_fpga_status_rpl.cmd_cap = FPGA_CMD_CAP; diff --git a/zcash_fpga/src/rtl/top/zcash_fpga_top.sv b/zcash_fpga/src/rtl/top/zcash_fpga_top.sv index f7201ba..795672c 100644 --- a/zcash_fpga/src/rtl/top/zcash_fpga_top.sv +++ b/zcash_fpga/src/rtl/top/zcash_fpga_top.sv @@ -27,37 +27,65 @@ module zcash_fpga_top parameter CORE_DAT_BYTS = 8 // Only tested at 8 byte data width )( // Clocks and resets - input i_clk_200, i_rst_200, - input i_clk_300, i_rst_300, - input i_clk_if, i_rst_if, + input i_clk_core0, i_rst_core0, // Core 0 is the main clock + input i_clk_core1, i_rst_core1, // Core 1 is used on logic with faster clock + input i_clk_if, i_rst_if, // Command interface clock (e.g. UART / PCIe) - // Interface input and output - // UART + // Command interface input and output if_axi_stream.sink rx_if, if_axi_stream.source tx_if ); -logic usr_rst, core_clk, core_rst; -if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS)) equihash_axi(core_clk); +logic rst_core0, rst_core1, rst_if, usr_rst, usr_rst_r; + +logic rst_200, rst_300; + +if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS)) equihash_axi(i_clk_core0); equihash_bm_t equihash_mask; logic equihash_mask_val; -always_comb begin - core_clk = i_clk_200; - core_rst = i_rst_200; +always_ff @ (posedge i_clk_core0) begin + usr_rst_r <= usr_rst; + rst_core0 <= i_rst_core0 || usr_rst_r; end +// Synchronize resets +(* DONT_TOUCH = "yes" *) +synchronizer #( + .DAT_BITS ( 1 ), + .NUM_CLKS ( 3 ) +) +core_rst1_sync ( + .i_clk_a ( i_clk_core0 ), + .i_clk_b ( i_clk_core1 ), + .i_dat_a ( usr_rst_r || i_rst_core1 ), + .o_dat_b ( rst_core1 ) +); + +(* DONT_TOUCH = "yes" *) +synchronizer #( + .DAT_BITS ( 1 ), + .NUM_CLKS ( 3 ) +) +if_rst_sync ( + .i_clk_a ( i_clk_core0 ), + .i_clk_b ( i_clk_if ), + .i_dat_a ( usr_rst_r || i_rst_if ), + .o_dat_b ( rst_if ) +); + // This block takes in the interface signals and interfaces with other blocks control_top #( .CORE_DAT_BYTS ( CORE_DAT_BYTS ), .IN_DAT_BYTS ( IF_DAT_BYTS ) ) control_top ( - .i_clk_core ( core_clk ), - .i_rst_core ( core_rst ), + .i_clk_core ( i_clk_core0 ), + .i_rst_core ( rst_core0 ), + .i_rst_core_perm ( i_rst_core0 ), .i_clk_if ( i_clk_if ), - .i_rst_if ( i_rst_if ), + .i_rst_if ( rst_if ), .o_usr_rst ( usr_rst ), .rx_if ( rx_if ), .tx_if ( tx_if ), @@ -72,12 +100,10 @@ equihash_verif_top #( .DAT_BYTS( CORE_DAT_BYTS ) ) equihash_verif_top ( - .i_clk ( core_clk ), - .i_rst ( core_rst || usr_rst ), - - .i_clk_300 ( i_clk_300 ), - .i_rst_300 ( i_rst_300 || usr_rst ), // Faster clock - + .i_clk ( i_clk_core0 ), + .i_rst ( core_rst ), + .i_clk_300 ( i_clk_core1 ), // Faster clock + .i_rst_300 ( rst_core1 ), .i_axi ( equihash_axi ), .o_mask ( equihash_mask ), .o_mask_val ( equihash_mask_val ) diff --git a/zcash_fpga/src/tb/secp256k1_mod_tb.sv b/zcash_fpga/src/tb/secp256k1_mod_tb.sv new file mode 100644 index 0000000..0dac1d0 --- /dev/null +++ b/zcash_fpga/src/tb/secp256k1_mod_tb.sv @@ -0,0 +1,116 @@ +/* + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +`timescale 1ps/1ps + +module secp256k1_mod_tb (); +import common_pkg::*; +import secp256k1_pkg::*; + +localparam CLK_PERIOD = 100; + +logic clk, rst; + +if_axi_stream #(.DAT_BYTS(512/8)) in_if(clk); +if_axi_stream #(.DAT_BYTS(256/8)) out_if(clk); + +initial begin + rst = 0; + repeat(2) #(20*CLK_PERIOD) rst = ~rst; +end + +initial begin + clk = 0; + forever #CLK_PERIOD clk = ~clk; +end + +always_comb begin + out_if.sop = 1; + out_if.eop = 1; + out_if.err = 0; + out_if.ctl = 0; + out_if.mod = 0; +end + +secp256k1_mod secp256k1_mod +( + .i_clk( clk ), + .i_rst( rst ), + .i_dat( in_if.dat ), + .i_val( in_if.val ), + .o_rdy( in_if.rdy ), + .o_dat( out_if.dat ), + .i_rdy( out_if.rdy ), + .o_val( out_if.val ) +); + +task test0(); +begin + integer signed get_len; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] expected, in_dat, get_dat; + $display("Running test0..."); + in_dat = 1 << 433; + expected = 256'd822752465816620949324161418291805943222876982255305228346720256; + fork + in_if.put_stream(in_dat, 512/8); + out_if.get_stream(get_dat, get_len); + join + + common_pkg::compare_and_print(get_dat, expected); + $display("test0 PASSED"); +end +endtask; + +task test_loop(); +begin + integer signed get_len, i, max; + logic [common_pkg::MAX_SIM_BYTS*8-1:0] expected, in_dat, get_dat; + $display("Running test_loop..."); + in_dat = 1 << 433; + expected = 256'd822752465816620949324161418291805943222876982255305228346720256; + i = 0; + max = 10000; + repeat (max) begin + + in_dat = in_dat*2; + expected = expected*2; + while (expected >= p_eq) + expected = expected - p_eq; + + fork + in_if.put_stream(in_dat, 512/8); + out_if.get_stream(get_dat, get_len); + join + + common_pkg::compare_and_print(get_dat, expected); + $display("test_loop PASSED loop %d/%d", i, max); + i = i + 1; + end + + + $display("test_loop PASSED"); +end +endtask; + +initial begin + out_if.rdy = 0; + in_if.val = 0; + #(40*CLK_PERIOD); + test0(); + test_loop(); + #1us $finish(); +end +endmodule \ No newline at end of file diff --git a/zcash_fpga/src/tb/zcash_fpga_top_tb.sv b/zcash_fpga/src/tb/zcash_fpga_top_tb.sv index 66502d1..13f6c4f 100644 --- a/zcash_fpga/src/tb/zcash_fpga_top_tb.sv +++ b/zcash_fpga/src/tb/zcash_fpga_top_tb.sv @@ -195,6 +195,7 @@ initial begin #20us; // Let internal memories reset test_block_346_equihash(); + test_ignored_message(); #1us $finish(); diff --git a/zcash_fpga/synth/zcash_fpga_top.xdc b/zcash_fpga/synth/zcash_fpga_top.xdc index b21032d..d5308ae 100644 --- a/zcash_fpga/synth/zcash_fpga_top.xdc +++ b/zcash_fpga/synth/zcash_fpga_top.xdc @@ -1,7 +1,10 @@ -create_clock -period 5.000 -name i_clk_200 -waveform {0.000 2.500} [get_ports -filter { NAME =~ "*i_clk_200*" && DIRECTION == "IN" }] -create_clock -period 3.333 -name i_clk_300 -waveform {0.000 1.666} [get_ports -filter { NAME =~ "i_clk_300" && DIRECTION == "IN" }] +create_clock -period 3.000 -name i_clk_core1 -waveform {0.000 1.500} [get_ports -filter { NAME =~ "i_clk_core1" && DIRECTION == "IN" }] +create_clock -period 5.000 -name i_clk_core0 -waveform {0.000 2.500} [get_ports -filter { NAME =~ "i_clk_core0" && DIRECTION == "IN" }] create_clock -period 10.000 -name i_clk_if -waveform {0.000 5.000} [get_ports -filter { NAME =~ "i_clk_if" && DIRECTION == "IN" }] +#Just for when we are synth a test block +create_clock -period 5.000 -name i_clk -waveform {0.000 2.500} [get_ports -filter { NAME =~ "i_clk" && DIRECTION == "IN" }] + set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ control_top/cdc_fifo_rx/cdc_fifo/synchronizer_wr_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ control_top/cdc_fifo_rx/cdc_fifo/synchronizer_wr_ptr/* }]] 2.500 set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ control_top/cdc_fifo_rx/cdc_fifo/synchronizer_wr_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ control_top/cdc_fifo_rx/cdc_fifo/synchronizer_wr_ptr/* }]] 2.500 set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ control_top/cdc_fifo_rx/cdc_fifo/synchronizer_rd_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ control_top/cdc_fifo_rx/cdc_fifo/synchronizer_rd_ptr/* }]] 5.000 @@ -48,5 +51,9 @@ set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [g set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ equihash_verif_top/dup_check_fifo_out/synchronizer_rd_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ equihash_verif_top/dup_check_fifo_out/synchronizer_rd_ptr/* }]] 1.667 set_bus_skew -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ equihash_verif_top/dup_check_fifo_out/* }]] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ equihash_verif_top/dup_check_fifo_out/* }]] 1.667 set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ equihash_verif_top/dup_check_fifo_out/* }]] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ equihash_verif_top/dup_check_fifo_out/* }]] 1.667 -set_multicycle_path -hold -from [get_pins control_top/o_usr_rst_reg/C] 5 -set_multicycle_path -setup -from [get_pins control_top/o_usr_rst_reg/C] 5 + + + +set_false_path -from [get_pins {core_rst1_sync/dat_reg[0][0]/C}] -to [get_pins {core_rst1_sync/dat_reg[2][0]_srl2/D}] +set_false_path -from [get_pins {if_rst_sync/dat_reg[0][0]/C}] -to [get_pins {if_rst_sync/dat_reg[2][0]_srl2/D}] +