Introduction to Verilog Hardware Description Language
Introduction Purpose of HDL: 2. Describe the circuit in algorithmic level (like c) and in gate-level (e.g. And gate) 3. Simulation 4. Synthesis 5. Words are better than pictures 2
The best way to describe a circuit? If both inputs are 1, change both outputs. If one input is 1 change an output as follows: If the previous outputs are equal change the output with input 0; If the previous outputs are unequal change the output with input 1. If both inputs are 0, change nothing. 3
Verilog Basics 4
helloWorld.v module helloWorld ; Modules are the unit building-blocks (components) Verilog uses to describe initial an entire hardware system. Modules are begin (for us) of three types: behavioral, dataflow, $display ("Hello World!!!"); gate-level. We ignore the switch-level in $finish; this course. end This module is behavioral. Behavioral endmodule System calls. modules contain code in procedural blocks. This is a procedural block. There are two types of procedural blocks: initial and always. More than one statement must be put in a begin-end group.
Module declaration Module Input Circuit X Wire Y Output Z O 05/25/12 6
Module declaration Module Input Circuit X Wire Y Output Z O Module name module sample (X,Y,Z,O); input X,Y,Z; output O; // Describe the circuit using logic symbols assign O = (X^Y)&Z; 05/25/12 endmodule 7
Typical Module Components Diagram Module name, Port list (optional, if there are ports) Port declarations Parameter list Declaration of variables (wires, reg, integer etc.) Instantiation of inner (lower-level) modules Structural statements (i.e., assign and gates) Procedural blocks (i.e., always and initial blocks) Tasks and functions endmodule declaration
Lexicography • Comments: Two Types: • // Comment • /* These comments extend over multiple lines. Good for commenting out code */ • Character Set: 0123456789ABCD..YZabcd...yz_$ Cannot start with a number or $ 9
systemCalls.v module systemCalls(clk); input clk; clockGenerator cg(clk); Compile with the clockGenerator.v module. initial begin Suspends simulation – enters interactive mode. #25 $stop; #50 $finish; end Terminates simulation. initial begin Similar output calls except $write("$write does not "); $display adds a new line. $write("add a new linen"); $display("$display does"); $display("add a new line"); $monitor produces output each time a variable changes $monitor("Clock = %d", cg.clk); end value. endmodule
Data Types • Nets and Registers • Vectors • Integer, Real, and Time Register Data Types • Arrays • Memories • Parameters • Strings 11 2005 Verilog HDL
Nets • Used to represent connections between HW elements  Values continuously driven on nets • Keyword: wire  Default: One-bit values  unless declared as vectors  Default value: z  For trireg, default is x  Examples  wire a;  wire b, c;  wire d=1’b0; 12 2005 Verilog HDL
Registers • Registers represent data storage elements  Retain value until next assignment  NOTE: this is not a hardware register or flipflop  Keyword: reg  Default value: x  Example: reg reset; initial begin reset = 1’b1; #100 reset=1’b0; end 13 2005 Verilog HDL
Vectors • Net and register data types can be declared as vectors (multiple bit widths) • Syntax:  wire/reg [msb_index : lsb_index] data_id; • Example wire a; wire [7:0] bus; wire [31:0] busA, busB, busC; reg clock; reg [0:40] virtual_addr; 14 2005 Verilog HDL
Vectors (cont’d) • Consider wire [7:0] bus; wire [31:0] busA, busB, busC; reg [0:40] virtual_addr; • Access to bits or parts of a vector is possible: busA[7] bus[2:0] // three least-significant bits of bus // bus[0:2] is illegal. virtual_addr[0:1] /* two most-significant bits * of virtual_addr */ 15 2005 Verilog HDL
Integer, Real, and Time Register Data Types • Integer  Keyword: integer  Very similar to a vector of reg integer variables are signed numbers reg vectors are unsigned numbers  Bit width: implementation-dependent (at least 32-bits) Designer can also specify a width: integer [7:0] tmp;  Examples: integer counter; initial counter = -1; 16 2005 Verilog HDL
Integer, Real, and Time Register Data Types (cont’d) • Real  Keyword: real  Values:  Default value: 0  Decimal notation: 12.24  Scientific notation: 3e6 (=3x106)  Cannot have range declaration  Example: real delta; initial begin delta=4e10; delta=2.13; end integer i; initial i = delta; // i gets the value 2 (rounded value of 2.13) 17 2005 Verilog HDL
Integer, Real, and Time Register Data Types (cont’d) • Time Used to store values of simulation time Keyword: time Bit width: implementation-dependent (at least 64) $time system function gives current simulation time Example: time save_sim_time; initial save_sim_time = $time; 18 2005 Verilog HDL
Arrays • Only one-dimensional arrays supported • Allowed for reg, integer, time  Not allowed for real data type • Syntax: <data_type> <var_name>[start_idx : end_idx]; • Examples: integer count[0:7]; reg bool[31:0]; time chk_point[1:100]; reg [4:0] port_id[0:7]; integer matrix[4:0][4:0]; // illegal count[5] chk_point[100] port_id[3] • Note the difference between vectors and arrays 19 2005 Verilog HDL
Memories • RAM, ROM, and register-files used many times in digital systems • Memory = array of registers in Verilog • Word = an element of the array  Can be one or more bits • Examples: reg membit[0:1023]; reg [7:0] membyte[0:1023]; membyte[511] • Note the difference (as in arrays): reg membit[0:127]; reg [0:127] register; 20 2005 Verilog HDL
Data Types ~ summary module sample (a,b,c,d); • Data Values: 0,1,x,z input a,b; • Wire output c,d; - Synthesizes into wires - Used in structural code wire [7:0] b; • Reg - May synthesize into latches, flip-flops or wires reg c,d; - Used in procedural code integer k; • Integer 32-bit integer used as indexes • Input, Output, inout Defines ports of a module (wire by default) 21
4valuedLogic.v module fourValues( a , b, c, d ); output a, b, c, d ; Conflict or race condition. assign a = 1; Remember this is assign b = 0; not a procedural assign c = a; (i.e., sequential) assign c = b; block! These are 4-valued logic: endmodule continuous assign- 0 – low ments. 1 – high module stimulus; x – unknown fourValues X(a, b, c, d); z – undriven wire Now explain output! initial begin #1 $display("a = %d b = %d, c = %d, d = %d", a, b, c, d); $finish; end endmodule
Data Values • Numbers: Numbers are defined by number of • Parameters: bits Value of 23: parameter n=4; 5’b10111 // Binary wire [n-1:0] t, d; 5’d23 // Decimal 5’h17 // Hex `define Reset_state = 0, state_B =1, • Constants: Run_state =2, finish_state = 3; wire [3:0] t,d; if(state==`Run_state) assign t = 23; assign d= 4’b0111; 23
numbers.v module numbers; integer i, j; Register array. reg[3:0] x, y; initial ‘<base>: base can be d, b, o, h Array of register arrays simulate begin memory. Example memory i = ‘b1101; declaration with 1K 32-bit words: $display( "decimal i = %d, binary i = %b", i, i ); reg[31:0] smallMem[0:1023]; $display( "octal i = %o, hex i = %h", i, i ); Default base: d j = -1; $display( "decimal j = %d, binary j = %b", j, j ); Negative numbers are stored $display( "octal j = %o, hex j = %h", j, j ); in two’s complement form. x = 4'b1011; $display( "decimal x = %d, binary x = %b", x, x ); $display( "octal x = %o, hex x = %h", x, x ); y = 4'd7; $display( "decimal y = %d, binary y = %b", y, y ); $display( "octal y = %o, hex y = %h", y, y ); Typical format: <size>’<base><number> $finish; size is a decimal value that specifies the end endmodule size of the number in bits.
Operators • Arithmetic: reg [3:0] a, b, c, d; *,+,-, /,% wire[7:0] x,y,z; • Relational parameter n =4; <,<=,>,>=,==, != • Bit-wise Operators c = a + b; • Not: ~ d = a *n; • XOR: ^ • And : & 5’b11001 & 5’b01101 ==> 5’b01001 If(x==y) d = 1; else d =0; • OR: | • XNOR: ~^ or ^~ d = a ~^ b; • Logical Operators Returns 1or 0, treats all nonzero as 1 if ((x>=y) && (z)) a=1; • ! : Not else a = !x; • && : AND 27 && -3 ==> 1 • || : OR 25
Operators module sample (a, b, c, d); • Reduction Operators: input [2:0] a, b; Unary operations returns single-bit values output [2;0] c, d; • & : and wire z,y; • | :or • ~& : nand assign z = ~| a; • ~| : nor c = a * b; • ^ : xor If(a==b) d = 1; else d =0; • ~^ :xnor • Shift Operators d = a ~^ b; Shift Left: << Shift right: >> if ((a>=b) && (z)) y=1; • Concatenation Operator else y = !x; { } (concatenation) { n{item} } (n fold replication of an item) assign d << 2; //shift left twice • Conditional Operator assign {carry, d} = a + b; assign c = {2{carry},2{1’b0}}; Implements if-then-else statement // c = {carry,carry,0,0} (cond) ? (result if cond true) : (result if cond false) assign c= (inc==2)? a+1:a-1; 26
clockGenerator.v Port list. Ports can be of three types: input, output, inout. Each must be declared. module clockGenerator(clk); output clk; Internal register. reg clk; Register reg data type can have one of four values: 0, 1, x, z. Registers store a initial value till the next assignment. Registers begin are assigned values in procedural blocks. clk = 0; end If this module is run stand-alone make sure to add a $finish statement here or always simulation will never complete! #5 clk = ~clk; endmodule The delay is half the clock period.
Verilog Structure • All code are contained A in modules module gate(Z,A,B,C); input A,B,C; C B • output Z; Can invoke other assign Z = A|(B&C); modules Endmodule • Modules cannot be A2 contained in another module two_gates(Z2,A2,B2,C2) C2 input A2,B2,C2; B2 module output Z2; gate gate_1(G2,A2,B2,C2); Z B2 gate gate_2(Z2,G2,A2,B2); A2 endmodule 28
Structural Vs Procedural Structural Procedural • textual description of circuit • Think like C code • order does not matter • Order of statements are • Starts with assign important statements • Starts with initial or always statement • Harder to code • Need to work out logic • Easy to code • Can use case, if, for reg c, d; always@ (a or b or c) wire c, d; begin assign c =a & b; c =a & b; assign d = c |b; d = c |b; end 29
Structural Vs Procedural Procedural Structural reg [3:0] Q; wire [3:0]Q; wire [1:0] y; wire [1:0]y; always@(y) begin assign Q=4’b0000; Q[0]=(~y[1])&(~y[0]), case(y) begin Q[1]=(~y[1])&y[0], 2’b00: Q[0]=1; Q[2]=y[1]&(~y[0]), 2’b01: Q[1]=1; Q[3]=y[1]&y[0]; 2’b10: Q[2]=1; 2’b11: Q[3]=1; endcase Q[0] end Q[1] y[0] You don’t Q[0] Q[2] have to Q[1] y[1] work out Q[2] y[0] logic Q[3] Q[3] y[1] 30
Blocking Vs Non-Blocking Blocking Non-blocking  <variable> = <statement>  <variable> <= <statement>  Similar to C code  The inputs are stored once the procedure is triggered  The next assignment waits until the present  Statements are executed in one is finished parallel  Used for combinational  Used for flip-flops, latches logic and registers Do not mix both assignments in one procedure 31
Blocking Vs Non-Blocking Initial begin #1 e=2; #1 b=1; #1 b<=0; e<=b; // grabbed the old b f=e; // used old e=2, did not wait e<=b 32
blockingVSnba1.v module blockingVSnba1; integer i, j, k, l; initial begin Blocking (procedural) assignment: the whole statement must execute before control is released, as in traditional #1 i = 3; programming languages. #1 i = i + 1; j = i +1; #1 $display( "i = %d, j = %d", i, j ); Non-blocking (procedural) assignment: all the RHSs for the #1 i = 3; current time instant are evaluated (and stored transparently #1 i <= i + 1; in temporaries) first and, subsequently, the LHSs are updated j <= i + 1; at the end of the time instant. #1 $display( "i = %d, j = %d", i, j ); $finish; end endmodule
blockingVSnba2.v module blockingVSnba2(clk); input clk; Compile with clockGenerator.v. clockGenerator cg(clk); integer i, j; An application of non-blocking assignments to solve a race problem. initial begin i = 10; #50 $finish; With blocking assignments we get different output depending on the order these two statements are end executed by the simulator, though they are both supposed to execute “simultaneously” at posedge clk always @(posedge clk) - race problem. i = i + 1; // i <= i + 1; always @(posedge clk) Race problem is solved if the non-blocking j = i; // j <= i; assignments (after the comments) are used instead - output is unique. always @(negedge clk) $display("i = %d, j = %d", i, j); endmodule
blockingVSnba3.v The most important application of module blockingVSnba3; non-blocking assignments is to reg[7:0] dataBuf, dataCache, instrBuf, instrCache; model concurrency in hardware systems at the behavioral level. initial begin dataCache = 8'b11010011; Both loads from dataCache to dataBuf and instrCache = 8'b10010010; instrCache to instrBuf happen concurrently in the 20-21 clock cycle. #20; $display("Time = %d, dataBuf = %b, instrBuf = %b", $time, dataBuf, instrBuf); dataBuf <= #1 dataCache; instrBuf <= #1 instrCache; #1 $display("Time = %d, dataBuf = %b, instrBuf = %b", $time, dataBuf, instrBuf); $finish; Replace non-blocking with blocking end assignments and observe. endmodule
System Tasks and Compiler Directives
System Tasks • System Tasks: standard routine operations provided by Verilog Displaying on screen, monitoring values, stopping and finishing simulation, etc. • All start with $ 2005 37 Verilog HDL
System Tasks (cont’d) • $display: displays values of variables, strings, expressions.  Syntax: $display(p1, p2, p3, …, pn);  p1,…, pn can be quoted string, variable, or expression  Adds a new-line after displaying pn by default  Format specifiers:  %d, %b, %h, %o: display variable respectively in decimal, binary, hex, octal  %c, %s: display character, string  %e, %f, %g: display real variable in scientific, decimal, or whichever smaller notation  %v: display strength  %t: display in current time format  %m: display hierarchical name of this module 2005 38 Verilog HDL
System Tasks (cont’d) • $display examples:  $display(“Hello Verilog World!”); Output: Hello Verilog World!  $display($time); Output: 230  reg [0:40] virtual_addr;  $display(“At time %d virtual address is %h”, $time, virtual_addr); Output: At time 200 virtual address is 1fe000001c 2005 39 Verilog HDL
System Tasks (cont’d) • reg [4:0] port_id; • $display(“ID of the port is %b”, port_id); Output: ID of the port is 00101 • reg [3:0] bus; • $display(“Bus value is %b”, bus); Output: Bus value is 10xx • $display(“Hierarchical name of this module is %m”); Output: Hierarchical name of this module is top.p1 • $display(“A n multiline string with a %% sign.”); Output: A multiline string with a % sign. 2005 40 Verilog HDL
System Tasks (cont’d) • $monitor: monitors a signal when its value changes • Syntax: $monitor(p1, p2, p3, …, pn);  p1,…, pn can be quoted string, variable, or signal names  Format specifiers just as $display  Continuously monitors the values of the specified variables or signals, and displays the entire list whenever any of them changes.  $monitor needs to be invoked only once (unlike $display) Only one $monitor (the latest one) can be active at any time $monitoroff to temporarily turn off monitoring $monitoron to turn monitoring on again 2005 41 Verilog HDL
System Tasks (cont’d) • $monitor Examples: initial begin $monitor($time, “Value of signals clock=%b, reset= %b”, clock, reset); end  Output: 0 value of signals clock=0, reset=1 5 value of signals clock=1, reset=1 10 value of signals clock=0, reset=0 2005 42 Verilog HDL
System Tasks (cont’d) • $stop: stops simulation  Simulation enters interactive mode when reaching a $stop system task  Most useful for debugging • $finish: terminates simulation • Examples: initial begin clock=0; reset=1; #100 $stop; #900 $finish; end 2005 43 Verilog HDL
Compiler Directives • General syntax: `<keyword> • `define: similar to #define in C, used to define macros • `<macro_name> to use the macro defined by `define • Examples: `define WORD_SIZE 32 `define S $stop `define WORD_REG reg [31:0] `WORD_REG a_32_bit_reg; 2005 44 Verilog HDL
Compiler Directives (cont’d) • `include: Similar to #include in C, includes entire contents of another file in your Verilog source file • Example: `include header.v ... <Verilog code in file design.v> ... 2005 45 Verilog HDL
Behavior Modeling
simpleBehavioral.v Sensitivity trigger: when any of a, b or c changes. Replace this statement with “initial”. Output?! Modules are of three types: behavioral, module aOrNotbOrc(d, a, b, c); dataflow, gate-level. Behavioral modules contain code in procedural blocks. output d; input a, b, c; Statements in a procedural block cannot be reg d, p; re-ordered without affecting the program as these statements are executed sequentially, always @(a or b or c) exactly like in a conventional programming language such as C. begin p = a || ~b; Ports are of three types: input, output, inout. d = p || c; Each must be declared. Each port also has a end data type: either reg or wire (net). Default is wire. endmodule Inputs and inouts are always wire. Output ports that hold their value are reg, otherwise wire. More later… One port register, one internal register. Wires are part of the more general class of nets. However, the only nets we shall design with are wires.
simpleBehavioral.v (cont.) Top-level stimulus module module stimulus; integer i, j, k; Verilog Good Design Principle There is one reg a, b, c; top-level module, typically called system or aOrNotbOrc X(d, a, b, c); stimulus, which is uninstantiated and has no ports. This module contains instantiations of initial Instantiation. lower-level (inner) sub-modules. Typical begin picture below. for ( i=0; i<=1; i=i+1 ) for ( j=0; j<=1; j=j+1 ) Top-level module for ( k=0; k<=1; k=k+1 ) begin Inner sub-modules a = i; b = j; c = k; #1 $display("a = %d b = %d, c = %d, d = %d", a, b, c, d) end $finish; Remove the #1 delay. Run. Explain! end endmodule
Port Rules Diagram Outside connectors to internal ports, i.e., variables corresponding to ports in instantiation EXTERNAL of internal module MODULE wire Example: module external reg a; wire inout wire b; internal in(a, b); //instantiation … Internal ports port-connector endmodule input output module internal(x, y) reg or wire wire wire INTERNAL reg or wire input x; MODULE output y; wire x; reg y; … endmodule General rule (with few exceptions) Ports in all modules except for the stimulus module should be wire. Stimulus module has registers to set data for internal modules and wire ports only to read data from internal modules.
If Statements Syntax if (expression) begin ...statements... end else if (expression) begin ...statements... end ...more else if blocks else begin ...statements... end 50
Case Statements Syntax case (expression) case_choice1: begin ...statements... end case_choice2: begin ...statements... end ...more case choices blocks... default: begin ...statements... end endcase 51
For loops Syntax for (count= value1; integer j; count</<=/>/>= value2; count=count+/- step) for(j=0;j<=7;j=j+1) begin begin ...statements... c[j] = a[j] + b[j]; end end 52
Component Inference
Flip-Flops always@(posedge clk) begin a<=b; a<=b&c; end C B D B Q A clk CLK 54
D Flip-Flop with Asynchronous Reset always@(posedge clk or negedge rst) begin rst if (!rst) a<=0; clr else a<=b; B D end Q A clk CLK 55
D Flip-flop with Synchronous reset and Enable always@(posedge clk) begin if (rst) a<=0; rst D B else if (enable) a<=b; enable EN Q A end clk CLK 56
Shift Registers reg[3:0] Q; always@(posedge clk or posedge rset ) begin if (rset) Q<=0; else begin D Q D Q D Q D Q Q <=Q << 1; Q[0]<=Q[3]; CLK CLK CLK CLK end clk 57
Multiplexers Method 1 assign a = (select ? b : c); Method 2 c 0 always@(select or b or c) begin if(select) a=b; b 1 a else a=c; end SL Method 2b case(select) 1’b1: a=b; select 1’b0: a=c; endcase 58
Counters reg [7:0] count; wire enable; rst always@(posedge clk or negedge rst) clr enable EN begin if (rst) count<=0; else if (enable) count count<=count+1; end 59
Step by Step 4-bit adder
4-bit Adder • Step 1: build a 1-bit full adder as a module S = (a) XOR (b) XOR (Cin ) ; ( S = a^b^Cin) Cout = (a&b) |(Cin&(a+b)) module FA_1bit (S,Cout,a,b,Cin); begin input a,b,Cin; Output S, Cout; assign Sum = a^b^Cin; Module add_1bit assign Carry = (a&b) | (Cin&(a^b)); endmodule 61
4-bit Adder • Step 2: initiate 4 instances of FA_1bit module B3 A3 A B A B2 A2 B1 1 0 0 1-bit Cout2 1-bit Cout1 1-bit Cout0 1-bit Full Full Full Full Cout Adder Adder Adder Adder Cin S3 S2 S1 S0 module FA_4bits (S,Cout,A,B,Cin); The inputs and the output are begin input [3:0] A, B; 4-bits wide input Cin; we need wires to propagate output [3:0] S; output Cout the carry from one stage to wire Cout0, Cout1, Cout2 the next FA_1bit FA1(S[0], Cout0,A[0],B[0],Cin); you may name the instances FA_1bit FA1(S[1], Cout1,A[1],B[1],Cout0); with any name, but you have FA_1bit FA1(S[2], Cout2,A[2],B[2],Cout1); to maintain the order of the FA_1bit FA1(S[3], Cout,A[3],B[3],Cout2); inputs and outputs end endmodule; 62
4-bit Adder • Step 3: write a test-bench to test your design and generate outs using sample inputs. test_bench initialize the inputs, and read the outputs Write a test_bench to A[3:0] 4 B[3:0] 4 4-bits Full Adder 4 S[3:0] test the design. Cin Cout
4-bit Adder module test_bench; // you may name it by any name //define the variables you will use in the design reg [3:0] A,B,S; reg Cin, Cout // Create an instance from the full adder FA_4bits FA(S[3:0],Cout, A[3:0], B[3:0], Cin); //initialize the variables once initial A = 5; B = 6; S = 0; Cin = 0; Cout = 0; initial begin $display(“A=%d, B=%d, the sum = %d, and the carry = %d”, A,B,S,Cout) $display $finish end endmodule
4-bit Adder module test_bench; // you may name it by any name //define the variables you will use in the design reg [3:0] A,B,S; integer I,j; reg Cin, Cout // Create an instance from the full adder FA_4bits FA(S,Cout, A, B, Cin); //initialize the variables once initial begin $monitor ("A: %d B: %d sum: %d carry: %d", A, B, sum, carry); for (i=0; i<16; i=i+1) for (j=0; j<16; j=j+1) begin A = i; B = j; #1 ; end System calls. $finish; $finish end endmodule
More Examples
blocksTime1.v module blocksTime1; integer i, j; Another behavioral module. initial Integer data type: other types are begin time, real and realtime (same as real). i = 0; j = 3; $display( "i = %d, j = %d", i, j ); One initial procedural block. $finish; end endmodule
blocksTime2.v module blocksTime2; integer i, j; initial Time delay models signal propagation begin delay in a circuit. #2 i = 0; #5 j = i; $display( "time = %d, i = %d, j = %d", $time, i, j ); end initial Multiple initial blocks. #3 i = 2; Delays add within each block, but different initial blocks all start initial at time $time = 0 and run #10 $finish; in parallel (i.e., concurrently). endmodule
blocksTime3.v module blocksTime3; integer i, j; initial begin Important Verilog is a discrete event simulator: #2 i = 0; events are executed in a time-ordered queue. #5 j = i; $display( "time = %d, i = %d, j = %d", $time, i, j ); end initial begin #3 i = 2; #2 j = i; $display( "time = %d, i = %d, j = %d", $time, i, j ); Multiple initial blocks. #1 j = 8; Predict output before $display( "time = %d, i = %d, j = %d", $time, i, j ); you run! end initial #10 $finish; endmodule
blocksTime4.v module blocksTime4; integer i, j; initial Always block is an infinite loop. Following are same: begin i = 0; always initial initial j = 3; begin begin begin end … while(1) forever end begin begin initial … … #10 $finish; end end end end always begin #1 Comment out this delay. i = i + 1; Run. Explain the problem! j = j + 1; $display( "i = %d, j = %d", i, j ); end endmodule
clockGenerator.v Port list. Ports can be of three types: input, output, inout. Each must be declared. module clockGenerator(clk); output clk; Internal register. reg clk; Register reg data type can have one of four values: 0, 1, x, z. Registers store a initial value till the next assignment. Registers begin are assigned values in procedural blocks. clk = 0; end If this module is run stand-alone make sure to add a $finish statement here or always simulation will never complete! #5 clk = ~clk; endmodule The delay is half the clock period.
useClock.v Compile with the clockGenerator.v module. module useClock(clk); input clk; clockGenerator cg(clk); initial #50 $finish; Event trigger. always @(posedge clk) $display("Time = %d, Clock up!", $time); always @(negedge clk) // $display("Time = %d, Clock down!", $time); endmodule
blocksTime5.v // Ordering processes without advancing time module blockTime5; #0 delay causes the statement to execute after other processes integer i, j; scheduled at that time instant have completed. $time does not advance initial till after the statement completes. #0 $display( "time = %d, i = %d, j = %d", $time, i, j ); initial begin i = 0; j = 5; Comment out the delay. end Run. Explain what happens! initial #10 $finish; endmodule
blocksTime6.v module blocksTime6; integer i, j; Intra-assignment delay: RHS is computed and stored in a temporary (transparent to user) and initial LHS is assigned the temporary after the delay. begin #2 i = 0; j = #5 i; $display( "time = %d, i = %d, j = %d", $time, i, j ); end initial #3 i = 2; Compare output with blocksTime2.v. initial #10 $finish; endmodule
simpleDataflow.v module aOrNotbOrc(d, a, b, c); A dataflow module does not contain procedures. output d; input a, b, c; Statements in a dataflow module can be re-ordered wire p, q; without affecting the program as they simply describe a set of data manipulations and movements rather than a sequence of actions as assign q = ~b; in behavioral code. In this regard dataflow code is assign p = a || q; very similar to gate-level code. assign d = p || c; endmodule Continuous assignment statements: any change in the RHS causes instantaneous update of the wire on the LHS, unless there is a programmed delay. Use stimulus module from behavioral code.
simpleGate.v A gate-level module does not contain procedures. module aOrNotbOrc(d, a, b, c); Statements in a gate-level module can be re-ordered output d; without affecting the program as they simply input a, b, c; describe a set of connections rather than a sequence of actions as in behavioral code. A gate-levelmodule wire p, q; is equivalent to a combinational circuit. not(q, b); Wire data type can have one of four values: 0, 1, x, z. or(p, a, q); Wires cannot store values – they are continuously or(d, p, c); driven. endmodule Primitive gates. Verilog provides several such, e.g., and, or, nand, nor, not, buf, etc. Use stimulus module from behavioral code.
4-to-1 multiplexor logic diagram
4-to-1 multiplexor (Folder Multiplexor) Following are four different Verilog implementations of the same multiplexor. A stimulus module is shared to test each implementation.
multiplexor4_1Gate.v module multiplexor4_1(out, in1, in2, in3, in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; Recall default type is wire. wire notcntlr1, notcntrl2, w, x, y, z; not (notcntrl1, cntrl1); Structural gate-level code based not (notcntrl2, cntrl2); exactly on the logic diagram. and (w, in1, notcntrl1, notcntrl2); and (x, in2, notcntrl1, cntrl2); and (y, in3, cntrl1, notcntrl2); and (z, in4, cntrl1, cntrl2); or (out, w, x, y, z); endmodule
multiplexor4_1Stimulus.v (Folder Multiplexor) module muxstimulus; Stimulus code that generates reg IN1, IN2, IN3, IN4, CNTRL1, CNTRL2; test vectors. wire OUT; multiplexor4_1 mux1_4(OUT, IN1, IN2, IN3, IN4, CNTRL1, CNTRL2); initial begin IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0; $display("Initial arbitrary values"); #0 $display("input1 = %b, input2 = %b, input3 = %b, input4 = %bn", IN1, IN2, IN3, IN4); Concatenation. {CNTRL1, CNTRL2} = 2'b00; #1 $display("cntrl1=%b, cntrl2=%b, output is %b", CNTRL1, CNTRL2, OUT);
multiplexor4_1Stimulus.v (cont.) {CNTRL1, CNTRL2} = 2'b01; #1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT); {CNTRL1, CNTRL2} = 2'b10; #1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT); {CNTRL1, CNTRL2} = 2'b11; #1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT); end endmodule
multiplexor4_1Logic.v (Folder Multiplexor) module multiplexor4_1(out, in1, in2, in3 ,in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; assign out = (in1 & ~cntrl1 & ~cntrl2) | RTL (dataflow) code using continuous assignments rather (in2 & ~cntrl1 & cntrl2) | than a gate list. (in3 & cntrl1 & ~cntrl2) | (in4 & cntrl1 & cntrl2); endmodule
multiplexor4_1Conditional.v (Folder Multiplexor) module multiplexor4_1(out, in1, in2, in3, in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; assign out = cntrl1 ? (cntrl2 ? in4 : in3) : (cntrl2 ? in2 : in1); endmodule More RTL (dataflow) code – this time using conditionals in a continuous assignment.
multiplexor4_1Case.v (Folder Multiplexor) module multiplexor4_1(out, in1, in2, in3, in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; reg out; Behavioral code: output out must now be of reg type as it is assigned values in a always @(in1 or in2 or in3 or in4 or cntrl1 or cntrl2) procedural block. case ({cntrl1, cntrl2}) 2'b00 : out = in1; 2'b01 : out = in2; 2'b10 : out = in3; 2'b11 : out = in4; default : $display("Please check control bits"); endcase endmodule
8-to-3 encoder truth table Input Output D7 D6 D5 D4 D3 D2 D1 D0 A2 A1 A0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 1 1
8-to-3 encoder (Folder Encoder) Following are four different Verilog implementations of the same encoder. Each has its own stimulus module.
encoder8_3Behavioral.v module encoder8_3( encoder_out , enable, encoder_in ); output[2:0] encoder_out; input enable; Sensitivity list. input[7:0] encoder_in; reg[2:0] encoder_out; always @ (enable or encoder_in) Simple behavioral code using the begin case statement. if (enable) case ( encoder_in ) 8'b00000001 : encoder_out = 3'b000; 8'b00000010 : encoder_out = 3'b001; 8'b00000100 : encoder_out = 3'b010; 8'b00001000 : encoder_out = 3'b011; 8'b00010000 : encoder_out = 3'b100; 8'b00100000 : encoder_out = 3'b101; 8'b01000000 : encoder_out = 3'b110; 8'b10000000 : encoder_out = 3'b111; default : $display("Check input bits."); endcase end endmodule
encoder8_3BehavioralStimulus.v module stimulus; wire[2:0] encoder_out; reg enable; Stimulus for the behavioral code. reg[7:0] encoder_in; encoder8_3 enc( encoder_out, enable, encoder_in ); initial begin enable = 1; encoder_in = 8'b00000010; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); Remove this delay. #1 enable = 0; encoder_in = 8'b00000001; Run. Explain! #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 enable = 1; encoder_in = 8'b00000001; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 $finish; end endmodule
8-to-3 encoder logic equations A0 = D1 + D3 + D5 + D7 A1 = D2 + D3 + D6 + D7 A2 = D4 + D5 + D6 + D7
encoder8_3structural.v (Folder Encoder) module encoder8_3( encoder_out , encoder_in ); output[2:0] encoder_out; Structural code. Why is there no input[7:0] encoder_in; enable wire?! Hint: think storage. or( encoder_out[0], encoder_in[1], encoder_in[3], encoder_in[5], encoder_in[7] ); or( encoder_out[1], encoder_in[2], encoder_in[3], encoder_in[6], encoder_in[7] ); or( encoder_out[2], encoder_in[4], encoder_in[5], encoder_in[6], encoder_in[7] ); endmodule
encoder8_3StructuralStimulus.v module stimulus; wire[2:0] encoder_out; Stimulus for the structural code. reg[7:0] encoder_in; encoder8_3 enc( encoder_out, encoder_in ); initial begin encoder_in = 8'b00000010; #1 $display("encoder_in = %b, encoder_out = %b", encoder_in, encoder_out); #1 encoder_in = 8'b00000001; #1 $display("encoder_in = %b, encoder_out = %b", encoder_in, encoder_out); #1 $finish; end endmodule
encoder8_3Mixed.v module encoder8_3( encoder_out , enable, encoder_in ); output[2:0] encoder_out; input enable; Mixed structural-behavioral code. Goal was input[7:0] encoder_in; to modify structural code to have an enable reg[2:0] encoder_out; wire, which requires register output for storage. wire b0, b1, b2; or( b0, encoder_in[1], encoder_in[3], encoder_in[5], encoder_in[7] ); or( b1, encoder_in[2], encoder_in[3], encoder_in[6], encoder_in[7] ); or( b2, encoder_in[4], encoder_in[5], encoder_in[6], encoder_in[7] ); always @(enable or encoder_in) Be careful with mixed design! It’s begin working may be difficult to understand. if (enable) encoder_out = {b2, b1, b0}; end endmodule
encoder8_3MixedStimulus.v module stimulus; wire[2:0] encoder_out; reg enable; Stimulus for the mixed code. reg[7:0] encoder_in; encoder8_3 enc( encoder_out, enable, encoder_in ); initial begin Output is puzzling! Explain! enable = 1; encoder_in = 8'b00000010; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 enable = 1; encoder_in = 8'b00000010; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out);
encoder8_3MixedStimulus.v #1 enable = 0; encoder_in = 8'b00000001; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 enable = 1; encoder_in = 8'b10000000; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 $finish; end endmodule
Comparator modules scheme
comparator.v Parameters that may be set Comparator makes the comparison A ? B when the module is instantiated. where ? Is determined by the input greaterNotLess and returns true(1) or false(0). module comparator (result, A, B, greaterNotLess); parameter width = 8; parameter delay = 1; input [width-1:0] A, B; // comparands input greaterNotLess; // 1 - greater, 0 - less than output result; // 1 if true, 0 if false assign #delay result = greaterNotLess ? (A > B) : (A < B); endmodule
stimulus.v Stimulus for the comparator. module system; wire greaterNotLess; // sense of comparison wire [15:0] A, B; // comparand values - 16 bit wire result; // comparison result // Module instances comparator #(16, 2) comp (result, A, B, greaterNotLess); testGenerator tg (A, B, greaterNotLess, result); endmodule Parameters being set at module instantiation.
testGen.v module testGenerator (A, B, greaterNotLess, result); output [15:0] A, B; output greaterNotLess; Module that generates test vectors for input result; the comparator and checks correctness parameter del = 5; of output. reg [15:0] A, B; reg greaterNotLess; task check; input shouldBe; Task definition: a task is exactly like a procedure in a conventional programming language. begin if (result != shouldBe) $display("Error! %d %s %d, result = %b", A, greaterNotLess?">":"<", B, result); end endtask initial begin // produce test data, check results A = 16'h1234; B = 16'b0001001000110100; greaterNotLess = 0;
testGen.v (cont.) #del check(0); B = 0; Task call greaterNotLess = 1; #del check(1); A = 1; greaterNotLess = 0; #del check(0); $finish; end endmodule
Finite State Machines
Standard Form for a Verilog FSM // state flip-flops // REGISTER DEFINITION reg [2:0] state, nxt_st; always@(posedge clk) // state definitions begin parameter reset=0,S1=1,S2=2,S3=3,.. state<=next_state; end // NEXT STATE CALCULATIONS always@(state or inputs or ...) // OUTPUT CALCULATIONS begin output= f(state, inputs) … next_state= ... … end 101
Example module myFSM (clk, x, z) // NEXT STATE CALCULATIONS input clk, x; always @(state or x) output z; begin // state flip-flops case (state) reg [2:0] state, nxt_st; S0: if(x) nxt_st=S1; // state definition else nxt_st=S0; S1: if(x) nxt_st=S3; parameter S0=0,S1=1,S2=2,S3=3,S7=7 else nxt_st=S2; S2: if(x) nxt_st=S0; else nxt_st=S7; // REGISTER DEFINITION S3: if(x) nxt_st=S2; always @(posedge clk) else nxt_st=S7; begin S7: nxt_st=S0; state<=nxt_st; default: nxt_st = S0; end endcase end // OUTPUTCALCULATIONS assign z = (state==S7); endmodule 102
0111 Sequence Detector 1 1 S0 0 z=0 S4 0 S1 0 z=1 z=0 0 1 0 1 S3 S2 z=0 z=0 1 103
Test Benches
System tasks • Used to generate input and output during simulation. Start with $ sign. • Display Selected Variables: $display (“format_string”,par_1,par_2,...); $monitor(“format_string”,par_1,par_2,...); Example: $display(“Output z: %b”, z); • Writing to a File: $fopen, $fdisplay, $fmonitor and $fwrite • Random number generator: $random (seed) • Query current simulation time: $time 105
Test Benches Overview Approach 1. Invoke the verilog under 3. Initialize all inputs design 5. Set the clk signal 2. Simulate input vectors 7. Send test vectors 3. Implement the system tasks to view the results 9. Specify when to end the simulation. 106
Example ‘timescale1 ns /100 ps // timeunit =1ns; precision=1/10ns; /****SPECIFY THE INPUT WAVEFORM x ****/ module my_fsm_tb; Initial begin reg clk, rst, x; #1 x=0; wire z; #400 x=1; $display(“Output z: %b”, z); /**** DESIGN TO SIMULATE (my_fsm) #100 x=0; INSTANTIATION ****/ @(posedge clk) x=1; myfsm dut1(clk, rst, x, z); #1000 $finish; //stop simulation /****RESET AND CLOCK SECTION****/ //without this, it will not stop Initial end begin endmodule clk=0; rst=0; #1rst=1; /*The delay gives rst a posedge for sure.*/ #200 rst=0; //Deactivate reset after two clock cycles +1ns*/ end always #50clk=~clk; /* 10MHz clock (50*1ns*2) with 50% duty-cycle */ 107
Modelsim Demonstration

Verilog tutorial

  • 1.
  • 2.
    Introduction Purpose of HDL: 2.Describe the circuit in algorithmic level (like c) and in gate-level (e.g. And gate) 3. Simulation 4. Synthesis 5. Words are better than pictures 2
  • 3.
    The best wayto describe a circuit? If both inputs are 1, change both outputs. If one input is 1 change an output as follows: If the previous outputs are equal change the output with input 0; If the previous outputs are unequal change the output with input 1. If both inputs are 0, change nothing. 3
  • 4.
  • 5.
    helloWorld.v module helloWorld ; Modules are the unit building-blocks (components) Verilog uses to describe initial an entire hardware system. Modules are begin (for us) of three types: behavioral, dataflow, $display ("Hello World!!!"); gate-level. We ignore the switch-level in $finish; this course. end This module is behavioral. Behavioral endmodule System calls. modules contain code in procedural blocks. This is a procedural block. There are two types of procedural blocks: initial and always. More than one statement must be put in a begin-end group.
  • 6.
    Module declaration Module Input Circuit X Wire Y Output Z O 05/25/12 6
  • 7.
    Module declaration Module Input Circuit X Wire Y Output Z O Module name module sample (X,Y,Z,O); input X,Y,Z; output O; // Describe the circuit using logic symbols assign O = (X^Y)&Z; 05/25/12 endmodule 7
  • 8.
    Typical Module Components Diagram Module name, Port list (optional, if there are ports) Port declarations Parameter list Declaration of variables (wires, reg, integer etc.) Instantiation of inner (lower-level) modules Structural statements (i.e., assign and gates) Procedural blocks (i.e., always and initial blocks) Tasks and functions endmodule declaration
  • 9.
    Lexicography • Comments: Two Types: • // Comment • /* These comments extend over multiple lines. Good for commenting out code */ • Character Set: 0123456789ABCD..YZabcd...yz_$ Cannot start with a number or $ 9
  • 10.
    systemCalls.v module systemCalls(clk); inputclk; clockGenerator cg(clk); Compile with the clockGenerator.v module. initial begin Suspends simulation – enters interactive mode. #25 $stop; #50 $finish; end Terminates simulation. initial begin Similar output calls except $write("$write does not "); $display adds a new line. $write("add a new linen"); $display("$display does"); $display("add a new line"); $monitor produces output each time a variable changes $monitor("Clock = %d", cg.clk); end value. endmodule
  • 11.
    Data Types • Nets and Registers • Vectors • Integer, Real, and Time Register Data Types • Arrays • Memories • Parameters • Strings 11 2005 Verilog HDL
  • 12.
    Nets • Used torepresent connections between HW elements  Values continuously driven on nets • Keyword: wire  Default: One-bit values  unless declared as vectors  Default value: z  For trireg, default is x  Examples  wire a;  wire b, c;  wire d=1’b0; 12 2005 Verilog HDL
  • 13.
    Registers • Registers representdata storage elements  Retain value until next assignment  NOTE: this is not a hardware register or flipflop  Keyword: reg  Default value: x  Example: reg reset; initial begin reset = 1’b1; #100 reset=1’b0; end 13 2005 Verilog HDL
  • 14.
    Vectors • Net andregister data types can be declared as vectors (multiple bit widths) • Syntax:  wire/reg [msb_index : lsb_index] data_id; • Example wire a; wire [7:0] bus; wire [31:0] busA, busB, busC; reg clock; reg [0:40] virtual_addr; 14 2005 Verilog HDL
  • 15.
    Vectors (cont’d) • Consider wire [7:0] bus; wire [31:0] busA, busB, busC; reg [0:40] virtual_addr; • Access to bits or parts of a vector is possible: busA[7] bus[2:0] // three least-significant bits of bus // bus[0:2] is illegal. virtual_addr[0:1] /* two most-significant bits * of virtual_addr */ 15 2005 Verilog HDL
  • 16.
    Integer, Real, andTime Register Data Types • Integer  Keyword: integer  Very similar to a vector of reg integer variables are signed numbers reg vectors are unsigned numbers  Bit width: implementation-dependent (at least 32-bits) Designer can also specify a width: integer [7:0] tmp;  Examples: integer counter; initial counter = -1; 16 2005 Verilog HDL
  • 17.
    Integer, Real, andTime Register Data Types (cont’d) • Real  Keyword: real  Values:  Default value: 0  Decimal notation: 12.24  Scientific notation: 3e6 (=3x106)  Cannot have range declaration  Example: real delta; initial begin delta=4e10; delta=2.13; end integer i; initial i = delta; // i gets the value 2 (rounded value of 2.13) 17 2005 Verilog HDL
  • 18.
    Integer, Real, andTime Register Data Types (cont’d) • Time Used to store values of simulation time Keyword: time Bit width: implementation-dependent (at least 64) $time system function gives current simulation time Example: time save_sim_time; initial save_sim_time = $time; 18 2005 Verilog HDL
  • 19.
    Arrays • Only one-dimensional arrays supported • Allowed for reg, integer, time  Not allowed for real data type • Syntax: <data_type> <var_name>[start_idx : end_idx]; • Examples: integer count[0:7]; reg bool[31:0]; time chk_point[1:100]; reg [4:0] port_id[0:7]; integer matrix[4:0][4:0]; // illegal count[5] chk_point[100] port_id[3] • Note the difference between vectors and arrays 19 2005 Verilog HDL
  • 20.
    Memories • RAM, ROM,and register-files used many times in digital systems • Memory = array of registers in Verilog • Word = an element of the array  Can be one or more bits • Examples: reg membit[0:1023]; reg [7:0] membyte[0:1023]; membyte[511] • Note the difference (as in arrays): reg membit[0:127]; reg [0:127] register; 20 2005 Verilog HDL
  • 21.
    Data Types ~summary module sample (a,b,c,d); • Data Values: 0,1,x,z input a,b; • Wire output c,d; - Synthesizes into wires - Used in structural code wire [7:0] b; • Reg - May synthesize into latches, flip-flops or wires reg c,d; - Used in procedural code integer k; • Integer 32-bit integer used as indexes • Input, Output, inout Defines ports of a module (wire by default) 21
  • 22.
    4valuedLogic.v module fourValues( a, b, c, d ); output a, b, c, d ; Conflict or race condition. assign a = 1; Remember this is assign b = 0; not a procedural assign c = a; (i.e., sequential) assign c = b; block! These are 4-valued logic: endmodule continuous assign- 0 – low ments. 1 – high module stimulus; x – unknown fourValues X(a, b, c, d); z – undriven wire Now explain output! initial begin #1 $display("a = %d b = %d, c = %d, d = %d", a, b, c, d); $finish; end endmodule
  • 23.
    Data Values • Numbers: Numbersare defined by number of • Parameters: bits Value of 23: parameter n=4; 5’b10111 // Binary wire [n-1:0] t, d; 5’d23 // Decimal 5’h17 // Hex `define Reset_state = 0, state_B =1, • Constants: Run_state =2, finish_state = 3; wire [3:0] t,d; if(state==`Run_state) assign t = 23; assign d= 4’b0111; 23
  • 24.
    numbers.v module numbers; integeri, j; Register array. reg[3:0] x, y; initial ‘<base>: base can be d, b, o, h Array of register arrays simulate begin memory. Example memory i = ‘b1101; declaration with 1K 32-bit words: $display( "decimal i = %d, binary i = %b", i, i ); reg[31:0] smallMem[0:1023]; $display( "octal i = %o, hex i = %h", i, i ); Default base: d j = -1; $display( "decimal j = %d, binary j = %b", j, j ); Negative numbers are stored $display( "octal j = %o, hex j = %h", j, j ); in two’s complement form. x = 4'b1011; $display( "decimal x = %d, binary x = %b", x, x ); $display( "octal x = %o, hex x = %h", x, x ); y = 4'd7; $display( "decimal y = %d, binary y = %b", y, y ); $display( "octal y = %o, hex y = %h", y, y ); Typical format: <size>’<base><number> $finish; size is a decimal value that specifies the end endmodule size of the number in bits.
  • 25.
    Operators • Arithmetic: reg [3:0] a, b, c, d; *,+,-, /,% wire[7:0] x,y,z; • Relational parameter n =4; <,<=,>,>=,==, != • Bit-wise Operators c = a + b; • Not: ~ d = a *n; • XOR: ^ • And : & 5’b11001 & 5’b01101 ==> 5’b01001 If(x==y) d = 1; else d =0; • OR: | • XNOR: ~^ or ^~ d = a ~^ b; • Logical Operators Returns 1or 0, treats all nonzero as 1 if ((x>=y) && (z)) a=1; • ! : Not else a = !x; • && : AND 27 && -3 ==> 1 • || : OR 25
  • 26.
    Operators module sample (a, b, c, d); • Reduction Operators: input [2:0] a, b; Unary operations returns single-bit values output [2;0] c, d; • & : and wire z,y; • | :or • ~& : nand assign z = ~| a; • ~| : nor c = a * b; • ^ : xor If(a==b) d = 1; else d =0; • ~^ :xnor • Shift Operators d = a ~^ b; Shift Left: << Shift right: >> if ((a>=b) && (z)) y=1; • Concatenation Operator else y = !x; { } (concatenation) { n{item} } (n fold replication of an item) assign d << 2; //shift left twice • Conditional Operator assign {carry, d} = a + b; assign c = {2{carry},2{1’b0}}; Implements if-then-else statement // c = {carry,carry,0,0} (cond) ? (result if cond true) : (result if cond false) assign c= (inc==2)? a+1:a-1; 26
  • 27.
    clockGenerator.v Port list. Ports can be of three types: input, output, inout. Each must be declared. module clockGenerator(clk); output clk; Internal register. reg clk; Register reg data type can have one of four values: 0, 1, x, z. Registers store a initial value till the next assignment. Registers begin are assigned values in procedural blocks. clk = 0; end If this module is run stand-alone make sure to add a $finish statement here or always simulation will never complete! #5 clk = ~clk; endmodule The delay is half the clock period.
  • 28.
    Verilog Structure • Allcode are contained A in modules module gate(Z,A,B,C); input A,B,C; C B • output Z; Can invoke other assign Z = A|(B&C); modules Endmodule • Modules cannot be A2 contained in another module two_gates(Z2,A2,B2,C2) C2 input A2,B2,C2; B2 module output Z2; gate gate_1(G2,A2,B2,C2); Z B2 gate gate_2(Z2,G2,A2,B2); A2 endmodule 28
  • 29.
    Structural Vs Procedural Structural Procedural • textual description of circuit • Think like C code • order does not matter • Order of statements are • Starts with assign important statements • Starts with initial or always statement • Harder to code • Need to work out logic • Easy to code • Can use case, if, for reg c, d; always@ (a or b or c) wire c, d; begin assign c =a & b; c =a & b; assign d = c |b; d = c |b; end 29
  • 30.
    Structural Vs Procedural Procedural Structural reg [3:0] Q; wire [3:0]Q; wire [1:0] y; wire [1:0]y; always@(y) begin assign Q=4’b0000; Q[0]=(~y[1])&(~y[0]), case(y) begin Q[1]=(~y[1])&y[0], 2’b00: Q[0]=1; Q[2]=y[1]&(~y[0]), 2’b01: Q[1]=1; Q[3]=y[1]&y[0]; 2’b10: Q[2]=1; 2’b11: Q[3]=1; endcase Q[0] end Q[1] y[0] You don’t Q[0] Q[2] have to Q[1] y[1] work out Q[2] y[0] logic Q[3] Q[3] y[1] 30
  • 31.
    Blocking Vs Non-Blocking Blocking Non-blocking  <variable> = <statement>  <variable> <= <statement>  Similar to C code  The inputs are stored once the procedure is triggered  The next assignment waits until the present  Statements are executed in one is finished parallel  Used for combinational  Used for flip-flops, latches logic and registers Do not mix both assignments in one procedure 31
  • 32.
    Blocking Vs Non-Blocking Initial begin #1 e=2; #1 b=1; #1 b<=0; e<=b; // grabbed the old b f=e; // used old e=2, did not wait e<=b 32
  • 33.
    blockingVSnba1.v module blockingVSnba1; integeri, j, k, l; initial begin Blocking (procedural) assignment: the whole statement must execute before control is released, as in traditional #1 i = 3; programming languages. #1 i = i + 1; j = i +1; #1 $display( "i = %d, j = %d", i, j ); Non-blocking (procedural) assignment: all the RHSs for the #1 i = 3; current time instant are evaluated (and stored transparently #1 i <= i + 1; in temporaries) first and, subsequently, the LHSs are updated j <= i + 1; at the end of the time instant. #1 $display( "i = %d, j = %d", i, j ); $finish; end endmodule
  • 34.
    blockingVSnba2.v module blockingVSnba2(clk); inputclk; Compile with clockGenerator.v. clockGenerator cg(clk); integer i, j; An application of non-blocking assignments to solve a race problem. initial begin i = 10; #50 $finish; With blocking assignments we get different output depending on the order these two statements are end executed by the simulator, though they are both supposed to execute “simultaneously” at posedge clk always @(posedge clk) - race problem. i = i + 1; // i <= i + 1; always @(posedge clk) Race problem is solved if the non-blocking j = i; // j <= i; assignments (after the comments) are used instead - output is unique. always @(negedge clk) $display("i = %d, j = %d", i, j); endmodule
  • 35.
    blockingVSnba3.v The most important application of module blockingVSnba3; non-blocking assignments is to reg[7:0] dataBuf, dataCache, instrBuf, instrCache; model concurrency in hardware systems at the behavioral level. initial begin dataCache = 8'b11010011; Both loads from dataCache to dataBuf and instrCache = 8'b10010010; instrCache to instrBuf happen concurrently in the 20-21 clock cycle. #20; $display("Time = %d, dataBuf = %b, instrBuf = %b", $time, dataBuf, instrBuf); dataBuf <= #1 dataCache; instrBuf <= #1 instrCache; #1 $display("Time = %d, dataBuf = %b, instrBuf = %b", $time, dataBuf, instrBuf); $finish; Replace non-blocking with blocking end assignments and observe. endmodule
  • 36.
  • 37.
    System Tasks • SystemTasks: standard routine operations provided by Verilog Displaying on screen, monitoring values, stopping and finishing simulation, etc. • All start with $ 2005 37 Verilog HDL
  • 38.
    System Tasks (cont’d) •$display: displays values of variables, strings, expressions.  Syntax: $display(p1, p2, p3, …, pn);  p1,…, pn can be quoted string, variable, or expression  Adds a new-line after displaying pn by default  Format specifiers:  %d, %b, %h, %o: display variable respectively in decimal, binary, hex, octal  %c, %s: display character, string  %e, %f, %g: display real variable in scientific, decimal, or whichever smaller notation  %v: display strength  %t: display in current time format  %m: display hierarchical name of this module 2005 38 Verilog HDL
  • 39.
    System Tasks (cont’d) •$display examples:  $display(“Hello Verilog World!”); Output: Hello Verilog World!  $display($time); Output: 230  reg [0:40] virtual_addr;  $display(“At time %d virtual address is %h”, $time, virtual_addr); Output: At time 200 virtual address is 1fe000001c 2005 39 Verilog HDL
  • 40.
    System Tasks (cont’d) • reg [4:0] port_id; • $display(“ID of the port is %b”, port_id); Output: ID of the port is 00101 • reg [3:0] bus; • $display(“Bus value is %b”, bus); Output: Bus value is 10xx • $display(“Hierarchical name of this module is %m”); Output: Hierarchical name of this module is top.p1 • $display(“A n multiline string with a %% sign.”); Output: A multiline string with a % sign. 2005 40 Verilog HDL
  • 41.
    System Tasks (cont’d) •$monitor: monitors a signal when its value changes • Syntax: $monitor(p1, p2, p3, …, pn);  p1,…, pn can be quoted string, variable, or signal names  Format specifiers just as $display  Continuously monitors the values of the specified variables or signals, and displays the entire list whenever any of them changes.  $monitor needs to be invoked only once (unlike $display) Only one $monitor (the latest one) can be active at any time $monitoroff to temporarily turn off monitoring $monitoron to turn monitoring on again 2005 41 Verilog HDL
  • 42.
    System Tasks (cont’d) • $monitor Examples: initial begin $monitor($time, “Value of signals clock=%b, reset= %b”, clock, reset); end  Output: 0 value of signals clock=0, reset=1 5 value of signals clock=1, reset=1 10 value of signals clock=0, reset=0 2005 42 Verilog HDL
  • 43.
    System Tasks (cont’d) •$stop: stops simulation  Simulation enters interactive mode when reaching a $stop system task  Most useful for debugging • $finish: terminates simulation • Examples: initial begin clock=0; reset=1; #100 $stop; #900 $finish; end 2005 43 Verilog HDL
  • 44.
    Compiler Directives • Generalsyntax: `<keyword> • `define: similar to #define in C, used to define macros • `<macro_name> to use the macro defined by `define • Examples: `define WORD_SIZE 32 `define S $stop `define WORD_REG reg [31:0] `WORD_REG a_32_bit_reg; 2005 44 Verilog HDL
  • 45.
    Compiler Directives (cont’d) •`include: Similar to #include in C, includes entire contents of another file in your Verilog source file • Example: `include header.v ... <Verilog code in file design.v> ... 2005 45 Verilog HDL
  • 46.
  • 47.
    simpleBehavioral.v Sensitivity trigger: when any of a, b or c changes. Replace this statement with “initial”. Output?! Modules are of three types: behavioral, module aOrNotbOrc(d, a, b, c); dataflow, gate-level. Behavioral modules contain code in procedural blocks. output d; input a, b, c; Statements in a procedural block cannot be reg d, p; re-ordered without affecting the program as these statements are executed sequentially, always @(a or b or c) exactly like in a conventional programming language such as C. begin p = a || ~b; Ports are of three types: input, output, inout. d = p || c; Each must be declared. Each port also has a end data type: either reg or wire (net). Default is wire. endmodule Inputs and inouts are always wire. Output ports that hold their value are reg, otherwise wire. More later… One port register, one internal register. Wires are part of the more general class of nets. However, the only nets we shall design with are wires.
  • 48.
    simpleBehavioral.v (cont.) Top-level stimulus module module stimulus; integer i, j, k; Verilog Good Design Principle There is one reg a, b, c; top-level module, typically called system or aOrNotbOrc X(d, a, b, c); stimulus, which is uninstantiated and has no ports. This module contains instantiations of initial Instantiation. lower-level (inner) sub-modules. Typical begin picture below. for ( i=0; i<=1; i=i+1 ) for ( j=0; j<=1; j=j+1 ) Top-level module for ( k=0; k<=1; k=k+1 ) begin Inner sub-modules a = i; b = j; c = k; #1 $display("a = %d b = %d, c = %d, d = %d", a, b, c, d) end $finish; Remove the #1 delay. Run. Explain! end endmodule
  • 49.
    Port Rules Diagram Outside connectors to internal ports, i.e., variables corresponding to ports in instantiation EXTERNAL of internal module MODULE wire Example: module external reg a; wire inout wire b; internal in(a, b); //instantiation … Internal ports port-connector endmodule input output module internal(x, y) reg or wire wire wire INTERNAL reg or wire input x; MODULE output y; wire x; reg y; … endmodule General rule (with few exceptions) Ports in all modules except for the stimulus module should be wire. Stimulus module has registers to set data for internal modules and wire ports only to read data from internal modules.
  • 50.
    If Statements Syntax if (expression) begin ...statements... end else if (expression) begin ...statements... end ...more else if blocks else begin ...statements... end 50
  • 51.
    Case Statements Syntax case (expression) case_choice1: begin ...statements... end case_choice2: begin ...statements... end ...more case choices blocks... default: begin ...statements... end endcase 51
  • 52.
    For loops Syntax for (count=value1; integer j; count</<=/>/>= value2; count=count+/- step) for(j=0;j<=7;j=j+1) begin begin ...statements... c[j] = a[j] + b[j]; end end 52
  • 53.
  • 54.
    Flip-Flops always@(posedge clk) begin a<=b; a<=b&c; end C B D B Q A clk CLK 54
  • 55.
    D Flip-Flop withAsynchronous Reset always@(posedge clk or negedge rst) begin rst if (!rst) a<=0; clr else a<=b; B D end Q A clk CLK 55
  • 56.
    D Flip-flop withSynchronous reset and Enable always@(posedge clk) begin if (rst) a<=0; rst D B else if (enable) a<=b; enable EN Q A end clk CLK 56
  • 57.
    Shift Registers reg[3:0] Q; always@(posedgeclk or posedge rset ) begin if (rset) Q<=0; else begin D Q D Q D Q D Q Q <=Q << 1; Q[0]<=Q[3]; CLK CLK CLK CLK end clk 57
  • 58.
    Multiplexers Method 1 assign a= (select ? b : c); Method 2 c 0 always@(select or b or c) begin if(select) a=b; b 1 a else a=c; end SL Method 2b case(select) 1’b1: a=b; select 1’b0: a=c; endcase 58
  • 59.
    Counters reg [7:0] count; wireenable; rst always@(posedge clk or negedge rst) clr enable EN begin if (rst) count<=0; else if (enable) count count<=count+1; end 59
  • 60.
    Step by Step 4-bit adder
  • 61.
    4-bit Adder • Step1: build a 1-bit full adder as a module S = (a) XOR (b) XOR (Cin ) ; ( S = a^b^Cin) Cout = (a&b) |(Cin&(a+b)) module FA_1bit (S,Cout,a,b,Cin); begin input a,b,Cin; Output S, Cout; assign Sum = a^b^Cin; Module add_1bit assign Carry = (a&b) | (Cin&(a^b)); endmodule 61
  • 62.
    4-bit Adder • Step2: initiate 4 instances of FA_1bit module B3 A3 A B A B2 A2 B1 1 0 0 1-bit Cout2 1-bit Cout1 1-bit Cout0 1-bit Full Full Full Full Cout Adder Adder Adder Adder Cin S3 S2 S1 S0 module FA_4bits (S,Cout,A,B,Cin); The inputs and the output are begin input [3:0] A, B; 4-bits wide input Cin; we need wires to propagate output [3:0] S; output Cout the carry from one stage to wire Cout0, Cout1, Cout2 the next FA_1bit FA1(S[0], Cout0,A[0],B[0],Cin); you may name the instances FA_1bit FA1(S[1], Cout1,A[1],B[1],Cout0); with any name, but you have FA_1bit FA1(S[2], Cout2,A[2],B[2],Cout1); to maintain the order of the FA_1bit FA1(S[3], Cout,A[3],B[3],Cout2); inputs and outputs end endmodule; 62
  • 63.
    4-bit Adder • Step3: write a test-bench to test your design and generate outs using sample inputs. test_bench initialize the inputs, and read the outputs Write a test_bench to A[3:0] 4 B[3:0] 4 4-bits Full Adder 4 S[3:0] test the design. Cin Cout
  • 64.
    4-bit Adder module test_bench;// you may name it by any name //define the variables you will use in the design reg [3:0] A,B,S; reg Cin, Cout // Create an instance from the full adder FA_4bits FA(S[3:0],Cout, A[3:0], B[3:0], Cin); //initialize the variables once initial A = 5; B = 6; S = 0; Cin = 0; Cout = 0; initial begin $display(“A=%d, B=%d, the sum = %d, and the carry = %d”, A,B,S,Cout) $display $finish end endmodule
  • 65.
    4-bit Adder module test_bench;// you may name it by any name //define the variables you will use in the design reg [3:0] A,B,S; integer I,j; reg Cin, Cout // Create an instance from the full adder FA_4bits FA(S,Cout, A, B, Cin); //initialize the variables once initial begin $monitor ("A: %d B: %d sum: %d carry: %d", A, B, sum, carry); for (i=0; i<16; i=i+1) for (j=0; j<16; j=j+1) begin A = i; B = j; #1 ; end System calls. $finish; $finish end endmodule
  • 66.
  • 67.
    blocksTime1.v module blocksTime1; integeri, j; Another behavioral module. initial Integer data type: other types are begin time, real and realtime (same as real). i = 0; j = 3; $display( "i = %d, j = %d", i, j ); One initial procedural block. $finish; end endmodule
  • 68.
    blocksTime2.v module blocksTime2; integeri, j; initial Time delay models signal propagation begin delay in a circuit. #2 i = 0; #5 j = i; $display( "time = %d, i = %d, j = %d", $time, i, j ); end initial Multiple initial blocks. #3 i = 2; Delays add within each block, but different initial blocks all start initial at time $time = 0 and run #10 $finish; in parallel (i.e., concurrently). endmodule
  • 69.
    blocksTime3.v module blocksTime3; integeri, j; initial begin Important Verilog is a discrete event simulator: #2 i = 0; events are executed in a time-ordered queue. #5 j = i; $display( "time = %d, i = %d, j = %d", $time, i, j ); end initial begin #3 i = 2; #2 j = i; $display( "time = %d, i = %d, j = %d", $time, i, j ); Multiple initial blocks. #1 j = 8; Predict output before $display( "time = %d, i = %d, j = %d", $time, i, j ); you run! end initial #10 $finish; endmodule
  • 70.
    blocksTime4.v module blocksTime4; integeri, j; initial Always block is an infinite loop. Following are same: begin i = 0; always initial initial j = 3; begin begin begin end … while(1) forever end begin begin initial … … #10 $finish; end end end end always begin #1 Comment out this delay. i = i + 1; Run. Explain the problem! j = j + 1; $display( "i = %d, j = %d", i, j ); end endmodule
  • 71.
    clockGenerator.v Port list. Ports can be of three types: input, output, inout. Each must be declared. module clockGenerator(clk); output clk; Internal register. reg clk; Register reg data type can have one of four values: 0, 1, x, z. Registers store a initial value till the next assignment. Registers begin are assigned values in procedural blocks. clk = 0; end If this module is run stand-alone make sure to add a $finish statement here or always simulation will never complete! #5 clk = ~clk; endmodule The delay is half the clock period.
  • 72.
    useClock.v Compile with the clockGenerator.v module. module useClock(clk); input clk; clockGenerator cg(clk); initial #50 $finish; Event trigger. always @(posedge clk) $display("Time = %d, Clock up!", $time); always @(negedge clk) // $display("Time = %d, Clock down!", $time); endmodule
  • 73.
    blocksTime5.v // Ordering processeswithout advancing time module blockTime5; #0 delay causes the statement to execute after other processes integer i, j; scheduled at that time instant have completed. $time does not advance initial till after the statement completes. #0 $display( "time = %d, i = %d, j = %d", $time, i, j ); initial begin i = 0; j = 5; Comment out the delay. end Run. Explain what happens! initial #10 $finish; endmodule
  • 74.
    blocksTime6.v module blocksTime6; integeri, j; Intra-assignment delay: RHS is computed and stored in a temporary (transparent to user) and initial LHS is assigned the temporary after the delay. begin #2 i = 0; j = #5 i; $display( "time = %d, i = %d, j = %d", $time, i, j ); end initial #3 i = 2; Compare output with blocksTime2.v. initial #10 $finish; endmodule
  • 75.
    simpleDataflow.v module aOrNotbOrc(d, a, b, c); A dataflow module does not contain procedures. output d; input a, b, c; Statements in a dataflow module can be re-ordered wire p, q; without affecting the program as they simply describe a set of data manipulations and movements rather than a sequence of actions as assign q = ~b; in behavioral code. In this regard dataflow code is assign p = a || q; very similar to gate-level code. assign d = p || c; endmodule Continuous assignment statements: any change in the RHS causes instantaneous update of the wire on the LHS, unless there is a programmed delay. Use stimulus module from behavioral code.
  • 76.
    simpleGate.v A gate-level module does not contain procedures. module aOrNotbOrc(d, a, b, c); Statements in a gate-level module can be re-ordered output d; without affecting the program as they simply input a, b, c; describe a set of connections rather than a sequence of actions as in behavioral code. A gate-levelmodule wire p, q; is equivalent to a combinational circuit. not(q, b); Wire data type can have one of four values: 0, 1, x, z. or(p, a, q); Wires cannot store values – they are continuously or(d, p, c); driven. endmodule Primitive gates. Verilog provides several such, e.g., and, or, nand, nor, not, buf, etc. Use stimulus module from behavioral code.
  • 77.
  • 78.
    4-to-1 multiplexor (Folder Multiplexor) Following are four different Verilog implementations of the same multiplexor. A stimulus module is shared to test each implementation.
  • 79.
    multiplexor4_1Gate.v module multiplexor4_1(out, in1,in2, in3, in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; Recall default type is wire. wire notcntlr1, notcntrl2, w, x, y, z; not (notcntrl1, cntrl1); Structural gate-level code based not (notcntrl2, cntrl2); exactly on the logic diagram. and (w, in1, notcntrl1, notcntrl2); and (x, in2, notcntrl1, cntrl2); and (y, in3, cntrl1, notcntrl2); and (z, in4, cntrl1, cntrl2); or (out, w, x, y, z); endmodule
  • 80.
    multiplexor4_1Stimulus.v (Folder Multiplexor) module muxstimulus; Stimulus code that generates reg IN1, IN2, IN3, IN4, CNTRL1, CNTRL2; test vectors. wire OUT; multiplexor4_1 mux1_4(OUT, IN1, IN2, IN3, IN4, CNTRL1, CNTRL2); initial begin IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0; $display("Initial arbitrary values"); #0 $display("input1 = %b, input2 = %b, input3 = %b, input4 = %bn", IN1, IN2, IN3, IN4); Concatenation. {CNTRL1, CNTRL2} = 2'b00; #1 $display("cntrl1=%b, cntrl2=%b, output is %b", CNTRL1, CNTRL2, OUT);
  • 81.
    multiplexor4_1Stimulus.v (cont.) {CNTRL1, CNTRL2} = 2'b01; #1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT); {CNTRL1, CNTRL2} = 2'b10; #1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT); {CNTRL1, CNTRL2} = 2'b11; #1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT); end endmodule
  • 82.
    multiplexor4_1Logic.v (Folder Multiplexor) module multiplexor4_1(out, in1, in2, in3 ,in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; assign out = (in1 & ~cntrl1 & ~cntrl2) | RTL (dataflow) code using continuous assignments rather (in2 & ~cntrl1 & cntrl2) | than a gate list. (in3 & cntrl1 & ~cntrl2) | (in4 & cntrl1 & cntrl2); endmodule
  • 83.
    multiplexor4_1Conditional.v (Folder Multiplexor) module multiplexor4_1(out, in1, in2, in3, in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; assign out = cntrl1 ? (cntrl2 ? in4 : in3) : (cntrl2 ? in2 : in1); endmodule More RTL (dataflow) code – this time using conditionals in a continuous assignment.
  • 84.
    multiplexor4_1Case.v (Folder Multiplexor) module multiplexor4_1(out, in1, in2, in3, in4, cntrl1, cntrl2); output out; input in1, in2, in3, in4, cntrl1, cntrl2; reg out; Behavioral code: output out must now be of reg type as it is assigned values in a always @(in1 or in2 or in3 or in4 or cntrl1 or cntrl2) procedural block. case ({cntrl1, cntrl2}) 2'b00 : out = in1; 2'b01 : out = in2; 2'b10 : out = in3; 2'b11 : out = in4; default : $display("Please check control bits"); endcase endmodule
  • 85.
    8-to-3 encoder truthtable Input Output D7 D6 D5 D4 D3 D2 D1 D0 A2 A1 A0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 1 1
  • 86.
    8-to-3 encoder (FolderEncoder) Following are four different Verilog implementations of the same encoder. Each has its own stimulus module.
  • 87.
    encoder8_3Behavioral.v module encoder8_3( encoder_out, enable, encoder_in ); output[2:0] encoder_out; input enable; Sensitivity list. input[7:0] encoder_in; reg[2:0] encoder_out; always @ (enable or encoder_in) Simple behavioral code using the begin case statement. if (enable) case ( encoder_in ) 8'b00000001 : encoder_out = 3'b000; 8'b00000010 : encoder_out = 3'b001; 8'b00000100 : encoder_out = 3'b010; 8'b00001000 : encoder_out = 3'b011; 8'b00010000 : encoder_out = 3'b100; 8'b00100000 : encoder_out = 3'b101; 8'b01000000 : encoder_out = 3'b110; 8'b10000000 : encoder_out = 3'b111; default : $display("Check input bits."); endcase end endmodule
  • 88.
    encoder8_3BehavioralStimulus.v module stimulus; wire[2:0] encoder_out; reg enable; Stimulus for the behavioral code. reg[7:0] encoder_in; encoder8_3 enc( encoder_out, enable, encoder_in ); initial begin enable = 1; encoder_in = 8'b00000010; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); Remove this delay. #1 enable = 0; encoder_in = 8'b00000001; Run. Explain! #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 enable = 1; encoder_in = 8'b00000001; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 $finish; end endmodule
  • 89.
    8-to-3 encoder logicequations A0 = D1 + D3 + D5 + D7 A1 = D2 + D3 + D6 + D7 A2 = D4 + D5 + D6 + D7
  • 90.
    encoder8_3structural.v (Folder Encoder) module encoder8_3( encoder_out , encoder_in ); output[2:0] encoder_out; Structural code. Why is there no input[7:0] encoder_in; enable wire?! Hint: think storage. or( encoder_out[0], encoder_in[1], encoder_in[3], encoder_in[5], encoder_in[7] ); or( encoder_out[1], encoder_in[2], encoder_in[3], encoder_in[6], encoder_in[7] ); or( encoder_out[2], encoder_in[4], encoder_in[5], encoder_in[6], encoder_in[7] ); endmodule
  • 91.
    encoder8_3StructuralStimulus.v module stimulus; wire[2:0] encoder_out; Stimulus for the structural code. reg[7:0] encoder_in; encoder8_3 enc( encoder_out, encoder_in ); initial begin encoder_in = 8'b00000010; #1 $display("encoder_in = %b, encoder_out = %b", encoder_in, encoder_out); #1 encoder_in = 8'b00000001; #1 $display("encoder_in = %b, encoder_out = %b", encoder_in, encoder_out); #1 $finish; end endmodule
  • 92.
    encoder8_3Mixed.v module encoder8_3( encoder_out, enable, encoder_in ); output[2:0] encoder_out; input enable; Mixed structural-behavioral code. Goal was input[7:0] encoder_in; to modify structural code to have an enable reg[2:0] encoder_out; wire, which requires register output for storage. wire b0, b1, b2; or( b0, encoder_in[1], encoder_in[3], encoder_in[5], encoder_in[7] ); or( b1, encoder_in[2], encoder_in[3], encoder_in[6], encoder_in[7] ); or( b2, encoder_in[4], encoder_in[5], encoder_in[6], encoder_in[7] ); always @(enable or encoder_in) Be careful with mixed design! It’s begin working may be difficult to understand. if (enable) encoder_out = {b2, b1, b0}; end endmodule
  • 93.
    encoder8_3MixedStimulus.v module stimulus; wire[2:0] encoder_out; reg enable; Stimulus for the mixed code. reg[7:0] encoder_in; encoder8_3 enc( encoder_out, enable, encoder_in ); initial begin Output is puzzling! Explain! enable = 1; encoder_in = 8'b00000010; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 enable = 1; encoder_in = 8'b00000010; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out);
  • 94.
    encoder8_3MixedStimulus.v #1 enable = 0; encoder_in = 8'b00000001; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 enable = 1; encoder_in = 8'b10000000; #1 $display("enable = %b, encoder_in = %b, encoder_out = %b", enable, encoder_in, encoder_out); #1 $finish; end endmodule
  • 95.
  • 96.
    comparator.v Parameters that maybe set Comparator makes the comparison A ? B when the module is instantiated. where ? Is determined by the input greaterNotLess and returns true(1) or false(0). module comparator (result, A, B, greaterNotLess); parameter width = 8; parameter delay = 1; input [width-1:0] A, B; // comparands input greaterNotLess; // 1 - greater, 0 - less than output result; // 1 if true, 0 if false assign #delay result = greaterNotLess ? (A > B) : (A < B); endmodule
  • 97.
    stimulus.v Stimulus for the comparator. module system; wire greaterNotLess; // sense of comparison wire [15:0] A, B; // comparand values - 16 bit wire result; // comparison result // Module instances comparator #(16, 2) comp (result, A, B, greaterNotLess); testGenerator tg (A, B, greaterNotLess, result); endmodule Parameters being set at module instantiation.
  • 98.
    testGen.v module testGenerator (A,B, greaterNotLess, result); output [15:0] A, B; output greaterNotLess; Module that generates test vectors for input result; the comparator and checks correctness parameter del = 5; of output. reg [15:0] A, B; reg greaterNotLess; task check; input shouldBe; Task definition: a task is exactly like a procedure in a conventional programming language. begin if (result != shouldBe) $display("Error! %d %s %d, result = %b", A, greaterNotLess?">":"<", B, result); end endtask initial begin // produce test data, check results A = 16'h1234; B = 16'b0001001000110100; greaterNotLess = 0;
  • 99.
    testGen.v (cont.) #del check(0); B = 0; Task call greaterNotLess = 1; #del check(1); A = 1; greaterNotLess = 0; #del check(0); $finish; end endmodule
  • 100.
  • 101.
    Standard Form fora Verilog FSM // state flip-flops // REGISTER DEFINITION reg [2:0] state, nxt_st; always@(posedge clk) // state definitions begin parameter reset=0,S1=1,S2=2,S3=3,.. state<=next_state; end // NEXT STATE CALCULATIONS always@(state or inputs or ...) // OUTPUT CALCULATIONS begin output= f(state, inputs) … next_state= ... … end 101
  • 102.
    Example module myFSM (clk,x, z) // NEXT STATE CALCULATIONS input clk, x; always @(state or x) output z; begin // state flip-flops case (state) reg [2:0] state, nxt_st; S0: if(x) nxt_st=S1; // state definition else nxt_st=S0; S1: if(x) nxt_st=S3; parameter S0=0,S1=1,S2=2,S3=3,S7=7 else nxt_st=S2; S2: if(x) nxt_st=S0; else nxt_st=S7; // REGISTER DEFINITION S3: if(x) nxt_st=S2; always @(posedge clk) else nxt_st=S7; begin S7: nxt_st=S0; state<=nxt_st; default: nxt_st = S0; end endcase end // OUTPUTCALCULATIONS assign z = (state==S7); endmodule 102
  • 103.
    0111 Sequence Detector 1 1 S0 0 z=0 S4 0 S1 0 z=1 z=0 0 1 0 1 S3 S2 z=0 z=0 1 103
  • 104.
  • 105.
    System tasks • Usedto generate input and output during simulation. Start with $ sign. • Display Selected Variables: $display (“format_string”,par_1,par_2,...); $monitor(“format_string”,par_1,par_2,...); Example: $display(“Output z: %b”, z); • Writing to a File: $fopen, $fdisplay, $fmonitor and $fwrite • Random number generator: $random (seed) • Query current simulation time: $time 105
  • 106.
    Test Benches Overview Approach 1. Invoke the verilog under 3. Initialize all inputs design 5. Set the clk signal 2. Simulate input vectors 7. Send test vectors 3. Implement the system tasks to view the results 9. Specify when to end the simulation. 106
  • 107.
    Example ‘timescale1 ns /100ps // timeunit =1ns; precision=1/10ns; /****SPECIFY THE INPUT WAVEFORM x ****/ module my_fsm_tb; Initial begin reg clk, rst, x; #1 x=0; wire z; #400 x=1; $display(“Output z: %b”, z); /**** DESIGN TO SIMULATE (my_fsm) #100 x=0; INSTANTIATION ****/ @(posedge clk) x=1; myfsm dut1(clk, rst, x, z); #1000 $finish; //stop simulation /****RESET AND CLOCK SECTION****/ //without this, it will not stop Initial end begin endmodule clk=0; rst=0; #1rst=1; /*The delay gives rst a posedge for sure.*/ #200 rst=0; //Deactivate reset after two clock cycles +1ns*/ end always #50clk=~clk; /* 10MHz clock (50*1ns*2) with 50% duty-cycle */ 107
  • 108.

Editor's Notes