/// 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