/// Notes and Demos for LSU EE 4702-1 Spring 2001 // Form 2: Edge 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 // Form 2: Edge Triggered Summary // Form 2, Basic // Form 2, Asynchronous Reset /// Form 2: Edge Triggered Summary // Describes registers clocked on the edge of a single signal which // can also be written with a constant at an asynchronous trigger. // Basic Form `ifdef XX always @( posedge s1 or posedge s2 or posedge s3 or /* ... */ posedge sn ) if( s1 ) begin <constant-assignments>; end else if ( s2 ) begin <constant-assignments>; end else if ( s3 ) begin /* ... */ end else begin <non-timing-statements>; end `endif // The form above must be adhered to, in particular: // // All terms in the event expression must be either posedge or negedge // of a signal. No signal can appear more than once. // The condition in each of the if statements shown above must be // one of the signals in the event expression. If the event // expression is "posedge foo" then the condition must be ( foo ) // and if the event expression is "negedge foo" the condition must // be ( !foo ). All of the signals in the event expression except // one must appear in one of the if conditions. /// The signal that's not used is called the clock. // Procedural statements can only be added where <constant-assignments> // and <non-timing-statements> appear. // // Assignments in <constant-assignments> can only assign constants // or constant expressions. x1 = 0 is okay but x1 = a1 is not. If // this rule is violated there will be a warning and the synthesized // hardware will behave differently than the simulated hardware. // One minor exception: signals in the event expression can be // tested, except the one in the condition immediately preceding the // code. (Whose value is known anyway.) // Assignments in <non-timing-statements> can assign any valid // expression. That is, a signal can be used in an expression // whether or not it appears in the event expression. Timing // controls cannot be used in <non-timing-statements>, nor can loops // with a non-constant number of iterations. // A register can be assigned multiple times within an always // block, but the same register CANNOT be assigned in different // always blocks. (This is true for all forms.) /// Inference of Registers (Synthesis of assignment statements.) // // Registers synthesized for all assignments. // // Unconditional assignment in <non-timing-statements>: // Edge-triggered (on clock). // x1 = a1 | a2; // x1 loaded with a1 | a2 on edge of clock. // // Conditional assignment in <non-timing-statements>: // Edge-triggered (on clock) with enable signal. // if( a3 ) x2 = a1 | a2; // x2 loaded with a1 | a2 on edge of clock if a3. // // Assignments in <constant-assignments> // Asynchronous set or reset triggered on signal in if condition. // x1 = 0; // Load x1 with zero when sx true or false. // // Note: The same register CAN be written in <constant-assignments> and // <non-timing-statements>, see "a" below: On a positive edge of // the clock (which may be sn) "a" will be loaded with "c". Whenever // "s1" is 1 a will be set to zero, when "s1" and "s2" are 0 "a" // will be set to one. // // Example: `ifdef NEVER module dummy(); always @( posedge s1 or negedge s2 or posedge s3 or /* ... */ posedge sn ) if( s1 ) begin // Can only assign constants here. a = 0; // Asynchronous reset when s1 true. b = c; // WRONG: c not a constant. end else if ( !s2 ) begin // Note condition in if. // Can only assign constants here. a = 1; // Asynchronous set when s2 false and s1 false. b = 0; // Asynchronous reset when s2 false and s1 false. end else if ( s3 ) begin // ... end else begin // Note that there is no condition after the else. // Edge triggered assignments here. a = c; // Assign a to c on a positive edge of the clk. if( c ) x1 = a3; // Edge triggered assignment to x1 if c true. end endmodule `endif /// Form 2, Basic `define xFORM2_FF1 `ifdef FORM2_FF1 module form2_basic(q, d, clk); input d, clk; output q; reg q; // A simple edge-triggered flip-flop. always @( posedge clk ) begin q = d; end endmodule `endif `define xFORM2_FF2 `ifdef FORM2_FF2 module form2_basic(q, d, r, clk); input d, r, clk; output q; reg q; always @( posedge clk ) begin // Synchronous reset if( r ) q = 0; else q = d; end endmodule `endif /// Multiple flip-flops clocked by same signal (clk). // `define xFORM2_FF3 `ifdef FORM2_FF3 module form2_basic(q1, q2, d1, d2, clk); input d1, d2, clk; output q1, q2; reg q1, q2; always @( posedge clk ) begin q1 = d1 | d2; q2 = d1 & d2; end endmodule `endif /// Multiple flip-flops, individually clocked. // `define xFORM2_FF4 `ifdef FORM2_FF4 module form2_basic(q1, q2, d1, d2, clk1, clk2); input d1, d2, clk1, clk2; output q1, q2; reg q1, q2; // Note: each always updates a different register. always @( posedge clk1 ) begin q1 = d1 | d2; end always @( posedge clk2 ) begin // Commented line not allowed. // q1 = d1 ^ d2; q2 = d1 & d2; end endmodule `endif `define xFORM2_UPDOWN `ifdef FORM2_UPDOWN module up_down_counter(count,op,din,clk); input op, din, clk; output count; wire [1:0] op; wire [3:0] din; wire clk; reg [3:0] count; parameter op_hold = 0; parameter op_up = 1; parameter op_down = 2; parameter op_load = 3; always @( posedge clk ) case( op ) op_hold: count = count; op_up: count = count + 1; op_down: count = count - 1; op_load: count = din; endcase endmodule `endif /// Form 2, Asynchronous Reset `define FORM2sr_FF1 `ifdef FORM2sr_FF1 module form2_sr(q, q1, q2, d, r, rx, clk, a, b); input d, r, clk, a, b, rx; output q, q1, q2; reg q; reg q1, q2; always @( posedge clk or posedge r or posedge rx ) begin // Asynchronous reset if( r ) begin q = 0; q1 = 1; end else if( rx ) begin q = 0; q1 = 0; end else begin q = d; q1 = a + b; end end endmodule `endif