We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for
Did you mean:
Highlighted
Observer
375 Views
Registered: ‎02-08-2019

## Verilog and "Unions"

Thinking in terms of programming in C, I can use a union to treat the same area of memory two different ways. I'm in the middle of a big project, where I'd like to do the same sort of thing in my FPGA. I have great huge shift register that contains 1600 bits, and somewhere near the middle, there are 64 bits that I'd like to treat as a long integer that I can increment. I know I can split this up into three registers and "verilog" the solution up that way, but that would require maintaining things in three pieces and tieing them together, etc. etc. The whole idea of verilog is to allow one to think more abstractly about hardware design. To that end, is there some way I can do the equivalent of a C union where the specification for loading and shifting my entire 1600 bits can be thought of in terms of a 1600 bit shift register under one name, while I have an alternative view of those 64 bits in the middle where I can refer to them by a different name and increment them, read them, and write them, even though they are simultaneously part of the 1600 bits in the large shift register under a different name?

-gt-

1 Solution

Accepted Solutions
Historian
368 Views
Registered: ‎01-23-2009

## Re: Verilog and "Unions"

So, first of all, you don't need anything like a union to do this. If the bits you want are bits 100 to 163 (just as an example), then you can do your shift register on all 1600 bits, but when you need to do somehing to those 64 bits, just use a part select for them. In any place where you can use a reg, you can use a partselect of a reg; so if your shift register is "reg [1599:0] my_shift", then you can use my_shift[163:100] in any expression or assignment - even

my_shift[163:100] <= my_shift[163:100] + 1'b1;

(in an always block)

However, if you really want to use a union, you will need to switch to SystemVerilog - standard Verilog does not have complex and user defined types, but SystemVerilog (which is completely backward compatible with Verilog) does - including unions.

Avrum

4 Replies
Historian
369 Views
Registered: ‎01-23-2009

## Re: Verilog and "Unions"

So, first of all, you don't need anything like a union to do this. If the bits you want are bits 100 to 163 (just as an example), then you can do your shift register on all 1600 bits, but when you need to do somehing to those 64 bits, just use a part select for them. In any place where you can use a reg, you can use a partselect of a reg; so if your shift register is "reg [1599:0] my_shift", then you can use my_shift[163:100] in any expression or assignment - even

my_shift[163:100] <= my_shift[163:100] + 1'b1;

(in an always block)

However, if you really want to use a union, you will need to switch to SystemVerilog - standard Verilog does not have complex and user defined types, but SystemVerilog (which is completely backward compatible with Verilog) does - including unions.

Avrum

Observer
286 Views
Registered: ‎02-08-2019

## Re: Verilog and "Unions"

Thanks for the response. Your solution brings about a new related question. Is verilog smart enough to handle and arbitrary arrangement of indices, or just a small "in-order" slice? In other words, lets say in the same project, I might want to increment the thing as a little-endian number, and other times as a big-endian number. Now I realize that "endian-ness" is an artifact of particular CPU architectures and we need not concern ourselves with it when working with FPGA's but on the other hand if you're pumping data in and out it may be a requirement to keep a particular organization. So if I have a 64 bit integer defined as myint[63:0] then I assume verilog interprets myint<=muyint+1 to be applied with bit 0 as the LSb and bit 63 as the MSb. But because I plan on pumping myint out of the FPGA into a computer, and because sometimes it will be a big-endian number and other times it will be a little-endian number, I might want to do the following SOMETIMES instead of myint<=myint+1 (which I may still wish to do at other times):

myint[63:56]<=myint[63:56]+1;

if(myint[63])

begin

myint[55:48]<=myint[55:48]+1;

if(myint[47 ...

you get the idea ... a bigendian increment.

So my question then becomes, is verilog able to do something like, say the short solution below (arbitrarily ordered indicies) instead of the long solution above:

myint[7:0,15:8,23:16,...63:56]<=myint[7:0,15:8,23:16,...63:56] + 1;

-gt-

Historian
279 Views
Registered: ‎01-23-2009

## Re: Verilog and "Unions"

In Verilog, "a bit is a bit" - it doesn't matter how a bit vector (really called a bus) is put together, a bit vector is the same as a number (this is not the same as in VHDL).

So if you want a 32 bit reg (I will use 32 instead of 64), you can define it as

reg [31:0] a0;
reg [0:31] a1;
reg [44:13] a2;

All of these are registers that can hold32 bit numbers, and can be used as 32 bit numbers in expressions. In each case, the least significant bit is always the rightmost bit - all that we are changing is the "name" of the bits. So the least significant bits of these numbers are a0[0], a1[31], and a2[13].

You can get any part select of a bus by simply using its names - so to get the least significant byte of these busses you would use

a0[7:0]
a1[24:31]
a2[20:13]

You can also do concatenation using the concatenation operator. The expression

{a0,a1} creates a 64 bit number which is the concatenation of a0 with a1 - effectively a0<<32 + a1

Putting these together, you can create a number with a concatenation of bits from the same bus in a different order

{a0[7:0],a0[15:8],a0[23:16],a0[31:23]}

This too is a 32 bit number.

Any expression can be used as a sub-expression, so

{a0[7:0],a0[15:8],a0[23:16],a0[31:23]} + 1'b1

Is the 32 bit number created above with one added to it.

The only operator you can do on the left hand side of an assignment operation is the concatenation operator - it is actually the reverse concatenation when used this way. So, to complete what you want, you can do

{a0[7:0],a0[15:8],a0[23:16],a0[31:23]}  <= {a0[7:0],a0[15:8],a0[23:16],a0[31:23]} + 1'b1;

This being said, you will never properly learn the language and its capabilities by asking questions on the forum. If you want to learn it, there are many textbooks on Verilog out there (and, no, I don't have a particular recommendation).

Avrum

Observer
271 Views
Registered: ‎02-08-2019