7

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
Morgan
  • 19,934
  • 8
  • 58
  • 84
farzin
  • 91
  • 1
  • 1
  • 2

2 Answers2

11

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.

CliffordVienna
  • 7,995
  • 1
  • 37
  • 57
  • 1
    Note that the outer concatenation in `ab_msb <= {{32'd0, A}*B} >> 32` is not required; the inner one is sufficient to make the multiplication, and down-shift, 64-bit. – EML May 14 '13 at 11:06
0

You are mixing blocking and non-blocking assignments here:

{C,Res}<={A*B}[63:32];  //< non-blocking
multState=2;            //< blocking

this is considered bad practice.

Not sure that a concatenation operation which is just {A*B} is valid. At best it does nothing.

The way you have encoded it looks like you will end up with 2 hardware multipliers. What makes you say you do not have a 64 bit reg, available? reg does not have to imply flip-flops. If you have 2 32bit regs then you could have 1 64 bit one. I would personally do the multiply on 1 line then split the result up and output as 2 32 bit sections.

However :

x <= (a*b)[31:0] is unfortunately not allowed. If x is 32 bits it will take the LSBs, so all you need is :

x <= (a*b)

To take the MSBs you could try:

reg [31:0] throw_away;
{x, throw_away} <= (a*b) ;
Morgan
  • 19,934
  • 8
  • 58
  • 84
  • It's not mixing non-blocking and blocking assignments that's the problem. AIUI the problems come from using blocking assignments to communicate between different blocks of hardware. http://www.sigasi.com/content/verilogs-major-flaw – Martin Thompson May 10 '13 at 11:04
  • @MartinThompson I have looked at that before but not read it in full. All I took away was `For synchronous design, that makes them harmless`, I have never had a problem with this in Verilog although VHDL users do point out on occasion this bug would never have happened in VHDL ;) – Morgan May 10 '13 at 11:58
  • The key bit from my (admittedly non-Verilogger) perspective is that you must *never* use *blocking* assignments for *communication*. Anything else is fine... And VHDL enforces that by not allowing variables (which have blocking semantics) to be accessed outside a process. – Martin Thompson May 10 '13 at 12:12
  • I am a non-VHDLer, I think that make sense though. I think it might be the working practise and how you use the language, working with experienced people you might learn not todo certain things. blocking assignments can be used to make (bad) combinatorial loops. I would only use `=` in combinatorial blocks and `<=` in sequential blocks sticking to this I have not seen any issues for RTL. Testbenches and models on the other hand might need more thought. – Morgan May 10 '13 at 12:29
  • @KrutarthRami sorry I did not get to approve your edit in time before it was rejected. You were correct I had mixed up the labelling of the assignments, good catch. – Morgan Mar 17 '15 at 08:04