529 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			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;
 | |
| 
 |