+-- Generic flash controller\r
+-- Should be placed between spi_slave and the local logic\r
+-- (see e.g. dirich/thresholds/thresholds.vhd)\r
+--\r
+-- Data in the user flash will be unpacked during boot, the data has the\r
+-- following format:\r
+-- Version : 1 Byte (must be 0x01, otherwise the unpacking will be cancelled)\r
+-- SPI address : 1 Byte\r
+-- SPI data : 2 Bytes in big-endian\r
+--\r
+-- SPI registers:\r
+-- 0x4x : Mapped flash page (16 Bytes)\r
+-- 0x50 : Flash command (see Padiwa manual)\r
+-- Bits 15-13 : Flash command\r
+-- Bits 12-0 : Flash page\r
+-- 0x5C : control register\r
+-- Bit 0 : Enable cfg flash\r
+-- Bit 1 : Master start (starts unpacking = booting)\r
+-- 0x5D-5F : Debug registers\r
+\r
+\r
library ieee;\r
use ieee.std_logic_1164.all;\r
use ieee.numeric_std.all;\r
use work.trb_net_std.all;\r
\r
entity generic_flash_ctrl is\r
+ generic (MASTER_STARTPAGE : std_logic_vector(12 downto 0) := "1" & x"C00");\r
port(\r
CLK : in std_logic;\r
RESET : in std_logic;\r
LOC_ADDR_OUT : out std_logic_vector(7 downto 0);\r
LOC_WRITE_OUT : out std_logic;\r
LOC_READ_OUT : out std_logic;\r
- LOC_READY_IN : in std_logic\r
- \r
+ LOC_READY_IN : in std_logic \r
);\r
end entity;\r
\r
);\r
end component;\r
\r
- --component flashram\r
- -- port (\r
- -- DataInA: in std_logic_vector(7 downto 0);\r
- -- DataInB: in std_logic_vector(7 downto 0);\r
- -- AddressA: in std_logic_vector(3 downto 0);\r
- -- AddressB: in std_logic_vector(3 downto 0);\r
- -- ClockA: in std_logic;\r
- -- ClockB: in std_logic;\r
- -- ClockEnA: in std_logic;\r
- -- ClockEnB: in std_logic;\r
- -- WrA: in std_logic;\r
- -- WrB: in std_logic;\r
- -- ResetA: in std_logic;\r
- -- ResetB: in std_logic;\r
- -- QA: out std_logic_vector(7 downto 0);\r
- -- QB: out std_logic_vector(7 downto 0)\r
- -- );\r
- --end component;\r
-\r
signal reg_SPI_DATA_OUT : std_logic_vector(15 downto 0);\r
signal reg_SPI_READY_OUT : std_logic;\r
signal reg_LOC_DATA_OUT : std_logic_vector(15 downto 0);\r
signal flashram_data_o : std_logic_vector(7 downto 0);\r
\r
signal flash_command : std_logic_vector(2 downto 0);\r
+ signal spi_flash_command : std_logic_vector(2 downto 0);\r
signal flash_page : std_logic_vector(12 downto 0);\r
+ signal spi_flash_page : std_logic_vector(12 downto 0);\r
signal flash_go : std_logic;\r
+ signal spi_flash_go : std_logic;\r
signal flash_busy : std_logic;\r
signal flash_err : std_logic;\r
\r
signal ram_data_i : std_logic_vector(7 downto 0);\r
signal ram_data_o : std_logic_vector(7 downto 0);\r
signal ram_addr_i : std_logic_vector(3 downto 0);\r
-\r
+ signal spi_ram_addr_i : std_logic_vector(3 downto 0);\r
+ \r
signal enable_cfg_flash : std_logic;\r
signal testreg : std_logic_vector(15 downto 0);\r
\r
signal out_delay : std_logic_vector(1 downto 0);\r
\r
+\r
+ type state_type is (IDLE, EnableFLASH1, EnableFLASH2, EnableFLASH3, Start, ReadPage, WaitFlash1, WaitFlash2, ReadRAM, WaitRAM1, WaitRAM2, WaitRAM3, WaitRAM4, WaitRAM5, WriteSPI);\r
+ signal state : state_type := IDLE;\r
+ signal master_running : std_logic;\r
+ signal master_word_counter : std_logic_vector(3 downto 0);\r
+ signal master_flash_page : std_logic_vector(12 downto 0) := "0000000000000";\r
+ signal master_flash_command : std_logic_vector(2 downto 0);\r
+ signal master_flash_go : std_logic;\r
+ signal master_start_reg : std_logic := '0';\r
+ signal clean_master_start_reg : std_logic := '0';\r
+ signal master_DATA_OUT : std_logic_vector(15 downto 0);\r
+ signal master_ADDR_OUT : std_logic_vector(7 downto 0);\r
+ signal master_WRITE_OUT : std_logic;\r
+ \r
+ signal auto_reset : std_logic := '1';\r
+ signal auto_dbg : std_logic := '0';\r
+ signal auto_cnt : std_logic_vector(19 downto 0) := x"00000";\r
\r
begin\r
\r
mem_rd_data => flashram_data_o\r
);\r
\r
-\r
- --ram_data_i <= LOC_DATA_IN(7 downto 0);\r
- --ram_addr_i <= SPI_ADDR_IN(3 downto 0);\r
-\r
LOC_DATA_OUT <= reg_LOC_DATA_OUT;\r
LOC_ADDR_OUT <= reg_LOC_ADDR_OUT;\r
LOC_WRITE_OUT <= reg_LOC_WRITE_OUT;\r
\r
ram_write_i <= '0';\r
ram_data_i <= x"00";\r
- ram_addr_i <= x"0";\r
- flash_go <= '0';\r
+ spi_ram_addr_i <= x"0";\r
+ spi_flash_go <= '0';\r
\r
+ if (clean_master_start_reg = '1') then\r
+ master_start_reg <= '0';\r
+ end if;\r
+ \r
if (SPI_WRITE_IN = '1') then\r
if (SPI_ADDR_IN(7 downto 4) = x"4") then\r
reg_LOC_WRITE_OUT <= '0';\r
ram_write_i <= '1';\r
ram_data_i <= SPI_DATA_IN(7 downto 0);\r
- ram_addr_i <= SPI_ADDR_IN(3 downto 0);\r
+ spi_ram_addr_i <= SPI_ADDR_IN(3 downto 0);\r
elsif (SPI_ADDR_IN(7 downto 0) = x"5C") then\r
reg_LOC_WRITE_OUT <= '0';\r
enable_cfg_flash <= SPI_DATA_IN(0);\r
+ master_start_reg <= SPI_DATA_IN(1);\r
elsif (SPI_ADDR_IN(7 downto 0) = x"5f") then\r
reg_LOC_WRITE_OUT <= '0';\r
testreg <= SPI_DATA_IN; \r
elsif (SPI_ADDR_IN(7 downto 0) = x"50") then\r
reg_LOC_WRITE_OUT <= '0';\r
- flash_command <= SPI_DATA_IN(15 downto 13);\r
- if(enable_cfg_flash = '1') then\r
- flash_page <= SPI_DATA_IN(12 downto 0);\r
+ spi_flash_command <= SPI_DATA_IN(15 downto 13);\r
+ if (enable_cfg_flash = '1') then\r
+ spi_flash_page <= SPI_DATA_IN(12 downto 0);\r
else\r
- flash_page <= "111" & SPI_DATA_IN(9 downto 0);\r
+ spi_flash_page <= "111" & SPI_DATA_IN(9 downto 0);\r
end if;\r
- flash_go <= '1'; \r
+ spi_flash_go <= '1'; \r
end if;\r
end if;\r
\r
+ if (master_running = '1') then\r
+ reg_LOC_WRITE_OUT <= master_WRITE_OUT;\r
+ reg_LOC_READ_OUT <= '0';\r
+ reg_LOC_DATA_OUT <= master_DATA_OUT;\r
+ reg_LOC_ADDR_OUT <= master_ADDR_OUT;\r
+ end if;\r
+ \r
+ \r
if (out_delay = "01") then\r
reg_LOC_READ_OUT <= '0';\r
reg_SPI_READY_OUT <= '0';\r
out_delay <= "01";\r
reg_LOC_READ_OUT <= '0';\r
reg_SPI_READY_OUT <= '0';\r
- ram_addr_i <= SPI_ADDR_IN(3 downto 0);\r
+ spi_ram_addr_i <= SPI_ADDR_IN(3 downto 0);\r
--reg_SPI_READY_OUT <= '1';\r
-- reg_SPI_DATA_OUT <= flash_busy & flash_err & "00" & ram_addr_i & ram_data_o;\r
+ elsif (SPI_ADDR_IN(7 downto 0) = x"5C") then\r
+ reg_LOC_READ_OUT <= '0';\r
+ reg_SPI_READY_OUT <= '1';\r
+ reg_SPI_DATA_OUT <= x"01" & "00000" & master_running & master_start_reg & enable_cfg_flash;\r
+ elsif (SPI_ADDR_IN(7 downto 0) = x"5d") then\r
+ reg_LOC_READ_OUT <= '0';\r
+ reg_SPI_READY_OUT <= '1';\r
+ reg_SPI_DATA_OUT <= auto_dbg & "00" & master_flash_page;\r
+ elsif (SPI_ADDR_IN(7 downto 0) = x"5e") then\r
+ reg_LOC_READ_OUT <= '0';\r
+ reg_SPI_READY_OUT <= '1';\r
+ reg_SPI_DATA_OUT <= master_DATA_OUT;\r
elsif (SPI_ADDR_IN(7 downto 0) = x"5f") then\r
reg_LOC_READ_OUT <= '0';\r
reg_SPI_READY_OUT <= '1';\r
- reg_SPI_DATA_OUT <= testreg;\r
+ -- reg_SPI_DATA_OUT <= testreg;\r
+ reg_SPI_DATA_OUT <= x"000" & master_word_counter;\r
end if;\r
end if;\r
\r
end process;\r
\r
- \r
+master_running <= '0' when state = IDLE else '1';\r
+ram_addr_i <= master_word_counter when master_running = '1' else spi_ram_addr_i;\r
+flash_go <= master_flash_go when master_running = '1' else spi_flash_go;\r
+flash_page <= master_flash_page when master_running = '1' else spi_flash_page;\r
+flash_command <= master_flash_command when master_running = '1' else spi_flash_command;\r
+\r
+state_machine : process (CLK)\r
+begin\r
+ if rising_edge(CLK) then\r
+ master_flash_go <= '0';\r
+ master_WRITE_OUT <= '0';\r
+ clean_master_start_reg <= '0';\r
+\r
+ case state is\r
+ when IDLE =>\r
+ if (master_start_reg = '1' or auto_reset = '1') then\r
+ state <= Start;\r
+ clean_master_start_reg <= '1';\r
+ master_DATA_OUT <= x"0000";\r
+ master_ADDR_OUT <= x"00";\r
+ if (auto_reset = '1') then\r
+ auto_cnt <= std_logic_vector(unsigned(auto_cnt) + 1);\r
+ state <= IDLE;\r
+ if (auto_cnt = x"FFFFF") then\r
+ auto_reset <= '0';\r
+ state <= EnableFLASH1;\r
+ master_flash_command <= "100";\r
+ master_flash_go <= '1';\r
+ end if;\r
+ else\r
+ master_flash_command <= "000";\r
+ end if;\r
+ end if;\r
+ when EnableFLASH1 =>\r
+ auto_dbg <= '1';\r
+ state <= EnableFLASH2;\r
+ when EnableFLASH2 =>\r
+ state <= EnableFLASH3;\r
+ when EnableFLASH3 =>\r
+ state <= EnableFLASH3;\r
+ if (flash_busy = '0') then\r
+ state <= Start;\r
+ master_flash_command <= "000";\r
+ end if; \r
+ when Start =>\r
+ master_flash_page <= MASTER_STARTPAGE;\r
+ master_word_counter <= "0000";\r
+ state <= ReadPage;\r
+ when ReadPage =>\r
+ master_flash_go <= '1';\r
+ state <= WaitFlash1;\r
+ when WaitFlash1 =>\r
+ state <= WaitFlash2;\r
+ when WaitFlash2 =>\r
+ state <= WaitFlash2;\r
+ if (flash_busy = '0') then\r
+ state <= ReadRAM;\r
+ end if;\r
+ when ReadRAM =>\r
+ state <= WaitRAM1;\r
+ master_word_counter <= std_logic_vector(unsigned(master_word_counter) + 1);\r
+ when WaitRAM1 =>\r
+ if (ram_data_o = x"01") then --Version OK\r
+ state <= WaitRAM2;\r
+ master_word_counter <= std_logic_vector(unsigned(master_word_counter) + 1);\r
+ else\r
+ master_DATA_OUT <= x"ff" & ram_data_o;\r
+ state <= IDLE;\r
+ end if;\r
+ when WaitRAM2 =>\r
+ master_ADDR_OUT <= ram_data_o;\r
+ state <= WaitRAM3;\r
+ master_word_counter <= std_logic_vector(unsigned(master_word_counter) + 1);\r
+ when WaitRAM3 =>\r
+ master_DATA_OUT <= ram_data_o & x"00";\r
+ state <= WaitRAM4;\r
+ when WaitRAM4 =>\r
+ master_DATA_OUT <= master_DATA_OUT(15 downto 8) & ram_data_o;\r
+ state <= WriteSPI;\r
+ master_WRITE_OUT <= '1';\r
+ when WriteSPI =>\r
+ -- prepare for next cycle\r
+ if (master_word_counter = x"F") then\r
+ master_DATA_OUT <= x"eeee";\r
+ state <= ReadPage;\r
+ master_word_counter <= "0000";\r
+ master_flash_page <= std_logic_vector(unsigned(master_flash_page) + 1);\r
+ else\r
+ state <= ReadRAM;\r
+ master_word_counter <= std_logic_vector(unsigned(master_word_counter) + 1);\r
+ end if;\r
+ end case;\r
+ end if;\r
+end process;\r
+ \r
+\r
end architecture;\r
\r
\r