ee5375 – add ii prof. macdonald - · pdf fileee5375 – add ii prof. macdonald ....
TRANSCRIPT
Verilog Overview
EE5375 – ADD II Prof. MacDonald
Verilog Overview
l C-Like Language used to describe hardware l VHDL is main competitor
– VHDL is more rigorous and typed – VHDL takes longer to write – VHDL is used by 50% of US / most of the world
l Verilog was originally owned by Cadence l Now an open language with standards l Used for ASIC design and FPGA programming l 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
circuit under test (CUT) count.v
tb.v testbench
clock gen
reset gen
any other inputs monitors
waveform gen
synthesizable code
unsynthesizable code – artificial and for verification only
Testbench `timescale 1ns/1ps module tb ();
reg clk, reset; wire [3:0] count; counter counter1 (.I_clk(clk), I_reset(reset), O_count(count)); initial clk = 0; //clock generator initial forever #10 clk = ~clk; //clock generator initial //main stimulus block
begin reset <= 1’b1;
#500 reset <= 1’b0; #1000 $finish;
end 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 – C or Matlab
l Register Transfer Level (RTL) – describes logic design with C like constructs – modern definition is that RTL is synthesizable
l Gate level (netlist) – describes design as a collection of logic gates connected
together – product of synthesizing RTL code
l Transistor level (circuit design) – gates (primitives) used in synthesis – details are hidden “under the hood” from logic designers
Verilog RTL example
Verilog netlist example
a b
y
NOR2X1
i_62 n_119
n_37 n_17
Layout example
Simple Design Flow (ASIC/FPGA)
Specification
Architecture
RTL Coding
Simulation
Synthesis
Place, Route, and Timing
standard cell library
Arithmetic Operators
- +, -, /, *, % l Arithmetic operators imply ALU in synthesis l Plus operator for addition + l Minus operator for subtraction – l Multiply operator for multiplication * l Division operator / (rarely used except in TBs) l Modulus operator % l Ensure input and output precision is appropriate
Logical Operators
l Logical operators take two or more boolean vars and provide a single boolean answer.
l If input is a vector, then false if all zeros, otherwise true l AND is && l OR is ||
wire [3:0] inputA = 4’d3; wire inputB = 1’b0; wire C = inputA && inputB; // C = false or zero
Bitwise Operators
l Bitwise operators work on each bit of vector l AND & l OR | l NOT ~ l Exclusive OR ^ l Exclusive NOR ~^ (compare)
wire [3:0] busA; // 0101 wire [3:0] busB; // 0011 wire [3:0] busAandB = busA & busB; // 0001
Unary Operators
l Unary operators act on one input variable l Not – inverts boolean l AND – provides the logical AND of entire bus l OR – provides the logical OR of entire bus l XOR – provides the exclusive OR of entire bus
wire D; wire [5:0] C = 6’b0101010; assign D = ^C; //D equals the parity of C assign D = |C; // D equals 1 assign D = &C; //D equals 0
Shift Operators
l Shift <<, >> shifts the index of a bus l <vector> >> <number of bits> l Better approach is using concatenation
wire [3:0] bus = 4’hA; wire [3:0] shifted_bus = bus >> 1; // 4’h5
Equality Operators
l Takes two values and compares, provides boolean l === compare with x and z values (simulation only) l == compares for equality, x or z result in x result l != compares for inequality, x or z results in x
wire [3:0] a = 4’hA; wire [3:0] b = 4’hA; Wire c = (a == b); // true
Compare Operators
l Takes two values and compares, provides boolean l > greater than l < less than l => greater than or equal l =< less than or equal
wire [3:0] a = 4’hA; wire [3:0] b = 4’hA; Wire c = (a => b); // true
Shift Operators
l Shift <<, >> shifts the index of a bus l <vector> >> <number of bits> l Better approach is using concatenation
wire [3:0] bus = 4’hA; wire [3:0] shifted_bus = bus >> 1; // 4’h5
Concatenation Operator
l Concatenation Operator {} l Used to splice busses together
wire [3:0] A = 4’hA; wire [3:0] B = 4’h5; wire [7:0] C; assign C = {A, B}; // 8’hA5 OR assign C = {1’b0, A, B[3:1]} // for shift with zero insert
Condition Operator (Mux)
l Condition operator used to imply muxes l <control> ? <selection1> : <selection0>; l 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 – must be driven by an output – can be connected to any number of inputs – are defined by continuous assignment statements
l 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 non-blocking assignment.
Use non-blocking for flops and blocking for combinatorial. always @(posedge CLK)
begin A <= B;
C <= A; end always @(A or B or Sel) begin
A = B; C = A; end
Very common interview question
Verilog Procedural Constructs
l If-then-else statement l case statement l for loop l while loop l 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
s0
s1
0 0
1 0
x z
s2 0 0
1 0
1 1
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, // clock x, // input z); // output input x, clk; // input declarations output z; // output declarations reg [1:0] state; // 2 state flip flops reg [1:0] next_state; // 2 wires feeding FF inputs reg z; // 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: if ( x ) next_state = S1; else next_state = IDLE; S1 : if ( x ) next_state = S1; else next_state = S2; 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) 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 <= 1; else state <= 0; endcase endmodule
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
state_machine
test_bench
clock generator
x clk
sequence generator
checker optional z stimulus
circuit under test
Only state_machine is synthesizable. All else is for verification purposes only.
reset generator
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) // should be name of file top.v input clk, reset, in1; // all ports as inputs defined output out1, out2; // all ports as outputs defined reg out1; // outputs can be defined as regs reg [1:0] count; // this is an internal reg wire out2; // outputs can be defined as wire wire [1:0] new_count = 2’b01; // this in an internal wire always @(posedge clk) if(reset) out1 <= 0; else if (new_count == 2’b10) out1 <= in1 && out2; else 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) // should be name of file bottom.v input [1:0] inA; // all ports as inputs defined output [1:0] outB; // all ports as outputs defined wire [1:0] outB; // outputs can be defined as wire assign outB = inA + 2’b01; // could be combined with wire above endmodule
Synthesis effects
wire start; assign start = ready && request;
Continuous statements always result in combinatorial logic - no flops or latches.
Synthesis effects
Wire [31:0] a ; Wire [31:0] b ; Wire the_same ; Assign the_same = a == b;
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
Synthesis effects
Always @(D or S or E)
if (S) A = D; else A = E;
Always block without posedge statement is combinatorial.
Always @(*) // verilog 2000
if (S) A = D; else A = E;
Synthesis effects
Wire [31:0] ina; Wire [31:0] inb; Reg [31:0] out; always @(ina or inb or subract)
if (subtract) out = ina + (!inb + 32’h1); else out = ina + inb;
Always block without posedge statement is combinatorial. This example will result in an ALU function.
Synthesis effects
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
Always block without posedge statement is combinatorial. This example will result in decoder.
Synthesis effects
always @(*) // verilog 2000 format – much better if (enable) Q = D;
always @(enable or D) // original verilog
if (enable) Q = D;
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.
Very common interview question
Synthesis effects
always @(posedge clk)
A <= E;
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.
Synthesis effects
always @(posedge clk)
if (reset) A <= 0; else A <= D;
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.
D FF
reset D
clk
Synthesis effects
always @(posedge clk or negedge reset)
if (reset) A <= 0; else A <= E;
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.
D FF
reset
D
clk
Synthesis effects
always @(posedge clk)
if (reset) A <= 0; else A <= E && C;
Always block with posedge clk statement is sequential but can include some input combinatorial logic as shown.
Synthesis effects
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
Shift register for parallel to serial conversion – susceptible to hold time violations
Synthesis effects - Latches
always @(clk or in) //unusual but intentional latch if (clk) A = in; else A = A;
always @(*) // typical unintentional latch
if (enable) A = in;
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.
Verilog Design Guidelines
l Use meaningful names for signals and variables l Use “I_” and “O_” for port names – I for input / O for output l Modify regs in only one always block l Only use dedicated clock for posedge statements l Constants and Parameters should be all caps l Never use tabs but do line up text with spaces l Avoid mixing positive and negative edge-triggered flip-flops l Use parentheses to optimize logic structure l Use continuous assign statements for simple combo logic. l Use non-blocking for sequential and blocking for combo logic l Define if-else/case statements explicitly – all vars for all cases l Always instantiate modules with explicit port listing.
Most common student mistakes
l Synthesizable code should – not have delays included (#) – only have always blocks and no initial blocks
l Define a reg in only one always block (otherwise ambiguity) l for loops are for spatial repeating - not temporal l Fully specify variables within an always block for readability
– 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)
l Fully specify sensitivity list in combinatorial always blocks l Blocking vs. Non-blocking assignments
– rule of thumb l if it has a posedge, use the “<=“ because it is sequential l otherwise use the “=“ because it is combinational l Really doesn’t matter if you only define a single variable in a block
Examples of bad code
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
In any always block, define all variables for all cases. Not doing so can cause latches and in general is hard to follow.
Examples of bad code
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;
Define any variable in only one always block. Otherwise, sim and synth will mismatch.
Examples of bad code
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;
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.
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 – port list and input/output declarations combined – sensitivity lists in always blocks need not be listed
l Good reference web pages for Verilog – www.deepchip.com – www.deeps.org/verilog – www.edacafe.com – www.cadence.com original company
www.synopsys.com most used synthesis tool – www.mentor.com commonly used simulator – www.magma-da.com new synthesis tool – www.altera.com FPGA companies – www.xylinx.com FPGA companies