Визуальная электроника

Статическая память с произвольным доступом (SRAM, static random access memory) — полупроводниковая оперативная память, в которой каждый двоичный или троичный разряд хранится в схеме с положительной обратной связью, позволяющей поддерживать состояние без регенерации, необходимой в динамической памяти (DRAM). Тем не менее сохранять данные без перезаписи SRAM может, только пока есть питание, то есть SRAM остается энергозависимым типом памяти. Не для кого не является секретом, что память подвержена повреждениям, например от воздействия статического электричества.  По просьбе одного из наших клиентов, мы реализовали простой тест статического памяти, установленной на наших платах.

Для генерации текстовой информации возьмем проект VGA-Text-Generator.

Использовать этот генератор достаточно просто. Достаточно создать экземпляр модуля вывода текстовой строки, и передать в него такие параметры, как:

  • длинну текста (textLength)
  • пиксельную частоту VGA (clock)
  • displayText (отображаемая строка)
  • position (позиция строки на экране)
  • horzCoord, vertCoord (текущая позиция развертки)
  • pixel (результат в виде пикселя, который принимает значение горит/не горит)
VHDL Code:
  1. textElement1: entity work.Pixel_On_Text
  2. generic map (
  3. textLength => 27
  4. )
  5. port map(
  6. clock => pixel_tick,
  7. displayText => displayText, -- text string
  8. position => (50, 50), -- text position (top left)
  9. horzCoord => pixel_x,
  10. vertCoord => pixel_y,
  11. pixel => font_bit -- result
  12. );

Параметры VGA сигнала берутся из модуля развертки:

VHDL Code:
  1. -- VGA signals
  2. vga_sync_unit: entity work.vga_sync
  3. port map(
  4. clock => ext_clk,
  5. reset => reset,
  6. hsync => hsync,
  7. vsync => vsync,
  8. video_on => video_on,
  9. pixel_tick => pixel_tick,
  10. pixel_x => pixel_x,
  11. pixel_y => pixel_y
  12. );

Теперь необходимо создать собственно сам тест памяти. Текущие тестируемый адрес и данные, мы будем показывать в HEX формате. Поэтому нам необходима функция, которая преобразует 4 бита из двоичной системы в шестнадцатиричную:

VHDL Code:
  1. function hex_to_str(int : unsigned(3 downto 0)) return string is
  2. variable a : natural := 0;
  3. variable r : string(1 to 1);
  4.  
  5. begin
  6. a := abs (to_integer(unsigned(int)));
  7.  
  8. case a is
  9. when 0 => r := "0";
  10. when 1 => r := "1";
  11. when 2 => r := "2";
  12. when 3 => r := "3";
  13. when 4 => r := "4";
  14. when 5 => r := "5";
  15. when 6 => r := "6";
  16. when 7 => r := "7";
  17. when 8 => r := "8";
  18. when 9 => r := "9";
  19. when 10 => r := "A";
  20. when 11 => r := "B";
  21. when 12 => r := "C";
  22. when 13 => r := "D";
  23. when 14 => r := "E";
  24. when 15 => r := "F";
  25.  
  26. when others => r := "?";
  27. end case;
  28.  
  29. --if (int < 0) then
  30. -- r := '-' & r(1 to 1);
  31. --end if;
  32.  
  33. return r;
  34. end hex_to_str;

Осталось написать сам тест памяти:

VHDL Code:
  1. architecture Behavioral of memory_test is
  2.  
  3. type state_type is (idle, w1, w2, r1, r2);
  4. signal state_reg, state_next: state_type;
  5. signal sram_d_reg: std_logic_vector(7 downto 0);
  6. signal sram_a_reg: std_logic_vector(18 downto 0);
  7. signal sram_cs_reg, sram_oe_reg, sram_we_reg, r_w_reg: std_logic;
  8. signal address: integer := 0;
  9. signal data: integer :=0;
  10. signal tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7: unsigned(3 downto 0);
  11.  
  12.  
  13. begin
  14.  
  15. -- address to string
  16. tmp1 <= to_unsigned(address / 65536,4);
  17. tmp2 <= to_unsigned(address / 4096,4);
  18. tmp3 <= to_unsigned(address / 256,4);
  19. tmp4 <= to_unsigned(address / 16,4);
  20. tmp5 <= to_unsigned(address,4);
  21.  
  22. -- data to string
  23. tmp6 <= to_unsigned(data / 16,4);
  24. tmp7 <= to_unsigned(data,4);
  25.  
  26. displayText <= "Testing at "
  27. & hex_to_str(tmp1)
  28. & hex_to_str(tmp2)
  29. & hex_to_str(tmp3)
  30. & hex_to_str(tmp4)
  31. & hex_to_str(tmp5)
  32. & " data is "
  33. & hex_to_str(tmp6)
  34. & hex_to_str(tmp7);
  35.  
  36. -- memory test process
  37. process(clock, reset)
  38. begin
  39. if reset = '0' then
  40. address <= 0;
  41. state_reg <= idle;
  42. sram_a_reg <= (others => '0');
  43. sram_d_reg <= (others => '0');
  44. sram_cs_reg <= '1';
  45. sram_oe_reg <= '0';
  46. sram_we_reg <= '0';
  47. elsif clock'event and clock = '1' then
  48. case state_reg is
  49. when idle =>
  50. sram_cs_reg <= '0';
  51. state_reg <= w1;
  52. when w1 =>
  53. r_w_reg <= '0';
  54. sram_oe_reg <= '1';
  55. sram_a_reg <= std_logic_vector(to_unsigned(address, 19));
  56. sram_d_reg <= std_logic_vector(to_unsigned(data, 8));
  57. sram_we_reg <= '0';
  58. state_reg <= w2;
  59. when w2 =>
  60. sram_we_reg <= '0';
  61. state_reg <= r1;
  62. when r1 =>
  63. r_w_reg <= '1';
  64. sram_we_reg <= '1';
  65. sram_a_reg <= std_logic_vector(to_unsigned(address, 19));
  66. state_reg <= r2;
  67. when r2 =>
  68. if sram_d = std_logic_vector(to_unsigned(data, 8)) then
  69. if address = 524287 then --end of memory
  70. address <= 0;
  71. data <= data + 1;
  72. else
  73. address <= address + 1;
  74. end if;
  75. state_reg <= w1;
  76. end if;
  77. end case;
  78. end if;
  79. end process;
  80.  
  81. sram_cs <= sram_cs_reg;
  82. sram_oe <= sram_oe_reg;
  83. sram_we <= sram_we_reg;
  84. sram_a <= sram_a_reg;
  85. sram_d <= sram_d_reg when r_w_reg = '0'
  86. else (others => 'Z');
  87.  
  88. end Behavioral;

Работает он достаточно просто. В первые два состояния (w1, w2) происходит запись тестовых данных по текущему адресу. Во вторые два состояния (r1, r2) происходит чтение данных. Если записанные и считанные данные не совпадают, процесс прерывается.

Для имитации ошибки нам пришлось оторвать один из разрядов шины данных. Ниже можно увидеть результат работы, и скачать исходные файлы:

Проект тест памяти для платы VE-XC6SLX9: memory_tst_XC6SLX9.zip

Проект тест памяти для платы VE-EP4CE10: memory_tst_EP4CE10.zip

Проект тест памяти для платы VE-LCMXO27000HC: memory_tst_LCMXO27000HC.zip

Добавить комментарий