Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

Inferring RAM, registered on inputs only

I need a dual-port RAM with registered inputs and unregistered outputs. I can easily create this using the megafunction wizard or by instantiating an altsyncram directly. Unfortunately, I also need to be able to initialize its contents using information supplied by a generic parameter, thus ruling out simply creating a static initialization file.

Inferred RAMs can quite easily be initialized like this:

type ram_t is array(2**g_addr_bits-1 downto 0) of std_logic_vector(g_data_bits-1 downto 0);

signal ram : ram_t := f_some_function(g_parameter);

... so I was thinking I would just use an inferred memory instead of the altsyncram.

However, I have been completely unable to coax quartus into inferring the required register placement. I've read the section "Inferring Memory Functions from HDL code" of the document "Recommended HDL coding styles". Unfortunately, that document only proposes two alternatives: 1) a reads-old-data example with registers on write inputs and read output. ie: the register is on the wrong side of the read port. 2) a reads-new-data example with registers on the inputs... but addition bypass logic i don't want.

Does anyone have any idea how I could get a solution here? So far the best I can think of is to use an altsyncram directly and add some fancy reset-triggered initialization process. That will put another MUX on my critical path, however.

This is frustrating, because I know the hardware can do what I want, but I can't communicate my intentions to quartus.

11 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I have not tried the shared variable. However, I think it would just be a matter of the order in which you assigned to the variable?

    -- New data

    ram(w_addr_i) := w_data_i;

    r_data_o <= ram(r_addr_i);

    -- Old data

    r_data_o <= ram(r_addr_i);

    ram(w_addr_i) := w_data_i;

    ... in any case, why would you ever want a "new data" RAM? It requires bypass logic and can always be avoided with a well designed pipeline. The "old data" approach works with a signal, so I will just stick with that.