Verilog Overview EE5375 – ADD II Prof. MacDonald Verilog Overview l l C-Like Language used to describe hardware VHDL is main competitor – – – l l l l VHDL is more rigorous and typed VHDL takes longer to write VHDL is used by 50% of US / most of the world Verilog was originally owned by Cadence Now an open language with standards Used for ASIC design and FPGA programming Verilog HDL : A Guide to Digital Design and Synthesis by Samir Palnitkar Simple Example module counter (I_reset, I_clk, O_count); input I_reset; input I_clk; output [3:0] O_count; reg [3:0] O_count; always @(posedge I_clk) if (I_reset) O_count <= 4’b0; else O_count <= O_count + 1; endmodule Testbench any other inputs reset gen circuit under test (CUT) count.v monitors clock gen synthesizable code unsynthesizable code – artificial and for verification only waveform gen tb.v testbench Testbench `timescale 1ns/1ps module tb (); reg wire [3:0] clk, reset; count; counter counter1 (.I_clk(clk), I_reset(reset), O_count(count)); initial clk = 0; initial forever #10 clk = ~clk; initial begin reset <= 1’b1; #500 reset <= 1’b0; #1000 $finish; end //clock generator //clock generator //main stimulus block always @(count) $display("counter value is now %x at time %t",count, $time); initial begin $dumpfile("verilog.dmp"); $dumpvars; end endmodule Verilog command line Output log (verilog.log) Compiling source file "tb.v" Compiling source file "counter.v" Highest level modules: tb counter value is now 0 at time 5 counter value is now 1 at time 1005 counter value is now 2 at time 1015 counter value is now 3 at time 1025 counter value is now 4 at time 1035 counter value is now 5 at time 356085 counter value is now 6 at time 356095 counter value is now 7 at time 356105 counter value is now 8 at time 356115 counter value is now 9 at time 356125 counter value is now a at time 356135 counter value is now b at time 356145 counter value is now c at time 356155 counter value is now d at time 356165 counter value is now e at time 356175 counter value is now f at time 356185 counter value is now 0 at time 356195 counter value is now 1 at time 356205 VERILOG interrupt at time 356210 C1 > 0 simulation events (use +profile or +listcounts option to count) CPU time: 0.2 secs to compile + 0.1 secs to link + 6.1 secs in simulation End of VERILOG-XL 3.40.p001 Nov 16, 2004 09:58:09 Output Waves Design Abstraction l High Level Behavioral – l Register Transfer Level (RTL) – – l describes logic design with C like constructs modern definition is that RTL is synthesizable Gate level (netlist) – l C or Matlab describes design as a collection of logic gates connected together – product of synthesizing RTL code Transistor level (circuit design) – – gates (primitives) used in synthesis details are hidden “under the hood” from logic designers Verilog RTL example Verilog netlist example n_119 n_37 i_62 a b y NOR2X1 n_17 Layout example Simple Design Flow (ASIC/FPGA) Specification Architecture RTL Coding Simulation standard cell library Synthesis Place, Route, and Timing Arithmetic Operators l l l l l l l - +, -, /, *, % Arithmetic operators imply ALU in synthesis Plus operator for addition + Minus operator for subtraction – Multiply operator for multiplication * Division operator / (rarely used except in TBs) Modulus operator % Ensure input and output precision is appropriate Logical Operators l l l l Logical operators take two or more boolean vars and provide a single boolean answer. If input is a vector, then false if all zeros, otherwise true AND is && OR is || wire [3:0] wire wire inputA = 4’d3; inputB = 1’b0; C = inputA && inputB; // C = false or zero Bitwise Operators l l l l l l Bitwise operators work on each bit of vector AND & OR | NOT ~ Exclusive OR ^ Exclusive NOR ~^ (compare) wire [3:0] busA; wire [3:0] busB; wire [3:0] busAandB = busA & busB; // 0101 // 0011 // 0001 Unary Operators l l l l l Unary operators act on one input variable Not – inverts boolean AND – provides the logical AND of entire bus OR – provides the logical OR of entire bus XOR – provides the exclusive OR of entire bus wire wire [5:0] assign assign assign D; C = 6’b0101010; D = ^C; //D equals the parity of C D = |C; // D equals 1 D = &C; //D equals 0 Shift Operators l l l Shift <<, >> shifts the index of a bus <vector> >> <number of bits> Better approach is using concatenation wire [3:0] wire [3:0] bus = 4’hA; shifted_bus = bus >> 1; // 4’h5 Equality Operators l l l l Takes two values and compares, provides boolean === compare with x and z values (simulation only) == compares for equality, x or z result in x result != compares for inequality, x or z results in x wire [3:0] wire [3:0] Wire a b c = 4’hA; = 4’hA; = (a == b); // true Compare Operators l l l l l Takes two values and compares, provides boolean > greater than < less than => greater than or equal =< less than or equal wire [3:0] wire [3:0] Wire a b c = 4’hA; = 4’hA; = (a => b); // true Shift Operators l l l Shift <<, >> shifts the index of a bus <vector> >> <number of bits> Better approach is using concatenation wire [3:0] wire [3:0] bus = 4’hA; shifted_bus = bus >> 1; // 4’h5 Concatenation Operator l l Concatenation Operator {} Used to splice busses together wire [3:0] wire [3:0] wire [7:0] assign A = 4’hA; B = 4’h5; C; C = {A, B}; // 8’hA5 OR assign C = {1’b0, A, B[3:1]} // for shift with zero insert Condition Operator (Mux) l l l Condition operator used to imply muxes <control> ? <selection1> : <selection0>; Some consider this too dense and confusing for RTL A = B ? C : D; // A = C if B=1 else A = D A = B ? (D ? E : F) : D; // embedded condition operator is terrible Verilog Data Types l Nets are represented by wire data type – – – l must be driven by an output can be connected to any number of inputs are defined by continuous assignment statements Flip Flops and nets are represented by reg data type – reg’s in verilog are not necessarily flip-flops are defined by procedural blocks always blocks with “posedge” are flip-flops always blocks without “posedge” are wires Initial blocks are for verification only (testbenches) l Other less common data types include time, real, – – – – integer Verilog Data Types - busses Wires and Regs can be defined as vectors or busses reg [7:0] counter; // 8 bit register of flip-flops wire [10:2] data_bus; // 9 bit bus Can be individually addressed assign output = data_bus[9]; or as a group assign data_bus_out = data_bus; Continuous Assignment Statements Assignment statements assign values to wires and can be used to describe combinatorial circuits only. Any change on the right side, effects left side immediately if no delay is specified. Delay if specified is un-synthesizable and is for tb only. Ex. wire C; assign C = (A & !B) | (!A & B); Procedural Blocks Procedural blocks are used to define reg data types and can be used to describe combinatorial or sequential circuits. Procedural blocks can use C-like constructs and begin with always or initial key words. Each block is an like an independent thread – all running in parallel. reg Q; always @(posedge CLK) begin if (reset) Q <= D; else Q <= 0; end Blocking vs. Non-blocking assignment Regs is procedural blocks can be defined with blocking or nonblocking assignment. Use non-blocking for flops and blocking for combinatorial. always @(posedge CLK) begin A <= B; C <= A; Very common end interview always @(A or B or Sel) question begin A = B; C = A; end Verilog Procedural Constructs l l l l l If-then-else statement case statement for loop while loop System Calls – – – – $display – dumps variable or string to standard output $time – tells current simulation time $stop – finishes the simulation $dumpvar – creates a waveform file for subsequent viewing State Machine Design Example x z 0 0 1 0 s0 0 0 s1 1 1 s2 1 0 0 0 X = 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 0 Z = 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 Port list, Reg/Wire/Param declaration module state_machine ( clk, x, z); // clock // input // output input x, clk; output z; // input declarations // output declarations reg [1:0] state; reg [1:0] next_state; reg z; // 2 state flip flops // 2 wires feeding FF inputs // output parameter IDLE = 2’b00; parameter S1 = 2’b01; parameter S2 = 2’b11; Next State Logic Section always @(state or x) begin case(state) IDLE: begin if ( x ) next_state = S1; else next_state = IDLE; end S1 : begin if ( x ) next_state = S1; else next_state = S2; end S2 : begin if ( x ) next_state = S1; else next_state = IDLE; end end Next State Logic Section always @(state or x) case(state) IDLE: S1 : S2 : if ( x ) next_state = S1; else next_state = IDLE; if ( x ) next_state = S1; else next_state = S2; if ( x ) next_state = S1; else next_state = IDLE; endcase My personal preference is to use only single statements and avoid the use of “Begin” and “End” – more readable. State Sequential Section always @(posedge CLK or posedge reset) begin if ( reset ) state <= IDLE; else state <= next_state; end Note that begin and end are not required here as the if-else statement is a single statement Output Logic Section always @(state or x) begin case(state) IDLE: begin if ( x ) z = 0; else z = 0; end S1 : begin if ( x ) z = 0; else z = 0; end S2 : begin if ( x ) z = 1; else z = 0; end end endmodule // ending statement for last 4 slides Alternative (better) Mealy Module detector (clk, reset, in, out) input clk, reset, in; output out; reg [1:0] state; wire out = (state == 2) & in; always @(posedge clk) if (reset) else case(state) 2’b00 : if (in) else 2’b01 : if (in) else 2’b10 : if (in) else endcase endmodule state <=0; state <= 1; state <= 0; state <= 1; state <= 2; state <= 1; state <= 0; Alternative Style (moore) Module detector (clk, reset, in, out) input clk, reset, in; output out; reg [1:0] state; wire out = (state == 3); always @(posedge clk) if (reset) state <=0; else case(state) 2’b00 : if (in) state <= 1; else state <= 0; 2’b01 : if (in) state <= 1; else state <= 2; 2’b10 : if (in) state <= 3; else state <= 0; 2’b11 : if (in) state <= 1; else state <= 2; endcase endmodule Testbench test_bench sequence generator stimulus clock generator state_machine x clk z checker optional reset generator circuit under test Only state_machine is synthesizable. All else is for verification purposes only. Testbench example module test_bench ( ); reg x, clk, reset; // reg declarations initial clk = 0; always forever #100 clk = ~clk; // clk generation initial begin // sequence generation reset = 1; x = 0; #(800) reset = 0; // better to use @(negedge clk) here, why? #(200) x = 0; #(200) x = 1; #(200) x = 0; $finish; end state_machine U0 (.X(x), .CLK(clk), .Z( ), .reset(reset)); endmodule Testbench Tasks Task adc_transaction ( ); // this task simulates a serial ADC off chip input [7:0] sample; begin @(posedge convert) serial_data <= 0; @(posedge sclk) serial_data <= sample[7]; @(posedge sclk) serial_data <= sample[6]; @(posedge sclk) serial_data <= sample[5]; @(posedge sclk) serial_data <= sample[4]; @(posedge sclk) serial_data <= sample[3]; @(posedge sclk) serial_data <= sample[2]; @(posedge sclk) serial_data <= sample[1]; @(posedge sclk) serial_data <= sample[0]; $display(“just transferred %x to ADC”, sample); end endtask Testbench monitors for the log file always @(posedge tb.dut.data_signal) $display(“%d, %x, %x, %t”, tb.dut.count, tb.dut.var1, tb.dut.var2, tb.dut.var3, $time); Hierarchy (contrived example) module top (clk, reset, in1, out1, out2) input clk, reset, in1; output out1, out2; reg out1; reg [1:0] count; wire out2; wire [1:0] new_count = 2’b01; always @(posedge clk) if(reset) else if (new_count == 2’b10) else // should be name of file top.v // all ports as inputs defined // all ports as outputs defined // outputs can be defined as regs // this is an internal reg // outputs can be defined as wire // this in an internal wire out1 <= 0; out1 <= in1 && out2; out1 <= out1; always @(posedge clk) count <= count + 1; assign out2 = in1 && out1; // could be combined with wire bottom bottom1 (.inA(count), .outB(new_count)); //instantiation endmodule Hierarchy (contrived example - 2) module bottom (inA, outB) input [1:0] inA; output [1:0] outB; wire [1:0] outB; assign outB = inA + 2’b01; endmodule // should be name of file bottom.v // all ports as inputs defined // all ports as outputs defined // outputs can be defined as wire // could be combined with wire above Synthesis effects Continuous statements always result in combinatorial logic - no flops or latches. wire start; assign start = ready && request; Synthesis effects Continuous statements always result in combinatorial logic. Here is a 32 bit comparator. Note that the size of the netlist doesn’t necessarily correspond to the number of lines of RTL Wire [31:0] Wire [31:0] Wire a; b; the_same ; Assign the_same = a == b; Synthesis effects Always block without posedge statement is combinatorial. Always @(D or S or E) if (S) A = D; else A = E; Always @(*) // verilog 2000 if (S) A = D; else A = E; Synthesis effects Always block without posedge statement is combinatorial. This example will result in an ALU function. Wire Wire Reg [31:0] [31:0] [31:0] ina; inb; out; always @(ina or inb or subract) if (subtract) out = ina + (!inb + 32’h1); else out = ina + inb; Synthesis effects Always block without posedge statement is combinatorial. This example will result in decoder. always @(index) case (index) 0: decoder_out = 8’h01; 1: decoder_out = 8’h02; 2: decoder_out = 8’h04; 3: decoder_out = 8’h08; 4: decoder_out = 8’h10; 5: decoder_out = 8’h20; 6: decoder_out = 8’h40; 7: decoder_out = 8’h80; endcase Synthesis effects Always block without posedge statement is combinatorial. This example will has a problem. All cases must be specified. Here if enable is high, Q=D. What happens if enable is low? Synthesis will add a latch to remember the old value of Q when it is undefined by the if statement. Latches are rarely meant to be used in logic and are a good sign of a problem when reported by synthesis. always @(*) if (enable) Q = D; // verilog 2000 format – much better always @(enable or D) // original verilog if (enable) Q = D; Very common interview question Synthesis effects Always block with posedge clk statement is sequential. This example will result in a simple non-resetable flip-flop. Flip flops that define state or control should be reset, however flip flops in the datapath can be left un-reset if data naturally flows through to initialize. always @(posedge clk) A <= E; Synthesis effects Always block with posedge clk statement is sequential. This example will result in a synchronous resetable flip-flop. Requires a clock to register the reset – but glitch proof. always @(posedge clk) if (reset) A <= 0; else A <= D; reset D D FF clk Synthesis effects Always block with posedge clk statement is sequential. This example will result in a asynchronously resettable flip-flop. The decision between asynch and synch resets is a religious one. Asynch are immediate but glitch-prone. Potential interview question. always @(posedge clk or negedge reset) if (reset) A <= 0; else A <= E; D D FF clk reset Synthesis effects Always block with posedge clk statement is sequential but can include some input combinatorial logic as shown. always @(posedge clk) if (reset) A <= 0; else A <= E && C; Synthesis effects Shift register for parallel to serial conversion – susceptible to hold time violations module p2s (in, out, load, clk, reset) input load, clk, reset; input [7:0] in; output out; reg [7:0] parallel_data; wire out = parallel_data[7]; always @(posedge clk) if (reset) parallel_data <= 0; else if (load) parallel_data <= in; else parallel_data <= {parallel[6:0], 1’b0}; endmodule Synthesis effects - Latches Always block with posedge clk statement is sequential. This example will result in a transparent latch. Very unusual in RTL. Typically, latches in the synthesized netlist are the sign of mistakes. always @(clk or in) if (clk) else //unusual but intentional latch A = in; A = A; always @(*) // typical unintentional latch if (enable) A = in; Verilog Design Guidelines l l l l l l l l l l l l Use meaningful names for signals and variables Use “I_” and “O_” for port names – I for input / O for output Modify regs in only one always block Only use dedicated clock for posedge statements Constants and Parameters should be all caps Never use tabs but do line up text with spaces Avoid mixing positive and negative edge-triggered flip-flops Use parentheses to optimize logic structure Use continuous assign statements for simple combo logic. Use non-blocking for sequential and blocking for combo logic Define if-else/case statements explicitly – all vars for all cases Always instantiate modules with explicit port listing. Most common student mistakes l Synthesizable code should – – l l l Define a reg in only one always block (otherwise ambiguity) for loops are for spatial repeating - not temporal Fully specify variables within an always block for readability – – l l not have delays included (#) only have always blocks and no initial blocks i.e. if (X) Y = A, else Y = B. Define Y in all possible cases. this may result in unwanted latches (as opposed to flip-flops) Fully specify sensitivity list in combinatorial always blocks Blocking vs. Non-blocking assignments – rule of thumb l l l if it has a posedge, use the “<=“ because it is sequential otherwise use the “=“ because it is combinational Really doesn’t matter if you only define a single variable in a block Examples of bad code In any always block, define all variables for all cases. Not doing so can cause latches and in general is hard to follow. always @(C or D or S or E) begin if (S) begin A = D; B = C; end else A = E; end always @(C or D or S or E) begin if (S) begin A = D; B = C; end else begin A = E; B = C; end end Examples of bad code Define any variable in only one always block. Otherwise, sim and synth will mismatch. always @(D or S) if (S) A = D; always @(G or E) if (G) A = E; always @(D or E or G or S) if (S) A = D; else if (G) A = E; else A = K; Examples of bad code Define only one if-else if-else statement per always block. Confusing to follow. Better to have one block for each variable and one variable per block. always @(D or S or K or J or E or C or G ) begin if (S) A = D; else if A = J; else A = K; if (G) B <= E; else B <= C; end always @(D or E or G or S) if (S) A = D; else if A = J; else A = K; always @(G or E or C) if (G) B = E; else B = C; Clocking Best to use one universal clock for design – avoid using data signals as clocks One clock is better for static timing – can only time paths between flops on the same clock. Each clock tree has to be balanced – the fewer the better. Some clever ideas bring ASIC methodologies to the knees. D FF D FF D FF Reference l Verilog 2001 Standard – new features added – – l port list and input/output declarations combined sensitivity lists in always blocks need not be listed Good reference web pages for Verilog – – – – – – – – www.deepchip.com www.deeps.org/verilog www.edacafe.com www.cadence.com www.synopsys.com www.mentor.com www.magma-da.com www.altera.com www.xylinx.com original company most used synthesis tool commonly used simulator new synthesis tool FPGA companies FPGA companies