Подключение периферийных модулей к MIPSfpga, на примере клавиатуры Pmod KYPD

Здравствуйте! Мы одни из победителей хакатона MIPfpga, в этой статье расскажем, как подключать модули в систему на кристалле на основе MIPSfpga на примере клавиатуры Pmod KYPD. Также ознакомим с написанием программы для управления подключенных модулей.
image

→ Описание клавиатуры найдете здесь

Pmod KYPD — 16-кнопочная клавиатура с цифрами в шестнадцатеричном формате (0-F). Опрос происходит способом поочередной подачи логического 0 на каждый столбец и считывания состояния строк. Если в момент опроса столбца одна из кнопок в нем нажата, соответствующая строка выдаст логическую 1.

Для начала необходимы исходники MIPSfpga.

Инструкция по скачиванию

Далее нужно скачать надстройку MIPSfpga-plus, которая позволяет записывать программы по UARTу.

Описание и инструкции по установке присутствуют, если коротко, то для того, чтобы была возможность просто запустить скрипт и проект собрался, необходимо:

— поместить исходники MIPSfpga в папку

C:\MIPSfpga;

а MIPSfpga-plus по директории:
C:\github\mipsfpga-plus;

Далее в папке C:\github\mipsfpga-plus\boards выбрать свою плату, у меня это de0_cv, и выполнить скрипт make_project. Проект, который нужно запускать, будет находиться в C:\github\mipsfpga-plus\boards\de0_cv\project.

Если для вашей платы нет проекта, то можно выбрать наиболее подходящую по количеству логических ячеек и изменить назначения;

— Еще вам понадобятся компилятор, линковщик Codescape, а также USB-UART преобразователь, например, pl2303hx или ch340.

image
Подключение клавиатуры и USB-UART преобразователя к плате

Клавиатура напрямую будет подключена к шине AHB-Lite. Для интеграции клавиатуры в систему мы создали модуль decoder.v. Данный модуль работает по следующему принципу: каждую миллисекунду опрашивается один из столбцов и. если в этот момент была нажата кнопка в этом столбце. то соответствующая строка выдаст логическую 1. Каждой комбинации строка+столбец соответствует цифра от 0 до F. Данная цифра записывается в регистр и по шине передается в память процессора. С помощью программного обеспечения данные с памяти выводятся на индикатор.

Код модуля
module decoder(
input i_row1,
input i_row2,
input i_row3,
input i_row4,
input i_clk,
input i_rst_n,
output [3:0] o_col,
output [3:0] o_number);

reg [3:0] col;

reg [31:0] counter;

reg [3:0] number;

parameter ZERO = 8'b11100111; //row, col
parameter ONE = 8'b01110111;
parameter TWO = 8'b01111011;
parameter THREE = 8'b01111101;
parameter FOUR = 8'b10110111;
parameter FIVE = 8'b10111011;
parameter SIX = 8'b10111101;
parameter SEVEN = 8'b11010111;
parameter EIGHT = 8'b11011011;
parameter NINE = 8'b11011101;
parameter TEN = 8'b01111110;
parameter ELEVEN = 8'b10111110;
parameter TWELVE = 8'b11011110;
parameter THIRTEEN = 8'b11101110;
parameter FOURTEEN = 8'b11101101;
parameter FIFTEEN = 8'b11101011;

always @(posedge i_clk or negedge i_rst_n)
begin
if (i_rst_n == 1'b0)
begin
col <= 4'b1110;
end
else
begin
if (counter == 31'b111001001110000111000000)
begin
col <= {col [0], col [3:1]};
end
end
end

always @*
begin
if (i_rst_n == 0)
begin
number <= 4'b0;
end
else
begin
case ({i_row1, i_row2, i_row3, i_row4, col [0], col [1], col [2], col [3]})
ZERO:
begin
number <= 4'b0000;
end
ONE:
begin
number <= 4'b0001;
end
TWO:
begin
number <= 4'b0010;
end
THREE:
begin
number <= 4'b0011;
end
FOUR:
begin
number <= 4'b0100;
end
FIVE:
begin
number <= 4'b0101;
end
SIX:
begin
number <= 4'b0110;
end
SEVEN:
begin
number <= 4'b0111;
end
EIGHT:
begin
number <= 4'b1000;
end
NINE:
begin
number <= 4'b1001;
end
TEN:
begin
number <= 4'b1010;
end
ELEVEN:
begin
number <= 4'b1011;
end
TWELVE:
begin
number <= 4'b1100;
end
THIRTEEN:
begin
number <= 4'b1101;
end
FOURTEEN:
begin
number <= 4'b1110;
end
FIFTEEN:
begin
number <= 4'b1111;
end
default:
begin
number <= number;
end
endcase
end
end

always @(posedge i_clk or negedge i_rst_n)
begin
if (i_rst_n == 0)
begin
counter = 31'b0;
end
else
begin
if (counter == 31'b111001001110000111000011)
begin
counter = 31'b0;
end
else
begin
counter = counter + 1'b1;
end
end
end

assign o_number = number;
assign o_col = col;

endmodule

image

Подключаем к проекту файл с описанным выше модулем. В файле верхнего уровня, у нас это de0_cv.v, добавим следующие строчки:

`ifdef MFP_PMOD_KYPD
			.KYPD_DATA		  ( GPIO_0 [35:28]  ),
	      .KEY_0           ( KEY    [0]      )
		  `endif

Выделим ножки GPIO_0 [35], GPIO_0 [34] для питания клавиатуры. В файле mfp_system.v добавляем входы и выходы:

 inout [7:0] KYPD_DATA,
	 input KEY_0

В описании модуля mfp_system добавим:

`ifdef MFP_PMOD_KYPD
	 wire [3:0] KYPD_OUT;
	 `endif
	  `ifdef MFP_PMOD_KYPD
		decoder decoder
	(
		  .i_clk	     (	SI_ClkIn					),
		  .i_rst_n    (   KEY_0  					),
		  .i_row1     (   KYPD_DATA [6]			),
		  .i_row2     (	KYPD_DATA [4]			),
		  .i_row3     (	KYPD_DATA [2]			),
		  .i_row4     (	KYPD_DATA [0]			),
		  .o_col  	  (  {KYPD_DATA [7], 
							   KYPD_DATA [5], 
								KYPD_DATA [3],
								KYPD_DATA [1]}		   ),
		  .o_number   (	KYPD_OUT					)
	);
	  `endif

При создании экземпляра модуля mfp_ahb_lite_matrix_with_loader добавим в список входов наши данные:

  `ifdef MFP_PMOD_KYPD
		  .KYPD_OUT	  		  (	KYPD_OUT	  		  ),	
		  `endif

В файлах mfp_ahb_lite_matrix_with_loader.v, mfp_ahb_lite_matrix.v, mfp_ahb_gpio_slave.v добавляем вход:

input [3:0] KYPD_OUT

В файле mfp_ahb_lite_matrix_config.vh, который находится в папке C:\github\mipsfpga-plus, добавляем следующие строчки:

`define MFP_PMOD_KYPD_IONUM         4'h5
`define MFP_PMOD_KYPD_ADDR          32'h1f800014

Собственно, это и есть адреса, по которым будут доступны регистры. Последним штрихом будет написание программы, которая отображает числа на семисегментном индикаторе.

Код программы
#include «mfp_memory_mapped_registers.h»

int main ()
{
int n = 0;

for (;;)
{

MFP_7_SEGMENT_HEX = MFP_PMOD_KYPD;
MFP_GREEN_LEDS = n++;

}

return 0;
}

Генерируем motorola_s_record файл:

08_generate_motorola_s_record_file

Проверяем к какому СОМ порту подключен USB UART преобразователь:

 11_check_which_com_port_is_used

Изменяем файл 12_upload_to_the_board_using_uart:

set a=7 
mode com%a% baud=115200 parity=n data=8 stop=1 to=off xon=off odsr=off octs=off dtr=off rts=off idsr=off type program.rec >\.\COM%a%,

где а – номер СОМ порта, к которому подключен USB UART преобразователь.

И наконец, загружаем программу:

 12_upload_to_the_board_using_uart



Желаем успеха.
  • +18
  • 2,8k
  • 2
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 2
  • 0
    Почему Вы пишете счётчик до 31'b111001001110000111000011, а не просто 15000003, понятнее же?
    И если интервал опроса столбца 1 мс, а столбец вы меняете раз в 15М тактов, то какая же там тактовая частота? Или я недопонял логику работы счётчика (там ещё вконце присваивание с = вместо <=, почему так?)?
    • +2
      За статью спасибо, но очень расстраивает такое небрежное отношение к выравниванию исходников.
      Как будто автор даже не посмотрел на результат перед публикацией.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.