Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verilog access specific bits

I have problem in accessing 32 most significant and 32 least significant bits in Verilog. I have written the following code but I get the error "Illegal part-select expression" The point here is that I don't have access to a 64 bit register. Could you please help.

`MLT: begin
  if (multState==0) begin
    {C,Res}<={A*B}[31:0];
    multState=1;
  end
  else
  begin
    {C,Res}<={A*B}[63:32];
    multState=2;  
  end
like image 717
farzin Avatar asked May 09 '13 18:05

farzin


People also ask

How do I select a part in Verilog?

A range of contiguous bits can be selected and is known as a part-select. There are two types of part-selects, one with a constant part-select and another with an indexed part-select. Having a variable part-select allows it to be used effectively in loops to select parts of the vector.

Can we use bit in Verilog?

Integer and Real Types Verilog's variable types are four-state: each bit is 0,1,X or Z. SystemVerilog introduces new two-state data types, where each bit is 0 or 1 only. You would use these when you do not need X and Z values, for example in test benches and as for-loop variables.

What is $bits in Verilog?

$bits. The $bits() system function returns the number of bits required to hold an expression as a bit stream. In the example below it is used to get the bitstream size of a struct and an array. One big advantage of the $bits() function is that it can be used as an elaboration time constant.


1 Answers

Unfortunately the bit-select and part-select features of Verilog are part of expression operands. They are not Verilog operators (see Sec. 5.2.1 of the Verilog 2005 Std. Document, IEEE Std 1364-2005) and can therefore not be applied to arbitrary expressions but only directly to registers or wires.

There are various ways to do what you want but I would recommend using a temporary 64 bit variable:

wire [31:0] A, B;
reg  [63:0] tmp;
reg  [31:0] ab_lsb, ab_msb;

always @(posedge clk) begin
  tmp = A*B;
  ab_lsb <= tmp[31:0];
  ab_msb <= tmp[63:32];
end

(The assignments to ab_lsb and ab_msb could be conditional. Otherwise a simple "{ab_msb, ab_lsb} <= A*B;" would do the trick as well of course.)

Note that I'm using a blocking assignment to assign 'tmp' as I need the value in the following two lines. This also means that it is unsafe to access 'tmp' from outside this always block.

Also note that the concatenation hack {A*B} is not needed here, as A*B is assigned to a 64 bit register. This also fits the recommendation in Sec 5.4.1 of IEEE Std 1364-2005:

Multiplication may be performed without losing any overflow bits by assigning the result to something wide enough to hold it.

However, you said: "The point here is that I don't have access to a 64 bit register".

So I will describe a solution that does not use any Verilog 64 bit registers. This will however not have any impact on the resulting hardware. It will only look different in the Verilog code.

The idea is to access the MSB bits by shifting the result of A*B. The following naive version of this will not work:

ab_msb <= (A*B) >> 32;  // Don't do this -- it won't work!

The reason why this does not work is that the width of A*B is determined by the left hand side of the assignment, which is 32 bits. Therefore the result of A*B will only contain the lower 32 bits of the results.

One way of making the bit width of an operation self-determined is by using the concatenation operator:

ab_msb <= {A*B} >> 32;  // Don't do this -- it still won't work!

Now the result width of the multiplication is determined using the max. width of its operands. Unfortunately both operands are 32 bit and therefore we still have a 32 bit multiplication. So we need to extend one operand to be 64 bit, e.g. by appending zeros (I assume unsigned operands):

ab_msb <= {{32'd0, A}*B} >> 32;

Accessing the lsb bits is easy as this is the default behavior anyways:

ab_lsb <= A*B;

So we end up with the following alternative code:

wire [31:0] A, B;
reg  [31:0] ab_lsb, ab_msb;

always @(posedge clk) begin
  ab_lsb <= A*B;
  ab_msb <= {{32'd0, A}*B} >> 32;
end

Xilinx XST 14.2 generates the same RTL netlist for both versions. I strongly recommend the first version as it is much easier to read and understand. If only 'ab_lsb' or 'ab_msb' is used, the synthesis tool will automatically discard the unused bits of 'tmp'. So there is really no difference.

If this is not the information you where looking for you should probably clarify why and how you "don't have access to 64 bit registers". After all, you try to access the bits [63:32] of a 64 bit value in your code as well. As you can't calculate the upper 32 bits of the product A*B without also performing almost all calculations required for the lower 32 bits, you might be asking for something that is not possible.

like image 117
CliffordVienna Avatar answered Sep 28 '22 14:09

CliffordVienna