A flip-flop captures data at its input at the positive or negative edge of a clock. The important thing to note is that whatever happens to data after the clock edge until the next clock edge will not be reflected in the output. A latch on the other hand, does not capture at the edge of a clock, instead the output follows input as long as the enable pin is asserted.
In this example, we'll build a latch that has three inputs and one output. The input d stands for data which can be either 0 or 1, rstn stands for active-low reset and en stands for enable which is used to make the input data latch to the output. Reset being active-low simply means that the design element will be reset when this input goes to 0 or in other words, reset is active when its value is low. The value of output q is dictated by the inputs d, en and rstn.
module d_latch ( input d, // 1-bit input pin for data input en, // 1-bit input pin for enabling the latch input rstn, // 1-bit input pin for active-low reset output reg q); // 1-bit output pin for data output // This always block is "always" triggered whenever en/rstn/d changes // If reset is asserted then output will be zero // Else as long as enable is high, output q follows input d always @ (en or rstn or d) if (!rstn) q <= 0; else if (en) q <= d; endmodule
Note that the sensitivity list to the
always block contains all the signals required to update the output. This block will be triggered whenever any of the signals in the sensitivity list changes its value. Also q will get the value of d only when en is high, and hence is a positive latch.
module tb_latch; // Declare variables that can be used to drive values to the design reg d; reg en; reg rstn; reg [2:0] delay; reg [1:0] delay2; integer i; // Instantiate design and connect design ports with TB signals d_latch dl0 ( .d (d), .en (en), .rstn (rstn), .q (q)); // This initial block forms the stimulus to test the design initial begin $monitor ("[%0t] en=%0b d=%0b q=%0b", $time, en, d, q); // 1. Initialize testbench variables d <= 0; en <= 0; rstn <= 0; // 2. Release reset #10 rstn <= 1; // 3. Randomly change d and enable for (i = 0; i < 5; i=i+1) begin delay = $random; delay2 = $random; #(delay2) en <= ~en; #(delay) d <= i; end end endmodule
To make our testbench assert and deassert signals in a more random manner, we have declared a
reg variable called delay of size 3 bits so that it can take any value from 0 to 7. Then the delay variable is used to delay the assignment of d and en to get different patterns in every loop.
ncsim> run  en=0 d=0 q=0  en=1 d=0 q=0  en=0 d=0 q=0  en=0 d=1 q=0  en=1 d=1 q=1  en=1 d=0 q=0  en=0 d=0 q=0  en=0 d=1 q=0  en=1 d=1 q=1  en=1 d=0 q=0 ncsim: *W,RNQUIE: Simulation is complete.
Click on the image to make it larger.
Click to try this example in a simulator!