├── .gitignore ├── LICENSE.md ├── README.md ├── core_src ├── crc.sv ├── crc.svh └── crc_byteEn.sv ├── correctness_verification ├── .gitignore ├── Makefile ├── board_clk_source.xdc ├── config.mk ├── hdl │ ├── config.svh │ ├── crc_byteEn_tb.sv │ ├── crc_byteEn_top.sv │ ├── crc_tb.sv │ ├── crc_top.sv │ ├── xoshiro128ss_simple.sv │ └── xoshiro32pp_simple.sv ├── outputs │ ├── .gitignore │ └── .keep ├── scripts │ ├── run_impl.tcl │ └── run_sim.tcl └── workdir │ ├── .gitignore │ └── .keep └── performance_evaluation ├── .gitignore ├── Makefile ├── config.mk ├── constraints ├── .gitignore ├── crc.xdc └── crc_byteEn.xdc ├── hdl ├── config.svh ├── crc_byteEn_top.sv └── crc_top.sv ├── outputs ├── fmax_results │ ├── .gitignore │ └── logs │ │ ├── .gitignore │ │ └── .keep └── pipe_lvl_results │ ├── .gitignore │ └── logs │ ├── .gitignore │ └── .keep ├── scripts ├── find_fmax_nopipe.tcl └── find_pipe_lvl_500mhz.tcl └── workdir ├── .gitignore └── .keep /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Qianfeng Shen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tbps_CRC 2 | A SytemVerilog implementation of Cyclic Redundancy Check runs at up to Terabits per second. 3 | 4 | ## Core HDL code for CRC calculation 5 | The core code of Tbps CRC is located in the `core_src` directory. There are 3 files in the folder: `crc.sv` contains the SystemVerilog module, which computes the CRC without the byte-enabled feature; `crc_byteEn.sv` contains the byte-enabled version of the SystemVerilog module; `crc.svh` contains SystemVerilog constant functions that run at elaboration (pre-synthesis) time. 6 | 7 | The byte-enabled version differs from the normal version in that the byte-enabled version allows the message length to be any length that is byte-aligned, while the normal version can only produce CRC results for messages whose size is a multiple of the selected input bus width. 8 | 9 | ## Correctness test 10 | The correctness test is under directory `correctness_verification`. There are 4 make options for the correctness test: 11 | 12 | `make sim` and `make sim_byteEn` will generate and run simulations to verify the correctness of the normal version and the byte-enabled version respectively 13 | 14 | `make gen_bitstream` and `make gen_bitstream_byteEn` will generate the bitstreams for the normal version and the byte-enabled version respectively 15 | 16 | One should modify the `board_clk_source.xdc` and `config.mk` for different CRC configurations and different target boards. 17 | 18 | Both simulation and on-board tests generate random messages of a given random size and feed the messages into the CRC module. The simulation compares the results generated by the hardware with the results computed by a software function and reports the mismatch (if any) between the software and hardware results. The on-board test uses a set of hardware random number generators to generate random messages and feed them into the CRC module. The message signal and the CRC result signal are probed by the ILA, allowing the results to be verified in hardware. 19 | 20 | ## Performance test 21 | The performance test is under directory `performance_evaluation`. Same as the correctness test, there are 4 make options for the performance test: 22 | 23 | `make find_fmax` and `make find_fmax_byteEn` find the Fmax for the non-pipelined CRC implementations for an assortment of commonly used CRC polynomials. 24 | 25 | `make find_pipe_lvl_500mhz` and `make find_pipe_lvl_500mhz_byteEn` find the minimum pipeline level implementation that can run at 500 MHz for different CRC polynomials. 26 | 27 | The summarized results can be found under /performance_evaluation/outputs. 28 | 29 | **The default configuration of the test is based on Xilinx's Alveo U250. User should modify the `config.mk` and the files under `constraints` for a different target board.** 30 | 31 | ## References 32 | To cite this work, reference the following paper: 33 | 34 | Q. Clark Shen, J. C. Vega and P. Chow, "Parallel CRC On An FPGA At Terabit Speeds," 2022 International Conference on Field-Programmable Technology (ICFPT), Hong Kong, 2022, pp. 1-6, doi: 10.1109/ICFPT56656.2022.9974233. 35 | -------------------------------------------------------------------------------- /core_src/crc.sv: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2022, Qianfeng (Clark) Shen 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. 7 | * @author Qianfeng (Clark) Shen 8 | * @email qianfeng.shen@gmail.com 9 | * @create date 2022-03-18 13:57:54 10 | * @modify date 2022-03-18 13:57:54 11 | */ 12 | 13 | `timescale 1ns / 1ps 14 | module crc_gen # 15 | ( 16 | parameter int DWIDTH = 512, 17 | parameter int CRC_WIDTH = 16, 18 | parameter int PIPE_LVL = 0, 19 | parameter CRC_POLY = 16'hda5f, 20 | parameter INIT = 16'b0, 21 | parameter XOR_OUT = 16'b0, 22 | parameter bit REFIN = 1'b0, 23 | parameter bit REFOUT = 1'b0 24 | ) 25 | ( 26 | input logic clk, 27 | input logic rst, 28 | input logic [DWIDTH-1:0] din, 29 | input logic dlast, 30 | input logic flitEn, 31 | (* keep = "true" *) output logic [CRC_WIDTH-1:0] crc_out = {CRC_WIDTH{1'b0}}, 32 | (* keep = "true" *) output logic crc_out_vld = 1'b0 33 | ); 34 | `include "crc.svh" 35 | localparam bit [CRC_WIDTH-1:0][CRC_WIDTH+DWIDTH-1:0] UNI_TABLE = gen_unified_table(); 36 | localparam bit [CRC_WIDTH-1:0][CRC_WIDTH-1:0] CRC_TABLE = gen_crc_table(UNI_TABLE); 37 | localparam bit [CRC_WIDTH-1:0][DWIDTH-1:0] DATA_TABLE = gen_data_table(UNI_TABLE); 38 | localparam int DIV_PER_LVL = get_div_per_lvl(); 39 | localparam bit [PIPE_LVL:0][31:0] N_TERMS = get_n_terms(DIV_PER_LVL); 40 | localparam bit [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] BRANCH_ENABLE_TABLE = get_branch_enable_table(DATA_TABLE,DIV_PER_LVL,N_TERMS); 41 | 42 | //input registers 43 | logic [PIPE_LVL:0] dlast_reg = {(PIPE_LVL+1){1'b0}}; 44 | logic [PIPE_LVL:0] flitEn_reg = {(PIPE_LVL+1){1'b0}}; 45 | 46 | //internal wire 47 | logic [CRC_WIDTH-1:0] crc_int; 48 | 49 | //refin-refout convertion 50 | logic [DWIDTH-1:0] din_refin; 51 | logic [CRC_WIDTH-1:0] crc_refout; 52 | 53 | //pipeline logic 54 | logic [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] data_pipe; 55 | logic [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] data_pipe_reg = {(PIPE_LVL+1){{CRC_WIDTH{{((DWIDTH-1)/DIV_PER_LVL+1){1'b0}}}}}}; 56 | 57 | //crc feedback 58 | (* keep = "true" *) logic [CRC_WIDTH-1:0] crc_previous = INIT; 59 | 60 | always_comb begin 61 | //REFIN logic 62 | if (REFIN) begin 63 | din_refin = {<<{din}}; 64 | din_refin = {<<8{din_refin}}; 65 | end 66 | else 67 | din_refin = din; 68 | 69 | //generate the first level 70 | data_pipe = {(PIPE_LVL+1){{CRC_WIDTH{{((DWIDTH-1)/DIV_PER_LVL+1){1'b0}}}}}}; 71 | for (int i = 0; i < CRC_WIDTH; i++) begin 72 | for (int j = 0; j < (DWIDTH-1)/DIV_PER_LVL+1; j++) begin 73 | for (int k = 0; k < DIV_PER_LVL && j*DIV_PER_LVL+k < DWIDTH; k++) begin 74 | if (DATA_TABLE[i][j*DIV_PER_LVL+k]) 75 | data_pipe[0][i][j] = data_pipe[0][i][j] ^ din_refin[j*DIV_PER_LVL+k]; 76 | end 77 | end 78 | end 79 | //level 2 -> aggregate data chain into 1 bit per crc bit 80 | for (int i = 1; i <= PIPE_LVL; i++) begin 81 | for (int j = 0; j < CRC_WIDTH; j++) begin 82 | for (int k = 0; k < (N_TERMS[i]-1)/DIV_PER_LVL+1; k++) begin 83 | for (int m = k*DIV_PER_LVL; m < (k+1)*DIV_PER_LVL && m < N_TERMS[i]; m++) begin 84 | if (BRANCH_ENABLE_TABLE[i-1][j][m]) 85 | data_pipe[i][j][k] = data_pipe[i][j][k] ^ data_pipe_reg[i-1][j][m]; 86 | end 87 | end 88 | end 89 | end 90 | //the last level 91 | crc_int = {CRC_WIDTH{1'b0}}; 92 | for (int i = 0; i < CRC_WIDTH; i++) begin 93 | for (int j = 0; j < CRC_WIDTH; j++) begin 94 | if (CRC_TABLE[i][j]) 95 | crc_int[i] = crc_int[i] ^ crc_previous[j]; 96 | end 97 | crc_int[i] = crc_int[i] ^ data_pipe[PIPE_LVL][i][0]; 98 | end 99 | end 100 | 101 | always_ff @(posedge clk) begin 102 | for (int i = 0; i < PIPE_LVL; i++) begin 103 | for (int j = 0; j < CRC_WIDTH; j++) begin 104 | for (int k = 0; k < N_TERMS[i+1]; k++) begin 105 | if (BRANCH_ENABLE_TABLE[i][j][k]) 106 | data_pipe_reg[i][j][k] <= data_pipe[i][j][k]; 107 | end 108 | end 109 | end 110 | end 111 | 112 | //input signal pipelining logic 113 | always_comb begin 114 | dlast_reg[0] = dlast; 115 | flitEn_reg[0] = flitEn; 116 | end 117 | always_ff @(posedge clk) begin 118 | for (int i = 1; i <= PIPE_LVL; i++) begin 119 | dlast_reg[i] <= dlast_reg[i-1]; 120 | flitEn_reg[i] <= flitEn_reg[i-1]; 121 | end 122 | end 123 | 124 | //register intermidate crc result 125 | always_ff @(posedge clk) begin 126 | if (rst) 127 | crc_previous <= INIT; 128 | else if (flitEn_reg[PIPE_LVL] & dlast_reg[PIPE_LVL]) 129 | crc_previous <= INIT; 130 | else if (flitEn_reg[PIPE_LVL]) 131 | crc_previous <= crc_int; 132 | end 133 | 134 | //refout logic 135 | always_comb begin 136 | if (REFOUT) 137 | crc_refout = {<<{crc_int}}; 138 | else 139 | crc_refout = crc_int; 140 | end 141 | 142 | //output the result 143 | always_ff @(posedge clk) begin 144 | if (rst) begin 145 | crc_out <= {CRC_WIDTH{1'b0}}; 146 | crc_out_vld <= 1'b0; 147 | end 148 | else begin 149 | if (flitEn_reg[PIPE_LVL] & dlast_reg[PIPE_LVL]) 150 | crc_out <= crc_refout ^ XOR_OUT; 151 | crc_out_vld <= flitEn_reg[PIPE_LVL] & dlast_reg[PIPE_LVL]; 152 | end 153 | end 154 | endmodule 155 | -------------------------------------------------------------------------------- /core_src/crc.svh: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2022, Qianfeng (Clark) Shen 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. 7 | * @author Qianfeng (Clark) Shen 8 | * @email qianfeng.shen@gmail.com 9 | * @create date 2022-03-18 13:57:54 10 | * @modify date 2022-03-18 13:57:54 11 | */ 12 | 13 | function bit [CRC_WIDTH-1:0][DWIDTH+CRC_WIDTH-1:0] gen_unified_table(); 14 | static bit [CRC_WIDTH-1:0][DWIDTH+CRC_WIDTH-1:0] table_old = {CRC_WIDTH{{(DWIDTH+CRC_WIDTH){1'b0}}}}; 15 | static bit [CRC_WIDTH-1:0][DWIDTH+CRC_WIDTH-1:0] unified_table = {CRC_WIDTH{{(DWIDTH+CRC_WIDTH){1'b0}}}}; 16 | for (int i = 0; i < CRC_WIDTH; i++) 17 | table_old[i][i] = 1'b1; 18 | for (int i = 0; i < DWIDTH; i++) begin 19 | /* - crc_out[0] = crc_in[CRC_WIDTH-1] ^ din[DWIDTH-1-i]; */ 20 | unified_table[0] = table_old[CRC_WIDTH-1]; 21 | unified_table[0][CRC_WIDTH+DWIDTH-1-i] = ~unified_table[0][CRC_WIDTH+DWIDTH-1-i]; 22 | ///////////////////////////////////////////////////////////// 23 | for (int j = 1; j < CRC_WIDTH; j++) begin 24 | if (CRC_POLY[j]) 25 | unified_table[j] = table_old[j-1] ^ unified_table[0]; 26 | else 27 | unified_table[j] = table_old[j-1]; 28 | end 29 | table_old = unified_table; 30 | end 31 | return unified_table; 32 | endfunction 33 | 34 | function bit [CRC_WIDTH-1:0][CRC_WIDTH-1:0] gen_crc_table( 35 | input bit [CRC_WIDTH-1:0][DWIDTH+CRC_WIDTH-1:0] unified_table 36 | ); 37 | static bit [CRC_WIDTH-1:0][CRC_WIDTH-1:0] crc_table; 38 | for (int i = 0; i < CRC_WIDTH; i++) begin 39 | for (int j = 0; j < CRC_WIDTH; j++) 40 | crc_table[i][j] = unified_table[i][j]; 41 | end 42 | return crc_table; 43 | endfunction 44 | 45 | function bit [CRC_WIDTH-1:0][DWIDTH-1:0] gen_data_table( 46 | input bit [CRC_WIDTH-1:0][DWIDTH+CRC_WIDTH-1:0] unified_table 47 | ); 48 | static bit [CRC_WIDTH-1:0][DWIDTH-1:0] data_table; 49 | for (int i = 0; i < CRC_WIDTH; i++) begin 50 | for (int j = 0; j < DWIDTH; j++) 51 | data_table[i][j] = unified_table[i][j+CRC_WIDTH]; 52 | end 53 | return data_table; 54 | endfunction 55 | 56 | function int get_div_per_lvl(); 57 | int divider_per_lvl; 58 | int n_last_lvl; 59 | int j; 60 | if (PIPE_LVL == 0) 61 | divider_per_lvl = DWIDTH; 62 | else begin 63 | j = 0; 64 | n_last_lvl = 1; 65 | while (1) begin 66 | while (1) begin 67 | if (n_last_lvl*(j**PIPE_LVL) >= DWIDTH) 68 | break; 69 | else 70 | j++; 71 | end 72 | if (n_last_lvl+CRC_WIDTH >= j) 73 | break; 74 | else begin 75 | n_last_lvl++; 76 | j = 0; 77 | end 78 | end 79 | divider_per_lvl = j; 80 | end 81 | return divider_per_lvl; 82 | endfunction 83 | 84 | function bit [PIPE_LVL:0][31:0] get_n_terms( 85 | input int divider_per_lvl 86 | ); 87 | static bit [PIPE_LVL:0][31:0] n_terms; 88 | n_terms[0] = DWIDTH; 89 | for (int i = 1; i <= PIPE_LVL; i++) begin 90 | n_terms[i] = (n_terms[i-1]-1)/divider_per_lvl+1; 91 | end 92 | return n_terms; 93 | endfunction 94 | 95 | function bit [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] get_branch_enable_table( 96 | input [CRC_WIDTH-1:0][DWIDTH-1:0] data_table, 97 | input int divider_per_lvl, 98 | input bit [PIPE_LVL:0][31:0] n_terms 99 | ); 100 | static bit [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] branch_enable_table = {(PIPE_LVL+1){{CRC_WIDTH{{((DWIDTH-1)/DIV_PER_LVL+1){1'b0}}}}}}; 101 | int n_terms_int; 102 | if (PIPE_LVL != 0) begin 103 | n_terms_int = int'(n_terms[0]); 104 | for (int i = 0; i < CRC_WIDTH; i++) begin 105 | for (int j = 0; j <= (n_terms_int-1)/divider_per_lvl; j++) begin 106 | for (int k = j*divider_per_lvl; k < (j+1)*divider_per_lvl && k < n_terms_int; k++) begin 107 | if (data_table[i][k]) begin 108 | branch_enable_table[0][i][j] = 1'b1; 109 | break; 110 | end 111 | end 112 | end 113 | end 114 | for (int i = 1; i < PIPE_LVL; i++) begin 115 | n_terms_int = int'(n_terms[i]); 116 | for (int j = 0; j < CRC_WIDTH; j++) begin 117 | for (int k = 0; k <= (n_terms_int-1)/divider_per_lvl; k++) begin 118 | for (int m = k*divider_per_lvl; m < (k+1)*divider_per_lvl && m < n_terms_int; m++) begin 119 | if (branch_enable_table[i-1][j][m]) begin 120 | branch_enable_table[i][j][k] = 1'b1; 121 | break; 122 | end 123 | end 124 | end 125 | end 126 | end 127 | end 128 | return branch_enable_table; 129 | endfunction 130 | 131 | function bit [$clog2(DWIDTH/8)-1:0][CRC_WIDTH-1:0][CRC_WIDTH-1:0] get_revert_table(); 132 | static bit [CRC_WIDTH-1:0][CRC_WIDTH-1:0] table_old; 133 | static bit [$clog2(DWIDTH/8)-1:0][CRC_WIDTH-1:0][CRC_WIDTH-1:0] revert_table = {$clog2(DWIDTH/8){{CRC_WIDTH{{CRC_WIDTH{1'b0}}}}}}; 134 | for (int i = 0; i < $clog2(DWIDTH/8); i++) begin 135 | table_old = {CRC_WIDTH{{CRC_WIDTH{1'b0}}}}; 136 | for (int j = 0; j < CRC_WIDTH; j++) begin 137 | table_old[j][j] = 1'b1; 138 | end 139 | for (int j = 0; j < 8*2**($clog2(DWIDTH/8)-1-i); j++) begin 140 | revert_table[i][CRC_WIDTH-1] = table_old[0]; 141 | for (int k = 0; k < CRC_WIDTH-1; k++) begin 142 | if (CRC_POLY[k+1]) 143 | revert_table[i][k] = table_old[k+1] ^ table_old[0]; 144 | else 145 | revert_table[i][k] = table_old[k+1]; 146 | end 147 | table_old = revert_table[i]; 148 | end 149 | end 150 | return revert_table; 151 | endfunction 152 | -------------------------------------------------------------------------------- /core_src/crc_byteEn.sv: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2022, Qianfeng (Clark) Shen 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. 7 | * @author Qianfeng (Clark) Shen 8 | * @email qianfeng.shen@gmail.com 9 | * @create date 2022-03-18 13:57:54 10 | * @modify date 2022-03-18 13:57:54 11 | */ 12 | 13 | `timescale 1ns / 1ps 14 | module crc_gen_byteEn # 15 | ( 16 | parameter int DWIDTH = 512, 17 | parameter int CRC_WIDTH = 16, 18 | parameter int PIPE_LVL = 0, 19 | parameter CRC_POLY = 16'hda5f, 20 | parameter INIT = 16'b0, 21 | parameter XOR_OUT = 16'b0, 22 | parameter bit REFIN = 1'b0, 23 | parameter bit REFOUT = 1'b0 24 | ) 25 | ( 26 | input logic clk, 27 | input logic rst, 28 | input logic [DWIDTH-1:0] din, 29 | input logic [DWIDTH/8-1:0] byteEn, 30 | input logic dlast, 31 | input logic flitEn, 32 | (* keep = "true" *) output logic [CRC_WIDTH-1:0] crc_out = {CRC_WIDTH{1'b0}}, 33 | (* keep = "true" *) output logic crc_out_vld = 1'b0 34 | ); 35 | generate 36 | if (DWIDTH % 8 != 0) $fatal(0,"DWIDTH has to be a multiple of 8"); 37 | if (DWIDTH <= 8) $fatal(0,"DWIDTH is not larger than 1 byte. You don't really need this byte enable version"); 38 | endgenerate 39 | `include "crc.svh" 40 | localparam bit [CRC_WIDTH-1:0][CRC_WIDTH+DWIDTH-1:0] UNI_TABLE = gen_unified_table(); 41 | localparam bit [CRC_WIDTH-1:0][CRC_WIDTH-1:0] CRC_TABLE = gen_crc_table(UNI_TABLE); 42 | localparam bit [CRC_WIDTH-1:0][DWIDTH-1:0] DATA_TABLE = gen_data_table(UNI_TABLE); 43 | localparam int DIV_PER_LVL = get_div_per_lvl(); 44 | localparam bit [PIPE_LVL:0][31:0] N_TERMS = get_n_terms(DIV_PER_LVL); 45 | localparam bit [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] BRANCH_ENABLE_TABLE = get_branch_enable_table(DATA_TABLE,DIV_PER_LVL,N_TERMS); 46 | localparam bit [$clog2(DWIDTH/8)-1:0][CRC_WIDTH-1:0][CRC_WIDTH-1:0] REVERT_TABLE = get_revert_table(); 47 | 48 | //input registers 49 | logic [$clog2(DWIDTH/8)-1:0] crc_rev_en_pipe_wire; 50 | logic [PIPE_LVL:0][$clog2(DWIDTH/8)-1:0] crc_rev_en_pipe_reg = {(PIPE_LVL+1){{$clog2(DWIDTH/8){1'b0}}}}; 51 | logic [PIPE_LVL:0] dlast_reg = {(PIPE_LVL+1){1'b0}}; 52 | logic [PIPE_LVL:0] flitEn_reg = {(PIPE_LVL+1){1'b0}}; 53 | logic [DWIDTH-1:0] din_reg = {DWIDTH{1'b0}}; 54 | 55 | //input mask 56 | logic [DWIDTH-1:0] mask_in_byte; 57 | 58 | //internal wire 59 | logic [CRC_WIDTH-1:0] crc_int; 60 | 61 | //refin-refout convertion 62 | logic [DWIDTH-1:0] din_refin; 63 | logic [CRC_WIDTH-1:0] crc_refout; 64 | 65 | //pipeline logic 66 | logic [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] data_pipe; 67 | logic [PIPE_LVL:0][CRC_WIDTH-1:0][(DWIDTH-1)/DIV_PER_LVL:0] data_pipe_reg = {(PIPE_LVL+1){{CRC_WIDTH{{((DWIDTH-1)/DIV_PER_LVL+1){1'b0}}}}}}; 68 | 69 | //crc feedback 70 | (* keep = "true" *) logic [CRC_WIDTH-1:0] crc_previous = INIT; 71 | 72 | //crc revert 73 | logic [$clog2(DWIDTH/8)-1:0][CRC_WIDTH-1:0] crc_rev_wire = {$clog2(DWIDTH/8){{CRC_WIDTH{1'b0}}}}; 74 | logic [$clog2(DWIDTH/8)-1:0][CRC_WIDTH-1:0] crc_rev_reg = {$clog2(DWIDTH/8){{CRC_WIDTH{1'b0}}}}; 75 | logic [$clog2(DWIDTH/8)-1:0][$clog2(DWIDTH/8)-1:0] crc_rev_en_reg = {$clog2(DWIDTH/8){{$clog2(DWIDTH/8){1'b0}}}}; 76 | logic [$clog2(DWIDTH/8)-1:0] crc_vld_rev_reg = {$clog2(DWIDTH/8){1'b0}}; 77 | 78 | //input regs 79 | always_comb begin 80 | for (int i = 0; i < DWIDTH/8; i++) 81 | mask_in_byte[(i+1)*8-1-:8] = byteEn[i] ? 8'hff : 8'h00; 82 | end 83 | 84 | always_ff @(posedge clk) begin 85 | if (rst) 86 | din_reg <= {DWIDTH{1'b0}}; 87 | else if (flitEn) begin 88 | din_reg <= din & mask_in_byte; 89 | end 90 | end 91 | 92 | always_comb begin 93 | //REFIN logic 94 | if (REFIN) begin 95 | din_refin = {<<{din_reg}}; 96 | din_refin = {<<8{din_refin}}; 97 | end 98 | else 99 | din_refin = din_reg; 100 | 101 | //generate the first level 102 | data_pipe = {(PIPE_LVL+1){{CRC_WIDTH{{((DWIDTH-1)/DIV_PER_LVL+1){1'b0}}}}}}; 103 | for (int i = 0; i < CRC_WIDTH; i++) begin 104 | for (int j = 0; j < (DWIDTH-1)/DIV_PER_LVL+1; j++) begin 105 | for (int k = 0; k < DIV_PER_LVL && j*DIV_PER_LVL+k < DWIDTH; k++) begin 106 | if (DATA_TABLE[i][j*DIV_PER_LVL+k]) 107 | data_pipe[0][i][j] = data_pipe[0][i][j] ^ din_refin[j*DIV_PER_LVL+k]; 108 | end 109 | end 110 | end 111 | //level 2 -> aggregate data chain into 1 bit per crc bit 112 | for (int i = 1; i <= PIPE_LVL; i++) begin 113 | for (int j = 0; j < CRC_WIDTH; j++) begin 114 | for (int k = 0; k < (N_TERMS[i]-1)/DIV_PER_LVL+1; k++) begin 115 | for (int m = k*DIV_PER_LVL; m < (k+1)*DIV_PER_LVL && m < N_TERMS[i]; m++) begin 116 | if (BRANCH_ENABLE_TABLE[i-1][j][m]) 117 | data_pipe[i][j][k] = data_pipe[i][j][k] ^ data_pipe_reg[i-1][j][m]; 118 | end 119 | end 120 | end 121 | end 122 | //the last level 123 | crc_int = {CRC_WIDTH{1'b0}}; 124 | for (int i = 0; i < CRC_WIDTH; i++) begin 125 | for (int j = 0; j < CRC_WIDTH; j++) begin 126 | if (CRC_TABLE[i][j]) 127 | crc_int[i] = crc_int[i] ^ crc_previous[j]; 128 | end 129 | crc_int[i] = crc_int[i] ^ data_pipe[PIPE_LVL][i][0]; 130 | end 131 | end 132 | 133 | always_ff @(posedge clk) begin 134 | for (int i = 0; i < PIPE_LVL; i++) begin 135 | for (int j = 0; j < CRC_WIDTH; j++) begin 136 | for (int k = 0; k < N_TERMS[i+1]; k++) begin 137 | if (BRANCH_ENABLE_TABLE[i][j][k]) 138 | data_pipe_reg[i][j][k] <= data_pipe[i][j][k]; 139 | end 140 | end 141 | end 142 | end 143 | //input signal pipelining logic 144 | always_comb begin 145 | crc_rev_en_pipe_wire = {$clog2(DWIDTH/8){1'b0}}; 146 | 147 | for (int i = 0; i < DWIDTH/8; i++) begin 148 | crc_rev_en_pipe_wire = crc_rev_en_pipe_wire + {~byteEn[i]}; 149 | end 150 | end 151 | always_ff @(posedge clk) begin 152 | crc_rev_en_pipe_reg[0] <= {<<{crc_rev_en_pipe_wire}}; 153 | dlast_reg[0] <= dlast; 154 | flitEn_reg[0] <= flitEn; 155 | for (int i = 1; i <= PIPE_LVL; i++) begin 156 | crc_rev_en_pipe_reg[i] <= crc_rev_en_pipe_reg[i-1]; 157 | dlast_reg[i] <= dlast_reg[i-1]; 158 | flitEn_reg[i] <= flitEn_reg[i-1]; 159 | end 160 | end 161 | 162 | //register intermidate crc result 163 | always_ff @(posedge clk) begin 164 | if (rst) 165 | crc_previous <= INIT; 166 | else if (flitEn_reg[PIPE_LVL] & dlast_reg[PIPE_LVL]) 167 | crc_previous <= INIT; 168 | else if (flitEn_reg[PIPE_LVL]) 169 | crc_previous <= crc_int; 170 | end 171 | 172 | //do crc revert to cancel the padding zeros 173 | always_comb begin 174 | crc_rev_wire = {($clog2(DWIDTH/8)){{CRC_WIDTH{1'b0}}}}; 175 | for (int i = 0; i < $clog2(DWIDTH/8); i++) begin 176 | for (int j = 0; j < CRC_WIDTH; j++) begin 177 | for (int k = 0; k < CRC_WIDTH; k++) begin 178 | if (REVERT_TABLE[i][j][k]) 179 | crc_rev_wire[i][j] = crc_rev_wire[i][j] ^ crc_rev_reg[i][k]; 180 | end 181 | end 182 | end 183 | end 184 | always_ff @(posedge clk) begin 185 | crc_rev_reg[0] <= crc_int; 186 | crc_vld_rev_reg[0] <= flitEn_reg[PIPE_LVL] & dlast_reg[PIPE_LVL]; 187 | crc_rev_en_reg[0] <= crc_rev_en_pipe_reg[PIPE_LVL]; 188 | for (int i = 1; i < $clog2(DWIDTH/8); i++) begin 189 | crc_rev_en_reg[i] <= crc_rev_en_reg[i-1]; 190 | if (crc_rev_en_reg[i-1][i-1]) 191 | crc_rev_reg[i] <= crc_rev_wire[i-1]; 192 | else 193 | crc_rev_reg[i] <= crc_rev_reg[i-1]; 194 | end 195 | for (int i = 1; i < $clog2(DWIDTH/8); i++) begin 196 | crc_vld_rev_reg[i] <= crc_vld_rev_reg[i-1]; 197 | end 198 | end 199 | 200 | //refout logic 201 | always_comb begin 202 | if (crc_rev_en_reg[$clog2(DWIDTH/8)-1][$clog2(DWIDTH/8)-1]) 203 | crc_refout = crc_rev_wire[$clog2(DWIDTH/8)-1]; 204 | else 205 | crc_refout = crc_rev_reg[$clog2(DWIDTH/8)-1]; 206 | 207 | if (REFOUT) 208 | crc_refout = {<<{crc_refout}}; 209 | end 210 | 211 | //output the result 212 | always_ff @(posedge clk) begin 213 | if (rst) begin 214 | crc_out <= {CRC_WIDTH{1'b0}}; 215 | crc_out_vld <= 1'b0; 216 | end 217 | else begin 218 | if (crc_vld_rev_reg[$clog2(DWIDTH/8)-1]) 219 | crc_out <= crc_refout ^ XOR_OUT; 220 | crc_out_vld <= crc_vld_rev_reg[$clog2(DWIDTH/8)-1]; 221 | end 222 | end 223 | endmodule 224 | -------------------------------------------------------------------------------- /correctness_verification/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /correctness_verification/Makefile: -------------------------------------------------------------------------------- 1 | include config.mk 2 | sim: hdl/crc_tb.sv hdl/crc_top.sv hdl/config.svh ../core_src/crc.sv ../core_src/crc.svh scripts/run_sim.tcl 3 | @rm -rf workdir/tbps_crc_simulation 4 | @vivado -mode tcl -nojournal -nolog -notrace -source scripts/run_sim.tcl -tclargs $(PART_NUM) $(DWIDTH) $(CRC_WIDTH) $(PIPE_LVL) $(CRC_POLY) $(INIT) $(XOR_OUT) $(REFIN) $(REFOUT) 0 $(N_MESSAGE) $(MESSAGE_LEN_MIN) $(MESSAGE_LEN_MAX) $(flitEn_ratio) 5 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk ! -name board_clk_source.xdc -type f | xargs -n 1 rm -rf 6 | @find . -mindepth 1 -maxdepth 1 ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 7 | 8 | sim_byteEn: hdl/crc_byteEn_tb.sv hdl/crc_byteEn_top.sv hdl/config.svh ../core_src/crc_byteEn.sv ../core_src/crc.svh scripts/run_sim.tcl 9 | @rm -rf workdir/tbps_crc_byteEn_simulation 10 | @vivado -mode tcl -nojournal -nolog -notrace -source scripts/run_sim.tcl -tclargs $(PART_NUM) $(DWIDTH) $(CRC_WIDTH) $(PIPE_LVL) $(CRC_POLY) $(INIT) $(XOR_OUT) $(REFIN) $(REFOUT) 1 $(N_MESSAGE) $(MESSAGE_LEN_MIN) $(MESSAGE_LEN_MAX) $(flitEn_ratio) 11 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk ! -name board_clk_source.xdc -type f | xargs -n 1 rm -rf 12 | @find . -mindepth 1 -maxdepth 1 ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 13 | 14 | gen_bitstream: hdl/crc_top.sv hdl/config.svh ../core_src/crc.sv ../core_src/crc.svh scripts/run_impl.tcl 15 | @rm -rf workdir/tbps_crc_implementation 16 | @vivado -mode batch -nojournal -nolog -notrace -source scripts/run_impl.tcl -tclargs $(PART_NUM) $(DWIDTH) $(CRC_WIDTH) $(PIPE_LVL) $(CRC_POLY) $(INIT) $(XOR_OUT) $(REFIN) $(REFOUT) 0 $(PKT_LIMIT) $(BYTE_BITS) 17 | @cp workdir/tbps_crc_implementation/tbps_crc_implementation.runs/impl_1/crc_top.bit outputs/ 18 | @cp workdir/tbps_crc_implementation/tbps_crc_implementation.runs/impl_1/crc_top.ltx outputs/ 19 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk ! -name board_clk_source.xdc -type f | xargs -n 1 rm -rf 20 | @find . -mindepth 1 -maxdepth 1 ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 21 | 22 | gen_bitstream_byteEn: hdl/crc_byteEn_top.sv hdl/config.svh ../core_src/crc_byteEn.sv ../core_src/crc.svh scripts/run_impl.tcl 23 | @rm -rf workdir/tbps_crc_byteEn_implementation 24 | @vivado -mode batch -nojournal -nolog -notrace -source scripts/run_impl.tcl -tclargs $(PART_NUM) $(DWIDTH) $(CRC_WIDTH) $(PIPE_LVL) $(CRC_POLY) $(INIT) $(XOR_OUT) $(REFIN) $(REFOUT) 1 $(PKT_LIMIT) $(BYTE_BITS) 25 | @cp workdir/tbps_crc_byteEn_implementation/tbps_crc_byteEn_implementation.runs/impl_1/crc_byteEn_top.bit outputs/ 26 | @cp workdir/tbps_crc_byteEn_implementation/tbps_crc_byteEn_implementation.runs/impl_1/crc_byteEn_top.ltx outputs/ 27 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk ! -name board_clk_source.xdc -type f | xargs -n 1 rm -rf 28 | @find . -mindepth 1 -maxdepth 1 ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 29 | 30 | clean: 31 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk ! -name board_clk_source.xdc -type f | xargs -n 1 rm -rf 32 | @find . -mindepth 1 -maxdepth 1 ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 33 | 34 | clean_all: 35 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk ! -name board_clk_source.xdc -type f | xargs -n 1 rm -rf 36 | @find . -mindepth 1 -maxdepth 1 ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 37 | @rm -rf workdir/* 38 | @rm -f outputs/* 39 | -------------------------------------------------------------------------------- /correctness_verification/board_clk_source.xdc: -------------------------------------------------------------------------------- 1 | #modify the period, IOSTANDARD and PACKAGE_PIN to match with your board 2 | create_clock -period 3.333 [get_ports clk_p] 3 | set_property IOSTANDARD LVDS [get_ports clk_p] 4 | set_property IOSTANDARD LVDS [get_ports clk_n] 5 | set_property PACKAGE_PIN AW20 [get_ports clk_p] 6 | set_property PACKAGE_PIN AW19 [get_ports clk_n] 7 | -------------------------------------------------------------------------------- /correctness_verification/config.mk: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #modify this config file for different configurations 3 | #board setting 4 | PART_NUM="xcu250-figd2104-2L-e" #the part number of the target fpga 5 | 6 | # general setup 7 | DWIDTH="512" #data width 8 | CRC_WIDTH="32" #crc polynomial width 9 | PIPE_LVL="0" #pipeline level for crc calculation, deeper pipeline increases overall latency and area, but results in better fmax/throughput 10 | CRC_POLY="32'h04C11DB7" #crc polynomial 11 | INIT="32'hffffffff" #init hex 12 | XOR_OUT="32'hffffffff" #xor out hex 13 | REFIN="1" #reflect in, 1 for yes, 0 for no 14 | REFOUT="1" #reflect out, 1 for yes, 0 for no 15 | 16 | # simulation 17 | N_MESSAGE="10" #number of messages to send in simulation 18 | MESSAGE_LEN_MIN="1" #min message size (in byte) in simulation 19 | MESSAGE_LEN_MAX="1500" #max message size (in byte) in simulation 20 | flitEn_ratio="0.8" #ratio of the valid flits during simulation, 0.8 means 80% of the flits are valid, 20% of bubble (invalid) flits for each message 21 | 22 | # hardware implementation 23 | PKT_LIMIT="10" #number of messages to send in hardware test 24 | BYTE_BITS="11" #max message size (in byte) in hardware test, here max message size is 2^11=2048 bytes 25 | -------------------------------------------------------------------------------- /correctness_verification/hdl/config.svh: -------------------------------------------------------------------------------- 1 | /*- general setup -*/ 2 | `ifndef DWIDTH 3 | `define DWIDTH 512 4 | `endif 5 | `ifndef CRC_WIDTH 6 | `define CRC_WIDTH 32 7 | `endif 8 | `ifndef PIPE_LVL 9 | `define PIPE_LVL 0 10 | `endif 11 | `ifndef CRC_POLY 12 | `define CRC_POLY 32'h04C11DB7 13 | `endif 14 | `ifndef INIT 15 | `define INIT 32'hffffffff 16 | `endif 17 | `ifndef XOR_OUT 18 | `define XOR_OUT 32'hffffffff 19 | `endif 20 | `ifndef REFIN 21 | `define REFIN 1'b1 22 | `endif 23 | `ifndef REFOUT 24 | `define REFOUT 1'b1 25 | `endif 26 | 27 | /*- simulation -*/ 28 | `ifndef N_MESSAGE 29 | `define N_MESSAGE 100 30 | `endif 31 | `ifndef MESSAGE_LEN_MIN 32 | `define MESSAGE_LEN_MIN 1 33 | `endif 34 | `ifndef MESSAGE_LEN_MAX 35 | `define MESSAGE_LEN_MAX 1500 36 | `endif 37 | `ifndef flitEn_ratio 38 | `define flitEn_ratio 0.8 //80% of the flits are valid 39 | `endif 40 | 41 | /*- hardware implementation -*/ 42 | `ifndef PKT_LIMIT 43 | `define PKT_LIMIT 10 44 | `endif 45 | `ifndef BYTE_BITS 46 | `define BYTE_BITS 11 //Max message size = 2^11 bytes 47 | `endif -------------------------------------------------------------------------------- /correctness_verification/hdl/crc_byteEn_tb.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | `ifndef SIM 4 | `define SIM 5 | `endif 6 | 7 | `include "config.svh" 8 | 9 | module crc_byteEn_tb(); 10 | parameter int N_MESSAGE = `N_MESSAGE; 11 | parameter int MESSAGE_LEN_MIN = `MESSAGE_LEN_MIN; 12 | parameter int MESSAGE_LEN_MAX = `MESSAGE_LEN_MAX; 13 | parameter real flitEn_ratio = `flitEn_ratio; 14 | 15 | parameter int DWIDTH = `DWIDTH; 16 | parameter int CRC_WIDTH = `CRC_WIDTH; 17 | parameter int PIPE_LVL = `PIPE_LVL; 18 | parameter CRC_POLY = `CRC_POLY; 19 | parameter INIT = `INIT; 20 | parameter XOR_OUT = `XOR_OUT; 21 | parameter bit REFIN = `REFIN; 22 | parameter bit REFOUT = `REFOUT; 23 | 24 | function string hex_str(input bit [CRC_WIDTH-1:0] hex); 25 | automatic bit [((CRC_WIDTH-1)/8)*8+7:0] new_hex = {(((CRC_WIDTH-1)/8+1)*8){1'b0}}; 26 | automatic string hex_string = ""; 27 | automatic string byte_string = ""; 28 | new_hex[CRC_WIDTH-1:0] = hex; 29 | for (int i = 0; i <= (CRC_WIDTH-1)/8; i++) begin 30 | $sformat(byte_string, "%2X", new_hex[((CRC_WIDTH-1)/8)*8+7-i*8-:8]); 31 | hex_string = {hex_string,byte_string}; 32 | end 33 | return hex_string; 34 | endfunction 35 | 36 | bit [8191:0][7:0] message; //here the message is set to be at most 8192 bytes, change it if it's too small for you 37 | int unsigned message_size; 38 | 39 | logic clk; 40 | logic rst; 41 | logic [DWIDTH-1:0] din; 42 | logic [DWIDTH/8-1:0] byteEn; 43 | logic dlast; 44 | logic flitEn; 45 | logic [CRC_WIDTH-1:0] crc_out; 46 | logic crc_out_vld; 47 | 48 | crc_byteEn_top #( 49 | .DWIDTH (DWIDTH ), 50 | .CRC_WIDTH (CRC_WIDTH ), 51 | .PIPE_LVL (PIPE_LVL ), 52 | .CRC_POLY (CRC_POLY ), 53 | .INIT (INIT ), 54 | .XOR_OUT (XOR_OUT ), 55 | .REFIN (REFIN ), 56 | .REFOUT (REFOUT ) 57 | ) u_crc_byteEn_top(.*); 58 | 59 | bit [CRC_WIDTH-1:0] crc_sw_out; 60 | bit [CRC_WIDTH+7:0] crc_sw_tmp; 61 | bit [7:0] crc_byte_tmp; 62 | 63 | bit [N_MESSAGE-1:0][CRC_WIDTH-1:0] crc_sw_out_fifo; 64 | 65 | int sim_exit = 0; 66 | 67 | initial begin 68 | //information 69 | $display("Configuration:"); 70 | $display(" CRC polynomial: %0d'h%s", CRC_WIDTH, hex_str(CRC_POLY)); 71 | $display(" Bus Width: %0d", DWIDTH); 72 | $display(" INIT: %0d'h%s", CRC_WIDTH, hex_str(INIT)); 73 | $display(" XOR OUT: %0d'h%s", CRC_WIDTH, hex_str(XOR_OUT)); 74 | if (REFIN) 75 | $display(" Reflect IN: True"); 76 | else 77 | $display(" Reflect IN: False"); 78 | if (REFOUT) 79 | $display(" Reflect OUT: True"); 80 | else 81 | $display(" Reflect OUT: False"); 82 | $display("Run test with %0d messages", N_MESSAGE); 83 | //reset the hardware 84 | din <= {DWIDTH{1'b0}}; 85 | byteEn <= {DWIDTH/8{1'b0}}; 86 | dlast <= 1'b0; 87 | flitEn <= 1'b0; 88 | rst <= 1'b1; 89 | repeat(20) @(posedge clk); 90 | rst <= 1'b0; 91 | repeat(10) @(posedge clk); 92 | //initialize the variables 93 | message_size = $urandom(111); // Initialize the generator 94 | for (int i = 0; i < N_MESSAGE; i++) begin 95 | if (sim_exit) 96 | break; 97 | message_size = $urandom_range(MESSAGE_LEN_MIN,MESSAGE_LEN_MAX); 98 | $display("The message #%0d is %0d bytes:", i, message_size); 99 | //generate the message 100 | for (int j = 0; j < message_size; j++) begin 101 | message[j] = $urandom & 255; 102 | $write("%02X",message[j]); 103 | if (j % 32 == 31) 104 | $write("\n"); 105 | end 106 | $write("\n"); 107 | //calculate the crc in software 108 | //assign INIT to crcSoFar 109 | crc_sw_tmp = {INIT,8'b0}; 110 | for (int j = 0; j < message_size; j++) begin 111 | if (REFIN) 112 | crc_byte_tmp = {<<{message[j]}}; 113 | else 114 | crc_byte_tmp = message[j]; 115 | //XOR crcSoFar with the message byte 116 | crc_sw_tmp[CRC_WIDTH+7-:8] = crc_sw_tmp[CRC_WIDTH+7-:8] ^ crc_byte_tmp; 117 | //Do 1-bit CRC algorithm 118 | for (int k = CRC_WIDTH+7; k >= CRC_WIDTH; k--) begin 119 | if (crc_sw_tmp[k]) 120 | crc_sw_tmp[k-1-:CRC_WIDTH] = crc_sw_tmp[k-1-:CRC_WIDTH] ^ CRC_POLY; 121 | end 122 | //shift crc_out for another iteration 123 | crc_sw_tmp = {crc_sw_tmp[CRC_WIDTH-1:0],8'b0}; 124 | end 125 | crc_sw_out = crc_sw_tmp[CRC_WIDTH+7-:CRC_WIDTH]; 126 | if (REFOUT) 127 | crc_sw_out = {<<{crc_sw_out}}; 128 | crc_sw_out = crc_sw_out ^ XOR_OUT; 129 | crc_sw_out_fifo[i] = crc_sw_out; 130 | //calculate the crc in hardware 131 | @(posedge clk); 132 | for (int j = 0; j < (message_size*8-1)/DWIDTH+1; ) begin 133 | if (real'($urandom_range(1,100))/100.0 <= flitEn_ratio) begin 134 | for (int k = 0; k < DWIDTH/8; k++) begin 135 | din[DWIDTH-1-k*8-:8] <= message[j*DWIDTH/8+k]; 136 | byteEn[DWIDTH/8-1-k] <= (j*DWIDTH/8 + k) < message_size; 137 | end 138 | dlast <= (j+1)*DWIDTH/8 >= message_size; 139 | flitEn <= 1'b1; 140 | j++; 141 | end 142 | else 143 | flitEn <= 1'b0; 144 | @(posedge clk); 145 | end 146 | din <= {DWIDTH{1'b0}}; 147 | byteEn <= {DWIDTH/8{1'b0}}; 148 | dlast <= 1'b0; 149 | flitEn <= 1'b0; 150 | end 151 | end 152 | 153 | initial begin 154 | sim_exit = 0; 155 | for (int i = 0; i < N_MESSAGE; ) begin 156 | if (crc_out_vld) begin 157 | if (crc_out != crc_sw_out_fifo[i]) begin 158 | sim_exit = 1; 159 | for (int j = 0; j < i; j++) 160 | $display("Message #%0d: SW CRC result = %0d'h%s, HW CRC result = %0d'h%s, results matched", j, CRC_WIDTH, hex_str(crc_sw_out_fifo[j]), CRC_WIDTH, hex_str(crc_sw_out_fifo[j])); 161 | $display("Message #%0d: SW CRC result = %0d'h%s, HW CRC result = %0d'h%s, results did not match", i, CRC_WIDTH, hex_str(crc_sw_out_fifo[i]), CRC_WIDTH, hex_str(crc_out)); 162 | $display("CRC results did not match for message #%0d, test FAILED", i); 163 | repeat(10) @(posedge clk); 164 | $finish; 165 | end 166 | i++; 167 | end 168 | @(posedge clk); 169 | end 170 | 171 | for (int i = 0; i < N_MESSAGE; i++) begin 172 | $display("Message #%0d: SW CRC result = %0d'h%s, HW CRC result = %0d'h%s, results matched", i, CRC_WIDTH, hex_str(crc_sw_out_fifo[i]), CRC_WIDTH, hex_str(crc_sw_out_fifo[i])); 173 | end 174 | $display("All CRC results matched, test PASSED for %m"); 175 | repeat(50) @(posedge clk); 176 | $finish; 177 | end 178 | 179 | initial begin 180 | clk = 1'b1; 181 | forever begin 182 | #(2ns) clk = ~ clk; 183 | end 184 | end 185 | endmodule 186 | `undef SIM 187 | -------------------------------------------------------------------------------- /correctness_verification/hdl/crc_byteEn_top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | `ifndef SIM 4 | `define GET_STATE_sub1(val) (val+64'h9e3779b97f4a7c15) 5 | `define GET_STATE_sub2(val) ((`GET_STATE_sub1(val) ^ (`GET_STATE_sub1(val) >> 30)) * 64'hbf58476d1ce4e5b9) 6 | `define GET_STATE_sub3(val) ((`GET_STATE_sub2(val) ^ (`GET_STATE_sub2(val) >> 27)) * 64'h94d049bb133111eb) 7 | `define GET_STATE(val) (`GET_STATE_sub3(val) ^ (`GET_STATE_sub3(val) >> 31)) 8 | `define A 64'd19911102 9 | `define B 64'h9e3779b97f4a7c15 10 | `endif 11 | 12 | `include "config.svh" 13 | 14 | module crc_byteEn_top #( 15 | parameter int DWIDTH = `DWIDTH, 16 | parameter int CRC_WIDTH = `CRC_WIDTH, 17 | parameter int PIPE_LVL = `PIPE_LVL, 18 | parameter CRC_POLY = `CRC_POLY, 19 | parameter INIT = `INIT, 20 | parameter XOR_OUT = `XOR_OUT, 21 | parameter bit REFIN = `REFIN, 22 | parameter bit REFOUT = `REFOUT, 23 | parameter bit [7:0] PKT_LIMIT = `PKT_LIMIT, 24 | parameter int BYTE_BITS = `BYTE_BITS 25 | ) ( 26 | `ifdef SIM 27 | input logic clk, 28 | input logic rst, 29 | input logic [DWIDTH-1:0] din, 30 | input logic [DWIDTH/8-1:0] byteEn, 31 | input logic dlast, 32 | input logic flitEn, 33 | output logic [CRC_WIDTH-1:0] crc_out, 34 | output logic crc_out_vld 35 | `else 36 | input logic clk_p, 37 | input logic clk_n 38 | `endif 39 | ); 40 | 41 | `ifndef SIM 42 | logic clk; 43 | logic rst; 44 | logic start; 45 | logic [DWIDTH-1:0] din; 46 | logic [DWIDTH/8-1:0] byteEn = {DWIDTH/8{1'b0}}; 47 | logic dlast = 1'b0; 48 | logic flitEn = 1'b0; 49 | logic [CRC_WIDTH-1:0] crc_out; 50 | logic crc_out_vld; 51 | logic done = 1'b0; 52 | 53 | logic [7:0] pkt_cnt = 8'b0; 54 | logic [BYTE_BITS-1:0] pkt_byte_cnt = {BYTE_BITS{1'b0}}; 55 | logic [((DWIDTH-1)/64+1)*64-1:0] din_tmp; 56 | 57 | logic [15:0] rand16; 58 | logic gen_new_pkt; 59 | 60 | IBUFDS ibufds_inst ( 61 | .I(clk_p), 62 | .IB(clk_n), 63 | .O(clk) 64 | ); 65 | 66 | `endif 67 | 68 | crc_gen_byteEn #( 69 | .DWIDTH (DWIDTH ), 70 | .CRC_WIDTH (CRC_WIDTH ), 71 | .PIPE_LVL (PIPE_LVL ), 72 | .CRC_POLY (CRC_POLY ), 73 | .INIT (INIT ), 74 | .XOR_OUT (XOR_OUT ), 75 | .REFIN (REFIN ), 76 | .REFOUT (REFOUT ) 77 | ) u_crc_gen(.*); 78 | 79 | `ifndef SIM 80 | vio_0 vio_inst ( 81 | .clk(clk), 82 | .probe_out0(start) 83 | ); 84 | 85 | ila_0 ila_inst ( 86 | .clk(clk), 87 | .probe0(start), 88 | .probe1(done), 89 | .probe2(din), 90 | .probe3(byteEn), 91 | .probe4(dlast), 92 | .probe5(flitEn), 93 | .probe6(crc_out), 94 | .probe7(crc_out_vld) 95 | ); 96 | 97 | genvar i; 98 | for (i = 0; i < (DWIDTH-1)/64+1; i++) begin 99 | xoshiro128ss_simple #( 100 | .S0 (`GET_STATE(`A+`B*i*2)), 101 | .S1 (`GET_STATE(`A+`B*(i*2+1))) 102 | ) rand_din ( 103 | .clk (clk ), 104 | .enable (start ), 105 | .rand64 (din_tmp[(i+1)*64-1-:64]) 106 | ); 107 | end 108 | 109 | xoshiro32pp_simple #( 110 | .S0 (16'h1991), 111 | .S1 (16'h1102) 112 | ) rand_pkt_len( 113 | .clk (clk), 114 | .enable (gen_new_pkt), 115 | .rand16 (rand16) 116 | ); 117 | 118 | always_ff @(posedge clk) begin 119 | if (~start) begin 120 | pkt_cnt <= 8'b0; 121 | done <= 1'b0; 122 | end 123 | else if (flitEn&dlast) begin 124 | pkt_cnt <= pkt_cnt + 1'b1; 125 | if (pkt_cnt + 1'b1 == PKT_LIMIT) 126 | done <= 1'b1; 127 | end 128 | end 129 | 130 | always_ff @(posedge clk) begin 131 | if (pkt_byte_cnt > DWIDTH/8) 132 | pkt_byte_cnt <= pkt_byte_cnt - DWIDTH/8; 133 | else if (start & ~done) 134 | pkt_byte_cnt <= rand16[15-:BYTE_BITS]; 135 | else 136 | pkt_byte_cnt <= {BYTE_BITS{1'b0}}; 137 | 138 | flitEn <= pkt_byte_cnt != {BYTE_BITS{1'b0}}; 139 | for (int i = 0; i < DWIDTH/8; i++) 140 | byteEn[DWIDTH/8-1-i] <= pkt_byte_cnt > i; 141 | dlast <= pkt_byte_cnt <= DWIDTH/8 && pkt_byte_cnt != {BYTE_BITS{1'b0}}; 142 | end 143 | 144 | assign rst = ~start; 145 | assign din = din_tmp[DWIDTH-1:0]; 146 | assign gen_new_pkt = start & ~done & (pkt_byte_cnt <= DWIDTH/8); 147 | `endif 148 | endmodule -------------------------------------------------------------------------------- /correctness_verification/hdl/crc_tb.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | `ifndef SIM 4 | `define SIM 5 | `endif 6 | 7 | `include "config.svh" 8 | 9 | module crc_tb(); 10 | parameter int N_MESSAGE = `N_MESSAGE; 11 | parameter int MESSAGE_LEN_MIN = `MESSAGE_LEN_MIN; 12 | parameter int MESSAGE_LEN_MAX = `MESSAGE_LEN_MAX; 13 | parameter real flitEn_ratio = `flitEn_ratio; 14 | 15 | parameter int DWIDTH = `DWIDTH; 16 | parameter int CRC_WIDTH = `CRC_WIDTH; 17 | parameter int PIPE_LVL = `PIPE_LVL; 18 | parameter CRC_POLY = `CRC_POLY; 19 | parameter INIT = `INIT; 20 | parameter XOR_OUT = `XOR_OUT; 21 | parameter bit REFIN = `REFIN; 22 | parameter bit REFOUT = `REFOUT; 23 | 24 | function string hex_str(input bit [CRC_WIDTH-1:0] hex); 25 | automatic bit [((CRC_WIDTH-1)/8)*8+7:0] new_hex = {(((CRC_WIDTH-1)/8+1)*8){1'b0}}; 26 | automatic string hex_string = ""; 27 | automatic string byte_string = ""; 28 | new_hex[CRC_WIDTH-1:0] = hex; 29 | for (int i = 0; i <= (CRC_WIDTH-1)/8; i++) begin 30 | $sformat(byte_string, "%2X", new_hex[((CRC_WIDTH-1)/8)*8+7-i*8-:8]); 31 | hex_string = {hex_string,byte_string}; 32 | end 33 | return hex_string; 34 | endfunction 35 | 36 | bit [8191:0][7:0] message; //here the message is set to be at most 8192 bytes, change it if it's too small for you 37 | int unsigned message_size; 38 | 39 | logic clk; 40 | logic rst; 41 | logic [DWIDTH-1:0] din; 42 | logic dlast; 43 | logic flitEn; 44 | logic [CRC_WIDTH-1:0] crc_out; 45 | logic crc_out_vld; 46 | 47 | crc_top #( 48 | .DWIDTH (DWIDTH ), 49 | .CRC_WIDTH (CRC_WIDTH ), 50 | .PIPE_LVL (PIPE_LVL ), 51 | .CRC_POLY (CRC_POLY ), 52 | .INIT (INIT ), 53 | .XOR_OUT (XOR_OUT ), 54 | .REFIN (REFIN ), 55 | .REFOUT (REFOUT ) 56 | ) u_crc_top(.*); 57 | 58 | bit [CRC_WIDTH-1:0] crc_sw_out; 59 | bit [CRC_WIDTH+7:0] crc_sw_tmp; 60 | bit [7:0] crc_byte_tmp; 61 | 62 | bit [N_MESSAGE-1:0][CRC_WIDTH-1:0] crc_sw_out_fifo; 63 | 64 | int sim_exit = 0; 65 | 66 | initial begin 67 | //information 68 | $display("Configuration:"); 69 | $display(" CRC polynomial: %0d'h%s", CRC_WIDTH, hex_str(CRC_POLY)); 70 | $display(" Bus Width: %0d", DWIDTH); 71 | $display(" INIT: %0d'h%s", CRC_WIDTH, hex_str(INIT)); 72 | $display(" XOR OUT: %0d'h%s", CRC_WIDTH, hex_str(XOR_OUT)); 73 | if (REFIN) 74 | $display(" Reflect IN: True"); 75 | else 76 | $display(" Reflect IN: False"); 77 | if (REFOUT) 78 | $display(" Reflect OUT: True"); 79 | else 80 | $display(" Reflect OUT: False"); 81 | $display("Run test with %0d messages", N_MESSAGE); 82 | //reset the hardware 83 | din <= {DWIDTH{1'b0}}; 84 | dlast <= 1'b0; 85 | flitEn <= 1'b0; 86 | rst <= 1'b1; 87 | repeat(20) @(posedge clk); 88 | rst <= 1'b0; 89 | repeat(10) @(posedge clk); 90 | //initialize the variables 91 | message_size = $urandom(111); // Initialize the generator 92 | for (int i = 0; i < N_MESSAGE; i++) begin 93 | if (sim_exit) 94 | break; 95 | message_size = $urandom_range(MESSAGE_LEN_MIN,MESSAGE_LEN_MAX); 96 | message_size = (message_size-1)/(DWIDTH/8)*(DWIDTH/8)+DWIDTH/8; 97 | $display("The message #%0d is %0d bytes:", i, message_size); 98 | //generate the message 99 | for (int j = 0; j < message_size; j++) begin 100 | message[j] = $urandom & 255; 101 | $write("%02X",message[j]); 102 | if (j % 32 == 31) 103 | $write("\n"); 104 | end 105 | $write("\n"); 106 | //calculate the crc in software 107 | //assign INIT to crcSoFar 108 | crc_sw_tmp = {INIT,8'b0}; 109 | for (int j = 0; j < message_size; j++) begin 110 | if (REFIN) 111 | crc_byte_tmp = {<<{message[j]}}; 112 | else 113 | crc_byte_tmp = message[j]; 114 | //XOR crcSoFar with the message byte 115 | crc_sw_tmp[CRC_WIDTH+7-:8] = crc_sw_tmp[CRC_WIDTH+7-:8] ^ crc_byte_tmp; 116 | //Do 1-bit CRC algorithm 117 | for (int k = CRC_WIDTH+7; k >= CRC_WIDTH; k--) begin 118 | if (crc_sw_tmp[k]) 119 | crc_sw_tmp[k-1-:CRC_WIDTH] = crc_sw_tmp[k-1-:CRC_WIDTH] ^ CRC_POLY; 120 | end 121 | //shift crc_out for another iteration 122 | crc_sw_tmp = {crc_sw_tmp[CRC_WIDTH-1:0],8'b0}; 123 | end 124 | crc_sw_out = crc_sw_tmp[CRC_WIDTH+7-:CRC_WIDTH]; 125 | if (REFOUT) 126 | crc_sw_out = {<<{crc_sw_out}}; 127 | crc_sw_out = crc_sw_out ^ XOR_OUT; 128 | crc_sw_out_fifo[i] = crc_sw_out; 129 | //calculate the crc in hardware 130 | @(posedge clk); 131 | for (int j = 0; j < (message_size*8-1)/DWIDTH+1; ) begin 132 | if (real'($urandom_range(1,100))/100.0 <= flitEn_ratio) begin 133 | for (int k = 0; k < DWIDTH/8; k++) begin 134 | din[DWIDTH-1-k*8-:8] <= message[j*DWIDTH/8+k]; 135 | end 136 | dlast <= (j+1)*DWIDTH/8 >= message_size; 137 | flitEn <= 1'b1; 138 | j++; 139 | end 140 | else 141 | flitEn <= 1'b0; 142 | @(posedge clk); 143 | end 144 | din <= {DWIDTH{1'b0}}; 145 | dlast <= 1'b0; 146 | flitEn <= 1'b0; 147 | end 148 | end 149 | 150 | initial begin 151 | sim_exit = 0; 152 | for (int i = 0; i < N_MESSAGE; ) begin 153 | if (crc_out_vld) begin 154 | if (crc_out != crc_sw_out_fifo[i]) begin 155 | sim_exit = 1; 156 | for (int j = 0; j < i; j++) 157 | $display("Message #%0d: SW CRC result = %0d'h%s, HW CRC result = %0d'h%s, results matched", j, CRC_WIDTH, hex_str(crc_sw_out_fifo[j]), CRC_WIDTH, hex_str(crc_sw_out_fifo[j])); 158 | $display("Message #%0d: SW CRC result = %0d'h%s, HW CRC result = %0d'h%s, results did not match", i, CRC_WIDTH, hex_str(crc_sw_out_fifo[i]), CRC_WIDTH, hex_str(crc_out)); 159 | $display("CRC results did not match for message #%0d, test FAILED", i); 160 | repeat(10) @(posedge clk); 161 | $finish; 162 | end 163 | i++; 164 | end 165 | @(posedge clk); 166 | end 167 | 168 | for (int i = 0; i < N_MESSAGE; i++) begin 169 | $display("Message #%0d: SW CRC result = %0d'h%s, HW CRC result = %0d'h%s, results matched", i, CRC_WIDTH, hex_str(crc_sw_out_fifo[i]), CRC_WIDTH, hex_str(crc_sw_out_fifo[i])); 170 | end 171 | $display("All CRC results matched, test PASSED for %m"); 172 | repeat(50) @(posedge clk); 173 | $finish; 174 | end 175 | 176 | initial begin 177 | clk = 1'b1; 178 | forever begin 179 | #(2ns) clk = ~ clk; 180 | end 181 | end 182 | endmodule 183 | `undef SIM 184 | -------------------------------------------------------------------------------- /correctness_verification/hdl/crc_top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | `ifndef SIM 4 | `define GET_STATE_sub1(val) (val+64'h9e3779b97f4a7c15) 5 | `define GET_STATE_sub2(val) ((`GET_STATE_sub1(val) ^ (`GET_STATE_sub1(val) >> 30)) * 64'hbf58476d1ce4e5b9) 6 | `define GET_STATE_sub3(val) ((`GET_STATE_sub2(val) ^ (`GET_STATE_sub2(val) >> 27)) * 64'h94d049bb133111eb) 7 | `define GET_STATE(val) (`GET_STATE_sub3(val) ^ (`GET_STATE_sub3(val) >> 31)) 8 | `define A 64'd19911102 9 | `define B 64'h9e3779b97f4a7c15 10 | `endif 11 | 12 | `include "config.svh" 13 | 14 | module crc_top #( 15 | parameter int DWIDTH = `DWIDTH, 16 | parameter int CRC_WIDTH = `CRC_WIDTH, 17 | parameter int PIPE_LVL = `PIPE_LVL, 18 | parameter CRC_POLY = `CRC_POLY, 19 | parameter INIT = `INIT, 20 | parameter XOR_OUT = `XOR_OUT, 21 | parameter bit REFIN = `REFIN, 22 | parameter bit REFOUT = `REFOUT, 23 | parameter bit [7:0] PKT_LIMIT = `PKT_LIMIT, 24 | parameter int BYTE_BITS = `BYTE_BITS 25 | ) ( 26 | `ifdef SIM 27 | input logic clk, 28 | input logic rst, 29 | input logic [DWIDTH-1:0] din, 30 | input logic dlast, 31 | input logic flitEn, 32 | output logic [CRC_WIDTH-1:0] crc_out, 33 | output logic crc_out_vld 34 | `else 35 | input logic clk_p, 36 | input logic clk_n 37 | `endif 38 | ); 39 | 40 | `ifndef SIM 41 | logic clk; 42 | logic rst; 43 | logic start; 44 | logic [DWIDTH-1:0] din; 45 | logic dlast = 1'b0; 46 | logic flitEn = 1'b0; 47 | logic [CRC_WIDTH-1:0] crc_out; 48 | logic crc_out_vld; 49 | logic done = 1'b0; 50 | 51 | logic [7:0] pkt_cnt = 8'b0; 52 | logic [BYTE_BITS-1:0] pkt_byte_cnt = {BYTE_BITS{1'b0}}; 53 | logic [((DWIDTH-1)/64+1)*64-1:0] din_tmp; 54 | 55 | logic [15:0] rand16; 56 | logic gen_new_pkt; 57 | 58 | IBUFDS ibufds_inst ( 59 | .I(clk_p), 60 | .IB(clk_n), 61 | .O(clk) 62 | ); 63 | `endif 64 | 65 | crc_gen #( 66 | .DWIDTH (DWIDTH ), 67 | .CRC_WIDTH (CRC_WIDTH ), 68 | .PIPE_LVL (PIPE_LVL ), 69 | .CRC_POLY (CRC_POLY ), 70 | .INIT (INIT ), 71 | .XOR_OUT (XOR_OUT ), 72 | .REFIN (REFIN ), 73 | .REFOUT (REFOUT ) 74 | ) u_crc_gen(.*); 75 | 76 | `ifndef SIM 77 | vio_0 vio_inst ( 78 | .clk(clk), 79 | .probe_out0(start) 80 | ); 81 | 82 | ila_0 ila_inst ( 83 | .clk(clk), 84 | .probe0(start), 85 | .probe1(done), 86 | .probe2(din), 87 | .probe3(dlast), 88 | .probe4(flitEn), 89 | .probe5(crc_out), 90 | .probe6(crc_out_vld) 91 | ); 92 | 93 | genvar i; 94 | for (i = 0; i < (DWIDTH-1)/64+1; i++) begin 95 | xoshiro128ss_simple #( 96 | .S0 (`GET_STATE(`A+`B*i*2)), 97 | .S1 (`GET_STATE(`A+`B*(i*2+1))) 98 | ) rand_din ( 99 | .clk (clk ), 100 | .enable (start ), 101 | .rand64 (din_tmp[(i+1)*64-1-:64]) 102 | ); 103 | end 104 | 105 | xoshiro32pp_simple #( 106 | .S0 (16'h1991), 107 | .S1 (16'h1102) 108 | ) rand_pkt_len( 109 | .clk (clk), 110 | .enable (gen_new_pkt), 111 | .rand16 (rand16) 112 | ); 113 | 114 | always_ff @(posedge clk) begin 115 | if (~start) begin 116 | pkt_cnt <= 8'b0; 117 | done <= 1'b0; 118 | end 119 | else if (flitEn&dlast) begin 120 | pkt_cnt <= pkt_cnt + 1'b1; 121 | if (pkt_cnt + 1'b1 == PKT_LIMIT) 122 | done <= 1'b1; 123 | end 124 | end 125 | 126 | always_ff @(posedge clk) begin 127 | if (pkt_byte_cnt > DWIDTH/8) 128 | pkt_byte_cnt <= pkt_byte_cnt - DWIDTH/8; 129 | else if (start & ~done) 130 | pkt_byte_cnt <= rand16[15-:BYTE_BITS]; 131 | else 132 | pkt_byte_cnt <= {BYTE_BITS{1'b0}}; 133 | 134 | flitEn <= pkt_byte_cnt != {BYTE_BITS{1'b0}}; 135 | dlast <= pkt_byte_cnt <= DWIDTH/8 && pkt_byte_cnt != {BYTE_BITS{1'b0}}; 136 | end 137 | 138 | assign rst = ~start; 139 | assign din = din_tmp[DWIDTH-1:0]; 140 | assign gen_new_pkt = start & ~done & (pkt_byte_cnt <= DWIDTH/8); 141 | `endif 142 | endmodule -------------------------------------------------------------------------------- /correctness_verification/hdl/xoshiro128ss_simple.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `define ROTL64(X,K) ({X << K} | {X >> (64-K)}) 3 | module xoshiro128ss_simple # 4 | ( 5 | parameter bit [63:0] S0 = 64'd1, 6 | parameter bit [63:0] S1 = 64'd2 7 | ) 8 | ( 9 | input logic clk, 10 | input logic enable, 11 | output logic [63:0] rand64 = `ROTL64({S0*5},7)*9 12 | ); 13 | logic [63:0] s0 = S0; 14 | logic [63:0] s1 = S1; 15 | 16 | logic [63:0] s0_new, s1_new; 17 | 18 | always_comb begin 19 | s0_new = s0; 20 | s1_new = s1; 21 | s1_new = s1_new ^ s0; 22 | s0_new = `ROTL64(s0_new, 24) ^ s1_new ^ (s1_new << 16); 23 | s1_new = `ROTL64(s1_new, 37); 24 | end 25 | 26 | always_ff @(posedge clk) begin 27 | if (enable) begin 28 | s0 <= s0_new; 29 | s1 <= s1_new; 30 | rand64 <= `ROTL64({s0*5},7)*9; 31 | end 32 | end 33 | endmodule 34 | -------------------------------------------------------------------------------- /correctness_verification/hdl/xoshiro32pp_simple.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `define ROTL16(X,K) ({X << K} | {X >> (16-K)}) 3 | module xoshiro32pp_simple # 4 | ( 5 | parameter bit [15:0] S0 = 16'd1, 6 | parameter bit [15:0] S1 = 16'd2 7 | ) 8 | ( 9 | input logic clk, 10 | input logic enable, 11 | output logic [15:0] rand16 = `ROTL16({S0+S1},9)+S0 12 | ); 13 | logic [15:0] s0 = S0; 14 | logic [15:0] s1 = S1; 15 | 16 | logic [15:0] s0_new, s1_new; 17 | 18 | always_comb begin 19 | s0_new = (`ROTL16(s0,13) ^ (s0 ^ s1)) ^ ((s0 ^ s1) <<< 5); 20 | s1_new = `ROTL16((s0^s1),10); 21 | end 22 | 23 | always_ff @(posedge clk) begin 24 | if (enable) begin 25 | s0 <= s0_new; 26 | s1 <= s1_new; 27 | rand16 <= `ROTL16((s0+s1),9) +s0; 28 | end 29 | end 30 | assign s0s1 = s0 ^ s1; 31 | endmodule -------------------------------------------------------------------------------- /correctness_verification/outputs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.keep 4 | -------------------------------------------------------------------------------- /correctness_verification/outputs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UofT-HPRC/Tbps_CRC/134c67845f2db14a991b7a2b8216ba182180ba47/correctness_verification/outputs/.keep -------------------------------------------------------------------------------- /correctness_verification/scripts/run_impl.tcl: -------------------------------------------------------------------------------- 1 | set PART_NUM [lindex $argv 0] 2 | set DWIDTH [lindex $argv 1] 3 | set CRC_WIDTH [lindex $argv 2] 4 | set PIPE_LVL [lindex $argv 3] 5 | set CRC_POLY [lindex $argv 4] 6 | set INIT [lindex $argv 5] 7 | set XOR_OUT [lindex $argv 6] 8 | set REFIN [lindex $argv 7] 9 | set REFOUT [lindex $argv 8] 10 | set BYTEEN [lindex $argv 9] 11 | set PKT_LIMIT [lindex $argv 10] 12 | set BYTE_BITS [lindex $argv 11] 13 | 14 | set script_dir [file dirname [file normalize [info script]]] 15 | set root_dir [file dirname [file dirname [file normalize [info script]]]] 16 | set work_dir "${root_dir}/workdir" 17 | 18 | if {$BYTEEN} { 19 | set project_name "tbps_crc_byteEn_implementation" 20 | create_project $project_name ${work_dir}/${project_name} -part $PART_NUM -force 21 | add_files -fileset sources_1 -norecurse [list "${root_dir}/hdl/crc_byteEn_top.sv" \ 22 | "${root_dir}/hdl/xoshiro128ss_simple.sv" \ 23 | "${root_dir}/hdl/xoshiro32pp_simple.sv" \ 24 | "${root_dir}/hdl/config.svh" \ 25 | "${root_dir}/../core_src/crc_byteEn.sv" \ 26 | "${root_dir}/../core_src/crc.svh" 27 | ] 28 | add_files -fileset constrs_1 "${root_dir}/board_clk_source.xdc" 29 | set top_rtl "crc_byteEn_top" 30 | } else { 31 | set project_name "tbps_crc_implementation" 32 | create_project $project_name ${work_dir}/${project_name} -part $PART_NUM -force 33 | add_files -fileset sources_1 -norecurse [list "${root_dir}/hdl/crc_top.sv" \ 34 | "${root_dir}/hdl/xoshiro128ss_simple.sv" \ 35 | "${root_dir}/hdl/xoshiro32pp_simple.sv" \ 36 | "${root_dir}/hdl/config.svh" \ 37 | "${root_dir}/../core_src/crc.sv" \ 38 | "${root_dir}/../core_src/crc.svh" 39 | ] 40 | add_files -fileset constrs_1 "${root_dir}/board_clk_source.xdc" 41 | set top_rtl "crc_top" 42 | } 43 | 44 | set_property top $top_rtl [get_filesets sources_1] 45 | 46 | create_ip -name vio -vendor xilinx.com -library ip -version 3.0 -module_name vio_0 47 | set_property -dict [list CONFIG.C_PROBE_OUT0_WIDTH {1} CONFIG.C_NUM_PROBE_OUT {1} CONFIG.C_NUM_PROBE_IN {0} CONFIG.C_EN_PROBE_IN_ACTIVITY {0}] [get_ips vio_0] 48 | create_ip -name ila -vendor xilinx.com -library ip -version 6.2 -module_name ila_0 49 | if {$BYTEEN} { 50 | set_property -dict [list CONFIG.C_PROBE6_WIDTH {32} CONFIG.C_PROBE3_WIDTH {64} CONFIG.C_PROBE2_WIDTH {512} CONFIG.C_NUM_OF_PROBES {8}] [get_ips ila_0] 51 | } else { 52 | set_property -dict [list CONFIG.C_PROBE5_WIDTH {32} CONFIG.C_PROBE2_WIDTH {512} CONFIG.C_NUM_OF_PROBES {7}] [get_ips ila_0] 53 | } 54 | 55 | reset_run synth_1 56 | set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value "-verilog_define DWIDTH=${DWIDTH} -verilog_define CRC_WIDTH=${CRC_WIDTH} -verilog_define PIPE_LVL=${PIPE_LVL} -verilog_define CRC_POLY=${CRC_POLY} -verilog_define INIT=${INIT} -verilog_define XOR_OUT=${XOR_OUT} -verilog_define REFIN=1'b${REFIN} -verilog_define REFOUT=1'b${REFOUT} -verilog_define PKT_LIMIT=${PKT_LIMIT} -verilog_define BYTE_BITS=${BYTE_BITS}" -objects [get_runs synth_1] 57 | 58 | launch_runs synth_1 -jobs 8 59 | wait_on_run synth_1 60 | if {[get_property PROGRESS [get_runs synth_1]] != "100%"} { 61 | error "ERROR: synthesis failed" 62 | } 63 | 64 | launch_runs impl_1 -to_step write_bitstream -jobs 8 65 | wait_on_run impl_1 66 | if {[get_property PROGRESS [get_runs impl_1]] != "100%"} { 67 | error "ERROR: implementation failed" 68 | } 69 | put "bitstream has been generated, you can find the bitstream ($top_rtl.bit) and the debug probe file ($top_rtl.ltx) under ${work_dir}/outputs/" 70 | exit 71 | -------------------------------------------------------------------------------- /correctness_verification/scripts/run_sim.tcl: -------------------------------------------------------------------------------- 1 | set PART_NUM [lindex $argv 0] 2 | set DWIDTH [lindex $argv 1] 3 | set CRC_WIDTH [lindex $argv 2] 4 | set PIPE_LVL [lindex $argv 3] 5 | set CRC_POLY [lindex $argv 4] 6 | set INIT [lindex $argv 5] 7 | set XOR_OUT [lindex $argv 6] 8 | set REFIN [lindex $argv 7] 9 | set REFOUT [lindex $argv 8] 10 | set BYTEEN [lindex $argv 9] 11 | set N_MESSAGE [lindex $argv 10] 12 | set MESSAGE_LEN_MIN [lindex $argv 11] 13 | set MESSAGE_LEN_MAX [lindex $argv 12] 14 | set flitEn_ratio [lindex $argv 13] 15 | 16 | set script_dir [file dirname [file normalize [info script]]] 17 | set root_dir [file dirname [file dirname [file normalize [info script]]]] 18 | set work_dir "${root_dir}/workdir" 19 | 20 | if {$BYTEEN} { 21 | create_project tbps_crc_byteEn_simulation ${work_dir}/tbps_crc_byteEn_simulation -part $PART_NUM -force 22 | add_files -fileset sim_1 -norecurse [list "${root_dir}/hdl/crc_byteEn_tb.sv" \ 23 | "${root_dir}/hdl/crc_byteEn_top.sv" \ 24 | "${root_dir}/hdl/config.svh" \ 25 | "${root_dir}/../core_src/crc_byteEn.sv" \ 26 | "${root_dir}/../core_src/crc.svh" 27 | ] 28 | set top_rtl "crc_byteEn_tb" 29 | } else { 30 | create_project tbps_crc_simulation ${work_dir}/tbps_crc_simulation -part $PART_NUM -force 31 | add_files -fileset sim_1 -norecurse [list "${root_dir}/hdl/crc_tb.sv" \ 32 | "${root_dir}/hdl/crc_top.sv" \ 33 | "${root_dir}/hdl/config.svh" \ 34 | "${root_dir}/../core_src/crc.sv" \ 35 | "${root_dir}/../core_src/crc.svh" 36 | ] 37 | set top_rtl "crc_tb" 38 | } 39 | 40 | set_property top $top_rtl [get_filesets sim_1] 41 | set_property -name {xsim.simulate.log_all_signals} -value {true} -objects [get_filesets sim_1] 42 | #had to add the dummy macro to prevent vivado from failing, this is dummy! 43 | set_property -name {xsim.compile.xvlog.more_options} -value "-d SIM -d DWIDTH=${DWIDTH} -d CRC_WIDTH=${CRC_WIDTH} -d PIPE_LVL=${PIPE_LVL} -d CRC_POLY=\"${CRC_POLY}\" -d INIT=\"${INIT}\" -d XOR_OUT=\"${XOR_OUT}\" -d REFIN=\"1'b${REFIN}\" -d REFOUT=\"1'b${REFOUT}\" -d N_MESSAGE=${N_MESSAGE} -d MESSAGE_LEN_MIN=${MESSAGE_LEN_MIN} -d MESSAGE_LEN_MAX=${MESSAGE_LEN_MAX} -d flitEn_ratio=${flitEn_ratio} -d dummy=\"'\"" -objects [get_filesets sim_1] 44 | 45 | launch_simulation 46 | run all 47 | put "type to see the waveform or type to close vivado" 48 | -------------------------------------------------------------------------------- /correctness_verification/workdir/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.keep 4 | -------------------------------------------------------------------------------- /correctness_verification/workdir/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UofT-HPRC/Tbps_CRC/134c67845f2db14a991b7a2b8216ba182180ba47/correctness_verification/workdir/.keep -------------------------------------------------------------------------------- /performance_evaluation/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /performance_evaluation/Makefile: -------------------------------------------------------------------------------- 1 | include config.mk 2 | find_fmax: hdl/crc_top.sv hdl/config.svh ../core_src/crc.sv ../core_src/crc.svh scripts/find_fmax_nopipe.tcl 3 | @rm -rf workdir/run_fmax.log 4 | @vivado -mode batch -nojournal -nolog -source scripts/find_fmax_nopipe.tcl -tclargs $(PART_NUM) 0 5 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk -type f | xargs -n 1 rm -rf 6 | @find . -mindepth 1 -maxdepth 1 ! -name constraints ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 7 | 8 | find_fmax_byteEn: hdl/crc_byteEn_top.sv hdl/config.svh ../core_src/crc_byteEn.sv ../core_src/crc.svh scripts/find_fmax_nopipe.tcl 9 | @rm -rf workdir/byteEn_run_fmax.log 10 | @vivado -mode batch -nojournal -nolog -source scripts/find_fmax_nopipe.tcl -tclargs $(PART_NUM) 1 11 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk -type f | xargs -n 1 rm -rf 12 | @find . -mindepth 1 -maxdepth 1 ! -name constraints ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 13 | 14 | find_pipe_lvl_500mhz: hdl/crc_top.sv hdl/config.svh ../core_src/crc.sv ../core_src/crc.svh scripts/find_pipe_lvl_500mhz.tcl 15 | @rm -rf workdir/run_pipe.log 16 | @vivado -mode batch -nojournal -nolog -source scripts/find_pipe_lvl_500mhz.tcl -tclargs $(PART_NUM) 0 17 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk -type f | xargs -n 1 rm -rf 18 | @find . -mindepth 1 -maxdepth 1 ! -name constraints ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 19 | 20 | find_pipe_lvl_500mhz_byteEn: hdl/crc_byteEn_top.sv hdl/config.svh ../core_src/crc_byteEn.sv ../core_src/crc.svh scripts/find_pipe_lvl_500mhz.tcl 21 | @rm -rf workdir/byteEn_run_pipe.log 22 | @vivado -mode batch -nojournal -nolog -source scripts/find_pipe_lvl_500mhz.tcl -tclargs $(PART_NUM) 1 23 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk -type f | xargs -n 1 rm -rf 24 | @find . -mindepth 1 -maxdepth 1 ! -name constraints ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 25 | 26 | clean: 27 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk -type f | xargs -n 1 rm -rf 28 | @find . -mindepth 1 -maxdepth 1 ! -name constraints ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 29 | 30 | clean_all: 31 | @rm -f workdir/*run*.log 32 | @rm -f outputs/fmax_results/result* 33 | @rm -f outputs/fmax_results/logs/* 34 | @rm -f outputs/pipe_lvl_results/result* 35 | @rm -f outputs/pipe_lvl_results/logs/* 36 | @find . -mindepth 1 -maxdepth 1 ! -name Makefile ! -name .gitignore ! -name config.mk -type f | xargs -n 1 rm -rf 37 | @find . -mindepth 1 -maxdepth 1 ! -name constraints ! -name hdl ! -name outputs ! -name scripts ! -name workdir -type d | xargs -n 1 rm -rf 38 | -------------------------------------------------------------------------------- /performance_evaluation/config.mk: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #modify this config file for different configurations 3 | #board setting 4 | PART_NUM="xcu250-figd2104-2L-e" #the part number of the target fpga 5 | -------------------------------------------------------------------------------- /performance_evaluation/constraints/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !crc_byteEn.xdc 4 | !crc.xdc 5 | -------------------------------------------------------------------------------- /performance_evaluation/constraints/crc.xdc: -------------------------------------------------------------------------------- 1 | set src_clk [get_clocks -of [get_ports clk]] 2 | #the top level ports are actually fake ports to prevent vivado from optimizing out the entire design 3 | #the real "ports" are the registers instantiated in the top level design, they emulates the logic that connect with the crc module 4 | #the top level ports don't really get placed at anywhere, hence there is no route from or to these ports 5 | #it makes no sense to care about the timing related to these fake top level ports 6 | #especially, vivado can't properly calculate the clock skew related to these ports (again, because they are not placed) 7 | #therefore, we set false path for all the fake top level ports 8 | set_false_path -from [get_ports rst] 9 | set_false_path -from [get_ports din[*]] 10 | set_false_path -from [get_ports dlast] 11 | set_false_path -from [get_ports flitEn] 12 | set_false_path -to [get_ports crc_out[*]] 13 | set_false_path -to [get_ports crc_out_vld] 14 | 15 | #restrict the place and route area for the crc module 16 | create_pblock crc_region 17 | resize_pblock crc_region -add {CLOCKREGION_X2Y5:CLOCKREGION_X2Y5} 18 | add_cells_to_pblock crc_region [get_cells u_crc_gen] 19 | set_property SNAPPING_MODE ON [get_pblocks crc_region] 20 | #assign a real clock buffer source to clk, so that clock skew can be realistically calculated 21 | set_property HD.CLK_SRC BUFGCE_X0Y133 [get_ports clk] 22 | -------------------------------------------------------------------------------- /performance_evaluation/constraints/crc_byteEn.xdc: -------------------------------------------------------------------------------- 1 | set src_clk [get_clocks -of [get_ports clk]] 2 | #the top level ports are actually fake ports to prevent vivado from optimizing out the entire design 3 | #the real "ports" are the registers instantiated in the top level design, they emulates the logic that connect with the crc module 4 | #the top level ports don't really get placed at anywhere, hence there is no route from or to these ports 5 | #it makes no sense to care about the timing related to these fake top level ports 6 | #especially, vivado can't properly calculate the clock skew related to these ports (again, because they are not placed) 7 | #therefore, we set false path for all the fake top level ports 8 | set_false_path -from [get_ports rst] 9 | set_false_path -from [get_ports din[*]] 10 | set_false_path -from [get_ports dlast] 11 | set_false_path -from [get_ports byteEn[*]] 12 | set_false_path -from [get_ports flitEn] 13 | set_false_path -to [get_ports crc_out[*]] 14 | set_false_path -to [get_ports crc_out_vld] 15 | 16 | #restrict the place and route area for the crc module 17 | create_pblock crc_region 18 | resize_pblock crc_region -add {CLOCKREGION_X1Y5:CLOCKREGION_X3Y5} 19 | add_cells_to_pblock crc_region [get_cells u_crc_gen] 20 | set_property SNAPPING_MODE ON [get_pblocks crc_region] 21 | #assign a real clock buffer source to clk, so that clock skew can be realistically calculated 22 | set_property HD.CLK_SRC BUFGCE_X0Y133 [get_ports clk] 23 | -------------------------------------------------------------------------------- /performance_evaluation/hdl/config.svh: -------------------------------------------------------------------------------- 1 | /*- general setup -*/ 2 | `ifndef DWIDTH 3 | `define DWIDTH 512 4 | `endif 5 | `ifndef CRC_WIDTH 6 | `define CRC_WIDTH 32 7 | `endif 8 | `ifndef PIPE_LVL 9 | `define PIPE_LVL 0 10 | `endif 11 | `ifndef CRC_POLY 12 | `define CRC_POLY 32'h04C11DB7 13 | `endif 14 | `ifndef INIT 15 | `define INIT 32'hffffffff 16 | `endif 17 | `ifndef XOR_OUT 18 | `define XOR_OUT 32'hffffffff 19 | `endif 20 | `ifndef REFIN 21 | `define REFIN 1'b1 22 | `endif 23 | `ifndef REFOUT 24 | `define REFOUT 1'b1 25 | `endif 26 | -------------------------------------------------------------------------------- /performance_evaluation/hdl/crc_byteEn_top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | `include "config.svh" 4 | 5 | module crc_byteEn_top( 6 | input logic clk, 7 | input logic rst, 8 | input logic [`DWIDTH-1:0] din, 9 | input logic [`DWIDTH/8-1:0] byteEn, 10 | input logic dlast, 11 | input logic flitEn, 12 | output logic [`CRC_WIDTH-1:0] crc_out, 13 | output logic crc_out_vld 14 | ); 15 | logic rst_reg; 16 | logic [`DWIDTH-1:0] din_reg; 17 | logic [`DWIDTH/8-1:0] byteEn_reg; 18 | logic dlast_reg; 19 | logic flitEn_reg; 20 | logic [`CRC_WIDTH-1:0] crc_out_wire; 21 | logic crc_out_vld_wire; 22 | 23 | crc_gen_byteEn #( 24 | .DWIDTH (`DWIDTH ), 25 | .CRC_WIDTH (`CRC_WIDTH ), 26 | .PIPE_LVL (`PIPE_LVL ), 27 | .CRC_POLY (`CRC_POLY ), 28 | .INIT (`INIT ), 29 | .XOR_OUT (`XOR_OUT ), 30 | .REFIN (`REFIN ), 31 | .REFOUT (`REFOUT ) 32 | ) u_crc_gen ( 33 | .clk (clk ), 34 | .rst (rst_reg ), 35 | .din (din_reg ), 36 | .byteEn (byteEn_reg ), 37 | .dlast (dlast_reg ), 38 | .flitEn (flitEn_reg ), 39 | .crc_out (crc_out_wire ), 40 | .crc_out_vld (crc_out_vld_wire) 41 | ); 42 | 43 | always_ff @(posedge clk) begin 44 | rst_reg <= rst; 45 | din_reg <= din; 46 | byteEn_reg <= byteEn; 47 | dlast_reg <= dlast; 48 | flitEn_reg <= flitEn; 49 | crc_out <= crc_out_wire; 50 | crc_out_vld <= crc_out_vld_wire; 51 | end 52 | endmodule 53 | -------------------------------------------------------------------------------- /performance_evaluation/hdl/crc_top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | `include "config.svh" 4 | 5 | module crc_top( 6 | input logic clk, 7 | input logic rst, 8 | input logic [`DWIDTH-1:0] din, 9 | input logic dlast, 10 | input logic flitEn, 11 | output logic [`CRC_WIDTH-1:0] crc_out, 12 | output logic crc_out_vld 13 | ); 14 | logic rst_reg; 15 | logic [`DWIDTH-1:0] din_reg; 16 | logic dlast_reg; 17 | logic flitEn_reg; 18 | logic [`CRC_WIDTH-1:0] crc_out_wire; 19 | logic crc_out_vld_wire; 20 | 21 | crc_gen #( 22 | .DWIDTH (`DWIDTH), 23 | .CRC_WIDTH (`CRC_WIDTH), 24 | .PIPE_LVL (`PIPE_LVL), 25 | .CRC_POLY (`CRC_POLY), 26 | .INIT (`INIT), 27 | .XOR_OUT (`XOR_OUT), 28 | .REFIN (`REFIN), 29 | .REFOUT (`REFOUT) 30 | ) u_crc_gen( 31 | .clk (clk ), 32 | .rst (rst_reg ), 33 | .din (din_reg ), 34 | .dlast (dlast_reg ), 35 | .flitEn (flitEn_reg ), 36 | .crc_out (crc_out_wire ), 37 | .crc_out_vld (crc_out_vld_wire) 38 | ); 39 | 40 | always_ff @(posedge clk) begin 41 | rst_reg <= rst; 42 | din_reg <= din; 43 | dlast_reg <= dlast; 44 | flitEn_reg <= flitEn; 45 | crc_out <= crc_out_wire; 46 | crc_out_vld <= crc_out_vld_wire; 47 | end 48 | endmodule 49 | -------------------------------------------------------------------------------- /performance_evaluation/outputs/fmax_results/.gitignore: -------------------------------------------------------------------------------- 1 | result.csv 2 | -------------------------------------------------------------------------------- /performance_evaluation/outputs/fmax_results/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.keep 4 | -------------------------------------------------------------------------------- /performance_evaluation/outputs/fmax_results/logs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UofT-HPRC/Tbps_CRC/134c67845f2db14a991b7a2b8216ba182180ba47/performance_evaluation/outputs/fmax_results/logs/.keep -------------------------------------------------------------------------------- /performance_evaluation/outputs/pipe_lvl_results/.gitignore: -------------------------------------------------------------------------------- 1 | result.csv 2 | -------------------------------------------------------------------------------- /performance_evaluation/outputs/pipe_lvl_results/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.keep 4 | -------------------------------------------------------------------------------- /performance_evaluation/outputs/pipe_lvl_results/logs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UofT-HPRC/Tbps_CRC/134c67845f2db14a991b7a2b8216ba182180ba47/performance_evaluation/outputs/pipe_lvl_results/logs/.keep -------------------------------------------------------------------------------- /performance_evaluation/scripts/find_fmax_nopipe.tcl: -------------------------------------------------------------------------------- 1 | set part_num [lindex $argv 0] 2 | set byteEn [lindex $argv 1] 3 | 4 | set script_dir [file dirname [file normalize [info script]]] 5 | set root_dir [file dirname [file dirname [file normalize [info script]]]] 6 | set work_dir "${root_dir}/workdir" 7 | set freq_xdc "${root_dir}/constraints/freq.xdc" 8 | 9 | set result_dir ${root_dir}/outputs/fmax_results 10 | set log_dir ${result_dir}/logs 11 | set dcp_dir ${result_dir}/dcps 12 | 13 | if {$byteEn} { 14 | set result_csv $result_dir/result_byteEn.csv 15 | } else { 16 | set result_csv $result_dir/result.csv 17 | } 18 | set result_f [open $result_csv w] 19 | puts $result_f "name,polynomial,bus width,fmax,throughput,latency,LUTs,FFs" 20 | close $result_f 21 | 22 | if {$byteEn} { 23 | set file_prefix "byteEn_" 24 | set top_rtl "crc_byteEn_top" 25 | } else { 26 | set file_prefix "" 27 | set top_rtl "crc_top" 28 | } 29 | 30 | foreach name {"CRC5-USB" "CRC8-Bluetooth" "CRC10-CDMA2000" "CRC16-IBM" "CRC32-Ethernet" "CRC64-ECMA"} poly {"5'h05" "8'hA7" "10'h3D9" "16'h8005" "32'h04C11DB7" "64'h42F0E1EBA9EA3693"} crc_width {5 8 10 16 32 64} init_hex {"5'b0" "8'b0" "10'b0" "16'b0" "32'hffffffff" "64'b0"} xorout {"5'b0" "8'b0" "10'b0" "16'b0" "32'hffffffff" "64'b0"} refin {"1'b0" "1'b0" "1'b0" "1'b0" "1'b1" "1'b0"} refout {"1'b0" "1'b0" "1'b0" "1'b0" "1'b1" "1'b0"} { 31 | set fmin 300 32 | set fmax 500 33 | foreach bus_width {64 128 256 512 1024} { 34 | puts "run poly: $name, bus width: $bus_width" 35 | set fmin 300 36 | set slack_met 1 37 | set init 1 38 | while {1} { 39 | if {$init == 1} { 40 | set init 0 41 | set freq $fmax 42 | } else { 43 | close_project 44 | set freq [format "%.3f" [expr ($fmin+$fmax)/2.0]] 45 | } 46 | set period [format "%.3f" [expr 1000.0/$freq]] 47 | set freq_xdc_f [open $freq_xdc w] 48 | puts $freq_xdc_f "create_clock -period $period \[get_ports clk\]" 49 | close $freq_xdc_f 50 | puts "try frequency: $freq MHz" 51 | create_project -in_memory -part $part_num 52 | if {$byteEn} { 53 | read_verilog $root_dir/../core_src/crc_byteEn.sv 54 | read_verilog $root_dir/hdl/crc_byteEn_top.sv 55 | } else { 56 | read_verilog $root_dir/../core_src/crc.sv 57 | read_verilog $root_dir/hdl/crc_top.sv 58 | } 59 | read_xdc $root_dir/constraints/freq.xdc 60 | if {$byteEn} { 61 | read_xdc $root_dir/constraints/crc_byteEn.xdc 62 | } else { 63 | read_xdc $root_dir/constraints/crc.xdc 64 | } 65 | 66 | synth_design -mode out_of_context -top $top_rtl -part $part_num \ 67 | -verilog_define DWIDTH=$bus_width \ 68 | -verilog_define CRC_WIDTH=$crc_width \ 69 | -verilog_define PIPE_LVL=0 \ 70 | -verilog_define CRC_POLY=$poly \ 71 | -verilog_define INIT=$init_hex \ 72 | -verilog_define XOR_OUT=$xorout \ 73 | -verilog_define REFIN=$refin \ 74 | -verilog_define REFOUT=$refout >> ${work_dir}/${file_prefix}run_fmax.log 75 | opt_design >> ${work_dir}/${file_prefix}run_fmax.log 76 | place_design >> ${work_dir}/${file_prefix}run_fmax.log 77 | phys_opt_design >> ${work_dir}/${file_prefix}run_fmax.log 78 | route_design >> ${work_dir}/${file_prefix}run_fmax.log 79 | phys_opt_design >> ${work_dir}/${file_prefix}run_fmax.log 80 | write_checkpoint -force ${dcp_dir}/${file_prefix}${name}_${bus_width}_${freq}.dcp 81 | 82 | set timing_log [report_timing_summary -setup -nworst 1 -return_string] 83 | if {[regexp {(VIOLATED)} $timing_log]} { 84 | set fmax $freq 85 | set slack_met 0 86 | report_timing_summary -nworst 10 -file $log_dir/${file_prefix}timing_${name}_${bus_width}_${freq}mhz.log 87 | } else { 88 | set fmin $freq 89 | set slack_met 1 90 | report_timing_summary -nworst 10 -file $log_dir/${file_prefix}timing_${name}_${bus_width}_${freq}mhz.log 91 | report_utilization -cells [get_cells u_crc_gen] -file $log_dir/${file_prefix}resource_${name}_${bus_width}.log 92 | regexp {CLB LUTs[ ]+\|[ ]+([0-9]+)} [report_utilization -cells [get_cells u_crc_gen] -return_string] matched luts 93 | regexp {CLB Registers[ ]+\|[ ]+([0-9]+)} [report_utilization -cells [get_cells u_crc_gen] -return_string] matched ffs 94 | } 95 | if {[expr $fmax-$fmin] <= 5} { 96 | break 97 | } 98 | } 99 | if {$slack_met} { 100 | set fmax $freq 101 | } else { 102 | set fmax $fmin 103 | } 104 | set throughput [format "%.1f" [expr $bus_width*$fmax/1000.0]] 105 | if {$byteEn} { 106 | set latency [format "%.1f" [expr (1000.0/$fmax)*(2+log($bus_width/8)/log(2))]] 107 | } else { 108 | set latency [format "%.1f" [expr 1000.0/$fmax]] 109 | } 110 | puts "$name,$poly,$bus_width:$fmax,$throughput,$latency,$luts,$ffs" 111 | set result_f [open $result_csv a] 112 | puts $result_f "$name,$poly,$bus_width,$fmax,$throughput,$latency,$luts,$ffs" 113 | close $result_f 114 | close_project 115 | } 116 | } 117 | puts "finished runs, the result table can be found at ${result_dir}" 118 | exit 119 | -------------------------------------------------------------------------------- /performance_evaluation/scripts/find_pipe_lvl_500mhz.tcl: -------------------------------------------------------------------------------- 1 | set part_num [lindex $argv 0] 2 | set byteEn [lindex $argv 1] 3 | 4 | set script_dir [file dirname [file normalize [info script]]] 5 | set root_dir [file dirname [file dirname [file normalize [info script]]]] 6 | set work_dir "${root_dir}/workdir" 7 | set freq_xdc "${root_dir}/constraints/freq.xdc" 8 | 9 | set result_dir ${root_dir}/outputs/pipe_lvl_results 10 | set log_dir ${result_dir}/logs 11 | set dcp_dir ${result_dir}/dcps 12 | 13 | set freq_xdc_f [open "$root_dir/constraints/freq_pipe.xdc" w] 14 | puts $freq_xdc_f "create_clock -period 2.000 \[get_ports clk\]" 15 | close $freq_xdc_f 16 | 17 | if {$byteEn} { 18 | set result_csv $result_dir/result_byteEn.csv 19 | } else { 20 | set result_csv $result_dir/result.csv 21 | } 22 | set result_f [open $result_csv w] 23 | puts $result_f "name,polynomial,bus width,pipeline levels,throughput,latency,LUTs,FFs" 24 | close $result_f 25 | 26 | if {$byteEn} { 27 | set file_prefix "byteEn_" 28 | set top_rtl "crc_byteEn_top" 29 | } else { 30 | set file_prefix "" 31 | set top_rtl "crc_top" 32 | } 33 | 34 | proc timeout_warning {} { 35 | puts "routing timeout, skipping" 36 | } 37 | 38 | foreach name {"CRC5-USB" "CRC16-IBM" "CRC32-Ethernet" "CRC64-ECMA"} poly {"5'h05" "16'h8005" "32'h04C11DB7" "64'h42F0E1EBA9EA3693"} crc_width {5 16 32 64} init_hex {"5'b0" "16'b0" "32'hffffffff" "64'b0"} xorout {"5'b0" "16'b0" "32'hffffffff" "64'b0"} refin {"1'b0" "1'b0" "1'b1" "1'b0"} refout {"1'b0" "1'b0" "1'b1" "1'b0"} { 39 | foreach bus_width {64 512 2048 8192} pipe_lvl_start {0 0 1 2} { 40 | set pipe_lvl $pipe_lvl_start 41 | puts "run poly: $name, bus width: $bus_width" 42 | set slack_met 0 43 | set init 1 44 | while {1} { 45 | if {$init != 1} { 46 | close_project 47 | } else { 48 | set init 0 49 | } 50 | puts "try pipe level: $pipe_lvl" 51 | create_project -in_memory -part $part_num 52 | if {$byteEn} { 53 | read_verilog $root_dir/../core_src/crc_byteEn.sv 54 | read_verilog $root_dir/hdl/crc_byteEn_top.sv 55 | } else { 56 | read_verilog $root_dir/../core_src/crc.sv 57 | read_verilog $root_dir/hdl/crc_top.sv 58 | } 59 | read_xdc $root_dir/constraints/freq.xdc 60 | if {$byteEn} { 61 | read_xdc $root_dir/constraints/crc_byteEn.xdc 62 | } else { 63 | read_xdc $root_dir/constraints/crc.xdc 64 | } 65 | 66 | synth_design -mode out_of_context -top $top_rtl -part $part_num \ 67 | -verilog_define DWIDTH=$bus_width \ 68 | -verilog_define CRC_WIDTH=$crc_width \ 69 | -verilog_define PIPE_LVL=$pipe_lvl \ 70 | -verilog_define CRC_POLY=$poly \ 71 | -verilog_define INIT=$init_hex \ 72 | -verilog_define XOR_OUT=$xorout \ 73 | -verilog_define REFIN=$refin \ 74 | -verilog_define REFOUT=$refout >> ${work_dir}/${file_prefix}run_pipe.log 75 | if {$pipe_lvl > 0} { 76 | resize_pblock crc_region -add {CLOCKREGION_X3Y5:CLOCKREGION_X3Y5} 77 | } 78 | opt_design >> ${work_dir}/${file_prefix}run_pipe.log 79 | place_design >> ${work_dir}/${file_prefix}run_pipe.log 80 | phys_opt_design >> ${work_dir}/${file_prefix}run_pipe.log 81 | after 1800000 timeout_warning continue 82 | route_design >> ${work_dir}/${file_prefix}run_pipe.log 83 | after cancel timeout_warning continue 84 | phys_opt_design >> ${work_dir}/${file_prefix}run_pipe.log 85 | write_checkpoint -force ${dcp_dir}/${file_prefix}${name}_${bus_width}_${pipe_lvl}.dcp 86 | set timing_log [report_timing_summary -setup -nworst 1 -return_string] 87 | if {[regexp {(VIOLATED)} $timing_log]} { 88 | set slack_met 0 89 | report_timing_summary -nworst 10 -file $log_dir/${file_prefix}timing_${name}_${bus_width}_${pipe_lvl}.log 90 | } else { 91 | set slack_met 1 92 | break 93 | } 94 | incr pipe_lvl 95 | } 96 | report_timing_summary -nworst 10 -file $log_dir/${file_prefix}timing_${name}_${bus_width}_${pipe_lvl}.log 97 | report_utilization -cells [get_cells u_crc_gen] -file $log_dir/${file_prefix}resource_${name}_${bus_width}.log 98 | regexp {CLB[ ]+\|[ ]+([0-9]+)} [report_utilization -cells [get_cells u_crc_gen] -return_string] matched clbs 99 | regexp {CLB LUTs[ ]+\|[ ]+([0-9]+)} [report_utilization -cells [get_cells u_crc_gen] -return_string] matched luts 100 | regexp {CLB Registers[ ]+\|[ ]+([0-9]+)} [report_utilization -cells [get_cells u_crc_gen] -return_string] matched ffs 101 | set throughput [format "%.1f" [expr $bus_width/2.0]] 102 | if {$byteEn} { 103 | set latency [format "%.1f" [expr 2*($pipe_lvl+2+log($bus_width/8)/log(2))]] 104 | } else { 105 | set latency [format "%.1f" [expr 2*($pipe_lvl+1)]] 106 | } 107 | puts "$name,$poly,$bus_width:$pipe_lvl,$throughput,$latency,$clbs,$luts,$ffs" 108 | set result_f [open $result_csv a] 109 | puts $result_f "$name,$poly,$bus_width,$pipe_lvl,$throughput,$latency,$clbs,$luts,$ffs" 110 | close $result_f 111 | close_project 112 | } 113 | } 114 | puts "finished runs, the result table can be found at ${result_dir}" 115 | exit 116 | -------------------------------------------------------------------------------- /performance_evaluation/workdir/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.keep 4 | -------------------------------------------------------------------------------- /performance_evaluation/workdir/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UofT-HPRC/Tbps_CRC/134c67845f2db14a991b7a2b8216ba182180ba47/performance_evaluation/workdir/.keep --------------------------------------------------------------------------------