74 lines
1.7 KiB
Scala
74 lines
1.7 KiB
Scala
// See README.md for license details.
|
|
|
|
package gcd
|
|
|
|
import chisel3._
|
|
import chisel3.util.Decoupled
|
|
|
|
class GcdInputBundle(val w: Int) extends Bundle {
|
|
val value1 = UInt(w.W)
|
|
val value2 = UInt(w.W)
|
|
}
|
|
|
|
class GcdOutputBundle(val w: Int) extends Bundle {
|
|
val value1 = UInt(w.W)
|
|
val value2 = UInt(w.W)
|
|
val gcd = UInt(w.W)
|
|
}
|
|
|
|
/**
|
|
* Compute Gcd using subtraction method.
|
|
* Subtracts the smaller from the larger until register y is zero.
|
|
* value input register x is then the Gcd.
|
|
* Unless first input is zero then the Gcd is y.
|
|
* Can handle stalls on the producer or consumer side
|
|
*/
|
|
class DecoupledGcd(width: Int) extends Module {
|
|
val input = IO(Flipped(Decoupled(new GcdInputBundle(width))))
|
|
val output = IO(Decoupled(new GcdOutputBundle(width)))
|
|
|
|
val xInitial = Reg(UInt())
|
|
val yInitial = Reg(UInt())
|
|
val x = Reg(UInt())
|
|
val y = Reg(UInt())
|
|
val busy = RegInit(false.B)
|
|
val resultValid = RegInit(false.B)
|
|
|
|
input.ready := ! busy
|
|
output.valid := resultValid
|
|
output.bits := DontCare
|
|
|
|
when(busy) {
|
|
when(x > y) {
|
|
x := x - y
|
|
}.otherwise {
|
|
y := y - x
|
|
}
|
|
when(x === 0.U || y === 0.U) {
|
|
when(x === 0.U) {
|
|
output.bits.gcd := y
|
|
}.otherwise {
|
|
output.bits.gcd := x
|
|
}
|
|
|
|
output.bits.value1 := xInitial
|
|
output.bits.value2 := yInitial
|
|
resultValid := true.B
|
|
|
|
when(output.ready && resultValid) {
|
|
busy := false.B
|
|
resultValid := false.B
|
|
}
|
|
}
|
|
}.otherwise {
|
|
when(input.valid) {
|
|
val bundle = input.deq()
|
|
x := bundle.value1
|
|
y := bundle.value2
|
|
xInitial := bundle.value1
|
|
yInitial := bundle.value2
|
|
busy := true.B
|
|
}
|
|
}
|
|
}
|