mor1kx-bemicrocv/cores/OLDflashrom-wb/flashrom-spi.vhd

169 lines
4.5 KiB
VHDL

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;