Первый проект для VE-EP4CE10E. Часть 3.

Теперь, когда наш контроллер умеет управлять выводом по командам, поступающим по USB. Мы можем создать проект где микроконтроллер и плис будут взаимодействовать. В качестве взаимодействия, выберем простое действие: при поступлении на вход FPGA логической единицы, на экране монитора будет появляться логотип нашей компании, а при появлении логического нуля соответственно пропадать. Сам процесс создания проекта для плис я опущу, он подробно описан в нашей статье Первый проект для VE-EP4CE10E. Часть 2.. Расскажу только об используемых модулях. Схема проекта представлена ниже:

 

Отдельно стоит обратить внимание на новый модуль ROM: 1-PORT. Создать его можно, вызвав IP Catalog->Installed IP->Library->Basic Functions->On Chip Memory->ROM: 1-PORT

На этой вкладке настраиваем тип памяти: 8 bits 32768 words. Остальное оставляем без изменений.

В этом месте можно настроить защелку на выходе шины данных, вход асинхронного сброса, сигнал разрешения чтения. Нам этого не надо.

На этом этапе нужно выбрать файл который будет содержаться в нашей памяти. В качестве исходного файла берем любой BMP файл размером меньше 32768 байт. В Quartus можно загрузить файлы типа hex. Поэтому конвертируем файл BMP в HEX. Для этого автор использовал утилиту J-Flash из стандартного набора отладчика SEGGER J-Link. Для того чтобы J-Link смог открыть нашу картинку, меняем расширение с BMP на BIN. Стартовый адрес указываем 0.

Нажимаем Next.

Выбираем пункт Quartus II symbol file. Это приведет к созданию символа для вставки в нашу схему. Теперь приступим к созданию кода:

  1. module hvsync_ex(
  2. // inputs:
  3. input wire char_clock,
  4.  
  5. input wire [3:0]red_in,
  6. input wire [3:0]green_in,
  7. input wire [3:0]blue_in,
  8.  
  9. // outputs:
  10. output reg [11:0]char_count_, //post reg
  11. output reg [11:0]line_count_, //post reg
  12.  
  13. output wire [3:0]red,
  14. output wire [3:0]green,
  15. output wire [3:0]blue,
  16.  
  17. output reg hsync,
  18. output reg vsync,
  19. output reg blank
  20. );
  21.  
  22. //VGA Standart
  23. `define h_visible_area 1024
  24. `define h_front_porch 24
  25. `define h_sync_pulse 136
  26. `define h_back_porch 160
  27.  
  28. `define v_visible_area 768
  29. `define v_front_porch 3
  30. `define v_sync_pulse 6
  31. `define v_back_porch 29
  32.  
  33. //variables
  34. reg [11:0]char_count;
  35. reg [1:0]pixel_state;
  36. reg [11:0]line_count;
  37. reg [1:0]line_state;
  38.  
  39. reg end_of_line;
  40. reg end_of_frame;
  41.  
  42. //permanent comb computations:
  43. always @*
  44. begin
  45. //horizontal processing
  46. if(char_count < `h_visible_area)
  47. pixel_state = 0; //active video
  48. else
  49. if(char_count < `h_visible_area + `h_front_porch)
  50. pixel_state = 1; //front porch
  51. else
  52. if(char_count < `h_visible_area + `h_front_porch + `h_sync_pulse)
  53. pixel_state = 2; //hsync impuls
  54. else
  55. pixel_state = 3; //back porch
  56.  
  57. if(char_count < `h_visible_area + `h_front_porch + `h_sync_pulse + `h_back_porch)
  58. end_of_line = 0;
  59. else
  60. end_of_line = 1;
  61.  
  62. //vert processing
  63. if(line_count < `v_visible_area)
  64. line_state = 0; //active video lines
  65. else
  66. if(line_count < `v_visible_area + `v_front_porch)
  67. line_state = 1; //front porch
  68. else
  69. if(line_count < `v_visible_area + `v_front_porch + `v_sync_pulse)
  70. line_state = 2; //vsync impuls
  71. else
  72. line_state = 3; //front porch
  73.  
  74. if(line_count < `v_visible_area + `v_front_porch + `v_sync_pulse + `v_back_porch)
  75. end_of_frame = 0;
  76. else
  77. end_of_frame = 1;
  78. end
  79.  
  80. //synchronous process
  81. always @(posedge char_clock)
  82. begin
  83. hsync <= (pixel_state!=2'b10);
  84. vsync <= (line_state!=2'b10);
  85. blank <= (pixel_state==2'b0 && line_state==2'b0);
  86.  
  87. //char_count_ <= char_count;
  88. line_count_ <= line_count;
  89.  
  90. if(end_of_line)
  91. begin
  92. char_count <= 0;
  93. char_count_ <= 0;
  94.  
  95. if(end_of_frame)
  96. line_count <= 0;
  97. else
  98. line_count <= line_count + 1'b1;
  99. end
  100. else
  101. begin
  102. char_count <= char_count + 1'b1;
  103. if (pixel_state==2'b0)
  104. char_count_ <= char_count_ + 1'b1;
  105. end
  106. end
  107.  
  108. assign red = red_in;
  109. assign green = green_in;
  110. assign blue = blue_in;
  111.  
  112. endmodule

Модуль hvsync_ex генерирует VGA развертку и положение точки на экране (char_count_, line_count_). Следующий код:

 

  1. module picture_gen(
  2.  
  3. //vga
  4. input [11:0]char_count,
  5. input [11:0]line_count,
  6. input wire mcu_data0,
  7. input wire blank,
  8. input wire char_clock,
  9.  
  10. output reg [3:0]red_out,
  11. output reg [3:0]green_out,
  12. output reg [3:0]blue_out,
  13.  
  14. //sram memory
  15. inout [7:0]data, // SRAM Data Bus
  16. output reg [18:0]adress, // SRAM Address
  17. output reg cs, // SRAM Chip Select
  18. output reg we, // SRAM Write Enable
  19. output reg oe, // SRAM Output Enable
  20.  
  21. //built-in memory
  22. input [7:0]bmp_data,
  23. output reg[14:0]bmp_adress
  24.  
  25. );
  26.  
  27. reg r_w=0;
  28. reg [7:0]out_data;
  29. reg [7:0]palit_adr;
  30. reg [3:0]r_state = state0;
  31. reg [11:0]x_cnt=0;
  32. reg [11:0]y_cnt=0;
  33. reg [7:0]R;
  34. reg [7:0]G;
  35. reg [7:0]B;
  36. reg [9:0]delay;
  37.  
  38. localparam
  39. state0 = 4'b0001,
  40. state1 = 4'b0010,
  41. state2 = 4'b0011,
  42. state3 = 4'b0100,
  43. state4 = 4'b0101,
  44. state5 = 4'b0110,
  45. state6 = 4'b0111,
  46. state7 = 4'b1000,
  47. state8 = 4'b1001,
  48. state9 = 4'b1010;<br />
  49. assign data = r_w ? 8'bzzzzzzzz : out_data; //tristate sram data bus
  50.  
  51. //sram in/out
  52. always @(posedge char_clock)
  53. begin
  54. if (blank)
  55. begin
  56. if(r_w==1) //read sram to VGA
  57. begin
  58. if(r_state == state0)
  59. begin
  60. cs <=1'b0;
  61. we <=1'b1;
  62. adress <= ((line_count>>1)*512 | char_count>>1);
  63. oe <=1'b0;
  64. r_state <= state1;
  65. end
  66. else if(r_state == state1)
  67. begin
  68. if(mcu_data0==0)
  69. begin
  70. red_out <= (data >> 4) & 8'b00001110;
  71. green_out <= (data >> 1) & 8'b00001100;
  72. blue_out <= (data<<1) & 8'b00001110;
  73. end
  74. else
  75. begin
  76. red_out <= 0;
  77. green_out <= 0;
  78. blue_out <= 0;
  79. end
  80. oe <=1'b1;
  81. r_state <= state0;
  82. end
  83. end
  84. else //write sram
  85. begin
  86. delay <= delay+1;
  87. if(delay>1)
  88. begin
  89. delay <= 0;
  90. if(r_state == state0)
  91. begin
  92. cs <= 1'b0;
  93. oe <= 1'b1;
  94. we <= 1'b1;
  95. adress <= (y_cnt*512 + x_cnt);
  96. if(x_cnt <= 246 && y_cnt <= 89)
  97. begin
  98. bmp_adress<=(y_cnt*248+x_cnt+1078);
  99. end
  100. r_state <= state1;
  101. end
  102.  
  103. else if(r_state == state1)
  104. begin
  105. if(x_cnt <= 246 && y_cnt <= 89)
  106. begin
  107. palit_adr <= bmp_data;
  108. end
  109. else
  110. begin
  111. palit_adr <= 0;
  112. end
  113. r_state <= state2;
  114. end
  115. else if(r_state == state2)
  116. begin
  117. bmp_adress <= (palit_adr*4+54);
  118. r_state <= state3;
  119. end
  120. else if(r_state == state3)
  121. begin
  122. B <= bmp_data;
  123. bmp_adress <= (palit_adr*4+55);
  124. r_state <= state4;
  125. end
  126. else if(r_state == state4)
  127. begin
  128. G <= bmp_data;
  129. bmp_adress <= (palit_adr*4+56);
  130. r_state <= state5;
  131. end
  132. else if(r_state == state5)
  133. begin
  134. R <= bmp_data;
  135. r_state <= state6;
  136. end
  137.  
  138. else if(r_state == state6)
  139. begin
  140. out_data <= (R & 8'b11100000) | (G>>3 & 8'b00011000) | (B>>5 & 8'b00000111);
  141. x_cnt <= x_cnt+1;
  142. r_state <= state7;
  143. end
  144.  
  145. else if(r_state == state7)
  146. begin
  147. we <=1'b0;
  148. if(x_cnt >= 512)
  149. begin
  150. x_cnt <= 0;
  151. y_cnt <= y_cnt+1;
  152. end
  153. if(y_cnt >= 384)
  154. begin
  155. y_cnt <= 0;
  156. end
  157. if((y_cnt*512 + x_cnt)==196608)
  158. begin
  159. ino<=1;
  160. end
  161. r_state <= state0;
  162. end
  163. end
  164. end
  165. end
  166. else
  167. begin
  168. red_out <= 0;
  169. green_out <= 0;
  170. blue_out <= 0;
  171. end
  172. end
  173.  
  174. endmodule

Сначала копирует наш BMP файл из встроенной памяти во внешнюю SRAM. Причем делает это с учетом палитры 8 битного BMP файла. Затем выводит содержимое памяти на монитор, учитывая состояние входа mcu_data0. Если на входе логический 0, то выводится содержимое внешней памяти, если логическая 1 то черный экран.

Назначение выводов:

Ну и в завершение скриншот:

Архив проекта: test_hardware.zip