Author Topic: Or-ing std_logic_vector of dynamic sizes  (Read 2684 times)

0 Members and 1 Guest are viewing this topic.

Offline polarKaungTopic starter

  • Contributor
  • Posts: 24
  • Country: mm
Or-ing std_logic_vector of dynamic sizes
« on: November 29, 2021, 06:34:01 am »
Hello, a question.

How do I "or" two std_logic_vector of different sizes? Is that even possible?

for example:
signal a : std_logic_vector(7 downto 0);
signal b : std_logic_vector(7 downto 0);
signal c : std_logic_vector(7 downto 0);

c <= a or b(index downto 0); -- where index is within 7 and 0 and comes from somewhere in the design) ^-^
 

Offline Daixiwen

  • Frequent Contributor
  • **
  • Posts: 367
  • Country: no
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #1 on: November 29, 2021, 02:38:14 pm »
What exactly are you trying to do? Do I understand correctly that your c and a vectors are still 8 bits wide, but that you want to combine a with only a variable number of least significant bits in b?
The or operator itself requires the two vectors to be of the same size. You can build an "extended" version of b always 8 bits wide, in which only the least significant bits that you want are copied from b, and the other most significant bits just set to 0. Then combine this vector with a to build c:
Code: [Select]
b_ext <= (index downto 0 => b(index downto 0), others => '0');
c <= a or b_ext;
This code should work in a simulator, but some synthesizers won't like the variable length. In that case you will need to create a for loop instead and just operate on each bit individually. Something like that (not tested/compiled)
Code: [Select]
or_operation: for i in 7 downto 0 generate
  if i <= index then
    c(i) <= a(i) or b(i);
  else
    c(i) <= a(i);
  end if;
end generate;
Alternatively if you can make your vectors of the signed or unsigned type instead of std_logic_vector, there is a resize() function that you can use directly.
 
The following users thanked this post: nctnico, polarKaung

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9935
  • Country: us
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #2 on: November 29, 2021, 05:03:48 pm »
I don't like the clever solutions because I can't convince myself that they will actually work.  I would spend a lot of time looking at the RTL Schematic to understand what was generated.

Instead, I would generate all 8 conceivable vectors and use a MUX to select the version I want.  Maybe a 'conditional assignment' would provide clarity.

https://www.ics.uci.edu/~jmoorkan/vhdlref/cond_s_a.html
 

Offline polarKaungTopic starter

  • Contributor
  • Posts: 24
  • Country: mm
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #3 on: November 29, 2021, 05:19:44 pm »
What exactly are you trying to do? Do I understand correctly that your c and a vectors are still 8 bits wide, but that you want to combine a with only a variable number of least significant bits in b?

yes the c and a vectors will still be 8 bits wide.

what i want is like
lets say index = 5
then
c <= a or "00" & b(index downto 0);

if index = 2
then
c <= a or "00000" & b(index downto 0);
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15328
  • Country: fr
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #4 on: November 29, 2021, 05:36:35 pm »
Various ways of doing this of course.

Apart from what Daixiwen suggested, here is one of them guaranteed to synthesize and not overly convoluted:

Code: [Select]
c(c'high downto index + 1) <= a(a'high downto index + 1);
c(index downto 0) <= a(index downto 0) or b(index downto 0);


 
The following users thanked this post: Bassman59

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9935
  • Country: us
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #5 on: November 29, 2021, 06:21:40 pm »
Various ways of doing this of course.

Apart from what Daixiwen suggested, here is one of them guaranteed to synthesize and not overly convoluted:

Code: [Select]
c(c'high downto index + 1) <= a(a'high downto index + 1);
c(index downto 0) <= a(index downto 0) or b(index downto 0);

If 'index' changes dynamically, what hardware does this instantiate?  I haven't tried such a thing where index changes during execution.  It will clearly work if index is a constant defined somewhere but I'm having trouble visualizing the logic that would be generated if index is dynamic.  I have the same mental fade over the 'for' 'generate' approach posted previously.

I can see where the 'for' 'generate' approach could be used to create the 8 possible patterns but it's my understanding that the 'for' 'generate' is unrolled during synthesis, not execution.  Maybe I missed something...

Will the 'index + 1' phrases bring along 8 bit adders?  Will the synthesizer pull out common subexpressions and eliminate one of them?  Should select <= index + 1; be defined elsewhere and used as the index instead of the index + 1 approach?

How is this simpler than just defining all 8 possible patterns and using a MUX selecting by index?

« Last Edit: November 29, 2021, 06:33:04 pm by rstofer »
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15328
  • Country: fr
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #6 on: November 29, 2021, 10:02:42 pm »
Dynamic indexing is synthesizable and not the problem here. But sorry, I was still a bit too fast, and my answer is not synthesizable indeed. Not because of dynamic indexing per se (this is routinely used), but for the fact that *slices* in VHDL are not synthesizable (at least usually?) if their *length* is not a constant. So for instance, (index downto index - 1) *is* synthesizable, but (index downto 0) *is not*.

In any case, except when indexing can be inferred as 'memory', it often gets synthesized as a MUX anyway. It's just a lot more convenient than expressing MUXes by hand.

But, as just said and as Daixiwen said too actually - overlooked it - slices of *non-constant length* are usually not synthesizable. So you can discard my proposal above. (But it would work in simulation.)

Now using some boolean arithmetic and a small amount of memory, here is a synthesizable (this time!) version, that is generic and (IMHO, YMMV) elegant. I'd be curious to have it compared with other approaches using various synthesis tools, but it's likely to be more efficient than using a MUX to select the portion of the OR'ed result according to index. Feel free to experiment though.

(Of course, if you don't care about genericity, you can discard my MakeMaskArray function and initialize the Masks array constant with a fixed initializer, but for just a few more lines, it makes things generic and avoids the hassle of typing all those masks by hand.)

Code: [Select]
subtype Data_t is std_logic_vector((DataBitWidth - 1) downto 0);
type DataArray_t is array(natural range <>) of Data_t;

function MakeMaskArray(n : natural) return DataArray_t is
variable MaskArray : DataArray_t(0 to (n - 1));
begin
for i in 0 to n - 1 loop
MaskArray(i) := std_logic_vector(to_unsigned(2**(i + 1) - 1, MaskArray(i)'length));
end loop;

return MaskArray;
end MakeMaskArray;

constant Masks : DataArray_t(0 to (DataBitWidth - 1)) := MakeMaskArray(DataBitWidth);

...
begin
...

c <= a or (b and Masks(index));
« Last Edit: November 29, 2021, 10:09:49 pm by SiliconWizard »
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9935
  • Country: us
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #7 on: November 29, 2021, 11:20:53 pm »
I like that solution!  I would just initialize the array but the 'for' loop approach is more elegant.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27935
  • Country: nl
    • NCT Developments
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #8 on: November 30, 2021, 12:03:39 am »
IMHO the solution from Daixiwen with the for-generate is nicer (clean and to the point) and likely is synthesized as a set of muxes anyway.
« Last Edit: November 30, 2021, 12:05:30 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #9 on: November 30, 2021, 10:27:06 am »
.
« Last Edit: August 19, 2022, 05:57:31 pm by emece67 »
 
The following users thanked this post: polarKaung

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27935
  • Country: nl
    • NCT Developments
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #10 on: December 01, 2021, 04:19:53 pm »
This is just the intermediate synthesis result. Look at it after it has been optimised and placed. And then do seperate runs to optimise for size and then for speed.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #11 on: December 01, 2021, 04:52:39 pm »
.
« Last Edit: August 19, 2022, 04:48:18 pm by emece67 »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3246
  • Country: ca
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #12 on: December 01, 2021, 04:53:08 pm »
If 'index' changes dynamically, what hardware does this instantiate?

On FPGA the combinatorial logic typically instantiates as LUTs.

You have 8 outputs (8 bits of c). Each output, to be calculated needs the following inputs:

- 3 bits of idx
- 1 bit from a
- 1 bit from b

Thus you need 8 5-input LUTs.

If you have 6-input LUTs, then 8 LUTs it is.

If you have 4-input LUTs, then it will be slightly more than 8 LUTs.

It's very likely that no matter how you write it, the result will be exactly the same. This is because it's small enough for the tools to figure everything out.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3246
  • Country: ca
Re: Or-ing std_logic_vector of dynamic sizes
« Reply #13 on: December 01, 2021, 05:29:36 pm »
Also, there may be some local optimizations.

For example, bit 4 of the result doesn't depend on two lower bits of idx, so the tools will only need a 3-input LUT for this bits.

Similarly, bits 2 and 6 do not depend on the lower bit of idx, so the tools will use 4-input LUTs for these bits.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf