verilog tutorial for beginners, Exercises of Digital Systems Design

This helps in understanding some of the basics of verilog

Typology: Exercises

2016/2017

Uploaded on 04/28/2017

hemalatha-m-1
hemalatha-m-1 🇮🇳

1 document

1 / 50

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
ECE 5745 Complex Digital ASIC Design, Spring 2016
Tutorial 4: Verilog Hardware Description Language
School of Electrical and Computer Engineering
Cornell University
revision: 2016-03-21-00-48
1 Introduction 3
2 Verilog Modeling: Synthesizable vs. Non-Synthesizable RTL 4
3 Verilog Basics: Data Types, Operators, and Conditionals 4
3.1 HelloWorld ........................................... 4
3.2 LogicDataTypes ........................................ 5
3.3 ShiftOperators ......................................... 10
3.4 ArithmeticOperators...................................... 11
3.5 RelationalOperators ...................................... 12
3.6 ConcatenationOperators.................................... 14
3.7 EnumDataTypes ........................................ 15
3.8 StructDataTypes ........................................ 17
3.9 TernaryOperator ........................................ 19
3.10IfStatements........................................... 20
3.11CaseStatements......................................... 21
3.12CasezStatements ........................................ 22
4 Registered Incrementer 22
4.1 RTL Model of Registered Incrementer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2 Simulating a Model using iverilog ............................. 25
4.3 Verifying a Model with Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.4 Reusing a Model with Structural Composition . . . . . . . . . . . . . . . . . . . . . . . 29
4.5 Parameterizing a Model with Static Elaboration . . . . . . . . . . . . . . . . . . . . . . 31
5 Sort Unit 33
5.1 FlatSorterImplementation................................... 33
5.2 UsingVerilogLineTraces ................................... 37
5.3 Structural Sorter Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.4 Evaluating the Sorter Using a Simulator . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32

Partial preview of the text

Download verilog tutorial for beginners and more Exercises Digital Systems Design in PDF only on Docsity!

Tutorial 4: Verilog Hardware Description Language

School of Electrical and Computer Engineering

 - ECE 5745 Complex Digital ASIC Design, Spring - revision: 2016-03-21-00- Cornell University 
  • 1 Introduction
  • 2 Verilog Modeling: Synthesizable vs. Non-Synthesizable RTL
  • 3 Verilog Basics: Data Types, Operators, and Conditionals
    • 3.1 Hello World
    • 3.2 Logic Data Types
    • 3.3 Shift Operators
    • 3.4 Arithmetic Operators
    • 3.5 Relational Operators
    • 3.6 Concatenation Operators
    • 3.7 Enum Data Types
    • 3.8 Struct Data Types
    • 3.9 Ternary Operator
    • 3.10 If Statements
    • 3.11 Case Statements
    • 3.12 Casez Statements
  • 4 Registered Incrementer
    • 4.1 RTL Model of Registered Incrementer
    • 4.2 Simulating a Model using iverilog
    • 4.3 Verifying a Model with Unit Testing
    • 4.4 Reusing a Model with Structural Composition
    • 4.5 Parameterizing a Model with Static Elaboration
  • 5 Sort Unit
    • 5.1 Flat Sorter Implementation
    • 5.2 Using Verilog Line Traces
    • 5.3 Structural Sorter Implementation
    • 5.4 Evaluating the Sorter Using a Simulator
  • 6 Greatest Common Divisor: Verilog Design Example
    • 6.1 Control/Datapath Split Implementation
    • 6.2 Evaluating GCD Unit using a Simulator
  • 7 TravisCI for Continuous Integration

2. Verilog Modeling: Synthesizable vs. Non-Synthesizable RTL

Verilog is a powerful language that was originally intended for building simulators of hardware as opposed to models that could automatically be transformed into hardware (e.g., synthesized to an FPGA or ASIC). Given this, it is very easy to write Verilog code that does not actually model any kind of realistic hardware. Indeed, we actually need this feature to be able to write clean and productive assertions and line tracing. Non-synthesizable Verilog modeling is also critical when implementing test harnesses. So students must be very diligent in actively deciding whether or not they are writing synthesizable register-transfer-level models or non-synthesizable code. Students must always keep in mind what hardware they are modeling and how they are modeling it!

Students’ design work will almost exclusively use synthesizable register-transfer-level (RTL) models. It is acceptable to include a limited amount of non-synthesizable code in students’ designs for the sole purpose of debugging, assertions, or line tracing. If the student includes non-synthesizable code in their actual design (i.e., not the test harness), they must explicitly demarcate this code by wrapping it in ‘ifndef SYNTHESIS and ‘endif. This explicitly documents the code as non-synthesizable and aids automated tools in removing this code before synthesizing the design. If at any time students are unclear about whether a specific construct is allowed in a synthesizable concurrent block, they should ask the instructors.

Appendix A includes a table that outlines which Verilog constructs are allowed in synthesizable RTL, which constructs are allowed in synthesizable RTL with limitations, and which constructs are explic- itly not allowed in synthesizable RTL. There are no limits on using the Verilog preprocessor, since the preprocessing step happens at compile time. Unlike ECE 4750, these rules are more of a sugges- tion than hard rules. Students are allowed to use anything that Synopsys Design Compiler can synthesize. If you figure out that Synopsys Design Compiler can synthesize a more sophisticated syntax that significantly simplifies your design, then by all means use that syntax.

3. Verilog Basics: Data Types, Operators, and Conditionals

We will begin by writing some very basic code to explore Verilog data types, operators, and condi- tionals. We will not be modeling actual hardware yet; we are just experimenting with the language. Start by creating a build directory to work in.

% mkdir ${TUTROOT}/build % cd ${TUTROOT}/build

3.1. Hello World

Create a new Verilog source file named hello-world.v with the contents shown in Figure 1 using your favorite text editor. A module is the fundamental hardware building block in Verilog, but for

1 module top; 2 initial begin 3 $display( "Hello World!" ); 4 end 5 endmodule Code at https://github.com/cbatten/x/blob/master/ex-basics-hello-world.v

Figure 1: Verilog Basics: Display Statement – The obligatory “Hello, World!” program to compiling a basic Verilog program.

now we are simply using it to encapsulate an initial block. The initial block specifies code which should be executed “at the beginning of time” when the simulator starts. Since real hardware cannot do anything “at the beginning of time” initial blocks are not synthesizable and you should not use them in the synthesizable portion of your designs. However, initial blocks can be useful for test harnesses and when experimenting with the Verilog language. The initial block in Figure 1 contains a single call to the display system task which will output the given string to the console. We will be using iverilog to compile Verilog models into simulators in the beginning of this tu- torial before we turn our attention to using Verilator. You can run iverilog as follows to compile hello-world.v.

% cd ${TUTROOT}/build % iverilog -g2012 -o hello-world hello-world.v

The -g2012 option tells iverilog to accept newer SystemVerilog syntax, and the -o specifies the name of the simulator that iverilog will create. You can run this simulator as follows.

% cd ${TUTROOT}/build % ./hello-world

As discussed in the Linux tutorial you can compile the Verilog and run the simulator in a single step.

% cd ${TUTROOT}/build % iverilog -g2012 -o hello-world hello-world.v && ./hello-world

This makes it easy to edit the Verilog source file, quickly recompile, and test your changes by switch- ing to your terminal, pressing the up-arrow key, and then pressing enter.

H To-Do On Your Own: Edit the string that is displayed in this simple program, recompile, and rerun the simulator.

3.2. Logic Data Types

To understand any new modeling language we usually start by exploring the primitive data types for representing values in a model. Verilog uses a combination of the wire and reg keywords which interact in subtle and confusing ways. SystemVerilog has simplified modeling by introducing the logic data type. We will be exclusively using logic as the general-purpose, hardware-centric data type for modeling a single bit or multiple bits. Each bit can take on one of four values: 0, 1, X, Z. X is used to represent unknown values (e.g., the state of a register on reset). Z is used to represent high-impedance values. Although we will use variables with X values in this course, we will not use variables with Z values (although you may see Z values if you forget to connect an input port of a module). Table 1 shows the operators that we will be primarily using in this course. Note that Verilog and SystemVerilog support additional operators including * for multiplication, / for division, % for mod- ulus, ** for exponent, and ===/!=== for special equality checks. There may occasionally be reasons to use one of these operators in your assertion or line tracing logic. However, these operators are either not synthesizable or synthesize poorly, so students are not allowed to use these operators in the synthesizable portion of their designs.

1 module top; 2 3 // Declare single-bit logic variables. 4 5 logic a; 6 logic b; 7 logic c; 8 9 initial begin 10 11 // Single-bit literals 12 13 a = 1'b0; $display( "1'b0 = %x ", a ); 14 a = 1'b1; $display( "1'b1 = %x ", a ); 15 a = 1'bx; $display( "1'bx = %x ", a ); 16 a = 1'bz; $display( "1'bz = %x ", a ); 17 18 // Bitwise logical operators for doing AND, OR, XOR, and NOT 19 20 a = 1'b0; 21 b = 1'b1; 22 23 c = a & b; $display( "0 & 1 = %x ", c ); 24 c = a | b; $display( "0 | 1 = %x ", c ); 25 c = a ^ b; $display( "0 ^ 1 = %x ", c ); 26 c = ~b; $display( "~1 = %x ", c ); 27 28 // Bitwise logical operators for doing AND, OR, XOR, and NOT with X 29 30 a = 1'b0; 31 b = 1'bx; 32 33 c = a & b; $display( "0 & x = %x ", c ); 34 c = a | b; $display( "0 | x = %x ", c ); 35 c = a ^ b; $display( "0 ^ x = %x ", c ); 36 c = ~b; $display( "~x = %x ", c ); 37 38 // Boolean logical operators 39 40 a = 1'b0; 41 b = 1'b1; 42 43 c = a && b; $display( "0 && 1 = %x ", c ); 44 c = a || b; $display( "0 || 1 = %x ", c ); 45 c = !b; $display( "!1 = %x ", c ); 46 47 end 48 49 endmodule

Code at https://github.com/cbatten/x/blob/master/ex-basics-logic-sbit.v

Figure 2: Verilog Basics: Single-Bit Logic and Logical Operators – Experimenting with single-bit logic variables and literals, logical bitwise operators, and logical boolean operators.

Multi-bit logic types are used for modeling bit vectors. Figure 3 shows an example program that illustrates multi-bit logic types. Create a new Verilog source file named logic-mbit.v and copy some or all of this code. Compile this source file and run the resulting simulator. Lines 5–8 declares multi-bit logic variables. The square brackets contain the index of the most- significant and the least-significant bit. In this course, you should always use zero as the index of the least significant bit. Note that to declare a four-bit logic value, we use [3:0] not [4:0]. Lines 14–17 illustrate multi-bit literals that can be used to declare constant values. These literals have the following general syntax: where can be b for binary, h for hexadecimal, or d for decimal. It is legal to include underscores in the literal, which can be helpful for improving the readability of long literals. Lines 24–28 illustrate multi-bit versions of the basic bitwise logic operators. As before, we should always ask ourselves, “What will happen if one of the inputs is an X?” Lines 35–39 illustrate what happens if two bits in the second value are Xs. Note that some bits in the result are X and some can be guaranteed to be either a 0 or 1. Lines 45–50 illustrate the reduction operators. These operators take a multi-bit logic value and com- bine all of the bits into a single-bit value. For example, the OR reduction operator (|) will OR all of the bits together.

H To-Do On Your Own: We will use relational operators (e.g., ==) to compare two multi-bit logic values, but see if you can achieve the same effect with the bitwise XOR/XNOR operators and OR/NOR reduction operators.

3.3. Shift Operators

Figure 4 illustrates three shift operators on multi-bit logic values. Create a new Verilog source file named logic-shift.v and copy some or all of this code. Compile this source file and run the result- ing simulator. Notice how the logical shift operators (<<, >>) always shift in zeros, but the arithmetic right shift operator (>>>) replicates the most-significant bit. Verilog requires that the left-hand operand to the arithmetic shift operator be explicitly denoted as signed, which we have done using the signed system task. We recommend this approach and avoiding the use of signed data types.

H To-Do On Your Own: Experiment different multi-bit logic values and shift amounts.

1 module top; 2 3 logic [7:0] A; 4 logic [7:0] B; 5 logic [7:0] C; 6 7 initial begin 8 9 // Fixed shift amount for logical shifts 10 11 A = 8'b1110_0101; 12 13 C = A << 1; $display( "8'b1110_0101 << 1 = %b", C ); 14 C = A << 2; $display( "8'b1110_0101 << 2 = %b", C ); 15 C = A << 3; $display( "8'b1110_0101 << 3 = %b", C ); 16 17 C = A >> 1; $display( "8'b1110_0101 >> 1 = %b", C ); 18 C = A >> 2; $display( "8'b1110_0101 >> 2 = %b", C ); 19 C = A >> 3; $display( "8'b1110_0101 >> 3 = %b", C ); 20 21 // Fixed shift amount for arithmetic shifts 22 23 A = 8'b0110_0100; 24 25 C = $signed(A) >>> 1; $display( "8'b0110_0100 >>> 1 = %b", C ); 26 C = $signed(A) >>> 2; $display( "8'b0110_0100 >>> 2 = %b", C ); 27 C = $signed(A) >>> 3; $display( "8'b0110_0100 >>> 3 = %b", C ); 28 29 A = 8'b1110_0101; 30 31 C = $signed(A) >>> 1; $display( "8'b1110_0101 >>> 1 = %b", C ); 32 C = $signed(A) >>> 2; $display( "8'b1110_0101 >>> 2 = %b", C ); 33 C = $signed(A) >>> 3; $display( "8'b1110_0101 >>> 3 = %b", C ); 34 35 // Variable shift amount for logical shifts 36 37 A = 8'b1110_0101; 38 B = 8'd2; 39 40 C = A << B; $display( "8'b1110_0101 << 2 = %b", C ); 41 C = A >> B; $display( "8'b1110_0101 >> 2 = %b", C ); 42 43 end 44 45 endmodule Code at https://github.com/cbatten/x/blob/master/ex-basics-logic-shift.v Figure 4: Verilog Basics: Shift Operators – Experimenting with logical and arithmetic shift operators and fixed/variable shift amounts.

3.4. Arithmetic Operators

Figure 5 illustrates the addition and subtraction operators for multi-bit logic values. Create a new Verilog source file named logic-arith.v and copy some or all of this code. Compile this source file and run the resulting simulator. These operators treat the multi-bit logic values as unsigned integers. Although Verilog does include support for signed arithmetic, these constructs may not be synthesizable so you are required to use only unsigned arithmetic. Also recall that *, /, %, ** are not allowed in the synthesizable portion of your design. Note that carefully considering the bitwidths of the input and output variables is important. Lines 22– 23 illustrate overflow and underflow. You can see that if you overflow the bitwidth of the output variable then the result will simply wrap around. Similarly, since we are using unsigned arithmetic negative numbers wrap around. This is also called modular arithmetic.

H To-Do On Your Own: Try writing some code which does a sequence of additions resulting in overflow and then a sequence of subtractions that essentially undo the overflow. For example, try 200 + 400 + 400 - 400 - 400. Does this expression produce the expected answer even though the intermediate values overflowed?

1 module top; 2 3 logic [7:0] A; 4 logic [7:0] B; 5 logic [7:0] C; 6 7 initial begin 8 9 // Basic arithmetic with no overflow or underflow 10 11 A = 8'd28; 12 B = 8'd15; 13 14 C = A + B; $display( "8'd28 + 8'd15 = %d", C ); 15 C = A - B; $display( "8'd28 - 8'd15 = %d", C ); 16 17 // Basic arithmetic with overflow and underflow 18 19 A = 8'd250; 20 B = 8'd15; 21 22 C = A + B; $display( "8'd250 + 8'd15 = %d", C ); 23 C = B - A; $display( "8'd15 - 8'd250 = %d", C ); 24 25 end 26 27 endmodule Code at https://github.com/cbatten/x/blob/master/ex-basics-logic-arith.v Figure 5: Verilog Basics: Arithmetic Operators – Experimenting with arithmetic operators for addi- tion and subtraction.

1 module top; 2 3 // Declare multi-bit logic variables 4 5 logic a; // 1-bit logic variable 6 logic [ 3:0] A; // 4-bit logic variable 7 logic [ 3:0] B; // 4-bit logic variable 8 9 initial begin 10 11 // Relational operators 12 13 A = 4'd15; B = 4'd09; 14 15 a = ( A == B ); $display( "(15 == 9) = %x", a ); 16 a = ( A != B ); $display( "(15 != 9) = %x", a ); 17 a = ( A > B ); $display( "(15 > 9) = %x", a ); 18 a = ( A >= B ); $display( "(15 >= 9) = %x", a ); 19 a = ( A < B ); $display( "(15 < 9) = %x", a ); 20 a = ( A <= B ); $display( "(15 <= 9) = %x", a ); 21 22 // Relational operators when some bits are X 23 24 A = 4'b1100; B = 4'b10xx; 25 26 a = ( A == B ); $display( "(4'b1100 == 4'b10xx) = %x", a ); 27 a = ( A != B ); $display( "(4'b1100 != 4'b10xx) = %x", a ); 28 a = ( A > B ); $display( "(4'b1100 > 4 'b10xx) = %x", a ); 29 a = ( A < B ); $display( "(4'b1100 < 4 'b10xx) = %x", a ); 30 31 // Signed relational operators 32 33 A = 4'b1111; // -1 in twos complement 34 B = 4'd0001; // 1 in twos complement 35 36 a = ( A > B ); $display( "(-1 > 1) = %x", a ); 37 a = ( A < B ); $display( "(-1 < 1) = %x", a ); 38 a = ( $signed(A) > $signed(B) ); $display( "(-1 > 1) = %x", a ); 39 a = ( $signed(A) < $signed(B) ); $display( "(-1 < 1) = %x", a ); 40 41 end 42 43 endmodule

Code at https://github.com/cbatten/x/blob/master/ex-basics-logic-relop.v Figure 6: Verilog Basics: Relational Operators – Experimenting with relational operators.

3.6. Concatenation Operators

Figure 7 illustrates the concatenation operators used for creating larger bit vectors from multiple smaller bit vectors. Create a new Verilog source file named logic-concat.v and copy some or all of this code. Compile this source file and run the resulting simulator. Lines 18–20 illustrate concatenating three four-bit logic variables and then assigning the result to a 12-bit logic variable. Lines 25–26 illustrate concatenating a four-bit logic variable with an eight-bit logic variable. The repeat operator can be used to duplicate a given logic variable multiple times when creating larger bit vectors. On Line 33, we replicate a four-bit logic value three times to create a 12-bit logic value.

H To-Do On Your Own: Experiment with different variations of concatenation and the repeat opera- tor to create interesting bit patterns.

1 module top; 2 3 logic [ 3:0] A; // 4-bit logic variable 4 logic [ 3:0] B; // 4-bit logic variable 5 logic [ 3:0] C; // 4-bit logic variable 6 logic [ 7:0] D; // 18-bit logic variable 7 logic [11:0] E; // 12-bit logic variable 8 9 initial begin 10 11 // Basic concatenation 12 13 A = 4'ha; 14 B = 4'hb; 15 C = 4'hc; 16 D = 8'hde; 17 18 E = { A, B, C }; $display( "{ 4'ha, 4'hb, 4'hc } = %x", E ); 19 E = { C, A, B }; $display( "{ 4'hc, 4'ha, 4'hb } = %x", E ); 20 E = { B, C, A }; $display( "{ 4'hb, 4'hc, 4'ha } = %x", E ); 21 22 E = { A, D }; $display( "{ 4'ha, 8 'hde } = %x", E ); 23 E = { D, A }; $display( "{ 8'hde, 4'ha } = %x", E ); 24 25 E = { A, 8'hf0 }; $display( "{ 4'ha, 8 'hf0 } = %x", E ); 26 E = { 8'hf0, A }; $display( "{ 8'hf0, 4'ha } = %x", E ); 27 28 // Repeat operator 29 30 A = 4'ha; 31 B = 4'hb; 32 33 E = { 3{A} }; $display( "{ 4'ha, 4'ha, 4'ha } = %x", E ); 34 E = { A, {2{B}} }; $display( "{ 4'ha, 4'hb, 4'hb } = %x", E ); 35 36 end 37 38 endmodule Code at https://github.com/cbatten/x/blob/master/ex-basics-logic-concat.v Figure 7: Verilog Basics: Concatenation Operators – Experimenting with the basic concatenation operator and the repeat operator.

1 // Declare enum type 2 3 typedef enum logic [$clog2(4)-1:0] { 4 STATE_A, 5 STATE_B, 6 STATE_C, 7 STATE_D 8 } state_t; 9 10 module top; 11 12 // Declare variables 13 14 state_t state; 15 logic result; 16 17 initial begin 18 19 // Enum lable literals 20 21 state = STATE_A; $display( "STATE_A = %d", state ); 22 state = STATE_B; $display( "STATE_B = %d", state ); 23 state = STATE_C; $display( "STATE_C = %d", state ); 24 state = STATE_D; $display( "STATE_D = %d", state ); 25 26 // Comparisons 27 28 state = STATE_A; 29 30 result = ( state == STATE_A ); 31 $display( "( STATE_A == STATE_A ) = %x", result ); 32 33 result = ( state == STATE_B ); 34 $display( "( STATE_A == STATE_B ) = %x", result ); 35 36 result = ( state != STATE_A ); 37 $display( "( STATE_A != STATE_A ) = %x", result ); 38 39 result = ( state != STATE_B ); 40 $display( "( STATE_A != STATE_B ) = %x", result ); 41 42 end 43 44 endmodule

Code at https://github.com/cbatten/x/blob/master/ex-basics-enum.v

Figure 8: Verilog Basics: Enum Data Types – Experimenting with enum data types including setting the value of an enum using a label and using the equality operator.

3.8. Struct Data Types

User-defined structures are now supported in SystemVerilog. Figure 9 illustrates creating and using a struct type for holding a variable with predefined named bit fields. Create a new Verilog source file named struct.v and copy all of this code. Compile this source file and run the resulting simulator. Lines 3–7 declare a new struct type named point_t. Again note that point_t is not a new variable but is instead a new type. As before we use the _t suffix to distinguish type names from variable names. Note that after the struct keyword we have included the packed keyword which specifies that variables of this type should have an equivalent underlying logic storage. SystemVerilog also includes support for unpacked structs, but in this course, you should limit yourself to the exact syntax shown in this example. In addition to declaring the name of the new struct type, we also declare the named bit fields within the new struct type. The order of these bit fields is important; the first field will go in the most significant position of the underlying logic storage, the second field will go in the next position, and so on. Lines 13–14 declare two new variables of type point_t. Line 18 declares a new logic variable with a bitwidth large enough to hold a variable of type point_t. We can use the bits system task to easily determine the total number of bits required to store a struct type. Lines 24–26 set the three fields of the point variable and Lines 28–30 read these three fields in order to display them. Line 34 copies one point variable into another point variable. Line 42 and 49 illustrate how to convert a point variable to/from a basic logic variable. There are several advantages to using a struct type compared to the basic logic type to represent a variable with a predefined set of named bit fields including: (1) more directly capturing the de- signer’s intent to improve code quality; (2) reducing the syntactic overhead of managing bit fields; and (3) preventing mistakes in modifying bit fields and in accessing bit fields.

H To-Do On Your Own: Create a new struct type for holding the an RGB color pixel. The struct should include three fields named red, green, and blue. Each field should be eight bits. Experi- ment with reading and writing these named fields.

3.9. Ternary Operator

Figure 10 illustrates using the ternary operator for conditional execution. Create a new Verilog source file named ternary.v and copy some or all of this code. Compile this source file and run the resulting simulator. Lines 12–19 illustrate using the ternary operator to choose what value to assign to the logic variable c. We can nest multiple ternary operators to com- pactly create expressions with multiple conditions. Lines 23–31 illustrate using four levels of nesting to choose among four different values for assigning c. Lines 35–53 illustrate how the ternary operator functions if the conditional is unknown. In lines 35–43, all bits of the conditional are unknown, while in lines 45–53 only one bit of the conditional is unknown. If you examine the output from this simulator, you will see that Verilog semantics re- quire any bits which can be guaranteed to be either 0 or 1 to be set as such, while the remaining bits are set to X. Regardless of the condition, the upper five bits of c are guaranteed to be 00001. Note that the four ternary operators cover all pos- sible combinations of the two-bit input, so the fi- nal value (i.e., 8’h0e) will never be used. In other words, if the conditionals contain unknowns this does not mean the condition evaluates to false. This is very different from the if statements described in the next subsection. Aside: For some reason, many students insist on writing code like this:

a = ( cond_a )? 1’b1 : 1’b0; b = ( cond_b )? 1’b0 : 1’b1;

This obfuscates the code and is not necessary. We are using a ternary operator to simply choose be- tween 0 or 1. You should just assign the result of the conditional expression to a and b like this:

a = ( cond_a ); b = !( cond_b );

H To-Do On Your Own: Experiment with different uses of the ternary operator.

1 module top; 2 3 logic [7:0] a; 4 logic [7:0] b; 5 logic [7:0] c; 6 logic [1:0] sel; 7 8 initial begin 9 10 // ternary statement 11 12 a = 8'd30; 13 b = 8'd16; 14 15 c = ( a < b )? 15 : 14; 16 $display( "c = %d", c ); 17 18 c = ( b < a )? 15 : 14; 19 $display( "c = %d", c ); 20 21 // nested ternary statement 22 23 sel = 2'b01; 24 25 c = ( sel == 2'b00 )? 8'h0a 26 : ( sel == 2'b01 )? 8'h0b 27 : ( sel == 2'b10 )? 8'h0c 28 : ( sel == 2'b11 )? 8'h0d 29 : 8 'h0e; 30 31 $display( "sel = 1, c = %b", c ); 32 33 // nested ternary statement w/ X 34 35 sel = 2'bxx; 36 37 c = ( sel == 2'b00 )? 8'h0a 38 : ( sel == 2'b01 )? 8'h0b 39 : ( sel == 2'b10 )? 8'h0c 40 : ( sel == 2'b11 )? 8'h0d 41 : 8 'h0e; 42 43 $display( "sel = x, c = %b", c ); 44 45 sel = 2'bx0; 46 47 c = ( sel == 2'b00 )? 8'h0a 48 : ( sel == 2'b01 )? 8'h0b 49 : ( sel == 2'b10 )? 8'h0c 50 : ( sel == 2'b11 )? 8'h0d 51 : 8 'h0e; 52 53 $display( "sel = x, c = %b", c ); 54 55 end 56 57 endmodule Code at https://github.com/cbatten/x/blob/ master/ex-basics-ternary.v Figure 10: Verilog Basics: Ternary Operator

- Experimenting with the ternary operator in- cluding nested statements and what happens if the conditional includes an unknown.

3.10. If Statements

Figure 11 illustrates using if statements. Create a new Verilog source file named if.v and copy some or all of this code. Compile this source file and run the resulting simulator. The if statement resembles similar constructs in many other programming languages. Lines 11– illustrate basic if statements and lines 24–33 illus- trate if/else statements. There are some subtle issues involved in how an if statement handles X values in the conditional. Lines 37–46 illustrate this issue. The sel value in this example is a single-bit X. What would we ex- pect the value of a to be after this if statement? Since the conditional is unknown, we might expect any variables that are written from within the if statement to also be unknown. In other words, we might expect the value of a to be X after this if statement. If you run this example code, you will see that the value of a is actually 8’h0b. This means that an X value in the conditional for an if state- ment is not treated as unknown but is instead sim- ply treated as if the conditional evaluated to false! This issue is called X optimism since unknowns are essentially optimistically turned into known val- ues. X optimism can cause subtle simulation/syn- thesis mismatch issues. If you are interested, there are several resources on the public course webpage that go into much more detail. For this course, we don’t need to worry too much about X optimism since we are not actually synthesizing our designs.

H To-Do On Your Own: Experiment with different if statements including nested if statements. Experiment with what happens when the con- ditional is unknown.

1 module top; 2 3 logic [7:0] a; 4 logic [7:0] b; 5 logic sel; 6 7 initial begin 8 9 // if statement 10 11 a = 8'd30; 12 b = 8'd16; 13 14 if ( a == b ) begin 15 $display( "30 == 16" ); 16 end 17 18 if ( a != b ) begin 19 $display( "30 != 16" ); 20 end 21 22 // if else statement 23 24 sel = 1'b1; 25 26 if ( sel == 1'b0 ) begin 27 a = 8'h0a; 28 end 29 else begin 30 a = 8'h0b; 31 end 32 33 $display( "sel = 1, a = %x ", a ); 34 35 // if else statement w/ X 36 37 sel = 1'bx; 38 39 if ( sel == 1'b0 ) begin 40 a = 8'h0a; 41 end 42 else begin 43 a = 8'h0b; 44 end 45 46 $display( "sel = x, a = %x ", a ); 47 48 end 49 50 endmodule Code at https://github.com/cbatten/x/blob/ master/ex-basics-if.v Figure 11: Verilog Basics: If Statements – Experimenting with if statements including what happens if the conditional includes an unknown.