Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16556 Discussions

Quartus 20.1.1 SE Crashes on Elaboration of Dual Port RAM VHDL Template

Dagobah
Novice
658 Views

Problem Details
Error:
Internal Error: Sub-system: VRFX, File: /quartus/synth/vrfx/verific/vhdl/vhdlvalue_elab.cpp, Line: 6821
w_ref_type_a != VHDL_RAM_REF_VARIABLE_WORD_VARIABLE_BYTE
Stack Trace:
0x12411d: vrfx_altera_assert(bool, char const*, int, char const*) + 0x1d (synth_vrfx)
0x2d40b4: VhdlArrayConstraint::CreateDualPortValue(std::string&, std::string&, VhdlIdDef*) const + 0x818 (synth_vrfx)
0x29c54e: VhdlDeclaration::CreateStaticValues(VhdlConstraint*, VhdlDataFlow*) + 0x314 (synth_vrfx)
0x299212: VhdlVariableDecl::RecursiveElaborate(VhdlDataFlow*) + 0xe6 (synth_vrfx)
0x298e21: VhdlDeclaration::Elaborate(VhdlDataFlow*) + 0x47 (synth_vrfx)
0x2bc1a5: VhdlArchitectureBody::Elaborate(VhdlBlockConfiguration*) + 0xbf (synth_vrfx)
0x2bcc67: VhdlEntityDecl::CoreElaborate(VhdlSecondaryUnit*, char const*, VhdlBlockConfiguration*) + 0x463 (synth_vrfx)
0x2c23c9: VhdlEntityDecl::Elaborate(char const*, Array*, Map*, VhdlBlockConfiguration*) + 0x403 (synth_vrfx)
0x146283: VRFX_VERIFIC_VHDL_ELABORATOR::elaborate(BASEX_ELABORATE_INFO*) + 0x1df (synth_vrfx)
0x13b4e9: VRFX_ELABORATOR::elaborate(BASEX_ELABORATE_INFO*) + 0xb9 (synth_vrfx)
0x17947e: SGN_FN_LIB::elaborate(BASEX_ELAB_INFO_CORE*) const + 0x18e (synth_sgn)
0x1818ee: SGN_FN_LIB::start_vrf_flow() const + 0xe (synth_sgn)
0x18251d: SGN_FN_LIB::start(SGN_WRAPPER_INFO*) + 0xb6d (synth_sgn)
0x186f49: SGN_EXTRACTOR::single_module_extraction(HDB_INSTANCE_NAME*, HDB_ENTITY*, SGN_WRAPPER_INFO*) const + 0x119 (synth_sgn)
0x18f6a1: SGN_EXTRACTOR::recursive_extraction(HDB_INSTANCE_NAME*, SGN_WRAPPER_INFO*, char const*) + 0xf1 (synth_sgn)
0x19b990: SGN_EXTRACTOR::extract() + 0x2b0 (synth_sgn)
0x1a6200: sgn_qic_full(CMP_FACADE*, std::vector<std::string, std::allocator<std::string> >&, std::vector<double, std::allocator<double> >&) + 0x250 (synth_sgn)
0x19773: qsyn_execute_sgn(CMP_FACADE*, std::vector<std::string, std::allocator<std::string> >&, std::string const&, THR_NAMED_PIPE*, THR_NAMED_PIPE*) + 0x173 (quartus_map)
0x34a09: QSYN_FRAMEWORK::execute_core(THR_NAMED_PIPE*, THR_NAMED_PIPE*) + 0x219 (quartus_map)
0x3771f: QSYN_FRAMEWORK::execute() + 0x8af (quartus_map)
0x1b026: qexe_standard_main(QEXE_FRAMEWORK*, QEXE_OPTION_DEFINITION const**, int, char const**) + 0x6a7 (comp_qexe)
0x2b821: qsyn_main(int, char const**) + 0x151 (quartus_map)
0x3ee30: msg_main_thread(void*) + 0x10 (ccl_msg)
0x5acc: thr_final_wrapper + 0xc (ccl_thr)
0x3eeef: msg_thread_wrapper(void* (*)(void*), void*) + 0x62 (ccl_msg)
0x9f9c: mem_thread_wrapper(void* (*)(void*), void*) + 0x5c (ccl_mem)
0x8b39: err_thread_wrapper(void* (*)(void*), void*) + 0x27 (ccl_err)
0x5b0f: thr_thread_wrapper + 0x15 (ccl_thr)
0x40ea1: msg_exe_main(int, char const**, int (*)(int, char const**)) + 0xb2 (ccl_msg)
0x237b3: __libc_start_main + 0xf3 (c.so.6)


End-trace


Executable: quartus_map
Comment:
Quartus Synthesis and Mapping crashes while elaborating Intel Design Template File for Dual Port Ram.
One VHDL input file is required to reproduce problem with the following contents:
-- Quartus Prime VHDL Template
--
-- True Dual-Port RAM with single clock and different data width on the two ports
--
-- The first datawidth and the widths of the addresses are specified
-- The second data width is equal to DATA_WIDTH1 * RATIO, where RATIO = (1 << (ADDRESS_WIDTH1 - ADDRESS_WIDTH2)
-- RATIO must have value that is supported by the memory blocks in your target
-- device. Otherwise, no RAM will be inferred.
--
-- Read-during-write behavior returns old data for all combinations of read and
-- write on both ports
--
-- This style of RAM cannot be used on certain devices, e.g. Stratix V; in that case use the template for Dual-Port RAM with new data on read-during write on the same port

library ieee;
use ieee.std_logic_1164.all;

entity mixed_width_true_dual_port_ram is
generic (
DATA_WIDTH1 : natural := 8;
ADDRESS_WIDTH1 : natural := 10;
ADDRESS_WIDTH2 : natural := 8);
port (
we1 : in std_logic;
we2 : in std_logic;
clk1 : in std_logic;
clk2 : in std_logic;
addr1 : in natural range 0 to (2 ** ADDRESS_WIDTH1 - 1);
addr2 : in natural range 0 to (2 ** ADDRESS_WIDTH2 - 1);
data_in1 : in std_logic_vector(DATA_WIDTH1 - 1 downto 0);
data_in2 : in std_logic_vector(DATA_WIDTH1 * (2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2)) - 1 downto 0);
data_out1 : out std_logic_vector(DATA_WIDTH1 - 1 downto 0);
data_out2 : out std_logic_vector(DATA_WIDTH1 * 2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2) - 1 downto 0));
end entity mixed_width_true_dual_port_ram;

architecture rtl of mixed_width_true_dual_port_ram is
constant RATIO : natural := 2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2);
constant DATA_WIDTH2 : natural := DATA_WIDTH1 * RATIO;
constant RAM_DEPTH : natural := 2 ** ADDRESS_WIDTH2;

-- Use a multidimensional array to model mixed-width
type word_t is array(RATIO - 1 downto 0) of std_logic_vector(DATA_WIDTH1 - 1 downto 0);
type ram_t is array (0 to RAM_DEPTH - 1) of word_t;

-- declare the RAM
shared variable ram : ram_t;
signal w1_local : word_t;
signal q1_local : word_t;

begin -- rtl
-- Re-organize the write data to match the RAM word type
unpack: for i in 0 to RATIO - 1 generate
w1_local(i) <= data_in2(DATA_WIDTH1*(i+1) - 1 downto DATA_WIDTH1*i);
data_out2(DATA_WIDTH1*(i+1) - 1 downto DATA_WIDTH1*i) <= q1_local(i);
end generate unpack;

-- port B
process(clk1)
begin
if (rising_edge(clk1)) then
data_out1 <= ram(addr1 / RATIO)(addr1 mod RATIO);
if (we1 ='1') then
ram(addr1 / RATIO)(addr1 mod RATIO) := data_in1;
end if;
end if;
end process;

--port A
process(clk2)
begin
if (rising_edge(clk2)) then
if (we2 = '1') then
ram(addr2) := w1_local;
end if;
q1_local <= ram(addr2);
end if;
end process;
end rtl;


System Information
Platform: linux64
OS name: CentOS Linux
OS version:

Quartus Prime Information
Address bits: 64
Version: 20.1.1
Build: 720
Edition: Standard Edition

0 Kudos
1 Solution
Dagobah
Novice
617 Views

Provided is a work around solution to prevent Quartus from crashing during elaboration of Mixed Width Dual Port RAM with STD_LOGIC_VECTOR instead of NATURAL that includes dual clocks.  RAM capacity and port widths are specified in bits.  An assertion is provided for simulation.   The required log base 2 utility function and package is also posted.  Thanks KennyT_Intel for the tip on why Quartus crashes so that a work around solution could be found and posted.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.utils.log2c;

entity ram_dptrue is
generic (
    ram_bits: natural;
    dq1_bits: natural range 1 to 128;
    dq2_bits: natural range 1 to 128);
port (
    clk1 : in std_logic;
    clk2 : in std_logic;

    addr1 : in std_logic_vector(log2c(ram_bits/dq1_bits)-1 downto 0);
    wren1 : in std_logic;
    d1 : in std_logic_vector(dq1_bits-1 downto 0);
    q1 : out std_logic_vector(dq1_bits-1 downto 0);

    addr2 : in std_logic_vector(log2c(ram_bits/dq2_bits)-1 downto 0);
    wren2 : in std_logic;
    d2 : in std_logic_vector(dq2_bits-1 downto 0);
    q2 : out std_logic_vector(dq2_bits-1 downto 0));
end entity ram_dptrue;

architecture behavioural of ram_dptrue is
    -- Build up 2D array to hold the memory
    constant ram_depth : natural := ram_bits/dq1_bits;
    constant ram_ratio : natural := dq1_bits/dq2_bits;

    type word_t is array(ram_ratio-1 downto 0) of std_logic_vector(dq2_bits-1 downto 0);
    type ram_t is array(0 to ram_depth-1) of word_t;

    shared variable ram : ram_t;
    signal d_local : word_t;
    signal q_local : word_t;

begin
    assert (ram_ratio > 0) and (2**log2c(ram_ratio) = ram_ratio)
    report "port size requires power of two ratio and dq1 >= dq2"
    severity failure;

    -- Reorganize the read data from the RAM to match the output
    unpack: for i in 0 to ram_ratio-1 generate
        d_local(i) <= d1(dq2_bits*(i+1)-1 downto dq2_bits*i);
        q1(dq2_bits*(i+1)-1 downto dq2_bits*i) <= q_local(i);
    end generate unpack;

    port1: process(clk1)
    begin
        if (rising_edge(clk1)) then
            if (wren1 = '1') then
                ram(to_integer(unsigned(addr1))) := d_local;
                -- Read during write returns NEW data
                q_local <= d_local;
            else
                -- Read only
                q_local <= ram(to_integer(unsigned(addr1)));
            end if;
        end if;
    end process;

    port2: process(clk2)
    begin
        if (rising_edge(clk2)) then
            if (wren2 = '1') then
                ram(to_integer(unsigned(addr2)) / ram_ratio)(to_integer(unsigned(addr2)) mod ram_ratio) := d2;
                -- Read during write returns NEW data
                q2 <= d2;
            else
                -- Read only
                q2 <= ram(to_integer(unsigned(addr2)) / ram_ratio)(to_integer(unsigned(addr2)) mod ram_ratio);
            end if;
        end if;
    end process;

end architecture behavioural;


-- Package Declaration
package utils is

    -- Functions
    function log2c(n: integer) return integer;

end package utils;

-- Package Body
package body utils is

    function log2c(n: integer) return integer is
        variable m, p: integer;
    begin
        m := 0;
        p := 1;
        while p < n loop
            m := m + 1;
            p := p * 2;
        end loop;
        return m;
    end log2c;

end package body utils;

View solution in original post

0 Kudos
3 Replies
Dagobah
Novice
627 Views

Yes, the posted link seems to be related to the problem and I am working on a VHDL work around to adhere to the RAM port width limitations of the tools.  However, I am now getting a different Fatal error with Segment Violation and would like to know if this is also a known issue with suggested method to fix or explanation for the crash:

Problem Details
Error:

*** Fatal Error: Segment Violation at 0x4b
Module: quartus_map
Stack Trace:
0x13ca17: CDB_SGATE_OTERM::adopt_fanouts(CDB_SGATE_OTERM*, bool) + 0x7 (db_cdb_sgate)
0x51032: OPT_RAM_CANDIDATE::create_bypass_logic(bool, bool) + 0x2e2 (synth_infer)
0x51e7e: OPT_RAM_CANDIDATE::do_non_tdp_conversion() + 0xce (synth_infer)
0x52aed: OPT_RAM_CANDIDATE::convert_to_megafunction() + 0x9d (synth_infer)
0x32106: opt_convert_candidates(std::vector<OPT_RAM_BLOCK_CANDIDATE*, std::allocator<OPT_RAM_BLOCK_CANDIDATE*> >&) + 0x76 (synth_infer)
0x19f6b9: RTL_SCRIPT::call_ram_rom_fns(char const*, char const*, char const*) + 0x459 (synth_opt)
0x19c67c: RTL_SCRIPT::call_named_function(char const*, char const*, char const*, int, int, int) + 0xaec (synth_opt)
0x19b2c7: RTL_SCRIPT::process_script(CDB_SGATE_NETLIST*, CDB_SGATE_HIERARCHY*, BASEX_ELABORATE_INFO*, CMP_FACADE*, RTL_SCRIPT_ENUM, char const* (*) [3], int, RTL_SCRIPT_STEP*, RTL_SCRIPT_STEP*) + 0x7c7 (synth_opt)
0x1ae3b1: opt_process_netlist_scripted(CMP_FACADE*, CDB_SGATE_HIERARCHY*, BASEX_ELABORATE_INFO*, RTL_SCRIPT_ENUM, bool) + 0x3c1 (synth_opt)
0x1af33c: RTL_ROOT::process_sgate_netlist(CMP_FACADE*, CDB_SGATE_HIERARCHY*, BASEX_ELABORATE_INFO*, RTL_PASS_ENUM) + 0x34c (synth_opt)
0x17ede7: SGN_SYNTHESIS::high_level_synthesis() + 0x1b7 (synth_sgn)
0x17fcc0: SGN_SYNTHESIS::process_current_stage() + 0x140 (synth_sgn)
0x191408: SGN_EXTRACTOR::synthesize_partition(unsigned long) + 0x378 (synth_sgn)
0x191ddc: SGN_EXTRACTOR::synthesis() + 0x1ec (synth_sgn)
0x1a58d4: SGN_EXTRACTOR::synthesis_and_post_processing() + 0x64 (synth_sgn)
0x1a65a0: sgn_qic_full(CMP_FACADE*, std::vector<std::string, std::allocator<std::string> >&, std::vector<double, std::allocator<double> >&) + 0x5f0 (synth_sgn)
0x19773: qsyn_execute_sgn(CMP_FACADE*, std::vector<std::string, std::allocator<std::string> >&, std::string const&, THR_NAMED_PIPE*, THR_NAMED_PIPE*) + 0x173 (quartus_map)
0x34a09: QSYN_FRAMEWORK::execute_core(THR_NAMED_PIPE*, THR_NAMED_PIPE*) + 0x219 (quartus_map)
0x3771f: QSYN_FRAMEWORK::execute() + 0x8af (quartus_map)
0x1b026: qexe_standard_main(QEXE_FRAMEWORK*, QEXE_OPTION_DEFINITION const**, int, char const**) + 0x6a7 (comp_qexe)
0x2b821: qsyn_main(int, char const**) + 0x151 (quartus_map)
0x3ee30: msg_main_thread(void*) + 0x10 (ccl_msg)
0x5acc: thr_final_wrapper + 0xc (ccl_thr)
0x3eeef: msg_thread_wrapper(void* (*)(void*), void*) + 0x62 (ccl_msg)
0x9f9c: mem_thread_wrapper(void* (*)(void*), void*) + 0x5c (ccl_mem)
0x8b39: err_thread_wrapper(void* (*)(void*), void*) + 0x27 (ccl_err)
0x5b0f: thr_thread_wrapper + 0x15 (ccl_thr)
0x40ea1: msg_exe_main(int, char const**, int (*)(int, char const**)) + 0xb2 (ccl_msg)
0x23493: __libc_start_main + 0xf3 (c.so.6)


End-trace


Executable: quartus_map
Comment:
None

System Information
Platform: linux64
OS name: CentOS Stream
OS version:

Quartus Prime Information
Address bits: 64
Version: 20.1.1
Build: 720
Edition: Standard Edition

0 Kudos
Dagobah
Novice
618 Views

Provided is a work around solution to prevent Quartus from crashing during elaboration of Mixed Width Dual Port RAM with STD_LOGIC_VECTOR instead of NATURAL that includes dual clocks.  RAM capacity and port widths are specified in bits.  An assertion is provided for simulation.   The required log base 2 utility function and package is also posted.  Thanks KennyT_Intel for the tip on why Quartus crashes so that a work around solution could be found and posted.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.utils.log2c;

entity ram_dptrue is
generic (
    ram_bits: natural;
    dq1_bits: natural range 1 to 128;
    dq2_bits: natural range 1 to 128);
port (
    clk1 : in std_logic;
    clk2 : in std_logic;

    addr1 : in std_logic_vector(log2c(ram_bits/dq1_bits)-1 downto 0);
    wren1 : in std_logic;
    d1 : in std_logic_vector(dq1_bits-1 downto 0);
    q1 : out std_logic_vector(dq1_bits-1 downto 0);

    addr2 : in std_logic_vector(log2c(ram_bits/dq2_bits)-1 downto 0);
    wren2 : in std_logic;
    d2 : in std_logic_vector(dq2_bits-1 downto 0);
    q2 : out std_logic_vector(dq2_bits-1 downto 0));
end entity ram_dptrue;

architecture behavioural of ram_dptrue is
    -- Build up 2D array to hold the memory
    constant ram_depth : natural := ram_bits/dq1_bits;
    constant ram_ratio : natural := dq1_bits/dq2_bits;

    type word_t is array(ram_ratio-1 downto 0) of std_logic_vector(dq2_bits-1 downto 0);
    type ram_t is array(0 to ram_depth-1) of word_t;

    shared variable ram : ram_t;
    signal d_local : word_t;
    signal q_local : word_t;

begin
    assert (ram_ratio > 0) and (2**log2c(ram_ratio) = ram_ratio)
    report "port size requires power of two ratio and dq1 >= dq2"
    severity failure;

    -- Reorganize the read data from the RAM to match the output
    unpack: for i in 0 to ram_ratio-1 generate
        d_local(i) <= d1(dq2_bits*(i+1)-1 downto dq2_bits*i);
        q1(dq2_bits*(i+1)-1 downto dq2_bits*i) <= q_local(i);
    end generate unpack;

    port1: process(clk1)
    begin
        if (rising_edge(clk1)) then
            if (wren1 = '1') then
                ram(to_integer(unsigned(addr1))) := d_local;
                -- Read during write returns NEW data
                q_local <= d_local;
            else
                -- Read only
                q_local <= ram(to_integer(unsigned(addr1)));
            end if;
        end if;
    end process;

    port2: process(clk2)
    begin
        if (rising_edge(clk2)) then
            if (wren2 = '1') then
                ram(to_integer(unsigned(addr2)) / ram_ratio)(to_integer(unsigned(addr2)) mod ram_ratio) := d2;
                -- Read during write returns NEW data
                q2 <= d2;
            else
                -- Read only
                q2 <= ram(to_integer(unsigned(addr2)) / ram_ratio)(to_integer(unsigned(addr2)) mod ram_ratio);
            end if;
        end if;
    end process;

end architecture behavioural;


-- Package Declaration
package utils is

    -- Functions
    function log2c(n: integer) return integer;

end package utils;

-- Package Body
package body utils is

    function log2c(n: integer) return integer is
        variable m, p: integer;
    begin
        m := 0;
        p := 1;
        while p < n loop
            m := m + 1;
            p := p * 2;
        end loop;
        return m;
    end log2c;

end package body utils;

0 Kudos
Reply