--====================================================================== library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.ipbus.all; use work.ipbus_reg_types.all; library unisim; use unisim.vcomponents.all; use work.ipbus_decode_flash_interface.all; --================================================== entity dth_flash_interface is port ( -- IPbus interface. clk : in std_logic; rst : in std_logic; ipb_in : in ipb_wbus; ipb_out : out ipb_rbus; -- AXI clock. axi_aclk : in std_logic; -- Flash interface. flash_data : inout std_logic_vector(15 downto 4); flash_add : out std_logic_vector(31 downto 0); flash_oen : out std_logic; flash_wen : out std_logic ); end dth_flash_interface; --================================================== architecture behavioral of dth_flash_interface is constant C_ACCESS_MODE_READ : std_logic := '0'; constant C_ACCESS_MODE_WRITE : std_logic := '1'; constant C_ACCESS_SIZE_WORD : std_logic := '0'; constant C_ACCESS_SIZE_SECTOR : std_logic := '1'; constant C_AXI_SEL_WORD : std_logic := '0'; constant C_AXI_SEL_SECTOR : std_logic := '1'; -- IPBus read/write buses. signal ipbw : ipb_wbus_array(N_SLAVES - 1 downto 0); signal ipbr : ipb_rbus_array(N_SLAVES - 1 downto 0); signal ctrl : ipb_reg_v(3 downto 0); signal stat : ipb_reg_v(2 downto 0); -- AXI-related signals. signal axi_reset : std_logic; signal axi_resetn : std_logic; signal axi_mem_awaddr : std_logic_vector(31 downto 0); signal axi_mem_awvalid : std_logic; signal axi_mem_awready : std_logic; signal axi_mem_wdata : std_logic_vector(31 downto 0); signal axi_mem_wstrb : std_logic_vector(3 downto 0); signal axi_mem_size : std_logic_vector(2 downto 0); signal axi_mem_wvalid : std_logic; signal axi_mem_wready : std_logic; signal axi_mem_bvalid : std_logic; signal axi_mem_bready : std_logic; signal axi_mem_araddr : std_logic_vector(31 downto 0); signal axi_mem_arvalid : std_logic; signal axi_mem_arready : std_logic; signal axi_mem_rdata : std_logic_vector(31 downto 0); signal axi_mem_rvalid : std_logic; signal axi_mem_rready : std_logic; signal axi_sel : std_logic; signal axi_rq_add : std_logic_vector(31 downto 0); signal axi_rq_strb : std_logic_vector(3 downto 0); signal axi_rq_dti : std_logic_vector(31 downto 0); signal axi_rtn_dto : std_logic_vector(31 downto 0); signal axi_rq_rd : std_logic; signal axi_rq_wr : std_logic; signal axi_tick : std_logic; signal axi_address_word : std_logic_vector(31 downto 0); signal axi_strobe_word : std_logic_vector(3 downto 0); signal axi_tick_word : std_logic; signal axi_dti_word : std_logic_vector(31 downto 0); signal axi_dto_word : std_logic_vector(31 downto 0); signal axi_read_word : std_logic; signal axi_write_word : std_logic; signal axi_address_sector : std_logic_vector(31 downto 0); signal axi_strobe_sector : std_logic_vector(3 downto 0); signal axi_tick_sector : std_logic; signal axi_dti_sector : std_logic_vector(31 downto 0); signal axi_dto_sector : std_logic_vector(31 downto 0); signal axi_read_sector : std_logic; signal axi_write_sector : std_logic; signal axi_status : std_logic_vector(31 downto 0); signal axi_done : std_logic; -- Flash-related signals. signal flash_data_out : std_logic_vector(15 downto 0); signal flash_data_tristate : std_logic_vector(15 downto 0); signal flash_data_in_startup : std_logic_vector(3 downto 0); signal flash_data_tristate_startup : std_logic_vector(3 downto 0); signal flash_data_out_startup : std_logic_vector(3 downto 0); signal flash_cen : std_logic; -- Misc. signal access_mode : std_logic; signal access_size : std_logic; signal trigger : std_logic; signal access_strobe : std_logic; signal trigger_read_sector : std_logic; signal trigger_write_sector : std_logic; signal sector_access_done : std_logic; type STATE is ( STATE_IDLE, STATE_BUFFER_READ_INIT, STATE_SECTOR_READ_0, STATE_SECTOR_READ_1, STATE_RAM_WRITE_0, STATE_RAM_WRITE_1, STATE_RAM_WRITE_2, STATE_BUFFER_WRITE_INIT, STATE_BUFFER_OPEN_00, STATE_BUFFER_OPEN_01, STATE_BUFFER_OPEN_10, STATE_BUFFER_OPEN_11, STATE_BUFFER_OPEN_20, STATE_BUFFER_OPEN_21, STATE_BUFFER_OPEN_30, STATE_BUFFER_OPEN_31, STATE_RAM_READ_0, STATE_RAM_READ_1, STATE_WORD_WRITE_0, STATE_WORD_WRITE_1, STATE_BUFFER_CHECK, STATE_BUFFER_WRITE_0, STATE_BUFFER_WRITE_1, STATE_STATUS_READ_0, STATE_STATUS_READ_1, STATE_STATUS_READ_2, STATE_STATUS_READ_3, STATE_STATUS_READ_4, STATE_CHECK_LOOP, STATE_BUFFER_ACCESS_DONE ); signal fsm_state : STATE; signal fsm_state_val : std_logic_vector(29 downto 0); -- The DTH P1V1/P1V2 flash is a Cypress S29GL01GS11DHIV2. -- The total flash address width is 26 bits. constant C_FLASH_FULL_ADDR_WIDTH : integer := 26; -- The top ten of the flash address bits specify the sector. constant C_FLASH_SECTOR_ADDR_WIDTH : integer := 10; -- The rest of the flash address bits specify the address in the -- sector. constant C_FLASH_IN_SECTOR_ADDR_WIDTH : integer := C_FLASH_FULL_ADDR_WIDTH - C_FLASH_SECTOR_ADDR_WIDTH; -- The in-flash buffer is 512 bytes large, or 256 flash words. constant C_FLASH_BUFFER_ADDR_WIDTH : integer := 8; constant C_FLASH_BUFFER_ADDR_MAX : integer := 2**C_FLASH_BUFFER_ADDR_WIDTH - 1; constant C_FLASH_BUFFER_SIZE : integer := 2**C_FLASH_BUFFER_ADDR_WIDTH; -- The buffer RAM holds 32-bit words, so has to contain half as many -- entries as there are 16-bit flash words. constant C_RAM_BUFFER_ADDR_WIDTH : integer := C_FLASH_IN_SECTOR_ADDR_WIDTH - 1; constant C_RAM_BUFFER_ADDR_MAX : integer := 2**C_RAM_BUFFER_ADDR_WIDTH - 1; signal sector_number : std_logic_vector(C_FLASH_SECTOR_ADDR_WIDTH - 1 downto 0); signal buffer_address : std_logic_vector(C_RAM_BUFFER_ADDR_WIDTH - 1 downto 0); signal is_flash_buffer_open : std_logic; -- signal buffer_access_strobe : std_logic; signal buffer_write_enable : std_logic; signal buffer_data_in : std_logic_vector(31 downto 0); signal buffer_data_out : std_logic_vector(31 downto 0); signal axi_addr : std_logic_vector(31 downto 0); begin -- IPBus address decoder. fabric : entity work.ipbus_fabric_sel generic map ( NSLV => N_SLAVES, SEL_WIDTH => IPBUS_SEL_WIDTH ) port map ( ipb_in => ipb_in, ipb_out => ipb_out, sel => ipbus_sel_flash_interface(ipb_in.ipb_addr), ipb_to_slaves => ipbw, ipb_from_slaves => ipbr ); ------------------------------------------ -- Main control and status register. csr : entity work.ipbus_ctrlreg_v generic map ( N_CTRL => 4, N_STAT => 3 ) port map ( clk => clk, reset => rst, ipbus_in => ipbw(N_SLV_CSR), ipbus_out => ipbr(N_SLV_CSR), q => ctrl, d => stat ); -- Access control signals. access_mode <= ctrl(0)(0); access_size <= ctrl(0)(1); -- Access operation triggers. trigger <= ctrl(0)(2); -- The AXI MUX auto-muxes based on the chosen access settings. axi_sel <= C_AXI_SEL_SECTOR when access_size = C_ACCESS_SIZE_SECTOR else C_AXI_SEL_WORD; -- Some things are only needed for the single-word access. axi_address_word <= ctrl(1); axi_dti_word <= ctrl(2); axi_strobe_word <= ctrl(3)(3 downto 0); axi_tick_word <= ctrl(3)(4); -- Some things are only needed for the full-sector access. sector_number <= ctrl(3)(C_FLASH_SECTOR_ADDR_WIDTH - 1 + 8 downto 8); -- Status signals back. stat(0) <= axi_status; stat(1)(0) <= sector_access_done; stat(2) <= axi_dto_word; ------------------------------------------ -- Make sure the triggers/access strobe is a proper strobe. pulser : entity work.edge_detector port map ( clk => clk, rst => rst, signal_in => trigger, pulse_out => access_strobe ); -- Read and write request strobes. axi_read_word <= access_strobe when (access_mode = C_ACCESS_MODE_READ and access_size = C_ACCESS_SIZE_WORD) else '0'; axi_write_word <= access_strobe when (access_mode = C_ACCESS_MODE_WRITE and access_size = C_ACCESS_SIZE_WORD) else '0'; trigger_read_sector <= access_strobe when (access_mode = C_ACCESS_MODE_READ and access_size = C_ACCESS_SIZE_SECTOR) else '0'; trigger_write_sector <= access_strobe when (access_mode = C_ACCESS_MODE_WRITE and access_size = C_ACCESS_SIZE_SECTOR) else '0'; cdc_reset : entity work.cdc_reset port map ( reset_in => rst, clk_dst => axi_aclk, reset_out => axi_reset ); axi_resetn <= not axi_reset; ------------------------------------------ -- An intermediate buffer for writes into the flash. This allows us -- to do (quite efficient) block transfers into here, and then do -- (reasonably fast) internal writes to the flash itself (instead of -- a terrifyingly slow series of single-register accesses all the -- way through to the flash). -- NOTE: The flash sectors span 128 kB, in 64 kEntries of 16-bit -- half-words. This corresponds to 32 kEntries worth of 32-bit words -- on our interface. buffer_ram : entity work.ipbus_ported_dpram generic map ( ADDR_WIDTH => C_RAM_BUFFER_ADDR_WIDTH, DATA_WIDTH => 32 ) port map ( clk => clk, rst => rst, ipb_in => ipbw(N_SLV_SECTOR_BUFFER), ipb_out => ipbr(N_SLV_SECTOR_BUFFER), rclk => clk,--buffer_access_strobe, we => buffer_write_enable, d => buffer_data_in, q => buffer_data_out, addr => buffer_address ); ------------------------------------------ -- One massive state-machine process to drive the contents moving -- between the buffer RAM and the flash. buffer_access : process(clk) is variable buffer_address_i : unsigned(C_RAM_BUFFER_ADDR_WIDTH - 1 downto 0); begin if rising_edge(clk) then if rst = '1' then fsm_state <= STATE_IDLE; else fsm_state <= fsm_state; is_flash_buffer_open <= is_flash_buffer_open; -- buffer_access_strobe <= buffer_access_strobe; buffer_write_enable <= buffer_write_enable; axi_addr <= axi_addr; axi_strobe_sector <= axi_strobe_sector; axi_dti_sector <= axi_dti_sector; axi_dto_sector <= axi_dto_sector; axi_read_sector <= axi_read_sector; axi_write_sector <= axi_write_sector; sector_access_done <= sector_access_done; case fsm_state is when STATE_IDLE => buffer_address_i := (others => '0'); is_flash_buffer_open <= '0'; -- buffer_access_strobe <= '0'; buffer_write_enable <= '0'; axi_write_sector <= '0'; sector_access_done <= '1'; if trigger_read_sector = '1' then fsm_state <= STATE_BUFFER_READ_INIT; end if; if trigger_write_sector = '1' then fsm_state <= STATE_BUFFER_WRITE_INIT; end if; ------------ -- Read flash sector to RAM buffer. ------------ when STATE_BUFFER_READ_INIT => buffer_write_enable <= '1'; sector_access_done <= '0'; fsm_state <= STATE_SECTOR_READ_0; when STATE_SECTOR_READ_0 => -- NOTE: This is the flash word address. We are stepping -- through a 32-bit wide buffer, so each step covers two -- 16-bit flash words. axi_addr(31 downto C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH) <= (others => '0'); axi_addr(C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto C_FLASH_IN_SECTOR_ADDR_WIDTH) <= sector_number; axi_addr(C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto 0) <= std_logic_vector(buffer_address_i) & '0'; axi_strobe_sector <= x"f"; axi_read_sector <= '1'; fsm_state <= STATE_SECTOR_READ_1; when STATE_SECTOR_READ_1 => axi_read_sector <= '0'; if axi_read_sector = '0' and axi_done = '1' then fsm_state <= STATE_RAM_WRITE_0; end if; when STATE_RAM_WRITE_0 => buffer_data_in <= axi_dto_sector; fsm_state <= STATE_RAM_WRITE_1; when STATE_RAM_WRITE_1 => -- buffer_access_strobe <= '1'; fsm_state <= STATE_RAM_WRITE_2; when STATE_RAM_WRITE_2 => -- buffer_access_strobe <= '0'; if buffer_address_i = C_RAM_BUFFER_ADDR_MAX then fsm_state <= STATE_BUFFER_ACCESS_DONE; else buffer_address_i := buffer_address_i + 1; fsm_state <= STATE_SECTOR_READ_0; end if; ------------ -- Write flash sector from RAM buffer. ------------ when STATE_BUFFER_WRITE_INIT => sector_access_done <= '0'; fsm_state <= STATE_RAM_READ_0; when STATE_RAM_READ_0 => -- Trigger read from buffer RAM. -- buffer_access_strobe <= '1'; fsm_state <= STATE_RAM_READ_1; when STATE_RAM_READ_1 => -- buffer_access_strobe <= '0'; if is_flash_buffer_open = '0' then fsm_state <= STATE_BUFFER_OPEN_00; else fsm_state <= STATE_WORD_WRITE_0; end if; when STATE_BUFFER_OPEN_00 => -- Unlock flash 1/2. axi_addr <= x"00000" & x"555"; axi_strobe_sector <= x"c"; axi_dti_sector <= x"00" & x"aa" & x"0000"; axi_write_sector <= '1'; fsm_state <= STATE_BUFFER_OPEN_01; when STATE_BUFFER_OPEN_01 => axi_write_sector <= '0'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_BUFFER_OPEN_10; end if; when STATE_BUFFER_OPEN_10 => -- Unlock flash 2/2. axi_addr <= x"00000" &x"2aa"; axi_strobe_sector <= x"3"; axi_dti_sector <= x"000000" & x"55"; axi_write_sector <= '1'; fsm_state <= STATE_BUFFER_OPEN_11; when STATE_BUFFER_OPEN_11 => axi_write_sector <= '0'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_BUFFER_OPEN_20; end if; when STATE_BUFFER_OPEN_20 => -- 'Write to buffer' command. -- NOTE: This is the sector address. axi_addr(31 downto C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH) <= (others => '0'); axi_addr(C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto C_FLASH_IN_SECTOR_ADDR_WIDTH) <= sector_number; axi_addr(C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto 0) <= (others => '0'); axi_strobe_sector <= x"3"; axi_dti_sector <= x"000000" & x"25"; axi_write_sector <= '1'; fsm_state <= STATE_BUFFER_OPEN_21; when STATE_BUFFER_OPEN_21 => axi_write_sector <= '0'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_BUFFER_OPEN_30; end if; when STATE_BUFFER_OPEN_30 => -- Write the number of flash words in the buffer minus 1 -- (to the same address as above). axi_addr <= axi_addr; axi_strobe_sector <= x"3"; axi_dti_sector <= x"0000" & std_logic_vector(to_unsigned(C_FLASH_BUFFER_SIZE - 1, 16)); axi_write_sector <= '1'; fsm_state <= STATE_BUFFER_OPEN_31; when STATE_BUFFER_OPEN_31 => axi_write_sector <= '0'; is_flash_buffer_open <= '1'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_WORD_WRITE_0; end if; when STATE_WORD_WRITE_0 => -- NOTE: This is the flash word address. axi_addr(31 downto C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH) <= (others => '0'); axi_addr(C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto C_FLASH_IN_SECTOR_ADDR_WIDTH) <= sector_number; axi_addr(C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto 0) <= std_logic_vector(buffer_address_i) & '0'; axi_strobe_sector <= x"f"; axi_dti_sector <= buffer_data_out; axi_write_sector <= '1'; fsm_state <= STATE_WORD_WRITE_1; when STATE_WORD_WRITE_1 => axi_write_sector <= '0'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_BUFFER_CHECK; end if; when STATE_BUFFER_CHECK => -- Every 512 bytes (so every 128 32-bit RAM entries) we -- need a fresh flash buffer. if buffer_address_i(C_FLASH_BUFFER_ADDR_WIDTH - 2 downto 0) = C_FLASH_BUFFER_ADDR_MAX / 2 then fsm_state <= STATE_BUFFER_WRITE_0; else fsm_state <= STATE_CHECK_LOOP; end if; when STATE_BUFFER_WRITE_0 => -- 'Program buffer to flash' command. -- NOTE: This is the sector address. axi_addr(31 downto C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH) <= (others => '0'); axi_addr(C_FLASH_SECTOR_ADDR_WIDTH + C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto C_FLASH_IN_SECTOR_ADDR_WIDTH) <= sector_number; axi_addr(C_FLASH_IN_SECTOR_ADDR_WIDTH - 1 downto 0) <= (others => '0'); axi_strobe_sector <= x"3"; axi_dti_sector <= x"000000" & x"29"; axi_write_sector <= '1'; fsm_state <= STATE_BUFFER_WRITE_1; when STATE_BUFFER_WRITE_1 => axi_write_sector <= '0'; is_flash_buffer_open <= '0'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_STATUS_READ_0; end if; when STATE_STATUS_READ_0 => -- Issue 'Read status register' command. axi_addr <= x"00000" & x"555"; axi_strobe_sector <= x"c"; axi_dti_sector <= x"00" & x"70" & x"0000"; axi_write_sector <= '1'; fsm_state <= STATE_STATUS_READ_1; when STATE_STATUS_READ_1 => axi_write_sector <= '0'; if axi_write_sector = '0' and axi_done = '1' then fsm_state <= STATE_STATUS_READ_2; end if; when STATE_STATUS_READ_2 => -- Read status register. axi_addr <= x"00000" & x"000"; axi_strobe_sector <= x"3"; axi_read_sector <= '1'; fsm_state <= STATE_STATUS_READ_3; when STATE_STATUS_READ_3 => axi_read_sector <= '0'; if axi_read_sector = '0' and axi_done = '1' then fsm_state <= STATE_STATUS_READ_4; end if; when STATE_STATUS_READ_4 => if axi_dto_sector(7) = '1' then fsm_state <= STATE_CHECK_LOOP; else fsm_state <= STATE_STATUS_READ_0; end if; when STATE_CHECK_LOOP => -- Check if we're done yet. if buffer_address_i = C_RAM_BUFFER_ADDR_MAX then fsm_state <= STATE_BUFFER_ACCESS_DONE; else buffer_address_i := buffer_address_i + 1; fsm_state <= STATE_RAM_READ_0; end if; ------------ when STATE_BUFFER_ACCESS_DONE => -- buffer_access_strobe <= '0'; buffer_write_enable <= '0'; sector_access_done <= '1'; fsm_state <= STATE_IDLE; ------------ when others => -- Just in case. fsm_state <= STATE_IDLE; end case; end if; buffer_address <= std_logic_vector(buffer_address_i); end if; end process; -- Convert from 16-bit flash word address to byte address for our -- AXI bridge. axi_address_sector <= axi_addr(axi_addr'high - 1 downto 0) & '0'; axi_tick_sector <= '0'; -- DEBUG DEBUG DEBUG fsm_state_val <= "000000000000000000000000000001" when fsm_state = STATE_IDLE else "000000000000000000000000000010" when fsm_state = STATE_BUFFER_READ_INIT else "000000000000000000000000000100" when fsm_state = STATE_SECTOR_READ_0 else "000000000000000000000000001000" when fsm_state = STATE_SECTOR_READ_1 else "000000000000000000000000010000" when fsm_state = STATE_RAM_WRITE_0 else "000000000000000000000000100000" when fsm_state = STATE_RAM_WRITE_1 else "000000000000000000000001000000" when fsm_state = STATE_RAM_WRITE_2 else "000000000000000000000010000000" when fsm_state = STATE_BUFFER_WRITE_INIT else "000000000000000000000100000000" when fsm_state = STATE_BUFFER_OPEN_00 else "000000000000000000001000000000" when fsm_state = STATE_BUFFER_OPEN_01 else "000000000000000000010000000000" when fsm_state = STATE_BUFFER_OPEN_10 else "000000000000000000100000000000" when fsm_state = STATE_BUFFER_OPEN_11 else "000000000000000001000000000000" when fsm_state = STATE_BUFFER_OPEN_20 else "000000000000000010000000000000" when fsm_state = STATE_BUFFER_OPEN_21 else "000000000000000100000000000000" when fsm_state = STATE_BUFFER_OPEN_30 else "000000000000001000000000000000" when fsm_state = STATE_BUFFER_OPEN_31 else "000000000000010000000000000000" when fsm_state = STATE_RAM_READ_0 else "000000000000100000000000000000" when fsm_state = STATE_RAM_READ_1 else "000000000001000000000000000000" when fsm_state = STATE_WORD_WRITE_0 else "000000000010000000000000000000" when fsm_state = STATE_WORD_WRITE_1 else "000000000100000000000000000000" when fsm_state = STATE_BUFFER_CHECK else "000000001000000000000000000000" when fsm_state = STATE_BUFFER_WRITE_0 else "000000010000000000000000000000" when fsm_state = STATE_BUFFER_WRITE_1 else "000000100000000000000000000000" when fsm_state = STATE_STATUS_READ_0 else "000001000000000000000000000000" when fsm_state = STATE_STATUS_READ_1 else "000010000000000000000000000000" when fsm_state = STATE_STATUS_READ_2 else "000100000000000000000000000000" when fsm_state = STATE_STATUS_READ_3 else "001000000000000000000000000000" when fsm_state = STATE_STATUS_READ_4 else "010000000000000000000000000000" when fsm_state = STATE_CHECK_LOOP else "100000000000000000000000000000" when fsm_state = STATE_BUFFER_ACCESS_DONE else (others => '0'); -- DEBUG DEBUG DEBUG end ------------------------------------------ -- The interface between our own signals and the AXI bus to the -- memory controller. axi4lite_interface : entity work.axi4lite_interface port map ( -- User interface side. reset => rst, usr_clock => clk, usr_add => axi_rq_add, usr_strb => axi_rq_strb, usr_dti => axi_rq_dti, usr_dto => axi_rtn_dto, usr_rdreq => axi_rq_rd, usr_wrreq => axi_rq_wr, usr_axi_tick => axi_tick, axi_status => axi_status, axi_done => axi_done, -- AXI side. s_axi_clock => axi_aclk, s_axi_awaddr => axi_mem_awaddr, s_axi_awvalid => axi_mem_awvalid, s_axi_awready => axi_mem_awready, s_axi_wdata => axi_mem_wdata, s_axi_wstrb => axi_mem_wstrb, s_axi_size => axi_mem_size, s_axi_wvalid => axi_mem_wvalid, s_axi_wready => axi_mem_wready, s_axi_bresp => "00", s_axi_bvalid => axi_mem_bvalid, s_axi_bready => axi_mem_bready, s_axi_araddr => axi_mem_araddr, s_axi_arvalid => axi_mem_arvalid, s_axi_arready => axi_mem_arready, s_axi_rdata => axi_mem_rdata, s_axi_rresp => "00", s_axi_rvalid => axi_mem_rvalid, s_axi_rready => axi_mem_rready ); -- MUX between the 'word_' and the 'sector_' access signals. axi_rq_add <= axi_address_word when axi_sel = C_AXI_SEL_WORD else axi_address_sector; axi_rq_strb <= axi_strobe_word when axi_sel = C_AXI_SEL_WORD else axi_strobe_sector; axi_tick <= axi_tick_word when axi_sel = C_AXI_SEL_WORD else axi_tick_sector; axi_rq_rd <= axi_read_word when axi_sel = C_AXI_SEL_WORD else axi_read_sector; axi_rq_wr <= axi_write_word when axi_sel = C_AXI_SEL_WORD else axi_write_sector; axi_rq_dti <= axi_dti_word when axi_sel = C_AXI_SEL_WORD else axi_dti_sector; axi_dto_word <= axi_rtn_dto when axi_sel = C_AXI_SEL_WORD else (others => '0'); axi_dto_sector <= axi_rtn_dto when axi_sel = C_AXI_SEL_SECTOR else (others => '0'); ------------------------------------------ -- The STARTUPE3 primitive gives us access to the FPGA -- PROM/configuration pins. startup : STARTUPE3 generic map ( PROG_USR => "FALSE" ) port map ( cfgclk => open, cfgmclk => open, di => flash_data_in_startup, eos => open, --flash_eos, preq => open, do => flash_data_out_startup, dts => flash_data_tristate_startup, fcsbo => flash_cen, fcsbts => '0', gsr => '0', gts => '0', keyclearb => '1', pack => '1', usrcclko => '0', usrcclkts => '0', usrdoneo => '1', usrdonets => '1' ); ------------------------------------------ -- The external memory controller gives us access to the PROM holding -- the FPGA image. flash_controller : entity work.axi_emc_flash_controller port map ( s_axi_aclk => axi_aclk, s_axi_aresetn => axi_resetn, rdclk => axi_aclk, s_axi_mem_awid => "0000", s_axi_mem_awaddr => axi_mem_awaddr, s_axi_mem_awlen => "00000000", s_axi_mem_awsize => axi_mem_size, s_axi_mem_awburst => "01", s_axi_mem_awlock => '0', s_axi_mem_awcache => "0000", s_axi_mem_awprot => "000", s_axi_mem_awvalid => axi_mem_awvalid, s_axi_mem_awready => axi_mem_awready, s_axi_mem_wdata => axi_mem_wdata, s_axi_mem_wstrb => axi_mem_wstrb, s_axi_mem_wlast => '1', s_axi_mem_wvalid => axi_mem_wvalid, s_axi_mem_wready => axi_mem_wready, s_axi_mem_bvalid => axi_mem_bvalid, s_axi_mem_bready => axi_mem_bready, s_axi_mem_arid => "0000", s_axi_mem_araddr => axi_mem_araddr, s_axi_mem_arlen => "00000000", s_axi_mem_arsize => axi_mem_size, s_axi_mem_arburst => "01", s_axi_mem_arlock => '0', s_axi_mem_arcache => "0000", s_axi_mem_arprot => "000", s_axi_mem_arvalid => axi_mem_arvalid, s_axi_mem_arready => axi_mem_arready, s_axi_mem_rdata => axi_mem_rdata, s_axi_mem_rvalid => axi_mem_rvalid, s_axi_mem_rready => axi_mem_rready, mem_dq_i(15 downto 4) => flash_data(15 downto 4), mem_dq_i(3 downto 0) => flash_data_in_startup(3 downto 0), mem_dq_o(15 downto 4) => flash_data_out(15 downto 4), mem_dq_o(3 downto 0) => flash_data_out_startup, mem_dq_t(15 downto 4) => flash_data_tristate(15 downto 4), mem_dq_t(3 downto 0) => flash_data_tristate_startup, mem_a(31 downto 0) => flash_add, mem_cen(0) => flash_cen, mem_oen(0) => flash_oen, mem_wen => flash_wen, mem_wait(0) => '0' ); ------------------------------------------ flash_data_bus : for i in 4 to 15 generate flash_data(i) <= flash_data_out(i) when flash_data_tristate(i) = '0' else 'Z'; end generate; end behavioral; --======================================================================