Ads

Get STM32 tutorial using HAL at $10 for a limited time!

Sunday, July 17, 2016

Verilog Tutorial 2 - ModelSim - Dual Priority Encoder

A priority encoder is a circuit or algorithm that compresses multiple binary inputs into a smaller number of outputs[1]. In priority encoder, if two or more inputs are given at the same time, the input having the highest priority will take precedence. This is the four-request priority encoder truth table from FPGA Prototyping by Verilog Example book by Pong P. Chu.


You can learn the code implementation of that priority encoder from that book. In this tutorial, I will implement a dual priority encoder from suggested experiment on chapter 3 of this book. A dual priority encoder returns the code of the highest and second-highest priority request. The input is 12-bit signal and the outputs are the first and second priority codes, which are 4-bit binary codes of the highest and second-highest priority request.

To implement this circuit, we can use one 12-to-4 priority encoder to get highest priority request. To get the second-highest priority request, we can use one 12-to-4 priority encoder, one 4-to-12 decoder, and logic gates (and gate and not gate). To get the second-highest priority request, we must clear the highest priority request bit of the input bits, then input that bits to another 12-to-4 priority encoder. The 4-to-12 decoder and logic gates is used for produce bit mask that will clear the highest priority request bit of the input bits. This is top level schematic of this circuit:


This is the example calculation to verify this circuit:


This is the code for the circuit using behavioral modeling:
// priority_encoder_12_4.v
module priority_encoder_12_4
    (
        input wire [11:0] r,
        output reg [3:0] y
    );

    // Body
    always @*
        if (r[11])
            y = 4'b1100;
        else if (r[10])
            y = 4'b1011;
        else if (r[9])
            y = 4'b1010;
        else if (r[8])
            y = 4'b1001;
        else if (r[7])
            y = 4'b1000;
        else if (r[6])
            y = 4'b0111;
        else if (r[5])
            y = 4'b0110;
        else if (r[4])
            y = 4'b0101;
        else if (r[3])
            y = 4'b0100;
        else if (r[2])
            y = 4'b0011;
        else if (r[1])
            y = 4'b0010;
        else if (r[0])
            y = 4'b0001;
        else
            y = 4'b0000;
endmodule
// decoder_4_12.v
module decoder_4_12
    (
        input wire [3:0] a,
        output reg [11:0] y
    );

    // Body
    always @*
        case (a)
            4'b0000: y = 12'b000000000000;
            4'b0001: y = 12'b000000000001;
            4'b0010: y = 12'b000000000010;
            4'b0011: y = 12'b000000000100;
            4'b0100: y = 12'b000000001000;
            4'b0101: y = 12'b000000010000;
            4'b0110: y = 12'b000000100000;
            4'b0111: y = 12'b000001000000;
            4'b1000: y = 12'b000010000000;
            4'b1001: y = 12'b000100000000;
            4'b1010: y = 12'b001000000000;
            4'b1011: y = 12'b010000000000;
            4'b1100: y = 12'b100000000000;
            default: y = 12'b000000000000;
        endcase

endmodule
// top.v
module top
    (
        input wire [11:0] r,
        output wire [3:0] p1,
        output wire [3:0] p2
    );

    // Signal declaration
    wire [3:0] first_prio_out;
    wire [11:0] first_prio_out_decode;
    reg [11:0] second_encoder_input;

    // Body
    priority_encoder_12_4 first_priority_encoder_unit 
        (.r(r), .y(first_prio_out));

    priority_encoder_12_4 second_priority_encoder_unit 
        (.r(second_encoder_input), .y(p2));

    decoder_4_12 uut (.a(first_prio_out), .y(first_prio_out_decode));
 
    always @*
        begin
            second_encoder_input = ~first_prio_out_decode & r;
        end
 
    assign p1 = first_prio_out;
 
endmodule
This is the testbench code for verify the result:
// top_tb.v
`timescale 1 ns/ 10 ps

module top_tb;
    // Signal declaration 
    reg [11:0] r_test;
    wire [3:0] p1_test;
    wire [3:0] p2_test;

    // Instantiate the circuit under test
    top uut (.r(r_test), .p1(p1_test), .p2(p2_test));

    // Test vector generator
    initial
    begin
        r_test = 12'b100000000000;
        # 200;
        r_test = 12'b000010000000;
        # 200;
        r_test = 12'b000011000000;
        # 200;
        r_test = 12'b000010100000;
        # 200;
        r_test = 12'b000010001000;
        # 200;
        r_test = 12'b000010101000;
        # 200;
        r_test = 12'b100000000001;
        # 200;
        r_test = 12'b000000000000;
        # 200;
        // Stop simulation
        $stop;
    end
 
endmodule
This is the simulation result:


You can download full project file of this tutorial from my repository.

References:
[1] https://en.wikipedia.org/wiki/Priority_encoder

4 comments :