• No results found

`define REG_DELAY 1

module countc(clock, reset, load, up, load_data, count);

input clock,reset, load, up;

input [15:0] load_data;

output [15:0] count;

reg [15:0] count;

always @(posedge clock) if (reset)

count <= 16'h0000;

else

if (load)

count <= #(`REG_DELAY) load_data;

else

if (up)

count <= #(`REG_DELAY) count + 16'h0001;

else

count <= #(`REG_DELAY) count - 16'h0001;

endmodule

LOOPS

The only loop that has been used so far in this book is the always loop. The always loop combines a starting point for execution with an infinite loop. The rest of the looping constructs do not imply starting places for execution. They must be contained in a procedural block of code so they have a starting point.

The forever Loop

The simplest loop is the forever loop. The forever loop is an infinite loop. The construct initial forever is almost identical in behavior to always. The forever loop contains a single statement. If you want multiple statements in the forever loop, use a begin-end block. Like the always statement, a forever loop without delay or event controls would be a zero-delay loop and inhibits simulation time from advancing.

Even though the forever loop is an infinite loop, there are two ways to stop it. The first way to stop a forever loop is with a $finish that ends simulation. The second way is to use the disable statement, which will be presented later in this chapter.

Example 10-9 and Example 10-10 compare the forever and always loops.

Example 10-9 Oscillator Using always module osc1(clock);

output clock;

reg clock;

initial begin clock = 0;

end always begin

#50 clock = ~clock;

end endmodule

Here is another version of the oscillator module using the forever loop.

Example 10-10 Oscillator Using forever module osc2(clock);

output clock;

reg clock;

initial begin clock = 0;

forever #50 clock = ~clock;

end endmodule

While the initial forever and the always loop are quite similar. Most synthesis tools do not synthesize the forever loop. The forever loop should only be used in behavioral models not intended for logic implementation or test benches.

Therepeat Loop

The repeat loop is the next simplest of the looping constructs in Verilog. The repeat loop takes some expression that will evaluate to an integer, and repeats the loop that many times. The repeat loop is similar to the forever loop in that it uses a single statement or a begin-end block.

Example 10-11 is a slight modification of the hello module in which the module prints “Hello Verilog” five times.

Example 10-11 Repeating “Hello Verilog”

module hellor;

initial repeat(5) $display("Hello Verilog");

endmodule

The repeat loop has uses in state machines, such as the simple shifter state machine shown in Example 10-12.

Example 10-12 Using repeat in a State Machine

`define REG_DELAY 1

module shift1(clock,start,data,s,out,done);

input clock,start;

input [15:0] data;

input [3:0] s;

output [15:0] out;

reg [15:0] out;

output done;

reg done;

always @(posedge clock) if (start) begin

done <= #(`REG_DELAY) 1'b0;

out <= #(`REG_DELAY) data;

repeat (s) // number of times to shift

@(posedge clock) out <= #(`REG_DELAY) out << 1;

@(posedge clock) done <= #(`REG_DELAY) 1'b1;

end endmodule

Please note that this is not the most simulation-efficient way to implement this shifter. Chapter 17 discusses performance issues and other shifter models will be presented.

Depending on the usage and synthesis tool, the repeat loop may be synthesizable.

The while Loop

The while loop is executed as long as its condition is true. Example 10-13 counts the number of 1s in an input signal.

Example 10-13 A while Loop

`define REG_DELAY 1

module onecount(clock,start,data,count,done);

input clock,start;

input [15:0] data;

reg [15:0] temp_data;

output [3:0] count;

reg [3:0] count;

output done;

reg done;

always @(posedge clock) if (start) begin

done <= #(`REG_DELAY) 1'b0;

count <= #(`REG_DELAY) 1'b0;

temp_data = data;

while(temp_data) begin// continue as long as non zero

@(posedge clock)

if (temp_data[0]) count <= #(`REG_DELAY) count + 1;

temp_data = temp_data >> 1;

end

@(posedge clock)

done <= #(`REG_DELAY) 1'b1;

end endmodule

Depending on the usage and synthesis tool, the while loop may be synthesizable.

The for Loop

The expression for the for loop is a bit more complicated. The for loop uses three expressions separated by semicolons to control the loop. The first expression (the initialization expression) is executed once before entering the loop the first time.

The second expression (the loop condition) is evaluated to determine if the contents of the loop should be executed. If the loop condition expression is true, the loop is entered. The final expression (the increment expression) is evaluated at the end of the loop.

Example 10-14 is another version of the hello module with a for loop. Notice the expression i=i+l in the loop. Those familiar with programming in C might try the ++ unary operator. A quick review of Chapter 8 will remind you that Verilog, unlike C, does not have a ++ operator.

Example 10-14 A Simplefor loop module hellof;

integer i;

initial for(i=0; i<5; i=i+1)

$display("Hello Verilog %0d", i);

endmodule

Because the expressions in the for loop all don’t need to reference the same register or variable, the for loop in Example 10-15 is also legal.

Example 10-15 A for Loop with Expressions Not Referencing the Same Variable

module for2;

reg [7:0] a,b,c,d;

initial begin

c = 9; // If c==0 the loop will not enter.

b = 3;

d = 0;

for(a = b; c; d=a) begin a = a + d;

c = c - b;

end

$display("a= %d, b=%d, c= %d, d=%d, OK?", a, b, c, d) ; end

endmodule

Depending on the usage and synthesis tool, the for loop may be synthesizable.

With the high level code you have just learned, you can now start to model more complex behavior. Take a break from the reading and try some exercises to practice what you have just learned.

Exercise 4 Using Expressions and case

In this exercise you will model a simple arithmetic logic unit (ALU). This will give you a chance to practice using text macros, the always statement, the case statement, and some expressions. The ALU has sixteen functions. These are described below. The ALU has three inputs: The a and b operands (16 bits), and the function select input (4 bits). The ALU has four outputs: aluout (the 16-bit result), a zero flag; a parity flag, and a carry flag. The ALU is combinatorial. The carry flag is the seventeenth bit of the result of addition, subtraction, shifts, and rotates. All of the operations generate a result in the carry. The zero flag is set if all the low 16 bits of aluout are 0. The parity flag is set if an odd number of bits is set in aluout.

Here are the opcodes for the ALU:

`define move 4'b0000 /* out = b */

`define comp 4'b0001 /* out = complement(b) */

`define and 4'b0010 /* out = a AND b */

`define or 4'b0011 /* out = a OR b */

`define xor 4'b0100 /* out = a XOR b */

`define add 4'b0101 /* out = a PLUS b */

`define incr 4'b0110 /* out = b PLUS 1*/

`define sub 4'b0111 /* out = a MINUS b */

`define rotl 4'b1000 /* out = rotate b left*/

`define lshl 4'b1001

/* out = logical shift left*/

`define rotr 4'b1010

/* out = rotate b right one bit */

`define lshr 4'b1011

/* out = logical shift b right one bit*/

`define xnor 4'b1100 /* out = a XNOR b */

`define nor 4'b1101 /* out = a NOR b */

`define decr 4'b1110 /* out = b MINUS 1 */

`define nand 4'b1111 /* out = a NAND b */

The operations are detailed in Table 10-2, Figure 10-1, Figure 10-2, Figure 10-3, and Figure 10-4.

Example 10-16 illustrates a test bench for the ALU.

Related documents