val path = System.getProperty("user.dir") + "/source/load-ivy.sc" interp.load.module(ammonite.ops.Path(java.nio.file.FileSystems.getDefault().getPath(path))) import chisel3._ import chisel3.util._ import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester} import chisel3.experimental._ abstract class MyAbstractClass { def myFunction(i: Int): Int val myValue: String } class ConcreteClass extends MyAbstractClass { def myFunction(i: Int): Int = i + 1 val myValue = "Hello World!" } // Uncomment below to test! // val abstractClass = new MyAbstractClass() // Illegal! Cannot instantiate an abstract class val concreteClass = new ConcreteClass() // Legal! trait HasFunction { def myFunction(i: Int): Int } trait HasValue { val myValue: String val myOtherValue = 100 } class MyClass extends HasFunction with HasValue { override def myFunction(i: Int): Int = i + 1 val myValue = "Hello World!" } // Uncomment below to test! // val myTraitFunction = new HasFunction() // Illegal! Cannot instantiate a trait // val myTraitValue = new HasValue() // Illegal! Cannot instantiate a trait val myClass = new MyClass() // Legal! object MyObject { def hi: String = "Hello World!" def apply(msg: String) = msg } println(MyObject.hi) println(MyObject("This message is important!")) // equivalent to MyObject.apply(msg) object Lion { def roar(): Unit = println("I'M AN OBJECT!") } class Lion { def roar(): Unit = println("I'M A CLASS!") } new Lion().roar() Lion.roar() object Animal { val defaultName = "Bigfoot" private var numberOfAnimals = 0 def apply(name: String): Animal = { numberOfAnimals += 1 new Animal(name, numberOfAnimals) } def apply(): Animal = apply(defaultName) } class Animal(name: String, order: Int) { def info: String = s"Hi my name is $name, and I'm $order in line!" } val bunny = Animal.apply("Hopper") // Calls the Animal factory method println(bunny.info) val cat = Animal("Whiskers") // Calls the Animal factory method println(cat.info) val yeti = Animal() // Calls the Animal factory method println(yeti.info) class Nail(length: Int) // Regular class val nail = new Nail(10) // Requires the `new` keyword // println(nail.length) // Illegal! Class constructor parameters are not by default externally visible class Screw(val threadSpace: Int) // By using the `val` keyword, threadSpace is now externally visible val screw = new Screw(2) // Requires the `new` keyword println(screw.threadSpace) case class Staple(isClosed: Boolean) // Case class constructor parameters are, by default, externally visible val staple = Staple(false) // No `new` keyword required println(staple.isClosed) case class SomeGeneratorParameters( someWidth: Int, someOtherWidth: Int = 10, pipelineMe: Boolean = false ) { require(someWidth >= 0) require(someOtherWidth >= 0) val totalWidth = someWidth + someOtherWidth } class NoGlitchCounterIO(bitwidth: Int) extends Bundle { val en = Input(Bool()) val out = Output(UInt(bitwidth.W)) } abstract class NoGlitchCounter(val maxCount: Int) extends Module { val bitwidth: Int val io = IO(new NoGlitchCounterIO(bitwidth)) } abstract class AsyncFIFO(depth: Int) extends Module { val io = IO(new Bundle{ // write inputs val write_clock = Input(Clock()) val write_enable = Input(Bool()) val write_data = Input(UInt(32.W)) // read inputs/outputs val read_clock = Input(Clock()) val read_enable = Input(Bool()) val read_data = Output(UInt(32.W)) // FIFO status val full = Output(Bool()) val empty = Output(Bool()) }) def makeCounter(maxCount: Int): NoGlitchCounter // add extra bit to counter to check for fully/empty status assert(isPow2(depth), "AsyncFIFO needs a power-of-two depth!") val write_counter = withClock(io.write_clock) { val count = makeCounter(depth * 2) count.io.en := io.write_enable && !io.full count.io.out } val read_counter = withClock(io.read_clock) { val count = makeCounter(depth * 2) count.io.en := io.read_enable && !io.empty count.io.out } // synchronize val sync = withClock(io.read_clock) { ShiftRegister(write_counter, 2) } // status logic goes here } class GrayCounter(val bitwidth: Int) extends NoGlitchCounter(bitwidth) { // todo } class RingCounter(maxCount: Int) extends NoGlitchCounter(maxCount) { // todo } import scala.math.pow // create a module class GrayCoder(bitwidth: Int) extends Module { val io = IO(new Bundle{ val in = Input(UInt(bitwidth.W)) val out = Output(UInt(bitwidth.W)) val encode = Input(Bool()) // decode on false }) when (io.encode) { //encode io.out := io.in ^ (io.in >> 1.U) } .otherwise { // decode, much more complicated io.out := Seq.fill(log2Ceil(bitwidth))(Wire(UInt(bitwidth.W))).zipWithIndex.fold((io.in, 0)){ case ((w1: UInt, i1: Int), (w2: UInt, i2: Int)) => { w2 := w1 ^ (w1 >> pow(2, log2Ceil(bitwidth)-i2-1).toInt.U) (w2, i1) } }._1 } } // test our gray coder val bitwidth = 4 Driver(() => new GrayCoder(bitwidth)) { c => new PeekPokeTester(c) { def toBinary(i: Int, digits: Int = 8) = String.format("%" + digits + "s", i.toBinaryString).replace(' ', '0') println("Encoding:") for (i <- 0 until pow(2, bitwidth).toInt) { poke(c.io.in, i) poke(c.io.encode, true) step(1) println(s"In = ${toBinary(i, bitwidth)}, Out = ${toBinary(peek(c.io.out).toInt, bitwidth)}") } println("Decoding:") for (i <- 0 until pow(2, bitwidth).toInt) { poke(c.io.in, i) poke(c.io.encode, false) step(1) println(s"In = ${toBinary(i, bitwidth)}, Out = ${toBinary(peek(c.io.out).toInt, bitwidth)}") } } } class AsyncFIFO(depth: Int = 16) extends Module { val io = IO(new Bundle{ // write inputs val write_clock = Input(Clock()) val write_enable = Input(Bool()) val write_data = Input(UInt(32.W)) // read inputs/outputs val read_clock = Input(Clock()) val read_enable = Input(Bool()) val read_data = Output(UInt(32.W)) // FIFO status val full = Output(Bool()) val empty = Output(Bool()) }) // add extra bit to counter to check for fully/empty status assert(isPow2(depth), "AsyncFIFO needs a power-of-two depth!") val write_counter = withClock(io.write_clock) { Counter(io.write_enable && !io.full, depth*2)._1 } val read_counter = withClock(io.read_clock) { Counter(io.read_enable && !io.empty, depth*2)._1 } // encode val encoder = new GrayCoder(write_counter.getWidth) encoder.io.in := write_counter encoder.io.encode := true.B // synchronize val sync = withClock(io.read_clock) { ShiftRegister(encoder.io.out, 2) } // decode val decoder = new GrayCoder(read_counter.getWidth) decoder.io.in := sync decoder.io.encode := false.B // status logic goes here }