0
\$\begingroup\$

I would like to ask some questions about inferring the priority and normal encoder using Verilog on the FPGA.

I've used the example codes from the book "advanced chip design practical examples in Verilog"

Code for pri_encoder

module pri_encoder
(D0, D1, D2, D3, D4, D5, D6, D7,
Q2Q1Q0);

input D0, D1, D2, D3, D4, D5, D6, D7;
output [2:0] Q2Q1Q0;
reg    [2:0] Q2Q1Q0;

always @*
  begin
    Q2Q1Q0 = 3'b000;
      if(D0) Q2Q1Q0 = 3'b000;
      else if(D1) Q2Q1Q0 = 3'b001;
      else if(D2) Q2Q1Q0 = 3'b010;
      else if(D3) Q2Q1Q0 = 3'b011;
      else if(D4) Q2Q1Q0 = 3'b100;
      else if(D5) Q2Q1Q0 = 3'b101;
      else if(D6) Q2Q1Q0 = 3'b110;
      else if(D7) Q2Q1Q0 = 3'b111;
  end
endmodule

Code for normal encoder

module encoder
(D0, D1, D2, D3, D4, D5, D6, D7,
Q2Q1Q0);

input D0, D1, D2, D3, D4, D5, D6, D7;
output [2:0] Q2Q1Q0;
reg    [2:0] Q2Q1Q0;

always @*
  begin
    Q2Q1Q0 = 3'b000;
    case (1'b1)
      D0: Q2Q1Q0 = 3'b000;
      D1: Q2Q1Q0 = 3'b001;
      D2: Q2Q1Q0 = 3'b010;
      D3: Q2Q1Q0 = 3'b011;
      D4: Q2Q1Q0 = 3'b100;
      D5: Q2Q1Q0 = 3'b101;
      D6: Q2Q1Q0 = 3'b110;
      D7: Q2Q1Q0 = 3'b111;
    endcase
  end
endmodule 

The first question is about the constant expression in the switch case. It seems that constant expression can be located inside the switch (exp) and the element that has 1'b1 can be picked. Does it infer the priority encoder or just normal encoder?

At the first glance, it seems like the case with constant expression will work like a priority encoder, but when I synthesize the above code on the Vivado platform, the synthesized schematic seems like below.

enter image description here

The second question is how can we know if the synthesized design is priority encoder or normal encoder if they are constructed using the LUTs? When I look at the Q2Q1Q02 and Q2Q1Q0[1] it seems that all the data D0 ~ D7 are connected to LUTs only one time. However, for the Q2Q1Q0[0] two LUT6 are connected to generate an output and some data inputs are connected to two LUTs.

\$\endgroup\$
  • \$\begingroup\$ Look up the 74LS148 or 74HC148 priority encoder, and examine its construction. It can only be a priority encoder and outputs an inverted octal value plus a interrupt. Handy if you have a simple MPU and only one interrupt pin. \$\endgroup\$ – Sparky256 Jan 17 '18 at 4:02
1
\$\begingroup\$

Your if-else and case(1'b1) are both priority encoders. A normal encoder would look like the following:

always @*
  begin
    Q2Q1Q0 = 3'b000;
    case ({D7,D6,D5,D4,D3,D2,D1,D0})
      8'h01: Q2Q1Q0 = 3'b000;
      8'h02: Q2Q1Q0 = 3'b001;
      8'h04: Q2Q1Q0 = 3'b010;
      8'h08: Q2Q1Q0 = 3'b011;
      8'h10: Q2Q1Q0 = 3'b100;
      8'h20: Q2Q1Q0 = 3'b101;
      8'h40: Q2Q1Q0 = 3'b110;
      8'h80: Q2Q1Q0 = 3'b111;
    endcase
  end

A normal encoder considers the whole input expression and only one bit must be one. If more bits are one then no conditions are meet (default and/or error condition depending it is coded).

Priority encoders have precedence to bits if two more more bits are high. If the input is 8'h12 then either 1 or 5 (depending on the priority order) will be returned. A normal encoder will return 0 (and/or an error) because the input is not one-hot. See the true table below.

$$ \begin{array}{r|lcr|lcr|l} \ \text{Normal} &&& \text{Priority (LSB)} &&& \text{Priority (MSB)} \\ 00000001 & 000 && ???????1&000 && 00000001 & 000 \\ 00000010 & 001 && ??????10&001 && 0000001? & 001 \\ 00000100 & 010 && ?????100&010 && 000001?? & 010 \\ 00001000 & 011 && ????1000&011 && 00001??? & 011 \\ 00010000 & 100 && ???10000&100 && 0001???? & 100 \\ 00100000 & 101 && ??100000&101 && 001????? & 101 \\ 01000000 & 110 && ?1000000&110 && 01?????? & 110 \\ 10000000 & 111 && 10000000&111 && 1??????? & 111 \\ \color{blue}{\text{otherwise}} & - \color{red}{\text{ [error]}} && 00000000 & - \color{red}{\text{ [error]}} && 00000000 & - \color{red}{\text{ [error]}} \\ \end{array} $$

The syntax case(1'b1) compares a value to a list a variables and executes the first match. Where as typical case statements compares a variable to a list for values and executes the first match. By default case(1'b1) infers a priority encoder. However, the synthesizer may choose to use a normal encoder if it can determine the input is guaranteed to be one-hot and if it satisfies timing and resource requirements. Most synthesizer have pragmas that allows to user force the type. Pragma commands are not universal so you will need to refer to the manual. Note pragmas are for experts, only use them when required.

\$\endgroup\$
  • \$\begingroup\$ Thanks for a great and clear answer! I have one further question about encoder/decoder. It seems that normal encoder converts one-hot to binary, so it has smaller output width compared to input width (4-to-2). Then does the term "encoder" encompasses the meaning that input is shrunk to smaller outputs? or any "symbols"? I am a little bit confusing because of the other en/decoder such as 8B/10B, 64B/66B schemes. \$\endgroup\$ – JaeHyuk Lee Jan 29 '18 at 9:44
  • \$\begingroup\$ It may be very dumb though, then can we say the encoder that translates the 2 width binary to 4 width one-hot as a 2-to-4 encoder? \$\endgroup\$ – JaeHyuk Lee Jan 29 '18 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.