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).