First Steps in Verilog CPSC 321 Computer Architecture Andreas Klappenecker
Verilog Simulators vcs from Synopsis powerful debugging tools Icarus Verilog compiler, free Veriwell simulator, free
Information about Verilog Short manual by Chauhan and Blair Verilog Quick Reference Guide by Sutherland HDL Appendix A in Fundamentals of Digital Logic by Brown and Vranesic Quick Reference for Verilog HDL by Rajeev Madhavan
Hello World module top; initial $display("Hello, world!"); endmodule initial statements are executed once by the simulator
Verilog Simulator The Verilog simulator is event driven Different styles of Verilog structural dataflow behavioral We will see examples of each type
Nets A net represents a node in the circuit The wire type connects an output of one element to an input of another element wire abar; not(abar, a); nand(b, abar,abar);
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;
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
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,s2s); 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 enableabz[3]z[2]z[1]z[0] 0xx
Demux: Structural Model // 2-to-4 demultiplexer with active-low outputs module demux1(z,a,b,enable); input a,b,enable; output [3:0] z; wire abar,bbar; // local signals not v0(abar,a), v1(bbar,b); nand n0(z[0],enable,abar,bbar); nand n1(z[1],enable,a,bbar); nand n2(z[2],enable,abar,b); nand n3(z[3],enable,a,b); endmodule
Demux: Dataflow model // 2-to-4 demux with active-low outputs // 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
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