Статическая память с произвольным доступом (SRAM, static random access memory) — полупроводниковая оперативная память, в которой каждый двоичный или троичный разряд хранится в схеме с положительной обратной связью, позволяющей поддерживать состояние без регенерации, необходимой в динамической памяти (DRAM). Тем не менее сохранять данные без перезаписи SRAM может, только пока есть питание, то есть SRAM остается энергозависимым типом памяти. Не для кого не является секретом, что память подвержена повреждениям, например от воздействия статического электричества. По просьбе одного из наших клиентов, мы реализовали простой тест статического памяти, установленной на наших платах.
Для генерации текстовой информации возьмем проект VGA-Text-Generator.
Использовать этот генератор достаточно просто. Достаточно создать экземпляр модуля вывода текстовой строки, и передать в него такие параметры, как:
- длинну текста (textLength)
- пиксельную частоту VGA (clock)
- displayText (отображаемая строка)
- position (позиция строки на экране)
- horzCoord, vertCoord (текущая позиция развертки)
- pixel (результат в виде пикселя, который принимает значение горит/не горит)
VHDL Code:
textElement1: entity work.Pixel_On_Text generic map ( textLength => 27 ) port map( clock => pixel_tick, displayText => displayText, -- text string position => (50, 50), -- text position (top left) horzCoord => pixel_x, vertCoord => pixel_y, pixel => font_bit -- result );
Параметры VGA сигнала берутся из модуля развертки:
VHDL Code:
-- VGA signals vga_sync_unit: entity work.vga_sync port map( clock => ext_clk, reset => reset, hsync => hsync, vsync => vsync, video_on => video_on, pixel_tick => pixel_tick, pixel_x => pixel_x, pixel_y => pixel_y );
Теперь необходимо создать собственно сам тест памяти. Текущие тестируемый адрес и данные, мы будем показывать в HEX формате. Поэтому нам необходима функция, которая преобразует 4 бита из двоичной системы в шестнадцатиричную:
VHDL Code:
function hex_to_str(int : unsigned(3 downto 0)) return string is variable a : natural := 0; variable r : string(1 to 1); begin a := abs (to_integer(unsigned(int))); case a is when 0 => r := "0"; when 1 => r := "1"; when 2 => r := "2"; when 3 => r := "3"; when 4 => r := "4"; when 5 => r := "5"; when 6 => r := "6"; when 7 => r := "7"; when 8 => r := "8"; when 9 => r := "9"; when 10 => r := "A"; when 11 => r := "B"; when 12 => r := "C"; when 13 => r := "D"; when 14 => r := "E"; when 15 => r := "F"; when others => r := "?"; end case; --if (int < 0) then -- r := '-' & r(1 to 1); --end if; return r; end hex_to_str;
Осталось написать сам тест памяти:
VHDL Code:
architecture Behavioral of memory_test is type state_type is (idle, w1, w2, r1, r2); signal state_reg, state_next: state_type; signal sram_d_reg: std_logic_vector(7 downto 0); signal sram_a_reg: std_logic_vector(18 downto 0); signal sram_cs_reg, sram_oe_reg, sram_we_reg, r_w_reg: std_logic; signal address: integer := 0; signal data: integer :=0; signal tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7: unsigned(3 downto 0); begin -- address to string tmp1 <= to_unsigned(address / 65536,4); tmp2 <= to_unsigned(address / 4096,4); tmp3 <= to_unsigned(address / 256,4); tmp4 <= to_unsigned(address / 16,4); tmp5 <= to_unsigned(address,4); -- data to string tmp6 <= to_unsigned(data / 16,4); tmp7 <= to_unsigned(data,4); displayText <= "Testing at " & hex_to_str(tmp1) & hex_to_str(tmp2) & hex_to_str(tmp3) & hex_to_str(tmp4) & hex_to_str(tmp5) & " data is " & hex_to_str(tmp6) & hex_to_str(tmp7); -- memory test process process(clock, reset) begin if reset = '0' then address <= 0; state_reg <= idle; sram_a_reg <= (others => '0'); sram_d_reg <= (others => '0'); sram_cs_reg <= '1'; sram_oe_reg <= '0'; sram_we_reg <= '0'; elsif clock'event and clock = '1' then case state_reg is when idle => sram_cs_reg <= '0'; state_reg <= w1; when w1 => r_w_reg <= '0'; sram_oe_reg <= '1'; sram_a_reg <= std_logic_vector(to_unsigned(address, 19)); sram_d_reg <= std_logic_vector(to_unsigned(data, 8)); sram_we_reg <= '0'; state_reg <= w2; when w2 => sram_we_reg <= '0'; state_reg <= r1; when r1 => r_w_reg <= '1'; sram_we_reg <= '1'; sram_a_reg <= std_logic_vector(to_unsigned(address, 19)); state_reg <= r2; when r2 => if sram_d = std_logic_vector(to_unsigned(data, 8)) then if address = 524287 then --end of memory address <= 0; data <= data + 1; else address <= address + 1; end if; state_reg <= w1; end if; end case; end if; end process; sram_cs <= sram_cs_reg; sram_oe <= sram_oe_reg; sram_we <= sram_we_reg; sram_a <= sram_a_reg; sram_d <= sram_d_reg when r_w_reg = '0' else (others => 'Z'); end Behavioral;
Работает он достаточно просто. В первые два состояния (w1, w2) происходит запись тестовых данных по текущему адресу. Во вторые два состояния (r1, r2) происходит чтение данных. Если записанные и считанные данные не совпадают, процесс прерывается.
Для имитации ошибки нам пришлось оторвать один из разрядов шины данных. Ниже можно увидеть результат работы, и скачать исходные файлы:
Проект тест памяти для платы VE-XC6SLX9: memory_tst_XC6SLX9.zip
Проект тест памяти для платы VE-EP4CE10: memory_tst_EP4CE10.zip
Проект тест памяти для платы VE-LCMXO27000HC: memory_tst_LCMXO27000HC.zip