Verilog bit change location

非 Y 不嫁゛ 提交于 2019-12-01 14:07:12
Guy

Same technique as described above but parametrized. Use XOR shifted by one bit to determine where bits change, then use a descending priority encoder to output the first change location. I stuffed with my_reg[0] so the first bit doesn't create a delta.

localparam width=16;

reg  [width-1:0] my_reg;
wire [width:0] delta;
reg  [$clog2(width)-1:0] index; // Note: $clog2 was added in IEEE1364-2005
integer i;

assign delta = my_reg ^ { my_reg, my_reg[0] };

always @* begin
  index = 0;
  for (i=0; i<width; i=i+1)
    if (delta[i])
      index = i;
end

Above code on EDA playground (thanks for heads up on this, BTW) http://www.edaplayground.com/x/3uP

A two-liner solution for this is the following:

my_reg1_diff = (my_reg1 ^ (my_reg1 << 1))>>1 ;
my_reg1_diff_pos = $floor($ln(my_reg1_diff)/$ln(2));    //log2 of (my_reg1_diff)

See a working example on edaplayground.com.

It is similar to the idea described in starbox's answer. You can model a synthesizable log2 function using a look-up table or case statement. See edaplayground.com for a sample.

What you need is a leading signs detector.

You can do this by performing an XOR of the 16-bit my_reg variable, then a case statement that will count the number of repeating bits, then you need to add one to this number.

For example:

if we have a four bit register, we can count the number of leading bits. You can modify this code for your purposes depending on how you want to handle what happens if all the bits are identical.

wire [3:0] my_reg;
wire [2:0] xor_bits;
reg [2:0] count;

// XOR bits
assign xor_bits = {my_reg[3] ^ my_reg[2], my_reg[2] ^ my_reg[1], my_reg[1] ^ my_reg[0];

always @ (*) begin
case (xor_bits)
000: change_location= 4;
00X: change_location= 3;
0XX: change_location= 2;
default: change_location= 1;
endcase

end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!