library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library ip; use ip.all; entity flashrom_spi is port( clk : in std_logic; spi_clk : in std_logic; rst : in std_logic; -- SPI flash hardware signals spi_si : out std_logic; -- SPI serial in spi_so : in std_logic; -- SPI serial out spi_sck : out std_logic; -- Create clock using PLL, then supply to chip and this module spi_reset_n : out std_logic; -- SPI hard reset spi_cs_n : out std_logic; -- SPI chip select spi_wp_n : out std_logic; -- SPI write protect -- FPGA -> ROM toSpiDataIn : in STD_LOGIC_VECTOR(7 DOWNTO 0); toSpiWrite : in STD_LOGIC; toSpiFull : out STD_LOGIC; -- ROM -> FPGA fromSpiDataOut : out STD_LOGIC_VECTOR(7 DOWNTO 0); fromSpiRead : in STD_LOGIC; fromSpiEmpty : out STD_LOGIC ); end entity flashrom_spi; architecture RTL of flashrom_spi is signal spi_rst : std_logic; signal toSpiRead : STD_LOGIC; signal toSpiDataOut : STD_LOGIC_VECTOR(7 DOWNTO 0); signal toSpiEmpty : STD_LOGIC; signal fromSpiDataIn : STD_LOGIC_VECTOR(7 DOWNTO 0); signal fromSpiWrite : STD_LOGIC; signal fromSpiFull : STD_LOGIC; signal outshifter_cnt : unsigned(2 downto 0); signal outshifter_data : std_logic_vector(7 downto 0); signal inshifter_cnt : unsigned(2 downto 0); signal inshifter_data : std_logic_vector(7 downto 0); signal spi_cs_n_del : std_logic; begin spi_sck <= spi_clk; resetSync : process(rst, spi_clk) is variable cnt : integer range 0 to 1; begin if rst = '1' then cnt := 1; spi_rst <= '1'; elsif rising_edge(spi_clk) then spi_rst <= '1'; if cnt = 0 then spi_rst <= '0'; else cnt := cnt - 1; end if; end if; end process resetSync; -- FPGA -> ROM shifter : process(spi_clk, rst) is variable loaded : std_logic; begin if rst = '1' then outshifter_data <= (others => '0'); outshifter_cnt <= (others => '1'); spi_cs_n <= '1'; toSpiRead <= '0'; loaded := '0'; elsif rising_edge(spi_clk) then -- provide data on falling edge toSpiRead <= '0'; if outshifter_cnt = "101" then if toSpiEmpty = '0' then toSpiRead <= '1'; loaded := '1'; end if; end if; if outshifter_cnt = "111" then if loaded = '1' then loaded := '0'; outshifter_data <= toSpiDataOut; spi_cs_n <= '0'; outshifter_cnt <= "000"; else spi_cs_n <= '1'; --shifter_cnt <= "000"; if toSpiEmpty = '0' then outshifter_cnt <= "101"; end if; end if; else outshifter_cnt <= outshifter_cnt + 1; outshifter_data <= outshifter_data(6 downto 0) & '0'; end if; end if; end process shifter; spi_si <= outshifter_data(7); spiFifo_wb2spi_inst : entity ip.spiFifo port map( aclr => rst, data => toSpiDataIn, rdclk => spi_clk, rdreq => toSpiRead, wrclk => clk, wrreq => toSpiWrite, q => toSpiDataOut, rdempty => toSpiEmpty, wrfull => toSpiFull ); errorHandler_wb : process(clk, rst) is begin if rst = '1' then elsif rising_edge(clk) then if toSpiWrite = '1' and toSpiFull = '1' then -- TODO: ERROR: Fifo full! report "ERROR: SPI transmit FIFO full!" severity failure; end if; end if; end process errorHandler_wb; -- ROM -> FPGA shifter_in : process(spi_clk, rst) is begin if rst = '1' then inshifter_data <= (others => '0'); inshifter_cnt <= (others => '0'); fromSpiWrite <= '0'; spi_cs_n_del <= '1'; elsif rising_edge(spi_clk) then -- sample on rising edge spi_cs_n_del <= spi_cs_n; fromSpiWrite <= '0'; if spi_cs_n = '0' then inshifter_cnt <= inshifter_cnt + 1; inshifter_data <= inshifter_data(6 downto 0) & spi_so; if inshifter_cnt = "111" then fromSpiWrite <= '1'; end if; else inshifter_data <= (others => '0'); inshifter_cnt <= (others => '0'); end if; end if; end process shifter_in; spiFifo_spi2wb_inst : entity ip.spiFifo port map( aclr => rst, data => fromSpiDataIn, rdclk => clk, rdreq => fromSpiRead, wrclk => spi_clk, wrreq => fromSpiWrite, q => fromSpiDataOut, rdempty => fromSpiEmpty, wrfull => fromSpiFull ); fromSpiDataIn <= inshifter_data; end architecture RTL;