169 lines
4.5 KiB
VHDL
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;
|