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).
Best Answer
Now that we have a testcase, ghdl reports:
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...
so you have a workaround, but it would be nice to get the aggregate working...
Relevant : (from the VHDL-2008 LRM)
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 forunsigned
, and theunsigned
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.