├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── blake2s.core ├── data └── sky130.tcl ├── src ├── model │ ├── LICENSE │ ├── Makefile │ ├── blake2s.c │ ├── blake2s.h │ └── blake2s_test.c ├── rtl │ ├── blake2s.v │ ├── blake2s_G.v │ ├── blake2s_core.v │ └── blake2s_m_select.v └── tb │ ├── tb_blake2s.v │ ├── tb_blake2s_G.v │ ├── tb_blake2s_core.v │ └── tb_blake2s_m_select.v └── toolruns └── Makefile /.gitattributes: -------------------------------------------------------------------------------- 1 | # Helping linguist detect files as Verilog, not Coq. 2 | *.v linguist-language=Verilog 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build-openlane-sky130 2 | on: [push] 3 | 4 | jobs: 5 | build-blake2s: 6 | runs-on: ubuntu-latest 7 | env: 8 | REPO : blake2s 9 | VLNV : secworks:crypto:blake2s 10 | steps: 11 | - name: Checkout repo 12 | uses: actions/checkout@v3 13 | with: 14 | path: blake2s 15 | - run: echo "EDALIZE_LAUNCHER=el_docker" >> $GITHUB_ENV 16 | - run: pip3 install fusesoc 17 | - run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO 18 | - run: fusesoc run --target=sky130 $VLNV 19 | 20 | sim-icarus: 21 | runs-on: ubuntu-latest 22 | env: 23 | REPO : blake2s 24 | VLNV : secworks:crypto:blake2s 25 | steps: 26 | - name: Checkout repo 27 | uses: actions/checkout@v3 28 | with: 29 | path: blake2s 30 | - run: sudo apt install iverilog 31 | - run: pip3 install fusesoc 32 | - run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO 33 | - run: fusesoc run --target=tb_blake2s $VLNV 34 | 35 | lint-verilator: 36 | runs-on: ubuntu-latest 37 | env: 38 | REPO : blake2s 39 | VLNV : secworks:crypto:blake2s 40 | steps: 41 | - name: Checkout repo 42 | uses: actions/checkout@v3 43 | with: 44 | path: blake2s 45 | - run: sudo apt install verilator 46 | - run: pip3 install fusesoc 47 | - run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO 48 | - run: fusesoc run --target=lint $VLNV 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #======================================================================= 2 | # 3 | # .gitignore 4 | # ---------- 5 | # Gitignore for core projects. 6 | #======================================================================= 7 | 8 | ## Generated files 9 | *.sim 10 | 11 | ## Log files 12 | *.log 13 | *.txt 14 | test_* 15 | /src/model/logs 16 | 17 | ## Subdirs in toolruns for vendor tools 18 | /toolruns/quartus 19 | /toolruns/ise/ 20 | /toolruns/vivado 21 | /toolruns/modelsim 22 | /toolruns/libero 23 | /toolruns/icestorm 24 | 25 | #======================================================================= 26 | # EOF .gitignore 27 | #======================================================================= 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, Assured AB 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![build-openlane-sky130](https://github.com/secworks/blake2s/actions/workflows/ci.yml/badge.svg?branch=master&event=push)](https://github.com/secworks/blake2s/actions/workflows/ci.yml) 2 | 3 | # blake2s 4 | Verilog implementation of the [BLAKE2s](https://blake2.net/) hash function. 5 | 6 | 7 | ## Implementation status 8 | Implementation completed. Functionally correct. Functionally verified in 9 | real hardware. *Ready for use*. 10 | 11 | 12 | ## Introduction 13 | BLAKE2s is 32-bit, embedded- and hardware-oriented version of the BLAKE2 hash 14 | function. See the [BLAKE2 paper](https://blake2.net/blake2.pdf) for more 15 | information. Additionally, [RFC 16 | 7693](https://tools.ietf.org/html/rfc7693) contains a good description, 17 | a reference model and a test vecrtor. 18 | 19 | BLAKE2s operates on 32-bit words and produces digests of up to 20 | 32 bytes. This version of BLAKE2s always generates a 32 byte (i.e. 256 21 | bit) digest. 22 | 23 | This repository contains a forked version of the BLAKE2s reference model 24 | by Markku-Juhani O. Saarinen that appears in [RFC 7693](https://www.rfc-editor.org/rfc/rfc7693.html). 25 | The original repository [can be found 26 | here](https://github.com/mjosaarinen/blake2_mjosref). The forked version 27 | contains additional test cases that checks corner cases. The forked 28 | version has also been instrumented to display internal values during 29 | processing. The model has been used to drive the functional 30 | verification of the core. 31 | 32 | 33 | ### Contact information ## 34 | Assured provides customer support including customization, integration 35 | and system development related to the core. For more information, 36 | please contact [Assured Security 37 | Consultants](https://www.assured.se/contact). 38 | 39 | 40 | ## Operation 41 | The core API follows the description in the BLAKE2s paper and the RFC, 42 | with separate calls to init(), update() and finish() the 43 | processing. (Note that finish() is called final() in the paper and the 44 | RFC, but final() is a reserved word in Verilog). 45 | 46 | One must always perform a init() operation separately, before any 47 | update() or finish() operations. One must also always perform a finish() 48 | operation to get the final digest. 49 | 50 | For messages smaller than a single 64 byte block, update() should not be 51 | called. Instead finish() should be called. It is the callers 52 | responsibility to set the blocklength to indicate the number of 53 | bytes. (A possible future improvement is to assume that the block size 54 | is 64 bytes for all blocks processed using the update() operation.) 55 | 56 | For messages spanning more than one block, perform as many update() 57 | operations as there are complete blocks and then a single final() 58 | operation. 59 | 60 | 61 | ### FuseSoC 62 | This core is supported by the 63 | [FuseSoC](https://github.com/olofk/fusesoc) core package manager and 64 | build system. Some quick FuseSoC instructions: 65 | 66 | install FuseSoC 67 | ~~~ 68 | pip install fusesoc 69 | ~~~ 70 | 71 | Create and enter a new workspace 72 | ~~~ 73 | mkdir workspace && cd workspace 74 | ~~~ 75 | 76 | Register blake2s as a library in the workspace 77 | ~~~ 78 | fusesoc library add blake2s /path/to/blake2s 79 | ~~~ 80 | 81 | ...if repo is available locally or... 82 | ...to get the upstream repo 83 | ~~~ 84 | fusesoc library add blake2s https://github.com/secworks/blake2s 85 | ~~~ 86 | 87 | To run lint 88 | ~~~ 89 | fusesoc run --target=lint secworks:crypto:blake2s 90 | ~~~ 91 | 92 | Run tb_blake2s testbench 93 | ~~~ 94 | fusesoc run --target=tb_blake2s secworks:crypto:blake2s 95 | ~~~ 96 | 97 | Run with modelsim instead of default tool (icarus) 98 | ~~~ 99 | fusesoc run --target=tb_blake2s --tool=modelsim secworks:crypto:blake2s 100 | ~~~ 101 | 102 | List all targets 103 | ~~~ 104 | fusesoc core show secworks:crypto:blake2s 105 | ~~~ 106 | 107 | 108 | ## Performance 109 | A single block is processed in 24 cycles. Of these 20 cycles is for the 10 110 | rounds. The init() operation takes two cycles, and the finish() 111 | operation takes two additional cycles besides 24 cycles for the final 112 | block processing. This means that for long messages, the core will take 113 | 0.375 cycles/byte. 114 | 115 | 116 | ## Implementation details 117 | The core is a high speed, big, yet iterative implemenatation. It will 118 | perform 10 rounds in sequence. But the core contains four G_function 119 | instantiations and can perform a round in two cycles. 120 | 121 | For more compact implementations, the core can be restructured to use 122 | two or just a single, shared G_function. 123 | 124 | The G_function itself is purely combinational logic, with no registers 125 | and no sharing of operations. For higher clock frequency, and/or a more 126 | compact implementation the G_function can be rewored to be pipelined and 127 | to share for example the adders. Note that this will have a big impact 128 | on the number of cycles required to process a block. Also the core 129 | itself will have to be updated to handle G_function latency beyond the 130 | currently expected one cycle latency. 131 | 132 | Note that there is no separate ports for key and key length. 133 | 134 | It is the callers responsibility to clear the unused bits in block 135 | containing less than 64 bytes. This holds for both the blake2s_core 136 | module and the blake2s top level wrapper. For the latter, this means 137 | writing one or more 32-bit all zero words. 138 | 139 | The core calculate message length based on the number of bytes given 140 | with each block. The core will also handle the last block as defined by 141 | the paper and the RFC. 142 | 143 | The message block buffer in blake_m_select.v is not mapped into a 144 | specific memory macro, and may be implemented with registers by the 145 | synthesis tool. For an efficient implementation, one would probably want 146 | to to change the implementation to use technology specific memory 147 | blocks. 148 | 149 | 150 | ## Implementation results 151 | Any implementation results provided would be greatly appreciated. 152 | 153 | 154 | ### Xilinx Artix 7 200T-1 ### 155 | - LUTs: 3387 156 | - Regs: 1893 157 | - Fmax: 61 MHz 158 | -------------------------------------------------------------------------------- /blake2s.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name : secworks:crypto:blake2s:0 4 | 5 | filesets: 6 | rtl: 7 | files: 8 | - src/rtl/blake2s.v 9 | - src/rtl/blake2s_core.v 10 | - src/rtl/blake2s_m_select.v 11 | - src/rtl/blake2s_G.v 12 | file_type : verilogSource 13 | 14 | tb: 15 | files: 16 | - src/tb/tb_blake2s.v 17 | file_type : verilogSource 18 | 19 | openlane: {files : [data/sky130.tcl : {file_type : tclSource}]} 20 | 21 | targets: 22 | default: 23 | filesets: [rtl] 24 | 25 | lint: 26 | default_tool : verilator 27 | filesets : [rtl] 28 | tools: 29 | verilator: 30 | mode : lint-only 31 | toplevel : blake2s 32 | 33 | sky130: 34 | default_tool: openlane 35 | filesets: [rtl, openlane] 36 | toplevel: blake2s 37 | 38 | tb_blake2s : &tb 39 | default_tool: icarus 40 | filesets: [rtl, tb] 41 | toplevel : tb_blake2s 42 | -------------------------------------------------------------------------------- /data/sky130.tcl: -------------------------------------------------------------------------------- 1 | 2 | # Design 3 | set ::env(CLOCK_PORT) "clk" 4 | set ::env(CLOCK_NET) $::env(CLOCK_PORT) 5 | set ::env(FP_CORE_UTIL) 20 6 | set ::env(SYNTH_MAX_FANOUT) 8 7 | set ::env(PL_TARGET_DENSITY) 0.25 8 | set ::env(CLOCK_PERIOD) "25.9" -------------------------------------------------------------------------------- /src/model/LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /src/model/Makefile: -------------------------------------------------------------------------------- 1 | #=================================================================== 2 | # 3 | # Makefile 4 | # -------- 5 | # Makefile for building the blake2s model. 6 | # 7 | # 8 | # Author: Joachim Strombergson 9 | # Copyright (c) 2014, Secworks Sweden AB 10 | # All rights reserved. 11 | # 12 | # Redistribution and use in source and binary forms, with or 13 | # without modification, are permitted provided that the following 14 | # conditions are met: 15 | # 16 | # 1. Redistributions of source code must retain the above copyright 17 | # notice, this list of conditions and the following disclaimer. 18 | # 19 | # 2. Redistributions in binary form must reproduce the above copyright 20 | # notice, this list of conditions and the following disclaimer in 21 | # the documentation and/or other materials provided with the 22 | # distribution. 23 | # 24 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | # 37 | #=================================================================== 38 | 39 | SRC = blake2s_test.c blake2s.c 40 | INC = blake2s.h 41 | 42 | CC = clang 43 | CC_FLAGS = -Wall 44 | 45 | blake2s_test: $(SRC) $(INC) 46 | $(CC) $(CC_FLAGS) -o $@ $(SRC) -I $(INC) 47 | 48 | 49 | clean: 50 | rm -f ./blake2s_test 51 | rm -f *.log 52 | rm -f *.txt 53 | -------------------------------------------------------------------------------- /src/model/blake2s.c: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s.c 4 | // --------- 5 | // 6 | // A simple BLAKE2s reference implementation. 7 | // 8 | // See LICENSE for license terms. 9 | // See README.md in the repo root for info about source code origin. 10 | //====================================================================== 11 | 12 | #include 13 | #include "blake2s.h" 14 | 15 | #define VERBOSE 0 16 | #define SHOW_V 0 17 | #define SHOW_M_WORDS 0 18 | 19 | 20 | // Cyclic right rotation. 21 | #ifndef ROTR32 22 | #define ROTR32(x, y) (((x) >> (y)) ^ ((x) << (32 - (y)))) 23 | #endif 24 | 25 | 26 | // Little-endian byte access. 27 | #define B2S_GET32(p) \ 28 | (((uint32_t) ((uint8_t *) (p))[0]) ^ \ 29 | (((uint32_t) ((uint8_t *) (p))[1]) << 8) ^ \ 30 | (((uint32_t) ((uint8_t *) (p))[2]) << 16) ^ \ 31 | (((uint32_t) ((uint8_t *) (p))[3]) << 24)) 32 | 33 | 34 | // Initialization Vector. 35 | static const uint32_t blake2s_iv[8] = { 36 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 37 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 38 | }; 39 | 40 | 41 | //------------------------------------------------------------------ 42 | //------------------------------------------------------------------ 43 | void print_v(uint32_t *v) { 44 | printf("0x%08x, 0x%08x, 0x%08x, 0x%08x\n", v[0], v[1], v[2], v[3]); 45 | printf("0x%08x, 0x%08x, 0x%08x, 0x%08x\n", v[4], v[5], v[6], v[7]); 46 | printf("0x%08x, 0x%08x, 0x%08x, 0x%08x\n", v[8], v[9], v[10], v[11]); 47 | printf("0x%08x, 0x%08x, 0x%08x, 0x%08x\n", v[12], v[13], v[14], v[15]); 48 | printf("\n"); 49 | } 50 | 51 | 52 | //------------------------------------------------------------------ 53 | // print_ctx() 54 | // Print the contents of the context data structure. 55 | //------------------------------------------------------------------ 56 | void print_ctx(blake2s_ctx *ctx) { 57 | printf("Chained state (h):\n"); 58 | printf("0x%08x, 0x%08x, 0x%08x, 0x%08x, ", 59 | ctx->h[0], ctx->h[1], ctx->h[2], ctx->h[3]); 60 | printf("0x%08x, 0x%08x, 0x%08x, 0x%08x", 61 | ctx->h[4], ctx->h[5], ctx->h[6], ctx->h[7]); 62 | printf("\n"); 63 | 64 | printf("Byte counter (t):\n"); 65 | printf("0x%08x, 0x%08x", ctx->t[0], ctx->t[1]); 66 | printf("\n"); 67 | 68 | printf("\n"); 69 | } 70 | 71 | 72 | //------------------------------------------------------------------ 73 | // B2S_G macro redefined as a G function. 74 | // Allows us to output intermediate values for debugging. 75 | //------------------------------------------------------------------ 76 | void G(uint32_t *v, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t y) { 77 | if (VERBOSE) { 78 | printf("G started.\n"); 79 | } 80 | 81 | if (SHOW_V) { 82 | printf("v before processing:\n"); 83 | print_v(&v[0]); 84 | } 85 | 86 | if (SHOW_M_WORDS) { 87 | printf("x: 0x%08x, y: 0x%08x\n", x, y); 88 | } 89 | 90 | v[a] = v[a] + v[b] + x; 91 | v[d] = ROTR32(v[d] ^ v[a], 16); 92 | v[c] = v[c] + v[d]; 93 | v[b] = ROTR32(v[b] ^ v[c], 12); 94 | v[a] = v[a] + v[b] + y; 95 | v[d] = ROTR32(v[d] ^ v[a], 8); 96 | v[c] = v[c] + v[d]; 97 | v[b] = ROTR32(v[b] ^ v[c], 7); 98 | 99 | if (SHOW_V) { 100 | printf("v after processing:\n"); 101 | print_v(&v[0]); 102 | } 103 | 104 | if (VERBOSE) { 105 | printf("G completed.\n\n"); 106 | } 107 | } 108 | 109 | 110 | //------------------------------------------------------------------ 111 | // Compression function. "last" flag indicates last block. 112 | //------------------------------------------------------------------ 113 | static void blake2s_compress(blake2s_ctx *ctx, int last) 114 | { 115 | const uint8_t sigma[10][16] = { 116 | {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 117 | {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, 118 | {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, 119 | {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, 120 | {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, 121 | {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, 122 | {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, 123 | {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, 124 | {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, 125 | {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0} 126 | }; 127 | 128 | int i; 129 | uint32_t v[16], m[16]; 130 | 131 | if (VERBOSE) { 132 | printf("blake2s_compress started.\n"); 133 | } 134 | 135 | // init work variables 136 | for (i = 0; i < 8; i++) { 137 | v[i] = ctx->h[i]; 138 | v[i + 8] = blake2s_iv[i]; 139 | } 140 | 141 | // low 32 bits of offset 142 | // high 32 bits 143 | if (VERBOSE) { 144 | printf("t[0]: 0x%08x, t[1]: 0x%08x\n", ctx->t[0], ctx->t[1]); 145 | } 146 | v[12] ^= ctx->t[0]; 147 | v[13] ^= ctx->t[1]; 148 | 149 | // last block flag set ? 150 | if (last) { 151 | v[14] = ~v[14]; 152 | } 153 | 154 | // get little-endian words 155 | for (i = 0; i < 16; i++) { 156 | m[i] = B2S_GET32(&ctx->b[4 * i]); 157 | } 158 | 159 | if (VERBOSE) { 160 | printf("v before G processing:\n"); 161 | print_v(&v[0]); 162 | } 163 | 164 | // Ten rounds of the G function applied on rows, diagonal. 165 | for (i = 0; i < 10; i++) { 166 | if (VERBOSE) { 167 | printf("Round %02d:\n", (i + 1)); 168 | printf("Row processing started.\n"); 169 | } 170 | 171 | G(&v[0], 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]); 172 | G(&v[0], 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]); 173 | G(&v[0], 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]); 174 | G(&v[0], 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]); 175 | 176 | if (VERBOSE) { 177 | printf("Row processing completed.\n"); 178 | printf("Diagonal processing started.\n"); 179 | } 180 | 181 | G(&v[0], 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]); 182 | G(&v[0], 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]); 183 | G(&v[0], 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]); 184 | G(&v[0], 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]); 185 | 186 | if (VERBOSE) { 187 | printf("Diagonal processing completed.\n"); 188 | printf("\n"); 189 | } 190 | } 191 | 192 | if (VERBOSE) { 193 | printf("v after G processing:\n"); 194 | print_v(&v[0]); 195 | } 196 | 197 | // Update the hash state. 198 | for (i = 0; i < 8; ++i) { 199 | ctx->h[i] ^= v[i] ^ v[i + 8]; 200 | } 201 | 202 | if (VERBOSE) { 203 | printf("blake2s_compress completed.\n"); 204 | } 205 | } 206 | 207 | 208 | //------------------------------------------------------------------ 209 | // Initialize the hashing context "ctx" with optional key "key". 210 | // 1 <= outlen <= 32 gives the digest size in bytes. 211 | // Secret key (also <= 32 bytes) is optional (keylen = 0). 212 | //------------------------------------------------------------------ 213 | int blake2s_init(blake2s_ctx *ctx, size_t outlen, 214 | const void *key, size_t keylen) // (keylen=0: no key) 215 | { 216 | size_t i; 217 | 218 | if (VERBOSE) { 219 | printf("blake2s_init started.\n"); 220 | printf("Context before blake2s_init processing:\n"); 221 | print_ctx(ctx); 222 | } 223 | 224 | if (outlen == 0 || outlen > 32 || keylen > 32) 225 | return -1; // illegal parameters 226 | 227 | for (i = 0; i < 8; i++) // state, "param block" 228 | ctx->h[i] = blake2s_iv[i]; 229 | ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen; 230 | 231 | ctx->t[0] = 0; // input count low word 232 | ctx->t[1] = 0; // input count high word 233 | ctx->c = 0; // pointer within buffer 234 | ctx->outlen = outlen; 235 | 236 | for (i = keylen; i < 64; i++) // zero input block 237 | ctx->b[i] = 0; 238 | if (keylen > 0) { 239 | blake2s_update(ctx, key, keylen); 240 | ctx->c = 64; // at the end 241 | } 242 | 243 | if (VERBOSE) { 244 | printf("Context after blake2s_init processing:\n"); 245 | print_ctx(ctx); 246 | printf("blake2s_init completed.\n"); 247 | } 248 | 249 | return 0; 250 | } 251 | 252 | 253 | //------------------------------------------------------------------ 254 | // Add "inlen" bytes from "in" into the hash. 255 | //------------------------------------------------------------------ 256 | void blake2s_update(blake2s_ctx *ctx, 257 | const void *in, size_t inlen) // data bytes 258 | { 259 | size_t i; 260 | 261 | if (VERBOSE) { 262 | printf("blake2s_update started.\n"); 263 | printf("Context before blake2s_update processing:\n"); 264 | print_ctx(ctx); 265 | } 266 | 267 | for (i = 0; i < inlen; i++) { 268 | if (ctx->c == 64) { // buffer full ? 269 | ctx->t[0] += ctx->c; // add counters 270 | if (ctx->t[0] < ctx->c) // carry overflow ? 271 | ctx->t[1]++; // high word 272 | blake2s_compress(ctx, 0); // compress (not last) 273 | ctx->c = 0; // counter to zero 274 | } 275 | ctx->b[ctx->c++] = ((const uint8_t *) in)[i]; 276 | } 277 | 278 | if (VERBOSE) { 279 | printf("Context after blake2s_update processing:\n"); 280 | print_ctx(ctx); 281 | printf("blake2s_update completed.\n"); 282 | } 283 | } 284 | 285 | 286 | //------------------------------------------------------------------ 287 | // Generate the message digest (size given in init). 288 | // Result placed in "out". 289 | //------------------------------------------------------------------ 290 | void blake2s_final(blake2s_ctx *ctx, void *out) 291 | { 292 | size_t i; 293 | 294 | if (VERBOSE) { 295 | printf("blake2s_final started.\n"); 296 | printf("Context before blake2s_final processing:\n"); 297 | print_ctx(ctx); 298 | } 299 | 300 | ctx->t[0] += ctx->c; // mark last block offset 301 | 302 | // carry overflow 303 | // high word 304 | if (ctx->t[0] < ctx->c) { 305 | ctx->t[1]++; 306 | } 307 | 308 | // fill up with zeros 309 | // final block flag = 1 310 | while (ctx->c < 64) { 311 | ctx->b[ctx->c++] = 0; 312 | } 313 | blake2s_compress(ctx, 1); 314 | 315 | // little endian convert and store 316 | for (i = 0; i < ctx->outlen; i++) { 317 | ((uint8_t *) out)[i] = 318 | (ctx->h[i >> 2] >> (8 * (i & 3))) & 0xFF; 319 | } 320 | 321 | if (VERBOSE) { 322 | printf("Context after blake2s_final processing:\n"); 323 | print_ctx(ctx); 324 | printf("blake2s_final completed.\n"); 325 | } 326 | } 327 | 328 | 329 | //------------------------------------------------------------------ 330 | // Convenience function for all-in-one computation. 331 | //------------------------------------------------------------------ 332 | int blake2s(void *out, size_t outlen, 333 | const void *key, size_t keylen, 334 | const void *in, size_t inlen) 335 | { 336 | blake2s_ctx ctx; 337 | 338 | if (blake2s_init(&ctx, outlen, key, keylen)) 339 | return -1; 340 | 341 | blake2s_update(&ctx, in, inlen); 342 | 343 | blake2s_final(&ctx, out); 344 | 345 | return 0; 346 | } 347 | 348 | //====================================================================== 349 | //====================================================================== 350 | -------------------------------------------------------------------------------- /src/model/blake2s.h: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s.h 4 | // --------- 5 | // BLAKE2s Hashing Context and API Prototypes 6 | // 7 | // See LICENSE for license terms. 8 | // See README.md in the repo root for info about source code origin. 9 | //====================================================================== 10 | 11 | #ifndef BLAKE2S_H 12 | #define BLAKE2S_H 13 | 14 | #include 15 | #include 16 | 17 | // state context 18 | typedef struct { 19 | uint8_t b[64]; // input buffer 20 | uint32_t h[8]; // chained state 21 | uint32_t t[2]; // total number of bytes 22 | size_t c; // pointer for b[] 23 | size_t outlen; // digest size 24 | } blake2s_ctx; 25 | 26 | // Initialize the hashing context "ctx" with optional key "key". 27 | // 1 <= outlen <= 32 gives the digest size in bytes. 28 | // Secret key (also <= 32 bytes) is optional (keylen = 0). 29 | int blake2s_init(blake2s_ctx *ctx, size_t outlen, 30 | const void *key, size_t keylen); // secret key 31 | 32 | // Add "inlen" bytes from "in" into the hash. 33 | void blake2s_update(blake2s_ctx *ctx, // context 34 | const void *in, size_t inlen); // data to be hashed 35 | 36 | // Generate the message digest (size given in init). 37 | // Result placed in "out". 38 | void blake2s_final(blake2s_ctx *ctx, void *out); 39 | 40 | // All-in-one convenience function. 41 | int blake2s(void *out, size_t outlen, // return buffer for digest 42 | const void *key, size_t keylen, // optional secret key 43 | const void *in, size_t inlen); // data to be hashed 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/model/blake2s_test.c: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s_test.c 4 | // -------------- 5 | // 6 | //====================================================================== 7 | 8 | #include 9 | #include "blake2s.h" 10 | 11 | 12 | //------------------------------------------------------------------ 13 | //------------------------------------------------------------------ 14 | void print_message(uint8_t *m, int mlen) { 15 | printf("The message:\n"); 16 | for (int i = 1 ; i <= mlen ; i++) { 17 | printf("0x%02x ", m[(i - 1)]); 18 | if (i % 8 == 0) { 19 | printf("\n"); 20 | } 21 | } 22 | printf("\n"); 23 | } 24 | 25 | 26 | //------------------------------------------------------------------ 27 | //------------------------------------------------------------------ 28 | void print_digest(uint8_t *md) { 29 | printf("The digest:\n"); 30 | for (int j = 0 ; j < 4 ; j++) { 31 | for (int i = 0 ; i < 8 ; i++) { 32 | printf("0x%02x ", md[i + 8 * j]); 33 | } 34 | printf("\n"); 35 | } 36 | printf("\n"); 37 | } 38 | 39 | 40 | //------------------------------------------------------------------ 41 | // test_zero_length() 42 | // Test with a zero length mwssage. 43 | //------------------------------------------------------------------ 44 | void test_zero_length() { 45 | 46 | uint8_t md[32]; 47 | 48 | printf("Testing zero byte message.\n"); 49 | blake2s(md, 32, NULL, 0, NULL, 0); 50 | print_digest(md); 51 | printf("\n"); 52 | } 53 | 54 | 55 | //------------------------------------------------------------------ 56 | // test_abc_message() 57 | // Test with a zero length mwssage. 58 | //------------------------------------------------------------------ 59 | void test_abc_message() { 60 | 61 | uint8_t md[32]; 62 | uint8_t msg[64] = {'a', 'b', 'c'}; 63 | 64 | printf("Testing with RFC 7693 three byte 'abc' message.\n"); 65 | print_message(msg, 3); 66 | 67 | blake2s(md, 32, NULL, 0, msg, 3); 68 | print_digest(md); 69 | printf("\n"); 70 | } 71 | 72 | 73 | //------------------------------------------------------------------ 74 | // test_one_block_message() 75 | // Test with a 64 byte message, filling one block. 76 | //------------------------------------------------------------------ 77 | void test_one_block_message() { 78 | 79 | uint8_t md[32]; 80 | uint8_t msg[64]; 81 | 82 | for (uint8_t i = 0 ; i < 64 ; i++) { 83 | msg[i] = i; 84 | } 85 | 86 | printf("Testing with 64 byte message.\n"); 87 | print_message(msg, 64); 88 | 89 | blake2s(md, 32, NULL, 0, msg, 64); 90 | print_digest(md); 91 | printf("\n"); 92 | } 93 | 94 | 95 | //------------------------------------------------------------------ 96 | // test_one_block_one_byte_message() 97 | // Test with a 65 byte message, filling one block and a single 98 | // byte in the next block. 99 | //------------------------------------------------------------------ 100 | void test_one_block_one_byte_message() { 101 | 102 | uint8_t md[32]; 103 | uint8_t msg[65]; 104 | 105 | for (uint8_t i = 0 ; i < 65 ; i++) { 106 | msg[i] = i; 107 | } 108 | 109 | printf("Testing with 65 byte message.\n"); 110 | print_message(msg, 65); 111 | 112 | blake2s(md, 32, NULL, 0, msg, 65); 113 | print_digest(md); 114 | printf("\n"); 115 | } 116 | 117 | 118 | //------------------------------------------------------------------ 119 | //------------------------------------------------------------------ 120 | int main(void) { 121 | printf("\n"); 122 | printf("BLAKE2s reference model started. Performing a set of tests..\n"); 123 | printf("Performing a set of tests.\n"); 124 | 125 | test_zero_length(); 126 | test_abc_message(); 127 | test_one_block_message(); 128 | test_one_block_one_byte_message(); 129 | 130 | printf("BLAKE2s reference model completed.\n"); 131 | printf("\n"); 132 | 133 | return 0; 134 | } 135 | 136 | //====================================================================== 137 | /// EOF blake2s_test.c 138 | //====================================================================== 139 | -------------------------------------------------------------------------------- /src/rtl/blake2s.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s.v 4 | // -------- 5 | // Top level wrapper for the blake2s hash function core providing 6 | // a simple memory like interface with 32 bit data access. 7 | // 8 | // 9 | // Author: Joachim Strömbergson// Copyright (c) 2018, Assured AB 10 | // 11 | // Redistribution and use in source and binary forms, with or 12 | // without modification, are permitted provided that the following 13 | // conditions are met: 14 | // 15 | // 1. Redistributions of source code must retain the above copyright 16 | // notice, this list of conditions and the following disclaimer. 17 | // 18 | // 2. Redistributions in binary form must reproduce the above copyright 19 | // notice, this list of conditions and the following disclaimer in 20 | // the documentation and/or other materials provided with the 21 | // distribution. 22 | // 23 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 32 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 34 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // 36 | //====================================================================== 37 | 38 | module blake2s( 39 | input wire clk, 40 | input wire reset_n, 41 | 42 | input wire cs, 43 | input wire we, 44 | 45 | input wire [7 : 0] address, 46 | input wire [31 : 0] write_data, 47 | output wire [31 : 0] read_data 48 | ); 49 | 50 | 51 | //---------------------------------------------------------------- 52 | // Internal constant and parameter definitions. 53 | //---------------------------------------------------------------- 54 | localparam ADDR_NAME0 = 8'h00; 55 | localparam ADDR_NAME1 = 8'h01; 56 | localparam ADDR_VERSION = 8'h02; 57 | 58 | localparam ADDR_CTRL = 8'h08; 59 | localparam CTRL_INIT_BIT = 0; 60 | localparam CTRL_UPDATE_BIT = 1; 61 | localparam CTRL_FINISH_BIT = 2; 62 | 63 | localparam ADDR_STATUS = 8'h09; 64 | localparam STATUS_READY_BIT = 0; 65 | 66 | localparam ADDR_BLOCKLEN = 8'h0a; 67 | 68 | localparam ADDR_BLOCK0 = 8'h10; 69 | localparam ADDR_BLOCK15 = 8'h1f; 70 | 71 | localparam ADDR_DIGEST0 = 8'h40; 72 | localparam ADDR_DIGEST7 = 8'h47; 73 | 74 | 75 | localparam CORE_NAME0 = 32'h626c616b; // "blak" 76 | localparam CORE_NAME1 = 32'h65327320; // "e2s " 77 | localparam CORE_VERSION = 32'h302e3830; // "0.80" 78 | 79 | 80 | //---------------------------------------------------------------- 81 | // Registers including update variables and write enable. 82 | //---------------------------------------------------------------- 83 | reg init_reg; 84 | reg init_new; 85 | reg update_reg; 86 | reg update_new; 87 | reg finish_reg; 88 | reg finish_new; 89 | reg [6 : 0] blocklen_reg; 90 | reg blocklen_we; 91 | 92 | reg [31 : 0] block_mem [0 : 15]; 93 | reg block_mem_we; 94 | 95 | 96 | //---------------------------------------------------------------- 97 | // Wires. 98 | //---------------------------------------------------------------- 99 | wire core_ready; 100 | wire [511 : 0] core_block; 101 | wire [255 : 0] core_digest; 102 | 103 | reg [31 : 0] tmp_read_data; 104 | 105 | 106 | //---------------------------------------------------------------- 107 | // Concurrent connectivity for ports etc. 108 | //---------------------------------------------------------------- 109 | assign core_block = {block_mem[0], block_mem[1], block_mem[2], block_mem[3], 110 | block_mem[4], block_mem[5], block_mem[6], block_mem[7], 111 | block_mem[8], block_mem[9], block_mem[10], block_mem[11], 112 | block_mem[12], block_mem[13], block_mem[14], block_mem[15]}; 113 | 114 | assign read_data = tmp_read_data; 115 | 116 | 117 | //---------------------------------------------------------------- 118 | // core instantiation. 119 | //---------------------------------------------------------------- 120 | blake2s_core core( 121 | .clk(clk), 122 | .reset_n(reset_n), 123 | 124 | .init(init_reg), 125 | .update(update_reg), 126 | .finish(finish_reg), 127 | 128 | .block(core_block), 129 | .blocklen(blocklen_reg), 130 | 131 | .digest(core_digest), 132 | .ready(core_ready) 133 | ); 134 | 135 | 136 | //---------------------------------------------------------------- 137 | // reg_update 138 | //---------------------------------------------------------------- 139 | always @ (posedge clk) 140 | begin : reg_update 141 | integer i; 142 | 143 | if (!reset_n) 144 | begin 145 | for (i = 0 ; i < 16 ; i = i + 1) 146 | block_mem[i] <= 32'h0; 147 | 148 | init_reg <= 1'h0; 149 | update_reg <= 1'h0; 150 | finish_reg <= 1'h0; 151 | blocklen_reg <= 7'h0; 152 | end 153 | else 154 | begin 155 | init_reg <= init_new; 156 | update_reg <= update_new; 157 | finish_reg <= finish_new; 158 | 159 | if (blocklen_we) begin 160 | blocklen_reg <= write_data[6 : 0]; 161 | end 162 | 163 | if (block_mem_we) begin 164 | block_mem[address[3 : 0]] <= write_data; 165 | end 166 | end 167 | end // reg_update 168 | 169 | 170 | //---------------------------------------------------------------- 171 | // api 172 | // The interface command decoding logic. 173 | //---------------------------------------------------------------- 174 | always @* 175 | begin : api 176 | init_new = 1'h0; 177 | update_new = 1'h0; 178 | finish_new = 1'h0; 179 | block_mem_we = 1'h0; 180 | blocklen_we = 1'h0; 181 | tmp_read_data = 32'h0; 182 | 183 | if (cs) 184 | begin 185 | if (we) 186 | begin 187 | if (address == ADDR_CTRL) begin 188 | init_new = write_data[CTRL_INIT_BIT]; 189 | update_new = write_data[CTRL_UPDATE_BIT]; 190 | finish_new = write_data[CTRL_FINISH_BIT]; 191 | end 192 | 193 | if (address == ADDR_BLOCKLEN) begin 194 | blocklen_we = 1; 195 | end 196 | 197 | if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15)) begin 198 | block_mem_we = 1; 199 | end 200 | end 201 | 202 | else 203 | begin 204 | if (address == ADDR_NAME0) begin 205 | tmp_read_data = CORE_NAME0; 206 | end 207 | 208 | if (address == ADDR_NAME1) begin 209 | tmp_read_data = CORE_NAME1; 210 | end 211 | 212 | if (address == ADDR_VERSION) begin 213 | tmp_read_data = CORE_VERSION; 214 | end 215 | 216 | if (address == ADDR_STATUS) begin 217 | tmp_read_data = {31'h0, core_ready}; 218 | end 219 | 220 | if ((address >= ADDR_DIGEST0) && (address <= ADDR_DIGEST7)) begin 221 | tmp_read_data = core_digest[(7 - (address - ADDR_DIGEST0)) * 32 +: 32]; 222 | end 223 | end 224 | end 225 | end // api 226 | endmodule // blake2s 227 | 228 | //====================================================================== 229 | // EOF blake2s.v 230 | //====================================================================== 231 | -------------------------------------------------------------------------------- /src/rtl/blake2s_G.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s_G.v 4 | // ----------- 5 | // Verilog 2001 implementation of the G function in the 6 | // blake2s hash function core. This is pure combinational logic in a 7 | // separade module to allow us to build versions with 1, 2, 4 8 | // and even 8 parallel compression functions. 9 | // 10 | // 11 | // Author: Joachim Strömbergson 12 | // Copyright (c) 2018, Assured AB 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or 16 | // without modification, are permitted provided that the following 17 | // conditions are met: 18 | // 19 | // 1. Redistributions of source code must retain the above copyright 20 | // notice, this list of conditions and the following disclaimer. 21 | // 22 | // 2. Redistributions in binary form must reproduce the above copyright 23 | // notice, this list of conditions and the following disclaimer in 24 | // the documentation and/or other materials provided with the 25 | // distribution. 26 | // 27 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 31 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 32 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 36 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 38 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | // 40 | //====================================================================== 41 | 42 | module blake2s_G( 43 | input wire [31 : 0] a, 44 | input wire [31 : 0] b, 45 | input wire [31 : 0] c, 46 | input wire [31 : 0] d, 47 | input wire [31 : 0] m0, 48 | input wire [31 : 0] m1, 49 | 50 | output wire [31 : 0] a_prim, 51 | output wire [31 : 0] b_prim, 52 | output wire [31 : 0] c_prim, 53 | output wire [31 : 0] d_prim 54 | ); 55 | 56 | 57 | //---------------------------------------------------------------- 58 | // Wires. 59 | //---------------------------------------------------------------- 60 | reg [31 : 0] a1; 61 | reg [31 : 0] a2; 62 | reg [31 : 0] b1; 63 | reg [31 : 0] b2; 64 | reg [31 : 0] b3; 65 | reg [31 : 0] b4; 66 | reg [31 : 0] c1; 67 | reg [31 : 0] c2; 68 | reg [31 : 0] d1; 69 | reg [31 : 0] d2; 70 | reg [31 : 0] d3; 71 | reg [31 : 0] d4; 72 | 73 | 74 | //---------------------------------------------------------------- 75 | // Concurrent connectivity for ports. 76 | //---------------------------------------------------------------- 77 | assign a_prim = a2; 78 | assign b_prim = b4; 79 | assign c_prim = c2; 80 | assign d_prim = d4; 81 | 82 | 83 | //---------------------------------------------------------------- 84 | // G_function 85 | //---------------------------------------------------------------- 86 | always @* 87 | begin : G_function 88 | a1 = a + b + m0; 89 | 90 | d1 = d ^ a1; 91 | d2 = {d1[15 : 0], d1[31 : 16]}; 92 | 93 | c1 = c + d2; 94 | 95 | b1 = b ^ c1; 96 | b2 = {b1[11 : 0], b1[31 : 12]}; 97 | 98 | a2 = a1 + b2 + m1; 99 | 100 | d3 = d2 ^ a2; 101 | d4 = {d3[7 : 0], d3[31 : 8]}; 102 | 103 | c2 = c1 + d4; 104 | 105 | b3 = b2 ^ c2; 106 | b4 = {b3[6 : 0], b3[31 : 7]}; 107 | end // G_function 108 | endmodule // blake2s_G 109 | 110 | //====================================================================== 111 | // EOF blake2s_G.v 112 | //====================================================================== 113 | -------------------------------------------------------------------------------- /src/rtl/blake2s_core.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s_core.v 4 | // -------------- 5 | // Verilog 2001 implementation of the hash function blake2s. 6 | // This is the internal core with wide interfaces. 7 | // 8 | // 9 | // Author: Joachim Strömbergson 10 | // Copyright (c) 2018, Assured AB 11 | // All rights reserved. 12 | // 13 | // Redistribution and use in source and binary forms, with or 14 | // without modification, are permitted provided that the following 15 | // conditions are met: 16 | // 17 | // 1. Redistributions of source code must retain the above copyright 18 | // notice, this list of conditions and the following disclaimer. 19 | // 20 | // 2. Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer in 22 | // the documentation and/or other materials provided with the 23 | // distribution. 24 | // 25 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 34 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 36 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | // 38 | //====================================================================== 39 | 40 | module blake2s_core( 41 | input wire clk, 42 | input wire reset_n, 43 | 44 | input wire init, 45 | input wire update, 46 | input wire finish, 47 | 48 | input wire [511 : 0] block, 49 | input wire [6 : 0] blocklen, 50 | 51 | output wire [255 : 0] digest, 52 | output wire ready 53 | ); 54 | 55 | 56 | //---------------------------------------------------------------- 57 | // Parameter block. 58 | // See BLAKE2 paper and RFC 7693 for definition. 59 | // Chapter 2.8 in https://blake2.net/blake2.pdf 60 | // Section 2.5 in https://tools.ietf.org/html/rfc7693 61 | //---------------------------------------------------------------- 62 | // The digest length in bytes. Minimum: 1, Maximum: 32 63 | localparam [7 : 0] DIGEST_LENGTH = 8'd32; 64 | localparam [7 : 0] KEY_LENGTH = 8'd0; 65 | localparam [7 : 0] FANOUT = 8'd1; 66 | localparam [7 : 0] DEPTH = 8'd01; 67 | localparam [31 : 0] LEAF_LENGTH = 32'd0; 68 | localparam [47 : 0] NODE_OFFSET = 48'd0; 69 | localparam [7 : 0] NODE_DEPTH = 8'd0; 70 | localparam [7 : 0] INNER_LENGTH = 8'd0; 71 | localparam [63 : 0] SALT = 64'h0; 72 | localparam [63 : 0] PERSONALIZATION = 64'h0; 73 | 74 | wire [255 : 0] parameter_block = {PERSONALIZATION, SALT, INNER_LENGTH, 75 | NODE_DEPTH, NODE_OFFSET, LEAF_LENGTH, 76 | DEPTH, FANOUT, KEY_LENGTH, DIGEST_LENGTH}; 77 | 78 | 79 | //---------------------------------------------------------------- 80 | // Internal constant definitions. 81 | //---------------------------------------------------------------- 82 | localparam NUM_ROUNDS = 10; 83 | localparam BLOCK_BYTES = 7'd64; 84 | 85 | // G function modes. 86 | localparam G_ROW = 1'h0; 87 | localparam G_DIAGONAL = 1'h1; 88 | 89 | // Initial vectors. 90 | localparam IV0 = 32'h6a09e667; 91 | localparam IV1 = 32'hbb67ae85; 92 | localparam IV2 = 32'h3c6ef372; 93 | localparam IV3 = 32'ha54ff53a; 94 | localparam IV4 = 32'h510e527f; 95 | localparam IV5 = 32'h9b05688c; 96 | localparam IV6 = 32'h1f83d9ab; 97 | localparam IV7 = 32'h5be0cd19; 98 | 99 | // Control FSM state names. 100 | localparam CTRL_IDLE = 3'h0; 101 | localparam CTRL_INIT_ROUND = 3'h1; 102 | localparam CTRL_G_ROW = 3'h2; 103 | localparam CTRL_G_DIAGONAL = 3'h3; 104 | localparam CTRL_COMP_DONE = 3'h4; 105 | localparam CTRL_FINISH = 3'h5; 106 | 107 | 108 | //---------------------------------------------------------------- 109 | // Registers including update variables and write enable. 110 | //---------------------------------------------------------------- 111 | reg [31 : 0] h_reg [0 : 7]; 112 | reg [31 : 0] h_new [0 : 7]; 113 | reg h_we; 114 | 115 | reg [31 : 0] v_reg [0 : 15]; 116 | reg [31 : 0] v_new [0 : 15]; 117 | reg v_we; 118 | reg init_v; 119 | reg update_v; 120 | 121 | reg [3 : 0] round_ctr_reg; 122 | reg [3 : 0] round_ctr_new; 123 | reg round_ctr_we; 124 | reg round_ctr_inc; 125 | reg round_ctr_rst; 126 | 127 | reg [31 : 0] t0_reg; 128 | reg [31 : 0] t0_new; 129 | reg t0_we; 130 | reg [31 : 0] t1_reg; 131 | reg [31 : 0] t1_new; 132 | reg t1_we; 133 | reg t_ctr_inc; 134 | reg t_ctr_rst; 135 | 136 | reg last_reg; 137 | reg last_new; 138 | reg last_we; 139 | 140 | reg ready_reg; 141 | reg ready_new; 142 | reg ready_we; 143 | 144 | reg [2 : 0] blake2s_ctrl_reg; 145 | reg [2 : 0] blake2s_ctrl_new; 146 | reg blake2s_ctrl_we; 147 | 148 | 149 | //---------------------------------------------------------------- 150 | // Wires. 151 | //---------------------------------------------------------------- 152 | reg init_state; 153 | reg update_state; 154 | reg load_m; 155 | reg G_mode; 156 | 157 | reg [31 : 0] G0_a; 158 | reg [31 : 0] G0_b; 159 | reg [31 : 0] G0_c; 160 | reg [31 : 0] G0_d; 161 | wire [31 : 0] G0_m0; 162 | wire [31 : 0] G0_m1; 163 | wire [31 : 0] G0_a_prim; 164 | wire [31 : 0] G0_b_prim; 165 | wire [31 : 0] G0_c_prim; 166 | wire [31 : 0] G0_d_prim; 167 | 168 | reg [31 : 0] G1_a; 169 | reg [31 : 0] G1_b; 170 | reg [31 : 0] G1_c; 171 | reg [31 : 0] G1_d; 172 | wire [31 : 0] G1_m0; 173 | wire [31 : 0] G1_m1; 174 | wire [31 : 0] G1_a_prim; 175 | wire [31 : 0] G1_b_prim; 176 | wire [31 : 0] G1_c_prim; 177 | wire [31 : 0] G1_d_prim; 178 | 179 | reg [31 : 0] G2_a; 180 | reg [31 : 0] G2_b; 181 | reg [31 : 0] G2_c; 182 | reg [31 : 0] G2_d; 183 | wire [31 : 0] G2_m0; 184 | wire [31 : 0] G2_m1; 185 | wire [31 : 0] G2_a_prim; 186 | wire [31 : 0] G2_b_prim; 187 | wire [31 : 0] G2_c_prim; 188 | wire [31 : 0] G2_d_prim; 189 | 190 | reg [31 : 0] G3_a; 191 | reg [31 : 0] G3_b; 192 | reg [31 : 0] G3_c; 193 | reg [31 : 0] G3_d; 194 | wire [31 : 0] G3_m0; 195 | wire [31 : 0] G3_m1; 196 | wire [31 : 0] G3_a_prim; 197 | wire [31 : 0] G3_b_prim; 198 | wire [31 : 0] G3_c_prim; 199 | wire [31 : 0] G3_d_prim; 200 | 201 | 202 | //---------------------------------------------------------------- 203 | // Module instantations. 204 | //---------------------------------------------------------------- 205 | blake2s_m_select mselect( 206 | .clk(clk), 207 | .reset_n(reset_n), 208 | .load(load_m), 209 | .m(block), 210 | .round(round_ctr_reg), 211 | .mode(G_mode), 212 | .G0_m0(G0_m0), 213 | .G0_m1(G0_m1), 214 | .G1_m0(G1_m0), 215 | .G1_m1(G1_m1), 216 | .G2_m0(G2_m0), 217 | .G2_m1(G2_m1), 218 | .G3_m0(G3_m0), 219 | .G3_m1(G3_m1) 220 | ); 221 | 222 | 223 | blake2s_G G0( 224 | .a(G0_a), 225 | .b(G0_b), 226 | .c(G0_c), 227 | .d(G0_d), 228 | .m0(G0_m0), 229 | .m1(G0_m1), 230 | .a_prim(G0_a_prim), 231 | .b_prim(G0_b_prim), 232 | .c_prim(G0_c_prim), 233 | .d_prim(G0_d_prim) 234 | ); 235 | 236 | 237 | blake2s_G G1( 238 | .a(G1_a), 239 | .b(G1_b), 240 | .c(G1_c), 241 | .d(G1_d), 242 | .m0(G1_m0), 243 | .m1(G1_m1), 244 | .a_prim(G1_a_prim), 245 | .b_prim(G1_b_prim), 246 | .c_prim(G1_c_prim), 247 | .d_prim(G1_d_prim) 248 | ); 249 | 250 | 251 | blake2s_G G2( 252 | .a(G2_a), 253 | .b(G2_b), 254 | .c(G2_c), 255 | .d(G2_d), 256 | .m0(G2_m0), 257 | .m1(G2_m1), 258 | 259 | .a_prim(G2_a_prim), 260 | .b_prim(G2_b_prim), 261 | .c_prim(G2_c_prim), 262 | .d_prim(G2_d_prim) 263 | ); 264 | 265 | 266 | blake2s_G G3( 267 | .a(G3_a), 268 | .b(G3_b), 269 | .c(G3_c), 270 | .d(G3_d), 271 | .m0(G3_m0), 272 | .m1(G3_m1), 273 | .a_prim(G3_a_prim), 274 | .b_prim(G3_b_prim), 275 | .c_prim(G3_c_prim), 276 | .d_prim(G3_d_prim) 277 | ); 278 | 279 | 280 | //---------------------------------------------------------------- 281 | // Concurrent connectivity for ports etc. 282 | //---------------------------------------------------------------- 283 | assign digest = {h_reg[0][7 : 0], h_reg[0][15 : 8], h_reg[0][23 : 16], h_reg[0][31 : 24], 284 | h_reg[1][7 : 0], h_reg[1][15 : 8], h_reg[1][23 : 16], h_reg[1][31 : 24], 285 | h_reg[2][7 : 0], h_reg[2][15 : 8], h_reg[2][23 : 16], h_reg[2][31 : 24], 286 | h_reg[3][7 : 0], h_reg[3][15 : 8], h_reg[3][23 : 16], h_reg[3][31 : 24], 287 | h_reg[4][7 : 0], h_reg[4][15 : 8], h_reg[4][23 : 16], h_reg[4][31 : 24], 288 | h_reg[5][7 : 0], h_reg[5][15 : 8], h_reg[5][23 : 16], h_reg[5][31 : 24], 289 | h_reg[6][7 : 0], h_reg[6][15 : 8], h_reg[6][23 : 16], h_reg[6][31 : 24], 290 | h_reg[7][7 : 0], h_reg[7][15 : 8], h_reg[7][23 : 16], h_reg[7][31 : 24]}; 291 | 292 | assign ready = ready_reg; 293 | 294 | 295 | //---------------------------------------------------------------- 296 | // reg_update 297 | //---------------------------------------------------------------- 298 | always @ (posedge clk) 299 | begin : reg_update 300 | integer i; 301 | 302 | if (!reset_n) begin 303 | for (i = 0; i < 8; i = i + 1) begin 304 | h_reg[i] <= 32'h0; 305 | end 306 | 307 | for (i = 0; i < 16; i = i + 1) begin 308 | v_reg[i] <= 32'h0; 309 | end 310 | 311 | t0_reg <= 32'h0; 312 | t1_reg <= 32'h0; 313 | last_reg <= 1'h0; 314 | ready_reg <= 1'h1; 315 | round_ctr_reg <= 4'h0; 316 | blake2s_ctrl_reg <= CTRL_IDLE; 317 | end 318 | else begin 319 | if (h_we) begin 320 | for (i = 0; i < 8; i = i + 1) begin 321 | h_reg[i] <= h_new[i]; 322 | end 323 | end 324 | 325 | if (v_we) begin 326 | for (i = 0; i < 16; i = i + 1) begin 327 | v_reg[i] <= v_new[i]; 328 | end 329 | end 330 | 331 | if (t0_we) begin 332 | t0_reg <= t0_new; 333 | end 334 | 335 | if (t1_we) begin 336 | t1_reg <= t1_new; 337 | end 338 | 339 | if (last_we) begin 340 | last_reg <= last_new; 341 | end 342 | 343 | if (ready_we) begin 344 | ready_reg <= ready_new; 345 | end 346 | 347 | if (round_ctr_we) begin 348 | round_ctr_reg <= round_ctr_new; 349 | end 350 | 351 | if (blake2s_ctrl_we) begin 352 | blake2s_ctrl_reg <= blake2s_ctrl_new; 353 | end 354 | end 355 | end // reg_update 356 | 357 | 358 | //---------------------------------------------------------------- 359 | // state_logic 360 | // 361 | // Logic for updating the hash state. 362 | //---------------------------------------------------------------- 363 | always @* 364 | begin : state_logic 365 | integer i; 366 | 367 | for (i = 0; i < 8; i = i + 1) begin 368 | h_new[i] = 32'h0; 369 | end 370 | h_we = 1'h0; 371 | 372 | if (init_state) begin 373 | h_new[0] = IV0 ^ parameter_block[31 : 0]; 374 | h_new[1] = IV1 ^ parameter_block[63 : 32]; 375 | h_new[2] = IV2 ^ parameter_block[95 : 64]; 376 | h_new[3] = IV3 ^ parameter_block[127 : 96]; 377 | h_new[4] = IV4 ^ parameter_block[159 : 128]; 378 | h_new[5] = IV5 ^ parameter_block[191 : 160]; 379 | h_new[6] = IV6 ^ parameter_block[223 : 192]; 380 | h_new[7] = IV7 ^ parameter_block[255 : 224]; 381 | h_we = 1; 382 | end 383 | 384 | if (update_state) begin 385 | h_new[0] = h_reg[0] ^ v_reg[0] ^ v_reg[8]; 386 | h_new[1] = h_reg[1] ^ v_reg[1] ^ v_reg[9]; 387 | h_new[2] = h_reg[2] ^ v_reg[2] ^ v_reg[10]; 388 | h_new[3] = h_reg[3] ^ v_reg[3] ^ v_reg[11]; 389 | h_new[4] = h_reg[4] ^ v_reg[4] ^ v_reg[12]; 390 | h_new[5] = h_reg[5] ^ v_reg[5] ^ v_reg[13]; 391 | h_new[6] = h_reg[6] ^ v_reg[6] ^ v_reg[14]; 392 | h_new[7] = h_reg[7] ^ v_reg[7] ^ v_reg[15]; 393 | h_we = 1; 394 | end 395 | end // state_logic 396 | 397 | 398 | //---------------------------------------------------------------- 399 | // compress_logic 400 | //---------------------------------------------------------------- 401 | always @* 402 | begin : compress_logic 403 | integer i; 404 | 405 | for (i = 0; i < 16; i = i + 1) begin 406 | v_new[i] = 32'h0; 407 | end 408 | v_we = 1'h0; 409 | 410 | G0_a = 32'h0; 411 | G0_b = 32'h0; 412 | G0_c = 32'h0; 413 | G0_d = 32'h0; 414 | G1_a = 32'h0; 415 | G1_b = 32'h0; 416 | G1_c = 32'h0; 417 | G1_d = 32'h0; 418 | G2_a = 32'h0; 419 | G2_b = 32'h0; 420 | G2_c = 32'h0; 421 | G2_d = 32'h0; 422 | G3_a = 32'h0; 423 | G3_b = 32'h0; 424 | G3_c = 32'h0; 425 | G3_d = 32'h0; 426 | 427 | if (init_v) 428 | begin 429 | v_new[0] = h_reg[0]; 430 | v_new[1] = h_reg[1]; 431 | v_new[2] = h_reg[2]; 432 | v_new[3] = h_reg[3]; 433 | v_new[4] = h_reg[4]; 434 | v_new[5] = h_reg[5]; 435 | v_new[6] = h_reg[6]; 436 | v_new[7] = h_reg[7]; 437 | v_new[8] = IV0; 438 | v_new[9] = IV1; 439 | v_new[10] = IV2; 440 | v_new[11] = IV3; 441 | v_new[12] = t0_reg ^ IV4; 442 | v_new[13] = t1_reg ^ IV5; 443 | 444 | if (last_reg) begin 445 | v_new[14] = ~IV6; 446 | end else begin 447 | v_new[14] = IV6; 448 | end 449 | 450 | v_new[15] = IV7; 451 | v_we = 1; 452 | end 453 | 454 | if (update_v) 455 | begin 456 | v_we = 1; 457 | 458 | if (G_mode == G_ROW) begin 459 | // Row updates. 460 | G0_a = v_reg[0]; 461 | G0_b = v_reg[4]; 462 | G0_c = v_reg[8]; 463 | G0_d = v_reg[12]; 464 | v_new[0] = G0_a_prim; 465 | v_new[4] = G0_b_prim; 466 | v_new[8] = G0_c_prim; 467 | v_new[12] = G0_d_prim; 468 | 469 | G1_a = v_reg[1]; 470 | G1_b = v_reg[5]; 471 | G1_c = v_reg[9]; 472 | G1_d = v_reg[13]; 473 | v_new[1] = G1_a_prim; 474 | v_new[5] = G1_b_prim; 475 | v_new[9] = G1_c_prim; 476 | v_new[13] = G1_d_prim; 477 | 478 | G2_a = v_reg[2]; 479 | G2_b = v_reg[6]; 480 | G2_c = v_reg[10]; 481 | G2_d = v_reg[14]; 482 | v_new[2] = G2_a_prim; 483 | v_new[6] = G2_b_prim; 484 | v_new[10] = G2_c_prim; 485 | v_new[14] = G2_d_prim; 486 | 487 | G3_a = v_reg[3]; 488 | G3_b = v_reg[7]; 489 | G3_c = v_reg[11]; 490 | G3_d = v_reg[15]; 491 | v_new[3] = G3_a_prim; 492 | v_new[7] = G3_b_prim; 493 | v_new[11] = G3_c_prim; 494 | v_new[15] = G3_d_prim; 495 | end 496 | else begin 497 | // Diagonal updates. 498 | G0_a = v_reg[0]; 499 | G0_b = v_reg[5]; 500 | G0_c = v_reg[10]; 501 | G0_d = v_reg[15]; 502 | v_new[0] = G0_a_prim; 503 | v_new[5] = G0_b_prim; 504 | v_new[10] = G0_c_prim; 505 | v_new[15] = G0_d_prim; 506 | 507 | G1_a = v_reg[1]; 508 | G1_b = v_reg[6]; 509 | G1_c = v_reg[11]; 510 | G1_d = v_reg[12]; 511 | v_new[1] = G1_a_prim; 512 | v_new[6] = G1_b_prim; 513 | v_new[11] = G1_c_prim; 514 | v_new[12] = G1_d_prim; 515 | 516 | G2_a = v_reg[2]; 517 | G2_b = v_reg[7]; 518 | G2_c = v_reg[8]; 519 | G2_d = v_reg[13]; 520 | v_new[2] = G2_a_prim; 521 | v_new[7] = G2_b_prim; 522 | v_new[8] = G2_c_prim; 523 | v_new[13] = G2_d_prim; 524 | 525 | G3_a = v_reg[3]; 526 | G3_b = v_reg[4]; 527 | G3_c = v_reg[9]; 528 | G3_d = v_reg[14]; 529 | v_new[3] = G3_a_prim; 530 | v_new[4] = G3_b_prim; 531 | v_new[9] = G3_c_prim; 532 | v_new[14] = G3_d_prim; 533 | end 534 | end // if (update_v) 535 | end // compress_logic 536 | 537 | 538 | //---------------------------------------------------------------- 539 | // t_ctr 540 | // Update logic for the length counter t, a monotonically 541 | // increasing counter with reset. 542 | //---------------------------------------------------------------- 543 | always @* 544 | begin : t_ctr 545 | t0_new = 32'h0; 546 | t0_we = 1'h0; 547 | t1_new = 32'h0; 548 | t1_we = 1'h0; 549 | 550 | if (t_ctr_rst) begin 551 | t0_new = 32'h0; 552 | t0_we = 1'h1; 553 | t1_new = 32'h0; 554 | t1_we = 1'h1; 555 | end 556 | 557 | if (t_ctr_inc) begin 558 | t0_we = 1'h1; 559 | 560 | if (last_new) begin 561 | t0_new = t0_reg + {25'h0, blocklen}; 562 | end else begin 563 | t0_new = t0_reg + {25'h0, BLOCK_BYTES}; 564 | end 565 | 566 | if (t0_new < t0_reg) begin 567 | t1_new = t1_reg + 1'h1; 568 | t1_we = 1'h1; 569 | end 570 | end 571 | end // t_ctr 572 | 573 | 574 | //---------------------------------------------------------------- 575 | // round_ctr 576 | // Update logic for the round counter, a monotonically 577 | // increasing counter with reset. 578 | //---------------------------------------------------------------- 579 | always @* 580 | begin : round_ctr 581 | round_ctr_new = 4'h0; 582 | round_ctr_we = 1'h0; 583 | 584 | if (round_ctr_rst) 585 | begin 586 | round_ctr_new = 4'h0; 587 | round_ctr_we = 1'h1; 588 | end 589 | 590 | if (round_ctr_inc) 591 | begin 592 | round_ctr_new = round_ctr_reg + 1'b1; 593 | round_ctr_we = 1'h1; 594 | end 595 | end // round_ctr 596 | 597 | 598 | //---------------------------------------------------------------- 599 | // blake2s_ctrl 600 | //---------------------------------------------------------------- 601 | always @* 602 | begin : blake2s_ctrl 603 | init_state = 1'h0; 604 | update_state = 1'h0; 605 | init_v = 1'h0; 606 | update_v = 1'h0; 607 | load_m = 1'h0; 608 | G_mode = G_ROW; 609 | round_ctr_inc = 1'h0; 610 | round_ctr_rst = 1'h0; 611 | t_ctr_inc = 1'h0; 612 | t_ctr_rst = 1'h0; 613 | last_new = 1'h0; 614 | last_we = 1'h0; 615 | ready_new = 1'h0; 616 | ready_we = 1'h0; 617 | blake2s_ctrl_new = CTRL_IDLE; 618 | blake2s_ctrl_we = 1'h0; 619 | 620 | 621 | case (blake2s_ctrl_reg) 622 | CTRL_IDLE: begin 623 | if (init) begin 624 | last_new = 1'h0; 625 | last_we = 1'h1; 626 | init_state = 1'h1; 627 | t_ctr_rst = 1'h1; 628 | ready_new = 1'h0; 629 | ready_we = 1'h1; 630 | blake2s_ctrl_new = CTRL_FINISH; 631 | blake2s_ctrl_we = 1'h1; 632 | end 633 | 634 | if (update) begin 635 | if (blocklen == BLOCK_BYTES) begin 636 | load_m = 1'h1; 637 | t_ctr_inc = 1'h1; 638 | ready_new = 1'h0; 639 | ready_we = 1'h1; 640 | blake2s_ctrl_new = CTRL_INIT_ROUND; 641 | blake2s_ctrl_we = 1'h1; 642 | end 643 | end 644 | 645 | if (finish) begin 646 | load_m = 1'h1; 647 | t_ctr_inc = 1'h1; 648 | last_new = 1'h1; 649 | last_we = 1'h1; 650 | ready_new = 1'h0; 651 | ready_we = 1'h1; 652 | blake2s_ctrl_new = CTRL_INIT_ROUND; 653 | blake2s_ctrl_we = 1'h1; 654 | end 655 | end 656 | 657 | 658 | CTRL_INIT_ROUND: begin 659 | init_v = 1'h1; 660 | round_ctr_rst = 1'h1; 661 | blake2s_ctrl_new = CTRL_G_ROW; 662 | blake2s_ctrl_we = 1'h1; 663 | end 664 | 665 | 666 | CTRL_G_ROW: begin 667 | G_mode = G_ROW; 668 | update_v = 1'h1; 669 | blake2s_ctrl_new = CTRL_G_DIAGONAL; 670 | blake2s_ctrl_we = 1'h1; 671 | end 672 | 673 | 674 | CTRL_G_DIAGONAL: begin 675 | G_mode = G_DIAGONAL; 676 | update_v = 1'h1; 677 | round_ctr_inc = 1'h1; 678 | if (round_ctr_reg == (NUM_ROUNDS - 1)) begin 679 | blake2s_ctrl_new = CTRL_COMP_DONE; 680 | blake2s_ctrl_we = 1'h1; 681 | end 682 | else begin 683 | blake2s_ctrl_new = CTRL_G_ROW; 684 | blake2s_ctrl_we = 1'h1; 685 | end 686 | end 687 | 688 | 689 | CTRL_COMP_DONE: begin 690 | last_new = 1'h0; 691 | last_we = 1'h1; 692 | update_state = 1'h1; 693 | blake2s_ctrl_new = CTRL_FINISH; 694 | blake2s_ctrl_we = 1'h1; 695 | end 696 | 697 | 698 | CTRL_FINISH: begin 699 | ready_new = 1'h1; 700 | ready_we = 1'h1; 701 | blake2s_ctrl_new = CTRL_IDLE; 702 | blake2s_ctrl_we = 1'h1; 703 | end 704 | 705 | 706 | default: begin end 707 | endcase // case (blake2s_ctrl_reg) 708 | end // blake2s_ctrl 709 | endmodule // blake2s_core 710 | 711 | //====================================================================== 712 | // EOF blake2s_core.v 713 | //====================================================================== 714 | -------------------------------------------------------------------------------- /src/rtl/blake2s_m_select.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // blake2s_m_select.v 4 | // ------------------ 5 | // Verilog 2001 implementation of the message word selection in the 6 | // blake2 hash function core. Based on the given round and mode, we 7 | // extract the indices for the eight m words to select. 8 | // The words are then selected and returned. This is basically a 9 | // mux based implementation of the permutation table in combination 10 | // with the actual word selection. 11 | // 12 | // 13 | // Note that we use the mode to signal which indices to select 14 | // for a given round. This is because we don't do 8 G-functions 15 | // in a single cycle. 16 | // 17 | // 18 | // Author: Joachim Strömbergson 19 | // Copyright (c) 2018, Assured AB 20 | // All rights reserved. 21 | // 22 | // Redistribution and use in source and binary forms, with or 23 | // without modification, are permitted provided that the following 24 | // conditions are met: 25 | // 26 | // 1. Redistributions of source code must retain the above copyright 27 | // notice, this list of conditions and the following disclaimer. 28 | // 29 | // 2. Redistributions in binary form must reproduce the above copyright 30 | // notice, this list of conditions and the following disclaimer in 31 | // the documentation and/or other materials provided with the 32 | // distribution. 33 | // 34 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 35 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 36 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 37 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 38 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 39 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 40 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 41 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 42 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 43 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 45 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | // 47 | //====================================================================== 48 | 49 | module blake2s_m_select( 50 | input wire clk, 51 | input wire reset_n, 52 | 53 | input wire load, 54 | input wire [511 : 0] m, 55 | 56 | input wire [3 : 0] round, 57 | input wire mode, 58 | 59 | output wire [31 : 0] G0_m0, 60 | output wire [31 : 0] G0_m1, 61 | output wire [31 : 0] G1_m0, 62 | output wire [31 : 0] G1_m1, 63 | output wire [31 : 0] G2_m0, 64 | output wire [31 : 0] G2_m1, 65 | output wire [31 : 0] G3_m0, 66 | output wire [31 : 0] G3_m1 67 | ); 68 | 69 | 70 | //---------------------------------------------------------------- 71 | // regs. 72 | //---------------------------------------------------------------- 73 | reg [31 : 0] m_mem [0 : 15]; 74 | 75 | 76 | //---------------------------------------------------------------- 77 | // Wires. 78 | //---------------------------------------------------------------- 79 | reg [3 : 0] i_G0_m0; 80 | reg [3 : 0] i_G0_m1; 81 | reg [3 : 0] i_G1_m0; 82 | reg [3 : 0] i_G1_m1; 83 | reg [3 : 0] i_G2_m0; 84 | reg [3 : 0] i_G2_m1; 85 | reg [3 : 0] i_G3_m0; 86 | reg [3 : 0] i_G3_m1; 87 | 88 | 89 | //---------------------------------------------------------------- 90 | // Concurrent connectivity for ports. 91 | //---------------------------------------------------------------- 92 | // Eight parallel, muxes that extract the message block words. 93 | assign G0_m0 = m_mem[i_G0_m0]; 94 | assign G0_m1 = m_mem[i_G0_m1]; 95 | assign G1_m0 = m_mem[i_G1_m0]; 96 | assign G1_m1 = m_mem[i_G1_m1]; 97 | assign G2_m0 = m_mem[i_G2_m0]; 98 | assign G2_m1 = m_mem[i_G2_m1]; 99 | assign G3_m0 = m_mem[i_G3_m0]; 100 | assign G3_m1 = m_mem[i_G3_m1]; 101 | 102 | 103 | //---------------------------------------------------------------- 104 | // reg_update 105 | // 106 | // Update functionality for all registers in the core. 107 | // All registers are positive edge triggered with synchronous, 108 | // active low reset. All registers have write enable. 109 | //---------------------------------------------------------------- 110 | always @ (posedge clk) 111 | begin : reg_update 112 | integer i; 113 | 114 | if (!reset_n) 115 | begin 116 | for (i = 0 ; i < 16 ; i = i + 1) 117 | m_mem[i] <= 32'h0; 118 | end 119 | else 120 | begin 121 | if (load) 122 | begin 123 | // Big to little endian conversion during register load. 124 | m_mem[00] <= {m[0487 : 0480], m[0495 : 0488], m[0503 : 0496], m[0511 : 0504]}; 125 | m_mem[01] <= {m[0455 : 0448], m[0463 : 0456], m[0471 : 0464], m[0479 : 0472]}; 126 | m_mem[02] <= {m[0423 : 0416], m[0431 : 0424], m[0439 : 0432], m[0447 : 0440]}; 127 | m_mem[03] <= {m[0391 : 0384], m[0399 : 0392], m[0407 : 0400], m[0415 : 0408]}; 128 | m_mem[04] <= {m[0359 : 0352], m[0367 : 0360], m[0375 : 0368], m[0383 : 0376]}; 129 | m_mem[05] <= {m[0327 : 0320], m[0335 : 0328], m[0343 : 0336], m[0351 : 0344]}; 130 | m_mem[06] <= {m[0295 : 0288], m[0303 : 0296], m[0311 : 0304], m[0319 : 0312]}; 131 | m_mem[07] <= {m[0263 : 0256], m[0271 : 0264], m[0279 : 0272], m[0287 : 0280]}; 132 | m_mem[08] <= {m[0231 : 0224], m[0239 : 0232], m[0247 : 0240], m[0255 : 0248]}; 133 | m_mem[09] <= {m[0199 : 0192], m[0207 : 0200], m[0215 : 0208], m[0223 : 0216]}; 134 | m_mem[10] <= {m[0167 : 0160], m[0175 : 0168], m[0183 : 0176], m[0191 : 0184]}; 135 | m_mem[11] <= {m[0135 : 0128], m[0143 : 0136], m[0151 : 0144], m[0159 : 0152]}; 136 | m_mem[12] <= {m[0103 : 0096], m[0111 : 0104], m[0119 : 0112], m[0127 : 0120]}; 137 | m_mem[13] <= {m[0071 : 0064], m[0079 : 0072], m[0087 : 0080], m[0095 : 0088]}; 138 | m_mem[14] <= {m[0039 : 0032], m[0047 : 0040], m[0055 : 0048], m[0063 : 0056]}; 139 | m_mem[15] <= {m[0007 : 0000], m[0015 : 0008], m[0023 : 0016], m[0031 : 0024]}; 140 | end 141 | end 142 | end // reg_update 143 | 144 | 145 | //---------------------------------------------------------------- 146 | // get_indices 147 | // 148 | // Get the indices from the permutation table given the 149 | // round and the G function mode. This is the SIGMA table. 150 | //---------------------------------------------------------------- 151 | always @* 152 | begin : get_indices 153 | i_G0_m0 = 4'd0; 154 | i_G0_m1 = 4'd0; 155 | i_G1_m0 = 4'd0; 156 | i_G1_m1 = 4'd0; 157 | i_G2_m0 = 4'd0; 158 | i_G2_m1 = 4'd0; 159 | i_G3_m0 = 4'd0; 160 | i_G3_m1 = 4'd0; 161 | 162 | case ({round, mode}) 163 | 0: begin 164 | i_G0_m0 = 4'd00; 165 | i_G0_m1 = 4'd01; 166 | i_G1_m0 = 4'd02; 167 | i_G1_m1 = 4'd03; 168 | i_G2_m0 = 4'd04; 169 | i_G2_m1 = 4'd05; 170 | i_G3_m0 = 4'd06; 171 | i_G3_m1 = 4'd07; 172 | end 173 | 174 | 1: begin 175 | i_G0_m0 = 4'd08; 176 | i_G0_m1 = 4'd09; 177 | i_G1_m0 = 4'd10; 178 | i_G1_m1 = 4'd11; 179 | i_G2_m0 = 4'd12; 180 | i_G2_m1 = 4'd13; 181 | i_G3_m0 = 4'd14; 182 | i_G3_m1 = 4'd15; 183 | end 184 | 185 | 2: begin 186 | i_G0_m0 = 4'd14; 187 | i_G0_m1 = 4'd10; 188 | i_G1_m0 = 4'd04; 189 | i_G1_m1 = 4'd08; 190 | i_G2_m0 = 4'd09; 191 | i_G2_m1 = 4'd15; 192 | i_G3_m0 = 4'd13; 193 | i_G3_m1 = 4'd06; 194 | end 195 | 196 | 3: begin 197 | i_G0_m0 = 4'd01; 198 | i_G0_m1 = 4'd12; 199 | i_G1_m0 = 4'd00; 200 | i_G1_m1 = 4'd02; 201 | i_G2_m0 = 4'd11; 202 | i_G2_m1 = 4'd07; 203 | i_G3_m0 = 4'd05; 204 | i_G3_m1 = 4'd03; 205 | end 206 | 207 | 4: begin 208 | i_G0_m0 = 4'd11; 209 | i_G0_m1 = 4'd08; 210 | i_G1_m0 = 4'd12; 211 | i_G1_m1 = 4'd00; 212 | i_G2_m0 = 4'd05; 213 | i_G2_m1 = 4'd02; 214 | i_G3_m0 = 4'd15; 215 | i_G3_m1 = 4'd13; 216 | end 217 | 218 | 5: begin 219 | i_G0_m0 = 4'd10; 220 | i_G0_m1 = 4'd14; 221 | i_G1_m0 = 4'd03; 222 | i_G1_m1 = 4'd06; 223 | i_G2_m0 = 4'd07; 224 | i_G2_m1 = 4'd01; 225 | i_G3_m0 = 4'd09; 226 | i_G3_m1 = 4'd04; 227 | end 228 | 229 | 6: begin 230 | i_G0_m0 = 4'd07; 231 | i_G0_m1 = 4'd09; 232 | i_G1_m0 = 4'd03; 233 | i_G1_m1 = 4'd01; 234 | i_G2_m0 = 4'd13; 235 | i_G2_m1 = 4'd12; 236 | i_G3_m0 = 4'd11; 237 | i_G3_m1 = 4'd14; 238 | end 239 | 240 | 7: begin 241 | i_G0_m0 = 4'd02; 242 | i_G0_m1 = 4'd06; 243 | i_G1_m0 = 4'd05; 244 | i_G1_m1 = 4'd10; 245 | i_G2_m0 = 4'd04; 246 | i_G2_m1 = 4'd00; 247 | i_G3_m0 = 4'd15; 248 | i_G3_m1 = 4'd08; 249 | end 250 | 251 | 8: begin 252 | i_G0_m0 = 4'd09; 253 | i_G0_m1 = 4'd00; 254 | i_G1_m0 = 4'd05; 255 | i_G1_m1 = 4'd07; 256 | i_G2_m0 = 4'd02; 257 | i_G2_m1 = 4'd04; 258 | i_G3_m0 = 4'd10; 259 | i_G3_m1 = 4'd15; 260 | end 261 | 262 | 9: begin 263 | i_G0_m0 = 4'd14; 264 | i_G0_m1 = 4'd01; 265 | i_G1_m0 = 4'd11; 266 | i_G1_m1 = 4'd12; 267 | i_G2_m0 = 4'd06; 268 | i_G2_m1 = 4'd08; 269 | i_G3_m0 = 4'd03; 270 | i_G3_m1 = 4'd13; 271 | end 272 | 273 | 10: begin 274 | i_G0_m0 = 4'd02; 275 | i_G0_m1 = 4'd12; 276 | i_G1_m0 = 4'd06; 277 | i_G1_m1 = 4'd10; 278 | i_G2_m0 = 4'd00; 279 | i_G2_m1 = 4'd11; 280 | i_G3_m0 = 4'd08; 281 | i_G3_m1 = 4'd03; 282 | end 283 | 284 | 11: begin 285 | i_G0_m0 = 4'd04; 286 | i_G0_m1 = 4'd13; 287 | i_G1_m0 = 4'd07; 288 | i_G1_m1 = 4'd05; 289 | i_G2_m0 = 4'd15; 290 | i_G2_m1 = 4'd14; 291 | i_G3_m0 = 4'd01; 292 | i_G3_m1 = 4'd09; 293 | end 294 | 295 | 12: begin 296 | i_G0_m0 = 4'd12; 297 | i_G0_m1 = 4'd05; 298 | i_G1_m0 = 4'd01; 299 | i_G1_m1 = 4'd15; 300 | i_G2_m0 = 4'd14; 301 | i_G2_m1 = 4'd13; 302 | i_G3_m0 = 4'd04; 303 | i_G3_m1 = 4'd10; 304 | end 305 | 306 | 13: begin 307 | i_G0_m0 = 4'd00; 308 | i_G0_m1 = 4'd07; 309 | i_G1_m0 = 4'd06; 310 | i_G1_m1 = 4'd03; 311 | i_G2_m0 = 4'd09; 312 | i_G2_m1 = 4'd02; 313 | i_G3_m0 = 4'd08; 314 | i_G3_m1 = 4'd11; 315 | end 316 | 317 | 14: begin 318 | i_G0_m0 = 4'd13; 319 | i_G0_m1 = 4'd11; 320 | i_G1_m0 = 4'd07; 321 | i_G1_m1 = 4'd14; 322 | i_G2_m0 = 4'd12; 323 | i_G2_m1 = 4'd01; 324 | i_G3_m0 = 4'd03; 325 | i_G3_m1 = 4'd09; 326 | end 327 | 328 | 15: begin 329 | i_G0_m0 = 4'd05; 330 | i_G0_m1 = 4'd00; 331 | i_G1_m0 = 4'd15; 332 | i_G1_m1 = 4'd04; 333 | i_G2_m0 = 4'd08; 334 | i_G2_m1 = 4'd06; 335 | i_G3_m0 = 4'd02; 336 | i_G3_m1 = 4'd10; 337 | end 338 | 339 | 16: begin 340 | i_G0_m0 = 4'd06; 341 | i_G0_m1 = 4'd15; 342 | i_G1_m0 = 4'd14; 343 | i_G1_m1 = 4'd09; 344 | i_G2_m0 = 4'd11; 345 | i_G2_m1 = 4'd03; 346 | i_G3_m0 = 4'd00; 347 | i_G3_m1 = 4'd08; 348 | end 349 | 350 | 17: begin 351 | i_G0_m0 = 4'd12; 352 | i_G0_m1 = 4'd02; 353 | i_G1_m0 = 4'd13; 354 | i_G1_m1 = 4'd07; 355 | i_G2_m0 = 4'd01; 356 | i_G2_m1 = 4'd04; 357 | i_G3_m0 = 4'd10; 358 | i_G3_m1 = 4'd05; 359 | end 360 | 361 | 18: begin 362 | i_G0_m0 = 4'd10; 363 | i_G0_m1 = 4'd02; 364 | i_G1_m0 = 4'd08; 365 | i_G1_m1 = 4'd04; 366 | i_G2_m0 = 4'd07; 367 | i_G2_m1 = 4'd06; 368 | i_G3_m0 = 4'd01; 369 | i_G3_m1 = 4'd05; 370 | end 371 | 372 | 19: begin 373 | i_G0_m0 = 4'd15; 374 | i_G0_m1 = 4'd11; 375 | i_G1_m0 = 4'd09; 376 | i_G1_m1 = 4'd14; 377 | i_G2_m0 = 4'd03; 378 | i_G2_m1 = 4'd12; 379 | i_G3_m0 = 4'd13; 380 | i_G3_m1 = 4'd00; 381 | end 382 | 383 | default: begin end 384 | endcase // case ({round, mode}) 385 | end 386 | 387 | endmodule // blake2s_m_select 388 | 389 | //====================================================================== 390 | // EOF blake2s_m_select.v 391 | //====================================================================== 392 | -------------------------------------------------------------------------------- /src/tb/tb_blake2s.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // tb_blake2s.v 4 | // ----------- 5 | // Testbench for the blake2s top level wrapper 6 | // 7 | // 8 | // Author: Joachim Strombergson 9 | // Copyright (c) 2019, Assured AB 10 | // All rights reserved. 11 | // 12 | // Redistribution and use in source and binary forms, with or 13 | // without modification, are permitted provided that the following 14 | // conditions are met: 15 | // 16 | // 1. Redistributions of source code must retain the above copyright 17 | // notice, this list of conditions and the following disclaimer. 18 | // 19 | // 2. Redistributions in binary form must reproduce the above copyright 20 | // notice, this list of conditions and the following disclaimer in 21 | // the documentation and/or other materials provided with the 22 | // distribution. 23 | // 24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | // 37 | //====================================================================== 38 | 39 | `default_nettype none 40 | 41 | module tb_blake2s(); 42 | 43 | //---------------------------------------------------------------- 44 | // Internal constant and parameter definitions. 45 | //---------------------------------------------------------------- 46 | parameter DEBUG = 0; 47 | parameter DUMP_WAIT = 0; 48 | 49 | parameter CLK_HALF_PERIOD = 1; 50 | parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD; 51 | 52 | localparam ADDR_NAME0 = 8'h00; 53 | localparam ADDR_NAME1 = 8'h01; 54 | localparam ADDR_VERSION = 8'h02; 55 | 56 | localparam ADDR_CTRL = 8'h08; 57 | localparam CTRL_INIT_BIT = 0; 58 | localparam CTRL_UPDATE_BIT = 1; 59 | localparam CTRL_FINISH_BIT = 2; 60 | 61 | localparam ADDR_STATUS = 8'h09; 62 | localparam STATUS_READY_BIT = 0; 63 | 64 | localparam ADDR_BLOCKLEN = 8'h0a; 65 | 66 | localparam ADDR_BLOCK0 = 8'h10; 67 | localparam ADDR_BLOCK15 = 8'h1f; 68 | 69 | localparam ADDR_DIGEST0 = 8'h40; 70 | localparam ADDR_DIGEST7 = 8'h47; 71 | 72 | 73 | //---------------------------------------------------------------- 74 | // Register and Wire declarations. 75 | //---------------------------------------------------------------- 76 | reg [31 : 0] cycle_ctr; 77 | reg [31 : 0] error_ctr; 78 | reg [31 : 0] tc_ctr; 79 | reg tb_monitor; 80 | 81 | reg display_dut_state; 82 | reg display_core_state; 83 | 84 | reg tb_clk; 85 | reg tb_reset_n; 86 | reg tb_cs; 87 | reg tb_we; 88 | reg [7 : 0] tb_address; 89 | reg [31 : 0] tb_write_data; 90 | wire [31 : 0] tb_read_data; 91 | 92 | reg [31 : 0] read_data; 93 | reg [255 : 0] digest; 94 | 95 | 96 | //---------------------------------------------------------------- 97 | // Device Under Test. 98 | //---------------------------------------------------------------- 99 | blake2s dut( 100 | .clk(tb_clk), 101 | .reset_n(tb_reset_n), 102 | 103 | .cs(tb_cs), 104 | .we(tb_we), 105 | 106 | .address(tb_address), 107 | .write_data(tb_write_data), 108 | .read_data(tb_read_data) 109 | ); 110 | 111 | 112 | //---------------------------------------------------------------- 113 | // clk_gen 114 | // 115 | // Always running clock generator process. 116 | //---------------------------------------------------------------- 117 | always 118 | begin : clk_gen 119 | #CLK_HALF_PERIOD; 120 | tb_clk = !tb_clk; 121 | end // clk_gen 122 | 123 | 124 | //---------------------------------------------------------------- 125 | // sys_monitor() 126 | // 127 | // An always running process that creates a cycle counter and 128 | // conditionally displays information about the DUT. 129 | //---------------------------------------------------------------- 130 | always 131 | begin : sys_monitor 132 | cycle_ctr = cycle_ctr + 1; 133 | #(CLK_PERIOD); 134 | if (tb_monitor) 135 | begin 136 | dump_dut_state(); 137 | end 138 | end 139 | 140 | 141 | //---------------------------------------------------------------- 142 | // dump_dut_state 143 | // 144 | // Dump the internal state of the dut to std out. 145 | //---------------------------------------------------------------- 146 | task dump_dut_state; 147 | begin 148 | $display("-------------------------------------------------------------------------------------"); 149 | $display("-------------------------------------------------------------------------------------"); 150 | $display("DUT internal state at cycle: %08d", cycle_ctr); 151 | $display("-------------------------------------"); 152 | if (display_dut_state) begin 153 | $display("block 0 ... 3: 0x%08x 0x%08x 0x%08x 0x%08x", 154 | dut.block_mem[0], dut.block_mem[1], dut.block_mem[2], dut.block_mem[3]); 155 | $display("block 4 ... 7: 0x%08x 0x%08x 0x%08x 0x%08x", 156 | dut.block_mem[4], dut.block_mem[5], dut.block_mem[6], dut.block_mem[7]); 157 | $display("block 8 ... 11: 0x%08x 0x%08x 0x%08x 0x%08x", 158 | dut.block_mem[8], dut.block_mem[9], dut.block_mem[10], dut.block_mem[11]); 159 | $display("block 12 ... 15: 0x%08x 0x%08x 0x%08x 0x%08x", 160 | dut.block_mem[12], dut.block_mem[13], dut.block_mem[14], dut.block_mem[15]); 161 | $display(""); 162 | 163 | end 164 | 165 | if (display_core_state) begin 166 | $display("Core internal state"); 167 | $display("-------------------"); 168 | $display("init: 0x%01x, update: 0x%01x, finish: 0x%01x", dut.core.init, dut.core.update, dut.core.finish); 169 | $display("block M: 0x%064x", dut.core.block[511 : 256]); 170 | $display("block L: 0x%064x", dut.core.block[255 : 000]); 171 | $display("blocklen: 0x%02x", dut.core.blocklen); 172 | $display("digest: 0x%064x", dut.core.digest); 173 | $display("ready: 0x%01x", dut.core.ready); 174 | $display(""); 175 | $display("blake2s_ctrl_reg: 0x%02x, blake2s_ctrl_new: 0x%02x, blake2s_ctrl_we: 0x%01x", 176 | dut.core.blake2s_ctrl_reg, dut.core.blake2s_ctrl_new, dut.core.blake2s_ctrl_we); 177 | $display(""); 178 | 179 | $display("h0: 0x%08x, h1: 0x%08x, h2: 0x%08x, h3: 0x%08x", 180 | dut.core.h_reg[0], dut.core.h_reg[1], dut.core.h_reg[2], dut.core.h_reg[3]); 181 | $display("h4: 0x%08x, h5: 0x%08x, h6: 0x%08x, h7: 0x%08x", 182 | dut.core.h_reg[4], dut.core.h_reg[5], dut.core.h_reg[6], dut.core.h_reg[7]); 183 | $display(""); 184 | $display("v0: 0x%08x, v1: 0x%08x, v2: 0x%08x, v3: 0x%08x", 185 | dut.core.v_reg[0], dut.core.v_reg[1], dut.core.v_reg[2], dut.core.v_reg[3]); 186 | $display("v4: 0x%08x, v5: 0x%08x, v6: 0x%08x, v7: 0x%08x", 187 | dut.core.v_reg[4], dut.core.v_reg[5], dut.core.v_reg[6], dut.core.v_reg[7]); 188 | $display("v8: 0x%08x, v9: 0x%08x, v10: 0x%08x, v11: 0x%08x", 189 | dut.core.v_reg[8], dut.core.v_reg[9], dut.core.v_reg[10], dut.core.v_reg[11]); 190 | $display("v12: 0x%08x, v13: 0x%08x, v14: 0x%08x, v15: 0x%08x", 191 | dut.core.v_reg[12], dut.core.v_reg[13], dut.core.v_reg[14], dut.core.v_reg[15]); 192 | $display("init_v: 0x%1x, update_v: 0x%1x, v_we: 0x%1x", dut.core.init_v, dut.core.update_v, dut.core.v_we); 193 | $display(""); 194 | 195 | $display("t0_reg: 0x%08x, t0_new: 0x%08x", dut.core.t0_reg, dut.core.t0_new); 196 | $display("t1_reg: 0x%08x, t1_new: 0x%08x", dut.core.t1_reg, dut.core.t1_new); 197 | $display("t_ctr_rst: 0x%1x, t_ctr_inc: 0x%1x", dut.core.t_ctr_rst, dut.core.t_ctr_inc); 198 | $display("last_reg: 0x%1x, last_new: 0x%1x, last_we: 0x%1x", 199 | dut.core.last_reg, dut.core.last_new, dut.core.last_we); 200 | $display(""); 201 | 202 | $display("v0_new: 0x%08x, v1_new: 0x%08x, v2_new: 0x%08x, v3_new: 0x%08x", 203 | dut.core.v_new[0], dut.core.v_new[1], dut.core.v_new[2], dut.core.v_new[3]); 204 | $display("v4_new: 0x%08x, v5_new: 0x%08x, v6_new: 0x%08x, v7_new: 0x%08x", 205 | dut.core.v_new[4], dut.core.v_new[5], dut.core.v_new[6], dut.core.v_new[7]); 206 | $display("v8_new: 0x%08x, v9_new: 0x%08x, v10_new: 0x%08x, v11_new: 0x%08x", 207 | dut.core.v_new[8], dut.core.v_new[9], dut.core.v_new[10], dut.core.v_new[11]); 208 | $display("v12_new: 0x%08x, v13_new: 0x%08x, v14_new: 0x%08x, v15_new: 0x%08x", 209 | dut.core.v_new[12], dut.core.v_new[13], dut.core.v_new[14], dut.core.v_new[15]); 210 | $display(""); 211 | 212 | $display("G_mode: 0x%1x, ", dut.core.G_mode); 213 | $display("G0_m0: 0x%08x, G0_m1: 0x%08x, G1_m0: 0x%08x, G1_m1: 0x%08x", 214 | dut.core.G0_m0, dut.core.G0_m1, dut.core.G1_m0, dut.core.G1_m1); 215 | $display("G2_m0: 0x%08x, G2_m1: 0x%08x, G3_m0: 0x%08x, G3_m1: 0x%08x", 216 | dut.core.G2_m0, dut.core.G2_m1, dut.core.G3_m0, dut.core.G3_m1); 217 | $display("round_ctr_reg: 0x%02x, round_ctr_new: 0x%02x", dut.core.round_ctr_reg, dut.core.round_ctr_reg); 218 | $display("round_ctr_rst: 0x%1x, round_ctr_inc: 0x%1x, round_ctr_we: 0x%1x", 219 | dut.core.round_ctr_rst, dut.core.round_ctr_inc, dut.core.round_ctr_we); 220 | end // if (display_core_state) 221 | 222 | $display("-------------------------------------------------------------------------------------"); 223 | $display("-------------------------------------------------------------------------------------"); 224 | $display(""); 225 | $display(""); 226 | end 227 | endtask // dump_dut_state 228 | 229 | 230 | //---------------------------------------------------------------- 231 | // reset_dut() 232 | // 233 | // Toggle reset to put the DUT into a well known state. 234 | //---------------------------------------------------------------- 235 | task reset_dut; 236 | begin 237 | $display("--- Toggle reset."); 238 | tb_reset_n = 0; 239 | #(2 * CLK_PERIOD); 240 | tb_reset_n = 1; 241 | end 242 | endtask // reset_dut 243 | 244 | 245 | //---------------------------------------------------------------- 246 | // display_test_result() 247 | // 248 | // Display the accumulated test results. 249 | //---------------------------------------------------------------- 250 | task display_test_result; 251 | begin 252 | $display(""); 253 | 254 | if (error_ctr == 0) begin 255 | $display("--- All %02d test cases completed successfully", tc_ctr); 256 | end else begin 257 | $display("--- %02d tests completed - %02d test cases did not complete successfully.", 258 | tc_ctr, error_ctr); 259 | end 260 | end 261 | endtask // display_test_result 262 | 263 | 264 | //---------------------------------------------------------------- 265 | // init_sim() 266 | // 267 | // Initialize all counters and testbed functionality as well 268 | // as setting the DUT inputs to defined values. 269 | //---------------------------------------------------------------- 270 | task init_sim; 271 | begin 272 | cycle_ctr = 0; 273 | error_ctr = 0; 274 | tc_ctr = 0; 275 | tb_monitor = 0; 276 | display_dut_state = 0; 277 | display_core_state = 0; 278 | 279 | tb_clk = 1'h0; 280 | tb_reset_n = 1'h1; 281 | tb_cs = 1'h0; 282 | tb_we = 1'h0; 283 | tb_address = 8'h0; 284 | tb_write_data = 32'h0; 285 | end 286 | endtask // init_sim 287 | 288 | 289 | //---------------------------------------------------------------- 290 | // write_word() 291 | // 292 | // Write the given word to the DUT using the DUT interface. 293 | //---------------------------------------------------------------- 294 | task write_word(input [11 : 0] address, 295 | input [31 : 0] word); 296 | begin 297 | if (DEBUG) 298 | begin 299 | $display("--- Writing 0x%08x to 0x%02x.", word, address); 300 | $display(""); 301 | end 302 | 303 | tb_address = address; 304 | tb_write_data = word; 305 | tb_cs = 1; 306 | tb_we = 1; 307 | #(2 * CLK_PERIOD); 308 | tb_cs = 0; 309 | tb_we = 0; 310 | end 311 | endtask // write_word 312 | 313 | 314 | //---------------------------------------------------------------- 315 | // read_word() 316 | // 317 | // Read a data word from the given address in the DUT. 318 | // the word read will be available in the global variable 319 | // read_data. 320 | //---------------------------------------------------------------- 321 | task read_word(input [11 : 0] address); 322 | begin 323 | tb_address = address; 324 | tb_cs = 1; 325 | tb_we = 0; 326 | #(CLK_PERIOD); 327 | read_data = tb_read_data; 328 | tb_cs = 0; 329 | 330 | if (DEBUG) 331 | begin 332 | $display("--- Reading 0x%08x from 0x%02x.", read_data, address); 333 | $display(""); 334 | end 335 | end 336 | endtask // read_word 337 | 338 | 339 | //---------------------------------------------------------------- 340 | // wait_ready() 341 | // 342 | // Wait for the ready flag to be set in dut. 343 | //---------------------------------------------------------------- 344 | task wait_ready; 345 | begin : wready 346 | read_word(ADDR_STATUS); 347 | while (read_data == 0) 348 | read_word(ADDR_STATUS); 349 | end 350 | endtask // wait_ready 351 | 352 | 353 | //---------------------------------------------------------------- 354 | // get_digest() 355 | //---------------------------------------------------------------- 356 | task get_digest; 357 | begin 358 | read_word(ADDR_DIGEST0); 359 | digest[255 : 224] = read_data; 360 | 361 | read_word(ADDR_DIGEST0 + 8'h1); 362 | digest[223 : 192] = read_data; 363 | 364 | read_word(ADDR_DIGEST0 + 8'h2); 365 | digest[191 : 160] = read_data; 366 | 367 | read_word(ADDR_DIGEST0 + 8'h3); 368 | digest[159 : 128] = read_data; 369 | 370 | read_word(ADDR_DIGEST0 + 8'h4); 371 | digest[127 : 96] = read_data; 372 | 373 | read_word(ADDR_DIGEST0 + 8'h5); 374 | digest[95 : 64] = read_data; 375 | 376 | read_word(ADDR_DIGEST0 + 8'h6); 377 | digest[63 : 32] = read_data; 378 | 379 | read_word(ADDR_DIGEST0 + 8'h7); 380 | digest[31 : 0] = read_data; 381 | end 382 | endtask // get_digest 383 | 384 | 385 | //---------------------------------------------------------------- 386 | // clean_block() 387 | //---------------------------------------------------------------- 388 | task clean_block; 389 | begin: clean_block 390 | integer i; 391 | for (i = 0 ; i < 16 ; i = i + 1) begin 392 | write_word(ADDR_BLOCK0 + i, 32'h0); 393 | end 394 | end 395 | endtask // clean_block 396 | 397 | 398 | //---------------------------------------------------------------- 399 | // test_name_version 400 | //---------------------------------------------------------------- 401 | task test_name_version; 402 | begin: test_name_version 403 | reg [31 : 0] name0; 404 | reg [31 : 0] name1; 405 | reg [31 : 0] version; 406 | 407 | $display(""); 408 | $display("--- test_name_version: Started."); 409 | 410 | read_word(ADDR_NAME0); 411 | name0 = read_data; 412 | 413 | read_word(ADDR_NAME1); 414 | name1 = read_data; 415 | 416 | read_word(ADDR_VERSION); 417 | version = read_data; 418 | 419 | $display("--- test_name_version: Name: %c%c%c%c%c%c%c%c", 420 | name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0], 421 | name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]); 422 | 423 | $display("--- test_name_version: Version: %c%c%c%c", 424 | version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]); 425 | 426 | 427 | $display("--- test_name_version: Completed."); 428 | $display(""); 429 | end 430 | endtask // test_name_version 431 | 432 | 433 | //---------------------------------------------------------------- 434 | // test_empty_message 435 | //---------------------------------------------------------------- 436 | task test_empty_message; 437 | begin : test_rfc_7693 438 | tc_ctr = tc_ctr + 1; 439 | 440 | tb_monitor = 0; 441 | display_dut_state = 0; 442 | display_core_state = 0; 443 | 444 | $display(""); 445 | $display("--- test_empty_message: Started."); 446 | 447 | $display("--- test_empty_message: Asserting init."); 448 | write_word(ADDR_CTRL, 32'h1); 449 | wait_ready(); 450 | $display("--- test_empty_message: Init should be completed."); 451 | 452 | 453 | $display("--- test_empty_message: Asserting finish."); 454 | write_word(ADDR_BLOCKLEN, 32'h0); 455 | write_word(ADDR_CTRL, 32'h4); 456 | wait_ready(); 457 | 458 | $display("--- test_empty_message: Finish should be completed."); 459 | get_digest(); 460 | 461 | $display("--- test_empty_message: Checking generated digest."); 462 | if (digest == 256'h69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9) begin 463 | $display("--- test_empty_message: Correct digest generated."); 464 | $display("--- test_empty_message: Got: 0x%064x", digest); 465 | end else begin 466 | $display("--- test_empty_message: Error. Incorrect digest generated."); 467 | $display("--- test_empty_message: Expected: 0x69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"); 468 | $display("--- test_empty_message: Got: 0x%064x", digest); 469 | error_ctr = error_ctr + 1; 470 | end 471 | 472 | tb_monitor = 0; 473 | display_dut_state = 0; 474 | display_core_state = 0; 475 | 476 | $display("--- test_empty_message: Completed.\n"); 477 | end 478 | endtask // test_empty_message 479 | 480 | 481 | //---------------------------------------------------------------- 482 | // test_rfc_7693 483 | //---------------------------------------------------------------- 484 | task test_rfc_7693; 485 | begin : test_rfc_7693 486 | tc_ctr = tc_ctr + 1; 487 | 488 | tb_monitor = 0; 489 | display_dut_state = 0; 490 | display_core_state = 0; 491 | 492 | clean_block(); 493 | 494 | $display(""); 495 | $display("--- ttest_rfc_7693: Started."); 496 | 497 | $display("--- test_rfc_7693: Asserting init."); 498 | write_word(ADDR_CTRL, 32'h1); 499 | wait_ready(); 500 | $display("--- test_rfc_7693: Init should be completed."); 501 | 502 | 503 | $display("--- test_rfc_7693: Writing message and message length."); 504 | write_word(ADDR_BLOCK0, 32'h61626300); 505 | write_word(ADDR_BLOCKLEN, 32'h3); 506 | $display("--- test_rfc_7693: Asserting finish."); 507 | write_word(ADDR_CTRL, 32'h4); 508 | wait_ready(); 509 | 510 | $display("--- test_rfc_7693: Finish should be completed."); 511 | get_digest(); 512 | 513 | $display("--- test_rfc_7693: Checking generated digest."); 514 | if (digest == 256'h508c5e8c327c14e2_e1a72ba34eeb452f_37458b209ed63a29_4d999b4c86675982) begin 515 | $display("--- test_rfc_7693: Correct digest generated."); 516 | $display("--- test_rfc_7693: Got: 0x%064x", digest); 517 | end else begin 518 | $display("--- test_rfc_7693: Error. Incorrect digest generated."); 519 | $display("--- test_rfc_7693: Expected: 0x508c5e8c327c14e2_e1a72ba34eeb452f_37458b209ed63a29_4d999b4c86675982"); 520 | $display("--- test_rfc_7693: Got: 0x%064x", digest); 521 | error_ctr = error_ctr + 1; 522 | end 523 | 524 | tb_monitor = 0; 525 | display_dut_state = 0; 526 | display_core_state = 0; 527 | 528 | $display("--- test_rfc_7693: Completed.\n"); 529 | end 530 | endtask // test_rfc_7693 531 | 532 | 533 | //---------------------------------------------------------------- 534 | // test_one_block_message 535 | //---------------------------------------------------------------- 536 | task test_one_block_message; 537 | begin : test_one_block_message 538 | tc_ctr = tc_ctr + 1; 539 | 540 | tb_monitor = 0; 541 | display_dut_state = 0; 542 | display_core_state = 0; 543 | 544 | clean_block(); 545 | 546 | $display(""); 547 | $display("--- test_one_block_message: Started."); 548 | 549 | $display("--- test_one_block_message: Asserting init."); 550 | write_word(ADDR_CTRL, 32'h1); 551 | wait_ready(); 552 | $display("--- test_one_block_message: Init should be completed."); 553 | 554 | 555 | $display("--- test_one_block_message: Writing message and message length."); 556 | write_word(ADDR_BLOCK0 + 0, 32'h00010203); 557 | write_word(ADDR_BLOCK0 + 1, 32'h04050607); 558 | write_word(ADDR_BLOCK0 + 2, 32'h08090a0b); 559 | write_word(ADDR_BLOCK0 + 3, 32'h0c0d0e0f); 560 | write_word(ADDR_BLOCK0 + 4, 32'h10111213); 561 | write_word(ADDR_BLOCK0 + 5, 32'h14151617); 562 | write_word(ADDR_BLOCK0 + 6, 32'h18191a1b); 563 | write_word(ADDR_BLOCK0 + 7, 32'h1c1d1e1f); 564 | write_word(ADDR_BLOCK0 + 8, 32'h20212223); 565 | write_word(ADDR_BLOCK0 + 9, 32'h24252627); 566 | write_word(ADDR_BLOCK0 + 10, 32'h28292a2b); 567 | write_word(ADDR_BLOCK0 + 11, 32'h2c2d2e2f); 568 | write_word(ADDR_BLOCK0 + 12, 32'h30313233); 569 | write_word(ADDR_BLOCK0 + 13, 32'h34353637); 570 | write_word(ADDR_BLOCK0 + 14, 32'h38393a3b); 571 | write_word(ADDR_BLOCK0 + 15, 32'h3c3d3e3f); 572 | write_word(ADDR_BLOCKLEN, 32'h40); 573 | $display("--- test_one_block_message: Asserting finish."); 574 | write_word(ADDR_CTRL, 32'h4); 575 | wait_ready(); 576 | 577 | $display("--- test_one_block_message: Finish should be completed."); 578 | get_digest(); 579 | 580 | $display("--- test_one_block_message: Checking generated digest."); 581 | if (digest == 256'h56f34e8b96557e90c1f24b52d0c89d51086acf1b00f634cf1dde9233b8eaaa3e) begin 582 | $display("--- test_one_block_message: Correct digest generated."); 583 | $display("--- test_one_block_message: Got: 0x%064x", digest); 584 | end else begin 585 | $display("--- test_one_block_message: Error. Incorrect digest generated."); 586 | $display("--- test_one_block_message: Expected: 0x56f34e8b96557e90c1f24b52d0c89d51086acf1b00f634cf1dde9233b8eaaa3e"); 587 | $display("--- test_one_block_message: Got: 0x%064x", digest); 588 | error_ctr = error_ctr + 1; 589 | end 590 | 591 | tb_monitor = 0; 592 | display_dut_state = 0; 593 | display_core_state = 0; 594 | 595 | $display("--- test_one_block_message: Completed.\n"); 596 | end 597 | endtask // test_one_block_message 598 | 599 | 600 | //---------------------------------------------------------------- 601 | // test_one_block_one_byte_message 602 | //---------------------------------------------------------------- 603 | task test_one_block_one_byte_message; 604 | begin : test_one_block_one_byte_message 605 | tc_ctr = tc_ctr + 1; 606 | 607 | tb_monitor = 0; 608 | display_dut_state = 0; 609 | display_core_state = 0; 610 | 611 | clean_block(); 612 | 613 | $display(""); 614 | $display("--- test_one_block_one_byte_message: Started."); 615 | 616 | $display("--- test_one_block_one_byte_message: Asserting init."); 617 | write_word(ADDR_CTRL, 32'h1); 618 | wait_ready(); 619 | $display("--- test_one_block_one_byte_message: Init should be completed."); 620 | 621 | 622 | $display("--- test_one_block_one_byte_message: Writing message and message length."); 623 | write_word(ADDR_BLOCK0 + 0, 32'h00010203); 624 | write_word(ADDR_BLOCK0 + 1, 32'h04050607); 625 | write_word(ADDR_BLOCK0 + 2, 32'h08090a0b); 626 | write_word(ADDR_BLOCK0 + 3, 32'h0c0d0e0f); 627 | write_word(ADDR_BLOCK0 + 4, 32'h10111213); 628 | write_word(ADDR_BLOCK0 + 5, 32'h14151617); 629 | write_word(ADDR_BLOCK0 + 6, 32'h18191a1b); 630 | write_word(ADDR_BLOCK0 + 7, 32'h1c1d1e1f); 631 | write_word(ADDR_BLOCK0 + 8, 32'h20212223); 632 | write_word(ADDR_BLOCK0 + 9, 32'h24252627); 633 | write_word(ADDR_BLOCK0 + 10, 32'h28292a2b); 634 | write_word(ADDR_BLOCK0 + 11, 32'h2c2d2e2f); 635 | write_word(ADDR_BLOCK0 + 12, 32'h30313233); 636 | write_word(ADDR_BLOCK0 + 13, 32'h34353637); 637 | write_word(ADDR_BLOCK0 + 14, 32'h38393a3b); 638 | write_word(ADDR_BLOCK0 + 15, 32'h3c3d3e3f); 639 | write_word(ADDR_BLOCKLEN, 32'h40); 640 | 641 | $display("--- test_one_block_one_byte_message: Asserting next."); 642 | write_word(ADDR_CTRL, 32'h2); 643 | wait_ready(); 644 | 645 | $display("--- test_one_block_one_byte_message: Next should be completed."); 646 | get_digest(); 647 | 648 | 649 | $display("--- test_one_block_one_byte_message: Writing message and message length."); 650 | clean_block(); 651 | write_word(ADDR_BLOCK0 + 0, 32'h40000000); 652 | write_word(ADDR_BLOCKLEN, 32'h01); 653 | 654 | $display("--- test_one_block_one_byte_message: Asserting finish."); 655 | write_word(ADDR_CTRL, 32'h4); 656 | wait_ready(); 657 | 658 | $display("--- test_one_block_one_byte_message: Finish should be completed."); 659 | get_digest(); 660 | 661 | $display("--- test_one_block_one_byte_message: Checking generated digest."); 662 | if (digest == 256'h1b53ee94aaf34e4b159d48de352c7f0661d0a40edff95a0b1639b4090e974472) begin 663 | $display("--- test_one_block_one_byte_message: Correct digest generated."); 664 | $display("--- test_one_block_one_byte_message: Got: 0x%064x", digest); 665 | end else begin 666 | $display("--- test_one_block_one_byte_message: Error. Incorrect digest generated."); 667 | $display("--- test_one_block_one_byte_message: Expected: 0x1b53ee94aaf34e4b159d48de352c7f0661d0a40edff95a0b1639b4090e974472"); 668 | $display("--- test_one_block_one_byte_message: Got: 0x%064x", digest); 669 | error_ctr = error_ctr + 1; 670 | end 671 | 672 | tb_monitor = 0; 673 | display_dut_state = 0; 674 | display_core_state = 0; 675 | 676 | $display("--- test_one_block_one_byte_message: Completed.\n"); 677 | end 678 | endtask // test_one_block_one_byte_message 679 | 680 | 681 | //---------------------------------------------------------------- 682 | // blake2s_test 683 | //---------------------------------------------------------------- 684 | initial 685 | begin : blake2s_test 686 | $display(" -= Testbench for blake2s started =-"); 687 | $display(" ================================="); 688 | $display(""); 689 | 690 | init_sim(); 691 | reset_dut(); 692 | 693 | test_name_version(); 694 | test_empty_message(); 695 | test_rfc_7693(); 696 | test_one_block_message(); 697 | test_one_block_one_byte_message(); 698 | 699 | display_test_result(); 700 | $display(""); 701 | $display(" -= Testbench for blake2s completed =-"); 702 | $display(" ================================="); 703 | $display(""); 704 | $finish; 705 | end // blake2s_test 706 | endmodule // tb_blake2s 707 | 708 | //====================================================================== 709 | // EOF tb_blake2s.v 710 | //====================================================================== 711 | -------------------------------------------------------------------------------- /src/tb/tb_blake2s_G.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // tb_blake2s_G.v 4 | // -------------- 5 | // Testbench for the BLAKE2s G function. 6 | // 7 | // 8 | // Author: Joachim Strömbergson 9 | // Copyright (c) 2018, Assured AB 10 | // All rights reserved. 11 | // 12 | // Redistribution and use in source and binary forms, with or 13 | // without modification, are permitted provided that the following 14 | // conditions are met: 15 | // 16 | // 1. Redistributions of source code must retain the above copyright 17 | // notice, this list of conditions and the following disclaimer. 18 | // 19 | // 2. Redistributions in binary form must reproduce the above copyright 20 | // notice, this list of conditions and the following disclaimer in 21 | // the documentation and/or other materials provided with the 22 | // distribution. 23 | // 24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | // 37 | //====================================================================== 38 | 39 | module tb_blake2s_G(); 40 | 41 | //---------------------------------------------------------------- 42 | // Internal constant and parameter definitions. 43 | //---------------------------------------------------------------- 44 | parameter DEBUG = 0; 45 | parameter VERBOSE = 0; 46 | 47 | parameter CLK_HALF_PERIOD = 2; 48 | parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD; 49 | 50 | 51 | //---------------------------------------------------------------- 52 | // Register and Wire declarations. 53 | //---------------------------------------------------------------- 54 | reg [63 : 0] cycle_ctr; 55 | reg [31 : 0] error_ctr; 56 | reg [31 : 0] tc_ctr; 57 | 58 | reg tb_clk; 59 | reg [31 : 0] tb_a; 60 | reg [31 : 0] tb_b; 61 | reg [31 : 0] tb_c; 62 | reg [31 : 0] tb_d; 63 | reg [31 : 0] tb_m0; 64 | reg [31 : 0] tb_m1; 65 | wire [31 : 0] tb_a_prim; 66 | wire [31 : 0] tb_b_prim; 67 | wire [31 : 0] tb_c_prim; 68 | wire [31 : 0] tb_d_prim; 69 | 70 | reg display_cycle_ctr; 71 | 72 | 73 | //---------------------------------------------------------------- 74 | // blake2_G device under test. 75 | //---------------------------------------------------------------- 76 | blake2s_G dut( 77 | .a(tb_a), 78 | .b(tb_b), 79 | .c(tb_c), 80 | .d(tb_d), 81 | .m0(tb_m0), 82 | .m1(tb_m1), 83 | .a_prim(tb_a_prim), 84 | .b_prim(tb_b_prim), 85 | .c_prim(tb_c_prim), 86 | .d_prim(tb_d_prim) 87 | ); 88 | 89 | 90 | //---------------------------------------------------------------- 91 | // clk_gen 92 | // 93 | // Clock generator process. 94 | //---------------------------------------------------------------- 95 | always 96 | begin : clk_gen 97 | #CLK_HALF_PERIOD tb_clk = !tb_clk; 98 | end // clk_gen 99 | 100 | 101 | //-------------------------------------------------------------------- 102 | // dut_monitor 103 | // 104 | // Monitor displaying information every cycle. 105 | // Includes the cycle counter. 106 | //-------------------------------------------------------------------- 107 | always @ (posedge tb_clk) 108 | begin : dut_monitor 109 | cycle_ctr = cycle_ctr + 1; 110 | 111 | if (display_cycle_ctr) 112 | begin 113 | $display("cycle = %016x:", cycle_ctr); 114 | end 115 | 116 | end // dut_monitor 117 | 118 | 119 | //---------------------------------------------------------------- 120 | // dump_dut_state 121 | // 122 | // Dump the internal state of the dut to std out. 123 | //---------------------------------------------------------------- 124 | task dump_dut_state; 125 | begin 126 | if (VERBOSE) 127 | begin 128 | $display(""); 129 | $display("DUT internal state"); 130 | $display("------------------"); 131 | $display("a1: 0x%08x, a2: 0x%08x", dut.a1, dut.a2); 132 | $display("b1: 0x%08x, b2: 0x%08x, b3: 0x%08x, b4: 0x%08x", dut.b1, dut.b2, dut.b3, dut.b4); 133 | $display("c1: 0x%08x, c2: 0x%08x", dut.c1, dut.c2); 134 | $display("d1: 0x%08x, d2: 0x%08x, d3: 0x%08x, d4: 0x%08x", dut.d1, dut.d2, dut.d3, dut.d4); 135 | $display(""); 136 | end 137 | end 138 | endtask // dump_dut_state 139 | 140 | 141 | //---------------------------------------------------------------- 142 | // display_test_result() 143 | // 144 | // Display the accumulated test results. 145 | //---------------------------------------------------------------- 146 | task display_test_result; 147 | begin 148 | $display("*** %02d test cases executed ****", tc_ctr); 149 | if (error_ctr == 0) 150 | begin 151 | $display("*** All %02d test cases completed successfully ****", tc_ctr); 152 | end 153 | else 154 | begin 155 | $display("*** %02d test cases did not complete successfully. ***", error_ctr); 156 | end 157 | end 158 | endtask // display_test_result 159 | 160 | 161 | //---------------------------------------------------------------- 162 | // init_dut() 163 | // 164 | // Set the input to the DUT to defined values. 165 | //---------------------------------------------------------------- 166 | task init_dut; 167 | begin 168 | cycle_ctr = 0; 169 | error_ctr = 0; 170 | tc_ctr = 0; 171 | tb_clk = 0; 172 | tb_a = 32'h0; 173 | tb_b = 32'h0; 174 | tb_c = 32'h0; 175 | tb_d = 32'h0; 176 | tb_m0 = 32'h0; 177 | tb_m1 = 32'h0; 178 | end 179 | endtask // init_dut 180 | 181 | 182 | //---------------------------------------------------------------- 183 | // task1 184 | // 185 | // First task with vectors captured from the blake2s reference 186 | // while running. 187 | //---------------------------------------------------------------- 188 | task test1; 189 | begin : tc1 190 | integer tc1_error; 191 | reg [31 : 0] expected_a; 192 | reg [31 : 0] expected_b; 193 | reg [31 : 0] expected_c; 194 | reg [31 : 0] expected_d; 195 | tc1_error = 0; 196 | tc_ctr = tc_ctr + 1; 197 | 198 | tb_a = 32'h6b08c647; 199 | tb_b = 32'h510e527f; 200 | tb_c = 32'h6a09e667; 201 | tb_d = 32'h510e523f; 202 | tb_m0 = 32'h03020100; 203 | tb_m1 = 32'h07060504; 204 | 205 | expected_a = 32'h263d8fa2; 206 | expected_b = 32'h0e16dfd0; 207 | expected_c = 32'h6b7198df; 208 | expected_d = 32'hb56dc461; 209 | 210 | $display("*** Running test case 1 ****"); 211 | dump_dut_state(); 212 | #(CLK_PERIOD); 213 | dump_dut_state(); 214 | 215 | if (tb_a_prim != expected_a) 216 | begin 217 | $display("Error in a. Expected 0x%08x. Got 0x%08x", expected_a, tb_a_prim); 218 | tc1_error = 1; 219 | end 220 | 221 | if (tb_b_prim != expected_b) 222 | begin 223 | $display("Error in b. Expected 0x%08x. Got 0x%08x", expected_b, tb_b_prim); 224 | tc1_error = 1; 225 | end 226 | 227 | if (tb_c_prim != expected_c) 228 | begin 229 | $display("Error in c. Expected 0x%08x. Got 0x%08x", expected_c, tb_c_prim); 230 | tc1_error = 1; 231 | end 232 | 233 | if (tb_d_prim != expected_d) 234 | begin 235 | $display("Error in d. Expected 0x%08x. Got 0x%08x", expected_d, tb_d_prim); 236 | tc1_error = 1; 237 | end 238 | 239 | if (tc1_error) 240 | error_ctr = error_ctr + 1; 241 | 242 | $display(""); 243 | end 244 | endtask // test1 245 | 246 | 247 | //---------------------------------------------------------------- 248 | // testrunner 249 | // 250 | // The main test functionality. 251 | //---------------------------------------------------------------- 252 | initial 253 | begin : testrunner 254 | $display("*** Testbench for BLAKE2 G function test started ***"); 255 | $display("----------------------------------------------------"); 256 | $display(""); 257 | 258 | init_dut(); 259 | test1(); 260 | display_test_result(); 261 | $display("*** BLAKE2 G functions simulation done ****"); 262 | $finish_and_return(error_ctr); 263 | end // testrunner 264 | 265 | endmodule // tb_blake2s_G 266 | 267 | //====================================================================== 268 | // EOF tb_blake2s_G.v 269 | //====================================================================== 270 | -------------------------------------------------------------------------------- /src/tb/tb_blake2s_core.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // tb_blake2s_core.v 4 | // ------------------ 5 | // Testbench for the BLAKE2s core function. 6 | // 7 | // 8 | // Author: Joachim Strömbergson 9 | // Copyright (c) 2018, Assured AB 10 | // All rights reserved. 11 | // 12 | // Redistribution and use in source and binary forms, with or 13 | // without modification, are permitted provided that the following 14 | // conditions are met: 15 | // 16 | // 1. Redistributions of source code must retain the above copyright 17 | // notice, this list of conditions and the following disclaimer. 18 | // 19 | // 2. Redistributions in binary form must reproduce the above copyright 20 | // notice, this list of conditions and the following disclaimer in 21 | // the documentation and/or other materials provided with the 22 | // distribution. 23 | // 24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | // 37 | //====================================================================== 38 | 39 | module tb_blake2s_core(); 40 | 41 | //---------------------------------------------------------------- 42 | // Internal constant and parameter definitions. 43 | //---------------------------------------------------------------- 44 | parameter DEBUG = 0; 45 | parameter VERBOSE = 0; 46 | 47 | parameter CLK_HALF_PERIOD = 2; 48 | parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD; 49 | 50 | 51 | //---------------------------------------------------------------- 52 | // Register and Wire declarations. 53 | //---------------------------------------------------------------- 54 | reg [63 : 0] cycle_ctr; 55 | reg [31 : 0] error_ctr; 56 | reg [31 : 0] tc_ctr; 57 | reg display_cycle_ctr; 58 | reg display_dut_state; 59 | 60 | reg tb_clk; 61 | reg tb_reset_n; 62 | 63 | reg tb_init; 64 | reg tb_update; 65 | reg tb_finish; 66 | reg [511 : 0] tb_block; 67 | reg [6 : 0] tb_blocklen; 68 | wire [255 : 0] tb_digest; 69 | wire tb_ready; 70 | 71 | 72 | //---------------------------------------------------------------- 73 | // Device under test. 74 | //---------------------------------------------------------------- 75 | blake2s_core dut( 76 | .clk(tb_clk), 77 | .reset_n(tb_reset_n), 78 | 79 | .init(tb_init), 80 | .update(tb_update), 81 | .finish(tb_finish), 82 | 83 | .block(tb_block), 84 | .blocklen(tb_blocklen), 85 | 86 | .digest(tb_digest), 87 | .ready(tb_ready) 88 | ); 89 | 90 | 91 | //---------------------------------------------------------------- 92 | // clk_gen 93 | // 94 | // Clock generator process. 95 | //---------------------------------------------------------------- 96 | always 97 | begin : clk_gen 98 | #CLK_HALF_PERIOD tb_clk = !tb_clk; 99 | end // clk_gen 100 | 101 | 102 | //-------------------------------------------------------------------- 103 | // dut_monitor 104 | // 105 | // Monitor displaying information every cycle. 106 | // Includes the cycle counter. 107 | //-------------------------------------------------------------------- 108 | always @ (posedge tb_clk) 109 | begin : dut_monitor 110 | cycle_ctr = cycle_ctr + 1; 111 | 112 | if (display_dut_state) 113 | dump_dut_state(); 114 | end // dut_monitor 115 | 116 | 117 | //---------------------------------------------------------------- 118 | // dump_dut_state 119 | // 120 | // Dump the internal state of the dut to std out. 121 | //---------------------------------------------------------------- 122 | task dump_dut_state; 123 | begin 124 | $display("-------------------------------------------------------------------------------------"); 125 | $display("-------------------------------------------------------------------------------------"); 126 | $display("DUT internal state at cycle: %08d", cycle_ctr); 127 | $display("-------------------------------------"); 128 | $display("init: 0x%01x, update: 0x%01x, finish: 0x%01x", dut.init, dut.update, dut.finish); 129 | $display("block M: 0x%064x", dut.block[511 : 256]); 130 | $display("block L: 0x%064x", dut.block[255 : 000]); 131 | $display("blocklen: 0x%02x", dut.blocklen); 132 | $display("digest: 0x%064x", dut.digest); 133 | $display("ready: 0x%01x", dut.ready); 134 | $display(""); 135 | $display("blake2s_ctrl_reg: 0x%02x, blake2s_ctrl_new: 0x%02x, blake2s_ctrl_we: 0x%01x", 136 | dut.blake2s_ctrl_reg, dut.blake2s_ctrl_new, dut.blake2s_ctrl_we); 137 | $display(""); 138 | 139 | $display("h0: 0x%08x, h1: 0x%08x, h2: 0x%08x, h3: 0x%08x", 140 | dut.h_reg[0], dut.h_reg[1], dut.h_reg[2], dut.h_reg[3]); 141 | $display("h4: 0x%08x, h5: 0x%08x, h6: 0x%08x, h7: 0x%08x", 142 | dut.h_reg[4], dut.h_reg[5], dut.h_reg[6], dut.h_reg[7]); 143 | $display(""); 144 | $display("v0: 0x%08x, v1: 0x%08x, v2: 0x%08x, v3: 0x%08x", 145 | dut.v_reg[0], dut.v_reg[1], dut.v_reg[2], dut.v_reg[3]); 146 | $display("v4: 0x%08x, v5: 0x%08x, v6: 0x%08x, v7: 0x%08x", 147 | dut.v_reg[4], dut.v_reg[5], dut.v_reg[6], dut.v_reg[7]); 148 | $display("v8: 0x%08x, v9: 0x%08x, v10: 0x%08x, v11: 0x%08x", 149 | dut.v_reg[8], dut.v_reg[9], dut.v_reg[10], dut.v_reg[11]); 150 | $display("v12: 0x%08x, v13: 0x%08x, v14: 0x%08x, v15: 0x%08x", 151 | dut.v_reg[12], dut.v_reg[13], dut.v_reg[14], dut.v_reg[15]); 152 | $display("init_v: 0x%1x, update_v: 0x%1x, v_we: 0x%1x", dut.init_v, dut.update_v, dut.v_we); 153 | $display(""); 154 | 155 | $display("t0_reg: 0x%08x, t0_new: 0x%08x", dut.t0_reg, dut.t0_new); 156 | $display("t1_reg: 0x%08x, t1_new: 0x%08x", dut.t1_reg, dut.t1_new); 157 | $display("t_ctr_rst: 0x%1x, t_ctr_inc: 0x%1x", dut.t_ctr_rst, dut.t_ctr_inc); 158 | $display("last_reg: 0x%1x, last_new: 0x%1x, last_we: 0x%1x", 159 | dut.last_reg, dut.last_new, dut.last_we); 160 | $display(""); 161 | 162 | $display("v0_new: 0x%08x, v1_new: 0x%08x, v2_new: 0x%08x, v3_new: 0x%08x", 163 | dut.v_new[0], dut.v_new[1], dut.v_new[2], dut.v_new[3]); 164 | $display("v4_new: 0x%08x, v5_new: 0x%08x, v6_new: 0x%08x, v7_new: 0x%08x", 165 | dut.v_new[4], dut.v_new[5], dut.v_new[6], dut.v_new[7]); 166 | $display("v8_new: 0x%08x, v9_new: 0x%08x, v10_new: 0x%08x, v11_new: 0x%08x", 167 | dut.v_new[8], dut.v_new[9], dut.v_new[10], dut.v_new[11]); 168 | $display("v12_new: 0x%08x, v13_new: 0x%08x, v14_new: 0x%08x, v15_new: 0x%08x", 169 | dut.v_new[12], dut.v_new[13], dut.v_new[14], dut.v_new[15]); 170 | $display(""); 171 | 172 | $display("G_mode: 0x%1x, ", dut.G_mode); 173 | $display("G0_m0: 0x%08x, G0_m1: 0x%08x, G1_m0: 0x%08x, G1_m1: 0x%08x", 174 | dut.G0_m0, dut.G0_m1, dut.G1_m0, dut.G1_m1); 175 | $display("G2_m0: 0x%08x, G2_m1: 0x%08x, G3_m0: 0x%08x, G3_m1: 0x%08x", 176 | dut.G2_m0, dut.G2_m1, dut.G3_m0, dut.G3_m1); 177 | $display("round_ctr_reg: 0x%02x, round_ctr_new: 0x%02x", dut.round_ctr_reg, dut.round_ctr_reg); 178 | $display("round_ctr_rst: 0x%1x, round_ctr_inc: 0x%1x, round_ctr_we: 0x%1x", 179 | dut.round_ctr_rst, dut.round_ctr_inc, dut.round_ctr_we); 180 | $display("-------------------------------------------------------------------------------------"); 181 | $display("-------------------------------------------------------------------------------------"); 182 | $display(""); 183 | $display(""); 184 | end 185 | endtask // dump_dut_state 186 | 187 | 188 | //---------------------------------------------------------------- 189 | // inc_tc_ctr 190 | //---------------------------------------------------------------- 191 | task inc_tc_ctr; 192 | tc_ctr = tc_ctr + 1; 193 | endtask // inc_tc_ctr 194 | 195 | 196 | //---------------------------------------------------------------- 197 | // inc_error_ctr 198 | //---------------------------------------------------------------- 199 | task inc_error_ctr; 200 | error_ctr = error_ctr + 1; 201 | endtask // inc_error_ctr 202 | 203 | 204 | //---------------------------------------------------------------- 205 | // pause_finish() 206 | // 207 | // Pause for a given number of cycles and then finish sim. 208 | //---------------------------------------------------------------- 209 | task pause_finish(input [31 : 0] num_cycles); 210 | begin 211 | $display("--- Pausing for %04d cycles and then finishing hard.", num_cycles); 212 | #(num_cycles * CLK_PERIOD); 213 | $finish; 214 | end 215 | endtask // pause_finish 216 | 217 | 218 | //---------------------------------------------------------------- 219 | // wait_ready() 220 | // 221 | // Wait for the ready flag to be set in dut. 222 | //---------------------------------------------------------------- 223 | task wait_ready; 224 | begin : wready 225 | while (!tb_ready) 226 | #(CLK_PERIOD); 227 | end 228 | endtask // wait_ready 229 | 230 | 231 | //---------------------------------------------------------------- 232 | // display_test_result() 233 | // 234 | // Display the accumulated test results. 235 | //---------------------------------------------------------------- 236 | task display_test_result; 237 | begin 238 | $display("--- %02d test cases executed ---", tc_ctr); 239 | if (error_ctr == 0) 240 | begin 241 | $display("--- All %02d test cases completed successfully ---", tc_ctr); 242 | end 243 | else 244 | begin 245 | $display("--- %02d test cases did not complete successfully ---", error_ctr); 246 | end 247 | end 248 | endtask // display_test_result 249 | 250 | 251 | //---------------------------------------------------------------- 252 | // init_sim() 253 | // 254 | // Set the input to the DUT to defined values. 255 | //---------------------------------------------------------------- 256 | task init_sim; 257 | begin 258 | cycle_ctr = 0; 259 | error_ctr = 0; 260 | tc_ctr = 0; 261 | 262 | display_cycle_ctr = 1; 263 | display_dut_state = 0; 264 | 265 | tb_clk = 1'h0; 266 | tb_reset_n = 1'h1; 267 | tb_init = 1'h0; 268 | tb_update = 1'h0; 269 | tb_finish = 1'h0; 270 | tb_block = 512'h0; 271 | tb_blocklen = 7'h0; 272 | end 273 | endtask // init_sim 274 | 275 | 276 | //---------------------------------------------------------------- 277 | // reset_dut() 278 | // 279 | // Toggle reset to put the DUT into a well known state. 280 | //---------------------------------------------------------------- 281 | task reset_dut; 282 | begin 283 | $display("--- TB: Resetting dut."); 284 | tb_reset_n = 1'h0; 285 | #(2 * CLK_PERIOD); 286 | tb_reset_n = 1'h1; 287 | #(2 * CLK_PERIOD); 288 | $display("--- TB: Reset done."); 289 | end 290 | endtask // reset_dut 291 | 292 | 293 | //---------------------------------------------------------------- 294 | // test_empty_message 295 | //---------------------------------------------------------------- 296 | task test_empty_message; 297 | begin : test_rfc_7693 298 | tc_ctr = tc_ctr + 1; 299 | 300 | $display(""); 301 | $display("--- test_empty_message: Started."); 302 | 303 | $display("--- test_empty_message: Asserting init."); 304 | tb_init = 1'h1; 305 | #(CLK_PERIOD); 306 | tb_init = 1'h0; 307 | 308 | wait_ready(); 309 | $display("--- test_empty_message: Init should be completed."); 310 | 311 | 312 | #(CLK_PERIOD); 313 | $display("--- test_empty_message: Asserting finish."); 314 | tb_blocklen = 7'h00; 315 | tb_block = 512'h0; 316 | tb_finish = 1'h1; 317 | #(CLK_PERIOD); 318 | tb_finish = 1'h0; 319 | wait_ready(); 320 | 321 | $display("--- test_empty_message: Finish should be completed."); 322 | #(CLK_PERIOD); 323 | 324 | $display("--- test_empty_message: Checking generated digest."); 325 | if (tb_digest == 256'h69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9) begin 326 | $display("--- test_empty_message: Correct digest generated."); 327 | $display("--- test_empty_message: Got: 0x%064x", tb_digest); 328 | end else begin 329 | $display("--- test_empty_message: Error. Incorrect digest generated."); 330 | $display("--- test_empty_message: Expected: 0x69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"); 331 | $display("--- test_empty_message: Got: 0x%064x", tb_digest); 332 | error_ctr = error_ctr + 1; 333 | end 334 | 335 | $display("--- test_empty_message: Completed.\n"); 336 | end 337 | endtask // test_empty_message 338 | 339 | 340 | //---------------------------------------------------------------- 341 | // test_one_block_message 342 | //---------------------------------------------------------------- 343 | task test_one_block_message; 344 | begin: test_one_block_message 345 | tc_ctr = tc_ctr + 1; 346 | 347 | $display(""); 348 | $display("--- test_one_block_message: Started."); 349 | 350 | #(CLK_PERIOD); 351 | $display("--- test_one_block_message: Asserting init."); 352 | tb_init = 1'h1; 353 | #(CLK_PERIOD); 354 | tb_init = 1'h0; 355 | 356 | wait_ready(); 357 | $display("--- test_one_block_message: Init completed."); 358 | 359 | tb_block = 512'h00010203_04050607_08090a0b_0c0d0e0f_10111213_14151617_18191a1b_1c1d1e1f_20212223_24252627_28292a2b_2c2d2e2f_30313233_34353637_38393a3b_3c3d3e3f; 360 | tb_blocklen = 7'h40; 361 | $display("--- test_one_block_message: Asserting finish."); 362 | tb_finish = 1'h1; 363 | #(CLK_PERIOD); 364 | tb_finish = 1'h0; 365 | wait_ready(); 366 | $display("--- test_one_block_message: Finish completed."); 367 | #(CLK_PERIOD); 368 | 369 | if (dut.digest == 256'h56f34e8b96557e90c1f24b52d0c89d51086acf1b00f634cf1dde9233b8eaaa3e) begin 370 | $display("--- test_one_block_message: Correct digest generated."); 371 | $display("--- test_one_block_message: Got: 0x%064x", dut.digest); 372 | 373 | end else begin 374 | $display("--- test_one_block_message: ERROR incorrect digest generated."); 375 | $display("--- test_one_block_message: Expected: 0x56f34e8b96557e90c1f24b52d0c89d51086acf1b00f634cf1dde9233b8eaaa3e"); 376 | $display("--- test_one_block_message: Got: 0x%064x", dut.digest); 377 | error_ctr = error_ctr + 1; 378 | end 379 | 380 | $display("--- test_one_block_message: Completed.\n"); 381 | #(2 * CLK_PERIOD); 382 | 383 | end 384 | endtask // test_one_block_message 385 | 386 | 387 | //---------------------------------------------------------------- 388 | // test_one_block_one_byte_message 389 | //---------------------------------------------------------------- 390 | task test_one_block_one_byte_message; 391 | begin: test_one_block_one_byte_message 392 | tc_ctr = tc_ctr + 1; 393 | 394 | $display(""); 395 | $display("--- test_one_block_one_byte_message: Started."); 396 | 397 | #(CLK_PERIOD); 398 | $display("--- test_one_block_one_byte_message: Asserting init."); 399 | tb_init = 1'h1; 400 | #(CLK_PERIOD); 401 | tb_init = 1'h0; 402 | 403 | wait_ready(); 404 | $display("--- test_one_block_one_byte_message: Init completed."); 405 | 406 | tb_block = 512'h00010203_04050607_08090a0b_0c0d0e0f_10111213_14151617_18191a1b_1c1d1e1f_20212223_24252627_28292a2b_2c2d2e2f_30313233_34353637_38393a3b_3c3d3e3f; 407 | tb_blocklen = 7'h40; 408 | $display("--- test_one_block_one_byte_message: Asserting update."); 409 | tb_update = 1'h1; 410 | #(CLK_PERIOD); 411 | tb_update = 1'h0; 412 | 413 | wait_ready(); 414 | $display("--- test_one_block_one_byte_message: Update completed."); 415 | #(CLK_PERIOD); 416 | 417 | tb_block = {8'h40, {63{8'h00}}}; 418 | tb_blocklen = 7'h01; 419 | $display("--- test_one_block_one_byte_message: Asserting finish."); 420 | tb_finish = 1'h1; 421 | #(CLK_PERIOD); 422 | tb_finish = 1'h0; 423 | wait_ready(); 424 | $display("--- test_one_block_one_byte_message: Finish completed."); 425 | #(CLK_PERIOD); 426 | 427 | if (dut.digest == 256'h1b53ee94aaf34e4b159d48de352c7f0661d0a40edff95a0b1639b4090e974472) begin 428 | $display("--- test_one_block_one_byte_message: Correct digest generated."); 429 | $display("--- test_one_block_one_byte_message: Got: 0x%064x", dut.digest); 430 | 431 | end else begin 432 | $display("--- test_one_block_one_byte_message: ERROR incorrect digest generated."); 433 | $display("--- test_one_block_one_byte_message: Expected: 0x1b53ee94aaf34e4b159d48de352c7f0661d0a40edff95a0b1639b4090e974472"); 434 | $display("--- test_one_block_one_byte_message: Got: 0x%064x", dut.digest); 435 | error_ctr = error_ctr + 1; 436 | end 437 | 438 | $display("--- test_one_block_one_byte_message: Completed.\n"); 439 | #(2 * CLK_PERIOD); 440 | 441 | end 442 | endtask // test_one_block_one_byte_message 443 | 444 | 445 | //---------------------------------------------------------------- 446 | // test_rfc_7693 447 | // Test using testvectors from RFC 7693. 448 | //---------------------------------------------------------------- 449 | task test_rfc_7693; 450 | begin : test_rfc_7693 451 | tc_ctr = tc_ctr + 1; 452 | 453 | $display(""); 454 | $display("--- test_rfc_7693: Started."); 455 | 456 | $display("--- test_rfc_7693: Asserting init."); 457 | tb_init = 1'h1; 458 | #(CLK_PERIOD); 459 | tb_init = 1'h0; 460 | 461 | wait_ready(); 462 | $display("--- test_rfc_7693: Init should be completed."); 463 | 464 | 465 | #(CLK_PERIOD); 466 | $display("--- test_rfc_7693: Setting message and message length."); 467 | tb_blocklen = 7'h03; 468 | tb_block = {32'h61626300, {15{32'h0}}}; 469 | $display("--- test_rfc_7693: Asserting finish."); 470 | tb_finish = 1'h1; 471 | #(CLK_PERIOD); 472 | tb_finish = 1'h0; 473 | wait_ready(); 474 | 475 | $display("--- test_rfc_7693: Finish should be completed."); 476 | #(CLK_PERIOD); 477 | 478 | $display("--- test_rfc_7693: Checking generated digest."); 479 | if (tb_digest == 256'h508c5e8c327c14e2_e1a72ba34eeb452f_37458b209ed63a29_4d999b4c86675982) begin 480 | $display("--- test_rfc_7693: Correct digest generated."); 481 | $display("--- test_rfc_7693: Got: 0x%064x", tb_digest); 482 | end else begin 483 | $display("--- test_rfc_7693: Error. Incorrect digest generated."); 484 | $display("--- test_rfc_7693: Expected: 0x508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"); 485 | $display("--- test_rfc_7693: Got: 0x%064x", tb_digest); 486 | error_ctr = error_ctr + 1; 487 | end 488 | 489 | $display("--- test_rfc_7693: Completed.\n"); 490 | end 491 | endtask // test_rfc_7693 492 | 493 | 494 | //---------------------------------------------------------------- 495 | // testrunner 496 | // 497 | // The main test functionality. 498 | //---------------------------------------------------------------- 499 | initial 500 | begin : testrunner 501 | $display(""); 502 | $display("-------------------------------------------"); 503 | $display("--- Testbench for BLAKE2s core started ---"); 504 | $display("-------------------------------------------"); 505 | $display(""); 506 | 507 | init_sim(); 508 | reset_dut(); 509 | 510 | test_empty_message(); 511 | test_one_block_message(); 512 | test_one_block_one_byte_message(); 513 | test_rfc_7693(); 514 | 515 | display_test_result(); 516 | 517 | $display(""); 518 | $display("-------------------------------------------"); 519 | $display("--- testbench for BLAKE2s core completed ---"); 520 | $display("--------------------------------------------"); 521 | $display(""); 522 | $finish_and_return(error_ctr); 523 | end // testrunner 524 | 525 | endmodule // tb_blake2s_core 526 | 527 | //====================================================================== 528 | // EOF tb_blake2s_core.v 529 | //====================================================================== 530 | -------------------------------------------------------------------------------- /src/tb/tb_blake2s_m_select.v: -------------------------------------------------------------------------------- 1 | //====================================================================== 2 | // 3 | // tb_blake2s_m_select.v 4 | // --------------------- 5 | // Testbench for the BLAKE2s M selection module. 6 | // 7 | // 8 | // Author: Joachim Strömbergson 9 | // Copyright (c) 2018, Assured AB 10 | // All rights reserved. 11 | // 12 | // Redistribution and use in source and binary forms, with or 13 | // without modification, are permitted provided that the following 14 | // conditions are met: 15 | // 16 | // 1. Redistributions of source code must retain the above copyright 17 | // notice, this list of conditions and the following disclaimer. 18 | // 19 | // 2. Redistributions in binary form must reproduce the above copyright 20 | // notice, this list of conditions and the following disclaimer in 21 | // the documentation and/or other materials provided with the 22 | // distribution. 23 | // 24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | // 37 | //====================================================================== 38 | 39 | module tb_blake2s_m_select(); 40 | 41 | //---------------------------------------------------------------- 42 | // Internal constant and parameter definitions. 43 | //---------------------------------------------------------------- 44 | parameter VERBOSE = 1; 45 | 46 | parameter CLK_HALF_PERIOD = 2; 47 | parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD; 48 | 49 | 50 | //---------------------------------------------------------------- 51 | // Register and Wire declarations. 52 | //---------------------------------------------------------------- 53 | reg [63 : 0] cycle_ctr; 54 | reg [31 : 0] error_ctr; 55 | reg [31 : 0] tc_ctr; 56 | 57 | reg tb_clk; 58 | reg tb_reset_n; 59 | reg tb_load; 60 | reg [511 : 0] tb_m; 61 | reg [3 : 0] tb_round; 62 | reg tb_mode; 63 | wire [31 : 0] tb_G0_m0; 64 | wire [31 : 0] tb_G0_m1; 65 | wire [31 : 0] tb_G1_m0; 66 | wire [31 : 0] tb_G1_m1; 67 | wire [31 : 0] tb_G2_m0; 68 | wire [31 : 0] tb_G2_m1; 69 | wire [31 : 0] tb_G3_m0; 70 | wire [31 : 0] tb_G3_m1; 71 | 72 | reg display_cycle_ctr; 73 | 74 | 75 | //---------------------------------------------------------------- 76 | // blake2_G device under test. 77 | //---------------------------------------------------------------- 78 | blake2s_m_select dut( 79 | .clk(tb_clk), 80 | .reset_n(tb_reset_n), 81 | .load(tb_load), 82 | .m(tb_m), 83 | .round(tb_round), 84 | .mode(tb_mode), 85 | .G0_m0(tb_G0_m0), 86 | .G0_m1(tb_G0_m1), 87 | .G1_m0(tb_G1_m0), 88 | .G1_m1(tb_G1_m1), 89 | .G2_m0(tb_G2_m0), 90 | .G2_m1(tb_G2_m1), 91 | .G3_m0(tb_G3_m0), 92 | .G3_m1(tb_G3_m1) 93 | ); 94 | 95 | 96 | //---------------------------------------------------------------- 97 | // clk_gen 98 | // 99 | // Clock generator process. 100 | //---------------------------------------------------------------- 101 | always 102 | begin : clk_gen 103 | #CLK_HALF_PERIOD tb_clk = !tb_clk; 104 | end // clk_gen 105 | 106 | 107 | //-------------------------------------------------------------------- 108 | // dut_monitor 109 | // 110 | // Monitor displaying information every cycle. 111 | // Includes the cycle counter. 112 | //-------------------------------------------------------------------- 113 | always @ (posedge tb_clk) 114 | begin : dut_monitor 115 | cycle_ctr = cycle_ctr + 1; 116 | 117 | if (display_cycle_ctr) 118 | begin 119 | $display("cycle = %016x:", cycle_ctr); 120 | end 121 | 122 | end // dut_monitor 123 | 124 | 125 | //---------------------------------------------------------------- 126 | // dump_dut_state 127 | // 128 | // Dump the internal state of the dut to std out. 129 | //---------------------------------------------------------------- 130 | task dump_dut_state; 131 | begin 132 | if (VERBOSE) 133 | begin 134 | $display(""); 135 | $display("DUT internal state"); 136 | $display("------------------"); 137 | $display("contents of m:"); 138 | $display("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ", 139 | dut.m_mem[0], dut.m_mem[1], dut.m_mem[2], dut.m_mem[3], 140 | dut.m_mem[4], dut.m_mem[5], dut.m_mem[6], dut.m_mem[7]); 141 | 142 | $display("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ", 143 | dut.m_mem[8], dut.m_mem[9], dut.m_mem[10], dut.m_mem[11], 144 | dut.m_mem[12], dut.m_mem[13], dut.m_mem[14], dut.m_mem[15]); 145 | $display(""); 146 | end 147 | end 148 | endtask // dump_dut_state 149 | 150 | 151 | //---------------------------------------------------------------- 152 | // display_test_result() 153 | // 154 | // Display the accumulated test results. 155 | //---------------------------------------------------------------- 156 | task display_test_result; 157 | begin 158 | $display("--- %02d test cases executed ---", tc_ctr); 159 | if (error_ctr == 0) 160 | begin 161 | $display("--- All %02d test cases completed successfully ---", tc_ctr); 162 | end 163 | else 164 | begin 165 | $display("--- %02d test cases did not complete successfully. ---", error_ctr); 166 | end 167 | end 168 | endtask // display_test_result 169 | 170 | 171 | //---------------------------------------------------------------- 172 | // init_dut() 173 | // 174 | // Set the input to the DUT to defined values. 175 | //---------------------------------------------------------------- 176 | task init_dut; 177 | begin 178 | cycle_ctr = 0; 179 | error_ctr = 0; 180 | display_cycle_ctr = 0; 181 | 182 | tc_ctr = 0; 183 | tb_clk = 0; 184 | tb_reset_n = 1; 185 | tb_load = 0; 186 | tb_m = 512'h0; 187 | tb_round = 0; 188 | tb_mode = 0; 189 | end 190 | endtask // init_dut 191 | 192 | 193 | //---------------------------------------------------------------- 194 | // test_reset 195 | // 196 | // Check that the m_memory registers cleared by dropping reset. 197 | //---------------------------------------------------------------- 198 | task test_reset; 199 | begin : tc_reset 200 | tc_ctr = tc_ctr + 1; 201 | 202 | $display("--- Testing that reset clears the m memory"); 203 | $display("--- Memory before reset:"); 204 | dump_dut_state(); 205 | tb_reset_n = 0; 206 | #(CLK_PERIOD); 207 | $display("--- Pulling reset"); 208 | tb_reset_n = 1; 209 | #(CLK_PERIOD); 210 | $display("--- Memory after reset:"); 211 | dump_dut_state(); 212 | $display(""); 213 | end 214 | endtask // test_reset 215 | 216 | 217 | //---------------------------------------------------------------- 218 | // test_case1 219 | // 220 | // Check that we can load a known block into m and get the 221 | // big to little endian conversion performed during load. 222 | //---------------------------------------------------------------- 223 | task test_case1; 224 | begin : tc1 225 | tc_ctr = tc_ctr + 1; 226 | 227 | tb_round = 0; 228 | tb_mode = 0; 229 | tb_load = 0; 230 | tb_m = {32'h00010203, 32'h04050607, 32'h08090a0b, 32'h0c0d0e0f, 231 | 32'h10111213, 32'h14151617, 32'h18191a1b, 32'h1c1d1e1f, 232 | 32'h20212223, 32'h24252627, 32'h28292a2b, 32'h2c2d2e2f, 233 | 32'h30313233, 32'h34353637, 32'h38393a3b, 32'h3c3d3e3f}; 234 | 235 | $display("--- TC1: Test case 1 started. Loading the m with a known block"); 236 | $display("--- TC1: Before loading:"); 237 | dump_dut_state(); 238 | 239 | tb_load = 1; 240 | #(CLK_PERIOD); 241 | tb_load = 0; 242 | $display("--- TC1: After loading:"); 243 | dump_dut_state(); 244 | 245 | $display(""); 246 | end 247 | endtask // test_case1 248 | 249 | 250 | //---------------------------------------------------------------- 251 | // test_case2 252 | // 253 | // Check that we can get expected words based on rounds and mode. 254 | //---------------------------------------------------------------- 255 | task test_case2; 256 | begin : tc2 257 | integer i; 258 | 259 | tc_ctr = tc_ctr + 1; 260 | 261 | tb_round = 0; 262 | tb_mode = 0; 263 | 264 | tb_load = 0; 265 | tb_m = {32'h00010203, 32'h04050607, 32'h08090a0b, 32'h0c0d0e0f, 266 | 32'h10111213, 32'h14151617, 32'h18191a1b, 32'h1c1d1e1f, 267 | 32'h20212223, 32'h24252627, 32'h28292a2b, 32'h2c2d2e2f, 268 | 32'h30313233, 32'h34353637, 32'h38393a3b, 32'h3c3d3e3f}; 269 | 270 | $display("--- TC2: Test case 2 started. Loading the m with a known block"); 271 | tb_load = 1; 272 | #(CLK_PERIOD); 273 | tb_load = 0; 274 | 275 | $display("--- TC2: Looping over all rounds and modes."); 276 | for (i = 0 ; i < 16 ; i = i + 1) begin 277 | tb_round = i[3 : 0]; 278 | tb_mode = 0; 279 | #(CLK_PERIOD); 280 | $display("--- TC2: round %2d, mode: %1x:", tb_round, tb_mode); 281 | $display("--- G0_m0: 0x%08x, G0_m1: 0x%08x, G1_m0: 0x%08x, G1_m1: 0x%08x", 282 | tb_G0_m0, tb_G0_m1, tb_G1_m0, tb_G1_m1); 283 | $display("--- G2_m0: 0x%08x, G2_m1: 0x%08x, G3_m0: 0x%08x, G3_m1: 0x%08x", 284 | tb_G2_m0, tb_G2_m1, tb_G3_m0, tb_G3_m1); 285 | #(CLK_PERIOD); 286 | 287 | tb_mode = 1; 288 | #(CLK_PERIOD); 289 | $display("--- TC2: round %2d, mode: %1x:", tb_round, tb_mode); 290 | $display("--- G0_m0: 0x%08x, G0_m1: 0x%08x, G1_m0: 0x%08x, G1_m1: 0x%08x", 291 | tb_G0_m0, tb_G0_m1, tb_G1_m0, tb_G1_m1); 292 | $display("--- G2_m0: 0x%08x, G2_m1: 0x%08x, G3_m0: 0x%08x, G3_m1: 0x%08x", 293 | tb_G2_m0, tb_G2_m1, tb_G3_m0, tb_G3_m1); 294 | #(CLK_PERIOD); 295 | end 296 | 297 | $display("--- TC2: Test case 2 completed"); 298 | tb_load = 1; 299 | $display(""); 300 | end 301 | endtask // test_case1 302 | 303 | 304 | //---------------------------------------------------------------- 305 | // testrunner 306 | // 307 | // The main test functionality. 308 | //---------------------------------------------------------------- 309 | initial 310 | begin : testrunner 311 | $display("--- Testbench for BLAKE2 m select module started ---"); 312 | $display("----------------------------------------------------"); 313 | $display(""); 314 | 315 | init_dut(); 316 | test_reset(); 317 | test_case1(); 318 | test_case2(); 319 | 320 | display_test_result(); 321 | $display("--- Testbench for BLAKE2 m select module completed ---"); 322 | $display("------------------------------------------------------"); 323 | $finish_and_return(error_ctr); 324 | end // testrunner 325 | 326 | endmodule // tb_blake2s_m_select 327 | 328 | //====================================================================== 329 | // EOF tb_blake2s_m_select.v 330 | //====================================================================== 331 | -------------------------------------------------------------------------------- /toolruns/Makefile: -------------------------------------------------------------------------------- 1 | #=================================================================== 2 | # 3 | # Makefile 4 | # -------- 5 | # Makefile for building the blake2s simulation targets, perform 6 | # linting etc. 7 | # 8 | # 9 | # Author: Joachim Strombergson 10 | # Copyright (c) 2018, Assured AB 11 | # All rights reserved. 12 | # 13 | # Redistribution and use in source and binary forms, with or 14 | # without modification, are permitted provided that the following 15 | # conditions are met: 16 | # 17 | # 1. Redistributions of source code must retain the above copyright 18 | # notice, this list of conditions and the following disclaimer. 19 | # 20 | # 2. Redistributions in binary form must reproduce the above copyright 21 | # notice, this list of conditions and the following disclaimer in 22 | # the documentation and/or other materials provided with the 23 | # distribution. 24 | # 25 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 34 | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 36 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | # 38 | #=================================================================== 39 | 40 | # Sources. 41 | GF_SRC = ../src/rtl/blake2s_G.v 42 | TB_GF_SRC = ../src/tb/tb_blake2s_G.v 43 | 44 | M_SELECT_SRC = ../src/rtl/blake2s_m_select.v 45 | TB_M_SELECT_SRC = ../src/tb/tb_blake2s_m_select.v 46 | 47 | CORE_SRC = ../src/rtl/blake2s_core.v $(M_SELECT_SRC) $(ROUND_SRC) $(GF_SRC) 48 | TB_CORE_SRC = ../src/tb/tb_blake2s_core.v 49 | 50 | TOP_SRC= ../src/rtl/blake2s.v $(CORE_SRC) 51 | TB_TOP_SRC = ../src/tb/tb_blake2s.v 52 | 53 | 54 | # Tools and flags. 55 | CC= iverilog 56 | CC_FLAGS= -Wall 57 | 58 | LINT= verilator 59 | LINT_FLAGS = +1364-2001ext+ --lint-only -Wall -Wno-fatal -Wno-DECLFILENAME 60 | 61 | 62 | # Targets. 63 | all: gf.sim m.sim core.sim top.sim 64 | 65 | 66 | gf.sim: $(TB_GF_SRC) $(GF_SRC) 67 | $(CC) $(CC_FLAGS) -o $@ $^ 68 | 69 | 70 | m.sim: $(TB_M_SELECT_SRC) $(M_SELECT_SRC) 71 | $(CC) $(CC_FLAGS) -o $@ $^ 72 | 73 | 74 | core.sim: $(TB_CORE_SRC) $(CORE_SRC) 75 | $(CC) $(CC_FLAGS) -o $@ $^ 76 | 77 | 78 | top.sim: $(TB_TOP_SRC) $(TOP_SRC) 79 | $(CC) $(CC_FLAGS) -o $@ $^ 80 | 81 | 82 | lint: $(TOP_SRC) 83 | $(LINT) $(LINT_FLAGS) $^ 84 | 85 | 86 | clean: 87 | rm -f *.sim 88 | rm -f *.log 89 | rm -f *.txt 90 | 91 | 92 | help: 93 | @echo "Build system for simulation of BLAKE2s core." 94 | @echo "" 95 | @echo "Supported targets:" 96 | @echo "------------------" 97 | @echo "all: Build all simulation targets." 98 | @echo "lint: Run linter on all rtl source files." 99 | @echo "top.sim: Build top level simulation target." 100 | @echo "core.sim: Build core level simulation target." 101 | @echo "gf.sim: Build G function simulation target." 102 | @echo "m.sim: Build m select module simulation target." 103 | @echo "clean: Delete all built files." 104 | @echo "help: This is it." 105 | 106 | #=================================================================== 107 | # EOF Makefile 108 | #=================================================================== 109 | --------------------------------------------------------------------------------