Forum Discussion
Quartus 20.1.1 SE Crashes on Elaboration of Dual Port RAM VHDL Template
- 5 years ago
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 isfunction 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;
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
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;