muchen 牧辰

Verilog Operations

Updated 2018-01-29

Loop Statements

Traditionally when we want to iterate, we use a counter. A behavior for-loop has the structure as follows

for (<initial>; <expression>; <step>)
begin
	<something>
end

A for loop can only be synthesized inside a process/always block because it is a sequential statement. It synthesizes when the loop range is constant at compile time, and does not contain WAIT statements.

The synthesizer will unroll every statements inside the for loop.

For example, some for loop code might be

for (...) begin
  P = P ^ SW[i]
end

unrolls into

P = P ^ SW[0];
P = P ^ SW[1];
P = P ^ SW[2];

Note that this example could be replaced by P=^SW

Let’s consider the ‘power of’ circuit again.

Writing out using for loops, we get

for (i=0; i < 3; i=i+1)
	P = P * X;

This will be unrolled to

always @(X)
  begin
    P = 1;
    P = P * X;
    P = P * X;
    P = P * X;
  end
endmodule

We cannot create hardware for an arbitrary number of exponents. Since we need a real, constant number in the for loop during compile time.

Loop isn’t a iterative events happening over time. It is just a shortcut to make writing hardware easier.

Loops are very useful in simulations and test benches to make life easier.

Generate Statements

Consider a problem where we have a bunch of multiplexers:

screenshot

It becomes really tedious when we have much more components to add and connect.

genvar i;

generate
  for (i=0; i<4; i=i+1) begin: big_mux
    mux_4to1 mux(W[4*i], W[4*i+1], W[4*i+1], W[4*i+2], W[4*i+3], S[1:0], M[i]);
  end
endgenerate

Notice that the assignment for mux ports depends on i. And that W is concatenated beforehand.

Similar to for loops, the generate statements will unroll it. But for loop is sequential, and generate statement is concurrent, meaning that all modules are placed at the same time in parallel.

An example of a useful scenario to use generate statements is an adder.

adder block

Note that we can also use conditional statements in the generate statement.

Tristate Logic

Normally when we have some kind of wire, it could be driven by some gate or input signal. Sometimes it is useful to have a bus where multiple module is connected to the same wire. Typically, there a module is driving the bus, and some other module that is connected to the bus is listening.

So the three states corresponding to:

What happens when the same wire is being driven by two sources? We don’t know.

page 28

When Verilog sees 0 and 1 driven into the same signal, it sets the value of the signal to X, which means the state is unknown. Note that in the real circuit, the node will always have some voltage.

page 30

Quartus synthesizer will thrown an error (Cant resolve multiple constant drivers for net).

Some how we need a control to say which one is actually driving it. Hence the tristate driver

Tristate Driver

page 32

If enable is high, out is driven with the value on in, if enable is low, the output is not being driven. Not being driven can be denoted as Z in simulation.

The truth table is as:

in enable out
0 0 Z
0 1 0
1 0 Z
1 1 1

Verilog example:

module tristate_driver9(I, ENABLE, F);
  input I, ENABLE;
  output reg F;

  always @(*)
    if (ENABLE == 1)
      F <= I;
  	else
      F <= 1'bz;
endmodule

page 37

What actually happen in FPGA’s?

People typically do not use tristate logic in their designs (because of speed issues). Modern FPGAs actually have no facility for implementing tristate drivers. (Synthesizer like Quartus will try to convert the tristate logic into multiplexer networks).

However, tristate is still used in off-chip I/O.