/// Notes and Demos for LSU EE 4702-1 Spring 2001
// Sources: Ci: Ciletti, Modeling, synthesis, and rapid prototyping
// with the Verilog HDL
// LRM: IEEE, Verilog Language Reference Manual
/// Contents
// Conditional Statement (if)
// Looping Statements (for,while,repeat,forever)
// disable. Used for exiting loops, etc.
// Case Statements
/// Conditional Statement (if)
// Ci 7.12.3, LRM 9.4
// if( CONDITION ) IF_TRUE_STATEMENT
// if( CONDITION ) IF_TRUE_STATEMENT else IF_FALSE_STATEMENT
// If CONDITION is a non-zero number, execute IF_TRUE_STATEMENT;
// If CONDITION is zero execute IF_FALSE_STATEMENT;
// If CONDITION contains an x or z, execute IF_FALSE_STATEMENT;
module if_example();
integer a, b, x, y, the_answer, the_right_answer;
initial begin
if( 123 ) $display("This should print.");
if( 123 )
$display("This should print.");
else
$display("This should NOT print.");
if( 0 )
$display("This should NOT print.");
else
$display("This should print.");
/// if/else/if Chains
// A common way of using if.
if( a < 10 ) b = 1;
else if( a < 20 ) b = 2;
else if( a < 30 ) b = 3;
else b = 4;
/// Multiple Statements in if
// The if only affects the statement immediately following,
// so y is always assigned.
if( a < 10 ) x = 1; y = 2; // Looks like a bug.
// If it is a bug, here is the correct way:
if( a < 10 ) begin x = 1; y = 2; end
// If the intent was to always assign y, then don't be misleading:
if( a < 10 ) x = 1;
y = 2;
// Note: begin foo; bar; foobar;... end is a single statement,
// consisting of a sequential (begin/end) block.
/// If and x's and z's.
if( 1'bx )
$display("This should NOT print.");
else
$display("This should.");
if( 1'bx === 1'bx )
$display("This should print.");
else
$display("But not this.");
if( 1'bx == 1'bx )
$display("This won't print.");
else
$display("This will.");
end
endmodule
/// Looping Statements
// Ci 7.12.4, LRM 9.6
// for( INIT_ASSIGN; CONDITION; STEP_ASSIGN ) STATEMENT
// while( CONDITION ) STATEMENT
// repeat( COUNT ) STATEMENT
// forever STATEMENT
// for C programmers might find the for loop disappointing:
// INIT_ASSIGN must be an assignment, not an arbitrary statement.
// STEP_ASSIGN must be an assignment, not an arbitrary statement.
// CONDITION is an expression that evaluates to an integer.
//
// 1. Execute INIT_ASSIGN.
// 2. Evaluate CONDITION, if true go to next step, else done.
// 3. Execute STATEMENT
// 4. Execute STEP_ASSIGN;
// 5. Go to step 2.
// while
//
// 1. Evaluate CONDITION, if false done, else go to next step.
// 2. Execute STATEMENT.
// 3. Go to step 1.
// repeat
// COUNT is an expression that evaluates to an integer.
//
// 1. Evaluate COUNT, call result the_count.
// 2. Execute STATEMENT the_count times.
// forever
//
// 1. Execute STATEMENT.
// 2. Go to step 1.
// There is a mechanism for breaking out of these loops, but
// it's not as convenient as C's break.
module looping_examples();
integer a, b, c;
integer i, pop, x;
reg clock, clock2;
initial begin
/// for
// Basic for loop.
for(i=0; i<3; i=i+1) $display("yada");
// There is no postincrement operator. :-(
// for(i=0; i<3; i++) $display("yada"); // Syntax error.
// Can only have a single initialization assignment. :-(
// for(i=0, j=0; i<3; i=i+1) $display("yada"); // Syntax error.
/// while
// Basic while loop.
while( x < 10 ) x = x + 1;
// Sorry, assignment (=) is not an operator as in C.
// while( i = i - 1 ) x = x + 1; // Syntax error.
/// Three Ways to Iterate Ten Times:
// This simplest way is the best. (repeat).
for(i=0; i<10; i=i+1) x = x + 1;
repeat( 10 ) x = x + 1;
i = 10; while( i ) begin i = i - 1; x = x + 1; end
// while example, count the 1's in b.
pop = 0;
while( b )
begin
pop = pop + b[0];
b = b >> 1;
end
end
/// forever, The Right Way
initial begin
// forever is normally used with a delay control.
// Example below implements a clock with a period of 2 cycles.
clock = 0;
forever begin #1 clock = ~clock; end
// If there was a statement here it would never be executed.
// This doesn't affect code in other initials.
end
/// forever, The Wrong Way.
initial begin
clock2 = 0;
// Example below implements a clock with a period of 1 / infinity.
// Because there is no delay the simulator will never advance
// time.
// As a result the simulation will be frozen at t=0.
// (Assuming the line below were uncommented.)
forever begin clock2 = ~clock2; end // Freezes simulator.
end
endmodule
/// Named Blocks and the Disable Statement
// LRM 11
/// Naming Blocks
///
/// begin:NAME ... end
//
// Block named NAME. NAME can be any valid identifier, by convention
// block names are all upper case.
//
// Variables can be declared within a named block. (See examples.)
// Execution can be "thrown" out of block. (See example.)
//
/// Disabling Blocks (Throwing Execution)
///
/// disable BLOCKNAME
//
// Force activity (execution of code) within BLOCKNAME to continue
// at the first statement outside of BLOCKNAME.
/// Uses for Disable
// Can be used to exit from loops, to jump to the beginning of an
// iteration, etc.
module disable_example(a,b);
input a, b;
integer i;
initial begin:INITIAL_BLOCK
// Declarations allowed here because this is a named block.
integer x;
/// Disable used to exit from a for loop. (Like C's break.)
begin:BLOCK1 // Note: BLOCK1 is outside of for loop.
for(i=1; i<10; i=i+1) begin
x = x * i;
// Early exit if x > 100.
if( x > 100 ) disable BLOCK1;
end
end
/// Disable used to exit from a forever loop. (Like C's break.)
x = 1; i = 1;
begin:BLOCK2
forever begin
x = x * i; i = i + 1;
// Exit exit if x > 100.
if( x > 100 ) disable BLOCK2;
end
end
/// Disable used to exit from or continue a for loop. (Like C's break and continue.)
begin:BLOCK3_THE_OUTSIDE_BLOCK
for(i=1; i<10; i=i+1)
begin:BLOCK4_THE_INSIDE_BLOCK
x = x * i;
// Early exit if x > 100.
if( x > 100 ) disable BLOCK3_THE_OUTSIDE_BLOCK;
// Start next iteration if x > 50
if( x > 50 ) disable BLOCK4_THE_INSIDE_BLOCK;
x = x + 2; // Only executed if x <= 50.
end
end
end
/// Using disable on a non-enclosing block.
// When a changes start printing a message every cycle.
always @( a ) begin:BLOCK_X
forever begin
$display("Greetings from block x.");
#1;
end
end
// When b changes stop the messages from the code above.
always @( b ) begin
disable BLOCK_X;
end
endmodule
/// Case Statement
// LRM 9.5
// Something like C's switch statement.
// Three kinds: case, casex, casez.
// case ( EXPR )
// CASE_EXPR00, CASE_EXPR01, .. : STATEMENT0;
// CASE_EXPR10, CASE_EXPR11, .. : STATEMENT1;
// ...
// [default: STATEMENTD;]
// endcase
//
// 1. Evaluate EXPR, call result expr.
// 2. Compare expr to CASE_EXPR00, CASE_EXPR01, ..., CASE_EXPR10,
// until a match is found. Comparison is the same as case equality.
// 3. If a match is found execute the corresponding STATEMENT.
// If no match is found and default is present, execute STATEMENTD.
// CASE_EXPR can be any expression, not just a constant.
// casex ( EXPR )
// CASE_EXPR00, CASE_EXPR01, .. : STATEMENT0;
// CASE_EXPR10, CASE_EXPR11, .. : STATEMENT1;
// ...
// [default: STATEMENTD;]
// endcase
//
// Same as case except x acts as a wildcard (don't care).
// casez ( EXPR )
// CASE_EXPR00, CASE_EXPR01, .. : STATEMENT0;
// CASE_EXPR10, CASE_EXPR11, .. : STATEMENT1;
// ...
// [default: STATEMENTD;]
// endcase
//
// Same as case except z acts as a wildcard (don't care).
module Case_examples();
integer a, b, c, d;
reg cin, bita, bitb, cout, sum;
integer the_answer, the_correct_answer;
integer foo, bar, foobar;
reg [7:0] input_1, input_2, input_3, key;
reg match;
initial begin
/// Case examples.
//
case( a )
1 : $display("a is 1.");
2,3 : $display("a is 2 or maybe 3.");
b : $display("a is equal to b.");
b+c : $display("a is equal to b+c");
default : $display("a is something else.");
endcase
case( input_1 )
8'bxxxxxxxx : $display("Input_1 is unknown.");
8'bzzzzzzzz : $display("Input_1 is high impedance.");
0 : $display("Input_1 is zero.");
255 : $display("Input_1 is 255.");
endcase
case( key )
input_1: match = 1;
input_2: match = 2;
input_3: match = 3;
default: match = 0;
endcase
case( the_answer == the_correct_answer )
1 : $display("Correct.");
default : $display("Wrong.");
endcase
/// Binary Full Adder using Case
//
case( {cin, bita, bitb } )
3'b000 : begin cout = 0; sum = 0; end
3'b001, 3'b010, 3'b100 : begin cout = 0; sum = 1; end
3'b110, 3'b101, 3'b011 : begin cout = 1; sum = 0; end
3'b111 : begin cout = 1; sum = 1; end
endcase
/// Lots of Opportunity for Fun
//
case( { a > b + 1, 1'b1, c[2:0] } )
{cin, cout, 3'b101 } : foo = foo + 1;
d[10:6] : bar = bar + 1;
{1'b1,a[4:0]} : foobar = foo + bar;
default : $display("None of the above.");
endcase
end
endmodule
module Casex_examples();
reg [3:0] a, pri;
initial begin
casex( a )
4'bxxx0: $display("a is even.");
default: $display("a is odd.");
endcase
// 2001 Homework 1,2-style Priority Encoder
casex( a )
4'bxxx1: pri = 4'b0001;
4'bxx11: $display("This can't happen.");
4'bxx10: pri = 4'b0010;
4'bx110: $display("This can't happen either.");
4'bx100: pri = 4'b0100;
4'b1000: pri = 4'b1000;
default: pri = 4'b0000;
endcase
end
endmodule