Forum Discussion

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

Strange block ram behavior

I have instantiated a dual port block ram in sopc builder. One end is connected to a nios2 processor, the other is connected to some custom vhdl code. The intent is for the nios2 to write to the ram which will trigger operations in the vhdl so at initialization, the vhdl is constantly trying to read the ram while the nios2 is setting up and eventually writing to the ram. What should happen is the nios2 writes to the ram and immediately, the vhdl should begin processing. However, I am seeing some strange behavior where most of the time an additional read or write to the ram is required for the vhdl to properly read the values. Has anyone encountered such an issue?

4 Replies

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

    I have a lot of vhdl code so not sure exactly what to post, but this module seems appropriate. This is the wrapper around the avalon bus coming from the block ram to my custom vhdl for reading from the ram.

    
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_arith.all;
    use ieee.std_logic_unsigned.all;
    entity Avalon_read is
    generic(
        ADDRS_WIDTH : integer;
        DATA_WIDTH : integer
    );
    port(
        -- user signals
        clk : in std_logic;
        read_en : std_logic;
        data_addrs_in : in integer range 0 to 2**ADDRS_WIDTH-1;
        data_out : out std_logic_vector(DATA_WIDTH-1 downto 0);
        -- avalon signals
        data_addrs_out : out std_logic_vector(31 downto 0);
        data_length_out : out std_logic_vector(31 downto 0);
        ctrl_go : out std_logic;
        ctrl_done : in std_logic;
        data_in : in std_logic_vector(DATA_WIDTH-1 downto 0);
        data_ready : in std_logic;
        data_read : out std_logic
    );
    end Avalon_read;
    architecture arch of Avalon_read is
        type tstate is (idle, send_ctrl, read, done);
        signal state : tstate := idle;
    begin
        state_machine : process(clk)
        begin
            if(rising_edge(clk)) then
                case state is
                    when idle =>
                        if(read_en='1') then
                            state <= send_ctrl;
                        end if;
                    when send_ctrl =>
                        state <= read;
                    when read =>
                        state <= done;
                    when done =>
                        state <= idle;
                end case;
            end if;
        end process;
        
        control_signals : process(state)
        begin
            case state is
                when idle | done =>
                    ctrl_go <= '0';
                    data_addrs_out <= (others=>'Z');
                    data_length_out <= (others=>'Z');
                    data_read <= '0';
                when send_ctrl =>
                    ctrl_go <= '1';
                    data_addrs_out <= conv_std_logic_vector(data_addrs_in*(DATA_WIDTH/8), 32);
                    data_length_out <= conv_std_logic_vector(DATA_WIDTH/8, 32);    --x"00000004";
                    data_read <= '0';
                when read =>
                    ctrl_go <= '0';
                    data_addrs_out <= (others=>'Z');
                    data_length_out <= (others=>'Z');
                    if(data_ready='1') then
                        data_read <= '1';
                    else
                        data_read <= '0';
                    end if;
            end case;
        end process;
        datat_ff : process(clk)
        begin
            if(rising_edge(clk)) then
                if(state=read) then
                    data_out <= data_in;
                end if;
            end if;
        end process;
    end arch;