Showing posts with label SystemVerilog. Show all posts
Showing posts with label SystemVerilog. Show all posts

Thursday, November 15, 2018

Kudos to Edaphic Studio

I have previously talked about my use of IntelliJ as my primary development environment for Scala, C++ (CLion), JavaScript (Webstorm), and Python (PyCharm). I cannot recommend it enough. As luck would have it, a company is developing an IntelliJ plugin for Verilog and SystemVerilog. The plugin is in beta phase but remains exceptionally usable. The author is responsive in addressing my bug reports. Most refreshing is the tools' transparent pricing structure. No EDA sales representatives to deal with!

In summary, I wholeheartedly recommend hardware developers check out: https://www.edaphic.studio/.

Monday, September 25, 2017

Example function to enhance Chisel bundle connection

Here's a real world example that demonstrates the flexibility of Chisel (or DSLs in general) compared to traditional languages for describing hardware.

It is my opinion that SystemVerilog's promise of making module connection more user (and verification) friendly has not been realized.  The interface construct was a good first step, so were interface modports.  The .* connection operator or parameterizable interfaces, not so much.  Traditional teams send their best (aka. quickest) Perl monkey to the rescue and, just like that, a new target for feature creep and "I'm busy, fix the script yourself" is created.

You have access to an API when using an internal DSL approach (such as Chisel).  If you wanted to write your own function to connect to arbitrary hardware interfaces - you do it.  This doesn't directly eliminate feature creep, but provides a better framework for development than Perl/RegEx can offer.  Consider this tradeoff.  How many lines of parsing, data structure definition, testing and software regression strategies are needed compared to a few lines of Scala.

Here's an example from my private repo.  It takes two Bundles as input and connects fields with matching names.

final def connect(left: Bundle, right: Bundle)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = {
  (left.elements.toSeq ++ right.elements.toSeq) // Map to Seq, then combine lhs and rhs
    .groupBy(_._1) // group by name of
    .filter(_._2.length == 2) // filter out non matches
    .foreach {
      case (k, v) => {
        (lhs.dir, rhs.dir) match {
          case (NODIR, NODIR) => attach(lhs.asInstanceOf[Analog], rhs.asInstanceOf[Analog]) // to support INOUT ports
          case (INPUT, OUTPUT) => rhs := lhs
          case (OUTPUT, INPUT) => lhs := rhs
          case (INPUT, INPUT) => rhs := lhs // TODO: verify more
          case (OUTPUT, OUTPUT) => lhs := rhs // TODO: verify mode
        }
      }
    }

PS. Slowly, but surely, I'm becoming functional.


Its difficult for the time being, especially without a IDE.  IntelliJ IDEA is terrific.  Still can't properly explain a Monad.  The ability to highlight a val, then hit "Alt-Enter", select "Add Type annotation to value definition", provides immeasurable value.  Here's an example.  By breaking up different parts of the above function, I can better determine (before compile time) the type of data structure that will be output.


    val a: Map[String, Data] = left.elements
    val b: Map[String, Data] = right.elements
    val c: Seq[(String, Data)] = a.toSeq
    val d: Seq[(String, Data)] = a.toSeq ++ b.toSeq
    val e: Map[String, Seq[(String, Data)]] = d.groupBy(_._1)

Wednesday, June 18, 2014

Wednesday Night Hack #4 - Commentary on SystemVerilog-Design Interface Example

I did not get around to synthesizing the example in Chapter 10 of Sutherland's book (refer to my previous post).  Instead, I have some comments about the published example. Most of my time tonight was spent preparing BARF for release.

To keep this post concise, I won't post snippets.  A copy of the source code can be found here.

Comment #1 : Modports TopReceive and CoreReceive are duplicated in interface Utopia.  I don't understand the decision to duplicate the modports.  The SVTB interface should describe the Utopia interface.  The Utopia interface is a set of signals and those signals can either be seen from point-of-view of receiver or transmitter.

Comment #2: The author made an interesting decision to model the register file using interface LookupTable.  I understand what he's trying to do -- DNR, do not repeat (yourself).  His control logic calls a function to read or write a memory array.  The function and memory array live in the interface rather than the module.  If you expect the synthesis tool to infer memories from RTL code, then it's a viable option.  If you need the ability to manually instantiate library cells for memory, then it's not so viable - you cannot instantiate modules within an interface.  I am somewhat weary about the approach for the following reason.  Yes, you can start with synthesis-inferred memory arrays, but what happens when/if you need to move to custom cells?  Then, the interface may not be able to serve its original purpose.

Comment #3: Why didn't author have the main FSM use signals in interfaces rather than drive temporary signals which are then assigned to the interface nets.

bit [0:NumTx-1] Txvalid; // FSM 'drives' this

for (TxIter=0; TxIter<NumTx; TxIter+=1) begin: GenTx
  assign Tx[TxIter].valid = Txvalid[TxIter] // assign to ifc

Comment #4: Combined blocking and non-blocking assignment in rx_valid_state

This example is all kinds of confusing.  I had to turn to StackOverflow to understand what was going on and I'm still not entirely clear how exactly that RTL code gets translated into gates.  The logic basically says to rotate the the round-robin pointer until one of the receivers has a valid cell that is ready to be processed.  Then, the cell is latched and the FSM advances to the next state.  It's an interesting strategy that I assume works because of SystemVerilog's always_ff.

Comment #5: What did I learn about networking?

Not much.  That ATM is a very old protocol.  That ATM is has nearly 10% "cell tax", meaning the header makes up that much of the total size of the cell.  The purpose of the design is to take in incoming ATM cells and arbitrate among receivers.  After a receiver is selected, the register file is accessed update the to-be-transmitted cell's VPI and compute it's new header error control (HEC) value.  Finally, there are two state machine that receive and transmit the cells according to Utopia protocol.

Thursday, June 12, 2014

Planning Ahead - SystemVerilog-Design and Networking Hardware

Chapter 10 of SystemVerilog for Design showcases the design of a Asynchronous Transfer Mode (ATM) user-to-network interface (UNI) and forwarding node.

I have no idea what that means.  Besides configuring home routers and configuring Windows / Linux PC to access them, I have next-to-no background in low-level computer networking.

The chapter also claims to summarize the SystemVerilog-Design concepts presented in the book.

I think it will be an interesting challenge to review the design presented in the book and attempt to implement it on my FPGA device.  It will be a good refresher for SystemVerilog-Design and I will learn a little something about networking hardware design.

I am hopeful that today's (2014) bundled synthesis tools are up for the challenge.