A positive edge detector will send out a pulse whenever the signal it is monitoring changes from 0 to 1 (positive edge).

Design

positive edge detector block diagram

The idea behind a positive edge detector is to delay the original signal by one clock cycle, take its inverse and perform a logical AND with the original signal.


module pos_edge_det ( input sig,            // Input signal for which positive edge has to be detected
                      input clk,            // Input signal for clock
                      output pe);           // Output signal that gives a pulse when a positive edge occurs

    reg   sig_dly;                          // Internal signal to store the delayed version of signal

    // This always block ensures that sig_dly is exactly 1 clock behind sig
	always @ (posedge clk) begin
		sig_dly <= sig;
	end

    // Combinational logic where sig is AND with delayed, inverted version of sig
    // Assign statement assigns the evaluated expression in the RHS to the internal net pe
	assign pe = sig & ~sig_dly;            
endmodule 

The module shown above is named pos_edge_det and has two inputs and one output. The design aims to detect the positive edge of input sig, and output pe. So we expect to see a pulse on pe whenever sig changes from value 0 to 1.

positive-edge-detector

We create an internal signal called sig_dly of type reg that can store a single clock cycle delayed version of sig, and is achieved by the always block. Output pe is an implicit variable of type wire and can be assigned only by a continous assignment. Hence we have used the assign statement to assign an expression to pe. The expression simply takes sig and does a logical AND with the inversion of sig.

Testbench

In order to simulate our design, we have to place the module of our verilog code inside a testbench. The testbench simply holds our design and provides us a way to send in signals as inputs and observe the outputs to make sure that it operates as required.


module tb;
	reg sig;         // Declare internal TB signal called sig to drive the sig pin of the design
	reg clk;         // Declare internal TB signal called clk to drive clock to the design
	
	// Instantiate the design in TB and connect with signals in TB
	pos_edge_det ped0 (  .sig(sig),           
    					 .clk(clk),
 			      		 .pe(pe));

	// Generate a clock of 100MHz
	always #5 clk = ~clk;           
	
	// Drive stimulus to the design
	initial begin
		clk <= 0;
		sig <= 0;
		#15 sig <= 1;
		#20 sig <= 0;
		#15 sig <= 1;
		#10 sig <= 0;
		#20 $finish;
	end	
endmodule

Clock for our design is generated by the always block which toggles clk every 5 time units, there by generating a clock with period = 10 time units. Basic design stimulus is written within the initial block which makes the simulator advance in time and drive the design with specific values appropriately.

Hardware Schematic

The behavioral model in Verilog was synthesized using Xilinx Vivado FPGA design tool and the hardware schematic has been generated as shown below. It can be seen that the one clock delay is implemented using a DFF and the output of the flip flop is wired to the input of an AND gate through an inverter. These digital elements are substituted with logical cells that belong to a real cell library for a given technology node.

Synthesized Netlist

The hardware schematic is replaced by cells required for the hardware to be implemented in Artix-7 FPGA and forms the netlist.


module pos_edge_det
   (sig,
    clk,
    pe);
  input sig;
  input clk;
  output pe;

  wire  ;
  wire  ;
  wire clk;
  wire clk_IBUF;
  wire clk_IBUF_BUFG;
  wire pe;
  wire pe_OBUF;
  wire sig;
  wire sig_IBUF;
  wire sig_dly;

  GND GND
       (.G( ));
  VCC VCC
       (.P( ));
  BUFG clk_IBUF_BUFG_inst
       (.I(clk_IBUF),
        .O(clk_IBUF_BUFG));
  IBUF clk_IBUF_inst
       (.I(clk),
        .O(clk_IBUF));
  OBUF pe_OBUF_inst
       (.I(pe_OBUF),
        .O(pe));
  LUT2 #(
    .INIT(4'h2)) 
    pe_OBUF_inst_i_1
       (.I0(sig_IBUF),
        .I1(sig_dly),
        .O(pe_OBUF));
  IBUF sig_IBUF_inst
       (.I(sig),
        .O(sig_IBUF));
  FDRE #(
    .INIT(1'b0)) 
    sig_dly_reg
       (.C(clk_IBUF_BUFG),
        .CE( ),
        .D(sig_IBUF),
        .Q(sig_dly),
        .R( ));
endmodule