-- init resets address counter and preloads pipeline -- after init_done content of address 0 is outputted -- the next rising edge after inca gives next content -- -- mem -> q2s -> q1s -> q0s library ieee; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity mempipe is port ( clk40 : in std_logic; cpuclk : in std_logic; reset_n : in std_logic; cpuaddr : in std_logic_vector(8 downto 0); cpudata : in std_logic_vector(31 downto 0); cpuwe : in std_logic; init : in std_logic; -- reset addresscounter and preload pipeline done : out std_logic; -- int and preload done inca : in std_logic; -- inc addr, present next data q : out std_logic_vector(31 downto 0)); end mempipe; architecture behv of mempipe is component tamem port ( addra : in std_logic_vector(8 downto 0); addrb : in std_logic_vector(8 downto 0); clka : in std_logic; clkb : in std_logic; dina : in std_logic_vector(31 downto 0); doutb : out std_logic_vector(31 downto 0); wea : in std_logic); end component; signal acnt : std_logic_vector(8 downto 0); signal acnt_clr : std_logic; signal acnt_en : std_logic; -- shift pipeline signal shift_en : std_logic; -- two pipeline stages for memdata signal q0reg, q1reg : std_logic_vector(31 downto 0); -- three pipeline for acnt_en and shift_en signal inca_pipe : std_logic_vector(1 downto 0); -- signals to mux signal q0s, q1s, q2s : std_logic_vector(31 downto 0); -- mltiplexer selector signal qsel : std_logic_vector(1 downto 0); -- Preload after clear signal preload : std_logic; -- FSM states type STATE_TYPE is (init_clr, init_1, init_2, init_done); signal state : STATE_TYPE; begin -- behv -- FSM fsm_seq : process (clk40, reset_n) begin -- process fsm_seq if reset_n = '0' then -- asynchronous reset (active low) state <= init_clr; elsif clk40'event and clk40 = '1' then -- rising clock edge case state is when init_clr => state <= init_1; when init_1 => state <= init_2; when init_2 => state <= init_done; when init_done => if init = '1' then state <= init_clr; else state <= init_done; end if; when others => null; end case; end if; end process fsm_seq; -- FSM outvectors acnt_clr <= '1' when state = init_clr else '0'; done <= '1' when state = init_done else '0'; with state select preload <= '1' when init_1 | init_2, '0' when others; -- Memory Block tamem_1 : tamem port map ( addra => cpuaddr, addrb => acnt, clka => cpuclk, clkb => clk40, dina => cpudata, doutb => q2s, wea => cpuwe); -- address counter acnt_p : process (clk40, reset_n) begin -- process acnt_p if reset_n = '0' then -- asynchronous reset (active low) acnt <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if acnt_clr = '1' then acnt <= (others => '0'); elsif acnt_en = '1' then acnt <= acnt + 1; end if; end if; end process acnt_p; -- data pipeline stages pi_p : process (clk40, reset_n) begin -- process pi_p if reset_n = '0' then -- asynchronous reset (active low) q0reg <= (others => '0'); q1reg <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if shift_en = '1' then q1reg <= q2s; q0reg <= q1reg; end if; end if; end process pi_p; q1s <= q1reg; q0s <= q0reg; -- inca pipeline incap : process (clk40, reset_n) begin -- process incap if reset_n = '0' then -- asynchronous reset (active low) inca_pipe <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge inca_pipe <= (inca or preload) & inca_pipe(1); end if; end process incap; -- Shift one cycle after increment address -- acnt_en <= inca_pipe(1); -- shift_en <= inca_pipe(0); acnt_en <= inca or preload; shift_en <= inca_pipe(1); -- multiplexer qsel <= inca & inca_pipe(1); with qsel select q <= q2s when "11", q1s when "01" | "10", q0s when others; end behv;