COE 405 Logic Design with Behavioral Models of
COE 405 Logic Design with Behavioral Models of Combinational & Sequential Logic Dr. Aiman H. El-Maleh Computer Engineering Department King Fahd University of Petroleum & Minerals
Outline n Behavioral Modeling n Data Types for Behavioral Modeling n Boolean Equation-Based Behavioral Models of Combinational Logic n Assign Statement n Verilog Operators n Propagation Delay & Continuous Assignment n Always Block, Procedural Assignment n If and Case Statements n Latches & D Flip-Flops 1 -2
Outline n Data Flow / Register Transfer Level (RTL( n Algorithm-Based Models n Repetitive Algorithms n Tasks and Functions n Behavioral Modeling of Control Unit n Behavioral Models of Counters n Behavioral Models of Registers n File I/O system functions and tasks 1 -3
Behavioral Modeling n Behavioral modeling describes the functionality of a design • What the design will do • Not how the design will be built in hardware n Behavioral models specify the input-output model of a logic circuit and suppress details about its low level internal structure. n Behavioral modeling encourages designers to • Rapidly create a behavioral prototype of a design • Verify its functionality • Use synthesis tool to optimize and map design into a given technology 1 -4
Data Types for Behavioral Modeling n All variables in Verilog have a predefined type. n There are two families of data types: nets and registers. n Net variables act like wires in physical circuit and establish connectivity between design objects. n Net types include: wire, tri, wand, wor, triand, trior, supply 0, supply 1, tri 0, tri 1, trireg. n Register variables act like variables in ordinary procedural languages – they store information while the program executes. n Register types include: reg, integer, realtime, time. 1 -5
Data Types for Behavioral Modeling n For synthesis, we use mainly the data types wire, reg and integer. n A wire and a reg have a default size of 1 bit. n Size of integer is the size of word length in a computer, at least 32. n A reg variable may never be the output of a primitive gate, the target of continuous assignment. 1 -6
Boolean Equation-Based Behavioral Models of Combinational Logic n A Boolean equation describes combinational logic by an expression of operations on variables. n In Verilog, this is done by continuous assignment statement. n Example: module AOI_5_CA 0 ( input x_in 1, x_in 2, x_in 3, x_in 4, x_in 5, output y_out ); assign y_out = !( (x_in 1 && x_in 2) || (x_in 3 && x_in 4 && x_in 5) ); endmodule 1 -7
Assign Statement n The keyword assign declares a continuous assignment. n It associates the Boolean expression on the RHS with the variable on the LHS. n The assignment is sensitive to the variables in the RHS. n Any time an event occurs on any of the variables on the RHS, the RHS expression is revaluated and the result is used to update the LHS. n A continuous assignment is said to describe implicit combinational logic. 1 -8
Assign Statement module AOI_5_CA 1 ( input x_in 1, x_in 2, x_in 3, x_in 4, x_in 5, enable, output y_out ); assign y_out = enable ? !((x_in 1 && x_in 2) || (x_in 3 && x_in 4 && x_in 5)) : 1’bz; endmodule 1 -9
Assign Statement n The conditional operator (? : ) acts like a software if-then -else switch that selects between two expressions. n If the value of enable is true, the expression to the right of the ? Is evaluated and used to assign value to y_out. n Otherwise, the expression to the right of the : is used. n Using 1’bz illustrates how to write models that include three-state outputs. n A module may contain multiple continuous assignments; the assignments are active concurrently with all other continuous assignments, primitives, behavioral statements, and instantiated modules. 1 -10
Assign Statement module Mux_2_32_CA #(parameter word_size=32) ( output [wordsize-1: 0] mux_out, input [wordsize-1: 0] data_1, data_0, input select ); assign mux_out = select ? data_1 : data_0; endmodule 1 -11
Verilog Operators {} concatenation ~ bit-wise NOT + - * / ** arithmetic & bit-wise AND % modulus | bit-wise OR > >= < <= relational ^ bit-wise XOR ^~ ~^ bit-wise XNOR & reduction AND | reduction OR ~& reduction NAND ~| reduction NOR ^ reduction XOR ! logical NOT && logical AND || logical OR == logical equality != logical inequality === case equality ~^ ^~ reduction XNOR !== case inequality << shift left ? : conditional >> shift right 1 -12
Verilog Operators n Arithmetic Operators: • Each operator takes two operands. + and – could also take a • • • n single operand During synthesis, the + and - operators infer an adder and a subtractor Xilinx XST software can infer a block multiplier during synthesis for the multiplication operator /, %, and ** operators usually cannot be synthesized automatically Shift operators: Four shift operators • >>, << logical shift right and left (0 s inserted from the right or • the left) >>>, <<< arithmetic shift right and left (sign bits are shifted in for the >>> operation and 0's are shifted in for the <<< operation) 1 -13
Verilog Operators • If both operands of a shift operator are signals, as in a << b, • n the operator infers a barrel shifter, a fairly complex circuit If the shifted amount is fixed, as in a << 2, the operation infers no logic and involves only routing of the input signals (can also be done with {} operator) Examples of shift operations: 1 -14
Verilog Operators n Relational and equality operators: • compare two operands and return a 1 -bit logical (Boolean) • • value: either 0 or 1 4 relational operators: >, <, <=, and >= 4 equality operators: ==, ! =, ===, and ! == Case equality (===) and case inequality (! ==) operators, take the x and z bits in the operands into consideration in the match cannot be synthesized. The relational operators and the == and ! = operators infer comparators during synthesis 1 -15
Verilog Operators n Bitwise operators: • 4 basic bitwise operators: & (and), I (or), ^ (xor), and ! (not) • The first three operators require two operands • Negation and xor operation can be combined, as in ~^ or ^~ • • to form the xnor operations are performed on a bit-by-bit basis Ex. : let a, b, and c be 4 -bit signals: i. e. wire [3: 0] a , b , c ; The statement: assign c = a I b ; is the same as: assign c[3] = a[3] I b[3]; assign c[2] = a[2] I b[2]; assign c[1] = a[1] I b[1]; assign c[0] = a[0] I b[0]; 1 -16
Verilog Operators n Reduction operators: &, I , and ^ operators may have only one operand then are known as reduction operators. • The single operand usually has an array data type. • The designated operation is performed on all elements of the • array and returns a I-bit result. For example, let a be a 4 -bit signal and y be a 1 -bit signal: wire [3: 0] a ; wire y ; The statement: assign y = I a ; // only one operand is the same as: assign y = a[3] | a[2] | a[1] | a[0] ; 1 -17
Verilog Operators n Logical operators: && (logical and), II (logical or), and ! (logical negate) • operands of a logical operator are interpreted as false (when • • n all bits are 0's) or true (when at least one bit is 1), and the operation always returns a 1 -bit result Usually used as logical connectives of Boolean expressions, bitwise and logical operators can be used interchangeably in some situations. Examples of bitwise and logical operations 1 -18
Verilog Operators n Conditional operator: ? : takes three operands and its general format is [signal] = [boolean-exp] ? [true-exp] : [false-exp]; • The [boolean-expl] is a Boolean expression that returns true • • • (1’b 1) or false ( 1'b 0). Ex. : assign max = (a>b) ? a : b; //max will get the maximum of the signals a and b The operator can be thought as a simplified if-then-else statement. Infers a mux. Can be cascaded or nested: assign max = (a>b) ? ((a>c) ? a : c) : ((b>c) ? b : c ) ; max of three ignals // 1 -19
Verilog Operators n Concatenation and replication operators: { } and {{ }} n { } combines segments of elements and small arrays to form a large array: wire a 1; wire [3: 0] a 4; wire [7: 0] b 8, c 8, d 8; assign b 8 = {a 4 , a 4} ; assign c 8 = {a 1, a 4, 2'b 00 } ; assign d 8 = {b 8[3: 0] , c 8[3: 0]} ; n Concatenation operator involves reconnection of the input and output signals and only requires "wiring”. Can be used for shifting or rotating data. 1 -20
Verilog Operators wire [7: 0] a, rot, shl , sha; assign rot = {a[2: 0], a[7: 3]) ; // Rotate a to right 3 bits assign shl = {3'b 000, a[7: 3]) ; // shift a to right 3 bits and insert 0 s (logical shift) assign sha = {a[7] , a[7: 3]} ; // arithmetic shift a to right 3 bits n The replication operator, N{ }, replicates the enclosed string. The replication constant, N, specifies the number of replications. For example: {4{2 'b 01}} returns 8' b 0101. 1 -21
Full Adder module fadd (output Cout, S, input A, B, Cin); assign S = A ^(B ^ Cin); assign Cout = (A & B) | (A & Cin) | (B & Cin) ; endmodule 1 -22
Behavioral Description of an Adder module adder #(parameter width = 4) (output cout, output [width-1: 0] sum, input [width-1: 0] a, b, input cin); 4 -bit operands, 5 -bit result assign {cout, sum} = a + b + cin; // note: Verilog treats wires as ‘unsigned’ numbers endmodule { Cout, S } is a 5 bit bus: Cout S[3] S[2] S[1] S[0] 1 -23
Propagation Delay & Continuous Assignment n Propagation delay can be associated with a continuous assignment so that its implicit logic has same functionality and timing characteristics as its gate level implementation. module fadd (output Cout, S, input A, B, Cin); assign #10 S = A ^(B ^ Cin); assign #10 Cout = (A & B) | (A & Cin) | (B & Cin) ; endmodule 1 -24
Always Block n always blocks are procedural blocks that contain sequential statements. n Syntax always @(sensitivity list) begin ………. end n sensitivity list prevents the always block from executing again until another change occurs on a signal in the sensitivity list. • Level type • always @(a or b or c) • Edge type • always @(posedge clock) • always @(negedge clock) 1 -25
Procedural Assignment n Assignments inside an always block are called procedural assignments n Can only be used within an always block or initial block n Two types : blocking assignment and nonblocking assignment. Basic syntax : • [variable-name] = [expression] ; // blocking assignment • [variable-name] <= [expression] ; // nonblocking assignment n In a blocking assignment, the expression is evaluated and then assigned to the variable immediately, before execution of the next statement (the assignment thus "blocks" the execution of other statements). It behaves like the normal variable assignment in the C language. 1 -26
Procedural Assignment n In a nonblocking assignment, the evaluated expression is assigned at the end of the always block (the assignment thus does not block the execution of other statements). n The basic rule of thumb is: n if-else and case statement are only in always block. • Use blocking assignments for a combinational circuit. • Use nonblocking assignments for a sequential circuit. 1 -27
Wire vs. Reg n There are two types of variables in Verilog: n Both variables can be used as inputs anywhere • wire (all outputs of assign statements must be wire) • reg (all outputs modified in always blocks must be reg) • Can use reg or wire as inputs (RHS) to assign statements • assign bus = Latch. Output + Immediate. Value • // bus must be a wire, but Latch. Output can be a reg • Can use reg or wire as inputs (RHS) in always blocks • always @ (in or clk) • if (clk) out = in // in can be a wire, out must be a reg 1 -28
Algorithm-Based Models n Algorithms prescribe a sequence of procedural assignments within a cyclic behavior. n The algorithm described by the model does not have explicit binding to hardware. n It does not have an implied architecture of registers, datapaths and computational resources. n This style is most challenging for a synthesis tool. n Synthesis tool needs to perform architectural synthesis which extracts the needed resources and schedules them into clock cycles. 1 -29
If Statements Syntax if (expression) begin. . . procedural statements. . . end else if (expression) begin. . . statements. . . end. . . more else if blocks else begin. . . statements. . . end module ALU #(parameter n=8) (output reg [n-1: 0] c, input [1: 0] s, input [n-1: 0] a, b); always @(s or a or b) begin if (s==2'b 00) c = a + b; else if (s==2'b 01) c = a - b; else if (s==2'b 10) c = a & b; else c = a | b; endmodule 1 -30
Case Statements Syntax case (expression) case_choice 1: begin. . . statements. . . end case_choice 2: begin. . . statements. . . end. . . more case choices blocks. . . default: begin. . . statements. . . endcase module ALU 2 #(parameter n=8) (output reg [n-1: 0] c, input [1: 0] s, input [n-1: 0] a, b); always @(s or a or b) begin case (s) 2'b 00: c = a + b; 2'b 01: c = a - b; 2'b 10: c = a & b; default: c = a | b; endcase endmodule 1 -31
Example: Full Adder module fadd 2 (output reg S, Cout, input A, B, Cin); always @(A or B or Cin) begin S = (A ^ B ^ Cin); Cout = (A & B) | (A & Cin) | (B & Cin); endmodule 1 -32
Example: Comparator module comp #(parameter width=32) (input [width-1: 0] A, B, output A_gt_B, A_lt_B, A_eq_B); assign A_gt_B = (A>B); assign A_lt_B = (A<B); assign A_eq_B = (A==B); endmodule 1 -33
Example: Comparator module comp 2 #(parameter width=2) (input [width-1: 0] A, B, output reg A_gt_B, A_lt_B, A_eq_B); always @(A, B) begin A_gt_B = 0; A_lt_B = 0; A_eq_B = 0; if (A == B) A_eq_B = 1; else if (A > B) A_gt_B = 1; else A_lt_B = 1; endmodule 1 -34
Example: 2 x 1 Multiplexer n Method 1 module mux 2 x 1 (input b, c, select, output a); assign a = (select ? b : c); endmodule n Method 2 module mux 2 x 1 (input b, c, select, output reg a); always@(select or b or c) begin if (select) a=b; else a=c; endmodule Method 3 module mux 2 x 1 (input b, c, select, output reg a); always@(select or b or c) begin case (select) 1’b 1: a=b; 1’b 0: a=c; endcase endmodule 1 -35
Example: De. Mux module demux ( input D, select, output reg y 0, y 1); always @( D or select ) begin if( select == 1’b 0) begin y 0 = D; y 1 = 1’b 0; end else begin y 0 = 1’b 0; y 1 = D; end endmodule 1 -36
Example: Arithmetic Unit module arithmetic #(parameter width=8) (input [width-1: 0] A, B, input [1: 0] Sel, output reg [width-1: 0] Y, output reg Cout); always @(A or B or Sel) begin case (Sel) 2'b 00 : {Cout, Y} = A+B; 2'b 01 : {Cout, Y} = A-B; 2'b 10 : {Cout, Y} = A+1; 2'b 11 : {Cout, Y} = A-1; default: begin Cout=0; Y=0; endcase endmodule 1 -37
Example: Logic Unit module logic #(parameter width=4) (input [width-1: 0] A, B, input [2: 0] Sel, output reg [width-1: 0] Y); always @(A or B or Sel) begin case (Sel) 3'b 000 : Y = A & B; // A and B 3'b 001 : Y = A | B; // A or B 3'b 010 : Y = A ^ B; // A xor B 3'b 011 : Y = ~A; // 1’s complement of A 3'b 100 : Y = ~(A & B); // A nand B 3'b 101 : Y = ~(A | B); // A nor B default : Y = 0; endcase endmodule 1 -38
Latches & Level-Sensitive Circuits n Latch can be modeled as: module latch (output q, qb, input set, reset); assign q = ~(set & qb); assign qb = ~(reset & q); endmodule n Some synthesis tools do not accommodate this form of feedback. n Latch is inferred by synthesis tools as follows: module dlatch (output q, input data_in, enable); assign q = enable ? data_in : q; endmodule dlatch 2 (output q, input data_in, enable, reset); assign q = (reset==1'b 0)? 0: enable ? data_in : q; endmodule 1 -39
D Latch module dlatch (output q, input data, enable); assign q = enable ? data: q; endmodule dlatch 2 (output reg q, input data, enable); always @(enable, data) if (enable == 1'b 1) q <= data; endmodule 1 -40
D Flip Flop – Synchronous Set/Reset module dff (output reg q, output q_bar, input data, set_b, reset_b, clk); assign q_bar = !q; always @(posedge clk) // Synchronous set/reset if (reset_b == 1'b 0) q <= 0; else if (set_b == 1'b 0) q <=1; else q <= data; endmodule 1 -41
D Flip Flop – Asynchronous Set/Reset module dff 2 (output reg q, output q_bar, input data, set_b, reset_b, clk); assign q_bar = !q; always @(posedge clk, negedge set_b, negedge reset_b ) // Asynchronous set/reset if (reset_b == 1'b 0) q <= 0; else if (set_b == 1'b 0) q <=1; else q <= data; endmodule 1 -42
Data Flow/ RTL Models n Data flow models describe concurrent operations on signals where computations are initiated at active edges of a clock and completed to be stored in a register at next active edge. n Also referred to as Register Transfer Level (RTL) as they describe transfer of data among registers. n A behavioral model of combinational logic can be described using concurrent assign statements or always statements. n A behavioral model of sequential logic can be described using always statements. 1 -43
Shift Register module shiftreg (output reg A, input E, clk, rst); reg B, C, D; always @(posedge clk, posedge rst) begin if (rst == 1'b 1) begin A=0; B=0; C=0; D=0; end else begin A = B; B = C; C = D; D = E; end endmodule 1 -44
Shift Register module shiftreg 2 (output reg A, input E, clk, rst); reg B, C, D; always @(posedge clk, posedge rst) begin if (rst == 1'b 1) begin A=0; B=0; C=0; D=0; end else begin D = E; What will happen in this model? C = D; B = C; A = B; end endmodule 1 -45
Shift Register module shiftreg 3 (output reg A, input E, clk, rst); reg B, C, D; always @(posedge clk, posedge rst) begin if (rst == 1'b 1) begin A<=0; B<=0; C<=0; D<=0; end else begin A <= B; B <= C; Non-blocking assignments (<=) execute concurrently. So they are order independent. C <= D; D <= E; end endmodule 1 -46
Behavioral Models of Multiplexor module Mux_4_1 #(parameter width=32) (output [width-1: 0] mux_out, input [width-1: 0] data_3, data_2, data_1, data_0, input [1: 0] select, input enable); reg [width-1: 0] mux_int; assign mux_out = enable ? mux_int : 'bz; always @(data_3, data_2, data_1, data_0, select) case (select) 0: mux_int = data_0; 1: mux_int = data_1; 2: mux_int = data_2; 3: mux_int = data_3; default: mux_int = 'bx; endcase endmodule 1 -47
Behavioral Models of Multiplexor module Mux_4_1_IF #(parameter width=32) (output [width-1: 0] mux_out, input [width-1: 0] data_3, data_2, data_1, data_0, input [1: 0] select, input enable); reg [width-1: 0] mux_int; assign mux_out = enable ? mux_int : 'bz; always @(data_3, data_2, data_1, data_0, select) if (select==0) mux_int = data_0; else if (select==1) mux_int = data_1; else if (select==2) mux_int = data_2; else if (select==3) mux_int = data_3; else mux_int = 'bx; endmodule 1 -48
Behavioral Models of Multiplexor module Mux_4_1_CA #(parameter width=32) (output [width-1: 0] mux_out, input [width-1: 0] data_3, data_2, data_1, data_0, input [1: 0] select, input enable); wire [width-1: 0] mux_int; assign mux_out = enable ? mux_int : 'bz; assign mux_int = (select==0) ? data_0: (select==1) ? data_1: (select==2) ? data_2: (select==3) ? data_3: 'bx; endmodule 1 -49
Behavioral Models of Encoder module encoder (output reg [2: 0] Code, input [7: 0] Data); always @(Data) if (Data==8'b 00000001) Code = 0; else if (Data==8'b 00000010) Code = 1; else if (Data==8'b 00000100) Code = 2; else if (Data==8'b 00001000) Code = 3; else if (Data==8'b 00010000) Code = 4; else if (Data==8'b 00100000) Code = 5; else if (Data==8'b 01000000) Code = 6; else if (Data==8'b 10000000) Code = 7; else Code = 'bx; endmodule 1 -50
Behavioral Models of Encoder module priority (output reg [2: 0] Code, output valid_data, input [7: 0] Data); assign valid_data = | Data; always @(Data) if (Data[7]) Code = 7; else if (Data[6]) Code = 6; else if (Data[5]) Code = 5; else if (Data[4]) Code = 4; else if (Data[3]) Code = 3; else if (Data[2]) Code = 2; else if (Data[1]) Code = 1; else if (Data[0]) Code = 0; else Code = 'bx; endmodule 1 -51
Behavioral Models of Encoder module priority 2 (output reg [2: 0] Code, output valid_data, input [7: 0] Data); assign valid_data = | Data; always @(Data) casex (Data) 8'b 1 xxxxxxx : Code = 7; 8'b 01 xxxxxx : Code = 6; 8'b 001 xxxxx : Code = 5; 8'b 0001 xxxx : Code = 4; 8'b 00001 xxx : Code = 3; 8'b 000001 xx : Code = 2; 8'b 0000001 x : Code = 1; 8'b 00000001 : Code = 0; default: Code = 'bx; endcase endmodule casex treats x values in the inputs as don’t care 1 -52
Behavioral Models of Decoder module decoder (output reg [7: 0] Data, input [2: 0] Code); always @(Code) if (Code == 0 ) Data= 8'b 00000001; else if (Code == 1 ) Data= 8'b 00000010; else if (Code == 2 ) Data= 8'b 00000100; else if (Code == 3 ) Data= 8'b 00001000; else if (Code == 4 ) Data= 8'b 00010000; else if (Code == 5 ) Data= 8'b 00100000; else if (Code == 6 ) Data= 8'b 01000000; else if (Code == 7 ) Data= 8'b 10000000; else Data = 'bx; endmodule 1 -53
Seven Segment Display Decoder module Seven_Segment_Display (output reg [6: 0] Display, input [3: 0] BCD); parameter BLANK = 7’b 111_1111; parameter ZERO= 7’b 000_0001; //abc_defg parameter ONE= 7’b 100_1111; parameter TWO= 7’b 001_0010; parameter THREE= 7’b 000_0110; parameter FOUR= 7’b 100_1100; parameter FIVE= 7’b 010_0100; parameter SIX= 7’b 010_0000; parameter SEVEN= 7’b 000_1111; parameter EIGHT= 7’b 000_0000; parameter NINE= 7’b 000_0100; always @(BCD) case (BCD) 0: Display = ZERO; 1: Display = ONE; 2: Display = TWO; 3: Display = THREE; 4: Display = FOUR; 5 : Display = FIVE; 6: Display = SIX; 7: Display = SEVEN; 8: Display = EIGHT; 9: Display = NINE; default: DISPLAY = BLANK; endcase endmodule 1 -54
Linear Feedback Shift Register (LFSR) 1 -55
Linear Feedback Shift Register (LFSR) 1 -56
Linear Feedback Shift Register (LFSR) module LFSR #(parameter Length=8, initial_state = 8'b 1001_0001, //91 h parameter [Length: 1] (input Tap_Coefficient = 8'b 1100_1111) clock, reset_b, output reg [1: Length] Y); always@ (posedge clock) if (reset_b == 1'b 0) Y<= initial_state; else begin Y[1] <= Y[8]; Y[2] <= Tap_Coefficient[7]? Y[1]^Y[8]: Y[1]; Y[3] <= Tap_Coefficient[6]? Y[2]^Y[8]: Y[2]; Y[4] <= Tap_Coefficient[5]? Y[3]^Y[8]: Y[3]; Y[5] <= Tap_Coefficient[4]? Y[4]^Y[8]: Y[4]; Y[6] <= Tap_Coefficient[3]? Y[5]^Y[8]: Y[5]; Y[7] <= Tap_Coefficient[2]? Y[6]^Y[8]: Y[6]; Y[8] <= Tap_Coefficient[1]? Y[7]^Y[8]: Y[7]; endmodule 1 -57
Repetitive Algorithms n for loop: • for (initial_statement; control expression; index_statement) • • statement_for_execution; initial_statement executes once to initialize a register variable (i. e. an integer or reg) that controls the loop If control_expression is true the statement_for_execution will execute After the statement_for_execution has executed, the index_statement will execute (usually to increment a counter) Then the control expression is checked again and if false the loop terminates. 1 -58
Linear Feedback Shift Register (LFSR) module LFSR 2 #(parameter Length=8, initial_state = 8'b 1001_0001, //91 h parameter [Length: 1] Tap_Coefficient = 8'b 1100_1111) (input clock, reset_b, output reg [1: Length] Y); integer k; always@ (posedge clock) if (reset_b == 1'b 0) Y<= initial_state; else begin for (k = 2; k <= Length; k = k+1) if (Tap_Coefficient[Length-k+1]==1) Y[k] <= Y[k-1]^Y[Length]; else Y[k] <= Y[k-1]; Y[1] <= Y[Length]; endmodule 1 -59
Linear Feedback Shift Register (LFSR) module LFSR 3 #(parameter Length=8, initial_state = 8'b 1001_0001, //91 h parameter [Length: 1] Tap_Coefficient = 8'b 1100_1111) (input clock, reset_b, output reg [1: Length] Y); integer k; always@ (posedge clock) if (reset_b == 1'b 0) Y<= initial_state; else begin for (k = 2; k <= Length; k = k+1) Y[k] <= Tap_Coefficient[Length-k+1]? Y[k-1]^Y[Length]: Y[k-1]; Y[1] <= Y[Length]; endmodule 1 -60
Majority module Majority #(parameter size=8, max=4, majority=5) (input [size-1: 0] Data, output reg Y); reg [max-1: 0] count; integer k; always@ (Data) begin count = 0; for (k=0; k < size; k = k+1) if (Data[k] == 1) count = count + 1; Y = (count >= majority); endmodule 1 -61
Repetitive Algorithms n repeat loop • repeat (expression) statement; • executes an associated statement or block of statements a specified number of times unless it is terminated by a disable statement within the activity flow n Example: a repeat loop is used to initialize a memory array word_address = 0; repeat (memory_size) begin memory[word_address]=0; word_address = word_address+1; end 1 -62
Repetitive Algorithms n while loop • while (expression) statement; • Executes repeatedly while a Boolean expression is true module Count. Ones (input [7: 0] reg_a, output reg [3: 0] count); always@ (reg_a) begin: count_of_1 s // declares a named block of statements reg [7: 0] temp_reg; count = 0; temp_reg = reg_a; // load a data word while (temp_reg) begin if (temp_reg[0]) count = count + 1; // count = count + temp_reg[0]; temp_reg = temp_reg >> 1; end endmodule 1 -63
Clock Generators module clockgen (output reg clock); parameter half_cycle = 50; parameter stop_time = 350; initial begin: clock_loop clock = 0; forever begin #half_cycle clock = 1; #half_cycle clock = 0; end initial #stop_time disable clock_loop; endmodule 1 -64
Disable Statement n Disable statement is used to prematurely terminate a named block of procedural statements. Execution is transferred to the statement that immediately follows the named block. module find_first_one (output reg [3: 0] index_value, input [15: 0] A_word, input trigger); always @(posedge trigger) begin: search_for_1 for (index_value=0; index_value<15; index_value=index_value+1) if (A_word[index_value] == 1) disable search_for_1; endmodule Not Supported by Synthesis Tools 1 -65
Tasks and Functions n Tasks create a hierarchical organization of procedural statements within a Verilog behavior. n Functions substitute for an expression. n Tasks and functions facilitate a readable style of code, with a single identifier conveying the meaning of many lines of code. n Encapsulation of Verilog code into tasks or functions hides the details of an implementation. n Overall, tasks and functions improve the readability, portability and maintainability of a model. 1 -66
Tasks n Tasks are declared within a module and they may be referenced from within a cyclic or single-pass behavior. n A task can have parameters passed to it and results of executing a task can be passed back to environment. n When a task is called, copies of parameters in environment are associated with inputs, outputs, and inouts within the task according to order of declaration n The variables in environment are visible to a task. n Local variables may be declared within a task. n A task can call itself. 1 -67
Tasks n A task must be named and may include declarations of any number of: parameter, input, output, inout, reg, integer, real, time, realtime. n Arguments of a task retain the type they hold in the environment that invokes the task. n All arguments of a task are passed by a value. n The basic syntax of a task is: task [task-id] ([arg]) ; begin [statements] ; endtask n [arg] is the argument declaration and is similar to port declaration except that the default output data type is reg and the wire data type can not be used as output. 1 -68
Tasks module adder_task (output reg c_out, output reg [3: 0] sum, input [3: 0] data_a, data_b, input c_in, clk, reset); always @(posedge clk, posedge reset) if (reset == 1’b 1) {c_out, sum} <= 0; else add_values(c_out, sum, data_a, data_b, c_in); task add_values (output c_out, output [3: 0] sum, input [3: 0] data_a, data_b, input c_in); {c_out, sum} <= data_a + data_b + c_in; endtask endmodule 1 -69
Tasks module adder_task 2 (output reg [5: 0] sum, input [3: 0] data_a, data_b, data_c, data_d, input clk, reset); reg [5: 0] sum 1, sum 2; always @(posedge clk, posedge reset) if (reset == 1) sum = 0; else begin add_values 2(sum 1, data_a, data_b); add_values 2(sum 2, data_c, data_d); add_values 2(sum, sum 1, sum 2); end task add_values 2 (output [5: 0] sum, input [5: 0] data_a, data_b); sum = data_a + data_b; endtask endmodule 1 -70
Tasks module eq 2 task (output reg aeqb, input [1: 0] a, b); reg e 0, e 1; always @* begin equ_task(2, a[0], b[0], e 0); equ_task(2, a[1], b[1], e 1); aeqb = e 0 & e 1; end task equ_task(input integer delay, input i 0, i 1, output eq); #delay eq = i 0 ~^ i 1; endtask endmodule 1 -71
Functions n Verilog functions are declared within a parent module and can be referenced in any valid expression. n A function is implemented by an expression and returns a value at the location of the function’s identifier. n Functions may implement only combinational behavior. n A function may not contain timing controls (#, @, wait), non-blocking statements. n Functions may not invoke a task but they may call other functions but not recursively. n Functions are expanded during synthesis and "flattened”. 1 -72
Functions n Basic syntax of a function is shown below: n [result-type] is the data type of the returned result (usually reg or integer). n Function name is specified by [func-id] n Function value is returned by a statement like: func-id =…; 1 -73
Functions n Consider the following module snippet: with one operation repeated 4 times n We can define a function ba and use it: n ba takes a 4 -bit reg argument and returns a 4 -bit reg signal 1 -74
Functions n A function could be used to calculate the constants whose values depend on other parameters: Note that the function in this example is evaluated during pre-processing, it does not infer any hardware (the for loop is usually not synthesizable) module modulo_counter #(parameter M=10)( input clk, reset, output reg [log 2 (M)-1: 0] q ); always @ (posedge clk) if (reset || q==M) q <= 0; else q <= q + 1; function integer log 2 (input integer n); integer i; begin log 2 = 1; for (i=0; 2**i<n; i=i+1) log 2 = i+1; endfunction endmodule 1 -75
Functions module arithmetic_unit ( output [4: 0] result_1, output [3: 0] result_2, input [3: 0] operand_1, operand_2); assign result_1 = sum_of_operands (operand_1, operand_2); assign result_2 = largest_operand (operand_1, operand_2); function [4: 0] sum_of_operands (input [3: 0] operand_1, operand_2); sum_of_operands = operand_1 + operand_2; endfunction [3: 0] largest_operand (input [3: 0] operand_1, operand_2); largest_operand = (operand_1 >= operand_2) ? operand_1: operand_2; endfunction endmodule 1 -76
FSM Modeling n Moore Sequence Detector: Detection sequence is 110 1 -77
FSM Modeling module moore_110_detector (output reg z, input x, clk, rst ); parameter reset = 2'b 00, got 1=2'b 01, got 11=2'b 10, got 110=2'b 11; reg [1: 0] state, next_state; always @(posedge clk) if (rst) state <= reset; else state <= next_state; always @(state, x) begin z = 0; case (state) reset: if (x) next_state=got 1; else next_state=reset; got 1: if (x) next_state=got 11; else next_state=reset; got 11: if (x) next_state=got 11; else next_state=got 110; got 110: begin z=1; if (x) next_state=got 1; else next_state=reset; endcase endmodule 1 -78
Behavioral Modeling of Control Unit module Controller (output reg Clr_P 1_P 0, Ld_R 0, input En, Ld, clk, rst); parameter S_idle = 2'b 00, S_1=2'b 01, S_full=2'b 10, S_wait=2'b 11; reg [1: 0] state, next_state; always @(posedge clk) if (rst) state <= S_idle; else state <= next_state; always @(state, En, Ld) begin Clr_P 1_P 0 = 0; Ld_P 1_P 0=0; Ld_R 0=0; case (state) S_idle: if (En) begin next_state=S_1; Ld_P 1_P 0=1; end else next_state=S_idle; 1 -79
Behavioral Modeling of Control Unit S_1: begin next_state=S_full; Ld_P 1_P 0=1; end S_full: if (!Ld) next_state=S_wait; else begin Ld_R 0=1; if (En) begin next_state=S_1; Ld_P 1_P 0=1; end else begin next_state=S_idle; Clr_P 1_P 0=1; end S_wait: if (!Ld) next_state=S_wait; else begin Ld_R 0=1; if (En) begin next_state=S_1; Ld_P 1_P 0=1; end else begin next_state=S_idle; Clr_P 1_P 0=1; end endcase endmodule 1 -80
Behavioral Models of Counters module Up_Down_Counter (output reg [2: 0] count, input [1: 0] up_dwn, input clock, reset_); always @(negedge clock, negedge reset_) if (reset_==1'b 0) count <= 3'b 0; else if (up_dwn == 2'b 01) count<=count+1; else if (up_dwn == 2'b 10) count<=count-1; endmodule 1 -81
Behavioral Models of Counters n A ring counter asserts a single bit that circulates through the counter in a synchronous manner. 1 -82
Behavioral Models of Counters module ring_counter #(parameter word_size=8) (output reg [word_size-1: 0] count, input enable, clock, reset); always @ (posedge clock, posedge reset) if (reset) count <= 1; else if (enable == 1'b 1) count <= {count[word_size-2: 0], count[word_size-1]}; endmodule 1 -83
Behavioral Models of Counters module Up_Down_Counter 2 ( output reg [2: 0] count, input load, count_up, counter_on, clock, reset, input [2: 0] Data_in); always @(posedge clock, posedge reset) if (reset==1'b 1) count <= 3'b 0; else if (load == 1'b 1) count <= Data_in; else if (counter_on == 1'b 1) begin if (count_up == 1'b 1) count<=count+1; else count<=count-1; endmodule 1 -84
Parallel Load Register module Par_load_reg 4 #(parameter word_size=4) ( output reg [word_size-1: 0] Data_out, input [word_size-1: 0] Data_in, input load, clock, reset); always @(posedge clock, posedge reset) if (reset==1'b 1) Data_out <= 0; else if (load==1'b 1) Data_out <= Data_in; endmodule 1 -85
Behavioral Models of Shift Registers module Shift_reg 4 #(parameter word_size=4) ( output Data_out, input Data_in, clock, reset); reg [word_size-1: 0] Data_reg; assign Data_out = Data_reg[0]; always @(posedge clock, negedge reset) if (reset==1'b 0) Data_reg <= 0; else Data_reg <= {Data_in, Data_reg[word_size-1: 1]}; endmodule 1 -86
Universal Shift Register module Universal_Shift_Register #(parameter word_size=4) ( output reg [word_size-1: 0] Data_Out, output MSB_Out, LSB_Out, input [word_size-1: 0] Data_In, input MSB_In, LSB_In, input s 1, s 0, clk, rst); assign MSB_Out = Data_Out[word_size-1]; assign LSB_Out = Data_Out[0]; always @(posedge clk) if (rst==1'b 1) Data_Out <= 0; else case ( {s 1, s 0} ) 0: Data_Out <= Data_Out; 1: Data_Out <= {MSB_In, Data_Out[word_size-1: 1]}; 2: Data_Out <= {Data_Out[word_size-2: 0], LSB_In}; 3: Data_Out <= Data_In; endcase endmodule 1 -87
Register Files module Register_File #(parameter word_size=32, addr_size=5) ( output [word_size-1: 0] Data_Out_1, Data_Out_2, input [word_size-1: 0] Data_In, input [addr_size-1: 0] Read_Addr_1, Read_Addr_2, Write_Addr, input Write_Enable, Clock); reg [word_size-1: 0] Reg_File[31: 0]; initial begin Reg_File[0]=10; Reg_File[1]=20; end assign Data_Out_1 = Reg_File[Read_Addr_1]; assign Data_Out_2= Reg_File[Read_Addr_2]; always @(posedge Clock) if (Write_Enable==1'b 1) Reg_File[Write_Addr] <= Data_In; endmodule 1 -88
File I/O system functions and tasks n Verilog provides a set of functions and tasks to access external data files. These are extremely useful in testbenches. n A file can be opened and closed by the $fopen and $fclose functions. The simplified syntax of using $fopen is: [mcd_name] = $fopen ( " [file_name] " ) ; n The $fopen returns a 32 -bit multichannel descriptor associated with the file. n The descriptor is a 32 -bit flag, in which each bit represents a file (i. e. , a channel). The LSB is reserved for the standard output (i. e. , the console). n When the file is opened successfully, a descriptor is returned with one bit asserted. n For example, 0. . . 0010 is returned for the first opened file, 0. . . 0100 is returned for the second opened file, and so on. The function returns all 0's if the open operation fails. 1 -89
Writing to an opened file n Data can be written to an opened file using the following system tasks: $fdisplay, $fwrite, $fstrobe, and $fmonitor. The syntax is: $fdisplay ([mcd_name] , [format_string] , arguement 1, arguement 2 , …) ; n [format_string] term contains regular characters and "escape sequences“ to specify the format of the corresponding arguments. When the string is displayed, the values of the corresponding arguments are substituted into the string and shown in the designated format. n The commonly used escape sequences include %d, %b, %o, %h, %c, %s, and %g, which are for decimal, binary, octal, hexadecimal, character, string, and real number, respectively. 1 -90
File write example n In the example below a descriptor (both_file) is created by a bitwise or operation over 2 multichannel descriptors. This is used to write text to the console and the log file. module filetest (); integer log_file, both_file; localparam con_file=16'h 0000_0001; initial begin log_file = $fopen("my_log"); if (log_file==0) $display("Fail to open file"); // write to console both_file = log_file | con_file; // write to both console and log file $fdisplay(both_file, "Simulation Started"); // write to log file only $fdisplay(log_file, "Writing to log file only"); // write to both console and log file $fdisplay(both_file, "Simulation Ended"); $fclose(log_file); endmodule 1 -91
Reading data from external files n There are two simple system tasks to retrieve data from an external file: $readmemb and $readmemh n These tasks assume that the external file stores the content of a memory array and reads the content into a variable. n The $readmemb and $readmemh tasks further assume that the content is in the binary and hexadecimal formats, respectively. n The simplified syntax is: $readmemb (" [file-name] " , [mem-variable]) ; $readmemh ("[file-name] " , [mem-variable]) ; n The following code segment illustrates the retrieval of an 8 by 4 memory array: reg [3: 0] v_mem [0: 7] ; . . . $readmemb ( “vector. txt" , v_mem) ; The vector. txt file should contain eight 4 -bit binary data separated by white spaces. 1 -92
Example: using external files to specify the test patterns and to record the simulation result module eq 2_file_tb(); reg [1: 0] test_in 0, test_in 1; wire test_out; integer log_file, console_file, out_file; reg [3: 0] v_mem [0: 7]; integer i; eq 2 uu (test_in 0, test_in 1, test_out); module eq 2(input [1: 0] a, b, output equal); assign equal = (a[0] ~^ b[0]) & (a[1] ~^ b[1]); endmodule initial begin log_file = $fopen("eqlog. txt"); if (!log_file) $display("Cannot open log file"); console_file=32'h 0000_0001; out_file = log_file | console_file; $readmemb("vector. txt", v_mem); 1 -93
Example, Contd. for (i=0; i<8; i=i+1) begin {test_in 0, test_in 1} = v_mem[i]; #200; end $fclose(log_file); $stop; end initial begin $fdisplay(out_file, " time test_in 0 test_in 1 test_out"); $fmonitor(out_file, "%10 d test_out); %b %b %b", $time, test_in 0, test_in 1, endmodule 1 -94
Example, Contd. n The vector. txt file stores the test patterns specified in 4 -bit binary format. The content of the file is: n The simulated result is written to the console and the log file, # eqlog. txt # n The content of the log file is: # # # # 00_00 01_11 10_10 10_00 11_11 11_01 00_10 time test_in 0 test_in 1 test_out 0 00 00 1 200 01 00 0 400 01 11 0 600 10 10 1 800 10 00 0 1000 11 11 1 1200 11 01 0 1400 00 10 0 1 -95
- Slides: 95