├── 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 | 10 | 11 | 12 | 13 | 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 | 10 | 11 | 12 | 13 | 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 | } --------------------------------------------------------------------------------