diff --git a/README.md b/README.md index a353e5e..56ff9e5 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ Homework 2 - Chisel State Adopting our agile mindset, some of these problems revise components introduced in prior homework assignments. Although we provide a skeleton for testers, you will need to implement them in order to use them. Be sure not to modify external IO interfaces to maintain compatability with the autograder. -# Problem 1 - Improved ComplexALU (50pts) -> Let's enhance our `ComplexALU` from HW1 using `Bundle`s and encapsulation. This problem will consist of multiple parts that build from each other. +# Problem 1 - Improved ComplexALU (15 pts) +> Let's enhance your `ComplexALU` from HW1 by using `Bundle`s and encapsulation. This problem will consist of multiple parts that build from each other. ### Part 1 - ComplexNum > Implement the `ComplexNum` bundle in `src/main/scala/hw2/Complex.scala` by adding two `SInt` fields: `real` and `imag` and four methods with the following signatures: > ```scala @@ -31,12 +31,12 @@ Adopting our agile mindset, some of these problems revise components introduced ### Part 3 - ComplexALU > Implement the `ComplexALU` module in `src/main/scala/hw2/Complex.scala` using only the methods defined in `ComplexNum` to perform arithmetic. It will behave similarly to HW1, except that if the `onlyAdder` parameter is true, the generated hardware will not even include a port for `doAdd`. >> - if `doAdd` is high, sum the real inputs and sum the imaginary inputs ->> - if `doAdd` is low, find difference between the real inputs and the difference between the imaginary inputs +>> - if `doAdd` is low, find the difference between the real inputs and the difference between the imaginary inputs >> - if `onlyAdder` is true, only generate logic to sum the real inputs and sum the imaginary inputs. Since we no longer need `doAdd`, it should be absent from the Verilog. -# Problem 2 - Improved PolyEval (40pts) -> Let's enhance our `PolyEval` from HW1 to support arbitrary polynomials. Implement the `PolyEval` module in `src/main/scala/hw2/PolyEval.scala`. The `coefs` parameter is a list of coefficients ordered by ascending exponent powers. The generated hardware should produce the result combinatorally (within a cycle). +# Problem 2 - Improved PolyEval (15 pts) +> Let's enhance your `PolyEval` from HW1 to support arbitrary polynomials. Implement the `PolyEval` module in `src/main/scala/hw2/PolyEval.scala`. The `coefs` parameter is a list of coefficients ordered by ascending exponent powers. The generated hardware should produce the result combinatorally (within a cycle). > > For example: > ``` @@ -45,11 +45,13 @@ Adopting our agile mindset, some of these problems revise components introduced > out = 4*x^0 + 5*x^1 + 6*x^2 = 4 + 10 + 24 = 38 -# Problem 3 - Sine Wave Generator (40pts) -> Sine waves are useful in DSPs, and in this problem, we will implement a sine wave generator (`SinGen`). Over multiple cycles, the generated hardware will produce the output values for a sine wave. Internally, it will track where it is in the period, and use that to index into a lookup table. The lookup table will hold a single period of the sine wave sampled at `n` points, and those precomputed `sin(x)` values will be stored in a ROM. Use the provided `SineWave` code to populate a ROM in the `SinGen` module located in `src/main/scala/hw2/SineWave.scala`. +# Problem 3 - Sine Wave Generator (30 pts) +> Sine waves are useful in DSPs, and in this problem, you will implement a sine wave generator (`SineWaveGen`). Over multiple cycles, the generated hardware will produce the output values for a sine wave. Internally, it will track where it is in the period, and use that to index into a lookup table. The lookup table will hold a single period of the sine wave sin(x) sampled at `period` points. Thus, due to the periodic nature of a sine wave, a point at _p_ should be the same as a point _p + period_. To assist, we provide `SineWave` (in `src/main/scala/hw2/SineWaveGen.scala`) which represents the sine wave to be turned into a hardware table, and it can also be used as a Scala functional model to get the needed points. -### Part 1 - SinGenIO -> Implement the `SinGenIO` bundle in `src/main/scala/hw2/SineWave.scala` by adding two `Input` fields: +> Since we are working with UInts instead of floating-point, we use the parameter `amplitude` to scale up the result. The generated hardware will take two inputs (`en` and `stride`). Each cycle the module will output the next sample if `en` is high, or keep returning the same sample if `en` is low. The `stride` input determines how many samples to step through the ROM each cycle. Note, that `stride` may not evenly divide the period. + +### Part 1 - SineWaveGenIO +> Implement the `SineWaveGenIO` bundle in `src/main/scala/hw2/SineWaveGen.scala` by adding two `Input` fields: > ```scala > stride: UInt > en: Bool @@ -59,28 +61,27 @@ Adopting our agile mindset, some of these problems revise components introduced > out: SInt > ``` -### Part 2 - SinGen -> Implement the `SinGen` module in `src/main/scala/hw2/SineWave.scala`. Use `SinGenIO` as the module's IO. Each cycle the module will output the next sample if `en` is high, or keep returning the same sample if `en` is low. The `stride` input determines how many samples to step through the ROM each cycle. +### Part 2 - SineWaveGen +> Implement the `SineWaveGen` module in `src/main/scala/hw2/SineWaveGen.scala`, using a `SineWaveGenIO` as the module's IO. >> Example given these parameters: >> ```scala ->> val period = 8 +>> val period = 16 >> val amplitude = 128 ->> val n = 16 >> ``` ->> If `stride` is `1` then `SinGen` will return one value each cycle in this order: +>> If `stride` is `1` then `SineWaveGen` will return one value each cycle in this order: >> ``` >> 0, 48, 90, 118, 128, 118, 90, 48, 0, -48, -90, -118, -128, -118, -90, -48 >> ``` ->> If `stride` is `2` then `SinGen` will return one value each cycle in this order: +>> If `stride` is `2` then `SineWaveGen` will return one value each cycle in this order: >> ``` >> 0, 90, 128, 90, 0, -90, -128, -90 >> ``` -# Problem 4 - XOR Cipher (60pts) -> The XOR operation is the basis of a simple cryptographic encryption algorithm called an [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher). Given a secret `key` and `data` of the same length, we can encrypt `data` by performing `ciphertext = in ^ key`. We can decrypt `ciphertext` by performing `in = ciphertext ^ key`. +# Problem 4 - XOR Cipher (40 pts) +> An [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) is a simple cryptographic encryption technique based on the XOR operation. Given a secret `key` and `data` of the same length, we can encrypt `data` by performing `ciphertext = data ^ key`. We can decrypt `ciphertext` by performing `data = ciphertext ^ key`. -> We will implement a simple XOR cipher. Inside the generated hardware, there will be a register to hold the data (potentially encrypted) and a register to hold the key. We will use a state machine internally to keep track of the status of the system. Upon reset, the system will wait until it is given a secret key to load in. With the secret key stored inside, it is now ready to accept data. When given data, it will encrypt it on the way in. The data can be decrypted, but after a cycle it must be overwritten or zeroed out. +> You will implement a simple XOR cipher. Inside the generated hardware, there will be a register _data_ to hold the data (potentially encrypted) and a register _key_ to hold the key. You will use a state machine internally to keep track of the status of the system. Upon reset, the system will wait until it is given an input secret key to load in. Once the secret key is stored inside _key_, it is now ready to accept input data. When given input data, it will encrypt it on the way in and store it in _data_ as ciphertext. The ciphertext in _data_ can be decrypted, but after a cycle the decrypted data must be overwritten or zeroed out. > > To encode commands, we use the following input signals: > - `clear`: zero out both the _data_ and the secret _key_ @@ -99,14 +100,14 @@ Adopting our agile mindset, some of these problems revise components introduced > out: UInt (output of data register) > full: Bool (data register has valid data) > encrypted: Bool (data register has encrypted data) -> state: UInt (eases testing of FSM) +> state: CipherState (eases testing of FSM) ### Part 2 - XORCipher > Implement the `XORCipher` module in `src/main/scala/hw2/XORCipher.scala` using `XORCipherIO` as the IO. We will build a FSM with four states: -> - `clear`: data and key are both 0 -> - `ready`: secret key is set -> - `encrypted`: data is stored encrypted -> - `decypted`: data is stored decrypted +> - `clear`: _data_ and _key_ are both 0 (initial state) +> - `ready`: secret _key_ is set +> - `encrypted`: _data_ is filled with ciphertext +> - `decypted`: _data_ is filled with decrypted data > The state transitions will follow this diagram: fsm schematic @@ -115,6 +116,6 @@ Adopting our agile mindset, some of these problems revise components introduced > ``` > clear > loadKey > loadAndEncrypt > decrypt > ``` -> For example, any time `clear` is seen, flush the contents and go to the `empty` state`. If none of the transition conditions are satisfied, remain in the present state. +> For example, any time `clear` is seen, flush the contents and go to the `empty` state. If none of the transition conditions are satisfied, remain in the present state. -> You may use the tester (after filling it in) located in `src/test/scala/hw2/XORCipherTestSuite.scala` to drive your development. +> We recommend using the tester (after filling it in) located in `src/test/scala/hw2/XORCipherTestSuite.scala` to drive your development. diff --git a/build.sbt b/build.sbt index 27d54a7..548a465 100644 --- a/build.sbt +++ b/build.sbt @@ -1,32 +1,25 @@ -// See README.md for license details. - -ThisBuild / scalaVersion := "2.13.7" +ThisBuild / scalaVersion := "2.13.14" ThisBuild / version := "0.1.0" ThisBuild / organization := "UCSC-AHD" -val chiselVersion = "3.5.0" -// For running the gradescope tests -libraryDependencies += "org.scalatestplus" %% "junit-4-13" % "3.2.10.0" % "test" +val chiselVersion = "3.6.1" -// This sets it up so all tests that end in "Tester" will be run when you run sbt test -// and all tests that end in "Grader" will run when you run sbt Grader / test -lazy val scalatest = "org.scalatest" %% "scalatest" % "3.2.10" -lazy val Grader = config("grader") extend(Test) -lazy val TestAll = config("testAll") extend(Test) -lazy val Hw2 = config("hw2") extend(Test) -def allFilter(name: String): Boolean = name endsWith "Tester" -def graderFilter(name: String): Boolean = name endsWith "Grader" -def hw2Filter(name: String): Boolean = name endsWith "Testerhw2" +// The following sets it up such that when you run sbt ... +// Grader / test you run all tests that end in "Grader" +// test you run all tests that don't end in "Grader" +lazy val Grader = config("grader") extend(Test) +def endsWithGrader(name: String): Boolean = name endsWith "Grader" +lazy val scalatest = "org.scalatest" %% "scalatest" % "3.2.15" lazy val root = (project in file(".")) -.configs(TestAll).configs(Grader).configs(Hw2) - .settings( - name := "hw2", +.configs(Grader) + .settings( + name := "hw2", libraryDependencies ++= Seq( "edu.berkeley.cs" %% "chisel3" % chiselVersion, - "edu.berkeley.cs" %% "chiseltest" % "0.5.0" % "test" + "edu.berkeley.cs" %% "chiseltest" % "0.6.2" % "test" ), scalacOptions ++= Seq( "-language:reflectiveCalls", @@ -35,18 +28,12 @@ lazy val root = (project in file(".")) "-Xcheckinit", ), addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full), - // from dino - inConfig(Grader)(Defaults.testTasks), - inConfig(TestAll)(Defaults.testTasks), - inConfig(Hw2)(Defaults.testTasks), - libraryDependencies += scalatest % TestAll, - libraryDependencies += scalatest % Grader, - libraryDependencies += scalatest % Hw2, + // For Gradescope tests + libraryDependencies += "org.scalatestplus" %% "junit-4-13" % "3.2.15.0" % "test", - testOptions in TestAll := Seq(Tests.Filter(allFilter)), - // CHANGE THE LINE BELOW FOR EACH LAB!!!! Use the matching filter - testOptions in Test := Seq(Tests.Filter(allFilter)), - testOptions in Grader := Seq(Tests.Filter(graderFilter)), - testOptions in Hw2 := Seq(Tests.Filter(hw2Filter)), + inConfig(Grader)(Defaults.testTasks), + libraryDependencies += scalatest % Grader, + Grader / testOptions := Seq(Tests.Filter(endsWithGrader)), + Test / testOptions := Seq(Tests.Filter(!endsWithGrader(_))), ) diff --git a/fsm.svg b/fsm.svg index 699f1a9..e7b56af 100644 --- a/fsm.svg +++ b/fsm.svg @@ -1,40 +1,40 @@ - + - + - Produced by OmniGraffle 7.19.3\n2022-01-21 20:52:30 +0000 - - hw2 - fsm - + Produced by OmniGraffle 7.22.4\n2024-01-20 03:31:07 +0000 + + hw2 - fsm dark/light + Layer 1 - - - ready + + + ready - - - empty + + + empty - - - encrypted + + + encrypted - - - decrypted + + + decrypted @@ -43,22 +43,22 @@ - + - + - + - + - + - + @@ -76,7 +76,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -100,7 +100,7 @@ - + @@ -112,6 +112,14 @@ ~loadAndEnc + + + + + + clear + + diff --git a/project/build.properties b/project/build.properties index ddffd37..8fd7d2e 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 1.4.9 +sbt.version = 1.9.0 diff --git a/src/main/scala/hw2/Complex.scala b/src/main/scala/hw2/Complex.scala index ece3455..54a68ed 100644 --- a/src/main/scala/hw2/Complex.scala +++ b/src/main/scala/hw2/Complex.scala @@ -1,4 +1,3 @@ -// See README.md for license details. package hw2 import chisel3._ @@ -6,7 +5,7 @@ import chisel3._ // Note ??? will compile but not work at runtime. /** - * @param width: Int + * @param width : Int * ___________________ * @field real: SInt * @field imag: SInt @@ -16,13 +15,13 @@ import chisel3._ * @method def diffImag(that: ComplexNum): SInt */ class ComplexNum(width: Int) extends Bundle { - ??? + ??? } /** - * @param width: Int - * @param onlyAdder: Boolean + * @param width : Int + * @param onlyAdder : Boolean * ___________________ * @field doAdd: Option[Bool] (Input) * @field c0: ComplexNum (Input) @@ -30,16 +29,15 @@ class ComplexNum(width: Int) extends Bundle { * @field out: ComplexNum (Output) */ class ComplexALUIO(width: Int, onlyAdder: Boolean) extends Bundle { - ??? + ??? } /** - * @param width: Int - * @param onlyAdder: Boolean + * @param width : Int + * @param onlyAdder : Boolean */ class ComplexALU(width: Int, onlyAdder: Boolean) extends Module { - val io = IO(new ComplexALUIO(width, onlyAdder)) - ??? + val io = IO(new ComplexALUIO(width, onlyAdder)) + ??? } - diff --git a/src/main/scala/hw2/PolyEval.scala b/src/main/scala/hw2/PolyEval.scala index 769ae8f..1e9030e 100644 --- a/src/main/scala/hw2/PolyEval.scala +++ b/src/main/scala/hw2/PolyEval.scala @@ -5,14 +5,14 @@ import chisel3._ /** * - * @param coefs: in ascending exponent order -> Seq(1, 2, 3) == 1 + 2x + 3x^2 - * @param width: the width of x + * @param coefs : in ascending exponent order -> Seq(1, 2, 3) == 1 + 2x + 3x^2 + * @param width : the width of x */ class PolyEval(coefs: Seq[Int], width: Int) extends Module { - val io = IO(new Bundle { - val x = Input(UInt(width.W)) - val out = Output(UInt()) - }) - - ??? + val io = IO(new Bundle { + val x = Input(UInt(width.W)) + val out = Output(UInt()) + }) + + ??? } diff --git a/src/main/scala/hw2/SineWave.scala b/src/main/scala/hw2/SineWave.scala deleted file mode 100644 index da5267c..0000000 --- a/src/main/scala/hw2/SineWave.scala +++ /dev/null @@ -1,43 +0,0 @@ -package hw2 - -import chisel3._ -import chisel3.util.log2Ceil - - -class SineWave(val period: Int, val amplitude: Int) { - require(period > 0) - val B: Double = (2.0 * math.Pi) / period.toDouble - - def apply(x: Double): Int = { - (amplitude.toDouble * math.sin(B * x)).toInt - } - - def sample(n: Int): Seq[Int] = { - val sampleInterval = period.toDouble / n.toDouble - (0 until n).map(x => apply(x * sampleInterval)) - } -} - - -/** - * - * @param s: SineWave - * @param n: The total number of points sampled -> ROM - * ________________________________ - * @field stride: UInt (Input) - * @field en: Bool (Input) - * @field out: SInt (Output) - */ -class SinGenIO (s: SineWave, n: Int) extends Bundle { - ??? -} - - -/** - * - * @param s: SineWave - * @param n: The total number of points sampled -> ROM - */ -class SinGen(s: SineWave, n: Int) extends Module { - val io = ??? -} diff --git a/src/main/scala/hw2/SineWaveGen.scala b/src/main/scala/hw2/SineWaveGen.scala new file mode 100644 index 0000000..a866f1a --- /dev/null +++ b/src/main/scala/hw2/SineWaveGen.scala @@ -0,0 +1,34 @@ +package hw2 + +import chisel3._ +import chisel3.util.log2Ceil + + +class SineWave(val period: Int, val amplitude: Int) { + require(period > 0) + val B: Double = (2.0 * math.Pi) / period.toDouble + + def apply(index: Int): Int = (amplitude.toDouble * math.sin(B * index)).toInt +} + + +/** + * + * @param s : SineWave (internally contains period & amplitude) + * ________________________________ + * @field stride: UInt (Input) + * @field en: Bool (Input) + * @field out: SInt (Output) + */ +class SineWaveGenIO (sw: SineWave) extends Bundle { + ??? +} + + +/** + * + * @param s : SineWave (internally contains period) + */ +class SineWaveGen(sw: SineWave) extends Module { + val io = ??? +} diff --git a/src/main/scala/hw2/XORCipher.scala b/src/main/scala/hw2/XORCipher.scala index 95302a3..8529d20 100644 --- a/src/main/scala/hw2/XORCipher.scala +++ b/src/main/scala/hw2/XORCipher.scala @@ -4,31 +4,29 @@ import chisel3._ import chisel3.util._ +object CipherState extends ChiselEnum { + val empty, ready, encrypted, decrypted = Value +} + class XORCipherCmds extends Bundle { - val clear = Input(Bool()) - val loadKey = Input(Bool()) - val loadAndEnc = Input(Bool()) - val decrypt = Input(Bool()) + val clear = Input(Bool()) + val loadKey = Input(Bool()) + val loadAndEnc = Input(Bool()) + val decrypt = Input(Bool()) } /** - * @param width: Int + * @param width : Int * @field in: UInt (Input) - payload or key * @field cmds: XORCipherCmds (Input) * @field out: UInt (Output) * @field full: Bool (Output) * @field encrypted: Bool (Output) - * @field state: UInt (Output) - visible for testing + * @field state: CipherState (Output) - visible for testing */ class XORCipherIO(width: Int) extends Bundle { - ??? -} - - -object XORCipher { - // States - val empty :: ready :: encrypted :: decrypted :: Nil = Enum(4) + ??? } @@ -36,10 +34,7 @@ object XORCipher { * @param width Int */ class XORCipher(width: Int) extends Module { - val io = IO(new XORCipherIO(width)) - - // import state names into namespace - import XORCipher._ - - ??? + val io = IO(new XORCipherIO(width)) + + ??? } diff --git a/src/test/scala/hw2/ComplexALUTester.scala b/src/test/scala/hw2/ComplexALUTester.scala index ad164d9..80ddc19 100644 --- a/src/test/scala/hw2/ComplexALUTester.scala +++ b/src/test/scala/hw2/ComplexALUTester.scala @@ -1,5 +1,3 @@ -// See README.md for license details. - package hw2 import chisel3._ @@ -7,28 +5,28 @@ import chiseltest._ import org.scalatest.flatspec.AnyFlatSpec class ComplexALUTester extends AnyFlatSpec with ChiselScalatestTester { - behavior of "ComplexALU" - it should "correctly calculate realOut onlyAdd=true" in { - test(new ComplexALU(width = 5, onlyAdder = true)) { dut => - ??? - } + behavior of "ComplexALU" + it should "correctly calculate realOut onlyAdd=true" in { + test(new ComplexALU(width = 5, onlyAdder = true)) { dut => + ??? } + } - it should "correctly calculate realOut onlyAdd=false" in { - test(new ComplexALU(width=5, onlyAdder=false)) { dut => - ??? - } + it should "correctly calculate realOut onlyAdd=false" in { + test(new ComplexALU(width=5, onlyAdder=false)) { dut => + ??? } + } - it should "correctly calculate imagOut onlyAdd=true" in { - test(new ComplexALU(width=5, onlyAdder=true)) { dut => - ??? - } + it should "correctly calculate imagOut onlyAdd=true" in { + test(new ComplexALU(width=5, onlyAdder=true)) { dut => + ??? } + } - it should "correctly calculate imagOut onlyAdd=false" in { - test(new ComplexALU(width=5, onlyAdder=false)) { dut => - ??? - } + it should "correctly calculate imagOut onlyAdd=false" in { + test(new ComplexALU(width=5, onlyAdder=false)) { dut => + ??? } + } } diff --git a/src/test/scala/hw2/PolyEvalTester.scala b/src/test/scala/hw2/PolyEvalTester.scala index b107b1b..af6aefa 100644 --- a/src/test/scala/hw2/PolyEvalTester.scala +++ b/src/test/scala/hw2/PolyEvalTester.scala @@ -1,34 +1,32 @@ package hw2 -// See README.md for license details. - import chisel3._ import chiseltest._ import org.scalatest.flatspec.AnyFlatSpec class PolyEvalTester extends AnyFlatSpec with ChiselScalatestTester { - val width = ??? - def testPolyEvalOut(n: Int): Unit = { - val coefs = ??? - test(new PolyEval(coefs, width)) { dut => - ??? - } + val width = ??? + def testPolyEvalOut(n: Int): Unit = { + val coefs = ??? + test(new PolyEval(coefs, width)) { dut => + ??? } + } - behavior of "PolyEval" - it should "correctly calculate output for deg(2) poly" in { - testPolyEvalOut(3) - } + behavior of "PolyEval" + it should "correctly calculate output for deg(2) poly" in { + testPolyEvalOut(3) + } - it should "correctly calculate output for deg(3) poly" in { - testPolyEvalOut(4) - } + it should "correctly calculate output for deg(3) poly" in { + testPolyEvalOut(4) + } - it should "correctly calculate output for deg(4) poly" in { - testPolyEvalOut(5) - } + it should "correctly calculate output for deg(4) poly" in { + testPolyEvalOut(5) + } - it should "correctly calculate output for deg(5) poly" in { - testPolyEvalOut(6) - } + it should "correctly calculate output for deg(5) poly" in { + testPolyEvalOut(6) + } } diff --git a/src/test/scala/hw2/SinGenTester.scala b/src/test/scala/hw2/SinGenTester.scala deleted file mode 100644 index 8f1eeac..0000000 --- a/src/test/scala/hw2/SinGenTester.scala +++ /dev/null @@ -1,29 +0,0 @@ -package hw2 - -import chisel3._ -import chisel3.tester._ -import chisel3.tester.RawTester.test -import chisel3.experimental.BundleLiterals._ - -object SinGenBehavior { - def testSinGenStride(stride: Int): Unit = { - val s = ??? - val n = ??? - test(new SinGen(s, n)) { dut => - ??? - } - } - - behavior of "SinGen" - it should "correctly calculate output for stride=1" in { - testSinGenStride(1) - } - - it should "correctly calculate output for stride=2" in { - testSinGenStride(2) - } - - it should "correctly calculate output for stride=4" in { - testSinGenStride(4) - } -} diff --git a/src/test/scala/hw2/SineWaveGenTester.scala b/src/test/scala/hw2/SineWaveGenTester.scala new file mode 100644 index 0000000..2ed9199 --- /dev/null +++ b/src/test/scala/hw2/SineWaveGenTester.scala @@ -0,0 +1,35 @@ +package hw2 + +import chisel3._ +import chiseltest._ +import org.scalatest.flatspec.AnyFlatSpec + +class SineWaveGenTester extends AnyFlatSpec with ChiselScalatestTester { + def testSineWaveGen(sw: SineWave, stride: Int): Unit = { + ??? + test(new SineWaveGen(sw)) { dut => + ??? + } + } + + behavior of "SineWaveGen" + it should "correctly calculate output for period=16 stride=1" in { + testSineWaveGen(new SineWave(16, 128), 1) + } + + it should "correctly calculate output for period=16 stride=2" in { + testSineWaveGen(new SineWave(16, 128), 2) + } + + it should "correctly calculate output for period=16 stride=3" in { + testSineWaveGen(new SineWave(16, 128), 3) + } + + it should "correctly calculate output for period=10 stride=1" in { + testSineWaveGen(new SineWave(10, 128), 1) + } + + it should "correctly calculate output for period=10 stride=3" in { + testSineWaveGen(new SineWave(10, 128), 3) + } +} diff --git a/src/test/scala/hw2/XORCipherTester.scala b/src/test/scala/hw2/XORCipherTester.scala index d33166d..59eca94 100644 --- a/src/test/scala/hw2/XORCipherTester.scala +++ b/src/test/scala/hw2/XORCipherTester.scala @@ -5,28 +5,28 @@ import chiseltest._ import org.scalatest.flatspec.AnyFlatSpec class XORCipherTester extends AnyFlatSpec with ChiselScalatestTester { - val key = ??? - val data = ??? - val width = ??? + val key = ??? + val data = ??? + val width = ??? - behavior of "XORCipher" - it should "go through common case (empty -> ready -> encrypted -> decrypted -> empty" in { - test(new XORCipher(width)).withAnnotations(Seq(WriteVcdAnnotation)) { dut => - // empty -> ready - dut.io.state.expect(XORCipher.empty) - dut.io.in.poke(key.U) - dut.io.cmds.clear.poke(false.B) - dut.io.cmds.loadKey.poke(true.B) - dut.io.cmds.loadAndEnc.poke(false.B) - dut.io.cmds.decrypt.poke(false.B) - dut.io.out.expect(0.U) - dut.io.full.expect(false.B) - dut.io.encrypted.expect(false.B) - dut.clock.step() - - ??? - } + behavior of "XORCipher" + it should "go through common case (empty -> ready -> encrypted -> decrypted -> empty" in { + test(new XORCipher(width)).withAnnotations(Seq(WriteVcdAnnotation)) { dut => + // empty -> ready + dut.io.state.expect(CipherState.empty) + dut.io.in.poke(key.U) + dut.io.cmds.clear.poke(false.B) + dut.io.cmds.loadKey.poke(true.B) + dut.io.cmds.loadAndEnc.poke(false.B) + dut.io.cmds.decrypt.poke(false.B) + dut.io.out.expect(0.U) + dut.io.full.expect(false.B) + dut.io.encrypted.expect(false.B) + dut.clock.step() + + ??? } - - // You will want to create additional tests to cover the other FSM arcs + } + + // You will want to create additional tests to cover the other FSM arcs }