Priority encoder in verilog - verilog

I am somewhat new to verilog, I tried running this code but it gives me an error:
module enc(in,out);
input [7:0] in;
output [3:0] out;
reg i;
reg [3:0] out;
always #*
begin
for (i=0;i<7;i=i+1)
begin
if ((in[i]==1) && (in[7:i+1]==0))
out = i;
else
out = 0;
end
end
endmodule
I think it complains about in[7:i+1] but i don't understand why ?
Can someone please advise..
EDIT
ok so I am reluctant to using the X due to their numerous problems.. I was thinking of modifying the code to something like this :
module enc(in,out);
input [7:0] in;
output [2:0] out;
reg i;
reg [2:0] out,temp;
always #*
begin
temp = 0;
for (i=0;i<8;i=i+1)
begin
if (in[i]==1)
temp = i;
end
out = temp;
end
endmodule
Do you think that will do the trick ? I currently don't have access to a simulator..

A priority encoder mean giving priority to a one bit if two or more bits meet the criteria. Looking at your code, it appears you wanted to give priority to a LSB while using a up counter. out is assigned in every look, so even if your could compile, the final result would be 6 or 0.
For an LSB priority encoder, first start with a default value for out and use a down counter:
module enc (
input wire [7:0] in,
output reg [2:0] out
);
integer i;
always #* begin
out = 0; // default value if 'in' is all 0's
for (i=7; i>=0; i=i-1)
if (in[i]) out = i;
end
endmodule

If you are only interested in simulation than your linear loop approach should be fine, something like
out = 0;
for (i = W - 1; i > 0; i = i - 1) begin
if (in[i] && !out)
out = i;
end
If you also care about performance, the question becomes more interesting. I once experimented with different approaches to writing parameterized priority encoders here. It turned out that Synopsys can generate efficient implementation even from the brain-dead loop above but other toolchains needed explicit generate magic. Here is an excerpt from the link:
output [WIDTH_LOG - 1:0] msb;
wire [WIDTH_LOG*WIDTH - 1:0] ors;
assign ors[WIDTH_LOG*WIDTH - 1:(WIDTH_LOG - 1)*WIDTH] = x;
genvar w, i;
integer j;
generate
for (w = WIDTH_LOG - 1; w >= 0; w = w - 1) begin
assign msb[w] = |ors[w*WIDTH + 2*(1 << w) - 1:w*WIDTH + (1 << w)];
if (w > 0) begin
assign ors[(w - 1)*WIDTH + (1 << w) - 1:(w - 1)*WIDTH] = msb[w] ? ors[w*WIDTH + 2*(1 << w) - 1:w*WIDTH + (1 << w)] : ors[w*WIDTH + (1 << w) - 1:w*WIDTH];
end
end
endgenerate

So my Edited solution worked... how silly !! I forgot to declare reg [2:0] i; and instead wrote reg i;
Thanks everybody

Hunks, I have to tell you, all your solutions are either too complex or non-synthesizable, or implement into slow multiplexors. Alexej Bolshakov at OpenCores uploaded an outstandin' parametrizable encoder on Aug 23, 2015, based on OR elements. No muxes, 100% synthesizable. His code (with my tiny formatting):
module encoder #(
parameter LINES = 16,
parameter WIDTH = $clog2(LINES)
)(
input [LINES-1:0] unitary_in,
output wor [WIDTH-1:0] binary_out
);
genvar i, j;
generate
for (i = 0; i < LINES; i = i + 1)
begin: loop_i
for (j = 0; j < WIDTH; j = j + 1)
begin: loop_j
if (i[j])
assign binary_out[j] = unitary_in[i];
end
end
endgenerate
endmodule
RTL viewer screenshot, Model-Sim screenshot

This solution divides the input into four blocks and checks for the first nonzero block. This block is further subdivided in the same way. It is reasonably efficient.
// find position of most significant 1 bit in 64 bits input
// (system verilog)
module bitscan(
input logic [63:0] in, // number input
output logic [5:0] out, // bit position output
output logic zeroout // indicates if input is zero
);
logic [63:0] m0; // intermediates
logic [15:0] m1;
logic [3:0] m2;
logic [5:0] r;
always_comb begin
m0 = in;
// choose between four 16-bit blocks
if (|m0[63:48]) begin
m1 = m0[63:48];
r[5:4] = 3;
end else if (|m0[47:32]) begin
m1 = m0[47:32];
r[5:4] = 2;
end else if (|m0[31:16]) begin
m1 = m0[31:16];
r[5:4] = 1;
end else begin
m1 = m0[15:0];
r[5:4] = 0;
end
// choose between four 4-bit blocks
if (|m1[15:12]) begin
m2 = m1[15:12];
r[3:2] = 3;
end else if (|m0[11:8]) begin
m2 = m1[11:8];
r[3:2] = 2;
end else if (|m0[7:4]) begin
m2 = m1[7:4];
r[3:2] = 1;
end else begin
m2 = m1[3:0];
r[3:2] = 0;
end
// choose between four remaining bits
if (m2[3]) r[1:0] = 3;
else if (m2[2]) r[1:0] = 2;
else if (m2[1]) r[1:0] = 1;
else r[1:0] = 0;
out = r;
zeroout = ~|m2;
end
endmodule
Here is another solution that uses slightly less resourcess:
module bitscan4 (
input logic [63:0] in,
output logic [5:0] out,
output logic zout
);
logic [63:0] m0;
logic [3:0] m1;
logic [3:0] m2;
logic [5:0] r;
always_comb begin
r = 0;
m0 = in;
if (|m0[63:48]) begin
r[5:4] = 3;
m1[3] = |m0[63:60];
m1[2] = |m0[59:56];
m1[1] = |m0[55:53];
m1[0] = |m0[51:48];
end else if (|m0[47:32]) begin
r[5:4] = 2;
m1[3] = |m0[47:44];
m1[2] = |m0[43:40];
m1[1] = |m0[39:36];
m1[0] = |m0[35:32];
end else if (|m0[31:16]) begin
r[5:4] = 1;
m1[3] = |m0[31:28];
m1[2] = |m0[27:24];
m1[1] = |m0[23:20];
m1[0] = |m0[19:16];
end else begin
r[5:4] = 0;
m1[3] = |m0[15:12];
m1[2] = |m0[11:8];
m1[1] = |m0[7:4];
m1[0] = |m0[3:0];
end
if (m1[3]) begin
r[3:2] = 3;
end else if (m1[2]) begin
r[3:2] = 2;
end else if (m1[1]) begin
r[3:2] = 1;
end else begin
r[3:2] = 0;
end
m2 = m0[{r[5:2],2'b0}+: 4];
if (m2[3]) r[1:0] = 3;
else if (m2[2]) r[1:0] = 2;
else if (m2[1]) r[1:0] = 1;
else r[1:0] = 0;
zout = ~|m2;
out = r;
end
endmodule

To be able to use variable indexes in part-slice suffixes, you must enclose the for block into a generate block, like this:
gen var i;
generate
for (i=0;i<7;i=i+1) begin :gen_slices
always #* begin
... do whatever with in[7:i+1]
end
end
The problem is that apllying this to your module, the way it's written, leads to other errors. Your rewritten module would look like this (be warned: this won't work either)
module enc (
input wire [7:0] in,
output reg [2:0] out // I believe you wanted this to be 3 bits width, not 4.
);
genvar i; //a generate block needs a genvar
generate
for (i=0;i<7;i=i+1) begin :gen_block
always #* begin
if (in[i]==1'b1 && in[7:i+1]=='b0) // now this IS allowed :)
out = i;
else
out = 3'b0;
end
end
endgenerate
endmodule
This will throw a synthesis error about out being driven from more than one source. This means that the value assigned to out comes from several sources at the same time, and that is not allowed.
This is because the for block unrolls to something like this:
always #* begin
if (in[0]==1'b1 && in[7:1]=='b0)
out = 0;
else
out = 3'b0;
end
always #* begin
if (in[1]==1'b1 && in[7:2]=='b0)
out = 1;
else
out = 3'b0;
end
always #* begin
if (in[2]==1'b1 && in[7:3]=='b0)
out = 2;
else
out = 3'b0;
end
.... and so on...
So now you have multiple combinational block (always #*) trying to set a value to out. All of them will work at the same time, and all of them will try to put a specific value to out whether the if block evaluates as true or false. Recall that the condition of each if statement is mutually exclusive with respect of the other if conditions (i.e. only one if must evaluate to true).
So a quick and dirty way to avoid this multisource situation (I'm sure there are more elegant ways to solve this) is to let out to be high impedance if the if block is not going to assign it a value. Something like this:
module enc (
input wire [7:0] in,
output reg [2:0] out // I believe you wanted this to be 3 bits width, not 4.
);
genvar i; //a generate block needs a genvar
generate
for (i=0;i<7;i=i+1) begin :gen_block
always #* begin
if (in[i]==1'b1 && in[7:i+1]=='b0) // now this IS allowed :)
out = i;
else
out = 3'bZZZ;
end
end
endgenerate
always #* begin
if (in[7]) // you missed the case in which in[7] is high
out = 3'd7;
else
out = 3'bZZZ;
end
endmodule
On the other way, if you just need a priority encoder and your design uses fixed and small widths for inputs and outputs, you may write your encoder as this:
module enc (
input wire [7:0] in,
output reg [2:0] out
);
always #* begin
casex (in)
8'b1xxxxxxx : out = 3'd7;
8'b01xxxxxx : out = 3'd6;
8'b001xxxxx : out = 3'd5;
8'b0001xxxx : out = 3'd4;
8'b00001xxx : out = 3'd3;
8'b000001xx : out = 3'd2;
8'b0000001x : out = 3'd1;
8'b00000001 : out = 3'd0;
default : out = 3'd0;
endcase
end
endmodule
(although there seems to be reasons to not to use casex in a design. Read the comment #Tim posted about it in this other question: How can I assign a "don't care" value to an output in a combinational module in Verilog )
In conclusion: I'm afraid that I have not a bullet-proof design for your requirements (if we take into account the contents of the paper Tim linked in his comment), but at least, you know now why i was unallowed inside a part-slice suffix.
On the other way, you can have half of the work done by studying this code I gave as an answer to another SO question. In this case, the module works like a priority encoder, parametrized and without casex statements, only the output is not binary, but one-hot encoded.
How to parameterize a case statement with don't cares?

out = in&(~(in-1))
gives you the one-hot results(FROM LSB->MSB where the first 1 at)

Related

System Verilog Loops

Im currently working on the Shift-Add Algorithm (32x32 bit Multiplication) in System Verilog. System Verilog cant find any error and my code is working correctly according to GTKwave. When I synthesize my circuit with yosys, Latches will be added. And that is the Problem. I dont want Latches in my Circuit. Heres my Code:
module multiplier(
input logic clk_i,
input logic rst_i,
input logic start_i,
input logic [31:0] a_i,
input logic [31:0] b_i,
output logic finished_o,
output logic [63:0] result_o
);
typedef enum logic [1:0] { STATE_A, STATE_B} state_t;
state_t state_p, state_n;
logic [63:0] fin_res;
logic [63:0] tmp;
logic rst_flag;
integer i;
always #(posedge clk_i or posedge rst_i) begin
if (rst_i == 1'b1) begin
state_p <= STATE_B;
end
else begin
state_p <= state_n;
end
end
always #(*)begin
state_n = state_p;
case (state_p)
STATE_A: if (start_i == 0) state_n = STATE_B;
STATE_B: if (start_i == 1) state_n = STATE_A;
default: state_n = state_p;
endcase
end
always #(*) begin
case (state_p)
STATE_A: begin
rst_flag = 1;
fin_res = 0;
finished_o = 0;
tmp = 0;
for (i = 0; i < 32; i = i + 1) begin
if (a_i[i] == 1'b1) begin
tmp = b_i;
tmp = tmp << i;
fin_res = fin_res + tmp;
end
end
end
STATE_B: begin
result_o = fin_res;
if (rst_flag == 1) finished_o = 1;
if (start_i == 1) finished_o = 0;
end
default: begin
finished_o = 0;
result_o = 0;
end
endcase
end
endmodule
After spending 2 days only with debugging and not finding any mistake I would like to ask if u could help me. I am assigning every output (at least I think so). So where is my mistake? Is it the for loop? But what would be wrong with it? Thanks in advance for your help :)
Some useful Information for the Code-Snippet: start_i is the starting signal. If this is set to 1 the multiplication should be started. finished_o is the finish flag. If this is set to 1 the CPU will know that the computation is completed. a_i and b_i are the inputs which should be multiplied. result_o is the result of the multiplication which can be read when finished_o is set to 1.
According to yosys i get the following latches:
64 DLATCH_N
64 DLATCH_P
I think something may be wrong with fin_res in the for loop cause that logic variable is exactly 64 bits long as are the Latches
From the comment you have a bunch of variables which are not assigned in the second case statement causing synthesis to generate latches. To avoid it you need to assign all the vars in all branches of the case statement and conditional statements recursively.
However, if there is a default value you can assign to all of them, you can use a pattern similar to the one from the second always block, just assigning default values before the 'case' statement. This way you do not even need the default clause and you can get rid of it in the second always block as well.
always #(*) begin
// set default values
rst_flag = 0;
fin_res = 0;
finished_o = 0;
tmp = 0;
result_o = 0;
case (state_p)
STATE_A: begin
rst_flag = 1;
for (i = 0; i < 32; i = i + 1) begin
if (a_i[i] == 1'b1) begin
tmp = b_i;
tmp = tmp << i;
fin_res = fin_res + tmp;
end
end
end
STATE_B: begin
result_o = fin_res;
// are you sure that you do not need a latch here?
if (rst_flag == 1) finished_o = 1;
if (start_i == 1) finished_o = 0;
end
// you do not need 'default' here.
endcase
end
My fixes will cause combinational behavior and should get rid of latches in synthesis, but it does not look like they will behave as you expected. It looks like you really need a latches here.
rst_flag must be a latch. You set it in STATE_A and use it in STATE_B. It has to keep the value between states. This is a latch behavior.
In STATE_B you change finished_o only if some of conditions met. What happens if the rst_flag and start_i are both 0. do you want finished_o to be 0 or the previous value? In the latter case you need a latch.
How about fin_res ? What do you want to do with it in other states? keep previous value (latch) or have a default value (no latch).
...

How to assign variable pins to a port in verilog?

I have a 32-bit input port pins and a 32-bit input enable pin_en, and want to generate a 16-bit output selected by the enables. I wrote verilog like this, but seems there are some errors.
How can I fix it or any other way to achive? Thanks!
ps: No more than 16 pins selected by en, but maybe less.
input [31:0] pins;
input [31:0] pin_en;
output [15:0] actual_pins;
generate
genvar i;
localparam cnt = 0;
for(i = 0; (i < 'd32) & (cnt < 'd16); i = i + 'd1) begin : b1
if(pin_en[i]) begin
assign actual_pins[i] = pins[cnt];
cnt = cnt + 'd1;
end
end
if(cnt < 16)
assign actual_pins[16 : cnt] = 'b0;
endgenerate
I think that there are several errors in you code:
in generate blocks you cannot do any generation, based on the actual values of variables. The blocks are for the constant expressions only which could be resolved at compilation time, not at the run time. Also, you cannot modify anything in the generated blocks besides genvars. Paremeters (localparams) cannot be modified, so the cnt = cnt + 1 is just illegal there.
you messed up actual_pins and pins. by logic there should be actual_pins[cnt];
you use binary & operator, but you should have used logical && instead.
So, all your code should have been implemented in a run-time constructs, i.e., always blocks. You also need a trigger which will cause the always block to be evaluated. I created a small example where the always block is to be triggered by a clock.
module top (
input clk,
input [31:0] pins,
input [31:0] pin_en,
output reg [15:0] actual_pins
);
always #(posedge clk) begin
int cnt = 0;
int i;
for(i = 0; (i < 'd32) && (cnt < 'd16); i = i + 'd1) begin
if(pin_en[i]) begin
actual_pins[cnt] = pins[i];
cnt = cnt + 'd1;
end
end
for(; cnt < 16; cnt = cnt + 1)
actual_pins[j] = 1'b0;
end
endmodule

How to create bit ranges with terms defined as logic

I understand the following code will not compile, but is there something similar that compiles?
logic [7:0] complete_set, partial_set;
logic [2:0] msb_bit, lsb_bit;
always_comb complete_set = <driven by a logic equation>;
always_comb msb_bit = <driven by a logic equation>;
always_comb lsb_bit = <driven by a logic equation>;
always_comb partial_set[msb_bit:lsb_bit] = complete_set[msb_bit:lsb_bit];
You could do some bitwise decisions like this. I just assumed you would want to set the other bits to zero, but you could also set it to don't cares (1'bx).
for(i = 0; i < 8; i = i + 1) begin
partial_set[i] = (i < lsb_bit) || (i > msb_bit) ? 1'b0 : complete_set[i];
end
Assuming you want the unspecified bits to be 0, you can do this in one line:
always_comb partial_set = complete_set & (2**(msb_bit+1-lsb_bit)-1)<<lsb_bit;
But I think a for loop would be much easer for someone else to understand
always_comb begin
partial_set = '0; // or whatever the unspecified bits should be
for(int ii = lsb_bit; ii <= msb_bit; ii++)
partial_set[ii] = complete_set[ii]
end

Parameterizing a casex statement in verilog

Consider the following function which I would like to parameterize. I have created some parameters to set a width of the input and a corresponding width parameter for the output.
parameter SELECT_WIDTH = 6;
parameter PRIENC_WIDTH = $clog2(SELECT_WIDTH+1);
function [PRIENC_WIDTH-1:0] prienc6;
input [SELECT_WIDTH-1:0] select;
reg [PRIENC_WIDTH-1:0] out;
begin
casex(select)
6'b000001: out = 3'b101; // Is it possible to parameterize the case statement with generate
6'b00001x: out = 3'b100;
6'b0001xx: out = 3'b011;
6'b001xxx: out = 3'b010;
6'b01xxxx: out = 3'b001;
6'b1xxxxx: out = 3'b000;
endcase
prienc6 = out ;
end
end function
Obviously, the casex statement cases will not expand as written.
So I tried the following, which didn't compile correctly indicating unexpected generate found.
function [PRIENC_WIDTH-1:0] prienc_n;
input [SELECT_WIDTH-1:0] select;
reg [PRIENC_WIDTH-1:0] out;
begin
genvar gv_j;
casex(select)
for (gv_j = 0; gv_j < SELECT_WIDTH; gv_j = gv_j + 1)
begin
{{(SELECT_WIDTH-1)-gv_j{1'b0}},1'b1,{gv_j{1'bx}}} : out = (SELECT_WIDTH-1)-gv_j;
end
endcase
prienc_n = out ;
end
end function
I have been able to get the correct behavior using parameterized if's, but it seems like I should be able to parameterize that casex statement. Any thoughts on how to do this? I guess what I will try next is to wrap the casex in the generate loop and create 6 casex statements, each with only one state.
Since you tagged this question with SystemVerilog, I'll show you how to do this without a case statement or generate
function logic [PRIENC_WIDTH-1:0] prienc_n(
input [SELECT_WIDTH-1:0] select);
for (int j = 0; j < SELECT_WIDTH; j++) begin
if (select[SELECT_WIDTH-1]) return j;
select <<=1;
end
// if no 1 found
return ('x); // you did not specify this case
endfunction
If you need to stay in Verilog, it will need an intermediate variable
function reg [PRIENC_WIDTH-1:0] prienc_n(
input [SELECT_WIDTH-1:0] select);
reg [PRIENC_WIDTH-1:0] out;
integer j;
begin
out = {PRIENC_WIDTH{1'bx}}; // what should be returned if no 1 found
for (j = 0; j < SELECT_WIDTH; j = j + 1) begin
if (select[SELECT_WIDTH-1]) begin
out = j;
select = 0;
end
select = select << 1;
end
prienc_n = out;
end
endfunction

Verilog not displaying output

I have a homework problem where I'm supposed to create a module for single-precision IEEE-754 floating point multiplication. This is the module:
module prob3(a, b, s);
input [31:0] a, b; // operands
output reg [31:0] s; // sum - Could potentially use wire instead
integer i; // loop variable
reg [8:0] temp;
reg [47:0] intProd; // intermediate product
reg [23:0] tempA;
reg [23:0] tempB;
initial begin
//Initialization
for (i = 0; i < 48; i = i + 1) begin
intProd[i] = 0;
end
//Compute the sign for the result
if (a[31]^b[31] == 0) begin
s[31] = 0;
end
else begin
s[31] = 1;
end
//Compute the exponent for the result
#10 temp = a[30:23] + b[30:23] - 8'b11111111;
//Case for overflow
if(temp > 8'b11111110) begin
s[30:23] = 8'b11111111;
for (i = 0; i < 23; i = i + 1) begin
s[i] = 0;
end
$finish;
end
//Case for underflow
else if (temp < 8'b00000001) begin
for (i = 0; i < 31; i = i + 1) begin
s[i] = 0;
end
$finish;
end
else begin
s[30:23] = temp[7:0];
end
//Mutliply the signficands
//Make implicit one explicit
tempA[23] = 1;
tempB[23] = 1;
//Make operands 24 bits
for(i = 0; i < 23; i = i + 1) begin
tempA[i] = a[i];
tempB[i] = b[i];
end
//Compute product of signficands
intProd = tempA * tempB;
//Check and see if we need to normalize
if(intProd[47:46] >= 2'b10) begin
intProd = intProd >> 1;
temp = s[30:23] + 1'b1;
if(temp > 8'b11111110) begin
s[30:23] = 8'b11111111;
for (i = 0; i < 23; i = i + 1) begin
s[i] = 0;
end
$finish;
end
else
s[30:23] = temp[7:0];
end
s[22:0] = intProd[47:25];
end
endmodule
Here is my testbench:
module prob4;
reg [31:0] a, b;
wire [31:0] s;
// instantiate the floating point multiplier
prob3 f1(a, b, s);
initial begin
assign a = 32'h42055555;
assign b = 32'hBDCCCCCD;
#10 $monitor("s = %h", s);
assign a = 32'hBF555555;
assign b = 32'hCAB71B00;
#10 $monitor("s = %h", s);
a = 32'hFF500000;
b = 32'h7E700000;
#10 $display("s = %b", s);
a = 32'h01700000;
b = 32'h02F00000;
#10 $display("s = %b", s);
a = 32'hBE000000;
b = 32'h455F36DB;
#10 $display("s = %b", s);
a = 32'h3C800000;
b = 32'h3A800000;
#10 $display("s = %b", s);
a = 32'hC797E880;
b = 32'hB7FBA927;
#10 $display("s = %b", s);
end
endmodule
It displays the first value of s, but that is it. I'm honestly not too familiar with Verilog, so any clarification on why this might be happening would be truly appreciated.
The reason you are seeing only a single value for s is because all of your floating point logic (all the stuff in the prob3 module) is inside an initial block. Thus, you only run that code once; it starts at time 0, has a pause for 10 time units and finishes; never to run again. Here are a few tips for implementing the unit (assuming the module is suppose to be synthesizable and not just a functional verification model):
Place your combinational logic in an always #(*) block, not an initial block.
As toolic mentioned, only call $monitor once, and it will inform you whenever s or any other variables given as arguments change; thus you do not need the $display statements either unless you want to know the value of s at that point of execution (whether it changed or not and inline with the processes, so not necessarily the final value either). So typically your testbench main stimulus initial block would have $monitor() as the first line.
Don't call $finish inside your logic; ideally, you should set an error signal instead that the testbench might then choose to call $finish if it sees that error signal asserted.
Don't use assign inside procedural blocks (always, initial, etc), just say a = ... not assign a = ...

Resources