1
0
mirror of https://github.com/Klagarge/Cursor.git synced 2025-06-26 04:12:31 +00:00

Initial commit

This commit is contained in:
Rémi Heredero
2021-11-24 10:50:51 +01:00
commit c7ba678fbb
961 changed files with 501515 additions and 0 deletions

View File

@ -0,0 +1,528 @@
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;

View File

@ -0,0 +1,83 @@
ARCHITECTURE test OF bram_tester IS
constant clockFrequencyA: real := 66.0E6;
constant clockFrequencyB: real := 20.0E6;
constant clockPeriodA: time := (1.0/clockFrequencyA) * 1 sec;
constant clockPeriodB: time := (1.0/clockFrequencyB) * 1 sec;
signal clockA_int: std_uLogic := '1';
signal clockB_int: std_uLogic := '1';
signal addressA_int: natural;
signal dataA_int: integer;
signal addressB_int: natural;
signal dataB_int: integer;
BEGIN
------------------------------------------------------------------------------
-- clocks
clockA_int <= not clockA_int after clockPeriodA/2;
clockA <= transport clockA_int after clockPeriodA*9/10;
clockB_int <= not clockB_int after clockPeriodB/2;
clockB <= transport clockB_int after clockPeriodB*9/10;
------------------------------------------------------------------------------
-- test sequence
portA: process
begin
enA <= '0';
writeEnA <= '0';
addressA_int <= 0;
dataA_int <= 0;
-- read initial BRAM data
wait for 5*clockPeriodA;
addressA_int <= 40;
enA <= '1';
wait for clockPeriodA;
enA <= '0';
-- write data on port A
wait for 10*clockPeriodA;
addressA_int <= 10;
dataA_int <= 5;
enA <= '1';
writeEnA <= '1';
wait for clockPeriodA;
enA <= '0';
writeEnA <= '0';
wait;
end process portA;
addressA <= std_ulogic_vector(to_unsigned(addressA_int, addressA'length));
dataInA <= std_ulogic_vector(to_signed(dataA_int, dataInA'length));
portB: process
begin
enB <= '0';
writeEnB <= '0';
addressB_int <= 0;
dataB_int <= 0;
-- write data on port B
wait for 10*clockPeriodB;
addressB_int <= 20;
dataB_int <= 10;
enB <= '1';
writeEnB <= '1';
wait for clockPeriodB;
enB <= '0';
writeEnB <= '0';
-- read data written on port A
wait for 2*clockPeriodB;
addressB_int <= 10;
enB <= '1';
wait for clockPeriodB;
enB <= '0';
wait;
end process portB;
addressB <= std_ulogic_vector(to_unsigned(addressB_int, addressB'length));
dataInB <= std_ulogic_vector(to_signed(dataB_int, dataInB'length));
END ARCHITECTURE test;

View File

@ -0,0 +1,339 @@
--LIBRARY std;
-- USE std.textio.ALL;
LIBRARY COMMON_TEST;
USE COMMON_TEST.testUtils.all;
ARCHITECTURE test OF fifo_tester IS
constant clockFrequency: real := 66.0E6;
constant clockPeriod: time := (1.0/clockFrequency) * 1 sec;
signal clock_int: std_ulogic := '1';
constant testInterval: time := 10*clockPeriod;
signal dataIn_int: integer;
signal read_int: std_ulogic;
signal dataOffset: integer;
signal dataValid: std_ulogic;
signal dataRead: integer;
BEGIN
------------------------------------------------------------------------------
-- reset and clock
reset <= '1', '0' after 2*clockPeriod;
clock_int <= not clock_int after clockPeriod/2;
clock <= transport clock_int after clockPeriod*9/10;
------------------------------------------------------------------------------
-- test sequence
process
variable readIndex: integer;
begin
write <= '0';
read_int <= '0';
dataOffset <= -16#10#;
wait for 5*clockPeriod;
print(
lf & lf & lf &
"----------------------------------------------------------------" & lf &
"Starting testbench" & lf &
lf & lf
);
--..........................................................................
-- full write / read after end of write
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", full FIFO write direclty followed by full read" &
lf & lf
);
-- write FIFO
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
write <= '1';
for index in 0 to fifoDepth-1 loop
dataIn_int <= dataOffset + index;
wait for clockPeriod;
end loop;
write <= '0';
-- read FIFO
read_int <= '1';
readIndex := 0;
while empty = '0' loop
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
readIndex := readIndex + 1;
wait until rising_edge(clock_int);
end loop;
read_int <= '0';
--..........................................................................
-- full write / read after some time
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", full FIFO write and delay before read" &
lf & lf
);
-- write FIFO
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
write <= '1';
for index in 0 to fifoDepth-1 loop
dataIn_int <= dataOffset + index;
wait for clockPeriod;
end loop;
write <= '0';
-- wait before read
wait for 4*clockPeriod;
-- read FIFO
read_int <= '1';
readIndex := 0;
while empty = '0' loop
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
readIndex := readIndex + 1;
wait until rising_edge(clock_int);
end loop;
read_int <= '0';
--..........................................................................
-- write / read direct
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", full FIFO write with asynchronous direct read" &
lf & lf
);
-- write FIFO
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
write <= '1', '0' after 8*clockPeriod;
dataIn_int <= dataOffset + 16#00#,
dataOffset + 16#01# after 1*clockPeriod,
dataOffset + 16#02# after 2*clockPeriod,
dataOffset + 16#03# after 3*clockPeriod,
dataOffset + 16#04# after 4*clockPeriod,
dataOffset + 16#05# after 5*clockPeriod,
dataOffset + 16#06# after 6*clockPeriod,
dataOffset + 16#07# after 7*clockPeriod;
-- read FIFO
wait until empty = '0';
read_int <= '1';
readIndex := -1;
while empty = '0' loop
if readIndex >= 0 then
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
end if;
readIndex := readIndex + 1;
wait until rising_edge(clock_int);
end loop;
read_int <= '0';
--..........................................................................
-- write / read direct with clock period delay
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", full FIFO write with synchronous direct read" &
lf & lf
);
-- write FIFO
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
write <= '1', '0' after 8*clockPeriod;
dataIn_int <= dataOffset + 16#00#,
dataOffset + 16#01# after 1*clockPeriod,
dataOffset + 16#02# after 2*clockPeriod,
dataOffset + 16#03# after 3*clockPeriod,
dataOffset + 16#04# after 4*clockPeriod,
dataOffset + 16#05# after 5*clockPeriod,
dataOffset + 16#06# after 6*clockPeriod,
dataOffset + 16#07# after 7*clockPeriod;
-- read FIFO
wait until empty = '0';
wait until rising_edge(clock_int);
read_int <= '1';
readIndex := 0;
while empty = '0' loop
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
readIndex := readIndex + 1;
wait until rising_edge(clock_int);
end loop;
read_int <= '0';
--..........................................................................
-- slow read sets FIFO full
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", slow reading sets FIFO full and requires waiting before writing on" &
lf & lf
);
-- prepare slow FIFO reading
wait until rising_edge(clock_int);
wait for 2*clockPeriod;
read_int <= '1' after 4*clockPeriod,
'0' after 5*clockPeriod,
'1' after 14*clockPeriod,
'0' after 15*clockPeriod,
'1' after 24*clockPeriod,
'0' after 25*clockPeriod,
'1' after 34*clockPeriod,
'0' after 35*clockPeriod,
'1' after 44*clockPeriod,
'0' after (45+2*fifoDepth-5)*clockPeriod;
-- write 2*FIFO depth
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
for index in 0 to 2*fifoDepth-1 loop
dataIn_int <= dataOffset + index;
if full = '1' then
wait until full = '0';
wait for clockPeriod/8;
end if;
write <= '1';
wait until rising_edge(clock_int);
write <= '0';
end loop;
--..........................................................................
-- write over full
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", attempt to write after FIFO full" &
lf & lf
);
-- write FIFO
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
write <= '1';
for index in 0 to fifoDepth+3 loop
dataIn_int <= dataOffset + index;
wait for clockPeriod;
end loop;
write <= '0';
--..........................................................................
-- read FIFO once too much
print(
"At time " & sprintf("%9.3tu", now) &
", attempt to read after FIFO empty" &
lf & lf
);
read_int <= '1';
wait for clockPeriod;
wait until empty = '1';
wait for clockPeriod;
read_int <= '0';
-- read when empty
wait until rising_edge(clock_int);
wait for 2*clockPeriod;
read_int <= '1';
wait for 2*clockPeriod;
read_int <= '0';
--..........................................................................
-- read constantly
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", reading FIFO constantly (data valid when empty = '0')" &
lf & lf
);
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
read_int <= '1';
wait for 2*clockPeriod;
wait until rising_edge(clock_int);
readIndex := -1;
write <= '1';
for index in 0 to fifoDepth-1 loop
if empty = '0' then
readIndex := readIndex + 1;
end if;
if (readIndex >= 0) and (empty = '0') then
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
end if;
dataIn_int <= dataOffset + index;
wait until rising_edge(clock_int);
end loop;
write <= '0';
wait until empty = '1';
wait for 2*clockPeriod;
read_int <= '0';
--..........................................................................
-- full write / read with breaks
wait for testInterval;
print(
"At time " & sprintf("%9.3tu", now) &
", reading FIFO with breaks" &
lf & lf
);
-- write FIFO
dataOffset <= dataOffset + 16#10#;
wait until rising_edge(clock_int);
write <= '1';
for index in 0 to fifoDepth-1 loop
dataIn_int <= dataOffset + index;
wait for clockPeriod;
end loop;
write <= '0';
-- wait before read
wait for 2*clockPeriod;
-- read FIFO
wait until rising_edge(clock_int);
readIndex := 0;
for index in 0 to fifoDepth/4-1 loop
read_int <= '1';
for rdIndex in 1 to 2 loop
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
readIndex := readIndex + 1;
wait until rising_edge(clock_int);
end loop;
read_int <= '0';
wait for 2*clockPeriod;
end loop;
read_int <= '1';
while empty = '0' loop
assert unsigned(dataOut) = dataOffset + readIndex
report "FIFO readback error"
severity error;
readIndex := readIndex + 1;
wait until rising_edge(clock_int);
end loop;
read_int <= '0';
--..........................................................................
-- end of tests
wait for testInterval;
assert false
report "END SIMULATION"
severity failure;
wait;
end process;
dataIn <= std_ulogic_vector(to_signed(dataIn_int, dataIn'length));
read <= read_int;
dataValid <= '1' when (read_int = '1') and (empty = '0')
else '0';
dataRead <= to_integer(signed(dataOut)) when dataValid = '1'
else 0;
END ARCHITECTURE test;

View File

@ -0,0 +1,88 @@
LIBRARY BoardTester_test;
USE BoardTester_test.testUtils.all;
ARCHITECTURE test OF flashController_tester IS
constant clockFrequency: real := 66.0E6;
constant clockPeriod: time := (1.0/clockFrequency) * 1 sec;
signal clock_int: std_uLogic := '1';
signal flashAddr_int: natural := 0;
signal flashDataOut_int: natural := 0;
signal refreshEn: std_uLogic := '0';
constant separator : string(1 to 80) := (others => '-');
constant indent : string(1 to 2) := (others => ' ');
BEGIN
------------------------------------------------------------------------------
-- reset and clock
reset <= '1', '0' after 2*clockPeriod;
clock_int <= not clock_int after clockPeriod/2;
clock <= transport clock_int after clockPeriod*9/10;
------------------------------------------------------------------------------
-- flash access
process
begin
flashRd <= '0';
flashWr <= '0';
flashEn <= '1';
wait for 1 us;
print(cr & separator);
-- erase block 0
print(sprintf("%tu", now) & ": Erasing block 0");
flashAddr_int <= 16#10000#;
flashDataOut_int <= 16#0020#;
flashWr <= '1', '0' after clockPeriod;
wait until falling_edge(flashDataValid);
wait for clockPeriod/10;
flashDataOut_int <= 16#00D0#;
flashWr <= '1', '0' after clockPeriod;
wait for 2 us;
-- program word
print(sprintf("%tu", now) & ": Writing data into Flash");
flashAddr_int <= 16#0000#;
flashDataOut_int <= 16#0040#;
flashWr <= '1', '0' after clockPeriod;
wait until falling_edge(flashDataValid);
wait for clockPeriod/10;
flashAddr_int <= 16#0010#;
flashDataOut_int <= 16#CAFE#;
flashWr <= '1', '0' after clockPeriod;
wait for 2 us;
-- read word
print(sprintf("%tu", now) & ": Reading data from Flash");
flashAddr_int <= 16#0000#;
flashRd <= '1', '0' after clockPeriod;
wait for 1 us;
-- read word
print(sprintf("%tu", now) & ": Reading data from Flash");
flashAddr_int <= 16#000F#;
flashRd <= '1', '0' after clockPeriod;
wait for 500 ns;
flashAddr_int <= 16#0010#;
flashRd <= '1', '0' after clockPeriod;
wait for 500 ns;
flashAddr_int <= 16#0011#;
flashRd <= '1', '0' after clockPeriod;
wait for 500 ns;
wait;
end process;
------------------------------------------------------------------------------
-- address and data
flashAddr <= to_unsigned(flashAddr_int, flashAddr'length);
flashDataOut <= std_ulogic_vector(to_unsigned(flashDataOut_int, flashDataOut'length));
------------------------------------------------------------------------------
-- memory bus hold
refreshEn <= '1' after 15*clockPeriod when refreshEn = '0'
else '0' after clockPeriod;
memBusEn_n <= refreshEn;
END ARCHITECTURE test;

View File

@ -0,0 +1,102 @@
LIBRARY BoardTester_test;
USE BoardTester_test.testUtils.all;
ARCHITECTURE test OF flash_tester IS
constant T_W2: time := 0 ns;
constant T_W3: time := 70 ns;
constant T_W4: time := 50 ns;
constant T_W5: time := 55 ns;
constant T_W6: time := 10 ns;
constant T_R3: time := 120 ns;
signal addr: natural;
signal data: integer;
signal writeFlash: std_ulogic := '0';
signal readFlash: std_ulogic := '0';
constant separator : string(1 to 80) := (others => '-');
constant indent : string(1 to 2) := (others => ' ');
BEGIN
------------------------------------------------------------------------------
-- Test
------------------------------------------------------------------------------
process
begin
RP_n <= '1';
wait for 1 us;
print(cr & separator);
-- erase block 0
print(sprintf("%tu", now) & ": Erasing block 0");
addr <= 16#10000#;
data <= 16#20#;
writeFlash <= '1', '0' after 1 ns;
wait for 100 ns;
data <= 16#D0#;
writeFlash <= '1', '0' after 1 ns;
wait for 2 us;
-- program word
print(sprintf("%tu", now) & ": Writing data into Flash");
addr <= 16#0000#;
data <= 16#0040#;
writeFlash <= '1', '0' after 1 ns;
wait for 100 ns;
addr <= 16#0010#;
data <= 16#CAFE#;
writeFlash <= '1', '0' after 1 ns;
wait for 2 us;
-- read word
print(sprintf("%tu", now) & ": Reading data from Flash");
addr <= 16#0000#;
readFlash <= '1', '0' after 1 ns;
wait for 500 ns;
-- read word
print(sprintf("%tu", now) & ": Reading data from Flash");
addr <= 16#0010#;
readFlash <= '1', '0' after 1 ns;
wait for 500 ns;
wait;
end process;
------------------------------------------------------------------------------
-- Board connections
------------------------------------------------------------------------------
CE(2 downto 1) <= (others => '0');
BYTE_n <= '1';
------------------------------------------------------------------------------
-- Write access
------------------------------------------------------------------------------
process
begin
CE(0) <= '1';
WE_N <= '1';
OE_N <= '1';
DQ <= (others => 'Z');
wait on writeFlash, readFlash;
if rising_edge(writeFlash) then
A <= to_unsigned(addr, A'length) after T_W3 - T_W5;
DQ <= std_logic_vector(to_unsigned(data, DQ'length)) after T_W3 - T_W4;
CE(0) <= '0';
wait for T_W2;
WE_N <= '0';
wait for T_W3;
WE_N <= '1';
wait for T_W6;
-- CE(0) <= '1';
elsif rising_edge(readFlash) then
OE_N <= '0';
A <= to_unsigned(addr, A'length);
CE(0) <= '0';
wait for T_R3 + 10 ns;
-- CE(0) <= '1';
end if;
end process;
END ARCHITECTURE test;

View File

@ -0,0 +1,18 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE std.textio.all;
PACKAGE mti_pkg IS
FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC;
FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER;
FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER;
FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER;
FUNCTION TO_INTEGER (input : STD_ULOGIC_VECTOR) RETURN INTEGER;
PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR);
function conv_std_logic_vector(i : integer; w : integer) return std_logic_vector;
procedure hexread(L : inout line; value:out bit_vector);
procedure hexread(L : inout line; value:out std_logic_vector);
END mti_pkg;

View File

@ -0,0 +1,234 @@
LIBRARY ieee;
USE ieee.numeric_std.all;
PACKAGE BODY mti_pkg IS
-- Convert BIT to STD_LOGIC
FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC IS
BEGIN
CASE s IS
WHEN '0' => RETURN ('0');
WHEN '1' => RETURN ('1');
WHEN OTHERS => RETURN ('0');
END CASE;
END;
-- Convert STD_LOGIC to INTEGER
FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS
VARIABLE result : INTEGER := 0;
VARIABLE weight : INTEGER := 1;
BEGIN
IF input = '1' THEN
result := weight;
ELSE
result := 0; -- if unknowns, default to logic 0
END IF;
RETURN result;
END TO_INTEGER;
-- Convert BIT_VECTOR to INTEGER
FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS
VARIABLE result : INTEGER := 0;
VARIABLE weight : INTEGER := 1;
BEGIN
FOR i IN input'LOW TO input'HIGH LOOP
IF input(i) = '1' THEN
result := result + weight;
ELSE
result := result + 0; -- if unknowns, default to logic 0
END IF;
weight := weight * 2;
END LOOP;
RETURN result;
END TO_INTEGER;
-- Convert STD_LOGIC_VECTOR to INTEGER
FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS
VARIABLE result : INTEGER := 0;
VARIABLE weight : INTEGER := 1;
BEGIN
FOR i IN input'LOW TO input'HIGH LOOP
IF input(i) = '1' THEN
result := result + weight;
ELSE
result := result + 0; -- if unknowns, default to logic 0
END IF;
weight := weight * 2;
END LOOP;
RETURN result;
END TO_INTEGER;
-- Convert STD_ULOGIC_VECTOR to INTEGER
FUNCTION TO_INTEGER (input : STD_ULOGIC_VECTOR) RETURN INTEGER IS
VARIABLE result : INTEGER := 0;
VARIABLE weight : INTEGER := 1;
BEGIN
FOR i IN input'LOW TO input'HIGH LOOP
IF input(i) = '1' THEN
result := result + weight;
ELSE
result := result + 0; -- if unknowns, default to logic 0
END IF;
weight := weight * 2;
END LOOP;
RETURN result;
END TO_INTEGER;
-- Conver INTEGER to BIT_VECTOR
PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS
VARIABLE work,offset,outputlen,j : INTEGER := 0;
BEGIN
--length of vector
IF output'LENGTH > 32 THEN --'
outputlen := 32;
offset := output'LENGTH - 32; --'
IF input >= 0 THEN
FOR i IN offset-1 DOWNTO 0 LOOP
output(output'HIGH - i) := '0'; --'
END LOOP;
ELSE
FOR i IN offset-1 DOWNTO 0 LOOP
output(output'HIGH - i) := '1'; --'
END LOOP;
END IF;
ELSE
outputlen := output'LENGTH; --'
END IF;
--positive value
IF (input >= 0) THEN
work := input;
j := outputlen - 1;
FOR i IN 1 to 32 LOOP
IF j >= 0 then
IF (work MOD 2) = 0 THEN
output(output'HIGH-j-offset) := '0'; --'
ELSE
output(output'HIGH-j-offset) := '1'; --'
END IF;
END IF;
work := work / 2;
j := j - 1;
END LOOP;
IF outputlen = 32 THEN
output(output'HIGH) := '0'; --'
END IF;
--negative value
ELSE
work := (-input) - 1;
j := outputlen - 1;
FOR i IN 1 TO 32 LOOP
IF j>= 0 THEN
IF (work MOD 2) = 0 THEN
output(output'HIGH-j-offset) := '1'; --'
ELSE
output(output'HIGH-j-offset) := '0'; --'
END IF;
END IF;
work := work / 2;
j := j - 1;
END LOOP;
IF outputlen = 32 THEN
output(output'HIGH) := '1'; --'
END IF;
END IF;
END TO_BITVECTOR;
function conv_std_logic_vector(i : integer; w : integer) return std_logic_vector is
variable tmp : std_logic_vector(w-1 downto 0);
begin
tmp := std_logic_vector(to_unsigned(i, w));
return(tmp);
end;
procedure char2hex(C: character; result: out bit_vector(3 downto 0);
good: out boolean; report_error: in boolean) is
begin
good := true;
case C is
when '0' => result := x"0";
when '1' => result := x"1";
when '2' => result := X"2";
when '3' => result := X"3";
when '4' => result := X"4";
when '5' => result := X"5";
when '6' => result := X"6";
when '7' => result := X"7";
when '8' => result := X"8";
when '9' => result := X"9";
when 'A' => result := X"A";
when 'B' => result := X"B";
when 'C' => result := X"C";
when 'D' => result := X"D";
when 'E' => result := X"E";
when 'F' => result := X"F";
when 'a' => result := X"A";
when 'b' => result := X"B";
when 'c' => result := X"C";
when 'd' => result := X"D";
when 'e' => result := X"E";
when 'f' => result := X"F";
when others =>
if report_error then
assert false report
"hexread error: read a '" & C & "', expected a hex character (0-F).";
end if;
good := false;
end case;
end;
procedure hexread(L:inout line; value:out bit_vector) is
variable OK: boolean;
variable C: character;
constant NE: integer := value'length/4; --'
variable BV: bit_vector(0 to value'length-1); --'
variable S: string(1 to NE-1);
begin
if value'length mod 4 /= 0 then --'
assert false report
"hexread Error: Trying to read vector " &
"with an odd (non multiple of 4) length";
return;
end if;
loop -- skip white space
read(L,C);
exit when ((C /= ' ') and (C /= CR) and (C /= HT));
end loop;
char2hex(C, BV(0 to 3), OK, false);
if not OK then
return;
end if;
read(L, S, OK);
-- if not OK then
-- assert false report "hexread Error: Failed to read the STRING";
-- return;
-- end if;
for I in 1 to NE-1 loop
char2hex(S(I), BV(4*I to 4*I+3), OK, false);
if not OK then
return;
end if;
end loop;
value := BV;
end hexread;
procedure hexread(L:inout line; value:out std_ulogic_vector) is
variable tmp: bit_vector(value'length-1 downto 0); --'
begin
hexread(L, tmp);
value := TO_X01(tmp);
end hexread;
procedure hexread(L:inout line; value:out std_logic_vector) is
variable tmp: std_ulogic_vector(value'length-1 downto 0); --'
begin
hexread(L, tmp);
value := std_logic_vector(tmp);
end hexread;
END mti_pkg;

View File

@ -0,0 +1,82 @@
ARCHITECTURE test OF sdramController_tester IS
constant clockFrequency: real := 66.0E6;
constant clockPeriod: time := (1.0/clockFrequency) * 1 sec;
signal clock_int: std_uLogic := '1';
signal ramAddr_int: natural := 0;
signal ramDataOut_int: natural := 0;
BEGIN
------------------------------------------------------------------------------
-- reset and clock
reset <= '1', '0' after 2*clockPeriod;
clock_int <= not clock_int after clockPeriod/2;
clock <= transport clock_int after clockPeriod*9/10;
------------------------------------------------------------------------------
-- test sequence
process
begin
ramRd <= '0';
ramWr <= '0';
ramEn <= '1';
-- wait for SDRAM ready
wait for 154.3 us - now;
-- write AAAA at address 000010
ramAddr_int <= 16#000010#;
ramDataOut_int <= 16#AAAA#;
ramWr <= '1', '0' after clockPeriod;
-- wait for SDRAM ready
wait for 164.5 us - now;
-- write AAAA at address 000011
ramAddr_int <= 16#000011#;
ramDataOut_int <= 16#BBBD#;
ramWr <= '1', '0' after clockPeriod;
-- wait for SDRAM ready
wait for 196.1 us - now;
-- read back from address 000010
ramAddr_int <= 16#000010#;
ramRd <= '1', '0' after clockPeriod;
-- -- wait for SDRAM ready
-- wait for 130 us;
-- -- write AAAA at address 000010
-- ramAddr_int <= 16#000010#;
-- ramDataOut_int <= 16#AAAA#;
-- ramWr <= '1', '0' after clockPeriod;
-- -- read back from same address
-- wait for 10*clockPeriod;
-- ramRd <= '1', '0' after clockPeriod;
-- -- wait for a refresh
-- wait for 140.3 us - now;
-- -- write 5555 at address 600010
-- ramAddr_int <= 16#600020#;
-- ramDataOut_int <= 16#5555#;
-- ramWr <= '1', '0' after clockPeriod;
-- -- read back from same address
-- wait for 1*clockPeriod;
-- ramRd <= '1', '0' after clockPeriod;
-- -- read back from address 600010
-- addr_from_up_int <= 16#600010#;
-- mem_read <= '1', '0' after clockPeriod;
-- wait for 10*clockPeriod;
-- -- wait for 3 refresh periods
-- wait until falling_edge(dram_busy);
-- wait until falling_edge(dram_busy);
-- wait until falling_edge(dram_busy);
-- -- read back from address 000010
-- addr_from_up_int <= 16#000010#;
-- mem_read <= '1', '0' after clockPeriod;
-- wait for 10*clockPeriod;
-- end of tests
wait;
end process;
------------------------------------------------------------------------------
-- address and data
ramAddr <= to_unsigned(ramAddr_int, ramAddr'length);
ramDataOut <= std_ulogic_vector(to_unsigned(ramDataOut_int, ramDataOut'length));
END ARCHITECTURE test;

File diff suppressed because it is too large Load Diff