Download chisel/src/test/NandTest.scala from Snapkitty/phaser-ags: direct link, hf CLI and curl.
- Browser
- Download file 8.87 kB
-
https://huggingface.co/Snapkitty/phaser-ags/resolve/main/chisel/src/test/NandTest.scala
- Command line
-
hf download hf://Snapkitty/phaser-ags/chisel/src/test/NandTest.scala
-
curl -L -o NandTest.scala https://huggingface.co/Snapkitty/phaser-ags/resolve/main/chisel/src/test/NandTest.scala
8.87 kB
| package nand | |
| import chisel3._ | |
| import chiseltest._ | |
| import org.scalatest.flatspec.AnyFlatSpec | |
| import org.scalatest.matchers.should.Matchers | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // TEST HARNESSES β ChiselTest verification for all NAND-derived | |
| // modules. Truth tables match SPICE circuit simulation results. | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class Nand2Test extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "Nand2" | |
| it should "match NAND truth table" in { | |
| test(new Nand2) { dut => | |
| for (a <- Seq(false, true); b <- Seq(false, true)) { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect(!(a && b).B) | |
| } | |
| } | |
| } | |
| } | |
| class Nand3Test extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "Nand3" | |
| it should "match 3-input NAND truth table" in { | |
| test(new Nand3) { dut => | |
| for { | |
| a <- Seq(false, true) | |
| b <- Seq(false, true) | |
| c <- Seq(false, true) | |
| } { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.io.c.poke(c.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect(!(a && b && c).B) | |
| } | |
| } | |
| } | |
| } | |
| class InvFromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "InvFromNand" | |
| it should "invert" in { | |
| test(new InvFromNand) { dut => | |
| dut.io.a.poke(false.B); dut.clock.step(1); dut.io.y.expect(true.B) | |
| dut.io.a.poke(true.B); dut.clock.step(1); dut.io.y.expect(false.B) | |
| } | |
| } | |
| } | |
| class And2FromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "And2FromNand" | |
| it should "match AND truth table" in { | |
| test(new And2FromNand) { dut => | |
| for (a <- Seq(false, true); b <- Seq(false, true)) { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect((a && b).B) | |
| } | |
| } | |
| } | |
| } | |
| class Or2FromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "Or2FromNand" | |
| it should "match OR truth table" in { | |
| test(new Or2FromNand) { dut => | |
| for (a <- Seq(false, true); b <- Seq(false, true)) { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect((a || b).B) | |
| } | |
| } | |
| } | |
| } | |
| class Xor2FromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "Xor2FromNand" | |
| it should "match XOR truth table" in { | |
| test(new Xor2FromNand) { dut => | |
| for (a <- Seq(false, true); b <- Seq(false, true)) { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect((a ^ b).B) | |
| } | |
| } | |
| } | |
| } | |
| class Xnor2FromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "Xnor2FromNand" | |
| it should "match XNOR truth table" in { | |
| test(new Xnor2FromNand) { dut => | |
| for (a <- Seq(false, true); b <- Seq(false, true)) { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect(!(a ^ b).B) | |
| } | |
| } | |
| } | |
| } | |
| class Mux2FromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "Mux2FromNand" | |
| it should "select a when sel=0, b when sel=1" in { | |
| test(new Mux2FromNand) { dut => | |
| for (sel <- Seq(false, true)) { | |
| for (a <- Seq(false, true); b <- Seq(false, true)) { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.io.sel.poke(sel.B) | |
| dut.clock.step(1) | |
| dut.io.y.expect((if (sel) b else a).B) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // βββ Sequential tests βββββββββββββββββββββββββββββββββββββββββββββ | |
| class SrLatchFromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "SrLatchFromNand" | |
| it should "SET, HOLD, RESET correctly" in { | |
| test(new SrLatchFromNand) { dut => | |
| // Initial: hold (both inactive-high) | |
| dut.io.s_n.poke(true.B) | |
| dut.io.r_n.poke(true.B) | |
| dut.clock.step(1) | |
| // SET: S'=0 | |
| dut.io.s_n.poke(false.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(true.B) | |
| dut.io.qbar.expect(false.B) | |
| // HOLD | |
| dut.io.s_n.poke(true.B) | |
| dut.io.r_n.poke(true.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(true.B) | |
| // RESET: R'=0 | |
| dut.io.r_n.poke(false.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(false.B) | |
| dut.io.qbar.expect(true.B) | |
| // HOLD after reset | |
| dut.io.r_n.poke(true.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(false.B) | |
| } | |
| } | |
| } | |
| class DFlipFlopFromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "DFlipFlopFromNand" | |
| it should "capture D on rising clock edge" in { | |
| test(new DFlipFlopFromNand) { dut => | |
| // Set D=1, clock low β nothing captured | |
| dut.io.d.poke(true.B) | |
| dut.io.clk.poke(false.B) | |
| dut.clock.step(2) | |
| // Rising edge β capture D=1 | |
| dut.io.clk.poke(true.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(true.B) | |
| // Change D while clock high β Q holds | |
| dut.io.d.poke(false.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(true.B) | |
| // Falling edge β Q still holds | |
| dut.io.clk.poke(false.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(true.B) | |
| // Next rising edge with D=0 β capture 0 | |
| dut.io.clk.poke(true.B) | |
| dut.clock.step(2) | |
| dut.io.q.expect(false.B) | |
| } | |
| } | |
| } | |
| // βββ Arithmetic tests βββββββββββββββββββββββββββββββββββββββββββββ | |
| class HalfAdderFromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "HalfAdderFromNand" | |
| it should "match half-adder truth table" in { | |
| test(new HalfAdderFromNand) { dut => | |
| Map( | |
| (false, false) -> (false, false), | |
| (false, true) -> (true, false), | |
| (true, false) -> (true, false), | |
| (true, true) -> (false, true), | |
| ).foreach { case ((a, b), (sum, cout)) => | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.clock.step(1) | |
| dut.io.sum.expect(sum.B) | |
| dut.io.cout.expect(cout.B) | |
| } | |
| } | |
| } | |
| } | |
| class FullAdderFromNandTest extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "FullAdderFromNand" | |
| it should "match full-adder truth table" in { | |
| test(new FullAdderFromNand) { dut => | |
| for { | |
| a <- Seq(false, true) | |
| b <- Seq(false, true) | |
| cin <- Seq(false, true) | |
| } { | |
| dut.io.a.poke(a.B) | |
| dut.io.b.poke(b.B) | |
| dut.io.cin.poke(cin.B) | |
| dut.clock.step(1) | |
| val total = (if (a) 1 else 0) + (if (b) 1 else 0) + (if (cin) 1 else 0) | |
| dut.io.sum.expect((total % 2 == 1).B) | |
| dut.io.cout.expect((total >= 2).B) | |
| } | |
| } | |
| } | |
| } | |
| class RippleCarryAdder8Test extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "RippleCarryAdder8" | |
| it should "add correctly for various operand pairs" in { | |
| test(new RippleCarryAdder(8)) { dut => | |
| val testCases = Seq( | |
| (0, 0, 0), | |
| (1, 1, 0), | |
| (42, 73, 0), | |
| (127, 128 % 256, 0), | |
| (200, 55, 0), | |
| (255, 1, 0), | |
| (255, 255, 0), | |
| (255, 255, 1), | |
| ) | |
| for ((a, b, cin) <- testCases) { | |
| dut.io.a.poke(a.U) | |
| dut.io.b.poke(b.U) | |
| dut.io.cin.poke((cin == 1).B) | |
| dut.clock.step(1) | |
| val expected = (a + b + cin) % 256 | |
| val carryOut = (a + b + cin) >= 256 | |
| dut.io.sum.expect(expected.U) | |
| dut.io.cout.expect(carryOut.B) | |
| } | |
| } | |
| } | |
| } | |
| class AluFromNand8Test extends AnyFlatSpec with ChiselScalatestTester with Matchers { | |
| behavior of "AluFromNand8" | |
| it should "perform AND, OR, XOR, ADD correctly" in { | |
| test(new AluFromNand(8)) { dut => | |
| // AND: op=00 | |
| dut.io.op.poke(0.U) | |
| dut.io.a.poke(0xFF.U); dut.io.b.poke(0x55.U) | |
| dut.clock.step(1) | |
| dut.io.y.expect(0x55.U) | |
| // OR: op=01 | |
| dut.io.op.poke(1.U) | |
| dut.io.a.poke(0x0F.U); dut.io.b.poke(0xF0.U) | |
| dut.clock.step(1) | |
| dut.io.y.expect(0xFF.U) | |
| // XOR: op=10 | |
| dut.io.op.poke(2.U) | |
| dut.io.a.poke(0xFF.U); dut.io.b.poke(0x55.U) | |
| dut.clock.step(1) | |
| dut.io.y.expect(0xAA.U) | |
| // ADD: op=11 | |
| dut.io.op.poke(3.U) | |
| dut.io.cin.poke(false.B) | |
| dut.io.a.poke(42.U); dut.io.b.poke(73.U) | |
| dut.clock.step(1) | |
| dut.io.y.expect(115.U) | |
| } | |
| } | |
| } | |