chisel tutorial examples

GCD

// See LICENSE.txt for license details.
package examples

import chisel3._

/**
 * Compute the GCD of 'a' and 'b' using Euclid's algorithm.
 * To start a computation, load the values into 'a' and 'b' and toggle 'load'
 * high.
 * The GCD will be returned in 'out' when 'valid' is high.
 */
class GCD extends Module {
  val io = IO(new Bundle {
    val a     = Input(UInt(16.W))
    val b     = Input(UInt(16.W))
    val load  = Input(Bool())
    val out   = Output(UInt(16.W))
    val valid = Output(Bool())
  })
  val x = Reg(UInt())
  val y = Reg(UInt())

  when (io.load) {
    x := io.a; y := io.b
  } .otherwise {
    when (x > y) {
      x := x - y
    } .elsewhen (x <= y) {
      y := y - x
    }
  }

  io.out := x
  io.valid := y === 0.U
}


fulladder

// See LICENSE.txt for license details.
package examples

import chisel3._

class FullAdder extends Module {
  val io = IO(new Bundle {
    val a    = Input(UInt(1.W))
    val b    = Input(UInt(1.W))
    val cin  = Input(UInt(1.W))
    val sum  = Output(UInt(1.W))
    val cout = Output(UInt(1.W))
  })

  // Generate the sum
  val a_xor_b = io.a ^ io.b
  io.sum := a_xor_b ^ io.cin
  // Generate the carry
  val a_and_b = io.a & io.b
  val b_and_cin = io.b & io.cin
  val a_and_cin = io.a & io.cin
  io.cout := a_and_b | b_and_cin | a_and_cin
}

chisel tutorial examples_第1张图片

adder4

// See LICENSE.txt for license details.
package examples

import chisel3._
import chisel3.util._

//A 4-bit adder with carry in and carry out
class Adder4 extends Module {
  val io = IO(new Bundle {
    val A    = Input(UInt(4.W))
    val B    = Input(UInt(4.W))
    val Cin  = Input(UInt(1.W))
    val Sum  = Output(UInt(4.W))
    val Cout = Output(UInt(1.W))
  })
  //Adder for bit 0
  val Adder0 = Module(new FullAdder())
  Adder0.io.a := io.A(0)
  Adder0.io.b := io.B(0)
  Adder0.io.cin := io.Cin
  val s0 = Adder0.io.sum
  //Adder for bit 1
  val Adder1 = Module(new FullAdder())
  Adder1.io.a := io.A(1)
  Adder1.io.b := io.B(1)
  Adder1.io.cin := Adder0.io.cout
  val s1 = Cat(Adder1.io.sum, s0)
  //Adder for bit 2
  val Adder2 = Module(new FullAdder())
  Adder2.io.a := io.A(2)
  Adder2.io.b := io.B(2)
  Adder2.io.cin := Adder1.io.cout
  val s2 = Cat(Adder2.io.sum, s1)
  //Adder for bit 3
  val Adder3 = Module(new FullAdder())
  Adder3.io.a := io.A(3)
  Adder3.io.b := io.B(3)
  Adder3.io.cin := Adder2.io.cout
  io.Sum := Cat(Adder3.io.sum, s2).asUInt
  io.Cout := Adder3.io.cout
}

adder

// See LICENSE.txt for license details.
package examples

import chisel3._

//A n-bit adder with carry in and carry out
class Adder(val n:Int) extends Module {
  val io = IO(new Bundle {
    val A    = Input(UInt(n.W))
    val B    = Input(UInt(n.W))
    val Cin  = Input(UInt(1.W))
    val Sum  = Output(UInt(n.W))
    val Cout = Output(UInt(1.W))
  })
  //create an Array of FullAdders
  //  NOTE: Since we do all the wiring during elaboration and not at run-time,
  //  i.e., we don't need to dynamically index into the data structure at run-time,
  //  we use an Array instead of a Vec.
  val FAs   = Array.fill(n)(Module(new FullAdder()).io)
  val carry = Wire(Vec(n+1, UInt(1.W)))
  val sum   = Wire(Vec(n, Bool()))

  //first carry is the top level carry in
  carry(0) := io.Cin

  //wire up the ports of the full adders
  for (i <- 0 until n) {
    FAs(i).a := io.A(i)
    FAs(i).b := io.B(i)
    FAs(i).cin := carry(i)
    carry(i+1) := FAs(i).cout
    sum(i) := FAs(i).sum.asBool
  }
  io.Sum := sum.asUInt
  io.Cout := carry(n)
}

shiftreg

// See LICENSE.txt for license details.
package examples

import chisel3._

class ShiftRegister extends Module {
  val io = IO(new Bundle {
    val in  = Input(UInt(1.W))
    val out = Output(UInt(1.W))
  })
  val r0 = RegNext(io.in)
  val r1 = RegNext(r0)
  val r2 = RegNext(r1)
  val r3 = RegNext(r2)
  io.out := r3
}


/
// See LICENSE.txt for license details.
package examples

import chisel3._

class EnableShiftRegister extends Module {
  val io = IO(new Bundle {
    val in    = Input(UInt(4.W))
    val shift = Input(Bool())
    val out   = Output(UInt(4.W))
  })
  val r0 = Reg(UInt())
  val r1 = Reg(UInt())
  val r2 = Reg(UInt())
  val r3 = Reg(UInt())
  when(reset.asBool) {
    r0 := 0.U(4.W)
    r1 := 0.U(4.W)
    r2 := 0.U(4.W)
    r3 := 0.U(4.W)
  } .elsewhen(io.shift) {
    r0 := io.in
    r1 := r0
    r2 := r1
    r3 := r2
  }
  io.out := r3
}

//
// See LICENSE.txt for license details.
package examples

import chisel3._

class ResetShiftRegister extends Module {
  val io = IO(new Bundle {
    val in    = Input(UInt(4.W))
    val shift = Input(Bool())
    val out   = Output(UInt(4.W))
  })
  // Register reset to zero
  val r0 = RegInit(0.U(4.W))
  val r1 = RegInit(0.U(4.W))
  val r2 = RegInit(0.U(4.W))
  val r3 = RegInit(0.U(4.W))
  when (io.shift) {
    r0 := io.in
    r1 := r0
    r2 := r1
    r3 := r2
  }
  io.out := r3
}


chisel tutorial examples_第2张图片
chisel tutorial examples_第3张图片

ByteSelector

// See LICENSE.txt for license details.
package examples

import chisel3._

class ByteSelector extends Module {
  val io = IO(new Bundle {
    val in     = Input(UInt(32.W))
    val offset = Input(UInt(2.W))
    val out    = Output(UInt(8.W))
  })
  io.out := 0.U(8.W)
  when (io.offset === 0.U(2.W)) {
    io.out := io.in(7,0)
  } .elsewhen (io.offset === 1.U) {
    io.out := io.in(15,8)
  } .elsewhen (io.offset === 2.U) {
    io.out := io.in(23,16)
  } .otherwise {
    io.out := io.in(31,24)
  }
}

HiLoMultiplier

// See LICENSE.txt for license details.
package examples

import chisel3._

//A 16*16-bit multiplier with separate high and low product outputs
class HiLoMultiplier() extends Module {
  val io = IO(new Bundle {
    val A  = Input(UInt(16.W))
    val B  = Input(UInt(16.W))
    val Hi = Output(UInt(16.W))
    val Lo = Output(UInt(16.W))
  })
  val mult = io.A * io.B
  io.Lo := mult(15, 0)
  io.Hi := mult(31, 16)
}

Stack

// See LICENSE.txt for license details.
package examples

import chisel3._
import chisel3.util.log2Ceil

class Stack(val depth: Int) extends Module {
  val io = IO(new Bundle {
    val push    = Input(Bool())
    val pop     = Input(Bool())
    val en      = Input(Bool())
    val dataIn  = Input(UInt(32.W))
    val dataOut = Output(UInt(32.W))
  })

  val stack_mem = Mem(depth, UInt(32.W))
  val sp        = RegInit(0.U(log2Ceil(depth+1).W))
  val out       = RegInit(0.U(32.W))

  when (io.en) {
    when(io.push && (sp < depth.asUInt)) {
      stack_mem(sp) := io.dataIn
      sp := sp + 1.U
    } .elsewhen(io.pop && (sp > 0.U)) {
      sp := sp - 1.U
    }
    when (sp > 0.U) {
      out := stack_mem(sp - 1.U)
    }
  }

  io.dataOut := out
}

LogShifter

// See LICENSE.txt for license details.
package examples

import chisel3._

class LogShifter extends Module {
  val io = IO(new Bundle {
    val in    = Input(UInt(16.W))
    val shamt = Input(UInt(4.W))
    val out   = Output(UInt(16.W))
  })
  val s0 = RegInit(0.U(16.W))
  when (io.shamt(3) === 1.U) {
    s0 := io.in << 8.U
  } .otherwise {
    s0 := io.in
  }
  val s1 = RegInit(0.U(16.W))
  when (io.shamt(2) === 1.U) {
    s1 := s0 << 4.U
  } .otherwise {
    s1 := s0
  }
  val s2 = RegInit(0.U(16.W))
  when (io.shamt(1) === 1.U) {
    s2 := s1 << 2.U
  } .otherwise {
    s2 := s1
  }
  when (io.shamt(1) === 1.U) {
    io.out := s2 << 1.U
  } .otherwise {
    io.out := s2
  }
}

risc

// See LICENSE.txt for license details.
package examples

import chisel3._
import chisel3.util._

class Risc extends Module {
  val io = IO(new Bundle {
    val isWr   = Input(Bool())
    val wrAddr = Input(UInt(8.W))
    val wrData = Input(UInt(32.W))
    val boot   = Input(Bool())
    val valid  = Output(Bool())
    val out    = Output(UInt(32.W))
  })
  val file = Mem(256, UInt(32.W))
  val code = Mem(256, UInt(32.W))
  val pc   = RegInit(0.U(8.W))

  val add_op :: imm_op :: Nil = Enum(2)

  val inst = code(pc)
  val op   = inst(31,24)
  val rci  = inst(23,16)
  val rai  = inst(15, 8)
  val rbi  = inst( 7, 0)

  val ra = Mux(rai === 0.U, 0.U, file(rai))
  val rb = Mux(rbi === 0.U, 0.U, file(rbi))
  val rc = Wire(UInt(32.W))

  io.valid := false.B
  io.out   := 0.U
  rc       := 0.U

  when (io.isWr) {
    code(io.wrAddr) := io.wrData
  } .elsewhen (io.boot) {
    pc := 0.U
  } .otherwise {
    switch(op) {
      is(add_op) { rc := ra + rb }
      is(imm_op) { rc := (rai << 8.U) | rbi }
    }
    io.out := rc
    when (rci === 255.U) {
      io.valid := true.B
    } .otherwise {
      file(rci) := rc
    }
    pc := pc + 1.U
  }
}

router

// See LICENSE for license details.

package examples

import chisel3._
import chisel3.util.{DeqIO, EnqIO, log2Ceil}

object Router {
  val addressWidth    = 32
  val dataWidth       = 64
  val headerWidth     =  8
  val routeTableSize  = 15
  val numberOfOutputs =  4
}

class ReadCmd extends Bundle {
  val addr = UInt(Router.addressWidth.W)
}

class WriteCmd extends ReadCmd {
  val data = UInt(Router.addressWidth.W)
}

class Packet extends Bundle {
  val header = UInt(Router.headerWidth.W)
  val body   = UInt(Router.dataWidth.W)
}

/**
  * The router circuit IO
  * It routes a packet placed on its single input port to one of n output ports
  *
  * @param n is the number of fanned outputs for the routed packet
  */
class RouterIO(val n: Int) extends Bundle {
  val read_routing_table_request   = DeqIO(new ReadCmd())
  val read_routing_table_response  = EnqIO(UInt(Router.addressWidth.W))
  val load_routing_table_request   = DeqIO(new WriteCmd())
  val in                           = DeqIO(new Packet())
  val outs                         = Vec(n, EnqIO(new Packet()))
}

/**
  * routes packets by using their header as an index into an externally loaded and readable table,
  * The number of addresses recognized does not need to match the number of outputs
  */
class Router extends Module {
  val depth: Int = Router.routeTableSize
  val n: Int = Router.numberOfOutputs
  val io    = IO(new RouterIO(n))
  val tbl   = Mem(depth, UInt(BigInt(n).bitLength.W))

  // These ensure all output signals are driven.
  io.read_routing_table_request.nodeq()
  io.load_routing_table_request.nodeq()
  io.read_routing_table_response.noenq()
  io.read_routing_table_response.bits := 0.U
  io.in.nodeq()
  io.outs.foreach { out =>
    out.bits := 0.U.asTypeOf(out.bits)
    out.noenq()
  }

  // We rely on Chisel's "last connect" semantics to override the default connections as appropriate.
  when(io.read_routing_table_request.valid && io.read_routing_table_response.ready) {
    io.read_routing_table_response.enq(tbl(
      io.read_routing_table_request.deq().addr
    ))
  }
  .elsewhen(io.load_routing_table_request.valid) {
    val cmd = io.load_routing_table_request.deq()
    tbl(cmd.addr) := cmd.data
    printf("setting tbl(%d) to %d\n", cmd.addr, cmd.data)
  }
  .elsewhen(io.in.valid) {
    val pkt = io.in.bits
    val idx = tbl(pkt.header(log2Ceil(Router.routeTableSize), 0))
    when(io.outs(idx).ready) {
      io.in.deq()
      io.outs(idx).enq(pkt)
      printf("got packet to route header %d, data %d, being routed to out(%d)\n", pkt.header, pkt.body, tbl(pkt.header))
    }
  }
}

life


// See LICENSE.txt for license details.
package examples

import chisel3._
import chisel3.util.log2Ceil

class Cell extends Module {
  //noinspection TypeAnnotation
  val io = IO(new Bundle {
    val neighbors = Vec(8, Input(Bool()))
    val out = Output(Bool())
    val running = Input(Bool())
    val writeEnable = Input(Bool())
    val writeValue = Input(Bool())
  })
  val isAlive = RegInit(false.B)

  when(!io.running) {
    when(io.writeEnable) {
      isAlive := io.writeValue
    }
      .otherwise {
        isAlive := isAlive
      }
  }.otherwise {
    val count = io.neighbors.foldRight(0.U(3.W))((x: Bool, y: UInt) => x.asUInt + y)

    when(isAlive) {
      when(count < 2.U) {
        isAlive := false.B
      }.elsewhen(count < 4.U) {
        isAlive := true.B
      }.otherwise {
        isAlive := false.B
      }
    }.otherwise {
      when(!isAlive && count === 3.U) {
        isAlive := true.B
      }
        .otherwise {
          isAlive := false.B
        }
    }
  }

  io.out := isAlive
}

class Life(val rows: Int, val cols: Int) extends Module {
  //noinspection TypeAnnotation
  val io = IO(new Bundle {
    val state = Output(Vec(rows, Vec(cols, Bool())))
    val running = Input(Bool())
    val writeValue = Input(Bool())
    val writeRowAddress = Input(UInt(log2Ceil(rows+1).W))
    val writeColAddress = Input(UInt(log2Ceil(cols+1).W))
  })

  private val cells = Array.fill(rows, cols)(Module(new Cell))

  for {
    row <- 0 until rows
    col <- 0 until cols
  } {
    io.state(row)(col) := cells(row)(col).io.out
    cells(row)(col).io.running := io.running
    cells(row)(col).io.writeValue := io.writeValue
    cells(row)(col).io.writeEnable := io.writeRowAddress === row.U & io.writeColAddress === col.U
  }

  def getNeighborIndex(row: Int, rowDelta: Int, col: Int, colDelta: Int): (Int, Int) = {
    def wrapIndex(index: Int, delta: Int, max: Int): Int = {
      if(index == 0 && delta == -1) { max - 1 }
      else if(index == max - 1 && delta == 1) { 0 }
      else { index + delta }
    }
    (wrapIndex(row, rowDelta, rows), wrapIndex(col, colDelta, cols))
  }

  // for every cell wire it up to it's neighbors, edges wrap, world is a torus
  for (row <- 0 until rows) {
    for (col <- 0 until cols) {
      val cell = cells(row)(col)
      var neighborInput = 0
      for (deltaRow <- -1 to 1) {
        for (deltaCol <- -1 to 1) {
          if (deltaRow != 0 || deltaCol != 0) {
            val (rowIndex, colIndex) = getNeighborIndex(row, deltaRow, col, deltaCol)
            cell.io.neighbors(neighborInput) := cells(rowIndex)(colIndex).io.out
            neighborInput = neighborInput + 1
          }
        }
      }
    }
  }
}

Parity

// See LICENSE.txt for license details.
package examples

import chisel3._
import chisel3.util.Enum

class Parity extends Module {
  val io = IO(new Bundle {
    val in  = Input(Bool())
    val out = Output(Bool())
  })
  val s_even :: s_odd :: Nil = Enum(2)
  val state  = RegInit(s_even)
  when (io.in) {
    when (state === s_even) { state := s_odd  }
    .otherwise              { state := s_even }
  }
  io.out := (state === s_odd)
}

SimpleALU

// See LICENSE.txt for license details.
package examples

import chisel3._

class BasicALU extends Module {
  val io = IO(new Bundle {
    val a = Input(UInt(4.W))
    val b = Input(UInt(4.W))
    val opcode = Input(UInt(4.W))
    val out = Output(UInt(4.W))
  })
  io.out := 0.U //THIS SEEMS LIKE A HACK/BUG
  when (io.opcode === 0.U) {
    io.out := io.a //pass A
  } .elsewhen (io.opcode === 1.U) {
    io.out := io.b //pass B
  } .elsewhen (io.opcode === 2.U) {
    io.out := io.a + 1.U //increment A by 1
  } .elsewhen (io.opcode === 3.U) {
    io.out := io.a - 1.U //increment B by 1
  } .elsewhen (io.opcode === 4.U) {
    io.out := io.a + 4.U //increment A by 4
  } .elsewhen (io.opcode === 5.U) {
    io.out := io.a - 4.U //decrement A by 4
  } .elsewhen (io.opcode === 6.U) {
    io.out := io.a + io.b //add A and B
  } .elsewhen (io.opcode === 7.U) {
    io.out := io.a - io.b //subtract B from A
  } .elsewhen (io.opcode === 8.U) {
    io.out := io.a < io.b //set on A less than B
  } .otherwise { 
    io.out :=  (io.a === io.b).asUInt //set on A equal to B
  }
}

class SimpleALU extends Module {
  val io = IO(new Bundle {
    val a      = Input(UInt(4.W))
    val b      = Input(UInt(4.W))
    val opcode = Input(UInt(2.W))
    val out = Output(UInt(4.W))
  })
  io.out := 0.U
  when (io.opcode === 0.U) {
    io.out := io.a + io.b //ADD
  } .elsewhen (io.opcode === 1.U) {
    io.out := io.a - io.b //SUB
  } .elsewhen (io.opcode === 2.U) {
    io.out := io.a  	     //PASS A
  } .otherwise {
    io.out := io.b        //PASS B
  }
}

tbl

// See LICENSE.txt for license details.
package examples

import chisel3._

class Tbl extends Module {
  val io = IO(new Bundle {
    val addr = Input(UInt(8.W))
    val out  = Output(UInt(8.W))
  })
  val r = VecInit(Range(0, 256).map(_.asUInt(8.W)))
  io.out := r(io.addr)
}

你可能感兴趣的:(chisel,fpga开发)