DataWidthConverter.scala 2.96 KB
Newer Older
1
package chisel.miscutils
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
import Chisel._

/**
 * DataWidthConverter converts the data width of a Queue.
 * Output is provided via a Queue, with increased or decreased
 * data rate, depending on the direction of the conversion.
 * Note: This would be much more useful, if the two Queues
 *       could use different clocks, but multi-clock support
 *       in Chisel is currently unstable.
 * @param inWidth Data width of input Decoupled (bits).
 * @param outWidth Data width of output Decoupled (bits); must
 *                 be integer multiples of each other.
 * @param littleEndian if inWidth > outWidth, determines
 *                     the order of the nibbles (low to high)
 **/
class DataWidthConverter(
    val inWidth: Int,
    val outWidth: Int,
    val littleEndian: Boolean = true
  ) extends Module {

  require (inWidth > 0, "inWidth must be > 0")
  require (outWidth > 0, "inWidth must be > 0")
  require (inWidth != outWidth, "inWidth (%d) must be different from outWidth (%d)"
             .format(inWidth, outWidth))
  require (inWidth % outWidth == 0 || outWidth % inWidth == 0,
           "inWidth (%d) and outWidth (%d) must be integer multiples of each other"
             .format(inWidth, outWidth))

  val io = new Bundle {
    val inq = Decoupled(UInt(width = inWidth)).flip()
    val deq = Decoupled(UInt(width = outWidth))
  }

  val ratio: Int = if (inWidth > outWidth) inWidth / outWidth else outWidth / inWidth
37
  val d_w = if (inWidth > outWidth) inWidth else outWidth // data register width
38

39
40
41
42
  if (inWidth > outWidth)
    downsize()
  else
    upsize()
43

44
45
46
  private def upsize() = {
    val i = Reg(UInt(width = log2Up(ratio + 1)))
    val d = Reg(UInt(width = outWidth))
47

48
    io.inq.ready := !reset && (i =/= UInt(0) || (io.inq.valid && io.deq.ready))
49
    io.deq.bits  := d
Jens Korinth's avatar
Jens Korinth committed
50
    io.deq.valid := !reset && i === UInt(0)
51
52
53
54
55
56
57
58
59
60
61

    when (reset) {
      i := UInt(ratio)
      d := UInt(0)
    }
    .otherwise {
      when (io.inq.ready && io.inq.valid) {
        if (littleEndian)
          d := Cat(io.inq.bits, d) >> UInt(inWidth)
        else
          d := (d << UInt(inWidth)) | io.inq.bits
Jens Korinth's avatar
Jens Korinth committed
62
63
64
        i := i - UInt(1)
      }
      when (io.deq.valid && io.deq.ready) {
65
        i := Mux(io.inq.valid, UInt(ratio - 1), UInt(ratio))
66
67
      }
    }
68
69
  }

70
  private def downsize() = {
Jens Korinth's avatar
Jens Korinth committed
71
    val i = Reg(UInt(width = log2Up(ratio + 1)))
72
73
    val d = Reg(UInt(width = inWidth))

Jens Korinth's avatar
Jens Korinth committed
74
    io.inq.ready := !reset && (i === UInt(0) || (i === UInt(1) && io.deq.ready))
75
76
77
78
    if (littleEndian)
      io.deq.bits := d(outWidth - 1, 0)
    else
      io.deq.bits := d(inWidth - 1, inWidth - outWidth)
Jens Korinth's avatar
Jens Korinth committed
79
    io.deq.valid := !reset && i > UInt(0)
80

81
82
83
84
    when (reset) {
      i := UInt(0)
      d := UInt(0)
    }
85
    .otherwise {
86
87
88
89
90
91
      when (i > UInt(0) && io.deq.ready) {
        if (littleEndian)
          d := d >> UInt(outWidth)
        else
          d := d << UInt(outWidth)
        i := i - UInt(1)
92
      }
Jens Korinth's avatar
Jens Korinth committed
93
      when (io.inq.ready && io.inq.valid) {
94
        d := io.inq.bits
Jens Korinth's avatar
Jens Korinth committed
95
        i := UInt(ratio)
96
97
      }
    }
98
99
100
  }
}