Files
vhdl/lib/spi/src/spi_flash_wb.vhd
T
jens ed3a943777 [spi_flash_wb.vhd]
- removed register interface
- first write data, then command

git-svn-id: http://moon:8086/svn/vhdl/trunk@1302 cc03376c-175c-47c8-b038-4cd826a8556b
2015-06-13 13:52:35 +00:00

253 lines
5.5 KiB
VHDL

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
LIBRARY WORK;
USE WORK.spi_types.all;
ENTITY spi_flash_wb IS
Generic
(
FLASH_ADDR_BITS : natural := 24;
CACHE_ADDR_BITS : natural := 8
);
Port
(
CLK_I : in STD_LOGIC;
RST_I : in STD_LOGIC;
INT_O : out STD_LOGIC;
CYC_I : in STD_LOGIC;
STB_I : in STD_LOGIC;
SEL_I : in unsigned(3 downto 0);
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);
spi_hold : in std_logic;
spi_ss : out std_logic;
spi_clk : out std_logic;
spi_miso : in std_logic;
spi_mosi : out std_logic
);
END spi_flash_wb;
ARCHITECTURE rtl OF spi_flash_wb IS
type state_t is (reset, idle, spi_cmd, spi_data, cache_fill_start, cache_fill, finish);
-- Signals for UART connections
signal mst_cmd : cmd_t;
signal mst_cmd_vld : std_logic;
signal mst_cmd_rdy : std_logic;
signal mst_shift_en : std_logic;
signal mst_din_vld : std_logic;
signal mst_din_rdy : std_logic;
signal mst_ctrl : ctrl_t;
signal mst_status : status_t;
signal mst_din : unsigned(31 downto 0);
signal mst_dout : unsigned(31 downto 0);
signal mst_dout_re : std_logic;
signal mst_dout_vld : std_logic;
signal fill_addr : unsigned(CACHE_ADDR_BITS-1 downto 2);
signal data_ram_addr_rd : unsigned(CACHE_ADDR_BITS-1 downto 2);
signal word_addr_reg : unsigned(CACHE_ADDR_BITS-1 downto 2);
signal tag_we : std_logic;
signal tag_reg : unsigned(FLASH_ADDR_BITS-1 downto CACHE_ADDR_BITS);
signal tag_valid : std_logic;
signal tag_match : std_logic;
signal state : state_t;
signal state_next : state_t;
signal SRDY_mem : std_logic;
signal ACK_mem : std_logic;
signal DAT_mem : unsigned(31 downto 0);
signal data_vld : std_logic;
begin
mst_ctrl.clk_div <= to_unsigned(0, 8);
mst_ctrl.cpol <= '0';
mst_ctrl.cpha <= '0';
mst_ctrl.msb_first <= '1';
mst_dout_re <= mst_dout_vld;
mst_shift_en <= not spi_hold;
mst_cmd <= to_cmd(32 + 8 * 2**CACHE_ADDR_BITS, 32);
mst_din <= X"03" & ADDR_I(FLASH_ADDR_BITS-1 downto CACHE_ADDR_BITS) & (CACHE_ADDR_BITS-1 downto 0 => '0');
INT_O <= '0';
ACK_O <= ACK_mem;
DAT_O <= DAT_mem;
SRDY_O <= SRDY_mem;
tag_match <= tag_valid when ADDR_I(tag_reg'range) = tag_reg else '0';
data_ram_addr_rd <= word_addr_reg when tag_we = '1' else ADDR_I(CACHE_ADDR_BITS-1 downto 2);
inst_spi_master : entity work.spi_master
GENERIC MAP
(
WORD_WIDTH => 32,
CAT_FIFO_DEPTH => 4,
DATA_FIFO_DEPTH => 4
)
PORT MAP
(
rst => RST_I,
clk => CLK_I,
cmd_vld => mst_cmd_vld,
cmd_rdy => mst_cmd_rdy,
cmd => mst_cmd,
din_vld => mst_din_vld,
din_rdy => mst_din_rdy,
din => mst_din,
dout_re => mst_dout_re,
dout_vld => mst_dout_vld,
dout => mst_dout,
shift_en => mst_shift_en,
mosi => spi_mosi,
miso => spi_miso,
sclk => spi_clk,
mso => spi_ss,
ctrl => mst_ctrl,
status => mst_status
);
inst_data_ram : entity work.dpram_1w1r2c_ra
GENERIC MAP
(
addr_width => CACHE_ADDR_BITS-2,
data_width => 32
)
PORT MAP
(
clk_a => CLK_I,
clk_b => CLK_I,
re_b => '1',
we_a => mst_dout_vld,
addr_a => fill_addr,
addr_b => data_ram_addr_rd,
din_a => mst_dout,
dout_b => DAT_mem
);
word_addr_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if (CYC_I and STB_I and SRDY_mem and not WE_I) = '1' then
word_addr_reg <= ADDR_I(CACHE_ADDR_BITS-1 downto 2);
end if;
end if;
end process;
read_cache_ack:
process(CLK_I)
begin
if rising_edge(CLK_I) then
ACK_mem <= data_vld;
end if;
end process;
tag_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
tag_valid <= '0';
elsif tag_we = '1' then
tag_valid <= '1';
tag_reg <= ADDR_I(tag_reg'range);
end if;
end if;
end process;
fill_addr_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if mst_cmd_vld = '1' then
fill_addr <= (others => '0');
elsif mst_dout_vld = '1' then
fill_addr <= fill_addr + 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
state <= reset;
else
state <= state_next;
end if;
end if;
end process;
proc_fsm:
process(state, CYC_I, STB_I, WE_I, tag_match, mst_cmd_rdy, mst_din_rdy, mst_status)
begin
state_next <= state;
SRDY_mem <= '0';
mst_cmd_vld <= '0';
mst_din_vld <= '0';
tag_we <= '0';
data_vld <= '0';
case state is
when reset =>
state_next <= idle;
when idle =>
SRDY_mem <= CYC_I;
if (CYC_I and STB_I and not WE_I) = '1' then
if tag_match = '0' then
state_next <= spi_data;
else
data_vld <= '1';
end if;
end if;
when spi_data =>
mst_din_vld <= '1';
if mst_din_rdy = '1' then
state_next <= spi_cmd;
end if;
when spi_cmd =>
mst_cmd_vld <= '1';
if mst_cmd_rdy = '1' then
state_next <= cache_fill_start;
end if;
when cache_fill_start =>
if mst_status.xfer_busy = '1' then
state_next <= cache_fill;
end if;
when cache_fill =>
if mst_status.xfer_busy = '0' then
state_next <= finish;
end if;
when finish =>
tag_we <= '1';
data_vld <= '1';
state_next <= idle;
when others =>
state_next <= idle;
end case;
end process;
end rtl;