[libre-riscv-dev] HDL selection

Luke Kenneth Casson Leighton lkcl at lkcl.net
Sat Nov 17 14:08:11 GMT 2018


RocketCore.scala: register file.
https://github.com/freechipsproject/rocket-chip/blob/master/src/main/scala/rocket/RocketCore.scala

(1) what on earth is canRead being set to false? that permanently
stops read from working!
(2) what on earth is a "=/=" operator?
(3) what's an _2?
(4) where are all the comments that are normally expected to be on
source code files, explaining the parameters and the purpose of the
class?
(5) what order are the parameters to "Mux"? what kind of "Mux" is it?

class RegFile(n: Int, w: Int, zero: Boolean = false) {
  private val rf = Mem(n, UInt(width = w))
  private def access(addr: UInt) = rf(~addr(log2Up(n)-1,0))
  private val reads = ArrayBuffer[(UInt,UInt)]()
  private var canRead = true
  def read(addr: UInt) = {
    require(canRead)
    reads += addr -> Wire(UInt())
    reads.last._2 := Mux(Bool(zero) && addr === UInt(0), UInt(0), access(addr))
    reads.last._2
  }
  def write(addr: UInt, data: UInt) = {
    canRead = false
    when (addr =/= UInt(0)) {
      access(addr) := data
      for ((raddr, rdata) <- reads)
        when (addr === raddr) { rdata := data }
    }
  }
}

-------
Algol's RegisterFile class (myhdl).
https://github.com/AngelTerrones/Algol/blob/master/Core/regfile.py

(1) it's got standard python documentation strings.
(2) Signal looks obvious what it does.
(3) modbv doesn't.
(4) _registers looks obvious.  it's a list of 32 "signals".
(5) read looks obvious (i left out the class "Port"), it goes "next
read of port data is from the indexed register if the port's ra (read
address) is non-zero.
(6) write looks obvious (if the doc string isn't clear).  update the
target register (from wd) if the address (wa) isn't zero.  oh and if
the writePort isn't locked for some reason (we).



def RegisterFile(clk,
                 portA,
                 portB,
                 writePort):
    """
    The Register File (RF) module.
    32 32-bit registers, with the register 0 hardwired to zero.

    :param clk:       System clock
    :param portA:     IO bundle (read port)
    :param portB:     IO bundle (read port)
    :param writePort: IO bundle (write port)
    """
    _registers = [Signal(modbv(0)[32:]) for ii in range(0, 32)]

    @always_comb
    def read():
        """
        Asynchronous read operation.
        """
        portA.rd.next = _registers[portA.ra] if portA.ra != 0 else 0
        portB.rd.next = _registers[portB.ra] if portB.ra != 0 else 0

    @always(clk.posedge)
    def write():
        """
        Synchronous write operation.

        If the write address is zero, do nothing.
        """
        if writePort.wa != 0 and writePort.we == 1:
            _registers[writePort.wa].next = writePort.wd

    return read, write


------
migen.  can't find an example "register file", did find this, which is
a fork of migen called "litex":
https://www.bunniestudios.com/blog/?p=5018

the key about litex (migen): *massive* incrreases in efficiency of the
auto-generated Verilog source.  far, far less resources utilised.

l.



More information about the libre-riscv-dev mailing list