Intro. to Verilog and Hardware Design


  • Concatenation of Bits
  • Data Assignments
  • Models of Implementing Memory in Hardware Design
  • Concatenate Tokens
  • Coding Style

I’ll not cover the trivial part of Verilog as their resources are vastly available.

Concatenation of Bits

  • Let a, b, c be registers of bit width 2
  • Let d be register of bit width 8
  • Correct way of concatenating a, b, c
    • d = {a, {2{b}}, c}
  • Wrong way of concatenating a, b, c
    • d = {a, 2{b}, c}


Data Assignments

  • Continuous Assignment: for wire assignment
    •  Imply that whenever any change on the RHS of the assignment occurs, it
      is evaluated and assigned to the LHS.

      •  e.g.    wire [3:0] a;
        assign a = b + c;    //continuous assignment


  •  Procedural Assignment: for reg assignment
    •  assignment to “register” data types may occur within always, initial, task and function . These expressions are controlled by triggers which cause the assignment to evaluate.
      • e.g.    reg a, clk;
        always #5 clk = ~clk;    //procedural assignment
      • e.g.    always @ (b)
        a = ~b; //procedural assignment with triggers


Models of Implementing Memory in Hardware Design (Using Registers)


Declaring a 2D Array Register

memory (3).png

The diagram above shows the implementation of 2D array in Verilog where the middle part are rows of bits (depending on the registers size). It’s advisable to use this method on the implementation of 2D memory if and only if you relate 100% to the mapped synthesized logic gates.

Alternate Method of Implementing 2D Memory in Hardware (Brute Force)

  • Construct a list of registers.
  • Every register consist of a single row on the diagram above.
  • This reduces the critical path to use a single mux to either read or write a single registers.

Implementing Memory in Hardware Design based on IP Core

memory (4).png

  • IP Core provides us with the memory block in the middle of the diagram above.
  • Usually we block the input data, address and output data with a flip-flop so that datapath of other logic blocks are kept clean from time spent on SRAM.
    • You can always take off the flip-flops at the input and output of the memory and save cycles, but there might be timing constrains that can’t be met if this is done.
  • As with my experience in RTL, there’d be hold time error from the input register to Memory.
    • It works perfectly fine for GATE Level so no worries 🙂
    • To prevent that error in RTL, just add #1 delay at the RHS of the non-blocking assignment operator.
      • e.x. data <= #1 data + 1;


Concatenate Tokens [source]

`define foo(f) f“_suffix

Macro foo(f) has an argument f. The two consecutive backticks in the macro body form the “token-gluing” or concatenation operation, allowing a macro argument to be concatenated with a piece of plain text without any intervening space. So `foo(bar) expands into bar_suffix

`define \goo* g_suffix

\goo* is a Verilog escaped identifier – this works anywhere in Verilog; any string of characters, prefixed with backslash and terminated with whitespace, is a legal identifier. And it’s being used here as a macro name. Why? I dunno. Madness. Anyway, the macro invocation `\goo* WITH SOME TRAILING SPACE will expand into g_suffix


Coding Style

  • Mixing both combinational and sequential circuit in an always block is bad for debugging.
  • Only declare variables that will be used for an always block right above it.
  • Don’t simply mix blocking and non-blocking assignments.
  • Don’t make empty assignments in combinational always block
  • Don’t drive two reg in a single always block. (easier to understand the synthesized circuit, and easier for debug)
  • Don’t use else if if else is sufficient.
  • Don’t write next state current state in a design with FSM.
    • If the current state register in the hardware is faulty, at least next state can still function properly with a constant assigned to it.
  • Adding ST_xxx before a macro that represent STATES in FSM.
  • When the amount to shift is a variable, it might be hard for EDA tools to determine the corresponding synthesized circuit, thus use mux manually instead.
  • Don’t fit too much combinational circuit into a single datapath, this might be bad for the whole design as the Total Execution Time = # Cycles * Max(Datapath Delay)
  • Don’t use nested else if if there’s a chance to combine the inner else if with the outer ones.
  • Don’t use next state in logical computation. (always use current state with some assisting conditions, usually the ones used alongside with the computation of next state).
    • There won’t be extra logic units needed because same logic units will be used in determining next state in the controller for FSM and it’ll be shared.
  • Add FSM States to sync clock cycles, don’t use dummy flip-flops in between, it’s defines the system more clearly and it’s better for debugging.
  • Always have FSM state flow relative to the flow of data.
  • When multiple datum are to be outputs of a module, implement a shift register for minimal area.


Open Source Base for Hardware


Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s