UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Scholar richardhead
Scholar
575 Views
Registered: ‎08-01-2012

Its 2018, and Vivado is inferring rams like its 2008

Jump to solution

So, its 2018 (tried in 2017.2 and 2018.2), and Im trying to infer an array of RAMS - Vivado says no to code that would compile in Quartus and infer rams 10 YEARS AGO. I even tried to make it easy for Vivado and gave each ram an individual read and write addresses - no go!

 

Has anyone successfully inferred arrays of rams, or do I have to infer them individually (what an chore!)

 

 

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

entity ram_test is
    port (
      clk   : in std_logic;

      ip    : in  std_logic_vector(31 downto 0);

      sel   : in  natural range 0 to 1;
      op    : out std_logic_vector(31 downto 0)
    );

end entity ram_test;

architecture rtl of ram_test is
    --I initially tried in VHDL2008, same lack of support
    --type slv_array_t is array(natural range <>) of std_logic_vector;

    type ram_t is array(0 to 63) of std_logic_vector( ip'range );
    type ram_array_t is array(0 to 1) of ram_t;

    type slv_array2_t is array(0 to 1) of std_logic_vector(31 downto 0);


    signal ram          : ram_array_t;

    signal ram_rd       : slv_array2_t;

    signal we           : std_logic_vector(0 to 1);
    signal cnt          : unsigned(4 downto 0)  := "00000";

begin

    ram_gen : for i in 0 to 1 generate
        signal waddr    : natural;
        signal raddr    : natural;
    begin
        ram_proc : process(clk)
        begin
          if rising_edge(clk) then
            waddr       <= to_integer(cnt);

              if we(i) = '1' then
                ram(i)(waddr)   <= ip;
              end if;

            raddr  <= to_integer(cnt-1);

          end if;
        end process;

        ram_rd(i)   <= ram(i)(raddr);
    end generate ram_gen;



    op  <= ram_rd(sel);



    cnt_proc : process(clk)
    begin
      if rising_edge(clk) then
        cnt <= cnt + 1;

        we <= std_logic_vector(cnt(1 downto 0));
      end if;
    end process;



end architecture rtl;

If anyone has any ideas why xilinx wont infer the rams - please let me know. Inference works without the generate loop! Can I modify this code to make it work (some subtlety missed)? Have I used the wrong characters on line 27? or is the grass just the wrong shade of green outside?

 

Please Please Please Please raise an enhancement request for this. Another feature where Xilinx is far far far behind the competition.

 

0 Kudos
1 Solution

Accepted Solutions
Scholar richardhead
Scholar
620 Views
Registered: ‎08-01-2012

Re: Its 2018, and Vivado is inferring rams like its 2008

Jump to solution

@dpaul24

Yes, the generate loop is deliberate - I want 2 rams (this is an example)

I found the solution anyway, declare the ram inside the generate loop - this isolates the ram into a self contained code template (and it works with 2008):

 

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

entity ram_test is
    port (
      clk   : in std_logic;

      ip    : in  std_logic_vector(31 downto 0);

      sel   : in  natural range 0 to 1;
      op    : out std_logic_vector(31 downto 0)
    );

end entity ram_test;

architecture rtl of ram_test is

    type slv_array_t is array(natural range <>) of std_logic_vector;

    signal ram_rd       : slv_array_t(0 to 1)(31 downto 0);

    signal we           : std_logic_vector(0 to 1);
    signal cnt          : unsigned(4 downto 0)  := "00000";

    signal waddr    : natural;
    signal raddr    : natural;

begin

    ram_gen : for i in 0 to 1 generate
      signal ram    : slv_array_t(0 to 63)(31 downto 0);
    begin
        ram_proc : process(clk)
        begin
          if rising_edge(clk) then
              if we(i) = '1' then
                ram(waddr)   <= ip;
              end if;
          end if;
        end process;

        ram_rd(i)   <= ram(raddr);
    end generate ram_gen;

    op  <= ram_rd(sel);

    cnt_proc : process(clk)
    begin
      if rising_edge(clk) then
        cnt <= cnt + 1;
        waddr       <= to_integer(cnt);
        raddr  <= to_integer(cnt-1);

        we <= std_logic_vector(cnt(1 downto 0));
      end if;
    end process;



end architecture rtl;
0 Kudos
3 Replies
Scholar dpaul24
Scholar
558 Views
Registered: ‎08-07-2014

Re: Its 2018, and Vivado is inferring rams like its 2008

Jump to solution

@richardhead,

 

I think the generate loop is creating the problem.

 

I am doing something like this:

.
.
type ram_type is array(0 to DEPTH-1) of unsigned(DATA_WIDTH-1 downto 0);

signal ram    : ram_type;   
attribute ram_style : string;
attribute ram_style of ram: signal is "block";
.
.
.
    begin
        if rising_edge(clk_i) then 
            if rst_n_i = '0' then
            .
            . 
            else
            .
                -- WRITE 
                if valid_wr_en_q = '1' then
                    ram(to_integer(internal_wr_addr_q)) <= wr_data_q;
                end if;

                -- READ
                rd_data <= ram(to_integer(internal_rd_addr_q));           
            end if;
 

In any case it is recommended to consult UG901 (v2017.4) December 20, 2017

 

 

 

--------------------------------------------------------------------------------------------------------
FPGA enthusiast!
All PMs will be ignored
--------------------------------------------------------------------------------------------------------
0 Kudos
Scholar richardhead
Scholar
621 Views
Registered: ‎08-01-2012

Re: Its 2018, and Vivado is inferring rams like its 2008

Jump to solution

@dpaul24

Yes, the generate loop is deliberate - I want 2 rams (this is an example)

I found the solution anyway, declare the ram inside the generate loop - this isolates the ram into a self contained code template (and it works with 2008):

 

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

entity ram_test is
    port (
      clk   : in std_logic;

      ip    : in  std_logic_vector(31 downto 0);

      sel   : in  natural range 0 to 1;
      op    : out std_logic_vector(31 downto 0)
    );

end entity ram_test;

architecture rtl of ram_test is

    type slv_array_t is array(natural range <>) of std_logic_vector;

    signal ram_rd       : slv_array_t(0 to 1)(31 downto 0);

    signal we           : std_logic_vector(0 to 1);
    signal cnt          : unsigned(4 downto 0)  := "00000";

    signal waddr    : natural;
    signal raddr    : natural;

begin

    ram_gen : for i in 0 to 1 generate
      signal ram    : slv_array_t(0 to 63)(31 downto 0);
    begin
        ram_proc : process(clk)
        begin
          if rising_edge(clk) then
              if we(i) = '1' then
                ram(waddr)   <= ip;
              end if;
          end if;
        end process;

        ram_rd(i)   <= ram(raddr);
    end generate ram_gen;

    op  <= ram_rd(sel);

    cnt_proc : process(clk)
    begin
      if rising_edge(clk) then
        cnt <= cnt + 1;
        waddr       <= to_integer(cnt);
        raddr  <= to_integer(cnt-1);

        we <= std_logic_vector(cnt(1 downto 0));
      end if;
    end process;



end architecture rtl;
0 Kudos
Scholar brimdavis
Scholar
520 Views
Registered: ‎04-26-2012

Re: Its 2018, and Vivado is inferring rams like its 2008

Jump to solution

@richardhead   "Vivado is inferring rams like its 2008"


Your 2008 target date is giving Vivado waaaay too much credit- I'd say FPGA Express circa 1998 is a better comparison :)

 

The following RAM inference AR's are listed as "Known Issues" for 2017.x :

  AR# 52331 Does Vivado Synthesis support VHDL record type to model a memory and infer a block RAM?
  https://www.xilinx.com/support/answers/52331.html

  AR# 64021 Vivado Synthesis - RAM not inferred when "wait until" is used for clock
  https://www.xilinx.com/support/answers/64021.html

  AR# 64033 2015.1 Vivado Synthesis: ERROR: [Synth 8-5548] Non zero range declaration for RAM (mem_reg) not supported. Use 0 for MSB or LSB for RAM declaration
  https://www.xilinx.com/support/answers/64033.html

  AR# 56457 Vivado Synthesis - Does Vivado Synthesis infer an optimal block RAM when both read address and the output data are registered in the HDL code?
  https://www.xilinx.com/support/answers/56457.html

  AR# 53507 Vivado 2012.x - Vivado Synthesis - Does Vivado Synthesis infer block RAM for multi-dimensional arrays greater than two dimensions?
  https://www.xilinx.com/support/answers/53507.html

  AR# 57854 2014.1 Vivado Synthesis - Some patterns of asymmetric BRAM inference are not successful.
  https://www.xilinx.com/support/answers/57854.html

  AR# 51088 Vivado Synthesis - For True Dual Port RAM coding styles, does the Vivado Synthesis tool generate RAMs when both ports are specified in the same always/process block?
  https://www.xilinx.com/support/answers/51088.html

 

---------------------------

Although RAM inference from records is presently listed as unsupported, last time I checked they actually synthesize now, *BUT* use a BRAM for each element of the record; e.g. attempting to infer a 1Kx32 RAM from a record with 8 elements that fit into 32 bits will produce 8 BRAMs instead of one.


-Brian