File size: 5,971 Bytes
829b19c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | package arithmetic
import chisel3._
import chisel3.util._
import nand._
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// ARITHMETIC FROM NAND β Adders and ALU built entirely from
// NAND-derived gates
//
// Hierarchy: NAND2 β XOR/AND/OR β Half Adder β Full Adder β
// Ripple Carry Adder β ALU slice
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// βββ HALF ADDER from NAND ββββββββββββββββββββββββββββββββββββββββ
// sum = a β b
// cout = a Β· b
class HalfAdderFromNand extends Module {
val io = IO(new Bundle {
val a = Input(Bool())
val b = Input(Bool())
val sum = Output(Bool())
val cout = Output(Bool())
})
val xor = Module(new Xor2FromNand)
xor.io.a := io.a
xor.io.b := io.b
io.sum := xor.io.y
val and = Module(new And2FromNand)
and.io.a := io.a
and.io.b := io.b
io.cout := and.io.y
}
// βββ FULL ADDER from NAND ββββββββββββββββββββββββββββββββββββββββ
// sum = a β b β cin
// cout = (aΒ·b) + (cinΒ·(aβb))
class FullAdderFromNand extends Module {
val io = IO(new Bundle {
val a = Input(Bool())
val b = Input(Bool())
val cin = Input(Bool())
val sum = Output(Bool())
val cout = Output(Bool())
})
// First half adder: a, b
val ha1 = Module(new HalfAdderFromNand)
ha1.io.a := io.a
ha1.io.b := io.b
// Second half adder: (aβb), cin
val ha2 = Module(new HalfAdderFromNand)
ha2.io.a := ha1.io.sum
ha2.io.b := io.cin
io.sum := ha2.io.sum
// cout = (aΒ·b) + (cinΒ·(aβb))
val or = Module(new Or2FromNand)
or.io.a := ha1.io.cout
or.io.b := ha2.io.cout
io.cout := or.io.y
}
// βββ RIPPLE CARRY ADDER from NAND βββββββββββββββββββββββββββββββ
// n-bit adder: chain of full adders, carry ripples LSB β MSB
class RippleCarryAdder(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(Bool())
val sum = Output(UInt(n.W))
val cout = Output(Bool())
})
val carries = Wire(Vec(n + 1, Bool()))
carries(0) := io.cin
val sums = Wire(Vec(n, Bool()))
for (i <- 0 until n) {
val fa = Module(new FullAdderFromNand)
fa.io.a := io.a(i)
fa.io.b := io.b(i)
fa.io.cin := carries(i)
sums(i) := fa.io.sum
carries(i+1) := fa.io.cout
}
io.sum := Cat(sums.reverse)
io.cout := carries(n)
}
// βββ ALU SLICE from NAND ββββββββββββββββββββββββββββββββββββββββ
// 1-bit ALU slice with 4 operations selected by 2-bit opcode:
// 00 β AND
// 01 β OR
// 10 β XOR
// 11 β ADD (with carry in/out)
//
// All gates built from NAND2 primitive chain
class AluSliceFromNand extends Module {
val io = IO(new Bundle {
val a = Input(Bool())
val b = Input(Bool())
val cin = Input(Bool())
val op = Input(UInt(2.W))
val y = Output(Bool())
val cout = Output(Bool())
})
// AND path
val andGate = Module(new And2FromNand)
andGate.io.a := io.a
andGate.io.b := io.b
// OR path
val orGate = Module(new Or2FromNand)
orGate.io.a := io.a
orGate.io.b := io.b
// XOR path
val xorGate = Module(new Xor2FromNand)
xorGate.io.a := io.a
xorGate.io.b := io.b
// ADD path (full adder)
val fa = Module(new FullAdderFromNand)
fa.io.a := io.a
fa.io.b := io.b
fa.io.cin := io.cin
// 4:1 MUX from two levels of 2:1 MUX
// Level 1: mux0 selects AND/OR on op[0], mux1 selects XOR/ADD-sum on op[0]
val mux0 = Module(new Mux2FromNand)
mux0.io.a := andGate.io.y // op[0]=0 β AND
mux0.io.b := orGate.io.y // op[0]=1 β OR
mux0.io.sel := io.op(0)
val mux1 = Module(new Mux2FromNand)
mux1.io.a := xorGate.io.y // op[0]=0 β XOR
mux1.io.b := fa.io.sum // op[0]=1 β ADD
mux1.io.sel := io.op(0)
// Level 2: select between level-1 results on op[1]
val mux2 = Module(new Mux2FromNand)
mux2.io.a := mux0.io.y // op[1]=0 β AND/OR
mux2.io.b := mux1.io.y // op[1]=1 β XOR/ADD
mux2.io.sel := io.op(1)
io.y := mux2.io.y
// Carry out: only meaningful for ADD (op=11), 0 otherwise
// Mux carry: pass cout when op==3, else 0
val is_add = Module(new And2FromNand)
is_add.io.a := io.op(0)
is_add.io.b := io.op(1)
val carry_mux = Module(new Mux2FromNand)
carry_mux.io.a := false.B
carry_mux.io.b := fa.io.cout
carry_mux.io.sel := is_add.io.y
io.cout := carry_mux.io.y
}
// βββ n-BIT ALU from NAND βββββββββββββββββββββββββββββββββββββββ
// Ripple ALU: chain of AluSliceFromNand for ADD,
// parallel for AND/OR/XOR (carry only used for ADD)
class AluFromNand(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(Bool())
val op = Input(UInt(2.W))
val y = Output(UInt(n.W))
val cout = Output(Bool())
})
val carries = Wire(Vec(n + 1, Bool()))
carries(0) := io.cin
val results = Wire(Vec(n, Bool()))
for (i <- 0 until n) {
val slice = Module(new AluSliceFromNand)
slice.io.a := io.a(i)
slice.io.b := io.b(i)
slice.io.cin := carries(i)
slice.io.op := io.op
results(i) := slice.io.y
carries(i + 1) := slice.io.cout
}
io.y := Cat(results.reverse)
io.cout := carries(n)
}
|