Line 35... |
Line 35... |
|
|
entity usb2mem is
|
entity usb2mem is
|
port (
|
port (
|
clk25 : in std_logic;
|
clk25 : in std_logic;
|
reset_n : in std_logic;
|
reset_n : in std_logic;
|
|
dongle_ver: in std_logic_vector(15 downto 0);
|
-- mem Bus
|
-- mem Bus
|
|
mem_busy_n : in std_logic;
|
|
mem_idle : out std_logic; -- '1' if controller is idle (flash is safe for LPC reads)
|
mem_addr : out std_logic_vector(23 downto 0);
|
mem_addr : out std_logic_vector(23 downto 0);
|
mem_do : out std_logic_vector(15 downto 0);
|
mem_do : out std_logic_vector(15 downto 0);
|
mem_di : in std_logic_vector(15 downto 0);
|
mem_di : in std_logic_vector(15 downto 0);
|
mem_wr : out std_logic;
|
mem_wr : out std_logic;
|
mem_val : out std_logic;
|
mem_val : out std_logic;
|
mem_ack : in std_logic;
|
mem_ack : in std_logic;
|
mem_cmd : out std_logic;
|
mem_cmd : out std_logic;
|
-- USB port
|
-- USB port
|
|
usb_mode_en: in std_logic; -- enable this block
|
usb_rd_n : out std_logic; -- enables out data if low (next byte detected by edge / in usb chip)
|
usb_rd_n : out std_logic; -- enables out data if low (next byte detected by edge / in usb chip)
|
usb_wr : out std_logic; -- write performed on edge \ of signal
|
usb_wr : out std_logic; -- write performed on edge \ of signal
|
usb_txe_n : in std_logic; -- tx fifo empty (redy for new data if low)
|
usb_txe_n : in std_logic; -- tx fifo empty (redy for new data if low)
|
usb_rxf_n : in std_logic; -- rx fifo empty (data redy if low)
|
usb_rxf_n : in std_logic; -- rx fifo empty (data redy if low)
|
usb_bd : inout std_logic_vector(7 downto 0) --bus data
|
usb_bd : inout std_logic_vector(7 downto 0) --bus data
|
Line 58... |
Line 62... |
architecture RTL of usb2mem is
|
architecture RTL of usb2mem is
|
|
|
|
|
|
|
|
|
type state_type is (RESETs,RXCMD0s,RXCMD1s,DECODEs,INTERNs,VCIRDs,VCIWRs,TXCMD0s,TXCMD1s);
|
type state_type is (RESETs,RXCMD0s,RXCMD1s,DECODEs,INTERNs,VCIRDs,VCIWRs,TXCMD0s,TXCMD1s,STS_WAITs);
|
signal CS : state_type;
|
signal CS : state_type;
|
|
|
signal data_reg_i : std_logic_vector(15 downto 0);
|
signal data_reg_i : std_logic_vector(15 downto 0);
|
signal data_reg_o : std_logic_vector(15 downto 0);
|
signal data_reg_o : std_logic_vector(15 downto 0);
|
signal data_oe : std_logic; -- rx fifo empty (data redy if low)
|
signal data_oe : std_logic; -- rx fifo empty (data redy if low)
|
signal usb_wr_d : std_logic; -- internal readable output state for write
|
signal usb_wr_d : std_logic; -- internal readable output state for write
|
signal addr_reg: std_logic_vector(23 downto 0);
|
signal addr_reg: std_logic_vector(23 downto 0);
|
|
|
--State machine
|
--State machine
|
signal cmd_cnt : std_logic_vector(7 downto 0);
|
signal cmd_cnt : std_logic_vector(15 downto 0);
|
signal state_cnt : std_logic_vector(3 downto 0);
|
signal state_cnt : std_logic_vector(3 downto 0);
|
--shyncro to USB
|
--shyncro to USB
|
signal usb_txe_nd : std_logic; -- tx fifo empty (redy for new data if low)
|
signal usb_txe_nd : std_logic; -- tx fifo empty (redy for new data if low)
|
signal usb_rxf_nd : std_logic; -- rx fifo empty (data redy if low)
|
signal usb_rxf_nd : std_logic; -- rx fifo empty (data redy if low)
|
signal internal_cmd : std_logic; -- rx fifo empty (data redy if low)
|
signal internal_cmd : std_logic; -- rx fifo empty (data redy if low)
|
|
|
signal read_mode : std_logic;
|
signal read_mode : std_logic;
|
signal write_mode : std_logic;
|
signal write_mode : std_logic;
|
signal write_count : std_logic;
|
signal write_count : std_logic;
|
signal first_word : std_logic;
|
signal first_word : std_logic;
|
|
signal mem_busy_nd : std_logic;
|
|
|
|
|
|
|
begin
|
begin
|
|
|
Line 96... |
Line 101... |
--These are spechial attention Flash commands
|
--These are spechial attention Flash commands
|
'1' when data_reg_i(7 downto 0) = x"E8" else
|
'1' when data_reg_i(7 downto 0) = x"E8" else
|
'0';
|
'0';
|
|
|
|
|
usb_wr <= usb_wr_d;
|
usb_wr <= usb_wr_d when usb_mode_en='1' else
|
|
'Z';
|
|
|
|
|
-- this goes to byte buffer for that reason send LSB first and MSB second
|
-- this goes to byte buffer for that reason send LSB first and MSB second
|
usb_bd <=data_reg_o(7 downto 0)when data_oe='1' and CS=TXCMD0s else --LSB byte first
|
usb_bd <=data_reg_o(7 downto 0)when data_oe='1' and CS=TXCMD0s and usb_mode_en='1' else --LSB byte first
|
data_reg_o(15 downto 8) when data_oe='1' and CS=TXCMD1s else --MSB byte second
|
data_reg_o(15 downto 8) when data_oe='1' and CS=TXCMD1s and usb_mode_en='1' else --MSB byte second
|
(others=>'Z');
|
(others=>'Z');
|
|
|
|
|
process (clk25,reset_n) --enable the scanning while in reset (simulation will be incorrect)
|
process (clk25,reset_n) --enable the scanning while in reset (simulation will be incorrect)
|
begin -- process
|
begin -- process
|
Line 125... |
Line 132... |
cmd_cnt <= (others=>'0');
|
cmd_cnt <= (others=>'0');
|
read_mode <='0';
|
read_mode <='0';
|
write_mode <='0';
|
write_mode <='0';
|
write_count <='0';
|
write_count <='0';
|
first_word <='0';
|
first_word <='0';
|
|
mem_idle <='1'; --set idle
|
|
mem_busy_nd <='1';
|
elsif clk25'event and clk25 = '1' then -- rising clock edge
|
elsif clk25'event and clk25 = '1' then -- rising clock edge
|
usb_txe_nd <= usb_txe_n;
|
usb_txe_nd <= usb_txe_n; --syncronize
|
usb_rxf_nd <= usb_rxf_n;
|
usb_rxf_nd <= usb_rxf_n; --syncronize
|
|
mem_busy_nd <=mem_busy_n; --syncronize
|
case CS is
|
case CS is
|
when RESETs =>
|
when RESETs =>
|
if usb_rxf_nd='0' then
|
if usb_rxf_nd='0' and usb_mode_en='1' and mem_busy_nd='1' then
|
state_cnt <=(others=>'0'); --init command counter
|
state_cnt <=(others=>'0'); --init command counter
|
data_oe <='0'; --we will read command in
|
data_oe <='0'; --we will read command in
|
|
mem_idle <='0'; --set busy untill return here
|
CS <= RXCMD0s;
|
CS <= RXCMD0s;
|
|
elsif mem_busy_nd='1' then
|
|
mem_idle <='1'; --set idle when here
|
end if;
|
end if;
|
when RXCMD0s =>
|
when RXCMD0s =>
|
if state_cnt="0000" then
|
if state_cnt="0000" then
|
usb_rd_n <='0'; -- set read low
|
usb_rd_n <='0'; -- set read low
|
state_cnt <= state_cnt + 1;-- must be min 50ns long (two cycles)
|
state_cnt <= state_cnt + 1;-- must be min 50ns long (two cycles)
|
Line 182... |
Line 195... |
else
|
else
|
state_cnt <=(others=>'0'); --init command counter
|
state_cnt <=(others=>'0'); --init command counter
|
CS <= INTERNs;
|
CS <= INTERNs;
|
end if;
|
end if;
|
when INTERNs =>
|
when INTERNs =>
|
if cmd_cnt=x"00" then
|
if cmd_cnt=x"0000" then
|
if data_reg_i(7 downto 0)=x"A0" then
|
if data_reg_i(7 downto 0)=x"A0" then
|
addr_reg(7 downto 0)<= data_reg_i(15 downto 8);
|
addr_reg(7 downto 0)<= data_reg_i(15 downto 8);
|
CS <= RESETs; --go back to resets
|
CS <= RESETs; --go back to resets
|
elsif data_reg_i(7 downto 0)=x"A1" then
|
elsif data_reg_i(7 downto 0)=x"A1" then
|
addr_reg(15 downto 8)<= data_reg_i(15 downto 8);
|
addr_reg(15 downto 8)<= data_reg_i(15 downto 8);
|
Line 195... |
Line 208... |
addr_reg(23 downto 16)<= data_reg_i(15 downto 8);
|
addr_reg(23 downto 16)<= data_reg_i(15 downto 8);
|
CS <= RESETs; --go back to resets
|
CS <= RESETs; --go back to resets
|
elsif data_reg_i(7 downto 0)=x"3F" then
|
elsif data_reg_i(7 downto 0)=x"3F" then
|
CS <= RESETs; --go back to resets --NOP command
|
CS <= RESETs; --go back to resets --NOP command
|
elsif data_reg_i(7 downto 0)=x"C5" then
|
elsif data_reg_i(7 downto 0)=x"C5" then
|
|
if (data_reg_i(15 downto 8))=x"00" then
|
data_reg_o <=x"3210";
|
data_reg_o <=x"3210";
|
|
else
|
|
data_reg_o <=dongle_ver;
|
|
end if;
|
CS <= TXCMD0s;
|
CS <= TXCMD0s;
|
elsif data_reg_i(7 downto 0)=x"CD" then
|
elsif data_reg_i(7 downto 0)=x"CD" then
|
cmd_cnt <= data_reg_i(15 downto 8) - 1; -- -1 as one read will be done right now
|
if (data_reg_i(15 downto 8))=x"00" then --64K word read coming
|
|
cmd_cnt <= (others=>'1'); --64K word count
|
|
else
|
|
cmd_cnt <= x"00"&data_reg_i(15 downto 8) - 1; -- -1 as one read will be done right now (cmd_cnt words)
|
|
end if;
|
CS <= VCIRDs; --go perform a read
|
CS <= VCIRDs; --go perform a read
|
read_mode <='1';
|
read_mode <='1';
|
elsif data_reg_i(7 downto 0)=x"E8" then
|
elsif data_reg_i(7 downto 0)=x"E8" then
|
--write_mode <='1';
|
--write_mode <='1';
|
write_count <='0';
|
write_count <='0';
|
first_word <='0';
|
first_word <='0';
|
cmd_cnt <= data_reg_i(15 downto 8) + 1; --+2 for direct count write +1
|
cmd_cnt <= x"00"&data_reg_i(15 downto 8) + 1; --+2 for direct count write +1
|
data_reg_i(15 downto 8)<=(others=>'0');
|
data_reg_i(15 downto 8)<=(others=>'0');
|
CS <= VCIWRs; --go perform a write
|
CS <= VCIWRs; --go perform a write
|
else
|
else
|
CS <= VCIWRs;
|
CS <= VCIWRs;
|
end if;
|
end if;
|
else
|
else
|
if cmd_cnt>x"00" then
|
if cmd_cnt>x"0000" then
|
cmd_cnt<= cmd_cnt - 1;
|
cmd_cnt<= cmd_cnt - 1;
|
if write_count='0' then
|
if write_count='0' then
|
write_count<='1';
|
write_count<='1';
|
elsif write_count='1' and first_word ='0' then
|
elsif write_count='1' and first_word ='0' then
|
first_word <='1';
|
first_word <='1';
|
Line 250... |
Line 271... |
if mem_ack='1' then
|
if mem_ack='1' then
|
mem_do <= (others=>'Z');
|
mem_do <= (others=>'Z');
|
mem_wr <='0'; --this is VCI write_not_read
|
mem_wr <='0'; --this is VCI write_not_read
|
mem_cmd <='0';
|
mem_cmd <='0';
|
mem_val <= '0';
|
mem_val <= '0';
|
if write_mode='0' then
|
--if write_mode='0' then
|
|
|
|
if cmd_cnt=x"0000" then --if flash command and not data
|
|
state_cnt <=(others=>'0'); --init command counter
|
|
CS <= STS_WAITs;
|
|
else
|
CS <= RESETs;
|
CS <= RESETs;
|
|
end if;
|
--else --else if was 0xE8 must read and return XSR
|
--else --else if was 0xE8 must read and return XSR
|
-- write_mode <='0'; --XSR return will no follow clear this bit
|
-- write_mode <='0'; --XSR return will no follow clear this bit
|
-- CS <= VCIRDs;
|
-- CS <= VCIRDs;
|
end if;
|
--end if;
|
end if;
|
end if;
|
when TXCMD0s => --transmit over USB what ever is in data_reg_o MSB first
|
when TXCMD0s => --transmit over USB what ever is in data_reg_o MSB first
|
|
|
if state_cnt="0000" then
|
if state_cnt="0000" then
|
if usb_txe_nd='0' then
|
if usb_txe_nd='0' then
|
Line 299... |
Line 326... |
state_cnt <= state_cnt + 1;-- now is ok
|
state_cnt <= state_cnt + 1;-- now is ok
|
data_oe<='0';
|
data_oe<='0';
|
elsif state_cnt="0111" then --must stay low at least 50ns
|
elsif state_cnt="0111" then --must stay low at least 50ns
|
if read_mode='0' then
|
if read_mode='0' then
|
CS <= RESETs;
|
CS <= RESETs;
|
elsif cmd_cnt="00" then --last word sent
|
elsif cmd_cnt="0000" then --last word sent
|
addr_reg <= addr_reg + 1; --autoincrement address in read mode
|
addr_reg <= addr_reg + 1; --autoincrement address in read mode
|
read_mode <='0';
|
read_mode <='0';
|
CS <= RESETs;
|
CS <= RESETs;
|
else
|
else
|
cmd_cnt<= cmd_cnt - 1;
|
cmd_cnt<= cmd_cnt - 1;
|
Line 312... |
Line 339... |
end if;
|
end if;
|
state_cnt <= (others=>'0');
|
state_cnt <= (others=>'0');
|
else
|
else
|
state_cnt <= state_cnt + 1;-- if intermediate cnt then count
|
state_cnt <= state_cnt + 1;-- if intermediate cnt then count
|
end if;
|
end if;
|
|
when STS_WAITs =>
|
|
if mem_busy_nd='0' then
|
|
CS <= RESETs; --now it's ok to go here
|
|
else
|
|
state_cnt <= state_cnt + 1;
|
|
if state_cnt="1111" then
|
|
--sts cant take longer than 500 ns to go low
|
|
CS <= RESETs; --time out go to resets anyway
|
|
end if;
|
|
end if;
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|