Leading zero encoders can be made with a nice balanced tree structure.
First, encode bits 2 by 2 :
- 00 => 10 : 2 leading zeros
- 01 => 01 : 1 leading zero
- 10 => 00 : 0 leading zero
- 11 => 00 : 0 leading zero
Then, assemble as pairs.
- If both sides start with 1xxx, the result is 10...0
- If the left side start with 0 the result is 0[left]
- If the left side starts with 1, the result is 01[right(msb-1:0)]
You only need multiplexers.
For example the 8 bits value : 00000111
- 2 by 2 : 00 00 01 11
- encoded : 10 10 01 00
- assemble : 100 001
- assemble : 0101 = 5 leading zeros.
In VHDL (I have no Verilog code at hand), you get that :
FUNCTION enc(CONSTANT a : unsigned(1 DOWNTO 0)) RETURN unsigned IS
BEGIN
CASE a IS
WHEN "00" => RETURN "10";
WHEN "01" => RETURN "01";
WHEN "10" => RETURN "00";
WHEN OTHERS => RETURN "00";
END CASE;
END FUNCTION enc;
FUNCTION clzi(
CONSTANT n : IN natural;
CONSTANT i : IN unsigned) RETURN unsigned IS
VARIABLE v : unsigned(i'length-1 DOWNTO 0):=i;
BEGIN
IF v(n-1+n)='0' THEN
RETURN (v(n-1+n) AND v(n-1)) & '0' & v(2*n-2 DOWNTO n);
ELSE
RETURN (v(n-1+n) AND v(n-1)) & NOT v(n-1) & v(n-2 DOWNTO 0);
END IF;
END FUNCTION clzi;
FUNCTION clz64 (CONSTANT v : unsigned(0 TO 63)) RETURN unsigned IS
VARIABLE e : unsigned(0 TO 63); -- 64
VARIABLE a : unsigned(0 TO 16*3-1); -- 48
VARIABLE b : unsigned(0 TO 8*4-1); -- 32
VARIABLE c : unsigned(0 TO 4*5-1); -- 20
VARIABLE d : unsigned(0 TO 2*6-1); -- 12
BEGIN
FOR i IN 0 TO 31 LOOP e(i*2 TO i*2+1):=enc(v(i*2 TO i*2+1)); END LOOP;
FOR i IN 0 TO 15 LOOP a(i*3 TO i*3+2):=clzi(2,e(i*4 TO i*4+3)); END LOOP;
FOR i IN 0 TO 7 LOOP b(i*4 TO i*4+3):=clzi(3,a(i*6 TO i*6+5)); END LOOP;
FOR i IN 0 TO 3 LOOP c(i*5 TO i*5+4):=clzi(4,b(i*8 TO i*8+7)); END LOOP;
FOR i IN 0 TO 1 LOOP d(i*6 TO i*6+5):=clzi(5,c(i*10 TO i*10+9)); END LOOP;
RETURN clzi(6,d(0 TO 11));
END FUNCTION clz64;
enc()
does the encoding
clzi()
merges two vectors.
clz64()
is a sample implementation for a 64bits input.
Your question says "a particular state", but it sounds like you want out[7:0]
to stay in each of its states for x clock cycles. If so, then you want to use temp[9:0]
as a "prescaler" — for every x clocks, you want to send one pulse to the out
counter. This works for any value of x.
For every clock cycle, check to see whether temp
equals x-1. If so, set temp
to zero and increment out
; otherwise, just increment temp
.
In Verilog:
always @(posedge clock) begin
if (temp >= (x-1)) begin
temp <= O;
count <= count + 1;
end else begin
temp <= temp + 1;
end
end
OK, now that the you have clarified the meaning of x, the following DDS code will implement what you want directly.
always @(posedge clock) begin
temp <= (temp & 10'h1FF) + x;
if (temp[9]) count <= count + 1;
end
If x=1, count
will only increment once every 512 clocks. If x=512, count
will increment on every clock. If x=40, count
will increment every 12.8 clocks on average.
In the general case of having two numbers, where the counting rate is x/y (x must be no greater than y), think about what the code above is actually doing with respect to the value y=512:
- What does the expression
temp & 10'h1FF
actually accomplish numerically?
- Similarly, what does looking at bit 9 being set mean numerically?
Best Answer
To implement rounding, you'll need an incrementer (add 1) for the round-up case.
Let's assume the rounding behavior you want is as follows:
The Verilog would look something like this:
The sharp-eyed among you will see that the increment select can be simplified as:
And you can suppress the wraparound case with one more trick, giving:
I'm sure there's other ways to code this, but they will all include at least the adder and the overflow range check to prevent wrap (that is, saturation.)