/// 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