----------------------------------------------------------------------- -- $Header: D:\usr\cvsroot/VHDL/lib/misc/flash_port_wb.vhd,v 1.2 2010/03/13 11:06:43 Jens Exp $ ----------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use work.async_types.all; ------------------------------------------------------------------ entity flash_port_wb is Generic ( f_sysclk : real := 100.0; addr_width : natural := 32; data_width : natural := 32; async_timespec : async_timespec_t ); Port ( CLK_I : in STD_LOGIC; RST_I : in STD_LOGIC; CYC_I : in STD_LOGIC; STB_I : in STD_LOGIC; WE_I : in STD_LOGIC; ACK_O : out STD_LOGIC; SRDY_O : out STD_LOGIC; MRDY_I : in STD_LOGIC; ADDR_I : in unsigned(31 downto 0); DAT_I : in unsigned(31 downto 0); DAT_O : out unsigned(31 downto 0); port_bsyi : in std_logic; port_bsyo : out std_logic; port_a : out unsigned(addr_width-1 downto 0); port_di : in unsigned(data_width-1 downto 0); port_do : out unsigned(data_width-1 downto 0); port_d_drv : out STD_LOGIC; port_wr : out STD_LOGIC; port_rd : out STD_LOGIC; flash_cs : out std_logic; flash_rst : out std_logic ); end flash_port_wb; architecture Behavioral of flash_port_wb is type async_t is record cs : std_logic; wr : std_logic; rd : std_logic; rst : std_logic; drive_d : std_logic; end record; type async_state_t is (start, reset, idle, go, leadin_rd, read, leadin_wr, write, leadout_rd, leadout_wr, release); signal s, sn : async_state_t; signal as : async_t; signal ack : std_logic; signal cc_rst : std_logic; signal cycle_cnt : natural range 0 to 31; signal cycle_reload : natural range 0 to 31; signal rdy : std_logic; signal rdyo : std_logic; signal en : std_logic; signal we_reg : std_logic; signal data_reg : unsigned(data_width-1 downto 0); signal addr_reg : unsigned(addr_width-1 downto 0); ------------------------------------------------------------------ begin SRDY_O <= CYC_I and rdyo; en <= CYC_I and STB_I; port_a <= addr_reg; port_do <= data_reg; port_d_drv <= as.drive_d; port_wr <= (not async_timespec.pol_we) xor as.wr; port_rd <= (not async_timespec.pol_oe) xor as.rd; proc_cycle_counter: process(CLK_I) begin if rising_edge(CLK_I) then if cc_rst = '1' then cycle_cnt <= cycle_reload; elsif cycle_cnt /= 0 then cycle_cnt <= cycle_cnt - 1; end if; end if; end process; ------------------------------------------------------------------ proc_state_next: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then s <= start; else s <= sn; end if; end if; end process; proc_state: process(s, cycle_cnt, en, we_reg, port_bsyi) begin cycle_reload <= to_cycles(async_timespec.T_pulse_rst, f_sysclk); cc_rst <= '0'; as.rst <= '0'; as.cs <= '0'; as.wr <= '0'; as.rd <= '0'; as.drive_d <= '0'; ack <= '0'; rdy <= '0'; port_bsyo <= '1'; sn <= s; case s is when start => cc_rst <= '1'; sn <= reset; when reset => as.rst <= '1'; if cycle_cnt = 0 then sn <= idle; end if; when idle => port_bsyo <= '0'; rdy <= '1'; if en = '1' then sn <= go; end if; when go => port_bsyo <= '0'; if port_bsyi = '0' then as.cs <= '1'; cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_leadin, f_sysclk)-1; if we_reg = '0' then sn <= leadin_rd; else sn <= leadin_wr; end if; end if; when leadin_rd => as.cs <= '1'; if cycle_cnt = 0 then cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_pulse_rd, f_sysclk)-1; as.rd <= '1'; sn <= read; end if; when leadin_wr => as.cs <= '1'; if cycle_cnt = 0 then cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_pulse_wr, f_sysclk)-1; as.wr <= '1'; as.drive_d <= '1'; sn <= write; end if; when read => as.cs <= '1'; as.rd <= '1'; if cycle_cnt = 0 then cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_leadout, f_sysclk)-1; -- as.rd <= '0'; sn <= leadout_rd; ack <= '1'; end if; when write => as.drive_d <= '1'; as.cs <= '1'; as.wr <= '1'; if cycle_cnt = 0 then as.wr <= '0'; cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_leadout, f_sysclk)-1; sn <= leadout_wr; -- ack <= '1'; end if; when leadout_rd => as.cs <= '1'; if cycle_cnt = 0 then cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_release, f_sysclk)-1; sn <= release; as.cs <= '0'; end if; when leadout_wr => as.cs <= '1'; as.drive_d <= '1'; if cycle_cnt = 0 then cc_rst <= '1'; cycle_reload <= to_cycles(async_timespec.T_release, f_sysclk)-1; sn <= release; as.cs <= '0'; end if; when release => if cycle_cnt = 0 then sn <= idle; end if; when others => sn <= idle; end case; end process; ------------------------------------------------------------------ output_ctrl: process(CLK_I) begin if rising_edge(CLK_I) then flash_cs <= (not async_timespec.pol_cs) xor as.cs; flash_rst <= (not async_timespec.pol_rst) xor as.rst; end if; end process; ------------------------------------------------------------------ din_register: process(CLK_I) begin if rising_edge(CLK_I) then if as.rd = '1' then DAT_O(data_width-1 downto 0) <= port_di; end if; end if; end process; ------------------------------------------------------------------ data_register: process(CLK_I) begin if rising_edge(CLK_I) then if en = '1' and rdy = '1' then we_reg <= WE_I; data_reg <= DAT_I(data_width-1 downto 0); end if; end if; end process; ------------------------------------------------------------------ addr_register: process(CLK_I) begin if rising_edge(CLK_I) then if en = '1' and rdy = '1' then addr_reg <= ADDR_I(addr_width-1 downto 0); end if; end if; end process; ------------------------------------------------------------------ output_SRDY: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then rdyo <= '1'; elsif en = '1' then rdyo <= rdy and not rdyo; end if; end if; end process; ------------------------------------------------------------------ output_ACK: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then ACK_O <= '0'; else ACK_O <= ack; end if; end if; end process; ------------------------------------------------------------------ end Behavioral;