Verilog HDL
HDLs • Hardware Description Languages • Widely used in logic design • Verilog and VHDL • Describe hardware using code • Document logic functions • Simulate logic before building • Synthesize code into gates and layout • Requires a library of standard cells
Module name Module ports Declaration of port modes Declaration of internal signal Instantiation of primitive gates Verilog keywords Taste of Verilog module Add_half ( sum, c_out, a, b ); input a, b; output sum, c_out; wire c_out_bar; xor (sum, a, b); nand (c_out_bar, a, b); not (c_out, c_out_bar); endmodule a sum b c_out_bar c_out
a sum Add_half b c_out Behavioral Description module Add_half ( sum, c_out, a, b ); input a, b; output sum, c_out; reg sum, c_out; always @ ( a or b ) begin sum = a ^ b; // Exclusive or c_out = a & b; // And end endmodule
rst data_in q clk Declaration of synchronous behavior Procedural statement Example of Flip-flop module Flip_flop ( q, data_in, clk, rst ); input data_in, clk, rst; output q; reg q; always @ ( posedge clk ) begin if ( rst == 1) q = 0; else q = data_in; end endmodule
Gate Delay • and (yout, x1, x2); // default, zero gate delay • and #3 (yout, x1, x2); // 3 units delay for all transitions • and #(2,3) G1(yout, x1, x2); // rising, falling delay • and #(2,3) G1(yout, x1, x2), G2(yout2, x3, x4); // Multiple instances • a_buffer #(3,5,2) (yout, x); // UDP, rise, fall, turnoff • bufif1 #(3:4:5, 6:7:9, 5:7:8) (yout, xin, enable); // min:typ:max / rise, fall, turnoff • Simulators simulate with only one of min, typ and max delay values • Selection is made through compiler directives or user interfaces • Default delay is typ delay
Time Scales • Time scale directive: ‘ timescale <time_unit>/<time_precision> • time_unit -> physical unit of measure, time scale of delay • time_precision -> time resolution/minimum step size during simulation • time_unit time_precision
2 2 2 2 2 4 4 4 4 4 6 6 6 6 6 8 8 8 8 8 10 10 10 10 10 Net Delay … … wire #2 y_tran; and #3 (y_tran, x1, x2); buf #1 (buf_out, y_tran); and #3 (y_inertial, x1, x2); … … x1 x2 y_inertial x1 y_tran buf_out y_tran x2 y_inertial buf_out
Structural vs. Behavioral Descriptions module my_module(…); … assign …; // continuous assignment and (…); // instantiation of primitive adder_16 M(…); // instantiation of module always @(…) begin … end initial begin … end endmodule Structural, no order Behavior, in order in each procedure
initial | always single_statement; | begin block_of_statements; end initial Activated from tsim = 0 Executed once Initialize a simulation always Activated from tsim = 0 Executed cyclically Continue till simulation terminates Behavioral Statements
Example of Behavioral Statement module clock1 ( clk ); parameter half_cycle = 50; parameter max_time = 1000; output clk; reg clk; initial clk = 0; always begin #half_cycle clk = ~clk; end initial #max_time $finish; endmodule clk 50 100 150 200 tsim
Assignment • Continuous assignment • Values are assigned to net variables due to some input variable changes • “assign …=… “ • Procedural assignment • Values are assigned to register variables when certain statement is executed in a behavioral description • Procedural assignment, “=“ • Procedural continuous assignment, “assign …=… [deassign] “ • Non-blocking assignment, “<=“
Procedural Continuous Assignment • Continuous assignment establishes static binding for net variables • Procedural continuous assignment (PCA) establishes dynamic binding for variables • “assign … deassign” for register variables only
Binding takes effect when PCA statement is executed Can be overridden by another PCA statement “deassign” is optional “assign” takes control, “deassign” release control module flop ( q, qbar, preset, clear, clock, data ); … assign qbar = ~q; initial q = 0; always @ ( negedge clk ) q = data; always @ ( clear or preset ) begin if ( !preset ) assign q = 1; else if ( !clear ) assign q = 0; elsedeassign q; end endmodule “assign … deassign” PCA
Example of assign module mux4_PCA(a, b, c, d, select, y_out); input a, b, c, d; input [1:0] select; output y_out; reg y_out; always @(select) begin if (select == 0) assign y_out=a; else if (select == 1) assign y_out=b; else if (select == 2) assign y_out=c; else if (select == 3) assign y_out=d; elseassign y_out=1’bx; end endmodule y_out changes with a;
Alternative module mux4_PCA(a, b, c, d, select, y_out); input a, b, c, d; input [1:0] select; output y_out; reg y_out; always @(select or a or b or c or d) begin if (select == 0) y_out=a; else if (select == 1) y_out=b; else if (select == 2) y_out=c; else if (select == 3) y_out=d; else y_out=1’bx; end endmodule Value of ‘a’ is assigned to y_out at this time
initial begin a = 1; b = 0; a = b; // a = 0; b = a; // b = 0; end initial begin a = 1; b = 0; a <= b; // a = 0; b <= a; // b = 1; end Blocking assignment “=“ Statement order matters A statement has to be executed before next statement Non-blocking assignment “<=“ Concurrent assignment If there are multiple non-blocking assignments to same variable in same behavior, latter overwrites previous Blocking and Non-blocking Assignment
Delay Control Operator (#) initial begin #0 in1 = 0; in2 = 1; #10 in3 = 1; #40 in4 = 0; in5 = 1; #60 in3 = 0; end
… @ ( eventA or eventB ) begin … @ ( eventC ) begin … end end Event -> identifier or expression When “@” is reached Activity flow is suspended The event is monitored Other processes keep going posedge: 0->1, 0->x, x->1 negedge: 1->0, 1->x, x->0 Event Control Operator (@)
module modA (…); … always begin … wait ( enable ) ra = rb; … end endmodule Activity flow is suspended if expression is false It resumes when the expression is true Other processes keep going The “wait” Construct
// B = 0 at time 0 // B = 1 at time 4 … #5 A = B; // A = 1 C = D; … A = #5 B; // A = 0 C = D; … A = @(enable) B; C = D; … A = @(named_event) B; C= D; … If timing control operator(#,@) on LHS Blocking delay RHS evaluated at (#,@) Assignment at (#,@) If timing control operator(#,@) on RHS Intra-assignment delay RHS evaluated immediately Assignment at (#,@) Intra-assignment Delay: Blocking Assignment
module multi_assign(); reg a, b, c, d; initial begin #5 a = 1; b = 0; end always @ ( posedge a ) begin c = a; end always @ ( posedge a ) begin c = b; end always @ ( posedge a ) begin d = b; end always @ ( posedge a ) begin d = a; end endmodule Multiple assignments are made to same variable in different behaviors Value depends on code order or vendor specifications Similar to race-conditions in hardware Indeterminate Assignment
if ( A == B ) P = d; if ( B < C ); if ( a >= b ) begin … end if ( A < B ) P = d; else P = k; if ( A > B ) P = d; else if ( A < B ) P = k; else P = Q; Syntax: if ( expression ) statement [ else statement ] Value of expression 0, x or z => false Non-zero number => true Activity Flow Control ( if … else )
Conditional Operator ( ? … : ) always @ ( posedge clock ) yout = ( sel ) ? a + b : a – b; • Conditional operator can be applied in • either continuous assignments • or behavioral descriptions
module mux4 ( a, b, c, d, select, yout ); input a, b, c, d; input [1:0] select; output yout; reg yout; always @( a or b or c or d or select ) begin case ( select ) 0: yout = a; 1: yout = b; 2: yout = c; 3: yout = d; default yout = 1`bx; endcase endmodule Case items are examined in order Exact match between case expression and case item casez – treats “z” as don’t cares casex – treats both “x” and “z” as don’t cares The case Statement
The repeat Loop … word_address = 0; repeat ( memory_size ) begin memory [word_address] = 0; word_address = word_address + 1; end …
The for Loop reg [15:0] regA; integer k; … for ( k = 4; k; k = k – 1 ) begin regA [ k+10 ] = 0; regA [ k+2 ] = 1; end … Loop variables have to be either integer or reg
begin cnt1s reg [7:0] tmp; cnt = 0; tmp = regA; while ( tmp ) begin cnt = cnt + tmp[0]; tmp = tmp >> 1; end end module sth ( externalSig ); input externalSig; always begin while ( externalSig ); end endmodule The while Loop Loop activities suspend external activities
The disable Statement begin k = 0; for ( k = 0; k <= 15; k = k + 1 ) if ( word[ k ] == 1 ) disable ; end Terminate prematurely in a block of procedural statements
The forever Loop parameter half_cycle = 50; initial begin : clock_loop clock = 0; forever begin #half_cycle clock = 1; #half_cycle clock = 0; end end initial #350 disable clock_loop;
Task module bit_counter (data, count); input [7:0] data; output [3:0] count; reg [3:0] count; always @(data) t(data, count); task t; input [7:0] a; output [3:0] c; reg [3:0] c; reg [7:0] tmp; begin c = 0; tmp = a; while (tmp) begin c = c + tmp[0]; tmp = tmp >> 1; end end endtask endmodule
Function module word_aligner (w_in, w_out); input [7:0] w_in; output [7:0] w_out; assign w_out = align (w_in); function [7:0] align; input [7:0] word; begin align = word; if (align != 0) while (align[7] == 0) align = align << 1; end endfunction endmodule
Switch Level NAND Gate module nand_2 ( Y, A, B ); output Y; input A, B; supply0 GND; supply1 PWR; wire w; pmos ( Y, PWR, A ); pmos ( Y, PWR, B ); nmos ( Y, w, A ); nmos ( w, GND, B ); endmodule Vdd B A Y A B
nand ( pull1, strong0 ) G1( Y, A, B ); wire ( pull0, weak1 ) A_wire = net1 || net2; assign ( pull1, weak0 ) A_net = reg_b; Drive strength is specified through an unordered pair one value from { supply0, strong0, pull0, weak0 , highz0 } the other from { supply1, strong1, pull1, weak1, highz1 } Only scalar nets may receive strength assignment Assign Drive Strengths
Latch Resulted from Unspecified Input State module myMux( y, selA, selB, a, b ); input selA, selB, a, b; output y; reg y; always @ ( selA or selB or a or b ) case ( {selA, selB} ) 2’b10: y = a; 2’b01: y = b; endcase endmodule b selA’ en selB y selA latch selB’ a
Synthesis of Loops • repeat, for, while, forever • Depends on • Venders • Timing control • Data dependencies • A loop is static or data-independent if the number of iterations can by determined by the complier before simulation
Static Loops without Internal Timing Controls –> Combinational Logic module count1sA ( bit_cnt, data, clk, rst ); parameter data_width = 4; parameter cnt_width = 3; output [cnt_width-1:0] bit_cnt; input [data_width-1:0] data; input clk, rst; reg [cnt_width-1:0] cnt, bit_cnt, i; reg [data_width-1:0] tmp; always @ ( posedge clk ) if ( rst ) begin cnt = 0; bit_cnt = 0; end else begin cnt = 0; tmp = data; for ( i = 0; i < data_width; i = i + 1 ) begin if ( tmp[0] ) cnt = cnt + 1; tmp = tmp >> 1; end bit_cnt = cnt; end endmodule
Static Loops with Internal Timing Controls –> Sequential Logic module count1sB ( bit_cnt, data, clk, rst ); parameter data_width = 4; parameter cnt_width = 3; output [cnt_width-1:0] bit_cnt; input [data_width-1:0] data; input clk, rst; reg [cnt_width-1:0] cnt, bit_cnt, i; reg [data_width-1:0] tmp; always @ ( posedge clk ) if ( rst ) begin cnt = 0; bit_cnt = 0; end else begin cnt = 0; tmp = data; for ( i = 0; i < data_width; i = i + 1 ) @ ( posedge clk ) begin if ( tmp[0] ) cnt = cnt + 1; tmp = tmp >> 1; end bit_cnt = cnt; end endmodule
Non-Static Loops without Internal Timing Controls –> Not Synthesizable module count1sC ( bit_cnt, data, clk, rst ); parameter data_width = 4; parameter cnt_width = 3; output [cnt_width-1:0] bit_cnt; input [data_width-1:0] data; input clk, rst; reg [cnt_width-1:0] cnt, bit_cnt, i; reg [data_width-1:0] tmp; always @ ( posedge clk ) if ( rst ) begin cnt = 0; bit_cnt = 0; end else begin cnt = 0; tmp = data; for ( i = 0; tmp; i = i + 1 ) begin if ( tmp[0] ) cnt = cnt + 1; tmp = tmp >> 1; end bit_cnt = cnt; end endmodule
Non-Static Loops with Internal Timing Controls –> Sequential Logic module count1sD ( bit_cnt, data, clk, rst ); parameter data_width = 4; parameter cnt_width = 3; output [cnt_width-1:0] bit_cnt; input [data_width-1:0] data; input clk, rst; reg [cnt_width-1:0] cnt, bit_cnt, i; reg [data_width-1:0] tmp; always @ ( posedge clk ) if ( rst ) begin cnt = 0; bit_cnt = 0; end else begin: bit_counter cnt = 0; tmp = data; while ( tmp ) @ ( posedge clk ) begin if ( rst ) begin cnt = 0; disable bit_counter; end else begin cnt = cnt + tmp[0]; tmp = tmp >> 1; end bit_cnt = cnt; end end endmodule