Forum Discussion

Dagobah's avatar
Dagobah
Icon for New Contributor rankNew Contributor
5 years ago
Solved

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

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...
  • Dagobah's avatar
    Dagobah
    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 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;