uninferred due to asynchronous read logic

Discussion in 'VHDL' started by Shannon, May 12, 2008.

  1. Shannon

    Shannon Guest

    I'm really having a bad day and I hope you guys can help me out AGAIN.

    I used altera's own template to instantiate a dual-port RAM. Pretty
    straight forward really. I've used the single port ram before with no
    problems. THIS time however when I compile it gives me some info:

    Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    read logic

    Hmm...ok so I go check the template. Yeah the read stuff is inside a
    clocked process. Hmm maybe what I'm driving the RAM_we signal with is
    asynchronous to the RAM clock. Nope. Looked at that and it is inside
    a clocked process that is clocked by the same clock as the RAM. Then
    I looked at the RTL viewer and sure enough the RAM_we signal is driven
    by a D-flip flop that is clocked by the right clock. So what am I
    missing?

    Shannon

    (I'm working on a sanitized version of the code that I can post here
    but I figured maybe I was missing somethnig obvious and should post
    first.)
     
    Shannon, May 12, 2008
    #1
    1. Advertising

  2. Shannon

    Shannon Guest

    On May 12, 3:11 pm, Shannon <> wrote:
    > I'm really having a bad day and I hope you guys can help me out AGAIN.
    >
    > I used altera's own template to instantiate a dual-port RAM.  Pretty
    > straight forward really.  I've used the single port ram before with no
    > problems.  THIS time however when I compile it gives me some info:
    >
    > Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    > read logic
    >
    > Hmm...ok so I go check the template.  Yeah the read stuff is inside a
    > clocked process.  Hmm maybe what I'm driving the RAM_we signal with is
    > asynchronous to the RAM clock.  Nope.  Looked at that and it is inside
    > a clocked process that is clocked by the same clock as the RAM.  Then
    > I looked at the RTL viewer and sure enough the RAM_we signal is driven
    > by a D-flip flop that is clocked by the right clock.  So what am I
    > missing?
    >
    > Shannon
    >
    > (I'm working on a sanitized version of the code that I can post here
    > but I figured maybe I was missing somethnig obvious and should post
    > first.)


    Ok, I thought I was on to something. The OTHER read signal was stuck
    asserted all the time. This is actually what I want but nevermind
    that. So what I did was made it synchronous just to see if the
    problem went away. Nope. But when I look closer at the RTL viewer it
    shows a "sync RAM" block that is being clocked by a single clock and
    whose write enable / read enable signals are fed from d-FFs that are
    clocked by the same clock. So, to me, it looks like the right thing.
    However, it's clearly using FF's to do it and NOT the on board RAM.

    Any ideas?
     
    Shannon, May 12, 2008
    #2
    1. Advertising

  3. Shannon wrote:

    >> I used altera's own template to instantiate a dual-port RAM. Pretty
    >> straight forward really. I've used the single port ram before with no
    >> problems. THIS time however when I compile it gives me some info:
    >>
    >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    >> read log

    > Any ideas?


    Dual port rams by X and A have an inference problem with
    simultaneous writes to the same address. It always requires
    some extra logic to arbitrate and synch things up. The easiest fix is
    something like this:

    ram_access : process (clk) is
    begin
    if rising_edge(clk) then
    if we = '1' then
    mem(to_integer(wr_adr)) <= (data_i);
    end if;
    data_q <= mem(to_integer(read_adr));
    end if;
    end process ram_access;

    -- Mike Treseler
     
    Mike Treseler, May 13, 2008
    #3
  4. Shannon

    Shannon Guest

    On May 12, 8:11 pm, Mike Treseler <> wrote:
    > Shannon wrote:
    > >> I used altera's own template to instantiate a dual-port RAM.  Pretty
    > >> straight forward really.  I've used the single port ram before with no
    > >> problems.  THIS time however when I compile it gives me some info:

    >
    > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    > >> read log

    > > Any ideas?

    >
    > Dual port rams by X and A have an inference problem with
    > simultaneous writes to the same address. It always requires
    > some extra logic to arbitrate and synch things up. The easiest fix is
    > something like this:
    >
    >     ram_access : process (clk) is
    >     begin
    >        if rising_edge(clk) then
    >           if we = '1' then
    >              mem(to_integer(wr_adr)) <= (data_i);
    >           end if;
    >           data_q <= mem(to_integer(read_adr));
    >        end if;
    >     end process ram_access;
    >
    >   -- Mike Treseler


    The template that 'A' provides is quite close to what you are
    suggesting:

    -- Port A
    process(clk)
    begin
    if(rising_edge(clk)) then
    if(we_a = '1') then
    ram(addr_a) <= data_a;
    -- Read-during-write on the same port returns NEW data
    q_a <= data_a;
    else
    -- Read-during-write on the mixed port returns OLD data
    q_a <= ram(addr_a);
    end if;
    end if;
    end process;

    They add the 'q_a <= data_a;' bit but otherwise it seems to be the
    same as what you suggest. Other than you have separate write and read
    address signals. Is that the part you are suggesting I add to their
    template?

    Actually as I'm typing this I'm reading their comments and becoming
    even more confused about what they intended. If there is only one
    "we_a" signal to control both reads AND writes, how is it POSSIBLE to
    ever have a "Read-during-write" event?
     
    Shannon, May 13, 2008
    #4
  5. Shannon

    KJ Guest

    On May 13, 10:52 am, Shannon <> wrote:
    > On May 12, 8:11 pm, Mike Treseler <> wrote:
    > > >> I used altera's own template to instantiate a dual-port RAM.  Pretty
    > > >> straight forward really.  I've used the single port ram before with no
    > > >> problems.  THIS time however when I compile it gives me some info:

    >
    > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    > > >> read log
    > > > Any ideas?

    >


    You're not following the template is my idea. Although I've also had
    problems with memory when it added unnecessary pass-thru logic because
    it had mucked with the read address logic in some unusual fashion.
    The work around there was to add the syn_preserve and syn_keep
    attributes to the read address signal. After that it didn't add any
    pass thru logic and implemented what it should have. That's not quite
    the same thing as what you're having trouble with but thought I'd
    share the info.

    >
    > The template that 'A' provides is quite close to what you are
    > suggesting:
    >
    > -- Port A
    > process(clk)
    > begin
    >   if(rising_edge(clk)) then
    >     if(we_a = '1') then
    >       ram(addr_a) <= data_a;
    >       -- Read-during-write on the same port returns NEW data
    >       q_a <= data_a;
    >     else
    >       -- Read-during-write on the mixed port returns OLD data
    >       q_a <= ram(addr_a);
    >     end if;
    >   end if;
    > end process;
    >

    You might want to check where you got your template from. The
    following is copy/pasted from the Quartus 2 manual from the heading
    'Implementing Inferred RAM (VHDL). As you can see it matches Mike's
    template, (and my template too for what it's worth).

    -- Start of text from Quartus 2 manual
    The example below shows ram_infer.vhd, a VHDL Design File that
    implements a 32 x 32-bit single-clock RAM with separate read and write
    addresses:

    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    ENTITY ram_infer IS
    PORT
    (
    clock: IN std_logic;
    data: IN std_logic_vector (31 DOWNTO 0);
    write_address: IN integer RANGE 0 to 31;
    read_address: IN integer RANGE 0 to 31;
    we: IN std_logic;
    q: OUT std_logic_vector (31 DOWNTO 0)
    );
    END ram_infer;
    ARCHITECTURE rtl OF ram_infer IS
    TYPE mem IS ARRAY(0 TO 31) OF std_logic_vector(31 DOWNTO 0);
    SIGNAL ram_block : mem;
    BEGIN
    PROCESS (clock)
    BEGIN
    IF (clock'event AND clock = '1') THEN
    IF (we = '1') THEN
    ram_block(write_address) <= data;
    END IF;
    q <= ram_block(read_address);
    END IF;
    END PROCESS;
    END rtl;
    -- End of text from Quartus 2 manual


    >
    > Actually as I'm typing this I'm reading their comments and becoming
    > even more confused about what they intended.  If there is only one
    > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
    > ever have a "Read-during-write" event?


    Reads are always occurring, you don't really have an explicit 'read'
    command to the memory. You're always able to read whether you're
    reading or not. The issue has to do with if you're reading from the
    same address that you're actively writing to (i.e. write_address =
    read_address and we='1'). In that situation the data from the newly
    written memory location won't show up until the clock cycle after the
    write completes.

    Kevin Jennings
     
    KJ, May 13, 2008
    #5
  6. Shannon

    KJ Guest

    Slight correction to previous post. What I said was...

    You're always able to read whether you're reading or not.



    What I meant to say was...

    You're always able to read whether you're writing or not.

    KJ
     
    KJ, May 13, 2008
    #6
  7. Shannon

    Shannon Guest

    On May 13, 9:22 am, KJ <> wrote:
    > On May 13, 10:52 am, Shannon <> wrote:
    >
    > > On May 12, 8:11 pm, Mike Treseler <> wrote:
    > > > >> I used altera's own template to instantiate a dual-port RAM.  Pretty
    > > > >> straight forward really.  I've used the single port ram before with no
    > > > >> problems.  THIS time however when I compile it gives me some info:

    >
    > > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    > > > >> read log
    > > > > Any ideas?

    >
    > You're not following the template is my idea.  Although I've also had
    > problems with memory when it added unnecessary pass-thru logic because
    > it had mucked with the read address logic in some unusual fashion.
    > The work around there was to add the syn_preserve and syn_keep
    > attributes to the read address signal.  After that it didn't add any
    > pass thru logic and implemented what it should have.  That's not quite
    > the same thing as what you're having trouble with but thought I'd
    > share the info.
    >
    >
    >
    >
    >
    >
    >
    > > The template that 'A' provides is quite close to what you are
    > > suggesting:

    >
    > > -- Port A
    > > process(clk)
    > > begin
    > >   if(rising_edge(clk)) then
    > >     if(we_a = '1') then
    > >       ram(addr_a) <= data_a;
    > >       -- Read-during-write on the same port returns NEW data
    > >       q_a <= data_a;
    > >     else
    > >       -- Read-during-write on the mixed port returns OLD data
    > >       q_a <= ram(addr_a);
    > >     end if;
    > >   end if;
    > > end process;

    >
    > You might want to check where you got your template from.  The
    > following is copy/pasted from the Quartus 2 manual from the heading
    > 'Implementing Inferred RAM (VHDL).  As you can see it matches Mike's
    > template, (and my template too for what it's worth).
    >
    > -- Start of text from Quartus 2 manual
    > The example below shows ram_infer.vhd, a VHDL Design File that
    > implements a 32 x 32-bit single-clock RAM with separate read and write
    > addresses:
    >
    > LIBRARY ieee;
    > USE ieee.std_logic_1164.ALL;
    > ENTITY ram_infer IS
    >    PORT
    >    (
    >       clock: IN   std_logic;
    >       data:  IN   std_logic_vector (31 DOWNTO 0);
    >       write_address:  IN   integer RANGE 0 to 31;
    >       read_address:   IN   integer RANGE 0 to 31;
    >       we:    IN   std_logic;
    >       q:     OUT  std_logic_vector (31 DOWNTO 0)
    >    );
    > END ram_infer;
    > ARCHITECTURE rtl OF ram_infer IS
    >    TYPE mem IS ARRAY(0 TO 31) OF std_logic_vector(31 DOWNTO 0);
    >    SIGNAL ram_block : mem;
    > BEGIN
    >    PROCESS (clock)
    >    BEGIN
    >       IF (clock'event AND clock = '1') THEN
    >          IF (we = '1') THEN
    >             ram_block(write_address) <= data;
    >          END IF;
    >          q <= ram_block(read_address);
    >       END IF;
    >    END PROCESS;
    > END rtl;
    > -- End of text from Quartus 2 manual
    >
    >
    >
    > > Actually as I'm typing this I'm reading their comments and becoming
    > > even more confused about what they intended.  If there is only one
    > > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
    > > ever have a "Read-during-write" event?

    >
    > Reads are always occurring, you don't really have an explicit 'read'
    > command to the memory.  You're always able to read whether you're
    > reading or not.  The issue has to do with if you're reading from the
    > same address that you're actively writing to (i.e. write_address =
    > read_address and we='1').  In that situation the data from the newly
    > written memory location won't show up until the clock cycle after the
    > write completes.
    >
    > Kevin Jennings- Hide quoted text -
    >
    > - Show quoted text -


    I think I'm quickly getting in over my head. Thanks for the response
    Kevin. I'm going to have to ponder what you're trying to tell me.

    I got my template from within Quartus II itself. It has a handy pull-
    down for "insert template". I'll paste it here:

    -- Quartus II VHDL Template
    -- True Dual-Port RAM with single clock

    library ieee;
    use ieee.std_logic_1164.all;

    entity true_dual_port_ram_single_clock is

    generic
    (
    DATA_WIDTH : natural := 8;
    ADDR_WIDTH : natural := 6
    );

    port
    (
    clk : in std_logic;
    addr_a : in natural range 0 to 2**ADDR_WIDTH - 1;
    addr_b : in natural range 0 to 2**ADDR_WIDTH - 1;
    data_a : in std_logic_vector((DATA_WIDTH-1) downto 0);
    data_b : in std_logic_vector((DATA_WIDTH-1) downto 0);
    we_a : in std_logic := '1';
    we_b : in std_logic := '1';
    q_a : out std_logic_vector((DATA_WIDTH -1) downto 0);
    q_b : out std_logic_vector((DATA_WIDTH -1) downto 0)
    );

    end true_dual_port_ram_single_clock;

    architecture rtl of true_dual_port_ram_single_clock is

    -- Build a 2-D array type for the RAM
    subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    type memory_t is array(addr_a'high downto 0) of word_t;

    -- Declare the RAM signal.
    signal ram : memory_t;

    begin

    -- Port A
    process(clk)
    begin
    if(rising_edge(clk)) then
    if(we_a = '1') then
    ram(addr_a) <= data_a;

    -- Read-during-write on the same port returns NEW data
    q_a <= data_a;
    else
    -- Read-during-write on the mixed port returns OLD data
    q_a <= ram(addr_a);
    end if;
    end if;
    end process;

    -- Port B
    process(clk)
    begin
    if(rising_edge(clk)) then
    if(we_b = '1') then
    ram(addr_b) <= data_b;

    -- Read-during-write on the same port returns NEW data
    q_b <= data_b;
    else
    -- Read-during-write on the mixed port returns OLD data
    q_b <= ram(addr_b);
    end if;
    end if;
    end process;

    end rtl;


    I do notice both you and Mike seem to be talking about something other
    than a dual-port RAM (in my simple mind). Both of your examples SEEM
    to me to be single-port rams with separate read and write address
    ports. Maybe I am just not understanding what I'm saying when I say
    dual-port RAM. I hope the cut and paste above from Quartus gives a
    hint of what I was trying to accomplish. Basically I have one module
    (a microP interface) that is reading OR writing whenever it wants.
    Then I have another module that is reading from the same RAM pretty
    much all the time. Ok, not ALL the time but it goes through bursts
    where it is incrementing the address and reading every clock cycle.

    I'll slowly read through your post and see if I can come up with
    relevent questions. I'm sensing I have two problems. One, I don't
    understand what a dual-port RAM is. And two I'm not understanding
    what the info "RAM logic "DPRAM:WIN_RAM|ram" uninferred due to
    asynchronous read logic" means.

    Shannon
     
    Shannon, May 13, 2008
    #7
  8. Shannon wrote:

    > If there is only one
    > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
    > ever have a "Read-during-write" event?


    By having two data buses.
     
    Mike Treseler, May 13, 2008
    #8
  9. Shannon

    Shannon Guest

    On May 13, 9:34 am, Shannon <> wrote:
    > On May 13, 9:22 am, KJ <> wrote:
    >
    >
    >
    >
    >
    > > On May 13, 10:52 am, Shannon <> wrote:

    >
    > > > On May 12, 8:11 pm, Mike Treseler <> wrote:
    > > > > >> I used altera's own template to instantiate a dual-port RAM.  Pretty
    > > > > >> straight forward really.  I've used the single port ram before with no
    > > > > >> problems.  THIS time however when I compile it gives me some info:

    >
    > > > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    > > > > >> read log
    > > > > > Any ideas?

    >
    > > You're not following the template is my idea.  Although I've also had
    > > problems with memory when it added unnecessary pass-thru logic because
    > > it had mucked with the read address logic in some unusual fashion.
    > > The work around there was to add the syn_preserve and syn_keep
    > > attributes to the read address signal.  After that it didn't add any
    > > pass thru logic and implemented what it should have.  That's not quite
    > > the same thing as what you're having trouble with but thought I'd
    > > share the info.

    >
    > > > The template that 'A' provides is quite close to what you are
    > > > suggesting:

    >
    > > > -- Port A
    > > > process(clk)
    > > > begin
    > > >   if(rising_edge(clk)) then
    > > >     if(we_a = '1') then
    > > >       ram(addr_a) <= data_a;
    > > >       -- Read-during-write on the same port returns NEW data
    > > >       q_a <= data_a;
    > > >     else
    > > >       -- Read-during-write on the mixed port returns OLD data
    > > >       q_a <= ram(addr_a);
    > > >     end if;
    > > >   end if;
    > > > end process;

    >
    > > You might want to check where you got your template from.  The
    > > following is copy/pasted from the Quartus 2 manual from the heading
    > > 'Implementing Inferred RAM (VHDL).  As you can see it matches Mike's
    > > template, (and my template too for what it's worth).

    >
    > > -- Start of text from Quartus 2 manual
    > > The example below shows ram_infer.vhd, a VHDL Design File that
    > > implements a 32 x 32-bit single-clock RAM with separate read and write
    > > addresses:

    >
    > > LIBRARY ieee;
    > > USE ieee.std_logic_1164.ALL;
    > > ENTITY ram_infer IS
    > >    PORT
    > >    (
    > >       clock: IN   std_logic;
    > >       data:  IN   std_logic_vector (31 DOWNTO 0);
    > >       write_address:  IN   integer RANGE 0 to 31;
    > >       read_address:   IN   integer RANGE 0 to 31;
    > >       we:    IN   std_logic;
    > >       q:     OUT  std_logic_vector (31 DOWNTO 0)
    > >    );
    > > END ram_infer;
    > > ARCHITECTURE rtl OF ram_infer IS
    > >    TYPE mem IS ARRAY(0 TO 31) OF std_logic_vector(31 DOWNTO 0);
    > >    SIGNAL ram_block : mem;
    > > BEGIN
    > >    PROCESS (clock)
    > >    BEGIN
    > >       IF (clock'event AND clock = '1') THEN
    > >          IF (we = '1') THEN
    > >             ram_block(write_address) <= data;
    > >          END IF;
    > >          q <= ram_block(read_address);
    > >       END IF;
    > >    END PROCESS;
    > > END rtl;
    > > -- End of text from Quartus 2 manual

    >
    > > > Actually as I'm typing this I'm reading their comments and becoming
    > > > even more confused about what they intended.  If there is only one
    > > > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
    > > > ever have a "Read-during-write" event?

    >
    > > Reads are always occurring, you don't really have an explicit 'read'
    > > command to the memory.  You're always able to read whether you're
    > > reading or not.  The issue has to do with if you're reading from the
    > > same address that you're actively writing to (i.e. write_address =
    > > read_address and we='1').  In that situation the data from the newly
    > > written memory location won't show up until the clock cycle after the
    > > write completes.

    >
    > > Kevin Jennings- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > I think I'm quickly getting in over my head.  Thanks for the response
    > Kevin.  I'm going to have to ponder what you're trying to tell me.
    >
    > I got my template from within Quartus II itself.  It has a handy pull-
    > down for "insert template".  I'll paste it here:
    >
    > -- Quartus II VHDL Template
    > -- True Dual-Port RAM with single clock
    >
    > library ieee;
    > use ieee.std_logic_1164.all;
    >
    > entity true_dual_port_ram_single_clock is
    >
    >         generic
    >         (
    >                 DATA_WIDTH : natural := 8;
    >                 ADDR_WIDTH : natural := 6
    >         );
    >
    >         port
    >         (
    >                 clk             : in std_logic;
    >                 addr_a  : in natural range 0 to 2**ADDR_WIDTH - 1;
    >                 addr_b  : in natural range 0 to 2**ADDR_WIDTH - 1;
    >                 data_a  : in std_logic_vector((DATA_WIDTH-1) downto 0);
    >                 data_b  : in std_logic_vector((DATA_WIDTH-1) downto 0);
    >                 we_a    : in std_logic := '1';
    >                 we_b    : in std_logic := '1';
    >                 q_a             : out std_logic_vector((DATA_WIDTH -1) downto 0);
    >                 q_b             : out std_logic_vector((DATA_WIDTH -1) downto 0)
    >         );
    >
    > end true_dual_port_ram_single_clock;
    >
    > architecture rtl of true_dual_port_ram_single_clock is
    >
    >         -- Build a 2-D array type for the RAM
    >         subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    >         type memory_t is array(addr_a'high downto 0) of word_t;
    >
    >         -- Declare the RAM signal.
    >         signal ram : memory_t;
    >
    > begin
    >
    >         -- Port A
    >         process(clk)
    >         begin
    >         if(rising_edge(clk)) then
    >                 if(we_a = '1') then
    >                         ram(addr_a) <= data_a;
    >
    >                         -- Read-during-write on the same port returns NEW data
    >                         q_a <= data_a;
    >                 else
    >                         -- Read-during-write on the mixed port returns OLD data
    >                         q_a <= ram(addr_a);
    >                 end if;
    >         end if;
    >         end process;
    >
    >         -- Port B
    >         process(clk)
    >         begin
    >         if(rising_edge(clk)) then
    >                 if(we_b = '1') then
    >                         ram(addr_b) <= data_b;
    >
    >                         -- Read-during-write on the same port returns NEW data
    >                         q_b <= data_b;
    >                 else
    >                         -- Read-during-write on the mixed port returns OLD data
    >                         q_b <= ram(addr_b);
    >                 end if;
    >         end if;
    >         end process;
    >
    > end rtl;
    >
    > I do notice both you and Mike seem to be talking about something other
    > than a dual-port RAM (in my simple mind).  Both of your examples SEEM
    > to me to be single-port rams with separate read and write address
    > ports.  Maybe I am just not understanding what I'm saying when I say
    > dual-port RAM.  I hope the cut and paste above from Quartus gives a
    > hint of what I was trying to accomplish.  Basically I have one module
    > (a microP interface) that is reading OR writing whenever it wants.
    > Then I have another module that is reading from the same RAM pretty
    > much all the time.  Ok, not ALL the time but it goes through bursts
    > where it is incrementing the address and reading every clock cycle.
    >
    > I'll slowly read through your post and see if I can come up with
    > relevent questions.  I'm sensing I have two problems.  One, I don't
    > understand what a dual-port RAM is.  And two I'm not understanding
    > what the info "RAM logic "DPRAM:WIN_RAM|ram" uninferred due to
    > asynchronous read logic" means.
    >
    > Shannon- Hide quoted text -
    >
    > - Show quoted text -


    First question. Is this "INFO" refering to something about the
    template that I'm using or is it refering to my use of the DPRAM? In
    other words, is Quartus complaining that something about the structure
    of the RAM template is telling it to infer logic over RAM? OR.... Is
    Quartus complaining that somewhere in MY code I'm performing an
    asynchronous read of the RAM so it will have to synthesize the RAM
    with logic to be able to deal with MY asynchronous behavior?

    Shannon
     
    Shannon, May 13, 2008
    #9
  10. Shannon

    Dave Guest

    On May 13, 12:34 pm, Shannon <> wrote:
    > On May 13, 9:22 am, KJ <> wrote:
    >
    >
    >
    > > On May 13, 10:52 am, Shannon <> wrote:

    >
    > > > On May 12, 8:11 pm, Mike Treseler <> wrote:
    > > > > >> I used altera's own template to instantiate a dual-port RAM. Pretty
    > > > > >> straight forward really. I've used the single port ram before with no
    > > > > >> problems. THIS time however when I compile it gives me some info:

    >
    > > > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
    > > > > >> read log
    > > > > > Any ideas?

    >
    > > You're not following the template is my idea. Although I've also had
    > > problems with memory when it added unnecessary pass-thru logic because
    > > it had mucked with the read address logic in some unusual fashion.
    > > The work around there was to add the syn_preserve and syn_keep
    > > attributes to the read address signal. After that it didn't add any
    > > pass thru logic and implemented what it should have. That's not quite
    > > the same thing as what you're having trouble with but thought I'd
    > > share the info.

    >
    > > > The template that 'A' provides is quite close to what you are
    > > > suggesting:

    >
    > > > -- Port A
    > > > process(clk)
    > > > begin
    > > > if(rising_edge(clk)) then
    > > > if(we_a = '1') then
    > > > ram(addr_a) <= data_a;
    > > > -- Read-during-write on the same port returns NEW data
    > > > q_a <= data_a;
    > > > else
    > > > -- Read-during-write on the mixed port returns OLD data
    > > > q_a <= ram(addr_a);
    > > > end if;
    > > > end if;
    > > > end process;

    >
    > > You might want to check where you got your template from. The
    > > following is copy/pasted from the Quartus 2 manual from the heading
    > > 'Implementing Inferred RAM (VHDL). As you can see it matches Mike's
    > > template, (and my template too for what it's worth).

    >
    > > -- Start of text from Quartus 2 manual
    > > The example below shows ram_infer.vhd, a VHDL Design File that
    > > implements a 32 x 32-bit single-clock RAM with separate read and write
    > > addresses:

    >
    > > LIBRARY ieee;
    > > USE ieee.std_logic_1164.ALL;
    > > ENTITY ram_infer IS
    > > PORT
    > > (
    > > clock: IN std_logic;
    > > data: IN std_logic_vector (31 DOWNTO 0);
    > > write_address: IN integer RANGE 0 to 31;
    > > read_address: IN integer RANGE 0 to 31;
    > > we: IN std_logic;
    > > q: OUT std_logic_vector (31 DOWNTO 0)
    > > );
    > > END ram_infer;
    > > ARCHITECTURE rtl OF ram_infer IS
    > > TYPE mem IS ARRAY(0 TO 31) OF std_logic_vector(31 DOWNTO 0);
    > > SIGNAL ram_block : mem;
    > > BEGIN
    > > PROCESS (clock)
    > > BEGIN
    > > IF (clock'event AND clock = '1') THEN
    > > IF (we = '1') THEN
    > > ram_block(write_address) <= data;
    > > END IF;
    > > q <= ram_block(read_address);
    > > END IF;
    > > END PROCESS;
    > > END rtl;
    > > -- End of text from Quartus 2 manual

    >
    > > > Actually as I'm typing this I'm reading their comments and becoming
    > > > even more confused about what they intended. If there is only one
    > > > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
    > > > ever have a "Read-during-write" event?

    >
    > > Reads are always occurring, you don't really have an explicit 'read'
    > > command to the memory. You're always able to read whether you're
    > > reading or not. The issue has to do with if you're reading from the
    > > same address that you're actively writing to (i.e. write_address =
    > > read_address and we='1'). In that situation the data from the newly
    > > written memory location won't show up until the clock cycle after the
    > > write completes.

    >
    > > Kevin Jennings- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > I think I'm quickly getting in over my head. Thanks for the response
    > Kevin. I'm going to have to ponder what you're trying to tell me.
    >
    > I got my template from within Quartus II itself. It has a handy pull-
    > down for "insert template". I'll paste it here:
    >
    > -- Quartus II VHDL Template
    > -- True Dual-Port RAM with single clock
    >
    > library ieee;
    > use ieee.std_logic_1164.all;
    >
    > entity true_dual_port_ram_single_clock is
    >
    > generic
    > (
    > DATA_WIDTH : natural := 8;
    > ADDR_WIDTH : natural := 6
    > );
    >
    > port
    > (
    > clk : in std_logic;
    > addr_a : in natural range 0 to 2**ADDR_WIDTH - 1;
    > addr_b : in natural range 0 to 2**ADDR_WIDTH - 1;
    > data_a : in std_logic_vector((DATA_WIDTH-1) downto 0);
    > data_b : in std_logic_vector((DATA_WIDTH-1) downto 0);
    > we_a : in std_logic := '1';
    > we_b : in std_logic := '1';
    > q_a : out std_logic_vector((DATA_WIDTH -1) downto 0);
    > q_b : out std_logic_vector((DATA_WIDTH -1) downto 0)
    > );
    >
    > end true_dual_port_ram_single_clock;
    >
    > architecture rtl of true_dual_port_ram_single_clock is
    >
    > -- Build a 2-D array type for the RAM
    > subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    > type memory_t is array(addr_a'high downto 0) of word_t;
    >
    > -- Declare the RAM signal.
    > signal ram : memory_t;
    >
    > begin
    >
    > -- Port A
    > process(clk)
    > begin
    > if(rising_edge(clk)) then
    > if(we_a = '1') then
    > ram(addr_a) <= data_a;
    >
    > -- Read-during-write on the same port returns NEW data
    > q_a <= data_a;
    > else
    > -- Read-during-write on the mixed port returns OLD data
    > q_a <= ram(addr_a);
    > end if;
    > end if;
    > end process;
    >
    > -- Port B
    > process(clk)
    > begin
    > if(rising_edge(clk)) then
    > if(we_b = '1') then
    > ram(addr_b) <= data_b;
    >
    > -- Read-during-write on the same port returns NEW data
    > q_b <= data_b;
    > else
    > -- Read-during-write on the mixed port returns OLD data
    > q_b <= ram(addr_b);
    > end if;
    > end if;
    > end process;
    >
    > end rtl;
    >
    > I do notice both you and Mike seem to be talking about something other
    > than a dual-port RAM (in my simple mind). Both of your examples SEEM
    > to me to be single-port rams with separate read and write address
    > ports. Maybe I am just not understanding what I'm saying when I say
    > dual-port RAM. I hope the cut and paste above from Quartus gives a
    > hint of what I was trying to accomplish. Basically I have one module
    > (a microP interface) that is reading OR writing whenever it wants.
    > Then I have another module that is reading from the same RAM pretty
    > much all the time. Ok, not ALL the time but it goes through bursts
    > where it is incrementing the address and reading every clock cycle.
    >
    > I'll slowly read through your post and see if I can come up with
    > relevent questions. I'm sensing I have two problems. One, I don't
    > understand what a dual-port RAM is. And two I'm not understanding
    > what the info "RAM logic "DPRAM:WIN_RAM|ram" uninferred due to
    > asynchronous read logic" means.
    >
    > Shannon


    It might matter what particular chip you're targetting. I remember
    some of the older Altera chips didn't have true dual-port RAM, but
    instead had separate read and write ports. Could it be that the chip
    you're targetting doesn't have a true dual-port RAM? What are you
    targetting?

    Dave
     
    Dave, May 13, 2008
    #10
  11. Shannon wrote:

    > I do notice both you and Mike seem to be talking about something other
    > than a dual-port RAM (in my simple mind). Both of your examples SEEM
    > to me to be single-port rams with separate read and write address
    > ports.


    Exactly. As far as I know this is the only case
    that can be inferred reliably across brands.

    > Maybe I am just not understanding what I'm saying when I say
    > dual-port RAM. I hope the cut and paste above from Quartus gives a
    > hint of what I was trying to accomplish. Basically I have one module
    > (a microP interface) that is reading OR writing whenever it wants.
    > Then I have another module that is reading from the same RAM pretty
    > much all the time.


    You have only one writer.
    I would have the microP write to two block rams and read one.
    If that won't do, Instance a true dual port.

    -- Mike Treseler
     
    Mike Treseler, May 13, 2008
    #11
  12. Shannon

    Shannon Guest

    Dave asked: What are you targetting?

    Cyclone. As far as I can tell from the data sheet it indicates that
    it is capable of true dual-port RAM


    > If that won't do, Instance a true dual port.
    >
    >             -- Mike Treseler


    Isn't that what I did?
     
    Shannon, May 13, 2008
    #12
  13. Shannon

    Shannon Guest

    Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    have this picture of a clown on a tiny tricycle peddling furiously but
    just going in a little circle)

    If you take the template I posted and try to synthesize it all by
    itself in Quartus II targeting a Cyclone, you will get the same
    warning as I've posted above. So, to me, this means the warning has
    nothing to do with MY use of the DPRAM elsewhere in my code. The
    problem is entirely inside Quartus's own template! Ok, now with your
    help I think we can make this thing infer real RAM. Any ideas? It
    seems to think the read is asynchronous but in my view the read
    behavior is inside a clocked process and the IF .. THEN is
    incomplete. This means it will make a register out of the read port
    so that it can hold it's value outside the process. That process is
    clocked so I can't see how it thinks reads are asynchronous.

    Shannon
     
    Shannon, May 13, 2008
    #13
  14. Shannon wrote:

    >> If that won't do, Instance a true dual port.
    >>
    >> -- Mike Treseler

    >
    > Isn't that what I did?


    As I understand it,
    you tried to infer one, and that didn't work.

    -- Mike Treseler
     
    Mike Treseler, May 13, 2008
    #14
  15. Shannon

    Shannon Guest

    On May 13, 10:48 am, Shannon <> wrote:
    > Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    > have this picture of a clown on a tiny tricycle peddling furiously but
    > just going in a little circle)
    >
    > If you take the template I posted and try to synthesize it all by
    > itself in Quartus II targeting a Cyclone, you will get the same
    > warning as I've posted above.  So, to me, this means the warning has
    > nothing to do with MY use of the DPRAM elsewhere in my code.  The
    > problem is entirely inside Quartus's own template!  Ok, now with your
    > help I think we can make this thing infer real RAM.  Any ideas?  It
    > seems to think the read is asynchronous but in my view the read
    > behavior is inside a clocked process and the IF .. THEN is
    > incomplete.  This means it will make a register out of the read port
    > so that it can hold it's value outside the process.  That process is
    > clocked so I can't see how it thinks reads are asynchronous.
    >
    > Shannon


    ooopss I had commented out the 'q_a <= data_a;' lines and it didn't
    work. but when I put them back it correctly infers an altsynchRAM.
    However, when I put this back into my project the error returns. I
    guess that means there MUST be something wrong with my code. It must
    be making it create an asynchronous read....grrrrrrr

    I'm lost.
    Shannon
     
    Shannon, May 13, 2008
    #15
  16. Shannon wrote:
    > Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    > have this picture of a clown on a tiny tricycle peddling furiously but
    > just going in a little circle)
    >
    > Ok, now with your
    > help I think we can make this thing infer real RAM. Any ideas?


    I assume you mean 'real' dual-port ram.
    Let me know if you work it out.
    I am done pushing on that rope.

    As long as the vendors use asych logic to arbitrate writes,
    the template, if it existed, would not be synchronous.

    I'll stick with building blocks of
    one read and one write port.
    I have yet to run out of block ram.

    -- Mike Treseler
     
    Mike Treseler, May 13, 2008
    #16
  17. Shannon

    Shannon Guest

    On May 13, 10:58 am, Mike Treseler <> wrote:
    > Shannon wrote:
    > > Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    > > have this picture of a clown on a tiny tricycle peddling furiously but
    > > just going in a little circle)

    >
    > > Ok, now with your
    > > help I think we can make this thing infer real RAM.  Any ideas?

    >
    > I assume you mean 'real' dual-port ram.
    > Let me know if you work it out.
    > I am done pushing on that rope.
    >
    > As long as the vendors use asych logic to arbitrate writes,
    > the template, if it existed, would not be synchronous.
    >
    > I'll stick with building blocks of
    > one read and one write port.
    > I have yet to run out of block ram.
    >
    >         -- Mike Treseler


    Thanks Mike. I appreciate all your help. I'll keep pushing on the
    rope for a little while longer. I'm one of those block heads that
    wants to understand WHY he can't do what he wants to do. I saw it
    infer a true dual-port when the template is by itself. To me, that
    means it is POSSIBLE to infer a true dual port RAM. I just have to
    figure out why my surrounding code makes it UNinfer.

    If anyone else has some tips or hints I'd be happy to hear 'em!

    Shannon
     
    Shannon, May 13, 2008
    #17
  18. Shannon

    Dave Guest

    On May 13, 1:51 pm, Shannon <> wrote:
    > On May 13, 10:48 am, Shannon <> wrote:
    >
    >
    >
    > > Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    > > have this picture of a clown on a tiny tricycle peddling furiously but
    > > just going in a little circle)

    >
    > > If you take the template I posted and try to synthesize it all by
    > > itself in Quartus II targeting a Cyclone, you will get the same
    > > warning as I've posted above. So, to me, this means the warning has
    > > nothing to do with MY use of the DPRAM elsewhere in my code. The
    > > problem is entirely inside Quartus's own template! Ok, now with your
    > > help I think we can make this thing infer real RAM. Any ideas? It
    > > seems to think the read is asynchronous but in my view the read
    > > behavior is inside a clocked process and the IF .. THEN is
    > > incomplete. This means it will make a register out of the read port
    > > so that it can hold it's value outside the process. That process is
    > > clocked so I can't see how it thinks reads are asynchronous.

    >
    > > Shannon

    >
    > ooopss I had commented out the 'q_a <= data_a;' lines and it didn't
    > work. but when I put them back it correctly infers an altsynchRAM.
    > However, when I put this back into my project the error returns. I
    > guess that means there MUST be something wrong with my code. It must
    > be making it create an asynchronous read....grrrrrrr
    >
    > I'm lost.
    > Shannon


    If it works when it's in its own entity, then maybe you should try
    leaving the DPRAM that way, and instantiating it as a component is the
    rest of your code. This might help Quartus see things more clearly.
    Memory inferring is tricky, and I've found that sometimes the tools
    need things a certain way just because, even though you're following
    all the rules.

    Dave
     
    Dave, May 13, 2008
    #18
  19. Shannon

    Shannon Guest

    On May 13, 11:33 am, Dave <> wrote:
    > On May 13, 1:51 pm, Shannon <> wrote:
    >
    >
    >
    >
    >
    > > On May 13, 10:48 am, Shannon <> wrote:

    >
    > > > Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    > > > have this picture of a clown on a tiny tricycle peddling furiously but
    > > > just going in a little circle)

    >
    > > > If you take the template I posted and try to synthesize it all by
    > > > itself in Quartus II targeting a Cyclone, you will get the same
    > > > warning as I've posted above.  So, to me, this means the warning has
    > > > nothing to do with MY use of the DPRAM elsewhere in my code.  The
    > > > problem is entirely inside Quartus's own template!  Ok, now with your
    > > > help I think we can make this thing infer real RAM.  Any ideas?  It
    > > > seems to think the read is asynchronous but in my view the read
    > > > behavior is inside a clocked process and the IF .. THEN is
    > > > incomplete.  This means it will make a register out of the read port
    > > > so that it can hold it's value outside the process.  That process is
    > > > clocked so I can't see how it thinks reads are asynchronous.

    >
    > > > Shannon

    >
    > > ooopss  I had commented out the 'q_a <= data_a;' lines and it didn't
    > > work.  but when I put them back it correctly infers an altsynchRAM.
    > > However, when I put this back into my project the error returns.  I
    > > guess that means there MUST be something wrong with my code.  It must
    > > be making it create an asynchronous read....grrrrrrr

    >
    > > I'm lost.
    > > Shannon

    >
    > If it works when it's in its own entity, then maybe you should try
    > leaving the DPRAM that way, and instantiating it as a component is the
    > rest of your code. This might help Quartus see things more clearly.
    > Memory inferring is tricky, and I've found that sometimes the tools
    > need things a certain way just because, even though you're following
    > all the rules.
    >
    > Dave- Hide quoted text -
    >
    > - Show quoted text -


    Excellent idea. I am doing a direct instantiation right now but if I
    understand you correctly, I could somehow complile it into a library
    or something and then stick it into my code thereby not letting
    Quartus re-synthesize the RAM part. Ok, it's back to the books to see
    how I can do all that!

    Shannon
     
    Shannon, May 13, 2008
    #19
  20. Shannon

    Dave Guest

    On May 13, 3:54 pm, Shannon <> wrote:
    > On May 13, 11:33 am, Dave <> wrote:
    >
    >
    >
    > > On May 13, 1:51 pm, Shannon <> wrote:

    >
    > > > On May 13, 10:48 am, Shannon <> wrote:

    >
    > > > > Ok! Now I'm getting somewhere (at least in my mind...for some reason I
    > > > > have this picture of a clown on a tiny tricycle peddling furiously but
    > > > > just going in a little circle)

    >
    > > > > If you take the template I posted and try to synthesize it all by
    > > > > itself in Quartus II targeting a Cyclone, you will get the same
    > > > > warning as I've posted above. So, to me, this means the warning has
    > > > > nothing to do with MY use of the DPRAM elsewhere in my code. The
    > > > > problem is entirely inside Quartus's own template! Ok, now with your
    > > > > help I think we can make this thing infer real RAM. Any ideas? It
    > > > > seems to think the read is asynchronous but in my view the read
    > > > > behavior is inside a clocked process and the IF .. THEN is
    > > > > incomplete. This means it will make a register out of the read port
    > > > > so that it can hold it's value outside the process. That process is
    > > > > clocked so I can't see how it thinks reads are asynchronous.

    >
    > > > > Shannon

    >
    > > > ooopss I had commented out the 'q_a <= data_a;' lines and it didn't
    > > > work. but when I put them back it correctly infers an altsynchRAM.
    > > > However, when I put this back into my project the error returns. I
    > > > guess that means there MUST be something wrong with my code. It must
    > > > be making it create an asynchronous read....grrrrrrr

    >
    > > > I'm lost.
    > > > Shannon

    >
    > > If it works when it's in its own entity, then maybe you should try
    > > leaving the DPRAM that way, and instantiating it as a component is the
    > > rest of your code. This might help Quartus see things more clearly.
    > > Memory inferring is tricky, and I've found that sometimes the tools
    > > need things a certain way just because, even though you're following
    > > all the rules.

    >
    > > Dave- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > Excellent idea. I am doing a direct instantiation right now but if I
    > understand you correctly, I could somehow complile it into a library
    > or something and then stick it into my code thereby not letting
    > Quartus re-synthesize the RAM part. Ok, it's back to the books to see
    > how I can do all that!
    >
    > Shannon


    That's a bit more than I meant... I was just meaning to instantiate
    your RAM code, like you would in any hierarchical design. Nothing
    more. No precompiling anything or any other weirdness.
     
    Dave, May 13, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Richard B. Katz

    MAPLD CFP: Abstracts Due April 26, 2004

    Richard B. Katz, Apr 21, 2004, in forum: VHDL
    Replies:
    0
    Views:
    497
    Richard B. Katz
    Apr 21, 2004
  2. avinash
    Replies:
    0
    Views:
    447
    avinash
    Mar 5, 2005
  3. Guest
    Replies:
    3
    Views:
    363
    Tom Jenkins
    Apr 12, 2005
  4. Fresh
    Replies:
    2
    Views:
    659
    Bo Persson
    Apr 22, 2008
  5. spike
    Replies:
    8
    Views:
    1,544
    Steve Holden
    Feb 9, 2010
Loading...

Share This Page