# VHDL Aggregate on Left Side of Assignment : Error in Simulator

I'm designing a counter with a combinational carry out (not registered). To do this I have a concurrent assignment to create the unregistered sum with carry by extending the unsigned input before incrementing and assigning the sum to an aggregate of the incremented value and the carry out as shown below. Count_a, the register, is in a clocked process with a simple assignment of nxt_cnt_a.

  Carry_Out_a : out std_logic
...
constant Cntr_Width : positive := 13;
signal Count_a, nxt_cnt_a : unsigned(Cntr_Width - 1 downto 0) := (others => '0');

(Carry_Out_a, nxt_cnt_a) <= RESIZE(Count_a, nxt_cnt_a'length + 1) + 1;


This synthesizes fine and produces exactly the adder with register plus a combinational carry output. But it won't simulate in Active-HDL. It compiles OK, but I get a run time error.

# RUNTIME: Fatal Error: RUNTIME_0046 VHDL_test.vhd (130): Incompatible ranges; left: (0 to 13), right: (0 downto 0).

The resize function should create an unsigned of the right length and the addition operator is supposed to convert the integer to the same width unsigned before adding, giving the correct size result.

So why is a run time message being generated? Is this a bug in the simulator? If the syntax is bad, why would it not be caught when the code is initially analyzed?

Do I need to post the entire design? It's currently 142 lines, but I could pare it down to a couple of dozen. The rest of the design is the same counter written in more verbose manners as test cases. This form is the simplest, so I'd like to get it working.

Here is the full test code. In this one the error is on line 26.

-- Test synthesis of counters and carry out flags
library ieee;
use ieee.NUMERIC_STD.all;
use ieee.std_logic_1164.all;
-- use work.Common.all;

entity VHDL_test is
generic(
CLK_HZ : REAL := 33.554432E6 );
port(
Clk         : in  std_logic := '1';
Cnt_En      : in  std_logic := '1';
Test_Out_a  : out std_logic;
Carry_Out_a : out std_logic
);
end VHDL_test;

architecture TB_ARCH of VHDL_test is
constant Clock_Half_Period : time := 500 ms / CLK_HZ;  -- 14901 ps;
constant Cntr_Width : positive := 13;
constant Cntr_Modulus : positive := 2**Cntr_Width;
signal Count_a, nxt_cnt_a : unsigned(Cntr_Width - 1 downto 0) := (others => '0');
begin
-- Clk_gen: Clk <= not Clk after Clock_Half_Period; -- comment out for synth

(Carry_Out_a, nxt_cnt_a) <= RESIZE(Count_a, nxt_cnt_a'length + 1) + 1; -- error

test_ag: process (Clk) is
begin
if rising_edge(Clk) then
Test_Out_a <= Carry_Out_a;
if (Cnt_En OR not Carry_Out_a) then
Count_a  <= nxt_cnt_a;
end if;
end if;
end process test_ag;

end TB_ARCH;  -- VHDL_test


This error has gotten worse, lol I thought I had a work around, but trying to use this in a useful program it fails with the forms that were working in the test code. The only difference was the test code was assigning the carry bit directly to the output std_logic. So I added a test case to use a signal declared in the entity.

  signal Test : std_logic := '1';

(Test, nxt_cnt_a) <= ("0" & Count_a) - 1; -- works
-- (Carry_Out_a, nxt_cnt_a) <= RESIZE(Count_a, nxt_cnt_a'length + 1) - 1; -- fails
-- (Carry_Out_a, nxt_cnt_a) <= RESIZE(Count_a, nxt_cnt_a'length + 1) - One_uns; -- works
-- (Carry_Out_a, nxt_cnt_a) <= ("0" & Count_a) - 1; -- works


Of course it works in the test code. In my work code I also tried making Test into an unsigned (0 downto 0) which also fails. The error is a bit different now.

# RUNTIME: Fatal Error: RUNTIME_0046 MilliSec.vhd (52): Incompatible ranges; left: (0 to 0), right: (12 downto 0).

• A warm welcome to the site. Minor but noteworthy: it's not a program, it's a design. Programs are set of instructions that run on CPUs. VHDL produces logic circuits, more an evolution of a netlist. – TonyM Oct 19 '20 at 7:09
• Pare it down to a couple of dozen. Nothing jumps out to me as obviously wrong in the coed posted, but there's not enough to compile in any other simulator to crosscheck it, and not enough context, e.g. I HOPE you're using numeric_std not that other one. – user_1818839 Oct 19 '20 at 14:00
• Yes, I'm not a newbie, although that doesn't rule out beginner mistakes. Once I reused some code and forgot to include an extra sync FF on an external input to the UART. I chased that one for weeks because I didn't suspect the FPGA at all. I'll add the code to the main post as formatting here is clumsy. – gnuarm Oct 19 '20 at 15:27
• Re: sync FF. I once debugged one of those in a minute ... with a hairdrier. A literal hairdrier. I don't know if the younger engineers were amused, or appalled! Re: 500 ms / CLK_HZ; -- 14901 ps; I don't know which synth tool you're using, but be aware of this : electronics.stackexchange.com/questions/124264/… and test with an assert/report. – user_1818839 Oct 20 '20 at 12:57
• The clock info is only for simulation of course. I'm not sure what you are cautioning about. Your original post in that thread talks about Synplify and time units which makes no sense because Synplify is a synthesis tool. Maybe the tool names just got mixed up and meant Modelsim which is mentioned earlier in the post. Or maybe I'm not familiar with the tool and Synplify is a simulator as well as synthesis. Your name is familiar. Have I seen you post in the newsgroups? – gnuarm Oct 20 '20 at 16:02

Now that we have a testcase, ghdl reports:

ghdl -a --std=08 VHDL_test.vhd
VHDL_test.vhd:26:17:error: can't match 'nxt_cnt_a' with type std_ulogic
VHDL_test.vhd:26:17:error: target is not a signal name


Which is a little less confused than your simulator, that the error is to do with mixing different types within an aggregate. (but see edit below : this is no longer an error in VHDL-2008 : and is compiled correctly by the current GHDL 1.0-dev build.

Now obviously we can do it by brute force : widening the intermediate signal for example...

  signal Count_a: unsigned(Cntr_Width - 1 downto 0) := (others => '0');
signal nxt_cnt_a : unsigned(Cntr_Width downto 0) := (others => '0');
begin
--(Carry_Out_a, nxt_cnt_a) <= RESIZE(Count_a, nxt_cnt_a'length + 1) + 1;
nxt_cnt_a <= RESIZE(Count_a, nxt_cnt_a'length ) + 1 ;
Carry_Out_a <= nxt_cnt_a(Cntr_Width);

-- in synch process
Count_a  <= nxt_cnt_a(Count_a'range);


so you have a workaround, but it would be nice to get the aggregate working...

Relevant : (from the VHDL-2008 LRM)

9.3.3.3 Array aggregates For an aggregate of a one-dimensional array type, each choice shall specify values of the index type, and the expression of each element association shall be of either the element type or the type of the aggregate. If the type of the expression of an element association is the type of the aggregate, then either the element association shall be positional or the choice shall be a discrete range.

I think we need to make it clear somehow that the aggregate type is unsigned.

EDIT: My reading suggests that this should in fact work: std_ulogic is a valid element type for unsigned, and the unsigned component of the aggregate should define its type.

Xilinx Vivado (2018.2) reproduces the compile error shown by ghdl(above) in VHDL(old) mode. However in VHDL-2008, it successfully compiles, and (making Clk an internal signal) simulates without runtime error.

Which leads me to suspect we are seeing TWO tool bugs:

ghdl - while excellent - does still have some holes in VHDL-2008 support (as has Vivado, which doesn't even support conditionals on std_logic yet) and this does seem to be one of the points where it hasn't caught up with -2008. EDIT : Now resolved : the current build DOES compile this case correctly with no runtime error.

your simulator : while it parses this expression, it doesn't appear to compile it correctly, leading to the runtime error you see. The fact that two other simulators run it happily supports this being a tool bug.

Now we see the value of a simple testcase : I think it is worth making the Clk changes to run standalone, and submitting to Aldec tech support for their review.

• The Original Poster got new errors and has updated the question. – Shashank V M Nov 7 '20 at 5:14
• @ShashankVM I suspect he is seeing a related manifestation of the same tool bug. Neither GHDL (updated) nor Vivado had trouble with his testcase. – user_1818839 Nov 7 '20 at 12:46