Created
June 30, 2015 18:30
-
-
Save kratsg/783da60a9274601e855a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--********************************************************************************* | |
-- Indiana University | |
-- Center for Exploration of Energy and Matter (CEEM) | |
-- | |
-- Project: ATLAS | |
-- | |
-- Author: Brandon Kunkler | |
-- | |
-- Date: 03/04/2015 | |
-- | |
--********************************************************************************* | |
-- Description: | |
-- Writes data to algorithm FPGA SPI flash. Assumes program and read-back data | |
-- written and read on Ethernet or algorithm FPGA clock. The configuration data is | |
-- written into the FIFO and will be written to flash when an entire page is present. | |
-- There is a state machine for each low-level function. The low-level state machines | |
-- are controlled by a high-level mode state machine. | |
-- | |
-- The rate at which operations will be completed is based upon RATE_DIV. The logic | |
-- operates at clock frequency/RATE_DIV because all states are transitioned by a | |
-- clock enable that is created base upon RATE_DIV. | |
-- | |
-- The timing of MISO can be changed with SODLY. | |
-- | |
-- A MULT-CYCLE PATH CONSTRAINT SHOULD BE CREATED FOR FLIP-FLOPS WITH CE PIN CONNECTED | |
-- TO BIT_CE AND BYT_CE. | |
-- | |
-- The entire array must be un-protected (unless the hardware is changed). To keep | |
-- the contents protected the entire device mus be un-protected, the half that will | |
-- not be programmed protected, the erase + programming operation executed, and the | |
-- half that was programmed protected. | |
-- | |
-- DO NOT USE PROTECTION UNTIL ALL OF FUNCTIONS HAVE BEEN TESTED. THE FLASH CAN BE | |
-- PLACED INTO A NON-WORKING CONFIGURATION. | |
-- | |
-- A sector is 256 kBytes. An entire sector can be erased or protected. | |
-- | |
-- A page size is 512 bytes. A full page can be read or written. | |
-- | |
-- PROTECTION: | |
-- The Persistent Protection Bits (PPB) are located in a separate non-volatile flash | |
-- array. One of the PPB bits is related to each sector. When a PPB is 0, its related | |
-- sector is protected from program and erase operations. The PPB are programmed | |
-- individually but must be erased as a group, similar to the way individual words may | |
-- be programmed in the main array but an entire sector must be erased at the same time. | |
-- The PPB have the same program and erase endurance as the main flash memory array. | |
-- Pre-programming and verification prior to erasure are handled by the device. | |
-- | |
-- Deficiencies: | |
--********************************************************************************* | |
library ieee; | |
use ieee.std_logic_1164.all; | |
use ieee.std_logic_unsigned.all; | |
use ieee.numeric_std.all; | |
use ieee.std_logic_misc.all; | |
library unisim; | |
use unisim.vcomponents.all; | |
entity flash_prog is | |
generic( | |
RATE_DIV : integer := 0; | |
SODLY : integer := 4; | |
SIM_SPEEDUP : std_logic := '0'); | |
port( | |
-- control signals --------------- | |
clk : in std_logic; | |
reset : in std_logic; | |
rd_wr_n : in std_logic;--1=read-back, 0=write (program) | |
wrptct : in std_logic;--write protect flash contents | |
gld_upgd_n : in std_logic;--1=write golden, 0=write upgrade | |
start : in std_logic;--1=start operation | |
done : out std_logic;--1=operation complete | |
-- Program FIFO interface ------------ | |
fifo_afull : out std_logic;--1=entire page in FIFO | |
fifo_full : out std_logic;--1=FIFO completely full | |
fifo_wren : in std_logic;--1=write configuration data | |
fifo_di : in std_logic_vector(7 downto 0);--configuration data input | |
-- Read-back interface --------------- | |
dvalid : out std_logic; | |
dout : out std_logic_vector(7 downto 0); | |
-- SPI flash interface --------------- | |
mux_s : out std_logic := '1';-- 0 = write flash, 1 = configure FPGA | |
sclk : out std_logic := '1'; | |
csn : out std_logic := '1'; | |
mosi : out std_logic := '1'; | |
miso : in std_logic; | |
-- Status Data ------------------------ | |
status : out std_logic_vector(7 downto 0)); | |
end flash_prog; | |
--------------------------------------------------------------------------------------------------------- | |
-- Architecture declaration | |
--------------------------------------------------------------------------------------------------------- | |
architecture behave of flash_prog is | |
constant GLDN_BASE : std_logic_vector(31 downto 0) := X"00000000"; | |
constant UPGD_BASE : std_logic_vector(31 downto 0) := X"02000000"; | |
constant NSECTORS : std_logic_vector(7 downto 0) := X"7F";--1/2 256 sector device | |
constant NPAGES : std_logic_vector(15 downto 0) := X"FFFF";--1/2 65536*2=131072 sector device | |
constant CMD_WREN : std_logic_vector(7 downto 0) := X"06"; | |
constant CMD_ERSE : std_logic_vector(7 downto 0) := X"DC"; | |
constant CMD_STS1 : std_logic_vector(7 downto 0) := X"05"; | |
constant CMD_PGPM : std_logic_vector(7 downto 0) := X"12"; | |
constant CMD_READ : std_logic_vector(7 downto 0) := X"13"; | |
constant CMD_UPTT : std_logic_vector(7 downto 0) := X"E4"; | |
constant CMD_PTCT : std_logic_vector(7 downto 0) := X"E3"; | |
constant SCR_INITV : std_logic_vector(7 downto 0) := NSECTORS; | |
constant SCR_SIMV : std_logic_vector(7 downto 0) := X"02"; | |
constant ERS_SIMV : std_logic_vector(31 downto 0) := X"00000004"; | |
constant PGE_INITV : std_logic_vector(15 downto 0) := NPAGES; | |
constant PGE_SIMV : std_logic_vector(15 downto 0) := X"0004"; | |
constant SECTOR_SZ : std_logic_vector(19 downto 0) := X"40000"; | |
constant SECTOR_SIM : std_logic_vector(19 downto 0) := X"40000"; | |
constant PAGE_SZ : std_logic_vector(11 downto 0) := X"200"; | |
constant PAGE_SIM : std_logic_vector(11 downto 0) := X"200"; | |
constant FAEPTY : bit_vector(15 downto 0) := X"0002"; | |
constant FAFULL : bit_vector(15 downto 0) := X"0008";--make sure we have an entire page | |
type mode_fsm_type is (IDLES,UNPTCTS,PTCT1S,ERASES,WRITES,PTCT2S,READS,DONES);--mode state machine | |
type wren_fsm_type is (IDLES,LDCMDS,WRCMDS,RDSTSS,DONES); | |
type sts_fsm_type is (IDLES,LDCMDS,WRCMDS,RDSTSS,DONES); | |
type erase_fsm_type is (IDLES,WRENS,LDCMDS,WRCMDS,RDSTSS,NXTBKS,DONES); | |
type write_fsm_type is (IDLES,WRENS,LDCMDS,WRCMDS,WRPGES,RDSTSS,NXTPGS,DONES); | |
type read_fsm_type is (IDLES,WRENS,LDCMDS,WRCMDS,RDARYS,DONES); | |
type uptct_fsm_type is (IDLES,WRENS,LDCMDS,WRCMDS,RDSTSS,DONES); | |
type ptct_fsm_type is (IDLES,WRENS,LDCMDS,WRCMDS,RDSTSS,NXTBKS,DONES); | |
signal ptt_sel : std_logic_vector(1 downto 0); | |
signal base_addr : std_logic_vector(31 downto 0); | |
signal ce_ctr : std_logic_vector(4 downto 0) := (others => '1'); | |
signal ce_bitsel : std_logic := '0'; | |
signal ce_bytsel : std_logic := '0'; | |
signal ce_bit : std_logic := '0'; | |
signal ce_byt : std_logic := '0'; | |
signal ce_bitstb : std_logic := '0'; | |
signal bit_ce : std_logic := '0'; | |
signal byt_ce : std_logic := '0'; | |
signal lreset : std_logic; | |
signal freset : std_logic; | |
signal rst_shift : std_logic_vector(7 downto 0) :=X"F8"; | |
signal dvalidf : std_logic_vector(1 downto 0); | |
--signal read_regv : std_logic_vector(3 downto 0);--valid --%works in hardware no I/O FFs | |
--signal read_regv : std_logic_vector(2 downto 0);--valid --%works in simulation no I/O FFs | |
--signal read_regv : std_logic_vector(3 downto 0);--valid --%works in simulation with I/O FFs | |
--signal read_regv : std_logic_vector(4 downto 0);--valid --%works in hardware with I/O FFs | |
signal read_regv : std_logic_vector(SODLY downto 0);--valid --%works in hardware with I/O FFs | |
signal read_reg : std_logic_vector(7 downto 0) := (others => '0'); | |
signal write_reg_ld : std_logic_vector(7 downto 0) := (others => '0'); | |
signal write_reg : std_logic_vector(47 downto 0); | |
-- mode state machine signals | |
signal mode_fsm_cs : mode_fsm_type; | |
signal uptct_en : std_logic; | |
signal erase_en : std_logic; | |
signal write_en : std_logic; | |
signal ptct_en : std_logic; | |
signal read_en : std_logic; | |
signal ptct_1_2_n : std_logic; | |
-- write enable state machine | |
signal wren_fsm_cs : wren_fsm_type; | |
signal wren_en : std_logic; | |
signal wren_cs : std_logic :='0'; | |
signal wren_ldc : std_logic; | |
signal wren_ack : std_logic; | |
signal wren_sen : std_logic; | |
signal wren_sse : std_logic; | |
-- status state machine | |
signal sts_fsm_cs : sts_fsm_type; | |
signal sts_en : std_logic; | |
signal sts_cs : std_logic :='0'; | |
signal sts_ldc : std_logic; | |
signal sts_ack : std_logic; | |
signal sts_sen : std_logic; | |
signal sts_wel : std_logic := '0';-- Status register 1 WEL bit | |
signal sts_wip : std_logic := '0';-- Status register 1 WIP bit | |
signal sts_perr : std_logic := '0';-- Status register 1 P_ERR bit | |
signal sts_errr : std_logic := '0';-- Status register 1 E_ERR bit | |
-- erase state machine | |
signal erase_fsm_cs : erase_fsm_type; | |
signal erase_wren : std_logic; | |
signal erase_ldc : std_logic; | |
signal erase_lds : std_logic;-- load sector count | |
signal erase_cs : std_logic :='0';-- chip select | |
signal erase_sen : std_logic;-- shift enable | |
signal erase_sce : std_logic;-- sector count enable | |
signal erase_sse : std_logic;-- status enable | |
signal erase_ack : std_logic; | |
-- write state machine | |
signal write_fsm_cs : write_fsm_type; | |
signal write_wren : std_logic; | |
signal write_ldc : std_logic; | |
signal write_ldd : std_logic;--load data | |
signal write_ldp : std_logic; | |
signal write_cs : std_logic :='0'; | |
signal write_sen : std_logic; | |
signal write_pce : std_logic; | |
signal write_sse : std_logic;-- status enable | |
signal write_ack : std_logic; | |
signal write_rden : std_logic; | |
-- read state machine | |
signal read_fsm_cs : read_fsm_type; | |
signal read_wren : std_logic; | |
signal read_ldc : std_logic; | |
signal read_ldp : std_logic; | |
signal read_cs : std_logic :='0'; | |
signal read_sen : std_logic; | |
signal read_pce : std_logic; | |
signal read_rbe : std_logic; --read-back enable | |
signal read_ack : std_logic; | |
-- un-protect state machine | |
signal uptct_fsm_cs : uptct_fsm_type; | |
signal uptct_wren : std_logic; | |
signal uptct_ldc : std_logic; | |
signal uptct_cs : std_logic :='0'; | |
signal uptct_sen : std_logic; | |
signal uptct_sse : std_logic; | |
signal uptct_ack : std_logic; | |
-- protect state machine | |
signal ptct_fsm_cs : ptct_fsm_type; | |
signal ptct_wren : std_logic; | |
signal ptct_ldc : std_logic; | |
signal ptct_lds : std_logic;-- load sector count | |
signal ptct_cs : std_logic :='0';-- chip select | |
signal ptct_sen : std_logic;-- shift enable | |
signal ptct_sce : std_logic;-- sector count enable | |
signal ptct_sse : std_logic;-- status enable | |
signal ptct_ack : std_logic; | |
signal fifo_rden : std_logic := '0'; | |
signal fifo_do : std_logic_vector(fifo_di'length-1 downto 0); | |
signal fifo_aepty : std_logic; | |
signal fifo_epty : std_logic; | |
signal fifo_rderr : std_logic; | |
signal fifo_wrerr : std_logic; | |
signal fifo_do0 : std_logic_vector(63 downto 0); | |
signal fifo_di0 : std_logic_vector(63 downto 0); | |
signal byte_plen : std_logic_vector(11 downto 0) := (others => '1'); | |
signal byte_slen : std_logic_vector(19 downto 0) := (others => '1'); | |
signal byte_ctr_ld : std_logic; | |
signal byte_ctr : std_logic_vector(19 downto 0) := (others => '1'); | |
signal byte_ctr_tc0 : std_logic := '0'; | |
signal byte_ctr_tc1 : std_logic := '0'; | |
signal byte_ctr_tc2 : std_logic := '0'; | |
signal pge_init : std_logic_vector(15 downto 0); | |
signal pge_ctr_ld : std_logic; | |
signal pge_ctr_en : std_logic; | |
signal pge_ctr : std_logic_vector(15 downto 0) := (others => '1'); | |
signal pge_ctr_tc : std_logic := '0'; | |
signal scr_init : std_logic_vector(7 downto 0); | |
signal scr_ctr_ld : std_logic; | |
signal scr_ctr_en : std_logic; | |
signal scr_ctr : std_logic_vector(7 downto 0) := (others => '1'); | |
signal scr_ctr_tc : std_logic := '0'; | |
signal ers_addr_ld : std_logic; | |
signal ers_addr_en : std_logic; | |
signal ers_addr : std_logic_vector(31 downto 0) := (others => '1'); | |
signal ptt_init : std_logic_vector(31 downto 0) := (others => '1'); | |
signal ptt_addr_ld : std_logic; | |
signal ptt_addr_en : std_logic; | |
signal ptt_addr : std_logic_vector(31 downto 0) := (others => '1'); | |
signal wr_addr_ld : std_logic; | |
signal wr_addr_en : std_logic; | |
signal wr_addr : std_logic_vector(31 downto 0) := (others => '1'); | |
begin | |
FIFO36E1_inst : FIFO36E1 | |
generic map( | |
ALMOST_EMPTY_OFFSET => FAEPTY, -- Sets the almost empty threshold | |
ALMOST_FULL_OFFSET => FAFULL, -- Sets almost full threshold | |
DATA_WIDTH => 9, -- Sets data width to 4-72 | |
DO_REG => 0, -- Enable output register (1-0) Must be 1 if EN_SYN = FALSE | |
EN_ECC_READ => FALSE, -- Enable ECC decoder, FALSE, TRUE | |
EN_ECC_WRITE => FALSE, -- Enable ECC encoder, FALSE, TRUE | |
EN_SYN => TRUE, -- Specifies FIFO as Asynchronous (FALSE) or Synchronous (TRUE) | |
FIFO_MODE => "FIFO36", -- Sets mode to "FIFO36" or "FIFO36_72" | |
FIRST_WORD_FALL_THROUGH => FALSE, -- Sets the FIFO FWFT to FALSE, TRUE | |
INIT => X"000000000000000000", -- Initial values on output port | |
SIM_DEVICE => "7SERIES", -- Must be set to "7SERIES" for simulation behavior | |
SRVAL => X"000000000000000000") -- Set/Reset value for output port | |
port map( | |
-- ECC Signals: 1-bit (each) output: Error Correction Circuitry ports | |
DBITERR => open, -- 1-bit output: Double bit error status | |
ECCPARITY => open, -- 8-bit output: Generated error correction parity | |
SBITERR => open, -- 1-bit output: Single bit error status | |
-- Read Data: 64-bit (each) output: Read output data | |
DO => fifo_do0, -- 64-bit output: Data output | |
DOP => open, -- 8-bit output: Parity data output | |
-- Status: 1-bit (each) output: Flags and other FIFO status outputs | |
ALMOSTEMPTY => fifo_aepty, -- 1-bit output: Almost empty flag | |
ALMOSTFULL => fifo_afull, -- 1-bit output: Almost full flag | |
EMPTY => fifo_epty, -- 1-bit output: Empty flag | |
FULL => fifo_full, -- 1-bit output: Full flag | |
RDCOUNT => open, -- 13-bit output: Read count | |
RDERR => fifo_rderr, -- 1-bit output: Read error | |
WRCOUNT => open, -- 13-bit output: Write count | |
WRERR => fifo_wrerr, -- 1-bit output: Write error | |
-- ECC Signals: 1-bit (each) input: Error Correction Circuitry ports | |
INJECTDBITERR => '0', -- 1-bit input: Inject a double bit error input | |
INJECTSBITERR => '0', | |
-- Read Control Signals: 1-bit (each) input: Read clock, enable and reset input signals | |
RDCLK => clk, -- 1-bit input: Read clock | |
RDEN => fifo_rden, -- 1-bit input: Read enable | |
REGCE => '1', -- 1-bit input: Clock enable | |
RST => freset, -- 1-bit input: Reset | |
RSTREG => '0', -- 1-bit input: Output register set/reset | |
-- Write Control Signals: 1-bit (each) input: Write clock and enable input signals | |
WRCLK => clk, -- 1-bit input: Rising edge write clock. | |
WREN => fifo_wren, -- 1-bit input: Write enable | |
-- Write Data: 64-bit (each) input: Write input data | |
DI => fifo_di0, -- 64-bit input: Data input | |
DIP => X"00" -- 8-bit input: Parity input | |
); | |
-- assertions for simulation | |
assert (fifo_rderr='0' or fifo_rderr='U') report "flash_prog FIFO read error" severity ERROR; | |
assert (fifo_wrerr='0' or fifo_wrerr='U') report "flash_prog FIFO write error" severity ERROR; | |
------------------------------------------------------------------------------------------------ | |
-- Component instantiations | |
------------------------------------------------------------------------------------------------ | |
------------------------------------------------------------------------------------------------ | |
-- Concurrent statements | |
------------------------------------------------------------------------------------------------ | |
-------------------------------------------------------- | |
-- Map signals to ports | |
-------------------------------------------------------- | |
fifo_di0 <= STD_LOGIC_VECTOR(RESIZE(UNSIGNED(fifo_di),fifo_di0'length)); | |
fifo_do <= fifo_do0(fifo_di'length-1 downto 0); | |
-------------------------------------------------------- | |
-- Combinational logic | |
-------------------------------------------------------- | |
base_addr <= GLDN_BASE when gld_upgd_n = '1' else UPGD_BASE; | |
byte_plen <= (PAGE_SIM-2) when SIM_SPEEDUP = '1' else (PAGE_SZ-2); | |
byte_slen <= SECTOR_SIM when SIM_SPEEDUP = '1' else SECTOR_SZ; | |
scr_init <= SCR_SIMV when SIM_SPEEDUP = '1' else SCR_INITV; | |
pge_init <= PGE_SIMV when SIM_SPEEDUP = '1' else PGE_INITV; | |
-- add or remove control signals here to add or remove low-level functions ---------- | |
wren_en <= ptct_wren or uptct_wren or read_wren or write_wren or erase_wren; | |
sts_en <= ptct_sse or uptct_sse or write_sse or erase_sse or wren_sse; | |
byte_ctr_ld <= not (ptct_sen or uptct_sen or read_sen or write_sen or erase_sen); | |
--byte_ctr_ld <= erase_lds; | |
scr_ctr_ld <= ptct_lds or erase_lds; | |
scr_ctr_en <= ptct_sce or erase_sce; | |
pge_ctr_ld <= read_ldp or write_ldp; | |
pge_ctr_en <= read_pce or write_pce; | |
write_reg_ld <= ptct_ldc & uptct_ldc & read_ldc & write_ldd & write_ldc & erase_ldc & sts_ldc & wren_ldc; | |
------------------------------------------------------------------------------------- | |
------------------------------------------------------------------------------------------------ | |
-- Asynchronous and Synchronous processes | |
------------------------------------------------------------------------------------------------ | |
------------------------------------------------------------------------------------------- | |
-- Asynchronous processes | |
------------------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------- | |
-- Select the address which to protect. When the golden is to be programmed | |
-- must protect the upgrade before erase then the golden after program. | |
-- When the upgrade is to be programmed must protect the golden before | |
-- erase then the upgrade after program. | |
-------------------------------------------------------------------------- | |
ptt_sel <= ptct_1_2_n & gld_upgd_n; | |
ptt_init_pcs : process(ptt_sel) | |
begin | |
case ptt_sel is | |
when "00" => | |
ptt_init <= UPGD_BASE; | |
when "01" => | |
ptt_init <= GLDN_BASE; | |
when "10" => | |
ptt_init <= GLDN_BASE; | |
when "11" => | |
ptt_init <= UPGD_BASE; | |
when others => | |
ptt_init <= (others => 'X'); | |
end case; | |
end process; | |
------------------------------------------------------------------------------------------- | |
-- Synchronous processes | |
------------------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------- | |
-- Generate clock enables - one for bit period and one for byte period. | |
-- Use them to lower the rate and synchronize read/write operations. Byte | |
-- clock enable will keep the state machines synchronized. | |
-------------------------------------------------------------------------- | |
ce_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
ce_ctr <= (others => '1'); | |
ce_bitsel <= '0'; | |
ce_bytsel <= '0'; | |
ce_bit <= '0'; | |
ce_byt <= '0'; | |
ce_bitstb <= '0'; | |
bit_ce <= '0'; | |
byt_ce <= '0'; | |
else | |
ce_ctr <= ce_ctr - '1'; | |
if RATE_DIV = 2 then | |
ce_bitsel <= ce_ctr(0); | |
ce_bytsel <= ce_ctr(3); | |
else | |
ce_bitsel <= ce_ctr(1); | |
ce_bytsel <= ce_ctr(4); | |
end if; | |
ce_bit <= ce_bitsel; | |
ce_byt <= ce_bytsel; | |
ce_bitstb <= ce_bit; | |
bit_ce <= (not ce_bit) and ce_bitsel; | |
byt_ce <= (not ce_byt) and ce_bytsel; | |
end if; | |
end if; | |
end process; | |
-------------------------------------------------------------------------- | |
-- Generate resets that satisfy FIFO constraints. | |
-------------------------------------------------------------------------- | |
reset_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if reset = '1' then | |
rst_shift <= X"F8"; | |
freset <= '0'; | |
lreset <= '0'; | |
else | |
rst_shift <= '0' & rst_shift(rst_shift'length-1 downto 1); | |
freset <= rst_shift(0); | |
lreset <= OR_REDUCE(rst_shift(5 downto 0)); | |
end if; | |
end if; | |
end process; | |
-------------------------------------------------------------------------- | |
-- Register the inputs | |
-------------------------------------------------------------------------- | |
in_regs_pcs : process(clk) | |
begin | |
if (clk'event and clk = '1') then | |
if bit_ce = '1' then | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Input serial to parallel shift register (read register). | |
------------------------------------------------------------- | |
rd_reg_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if bit_ce = '1' then | |
read_reg <= read_reg(read_reg'length-2 downto 0) & miso; | |
end if; | |
-- latch the status bits when valid | |
if bit_ce = '1' then | |
read_regv <= byt_ce & read_regv(read_regv'length-1 downto 1); | |
end if; | |
if bit_ce = '0' then | |
if read_regv(1) = '1' then | |
sts_wel <= read_reg(1); | |
sts_wip <= read_reg(0); | |
if sts_cs = '1' then | |
sts_perr <= read_reg(6); | |
sts_errr <= read_reg(5); | |
end if; | |
end if; | |
end if; | |
-- mask first read valid pulses so wait for valid first read data | |
if read_rbe = '0' then | |
dvalidf <= (others => '0'); | |
else | |
if byt_ce = '1' then | |
dvalidf <= '1' & dvalidf(dvalidf'length-1 downto 1); | |
end if; | |
end if; | |
end if; | |
end process; | |
-------------------------------------------------------------------------- | |
-- Output registers. | |
-------------------------------------------------------------------------- | |
out_regs_pcs : process(clk) | |
begin | |
if (clk'event and clk = '1') then | |
if lreset = '1' then | |
mux_s <= '1'; | |
dvalid <= '0'; | |
dout <= (others => '0'); | |
sclk <= '1'; | |
csn <= '1'; | |
mosi <= '1'; | |
else | |
-- SPI Interface registers | |
mux_s <= not (uptct_en or erase_en or write_en or ptct_en or read_en);--assert if any mode active | |
dvalid <= bit_ce and dvalidf(0) and read_regv(1) and read_rbe; | |
dout <= read_reg; | |
sclk <= not ce_bitstb; | |
csn <= not (ptct_cs or uptct_cs or wren_cs or sts_cs or erase_cs or write_cs or read_cs); | |
mosi <= write_reg(write_reg'length-1); | |
end if; | |
-- concatenate the current mode and status register 1 error bits into a status word | |
status <= "0" & sts_perr & sts_errr & uptct_en & erase_en & write_en & ptct_en & read_en; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Output parallel to serial shift register with multiplexed | |
-- input. Make it long enough to shift command, address, and | |
-- first data byte to avoid delays. | |
------------------------------------------------------------- | |
write_reg_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if bit_ce = '1' then | |
case write_reg_ld is | |
when X"00" =>--shift | |
write_reg <= write_reg(write_reg'length-2 downto 0) & '0'; | |
when X"01" =>--set WEL bit command | |
write_reg <= CMD_WREN & X"0000000000"; | |
when X"02" =>--read status command | |
write_reg <= CMD_STS1 & X"0000000000"; | |
when X"04" =>--erase array command | |
write_reg <= CMD_ERSE & ers_addr & X"00"; | |
when X"08" =>--program array command | |
write_reg <= CMD_PGPM & wr_addr & fifo_do; | |
when X"10" =>--program array values with FIFO data | |
write_reg <= fifo_do & X"0000000000"; | |
when X"20" =>--read array data command | |
write_reg <= CMD_READ & base_addr & X"00"; | |
when X"40" =>--un-protect command | |
write_reg <= CMD_UPTT & X"0000000000"; | |
when X"80" =>--protect command | |
write_reg <= CMD_PTCT & ptt_addr & X"00"; | |
when others =>--shift | |
write_reg <= write_reg(write_reg'length-2 downto 0) & '0'; | |
end case; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Mode state machine. High-level control of the functionality. | |
------------------------------------------------------------- | |
mode_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
ptct_1_2_n <= '1'; | |
uptct_en <= '0'; | |
erase_en <= '0'; | |
write_en <= '0'; | |
ptct_en <= '0'; | |
read_en <= '0'; | |
done <= '0'; | |
mode_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
ptct_1_2_n <= '1'; | |
uptct_en <= '0'; | |
erase_en <= '0'; | |
write_en <= '0'; | |
ptct_en <= '0'; | |
read_en <= '0'; | |
done <= '0'; | |
------------------------------------------- | |
case mode_fsm_cs is | |
when IDLES => | |
-- wait for start to go high | |
if start = '1' then | |
if rd_wr_n = '1' then | |
-- read | |
mode_fsm_cs <= READS; | |
else | |
-- write | |
if wrptct = '1' then | |
-- un-protect | |
mode_fsm_cs <= UNPTCTS; | |
else | |
-- just write (after erase) | |
mode_fsm_cs <= ERASES; | |
end if; | |
end if; | |
else | |
mode_fsm_cs <= IDLES; | |
end if; | |
when UNPTCTS =>-- un-protect the entire flash | |
uptct_en <= '1'; | |
if uptct_ack = '1' then | |
mode_fsm_cs <= PTCT1S; | |
else | |
mode_fsm_cs <= UNPTCTS; | |
end if; | |
when PTCT1S =>-- protect half of flash that will not program | |
ptct_1_2_n <= '1'; | |
ptct_en <= '1'; | |
if ptct_ack = '1' then | |
mode_fsm_cs <= ERASES; | |
else | |
mode_fsm_cs <= PTCT1S; | |
end if; | |
when ERASES =>-- sector erase half of flash (must erase before write) | |
erase_en <= '1'; | |
if erase_ack = '1' then | |
mode_fsm_cs <= WRITES; | |
else | |
mode_fsm_cs <= ERASES; | |
end if; | |
when WRITES =>-- page program half of the flash | |
write_en <= '1'; | |
if write_ack = '1' then | |
if wrptct = '1' then | |
-- protect flash array | |
mode_fsm_cs <= PTCT2S; | |
else | |
-- we are done | |
mode_fsm_cs <= DONES; | |
end if; | |
else | |
mode_fsm_cs <= WRITES; | |
end if; | |
when PTCT2S =>-- protect half of flash that we programmed | |
ptct_1_2_n <= '0'; | |
ptct_en <= '1'; | |
if ptct_ack = '1' then | |
mode_fsm_cs <= DONES; | |
else | |
mode_fsm_cs <= PTCT2S; | |
end if; | |
when READS =>-- read back array | |
-- read entire flash | |
read_en <= '1'; | |
if read_ack = '1' then | |
mode_fsm_cs <= DONES; | |
else | |
mode_fsm_cs <= READS; | |
end if; | |
when DONES =>-- pulse done to signal end of operation | |
done <= '1'; | |
mode_fsm_cs <= IDLES; | |
when others => | |
mode_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- WREN state machine. Must execute this command before doing | |
-- anything else. Allows write to command registers. | |
------------------------------------------------------------- | |
wren_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
wren_ldc <= '0'; | |
wren_cs <= '0'; | |
wren_sen <= '0';--shift enable | |
wren_ack <= '0'; | |
wren_sse <= '0'; | |
wren_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
wren_cs <= '0'; | |
wren_ldc <= '0'; | |
wren_sen <= '0'; | |
wren_ack <= '0'; | |
wren_sse <= '0'; | |
------------------------------------------- | |
case wren_fsm_cs is | |
when IDLES =>-- wait for start to go high | |
if wren_en = '1' then | |
wren_fsm_cs <= LDCMDS; | |
else | |
wren_fsm_cs <= IDLES; | |
end if; | |
when LDCMDS =>-- load the command | |
wren_ldc <= '1'; | |
if byt_ce = '1' then | |
wren_fsm_cs <= WRCMDS; | |
else | |
wren_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>--write command | |
wren_cs <= '1'; | |
wren_sen <= '1'; | |
if byt_ce = '1' then | |
wren_fsm_cs <= RDSTSS; | |
else | |
wren_fsm_cs <= WRCMDS; | |
end if; | |
when RDSTSS =>-- read status register | |
wren_sse <= '1'; | |
-- wait until status good | |
if (sts_wel and (not sts_wip)) = '1' then | |
wren_fsm_cs <= DONES; | |
else | |
wren_fsm_cs <= RDSTSS; | |
end if; | |
when DONES =>-- signal end of operation | |
wren_ack <= sts_ack; | |
if (wren_en or sts_ack) = '0' then | |
wren_fsm_cs <= IDLES; | |
else | |
wren_fsm_cs <= DONES; | |
end if; | |
when others => | |
wren_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Status state machine. Read status register 1. Assume this | |
-- will be executed until operation successful. | |
-- MAKE SURE THIS FSM IS DONE BEFORE TRANSITIONING STATES IN | |
-- CONTROLLING STATE MACHINE. | |
------------------------------------------------------------- | |
sts_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
sts_ldc <= '0'; | |
sts_cs <= '0'; | |
sts_sen <= '0';--shift enable | |
sts_ack <= '0'; | |
sts_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
sts_cs <= '0'; | |
sts_ldc <= '0'; | |
sts_sen <= '0'; | |
sts_ack <= '0'; | |
------------------------------------------- | |
case sts_fsm_cs is | |
when IDLES =>-- wait for start to go high | |
sts_cs <= '0'; | |
sts_ldc <= '0'; | |
sts_sen <= '0'; | |
sts_ack <= '0'; | |
if sts_en = '1' then | |
sts_fsm_cs <= LDCMDS; | |
else | |
sts_fsm_cs <= IDLES; | |
end if; | |
when LDCMDS =>-- load the command | |
sts_ldc <= '1'; | |
if byt_ce = '1' then | |
sts_fsm_cs <= WRCMDS; | |
else | |
sts_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>--write command | |
sts_cs <= '1'; | |
sts_sen <= '1'; | |
if byt_ce = '1' then | |
sts_fsm_cs <= RDSTSS; | |
else | |
sts_fsm_cs <= WRCMDS; | |
end if; | |
when RDSTSS =>-- read status register | |
sts_cs <= '1'; | |
sts_sen <= '1'; | |
if ((not sts_en) and byt_ce) = '1' then | |
sts_fsm_cs <= DONES; | |
else | |
sts_fsm_cs <= RDSTSS; | |
end if; | |
when DONES =>-- signal end of operation | |
sts_ack <= '1'; | |
if sts_en = '0' then | |
sts_fsm_cs <= IDLES; | |
else | |
sts_fsm_cs <= DONES; | |
end if; | |
when others => | |
sts_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Erase state machine. Must execute this command before | |
-- writing configuration data to flash. | |
------------------------------------------------------------- | |
erase_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
erase_wren <= '0'; | |
erase_ldc <= '0'; | |
erase_lds <= '0'; | |
ers_addr_ld <= '0'; | |
erase_cs <= '0'; | |
erase_sen <= '0'; | |
erase_sce <= '0'; | |
ers_addr_en <= '0'; | |
erase_sse <= '0'; | |
erase_ack <= '0'; | |
erase_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
erase_wren <= '0'; | |
erase_ldc <= '0'; | |
erase_lds <= '0'; | |
ers_addr_ld <= '0'; | |
erase_cs <= '0'; | |
erase_sen <= '0'; | |
erase_sce <= '0'; | |
ers_addr_en <= '0'; | |
erase_sse <= '0'; | |
erase_ack <= '0'; | |
------------------------------------------- | |
case erase_fsm_cs is | |
when IDLES =>-- until erase required | |
if erase_en = '1' then | |
erase_lds <= '1'; | |
ers_addr_ld <= '1'; | |
erase_fsm_cs <= WRENS; | |
else | |
erase_lds <= '0'; | |
ers_addr_ld <= '0'; | |
erase_fsm_cs <= IDLES; | |
end if; | |
when WRENS =>-- set WEL bit | |
erase_wren <= '1'; | |
if wren_ack = '1' then | |
erase_fsm_cs <= LDCMDS; | |
else | |
erase_fsm_cs <= WRENS; | |
end if; | |
when LDCMDS =>-- load the sector erase command and address | |
erase_ldc <= '1'; | |
if byt_ce = '1' then | |
erase_fsm_cs <= WRCMDS; | |
else | |
erase_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>-- erase half of the flash | |
erase_sen <= '1'; | |
if byte_ctr_tc0 = '1' then | |
erase_cs <= '0'; | |
ers_addr_en <= '1'; | |
erase_fsm_cs <= RDSTSS; | |
else | |
erase_cs <= '1'; | |
ers_addr_en <= '0'; | |
erase_fsm_cs <= WRCMDS; | |
end if; | |
when RDSTSS =>-- read the status bit | |
-- read entire flash | |
erase_sse <= '1'; | |
if (read_regv(0) and (not sts_wip)) = '1' then | |
erase_fsm_cs <= NXTBKS;--!check the WIP (SR1[0]) and E_ERR (SR1[5]) bits | |
else | |
erase_fsm_cs <= RDSTSS; | |
end if; | |
when NXTBKS =>-- read next block or done | |
-- read entire flash | |
if sts_ack = '1' then | |
erase_sce <= '1'; | |
if scr_ctr_tc = '1' then | |
erase_fsm_cs <= DONES; | |
else | |
erase_fsm_cs <= WRENS; | |
end if; | |
else | |
erase_sce <= '0'; | |
erase_fsm_cs <= NXTBKS; | |
end if; | |
when DONES =>-- signal end of operation | |
erase_ack <= '1'; | |
if erase_en = '0' then | |
erase_fsm_cs <= IDLES; | |
else | |
erase_fsm_cs <= DONES; | |
end if; | |
when others => | |
erase_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Write state machine. Write pages of data to the flash array. | |
-- Must have an entire page in FIFO before write starts | |
-- (WRPGES state). | |
------------------------------------------------------------- | |
write_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
write_wren <= '0'; | |
write_ldc <= '0'; | |
write_ldd <= '0'; | |
write_ldp <= '0'; | |
wr_addr_ld <= '0'; | |
write_cs <= '0'; | |
write_sen <= '0'; | |
write_pce <= '0'; | |
wr_addr_en <= '0'; | |
write_sse <= '0'; | |
write_ack <= '0'; | |
write_rden <= '0'; | |
write_fsm_cs <= IDLES; | |
fifo_rden <= '0'; | |
else | |
-- generate one clock FIFO read enable | |
fifo_rden <= write_rden and byt_ce; | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
write_wren <= '0'; | |
write_ldc <= '0'; | |
write_ldd <= '0'; | |
write_ldp <= '0'; | |
wr_addr_ld <= '0'; | |
write_cs <= '0'; | |
write_sen <= '0'; | |
write_pce <= '0'; | |
wr_addr_en <= '0'; | |
write_sse <= '0'; | |
write_ack <= '0'; | |
write_rden <= '0'; | |
------------------------------------------- | |
case write_fsm_cs is | |
when IDLES =>-- wait for start | |
if (write_en and (not fifo_aepty)) = '1' then | |
write_ldp <= '1'; | |
wr_addr_ld <= '1'; | |
write_fsm_cs <= WRENS; | |
else | |
write_ldp <= '0'; | |
wr_addr_ld <= '0'; | |
write_fsm_cs <= IDLES; | |
end if; | |
when WRENS =>-- set the WEL bit so we can write command | |
write_wren <= '1'; | |
if (wren_ack and (not fifo_aepty)) = '1' then | |
write_fsm_cs <= LDCMDS; | |
else | |
write_fsm_cs <= WRENS; | |
end if; | |
when LDCMDS =>-- load the sector erase command and address and first data byte | |
write_ldc <= '1'; | |
write_rden <= '1'; | |
if byt_ce = '1' then | |
write_fsm_cs <= WRCMDS; | |
else | |
write_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>-- erase half of the flash | |
write_cs <= '1'; | |
if byte_ctr_tc0 = '1' then | |
write_sen <= '0'; | |
wr_addr_en <= '1'; | |
write_fsm_cs <= WRPGES; | |
else | |
write_sen <= '1'; | |
wr_addr_en <= '0'; | |
write_fsm_cs <= WRCMDS; | |
end if; | |
when WRPGES =>-- write a page | |
write_ldd <= byt_ce;-- wait until FIFO data valid | |
write_sen <= '1'; | |
write_rden <= '1'; | |
if byte_ctr_tc1 = '1' then | |
write_cs <= '0'; | |
write_fsm_cs <= RDSTSS; | |
else | |
write_cs <= '1'; | |
write_fsm_cs <= WRPGES; | |
end if; | |
when RDSTSS =>-- check the WIP (SR1[0]) and P_ERR (SR1[6]) bits | |
write_sse <= '1'; | |
if (read_regv(0) and (not sts_wip)) = '1' then | |
write_fsm_cs <= NXTPGS; | |
else | |
write_fsm_cs <= RDSTSS; | |
end if; | |
when NXTPGS =>-- get the next page or finish | |
write_sen <= '1'; | |
if sts_ack = '1' then | |
write_pce <='1'; | |
if pge_ctr_tc = '1' then | |
write_fsm_cs <= DONES; | |
else | |
write_fsm_cs <= WRENS; | |
end if; | |
else | |
write_pce <='0'; | |
write_fsm_cs <= NXTPGS; | |
end if; | |
when DONES =>-- signal end of operation | |
write_ack <= '1'; | |
if write_en = '0' then | |
write_fsm_cs <= IDLES; | |
else | |
write_fsm_cs <= DONES; | |
end if; | |
when others => | |
write_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Read state machine. Read half of the memory array. | |
------------------------------------------------------------- | |
read_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
read_wren <= '0'; | |
read_ldc <= '0'; | |
read_ldp <= '1'; | |
read_cs <= '0'; | |
read_sen <= '0'; | |
read_pce <= '0'; | |
read_rbe <= '0'; | |
read_ack <= '0'; | |
read_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
read_wren <= '0'; | |
read_ldc <= '0'; | |
read_ldp <= '0'; | |
read_cs <= '0'; | |
read_sen <= '0'; | |
read_pce <= '0'; | |
read_rbe <= '0'; | |
read_ack <= '0'; | |
------------------------------------------- | |
case read_fsm_cs is | |
when IDLES =>-- wait for start | |
if read_en = '1' then | |
read_fsm_cs <= WRENS; | |
else | |
read_fsm_cs <= IDLES; | |
end if; | |
when WRENS =>-- set the WEL so we can write | |
read_wren <= '1'; | |
if wren_ack = '1' then | |
read_fsm_cs <= LDCMDS; | |
else | |
read_fsm_cs <= WRENS; | |
end if; | |
when LDCMDS =>-- load the sector erase command and address | |
read_ldc <= '1'; | |
read_ldp <= '1'; | |
read_sen <= '1'; | |
if byt_ce = '1' then | |
read_fsm_cs <= WRCMDS; | |
else | |
read_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>-- write command to device | |
read_ldp <= '1'; | |
read_cs <= '1'; | |
if byte_ctr_tc0 = '1' then | |
read_sen <= '0'; | |
read_fsm_cs <= RDARYS; | |
else | |
read_sen <= '1'; | |
read_fsm_cs <= WRCMDS; | |
end if; | |
when RDARYS =>-- read half of the flash (+ one more byte?) | |
read_cs <= '1'; | |
read_sen <= not (byte_ctr_tc1 and byt_ce); | |
read_pce <= byte_ctr_tc1 and byt_ce; | |
read_rbe <= '1'; | |
if (pge_ctr_tc and byt_ce) = '1' then | |
read_fsm_cs <= DONES; | |
else | |
read_fsm_cs <= RDARYS; | |
end if; | |
when DONES =>-- signal end of operation | |
read_ldp <= '1'; | |
read_ack <= '1'; | |
read_rbe <= '1';--capture the last byte | |
if read_en = '0' then | |
read_fsm_cs <= IDLES; | |
else | |
read_fsm_cs <= DONES; | |
end if; | |
when others => | |
read_ldp <= '1'; | |
read_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Un-protect state machine. Protect half of the flash. | |
------------------------------------------------------------- | |
uptct_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
uptct_wren <= '0'; | |
uptct_ldc <= '0'; | |
uptct_cs <= '0'; | |
uptct_sen <= '0'; | |
uptct_sse <= '0'; | |
uptct_ack <= '0'; | |
uptct_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
uptct_wren <= '0'; | |
uptct_ldc <= '0'; | |
uptct_cs <= '0'; | |
uptct_sen <= '0'; | |
uptct_sse <= '0'; | |
uptct_ack <= '0'; | |
------------------------------------------- | |
case uptct_fsm_cs is | |
when IDLES =>-- wait until un-protect required | |
if uptct_en = '1' then | |
uptct_fsm_cs <= WRENS; | |
else | |
uptct_fsm_cs <= IDLES; | |
end if; | |
when WRENS =>-- set the WEL so we can write | |
uptct_wren <= '1'; | |
if wren_ack = '1' then | |
uptct_fsm_cs <= LDCMDS; | |
else | |
uptct_fsm_cs <= WRENS; | |
end if; | |
when LDCMDS =>-- load the sector unptct command and address | |
uptct_ldc <= '1'; | |
if byt_ce = '1' then | |
uptct_fsm_cs <= WRCMDS; | |
else | |
uptct_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>-- unptct half of the flash | |
uptct_sen <= '1'; | |
uptct_cs <= '1'; | |
if byt_ce = '1' then | |
uptct_fsm_cs <= RDSTSS; | |
else | |
uptct_fsm_cs <= WRCMDS; | |
end if; | |
when RDSTSS =>-- read the status register | |
uptct_sse <= '1'; | |
if (read_regv(0) and (not sts_wip)) = '1' then | |
uptct_fsm_cs <= DONES;--check the WIP (SR1[0]) bit | |
else | |
uptct_fsm_cs <= RDSTSS; | |
end if; | |
when DONES =>-- signal end of operation | |
uptct_ack <= '1'; | |
if uptct_en = '0' then | |
uptct_fsm_cs <= IDLES; | |
else | |
uptct_fsm_cs <= DONES; | |
end if; | |
when others => | |
uptct_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Protect state machine. Protect the half of the flash that | |
-- is not to be written or that was just written. | |
------------------------------------------------------------- | |
ptct_fsm : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if lreset = '1' then | |
ptct_wren <= '0'; | |
ptct_ldc <= '0'; | |
ptct_lds <= '0'; | |
ptt_addr_ld <= '0'; | |
ptct_cs <= '0'; | |
ptct_sen <= '0'; | |
ptct_sce <= '0'; | |
ptt_addr_en <= '0'; | |
ptct_sse <= '0'; | |
ptct_ack <= '0'; | |
ptct_fsm_cs <= IDLES; | |
else | |
if bit_ce = '1' then | |
-- default values ------------------------- | |
ptct_wren <= '0'; | |
ptct_ldc <= '0'; | |
ptct_lds <= '0'; | |
ptt_addr_ld <= '0'; | |
ptct_cs <= '0'; | |
ptct_sen <= '0'; | |
ptct_sce <= '0'; | |
ptt_addr_en <= '0'; | |
ptct_sse <= '0'; | |
ptct_ack <= '0'; | |
------------------------------------------- | |
case ptct_fsm_cs is | |
when IDLES =>-- until protect required | |
if ptct_en = '1' then | |
ptct_lds <= '1'; | |
ptt_addr_ld <= '1'; | |
ptct_fsm_cs <= WRENS; | |
else | |
ptct_lds <= '0'; | |
ptt_addr_ld <= '0'; | |
ptct_fsm_cs <= IDLES; | |
end if; | |
when WRENS =>-- set the WEL so we can write | |
ptct_wren <= '1'; | |
if wren_ack = '1' then | |
ptct_fsm_cs <= LDCMDS; | |
else | |
ptct_fsm_cs <= WRENS; | |
end if; | |
when LDCMDS =>-- load the sector erase command and address | |
ptct_ldc <= '1'; | |
if byt_ce = '1' then | |
ptct_fsm_cs <= WRCMDS; | |
else | |
ptct_fsm_cs <= LDCMDS; | |
end if; | |
when WRCMDS =>-- erase half of the flash | |
ptct_sen <= '1'; | |
if byte_ctr_tc0 = '1' then | |
ptct_cs <= '0'; | |
ptt_addr_en <= '1'; | |
ptct_fsm_cs <= RDSTSS; | |
else | |
ptct_cs <= '1'; | |
ptt_addr_en <= '0'; | |
ptct_fsm_cs <= WRCMDS; | |
end if; | |
when RDSTSS =>-- read the status bit | |
ptct_sse <= '1'; | |
if (read_regv(0) and (not sts_wip)) = '1' then | |
ptct_fsm_cs <= NXTBKS;--check the WIP (SR1[0]) and P_ERR (SR1[6]) bits | |
else | |
ptct_fsm_cs <= RDSTSS; | |
end if; | |
when NXTBKS =>-- protect next block or done | |
if sts_ack = '1' then | |
ptct_sce <= '1'; | |
if scr_ctr_tc = '1' then | |
ptct_fsm_cs <= DONES; | |
else | |
ptct_fsm_cs <= WRENS; | |
end if; | |
else | |
ptct_sce <= '0'; | |
ptct_fsm_cs <= NXTBKS; | |
end if; | |
when DONES =>-- signal end of operation | |
ptct_ack <= '1'; | |
if ptct_en = '0' then | |
ptct_fsm_cs <= IDLES; | |
else | |
ptct_fsm_cs <= DONES; | |
end if; | |
when others => | |
ptct_fsm_cs <= IDLES; | |
end case; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Count the number of bytes so we know when to increment the | |
-- page counter. | |
------------------------------------------------------------- | |
byte_count_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if byte_ctr_ld = '1' then | |
byte_ctr <= (others => '0'); | |
else | |
if byt_ce = '1' then | |
if byt_ce = '1' then | |
byte_ctr <= byte_ctr + 1; | |
end if; | |
end if; | |
end if; | |
-- terminal counts --------------- | |
if byt_ce = '1' then | |
-- control word + address | |
if (byte_ctr = X"000004") then | |
byte_ctr_tc0 <= '1'; | |
else | |
byte_ctr_tc0 <= '0'; | |
end if; | |
-- full page | |
if (byte_ctr = byte_plen) then | |
byte_ctr_tc1 <= '1'; | |
else | |
byte_ctr_tc1 <= '0'; | |
end if; | |
-- full sector | |
if (byte_ctr = byte_slen) then | |
byte_ctr_tc2 <= '1'; | |
else | |
byte_ctr_tc2 <= '0'; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Count the number of pages we have written or read. | |
------------------------------------------------------------- | |
page_count_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if pge_ctr_ld = '1' then | |
pge_ctr <= pge_init; | |
else | |
if bit_ce = '1' then | |
if pge_ctr_en = '1' then | |
pge_ctr <= pge_ctr - 1; | |
end if; | |
end if; | |
end if; | |
-- terminal count --------------- | |
if (pge_ctr = 0) then | |
pge_ctr_tc <= '1'; | |
else | |
pge_ctr_tc <= '0'; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Count the number of sectors we have erased or protected. | |
------------------------------------------------------------- | |
sector_count_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if scr_ctr_ld = '1' then | |
scr_ctr <= scr_init; | |
else | |
if bit_ce = '1' then | |
if scr_ctr_en = '1' then | |
scr_ctr <= scr_ctr - 1; | |
end if; | |
end if; | |
end if; | |
-- terminal count --------------- | |
if (scr_ctr = 0) then | |
scr_ctr_tc <= '1'; | |
else | |
scr_ctr_tc <= '0'; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Generate address for sector erase. | |
------------------------------------------------------------- | |
ers_addr_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if ers_addr_ld = '1' then | |
ers_addr <= base_addr; | |
else | |
if bit_ce = '1' then | |
if ers_addr_en = '1' then | |
ers_addr <= ers_addr + SECTOR_SZ; | |
end if; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Generate address for sector protect. | |
------------------------------------------------------------- | |
ptt_addr_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if ptt_addr_ld = '1' then | |
ptt_addr <= ptt_init; | |
else | |
if bit_ce = '1' then | |
if ptt_addr_en = '1' then | |
ptt_addr <= ptt_addr + SECTOR_SZ; | |
end if; | |
end if; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------- | |
-- Generate address for array write. | |
------------------------------------------------------------- | |
wr_addr_pcs : process(clk) | |
begin | |
if (clk'event and clk='1') then | |
if wr_addr_ld = '1' then | |
wr_addr <= base_addr; | |
else | |
if bit_ce = '1' then | |
if wr_addr_en = '1' then | |
wr_addr <= wr_addr + PAGE_SZ; | |
end if; | |
end if; | |
end if; | |
end if; | |
end process; | |
end behave; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment