Verilog II CPSC 321 Andreas Klappenecker
Today’s Menu Verilog, Verilog
Modules module mod_name (parameters); input … output … reg … …… endmodule
Full Adder module fulladd(cin, x, y, s, cout) input cin, x, y; output s, cout; assign s = x ^ y ^ cin; assign cout = (x & y) | (cin & x) | (cin & y); endmodule
Full Adder module fulladd(cin, x,y,s, cout); input cin, x, y; output s, cout; assign { cout, s } = x + y + cin; endmodule The assign statement assigns the MSB to cout and the LSB to s.
Hello World module top; initial $display("Hello, world!"); endmodule initial statements are executed once by the simulator
Vector wires Range [msb: lsb] wire [3:0] S; S = 4’b0011 The result of this assignment is S[3] = 0, S[2] = 0, S[1] = 1, S[0] = 1 wire [1:2] A; A = S[2:1]; means A[1] = S[2], A[2] = S[1]
Variables Variables come in two flavors reg integers reg can model combinatorial or sequential parts of the circuits reg does not necessarily denote a register! Integers often used as loop control variables useful for describing the behavior of a module
Simple Example module testgate; reg b, c; // variables wire a, d, e; // nets and (d, b, c); // gates or (e, d, c); // nand(a, e, b); // initial begin // simulated once b=1; c=0; // blocking assignments #10 $display("a = %b", a); end endmodule What value will be printed?
Operators 1’s complement ~A 2’s complement -A bitwise AND A&B reduction &A produces AND of all bits in A Concatenate {a,b,c} | {a,b,c} = a | b | c Replication operators 2{A} = {A,A} {2{A},3{B}} = {A,A,B,B,B}
Continuous assignments Single bit assignments assign s = x ^ y ^ cin; assign cout = (x & y) | (cin & x) | (cin &y ) Multibit assignments wire [1:3] a,b,c; … assign c = a & b;
Always Blocks An always block contains one or more procedural statements list) or y) begin s = x ^ y; c = x & y; end
Mux: Structural Verilog module mux(f, a,b,sel); input a,b,sel; output f; wire f1, f2; not(nsel, sel); and(f1, a,nsel); and(f2, b, sel); or (f, f1, f2); endmodule b a sel f
Mux: Dataflow Model module mux2(f, a,b,sel); output f; input a,b,sel; assign f = (a & ~sel) | (b & sel); endmodule
Mux: Behavioral Model module mux2(f, a,b,sel); output f; input a,b,sel; reg f; or b or sel) if (sel==1) f = b; else f = a; endmodule
Sign extension and addition module adder_sign(x,y,s,ss); input [3:0] x,y; output [7:0] s, ss; assign s = x + y, ss = {{4{x[3]}},x}+{{4{y[3]},y} endmodule x = 0011, y = 1101 s = = ss = = =
Demux Example 2-to-4 demultiplexer with active low enableab z[3]z[2]z[1]z[0] 0xx
Demux: Structural Model // 2-to-4 demultiplexer module demux1(z,a,b,enable); input a,b,enable; output [3:0] z; wire abar,bbar; not v0(abar,a), v1(bbar,b); nand (z[0],enable,abar,bbar); nand (z[1],enable,a,bbar); nand (z[2],enable,abar,b); nand (z[3],enable,a,b); endmodule enableab z[3]z[2]z[1] z[0 ] 0xx
Demux: Dataflow model // 2-to-4 demux // dataflow model module demux2(z,a,b,enable); input a,b,enable; output [3:0] z; assign z[0] = | {~enable,a,b}; assign z[1] = ~(enable & a & ~b); assign z[2] = ~(enable & ~a & b); assign z[3] = enable ? ~(a & b) : 1'b1; endmodule enableab z[3]z[2]z[1]z[0] 0xx
Demux: Behavioral Model // 2-to-4 demultiplexer with active-low outputs module demux3(z,a,b,enable); input a,b,enable; output [3:0] z; reg z; // not really a register! or b or enable) case ({enable,a,b}) default: z = 4'b1111; 3'b100: z = 4'b1110; 3'b110: z = 4'b1101; 3'b101: z = 4'b1011; 3'b111: z = 4'b0111; endcase endmodule enableab z[3]z[2]z[1]z[0] 0xx
Always Blocks The sensitivity … ) contains the events triggering an evaluation of the or b or b) A Verilog compiler evaluates the statements in the always block in the order in which they are written
Assignments If a variable is assigned a value in a blocking assignment a = b & c; then subsequent references to a contain the new value of a Non-blocking assignments <= assigns the value that the variables had while entering the always block
D Flip-flop module D_FF(Q,D,clock); output Q; input D, clock; reg Q; clock) Q <= D; endmodule
Clock A sequential circuit will need a clock supplied by the testbed Clock code fragment reg clock; parameter period = 100; initial clock 0; clock = ~clock;
D-Flipflop with Synchronous Reset module flipflop(D, Clock, Resetn, Q); input D, Clock, Resetn; output Q; reg Q; Clock) if (!Resetn) Q <= 0; else Q <= D; endmodule // 7.46 in [BV]
module latch(D, clk, Q) input D, clk; output Q; reg Q; or clk) if (clk) Q <= D; endmodule Missing else clause => a latch will be synthesized to keep value of Q when clk=0 Gated D-Latch
module example(D,Clock, Q1, Q2) input D, Clock; output Q1, Q2; reg Q1, Q2; Clock) begin end endmodule Shift Register: What is wrong here? Q1 = D; Q2 = Q1; Q1 = D; Q2 = Q1; // D=Q1=Q2
Shift register: Correct Version module example(D,Clock, Q1, Q2) input D, Clock; output Q1, Q2; reg Q1, Q2; Clock) begin Q1 <= D; Q2 <= Q1; end endmodule
Rule of Thumb Blocking assignments are used to describe combinatorial circuits Non-blocking assignments are used in sequential circuits
n-bit Ripple Carry Adder module ripple(cin, X, Y, S, cout); parameter n = 4; input cin; input [n-1:0] X, Y; output [n-1:0] S; output cout; reg [n-1:0] S; reg [n:0] C; reg cout; integer k; or Y or cin) begin C[0] = cin; for(k = 0; k <= n-1; k=k+1) begin S[k] = X[k]^Y[k]^C[k]; C[k+1] = (X[k] & Y[k]) |(C[k]&X[k])|(C[k]&Y[k]); end cout = C[n]; end endmodule
Loops and Integers The for loop is used to instantiate hardware modules The integer k simply keeps track of instantiated hardware Do not confuse integers with reg variables
Bit-Counter Count the number of bits having value 1 in register X Again an example for parameters Another example of a for loop
Bit Counter module bit_cnt(X,Count); parameter n = 4; parameter logn = 2; input [n-1:0] X; output [logn:0] Count; reg [logn:0] Count; integer k; begin Count = 0; for(k=0;k<n;k= k+1) Count=Count+X[k]; end endmodule
Blocks of Procedural Code initial executed once at the beginning of simulation initial $display(“Hello World”); always repeatedly executed begin-end sequential execution of block statements delays add up fork-join blocks concurrent execution of statements
Concurrency Example module concurrency_example; initial begin #1 $display(“Block 1 stmt 1"); $display(“Block 1 stmt 2"); #2 $display(“Block 1 stmt 3"); end initial begin $display("Block 2 stmt 1"); #2 $display("Block 2 stmt 2"); #2 $display("Block 2 stmt 3"); end endmodule Block 2 stmt 1 Block 1 stmt 1 Block 1 stmt 2 Block 2 stmt 2 Block 1 stmt 3 Block 2 stmt 3
Concurrency Example module concurrency_example; initial begin #1 $display(“Block 1 stmt 1"); $display(“Block 1 stmt 2"); #2 $display(“Block 1 stmt 3"); end initial begin $display("Block 2 stmt 1"); #2 $display("Block 2 stmt 2"); #2 $display("Block 2 stmt 3"); end endmodule Block 2 stmt 1 Block 1 stmt 1 Block 1 stmt 2 Block 2 stmt 2 Block 1 stmt 3 Block 2 stmt 3
Concurrency: fork and join module concurrency_example; initial fork #1 $display(“Block 1 stmt 1"); $display(“Block 1 stmt 2"); #2 $display(“Block 1 stmt 3"); join initial fork $display("Block 2 stmt 1"); #2 $display("Block 2 stmt 2"); #2 $display("Block 2 stmt 3"); join endmodule Block 1 stmt 2 Block 2 stmt 1 Block 1 stmt 1 Block 1 stmt 3 Block 2 stmt 2 Block 2 stmt 3
Displaying Results a = 4’b0011 $display(“The value of a is %b”, a); The value of a is 0011 $display(“The value of a is %0b”, a); The value of a is 11 If you you $display to print a value that is changing during this time step, then you might get the new or the old value; use $strobe to get the new value
Displaying Results Standard displaying functions $display, $write, $strobe, $monitor Writing to a file instead of stdout $fdisplay, $fwrite, $fstrobe, $fmonitor Format specifiers %b, %0b, %d, %0d, %h, %0h, %c, %s,…
Display Example module f1; integer f; initial begin f = $fopen("myFile"); $fdisplay(f, "Hello, bla bla"); end endmodule
Moore Machines The output of a Moore machine depends only on the current state. Output logic and next state logic are sometimes merged. next state logic present state register output logic input
Coding Moore Machines The logic in the Moore machine can be described by two case statements (one case statement if logic blocks are merged) Enumerate all possible states of input and current state, and generate the output and next state Give states meaningful names using define or parameters
Moore Machine Example Automatic food cooker Has a supply of food Can load food into the heater when requested Cooker unloads the food when cooking done
Automated Cooker Outputs from the machine load = signal that sends food into the cooker heat = signal that turns on the heater unload = signal that removes food from cooker beep = signal that alerts that food is done
Automated Cooker Inputs clock start = start the load, cook, unload cycle temp_ok = temperature sensor detecting when preheating is done done = signal from timer when done quiet = Should cooker beep?
Cooker module cooker( clock, start, temp_ok, done, quiet, load, heat, unload, beep ); input clock, start, temp_ok, done, quiet; output load, heat, unload, beep; reg load, heat, unload, beep; reg [2:0] state, next_state;
Defining States `define IDLE 3'b000 `define PREHEAT 3'b001 `define LOAD 3'b010 `define COOK 3'b011 `define EMPTY 3'b100 You can refer to these states as ‘IDLE, ‘PREHEAT, etc.
State Register Block `define REG_DELAY 1 clock) state <= #(`REG_DELAY) next_state;
Next State Logic or start or temp_ok or done) // whenever there is a change in input begin case (state) `IDLE: if (start) next_state=`PREHEAT; `PREHEAT: if (temp_ok) next_state = `LOAD; `LOAD: next_state = `COOK; `COOK: if (done) next_state=`EMPTY; `EMPTY: next_state = `IDLE; default: next_state = `IDLE; endcase end
Output Logic begin if(state == `LOAD) load = 1; else load = 0; if(state == `EMPTY) unload =1; else unload = 0; if(state == `EMPTY && quiet == 0) beep =1; else beep = 0; if(state == `PREHEAT || state == `LOAD || state == `COOK) heat = 1; else heat =0; end