From c7eed7504da2780d054c5fdd0ca84c670cfbc3bb Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 13 Jun 2015 09:57:36 +0000 Subject: [PATCH] [spi_flash_wb.vhd] - added caching git-svn-id: http://moon:8086/svn/vhdl/trunk@1296 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/spi/src/spi_flash_wb.vhd | 198 ++++++++++++++++++++++++++------ lib/spi/src/tb_spi_flash_wb.vhd | 51 ++++++++ 2 files changed, 217 insertions(+), 32 deletions(-) diff --git a/lib/spi/src/spi_flash_wb.vhd b/lib/spi/src/spi_flash_wb.vhd index 9b9bdc6..c0b410f 100644 --- a/lib/spi/src/spi_flash_wb.vhd +++ b/lib/spi/src/spi_flash_wb.vhd @@ -36,6 +36,8 @@ 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; @@ -50,22 +52,37 @@ ARCHITECTURE rtl OF spi_flash_wb IS signal mst_dout : unsigned(31 downto 0); signal mst_dout_re : std_logic; signal mst_dout_vld : std_logic; - signal word_addr : unsigned(CACHE_ADDR_BITS-1 downto 0); + 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 cache_miss : std_logic; signal register_access : std_logic; + + signal state : state_t; + signal state_next : state_t; + + signal ACK_mem : std_logic; + signal ACK_reg : std_logic; + signal DAT_mem : unsigned(31 downto 0); + signal DAT_reg : unsigned(31 downto 0); begin + mst_dout_re <= '1'; mst_shift_en <= not spi_hold; - - SRDY_O <= CYC_I; + mst_cmd <= to_cmd(2080, 32); + mst_din <= X"03" & ADDR_I(FLASH_ADDR_BITS-1 downto CACHE_ADDR_BITS) & X"00"; INT_O <= '0'; - - tag_match <= '1' when ADDR_I(tag_reg'range) = tag_reg else '0'; - cache_miss <= CYC_I and STB_I and not WE_I and not tag_match; - register_access <= CYC_I and STB_I and ADDR_I(FLASH_ADDR_BITS); + ACK_O <= ACK_mem or ACK_reg; + DAT_O <= DAT_reg when ACK_reg = '1' else DAT_mem; + + tag_match <= tag_valid when ADDR_I(tag_reg'range) = tag_reg else '0'; + register_access <= ADDR_I(FLASH_ADDR_BITS); + + 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 @@ -97,33 +114,152 @@ inst_spi_master : entity work.spi_master ); +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 not register_access 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 <= (CYC_I and STB_I and not register_access and not WE_I and tag_match) or tag_we; + 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, register_access) +begin + state_next <= state; + SRDY_O <= CYC_I; + mst_cmd_vld <= '0'; + mst_din_vld <= '0'; + tag_we <= '0'; + case state is + + when reset => + state_next <= idle; + + when idle => + if (CYC_I and STB_I and not WE_I and not register_access) = '1' then + if tag_match = '0' then + state_next <= spi_cmd; + end if; + end if; + + when spi_cmd => + mst_cmd_vld <= '1'; + if mst_cmd_rdy = '1' then + state_next <= spi_data; + end if; + + when spi_data => + mst_din_vld <= '1'; + if mst_din_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'; + state_next <= idle; + + when others => + state_next <= idle; + + end case; +end process; + ------------------------------------------------------------------ registers_write: process(CLK_I) begin if rising_edge(CLK_I) then - mst_cmd_vld <= '0'; - mst_din_vld <= '0'; if RST_I = '1' then - mst_ctrl.clk_div <= to_unsigned(100, 8); + mst_ctrl.clk_div <= to_unsigned(0, 8); mst_ctrl.cpol <= '0'; mst_ctrl.cpha <= '0'; mst_ctrl.msb_first <= '1'; - elsif (register_access and WE_I) = '1' then + elsif (CYC_I and STB_I and register_access and WE_I) = '1' then case ADDR_I(5 downto 2) is when "0000" => - mst_cmd_vld <= DAT_I(0); when "0001" => - mst_cmd.xfer_size <= DAT_I; when "0010" => - mst_cmd.data_size <= DAT_I; when "0011" => - mst_din <= DAT_I; - mst_din_vld <= '1'; when "0100" => mst_ctrl.clk_div <= DAT_I(7 downto 0); @@ -141,32 +277,30 @@ registers_read: process(CLK_I) begin if rising_edge(CLK_I) then - mst_dout_re <= '0'; - ACK_O <= '0'; - if (register_access) = '1' then - ACK_O <= not WE_I; - DAT_O <= (others => '0'); + ACK_reg <= '0'; + if (CYC_I and STB_I and register_access) = '1' then + ACK_reg <= not WE_I; + DAT_reg <= (others => '0'); case ADDR_I(5 downto 2) is when "0000" => - DAT_O(2 downto 0) <= mst_dout_vld & mst_din_rdy & mst_cmd_rdy; - DAT_O(15 downto 8) <= spi_hold & mst_status.rx_valid & mst_status.read_fifo_empty & mst_status.read_fifo_full & mst_status.write_fifo_empty & mst_status.write_fifo_full & mst_status.cmd_fifo_empty & mst_status.cmd_fifo_full; + DAT_reg(2 downto 0) <= mst_dout_vld & mst_din_rdy & mst_cmd_rdy; + DAT_reg(15 downto 8) <= spi_hold & mst_status.xfer_busy & mst_status.read_fifo_empty & mst_status.read_fifo_full & mst_status.write_fifo_empty & mst_status.write_fifo_full & mst_status.cmd_fifo_empty & mst_status.cmd_fifo_full; when "0001" => - DAT_O <= mst_cmd.xfer_size; + DAT_reg <= mst_cmd.xfer_size; when "0010" => - DAT_O <= mst_cmd.data_size; + DAT_reg <= mst_cmd.data_size; when "0011" => - DAT_O <= mst_dout; - mst_dout_re <= not WE_I; + DAT_reg <= mst_dout; when "0100" => - DAT_O(7 downto 0) <= mst_ctrl.clk_div; - DAT_O(8) <= mst_ctrl.cpol; - DAT_O(9) <= mst_ctrl.cpha; - DAT_O(10) <= mst_ctrl.msb_first; + DAT_reg(7 downto 0) <= mst_ctrl.clk_div; + DAT_reg(8) <= mst_ctrl.cpol; + DAT_reg(9) <= mst_ctrl.cpha; + DAT_reg(10) <= mst_ctrl.msb_first; when others => null; end case; diff --git a/lib/spi/src/tb_spi_flash_wb.vhd b/lib/spi/src/tb_spi_flash_wb.vhd index 5f683f2..9f68ec6 100644 --- a/lib/spi/src/tb_spi_flash_wb.vhd +++ b/lib/spi/src/tb_spi_flash_wb.vhd @@ -88,6 +88,13 @@ uut : entity work.spi_flash_wb ); inst_spi_slave: entity work.S25fl064k + GENERIC MAP + ( + UserPreload => TRUE, + mem_file_name => "tb_spi_flash_wb.mem", + screg_file_name => "none" + + ) PORT MAP ( SCK => mst_clk, -- serial clock input SI => mosi, -- serial data input @@ -122,6 +129,50 @@ STIMULUS: process wait until rising_edge(CLK) and ACK_O = '1'; CYC_I <= '0'; + wait for 10*CLK_PERIOD; + wait until rising_edge(CLK); + ADDR_I <= X"0000_0000"; + STB_I <= '1'; + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + wait until rising_edge(CLK) and ACK_O = '1'; + CYC_I <= '0'; + + wait for 10*CLK_PERIOD; + wait until rising_edge(CLK); + ADDR_I <= X"0000_0004"; + STB_I <= '1'; + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + wait until rising_edge(CLK) and ACK_O = '1'; + CYC_I <= '0'; + + wait for 10*CLK_PERIOD; + wait until rising_edge(CLK); + ADDR_I <= X"0000_0100"; + STB_I <= '1'; + CYC_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + wait until rising_edge(CLK) and ACK_O = '1'; + CYC_I <= '0'; + + wait for 10*CLK_PERIOD; + CYC_I <= '1'; + + for i in 0 to 63 loop + ADDR_I <= to_unsigned(4*i, 32); + STB_I <= '1'; + wait until rising_edge(CLK) and SRDY_O = '1'; + STB_I <= '0'; + wait until rising_edge(CLK) and ACK_O = '1'; + + end loop; + wait for 10*CLK_PERIOD; + CYC_I <= '1'; + wait; end process;