A previous article showed different examples of using an always
block to implement combinational logic. An always
block is also mainly used to implement sequential logic which has memory elements like flip flops that can hold values.
JK Flip Flop
A JK flip flop is one of the many types of flops used to store values and has two data inputs j and k along with one for reset rstn and another for clock clk . The truth table for a JK flop is shown below and is typically implemented using NAND gates.
rstn | j | k | q | Comments |
---|---|---|---|---|
0 | 0 | 0 | 0 | When reset is asserted, output is always zero |
1 | 0 | 0 | Hold value | When both j and k are 0, output remains the same as before |
1 | 0 | 1 | 1 | When k=1, output becomes 1 |
1 | 1 | 0 | 0 | When k=0, output becomes 0 |
1 | 1 | 1 | Toggle value | When j=1,k=1 output toggles current value |
The behavioral Verilog code for a JK flip-flop can be written as shown below
module jk_ff ( input j, // Input J
input k, // Input K
input rstn, // Active-low async reset
input clk, // Input clk
output reg q); // Output Q
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
q <= 0;
end else begin
q <= (j & ~q) | (~k & q);
end
end
endmodule
Testbench
First declare all variables used in the testbench and start a clock using a simple always
block that can be driven to the design. Then instantiate the design and connect its ports with corresponding testbench variables. Note that q is of type wire
because it is connected to an output of the design which will be actively driving it. All other inputs to the design are of type reg
so that they can be driven within a procedural block such as initial
.
The stimulus first initializes all inputs to the design to zero and then de-asserts reset after some time. A for
loop is used to drive different values to j and k which are driven at random times. Once the loop is done, wait for some more time and finish the simulation.
module tb;
// Declare testbench variables
reg j, k, rstn, clk;
wire q;
integer i;
reg [2:0] dly;
// Start the clock
always #10 clk = ~clk;
// Instantiate the design
jk_ff u0 ( .j(j), .k(k), .clk(clk), .rstn(rstn), .q(q));
// Write the stimulus
initial begin
{j, k, rstn, clk} <= 0;
#10 rstn <= 1;
for (i = 0; i < 10; i = i+1) begin
dly = $random;
#(dly) j <= $random;
#(dly) k <= $random;
end
#20 $finish;
end
endmodule
Note from the simulation wave that at the posedge of clock, output q changes value based on the state of inputs j and k as given in the truth table.

Modulo-10 counter
Modulus(MOD) counters simply count upto a certain number before rolling back to zero. A MOD-N counter will count from 0 to N-1 and then roll back to zero and start counting again. Such counters typically require log2N number of flops to hold the count value. Shown below is the Verilog code for a MOD-10 counter that keeps counting up at every clock clk as long as reset rstn is deasserted.
Verilog parameters can be used to make a MOD-N counter which is more scalable.
module mod10_counter ( input clk,
input rstn,
output reg[3:0] out);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
if (out == 10)
out <= 0;
else
out <= out + 1;
end
end
endmodule
Testbench
The testbench first declares some variables that can be assigned some values and driven to the design inputs. The counter module is then instantiated and connected with the testbench signals which are later driven with some values in the stimulus. Since the counter also requires a clock, the testbench clock is modeled with an always
block. The stimulus simply sets default values at time 0ns, then deasserts reset after 10ns and the design is allowed to run for some time.
module tb;
reg clk, rstn;
reg [3:0] out;
mod10_counter u0 ( .clk(clk), .rstn(rstn), .out(out));
always #10 clk = ~clk;
initial begin
{clk, rstn} <= 0;
#10 rstn <= 1;
#450 $finish;
end
endmodule
See that the counter module counts from zero to 9, rolls over to zero and starts counting again.

4bit Left Shift Register
Shown below is a 4-bit left shift register that accepts an input d into LSB and all other bits will be shifted left by 1. For example, if d equals zero and the initial value of the register is 0011, it will become 0110 at the next edge of the clock clk .
module lshift_4b_reg ( input d,
input clk,
input rstn,
output reg [3:0] out
);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
out <= {out[2:0], d};
end
end
endmodule
Testbench
The testbench follows a similar template like the one shown before where some variables are declared, design module is instantiated and connected with the testbench signals. Then a clock is started and the stimulus is driven to the design using an initial
block. In this testbench example, different values of d has to be exercised and hence a for
loop is used to iterate 20 times and apply random values to the design.
module tb;
reg clk, rstn, d;
wire [3:0] out;
integer i;
lshift_4b_reg u0 ( .d(d), .clk(clk), .rstn(rstn), .out(out));
always #10 clk = ~clk;
initial begin
{clk, rstn, d} <= 0;
#10 rstn <= 1;
for (i = 0; i < 20; i=i+1) begin
@(posedge clk) d <= $random;
end
#10 $finish;
end
endmodule
Note that each bit is shifted to the left by 1 and the new value of d is applied to LSB.
