/// Notes and Demos for LSU EE 4702-1 Spring 2001 /// Form 1: Combinational / Level Triggered // Sources: Ci: Ciletti, Modeling, synthesis, and rapid prototyping // with the Verilog HDL // Leo: Exemplar Logic (Mentor Graphics), // LeonardoSpectrum HDL Synthesis Manual, October 2000 /// Contents // Summary of Form 1 // Synthesis of Combinational Logic // Inference of Arithmetic Units // Inference of Registers. (When is a reg a register?) // Un-synthesizable Code (barely started) // Loops (Forms 1 and 2) (incomplete) // Case, If / Then /Else (barely started) /// Summary of Form 1 /// Form 1: Combinational / Level Triggered // // Describes combinational logic. // Describes level-triggered registers. // Unlimited number of level-trigger conditions. // /// Basic Form // // always @( a1 or a2 or /* ... */ an ) begin // <non-timing-statements>; // end // // The non-timing-statements include some but not all Verilog // statements. A complete list is not given here. // // Expressions used in non-timing-statements should use variables // listed in the event control (a1, a2, ..., an) or variables that // will have been written since the last event. // Examples: `ifdef NEVER always @( a1 or a2 ) begin x = a1; // Okay, a1 in event control. z1 = x; // Okay, x written by this point. z2 = y; // Not okay, y not written since last event. y = b; // Not okay, b not in event control and not written here. if( a1 ) w = a2; // Okay. v = w; // Not okay, w may not be written since last event. if( a1 ) u = a2; else u = a1; s = u; // Okay, u always written since last event. end `endif // Not allowed: // Delays, including delayed nonblocking assignments. // Edge trigger: @( a1 or posedge a2 ... ) // Event controls (other than first): @( foo or bar ). // Looping constructs with an infinite or non-constant number of iterations. // /// Inference of Registers (Synthesis of assignment statements.) // // Unconditional assignment to register generates wire: // x1 = a1 | a2; // x1 synthesized as a wire, not a register. // Conditional assignment to register generates level-triggered register. // if( a3 ) x2 = a1 | a2; // x2 synthesized as a register. // If there are multiple conditional assignments to a register and // at least one of them will execute, register synthesized as wire. // Example: `ifdef NEVER module ex1(); always @( a1 or a2 or /* ... */ an ) begin // No event controls. Not allowed: @( a1 ) // Only signals in event control, a1 .. an, can appear in expressions. x1 = a1 | a2; // Okay. x1 synthesized as wire. x2 = b1 | a1; // WARNING: b1 not in event control. syn != sim. if( a3 ) x3 = a1 & a2; // x3 synthesized as level-triggered register. if( a1 | a2 ) x4 = a1 | a2; // x4 synthesized as level-trig. register. if( a4 ) x5 = a3; // Because this or assignment below will execute ... if( !a4 ) x5 = a2; // ...x5 synthesized as wire. end endmodule `endif /// Synthesis of Combinational Logic /// Describes a few simple gates. module imply(aib,a,b); input a, b; output aib; wire a, b; reg aib; // Note: all inputs in event control. // Though declared as a register, aib will be synthesized as wire. always @( a or b ) aib = ~a | b; endmodule module bfa_behavioral(sum,cout,a,b,c); input a,b,c; output sum, cout; reg sum, cout; reg ab, ac, bc; // Because they are always assigned, regs above synthesized as wire. always @( a or b or c ) begin sum = a ^ b ^ c; ab = a & b; ac = a & c; bc = b & c; cout = ab | ac | bc; end endmodule module l(q,d,c); input d, c; output q; reg q; always @( d or c ) if( c ) q = d; else q = ~d; endmodule /// Inference of Arithmetic Units // Synthesis programs recognize common complex devices. Usually // arithmetic, comparison, and memory. // Will match to technology-optimized version, if available. // Otherwise will substitute gates realizing complex device. // Describes a simple multiplier. module times_ten(tt,a); input a; output tt; wire [31:0] a; reg [31:0] tt; always @( a ) tt = a * 10; endmodule /// Inference of Registers. (When is a reg a register?) // Applies to Form 1 /// In Form 1 a reg is synthesized as wire if: // the synthesis program determines that // it will be assigned on every iteration of the always block. module inf_reg_examp(a, b, clk); input a, b, clk; wire [7:0] a, b; reg [7:0] x, y, z, w, r; always @( a or b or clk ) begin x = a * 2 + b; // Assigned when clk is high, y is a level-triggered register. if( clk ) y = a + b; // Assigned whenever a > b, r is a level-triggered register. if( a > b ) r = 2 * a; // Combinational logic, probably a mux, with output z and // two inputs, a+b and a-b. (No register.) if( clk ) z = a + b; else z = a - b; // a will be either 0, 1, or 6, nothing else!!!!!!!!!!!!!!!!!!!! // w is a register. The comment above suggests w can be wire, // but the synthesis program can't read and understand it. if( a == 1 ) w = b + 5; if( a == 6 ) w = b - 5; if( a == 0 ) w = 0; end endmodule /// Un-synthesizable Code // Leonardo 2000 (and many similar programs) will not synthesize: // Code in an initial block. // System tasks. ($display, etc.) // Delays. (#3) // Waits (wait( a==2)) /// Loops (Forms 1 and 2) // Loops are allowed in Forms 1 and 2 iff: // the number of iterations can be determined at synthesis time. // (Can be determined by the synthesis program.) // The loop is synthesized as though the loop were completely // unrolled, that is as if the loop body were repeated for each loop index: // A loop such as this: // for(i=0; i<3; i=i+1) a[i] = b[i]; // // Is synthesized as though it were written like this: // a[0] = b[0]; // a[1] = b[1]; // a[2] = b[2]; module yet_another_pop(p,a); input a; output p; wire [31:0] a; reg [5:0] p; integer i; always @( a ) begin p = 0; // Loop okay, it's 32 iterations. // Synthesized hardware (before optimization) will use // 32 adders. // Since this is Form 1 and p always assigned, p is // synthesized as wire. // Actually, there will be 33 different wires that can be // labeled p (before optimization, and not counting the // individual bits). // Each assignment defines a new p, the p assigned in the // last iteration of the loop is the module output. for(i=0; i<32; i=i+1) p = p + a[i]; end endmodule module yet_another_pop_II(p,a); input a; output p; wire [31:0] a; reg [5:0] p; reg [31:0] acopy; always @( a ) begin p = 0; acopy = a; // Loop okay, it's 32 iterations. // This also synthesizes p and acopy as wire since // they are always assigned. Similar to the previous // example, there will be 33 different wires that can // be called p and acopy. repeat( 32 ) begin p = p + acopy[0]; acopy = acopy >> 1; end end endmodule module yet_another_pop_III(p,a); input a; output p; wire [31:0] a; reg [5:0] p; reg [31:0] acopy; always @( a ) begin p = 0; acopy = a; // Loop not okay. while( acopy ) begin p = p + acopy[0]; acopy = acopy >> 1; end end endmodule /// If / Else // Here is how code containing if / else statements will be // synthesized. The inference of logic applies only to Form 1 but the // combinational logic applies to all forms. module if_else_example(x,y,z,a,b,s); input a, b, s; output x, y, z; reg x, y, z; always @( a or b or s ) begin // Code below might be synthesized as a multiplexor, with // s as the control input and a and b as two data inputs. // // Because x is always assigned it is synthesized as wire. // Because y and z are sometimes assigned, they will be // synthesized as level-triggered registers. Register y is // clocked using s and z using not s. if( s ) begin x = a; y = a; end else begin x = b; z = b; end end endmodule module nested_if_example(x,a,b); input a, b; output x; wire [7:0] a, b; reg [7:0] x; // Since x is always assigned it will be synthesized as wire // (no registers). // The logic will consist of multiplexors, a multiplier (for b*a), // and two subtractors. (The synthesis program probably won't use // one subtractor for both a-b and b-a.) always @( a or b ) begin if( a > 100 ) begin if( b == 0 ) x = 1; else x = b * a; end else begin if( b < a ) x = a - b; else x = b - a; end end endmodule module if_else_example2(x,a,b,c,d,s); input a, b, c, d, s; output x; wire [2:0] s; reg x; always @( a or b or c or d or s ) begin // Code below might be synthesized as a multiplexor, or // a cascade of three two-input multiplexors. // // Because x is always assigned it is synthesized as wire. if( s[0] ) x = a; else if ( s[1] ) x = b; else if ( s[2] ) x = c; else x = d; end endmodule module if_else_example3(x,a,b,c,d,s); input a, b, c, d, s; output x; wire [3:0] s; reg x; always @( a or b or c or d or s ) begin // Code below might be synthesized as a multiplexor, or // a cascade of three two-input multiplexors. // // Unlike the example above, here x may not be assigned (when // s == 0, and so it will be synthesized as a register. // The register is clocked when x is assigned, which is // when s is nonzero. if( s[0] ) x = a; else if ( s[1] ) x = b; else if ( s[2] ) x = c; else if ( s[3] ) x = d; end endmodule /// Case // A case statement can be converted to an if/else chain (see // Case_eq_if) example below), and so alot of the synthesis rules for // if/else chains apply to case statements. However, synthesis // programs can sometimes recognize special forms of case statements // that result in simpler logic. module Case_eq_if(x, y, a, b, c); input a, b, c; output x, y; wire [3:0] a, b, c; reg [3:0] x, y; always @( a or b ) begin // A case statement. // Since x is always assigned it is synthesized as // a wire. Multiplexors pass the correct value of x, // the control inputs are based on the case conditions. casez( {a,b<c} ) {b, c[1]}: x = 3; {4'd5, 1'd1}: x = c; {4'b???, a<b}: x = b; default: x = a; endcase // The equivalent if/else chain. if ( a === b && (b<c) == c[1] ) y = 3; else if ( a === 4'd5 && (b<c) == 1'd1 ) y = c; else if ( (b<c) == (a<b) ) y = c; else y = a; end endmodule // The example below shows a case statement as it will more // commonly be used. module alu(op,r,a,b); input op, a, b; output r; reg r; wire [1:0] op; // Because the case items are sequential constants, the // synthesis program should use a multiplexor controlled by // op, rather than a cascade of multiplexors, as would // be used by the code above. Also, the synthesis program // will realize that r is always assigned because op is // two bits and all cases are present, and so r is wire, // not a register. always @( op or a or b ) case ( op ) 2: r = a & b; 3: r = a | b; 1: r = a + b; 0: r = a - b; endcase endmodule /// Case Statement Synthesis Directives /// (Leonardo Spectrum v1999.1f) // /// Purpose: // Tell synthesis program which case expression values are impossible. // With this information unnecessary hardware omitted. // /// Directives: // parallel_case: At most one case item is true. // full_case: At least one case item is true. // /// full_case // At least one case item is true. // With this directive synthesis program will omit latches under // certain circumstances. // /// parallel_case // At most one case item is true. // Simplifies case logic. // /// Automatic Detection of Case Item Possibilities // Leonardo can automatically detect when full_case and parallel_case // apply to case statements. // Its detection capabilities are limited though: // In some cases it cannot detect parallel and full case even though // there is enough information in the case statement to do so. // In other cases information not present in the module (and // unavailable to the synthesizer) is needed to prove that cases // are parallel or full.