library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.flashrom_pkg.all; entity flashrom_controller is port( clk : in std_logic; rst : in std_logic; clr : in std_logic; -- Control IF ready : out std_logic; -- The controller is ready to accept commands page : in std_logic_vector(FLASHROM_ADDR_WIDTH - 1 downto 0); sync_stb : in std_logic; -- Synchronize current memory page with chip, only sampled when ready load_stb : in std_logic; -- Load page into local buffer, only sampled when ready status_update_stb : in std_logic; -- Update status vector status : out std_logic_vector(31 downto 0); -- value of the status register (update using status_update_stb) info : out std_logic_vector(31 downto 0); -- value of the information register (updated on reset) -- Data IF data_in : in std_logic_vector(7 downto 0); data_in_valid : in std_logic; data_out : out std_logic_vector(7 downto 0); data_out_valid : out 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 ); end entity flashrom_controller; architecture RTL of flashrom_controller is constant spif_max_word_length : integer := 32; constant max_dummy_bits : integer := 16; type state_t is (INIT, GETINFO, IDLE); signal state : state_t; signal spif_data_in_valid : std_logic; signal spif_data_in : std_logic_vector(spif_max_word_length - 1 downto 0); signal spif_data_in_length : integer range 0 to spif_max_word_length; signal spif_data_next : std_logic; signal spif_data_out : std_logic_vector(spif_max_word_length - 1 downto 0); signal spif_data_out_valid : std_logic; signal spif_data_out_length : integer range 0 to spif_max_word_length; signal words_sent : integer range 0 to 511; signal spif_data_out_dummy_bits : integer range 0 to max_dummy_bits; signal spif_transmission_active : std_logic; begin spi_wp_n <= '1'; flashrom_spi_inst : entity work.flashrom_spi generic map( clk_divider => 2, max_word_length => spif_max_word_length, max_dummy_bits => max_dummy_bits) port map( clk => clk, rst => rst, clr => clr, spi_si => spi_si, spi_so => spi_so, spi_sck => spi_sck, spi_cs_n => spi_cs_n, data_in_valid => spif_data_in_valid, data_in => spif_data_in, data_in_length => spif_data_in_length, data_next => spif_data_next, data_out => spif_data_out, data_out_valid => spif_data_out_valid, data_out_length => spif_data_out_length, data_out_dummy_bits => spif_data_out_dummy_bits, transmission_active => spif_transmission_active); flashrom_controller_p : process(clk, rst) is procedure default_state is begin spi_reset_n <= '1'; spif_data_in_valid <= '0'; end procedure default_state; procedure reset_state is begin default_state; state <= INIT; spi_reset_n <= '0'; words_sent <= 0; spif_data_in <= (others => '0'); spif_data_in_length <= 0; spif_data_out_length <= 0; spif_data_out_dummy_bits <= 0; end procedure reset_state; begin if rst = '1' then reset_state; elsif rising_edge(clk) then default_state; if clr = '1' then reset_state; else case state is when INIT => words_sent <= 0; state <= GETINFO; when GETINFO => spif_data_in_length <= 16; -- Other bits after OpCode are don't care, so just repeat OPC spif_data_out_length <= 32; spif_data_out_dummy_bits <= 8; spif_data_in_valid <= '1'; spif_data_in <= FLASHROM_COMMAND_MANUFACTURER_ID & padBits(spif_data_in, FLASHROM_COMMAND_MANUFACTURER_ID); if spif_data_out_valid = '1' then info <= spif_data_out; state <= IDLE; spif_data_in_valid <= '0'; end if; when IDLE => null; end case; end if; end if; end process flashrom_controller_p; end architecture RTL;