📄 flashctrl.vhd
字号:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--This is a simplified version of Flash Control. Only a subset of flash control is implemented.
--The following operation are supported:
entity FlashCtrl is
generic(ADDRESS_WIDTH : integer range 0 to 32 := 24;
DATA_WIDTH : integer range 0 to 16 := 8;
READ_CYCLES : integer range 0 to 15 := 9);
port(
reset : in std_logic; --reset signal.
clk : in std_logic; --60MHz Clock
--Computer Interface:
--In 8 bit flash control, the command is 16bit, thus we need 2 wrCmdByte operation to send one command
CS : in std_logic;
wrCmdByte : in std_logic;
CmdByte : in std_logic_vector(7 downto 0);
--test pins:
wrEPPCmdOut : out std_logic;
EPPCmdWordOut : out std_logic_vector(15 downto 0);
--
--Return value to computer
DataToEPP : out std_logic_vector(7 downto 0);
--LookupTable Interface:
rdLUT : in std_logic;
LUTAddr : in std_logic_vector(ADDRESS_WIDTH-1 downto 0);
LUTData : out std_logic_vector(DATA_WIDTH-1 downto 0);
--Flash Memory Interface
FlashAddr : out std_logic_vector(ADDRESS_WIDTH-1 downto 0);
FlashDQ : inout std_logic_vector(DATA_WIDTH-1 downto 0);
CENeg : OUT std_ulogic := 'U';
OENeg : OUT std_ulogic := 'U';
WENeg : OUT std_ulogic := 'U';
RESETNeg : OUT std_ulogic := 'U';
WPNeg : OUT std_ulogic := 'U'; --WP#/ACC
BYTENeg : OUT std_ulogic := 'U';
RY : IN std_ulogic := 'U' --RY/BY#
);
end entity FlashCtrl;
architecture arch1 of FlashCtrl is
component dffsr is --synchronous reset
port(
clk: in std_logic;
sreset : in std_logic;
d: in std_logic;
q: out std_logic);
end component;
component lpm_fifo16x16 IS
PORT
(
aclr : IN STD_LOGIC ;
clock : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
rdreq : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
empty : OUT STD_LOGIC ;
full : OUT STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
usedw : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END component;
--Signals for store command from EPP
signal CmdFlag: std_logic; --This is the flag to show wich byte of EPPCmdWord is to be written
signal EPPCmdWord : std_Logic_vector(15 downto 0); --This is the command get from EPP, all the other operation are controlled by this
--it can be split to two part: ControlByte(7 downto 0) and DataByte(7 downto 0):
signal ControlByte, DataByte : std_logic_vector(7 downto 0);
signal wrEPPCmd : std_logic;
--Fifos: Here we need two fifo, Read Fifo and Write Fifo:
--1. WriteFifo:
signal WriteFifoAclr, WriteFifoClock, WriteFifoRdReq, WriteFifoWrreq, WriteFifoEmpty, WriteFifoFull: std_logic;
signal WriteFifoUsedw: std_logic_vector(3 downto 0);
signal WriteFifoData, WriteFifoQ : std_logic_vector(15 downto 0);
signal WriteFifoStatus : std_logic_vector(5 downto 0);
--2. ReadFifo:
signal ReadFifoAclr, ReadFifoClock, ReadFifoRdreq, ReadFifoWrreq, ReadFifoEmpty, ReadFifoFull : std_logic;
signal ReadFifoUsedw: std_logic_vector(3 downto 0);
signal ReadFifoData, ReadFifoQ : std_logic_vector(15 downto 0);
signal ReadFifoStatus : std_logic_vector(5 downto 0);
--Flash Memory Control Statemachine
type FlashCtrlStateTYPE is(IDLE, SingleRead, BlockRead, BlockWrite, SECTORERASE, CHIPERASE, CHIPRESET);
signal FlashState : FlashCtrlStateTYPE;
signal FlashStateStatus : std_logic_vector(7 downto 0);
--Signal for READ Flash Memroy(both SingleRead and BlockRead):
signal ReadFlashTimer : integer range 0 to 15;
signal ReadFlashCounter : integer range 0 to 16;
signal TargetFlashMemPageAddr : std_logic_vector(ADDRESS_WIDTH-1 downto 0); --This is the Flash Memory Page Address that will be operated,
--Page address means that the lower 4bit is '0';
--Signal for Write Flash Memory
signal WriteTimer : integer range 0 to 511;
signal SingleWriteTimer : integer range 0 to 15;
signal WriteFlashCounter: integer range 0 to 16;
signal TargetFlashMemSectorAddr : std_logic_vector(ADDRESS_WIDTH-1 downto 0); -- This is the Sector Address that is needed for BlockWrite
--SECTORERASE and CHIPERASE operation
begin
wrEPPCmdOut <= wrEPPCmd;
EPPCmdWordOut <= EPPCmdWord;
---------------------------------------------------------------------------------------------------------
--get Command from EPPInterface
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
--get Command from EPPInterface
---------------------------------------------------------------------------------------------------------
gen_EPPCmdWord: process(reset,clk)
begin
if reset='1' then
CmdFlag <= '0';
EPPCmdWord <= (others => '0');
wrEPPCmd <= '0';
elsif clk'event and clk='1' then
if CS = '1' and wrCmdByte = '1' then
CmdFlag <= not CmdFlag;
if CmdFlag = '1' then
wrEPPCmd <= '1';
else
wrEPPCmd <= '0';
end if;
case CmdFlag is
when '0' => EPPCmdWord(7 downto 0) <= CmdByte;
when '1' => EPPCmdWord(15 downto 8) <= CmdByte;
when others =>
end case;
else
wrEPPCmd <= '0';
end if;
end if;
end process;
ControlByte(7 downto 0) <= EPPCmdWord(15 downto 8);
DataByte(7 downto 0) <= EPPCmdWord(7 downto 0);
---------------------------------------------------------------------------------------------------------
--WriteFifo Control
--WriteFifo use ControlByte address space 0x50~0x5F
---------------------------------------------------------------------------------------------------------
WriteFifo: lpm_fifo16x16
port map(
aclr => WriteFifoAclr,
clock => WriteFifoClock,
data => WriteFifoData,
rdreq => WriteFifoRdreq,
wrreq => WriteFifoWrreq,
empty => WriteFifoEmpty,
full => WriteFifoFull,
q => WriteFifoQ,
usedw => WriteFifoUsedw);
WriteFifoClock <= clk;
WriteFifoStatus <= WriteFifoEmpty & WriteFifoFull & WriteFifoUsedw;
gen_WriteFifoAclr: process(reset,clk)
begin
if reset = '1' then
WriteFifoAclr <= '1';
elsif clk'event and clk='1' then
if wrEPPCmd='1' and ControlByte = X"50" then
WriteFifoAclr <= '1';
else
WriteFifoAclr <= '0';
end if;
end if;
end process;
gen_WriteFifoData : process(reset,clk)
begin
if reset = '1' then
WriteFifoWrreq <= '0';
WriteFifoData <= (others => '0');
elsif clk'event and clk = '1' then
--wrEPPCmd is a one clock cycle wide pulse, thus the width of WriteFifoWrreq will be 1 clock cycle
if wrEPPCmd = '1' then
case ControlByte is
when X"51" =>
WriteFifoData(7 downto 0) <= DataByte;
when X"52" =>
WriteFifoWrreq <= '1';
WriteFifoData(15 downto 8) <= DataByte;
when others =>
WriteFifoWrreq <= '0';
end case;
else
WriteFifoWrreq <= '0';
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------------
--ReadFifo Control
--ReadFifo uses ControlByte address space 0x60~0x6F
---------------------------------------------------------------------------------------------------------
ReadFifo: lpm_fifo16x16
port map(
aclr => ReadFifoAclr,
clock => ReadFifoClock,
data => ReadFifoData,
rdreq => ReadFifoRdreq,
wrreq => ReadFifoWrreq,
empty => ReadFifoEmpty,
full => ReadFifoFull,
q => ReadFifoQ,
usedw => ReadFifoUsedw);
ReadFifoClock <= clk;
ReadFifoStatus <= ReadFifoEmpty & ReadFifoFull & ReadFifoUsedw;
gen_ReadFifoAclk : process(reset,clk)
begin
if reset = '1' then
ReadFifoAclr <= '1';
elsif clk'event and clk='1' then
if wrEPPCmd = '1' and ControlByte <= X"60" then
ReadFifoAclr <= '1';
else
ReadFifoAclr <= '0';
end if;
end if;
end process;
gen_ReadFifoRdreq : process(reset,clk)
begin
if reset = '1' then
ReadFifoRdreq <= '0';
elsif clk'event and clk='1' then
if wrEPPCmd = '1' and ControlByte <= X"61" then
ReadFifoRdreq <= '1';
else
ReadFifoRdreq <= '0';
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------------
--Target Address:
--TargetFlashMemPageAddr and TargetFlashMemSectorAddr
---------------------------------------------------------------------------------------------------------
gen_TargetFlashAddr : process(reset,clk)
begin
if reset = '1' then
TargetFlashMemPageAddr <= (others => '0');
TargetFlashMemSectorAddr <= (others => '0');
elsif clk'event and clk='1' then
if wrEPPCmd = '1' then
case ControlByte is
when X"19" => TargetFlashMemPageAddr(7 downto 0) <= DataByte;
when X"1A" => TargetFlashMemPageAddr(15 downto 8) <= DataByte;
when X"1B" => TargetFlashMemPageAddr(23 downto 16) <= DataByte;
when X"1C" => TargetFlashMemSectorAddr(7 downto 0) <= DataByte;
when X"1D" => TargetFlashMemSectorAddr(15 downto 8) <= DataByte;
when X"1E" => TargetFlashMemSectorAddr(23 downto 16) <= DataByte;
when others =>
end case;
end if;
end if;
end process;
----------------------------------------------------------------------------------------------------------
--ReadOut
----------------------------------------------------------------------------------------------------------
gen_DataToEPP: process(reset,clk)
begin
if reset = '1' then
DataToEPP <= (others => '0');
elsif clk'event and clk = '1' then
if wrEPPCmd = '1' then
case ControlByte is
when X"53" => --Status of WriteFifo
DataToEPP(5 downto 0) <= WriteFifoStatus(5 downto 0);
DataToEPP(7 downto 6) <= (others => '0');
when X"62" =>
DataToEPP <= ReadFifoQ(7 downto 0);
when X"63" =>
DataToEPP <= ReadFifoQ(15 downto 8); --Even for 8bit operation, since we use 16bit Fifo, still we have ReadFifoQ(15 downto 8),
--it will be X"00" in 8 bit mode;
when X"64" => --Status of ReadFifo
DataToEPP(5 downto 0) <= ReadFifoStatus(5 downto 0);
DataToEPP(7 downto 6) <= (others => '0');
when X"17" => --FlashStateStatus
DataToEPP <= FlashStateStatus;
when others =>
end case;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------------
--State Machine:
---------------------------------------------------------------------------------------------------------
genFlashState: process(reset,clk)
begin
if reset = '1' then
FlashState <= IDLE;
CENeg <= '1';
WENeg <= '1';
OENeg <= '1';
RESETNeg <= '1';
--Sig for rdLUT:
ReadFlashTimer <= 0;
ReadFlashCounter <= 0;
--Sig for Write and ERASE
WriteTimer <= 0;
SingleWriteTimer <= 0;
WriteFlashCounter <= 0;
LUTData <= (others => 'Z');
FlashAddr <= (others => '0');
ReadFifoData <= (others => '0');
WriteFifoRdReq <= '0';
ReadFifoWrreq <= '0';
FlashDQ <= (others => 'Z');
FlashStateStatus <= X"00";
elsif clk'event and clk='1' then
case FlashState is
when IDLE =>
CENeg <= '1';
WENeg <= '1';
OENeg <= '1';
RESETNeg <= '1';
ReadFlashTimer <= 0;
ReadFlashCounter <= 0;
WriteTimer <= 0;
SingleWriteTimer <= 0;
WriteFlashCounter <= 0;
LUTData <= (others => 'Z');
FlashAddr <= (others => '0');
FlashDQ <= (others => 'Z');
if wrEPPCmd = '1' then
case ControlByte is
when X"11" =>
FlashState <= SingleRead;
when X"12" =>
FlashState <= BlockRead;
when X"13" =>
FlashState <= BlockWrite;
when X"14" =>
FlashState <= SECTORERASE;
when X"15" =>
FlashState <= CHIPERASE;
when X"16" =>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -