1

Assuming I have a register reg [15:0] my_reg, which contains a 16-bit signed sample:

How can I find the place where the first bit change is located? Meaning, that if assuming that my_reg = 16'b0001011011010111, how can I know that the first change from 0 to 1 is at my_reg [12]? Same for numbers starting with 1,negative numbers, e.g. my_reg = 16'b1111011011010111 would be interested in the position of the first appearing 0 (which is 11 in this case).

The ultimate goal (to add a little bit of context) is to implement a digital FPGA built-in automatic gain control (AGC).

2
  • 1
    When you say "(which is 5 in this case)", do you mean bit number 11? Commented Jun 11, 2014 at 17:11
  • @Ari : yes, sorry I got that mixed up. The change would be at my_reg[11], thus place 11 (as you pointed out) Commented Jun 12, 2014 at 7:26

3 Answers 3

4

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

Sign up to request clarification or add additional context in comments.

4 Comments

Pretty good for a first answer. I converted it from SystemVerilog to Verilog to match with the question's requirements.
@Greg : thanks for the answer! One question: shouldn't the foor-loop be reversed (meaning for(i=0;i<=width-1;i++))? In your implementation I would get the smallest index where there is a bit change. Or am I seeing something wrong?
@titus.andronicus, The answer came from Guy. And yes, you want to reverse to loop. I updated the answer
Sorry, I assumed by first you mean the lsb. Yes if you want the first msb change you need to reverse the loop.
2

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.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.