1
0
SEm-Labos/Libs/Memory_test/hdl/Flash_behav.vhd
github-classroom[bot] d212040c30
Initial commit
2024-02-23 13:01:05 +00:00

529 lines
21 KiB
VHDL

use std.textio.all;
ARCHITECTURE behav OF flash_28F128J3A IS
-- controls
signal chipSelect : std_ulogic;
signal writePulse : std_ulogic;
signal writePulseDelayed : std_ulogic;
signal memoryCommand : unsigned(7 downto 0);
signal wordProgramBusy : std_ulogic := '0';
signal blockEraseBusy : std_ulogic := '0';
signal busy : std_ulogic;
signal readPulseCs : std_ulogic := '0';
signal readPulseOe : std_ulogic := '0';
signal readPulse : std_ulogic;
signal memoryAddressDebug : unsigned(A'range);
type state_type is (
READ_ARRAY,
READ_ID_CODES,
READ_QUERY,
READ_STATUS,
WRITE_BUFFER,
WORD_PROGRAM_1,
WORD_PROGRAM_2,
BLOCK_ERASE_1,
BLOCK_ERASE_2,
CONFIG,
PROG_LOCK_BITS,
PROG_PROT,
BOTCH_LOCK,--
BOTCH_LOCK_ERS_SUSP,--
LOCK_DONE,
PROG_LOCK_BITS_ERS_SUSP,--
LOCK_DONE_ERS_SUSP,
PROT_PROG_BUSY,--
PROT_PROG_DONE,--
WORD_PROGRAM_1_ERS_SUSP,--
PROG_BUSY,--
PROG_BUSY_ERS_SUSP,--
READ_STATUS_PROG_SUSP,--
READ_ARRAY_PROG_SUSP,--
READ_CONFIG_PROG_SUSP,--
READ_QUERY_PROG_SUSP,--
PROGRAM_DONE,--
PROGRAM_DONE_ERS_SUSP,--
BOTCH_ERS,--
ERASE_BUSY,--
READ_STATUS_ERS_SUSP,--
READ_ARRAY_ERS_SUSP,--
READ_CONFIG_ERS_SUSP,--
READ_QUERY_ERS_SUSP,--
ERASE_DONE--
);
signal currentState : state_type;
signal nextState : state_type;
-- storage
constant blockLength : positive:= 16#10000#; -- 64 Kword blocks
constant memoryLength: positive := 2**(A'length-1);
-- constant memoryLength : positive := 2*blockLength;
subtype memoryWord is std_ulogic_vector(DQ'range);
type memoryArray is array(0 to memoryLength-1) of memoryWord;
signal memoryDataWord : memoryWord;
BEGIN
--############################################################################
-- Controls
------------------------------------------------------------------------------
chipSelect <= ( (not CE(2)) and (not CE(1)) and (not CE(0)) ) or
( CE(2) and ( (not CE(1)) or (not CE(0)) ) );
writePulse <= chipSelect and not(WE_n);
writePulseDelayed <= writePulse after 1 ns;
memoryCommand <= unsigned(DQ(memoryCommand'range));
process(chipSelect)
begin
if rising_edge(chipSelect) then
readPulseCs <= '1' after T_R3;
elsif falling_edge(chipSelect) then
readPulseCs <= '0' after T_R8;
end if;
end process;
process(OE_n)
begin
if falling_edge(OE_n) then
readPulseOe <= '1' after T_R7;
elsif rising_edge(OE_n) then
readPulseOe <= '0' after T_R9;
end if;
end process;
readPulse <= readPulseCs and readPulseOe;
------------------------------------------------------------------------------
-- Programming delays
------------------------------------------------------------------------------
wordProgramBusy <= '1', '0' after T_W16_program when currentState = WORD_PROGRAM_2;
blockEraseBusy <= '1', '0' after T_W16_erase when currentState = BLOCK_ERASE_2;
busy <= wordProgramBusy or blockEraseBusy;
------------------------------------------------------------------------------
-- FSM: find next state
------------------------------------------------------------------------------
-- Table 4 p. 12
process(writePulse, busy)
begin
case currentState is
when READ_ARRAY | READ_ID_CODES | READ_QUERY | READ_STATUS =>
case to_integer(memoryCommand) is
when 16#FF# => nextState <= READ_ARRAY;
when 16#90# => nextState <= READ_ID_CODES;
when 16#98# => nextState <= READ_QUERY;
when 16#70# => nextState <= READ_STATUS;
when 16#E8# => nextState <= WRITE_BUFFER;
when 16#10# | 16#40# => nextState <= WORD_PROGRAM_1;
when 16#20# => nextState <= BLOCK_ERASE_1;
when 16#B8# => nextState <= CONFIG;
when 16#60# => nextState <= PROG_LOCK_BITS;
when 16#C0# => nextState <= PROG_PROT;
when others => nextState <= READ_ARRAY;
end case;
when WORD_PROGRAM_1 =>
nextState <= WORD_PROGRAM_2;
when WORD_PROGRAM_2 =>
nextState <= READ_ARRAY;
when BLOCK_ERASE_1 =>
if to_integer(memoryCommand) = 16#D0# then
nextState <= BLOCK_ERASE_2;
else
nextState <= READ_ARRAY;
end if;
when BLOCK_ERASE_2 =>
nextState <= READ_ARRAY;
-- WHEN PROG_LOCK_BITS =>
-- IF rising_edge(WENeg) THEN
-- -- SECOND CYCLE CHECK
-- IF data=16#D0# OR data=16#01# OR data=16#2F# THEN
-- nextState<=READ_ARRAY;
-- ELSE
-- nextState <= BOTCH_LOCK;
-- END IF;
-- END IF;
--
-- WHEN PROG_LOCK_BITS_ERS_SUSP =>
-- IF rising_edge(WENeg) THEN
-- IF data=16#D0# OR data=16#01# OR data=16#2F# THEN
-- nextState<=READ_ARRAY_ERS_SUSP;
-- ELSE
-- nextState <= BOTCH_LOCK_ERS_SUSP;
-- END IF;
-- END IF;
--
--
-- WHEN LOCK_DONE =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1;
-- WHEN 16#20# => nextState <= BLOCK_ERASE_1;
-- WHEN 16#70# => nextState <= READ_STATUS;
-- WHEN 16#90# => nextState <= READ_CONFIG;
-- WHEN 16#98# => nextState <= READ_QUERY;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS;
-- WHEN 16#C0# => nextState <= PROG_PROT;
-- WHEN OTHERS => nextState <= READ_ARRAY;
-- END CASE;
-- END IF;
--
-- WHEN LOCK_DONE_ERS_SUSP =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1_ERS_SUSP;
-- WHEN 16#70# => nextState <= READ_STATUS_ERS_SUSP;
-- WHEN 16#90# => nextState <= READ_CONFIG_ERS_SUSP;
-- WHEN 16#98# => nextState <= READ_QUERY_ERS_SUSP;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS_ERS_SUSP;
-- WHEN 16#D0# => nextState <= ERASE_BUSY;
-- WHEN OTHERS => nextState <= READ_ARRAY_ERS_SUSP;
-- END CASE;
-- END IF;
--
-- WHEN BOTCH_LOCK =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1;
-- WHEN 16#20# => nextState <= BLOCK_ERASE_1;
-- WHEN 16#70# => nextState <= READ_STATUS;
-- WHEN 16#90# => nextState <= READ_CONFIG;
-- WHEN 16#98# => nextState <= READ_QUERY;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS;
-- WHEN 16#C0# => nextState <= PROG_PROT;
-- WHEN OTHERS => nextState <= READ_ARRAY;
-- END CASE;
-- END IF;
--
-- WHEN BOTCH_LOCK_ERS_SUSP =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# =>
-- nextState <= WORD_PROGRAM_1_ERS_SUSP;
-- WHEN 16#70# => nextState <= READ_STATUS_ERS_SUSP;
-- WHEN 16#90# => nextState <= READ_CONFIG_ERS_SUSP;
-- WHEN 16#98# => nextState <= READ_QUERY_ERS_SUSP;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS_ERS_SUSP;
-- WHEN OTHERS => nextState <= READ_ARRAY_ERS_SUSP;
-- END CASE;
-- END IF;
--
--
-- WHEN BOTCH_ERS =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# =>
-- nextState <= WORD_PROGRAM_1;
-- WHEN 16#20# => nextState <=BLOCK_ERASE_1;
-- WHEN 16#70# => nextState <= READ_STATUS;
-- WHEN 16#90# => nextState <= READ_CONFIG;
-- WHEN 16#98# => nextState <= READ_QUERY;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS;
-- WHEN 16#C0# => nextState <= PROG_PROT;
-- WHEN OTHERS => nextState <= READ_ARRAY;
-- END CASE;
-- END IF;
--
--
-- WHEN PROG_PROT =>
-- IF rising_edge(WENeg) THEN
-- nextState <= PROT_PROG_BUSY;
-- END IF;
--
-- WHEN PROT_PROG_BUSY =>
-- IF S_Reg(7)='1' THEN
-- nextState <= PROT_PROG_DONE;
-- ELSE
-- nextState <= PROT_PROG_BUSY;
-- END IF;
--
-- WHEN PROT_PROG_DONE =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1;
-- WHEN 16#20# => nextState <= BLOCK_ERASE_1;
-- WHEN 16#70# => nextState <= READ_STATUS;
-- WHEN 16#90# => nextState <= READ_CONFIG;
-- WHEN 16#98# => nextState <= READ_QUERY;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS;
-- WHEN 16#C0# => nextState <= PROG_PROT;
-- WHEN OTHERS => nextState <= READ_ARRAY;
-- END CASE;
-- END IF;
--
-- WHEN WORD_PROGRAM_1 =>
-- IF rising_edge(WENeg) THEN
-- nextState <= PROG_BUSY;
-- END IF;
--
-- WHEN WORD_PROGRAM_1_ERS_SUSP =>
-- IF rising_edge(WENeg) THEN
-- nextState <= PROG_BUSY_ERS_SUSP;
-- END IF;
--
-- WHEN PROG_BUSY =>
-- IF WDone THEN
-- nextState<=PROGRAM_DONE;
-- ELSIF rising_edge(WENeg) THEN
-- IF data= 16#B0# THEN
-- nextState <= READ_STATUS_PROG_SUSP;
-- ELSE
-- nextState <= PROG_BUSY;
-- END IF;
-- END IF;
--
-- WHEN PROG_BUSY_ERS_SUSP =>
-- IF WDone THEN
-- nextState<=PROGRAM_DONE_ERS_SUSP;
-- ELSIF rising_edge(WENeg) THEN
-- nextState <= PROG_BUSY_ERS_SUSP;
-- END IF;
--
-- WHEN READ_STATUS_PROG_SUSP | READ_ARRAY_PROG_SUSP |
-- READ_CONFIG_PROG_SUSP | READ_QUERY_PROG_SUSP =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- --WHEN 16#D0# => nextState <= READ_ARRAY_PROG_SUSP;
-- WHEN 16#D0# => nextState <= PROG_BUSY;
-- WHEN 16#B0# | 16#70# => nextState <= READ_STATUS_PROG_SUSP;
-- WHEN 16#90# => nextState <= READ_CONFIG_PROG_SUSP;
-- WHEN 16#98# => nextState <= READ_QUERY_PROG_SUSP;
-- WHEN OTHERS => nextState <= READ_ARRAY_PROG_SUSP;
-- END CASE;
-- END IF;
--
-- WHEN PROGRAM_DONE =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1;
-- WHEN 16#20# => nextState <= BLOCK_ERASE_1;
-- WHEN 16#70# => nextState <= READ_STATUS;
-- WHEN 16#90# => nextState <= READ_CONFIG;
-- WHEN 16#98# => nextState <= READ_QUERY;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS;
-- WHEN 16#C0# => nextState <= PROG_PROT;
-- WHEN OTHERS => nextState <= READ_ARRAY;
-- END CASE;
-- END IF;
--
-- WHEN PROGRAM_DONE_ERS_SUSP =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1_ERS_SUSP;
-- WHEN 16#B0# | 16#70# => nextState <= READ_STATUS_ERS_SUSP;
-- WHEN 16#D0# => nextState <= ERASE_BUSY;
-- WHEN 16#90# => nextState <= READ_CONFIG_ERS_SUSP;
-- WHEN 16#98# => nextState <= READ_QUERY_ERS_SUSP;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS_ERS_SUSP;
-- WHEN OTHERS => nextState <= READ_ARRAY_ERS_SUSP;
-- END CASE;
-- END IF;
--
--
-- WHEN ERASE_BUSY =>
-- IF rising_edge(WENeg) AND data= 16#B0# THEN
-- nextState <= READ_STATUS_ERS_SUSP;
-- ELSIF EDone AND ECount=31 THEN
-- nextState<=ERASE_DONE;
-- ELSE
-- nextState <= ERASE_BUSY;
-- END IF;
--
-- WHEN READ_STATUS_ERS_SUSP | READ_ARRAY_ERS_SUSP |
-- READ_CONFIG_ERS_SUSP | READ_QUERY_ERS_SUSP =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <=WORD_PROGRAM_1_ERS_SUSP;
-- WHEN 16#B0# | 16#70# | 16#80# =>
-- nextState<= READ_STATUS_ERS_SUSP;
-- WHEN 16#D0# => nextState <= ERASE_BUSY;
-- WHEN 16#90# => nextState <= READ_CONFIG_ERS_SUSP;
-- WHEN 16#98# => nextState <= READ_QUERY_ERS_SUSP;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS_ERS_SUSP;
-- WHEN OTHERS => nextState <= READ_ARRAY_ERS_SUSP;
-- END CASE;
-- END IF;
--
-- WHEN ERASE_DONE =>
-- IF rising_edge(WENeg) THEN
-- CASE data IS
-- WHEN 16#10# | 16#40# => nextState <= WORD_PROGRAM_1;
-- WHEN 16#20# => nextState <= BLOCK_ERASE_1;
-- WHEN 16#70# => nextState <= READ_STATUS;
-- WHEN 16#90# => nextState <= READ_CONFIG;
-- WHEN 16#98# => nextState <= READ_QUERY;
-- WHEN 16#60# => nextState <= PROG_LOCK_BITS;
-- WHEN 16#C0# => nextState <= PROG_PROT;
-- WHEN OTHERS => nextState <= READ_ARRAY;
-- END CASE;
-- END IF;
when others => nextState <= READ_ARRAY;
end case;
end process;
------------------------------------------------------------------------------
-- FSM: update state
------------------------------------------------------------------------------
process(RP_N, writePulseDelayed, busy)
begin
if RP_n = '0' then
currentState <= READ_ARRAY;
elsif falling_edge(writePulseDelayed) then
currentState <= nextState;
elsif falling_edge(busy) then
currentState <= nextState;
end if;
end process;
------------------------------------------------------------------------------
-- STS
------------------------------------------------------------------------------
process
begin
STS <= '1';
wait on busy;
if rising_edge(busy) then
STS <= '0' after T_W13;
wait until falling_edge(busy);
end if;
end process;
--############################################################################
-- Storage
------------------------------------------------------------------------------
process(writePulse, A)
variable memContent : memoryArray; -- much faster than using a signal
variable loadMemFromFile : boolean := true;
file memoryFile : text open read_mode is fileSpec;
variable srecLine : line;
variable srecChar : character;
variable srecType : natural;
variable srecAddrLength : natural;
variable srecWordAscii : string(8 downto 1);
variable srecLength : natural;
variable srecAddress : natural;
variable memoryAddress : natural;
variable srecData : natural;
function readNumber(hexString: string) return natural is
variable currentCharPos: natural;
variable intValue: natural;
variable accValue: natural;
begin
accValue := 0;
for index in hexString'range loop
currentCharPos := character'pos(hexString(index));
if currentCharPos <= character'pos('9') then
intValue := currentCharPos - character'pos('0');
else
intValue := currentCharPos - character'pos('A') + 10;
end if;
accValue := accValue * 16 + intValue;
end loop;
return accValue;
end readNumber;
begin
if loadMemFromFile then
-- only happens at simulation start
while not endfile(memoryFile) loop
readline(memoryFile, srecLine);
--report "-> " & srecLine.all;
-- trim leading whitespaces
while (not (srecLine'length=0)) and (srecLine(srecLine'left) = ' ') loop
read(srecLine, srecChar);
end loop;
-- get record type
if srecLine'length > 0 then
read(srecLine, srecChar);
if (srecChar = 'S') or (srecChar = 's') then
read(srecLine, srecChar);
srecType := character'pos(srecChar) - character'pos('0');
--report "-> srec type: " & integer'image(srecType);
srecAddrLength := srecType + 1;
if (srecType >= 1) and (srecType <= 3) then
-- get record length
srecWordAscii := (others => '0');
read(srecLine, srecWordAscii(2));
read(srecLine, srecWordAscii(1));
srecLength := readNumber(srecWordAscii);
-- get record base address
srecWordAscii := (others => '0');
for index in 2*(srecAddrLength) downto 1 loop
read(srecLine, srecWordAscii(index));
end loop;
srecAddress := readNumber(srecWordAscii);
memoryAddress := srecAddress/2;
-- get record data
for index1 in 1 to (srecLength - srecAddrLength - 1) / 2 loop
srecWordAscii := (others => '0');
for index2 in 4 downto 1 loop
read(srecLine, srecWordAscii(index2));
end loop;
srecData := readNumber(srecWordAscii);
if memoryAddress < memoryLength then
memContent(memoryAddress) := std_ulogic_vector(to_unsigned(srecData, memoryWord'length));
end if;
memoryAddress := memoryAddress + 1;
end loop;
end if;
end if;
end if;
end loop;
loadMemFromFile := false;
else
-- normal functionality
if falling_edge(writePulse) then
-- program a word
if currentState = WORD_PROGRAM_1 then
memoryAddress := to_integer(A(A'high downto 1));
memoryAddressDebug <= to_unsigned(memoryAddress, memoryAddressDebug'length);
memContent(memoryAddress) := std_ulogic_vector(DQ);
-- erase a block
elsif currentState = BLOCK_ERASE_1 then
memoryAddress := to_integer(A and not(to_unsigned(blockLength-1, A'length)));
for index in 0 to blockLength-1 loop
if memoryAddress < memoryLength then
memContent(memoryAddress) := (others => '1');
memoryAddress := memoryAddress + 1;
end if;
end loop;
end if;
end if;
-- update readout data
if A'event then
memoryAddress := to_integer(A(A'high downto 1));
memoryAddressDebug <= to_unsigned(memoryAddress, memoryAddressDebug'length);
memoryDataWord <= memContent(memoryAddress) after T_R2;
end if;
end if;
end process;
process(memoryDataWord, readPulse)
begin
if readPulse = '1' then
DQ <= std_logic_vector(memoryDataWord);
else
DQ <= (others => 'Z');
end if;
end process;
END ARCHITECTURE behav;