├── project
├── build.properties
└── plugins.sbt
├── media
├── AES.pdf
└── AES-dinotrace-waves.jpg
├── src
├── main
│ └── scala
│ │ ├── aes
│ │ ├── Params.scala
│ │ ├── AddRoundKey.scala
│ │ ├── ShiftRows.scala
│ │ ├── InvShiftRows.scala
│ │ ├── DASCA.scala
│ │ ├── Cipher.scala
│ │ ├── InvCipher.scala
│ │ ├── CipherRound.scala
│ │ ├── InvSubBytes.scala
│ │ ├── InvCipherRound.scala
│ │ ├── SubBytes.scala
│ │ ├── AES.scala
│ │ ├── ExpandedKey.scala
│ │ ├── ROMeKeys.scala
│ │ └── MixColumns.scala
│ │ ├── gcd
│ │ └── GCD.scala
│ │ └── lfsr
│ │ └── LFSR.scala
└── test
│ └── scala
│ ├── gcd
│ ├── GCDMain.scala
│ └── GCDUnitTest.scala
│ ├── lfsr
│ └── LFSRUnitTest.scala
│ └── aes
│ ├── DASCAUnitTest.scala
│ ├── AddRoundKeyUnitTest.scala
│ ├── ShiftRowsUnitTest.scala
│ ├── InvShiftRowsUnitTest.scala
│ ├── CipherRoundUnitTest.scala
│ ├── InvCipherRoundUnitTest.scala
│ ├── SubBytesUnitTest.scala
│ ├── InvSubBytesUnitTest.scala
│ ├── CipherUnitTest.scala
│ ├── InvCipherUnitTest.scala
│ ├── AESUnitTest.scala
│ ├── UnrolledAESUnitTest.scala
│ ├── MixColumnsUnitTest.scala
│ └── InvMixColumnsUnitTest.scala
├── aes_tests.sh
├── tutorials
├── 01.test_aes_chisel.md
└── deploying_to_maven.md
├── README.md
├── scalastyle-config.xml
├── .gitignore
├── scalastyle-test-config.xml
└── LICENSE
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version = 1.1.1
2 |
--------------------------------------------------------------------------------
/media/AES.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hplp/aes_chisel/HEAD/media/AES.pdf
--------------------------------------------------------------------------------
/media/AES-dinotrace-waves.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hplp/aes_chisel/HEAD/media/AES-dinotrace-waves.jpg
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | logLevel := Level.Warn
2 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.3")
3 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1")
4 |
--------------------------------------------------------------------------------
/src/main/scala/aes/Params.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | object Params {
4 | val Nb: Int = 4 // columns in state (in this standard)
5 | val rows: Int = 4
6 | val StateLength: Int = Nb * rows
7 | }
--------------------------------------------------------------------------------
/src/main/scala/aes/AddRoundKey.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements AddRoundKey
7 | class AddRoundKey(Pipelined: Boolean = false) extends Module {
8 | val io = IO(new Bundle {
9 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
10 | val roundKey = Input(Vec(Params.StateLength, UInt(8.W)))
11 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
12 | })
13 |
14 | for (i <- 0 until Params.StateLength) {
15 | if (Pipelined) {
16 | io.state_out(i) := ShiftRegister(io.state_in(i) ^ io.roundKey(i), 1)
17 | } else {
18 | io.state_out(i) := io.state_in(i) ^ io.roundKey(i)
19 | }
20 | }
21 | }
22 |
23 | object AddRoundKey {
24 | def apply(Pipelined: Boolean = false): AddRoundKey = Module(new AddRoundKey(Pipelined))
25 | }
--------------------------------------------------------------------------------
/aes_tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # script to run all tests at once
3 |
4 | echo -e "SubBytesTester:\n"
5 | sbt 'testOnly aes.SubBytesTester'
6 |
7 | echo -e "ShiftRowsTester:\n"
8 | sbt 'testOnly aes.ShiftRowsTester'
9 |
10 | echo -e "MixColumnsTester:\n"
11 | sbt 'testOnly aes.MixColumnsTester'
12 |
13 | echo -e "InvSubBytesTester:\n"
14 | sbt 'testOnly aes.InvSubBytesTester'
15 |
16 | echo -e "InvShiftRowsTester:\n"
17 | sbt 'testOnly aes.InvShiftRowsTester'
18 |
19 | echo -e "InvMixColumnsTester:\n"
20 | sbt 'testOnly aes.InvMixColumnsTester'
21 |
22 | echo -e "AddRoundKeyTester:\n"
23 | sbt 'testOnly aes.AddRoundKeyTester'
24 |
25 | echo -e "CipherTester:\n"
26 | sbt 'testOnly aes.CipherTester'
27 |
28 | echo -e "InvCipherTester:\n"
29 | sbt 'testOnly aes.InvCipherTester'
30 |
31 | echo -e "AESTester:\n"
32 | sbt 'testOnly aes.AESTester'
33 |
34 |
35 | echo "Tests Finished!"
--------------------------------------------------------------------------------
/src/main/scala/gcd/GCD.scala:
--------------------------------------------------------------------------------
1 | // See README.md for license details.
2 |
3 | package gcd
4 |
5 | import chisel3._
6 |
7 | /**
8 | * Compute GCD using subtraction method.
9 | * Subtracts the smaller from the larger until register y is zero.
10 | * value in register x is then the GCD
11 | */
12 | class GCD extends Module {
13 | val io = IO(new Bundle {
14 | val value1 = Input(UInt(16.W))
15 | val value2 = Input(UInt(16.W))
16 | val loadingValues = Input(Bool())
17 | val outputGCD = Output(UInt(16.W))
18 | val outputValid = Output(Bool())
19 | })
20 |
21 | val x = Reg(UInt())
22 | val y = Reg(UInt())
23 |
24 | when(x > y) { x := x - y }
25 | .otherwise { y := y - x }
26 |
27 | when(io.loadingValues) {
28 | x := io.value1
29 | y := io.value2
30 | }
31 |
32 | io.outputGCD := x
33 | io.outputValid := y === 0.U
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/scala/aes/ShiftRows.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 |
5 | // implements ShiftRows
6 | class ShiftRows extends Module {
7 | val io = IO(new Bundle {
8 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
9 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
10 | })
11 |
12 | io.state_out(0) := io.state_in(0)
13 | io.state_out(1) := io.state_in(5)
14 | io.state_out(2) := io.state_in(10)
15 | io.state_out(3) := io.state_in(15)
16 |
17 | io.state_out(4) := io.state_in(4)
18 | io.state_out(5) := io.state_in(9)
19 | io.state_out(6) := io.state_in(14)
20 | io.state_out(7) := io.state_in(3)
21 |
22 | io.state_out(8) := io.state_in(8)
23 | io.state_out(9) := io.state_in(13)
24 | io.state_out(10) := io.state_in(2)
25 | io.state_out(11) := io.state_in(7)
26 |
27 | io.state_out(12) := io.state_in(12)
28 | io.state_out(13) := io.state_in(1)
29 | io.state_out(14) := io.state_in(6)
30 | io.state_out(15) := io.state_in(11)
31 | }
32 |
33 | object ShiftRows {
34 | def apply(): ShiftRows = Module(new ShiftRows())
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/scala/aes/InvShiftRows.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 |
5 | // implements InvShiftRows
6 | class InvShiftRows extends Module {
7 | val io = IO(new Bundle {
8 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
9 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
10 | })
11 |
12 | io.state_out(0) := io.state_in(0)
13 | io.state_out(1) := io.state_in(13)
14 | io.state_out(2) := io.state_in(10)
15 | io.state_out(3) := io.state_in(7)
16 |
17 | io.state_out(4) := io.state_in(4)
18 | io.state_out(5) := io.state_in(1)
19 | io.state_out(6) := io.state_in(14)
20 | io.state_out(7) := io.state_in(11)
21 |
22 | io.state_out(8) := io.state_in(8)
23 | io.state_out(9) := io.state_in(5)
24 | io.state_out(10) := io.state_in(2)
25 | io.state_out(11) := io.state_in(15)
26 |
27 | io.state_out(12) := io.state_in(12)
28 | io.state_out(13) := io.state_in(9)
29 | io.state_out(14) := io.state_in(6)
30 | io.state_out(15) := io.state_in(3)
31 | }
32 |
33 | object InvShiftRows {
34 | def apply(): InvShiftRows = Module(new InvShiftRows())
35 | }
--------------------------------------------------------------------------------
/src/main/scala/lfsr/LFSR.scala:
--------------------------------------------------------------------------------
1 | package lfsr
2 |
3 | import chisel3._
4 | import chisel3.util.Cat
5 |
6 | class LFSR extends Module {
7 | //declare input-output interface signals
8 | val io = IO(new Bundle {
9 | //clock and reset are default,
10 | //no other inputs necessary
11 | //lfsr_6 and lfsr_3r will have the random values
12 | val lfsr_6 = Output(UInt(6.W))
13 | val lfsr_3r = Output(UInt(3.W))
14 | })
15 |
16 | //declare the 6-bit register and initialize to 000001
17 | val D0123456 = RegInit(1.U(6.W)) //will init at reset
18 |
19 | //next clk value is XOR of 2 MSBs as LSB concatenated with left shift rest
20 | //example: 010010 => 100101 = Cat('10010','0^1')
21 | val nxt_D0123456 = Cat(D0123456(4, 0), D0123456(5) ^ D0123456(4))
22 |
23 | //update 6-bit register will happen in sync with clk
24 | D0123456 := nxt_D0123456
25 |
26 | //assign outputs
27 | io.lfsr_6 := D0123456
28 | //lfsr_3r in reverse order just for fun
29 | io.lfsr_3r := Cat(D0123456(1), D0123456(3), D0123456(5))
30 | }
31 |
32 | object LFSR {
33 | def apply(): LFSR = Module(new LFSR())
34 | }
--------------------------------------------------------------------------------
/src/main/scala/aes/DASCA.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 |
5 | class DASCA extends Module {
6 | val io = IO(new Bundle {
7 | val plaintext = Input(Vec(Params.StateLength, UInt(8.W))) // plaintext
8 | val roundKey = Input(Vec(Params.StateLength, UInt(8.W))) // roundKey
9 | val ciphertext = Output(Vec(Params.StateLength, UInt(8.W))) // ciphertext
10 | })
11 |
12 | printf("plaintext: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", io.plaintext(0), io.plaintext(1), io.plaintext(2), io.plaintext(3), io.plaintext(4), io.plaintext(5), io.plaintext(6), io.plaintext(7), io.plaintext(8), io.plaintext(9), io.plaintext(10), io.plaintext(11), io.plaintext(12), io.plaintext(13), io.plaintext(14), io.plaintext(15))
13 |
14 | // Instantiate module objects
15 | val AddRoundKeyModule = AddRoundKey()
16 | val SubBytesModule = SubBytes()
17 |
18 | // AddRoundKey whitening transform
19 | AddRoundKeyModule.io.state_in := io.plaintext
20 | AddRoundKeyModule.io.roundKey := io.roundKey
21 |
22 | // SubBytes transform
23 | SubBytesModule.io.state_in := AddRoundKeyModule.io.state_out
24 |
25 | // done!
26 | io.ciphertext := SubBytesModule.io.state_out
27 | }
28 |
29 | object DASCA {
30 | def apply(): DASCA = Module(new DASCA)
31 | }
--------------------------------------------------------------------------------
/tutorials/01.test_aes_chisel.md:
--------------------------------------------------------------------------------
1 | # How to run _aes_chisel_ tests?
2 |
3 | This repository can be overwhelming when getting started. There's just so much code and so many dependencies! This
4 | is why these instructions were created.
5 |
6 | ## Method 1: Run the provided script
7 |
8 | We, the author(s), provide a linux terminal script that executes all available tests, one by one. Thus, to run
9 | all tests, just run:
10 |
11 | ./aes_tests.sh > log.txt
12 | The test run details will be stored in the _log.txt_ file.
13 |
14 | Easy, right!? If you want to make sure that all the test files are generated from scratch, you can delete the directory
15 | before running the tests.
16 |
17 | rm -r test_run_dir
18 | Running all tests can take a while, but it's a simple method to check all modules.
19 |
20 | ## Method 2: Run with _sbt_
21 |
22 | Each test file (see _src/test/scala/aes/_) can be run with _sbt_ by executing
23 |
24 | sbt 'testOnly aes.ModuleNameTester'
25 | For example:
26 |
27 | sbt 'testOnly aes.AddRoundKeyTester'
28 | sbt 'testOnly aes.SubBytesTester'
29 | This will run all the available tests for that module. If you would like to run a specific test,
30 | add _-- -z_ plus a keyword available in the test description. Example:
31 |
32 | sbt 'testOnly aes.CipherTester -- -z verbose'
33 |
34 |
--------------------------------------------------------------------------------
/src/test/scala/gcd/GCDMain.scala:
--------------------------------------------------------------------------------
1 | // See README.md for license details.
2 |
3 | package gcd
4 |
5 | import chisel3._
6 |
7 | /**
8 | * This provides an alternate way to run tests, by executing then as a main
9 | * From sbt (Note: the test: prefix is because this main is under the test package hierarchy):
10 | * {{{
11 | * test:runMain gcd.GCDMain
12 | * }}}
13 | * To see all command line options use:
14 | * {{{
15 | * test:runMain gcd.GCDMain --help
16 | * }}}
17 | * To run with verilator:
18 | * {{{
19 | * test:runMain gcd.GCDMain --backend-name verilator
20 | * }}}
21 | * To run with verilator from your terminal shell use:
22 | * {{{
23 | * sbt 'test:runMain gcd.GCDMain --backend-name verilator'
24 | * }}}
25 | */
26 | object GCDMain extends App {
27 | iotesters.Driver.execute(args, () => new GCD) {
28 | c => new GCDUnitTester(c)
29 | }
30 | }
31 |
32 | /**
33 | * This provides a way to run the firrtl-interpreter REPL (or shell)
34 | * on the lowered firrtl generated by your circuit. You will be placed
35 | * in an interactive shell. This can be very helpful as a debugging
36 | * technique. Type help to see a list of commands.
37 | *
38 | * To run from sbt
39 | * {{{
40 | * test:runMain gcd.GCDRepl
41 | * }}}
42 | * To run from sbt and see the half a zillion options try
43 | * {{{
44 | * test:runMain gcd.GCDRepl --help
45 | * }}}
46 | */
47 | object GCDRepl extends App {
48 | iotesters.Driver.executeFirrtlRepl(args, () => new GCD)
49 | }
--------------------------------------------------------------------------------
/src/test/scala/lfsr/LFSRUnitTest.scala:
--------------------------------------------------------------------------------
1 | package lfsr
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class LFSRUnitTester(c: LFSR) extends PeekPokeTester(c) {
7 | //init D0123456 to 1
8 | var D0123456 = 1
9 | for (t <- 0 until 63) {
10 | step(1)
11 | val bit = ((D0123456 >> 5) ^ (D0123456 >> 4)) & 1;
12 | D0123456 = (D0123456 << 1) | bit;
13 | if (D0123456 > 63) {
14 | D0123456 = D0123456 - 64
15 | }
16 | expect(c.io.lfsr_6, D0123456)
17 | }
18 | }
19 |
20 | // Run with:
21 | // sbt 'testOnly lfsr.LFSRTester'
22 | // or sbt 'testOnly lfsr.LFSRTester -- -z verbose'
23 | // or sbt 'testOnly lfsr.LFSRTester -- -z vcd'
24 |
25 | class LFSRTester extends ChiselFlatSpec {
26 |
27 | private val backendNames = Array[String]("firrtl", "verilator")
28 | private val dir = "LFSR"
29 |
30 | for (backendName <- backendNames) {
31 | "LFSR" should s"calculate proper greatest common denominator (with $backendName)" in {
32 | Driver(() => new LFSR, backendName) {
33 | c => new LFSRUnitTester(c)
34 | } should be(true)
35 | }
36 | }
37 |
38 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
39 | iotesters.Driver.execute(
40 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new LFSR) {
41 | c => new LFSRUnitTester(c)
42 | } should be(true)
43 | }
44 |
45 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
46 | if (backendNames.contains("verilator")) {
47 | iotesters.Driver.execute(
48 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
49 | "--backend-name", "verilator"), () => new LFSR) {
50 | c => new LFSRUnitTester(c)
51 | } should be(true)
52 | }
53 | }
54 |
55 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
56 | if (backendNames.contains("firrtl")) {
57 | iotesters.Driver.execute(
58 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
59 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new LFSR) {
60 | c => new LFSRUnitTester(c)
61 | } should be(true)
62 | }
63 | }
64 |
65 | "running with --is-verbose" should "show more about what's going on in your tester" in {
66 | iotesters.Driver.execute(
67 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
68 | "--is-verbose"), () => new LFSR) {
69 | c => new LFSRUnitTester(c)
70 | } should be(true)
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Implementation of the Advanced Encryption Standard (AES) in [Chisel](https://chisel.eecs.berkeley.edu/)
2 |
3 |
4 | ## Motivation
5 | * Implement an open-source, transparent, secure encryption module in Chisel
6 | * Equip developers with ready-to-use, efficient, parameterizable, encryption macros for RISC-V systems
7 | * Compare performance and resource utilization of generated HDL with pure Verilog and Vivado HLS
8 | * Compare code size with Verilog, Python, C++ and Vivado HLS as a index of development productivity
9 |
10 | ## Features
11 | * _(more to come)_
12 | * Compact AES Cipher and Inverse Cipher Chisel implementation
13 | * Basic side-channel attack defense based on LFSR noise
14 | * IDE (IntelliJ) compatible
15 |
16 | ## Instructions
17 | * Run `./aes_tests.sh > logfile.txt` to run all tests and store console output into logfile
18 | * Generated Verilog will be in directory _/test_run_dir_
19 | * Either [gtkwave](http://gtkwave.sourceforge.net/) or [dinotrace](https://www.veripool.org/wiki/dinotrace) (or other wave viewer) can be used to display _.vcd_ files
20 |
21 | ## References
22 | * Our implementations of AES in Python, C/C++, Vivado HLS: [github.com/hplp/AES_implementations](https://github.com/hplp/AES_implementations)
23 | * This project was created using the [chisel-template](https://github.com/freechipsproject/chisel-template) from [freechipsproject](https://github.com/freechipsproject)
24 | * Other available Chisel [IP Contributions](https://github.com/freechipsproject/ip-contributions)
25 | * Yet another AES implementation in Chisel: [github.com/yaozhaosh/chisel-aes](https://github.com/yaozhaosh/chisel-aes)
26 | * Best resource for learning Chisel: [chisel-bootcamp](https://github.com/freechipsproject/chisel-bootcamp)
27 | * Useful and highly recommeded [Scala class on coursera](https://www.coursera.org/learn/progfun1)
28 |
29 | ## Citation
30 |
31 | This work resulted in the folowwing publications:
32 |
33 | ```
34 | @article{guo2022agile,
35 | title={Agile-AES: Implementation of configurable AES primitive with agile design approach},
36 | author={Guo, Xinfei and El-Hadedy, Mohamed and Mosanu, Sergiu and Wei, Xiangdong and Skadron, Kevin and Stan, Mircea R},
37 | journal={Integration},
38 | year={2022},
39 | publisher={Elsevier}
40 | }
41 | @inproceedings{mosanu2019flexi,
42 | title={Flexi-AES: A Highly-Parameterizable Cipher for a Wide Range of Design Constraints},
43 | author={Mosanu, Sergiu and Guo, Xinfei and El-Hadedy, Mohamed and Anghel, Lorena and Stan, Mircea},
44 | booktitle={2019 IEEE 27th Annual International Symposium on Field-Programmable Custom Computing Machines (FCCM)},
45 | pages={338--338},
46 | year={2019},
47 | organization={IEEE}
48 | }
49 | ```
50 |
--------------------------------------------------------------------------------
/tutorials/deploying_to_maven.md:
--------------------------------------------------------------------------------
1 | # How _(not)_ to deploy to Maven Central with sbt
2 |
3 | This AES implementation in Chisel is now available on [Maven Central](https://search.maven.org/search?q=g:com.github.hplp),
4 | so anyone can easily import it into their projects. You should deploy your awesome library too! Here's how deploying went for me.
5 |
6 | ## Use this guide and you'll be done in no time!
7 |
8 | According to Chick and Jim, using this [in-depth-guide-to-deploying-to-maven-central](https://leonard.io/blog/2017/01/an-in-depth-guide-to-deploying-to-maven-central/)
9 | should make it all trivial. And it was indeed very helpful and easy - I highly recommend following these steps.
10 |
11 | Even so, I made a few mistakes, got stuck, searched online for help, and eventually figured it out. Therefore:
12 |
13 | ## A few additional details
14 |
15 | * If, after adding the `sbt-pgp` plugin in _project/plugins.sbt_ you still get an error when you run `sbt pgp-cmd`,
16 | try running `sbt clean` followed by `sbt compile`.
17 | * While in the `sbt` shell, I found it helpful to test other `pgp-cmd` commands such as `list-keys`.
18 |
19 | * Settings in _build.sbt_:
20 | * Did you also start with the [chisel template](https://github.com/freechipsproject/chisel-template)? I certainly did,
21 | and only updated the `name` value. Do yourself a favour, don't repeat my mistake and update the `version` value to something
22 | reasonable. This value will appear on Maven. That's how I ended up with the first release being at version 3.2.0.
23 | * If your code is on GitHub under _github.com/username/reponame_ - it seems to be recommended to set the `organization`
24 | to `"com.github.username"`.
25 | * You can also set the `organizationName` and `homepage` parameters.
26 | * Also, to make your life easy when publishing and updating, use these 2 lines:
27 |
28 | ```sbtshell
29 | publishConfiguration := publishConfiguration.value.withOverwrite(true)
30 | publishLocalConfiguration := publishLocalConfiguration.value.withOverwrite(true)
31 | ```
32 |
33 | * After generating a PGP key and deploying it to a key server, have some patience - the key will not be available on all servers immediately.
34 | * In the _sbt_ shell, start by typing `pgp-cmd` and press _Tab_ to see the available options.
35 | * I found the _Tab_ available options like a mentor, guiding me through the unknown.
36 | * In particular, my key was not ending up on [keyserver.ubuntu.com:11371](http://keyserver.ubuntu.com:11371/), so I
37 | tried a few things and eventually uploaded it there separately. That fixed it.
38 | * You need to create a Sonatype account, and, even more important, you need to then create a "New Project" Issue
39 | and wait for it to be approved by the Sonatype overlords. This is what allows you to deploy and publish your library.
40 | * Example: the [issue that I created](https://issues.sonatype.org/browse/OSSRH-47390).
41 | * I also consulted the [sbt Sonatype setup official guide](http://www.scala-sbt.org/release/docs/Using-Sonatype.html) to clarify a few things here and there.
42 |
43 | I hope this helps - good luck!
--------------------------------------------------------------------------------
/src/main/scala/aes/Cipher.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements AES_Encrypt
7 | // change Nk=4 for AES128, NK=6 for AES192, Nk=8 for AES256
8 | class Cipher(Nk: Int, SubBytes_SCD: Boolean) extends Module {
9 | require(Nk == 4 || Nk == 6 || Nk == 8)
10 | val KeyLength: Int = Nk * Params.rows
11 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
12 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
13 |
14 | val io = IO(new Bundle {
15 | val plaintext = Input(Vec(Params.StateLength, UInt(8.W)))
16 | val roundKey = Input(Vec(Params.StateLength, UInt(8.W)))
17 | val start = Input(Bool())
18 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
19 | val state_out_valid = Output(Bool())
20 | })
21 |
22 | // Instantiate module objects
23 | val AddRoundKeyModule = AddRoundKey()
24 | val SubBytesModule = SubBytes(SubBytes_SCD)
25 | val ShiftRowsModule = ShiftRows()
26 | val MixColumnsModule = MixColumns()
27 |
28 | // Internal variables
29 | val initValues = Seq.fill(Params.StateLength)(0.U(8.W))
30 | val state = RegInit(VecInit(initValues))
31 | val rounds = RegInit(0.U(4.W))
32 |
33 | // STM
34 | val sIdle :: sInitialAR :: sBusy :: Nil = Enum(3)
35 | val STM = RegInit(sIdle)
36 |
37 | switch(STM) {
38 | is(sIdle) {
39 | when(io.start) {
40 | STM := sInitialAR
41 | } // Start cipher
42 | rounds := 0.U
43 | }
44 | is(sInitialAR) {
45 | rounds := rounds + 1.U
46 | STM := sBusy
47 | }
48 | is(sBusy) {
49 | rounds := rounds + 1.U
50 | when(rounds === Nr.U) {
51 | STM := sIdle
52 | }
53 | }
54 | }
55 |
56 | // SubBytes state
57 | SubBytesModule.io.state_in := state
58 |
59 | // ShiftRows state
60 | ShiftRowsModule.io.state_in := SubBytesModule.io.state_out
61 |
62 | // MixColumns state
63 | MixColumnsModule.io.state_in := ShiftRowsModule.io.state_out
64 |
65 | // AddRoundKey state
66 | AddRoundKeyModule.io.state_in := Mux(STM === sInitialAR, io.plaintext,
67 | Mux(rounds === Nr.U, ShiftRowsModule.io.state_out, MixColumnsModule.io.state_out))
68 | AddRoundKeyModule.io.roundKey := io.roundKey
69 |
70 | state := Mux(STM =/= sIdle, AddRoundKeyModule.io.state_out, VecInit(initValues))
71 |
72 | // Set state_out_valid true when cipher ends
73 | io.state_out_valid := rounds === Nrplus1.U
74 | io.state_out := Mux(rounds === Nrplus1.U, state, RegInit(VecInit(initValues)))
75 |
76 | // Debug statements
77 | // printf("E_STM: %d, rounds: %d, valid: %d\n", STM, rounds, io.state_out_valid)
78 | // printf("E_roundKey: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", io.roundKey(0), io.roundKey(1), io.roundKey(2), io.roundKey(3), io.roundKey(4), io.roundKey(5), io.roundKey(6), io.roundKey(7), io.roundKey(8), io.roundKey(9), io.roundKey(10), io.roundKey(11), io.roundKey(12), io.roundKey(13), io.roundKey(14), io.roundKey(15))
79 | // printf("state: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", state(0), state(1), state(2), state(3), state(4), state(5), state(6), state(7), state(8), state(9), state(10), state(11), state(12), state(13), state(14), state(15))
80 | }
81 |
82 | object Cipher {
83 | def apply(Nk: Int, SubBytes_SCD: Boolean): Cipher = Module(new Cipher(Nk, SubBytes_SCD))
84 | }
--------------------------------------------------------------------------------
/src/test/scala/aes/DASCAUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class DASCAUnitTester(c: DASCA) extends PeekPokeTester(c) {
7 |
8 | private val dasca = c
9 |
10 | val plaintext = Array(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
11 | val roundKey = Array(0x53, 0x51, 0x12, 0x78, 0xa4, 0xb2, 0x3c, 0x96, 0x84, 0xd2, 0x81, 0xe4, 0xfa, 0x3c, 0x21, 0x79)
12 | val r = scala.util.Random
13 |
14 | // send the roundKey
15 | for (i <- 0 until Params.StateLength) {
16 | poke(dasca.io.roundKey(i), roundKey(i))
17 | }
18 |
19 | // start tests
20 | for (t <- 0 until 10000) {
21 | printf("test %d: \n", t)
22 | // generate plaintext
23 | for (i <- 0 until Params.StateLength) {
24 | plaintext(i) = r.nextInt(256)
25 | }
26 | // send the plaintext
27 | for (i <- 0 until Params.StateLength) {
28 | poke(dasca.io.plaintext(i), plaintext(i))
29 | }
30 | step(1)
31 | }
32 |
33 | step(4)
34 | }
35 |
36 | // Run test with:
37 | // sbt 'testOnly aes.DASCATester'
38 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
39 |
40 | class DASCATester extends ChiselFlatSpec {
41 |
42 | // private val Nk = 8 // 4, 6, 8 [32-bit words] columns in cipher key
43 | // private val SubBytes_SCD = true
44 | private val backendNames = Array("firrtl", "verilator")
45 | private val dir = "DASCA"
46 |
47 | for (backendName <- backendNames) {
48 | "DASCA" should s"execute DASCA (with $backendName)" in {
49 | Driver(() => new DASCA(), backendName) {
50 | c => new DASCAUnitTester(c)
51 | } should be(true)
52 | }
53 | }
54 |
55 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
56 | iotesters.Driver.execute(
57 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
58 | () => new DASCA()) {
59 | c => new DASCAUnitTester(c)
60 | } should be(true)
61 | }
62 |
63 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
64 | if (backendNames.contains("verilator")) {
65 | iotesters.Driver.execute(
66 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
67 | "--backend-name", "verilator"), () => new DASCA()) {
68 | c => new DASCAUnitTester(c)
69 | } should be(true)
70 | }
71 | }
72 |
73 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
74 | if (backendNames.contains("firrtl")) {
75 | iotesters.Driver.execute(
76 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
77 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new DASCA()) {
78 | c => new DASCAUnitTester(c)
79 | } should be(true)
80 | }
81 | }
82 |
83 | "running with --is-verbose" should "show more about what's going on in your tester" in {
84 | iotesters.Driver.execute(
85 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
86 | "--is-verbose"), () => new DASCA()) {
87 | c => new DASCAUnitTester(c)
88 | } should be(true)
89 | }
90 |
91 | }
--------------------------------------------------------------------------------
/src/main/scala/aes/InvCipher.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements AES_Decrypt
7 | // change Nk=4 for AES128, NK=6 for AES192, Nk=8 for AES256
8 | class InvCipher(Nk: Int, InvSubBytes_SCD: Boolean) extends Module {
9 | require(Nk == 4 || Nk == 6 || Nk == 8)
10 | val KeyLength: Int = Nk * Params.rows
11 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
12 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
13 |
14 | val io = IO(new Bundle {
15 | val ciphertext = Input(Vec(Params.StateLength, UInt(8.W)))
16 | val roundKey = Input(Vec(Params.StateLength, UInt(8.W)))
17 | val start = Input(Bool())
18 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
19 | val state_out_valid = Output(Bool())
20 | })
21 |
22 | // Instantiate module objects
23 | val AddRoundKeyModule = AddRoundKey()
24 | val InvSubBytesModule = InvSubBytes(InvSubBytes_SCD)
25 | val InvShiftRowsModule = InvShiftRows()
26 | val InvMixColumnsModule = InvMixColumns()
27 |
28 | // Internal variables
29 | val initValues = Seq.fill(Params.StateLength)(0.U(8.W))
30 | val state = RegInit(VecInit(initValues))
31 | val rounds = RegInit(0.U(4.W))
32 |
33 | // STM
34 | val sIdle :: sInitialAR :: sBusy :: Nil = Enum(3)
35 | val STM = RegInit(sIdle)
36 |
37 | switch(STM) {
38 | is(sIdle) {
39 | when(io.start) {
40 | STM := sInitialAR
41 | } // Start cipher
42 | rounds := 0.U
43 | }
44 | is(sInitialAR) {
45 | rounds := rounds + 1.U
46 | STM := sBusy
47 | }
48 | is(sBusy) {
49 | rounds := rounds + 1.U
50 | when(rounds === Nr.U) {
51 | STM := sIdle
52 | }
53 | }
54 | }
55 |
56 | // InvShiftRows state
57 | InvShiftRowsModule.io.state_in := state
58 |
59 | // InvSubBytes state
60 | InvSubBytesModule.io.state_in := InvShiftRowsModule.io.state_out
61 |
62 | // AddRoundKey state
63 | AddRoundKeyModule.io.state_in := Mux(STM === sInitialAR, io.ciphertext, InvSubBytesModule.io.state_out)
64 | AddRoundKeyModule.io.roundKey := io.roundKey
65 |
66 | // InvMixColumns state
67 | InvMixColumnsModule.io.state_in := AddRoundKeyModule.io.state_out
68 |
69 | state := Mux(STM =/= sIdle, Mux((rounds > 0.U) & (rounds < Nr.U), InvMixColumnsModule.io.state_out, AddRoundKeyModule.io.state_out), VecInit(initValues))
70 |
71 | // Set state_out_valid true when cipher ends
72 | io.state_out_valid := rounds === Nrplus1.U
73 | io.state_out := Mux(rounds === Nrplus1.U, state, RegInit(VecInit(initValues)))
74 |
75 | // Debug statements
76 | // printf("D_STM: %d, rounds: %d, valid: %d\n", STM, rounds, io.state_out_valid)
77 | // printf("D_roundKey: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", io.roundKey(0), io.roundKey(1), io.roundKey(2), io.roundKey(3), io.roundKey(4), io.roundKey(5), io.roundKey(6), io.roundKey(7), io.roundKey(8), io.roundKey(9), io.roundKey(10), io.roundKey(11), io.roundKey(12), io.roundKey(13), io.roundKey(14), io.roundKey(15))
78 | // printf("state: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", state(0), state(1), state(2), state(3), state(4), state(5), state(6), state(7), state(8), state(9), state(10), state(11), state(12), state(13), state(14), state(15))
79 | }
80 |
81 | object InvCipher {
82 | def apply(Nk: Int, InvSubBytes_SCD: Boolean): InvCipher = Module(new InvCipher(Nk, InvSubBytes_SCD))
83 | }
--------------------------------------------------------------------------------
/src/main/scala/aes/CipherRound.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements AES_Encrypt round transforms
7 | class CipherRound(transform: String, SubBytes_SCD: Boolean = false) extends Module {
8 | require(transform == "AddRoundKeyOnly" || transform == "NoMixColumns" || transform == "CompleteRound")
9 | val io = IO(new Bundle {
10 | val input_valid = Input(Bool())
11 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
12 | val roundKey = Input(Vec(Params.StateLength, UInt(8.W)))
13 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
14 | val output_valid = Output(Bool())
15 | })
16 |
17 | // A well defined 'DontCare' or Initialization value
18 | val ZeroInit = Vec(Seq.fill(Params.StateLength)(0.U(8.W)))
19 |
20 | // Transform sequences
21 | if (transform == "AddRoundKeyOnly") {
22 |
23 | // Instantiate module objects
24 | val AddRoundKeyModule = AddRoundKey()
25 |
26 | // AddRoundKey
27 | when(io.input_valid) {
28 | AddRoundKeyModule.io.state_in := io.state_in
29 | AddRoundKeyModule.io.roundKey := io.roundKey
30 | }.otherwise {
31 | AddRoundKeyModule.io.state_in := ZeroInit
32 | AddRoundKeyModule.io.roundKey := ZeroInit
33 | }
34 |
35 | // output
36 | io.state_out := ShiftRegister(AddRoundKeyModule.io.state_out, 1)
37 | io.output_valid := ShiftRegister(io.input_valid, 1)
38 |
39 | } else if (transform == "NoMixColumns") {
40 |
41 | // Instantiate module objects
42 | val AddRoundKeyModule = AddRoundKey()
43 | val SubBytesModule = SubBytes(SubBytes_SCD)
44 | val ShiftRowsModule = ShiftRows()
45 |
46 | // SubBytes and AddRoundKeyModule roundKey
47 | when(io.input_valid) {
48 | SubBytesModule.io.state_in := io.state_in
49 | AddRoundKeyModule.io.roundKey := io.roundKey
50 | }.otherwise {
51 | SubBytesModule.io.state_in := ZeroInit
52 | AddRoundKeyModule.io.roundKey := ZeroInit
53 | }
54 | // ShiftRows
55 | ShiftRowsModule.io.state_in := SubBytesModule.io.state_out
56 | // AddRoundKey
57 | AddRoundKeyModule.io.state_in := ShiftRowsModule.io.state_out
58 |
59 | // output
60 | io.state_out := ShiftRegister(AddRoundKeyModule.io.state_out, 1)
61 | io.output_valid := ShiftRegister(io.input_valid, 1)
62 |
63 | } else if (transform == "CompleteRound") {
64 |
65 | // Instantiate module objects
66 | val AddRoundKeyModule = AddRoundKey()
67 | val SubBytesModule = SubBytes(SubBytes_SCD)
68 | val ShiftRowsModule = ShiftRows()
69 | val MixColumnsModule = MixColumns()
70 |
71 | // SubBytes and AddRoundKeyModule roundKey
72 | when(io.input_valid) {
73 | SubBytesModule.io.state_in := io.state_in
74 | AddRoundKeyModule.io.roundKey := io.roundKey
75 | }.otherwise {
76 | SubBytesModule.io.state_in := ZeroInit
77 | AddRoundKeyModule.io.roundKey := ZeroInit
78 | }
79 | // ShiftRows
80 | ShiftRowsModule.io.state_in := SubBytesModule.io.state_out
81 | // MixColumns
82 | MixColumnsModule.io.state_in := ShiftRowsModule.io.state_out
83 | // AddRoundKey
84 | AddRoundKeyModule.io.state_in := MixColumnsModule.io.state_out
85 |
86 | // output
87 | io.state_out := ShiftRegister(AddRoundKeyModule.io.state_out, 1)
88 | io.output_valid := ShiftRegister(io.input_valid, 1)
89 | }
90 |
91 | }
92 |
93 | object CipherRound {
94 | def apply(transform: String, SubBytes_SCD: Boolean = false): CipherRound = Module(new CipherRound(transform, SubBytes_SCD))
95 | }
--------------------------------------------------------------------------------
/src/main/scala/aes/InvSubBytes.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import lfsr.LFSR
6 |
7 | // implements InvSubBytes
8 | class InvSubBytes(SCD: Boolean = false, Pipelined: Boolean = false) extends Module {
9 | val io = IO(new Bundle {
10 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
11 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
12 | })
13 |
14 | val inverted_s_box = VecInit(Array(
15 | 0x52.U, 0x09.U, 0x6a.U, 0xd5.U, 0x30.U, 0x36.U, 0xa5.U, 0x38.U, 0xbf.U, 0x40.U, 0xa3.U, 0x9e.U, 0x81.U, 0xf3.U, 0xd7.U, 0xfb.U,
16 | 0x7c.U, 0xe3.U, 0x39.U, 0x82.U, 0x9b.U, 0x2f.U, 0xff.U, 0x87.U, 0x34.U, 0x8e.U, 0x43.U, 0x44.U, 0xc4.U, 0xde.U, 0xe9.U, 0xcb.U,
17 | 0x54.U, 0x7b.U, 0x94.U, 0x32.U, 0xa6.U, 0xc2.U, 0x23.U, 0x3d.U, 0xee.U, 0x4c.U, 0x95.U, 0x0b.U, 0x42.U, 0xfa.U, 0xc3.U, 0x4e.U,
18 | 0x08.U, 0x2e.U, 0xa1.U, 0x66.U, 0x28.U, 0xd9.U, 0x24.U, 0xb2.U, 0x76.U, 0x5b.U, 0xa2.U, 0x49.U, 0x6d.U, 0x8b.U, 0xd1.U, 0x25.U,
19 | 0x72.U, 0xf8.U, 0xf6.U, 0x64.U, 0x86.U, 0x68.U, 0x98.U, 0x16.U, 0xd4.U, 0xa4.U, 0x5c.U, 0xcc.U, 0x5d.U, 0x65.U, 0xb6.U, 0x92.U,
20 | 0x6c.U, 0x70.U, 0x48.U, 0x50.U, 0xfd.U, 0xed.U, 0xb9.U, 0xda.U, 0x5e.U, 0x15.U, 0x46.U, 0x57.U, 0xa7.U, 0x8d.U, 0x9d.U, 0x84.U,
21 | 0x90.U, 0xd8.U, 0xab.U, 0x00.U, 0x8c.U, 0xbc.U, 0xd3.U, 0x0a.U, 0xf7.U, 0xe4.U, 0x58.U, 0x05.U, 0xb8.U, 0xb3.U, 0x45.U, 0x06.U,
22 | 0xd0.U, 0x2c.U, 0x1e.U, 0x8f.U, 0xca.U, 0x3f.U, 0x0f.U, 0x02.U, 0xc1.U, 0xaf.U, 0xbd.U, 0x03.U, 0x01.U, 0x13.U, 0x8a.U, 0x6b.U,
23 | 0x3a.U, 0x91.U, 0x11.U, 0x41.U, 0x4f.U, 0x67.U, 0xdc.U, 0xea.U, 0x97.U, 0xf2.U, 0xcf.U, 0xce.U, 0xf0.U, 0xb4.U, 0xe6.U, 0x73.U,
24 | 0x96.U, 0xac.U, 0x74.U, 0x22.U, 0xe7.U, 0xad.U, 0x35.U, 0x85.U, 0xe2.U, 0xf9.U, 0x37.U, 0xe8.U, 0x1c.U, 0x75.U, 0xdf.U, 0x6e.U,
25 | 0x47.U, 0xf1.U, 0x1a.U, 0x71.U, 0x1d.U, 0x29.U, 0xc5.U, 0x89.U, 0x6f.U, 0xb7.U, 0x62.U, 0x0e.U, 0xaa.U, 0x18.U, 0xbe.U, 0x1b.U,
26 | 0xfc.U, 0x56.U, 0x3e.U, 0x4b.U, 0xc6.U, 0xd2.U, 0x79.U, 0x20.U, 0x9a.U, 0xdb.U, 0xc0.U, 0xfe.U, 0x78.U, 0xcd.U, 0x5a.U, 0xf4.U,
27 | 0x1f.U, 0xdd.U, 0xa8.U, 0x33.U, 0x88.U, 0x07.U, 0xc7.U, 0x31.U, 0xb1.U, 0x12.U, 0x10.U, 0x59.U, 0x27.U, 0x80.U, 0xec.U, 0x5f.U,
28 | 0x60.U, 0x51.U, 0x7f.U, 0xa9.U, 0x19.U, 0xb5.U, 0x4a.U, 0x0d.U, 0x2d.U, 0xe5.U, 0x7a.U, 0x9f.U, 0x93.U, 0xc9.U, 0x9c.U, 0xef.U,
29 | 0xa0.U, 0xe0.U, 0x3b.U, 0x4d.U, 0xae.U, 0x2a.U, 0xf5.U, 0xb0.U, 0xc8.U, 0xeb.U, 0xbb.U, 0x3c.U, 0x83.U, 0x53.U, 0x99.U, 0x61.U,
30 | 0x17.U, 0x2b.U, 0x04.U, 0x7e.U, 0xba.U, 0x77.U, 0xd6.U, 0x26.U, 0xe1.U, 0x69.U, 0x14.U, 0x63.U, 0x55.U, 0x21.U, 0x0c.U, 0x7d.U))
31 |
32 | for (i <- 0 until Params.StateLength) {
33 | if (Pipelined) {
34 | io.state_out(i) := ShiftRegister(inverted_s_box(io.state_in(i)), 1)
35 | } else {
36 | io.state_out(i) := inverted_s_box(io.state_in(i))
37 | }
38 | }
39 |
40 | if (SCD) {
41 | // dummy noise module with LFSR
42 | val LFSRModule = LFSR()
43 | val lfsr6 = RegInit(0.U(6.W)) // 6 LFSR bits
44 | lfsr6 := LFSRModule.io.lfsr_6
45 | val lfsr3r = RegInit(0.U(3.W)) // 3 LFSR bits extracted
46 | lfsr3r := LFSRModule.io.lfsr_3r
47 | val inverted_s_box_lfsr = RegInit(0.U(8.W))
48 | inverted_s_box_lfsr := inverted_s_box(Cat(lfsr6(4, 0), lfsr3r)) // 5 + 3 bits
49 | //printf("LFSR ISB %b %b %b %b %b \n", lfsr6, lfsr6(4, 0), lfsr3r, Cat(lfsr6(4, 0), lfsr3r), inverted_s_box_lfsr)
50 | }
51 | }
52 |
53 | object InvSubBytes {
54 | def apply(SCD: Boolean = false, Pipelined: Boolean = false): InvSubBytes = Module(new InvSubBytes(SCD, Pipelined))
55 | }
--------------------------------------------------------------------------------
/src/main/scala/aes/InvCipherRound.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements AES_Decrypt round transforms
7 | class InvCipherRound(transform: String, InvSubBytes_SCD: Boolean) extends Module {
8 | require(transform == "AddRoundKeyOnly" || transform == "NoInvMixColumns" || transform == "CompleteRound")
9 | val io = IO(new Bundle {
10 | val input_valid = Input(Bool())
11 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
12 | val roundKey = Input(Vec(Params.StateLength, UInt(8.W)))
13 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
14 | val output_valid = Output(Bool())
15 | })
16 |
17 | // A well defined 'DontCare' or Initialization value
18 | val ZeroInit = Vec(Seq.fill(Params.StateLength)(0.U(8.W)))
19 |
20 | // Transform sequences
21 | if (transform == "AddRoundKeyOnly") {
22 |
23 | // Instantiate module objects
24 | val AddRoundKeyModule = AddRoundKey()
25 |
26 | // AddRoundKey
27 | when(io.input_valid) {
28 | AddRoundKeyModule.io.state_in := io.state_in
29 | AddRoundKeyModule.io.roundKey := io.roundKey
30 | }.otherwise {
31 | AddRoundKeyModule.io.state_in := ZeroInit
32 | AddRoundKeyModule.io.roundKey := ZeroInit
33 | }
34 |
35 | // output
36 | io.state_out := ShiftRegister(AddRoundKeyModule.io.state_out, 1)
37 | io.output_valid := ShiftRegister(io.input_valid, 1)
38 |
39 | } else if (transform == "NoInvMixColumns") {
40 |
41 | // Instantiate module objects
42 | val AddRoundKeyModule = AddRoundKey()
43 | val InvSubBytesModule = InvSubBytes(InvSubBytes_SCD)
44 | val InvShiftRowsModule = InvShiftRows()
45 |
46 | // InvShiftRows and AddRoundKeyModule roundKey
47 | when(io.input_valid) {
48 | InvShiftRowsModule.io.state_in := io.state_in
49 | AddRoundKeyModule.io.roundKey := io.roundKey
50 | }.otherwise {
51 | InvShiftRowsModule.io.state_in := ZeroInit
52 | AddRoundKeyModule.io.roundKey := ZeroInit
53 | }
54 | // InvSubBytes
55 | InvSubBytesModule.io.state_in := InvShiftRowsModule.io.state_out
56 | // AddRoundKey
57 | AddRoundKeyModule.io.state_in := InvSubBytesModule.io.state_out
58 |
59 | // output
60 | io.state_out := ShiftRegister(AddRoundKeyModule.io.state_out, 1)
61 | io.output_valid := ShiftRegister(io.input_valid, 1)
62 |
63 | } else if (transform == "CompleteRound") {
64 |
65 | // Instantiate module objects
66 | val AddRoundKeyModule = AddRoundKey()
67 | val InvSubBytesModule = InvSubBytes(InvSubBytes_SCD)
68 | val InvShiftRowsModule = InvShiftRows()
69 | val InvMixColumnsModule = InvMixColumns()
70 |
71 | // InvShiftRows and AddRoundKeyModule roundKey
72 | when(io.input_valid) {
73 | InvShiftRowsModule.io.state_in := io.state_in
74 | AddRoundKeyModule.io.roundKey := io.roundKey
75 | }.otherwise {
76 | InvShiftRowsModule.io.state_in := ZeroInit
77 | AddRoundKeyModule.io.roundKey := ZeroInit
78 | }
79 | // InvSubBytes
80 | InvSubBytesModule.io.state_in := InvShiftRowsModule.io.state_out
81 | // AddRoundKey
82 | AddRoundKeyModule.io.state_in := InvSubBytesModule.io.state_out
83 | // InvMixColumns
84 | InvMixColumnsModule.io.state_in := AddRoundKeyModule.io.state_out
85 |
86 | // output
87 | io.state_out := ShiftRegister(InvMixColumnsModule.io.state_out, 1)
88 | io.output_valid := ShiftRegister(io.input_valid, 1)
89 |
90 | }
91 |
92 | }
93 |
94 | object InvCipherRound {
95 | def apply(transform: String, SubBytes_SCD: Boolean): InvCipherRound = Module(new InvCipherRound(transform, SubBytes_SCD))
96 | }
--------------------------------------------------------------------------------
/src/test/scala/aes/AddRoundKeyUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class AddRoundKeyUnitTester(c: AddRoundKey, Pipelined: Boolean) extends PeekPokeTester(c) {
7 |
8 | def computeAddRoundKey(state_in: Array[Int], roundKey: Array[Int]): Array[Int] = {
9 |
10 | var state_out = new Array[Int](Params.StateLength)
11 |
12 | for (i <- 0 until Params.StateLength) {
13 | state_out(i) = state_in(i) ^ roundKey(i)
14 | }
15 |
16 | state_out
17 | }
18 |
19 | private val aes_ark = c
20 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
21 | var roundKey = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
22 |
23 | for (i <- 0 until Params.StateLength) {
24 | poke(aes_ark.io.state_in(i), state(i))
25 | poke(aes_ark.io.roundKey(i), roundKey(i))
26 | }
27 |
28 | state = computeAddRoundKey(state, roundKey)
29 | println(state.deep.mkString(" "))
30 |
31 | if (Pipelined) {
32 | step(2)
33 | } else {
34 | step(1)
35 | }
36 |
37 | for (i <- 0 until Params.StateLength)
38 | expect(aes_ark.io.state_out(i), state(i))
39 | }
40 |
41 | // Run test with:
42 | // sbt 'testOnly aes.AddRoundKeyTester'
43 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
44 |
45 | class AddRoundKeyTester extends ChiselFlatSpec {
46 |
47 | private val Pipelined = true // [false -> 127 LUTs, true -> 64 LUTs and 128 FFs]
48 | private val backendNames = Array("firrtl", "verilator")
49 | private val dir = "AddRoundKey"
50 |
51 | for (backendName <- backendNames) {
52 | "AddRoundKey" should s"execute AES AddRoundKey (with $backendName)" in {
53 | Driver(() => new AddRoundKey(Pipelined), backendName) {
54 | c => new AddRoundKeyUnitTester(c, Pipelined)
55 | } should be(true)
56 | }
57 | }
58 |
59 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
60 | iotesters.Driver.execute(
61 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new AddRoundKey(Pipelined)) {
62 | c => new AddRoundKeyUnitTester(c, Pipelined)
63 | } should be(true)
64 | }
65 |
66 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
67 | if (backendNames.contains("verilator")) {
68 | iotesters.Driver.execute(
69 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
70 | "--backend-name", "verilator"), () => new AddRoundKey(Pipelined)) {
71 | c => new AddRoundKeyUnitTester(c, Pipelined)
72 | } should be(true)
73 | }
74 | }
75 |
76 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
77 | if (backendNames.contains("firrtl")) {
78 | iotesters.Driver.execute(
79 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
80 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new AddRoundKey(Pipelined)) {
81 | c => new AddRoundKeyUnitTester(c, Pipelined)
82 | } should be(true)
83 | }
84 | }
85 |
86 | "running with --is-verbose" should "show more about what's going on in your tester" in {
87 | iotesters.Driver.execute(
88 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
89 | "--is-verbose"), () => new AddRoundKey(Pipelined)) {
90 | c => new AddRoundKeyUnitTester(c, Pipelined)
91 | } should be(true)
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/scala/aes/SubBytes.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import lfsr.LFSR
6 |
7 | // implements SubBytes
8 | class SubBytes(SCD: Boolean = false, Pipelined: Boolean = false) extends Module {
9 | val io = IO(new Bundle {
10 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
11 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
12 | })
13 | printf("SBin: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", io.state_in(0), io.state_in(1), io.state_in(2), io.state_in(3), io.state_in(4), io.state_in(5), io.state_in(6), io.state_in(7), io.state_in(8), io.state_in(9), io.state_in(10), io.state_in(11), io.state_in(12), io.state_in(13), io.state_in(14), io.state_in(15))
14 | val s_box = VecInit(Array(
15 | 0x63.U, 0x7c.U, 0x77.U, 0x7b.U, 0xf2.U, 0x6b.U, 0x6f.U, 0xc5.U, 0x30.U, 0x01.U, 0x67.U, 0x2b.U, 0xfe.U, 0xd7.U, 0xab.U, 0x76.U,
16 | 0xca.U, 0x82.U, 0xc9.U, 0x7d.U, 0xfa.U, 0x59.U, 0x47.U, 0xf0.U, 0xad.U, 0xd4.U, 0xa2.U, 0xaf.U, 0x9c.U, 0xa4.U, 0x72.U, 0xc0.U,
17 | 0xb7.U, 0xfd.U, 0x93.U, 0x26.U, 0x36.U, 0x3f.U, 0xf7.U, 0xcc.U, 0x34.U, 0xa5.U, 0xe5.U, 0xf1.U, 0x71.U, 0xd8.U, 0x31.U, 0x15.U,
18 | 0x04.U, 0xc7.U, 0x23.U, 0xc3.U, 0x18.U, 0x96.U, 0x05.U, 0x9a.U, 0x07.U, 0x12.U, 0x80.U, 0xe2.U, 0xeb.U, 0x27.U, 0xb2.U, 0x75.U,
19 | 0x09.U, 0x83.U, 0x2c.U, 0x1a.U, 0x1b.U, 0x6e.U, 0x5a.U, 0xa0.U, 0x52.U, 0x3b.U, 0xd6.U, 0xb3.U, 0x29.U, 0xe3.U, 0x2f.U, 0x84.U,
20 | 0x53.U, 0xd1.U, 0x00.U, 0xed.U, 0x20.U, 0xfc.U, 0xb1.U, 0x5b.U, 0x6a.U, 0xcb.U, 0xbe.U, 0x39.U, 0x4a.U, 0x4c.U, 0x58.U, 0xcf.U,
21 | 0xd0.U, 0xef.U, 0xaa.U, 0xfb.U, 0x43.U, 0x4d.U, 0x33.U, 0x85.U, 0x45.U, 0xf9.U, 0x02.U, 0x7f.U, 0x50.U, 0x3c.U, 0x9f.U, 0xa8.U,
22 | 0x51.U, 0xa3.U, 0x40.U, 0x8f.U, 0x92.U, 0x9d.U, 0x38.U, 0xf5.U, 0xbc.U, 0xb6.U, 0xda.U, 0x21.U, 0x10.U, 0xff.U, 0xf3.U, 0xd2.U,
23 | 0xcd.U, 0x0c.U, 0x13.U, 0xec.U, 0x5f.U, 0x97.U, 0x44.U, 0x17.U, 0xc4.U, 0xa7.U, 0x7e.U, 0x3d.U, 0x64.U, 0x5d.U, 0x19.U, 0x73.U,
24 | 0x60.U, 0x81.U, 0x4f.U, 0xdc.U, 0x22.U, 0x2a.U, 0x90.U, 0x88.U, 0x46.U, 0xee.U, 0xb8.U, 0x14.U, 0xde.U, 0x5e.U, 0x0b.U, 0xdb.U,
25 | 0xe0.U, 0x32.U, 0x3a.U, 0x0a.U, 0x49.U, 0x06.U, 0x24.U, 0x5c.U, 0xc2.U, 0xd3.U, 0xac.U, 0x62.U, 0x91.U, 0x95.U, 0xe4.U, 0x79.U,
26 | 0xe7.U, 0xc8.U, 0x37.U, 0x6d.U, 0x8d.U, 0xd5.U, 0x4e.U, 0xa9.U, 0x6c.U, 0x56.U, 0xf4.U, 0xea.U, 0x65.U, 0x7a.U, 0xae.U, 0x08.U,
27 | 0xba.U, 0x78.U, 0x25.U, 0x2e.U, 0x1c.U, 0xa6.U, 0xb4.U, 0xc6.U, 0xe8.U, 0xdd.U, 0x74.U, 0x1f.U, 0x4b.U, 0xbd.U, 0x8b.U, 0x8a.U,
28 | 0x70.U, 0x3e.U, 0xb5.U, 0x66.U, 0x48.U, 0x03.U, 0xf6.U, 0x0e.U, 0x61.U, 0x35.U, 0x57.U, 0xb9.U, 0x86.U, 0xc1.U, 0x1d.U, 0x9e.U,
29 | 0xe1.U, 0xf8.U, 0x98.U, 0x11.U, 0x69.U, 0xd9.U, 0x8e.U, 0x94.U, 0x9b.U, 0x1e.U, 0x87.U, 0xe9.U, 0xce.U, 0x55.U, 0x28.U, 0xdf.U,
30 | 0x8c.U, 0xa1.U, 0x89.U, 0x0d.U, 0xbf.U, 0xe6.U, 0x42.U, 0x68.U, 0x41.U, 0x99.U, 0x2d.U, 0x0f.U, 0xb0.U, 0x54.U, 0xbb.U, 0x16.U))
31 |
32 | for (i <- 0 until Params.StateLength) {
33 | if (Pipelined) {
34 | io.state_out(i) := ShiftRegister(s_box(io.state_in(i)), 1)
35 | } else {
36 | io.state_out(i) := s_box(io.state_in(i))
37 | }
38 | }
39 |
40 | if (SCD) {
41 | // dummy noise module with LFSR
42 | val LFSRModule = LFSR()
43 | val lfsr6 = RegInit(0.U(6.W)) // 6 LFSR bits
44 | lfsr6 := LFSRModule.io.lfsr_6
45 | val lfsr3r = RegInit(0.U(3.W)) // 3 LFSR bits extracted
46 | lfsr3r := LFSRModule.io.lfsr_3r
47 | val s_box_lfsr = RegInit(0.U(8.W))
48 | s_box_lfsr := s_box(Cat(lfsr6(4, 0), lfsr3r)) // 5 + 3 bits
49 | //printf("LFSR SB %b %b %b %b %b \n", lfsr6, lfsr6(4, 0), lfsr3r, Cat(lfsr6(4, 0), lfsr3r), s_box_lfsr)
50 | }
51 | }
52 |
53 | object SubBytes {
54 | def apply(SCD: Boolean = false, Pipelined: Boolean = false): SubBytes = Module(new SubBytes(SCD, Pipelined))
55 | }
--------------------------------------------------------------------------------
/src/test/scala/aes/ShiftRowsUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class ShiftRowsUnitTester(c: ShiftRows) extends PeekPokeTester(c) {
7 |
8 | // ShiftRows in Scala
9 | def computeShiftRows(state_in: Array[Int]): Array[Int] = {
10 | var state_out = new Array[Int](Params.StateLength)
11 |
12 | state_out(0) = state_in(0)
13 | state_out(1) = state_in(5)
14 | state_out(2) = state_in(10)
15 | state_out(3) = state_in(15)
16 |
17 | state_out(4) = state_in(4)
18 | state_out(5) = state_in(9)
19 | state_out(6) = state_in(14)
20 | state_out(7) = state_in(3)
21 |
22 | state_out(8) = state_in(8)
23 | state_out(9) = state_in(13)
24 | state_out(10) = state_in(2)
25 | state_out(11) = state_in(7)
26 |
27 | state_out(12) = state_in(12)
28 | state_out(13) = state_in(1)
29 | state_out(14) = state_in(6)
30 | state_out(15) = state_in(11)
31 |
32 | state_out
33 | }
34 |
35 | private val aes_sr = c
36 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
37 |
38 | for (i <- 0 until Params.StateLength)
39 | poke(aes_sr.io.state_in(i), state(i))
40 |
41 | // run in Scala
42 | state = computeShiftRows(state)
43 | println(state.deep.mkString(" "))
44 |
45 | step(1)
46 |
47 | // match chisel and Scala
48 | for (i <- 0 until Params.StateLength)
49 | expect(aes_sr.io.state_out(i), state(i))
50 | }
51 |
52 | // Run test with:
53 | // sbt 'testOnly aes.ShiftRowsTester'
54 | // or sbt 'testOnly aes.ShiftRowsTester -- -z verbose'
55 | // or sbt 'testOnly aes.ShiftRowsTester -- -z vcd'
56 |
57 | class ShiftRowsTester extends ChiselFlatSpec {
58 |
59 | private val backendNames = Array("firrtl", "verilator")
60 | private val dir = "ShiftRows"
61 |
62 | for (backendName <- backendNames) {
63 | "ShiftRows" should s"execute AES ShiftRows (with $backendName)" in {
64 | Driver(() => new ShiftRows, backendName) {
65 | c => new ShiftRowsUnitTester(c)
66 | } should be(true)
67 | }
68 | }
69 |
70 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
71 | iotesters.Driver.execute(
72 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new ShiftRows) {
73 | c => new ShiftRowsUnitTester(c)
74 | } should be(true)
75 | }
76 |
77 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
78 | if (backendNames.contains("verilator")) {
79 | iotesters.Driver.execute(
80 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
81 | "--backend-name", "verilator"), () => new ShiftRows) {
82 | c => new ShiftRowsUnitTester(c)
83 | } should be(true)
84 | }
85 | }
86 |
87 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
88 | if (backendNames.contains("firrtl")) {
89 | iotesters.Driver.execute(
90 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
91 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new ShiftRows) {
92 | c => new ShiftRowsUnitTester(c)
93 | } should be(true)
94 | }
95 | }
96 |
97 | "running with --is-verbose" should "show more about what's going on in your tester" in {
98 | iotesters.Driver.execute(
99 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
100 | "--is-verbose"), () => new ShiftRows) {
101 | c => new ShiftRowsUnitTester(c)
102 | } should be(true)
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/test/scala/gcd/GCDUnitTest.scala:
--------------------------------------------------------------------------------
1 | // See README.md for license details.
2 |
3 | package gcd
4 |
5 | import java.io.File
6 |
7 | import chisel3.iotesters
8 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
9 |
10 | class GCDUnitTester(c: GCD) extends PeekPokeTester(c) {
11 | /**
12 | * compute the gcd and the number of steps it should take to do it
13 | *
14 | * @param a positive integer
15 | * @param b positive integer
16 | * @return the GCD of a and b
17 | */
18 | def computeGcd(a: Int, b: Int): (Int, Int) = {
19 | var x = a
20 | var y = b
21 | var depth = 1
22 | while (y > 0) {
23 | if (x > y) {
24 | x -= y
25 | }
26 | else {
27 | y -= x
28 | }
29 | depth += 1
30 | }
31 | (x, depth)
32 | }
33 |
34 | private val gcd = c
35 |
36 | for (i <- 1 to 40 by 3) {
37 | for (j <- 1 to 40 by 7) {
38 | poke(gcd.io.value1, i)
39 | poke(gcd.io.value2, j)
40 | poke(gcd.io.loadingValues, 1)
41 | step(1)
42 | poke(gcd.io.loadingValues, 0)
43 |
44 | val (expected_gcd, steps) = computeGcd(i, j)
45 |
46 | step(steps - 1) // -1 is because we step(1) already to toggle the enable
47 | expect(gcd.io.outputGCD, expected_gcd)
48 | expect(gcd.io.outputValid, 1)
49 | }
50 | }
51 | }
52 |
53 | /**
54 | * This is a trivial example of how to run this Specification
55 | * From within sbt use:
56 | * {{{
57 | * testOnly gcd.GCDTester
58 | * }}}
59 | * From a terminal shell use:
60 | * {{{
61 | * sbt 'testOnly gcd.GCDTester'
62 | * }}}
63 | * From a terminal shell, append '-- -z search_word' for a specific test:
64 | * {{{
65 | * sbt 'testOnly gcd.GCDTester -- -z verbose'
66 | * }}}
67 | */
68 | class GCDTester extends ChiselFlatSpec {
69 |
70 | private val backendNames = Array("firrtl", "verilator")
71 | private val dir = "GCD"
72 |
73 | for (backendName <- backendNames) {
74 | "GCD" should s"calculate proper greatest common denominator (with $backendName)" in {
75 | Driver(() => new GCD, backendName) {
76 | c => new GCDUnitTester(c)
77 | } should be(true)
78 | }
79 | }
80 |
81 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
82 | iotesters.Driver.execute(
83 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new GCD) {
84 | c => new GCDUnitTester(c)
85 | } should be(true)
86 | }
87 |
88 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
89 | if (backendNames.contains("verilator")) {
90 | iotesters.Driver.execute(
91 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
92 | "--backend-name", "verilator"), () => new GCD) {
93 | c => new GCDUnitTester(c)
94 | } should be(true)
95 | }
96 | }
97 |
98 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
99 | if (backendNames.contains("firrtl")) {
100 | iotesters.Driver.execute(
101 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
102 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new GCD) {
103 | c => new GCDUnitTester(c)
104 | } should be(true)
105 | }
106 | }
107 |
108 | "running with --is-verbose" should "show more about what's going on in your tester" in {
109 | iotesters.Driver.execute(
110 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
111 | "--is-verbose"), () => new GCD) {
112 | c => new GCDUnitTester(c)
113 | } should be(true)
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/src/test/scala/aes/InvShiftRowsUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class InvShiftRowsUnitTester(c: InvShiftRows) extends PeekPokeTester(c) {
7 |
8 | // InvShiftRows in Scala
9 | def computeInvShiftRows(state_in: Array[Int]): Array[Int] = {
10 | var state_out = new Array[Int](Params.StateLength)
11 |
12 | state_out(0) = state_in(0)
13 | state_out(1) = state_in(13)
14 | state_out(2) = state_in(10)
15 | state_out(3) = state_in(7)
16 |
17 | state_out(4) = state_in(4)
18 | state_out(5) = state_in(1)
19 | state_out(6) = state_in(14)
20 | state_out(7) = state_in(11)
21 |
22 | state_out(8) = state_in(8)
23 | state_out(9) = state_in(5)
24 | state_out(10) = state_in(2)
25 | state_out(11) = state_in(15)
26 |
27 | state_out(12) = state_in(12)
28 | state_out(13) = state_in(9)
29 | state_out(14) = state_in(6)
30 | state_out(15) = state_in(3)
31 |
32 | state_out
33 | }
34 |
35 | private val aes_isr = c
36 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
37 |
38 | for (i <- 0 until Params.StateLength)
39 | poke(aes_isr.io.state_in(i), state(i))
40 |
41 | // run in Scala
42 | state = computeInvShiftRows(state)
43 | println(state.deep.mkString(" "))
44 |
45 | step(1)
46 |
47 | // match chisel and Scala
48 | for (i <- 0 until Params.StateLength)
49 | expect(aes_isr.io.state_out(i), state(i))
50 | }
51 |
52 | // Run test with:
53 | // sbt 'testOnly aes.InvShiftRowsTester'
54 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
55 |
56 | class InvShiftRowsTester extends ChiselFlatSpec {
57 |
58 | private val backendNames = Array("firrtl", "verilator")
59 | private val dir = "InvShiftRows"
60 |
61 | for (backendName <- backendNames) {
62 | "InvShiftRows" should s"execute AES InvShiftRows (with $backendName)" in {
63 | Driver(() => new InvShiftRows, backendName) {
64 | c => new InvShiftRowsUnitTester(c)
65 | } should be(true)
66 | }
67 | }
68 |
69 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
70 | iotesters.Driver.execute(
71 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new InvShiftRows) {
72 | c => new InvShiftRowsUnitTester(c)
73 | } should be(true)
74 | }
75 |
76 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
77 | if (backendNames.contains("verilator")) {
78 | iotesters.Driver.execute(
79 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
80 | "--backend-name", "verilator"), () => new InvShiftRows) {
81 | c => new InvShiftRowsUnitTester(c)
82 | } should be(true)
83 | }
84 | }
85 |
86 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
87 | if (backendNames.contains("firrtl")) {
88 | iotesters.Driver.execute(
89 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
90 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new InvShiftRows) {
91 | c => new InvShiftRowsUnitTester(c)
92 | } should be(true)
93 | }
94 | }
95 |
96 | "running with --is-verbose" should "show more about what's going on in your tester" in {
97 | iotesters.Driver.execute(
98 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
99 | "--is-verbose"), () => new InvShiftRows) {
100 | c => new InvShiftRowsUnitTester(c)
101 | } should be(true)
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/test/scala/aes/CipherRoundUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class CipherRoundUnitTester(c: CipherRound, transform: String, SubBytes_SCD: Boolean = false) extends PeekPokeTester(c) {
7 | require(transform == "AddRoundKeyOnly" || transform == "NoMixColumns" || transform == "CompleteRound")
8 |
9 | private val aes_cipher_round = c
10 |
11 | val state_in = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
12 | val roundKey = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
13 |
14 | val state_out_ARK = Array(0x32, 0x42, 0xf4, 0xab, 0x8c, 0x5f, 0x36, 0x8a, 0x39, 0x38, 0x92, 0xa9, 0xec, 0x3a, 0x9, 0x3b)
15 | val state_out_NMC = Array(0x23, 0xbf, 0x44, 0x1b, 0xc0, 0xc2, 0xc3, 0xc5, 0xcf, 0x93, 0x48, 0x56, 0xed, 0x17, 0xa, 0x35)
16 | val state_out_C = Array(0xc1, 0x97, 0x3b, 0xae, 0xc2, 0xc2, 0xc9, 0xcd, 0x37, 0x7a, 0x34, 0x3b, 0xc5, 0xee, 0xb3, 0x5d)
17 |
18 | val state_out = transform match {
19 | case "AddRoundKeyOnly" => state_out_ARK
20 | case "NoMixColumns" => state_out_NMC
21 | case "CompleteRound" => state_out_C
22 | }
23 |
24 | step(4) // test that things are fine in Idle state
25 |
26 | // send the plaintext
27 | for (i <- 0 until Params.StateLength) {
28 | poke(aes_cipher_round.io.state_in(i), state_in(i))
29 | }
30 | // send the round key
31 | for (j <- 0 until Params.StateLength)
32 | poke(aes_cipher_round.io.roundKey(j), roundKey(j))
33 | // send input valid
34 | poke(aes_cipher_round.io.input_valid, 1)
35 | step(1)
36 | poke(aes_cipher_round.io.input_valid, 0)
37 |
38 | // check output
39 | for (i <- 0 until Params.StateLength)
40 | expect(aes_cipher_round.io.state_out(i), state_out(i))
41 | expect(aes_cipher_round.io.output_valid, 1)
42 |
43 | step(4)
44 | }
45 |
46 | // Run test with:
47 | // sbt 'testOnly aes.CipherRoundTester'
48 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
49 |
50 | class CipherRoundTester extends ChiselFlatSpec {
51 |
52 | private val transform = "NoMixColumns" // AddRoundKeyOnly NoMixColumns CompleteRound
53 | private val SubBytes_SCD = false
54 | private val backendNames = Array("firrtl", "verilator")
55 | private val dir = "CipherRound"
56 |
57 | for (backendName <- backendNames) {
58 | "CipherRound" should s"execute AES Cipher Round (with $backendName)" in {
59 | Driver(() => new CipherRound(transform, SubBytes_SCD), backendName) {
60 | c => new CipherRoundUnitTester(c, transform, SubBytes_SCD)
61 | } should be(true)
62 | }
63 | }
64 |
65 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
66 | iotesters.Driver.execute(
67 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
68 | () => new CipherRound(transform, SubBytes_SCD)) {
69 | c => new CipherRoundUnitTester(c, transform, SubBytes_SCD)
70 | } should be(true)
71 | }
72 |
73 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
74 | if (backendNames.contains("verilator")) {
75 | iotesters.Driver.execute(
76 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
77 | "--backend-name", "verilator"), () => new CipherRound(transform, SubBytes_SCD)) {
78 | c => new CipherRoundUnitTester(c, transform, SubBytes_SCD)
79 | } should be(true)
80 | }
81 | }
82 |
83 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
84 | if (backendNames.contains("firrtl")) {
85 | iotesters.Driver.execute(
86 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
87 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new CipherRound(transform, SubBytes_SCD)) {
88 | c => new CipherRoundUnitTester(c, transform, SubBytes_SCD)
89 | } should be(true)
90 | }
91 | }
92 |
93 | "running with --is-verbose" should "show more about what's going on in your tester" in {
94 | iotesters.Driver.execute(
95 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
96 | "--is-verbose"), () => new CipherRound(transform, SubBytes_SCD)) {
97 | c => new CipherRoundUnitTester(c, transform, SubBytes_SCD)
98 | } should be(true)
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/src/test/scala/aes/InvCipherRoundUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class InvCipherRoundUnitTester(c: InvCipherRound, transform: String, InvSubBytes_SCD: Boolean) extends PeekPokeTester(c) {
7 | require(transform == "AddRoundKeyOnly" || transform == "NoInvMixColumns" || transform == "CompleteRound")
8 |
9 | private val aes_icipher_round = c
10 |
11 | val state_in = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
12 | val roundKey = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
13 |
14 | val state_out_ARK = Array(0x32, 0x42, 0xf4, 0xab, 0x8c, 0x5f, 0x36, 0x8a, 0x39, 0x38, 0x92, 0xa9, 0xec, 0x3a, 0x9, 0x3b)
15 | val state_out_NMC = Array(0xa1, 0xb3, 0xe0, 0xb7, 0x93, 0x61, 0x3e, 0x1d, 0x26, 0x4f, 0xdc, 0x23, 0xac, 0x23, 0x6, 0x60)
16 | val state_out_C = Array(0xc1, 0x5e, 0xa, 0xd0, 0xed, 0x37, 0xf9, 0xf2, 0x7b, 0x93, 0xb6, 0xc8, 0xd7, 0x9e, 0xb4, 0x14)
17 |
18 | val state_out = transform match {
19 | case "AddRoundKeyOnly" => state_out_ARK
20 | case "NoInvMixColumns" => state_out_NMC
21 | case "CompleteRound" => state_out_C
22 | }
23 |
24 | step(4) // test that things are fine in Idle state
25 |
26 | // send the ciphertext
27 | for (i <- 0 until Params.StateLength) {
28 | poke(aes_icipher_round.io.state_in(i), state_in(i))
29 | }
30 | // send the round key
31 | for (j <- 0 until Params.StateLength)
32 | poke(aes_icipher_round.io.roundKey(j), roundKey(j))
33 | // send input valid
34 | poke(aes_icipher_round.io.input_valid, 1)
35 | step(1)
36 | poke(aes_icipher_round.io.input_valid, 0)
37 |
38 | // check output
39 | for (i <- 0 until Params.StateLength)
40 | expect(aes_icipher_round.io.state_out(i), state_out(i))
41 | expect(aes_icipher_round.io.output_valid, 1)
42 |
43 | step(4)
44 | }
45 |
46 | // Run test with:
47 | // sbt 'testOnly aes.InvCipherRoundTester'
48 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
49 |
50 | class InvCipherRoundTester extends ChiselFlatSpec {
51 |
52 | private val transform = "CompleteRound" // AddRoundKeyOnly NoInvMixColumns CompleteRound
53 | private val InvSubBytes_SCD = false
54 | private val backendNames = Array("firrtl", "verilator")
55 | private val dir = "InvCipherRound"
56 |
57 | for (backendName <- backendNames) {
58 | "Inverse Cipher" should s"execute AES Inverse Cipher (with $backendName)" in {
59 | Driver(() => new InvCipherRound(transform, InvSubBytes_SCD), backendName) {
60 | c => new InvCipherRoundUnitTester(c, transform, InvSubBytes_SCD)
61 | } should be(true)
62 | }
63 | }
64 |
65 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
66 | iotesters.Driver.execute(
67 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
68 | () => new InvCipherRound(transform, InvSubBytes_SCD)) {
69 | c => new InvCipherRoundUnitTester(c, transform, InvSubBytes_SCD)
70 | } should be(true)
71 | }
72 |
73 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
74 | if (backendNames.contains("verilator")) {
75 | iotesters.Driver.execute(
76 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
77 | "--backend-name", "verilator"), () => new InvCipherRound(transform, InvSubBytes_SCD)) {
78 | c => new InvCipherRoundUnitTester(c, transform, InvSubBytes_SCD)
79 | } should be(true)
80 | }
81 | }
82 |
83 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
84 | if (backendNames.contains("firrtl")) {
85 | iotesters.Driver.execute(
86 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
87 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new InvCipherRound(transform, InvSubBytes_SCD)) {
88 | c => new InvCipherRoundUnitTester(c, transform, InvSubBytes_SCD)
89 | } should be(true)
90 | }
91 | }
92 |
93 | "running with --is-verbose" should "show more about what's going on in your tester" in {
94 | iotesters.Driver.execute(
95 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
96 | "--is-verbose"), () => new InvCipherRound(transform, InvSubBytes_SCD)) {
97 | c => new InvCipherRoundUnitTester(c, transform, InvSubBytes_SCD)
98 | } should be(true)
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/src/test/scala/aes/SubBytesUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class SubBytesUnitTester(c: SubBytes, SCD: Boolean, Pipelined: Boolean) extends PeekPokeTester(c) {
7 |
8 | def computeSubBytes(state_in: Array[Int]): Array[Int] = {
9 | var s_box = Array(
10 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
11 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
12 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
13 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
14 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
15 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
16 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
17 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
18 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
19 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
20 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
21 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
22 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
23 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
24 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
25 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16)
26 |
27 | var state_out = new Array[Int](Params.StateLength)
28 |
29 | for (i <- 0 until Params.StateLength) {
30 | state_out(i) = s_box(state_in(i))
31 | }
32 | state_out
33 | }
34 |
35 | private val aes_sb = c
36 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
37 |
38 | for (i <- 0 until Params.StateLength)
39 | poke(aes_sb.io.state_in(i), state(i))
40 |
41 | state = computeSubBytes(state)
42 | println(state.deep.mkString(" "))
43 |
44 | if (Pipelined) {
45 | step(2)
46 | } else {
47 | step(1)
48 | }
49 |
50 | for (i <- 0 until Params.StateLength)
51 | expect(aes_sb.io.state_out(i), state(i))
52 |
53 | step(4)
54 | }
55 |
56 | // Run test with:
57 | // sbt 'testOnly aes.SubBytesTester'
58 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
59 |
60 | class SubBytesTester extends ChiselFlatSpec {
61 |
62 | private val SCD = true // true or false
63 | private val Pipelined = false // [false -> 640 LUTs, true -> 608 LUTs and 128 FFs]
64 | private val backendNames = Array("firrtl", "verilator")
65 | private val dir = "SubBytes"
66 |
67 | for (backendName <- backendNames) {
68 | "SubBytes" should s"execute AES SubBytes (with $backendName)" in {
69 | Driver(() => new SubBytes(SCD, Pipelined), backendName) {
70 | c => new SubBytesUnitTester(c, SCD, Pipelined)
71 | } should be(true)
72 | }
73 | }
74 |
75 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
76 | iotesters.Driver.execute(
77 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new SubBytes(SCD, Pipelined)) {
78 | c => new SubBytesUnitTester(c, SCD, Pipelined)
79 | } should be(true)
80 | }
81 |
82 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
83 | if (backendNames.contains("verilator")) {
84 | iotesters.Driver.execute(
85 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
86 | "--backend-name", "verilator"), () => new SubBytes(SCD, Pipelined)) {
87 | c => new SubBytesUnitTester(c, SCD, Pipelined)
88 | } should be(true)
89 | }
90 | }
91 |
92 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
93 | if (backendNames.contains("firrtl")) {
94 | iotesters.Driver.execute(
95 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
96 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new SubBytes(SCD, Pipelined)) {
97 | c => new SubBytesUnitTester(c, SCD, Pipelined)
98 | } should be(true)
99 | }
100 | }
101 |
102 | "running with --is-verbose" should "show more about what's going on in your tester" in {
103 | iotesters.Driver.execute(
104 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
105 | "--is-verbose"), () => new SubBytes(SCD, Pipelined)) {
106 | c => new SubBytesUnitTester(c, SCD, Pipelined)
107 | } should be(true)
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/test/scala/aes/InvSubBytesUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class InvSubBytesUnitTester(c: InvSubBytes, SCD: Boolean, Pipelined: Boolean) extends PeekPokeTester(c) {
7 |
8 | def computeInvSubBytes(state_in: Array[Int]): Array[Int] = {
9 | var inverted_s_box = Array(
10 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
11 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
12 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
13 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
14 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
15 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
16 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
17 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
18 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
19 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
20 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
21 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
22 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
23 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
24 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
25 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
26 |
27 | var state_out = new Array[Int](Params.StateLength)
28 |
29 | for (i <- 0 until Params.StateLength) {
30 | state_out(i) = inverted_s_box(state_in(i))
31 | }
32 | state_out
33 | }
34 |
35 | private val aes_isb = c
36 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
37 |
38 | for (i <- 0 until Params.StateLength)
39 | poke(aes_isb.io.state_in(i), state(i))
40 |
41 | state = computeInvSubBytes(state)
42 | println(state.deep.mkString(" "))
43 |
44 | if (Pipelined) {
45 | step(2)
46 | } else {
47 | step(1)
48 | }
49 |
50 | for (i <- 0 until Params.StateLength)
51 | expect(aes_isb.io.state_out(i), state(i))
52 |
53 | step(4)
54 | }
55 |
56 | // Run test with:
57 | // sbt 'testOnly aes.InvSubBytesTester'
58 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
59 |
60 | class InvSubBytesTester extends ChiselFlatSpec {
61 |
62 | private val SCD = false
63 | private val Pipelined = false // [false -> 640 LUTs, true -> 624 LUTs and 128 FFs]
64 | private val backendNames = Array("firrtl", "verilator")
65 | private val dir = "InvSubBytes"
66 |
67 | for (backendName <- backendNames) {
68 | "InvSubBytes" should s"execute AES InvSubBytes (with $backendName)" in {
69 | Driver(() => new InvSubBytes(SCD, Pipelined), backendName) {
70 | c => new InvSubBytesUnitTester(c, SCD, Pipelined)
71 | } should be(true)
72 | }
73 | }
74 |
75 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
76 | iotesters.Driver.execute(
77 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new InvSubBytes(SCD, Pipelined)) {
78 | c => new InvSubBytesUnitTester(c, SCD, Pipelined)
79 | } should be(true)
80 | }
81 |
82 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
83 | if (backendNames.contains("verilator")) {
84 | iotesters.Driver.execute(
85 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
86 | "--backend-name", "verilator"), () => new InvSubBytes(SCD, Pipelined)) {
87 | c => new InvSubBytesUnitTester(c, SCD, Pipelined)
88 | } should be(true)
89 | }
90 | }
91 |
92 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
93 | if (backendNames.contains("firrtl")) {
94 | iotesters.Driver.execute(
95 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
96 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new InvSubBytes(SCD, Pipelined)) {
97 | c => new InvSubBytesUnitTester(c, SCD, Pipelined)
98 | } should be(true)
99 | }
100 | }
101 |
102 | "running with --is-verbose" should "show more about what's going on in your tester" in {
103 | iotesters.Driver.execute(
104 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
105 | "--is-verbose"), () => new InvSubBytes(SCD, Pipelined)) {
106 | c => new InvSubBytesUnitTester(c, SCD, Pipelined)
107 | } should be(true)
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/scala/aes/AES.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements wrapper for AES cipher and inverse cipher
7 | // change Nk=4 for AES128, NK=6 for AES192, Nk=8 for AES256
8 | // change expandedKeyMemType= ROM, Mem, SyncReadMem
9 | class AES(Nk: Int, unrolled: Int, SubBytes_SCD: Boolean, InvSubBytes_SCD: Boolean, expandedKeyMemType: String) extends Module {
10 | require(Nk == 4 || Nk == 6 || Nk == 8)
11 | require(expandedKeyMemType == "ROM" || expandedKeyMemType == "Mem" || expandedKeyMemType == "SyncReadMem")
12 | val KeyLength: Int = Nk * Params.rows
13 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
14 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
15 | val EKDepth: Int = 16 // enough memory for any expanded key
16 |
17 | val io = IO(new Bundle {
18 | val AES_mode = Input(UInt(2.W)) // 0=00=off, 1=01=expanded key update, 2=10=cipher, 3=11=inverse cipher
19 | //
20 | val input_text = Input(Vec(Params.StateLength, UInt(8.W))) // plaintext, ciphertext, roundKey
21 | //
22 | val output_text = Output(Vec(Params.StateLength, UInt(8.W))) // ciphertext or plaintext
23 | val output_valid = Output(Bool())
24 | })
25 |
26 | // Instantiate module objects
27 | val CipherModule = Cipher(Nk, SubBytes_SCD)
28 | val InvCipherModule = InvCipher(Nk, InvSubBytes_SCD)
29 |
30 | // A roundKey is Params.StateLength bytes, and 1+(10/12/14) (< EKDepth) of them are needed
31 | // Mem = combinational/asynchronous-read, sequential/synchronous-write = register banks
32 | // Create a asynchronous-read, synchronous-write memory block big enough for any key length
33 | val expandedKeyARMem = Mem(EKDepth, Vec(Params.StateLength, UInt(8.W)))
34 |
35 | // SyncReadMem = sequential/synchronous-read, sequential/synchronous-write = SRAMs
36 | // Create a synchronous-read, synchronous-write memory block big enough for any key length
37 | val expandedKeySRMem = SyncReadMem(EKDepth, Vec(Params.StateLength, UInt(8.W)))
38 |
39 | // use the same address and dataOut val elements to interface with the parameterized memory
40 | val address = RegInit(0.U(log2Ceil(EKDepth).W))
41 | val dataOut = Wire(Vec(Params.StateLength, UInt(8.W)))
42 |
43 | when(io.AES_mode === 1.U) { // write to memory
44 | if (expandedKeyMemType == "Mem") {
45 | expandedKeyARMem.write(address, io.input_text)
46 | }
47 | else if (expandedKeyMemType == "SyncReadMem") {
48 | expandedKeySRMem.write(address, io.input_text)
49 | }
50 | dataOut := DontCare
51 | address := address + 1.U
52 | }
53 | .otherwise { // read from memory
54 | if (expandedKeyMemType == "Mem") {
55 | dataOut := expandedKeyARMem.read(address)
56 | }
57 | else if (expandedKeyMemType == "SyncReadMem") {
58 | dataOut := expandedKeySRMem.read(address)
59 | }
60 | else if (expandedKeyMemType == "ROM") {
61 | Nk match {
62 | case 4 => dataOut := ROMeKeys.expandedKey128(address)
63 | case 6 => dataOut := ROMeKeys.expandedKey192(address)
64 | case 8 => dataOut := ROMeKeys.expandedKey256(address)
65 | }
66 | }
67 |
68 | // address logistics
69 | when(
70 | if ((expandedKeyMemType == "Mem") || (expandedKeyMemType == "ROM")) {
71 | (ShiftRegister(io.AES_mode, 1) === 2.U) // delay by 1 for Mem and ROM
72 | }
73 | else {
74 | (io.AES_mode === 2.U) // no delay for SyncReadMem
75 | }
76 | ) {
77 | address := address + 1.U
78 | }
79 | .elsewhen(io.AES_mode === 3.U) {
80 | when(address === 0.U) {
81 | address := Nr.U
82 | }
83 | .otherwise {
84 | address := address - 1.U
85 | }
86 | }
87 | .otherwise {
88 | address := 0.U
89 | }
90 | }
91 |
92 | // The roundKey for each round can go to both the cipher and inverse cipher (for now TODO)
93 | CipherModule.io.roundKey := dataOut
94 | InvCipherModule.io.roundKey := dataOut
95 |
96 | // The input text can go to both the cipher and the inverse cipher (for now TODO)
97 | CipherModule.io.plaintext <> io.input_text
98 | InvCipherModule.io.ciphertext <> io.input_text
99 |
100 | // Cipher starts at AES_Mode=2
101 | CipherModule.io.start := (io.AES_mode === 2.U)
102 | // Inverse Cipher starts at AES_Mode=3 and address=Nr
103 | if (expandedKeyMemType == "SyncReadMem") {
104 | InvCipherModule.io.start := (ShiftRegister(io.AES_mode, 1) === 3.U) // delay by 1 for SyncReadMem
105 | }
106 | else {
107 | InvCipherModule.io.start := (io.AES_mode === 3.U) // no delay for Mem and ROM
108 | }
109 |
110 | // AES output_valid can be the Cipher.output_valid OR InvCipher.output_valid
111 | io.output_valid := CipherModule.io.state_out_valid || InvCipherModule.io.state_out_valid
112 | // AES output can be managed using a Mux on the Cipher output and the InvCipher output
113 | io.output_text <> Mux(CipherModule.io.state_out_valid, CipherModule.io.state_out, InvCipherModule.io.state_out)
114 |
115 | // Debug statements
116 | // printf("AES mode=%b, mem_address=%d, mem_dataOut=%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x \n", io.AES_mode, address, dataOut(0), dataOut(1), dataOut(2), dataOut(3), dataOut(4), dataOut(5), dataOut(6), dataOut(7), dataOut(8), dataOut(9), dataOut(10), dataOut(11), dataOut(12), dataOut(13), dataOut(14), dataOut(15))
117 | }
118 |
119 | object AES {
120 | def apply(Nk: Int, unrolled: Int, SubBytes_SCD: Boolean, InvSubBytes_SCD: Boolean, expandedKeyMemType: String): AES = Module(new AES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType))
121 | }
--------------------------------------------------------------------------------
/scalastyle-config.xml:
--------------------------------------------------------------------------------
1 |
2 | Scalastyle standard configuration
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | No lines ending with a ;
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | |\|\||&&|:=|<>|<=|>=|!=|===|<<|>>|##|unary_(~|\-%?|!))$]]>
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Project Specific stuff
2 | test_run_dir/*
3 | ### XilinxISE template
4 | # intermediate build files
5 | *.bgn
6 | *.bit
7 | *.bld
8 | *.cmd_log
9 | *.drc
10 | *.ll
11 | *.lso
12 | *.msd
13 | *.msk
14 | *.ncd
15 | *.ngc
16 | *.ngd
17 | *.ngr
18 | *.pad
19 | *.par
20 | *.pcf
21 | *.prj
22 | *.ptwx
23 | *.rbb
24 | *.rbd
25 | *.stx
26 | *.syr
27 | *.twr
28 | *.twx
29 | *.unroutes
30 | *.ut
31 | *.xpi
32 | *.xst
33 | *_bitgen.xwbt
34 | *_envsettings.html
35 | *_map.map
36 | *_map.mrp
37 | *_map.ngm
38 | *_map.xrpt
39 | *_ngdbuild.xrpt
40 | *_pad.csv
41 | *_pad.txt
42 | *_par.xrpt
43 | *_summary.html
44 | *_summary.xml
45 | *_usage.xml
46 | *_xst.xrpt
47 |
48 | # project-wide generated files
49 | *.gise
50 | par_usage_statistics.html
51 | usage_statistics_webtalk.html
52 | webtalk.log
53 | webtalk_pn.xml
54 |
55 | # generated folders
56 | iseconfig/
57 | xlnx_auto_0_xdb/
58 | xst/
59 | _ngo/
60 | _xmsgs/
61 | ### Eclipse template
62 | *.pydevproject
63 | .metadata
64 | .gradle
65 | bin/
66 | tmp/
67 | *.tmp
68 | *.bak
69 | *.swp
70 | *~.nib
71 | local.properties
72 | .settings/
73 | .loadpath
74 |
75 | # Eclipse Core
76 | .project
77 |
78 | # External tool builders
79 | .externalToolBuilders/
80 |
81 | # Locally stored "Eclipse launch configurations"
82 | *.launch
83 |
84 | # CDT-specific
85 | .cproject
86 |
87 | # JDT-specific (Eclipse Java Development Tools)
88 | .classpath
89 |
90 | # Java annotation processor (APT)
91 | .factorypath
92 |
93 | # PDT-specific
94 | .buildpath
95 |
96 | # sbteclipse plugin
97 | .target
98 |
99 | # TeXlipse plugin
100 | .texlipse
101 | ### C template
102 | # Object files
103 | *.o
104 | *.ko
105 | *.obj
106 | *.elf
107 |
108 | # Precompiled Headers
109 | *.gch
110 | *.pch
111 |
112 | # Libraries
113 | *.lib
114 | *.a
115 | *.la
116 | *.lo
117 |
118 | # Shared objects (inc. Windows DLLs)
119 | *.dll
120 | *.so
121 | *.so.*
122 | *.dylib
123 |
124 | # Executables
125 | *.exe
126 | *.out
127 | *.app
128 | *.i*86
129 | *.x86_64
130 | *.hex
131 |
132 | # Debug files
133 | *.dSYM/
134 | ### SBT template
135 | # Simple Build Tool
136 | # http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
137 |
138 | target/
139 | lib_managed/
140 | src_managed/
141 | project/boot/
142 | .history
143 | .cache
144 | ### Emacs template
145 | # -*- mode: gitignore; -*-
146 | *~
147 | \#*\#
148 | /.emacs.desktop
149 | /.emacs.desktop.lock
150 | *.elc
151 | auto-save-list
152 | tramp
153 | .\#*
154 |
155 | # Org-mode
156 | .org-id-locations
157 | *_archive
158 |
159 | # flymake-mode
160 | *_flymake.*
161 |
162 | # eshell files
163 | /eshell/history
164 | /eshell/lastdir
165 |
166 | # elpa packages
167 | /elpa/
168 |
169 | # reftex files
170 | *.rel
171 |
172 | # AUCTeX auto folder
173 | /auto/
174 |
175 | # cask packages
176 | .cask/
177 | ### Vim template
178 | [._]*.s[a-w][a-z]
179 | [._]s[a-w][a-z]
180 | *.un~
181 | Session.vim
182 | .netrwhist
183 | *~
184 | ### JetBrains template
185 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
186 |
187 | *.iml
188 |
189 | ## Directory-based project format:
190 | .idea/
191 | # if you remove the above rule, at least ignore the following:
192 |
193 | # User-specific stuff:
194 | # .idea/workspace.xml
195 | # .idea/tasks.xml
196 | # .idea/dictionaries
197 |
198 | # Sensitive or high-churn files:
199 | # .idea/dataSources.ids
200 | # .idea/dataSources.xml
201 | # .idea/sqlDataSources.xml
202 | # .idea/dynamic.xml
203 | # .idea/uiDesigner.xml
204 |
205 | # Gradle:
206 | # .idea/gradle.xml
207 | # .idea/libraries
208 |
209 | # Mongo Explorer plugin:
210 | # .idea/mongoSettings.xml
211 |
212 | ## File-based project format:
213 | *.ipr
214 | *.iws
215 |
216 | ## Plugin-specific files:
217 |
218 | # IntelliJ
219 | /out/
220 |
221 | # mpeltonen/sbt-idea plugin
222 | .idea_modules/
223 |
224 | # JIRA plugin
225 | atlassian-ide-plugin.xml
226 |
227 | # Crashlytics plugin (for Android Studio and IntelliJ)
228 | com_crashlytics_export_strings.xml
229 | crashlytics.properties
230 | crashlytics-build.properties
231 | ### C++ template
232 | # Compiled Object files
233 | *.slo
234 | *.lo
235 | *.o
236 | *.obj
237 |
238 | # Precompiled Headers
239 | *.gch
240 | *.pch
241 |
242 | # Compiled Dynamic libraries
243 | *.so
244 | *.dylib
245 | *.dll
246 |
247 | # Fortran module files
248 | *.mod
249 |
250 | # Compiled Static libraries
251 | *.lai
252 | *.la
253 | *.a
254 | *.lib
255 |
256 | # Executables
257 | *.exe
258 | *.out
259 | *.app
260 | ### OSX template
261 | .DS_Store
262 | .AppleDouble
263 | .LSOverride
264 |
265 | # Icon must end with two \r
266 | Icon
267 |
268 | # Thumbnails
269 | ._*
270 |
271 | # Files that might appear in the root of a volume
272 | .DocumentRevisions-V100
273 | .fseventsd
274 | .Spotlight-V100
275 | .TemporaryItems
276 | .Trashes
277 | .VolumeIcon.icns
278 |
279 | # Directories potentially created on remote AFP share
280 | .AppleDB
281 | .AppleDesktop
282 | Network Trash Folder
283 | Temporary Items
284 | .apdisk
285 | ### Xcode template
286 | # Xcode
287 | #
288 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
289 |
290 | ## Build generated
291 | build/
292 | DerivedData
293 |
294 | ## Various settings
295 | *.pbxuser
296 | !default.pbxuser
297 | *.mode1v3
298 | !default.mode1v3
299 | *.mode2v3
300 | !default.mode2v3
301 | *.perspectivev3
302 | !default.perspectivev3
303 | xcuserdata
304 |
305 | ## Other
306 | *.xccheckout
307 | *.moved-aside
308 | *.xcuserstate
309 | ### Scala template
310 | *.class
311 | *.log
312 |
313 | # sbt specific
314 | .cache
315 | .history
316 | .lib/
317 | dist/*
318 | target/
319 | lib_managed/
320 | src_managed/
321 | project/boot/
322 | project/plugins/project/
323 |
324 | # Scala-IDE specific
325 | .scala_dependencies
326 | .worksheet
327 | ### Java template
328 | *.class
329 |
330 | # Mobile Tools for Java (J2ME)
331 | .mtj.tmp/
332 |
333 | # Package Files #
334 | *.jar
335 | *.war
336 | *.ear
337 |
338 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
339 | hs_err_pid*
340 |
341 | # synthesis directories
342 | synthesis/
343 |
344 | # scratch
345 | test_data.txt
--------------------------------------------------------------------------------
/scalastyle-test-config.xml:
--------------------------------------------------------------------------------
1 |
2 | Scalastyle configuration for Chisel3 unit tests
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | No lines ending with a ;
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | |\|\||&&|:=|<>|<=|>=|!=|===|<<|>>|##|unary_(~|\-%?|!))$]]>
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/src/main/scala/aes/ExpandedKey.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 |
5 | // This module is not used and the file can be deleted.
6 | // This file is same as ROMeKeys.scala except it doesn't have the detailed indexing
7 |
8 | object ExpandedKey {
9 | val roundKey128 = VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U))
10 | val expandedKey128 = VecInit(Array(
11 | VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U)),
12 | VecInit(Array(0xd6.U, 0xaa.U, 0x74.U, 0xfd.U, 0xd2.U, 0xaf.U, 0x72.U, 0xfa.U, 0xda.U, 0xa6.U, 0x78.U, 0xf1.U, 0xd6.U, 0xab.U, 0x76.U, 0xfe.U)),
13 | VecInit(Array(0xb6.U, 0x92.U, 0xcf.U, 0x0b.U, 0x64.U, 0x3d.U, 0xbd.U, 0xf1.U, 0xbe.U, 0x9b.U, 0xc5.U, 0x00.U, 0x68.U, 0x30.U, 0xb3.U, 0xfe.U)),
14 | VecInit(Array(0xb6.U, 0xff.U, 0x74.U, 0x4e.U, 0xd2.U, 0xc2.U, 0xc9.U, 0xbf.U, 0x6c.U, 0x59.U, 0x0c.U, 0xbf.U, 0x04.U, 0x69.U, 0xbf.U, 0x41.U)),
15 | VecInit(Array(0x47.U, 0xf7.U, 0xf7.U, 0xbc.U, 0x95.U, 0x35.U, 0x3e.U, 0x03.U, 0xf9.U, 0x6c.U, 0x32.U, 0xbc.U, 0xfd.U, 0x05.U, 0x8d.U, 0xfd.U)),
16 | VecInit(Array(0x3c.U, 0xaa.U, 0xa3.U, 0xe8.U, 0xa9.U, 0x9f.U, 0x9d.U, 0xeb.U, 0x50.U, 0xf3.U, 0xaf.U, 0x57.U, 0xad.U, 0xf6.U, 0x22.U, 0xaa.U)),
17 | VecInit(Array(0x5e.U, 0x39.U, 0x0f.U, 0x7d.U, 0xf7.U, 0xa6.U, 0x92.U, 0x96.U, 0xa7.U, 0x55.U, 0x3d.U, 0xc1.U, 0x0a.U, 0xa3.U, 0x1f.U, 0x6b.U)),
18 | VecInit(Array(0x14.U, 0xf9.U, 0x70.U, 0x1a.U, 0xe3.U, 0x5f.U, 0xe2.U, 0x8c.U, 0x44.U, 0x0a.U, 0xdf.U, 0x4d.U, 0x4e.U, 0xa9.U, 0xc0.U, 0x26.U)),
19 | VecInit(Array(0x47.U, 0x43.U, 0x87.U, 0x35.U, 0xa4.U, 0x1c.U, 0x65.U, 0xb9.U, 0xe0.U, 0x16.U, 0xba.U, 0xf4.U, 0xae.U, 0xbf.U, 0x7a.U, 0xd2.U)),
20 | VecInit(Array(0x54.U, 0x99.U, 0x32.U, 0xd1.U, 0xf0.U, 0x85.U, 0x57.U, 0x68.U, 0x10.U, 0x93.U, 0xed.U, 0x9c.U, 0xbe.U, 0x2c.U, 0x97.U, 0x4e.U)),
21 | VecInit(Array(0x13.U, 0x11.U, 0x1d.U, 0x7f.U, 0xe3.U, 0x94.U, 0x4a.U, 0x17.U, 0xf3.U, 0x07.U, 0xa7.U, 0x8b.U, 0x4d.U, 0x2b.U, 0x30.U, 0xc5.U))))
22 |
23 | val roundKey192 = VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U, 0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U))
24 | val expandedKey192 = VecInit(Array(
25 | VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U)),
26 | VecInit(Array(0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U, 0x58.U, 0x46.U, 0xf2.U, 0xf9.U, 0x5c.U, 0x43.U, 0xf4.U, 0xfe.U)),
27 | VecInit(Array(0x54.U, 0x4a.U, 0xfe.U, 0xf5.U, 0x58.U, 0x47.U, 0xf0.U, 0xfa.U, 0x48.U, 0x56.U, 0xe2.U, 0xe9.U, 0x5c.U, 0x43.U, 0xf4.U, 0xfe.U)),
28 | VecInit(Array(0x40.U, 0xf9.U, 0x49.U, 0xb3.U, 0x1c.U, 0xba.U, 0xbd.U, 0x4d.U, 0x48.U, 0xf0.U, 0x43.U, 0xb8.U, 0x10.U, 0xb7.U, 0xb3.U, 0x42.U)),
29 | VecInit(Array(0x58.U, 0xe1.U, 0x51.U, 0xab.U, 0x04.U, 0xa2.U, 0xa5.U, 0x55.U, 0x7e.U, 0xff.U, 0xb5.U, 0x41.U, 0x62.U, 0x45.U, 0x08.U, 0x0c.U)),
30 | VecInit(Array(0x2a.U, 0xb5.U, 0x4b.U, 0xb4.U, 0x3a.U, 0x02.U, 0xf8.U, 0xf6.U, 0x62.U, 0xe3.U, 0xa9.U, 0x5d.U, 0x66.U, 0x41.U, 0x0c.U, 0x08.U)),
31 | VecInit(Array(0xf5.U, 0x01.U, 0x85.U, 0x72.U, 0x97.U, 0x44.U, 0x8d.U, 0x7e.U, 0xbd.U, 0xf1.U, 0xc6.U, 0xca.U, 0x87.U, 0xf3.U, 0x3e.U, 0x3c.U)),
32 | VecInit(Array(0xe5.U, 0x10.U, 0x97.U, 0x61.U, 0x83.U, 0x51.U, 0x9b.U, 0x69.U, 0x34.U, 0x15.U, 0x7c.U, 0x9e.U, 0xa3.U, 0x51.U, 0xf1.U, 0xe0.U)),
33 | VecInit(Array(0x1e.U, 0xa0.U, 0x37.U, 0x2a.U, 0x99.U, 0x53.U, 0x09.U, 0x16.U, 0x7c.U, 0x43.U, 0x9e.U, 0x77.U, 0xff.U, 0x12.U, 0x05.U, 0x1e.U)),
34 | VecInit(Array(0xdd.U, 0x7e.U, 0x0e.U, 0x88.U, 0x7e.U, 0x2f.U, 0xff.U, 0x68.U, 0x60.U, 0x8f.U, 0xc8.U, 0x42.U, 0xf9.U, 0xdc.U, 0xc1.U, 0x54.U)),
35 | VecInit(Array(0x85.U, 0x9f.U, 0x5f.U, 0x23.U, 0x7a.U, 0x8d.U, 0x5a.U, 0x3d.U, 0xc0.U, 0xc0.U, 0x29.U, 0x52.U, 0xbe.U, 0xef.U, 0xd6.U, 0x3a.U)),
36 | VecInit(Array(0xde.U, 0x60.U, 0x1e.U, 0x78.U, 0x27.U, 0xbc.U, 0xdf.U, 0x2c.U, 0xa2.U, 0x23.U, 0x80.U, 0x0f.U, 0xd8.U, 0xae.U, 0xda.U, 0x32.U)),
37 | VecInit(Array(0xa4.U, 0x97.U, 0x0a.U, 0x33.U, 0x1a.U, 0x78.U, 0xdc.U, 0x09.U, 0xc4.U, 0x18.U, 0xc2.U, 0x71.U, 0xe3.U, 0xa4.U, 0x1d.U, 0x5d.U))))
38 |
39 | val roundKey256 = VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U, 0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U, 0x18.U, 0x19.U, 0x1a.U, 0x1b.U, 0x1c.U, 0x1d.U, 0x1e.U, 0x1f.U))
40 | val expandedKey256 = VecInit(Array(
41 | VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U)),
42 | VecInit(Array(0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U, 0x18.U, 0x19.U, 0x1a.U, 0x1b.U, 0x1c.U, 0x1d.U, 0x1e.U, 0x1f.U)),
43 | VecInit(Array(0xa5.U, 0x73.U, 0xc2.U, 0x9f.U, 0xa1.U, 0x76.U, 0xc4.U, 0x98.U, 0xa9.U, 0x7f.U, 0xce.U, 0x93.U, 0xa5.U, 0x72.U, 0xc0.U, 0x9c.U)),
44 | VecInit(Array(0x16.U, 0x51.U, 0xa8.U, 0xcd.U, 0x02.U, 0x44.U, 0xbe.U, 0xda.U, 0x1a.U, 0x5d.U, 0xa4.U, 0xc1.U, 0x06.U, 0x40.U, 0xba.U, 0xde.U)),
45 | VecInit(Array(0xae.U, 0x87.U, 0xdf.U, 0xf0.U, 0x0f.U, 0xf1.U, 0x1b.U, 0x68.U, 0xa6.U, 0x8e.U, 0xd5.U, 0xfb.U, 0x03.U, 0xfc.U, 0x15.U, 0x67.U)),
46 | VecInit(Array(0x6d.U, 0xe1.U, 0xf1.U, 0x48.U, 0x6f.U, 0xa5.U, 0x4f.U, 0x92.U, 0x75.U, 0xf8.U, 0xeb.U, 0x53.U, 0x73.U, 0xb8.U, 0x51.U, 0x8d.U)),
47 | VecInit(Array(0xc6.U, 0x56.U, 0x82.U, 0x7f.U, 0xc9.U, 0xa7.U, 0x99.U, 0x17.U, 0x6f.U, 0x29.U, 0x4c.U, 0xec.U, 0x6c.U, 0xd5.U, 0x59.U, 0x8b.U)),
48 | VecInit(Array(0x3d.U, 0xe2.U, 0x3a.U, 0x75.U, 0x52.U, 0x47.U, 0x75.U, 0xe7.U, 0x27.U, 0xbf.U, 0x9e.U, 0xb4.U, 0x54.U, 0x07.U, 0xcf.U, 0x39.U)),
49 | VecInit(Array(0x0b.U, 0xdc.U, 0x90.U, 0x5f.U, 0xc2.U, 0x7b.U, 0x09.U, 0x48.U, 0xad.U, 0x52.U, 0x45.U, 0xa4.U, 0xc1.U, 0x87.U, 0x1c.U, 0x2f.U)),
50 | VecInit(Array(0x45.U, 0xf5.U, 0xa6.U, 0x60.U, 0x17.U, 0xb2.U, 0xd3.U, 0x87.U, 0x30.U, 0x0d.U, 0x4d.U, 0x33.U, 0x64.U, 0x0a.U, 0x82.U, 0x0a.U)),
51 | VecInit(Array(0x7c.U, 0xcf.U, 0xf7.U, 0x1c.U, 0xbe.U, 0xb4.U, 0xfe.U, 0x54.U, 0x13.U, 0xe6.U, 0xbb.U, 0xf0.U, 0xd2.U, 0x61.U, 0xa7.U, 0xdf.U)),
52 | VecInit(Array(0xf0.U, 0x1a.U, 0xfa.U, 0xfe.U, 0xe7.U, 0xa8.U, 0x29.U, 0x79.U, 0xd7.U, 0xa5.U, 0x64.U, 0x4a.U, 0xb3.U, 0xaf.U, 0xe6.U, 0x40.U)),
53 | VecInit(Array(0x25.U, 0x41.U, 0xfe.U, 0x71.U, 0x9b.U, 0xf5.U, 0x00.U, 0x25.U, 0x88.U, 0x13.U, 0xbb.U, 0xd5.U, 0x5a.U, 0x72.U, 0x1c.U, 0x0a.U)),
54 | VecInit(Array(0x4e.U, 0x5a.U, 0x66.U, 0x99.U, 0xa9.U, 0xf2.U, 0x4f.U, 0xe0.U, 0x7e.U, 0x57.U, 0x2b.U, 0xaa.U, 0xcd.U, 0xf8.U, 0xcd.U, 0xea.U)),
55 | VecInit(Array(0x24.U, 0xfc.U, 0x79.U, 0xcc.U, 0xbf.U, 0x09.U, 0x79.U, 0xe9.U, 0x37.U, 0x1a.U, 0xc2.U, 0x3c.U, 0x6d.U, 0x68.U, 0xde.U, 0x36.U))))
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/scala/aes/ROMeKeys.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 |
5 | // I think there is a bug in Chisel; it should be fine to use each val in other Chisel modules with Tables.val_name
6 | // and it actually works when running a single test, but not when running more than one test
7 |
8 | object ROMeKeys {
9 | val roundKey128 = VecInit(Array(
10 | 0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U))
11 | val expandedKey128 = Reg(Vec(16, Vec(Params.StateLength, UInt(8.W))))
12 | expandedKey128(0) := VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U))
13 | expandedKey128(1) := VecInit(Array(0xd6.U, 0xaa.U, 0x74.U, 0xfd.U, 0xd2.U, 0xaf.U, 0x72.U, 0xfa.U, 0xda.U, 0xa6.U, 0x78.U, 0xf1.U, 0xd6.U, 0xab.U, 0x76.U, 0xfe.U))
14 | expandedKey128(2) := VecInit(Array(0xb6.U, 0x92.U, 0xcf.U, 0x0b.U, 0x64.U, 0x3d.U, 0xbd.U, 0xf1.U, 0xbe.U, 0x9b.U, 0xc5.U, 0x00.U, 0x68.U, 0x30.U, 0xb3.U, 0xfe.U))
15 | expandedKey128(3) := VecInit(Array(0xb6.U, 0xff.U, 0x74.U, 0x4e.U, 0xd2.U, 0xc2.U, 0xc9.U, 0xbf.U, 0x6c.U, 0x59.U, 0x0c.U, 0xbf.U, 0x04.U, 0x69.U, 0xbf.U, 0x41.U))
16 | expandedKey128(4) := VecInit(Array(0x47.U, 0xf7.U, 0xf7.U, 0xbc.U, 0x95.U, 0x35.U, 0x3e.U, 0x03.U, 0xf9.U, 0x6c.U, 0x32.U, 0xbc.U, 0xfd.U, 0x05.U, 0x8d.U, 0xfd.U))
17 | expandedKey128(5) := VecInit(Array(0x3c.U, 0xaa.U, 0xa3.U, 0xe8.U, 0xa9.U, 0x9f.U, 0x9d.U, 0xeb.U, 0x50.U, 0xf3.U, 0xaf.U, 0x57.U, 0xad.U, 0xf6.U, 0x22.U, 0xaa.U))
18 | expandedKey128(6) := VecInit(Array(0x5e.U, 0x39.U, 0x0f.U, 0x7d.U, 0xf7.U, 0xa6.U, 0x92.U, 0x96.U, 0xa7.U, 0x55.U, 0x3d.U, 0xc1.U, 0x0a.U, 0xa3.U, 0x1f.U, 0x6b.U))
19 | expandedKey128(7) := VecInit(Array(0x14.U, 0xf9.U, 0x70.U, 0x1a.U, 0xe3.U, 0x5f.U, 0xe2.U, 0x8c.U, 0x44.U, 0x0a.U, 0xdf.U, 0x4d.U, 0x4e.U, 0xa9.U, 0xc0.U, 0x26.U))
20 | expandedKey128(8) := VecInit(Array(0x47.U, 0x43.U, 0x87.U, 0x35.U, 0xa4.U, 0x1c.U, 0x65.U, 0xb9.U, 0xe0.U, 0x16.U, 0xba.U, 0xf4.U, 0xae.U, 0xbf.U, 0x7a.U, 0xd2.U))
21 | expandedKey128(9) := VecInit(Array(0x54.U, 0x99.U, 0x32.U, 0xd1.U, 0xf0.U, 0x85.U, 0x57.U, 0x68.U, 0x10.U, 0x93.U, 0xed.U, 0x9c.U, 0xbe.U, 0x2c.U, 0x97.U, 0x4e.U))
22 | expandedKey128(10) := VecInit(Array(0x13.U, 0x11.U, 0x1d.U, 0x7f.U, 0xe3.U, 0x94.U, 0x4a.U, 0x17.U, 0xf3.U, 0x07.U, 0xa7.U, 0x8b.U, 0x4d.U, 0x2b.U, 0x30.U, 0xc5.U))
23 | expandedKey128(11) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
24 | expandedKey128(12) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
25 | expandedKey128(13) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
26 | expandedKey128(14) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
27 | expandedKey128(15) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
28 |
29 | val roundKey192 = VecInit(Array(
30 | 0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U, 0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U))
31 | val expandedKey192 = Reg(Vec(16, Vec(Params.StateLength, UInt(8.W))))
32 | expandedKey192(0) := VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U))
33 | expandedKey192(1) := VecInit(Array(0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U, 0x58.U, 0x46.U, 0xf2.U, 0xf9.U, 0x5c.U, 0x43.U, 0xf4.U, 0xfe.U))
34 | expandedKey192(2) := VecInit(Array(0x54.U, 0x4a.U, 0xfe.U, 0xf5.U, 0x58.U, 0x47.U, 0xf0.U, 0xfa.U, 0x48.U, 0x56.U, 0xe2.U, 0xe9.U, 0x5c.U, 0x43.U, 0xf4.U, 0xfe.U))
35 | expandedKey192(3) := VecInit(Array(0x40.U, 0xf9.U, 0x49.U, 0xb3.U, 0x1c.U, 0xba.U, 0xbd.U, 0x4d.U, 0x48.U, 0xf0.U, 0x43.U, 0xb8.U, 0x10.U, 0xb7.U, 0xb3.U, 0x42.U))
36 | expandedKey192(4) := VecInit(Array(0x58.U, 0xe1.U, 0x51.U, 0xab.U, 0x04.U, 0xa2.U, 0xa5.U, 0x55.U, 0x7e.U, 0xff.U, 0xb5.U, 0x41.U, 0x62.U, 0x45.U, 0x08.U, 0x0c.U))
37 | expandedKey192(5) := VecInit(Array(0x2a.U, 0xb5.U, 0x4b.U, 0xb4.U, 0x3a.U, 0x02.U, 0xf8.U, 0xf6.U, 0x62.U, 0xe3.U, 0xa9.U, 0x5d.U, 0x66.U, 0x41.U, 0x0c.U, 0x08.U))
38 | expandedKey192(6) := VecInit(Array(0xf5.U, 0x01.U, 0x85.U, 0x72.U, 0x97.U, 0x44.U, 0x8d.U, 0x7e.U, 0xbd.U, 0xf1.U, 0xc6.U, 0xca.U, 0x87.U, 0xf3.U, 0x3e.U, 0x3c.U))
39 | expandedKey192(7) := VecInit(Array(0xe5.U, 0x10.U, 0x97.U, 0x61.U, 0x83.U, 0x51.U, 0x9b.U, 0x69.U, 0x34.U, 0x15.U, 0x7c.U, 0x9e.U, 0xa3.U, 0x51.U, 0xf1.U, 0xe0.U))
40 | expandedKey192(8) := VecInit(Array(0x1e.U, 0xa0.U, 0x37.U, 0x2a.U, 0x99.U, 0x53.U, 0x09.U, 0x16.U, 0x7c.U, 0x43.U, 0x9e.U, 0x77.U, 0xff.U, 0x12.U, 0x05.U, 0x1e.U))
41 | expandedKey192(9) := VecInit(Array(0xdd.U, 0x7e.U, 0x0e.U, 0x88.U, 0x7e.U, 0x2f.U, 0xff.U, 0x68.U, 0x60.U, 0x8f.U, 0xc8.U, 0x42.U, 0xf9.U, 0xdc.U, 0xc1.U, 0x54.U))
42 | expandedKey192(10) := VecInit(Array(0x85.U, 0x9f.U, 0x5f.U, 0x23.U, 0x7a.U, 0x8d.U, 0x5a.U, 0x3d.U, 0xc0.U, 0xc0.U, 0x29.U, 0x52.U, 0xbe.U, 0xef.U, 0xd6.U, 0x3a.U))
43 | expandedKey192(11) := VecInit(Array(0xde.U, 0x60.U, 0x1e.U, 0x78.U, 0x27.U, 0xbc.U, 0xdf.U, 0x2c.U, 0xa2.U, 0x23.U, 0x80.U, 0x0f.U, 0xd8.U, 0xae.U, 0xda.U, 0x32.U))
44 | expandedKey192(12) := VecInit(Array(0xa4.U, 0x97.U, 0x0a.U, 0x33.U, 0x1a.U, 0x78.U, 0xdc.U, 0x09.U, 0xc4.U, 0x18.U, 0xc2.U, 0x71.U, 0xe3.U, 0xa4.U, 0x1d.U, 0x5d.U))
45 | expandedKey192(13) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
46 | expandedKey192(14) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
47 | expandedKey192(15) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
48 |
49 | val roundKey256 = VecInit(Array(
50 | 0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U, 0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U, 0x18.U, 0x19.U, 0x1a.U, 0x1b.U, 0x1c.U, 0x1d.U, 0x1e.U, 0x1f.U))
51 | val expandedKey256 = Reg(Vec(16, Vec(Params.StateLength, UInt(8.W))))
52 | expandedKey256(0) := VecInit(Array(0x00.U, 0x01.U, 0x02.U, 0x03.U, 0x04.U, 0x05.U, 0x06.U, 0x07.U, 0x08.U, 0x09.U, 0x0a.U, 0x0b.U, 0x0c.U, 0x0d.U, 0x0e.U, 0x0f.U))
53 | expandedKey256(1) := VecInit(Array(0x10.U, 0x11.U, 0x12.U, 0x13.U, 0x14.U, 0x15.U, 0x16.U, 0x17.U, 0x18.U, 0x19.U, 0x1a.U, 0x1b.U, 0x1c.U, 0x1d.U, 0x1e.U, 0x1f.U))
54 | expandedKey256(2) := VecInit(Array(0xa5.U, 0x73.U, 0xc2.U, 0x9f.U, 0xa1.U, 0x76.U, 0xc4.U, 0x98.U, 0xa9.U, 0x7f.U, 0xce.U, 0x93.U, 0xa5.U, 0x72.U, 0xc0.U, 0x9c.U))
55 | expandedKey256(3) := VecInit(Array(0x16.U, 0x51.U, 0xa8.U, 0xcd.U, 0x02.U, 0x44.U, 0xbe.U, 0xda.U, 0x1a.U, 0x5d.U, 0xa4.U, 0xc1.U, 0x06.U, 0x40.U, 0xba.U, 0xde.U))
56 | expandedKey256(4) := VecInit(Array(0xae.U, 0x87.U, 0xdf.U, 0xf0.U, 0x0f.U, 0xf1.U, 0x1b.U, 0x68.U, 0xa6.U, 0x8e.U, 0xd5.U, 0xfb.U, 0x03.U, 0xfc.U, 0x15.U, 0x67.U))
57 | expandedKey256(5) := VecInit(Array(0x6d.U, 0xe1.U, 0xf1.U, 0x48.U, 0x6f.U, 0xa5.U, 0x4f.U, 0x92.U, 0x75.U, 0xf8.U, 0xeb.U, 0x53.U, 0x73.U, 0xb8.U, 0x51.U, 0x8d.U))
58 | expandedKey256(6) := VecInit(Array(0xc6.U, 0x56.U, 0x82.U, 0x7f.U, 0xc9.U, 0xa7.U, 0x99.U, 0x17.U, 0x6f.U, 0x29.U, 0x4c.U, 0xec.U, 0x6c.U, 0xd5.U, 0x59.U, 0x8b.U))
59 | expandedKey256(7) := VecInit(Array(0x3d.U, 0xe2.U, 0x3a.U, 0x75.U, 0x52.U, 0x47.U, 0x75.U, 0xe7.U, 0x27.U, 0xbf.U, 0x9e.U, 0xb4.U, 0x54.U, 0x07.U, 0xcf.U, 0x39.U))
60 | expandedKey256(8) := VecInit(Array(0x0b.U, 0xdc.U, 0x90.U, 0x5f.U, 0xc2.U, 0x7b.U, 0x09.U, 0x48.U, 0xad.U, 0x52.U, 0x45.U, 0xa4.U, 0xc1.U, 0x87.U, 0x1c.U, 0x2f.U))
61 | expandedKey256(9) := VecInit(Array(0x45.U, 0xf5.U, 0xa6.U, 0x60.U, 0x17.U, 0xb2.U, 0xd3.U, 0x87.U, 0x30.U, 0x0d.U, 0x4d.U, 0x33.U, 0x64.U, 0x0a.U, 0x82.U, 0x0a.U))
62 | expandedKey256(10) := VecInit(Array(0x7c.U, 0xcf.U, 0xf7.U, 0x1c.U, 0xbe.U, 0xb4.U, 0xfe.U, 0x54.U, 0x13.U, 0xe6.U, 0xbb.U, 0xf0.U, 0xd2.U, 0x61.U, 0xa7.U, 0xdf.U))
63 | expandedKey256(11) := VecInit(Array(0xf0.U, 0x1a.U, 0xfa.U, 0xfe.U, 0xe7.U, 0xa8.U, 0x29.U, 0x79.U, 0xd7.U, 0xa5.U, 0x64.U, 0x4a.U, 0xb3.U, 0xaf.U, 0xe6.U, 0x40.U))
64 | expandedKey256(12) := VecInit(Array(0x25.U, 0x41.U, 0xfe.U, 0x71.U, 0x9b.U, 0xf5.U, 0x00.U, 0x25.U, 0x88.U, 0x13.U, 0xbb.U, 0xd5.U, 0x5a.U, 0x72.U, 0x1c.U, 0x0a.U))
65 | expandedKey256(13) := VecInit(Array(0x4e.U, 0x5a.U, 0x66.U, 0x99.U, 0xa9.U, 0xf2.U, 0x4f.U, 0xe0.U, 0x7e.U, 0x57.U, 0x2b.U, 0xaa.U, 0xcd.U, 0xf8.U, 0xcd.U, 0xea.U))
66 | expandedKey256(14) := VecInit(Array(0x24.U, 0xfc.U, 0x79.U, 0xcc.U, 0xbf.U, 0x09.U, 0x79.U, 0xe9.U, 0x37.U, 0x1a.U, 0xc2.U, 0x3c.U, 0x6d.U, 0x68.U, 0xde.U, 0x36.U))
67 | expandedKey256(15) := VecInit(Array(0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U, 0x00.U))
68 | }
--------------------------------------------------------------------------------
/src/test/scala/aes/CipherUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class CipherUnitTester(c: Cipher, Nk: Int, SubBytes_SCD: Boolean) extends PeekPokeTester(c) {
7 | require(Nk == 4 || Nk == 6 || Nk == 8)
8 |
9 | private val aes_cipher = c
10 |
11 | val KeyLength: Int = Nk * Params.rows
12 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
13 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
14 |
15 | val state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
16 |
17 | val Key128 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
18 | val expandedKey128 = Array(
19 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
20 | Array(0xd6, 0xaa, 0x74, 0xfd, 0xd2, 0xaf, 0x72, 0xfa, 0xda, 0xa6, 0x78, 0xf1, 0xd6, 0xab, 0x76, 0xfe),
21 | Array(0xb6, 0x92, 0xcf, 0x0b, 0x64, 0x3d, 0xbd, 0xf1, 0xbe, 0x9b, 0xc5, 0x00, 0x68, 0x30, 0xb3, 0xfe),
22 | Array(0xb6, 0xff, 0x74, 0x4e, 0xd2, 0xc2, 0xc9, 0xbf, 0x6c, 0x59, 0x0c, 0xbf, 0x04, 0x69, 0xbf, 0x41),
23 | Array(0x47, 0xf7, 0xf7, 0xbc, 0x95, 0x35, 0x3e, 0x03, 0xf9, 0x6c, 0x32, 0xbc, 0xfd, 0x05, 0x8d, 0xfd),
24 | Array(0x3c, 0xaa, 0xa3, 0xe8, 0xa9, 0x9f, 0x9d, 0xeb, 0x50, 0xf3, 0xaf, 0x57, 0xad, 0xf6, 0x22, 0xaa),
25 | Array(0x5e, 0x39, 0x0f, 0x7d, 0xf7, 0xa6, 0x92, 0x96, 0xa7, 0x55, 0x3d, 0xc1, 0x0a, 0xa3, 0x1f, 0x6b),
26 | Array(0x14, 0xf9, 0x70, 0x1a, 0xe3, 0x5f, 0xe2, 0x8c, 0x44, 0x0a, 0xdf, 0x4d, 0x4e, 0xa9, 0xc0, 0x26),
27 | Array(0x47, 0x43, 0x87, 0x35, 0xa4, 0x1c, 0x65, 0xb9, 0xe0, 0x16, 0xba, 0xf4, 0xae, 0xbf, 0x7a, 0xd2),
28 | Array(0x54, 0x99, 0x32, 0xd1, 0xf0, 0x85, 0x57, 0x68, 0x10, 0x93, 0xed, 0x9c, 0xbe, 0x2c, 0x97, 0x4e),
29 | Array(0x13, 0x11, 0x1d, 0x7f, 0xe3, 0x94, 0x4a, 0x17, 0xf3, 0x07, 0xa7, 0x8b, 0x4d, 0x2b, 0x30, 0xc5))
30 |
31 | val Key192 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)
32 | val expandedKey192 = Array(
33 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
34 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x58, 0x46, 0xf2, 0xf9, 0x5c, 0x43, 0xf4, 0xfe),
35 | Array(0x54, 0x4a, 0xfe, 0xf5, 0x58, 0x47, 0xf0, 0xfa, 0x48, 0x56, 0xe2, 0xe9, 0x5c, 0x43, 0xf4, 0xfe),
36 | Array(0x40, 0xf9, 0x49, 0xb3, 0x1c, 0xba, 0xbd, 0x4d, 0x48, 0xf0, 0x43, 0xb8, 0x10, 0xb7, 0xb3, 0x42),
37 | Array(0x58, 0xe1, 0x51, 0xab, 0x04, 0xa2, 0xa5, 0x55, 0x7e, 0xff, 0xb5, 0x41, 0x62, 0x45, 0x08, 0x0c),
38 | Array(0x2a, 0xb5, 0x4b, 0xb4, 0x3a, 0x02, 0xf8, 0xf6, 0x62, 0xe3, 0xa9, 0x5d, 0x66, 0x41, 0x0c, 0x08),
39 | Array(0xf5, 0x01, 0x85, 0x72, 0x97, 0x44, 0x8d, 0x7e, 0xbd, 0xf1, 0xc6, 0xca, 0x87, 0xf3, 0x3e, 0x3c),
40 | Array(0xe5, 0x10, 0x97, 0x61, 0x83, 0x51, 0x9b, 0x69, 0x34, 0x15, 0x7c, 0x9e, 0xa3, 0x51, 0xf1, 0xe0),
41 | Array(0x1e, 0xa0, 0x37, 0x2a, 0x99, 0x53, 0x09, 0x16, 0x7c, 0x43, 0x9e, 0x77, 0xff, 0x12, 0x05, 0x1e),
42 | Array(0xdd, 0x7e, 0x0e, 0x88, 0x7e, 0x2f, 0xff, 0x68, 0x60, 0x8f, 0xc8, 0x42, 0xf9, 0xdc, 0xc1, 0x54),
43 | Array(0x85, 0x9f, 0x5f, 0x23, 0x7a, 0x8d, 0x5a, 0x3d, 0xc0, 0xc0, 0x29, 0x52, 0xbe, 0xef, 0xd6, 0x3a),
44 | Array(0xde, 0x60, 0x1e, 0x78, 0x27, 0xbc, 0xdf, 0x2c, 0xa2, 0x23, 0x80, 0x0f, 0xd8, 0xae, 0xda, 0x32),
45 | Array(0xa4, 0x97, 0x0a, 0x33, 0x1a, 0x78, 0xdc, 0x09, 0xc4, 0x18, 0xc2, 0x71, 0xe3, 0xa4, 0x1d, 0x5d))
46 |
47 | val Key256 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f)
48 | val expandedKey256 = Array(
49 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
50 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f),
51 | Array(0xa5, 0x73, 0xc2, 0x9f, 0xa1, 0x76, 0xc4, 0x98, 0xa9, 0x7f, 0xce, 0x93, 0xa5, 0x72, 0xc0, 0x9c),
52 | Array(0x16, 0x51, 0xa8, 0xcd, 0x02, 0x44, 0xbe, 0xda, 0x1a, 0x5d, 0xa4, 0xc1, 0x06, 0x40, 0xba, 0xde),
53 | Array(0xae, 0x87, 0xdf, 0xf0, 0x0f, 0xf1, 0x1b, 0x68, 0xa6, 0x8e, 0xd5, 0xfb, 0x03, 0xfc, 0x15, 0x67),
54 | Array(0x6d, 0xe1, 0xf1, 0x48, 0x6f, 0xa5, 0x4f, 0x92, 0x75, 0xf8, 0xeb, 0x53, 0x73, 0xb8, 0x51, 0x8d),
55 | Array(0xc6, 0x56, 0x82, 0x7f, 0xc9, 0xa7, 0x99, 0x17, 0x6f, 0x29, 0x4c, 0xec, 0x6c, 0xd5, 0x59, 0x8b),
56 | Array(0x3d, 0xe2, 0x3a, 0x75, 0x52, 0x47, 0x75, 0xe7, 0x27, 0xbf, 0x9e, 0xb4, 0x54, 0x07, 0xcf, 0x39),
57 | Array(0x0b, 0xdc, 0x90, 0x5f, 0xc2, 0x7b, 0x09, 0x48, 0xad, 0x52, 0x45, 0xa4, 0xc1, 0x87, 0x1c, 0x2f),
58 | Array(0x45, 0xf5, 0xa6, 0x60, 0x17, 0xb2, 0xd3, 0x87, 0x30, 0x0d, 0x4d, 0x33, 0x64, 0x0a, 0x82, 0x0a),
59 | Array(0x7c, 0xcf, 0xf7, 0x1c, 0xbe, 0xb4, 0xfe, 0x54, 0x13, 0xe6, 0xbb, 0xf0, 0xd2, 0x61, 0xa7, 0xdf),
60 | Array(0xf0, 0x1a, 0xfa, 0xfe, 0xe7, 0xa8, 0x29, 0x79, 0xd7, 0xa5, 0x64, 0x4a, 0xb3, 0xaf, 0xe6, 0x40),
61 | Array(0x25, 0x41, 0xfe, 0x71, 0x9b, 0xf5, 0x00, 0x25, 0x88, 0x13, 0xbb, 0xd5, 0x5a, 0x72, 0x1c, 0x0a),
62 | Array(0x4e, 0x5a, 0x66, 0x99, 0xa9, 0xf2, 0x4f, 0xe0, 0x7e, 0x57, 0x2b, 0xaa, 0xcd, 0xf8, 0xcd, 0xea),
63 | Array(0x24, 0xfc, 0x79, 0xcc, 0xbf, 0x09, 0x79, 0xe9, 0x37, 0x1a, 0xc2, 0x3c, 0x6d, 0x68, 0xde, 0x36))
64 |
65 | val Key = Nk match {
66 | case 4 => Key128
67 | case 6 => Key192
68 | case 8 => Key256
69 | }
70 |
71 | val expandedKey = Nk match {
72 | case 4 => expandedKey128
73 | case 6 => expandedKey192
74 | case 8 => expandedKey256
75 | }
76 |
77 | val state_e128 = Array(0x89, 0xed, 0x5e, 0x6a, 0x05, 0xca, 0x76, 0x33, 0x81, 0x35, 0x08, 0x5f, 0xe2, 0x1c, 0x40, 0xbd)
78 | val state_e192 = Array(0xbc, 0x3a, 0xaa, 0xb5, 0xd9, 0x7b, 0xaa, 0x7b, 0x32, 0x5d, 0x7b, 0x8f, 0x69, 0xcd, 0x7c, 0xa8)
79 | val state_e256 = Array(0x9a, 0x19, 0x88, 0x30, 0xff, 0x9a, 0x4e, 0x39, 0xec, 0x15, 0x01, 0x54, 0x7d, 0x4a, 0x6b, 0x1b)
80 |
81 | val state_e = Nk match {
82 | case 4 => state_e128
83 | case 6 => state_e192
84 | case 8 => state_e256
85 | }
86 |
87 | poke(aes_cipher.io.start, 0)
88 | step(4) // test that things are fine in Idle state
89 |
90 | // send start
91 | poke(aes_cipher.io.start, 1)
92 | step(1)
93 |
94 | // send the plaintext
95 | for (i <- 0 until Params.StateLength) {
96 | poke(aes_cipher.io.plaintext(i), state(i))
97 | }
98 | // send the expanded key for round 1
99 | for (j <- 0 until Params.StateLength)
100 | poke(aes_cipher.io.roundKey(j), expandedKey(0)(j))
101 | // reset start
102 | poke(aes_cipher.io.start, 0)
103 | step(1)
104 |
105 | // remaining rounds
106 | for (i <- 1 until Nrplus1) {
107 | for (j <- 0 until Params.StateLength)
108 | poke(aes_cipher.io.roundKey(j), expandedKey(i)(j))
109 | step(1)
110 | }
111 |
112 | for (i <- 0 until Params.StateLength)
113 | expect(aes_cipher.io.state_out(i), state_e(i))
114 | expect(aes_cipher.io.state_out_valid, 1)
115 |
116 | step(4)
117 | }
118 |
119 | // Run test with:
120 | // sbt 'testOnly aes.CipherTester'
121 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
122 |
123 | class CipherTester extends ChiselFlatSpec {
124 |
125 | private val Nk = 8 // 4, 6, 8 [32-bit words] columns in cipher key
126 | private val SubBytes_SCD = true
127 | private val backendNames = Array("firrtl", "verilator")
128 | private val dir = "Cipher"
129 |
130 | for (backendName <- backendNames) {
131 | "Cipher" should s"execute AES Cipher (with $backendName)" in {
132 | Driver(() => new Cipher(Nk, SubBytes_SCD), backendName) {
133 | c => new CipherUnitTester(c, Nk, SubBytes_SCD)
134 | } should be(true)
135 | }
136 | }
137 |
138 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
139 | iotesters.Driver.execute(
140 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
141 | () => new Cipher(Nk, SubBytes_SCD)) {
142 | c => new CipherUnitTester(c, Nk, SubBytes_SCD)
143 | } should be(true)
144 | }
145 |
146 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
147 | if (backendNames.contains("verilator")) {
148 | iotesters.Driver.execute(
149 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
150 | "--backend-name", "verilator"), () => new Cipher(Nk, SubBytes_SCD)) {
151 | c => new CipherUnitTester(c, Nk, SubBytes_SCD)
152 | } should be(true)
153 | }
154 | }
155 |
156 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
157 | if (backendNames.contains("firrtl")) {
158 | iotesters.Driver.execute(
159 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
160 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new Cipher(Nk, SubBytes_SCD)) {
161 | c => new CipherUnitTester(c, Nk, SubBytes_SCD)
162 | } should be(true)
163 | }
164 | }
165 |
166 | "running with --is-verbose" should "show more about what's going on in your tester" in {
167 | iotesters.Driver.execute(
168 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
169 | "--is-verbose"), () => new Cipher(Nk, SubBytes_SCD)) {
170 | c => new CipherUnitTester(c, Nk, SubBytes_SCD)
171 | } should be(true)
172 | }
173 |
174 | }
175 |
--------------------------------------------------------------------------------
/src/test/scala/aes/InvCipherUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class InvCipherUnitTester(c: InvCipher, Nk: Int, InvSubBytes_SCD: Boolean) extends PeekPokeTester(c) {
7 | require(Nk == 4 || Nk == 6 || Nk == 8)
8 |
9 | private val aes_icipher = c
10 |
11 | val KeyLength: Int = Nk * Params.rows
12 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
13 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
14 |
15 | val state128 = Array(0x89, 0xed, 0x5e, 0x6a, 0x05, 0xca, 0x76, 0x33, 0x81, 0x35, 0x08, 0x5f, 0xe2, 0x1c, 0x40, 0xbd)
16 | val state192 = Array(0xbc, 0x3a, 0xaa, 0xb5, 0xd9, 0x7b, 0xaa, 0x7b, 0x32, 0x5d, 0x7b, 0x8f, 0x69, 0xcd, 0x7c, 0xa8)
17 | val state256 = Array(0x9a, 0x19, 0x88, 0x30, 0xff, 0x9a, 0x4e, 0x39, 0xec, 0x15, 0x01, 0x54, 0x7d, 0x4a, 0x6b, 0x1b)
18 | val state = Nk match {
19 | case 4 => state128
20 | case 6 => state192
21 | case 8 => state256
22 | }
23 |
24 | val Key128 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
25 | val expandedKey128 = Array(
26 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
27 | Array(0xd6, 0xaa, 0x74, 0xfd, 0xd2, 0xaf, 0x72, 0xfa, 0xda, 0xa6, 0x78, 0xf1, 0xd6, 0xab, 0x76, 0xfe),
28 | Array(0xb6, 0x92, 0xcf, 0x0b, 0x64, 0x3d, 0xbd, 0xf1, 0xbe, 0x9b, 0xc5, 0x00, 0x68, 0x30, 0xb3, 0xfe),
29 | Array(0xb6, 0xff, 0x74, 0x4e, 0xd2, 0xc2, 0xc9, 0xbf, 0x6c, 0x59, 0x0c, 0xbf, 0x04, 0x69, 0xbf, 0x41),
30 | Array(0x47, 0xf7, 0xf7, 0xbc, 0x95, 0x35, 0x3e, 0x03, 0xf9, 0x6c, 0x32, 0xbc, 0xfd, 0x05, 0x8d, 0xfd),
31 | Array(0x3c, 0xaa, 0xa3, 0xe8, 0xa9, 0x9f, 0x9d, 0xeb, 0x50, 0xf3, 0xaf, 0x57, 0xad, 0xf6, 0x22, 0xaa),
32 | Array(0x5e, 0x39, 0x0f, 0x7d, 0xf7, 0xa6, 0x92, 0x96, 0xa7, 0x55, 0x3d, 0xc1, 0x0a, 0xa3, 0x1f, 0x6b),
33 | Array(0x14, 0xf9, 0x70, 0x1a, 0xe3, 0x5f, 0xe2, 0x8c, 0x44, 0x0a, 0xdf, 0x4d, 0x4e, 0xa9, 0xc0, 0x26),
34 | Array(0x47, 0x43, 0x87, 0x35, 0xa4, 0x1c, 0x65, 0xb9, 0xe0, 0x16, 0xba, 0xf4, 0xae, 0xbf, 0x7a, 0xd2),
35 | Array(0x54, 0x99, 0x32, 0xd1, 0xf0, 0x85, 0x57, 0x68, 0x10, 0x93, 0xed, 0x9c, 0xbe, 0x2c, 0x97, 0x4e),
36 | Array(0x13, 0x11, 0x1d, 0x7f, 0xe3, 0x94, 0x4a, 0x17, 0xf3, 0x07, 0xa7, 0x8b, 0x4d, 0x2b, 0x30, 0xc5))
37 |
38 | val Key192 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)
39 | val expandedKey192 = Array(
40 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
41 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x58, 0x46, 0xf2, 0xf9, 0x5c, 0x43, 0xf4, 0xfe),
42 | Array(0x54, 0x4a, 0xfe, 0xf5, 0x58, 0x47, 0xf0, 0xfa, 0x48, 0x56, 0xe2, 0xe9, 0x5c, 0x43, 0xf4, 0xfe),
43 | Array(0x40, 0xf9, 0x49, 0xb3, 0x1c, 0xba, 0xbd, 0x4d, 0x48, 0xf0, 0x43, 0xb8, 0x10, 0xb7, 0xb3, 0x42),
44 | Array(0x58, 0xe1, 0x51, 0xab, 0x04, 0xa2, 0xa5, 0x55, 0x7e, 0xff, 0xb5, 0x41, 0x62, 0x45, 0x08, 0x0c),
45 | Array(0x2a, 0xb5, 0x4b, 0xb4, 0x3a, 0x02, 0xf8, 0xf6, 0x62, 0xe3, 0xa9, 0x5d, 0x66, 0x41, 0x0c, 0x08),
46 | Array(0xf5, 0x01, 0x85, 0x72, 0x97, 0x44, 0x8d, 0x7e, 0xbd, 0xf1, 0xc6, 0xca, 0x87, 0xf3, 0x3e, 0x3c),
47 | Array(0xe5, 0x10, 0x97, 0x61, 0x83, 0x51, 0x9b, 0x69, 0x34, 0x15, 0x7c, 0x9e, 0xa3, 0x51, 0xf1, 0xe0),
48 | Array(0x1e, 0xa0, 0x37, 0x2a, 0x99, 0x53, 0x09, 0x16, 0x7c, 0x43, 0x9e, 0x77, 0xff, 0x12, 0x05, 0x1e),
49 | Array(0xdd, 0x7e, 0x0e, 0x88, 0x7e, 0x2f, 0xff, 0x68, 0x60, 0x8f, 0xc8, 0x42, 0xf9, 0xdc, 0xc1, 0x54),
50 | Array(0x85, 0x9f, 0x5f, 0x23, 0x7a, 0x8d, 0x5a, 0x3d, 0xc0, 0xc0, 0x29, 0x52, 0xbe, 0xef, 0xd6, 0x3a),
51 | Array(0xde, 0x60, 0x1e, 0x78, 0x27, 0xbc, 0xdf, 0x2c, 0xa2, 0x23, 0x80, 0x0f, 0xd8, 0xae, 0xda, 0x32),
52 | Array(0xa4, 0x97, 0x0a, 0x33, 0x1a, 0x78, 0xdc, 0x09, 0xc4, 0x18, 0xc2, 0x71, 0xe3, 0xa4, 0x1d, 0x5d))
53 |
54 | val Key256 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f)
55 | val expandedKey256 = Array(
56 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
57 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f),
58 | Array(0xa5, 0x73, 0xc2, 0x9f, 0xa1, 0x76, 0xc4, 0x98, 0xa9, 0x7f, 0xce, 0x93, 0xa5, 0x72, 0xc0, 0x9c),
59 | Array(0x16, 0x51, 0xa8, 0xcd, 0x02, 0x44, 0xbe, 0xda, 0x1a, 0x5d, 0xa4, 0xc1, 0x06, 0x40, 0xba, 0xde),
60 | Array(0xae, 0x87, 0xdf, 0xf0, 0x0f, 0xf1, 0x1b, 0x68, 0xa6, 0x8e, 0xd5, 0xfb, 0x03, 0xfc, 0x15, 0x67),
61 | Array(0x6d, 0xe1, 0xf1, 0x48, 0x6f, 0xa5, 0x4f, 0x92, 0x75, 0xf8, 0xeb, 0x53, 0x73, 0xb8, 0x51, 0x8d),
62 | Array(0xc6, 0x56, 0x82, 0x7f, 0xc9, 0xa7, 0x99, 0x17, 0x6f, 0x29, 0x4c, 0xec, 0x6c, 0xd5, 0x59, 0x8b),
63 | Array(0x3d, 0xe2, 0x3a, 0x75, 0x52, 0x47, 0x75, 0xe7, 0x27, 0xbf, 0x9e, 0xb4, 0x54, 0x07, 0xcf, 0x39),
64 | Array(0x0b, 0xdc, 0x90, 0x5f, 0xc2, 0x7b, 0x09, 0x48, 0xad, 0x52, 0x45, 0xa4, 0xc1, 0x87, 0x1c, 0x2f),
65 | Array(0x45, 0xf5, 0xa6, 0x60, 0x17, 0xb2, 0xd3, 0x87, 0x30, 0x0d, 0x4d, 0x33, 0x64, 0x0a, 0x82, 0x0a),
66 | Array(0x7c, 0xcf, 0xf7, 0x1c, 0xbe, 0xb4, 0xfe, 0x54, 0x13, 0xe6, 0xbb, 0xf0, 0xd2, 0x61, 0xa7, 0xdf),
67 | Array(0xf0, 0x1a, 0xfa, 0xfe, 0xe7, 0xa8, 0x29, 0x79, 0xd7, 0xa5, 0x64, 0x4a, 0xb3, 0xaf, 0xe6, 0x40),
68 | Array(0x25, 0x41, 0xfe, 0x71, 0x9b, 0xf5, 0x00, 0x25, 0x88, 0x13, 0xbb, 0xd5, 0x5a, 0x72, 0x1c, 0x0a),
69 | Array(0x4e, 0x5a, 0x66, 0x99, 0xa9, 0xf2, 0x4f, 0xe0, 0x7e, 0x57, 0x2b, 0xaa, 0xcd, 0xf8, 0xcd, 0xea),
70 | Array(0x24, 0xfc, 0x79, 0xcc, 0xbf, 0x09, 0x79, 0xe9, 0x37, 0x1a, 0xc2, 0x3c, 0x6d, 0x68, 0xde, 0x36))
71 |
72 | val Key = Nk match {
73 | case 4 => Key128
74 | case 6 => Key192
75 | case 8 => Key256
76 | }
77 |
78 | val expandedKey = Nk match {
79 | case 4 => expandedKey128
80 | case 6 => expandedKey192
81 | case 8 => expandedKey256
82 | }
83 |
84 | poke(aes_icipher.io.start, 0)
85 | step(4) // test that things are fine in Idle state
86 |
87 | // send start
88 | poke(aes_icipher.io.start, 1)
89 | step(1)
90 |
91 | // send the ciphertext
92 | for (i <- 0 until Params.StateLength) {
93 | poke(aes_icipher.io.ciphertext(i), state(i))
94 | }
95 | // send the expanded key for round 1
96 | for (j <- 0 until Params.StateLength)
97 | poke(aes_icipher.io.roundKey(j), expandedKey(Nr)(j))
98 | // reset start
99 | poke(aes_icipher.io.start, 0)
100 | step(1)
101 |
102 | // remaining rounds
103 | for (i <- 1 until Nrplus1) {
104 | for (j <- 0 until Params.StateLength)
105 | poke(aes_icipher.io.roundKey(j), expandedKey(Nr - i)(j))
106 | step(1)
107 | }
108 |
109 | val state_e = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
110 |
111 | for (i <- 0 until Params.StateLength)
112 | expect(aes_icipher.io.state_out(i), state_e(i))
113 | expect(aes_icipher.io.state_out_valid, 1)
114 |
115 | step(4)
116 | }
117 |
118 | // Run test with:
119 | // sbt 'testOnly aes.InvCipherTester'
120 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
121 |
122 | class InvCipherTester extends ChiselFlatSpec {
123 |
124 | private val Nk = 8 // 4, 6, 8 [32-bit words] columns in cipher key
125 | private val InvSubBytes_SCD = true
126 | private val backendNames = Array("firrtl", "verilator")
127 | private val dir = "InvCipher"
128 |
129 | for (backendName <- backendNames) {
130 | "Inverse Cipher" should s"execute AES Inverse Cipher (with $backendName)" in {
131 | Driver(() => new InvCipher(Nk, InvSubBytes_SCD), backendName) {
132 | c => new InvCipherUnitTester(c, Nk, InvSubBytes_SCD)
133 | } should be(true)
134 | }
135 | }
136 |
137 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
138 | iotesters.Driver.execute(
139 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
140 | () => new InvCipher(Nk, InvSubBytes_SCD)) {
141 | c => new InvCipherUnitTester(c, Nk, InvSubBytes_SCD)
142 | } should be(true)
143 | }
144 |
145 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
146 | if (backendNames.contains("verilator")) {
147 | iotesters.Driver.execute(
148 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
149 | "--backend-name", "verilator"), () => new InvCipher(Nk, InvSubBytes_SCD)) {
150 | c => new InvCipherUnitTester(c, Nk, InvSubBytes_SCD)
151 | } should be(true)
152 | }
153 | }
154 |
155 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
156 | if (backendNames.contains("firrtl")) {
157 | iotesters.Driver.execute(
158 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
159 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new InvCipher(Nk, InvSubBytes_SCD)) {
160 | c => new InvCipherUnitTester(c, Nk, InvSubBytes_SCD)
161 | } should be(true)
162 | }
163 | }
164 |
165 | "running with --is-verbose" should "show more about what's going on in your tester" in {
166 | iotesters.Driver.execute(
167 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
168 | "--is-verbose"), () => new InvCipher(Nk, InvSubBytes_SCD)) {
169 | c => new InvCipherUnitTester(c, Nk, InvSubBytes_SCD)
170 | } should be(true)
171 | }
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2016-2019 HPLP UVA
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/test/scala/aes/AESUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class AESUnitTester(c: AES, Nk: Int, unrolled: Int, SubBytes_SCD: Boolean, InvSubBytes_SCD: Boolean, expandedKeyMemType: String) extends PeekPokeTester(c) {
7 | require(Nk == 4 || Nk == 6 || Nk == 8)
8 | require(expandedKeyMemType == "ROM" || expandedKeyMemType == "Mem" || expandedKeyMemType == "SyncReadMem")
9 |
10 | private val aes_i = c
11 |
12 | val KeyLength: Int = Nk * Params.rows
13 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
14 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
15 |
16 | printf("\nStarting the tests with 4 idle cycles\n")
17 | poke(aes_i.io.AES_mode, 0) // off
18 | step(4) // test that things are fine in Idle state
19 |
20 | val input_text = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
21 |
22 | if (expandedKeyMemType == "Mem" || expandedKeyMemType == "SyncReadMem") {
23 | val roundKey128 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
24 | val expandedKey128 = Array(
25 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
26 | Array(0xd6, 0xaa, 0x74, 0xfd, 0xd2, 0xaf, 0x72, 0xfa, 0xda, 0xa6, 0x78, 0xf1, 0xd6, 0xab, 0x76, 0xfe),
27 | Array(0xb6, 0x92, 0xcf, 0x0b, 0x64, 0x3d, 0xbd, 0xf1, 0xbe, 0x9b, 0xc5, 0x00, 0x68, 0x30, 0xb3, 0xfe),
28 | Array(0xb6, 0xff, 0x74, 0x4e, 0xd2, 0xc2, 0xc9, 0xbf, 0x6c, 0x59, 0x0c, 0xbf, 0x04, 0x69, 0xbf, 0x41),
29 | Array(0x47, 0xf7, 0xf7, 0xbc, 0x95, 0x35, 0x3e, 0x03, 0xf9, 0x6c, 0x32, 0xbc, 0xfd, 0x05, 0x8d, 0xfd),
30 | Array(0x3c, 0xaa, 0xa3, 0xe8, 0xa9, 0x9f, 0x9d, 0xeb, 0x50, 0xf3, 0xaf, 0x57, 0xad, 0xf6, 0x22, 0xaa),
31 | Array(0x5e, 0x39, 0x0f, 0x7d, 0xf7, 0xa6, 0x92, 0x96, 0xa7, 0x55, 0x3d, 0xc1, 0x0a, 0xa3, 0x1f, 0x6b),
32 | Array(0x14, 0xf9, 0x70, 0x1a, 0xe3, 0x5f, 0xe2, 0x8c, 0x44, 0x0a, 0xdf, 0x4d, 0x4e, 0xa9, 0xc0, 0x26),
33 | Array(0x47, 0x43, 0x87, 0x35, 0xa4, 0x1c, 0x65, 0xb9, 0xe0, 0x16, 0xba, 0xf4, 0xae, 0xbf, 0x7a, 0xd2),
34 | Array(0x54, 0x99, 0x32, 0xd1, 0xf0, 0x85, 0x57, 0x68, 0x10, 0x93, 0xed, 0x9c, 0xbe, 0x2c, 0x97, 0x4e),
35 | Array(0x13, 0x11, 0x1d, 0x7f, 0xe3, 0x94, 0x4a, 0x17, 0xf3, 0x07, 0xa7, 0x8b, 0x4d, 0x2b, 0x30, 0xc5))
36 |
37 | val roundKey192 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)
38 | val expandedKey192 = Array(
39 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
40 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x58, 0x46, 0xf2, 0xf9, 0x5c, 0x43, 0xf4, 0xfe),
41 | Array(0x54, 0x4a, 0xfe, 0xf5, 0x58, 0x47, 0xf0, 0xfa, 0x48, 0x56, 0xe2, 0xe9, 0x5c, 0x43, 0xf4, 0xfe),
42 | Array(0x40, 0xf9, 0x49, 0xb3, 0x1c, 0xba, 0xbd, 0x4d, 0x48, 0xf0, 0x43, 0xb8, 0x10, 0xb7, 0xb3, 0x42),
43 | Array(0x58, 0xe1, 0x51, 0xab, 0x04, 0xa2, 0xa5, 0x55, 0x7e, 0xff, 0xb5, 0x41, 0x62, 0x45, 0x08, 0x0c),
44 | Array(0x2a, 0xb5, 0x4b, 0xb4, 0x3a, 0x02, 0xf8, 0xf6, 0x62, 0xe3, 0xa9, 0x5d, 0x66, 0x41, 0x0c, 0x08),
45 | Array(0xf5, 0x01, 0x85, 0x72, 0x97, 0x44, 0x8d, 0x7e, 0xbd, 0xf1, 0xc6, 0xca, 0x87, 0xf3, 0x3e, 0x3c),
46 | Array(0xe5, 0x10, 0x97, 0x61, 0x83, 0x51, 0x9b, 0x69, 0x34, 0x15, 0x7c, 0x9e, 0xa3, 0x51, 0xf1, 0xe0),
47 | Array(0x1e, 0xa0, 0x37, 0x2a, 0x99, 0x53, 0x09, 0x16, 0x7c, 0x43, 0x9e, 0x77, 0xff, 0x12, 0x05, 0x1e),
48 | Array(0xdd, 0x7e, 0x0e, 0x88, 0x7e, 0x2f, 0xff, 0x68, 0x60, 0x8f, 0xc8, 0x42, 0xf9, 0xdc, 0xc1, 0x54),
49 | Array(0x85, 0x9f, 0x5f, 0x23, 0x7a, 0x8d, 0x5a, 0x3d, 0xc0, 0xc0, 0x29, 0x52, 0xbe, 0xef, 0xd6, 0x3a),
50 | Array(0xde, 0x60, 0x1e, 0x78, 0x27, 0xbc, 0xdf, 0x2c, 0xa2, 0x23, 0x80, 0x0f, 0xd8, 0xae, 0xda, 0x32),
51 | Array(0xa4, 0x97, 0x0a, 0x33, 0x1a, 0x78, 0xdc, 0x09, 0xc4, 0x18, 0xc2, 0x71, 0xe3, 0xa4, 0x1d, 0x5d))
52 |
53 | val roundKey256 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f)
54 | val expandedKey256 = Array(
55 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
56 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f),
57 | Array(0xa5, 0x73, 0xc2, 0x9f, 0xa1, 0x76, 0xc4, 0x98, 0xa9, 0x7f, 0xce, 0x93, 0xa5, 0x72, 0xc0, 0x9c),
58 | Array(0x16, 0x51, 0xa8, 0xcd, 0x02, 0x44, 0xbe, 0xda, 0x1a, 0x5d, 0xa4, 0xc1, 0x06, 0x40, 0xba, 0xde),
59 | Array(0xae, 0x87, 0xdf, 0xf0, 0x0f, 0xf1, 0x1b, 0x68, 0xa6, 0x8e, 0xd5, 0xfb, 0x03, 0xfc, 0x15, 0x67),
60 | Array(0x6d, 0xe1, 0xf1, 0x48, 0x6f, 0xa5, 0x4f, 0x92, 0x75, 0xf8, 0xeb, 0x53, 0x73, 0xb8, 0x51, 0x8d),
61 | Array(0xc6, 0x56, 0x82, 0x7f, 0xc9, 0xa7, 0x99, 0x17, 0x6f, 0x29, 0x4c, 0xec, 0x6c, 0xd5, 0x59, 0x8b),
62 | Array(0x3d, 0xe2, 0x3a, 0x75, 0x52, 0x47, 0x75, 0xe7, 0x27, 0xbf, 0x9e, 0xb4, 0x54, 0x07, 0xcf, 0x39),
63 | Array(0x0b, 0xdc, 0x90, 0x5f, 0xc2, 0x7b, 0x09, 0x48, 0xad, 0x52, 0x45, 0xa4, 0xc1, 0x87, 0x1c, 0x2f),
64 | Array(0x45, 0xf5, 0xa6, 0x60, 0x17, 0xb2, 0xd3, 0x87, 0x30, 0x0d, 0x4d, 0x33, 0x64, 0x0a, 0x82, 0x0a),
65 | Array(0x7c, 0xcf, 0xf7, 0x1c, 0xbe, 0xb4, 0xfe, 0x54, 0x13, 0xe6, 0xbb, 0xf0, 0xd2, 0x61, 0xa7, 0xdf),
66 | Array(0xf0, 0x1a, 0xfa, 0xfe, 0xe7, 0xa8, 0x29, 0x79, 0xd7, 0xa5, 0x64, 0x4a, 0xb3, 0xaf, 0xe6, 0x40),
67 | Array(0x25, 0x41, 0xfe, 0x71, 0x9b, 0xf5, 0x00, 0x25, 0x88, 0x13, 0xbb, 0xd5, 0x5a, 0x72, 0x1c, 0x0a),
68 | Array(0x4e, 0x5a, 0x66, 0x99, 0xa9, 0xf2, 0x4f, 0xe0, 0x7e, 0x57, 0x2b, 0xaa, 0xcd, 0xf8, 0xcd, 0xea),
69 | Array(0x24, 0xfc, 0x79, 0xcc, 0xbf, 0x09, 0x79, 0xe9, 0x37, 0x1a, 0xc2, 0x3c, 0x6d, 0x68, 0xde, 0x36))
70 |
71 | val roundKey = Nk match {
72 | case 4 => roundKey128
73 | case 6 => roundKey192
74 | case 8 => roundKey256
75 | }
76 |
77 | val expandedKey = Nk match {
78 | case 4 => expandedKey128
79 | case 6 => expandedKey192
80 | case 8 => expandedKey256
81 | }
82 |
83 | printf("\nSending expanded AES key\n")
84 | // send expanded key to AES memory block
85 | poke(aes_i.io.AES_mode, 1) // configure key
86 | for (i <- 0 until Nrplus1) {
87 | for (j <- 0 until Params.StateLength) {
88 | poke(aes_i.io.input_text(j), expandedKey(i)(j))
89 | }
90 | step(1)
91 | }
92 |
93 | printf("\nStaying idle for 4 cycles\n")
94 | poke(aes_i.io.AES_mode, 0) // must stop when all roundKeys were sent
95 | step(4)
96 | }
97 |
98 | printf("\nStarting AES cipher mode, sending plaintext\n")
99 | poke(aes_i.io.AES_mode, 2) // cipher
100 | step(1)
101 |
102 | // send the plaintext
103 | for (i <- 0 until Params.StateLength) {
104 | poke(aes_i.io.input_text(i), input_text(i))
105 | }
106 | step(1)
107 |
108 | // remaining rounds
109 | for (i <- 1 until Nrplus1) {
110 | step(1)
111 | }
112 |
113 | val state_e128 = Array(0x89, 0xed, 0x5e, 0x6a, 0x05, 0xca, 0x76, 0x33, 0x81, 0x35, 0x08, 0x5f, 0xe2, 0x1c, 0x40, 0xbd)
114 | val state_e192 = Array(0xbc, 0x3a, 0xaa, 0xb5, 0xd9, 0x7b, 0xaa, 0x7b, 0x32, 0x5d, 0x7b, 0x8f, 0x69, 0xcd, 0x7c, 0xa8)
115 | val state_e256 = Array(0x9a, 0x19, 0x88, 0x30, 0xff, 0x9a, 0x4e, 0x39, 0xec, 0x15, 0x01, 0x54, 0x7d, 0x4a, 0x6b, 0x1b)
116 |
117 | val state_e = Nk match {
118 | case 4 => state_e128
119 | case 6 => state_e192
120 | case 8 => state_e256
121 | }
122 |
123 | printf("\nInspecting cipher output\n")
124 | // verify aes cipher output
125 | for (i <- 0 until Params.StateLength)
126 | expect(aes_i.io.output_text(i), state_e(i))
127 | expect(aes_i.io.output_valid, 1)
128 |
129 | // store cipher output
130 | val cipher_output = peek(aes_i.io.output_text)
131 |
132 | printf("\nStaying idle for 4 cycles\n")
133 | poke(aes_i.io.AES_mode, 0) // off
134 | step(4)
135 |
136 | printf("\nStarting AES inverse cipher mode, sending ciphertext\n")
137 | poke(aes_i.io.AES_mode, 3) // inverse cipher
138 | step(1)
139 |
140 | // send the ciphertext
141 | for (i <- 0 until Params.StateLength) {
142 | poke(aes_i.io.input_text(i), cipher_output(i)) // same as state_e(i)
143 | }
144 | step(1)
145 |
146 | // remaining rounds
147 | for (i <- 1 until Nrplus1) {
148 | step(1)
149 | }
150 |
151 | if (expandedKeyMemType == "SyncReadMem") {
152 | step(1) // InvCipher takes 1 extra clk for SyncReadMem
153 | }
154 |
155 | printf("\nInspecting inverse cipher output\n")
156 | // verify aes cipher output
157 | for (i <- 0 until Params.StateLength)
158 | expect(aes_i.io.output_text(i), input_text(i))
159 | expect(aes_i.io.output_valid, 1)
160 |
161 | printf("\nStaying idle for 4 cycles\n")
162 | step(4)
163 | }
164 |
165 | // Run test with:
166 | // sbt 'testOnly aes.AESTester'
167 | // sbt 'testOnly aes.AESTester -- -z "using verilator"'
168 | // sbt 'testOnly aes.AESTester -- -z "using firrtl"'
169 | // sbt 'testOnly aes.AESTester -- -z verbose'
170 | // sbt 'testOnly aes.AESTester -- -z vcd'
171 |
172 | class AESTester extends ChiselFlatSpec {
173 |
174 | private val expandedKeyMemType = "SyncReadMem" // ROM or Mem or SyncReadMem works
175 | private val SubBytes_SCD = false
176 | private val InvSubBytes_SCD = false
177 | private val Nk = 8 // 4, 6, 8 [32-bit words] columns in cipher key
178 | private val unrolled = 14
179 | private val backendNames = Array("firrtl", "verilator")
180 | private val dir = "AES"
181 |
182 | for (backendName <- backendNames) {
183 | "AES" should s"execute cipher and inverse cipher (with $backendName)" in {
184 | Driver(() => new AES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType), backendName) {
185 | c => new AESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
186 | } should be(true)
187 | }
188 | }
189 |
190 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
191 | iotesters.Driver.execute(
192 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
193 | () => new AES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
194 | c => new AESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
195 | } should be(true)
196 | }
197 |
198 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
199 | if (backendNames.contains("verilator")) {
200 | iotesters.Driver.execute(
201 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
202 | "--backend-name", "verilator"), () => new AES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
203 | c => new AESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
204 | } should be(true)
205 | }
206 | }
207 |
208 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
209 | if (backendNames.contains("firrtl")) {
210 | iotesters.Driver.execute(
211 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
212 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new AES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
213 | c => new AESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
214 | } should be(true)
215 | }
216 | }
217 |
218 | "running with --is-verbose" should "show more about what's going on in your tester" in {
219 | iotesters.Driver.execute(
220 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
221 | "--is-verbose"), () => new AES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
222 | c => new AESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
223 | } should be(true)
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/src/test/scala/aes/UnrolledAESUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class UnrolledAESUnitTester(c: UnrolledAES, Nk: Int, unrolled: Int, SubBytes_SCD: Boolean, InvSubBytes_SCD: Boolean, expandedKeyMemType: String) extends PeekPokeTester(c) {
7 | require(Nk == 4 || Nk == 6 || Nk == 8)
8 | require(expandedKeyMemType == "ROM" || expandedKeyMemType == "Mem" || expandedKeyMemType == "SyncReadMem")
9 |
10 | private val aes_i = c
11 |
12 | val KeyLength: Int = Nk * Params.rows
13 | val Nr: Int = Nk + 6 // 10, 12, 14 rounds
14 | val Nrplus1: Int = Nr + 1 // 10+1, 12+1, 14+1
15 |
16 | printf("\nStarting the tests with 4 idle cycles\n")
17 | poke(aes_i.io.AES_mode, 0) // off
18 | step(4) // test that things are fine in Idle state
19 |
20 | val input_text = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
21 |
22 | if (expandedKeyMemType == "Mem" || expandedKeyMemType == "SyncReadMem") {
23 | val roundKey128 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f)
24 | val expandedKey128 = Array(
25 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
26 | Array(0xd6, 0xaa, 0x74, 0xfd, 0xd2, 0xaf, 0x72, 0xfa, 0xda, 0xa6, 0x78, 0xf1, 0xd6, 0xab, 0x76, 0xfe),
27 | Array(0xb6, 0x92, 0xcf, 0x0b, 0x64, 0x3d, 0xbd, 0xf1, 0xbe, 0x9b, 0xc5, 0x00, 0x68, 0x30, 0xb3, 0xfe),
28 | Array(0xb6, 0xff, 0x74, 0x4e, 0xd2, 0xc2, 0xc9, 0xbf, 0x6c, 0x59, 0x0c, 0xbf, 0x04, 0x69, 0xbf, 0x41),
29 | Array(0x47, 0xf7, 0xf7, 0xbc, 0x95, 0x35, 0x3e, 0x03, 0xf9, 0x6c, 0x32, 0xbc, 0xfd, 0x05, 0x8d, 0xfd),
30 | Array(0x3c, 0xaa, 0xa3, 0xe8, 0xa9, 0x9f, 0x9d, 0xeb, 0x50, 0xf3, 0xaf, 0x57, 0xad, 0xf6, 0x22, 0xaa),
31 | Array(0x5e, 0x39, 0x0f, 0x7d, 0xf7, 0xa6, 0x92, 0x96, 0xa7, 0x55, 0x3d, 0xc1, 0x0a, 0xa3, 0x1f, 0x6b),
32 | Array(0x14, 0xf9, 0x70, 0x1a, 0xe3, 0x5f, 0xe2, 0x8c, 0x44, 0x0a, 0xdf, 0x4d, 0x4e, 0xa9, 0xc0, 0x26),
33 | Array(0x47, 0x43, 0x87, 0x35, 0xa4, 0x1c, 0x65, 0xb9, 0xe0, 0x16, 0xba, 0xf4, 0xae, 0xbf, 0x7a, 0xd2),
34 | Array(0x54, 0x99, 0x32, 0xd1, 0xf0, 0x85, 0x57, 0x68, 0x10, 0x93, 0xed, 0x9c, 0xbe, 0x2c, 0x97, 0x4e),
35 | Array(0x13, 0x11, 0x1d, 0x7f, 0xe3, 0x94, 0x4a, 0x17, 0xf3, 0x07, 0xa7, 0x8b, 0x4d, 0x2b, 0x30, 0xc5))
36 |
37 | val roundKey192 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)
38 | val expandedKey192 = Array(
39 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
40 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x58, 0x46, 0xf2, 0xf9, 0x5c, 0x43, 0xf4, 0xfe),
41 | Array(0x54, 0x4a, 0xfe, 0xf5, 0x58, 0x47, 0xf0, 0xfa, 0x48, 0x56, 0xe2, 0xe9, 0x5c, 0x43, 0xf4, 0xfe),
42 | Array(0x40, 0xf9, 0x49, 0xb3, 0x1c, 0xba, 0xbd, 0x4d, 0x48, 0xf0, 0x43, 0xb8, 0x10, 0xb7, 0xb3, 0x42),
43 | Array(0x58, 0xe1, 0x51, 0xab, 0x04, 0xa2, 0xa5, 0x55, 0x7e, 0xff, 0xb5, 0x41, 0x62, 0x45, 0x08, 0x0c),
44 | Array(0x2a, 0xb5, 0x4b, 0xb4, 0x3a, 0x02, 0xf8, 0xf6, 0x62, 0xe3, 0xa9, 0x5d, 0x66, 0x41, 0x0c, 0x08),
45 | Array(0xf5, 0x01, 0x85, 0x72, 0x97, 0x44, 0x8d, 0x7e, 0xbd, 0xf1, 0xc6, 0xca, 0x87, 0xf3, 0x3e, 0x3c),
46 | Array(0xe5, 0x10, 0x97, 0x61, 0x83, 0x51, 0x9b, 0x69, 0x34, 0x15, 0x7c, 0x9e, 0xa3, 0x51, 0xf1, 0xe0),
47 | Array(0x1e, 0xa0, 0x37, 0x2a, 0x99, 0x53, 0x09, 0x16, 0x7c, 0x43, 0x9e, 0x77, 0xff, 0x12, 0x05, 0x1e),
48 | Array(0xdd, 0x7e, 0x0e, 0x88, 0x7e, 0x2f, 0xff, 0x68, 0x60, 0x8f, 0xc8, 0x42, 0xf9, 0xdc, 0xc1, 0x54),
49 | Array(0x85, 0x9f, 0x5f, 0x23, 0x7a, 0x8d, 0x5a, 0x3d, 0xc0, 0xc0, 0x29, 0x52, 0xbe, 0xef, 0xd6, 0x3a),
50 | Array(0xde, 0x60, 0x1e, 0x78, 0x27, 0xbc, 0xdf, 0x2c, 0xa2, 0x23, 0x80, 0x0f, 0xd8, 0xae, 0xda, 0x32),
51 | Array(0xa4, 0x97, 0x0a, 0x33, 0x1a, 0x78, 0xdc, 0x09, 0xc4, 0x18, 0xc2, 0x71, 0xe3, 0xa4, 0x1d, 0x5d))
52 |
53 | val roundKey256 = Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f)
54 | val expandedKey256 = Array(
55 | Array(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),
56 | Array(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f),
57 | Array(0xa5, 0x73, 0xc2, 0x9f, 0xa1, 0x76, 0xc4, 0x98, 0xa9, 0x7f, 0xce, 0x93, 0xa5, 0x72, 0xc0, 0x9c),
58 | Array(0x16, 0x51, 0xa8, 0xcd, 0x02, 0x44, 0xbe, 0xda, 0x1a, 0x5d, 0xa4, 0xc1, 0x06, 0x40, 0xba, 0xde),
59 | Array(0xae, 0x87, 0xdf, 0xf0, 0x0f, 0xf1, 0x1b, 0x68, 0xa6, 0x8e, 0xd5, 0xfb, 0x03, 0xfc, 0x15, 0x67),
60 | Array(0x6d, 0xe1, 0xf1, 0x48, 0x6f, 0xa5, 0x4f, 0x92, 0x75, 0xf8, 0xeb, 0x53, 0x73, 0xb8, 0x51, 0x8d),
61 | Array(0xc6, 0x56, 0x82, 0x7f, 0xc9, 0xa7, 0x99, 0x17, 0x6f, 0x29, 0x4c, 0xec, 0x6c, 0xd5, 0x59, 0x8b),
62 | Array(0x3d, 0xe2, 0x3a, 0x75, 0x52, 0x47, 0x75, 0xe7, 0x27, 0xbf, 0x9e, 0xb4, 0x54, 0x07, 0xcf, 0x39),
63 | Array(0x0b, 0xdc, 0x90, 0x5f, 0xc2, 0x7b, 0x09, 0x48, 0xad, 0x52, 0x45, 0xa4, 0xc1, 0x87, 0x1c, 0x2f),
64 | Array(0x45, 0xf5, 0xa6, 0x60, 0x17, 0xb2, 0xd3, 0x87, 0x30, 0x0d, 0x4d, 0x33, 0x64, 0x0a, 0x82, 0x0a),
65 | Array(0x7c, 0xcf, 0xf7, 0x1c, 0xbe, 0xb4, 0xfe, 0x54, 0x13, 0xe6, 0xbb, 0xf0, 0xd2, 0x61, 0xa7, 0xdf),
66 | Array(0xf0, 0x1a, 0xfa, 0xfe, 0xe7, 0xa8, 0x29, 0x79, 0xd7, 0xa5, 0x64, 0x4a, 0xb3, 0xaf, 0xe6, 0x40),
67 | Array(0x25, 0x41, 0xfe, 0x71, 0x9b, 0xf5, 0x00, 0x25, 0x88, 0x13, 0xbb, 0xd5, 0x5a, 0x72, 0x1c, 0x0a),
68 | Array(0x4e, 0x5a, 0x66, 0x99, 0xa9, 0xf2, 0x4f, 0xe0, 0x7e, 0x57, 0x2b, 0xaa, 0xcd, 0xf8, 0xcd, 0xea),
69 | Array(0x24, 0xfc, 0x79, 0xcc, 0xbf, 0x09, 0x79, 0xe9, 0x37, 0x1a, 0xc2, 0x3c, 0x6d, 0x68, 0xde, 0x36))
70 |
71 | val roundKey = Nk match {
72 | case 4 => roundKey128
73 | case 6 => roundKey192
74 | case 8 => roundKey256
75 | }
76 |
77 | val expandedKey = Nk match {
78 | case 4 => expandedKey128
79 | case 6 => expandedKey192
80 | case 8 => expandedKey256
81 | }
82 |
83 | printf("\nSending expanded AES key\n")
84 | // send expanded key to AES memory block
85 | poke(aes_i.io.AES_mode, 1) // configure key
86 | for (i <- 0 until Nrplus1) {
87 | for (j <- 0 until Params.StateLength) {
88 | poke(aes_i.io.input_text(j), expandedKey(i)(j))
89 | }
90 | step(1)
91 | }
92 |
93 | printf("\nStaying idle for 4 cycles\n")
94 | poke(aes_i.io.AES_mode, 0) // must stop when all roundKeys were sent
95 | step(4)
96 | }
97 |
98 | printf("\nStarting AES cipher mode, sending plaintext\n")
99 | poke(aes_i.io.AES_mode, 2) // cipher
100 | // send the plaintext
101 | for (i <- 0 until Params.StateLength) {
102 | poke(aes_i.io.input_text(i), input_text(i))
103 | }
104 | step(1)
105 | poke(aes_i.io.AES_mode, 0) // idle
106 |
107 | // remaining rounds
108 | for (i <- 1 until Nrplus1) {
109 | step(1)
110 | }
111 |
112 | val state_e128 = Array(0x89, 0xed, 0x5e, 0x6a, 0x05, 0xca, 0x76, 0x33, 0x81, 0x35, 0x08, 0x5f, 0xe2, 0x1c, 0x40, 0xbd)
113 | val state_e192 = Array(0xbc, 0x3a, 0xaa, 0xb5, 0xd9, 0x7b, 0xaa, 0x7b, 0x32, 0x5d, 0x7b, 0x8f, 0x69, 0xcd, 0x7c, 0xa8)
114 | val state_e256 = Array(0x9a, 0x19, 0x88, 0x30, 0xff, 0x9a, 0x4e, 0x39, 0xec, 0x15, 0x01, 0x54, 0x7d, 0x4a, 0x6b, 0x1b)
115 |
116 | val state_e = Nk match {
117 | case 4 => state_e128
118 | case 6 => state_e192
119 | case 8 => state_e256
120 | }
121 |
122 | printf("\nInspecting cipher output\n")
123 | // verify aes cipher output
124 | for (i <- 0 until Params.StateLength)
125 | expect(aes_i.io.output_text(i), state_e(i))
126 | expect(aes_i.io.output_valid, 1)
127 |
128 | // store cipher output
129 | val cipher_output = peek(aes_i.io.output_text)
130 |
131 | printf("\nStaying idle for 4 cycles\n")
132 | poke(aes_i.io.AES_mode, 0) // off
133 | step(4)
134 |
135 | printf("\nStarting AES inverse cipher mode, sending ciphertext\n")
136 | poke(aes_i.io.AES_mode, 3) // inverse cipher
137 | // send the ciphertext
138 | for (i <- 0 until Params.StateLength) {
139 | poke(aes_i.io.input_text(i), cipher_output(i)) // same as state_e(i)
140 | }
141 | step(1)
142 | poke(aes_i.io.AES_mode, 0) // idle
143 |
144 | // remaining rounds
145 | for (i <- 1 until Nrplus1) {
146 | step(1)
147 | }
148 |
149 | printf("\nInspecting inverse cipher output\n")
150 | // verify aes inverse cipher output
151 | for (i <- 0 until Params.StateLength)
152 | expect(aes_i.io.output_text(i), input_text(i))
153 | expect(aes_i.io.output_valid, 1)
154 |
155 | printf("\nStaying idle for 4 cycles\n")
156 | step(4)
157 | }
158 |
159 | // Run test with:
160 | // sbt 'testOnly aes.UnrolledAESTester'
161 | // sbt 'testOnly aes.UnrolledAESTester -- -z "using verilator"'
162 | // sbt 'testOnly aes.UnrolledAESTester -- -z "using firrtl"'
163 | // sbt 'testOnly aes.UnrolledAESTester -- -z verbose'
164 | // sbt 'testOnly aes.UnrolledAESTester -- -z vcd'
165 |
166 | class UnrolledAESTester extends ChiselFlatSpec {
167 |
168 | private val expandedKeyMemType = "SyncReadMem" // ROM or Mem or SyncReadMem works
169 | private val SubBytes_SCD = false
170 | private val InvSubBytes_SCD = false
171 | private val Nk = 8 // 4, 6, 8 [32-bit words] columns in cipher key
172 | private val unrolled = 10
173 | private val backendNames = Array("firrtl", "verilator")
174 | private val dir = "UnrolledAES"
175 |
176 | for (backendName <- backendNames) {
177 | "UnrolledAES" should s"execute cipher and inverse cipher (with $backendName)" in {
178 | Driver(() => new UnrolledAES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType), backendName) {
179 | c => new UnrolledAESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
180 | } should be(true)
181 | }
182 | }
183 |
184 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
185 | iotesters.Driver.execute(
186 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir),
187 | () => new UnrolledAES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
188 | c => new UnrolledAESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
189 | } should be(true)
190 | }
191 |
192 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
193 | if (backendNames.contains("verilator")) {
194 | iotesters.Driver.execute(
195 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
196 | "--backend-name", "verilator"), () => new UnrolledAES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
197 | c => new UnrolledAESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
198 | } should be(true)
199 | }
200 | }
201 |
202 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
203 | if (backendNames.contains("firrtl")) {
204 | iotesters.Driver.execute(
205 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
206 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new UnrolledAES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
207 | c => new UnrolledAESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
208 | } should be(true)
209 | }
210 | }
211 |
212 | "running with --is-verbose" should "show more about what's going on in your tester" in {
213 | iotesters.Driver.execute(
214 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
215 | "--is-verbose"), () => new UnrolledAES(Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)) {
216 | c => new UnrolledAESUnitTester(c, Nk, unrolled, SubBytes_SCD, InvSubBytes_SCD, expandedKeyMemType)
217 | } should be(true)
218 | }
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/src/test/scala/aes/MixColumnsUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class MixColumnsUnitTester(c: MixColumns, Pipelined: Boolean) extends PeekPokeTester(c) {
7 |
8 | def computeMixColumns(state_in: Array[Int]): Array[Int] = {
9 | var state_out = new Array[Int](Params.StateLength)
10 |
11 | var mul02 = Array(
12 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
13 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
14 | 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
15 | 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
16 | 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
17 | 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
18 | 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
19 | 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
20 | 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
21 | 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
22 | 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
23 | 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
24 | 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
25 | 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
26 | 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
27 | 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5)
28 |
29 | var mul03 = Array(
30 | 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
31 | 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
32 | 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
33 | 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
34 | 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
35 | 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
36 | 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
37 | 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
38 | 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
39 | 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
40 | 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
41 | 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
42 | 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
43 | 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
44 | 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
45 | 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a)
46 |
47 | /*
48 | var mul09 = Array(
49 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
50 | 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
51 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
52 | 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
53 | 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
54 | 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
55 | 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
56 | 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
57 | 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
58 | 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
59 | 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
60 | 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
61 | 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
62 | 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
63 | 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
64 | 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46)
65 |
66 | var mul11 = Array(
67 | 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
68 | 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
69 | 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
70 | 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
71 | 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
72 | 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
73 | 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
74 | 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
75 | 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
76 | 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
77 | 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
78 | 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
79 | 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
80 | 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
81 | 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
82 | 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3)
83 |
84 | var mul13 = Array(
85 | 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
86 | 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
87 | 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
88 | 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
89 | 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
90 | 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
91 | 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
92 | 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
93 | 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
94 | 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
95 | 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
96 | 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
97 | 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
98 | 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
99 | 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
100 | 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97)
101 |
102 | var mul14 = Array(
103 | 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
104 | 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
105 | 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
106 | 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
107 | 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
108 | 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
109 | 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
110 | 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
111 | 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
112 | 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
113 | 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
114 | 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
115 | 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
116 | 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
117 | 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
118 | 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d)
119 | */
120 |
121 | state_out(0) = mul02(state_in(0)) ^ mul03(state_in(1)) ^ state_in(2) ^ state_in(3)
122 | state_out(1) = state_in(0) ^ mul02(state_in(1)) ^ mul03(state_in(2)) ^ state_in(3)
123 | state_out(2) = state_in(0) ^ state_in(1) ^ mul02(state_in(2)) ^ mul03(state_in(3))
124 | state_out(3) = mul03(state_in(0)) ^ state_in(1) ^ state_in(2) ^ mul02(state_in(3))
125 |
126 | state_out(4) = mul02(state_in(4)) ^ mul03(state_in(5)) ^ state_in(6) ^ state_in(7)
127 | state_out(5) = state_in(4) ^ mul02(state_in(5)) ^ mul03(state_in(6)) ^ state_in(7)
128 | state_out(6) = state_in(4) ^ state_in(5) ^ mul02(state_in(6)) ^ mul03(state_in(7))
129 | state_out(7) = mul03(state_in(4)) ^ state_in(5) ^ state_in(6) ^ mul02(state_in(7))
130 |
131 | state_out(8) = mul02(state_in(8)) ^ mul03(state_in(9)) ^ state_in(10) ^ state_in(11)
132 | state_out(9) = state_in(8) ^ mul02(state_in(9)) ^ mul03(state_in(10)) ^ state_in(11)
133 | state_out(10) = state_in(8) ^ state_in(9) ^ mul02(state_in(10)) ^ mul03(state_in(11))
134 | state_out(11) = mul03(state_in(8)) ^ state_in(9) ^ state_in(10) ^ mul02(state_in(11))
135 |
136 | state_out(12) = mul02(state_in(12)) ^ mul03(state_in(13)) ^ state_in(14) ^ state_in(15)
137 | state_out(13) = state_in(12) ^ mul02(state_in(13)) ^ mul03(state_in(14)) ^ state_in(15)
138 | state_out(14) = state_in(12) ^ state_in(13) ^ mul02(state_in(14)) ^ mul03(state_in(15))
139 | state_out(15) = mul03(state_in(12)) ^ state_in(13) ^ state_in(14) ^ mul02(state_in(15))
140 |
141 | state_out
142 | }
143 |
144 | private val aes_mc = c
145 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
146 |
147 | for (i <- 0 until Params.StateLength)
148 | poke(aes_mc.io.state_in(i), state(i))
149 |
150 | state = computeMixColumns(state)
151 | println(state.deep.mkString(" "))
152 |
153 | if (Pipelined) {
154 | step(2)
155 | } else {
156 | step(1)
157 | }
158 |
159 | for (i <- 0 until Params.StateLength)
160 | expect(aes_mc.io.state_out(i), state(i))
161 | }
162 |
163 | // Run test with:
164 | // sbt 'testOnly aes.MixColumnsTester'
165 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
166 |
167 | class MixColumnsTester extends ChiselFlatSpec {
168 |
169 | private val Pipelined = false // [false -> 136 LUTs, true -> 128 LUTs and 128 FFs]
170 | private val backendNames = Array("firrtl", "verilator")
171 | private val dir = "MixColumns"
172 |
173 | for (backendName <- backendNames) {
174 | "MixColumns" should s"execute AES MixColumns (with $backendName)" in {
175 | Driver(() => new MixColumns(Pipelined), backendName) {
176 | c => new MixColumnsUnitTester(c, Pipelined)
177 | } should be(true)
178 | }
179 | }
180 |
181 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
182 | iotesters.Driver.execute(
183 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new MixColumns(Pipelined)) {
184 | c => new MixColumnsUnitTester(c, Pipelined)
185 | } should be(true)
186 | }
187 |
188 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
189 | if (backendNames.contains("verilator")) {
190 | iotesters.Driver.execute(
191 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
192 | "--backend-name", "verilator"), () => new MixColumns(Pipelined)) {
193 | c => new MixColumnsUnitTester(c, Pipelined)
194 | } should be(true)
195 | }
196 | }
197 |
198 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
199 | if (backendNames.contains("firrtl")) {
200 | iotesters.Driver.execute(
201 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
202 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new MixColumns(Pipelined)) {
203 | c => new MixColumnsUnitTester(c, Pipelined)
204 | } should be(true)
205 | }
206 | }
207 |
208 | "running with --is-verbose" should "show more about what's going on in your tester" in {
209 | iotesters.Driver.execute(
210 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
211 | "--is-verbose"), () => new MixColumns(Pipelined)) {
212 | c => new MixColumnsUnitTester(c, Pipelined)
213 | } should be(true)
214 | }
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/src/test/scala/aes/InvMixColumnsUnitTest.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3.iotesters
4 | import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
5 |
6 | class InvMixColumnsUnitTester(c: InvMixColumns, Pipelined: Boolean) extends PeekPokeTester(c) {
7 |
8 | def computeInvMixColumns(state_in: Array[Int]): Array[Int] = {
9 | var state_out = new Array[Int](Params.StateLength)
10 |
11 | /*
12 | var mul02 = Array(
13 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
14 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
15 | 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
16 | 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
17 | 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
18 | 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
19 | 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
20 | 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
21 | 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
22 | 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
23 | 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
24 | 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
25 | 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
26 | 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
27 | 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
28 | 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5)
29 |
30 | var mul03 = Array(
31 | 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
32 | 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
33 | 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
34 | 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
35 | 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
36 | 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
37 | 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
38 | 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
39 | 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
40 | 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
41 | 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
42 | 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
43 | 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
44 | 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
45 | 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
46 | 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a)
47 | */
48 |
49 | var mul09 = Array(
50 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
51 | 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
52 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
53 | 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
54 | 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
55 | 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
56 | 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
57 | 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
58 | 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
59 | 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
60 | 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
61 | 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
62 | 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
63 | 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
64 | 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
65 | 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46)
66 |
67 | var mul11 = Array(
68 | 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
69 | 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
70 | 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
71 | 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
72 | 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
73 | 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
74 | 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
75 | 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
76 | 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
77 | 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
78 | 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
79 | 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
80 | 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
81 | 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
82 | 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
83 | 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3)
84 |
85 | var mul13 = Array(
86 | 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
87 | 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
88 | 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
89 | 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
90 | 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
91 | 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
92 | 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
93 | 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
94 | 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
95 | 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
96 | 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
97 | 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
98 | 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
99 | 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
100 | 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
101 | 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97)
102 |
103 | var mul14 = Array(
104 | 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
105 | 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
106 | 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
107 | 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
108 | 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
109 | 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
110 | 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
111 | 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
112 | 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
113 | 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
114 | 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
115 | 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
116 | 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
117 | 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
118 | 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
119 | 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d)
120 |
121 | state_out(0) = mul14(state_in(0)) ^ mul11(state_in(1)) ^ mul13(state_in(2)) ^ mul09(state_in(3))
122 | state_out(1) = mul09(state_in(0)) ^ mul14(state_in(1)) ^ mul11(state_in(2)) ^ mul13(state_in(3))
123 | state_out(2) = mul13(state_in(0)) ^ mul09(state_in(1)) ^ mul14(state_in(2)) ^ mul11(state_in(3))
124 | state_out(3) = mul11(state_in(0)) ^ mul13(state_in(1)) ^ mul09(state_in(2)) ^ mul14(state_in(3))
125 |
126 | state_out(4) = mul14(state_in(4)) ^ mul11(state_in(5)) ^ mul13(state_in(6)) ^ mul09(state_in(7))
127 | state_out(5) = mul09(state_in(4)) ^ mul14(state_in(5)) ^ mul11(state_in(6)) ^ mul13(state_in(7))
128 | state_out(6) = mul13(state_in(4)) ^ mul09(state_in(5)) ^ mul14(state_in(6)) ^ mul11(state_in(7))
129 | state_out(7) = mul11(state_in(4)) ^ mul13(state_in(5)) ^ mul09(state_in(6)) ^ mul14(state_in(7))
130 |
131 | state_out(8) = mul14(state_in(8)) ^ mul11(state_in(9)) ^ mul13(state_in(10)) ^ mul09(state_in(11))
132 | state_out(9) = mul09(state_in(8)) ^ mul14(state_in(9)) ^ mul11(state_in(10)) ^ mul13(state_in(11))
133 | state_out(10) = mul13(state_in(8)) ^ mul09(state_in(9)) ^ mul14(state_in(10)) ^ mul11(state_in(11))
134 | state_out(11) = mul11(state_in(8)) ^ mul13(state_in(9)) ^ mul09(state_in(10)) ^ mul14(state_in(11))
135 |
136 | state_out(12) = mul14(state_in(12)) ^ mul11(state_in(13)) ^ mul13(state_in(14)) ^ mul09(state_in(15))
137 | state_out(13) = mul09(state_in(12)) ^ mul14(state_in(13)) ^ mul11(state_in(14)) ^ mul13(state_in(15))
138 | state_out(14) = mul13(state_in(12)) ^ mul09(state_in(13)) ^ mul14(state_in(14)) ^ mul11(state_in(15))
139 | state_out(15) = mul11(state_in(12)) ^ mul13(state_in(13)) ^ mul09(state_in(14)) ^ mul14(state_in(15))
140 |
141 | state_out
142 | }
143 |
144 | private val aes_imc = c
145 | var state = Array(0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34)
146 |
147 | for (i <- 0 until Params.StateLength)
148 | poke(aes_imc.io.state_in(i), state(i))
149 |
150 | state = computeInvMixColumns(state)
151 | println(state.deep.mkString(" "))
152 |
153 | if (Pipelined) {
154 | step(2)
155 | } else {
156 | step(1)
157 | }
158 |
159 | for (i <- 0 until Params.StateLength)
160 | expect(aes_imc.io.state_out(i), state(i))
161 | }
162 |
163 | // Run test with:
164 | // sbt 'testOnly aes.InvMixColumnsTester'
165 | // extend with the option '-- -z verbose' or '-- -z vcd' for specific test
166 |
167 | class InvMixColumnsTester extends ChiselFlatSpec {
168 |
169 | private val Pipelined = false // [false -> 240 LUTs, true -> 236 LUTs and 128 FFs]
170 | private val backendNames = Array("firrtl", "verilator")
171 | private val dir = "InvMixColumns"
172 |
173 | for (backendName <- backendNames) {
174 | "InvMixColumns" should s"execute AES InvMixColumns (with $backendName)" in {
175 | Driver(() => new InvMixColumns(Pipelined), backendName) {
176 | c => new InvMixColumnsUnitTester(c, Pipelined)
177 | } should be(true)
178 | }
179 | }
180 |
181 | "Basic test using Driver.execute" should "be used as an alternative way to run specification" in {
182 | iotesters.Driver.execute(
183 | Array("--target-dir", "test_run_dir/" + dir + "_basic_test", "--top-name", dir), () => new InvMixColumns(Pipelined)) {
184 | c => new InvMixColumnsUnitTester(c, Pipelined)
185 | } should be(true)
186 | }
187 |
188 | "using --backend-name verilator" should "be an alternative way to run using verilator" in {
189 | if (backendNames.contains("verilator")) {
190 | iotesters.Driver.execute(
191 | Array("--target-dir", "test_run_dir/" + dir + "_verilator_test", "--top-name", dir,
192 | "--backend-name", "verilator"), () => new InvMixColumns(Pipelined)) {
193 | c => new InvMixColumnsUnitTester(c, Pipelined)
194 | } should be(true)
195 | }
196 | }
197 |
198 | "using --backend-name firrtl" should "be an alternative way to run using firrtl" in {
199 | if (backendNames.contains("firrtl")) {
200 | iotesters.Driver.execute(
201 | Array("--target-dir", "test_run_dir/" + dir + "_firrtl_test", "--top-name", dir,
202 | "--backend-name", "firrtl", "--generate-vcd-output", "on"), () => new InvMixColumns(Pipelined)) {
203 | c => new InvMixColumnsUnitTester(c, Pipelined)
204 | } should be(true)
205 | }
206 | }
207 |
208 | "running with --is-verbose" should "show more about what's going on in your tester" in {
209 | iotesters.Driver.execute(
210 | Array("--target-dir", "test_run_dir/" + dir + "_verbose_test", "--top-name", dir,
211 | "--is-verbose"), () => new InvMixColumns(Pipelined)) {
212 | c => new InvMixColumnsUnitTester(c, Pipelined)
213 | } should be(true)
214 | }
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/src/main/scala/aes/MixColumns.scala:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | // implements MixColumns
7 | class MixColumns(Pipelined: Boolean = false) extends Module {
8 | val io = IO(new Bundle {
9 | val state_in = Input(Vec(Params.StateLength, UInt(8.W)))
10 | val state_out = Output(Vec(Params.StateLength, UInt(8.W)))
11 | })
12 |
13 | val mul02 = VecInit(Array(
14 | 0x00.U, 0x02.U, 0x04.U, 0x06.U, 0x08.U, 0x0a.U, 0x0c.U, 0x0e.U, 0x10.U, 0x12.U, 0x14.U, 0x16.U, 0x18.U, 0x1a.U, 0x1c.U, 0x1e.U,
15 | 0x20.U, 0x22.U, 0x24.U, 0x26.U, 0x28.U, 0x2a.U, 0x2c.U, 0x2e.U, 0x30.U, 0x32.U, 0x34.U, 0x36.U, 0x38.U, 0x3a.U, 0x3c.U, 0x3e.U,
16 | 0x40.U, 0x42.U, 0x44.U, 0x46.U, 0x48.U, 0x4a.U, 0x4c.U, 0x4e.U, 0x50.U, 0x52.U, 0x54.U, 0x56.U, 0x58.U, 0x5a.U, 0x5c.U, 0x5e.U,
17 | 0x60.U, 0x62.U, 0x64.U, 0x66.U, 0x68.U, 0x6a.U, 0x6c.U, 0x6e.U, 0x70.U, 0x72.U, 0x74.U, 0x76.U, 0x78.U, 0x7a.U, 0x7c.U, 0x7e.U,
18 | 0x80.U, 0x82.U, 0x84.U, 0x86.U, 0x88.U, 0x8a.U, 0x8c.U, 0x8e.U, 0x90.U, 0x92.U, 0x94.U, 0x96.U, 0x98.U, 0x9a.U, 0x9c.U, 0x9e.U,
19 | 0xa0.U, 0xa2.U, 0xa4.U, 0xa6.U, 0xa8.U, 0xaa.U, 0xac.U, 0xae.U, 0xb0.U, 0xb2.U, 0xb4.U, 0xb6.U, 0xb8.U, 0xba.U, 0xbc.U, 0xbe.U,
20 | 0xc0.U, 0xc2.U, 0xc4.U, 0xc6.U, 0xc8.U, 0xca.U, 0xcc.U, 0xce.U, 0xd0.U, 0xd2.U, 0xd4.U, 0xd6.U, 0xd8.U, 0xda.U, 0xdc.U, 0xde.U,
21 | 0xe0.U, 0xe2.U, 0xe4.U, 0xe6.U, 0xe8.U, 0xea.U, 0xec.U, 0xee.U, 0xf0.U, 0xf2.U, 0xf4.U, 0xf6.U, 0xf8.U, 0xfa.U, 0xfc.U, 0xfe.U,
22 | 0x1b.U, 0x19.U, 0x1f.U, 0x1d.U, 0x13.U, 0x11.U, 0x17.U, 0x15.U, 0x0b.U, 0x09.U, 0x0f.U, 0x0d.U, 0x03.U, 0x01.U, 0x07.U, 0x05.U,
23 | 0x3b.U, 0x39.U, 0x3f.U, 0x3d.U, 0x33.U, 0x31.U, 0x37.U, 0x35.U, 0x2b.U, 0x29.U, 0x2f.U, 0x2d.U, 0x23.U, 0x21.U, 0x27.U, 0x25.U,
24 | 0x5b.U, 0x59.U, 0x5f.U, 0x5d.U, 0x53.U, 0x51.U, 0x57.U, 0x55.U, 0x4b.U, 0x49.U, 0x4f.U, 0x4d.U, 0x43.U, 0x41.U, 0x47.U, 0x45.U,
25 | 0x7b.U, 0x79.U, 0x7f.U, 0x7d.U, 0x73.U, 0x71.U, 0x77.U, 0x75.U, 0x6b.U, 0x69.U, 0x6f.U, 0x6d.U, 0x63.U, 0x61.U, 0x67.U, 0x65.U,
26 | 0x9b.U, 0x99.U, 0x9f.U, 0x9d.U, 0x93.U, 0x91.U, 0x97.U, 0x95.U, 0x8b.U, 0x89.U, 0x8f.U, 0x8d.U, 0x83.U, 0x81.U, 0x87.U, 0x85.U,
27 | 0xbb.U, 0xb9.U, 0xbf.U, 0xbd.U, 0xb3.U, 0xb1.U, 0xb7.U, 0xb5.U, 0xab.U, 0xa9.U, 0xaf.U, 0xad.U, 0xa3.U, 0xa1.U, 0xa7.U, 0xa5.U,
28 | 0xdb.U, 0xd9.U, 0xdf.U, 0xdd.U, 0xd3.U, 0xd1.U, 0xd7.U, 0xd5.U, 0xcb.U, 0xc9.U, 0xcf.U, 0xcd.U, 0xc3.U, 0xc1.U, 0xc7.U, 0xc5.U,
29 | 0xfb.U, 0xf9.U, 0xff.U, 0xfd.U, 0xf3.U, 0xf1.U, 0xf7.U, 0xf5.U, 0xeb.U, 0xe9.U, 0xef.U, 0xed.U, 0xe3.U, 0xe1.U, 0xe7.U, 0xe5.U))
30 |
31 | val mul03 = VecInit(Array(
32 | 0x00.U, 0x03.U, 0x06.U, 0x05.U, 0x0c.U, 0x0f.U, 0x0a.U, 0x09.U, 0x18.U, 0x1b.U, 0x1e.U, 0x1d.U, 0x14.U, 0x17.U, 0x12.U, 0x11.U,
33 | 0x30.U, 0x33.U, 0x36.U, 0x35.U, 0x3c.U, 0x3f.U, 0x3a.U, 0x39.U, 0x28.U, 0x2b.U, 0x2e.U, 0x2d.U, 0x24.U, 0x27.U, 0x22.U, 0x21.U,
34 | 0x60.U, 0x63.U, 0x66.U, 0x65.U, 0x6c.U, 0x6f.U, 0x6a.U, 0x69.U, 0x78.U, 0x7b.U, 0x7e.U, 0x7d.U, 0x74.U, 0x77.U, 0x72.U, 0x71.U,
35 | 0x50.U, 0x53.U, 0x56.U, 0x55.U, 0x5c.U, 0x5f.U, 0x5a.U, 0x59.U, 0x48.U, 0x4b.U, 0x4e.U, 0x4d.U, 0x44.U, 0x47.U, 0x42.U, 0x41.U,
36 | 0xc0.U, 0xc3.U, 0xc6.U, 0xc5.U, 0xcc.U, 0xcf.U, 0xca.U, 0xc9.U, 0xd8.U, 0xdb.U, 0xde.U, 0xdd.U, 0xd4.U, 0xd7.U, 0xd2.U, 0xd1.U,
37 | 0xf0.U, 0xf3.U, 0xf6.U, 0xf5.U, 0xfc.U, 0xff.U, 0xfa.U, 0xf9.U, 0xe8.U, 0xeb.U, 0xee.U, 0xed.U, 0xe4.U, 0xe7.U, 0xe2.U, 0xe1.U,
38 | 0xa0.U, 0xa3.U, 0xa6.U, 0xa5.U, 0xac.U, 0xaf.U, 0xaa.U, 0xa9.U, 0xb8.U, 0xbb.U, 0xbe.U, 0xbd.U, 0xb4.U, 0xb7.U, 0xb2.U, 0xb1.U,
39 | 0x90.U, 0x93.U, 0x96.U, 0x95.U, 0x9c.U, 0x9f.U, 0x9a.U, 0x99.U, 0x88.U, 0x8b.U, 0x8e.U, 0x8d.U, 0x84.U, 0x87.U, 0x82.U, 0x81.U,
40 | 0x9b.U, 0x98.U, 0x9d.U, 0x9e.U, 0x97.U, 0x94.U, 0x91.U, 0x92.U, 0x83.U, 0x80.U, 0x85.U, 0x86.U, 0x8f.U, 0x8c.U, 0x89.U, 0x8a.U,
41 | 0xab.U, 0xa8.U, 0xad.U, 0xae.U, 0xa7.U, 0xa4.U, 0xa1.U, 0xa2.U, 0xb3.U, 0xb0.U, 0xb5.U, 0xb6.U, 0xbf.U, 0xbc.U, 0xb9.U, 0xba.U,
42 | 0xfb.U, 0xf8.U, 0xfd.U, 0xfe.U, 0xf7.U, 0xf4.U, 0xf1.U, 0xf2.U, 0xe3.U, 0xe0.U, 0xe5.U, 0xe6.U, 0xef.U, 0xec.U, 0xe9.U, 0xea.U,
43 | 0xcb.U, 0xc8.U, 0xcd.U, 0xce.U, 0xc7.U, 0xc4.U, 0xc1.U, 0xc2.U, 0xd3.U, 0xd0.U, 0xd5.U, 0xd6.U, 0xdf.U, 0xdc.U, 0xd9.U, 0xda.U,
44 | 0x5b.U, 0x58.U, 0x5d.U, 0x5e.U, 0x57.U, 0x54.U, 0x51.U, 0x52.U, 0x43.U, 0x40.U, 0x45.U, 0x46.U, 0x4f.U, 0x4c.U, 0x49.U, 0x4a.U,
45 | 0x6b.U, 0x68.U, 0x6d.U, 0x6e.U, 0x67.U, 0x64.U, 0x61.U, 0x62.U, 0x73.U, 0x70.U, 0x75.U, 0x76.U, 0x7f.U, 0x7c.U, 0x79.U, 0x7a.U,
46 | 0x3b.U, 0x38.U, 0x3d.U, 0x3e.U, 0x37.U, 0x34.U, 0x31.U, 0x32.U, 0x23.U, 0x20.U, 0x25.U, 0x26.U, 0x2f.U, 0x2c.U, 0x29.U, 0x2a.U,
47 | 0x0b.U, 0x08.U, 0x0d.U, 0x0e.U, 0x07.U, 0x04.U, 0x01.U, 0x02.U, 0x13.U, 0x10.U, 0x15.U, 0x16.U, 0x1f.U, 0x1c.U, 0x19.U, 0x1a.U))
48 |
49 | /*
50 | val mul09 = VecInit(Array(
51 | 0x00.U, 0x09.U, 0x12.U, 0x1b.U, 0x24.U, 0x2d.U, 0x36.U, 0x3f.U, 0x48.U, 0x41.U, 0x5a.U, 0x53.U, 0x6c.U, 0x65.U, 0x7e.U, 0x77.U,
52 | 0x90.U, 0x99.U, 0x82.U, 0x8b.U, 0xb4.U, 0xbd.U, 0xa6.U, 0xaf.U, 0xd8.U, 0xd1.U, 0xca.U, 0xc3.U, 0xfc.U, 0xf5.U, 0xee.U, 0xe7.U,
53 | 0x3b.U, 0x32.U, 0x29.U, 0x20.U, 0x1f.U, 0x16.U, 0x0d.U, 0x04.U, 0x73.U, 0x7a.U, 0x61.U, 0x68.U, 0x57.U, 0x5e.U, 0x45.U, 0x4c.U,
54 | 0xab.U, 0xa2.U, 0xb9.U, 0xb0.U, 0x8f.U, 0x86.U, 0x9d.U, 0x94.U, 0xe3.U, 0xea.U, 0xf1.U, 0xf8.U, 0xc7.U, 0xce.U, 0xd5.U, 0xdc.U,
55 | 0x76.U, 0x7f.U, 0x64.U, 0x6d.U, 0x52.U, 0x5b.U, 0x40.U, 0x49.U, 0x3e.U, 0x37.U, 0x2c.U, 0x25.U, 0x1a.U, 0x13.U, 0x08.U, 0x01.U,
56 | 0xe6.U, 0xef.U, 0xf4.U, 0xfd.U, 0xc2.U, 0xcb.U, 0xd0.U, 0xd9.U, 0xae.U, 0xa7.U, 0xbc.U, 0xb5.U, 0x8a.U, 0x83.U, 0x98.U, 0x91.U,
57 | 0x4d.U, 0x44.U, 0x5f.U, 0x56.U, 0x69.U, 0x60.U, 0x7b.U, 0x72.U, 0x05.U, 0x0c.U, 0x17.U, 0x1e.U, 0x21.U, 0x28.U, 0x33.U, 0x3a.U,
58 | 0xdd.U, 0xd4.U, 0xcf.U, 0xc6.U, 0xf9.U, 0xf0.U, 0xeb.U, 0xe2.U, 0x95.U, 0x9c.U, 0x87.U, 0x8e.U, 0xb1.U, 0xb8.U, 0xa3.U, 0xaa.U,
59 | 0xec.U, 0xe5.U, 0xfe.U, 0xf7.U, 0xc8.U, 0xc1.U, 0xda.U, 0xd3.U, 0xa4.U, 0xad.U, 0xb6.U, 0xbf.U, 0x80.U, 0x89.U, 0x92.U, 0x9b.U,
60 | 0x7c.U, 0x75.U, 0x6e.U, 0x67.U, 0x58.U, 0x51.U, 0x4a.U, 0x43.U, 0x34.U, 0x3d.U, 0x26.U, 0x2f.U, 0x10.U, 0x19.U, 0x02.U, 0x0b.U,
61 | 0xd7.U, 0xde.U, 0xc5.U, 0xcc.U, 0xf3.U, 0xfa.U, 0xe1.U, 0xe8.U, 0x9f.U, 0x96.U, 0x8d.U, 0x84.U, 0xbb.U, 0xb2.U, 0xa9.U, 0xa0.U,
62 | 0x47.U, 0x4e.U, 0x55.U, 0x5c.U, 0x63.U, 0x6a.U, 0x71.U, 0x78.U, 0x0f.U, 0x06.U, 0x1d.U, 0x14.U, 0x2b.U, 0x22.U, 0x39.U, 0x30.U,
63 | 0x9a.U, 0x93.U, 0x88.U, 0x81.U, 0xbe.U, 0xb7.U, 0xac.U, 0xa5.U, 0xd2.U, 0xdb.U, 0xc0.U, 0xc9.U, 0xf6.U, 0xff.U, 0xe4.U, 0xed.U,
64 | 0x0a.U, 0x03.U, 0x18.U, 0x11.U, 0x2e.U, 0x27.U, 0x3c.U, 0x35.U, 0x42.U, 0x4b.U, 0x50.U, 0x59.U, 0x66.U, 0x6f.U, 0x74.U, 0x7d.U,
65 | 0xa1.U, 0xa8.U, 0xb3.U, 0xba.U, 0x85.U, 0x8c.U, 0x97.U, 0x9e.U, 0xe9.U, 0xe0.U, 0xfb.U, 0xf2.U, 0xcd.U, 0xc4.U, 0xdf.U, 0xd6.U,
66 | 0x31.U, 0x38.U, 0x23.U, 0x2a.U, 0x15.U, 0x1c.U, 0x07.U, 0x0e.U, 0x79.U, 0x70.U, 0x6b.U, 0x62.U, 0x5d.U, 0x54.U, 0x4f.U, 0x46.U))
67 |
68 | val mul11 = VecInit(Array(
69 | 0x00.U, 0x0b.U, 0x16.U, 0x1d.U, 0x2c.U, 0x27.U, 0x3a.U, 0x31.U, 0x58.U, 0x53.U, 0x4e.U, 0x45.U, 0x74.U, 0x7f.U, 0x62.U, 0x69.U,
70 | 0xb0.U, 0xbb.U, 0xa6.U, 0xad.U, 0x9c.U, 0x97.U, 0x8a.U, 0x81.U, 0xe8.U, 0xe3.U, 0xfe.U, 0xf5.U, 0xc4.U, 0xcf.U, 0xd2.U, 0xd9.U,
71 | 0x7b.U, 0x70.U, 0x6d.U, 0x66.U, 0x57.U, 0x5c.U, 0x41.U, 0x4a.U, 0x23.U, 0x28.U, 0x35.U, 0x3e.U, 0x0f.U, 0x04.U, 0x19.U, 0x12.U,
72 | 0xcb.U, 0xc0.U, 0xdd.U, 0xd6.U, 0xe7.U, 0xec.U, 0xf1.U, 0xfa.U, 0x93.U, 0x98.U, 0x85.U, 0x8e.U, 0xbf.U, 0xb4.U, 0xa9.U, 0xa2.U,
73 | 0xf6.U, 0xfd.U, 0xe0.U, 0xeb.U, 0xda.U, 0xd1.U, 0xcc.U, 0xc7.U, 0xae.U, 0xa5.U, 0xb8.U, 0xb3.U, 0x82.U, 0x89.U, 0x94.U, 0x9f.U,
74 | 0x46.U, 0x4d.U, 0x50.U, 0x5b.U, 0x6a.U, 0x61.U, 0x7c.U, 0x77.U, 0x1e.U, 0x15.U, 0x08.U, 0x03.U, 0x32.U, 0x39.U, 0x24.U, 0x2f.U,
75 | 0x8d.U, 0x86.U, 0x9b.U, 0x90.U, 0xa1.U, 0xaa.U, 0xb7.U, 0xbc.U, 0xd5.U, 0xde.U, 0xc3.U, 0xc8.U, 0xf9.U, 0xf2.U, 0xef.U, 0xe4.U,
76 | 0x3d.U, 0x36.U, 0x2b.U, 0x20.U, 0x11.U, 0x1a.U, 0x07.U, 0x0c.U, 0x65.U, 0x6e.U, 0x73.U, 0x78.U, 0x49.U, 0x42.U, 0x5f.U, 0x54.U,
77 | 0xf7.U, 0xfc.U, 0xe1.U, 0xea.U, 0xdb.U, 0xd0.U, 0xcd.U, 0xc6.U, 0xaf.U, 0xa4.U, 0xb9.U, 0xb2.U, 0x83.U, 0x88.U, 0x95.U, 0x9e.U,
78 | 0x47.U, 0x4c.U, 0x51.U, 0x5a.U, 0x6b.U, 0x60.U, 0x7d.U, 0x76.U, 0x1f.U, 0x14.U, 0x09.U, 0x02.U, 0x33.U, 0x38.U, 0x25.U, 0x2e.U,
79 | 0x8c.U, 0x87.U, 0x9a.U, 0x91.U, 0xa0.U, 0xab.U, 0xb6.U, 0xbd.U, 0xd4.U, 0xdf.U, 0xc2.U, 0xc9.U, 0xf8.U, 0xf3.U, 0xee.U, 0xe5.U,
80 | 0x3c.U, 0x37.U, 0x2a.U, 0x21.U, 0x10.U, 0x1b.U, 0x06.U, 0x0d.U, 0x64.U, 0x6f.U, 0x72.U, 0x79.U, 0x48.U, 0x43.U, 0x5e.U, 0x55.U,
81 | 0x01.U, 0x0a.U, 0x17.U, 0x1c.U, 0x2d.U, 0x26.U, 0x3b.U, 0x30.U, 0x59.U, 0x52.U, 0x4f.U, 0x44.U, 0x75.U, 0x7e.U, 0x63.U, 0x68.U,
82 | 0xb1.U, 0xba.U, 0xa7.U, 0xac.U, 0x9d.U, 0x96.U, 0x8b.U, 0x80.U, 0xe9.U, 0xe2.U, 0xff.U, 0xf4.U, 0xc5.U, 0xce.U, 0xd3.U, 0xd8.U,
83 | 0x7a.U, 0x71.U, 0x6c.U, 0x67.U, 0x56.U, 0x5d.U, 0x40.U, 0x4b.U, 0x22.U, 0x29.U, 0x34.U, 0x3f.U, 0x0e.U, 0x05.U, 0x18.U, 0x13.U,
84 | 0xca.U, 0xc1.U, 0xdc.U, 0xd7.U, 0xe6.U, 0xed.U, 0xf0.U, 0xfb.U, 0x92.U, 0x99.U, 0x84.U, 0x8f.U, 0xbe.U, 0xb5.U, 0xa8.U, 0xa3.U))
85 |
86 | val mul13 = VecInit(Array(
87 | 0x00.U, 0x0d.U, 0x1a.U, 0x17.U, 0x34.U, 0x39.U, 0x2e.U, 0x23.U, 0x68.U, 0x65.U, 0x72.U, 0x7f.U, 0x5c.U, 0x51.U, 0x46.U, 0x4b.U,
88 | 0xd0.U, 0xdd.U, 0xca.U, 0xc7.U, 0xe4.U, 0xe9.U, 0xfe.U, 0xf3.U, 0xb8.U, 0xb5.U, 0xa2.U, 0xaf.U, 0x8c.U, 0x81.U, 0x96.U, 0x9b.U,
89 | 0xbb.U, 0xb6.U, 0xa1.U, 0xac.U, 0x8f.U, 0x82.U, 0x95.U, 0x98.U, 0xd3.U, 0xde.U, 0xc9.U, 0xc4.U, 0xe7.U, 0xea.U, 0xfd.U, 0xf0.U,
90 | 0x6b.U, 0x66.U, 0x71.U, 0x7c.U, 0x5f.U, 0x52.U, 0x45.U, 0x48.U, 0x03.U, 0x0e.U, 0x19.U, 0x14.U, 0x37.U, 0x3a.U, 0x2d.U, 0x20.U,
91 | 0x6d.U, 0x60.U, 0x77.U, 0x7a.U, 0x59.U, 0x54.U, 0x43.U, 0x4e.U, 0x05.U, 0x08.U, 0x1f.U, 0x12.U, 0x31.U, 0x3c.U, 0x2b.U, 0x26.U,
92 | 0xbd.U, 0xb0.U, 0xa7.U, 0xaa.U, 0x89.U, 0x84.U, 0x93.U, 0x9e.U, 0xd5.U, 0xd8.U, 0xcf.U, 0xc2.U, 0xe1.U, 0xec.U, 0xfb.U, 0xf6.U,
93 | 0xd6.U, 0xdb.U, 0xcc.U, 0xc1.U, 0xe2.U, 0xef.U, 0xf8.U, 0xf5.U, 0xbe.U, 0xb3.U, 0xa4.U, 0xa9.U, 0x8a.U, 0x87.U, 0x90.U, 0x9d.U,
94 | 0x06.U, 0x0b.U, 0x1c.U, 0x11.U, 0x32.U, 0x3f.U, 0x28.U, 0x25.U, 0x6e.U, 0x63.U, 0x74.U, 0x79.U, 0x5a.U, 0x57.U, 0x40.U, 0x4d.U,
95 | 0xda.U, 0xd7.U, 0xc0.U, 0xcd.U, 0xee.U, 0xe3.U, 0xf4.U, 0xf9.U, 0xb2.U, 0xbf.U, 0xa8.U, 0xa5.U, 0x86.U, 0x8b.U, 0x9c.U, 0x91.U,
96 | 0x0a.U, 0x07.U, 0x10.U, 0x1d.U, 0x3e.U, 0x33.U, 0x24.U, 0x29.U, 0x62.U, 0x6f.U, 0x78.U, 0x75.U, 0x56.U, 0x5b.U, 0x4c.U, 0x41.U,
97 | 0x61.U, 0x6c.U, 0x7b.U, 0x76.U, 0x55.U, 0x58.U, 0x4f.U, 0x42.U, 0x09.U, 0x04.U, 0x13.U, 0x1e.U, 0x3d.U, 0x30.U, 0x27.U, 0x2a.U,
98 | 0xb1.U, 0xbc.U, 0xab.U, 0xa6.U, 0x85.U, 0x88.U, 0x9f.U, 0x92.U, 0xd9.U, 0xd4.U, 0xc3.U, 0xce.U, 0xed.U, 0xe0.U, 0xf7.U, 0xfa.U,
99 | 0xb7.U, 0xba.U, 0xad.U, 0xa0.U, 0x83.U, 0x8e.U, 0x99.U, 0x94.U, 0xdf.U, 0xd2.U, 0xc5.U, 0xc8.U, 0xeb.U, 0xe6.U, 0xf1.U, 0xfc.U,
100 | 0x67.U, 0x6a.U, 0x7d.U, 0x70.U, 0x53.U, 0x5e.U, 0x49.U, 0x44.U, 0x0f.U, 0x02.U, 0x15.U, 0x18.U, 0x3b.U, 0x36.U, 0x21.U, 0x2c.U,
101 | 0x0c.U, 0x01.U, 0x16.U, 0x1b.U, 0x38.U, 0x35.U, 0x22.U, 0x2f.U, 0x64.U, 0x69.U, 0x7e.U, 0x73.U, 0x50.U, 0x5d.U, 0x4a.U, 0x47.U,
102 | 0xdc.U, 0xd1.U, 0xc6.U, 0xcb.U, 0xe8.U, 0xe5.U, 0xf2.U, 0xff.U, 0xb4.U, 0xb9.U, 0xae.U, 0xa3.U, 0x80.U, 0x8d.U, 0x9a.U, 0x97.U))
103 |
104 | val mul14 = VecInit(Array(
105 | 0x00.U, 0x0e.U, 0x1c.U, 0x12.U, 0x38.U, 0x36.U, 0x24.U, 0x2a.U, 0x70.U, 0x7e.U, 0x6c.U, 0x62.U, 0x48.U, 0x46.U, 0x54.U, 0x5a.U,
106 | 0xe0.U, 0xee.U, 0xfc.U, 0xf2.U, 0xd8.U, 0xd6.U, 0xc4.U, 0xca.U, 0x90.U, 0x9e.U, 0x8c.U, 0x82.U, 0xa8.U, 0xa6.U, 0xb4.U, 0xba.U,
107 | 0xdb.U, 0xd5.U, 0xc7.U, 0xc9.U, 0xe3.U, 0xed.U, 0xff.U, 0xf1.U, 0xab.U, 0xa5.U, 0xb7.U, 0xb9.U, 0x93.U, 0x9d.U, 0x8f.U, 0x81.U,
108 | 0x3b.U, 0x35.U, 0x27.U, 0x29.U, 0x03.U, 0x0d.U, 0x1f.U, 0x11.U, 0x4b.U, 0x45.U, 0x57.U, 0x59.U, 0x73.U, 0x7d.U, 0x6f.U, 0x61.U,
109 | 0xad.U, 0xa3.U, 0xb1.U, 0xbf.U, 0x95.U, 0x9b.U, 0x89.U, 0x87.U, 0xdd.U, 0xd3.U, 0xc1.U, 0xcf.U, 0xe5.U, 0xeb.U, 0xf9.U, 0xf7.U,
110 | 0x4d.U, 0x43.U, 0x51.U, 0x5f.U, 0x75.U, 0x7b.U, 0x69.U, 0x67.U, 0x3d.U, 0x33.U, 0x21.U, 0x2f.U, 0x05.U, 0x0b.U, 0x19.U, 0x17.U,
111 | 0x76.U, 0x78.U, 0x6a.U, 0x64.U, 0x4e.U, 0x40.U, 0x52.U, 0x5c.U, 0x06.U, 0x08.U, 0x1a.U, 0x14.U, 0x3e.U, 0x30.U, 0x22.U, 0x2c.U,
112 | 0x96.U, 0x98.U, 0x8a.U, 0x84.U, 0xae.U, 0xa0.U, 0xb2.U, 0xbc.U, 0xe6.U, 0xe8.U, 0xfa.U, 0xf4.U, 0xde.U, 0xd0.U, 0xc2.U, 0xcc.U,
113 | 0x41.U, 0x4f.U, 0x5d.U, 0x53.U, 0x79.U, 0x77.U, 0x65.U, 0x6b.U, 0x31.U, 0x3f.U, 0x2d.U, 0x23.U, 0x09.U, 0x07.U, 0x15.U, 0x1b.U,
114 | 0xa1.U, 0xaf.U, 0xbd.U, 0xb3.U, 0x99.U, 0x97.U, 0x85.U, 0x8b.U, 0xd1.U, 0xdf.U, 0xcd.U, 0xc3.U, 0xe9.U, 0xe7.U, 0xf5.U, 0xfb.U,
115 | 0x9a.U, 0x94.U, 0x86.U, 0x88.U, 0xa2.U, 0xac.U, 0xbe.U, 0xb0.U, 0xea.U, 0xe4.U, 0xf6.U, 0xf8.U, 0xd2.U, 0xdc.U, 0xce.U, 0xc0.U,
116 | 0x7a.U, 0x74.U, 0x66.U, 0x68.U, 0x42.U, 0x4c.U, 0x5e.U, 0x50.U, 0x0a.U, 0x04.U, 0x16.U, 0x18.U, 0x32.U, 0x3c.U, 0x2e.U, 0x20.U,
117 | 0xec.U, 0xe2.U, 0xf0.U, 0xfe.U, 0xd4.U, 0xda.U, 0xc8.U, 0xc6.U, 0x9c.U, 0x92.U, 0x80.U, 0x8e.U, 0xa4.U, 0xaa.U, 0xb8.U, 0xb6.U,
118 | 0x0c.U, 0x02.U, 0x10.U, 0x1e.U, 0x34.U, 0x3a.U, 0x28.U, 0x26.U, 0x7c.U, 0x72.U, 0x60.U, 0x6e.U, 0x44.U, 0x4a.U, 0x58.U, 0x56.U,
119 | 0x37.U, 0x39.U, 0x2b.U, 0x25.U, 0x0f.U, 0x01.U, 0x13.U, 0x1d.U, 0x47.U, 0x49.U, 0x5b.U, 0x55.U, 0x7f.U, 0x71.U, 0x63.U, 0x6d.U,
120 | 0xd7.U, 0xd9.U, 0xcb.U, 0xc5.U, 0xef.U, 0xe1.U, 0xf3.U, 0xfd.U, 0xa7.U, 0xa9.U, 0xbb.U, 0xb5.U, 0x9f.U, 0x91.U, 0x83.U, 0x8d.U))
121 | */
122 | val tmp_state = Wire(Vec(Params.StateLength, UInt(8.W)))
123 |
124 | tmp_state(0) := mul02(io.state_in(0)) ^ mul03(io.state_in(1)) ^ io.state_in(2) ^ io.state_in(3)
125 | tmp_state(1) := io.state_in(0) ^ mul02(io.state_in(1)) ^ mul03(io.state_in(2)) ^ io.state_in(3)
126 | tmp_state(2) := io.state_in(0) ^ io.state_in(1) ^ mul02(io.state_in(2)) ^ mul03(io.state_in(3))
127 | tmp_state(3) := mul03(io.state_in(0)) ^ io.state_in(1) ^ io.state_in(2) ^ mul02(io.state_in(3))
128 |
129 | tmp_state(4) := mul02(io.state_in(4)) ^ mul03(io.state_in(5)) ^ io.state_in(6) ^ io.state_in(7)
130 | tmp_state(5) := io.state_in(4) ^ mul02(io.state_in(5)) ^ mul03(io.state_in(6)) ^ io.state_in(7)
131 | tmp_state(6) := io.state_in(4) ^ io.state_in(5) ^ mul02(io.state_in(6)) ^ mul03(io.state_in(7))
132 | tmp_state(7) := mul03(io.state_in(4)) ^ io.state_in(5) ^ io.state_in(6) ^ mul02(io.state_in(7))
133 |
134 | tmp_state(8) := mul02(io.state_in(8)) ^ mul03(io.state_in(9)) ^ io.state_in(10) ^ io.state_in(11)
135 | tmp_state(9) := io.state_in(8) ^ mul02(io.state_in(9)) ^ mul03(io.state_in(10)) ^ io.state_in(11)
136 | tmp_state(10) := io.state_in(8) ^ io.state_in(9) ^ mul02(io.state_in(10)) ^ mul03(io.state_in(11))
137 | tmp_state(11) := mul03(io.state_in(8)) ^ io.state_in(9) ^ io.state_in(10) ^ mul02(io.state_in(11))
138 |
139 | tmp_state(12) := mul02(io.state_in(12)) ^ mul03(io.state_in(13)) ^ io.state_in(14) ^ io.state_in(15)
140 | tmp_state(13) := io.state_in(12) ^ mul02(io.state_in(13)) ^ mul03(io.state_in(14)) ^ io.state_in(15)
141 | tmp_state(14) := io.state_in(12) ^ io.state_in(13) ^ mul02(io.state_in(14)) ^ mul03(io.state_in(15))
142 | tmp_state(15) := mul03(io.state_in(12)) ^ io.state_in(13) ^ io.state_in(14) ^ mul02(io.state_in(15))
143 |
144 | if (Pipelined) {
145 | io.state_out := ShiftRegister(tmp_state, 1)
146 | } else {
147 | io.state_out := tmp_state
148 | }
149 | }
150 |
151 | object MixColumns {
152 | def apply(Pipelined: Boolean = false): MixColumns = Module(new MixColumns(Pipelined))
153 | }
--------------------------------------------------------------------------------