├── .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 | [](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 |
--------------------------------------------------------------------------------