2014-09-13 00:31:38 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
2012-10-11 00:42:39 +02:00
|
|
|
package uncore
|
2012-03-16 02:36:07 +01:00
|
|
|
import Chisel._
|
|
|
|
|
2013-08-12 19:36:44 +02:00
|
|
|
class SlowIO[T <: Data](val divisor_max: Int)(data: => T) extends Module
|
2012-03-16 02:36:07 +01:00
|
|
|
{
|
|
|
|
val io = new Bundle {
|
2013-08-12 19:36:44 +02:00
|
|
|
val out_fast = Decoupled(data).flip
|
|
|
|
val out_slow = Decoupled(data)
|
|
|
|
val in_fast = Decoupled(data)
|
|
|
|
val in_slow = Decoupled(data).flip
|
2012-03-16 02:36:07 +01:00
|
|
|
val clk_slow = Bool(OUTPUT)
|
2013-08-12 19:36:44 +02:00
|
|
|
val set_divisor = Valid(Bits(width = 32)).flip
|
2013-01-25 08:40:47 +01:00
|
|
|
val divisor = Bits(OUTPUT, 32)
|
|
|
|
}
|
|
|
|
|
|
|
|
require(divisor_max >= 8 && divisor_max <= 65536 && isPow2(divisor_max))
|
2013-08-16 00:27:38 +02:00
|
|
|
val divisor = Reg(init=UInt(divisor_max-1))
|
|
|
|
val d_shadow = Reg(init=UInt(divisor_max-1))
|
|
|
|
val hold = Reg(init=UInt(divisor_max/4-1))
|
|
|
|
val h_shadow = Reg(init=UInt(divisor_max/4-1))
|
2013-01-25 08:40:47 +01:00
|
|
|
when (io.set_divisor.valid) {
|
2013-08-12 19:36:44 +02:00
|
|
|
d_shadow := io.set_divisor.bits(log2Up(divisor_max)-1, 0).toUInt
|
|
|
|
h_shadow := io.set_divisor.bits(log2Up(divisor_max)-1+16, 16).toUInt
|
2012-03-16 02:36:07 +01:00
|
|
|
}
|
2013-08-12 19:36:44 +02:00
|
|
|
io.divisor := hold << UInt(16) | divisor
|
2012-03-16 02:36:07 +01:00
|
|
|
|
2013-08-12 19:36:44 +02:00
|
|
|
val count = Reg{UInt(width = log2Up(divisor_max))}
|
|
|
|
val myclock = Reg{Bool()}
|
|
|
|
count := count + UInt(1)
|
2012-03-16 02:36:07 +01:00
|
|
|
|
2013-08-12 19:36:44 +02:00
|
|
|
val rising = count === (divisor >> UInt(1))
|
2013-01-25 08:40:47 +01:00
|
|
|
val falling = count === divisor
|
2013-08-12 19:36:44 +02:00
|
|
|
val held = count === (divisor >> UInt(1)) + hold
|
2013-01-25 08:40:47 +01:00
|
|
|
|
|
|
|
when (falling) {
|
|
|
|
divisor := d_shadow
|
|
|
|
hold := h_shadow
|
2013-08-12 19:36:44 +02:00
|
|
|
count := UInt(0)
|
|
|
|
myclock := Bool(false)
|
2013-01-25 08:40:47 +01:00
|
|
|
}
|
|
|
|
when (rising) {
|
2013-08-12 19:36:44 +02:00
|
|
|
myclock := Bool(true)
|
2013-01-25 08:40:47 +01:00
|
|
|
}
|
2012-03-16 02:36:07 +01:00
|
|
|
|
2013-08-16 00:27:38 +02:00
|
|
|
val in_slow_rdy = Reg(init=Bool(false))
|
|
|
|
val out_slow_val = Reg(init=Bool(false))
|
2013-08-12 19:36:44 +02:00
|
|
|
val out_slow_bits = Reg(data)
|
2012-03-16 02:36:07 +01:00
|
|
|
|
2013-08-12 19:36:44 +02:00
|
|
|
val fromhost_q = Module(new Queue(data,1))
|
2013-08-13 05:52:18 +02:00
|
|
|
fromhost_q.io.enq.valid := rising && (io.in_slow.valid && in_slow_rdy || this.reset)
|
2012-03-16 02:36:07 +01:00
|
|
|
fromhost_q.io.enq.bits := io.in_slow.bits
|
|
|
|
fromhost_q.io.deq <> io.in_fast
|
|
|
|
|
2013-08-12 19:36:44 +02:00
|
|
|
val tohost_q = Module(new Queue(data,1))
|
2012-03-16 02:36:07 +01:00
|
|
|
tohost_q.io.enq <> io.out_fast
|
2013-01-25 08:40:47 +01:00
|
|
|
tohost_q.io.deq.ready := rising && io.out_slow.ready && out_slow_val
|
2012-03-16 02:36:07 +01:00
|
|
|
|
2013-01-25 08:40:47 +01:00
|
|
|
when (held) {
|
2012-03-16 02:36:07 +01:00
|
|
|
in_slow_rdy := fromhost_q.io.enq.ready
|
|
|
|
out_slow_val := tohost_q.io.deq.valid
|
2013-08-13 05:52:18 +02:00
|
|
|
out_slow_bits := Mux(this.reset, fromhost_q.io.deq.bits, tohost_q.io.deq.bits)
|
2012-03-16 02:36:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
io.in_slow.ready := in_slow_rdy
|
|
|
|
io.out_slow.valid := out_slow_val
|
|
|
|
io.out_slow.bits := out_slow_bits
|
2013-08-12 19:36:44 +02:00
|
|
|
io.clk_slow := myclock
|
2012-03-16 02:36:07 +01:00
|
|
|
}
|