GCD
package examples
import chisel3._
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
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))
})
val a_xor_b = io.a ^ io.b
io.sum := a_xor_b ^ io.cin
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
}
adder4
package examples
import chisel3._
import chisel3.util._
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))
})
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
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)
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)
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
package examples
import chisel3._
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))
})
val FAs = Array.fill(n)(Module(new FullAdder()).io)
val carry = Wire(Vec(n+1, UInt(1.W)))
val sum = Wire(Vec(n, Bool()))
carry(0) := io.Cin
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
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
}
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
}
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))
})
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
}
ByteSelector
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
package examples
import chisel3._
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
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
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
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
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)
}
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()))
}
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))
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()
}
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
package examples
import chisel3._
import chisel3.util.log2Ceil
class Cell extends Module {
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 {
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 (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
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
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
when (io.opcode === 0.U) {
io.out := io.a
} .elsewhen (io.opcode === 1.U) {
io.out := io.b
} .elsewhen (io.opcode === 2.U) {
io.out := io.a + 1.U
} .elsewhen (io.opcode === 3.U) {
io.out := io.a - 1.U
} .elsewhen (io.opcode === 4.U) {
io.out := io.a + 4.U
} .elsewhen (io.opcode === 5.U) {
io.out := io.a - 4.U
} .elsewhen (io.opcode === 6.U) {
io.out := io.a + io.b
} .elsewhen (io.opcode === 7.U) {
io.out := io.a - io.b
} .elsewhen (io.opcode === 8.U) {
io.out := io.a < io.b
} .otherwise {
io.out := (io.a === io.b).asUInt
}
}
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
} .elsewhen (io.opcode === 1.U) {
io.out := io.a - io.b
} .elsewhen (io.opcode === 2.U) {
io.out := io.a
} .otherwise {
io.out := io.b
}
}
tbl
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)
}