diff --git a/uncore/src/slowio.scala b/uncore/src/slowio.scala index fa6fef94..cf00ae6e 100644 --- a/uncore/src/slowio.scala +++ b/uncore/src/slowio.scala @@ -3,7 +3,7 @@ package uncore import Chisel._ import Constants._ -class slowIO[T <: Data](val divisor: Int, hold_cycles_in: Int = -1)(data: => T) extends Component +class SlowIO[T <: Data](val divisor_max: Int)(data: => T) extends Component { val io = new Bundle { val out_fast = new FIFOIO()(data).flip @@ -13,31 +13,54 @@ class slowIO[T <: Data](val divisor: Int, hold_cycles_in: Int = -1)(data: => T) val in_slow = new FIFOIO()(data).flip val clk_slow = Bool(OUTPUT) + + val set_divisor = new PipeIO()(Bits(width = 32)).flip + val divisor = Bits(OUTPUT, 32) } - val hold_cycles = if (hold_cycles_in == -1) divisor/4 else hold_cycles_in - require((divisor & (divisor-1)) == 0) - require(hold_cycles < divisor/2 && hold_cycles >= 1) + require(divisor_max >= 8 && divisor_max <= 65536 && isPow2(divisor_max)) + val divisor = Reg(resetVal = UFix(divisor_max-1)) + val d_shadow = Reg(resetVal = UFix(divisor_max-1)) + val hold = Reg(resetVal = UFix(divisor_max/4-1)) + val h_shadow = Reg(resetVal = UFix(divisor_max/4-1)) + when (io.set_divisor.valid) { + d_shadow := io.set_divisor.bits(log2Up(divisor_max)-1, 0).toUFix + h_shadow := io.set_divisor.bits(log2Up(divisor_max)-1+16, 16).toUFix + } + io.divisor := hold << UFix(16) | divisor - val cnt = Reg() { UFix(width = log2Up(divisor)) } - cnt := cnt + UFix(1) - val out_en = cnt === UFix(divisor/2+hold_cycles-1) // rising edge + hold time - val in_en = cnt === UFix(divisor/2-1) // rising edge + val count = Reg{UFix(width = log2Up(divisor_max))} + val clock = Reg{Bool()} + count := count + UFix(1) + + val rising = count === (divisor >> UFix(1)) + val falling = count === divisor + val held = count === (divisor >> UFix(1)) + hold + + when (falling) { + divisor := d_shadow + hold := h_shadow + count := UFix(0) + clock := Bool(false) + } + when (rising) { + clock := Bool(true) + } val in_slow_rdy = Reg(resetVal = Bool(false)) val out_slow_val = Reg(resetVal = Bool(false)) val out_slow_bits = Reg() { data } val fromhost_q = new Queue(1)(data) - fromhost_q.io.enq.valid := in_en && (io.in_slow.valid && in_slow_rdy || reset) + fromhost_q.io.enq.valid := rising && (io.in_slow.valid && in_slow_rdy || reset) fromhost_q.io.enq.bits := io.in_slow.bits fromhost_q.io.deq <> io.in_fast val tohost_q = new Queue(1)(data) tohost_q.io.enq <> io.out_fast - tohost_q.io.deq.ready := in_en && io.out_slow.ready && out_slow_val + tohost_q.io.deq.ready := rising && io.out_slow.ready && out_slow_val - when (out_en) { + when (held) { in_slow_rdy := fromhost_q.io.enq.ready out_slow_val := tohost_q.io.deq.valid out_slow_bits := Mux(reset, fromhost_q.io.deq.bits, tohost_q.io.deq.bits) @@ -46,5 +69,5 @@ class slowIO[T <: Data](val divisor: Int, hold_cycles_in: Int = -1)(data: => T) io.in_slow.ready := in_slow_rdy io.out_slow.valid := out_slow_val io.out_slow.bits := out_slow_bits - io.clk_slow := cnt(log2Up(divisor)-1).toBool + io.clk_slow := clock }