Or-ing std_logic_vector of dynamic sizes - Page 1
Forum section: electronics / general

author: polarKaung
author_rank: Contributor
timestamp: November 29, 2021, 06:34:01 am
content: 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)

author: Daixiwen
author_rank: Frequent Contributor
timestamp: November 29, 2021, 02:38:14 pm
content: 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: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:or_operation: for i in 7 downto 0 generateif i <= index thenc(i) <= a(i) or b(i);elsec(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.

author: rstofer
author_rank: Super Contributor
timestamp: November 29, 2021, 05:03:48 pm
content: 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

author: polarKaung
author_rank: Contributor
timestamp: November 29, 2021, 05:19:44 pm
content: Quote from: Daixiwen on November 29, 2021, 02:38:14 pmyes the c and a vectors will still be 8 bits wide.what i want is likelets say index = 5thenc <= a or "00" & b(index downto 0);if index = 2thenc <= a or "00000" & b(index downto 0);

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 29, 2021, 05:36:35 pm
content: 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: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);

author: rstofer
author_rank: Super Contributor
timestamp: November 29, 2021, 06:21:40 pm
content: Quote from: SiliconWizard on November 29, 2021, 05:36:35 pmIf '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?

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 29, 2021, 10:02:42 pm
content: 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: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 isvariable MaskArray : DataArray_t(0 to (n - 1));beginfor i in 0 to n - 1 loopMaskArray(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));

author: rstofer
author_rank: Super Contributor
timestamp: November 29, 2021, 11:20:53 pm
content: I like that solution! I would just initialize the array but the 'for' loop approach is more elegant.

author: nctnico
author_rank: Super Contributor
timestamp: November 30, 2021, 12:03:39 am
content: 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.

author: emece67
author_rank: Frequent Contributor
timestamp: November 30, 2021, 10:27:06 am
content: .

author: nctnico
author_rank: Super Contributor
timestamp: December 01, 2021, 04:19:53 pm
content: 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.

author: emece67
author_rank: Frequent Contributor
timestamp: December 01, 2021, 04:52:39 pm
content: .

author: NorthGuy
author_rank: Super Contributor
timestamp: December 01, 2021, 04:53:08 pm
content: Quote from: rstofer on November 29, 2021, 06:21:40 pmOn 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 bThus 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.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 01, 2021, 05:29:36 pm
content: 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.