diff --git a/bench/bench_flashrom_wb.vhd b/bench/bench_flashrom_wb.vhd new file mode 100644 index 0000000..2d2eba5 --- /dev/null +++ b/bench/bench_flashrom_wb.vhd @@ -0,0 +1,173 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library design; +use design.all; + +library ip; +use ip.wishbone_package.all; + +entity bench_flashrom_wb is +end entity bench_flashrom_wb; + +architecture RTL of bench_flashrom_wb is + signal clk : std_logic; + signal rst : std_logic; + signal clr : std_logic; + signal wb_in : wishbone_v3_slave_in; + signal wb_out : wishbone_v3_slave_out; + signal spi_si : std_logic; + signal spi_so : std_logic; + signal spi_sck : std_logic; + signal spi_reset_n : std_logic; + signal spi_cs_n : std_logic; + signal spi_wp_n : std_logic; + signal spi_busy : std_logic; + + procedure waitclk is + begin + wait until rising_edge(clk); + end procedure waitclk; + procedure waitnclk(n : integer) is + begin + for i in 1 to n loop + wait until rising_edge(clk); + end loop; + end procedure waitnclk; + procedure strobe(signal s : out std_logic) is + begin + s <= '1'; + waitclk; + s <= '0'; + waitclk; + end procedure strobe; +begin + DataFlash_inst : entity work.DataFlash + generic map( + flashmemory => "devicemodels/memory.txt", + Rapid_interface => true, + fsck => 66, + DEVICE => "AT45DB011D", --AT45DB011D + Tsck => 13.6 ns) + port map( + SI => spi_si, + CSB => spi_cs_n, + SCK => spi_sck, + WPB => spi_wp_n, + RESETB => spi_reset_n, + SO => spi_so, + RDYBSY => spi_busy + ); + + flashrom_wb_inst : entity design.flashrom_wb + port map( + clk => clk, + rst => rst, + clr => clr, + wb_in => wb_in, + wb_out => wb_out, + spi_si => spi_si, + spi_so => spi_so, + spi_sck => spi_sck, + spi_reset_n => spi_reset_n, + spi_cs_n => spi_cs_n, + spi_wp_n => spi_wp_n + ); + + clock_driver : process + constant period : time := 10 ns; + begin + clk <= '0'; + wait for period / 2; + clk <= '1'; + wait for period / 2; + end process clock_driver; + + test : process is + begin + rst <= '1'; + wb_in.ADR <= (others => '0'); + wait for 10 ns * 2; + wait until (rising_edge(clk)); + rst <= '0'; + wait for 10 ns * 2; + wait until (rising_edge(clk)); + + wb_in.ADR <= std_logic_vector(to_unsigned(0, 32)); + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '0'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(4, 32)); + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '0'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(4, 32)); + wb_in.DAT <= x"deadbeef"; + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '1'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(4, 32)); + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '0'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(256, 32)); + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '0'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(256, 32)); + wb_in.DAT <= x"b000b1e5"; + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '1'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(256, 32)); + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '0'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + + wb_in.ADR <= std_logic_vector(to_unsigned(4, 32)); + wb_in.CYC <= '1'; + wb_in.STB <= '1'; + wb_in.WE <= '0'; + wait until wb_out.ACK = '1'; + wb_in.CYC <= '0'; + wb_in.STB <= '0'; + waitnclk(30); + wait; + end process test; + +end architecture RTL; diff --git a/cores/flashrom-wb/flashrom_wb.vhd b/cores/flashrom-wb/flashrom_wb.vhd new file mode 100644 index 0000000..2244121 --- /dev/null +++ b/cores/flashrom-wb/flashrom_wb.vhd @@ -0,0 +1,202 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library ip; +use ip.wishbone_package.all; +use ip.all; + +use work.flashrom_pkg.all; + +entity flashrom_wb is + port( + clk : in std_logic; + rst : in std_logic; + clr : in std_logic; + + -- Wishbone + wb_in : in wishbone_v3_slave_in; + wb_out : out wishbone_v3_slave_out; + + -- 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; -- spi clock + 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_wb; + +architecture rtl of flashrom_wb is + -- Controller Signals + signal current_page : std_logic_vector(FLASHROM_PAGE_ADDR_WIDTH - 1 downto 0); + signal ready : std_logic; + signal sync_stb : std_logic; + signal load_stb : std_logic; + signal status_update_stb : std_logic; + signal status : std_logic_vector(7 downto 0); + signal info : std_logic_vector(31 downto 0); + signal data_in : std_logic_vector(7 downto 0); + signal data_in_next : std_logic; + signal data_out : std_logic_vector(7 downto 0); + signal data_out_valid : std_logic; + -- + signal bootup_complete : std_logic; + type state_t is (WAITCON, IDLE, LOADPAGE, WRITEPAGE); + signal state : state_t; + -- + signal requested_page : std_logic_vector(current_page'range); + signal requested_byte : std_logic_vector(7 downto 0); + signal dirty : std_logic; + -- Cache Memory + type cache_t is array (0 to 63) of std_logic_vector(31 downto 0); + signal cache : cache_t; + signal cache_addr : std_logic_vector(7 downto 0); + signal cache_control_addr : unsigned(7 downto 0); + signal cache_we : std_logic; + signal cache_dOut : std_logic_vector(31 downto 0); + signal cache_dIn : std_logic_vector(31 downto 0); + signal data_in_shift : std_logic_vector(31 downto 0); + signal delay_cycle : std_logic; +begin + flashrom_controller_inst : entity work.flashrom_controller + port map( + clk => clk, + rst => rst, + clr => clr, + page => current_page, + ready => ready, + sync_stb => sync_stb, + load_stb => load_stb, + status_update_stb => status_update_stb, + status => status, + info => info, + data_in => data_in, + data_in_next => data_in_next, + data_out => data_out, + data_out_valid => data_out_valid, + spi_si => spi_si, + spi_so => spi_so, + spi_sck => spi_sck, + spi_reset_n => spi_reset_n, + spi_cs_n => spi_cs_n, + spi_wp_n => spi_wp_n + ); + + wb_ctrl : process(clk, rst) is + procedure default_state is + begin + load_stb <= '0'; + sync_stb <= '0'; + wb_out.ACK <= '0'; + cache_we <= '0'; + delay_cycle <= '0'; + end procedure default_state; + + procedure reset_state is + begin + default_state; + state <= WAITCON; + bootup_complete <= '0'; + dirty <= '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 WAITCON => + if ready = '1' then + state <= IDLE; + end if; + when IDLE => + if ready = '1' and delay_cycle = '0' then + if wb_in.CYC = '1' and wb_in.STB = '1' then + if (requested_page /= current_page) then -- Page swap required + if (dirty = '0') then + state <= LOADPAGE; + load_stb <= '1'; + cache_control_addr <= (others => '1'); -- Wraparound... + end if; + + if (dirty = '1') then + state <= WRITEPAGE; + sync_stb <= '1'; + cache_control_addr <= to_unsigned(1, cache_control_addr'length); + end if; + else -- Same page + wb_out.ACK <= '1'; + if wb_in.WE = '1' then + dirty <= '1'; + cache_dIn <= wb_in.DAT; + cache_we <= '1'; + cache_control_addr <= unsigned(wb_in.ADR(7 downto 0)); + end if; + end if; + end if; + end if; + + if (bootup_complete = '0') then + state <= LOADPAGE; + load_stb <= '1'; + cache_control_addr <= (others => '1'); -- Wraparound... + end if; + when LOADPAGE => + bootup_complete <= '1'; + current_page <= requested_page; + if data_out_valid = '1' then + cache_dIn <= cache_dIn(23 downto 0) & data_out; + cache_control_addr <= cache_control_addr + 1; + cache_we <= '1'; + if cache_control_addr = 254 then + state <= IDLE; + delay_cycle <= '1'; + end if; + end if; + when WRITEPAGE => + if cache_control_addr = 1 then + data_in_shift <= cache_dOut; + end if; + if data_in_next = '1' then + if cache_control_addr(1 downto 0) = "00" then + data_in_shift <= cache_dOut; + else + data_in_shift <= data_in_shift(23 downto 0) & x"00"; + end if; + cache_control_addr <= cache_control_addr + 1; + + if cache_control_addr = 0 then + state <= IDLE; + dirty <= '0'; + delay_cycle <= '1'; + end if; + end if; + end case; + end if; + end if; + end process wb_ctrl; + requested_page <= wb_in.ADR(FLASHROM_PAGE_ADDR_WIDTH + 8 - 1 downto 8); + requested_byte <= wb_in.ADR(7 downto 0); + data_in <= data_in_shift(31 downto 24); + + -- Cache Memory Controller + cache_mem_p : process(clk, rst) is + begin + if rst = '1' then + cache_dOut <= (others => '0'); + elsif rising_edge(clk) then + cache_dOut <= cache(to_integer(unsigned(cache_addr(cache_addr'length - 1 downto 2)))); + if cache_we = '1' then + cache(to_integer(unsigned(cache_addr(cache_addr'length - 1 downto 2)))) <= cache_dIn; + end if; + end if; + end process cache_mem_p; + + cache_addr <= wb_in.ADR(7 downto 0) when (state = IDLE and cache_we = '0') else std_logic_vector(cache_control_addr); + wb_out.DAT <= cache_dOut; +end architecture rtl; diff --git a/wave/flashrom_wb.do b/wave/flashrom_wb.do new file mode 100644 index 0000000..6dfc25e --- /dev/null +++ b/wave/flashrom_wb.do @@ -0,0 +1,89 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/clk +add wave -noupdate /bench_flashrom_wb/DataFlash_inst/RDYBSY +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/rst +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/clr +add wave -noupdate -expand /bench_flashrom_wb/flashrom_wb_inst/wb_in +add wave -noupdate -expand /bench_flashrom_wb/flashrom_wb_inst/wb_out +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/spi_si +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/spi_so +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/spi_sck +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/spi_reset_n +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/spi_cs_n +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/spi_wp_n +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/current_page +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/ready +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/sync_stb +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/load_stb +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/status_update_stb +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/status +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/info +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/data_in +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/data_in_next +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/data_out +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/data_out_valid +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/bootup_complete +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/state +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/requested_page +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/requested_byte +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/dirty +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/cache_we +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/cache_addr +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/cache_control_addr +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/cache_dOut +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/cache_dIn +add wave -noupdate /bench_flashrom_wb/flashrom_wb_inst/cache +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/rst +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/clr +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/ready +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/page +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/sync_stb +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/load_stb +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/status_update_stb +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/status +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/info +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/data_in +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/data_in_next +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/data_out +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/data_out_valid +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spi_si +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spi_so +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spi_sck +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spi_reset_n +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spi_cs_n +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spi_wp_n +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/state +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_in_valid +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_in +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_in_length +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_next +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_out +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_out_valid +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_out_length +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/words_sent +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_data_out_dummy_bits +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_transmission_active +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/command_is_latched +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/spif_max_word_length +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/max_dummy_bits +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/bootup_delay +add wave -noupdate -expand -group flashrom-ctrlr /bench_flashrom_wb/flashrom_wb_inst/flashrom_controller_inst/status_reg_poll_delay +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {182209 ns} 0} +quietly wave cursor active 1 +configure wave -namecolwidth 173 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {168208 ns} {199740 ns}