View Course Path

Verilog code for priority encoder – All modeling styles

In this article, we will learn to

  • Describe the Priority Encoder using different levels of abstraction in Verilog – Gate levelDataflow, behavioral, and structural modeling.
  • Generate the RTL schematic for the Priority Encoder.
  • Write the testbench.
  • Generate simulated waveforms.

What is a Priority Encoder?

Before explaining the priority encoder, you must know what an encoder is.

An encoder is a combinational circuit. It has 2^n input lines and n output lines. It takes up these 2^n input data and encodes them into n-bit data. In other words, it produces the binary code equivalent of the input line, which is active high.

But, a normal encoder has a problem. If there is more than one input line with logic 1 value, it will encode the wrong output. It only works when only one of the inputs is high. It malfunctions in the case of multiple high inputs.

Thus, to solve the above disadvantage, we “prioritize” the level of each input. Hence, if multiple input lines are selected, the output code will correspond to the input with the highest designated priority. This type of encoder is called the Priority Encoder.

Now, we will learn how to design a 4:2 Priority Encoder using different modeling styles in Verilog.

Gate Level Modeling

This is virtually the lowest abstraction layer, which is used by designers for implementing the lowest level modules, as the switch level modeling isn’t that common. As the name suggests, gate-level modeling makes use of the gate primitives available in Verilog. The prerequisite for this style is knowing the basic logic diagram of the digital circuit that you wish to code. You can learn everything about the Gate level modeling method in Verilog over here.

As we are describing a Priority Encoder using Gate-Level modeling, let’s see the logic circuit:

4:2 PRIORITY ENCODER LOGIC CIRCUIT
4:2 Priority Encoder logic circuit

From the circuit, we can observe that one AND, two OR and one NOT gates are required for designing. Let’s start coding.

Gate level Modeling for 4:2 priority encoder:

As any Verilog code, we start by declaring the module and terminal ports.

module priority_encoder_42(A0,A1,Y0,Y1,Y2,Y3);
....
endmodule

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

Let’s declare the input and output ports.

input Y3, Y2, Y1, Y0;
output A0, A1;

Now, we can declare the intermediate signals. These are signals that are not the terminal ports. From the above circuit, the signals from NOT and AND gates can be treated as intermediate signals.

wire y2bar; //not of y2 
wire and_out; // and of y2bar and y1

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

not(y2bar, y2);
and(and_out, y2bar, y1);
or(A1, Y3, Y2);
or(A0, and_out, Y3);

So, our final code is:

module priority_encoder_42(A0,A1,Y0,Y1,Y2,Y3);

input Y3, Y2, Y1, Y0;
output A0, A1;

wire y2bar; //not of y2 
wire and_out; // and of y2bar and y1

not(y2bar, y2);
and(and_out, y2bar, y1);
or(A1, Y3, Y2);
or(A0, and_out, Y3);

endmodule

Dataflow Modeling

In this modeling technique, we use logic equations to describe the flow of data from input to the output. We need not bother about the gates that make up the circuit. Hence, it is much easier to construct complex circuits using this level of abstraction since there is no need to know the actual physical layout. You can read all about the dataflow modeling technique in Verilog over here.

To describe the circuit using the logic equation, this modeling uses the keyword assign. We can see how it is done.

Shouldn’t we know the logic equation for the priority encoder?

Correct! Here it is:

A1 = Y3 + Y2

A0 = Y3 + Y1Y2′

Now, let’s proceed with the coding.

Dataflow modeling of 4:2 Priority Encoder

As always, we start with the module and port declarations:

module priority_encoder_datafloe(A0,A1,Y0,Y1,Y2,Y3);
input Y0,Y1,Y2,Y3;
output A0,A1;

Now, we have to describe the flow of data to the outputs using assign.

assign A1 = Y3 + Y2;
assign A0 = Y3 + ((~Y2)&Y1);

Hence, our final code:

module priority_encoder_datafloe(A0,A1,Y0,Y1,Y2,Y3);
input Y0,Y1,Y2,Y3;
output A0,A1;

assign A1 = Y3 + Y2;
assign A0 = Y3 + ((~Y2)&Y1);

endmodule

Behavioral Modeling

Behavioral Modeling is the highest level of abstraction in Verilog HDL. We can describe the circuit by just knowing how it works. Moreover, there’s additional good news! We do not need to know the logic circuit or logic equation. We just need a simple truth table. You can check out our in-depth guide on behavioral modeling in Verilog here.

Y3 Y2 Y1 Y0 A1 A0
0 0 0 1 0 0
0 0 1 x 0 1
0 1 x x 1 0
1 x x x 1 1

With this truth table, we can design our priority Encoder using Verilog.

Let’s see how:

Behavioral Modeling of 4:2 Priority Encoder

As usual, starting with the module and the port declaration.

module priority_encoderbehave(A, Y);

input [3:0]Y;
output reg [1:0]A;
We have to mention output as reg in behavioral modeling. As we use procedural assignments in this style of modeling, we have to make sure the outputs retain their value until the next value is given to them.
Moving on,
always@(Y)
begin
....
end

What we have declared in brackets is the sensitivity list. Here, depending on the value of Y, the statements between begin and end will be executed. The always keyword will make sure that the statements get executed every time the sensitivity list is triggered.

In between begin and end, we write the procedure for how the system works:

casex(Y)

4'b0001:A = 2'b00;
4'b001x:A = 2'b01;
4'b01xx:A = 2'b10;
4'b1xxx:A = 2'b11;
default:$display("Error!");

endcase

The case compares an expression to a series of cases and executes the statement or statement group associated with the first matching case. We have used casex, which is a special version of the case. This will treat the x and z values as don’t cares.

Therefore, our final code will be:

module priority_encoderbehave(A, Y);

input [3:0]Y;
output reg [1:0]A;

always@(Y)
begin

casex(Y)

4'b0001:A = 2'b00;
4'b001x:A = 2'b01;
4'b01xx:A = 2'b10;
4'b1xxx:A = 2'b11;
default:$display("Error!");
endcase
end
endmodule

Structural Modeling

Structural modeling describes the hardware structure of a digital system. It is somewhat similar to gate-level modeling. The only difference is it doesn’t include any built-in gates. We create separate modules for each gate and then integrate to form the whole circuit

Logic Circuit

In the case of 4:2 priority encoder, we require two OR, an AND and a NOT gates.

logic circuit for priority encoder
logic circuit for priority encoder

We have to structurize each gate with their respective module.

Structural Modeling of 4:2 Priority Encoder

To start with code, we will first structurize the OR gate.

We declare the module as or_gate. Then, we declare input and output ports

module or_gate(c,a,b);
input a,b
output c;

Then, we use assign statement to write the logical expression for OR.

assign c = a|b;

Thus our OR gate module will be:

module or_gate(c,a,b);
input a,b;
output c;

assign c = a|b;

endmodule

Similarly, we do for AND gate:

module and_gate(z,x,y);

input x,y;
output z;

assign z = x&y;

endmodule 

And NOT gate:

module not_gate(f,e);

input e;
output f;

assign f = ~e;

endmodule

Note: We keep variables for assigning inputs and outputs in one module different from others. This ensures mixing up of signals does not happen during a simulation.

Now we can proceed describing the Priority Encoder as the top-level module.

As usual, start with the module and port declarations.

module priority_encoder_struct(A0,A1,Y0,Y1,Y2,Y3);

input Y0, Y1, Y2, Y3;
output A0,A1;

Time for us to combine these individual modules for logic gates into one single module for the top module. This is done with the help of a concept called module instantiation in which top modules are build using lower modules.

Using the logic circuit, we will instantiate the lower modules in this top using instantiation by port name.

not_gate u1(.f(y2bar), .e(y2));
and_gate u2(.z(w1), .x(y2bar), .y(y1));
or_gate(.c(A1), .a(Y3), .b(Y2));
or_gate(.c(A0), .a(Y1), .b(w1));

Hence, the Verilog code for the priority encoder in structural style is:

module or_gate(c,a,b);
input a,b;
output c;
assign c = a|b;
endmodule

module not_gate(f,e);
input e;
output f;
assign f = ~e;
endmodule

module and_gate(z,x,y);
input x,y;
output z;
assign z = x&y;
endmodule 

module priority_encoder_struct(A0,A1,Y0,Y1,Y2,Y3);
input Y0, Y1, Y2, Y3;
output A0,A1;

not_gate u1(.f(y2bar), .e(y2));
and_gate u2(.z(w1), .x(y2bar), .y(y1));
or_gate(.c(A1), .a(Y3), .b(Y2));
or_gate(.c(A0), .a(Y1), .b(w1));

endmodoule

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.

Let’s see the test bench for the priority encoder:

module PriorityEncoder_Test;
 //Reg and Wire declarations
 reg [3:0] y;
 wire [1:0] a;
 
 // Instantiate the Unit Under Test (UUT)
priority_encoderbehave uut (.Y(y), .A(a));
 initial 
begin
 // Initialize Inputs
 Y = 0;
 // Wait 100 ns for global reset to finish
 #100;        
// apply test vectors

 #10 Y = 4'b0000;
 #10 Y = 4'b1000;
 #10 Y = 4'b0100;
 #10 Y = 4'b0010;
 #10 Y = 4'b0001;
 #10 Y = 4'b1010;
 #10 Y = 4'b1111;
 end 
 initial begin
 $monitor("time=",$time,, "D=%b : Y=%b V=%b",D,Y,V); 
 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 Priority Encoder.

RTL schematic 4:2 priority encoder
RTL schematic 4:2 priority encoder

Simulated Waveforms

We can verify the functional correctness of described Priority Encoder by simulation. Here’s the simulated waveform.

4:2 priority encoder simulated wave form
4:2 priority encoder simulated waveform

We hope you understood the implementation of the Priority Encoder using the various modeling styles in Verilog. For any queries, leave us a comment below.