OpenCores
URL https://opencores.org/ocsvn/nand_controller/nand_controller/trunk

Subversion Repositories nand_controller

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/nand_controller/trunk/VHDL/nand_interface.vhd
0,0 → 1,266
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- Title : NAND interface
-- File : nand_interface.vhd
-- Author : Alexey Lyashko <pradd@opencores.org>
-- License : LGPL
--------------------------------------------------------------------------
-- Description :
-- This file implements a simplistic NAND interface driven by 5 control signals:
-- action_cmd, action_address, action_read and action_write which trigger
-- execution of Command Latch Cycle, Address Latch Cycle, Data Output and
-- Data Input cycles respectively.
-- This component may be used as a standalone NAND Flash adapter, although,
-- I would recommend using the controller as a whole.
--------------------------------------------------------------------------
--------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.nand_stuff.all;
 
entity nand_interface is
port
(
-- NAND HW interface
nand_cle : out std_logic := '0';
nand_ale : out std_logic := '0';
nand_n_we : out std_logic := '1';
nand_n_wp : out std_logic := '1';
nand_n_ce : out std_logic := '1';
nand_n_re : out std_logic := '1';
nand_r_nb : in std_logic := '1';
nand_io : inout std_logic_vector(15 downto 0);
-- System interface
clk : in std_logic;
-- NAND controller internal interface
data_rx : in std_logic_vector(15 downto 0);
data_tx : out std_logic_vector(15 downto 0);
ready : out std_logic := '0';
n_nand_enable : in std_logic := '1';
action_cmd : in std_logic := '0';
action_address : in std_logic := '0';
action_read : in std_logic := '0';
action_write : in std_logic := '0'
);
end nand_interface;
 
architecture action of nand_interface is
-- NAND IO
signal nand_io_rx : std_logic_vector(15 downto 0);
signal nand_io_tx : std_logic_vector(15 downto 0);
signal nand_oe : std_logic;
signal nand_io_buffer : std_logic_vector(15 downto 0);
-- Main FSM
type c_state_t is (C_IDLE, C_COMMAND, C_ADDRESS, C_READ, C_WRITE, C_DELAY);
signal c_state : c_state_t := C_IDLE;
signal r_state : c_state_t;
-- Latch states
type l_state_t is (L_BEGIN, L_WE, L_RE, L_HOLD, L_END);
signal l_state : l_state_t := L_BEGIN;
-- Delay counter
signal delay_cnt : integer := 0;
begin
-- NAND chip enable
nand_n_ce <= n_nand_enable;
-- NAND IO bidirectional "pin"
nand_io <= nand_io_tx when nand_oe = '1' else "ZZZZZZZZZZZZZZZZ";
data_tx <= nand_io_buffer;
-- READY
ready <= '1' when c_state = C_IDLE and nand_r_nb = '1' and n_nand_enable = '0' else '0';
-- NAND write enable
nand_n_we <= '0' when (c_state = C_COMMAND and (l_state = L_BEGIN or l_state = L_WE)) or
(c_state = C_DELAY and r_state = C_COMMAND and (l_state = L_BEGIN or l_state = L_WE)) or
(c_state = C_ADDRESS and (l_state = L_BEGIN or l_state = L_WE)) or
(c_state = C_DELAY and r_state = C_ADDRESS and (l_state = L_BEGIN or l_state = L_WE)) or
(c_state = C_WRITE and (l_state = L_BEGIN or l_state = L_WE)) or
(c_state = C_DELAY and r_state = C_WRITE and (l_state = L_BEGIN or l_state = L_WE))
else
'1';
-- NAND io port output enable
nand_oe <= '1' when (c_state = C_COMMAND and (l_state = L_BEGIN or l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_DELAY and r_state = C_COMMAND and (l_state = L_BEGIN or l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_ADDRESS and (l_state = L_BEGIN or l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_DELAY and r_state = C_ADDRESS and (l_state = L_BEGIN or l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_WRITE and (l_state = L_BEGIN or l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_DELAY and r_state = C_WRITE and (l_state = L_BEGIN or l_state = L_WE or l_state = L_HOLD))
else
'0';
-- NAND read enable
nand_n_re <= '0' when (c_state = C_READ and (l_state = L_BEGIN or l_state = L_RE)) or
(c_state = C_DELAY and r_state = C_READ and (l_state = L_BEGIN or l_state = L_RE))
else
'1';
-- NAND Command Latch
nand_cle <= '1' when (c_state = C_COMMAND and (l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_DELAY and r_state = C_COMMAND and (l_state = L_WE or l_state = L_HOLD))
else
'0';
-- NAND Address Latch
nand_ale <= '1' when (c_state = C_ADDRESS and (l_state = L_WE or l_state = L_HOLD)) or
(c_state = C_DELAY and r_state = C_ADDRESS and (l_state = L_WE or l_state = L_HOLD))
else
'0';
NAND_IFACE: process(clk, action_cmd, action_address, action_read, action_write, nand_r_nb)
begin
if(rising_edge(clk) and n_nand_enable = '0')then
case c_state is
----------------------------------------------------
-- Idle state - controller awaits orders
----------------------------------------------------
when C_IDLE =>
delay_cnt <= 0;
l_state <= L_BEGIN;
if(action_cmd = '1')then
c_state <= C_DELAY;
r_state <= C_COMMAND;
delay_cnt <= t_wp - t_cls - 1;
nand_io_tx(7 downto 0) <= data_rx(7 downto 0);
nand_io_tx(15 downto 8) <= "00000000"; -- bits 15 to 8 should be pulled low during command submission
elsif(action_address = '1')then
c_state <= C_DELAY;
r_state <= C_ADDRESS;
delay_cnt <= t_wp - t_als - 1;
nand_io_tx(7 downto 0) <= data_rx(7 downto 0);
nand_io_tx(15 downto 8) <= "00000000"; -- bits 15 to 8 should be pulled low during address submission
elsif(action_read = '1')then
c_state <= C_READ;
elsif(action_write = '1')then
c_state <= C_WRITE;
nand_io_tx <= data_rx;
else
c_state <= C_IDLE;
end if;
----------------------------------------------------
-- Command submission state - controller forwards
-- command to the NAND flash
----------------------------------------------------
when C_COMMAND =>
if(l_state = L_BEGIN)then
l_state <= L_WE; -- nand_n_we goes low, nand_oe goes high
delay_cnt <= t_cls;
r_state <= C_COMMAND;
c_state <= C_DELAY;
elsif(l_state = L_WE)then
l_state <= L_HOLD;
delay_cnt <= t_clh;
r_state <= C_COMMAND;
c_state <= C_DELAY;
elsif(l_state = L_HOLD)then
c_state <= C_IDLE;
l_state <= L_BEGIN;
end if;
----------------------------------------------------
-- Address submission state - controller forwards
-- address byte to the NAND flash
----------------------------------------------------
when C_ADDRESS =>
if(l_state = L_BEGIN)then
l_state <= L_WE;
delay_cnt <= t_als;
r_state <= C_ADDRESS;
c_state <= C_DELAY;
elsif(l_state = L_WE)then
l_state <= L_HOLD;
delay_cnt <= t_alh;
r_state <= C_ADDRESS;
c_state <= C_DELAY;
elsif(l_state = L_HOLD)then
delay_cnt <= t_wh - t_alh;
c_state <= C_DELAY;
r_state <= C_IDLE;
l_state <= L_BEGIN;
end if;
----------------------------------------------------
-- Data Input state - one byte/word is written
-- to the NAND device
----------------------------------------------------
when C_WRITE =>
if(l_state = L_BEGIN)then
l_state <= L_WE;
delay_cnt <= t_wp;
r_state <= C_WRITE;
c_state <= C_DELAY;
elsif(l_state = L_WE)then
l_state <= L_HOLD;
delay_cnt <= t_wh;
r_state <= C_WRITE;
c_state <= C_DELAY;
elsif(l_state = L_HOLD)then
l_state <= L_BEGIN;
c_state <= C_IDLE;
end if;
----------------------------------------------------
-- Data Output state - one byte/word is read
-- from the NAND device and stored to nand_io_buffer
----------------------------------------------------
when C_READ =>
if(l_state = L_BEGIN)then
l_state <= L_RE;
delay_cnt <= t_rp;
r_state <= C_READ;
c_state <= C_DELAY;
elsif(l_state = L_RE)then
nand_io_buffer <= nand_io;
l_state <= L_HOLD;
delay_cnt <= t_reh;
r_state <= C_READ;
c_state <= C_DELAY;
elsif(l_state = L_HOLD)then
l_state <= L_BEGIN;
c_state <= C_IDLE;
end if;
----------------------------------------------------
-- Delay state - controller "waits" until delay_cnt
-- reaches 0 (delay expires)
----------------------------------------------------
when C_DELAY =>
if(delay_cnt > 0)then
delay_cnt <= delay_cnt - 1;
else
c_state <= r_state;
end if;
----------------------------------------------------
-- Default state - we need to make sure that
-- the controller is in IDLE state on power op or if
-- anything goes wrong
----------------------------------------------------
when others =>
c_state <= C_IDLE;
end case;
end if;
end process;
end action;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.