Concatenating vectors in VHDL - Page 1
Forum section: electronics / general

author: Kilrah
author_rank: Unknown
timestamp: July 25, 2016, 10:41:25 am
content: I'm having trouble with something that seems as simple as it gets, alas even after reading about and trying many possible solutions I'm not getting success.I have a simple entity:Code:entity periph_btn isPort ( sel_i : in STD_LOGIC;n_rd_i : in STD_LOGIC;data_o : out STD_LOGIC_VECTOR (7 downto 0);btns_i : in STD_LOGIC_VECTOR (3 downto 0));end periph_btn;The intended behavior is just as simple:Code:architecture Behavioral of periph_btn isbegindata_o <= btns_i when n_rd_i = '0' and sel_i = '1' else (others => 'Z');end Behavioral;Now obviously as btns_i is only 4 bits and data_o is 8, something's missing. Question, how to define that the 4 MSB of data_o should be '0'?Several of the solutions online worked perfectly as expected in a simple behavioral simulation, but when I run a post-implementation simulation (Vivado) those bits always show up as state 'U'An example of what I've tried that gives this result, using the & operator:Code:architecture Behavioral of periph_btn issignal data_s : STD_LOGIC_VECTOR (7 downto 0);signal zeroes_s : STD_LOGIC_VECTOR (3 downto 0);beginzeroes_s <= (others => '0');data_s <= zeroes_s & btns_i;data_o <= data_s when n_rd_i = '0' and sel_i = '1' else (others => 'Z');end Behavioral;Both behavioral and post-implementation simulation of the system this is a component of are posted below. The behavioral simulation looks exactly as expected, but on the post-implementation one the last line that is of concern is getting 0xZA instead of 0x0A. As a result, data1_i of the component that receives this signal (Mux, data1_i) sees 0xUA.In the end the top level signal's behavior (AD) is as desired, so maybe it's normal for the internal signals to do some mess and that can be ignored, it looks like implementation also simplifies some signals when they're not being looked at...Note that the design could be simplified and the problem would disappear - but I'd rather learn something while I'm there.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 25, 2016, 10:59:45 am
content: I've had some unexpected weirdness with Vivado when it comes to assigning different length vectors to each other. Simulation and implementation have mismatches. I've never got down to the bottom of it....Code:architecture Behavioral of periph_btn isbegindata_o(7 downto 4) <= (others => 'Z');data_o(3 downto 0) <= btns_i when n_rd_i = '0' and sel_i = '1' else (others => 'Z');end Behavioral;However... for best results, NEVER use tristate logic within the internals of a design. Experience has taught me that it never ends good.To avoid grief tristates logic on the edge of the FPGA design, and I do it explicitly with a tristate buffer, which has a data_in, data_out, and tristate signals).If more than one component needs to output from the FPGA, the tristate is an OR of all the component signals, and the data signal can be either a MUX of the driving components, based on which component is active, or an OR if you can ensure that components driving the bus generate 0s when not selected.

author: Kilrah
author_rank: Unknown
timestamp: July 25, 2016, 11:26:26 am
content: Quote from: hamster_nz on July 25, 2016, 10:59:45 amOK, good to know...Quote from: hamster_nz on July 25, 2016, 10:59:45 amI tried something like that as well - but then those MSBs are always 'Z' when I'd rather have them at '0'...Quote from: hamster_nz on July 25, 2016, 10:59:45 amOK, I was kinda wondering about that, figured it might not be the best thing to do but decided on having the internal 'Z' states mostly for clarity - i.e. 0xZZ makes it obvious that the source is inactive unlike just having it spit out 0x00 which could as well be unwanted data. I'll throw them out, replace them with 0s and just look at the right place. Saves some LEs as well.

author: Kilrah
author_rank: Unknown
timestamp: July 25, 2016, 11:55:57 am
content: OK, I've done the few simplifications I was thinking of, gotten rid of the internal Zs, and also removed that component entirely as it could now be easily replaced by basic built-in Vivado elements (concatenator / constant).Behavioral simulation is still as expected, and post-implementation one still has those U's. Since they now come from built-in primitives I'll consider they're a fluke of the tool / not important, not me screwing up.Didn't do the manual tristate buffer instanciation because I believe that it's something the tool should get right with everything it recognises automatically and want to verify it... but I'll keep it in mind if it screws up. It did recognise my clock and require me to locate it properly on a clock-capable IO even if nothing was specifying it as such, I still don't really know how (nothing explicitly specifies a clock in my VHDL files, and if it was looking at the process sensitivity lists it could just as well have picked up the reset signal as well).

author: nctnico
author_rank: Super Contributor
timestamp: July 25, 2016, 01:03:09 pm
content: Doesn't U stand for uninitialised in VHDL? Perhaps initial values or reset logic are missing.

author: Kilrah
author_rank: Unknown
timestamp: July 25, 2016, 01:08:04 pm
content: Yep, but that part is purely combinatorial and defined, that's the whole reason for the confusion

author: exmadscientist
author_rank: Frequent Contributor
timestamp: July 25, 2016, 03:50:56 pm
content: Personally I'd write it a bit more explicitly:Code:data_o <= (others => '0');if (n_rd_i = '0') and (sel_i = '1') thendata_o(btns_i'range) <= btns_i;end if;(Note: code typed in on a mobile device, not tested, may set Vivado on fire, &c, &c.)That will unconditionally zero the outputs, then set only the appropriate number of low-order bits to their new values.Sometimes VHDL is annoying, but I still think it's better than Verilog.

author: Kilrah
author_rank: Unknown
timestamp: July 25, 2016, 05:23:58 pm
content: OK:Code:process (btns_i) isbegindata_o <= (others => '0');if (n_rd_i = '0') and (sel_i = '1') thendata_o(btns_i'range) <= btns_i;end if;end process;That produces the same result, with the difference that the upper bits are dumped already at the synth stage. With the previous attempt there were actual LUTs tying them to 0, if they were optimized that was apparently later...