View Course Path

# Verilog code for JK flip-flop – All modeling styles

Contents

## What is a JK flip flop?

Flip-flops are fundamental building blocks of sequential circuits. A flip flop can store one bit of data. Hence, it is known as a memory cell. Since they work on the application of a clock signal, they come under the category of synchronous circuits.

The J-K flip-flop is the most versatile of the basic flip flops. The JK flip flop is a gated SR flip-flop with the addition of a clock input circuitry that prevents the illegal or invalid output condition that can occur when both inputs S and R are equal to logic 1. Due to this additional clocked input, a JK flip-flop has four possible input combinations, “logic 1”, “logic 0”, “no change” and “toggle”.

As we proceed, we will see how to write Verilog code for SR Flip Flop using different levels of abstraction.

## Gate-Level Modeling

With the help of a logic diagram, we will be able to know the essential logic gates needed to build a circuit. Verilog provides us with gate primitives, which help us create a circuit by connecting basic logic gates. Gate level modeling enables us to describe the circuit using these gate primitives.

Given below is the logic diagram of a JK flip flop.

From the above logic circuit, we can see that we need four NAND gates to construct a JK flip flop.

### Gate Level Modeling of JK Flip Flop

As always, the `module` declaration in Verilog is done by listing the terminal ports in the logic circuit.

`module jkff_gate(q,qbar,clk,j,k);`

Note that we declare outputs first followed by inputs since built-in gates also follow the same pattern.

Now, let’s declare the input and output ports using the syntax for IO port declaration.

```input j,k,clk;
output q,qbar;

```
Next, we have to declare intermediate signals. These are signals that aren’t terminal ports—for example, the signals outgoing from the nand 1, nand2.
```wire nand1_out; // output from nand1
wire nand2_out; // output from nand2```

Time for us to write logic gates. We use the gate (<outputs>,<inputs>) format to use the in-built gates in Verilog.

```nand(nand1_out, j,clk,qbar);
nand(nand2_out, k,clk,q);
nand(q,qbar,nand1_out);
nand(qbar,q,nand2_out);```

and thus the final code will be:

```module jkff_gate(q,qbar,clk,j,k);

input j,k,clk;
output q,qbar;

wire nand1_out; // output from nand1
wire nand2_out; // output from nand2

nand(nand1_out, j,clk,qbar);
nand(nand2_out, k,clk,q);
nand(q,qbar,nand1_out);
nand(qbar,q,nand2_out);

endmodule

```

## Dataflow Modeling

Describing a flip flop using dataflow modeling is not applicable. Flip flops are supposed to work on edge-triggered clocks. In dataflow modeling, it is not possible to construct an edge-triggered flip flop. It works more like a latch. Also, when modeling sequential circuits with dataflow, it can sometimes result in an unpredictable output during a simulation. Hence, we prefer the highest level of abstraction (behavioral modeling) to describe sequential circuits like flip flops.

## Behavioral Modeling

Behavioral modeling is the highest level of abstraction. Unlike gate and dataflow modeling, behavior modeling does not demand knowing logic circuits or logic equations. As a designer, we just need to know the algorithm (behavior) of how we want the system to work. This type of modeling is simple since it does not involve using complex circuitry. A simple truth table will help us describe the design.

 CLOCK J K Q Q’ State Positive edge 0 0 Q Q’ No change Positive edge 0 1 0 1 Reset Positive edge 1 0 1 0 Set Positive edge 1 1 (Qprev)’ Qprev Toggle

Using the described behavior, we can start coding.

### Behavioral Modeling of JK Flip Flop

As always, we start with the `module` declaration and the port declarations

```module jkff_behave(clk,j,knq,qbar);

input clk,j,k;
output reg q,qbar;```

Wait! Did we mention output as reg? Yes, we did. Why? We define output using the  `reg` datatype because we use procedural assignments. Therefore, we have to make sure the outputs retain their value until the next value is given to them.

Then we write:

```[email protected](posedge clk)
begin
.....
end```

The `always` keyword makes sure the statements between `begin` and `end` will be executed as soon as the sensitivity list is triggered. Here, we are designing a positive edge-triggered JK Flipflop. The `posedge clk` in the sensitivity list will make sure the statements between `begin` and `end` will be executed as soon as the positive edge of the clock is detected.

Now, we describe how we want our flip flop to work. Depending on the values given to J and K, we assign our Q and Q’ output.

```[email protected](posedge clk)
begin
if(k = 0)
begin
q <= 0;
qbar <= 1;
end
else if(j = 1)
begin
q <= 0;
qbar <= 0;
end
else if(j = 0 & k = 0)
begin
q <= q;
qbar <= qbar;
end
else if(j = 1 & k = 1)
begin
q <= ~q;
qbar <= ~qbar;
end
end

```

Depending on the conditions applied, the `if-else` statements execute the statement.  As per above code, depending on the J and K inputs, the statements for Q and Q’ output will be executed.

Hence, our final code be:

```module jkff_behave(clk,j,knq,qbar);

input clk,j,k;
output reg q,qbar;

[email protected](posedge clk)
begin
if(k = 0)
begin
q <= 0;
qbar <= 1;
end
[email protected](posedge clk)
begin
if(k = 0)
begin
q <= 0;
qbar <= 1;
end
else if(j = 1)
begin
q <= 0;
qbar <= 0;
end
else if(j = 0 & k = 0)
begin
q <= q;
qbar <= qbar;
end
else if(j = 1 & k = 1)
begin
q <= ~q;
qbar <= ~qbar;
end
end

endmodule

```

## Testbench

testbench is an HDL module that is used to test another module, called the device under test (DUT). The test bench contains statements to apply inputs to the DUT and, ideally, to check that the correct outputs are produced. The input and desired output patterns are called test vectors.

Ler’s see how we can write the testbench for JK flip flop.

```//test bench for JK flip flop
//1. Declare module and ports

module jkff_test;
reg J,K, CLK;
wire Q, QBAR;

//2. Instantiate the module we want to test. We have instantiated the jkff_behavior
jkff_behavior dut(.q(Q), .qbar(QBAR), .j(J), .k(K), .clk(CLK)); // instantiation by port name.

//3. Monitor TB ports
\$monitor("simtime = %g, CLK = %b, J = %b, K = %b, Q = %b, QBAR = %b", \$time, CLK, J, K, Q, QBAR);

//4. apply test vectors
initial begin
clk=0;
forever #10 clk = ~clk;
end
initial begin
J= 1; K= 0;
#100; J= 0; K= 1;
#100; J= 0; K= 0;
#100; J= 1; K=1;
end
endmodule```

## RTL Schematic

Here’s how the RTL Schematic will look if we peek into the elaborate design of the behavioral model of the JK-flip flop.