Author Topic: Concatenating vectors in VHDL  (Read 6423 times)

0 Members and 1 Guest are viewing this topic.

Offline KilrahTopic starter

  • Supporter
  • ****
  • Posts: 1852
  • Country: ch
Concatenating vectors in VHDL
« on: July 25, 2016, 10:41:25 am »
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: [Select]
entity periph_btn is
    Port ( 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: [Select]
architecture Behavioral of periph_btn is
begin

  data_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: [Select]
architecture Behavioral of periph_btn is

signal data_s   : STD_LOGIC_VECTOR (7 downto 0);
signal zeroes_s : STD_LOGIC_VECTOR (3 downto 0);

begin

  zeroes_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.
« Last Edit: July 25, 2016, 10:52:26 am by Kilrah »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Concatenating vectors in VHDL
« Reply #1 on: July 25, 2016, 10:59:45 am »
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: [Select]
architecture Behavioral of periph_btn is
begin
  data_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.
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline KilrahTopic starter

  • Supporter
  • ****
  • Posts: 1852
  • Country: ch
Re: Concatenating vectors in VHDL
« Reply #2 on: July 25, 2016, 11:26:26 am »
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....

OK, good to know...

Code: [Select]
architecture Behavioral of periph_btn is
begin
  data_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;

I tried something like that as well - but then those MSBs are always 'Z' when I'd rather have them at '0'...

However... for best results, NEVER use tristate logic within the internals of a design.
OK, 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.
« Last Edit: July 25, 2016, 11:28:51 am by Kilrah »
 

Offline KilrahTopic starter

  • Supporter
  • ****
  • Posts: 1852
  • Country: ch
Re: Concatenating vectors in VHDL
« Reply #3 on: July 25, 2016, 11:55:57 am »
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  :-//).
« Last Edit: July 25, 2016, 11:57:50 am by Kilrah »
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 26751
  • Country: nl
    • NCT Developments
Re: Concatenating vectors in VHDL
« Reply #4 on: July 25, 2016, 01:03:09 pm »
Doesn't U stand for uninitialised in VHDL? Perhaps initial values or reset logic are missing.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline KilrahTopic starter

  • Supporter
  • ****
  • Posts: 1852
  • Country: ch
Re: Concatenating vectors in VHDL
« Reply #5 on: July 25, 2016, 01:08:04 pm »
Yep, but that part is purely combinatorial and defined, that's the whole reason for the confusion  :-\
 

Offline exmadscientist

  • Frequent Contributor
  • **
  • Posts: 338
  • Country: us
  • Technically A Professional
Re: Concatenating vectors in VHDL
« Reply #6 on: July 25, 2016, 03:50:56 pm »
Personally I'd write it a bit more explicitly:

Code: [Select]
data_o <= (others => '0');
if (n_rd_i = '0') and (sel_i = '1') then
data_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.
 

Offline KilrahTopic starter

  • Supporter
  • ****
  • Posts: 1852
  • Country: ch
Re: Concatenating vectors in VHDL
« Reply #7 on: July 25, 2016, 05:23:58 pm »
OK:

Code: [Select]
  process (btns_i) is
  begin
    data_o <= (others => '0');
    if (n_rd_i = '0') and (sel_i = '1') then
      data_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...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf