[libre-riscv-dev] HDL selection

Jacob Lifshay programmerjake at gmail.com
Sun Nov 18 20:24:59 GMT 2018


On Sat, Nov 17, 2018, 06:08 Luke Kenneth Casson Leighton <lkcl at lkcl.net
wrote:

> 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!
>
I think that's to enforce that read declarations have to come before write
declarations. Not sure why they are doing that.

> (2) what on earth is a "=/=" operator?
>
Inequality operator for generated code:
https://github.com/freechipsproject/chisel3/wiki/Builtin-Operators

> (3) what's an _2?
>
second element of a tuple

> (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?
>
Missing; they probably figured it was obvious from the code: You'd use it
like:
val rf = new RegFile(31 /* register count */, 64 /* XLEN */, true /*
reading the zero reg returns zero */);
rf.write(rd, rf.read(rs1) + rf.read(rs2)); // generates a 2R1W register
file because read is called twice and write is called once where write
enable is rd =/= 0

> (5) what order are the parameters to "Mux"? what kind of "Mux" is it?
>
2-input mux: Mux(a, b, c) is the generated code version of C's a ? b : c
https://github.com/freechipsproject/chisel3/wiki/Builtin-Operators

>
> 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.
>
I don't litex is any better/worse than chisel for resource utilization,
it's just that they are both better than the IP that comes with Vivado,
which is particularly terrible. Note that I haven't tested anything
personally though.

Jacob


More information about the libre-riscv-dev mailing list