make external clock divider programmable
This commit is contained in:
parent
c211d74e95
commit
1945fa898b
@ -3,7 +3,7 @@ package uncore
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import Constants._
|
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 io = new Bundle {
|
||||||
val out_fast = new FIFOIO()(data).flip
|
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 in_slow = new FIFOIO()(data).flip
|
||||||
|
|
||||||
val clk_slow = Bool(OUTPUT)
|
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_max >= 8 && divisor_max <= 65536 && isPow2(divisor_max))
|
||||||
require((divisor & (divisor-1)) == 0)
|
val divisor = Reg(resetVal = UFix(divisor_max-1))
|
||||||
require(hold_cycles < divisor/2 && hold_cycles >= 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)) }
|
val count = Reg{UFix(width = log2Up(divisor_max))}
|
||||||
cnt := cnt + UFix(1)
|
val clock = Reg{Bool()}
|
||||||
val out_en = cnt === UFix(divisor/2+hold_cycles-1) // rising edge + hold time
|
count := count + UFix(1)
|
||||||
val in_en = cnt === UFix(divisor/2-1) // rising edge
|
|
||||||
|
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 in_slow_rdy = Reg(resetVal = Bool(false))
|
||||||
val out_slow_val = Reg(resetVal = Bool(false))
|
val out_slow_val = Reg(resetVal = Bool(false))
|
||||||
val out_slow_bits = Reg() { data }
|
val out_slow_bits = Reg() { data }
|
||||||
|
|
||||||
val fromhost_q = new Queue(1)(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.enq.bits := io.in_slow.bits
|
||||||
fromhost_q.io.deq <> io.in_fast
|
fromhost_q.io.deq <> io.in_fast
|
||||||
|
|
||||||
val tohost_q = new Queue(1)(data)
|
val tohost_q = new Queue(1)(data)
|
||||||
tohost_q.io.enq <> io.out_fast
|
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
|
in_slow_rdy := fromhost_q.io.enq.ready
|
||||||
out_slow_val := tohost_q.io.deq.valid
|
out_slow_val := tohost_q.io.deq.valid
|
||||||
out_slow_bits := Mux(reset, fromhost_q.io.deq.bits, tohost_q.io.deq.bits)
|
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.in_slow.ready := in_slow_rdy
|
||||||
io.out_slow.valid := out_slow_val
|
io.out_slow.valid := out_slow_val
|
||||||
io.out_slow.bits := out_slow_bits
|
io.out_slow.bits := out_slow_bits
|
||||||
io.clk_slow := cnt(log2Up(divisor)-1).toBool
|
io.clk_slow := clock
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user