repo2/mist/data_io.vhdl @ 173
1 | markw | LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|||
use ieee.numeric_std.all;
|
|||
LIBRARY work;
|
|||
ENTITY data_io IS
|
|||
PORT
|
|||
(
|
|||
CLK : in std_logic;
|
|||
RESET_n : in std_logic;
|
|||
-- SPI connection - up to upstream to make miso 'Z' on ss_io going high
|
|||
SPI_CLK : in std_logic;
|
|||
SPI_SS_IO : in std_logic;
|
|||
SPI_MISO: out std_logic;
|
|||
SPI_MOSI : in std_logic;
|
|||
70 | markw | -- Sector access read_request
|
|
read_request : in std_logic;
|
|||
write_request : in std_logic;
|
|||
162 | markw | sector : in std_logic_vector(25 downto 0);
|
|
1 | markw | ready : out std_logic;
|
|
-- DMA to RAM
|
|||
ADDR: out std_logic_vector(8 downto 0);
|
|||
DATA_OUT : out std_logic_vector(7 downto 0);
|
|||
DATA_IN : in std_logic_vector(7 downto 0);
|
|||
WR_EN : out std_logic
|
|||
);
|
|||
end data_io;
|
|||
architecture vhdl of data_io is
|
|||
signal sbuf_next : std_logic_vector(6 downto 0);
|
|||
signal sbuf_reg : std_logic_vector(6 downto 0);
|
|||
signal cmd_next : std_logic_vector(7 downto 0);
|
|||
signal cmd_reg : std_logic_vector(7 downto 0);
|
|||
signal cnt_next : std_logic_vector(15 downto 0);
|
|||
signal cnt_reg : std_logic_vector(15 downto 0);
|
|||
70 | markw | ||
signal data_in_next : std_logic_vector(7 downto 0);
|
|||
signal data_in_reg : std_logic_vector(7 downto 0);
|
|||
1 | markw | ||
signal data_out_next : std_logic_vector(7 downto 0);
|
|||
signal data_out_reg : std_logic_vector(7 downto 0);
|
|||
signal addr_next : std_logic_vector(8 downto 0);
|
|||
signal addr_reg : std_logic_vector(8 downto 0);
|
|||
signal wren_next : std_logic;
|
|||
signal wren_reg : std_logic;
|
|||
signal ready_next : std_logic;
|
|||
signal ready_reg : std_logic;
|
|||
signal transmit_next : std_logic_vector(7 downto 0);
|
|||
signal transmit_reg : std_logic_vector(7 downto 0);
|
|||
162 | markw | signal sector_next : std_logic_vector(25 downto 0);
|
|
signal sector_reg : std_logic_vector(25 downto 0);
|
|||
1 | markw | ||
70 | markw | signal read_request_next : std_logic;
|
|
signal read_request_reg : std_logic;
|
|||
1 | markw | ||
70 | markw | signal write_request_next : std_logic;
|
|
signal write_request_reg : std_logic;
|
|||
signal clk2 : std_logic;
|
|||
1 | markw | begin
|
|
70 | markw | clk2 <= clk or spi_ss_io;
|
|
process(clk2,reset_n,spi_ss_io)
|
|||
1 | markw | begin
|
|
70 | markw | if (spi_ss_io = '1') then
|
|
cnt_reg <= (others=>'0');
|
|||
cmd_reg <= (others=>'0');
|
|||
wren_reg <= '0';
|
|||
elsif (reset_n = '0') then
|
|||
1 | markw | cnt_reg <= (others=>'0');
|
|
cmd_reg <= (others=>'0');
|
|||
sbuf_reg <= (others=>'0');
|
|||
addr_reg <= (others => '0');
|
|||
70 | markw | data_in_reg <= (others => '0');
|
|
1 | markw | data_out_reg <= (others => '0');
|
|
wren_reg <= '0';
|
|||
ready_reg <= '0';
|
|||
transmit_reg <= (others=>'0');
|
|||
70 | markw | read_request_reg <= '0';
|
|
write_request_reg <= '0';
|
|||
1 | markw | sector_reg <=(others=>'0');
|
|
70 | markw | elsif (clk2'event and clk2='1') then
|
|
1 | markw | cnt_reg <= cnt_next;
|
|
cmd_reg <= cmd_next;
|
|||
sbuf_reg <= sbuf_next;
|
|||
addr_reg <= addr_next;
|
|||
70 | markw | data_in_reg <= data_in_next;
|
|
1 | markw | data_out_reg <= data_out_next;
|
|
wren_reg <= wren_next;
|
|||
ready_reg <= ready_next;
|
|||
transmit_reg <= transmit_next;
|
|||
70 | markw | read_request_reg <= read_request_next;
|
|
write_request_reg <= write_request_next;
|
|||
1 | markw | sector_reg <= sector_next;
|
|
end if;
|
|||
end process;
|
|||
-- clk_sync : synchronizer
|
|||
-- PORT MAP ( CLK => clk, raw => spi_clk, sync=>spi_clk_next);
|
|||
--spi_clk_next <= spi_clk;
|
|||
-- input_sync : synchronizer
|
|||
-- PORT MAP ( CLK => clk, raw => spi_mosi, sync=>spi_mosi_next);
|
|||
-- select_sync : synchronizer
|
|||
-- PORT MAP ( CLK => clk, raw => spi_ss_io, sync=>spi_ss_next);
|
|||
70 | markw | ||
data_in_next <= data_in;
|
|||
1 | markw | ||
70 | markw | process(spi_ss_io,cnt_reg, sbuf_reg, transmit_reg, spi_mosi, addr_reg, cmd_reg, sector_reg, write_request_reg, read_request_reg, ready_reg,read_request,write_request,sector,data_in_reg)
|
|
1 | markw | begin
|
|
cnt_next <= cnt_reg;
|
|||
sbuf_next <= sbuf_reg;
|
|||
cmd_next <= cmd_reg;
|
|||
70 | markw | ready_next <= ready_reg and (read_request or write_request); -- stay ready until read_request cleared (received by other end)
|
|
1 | markw | ||
transmit_next <= transmit_reg;
|
|||
wren_next <= '0';
|
|||
data_out_next <= (others=>'0');
|
|||
addr_next <= addr_reg;
|
|||
sector_next <= sector_reg;
|
|||
70 | markw | read_request_next <= read_request_reg;
|
|
write_request_next <= write_request_reg;
|
|||
1 | markw | ||
--- It polls get_status 10 times a second
|
|||
--- it uses SPI_SS2 for this
|
|||
--- it sends command code 0x50
|
|||
--- reads 4 bytes afterwards
|
|||
--- it reports whenever the returned value is different then the one from previous get_status
|
|||
--- if the lowest byte of the status (the last transmitted of the four) is 0xa5:
|
|||
--- a sector is read from sd card with the sector no being the upper/first three bytes transmitted
|
|||
--- if the sector could be read
|
|||
--- SPI_SS2 is activated
|
|||
--- command byte 0x51 is sent
|
|||
--- all 512 sector bytes are sent
|
|||
--if (spi_clk_reg = '1' and spi_clk_next = '0') then
|
|||
transmit_next(7 downto 1) <= transmit_reg(6 downto 0);
|
|||
transmit_next(0) <= '0';
|
|||
cnt_next <= std_logic_vector(unsigned(cnt_reg) + 1);
|
|||
sbuf_next(6 downto 1) <= sbuf_reg(5 downto 0);
|
|||
sbuf_next(0) <= SPI_MOSI;
|
|||
70 | markw | ||
if (cnt_reg = X"0000") then
|
|||
addr_next <= (others=>'0');
|
|||
end if;
|
|||
1 | markw | ||
if (cnt_reg = X"0007") then
|
|||
cmd_next(7 downto 1) <= sbuf_reg;
|
|||
cmd_next(0) <= SPI_MOSI;
|
|||
sector_next <= sector;
|
|||
70 | markw | read_request_next <= read_request;
|
|
write_request_next <= write_request;
|
|||
1 | markw | end if;
|
|
--end if;
|
|||
case cmd_reg is
|
|||
when X"50" => --get status
|
|||
case cnt_reg is
|
|||
when X"0008" =>
|
|||
162 | markw | transmit_next <= sector_reg(25 downto 18);
|
|
1 | markw | when X"0010" =>
|
|
162 | markw | transmit_next <= sector_reg(17 downto 10);
|
|
1 | markw | when X"0018" =>
|
|
162 | markw | transmit_next <= sector_reg(9 downto 2);
|
|
1 | markw | when X"0020" =>
|
|
162 | markw | transmit_next <= sector_reg(1 downto 0)&"1010"&write_request_reg&read_request_reg; --read read_request
|
|
1 | markw | when others =>
|
|
-- nothing
|
|||
end case;
|
|||
when X"51" => --sector read from sd, write it...
|
|||
70 | markw | if (cnt_reg = X"0008") then
|
|
addr_next <= (others=>'1');
|
|||
end if;
|
|||
1 | markw | if (cnt_reg(2 downto 0) = "111") then
|
|
addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
|
|||
data_out_next(7 downto 1) <= sbuf_reg;
|
|||
data_out_next(0) <= SPI_MOSI;
|
|||
70 | markw | wren_next <= read_request;
|
|
1 | markw | ||
if (cnt_reg(12) = '1')then
|
|||
ready_next <= '1';
|
|||
end if;
|
|||
end if;
|
|||
70 | markw | when X"52" => -- read from write, write to sd
|
|
if (cnt_reg(2 downto 0) = "000") then
|
|||
addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
|
|||
transmit_next <= data_in_reg;
|
|||
if (cnt_reg(12) = '1')then
|
|||
ready_next <= '1';
|
|||
end if;
|
|||
end if;
|
|||
1 | markw | when others =>
|
|
-- nop
|
|||
end case;
|
|||
end process;
|
|||
-- outputs
|
|||
70 | markw | addr <= addr_next;
|
|
data_out <= data_out_next;
|
|||
wr_en <= wren_next;
|
|||
1 | markw | ||
ready <= ready_reg;
|
|||
spi_miso <= transmit_next(7);
|
|||
end vhdl;
|