---------------------------------------------------------------------------------- -- Company: University of New Mexico -- Engineer: Professor Jim Plusquellic, Copyright Univ. of New Mexico -- -- Create Date: -- Design Name: -- Module Name: LoadUnLoadMem - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- -- LoadUnLoadMem securely transfers data into or out of PNL_BRAM using GPIO registers library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.all; library work; use work.DataTypes_pkg.all; entity LoadUnLoadMem is port( Clk: in std_logic; RESET: in std_logic; start: in std_logic; ready: out std_logic; load_unload: in std_logic; stopped: out std_logic; continue: in std_logic; done: in std_logic; base_address: in std_logic_vector(PNL_BRAM_ADDR_SIZE_NB-1 downto 0); upper_limit: in std_logic_vector(PNL_BRAM_ADDR_SIZE_NB-1 downto 0); CP_in_word: in std_logic_vector(WORD_SIZE_NB-1 downto 0); CP_out_word: out std_logic_vector(WORD_SIZE_NB-1 downto 0); PNL_BRAM_addr: out std_logic_vector(PNL_BRAM_ADDR_SIZE_NB-1 downto 0); PNL_BRAM_din: out std_logic_vector(PNL_BRAM_DBITS_WIDTH_NB-1 downto 0); PNL_BRAM_dout: in std_logic_vector(PNL_BRAM_DBITS_WIDTH_NB-1 downto 0); PNL_BRAM_we: out std_logic_vector(0 to 0) ); end LoadUnLoadMem; architecture beh of LoadUnLoadMem is type state_type is (idle, load_mem, unload_mem, wait_load_unload, wait_done); signal state_reg, state_next: state_type; signal ready_reg, ready_next: std_logic; signal PNL_BRAM_addr_reg, PNL_BRAM_addr_next: unsigned(PNL_BRAM_ADDR_SIZE_NB-1 downto 0); signal PNL_BRAM_upper_limit_reg, PNL_BRAM_upper_limit_next: unsigned(PNL_BRAM_ADDR_SIZE_NB-1 downto 0); begin -- ============================================================================================= -- State and register logic -- ============================================================================================= process(Clk, RESET) begin if ( RESET = '1' ) then state_reg <= idle; ready_reg <= '1'; PNL_BRAM_addr_reg <= (others=>'0'); PNL_BRAM_upper_limit_reg <= (others=>'0'); elsif ( Clk'event and Clk = '1' ) then state_reg <= state_next; ready_reg <= ready_next; PNL_BRAM_addr_reg <= PNL_BRAM_addr_next; PNL_BRAM_upper_limit_reg <= PNL_BRAM_upper_limit_next; end if; end process; -- ============================================================================================= -- Combo logic -- ============================================================================================= process (state_reg, start, ready_reg, load_unload, PNL_BRAM_addr_reg, PNL_BRAM_upper_limit_reg, PNL_BRAM_dout, CP_in_word, continue, base_address, upper_limit, done) begin state_next <= state_reg; ready_next <= ready_reg; PNL_BRAM_addr_next <= PNL_BRAM_addr_reg; PNL_BRAM_upper_limit_next <= PNL_BRAM_upper_limit_reg; PNL_BRAM_we <= "0"; PNL_BRAM_din <= (others=>'0'); CP_out_word <= (others=>'0'); stopped <= '0'; case state_reg is -- ===================== when idle => ready_next <= '1'; if ( start = '1' ) then ready_next <= '0'; -- Latch the 'base_address' and 'upper_limit' at the instant 'start' is asserted. NOTE: These signals MAY BE SET -- BACK TO all 0's after the 'start' signal is received. PNL_BRAM_addr_next <= unsigned(base_address); PNL_BRAM_upper_limit_next <= unsigned(upper_limit); if ( load_unload = '0' ) then state_next <= load_mem; else state_next <= unload_mem; end if; end if; -- ===================== -- Write value to memory location when load_mem => -- Signal C program that we are ready to receive a word. Once ready ('continue' becomes '1'), transfer and complete handshake. stopped <= '1'; if ( done = '0' ) then if ( continue = '1' ) then PNL_BRAM_we <= "1"; PNL_BRAM_din <= (PNL_BRAM_DBITS_WIDTH_NB-1 downto WORD_SIZE_NB => '0') & CP_in_word; -- Wait handshake signals state_next <= wait_load_unload; end if; -- Handle case where C program has nothing to store. else state_next <= wait_done; end if; -- ===================== -- Get value at memory location when unload_mem => -- Put the PNL BRAM word on CP_out_word. Do NOT do this by default for security reasons. CP_out_word <= PNL_BRAM_dout(WORD_SIZE_NB-1 downto 0); -- Signal C program that we are ready to deliver a word. Once it reads the word, it sets 'continue' to '1'. stopped <= '1'; if ( continue = '1' ) then -- Wait handshake signals state_next <= wait_load_unload; end if; -- Handle case where C program does not want to read any data. if ( done = '1' ) then state_next <= wait_done; end if; -- ===================== -- Complete handshake and update addresses when wait_load_unload => -- C program holds 'continue' at 1 until it sees 'stopped' go to 0, and then it writes a '0' to continue. It also writes -- 'done' with a '1' when last transfer is made. if ( continue = '0' ) then -- Done collecting C program transmitted words. Force a finish if the upper limit has been reached. This will protect the memory -- from overruns (reading or writing). if ( done = '1' ) then state_next <= wait_done; elsif ( PNL_BRAM_addr_reg = PNL_BRAM_upper_limit_reg ) then state_next <= idle; else PNL_BRAM_addr_next <= PNL_BRAM_addr_reg + 1; if ( load_unload = '0' ) then state_next <= load_mem; else state_next <= unload_mem; end if; end if; end if; -- ===================== -- Wait for 'done' to return to 0 before returning to idle, if it was set by the C program to exit early. when wait_done => if ( done = '0' ) then state_next <= idle; end if; end case; end process; -- Use 'look-ahead' signal for BRAM address. PNL_BRAM_addr <= std_logic_vector(PNL_BRAM_addr_next); ready <= ready_reg; end beh;