Факультет Микроприборов и технической кибернетики
Кафедра вычислительной техники
Практикум по программируемым логическим интегральным схемам
Отчет по курсовой работе
Работу выполнили
студенты группы МП-31
Денискин М.Ю.
Коробков Д.Ю.
Свинченко А.А.
Преподаватель:
Беклемишев Д.Н.
Москва 2017
Содержание
1. Постановка задачи
2. Средства разработки
3. Структура проекта
а) ps2protocol, KP, keytodigit
б) VGA
в) i2c
г) audiocodec, Mem
д) Labirint
4. Отладка устройства на учебном стенде
5. Заключение
6. Список использованной литературы
7. Приложение 1
8. Приложение 2
9. Приложение 3
10. Приложение 4
11. Приложение 5
Постановка задачи
Создание ВУ, которое выполняет следующие функции:
1. Выводит на экран монитора лабиринт с объектом на входе и позволяет пользователю
а) Задавать цвет лабиринта и объекта;
б) Перемещать объект влево, вправо, вверх и вниз при помощи клавиш клавиатуры с учётом наличия стенок в лабиринте;
в) Завершать показ лабиринта с объектом на экране монитора и начинать сначала.
2. Воспроизведение музыки через динамики: включение/выключение с помощью переключателя на учебном стенде.
Средства разработки
1. В ходе работы использовался САПР Quartus II и высокоуровневый язык описания аппаратуры Verilog HDL. При разработке ВУ применялись редакторы схем, кода Verilog HDL, средства симуляции и компиляции, встроенные в Quartus II.
2. Также использовался учебный стенд, который представляет собой плату, на которой размещены интегральная схема программируемой логики и устройства ввода/вывода (рис.1).
Рис.1. Внешний вид учебного стенда
На рис.2 приведена упрощенная структура стенда. Центральное место на плате занимает программируемая логическая интегральная схема фирмы Altera Cyclone II EP2C20F484C7N. Загрузка ОЗУ ПЛИС производится с помощью инструментального компьютера, кабеля программирования и САПР Quartus II.
Рис.2. Структура учебного стенда
Структура проекта
В состав ВУ входят следующие модули:
| |||||||
|
| ||||||
| |||||||
|
Ниже представлено описание каждого из них.
Ps2protocol, KP, keytodigit
Данные модули выполняют следующие функции:
1. Обеспечивают передачу кода нажатой клавиши с клавиатуры, работающей по интерфейсу PS/2, на ВУ, а также передачу на клавиатуру данных: байт данных задаётся с помощью переключателей 0-7 на стенде, а сам процесс передачи инициируется нажатием кнопки 1 (ps2protocol).
Рис.3. Временная диаграмма приёма кода клавиши (10001000)
2. Формируют сигнал нажатия клавиши KP («0», если ни одна из клавиш не нажата, иначе — «1») (KP).
3. Коды клавиш «0», «1», «2» - «E», «F» переводят в соответствующие шестнадцатеричные цифры и выдают сигнал, информирующий о нажатии данных клавиш (keytodigit).
HDL-описание этих модулей приведено в приложении 1.
VGA
Данный модуль обеспечивает передачу изображения на монитор по интерфейсу VGA совместно с модулем Labirint.
Рис.4. Временная диаграмма передачи строки пикселей по VGA. Передача кадра имеет тот же вид, за исключением того, что используется другая линия синхронизации — VSYNC
Режим VGA | Длины временных промежутков при передаче строки | |||||
Конфигурация | Разрешение | a (мс) | b (мс) | c (мс) | d (мс) | Частота передачи пикселей (МГц) |
VGA (60 Гц) | 640x480 | 3,8 | 1,9 | 25,4 | 0,6 | 25 (640/c) |
Таблица 1. Характеристики передачи строки пикселей
Режим VGA | Длины временных промежутков при передаче кадра | ||||
Конфигурация | Разрешение | a (линии) | b (линии) | c (линии) | d (линии) |
VGA (60 Гц) | 640x480 |
Таблица 2. Характеристики передачи кадра
Цвет пикселей задаётся с помощью 3 составляющих: R, G, B. Каждая из них определяется 4 битами (в самом интерфейсе VGA составляющие цвета являются аналоговыми сигналами, но на стенде присутствуют три 4-битных ЦАП, которые формируют эти сигналы).
Рис.5. Схема подключения VGA
HDL-описание этого модуля приведено в приложении 2.
I2c
Этот модуль обеспечивает передачу данных по интерфейсу I2C на конфигурируемый 24-битный аудиокодек Wolfson WM8731, поддерживающий частоту дискретизации от 8 кГц до 96 кГц (при воспроизведении музыки используется 8 кГц) и имеющий линейный вход, линейных выход и вход для микрофона (используется только линейный выход).
Рис.6. Временная диаграмма передачи данных на кодек по I2C
Рис.7. Схема подключения WM8731
Если при передаче данных приёмник (WM8731) не выставил «0» на шине данных I2C_SDAT при ответе, то на стенде загорается зелёный светодиод 1.
При успешной передаче по I2C загорается зелёный светодиод 0.
HDL-описание этого модуля приведено в приложении 3.
Audiocodec, Mem
Данный модуль выполняет следующие функции:
1. Хранит 53248 выборок звука, сжатых по алгоритму IMA ADPCM (находятся в модуле Mem — однопортовая ROM-память, сгенерированная средствами Quartus);
2. Декодирует эти выборки в 16-битные коды и подаёт их на ЦАП в WM8731.
3. Конфигурирует WM8731, посылая соответствующие данные по I2C.
Адрес регистра WM8731 | Данные регистра WM8731 | Что делает |
Включает WM8731, линейный выход и ЦАП | ||
Подключает к линейному выходу ЦАП | ||
Задаёт следующие параметры: 1. Режим работы аудиокодека: Master Mode; 2. Режим подачи кода на ЦАП: DSP Mode A; 3. Размер выборок: 16 бит. | ||
Задаёт следующие параметры: 1. Частота дискретизации ЦАП: 8 кГц; 2. Режим тактирования: USB Mode (12 МГц); 3. Входной тактовый сигнал делится на 2 (на вход подаётся 24 МГц). | ||
Изменяет значения на выходе ЦАП, близкие к 0 и подаваемые на левый динамик, для улучшения звука | ||
Изменяет значения на выходе ЦАП, близкие к 0 и подаваемые на правый динамик, для улучшения звука |
Таблица 3. Настройки WM8731
При успешной конфигурации кодека загорается зелёный светодиод 3.
Рис.8. Временная диаграмма подачи выборки звука на ЦАП (n=16)
При выставлении «1» на линии LRCLK загорается зелёный светодиод 2 (если включена передача звука).
Воспроизведение музыки начинается, если переключатель 8 переведён в верхнее положение («1»). Звук перестаёт воспроизводиться, если этот переключатель в нижнем положении («0»).
HDL - описание этого модуля и выборки звука (в шестнадцатеричном виде) приведены в приложении 4.
Labirint
Это главный модуль. Он выполняет следующие задачи:
1. Хранит два кадра для монитора, один из которых изображает лабиринт, а другой — финальное сообщение. Также совместно с модулем VGA подаёт видеоданные на монитор.
Рис.9. Лабиринт.
Рис.10. Финальное сообщение
2. Обеспечивает передвижение объекта по лабиринту посредством нажатия пользователем клавиш «↑», «←», «→», «↓», учитывая наличие стенок.
3. Позволяет пользователю задавать цвет лабиринта и объекта, а также повторно запускать приложение с лабиринтом.
Алгоритм использования ВУ:
1. Ввод цвета лабиринта: на клавиатуре нажать на три клавиши, соответствующие шестнадцатеричным цифрам. Первая цифра - интенсивность красного цвета, вторая - зеленого, третья - синего. Возможен пропуск задания интенсивности цвета посредством нажатия на клавишу «Space».
2. Аналогично ввод цвета объекта. Цвета объекта и лабиринта не должны совпадать и не должны быть одновременно равны нулю.
3. Нажатие на клавишу «Enter».
4. После появления изображения лабиринта на экране монитора нужно переместить объект в лабиринте посредством нажатия клавиш «↑», «←», «→», «↓» к щели в самой правой стене этого лабиринта. При достижении данного места выведется сообщение «WIN!».
5. Нажатие на клавишу 0 на учебном стенде для перезапуска.
В любой момент времени можно перевести переключатель 8 в верхнее/нижнее положение, чтобы начать/остановить воспроизведение музыки.
HDL - описание данного модуля приведено в приложении 5.
Отладка устройства на учебном стенде
Отладку производим в соответствии с алгоритмом использования ВУ, описанным в предыдущем пункте.
Рис.11. Учебный стенд при вводе цвета лабиринта.
Рис.12. Учебный стенд при воспроизведении звука.
Рис.13. Экран монитора с лабиринтом и объектом.
Рис.14. Экран монитора с финальным сообщением.
Рис.15. Учебный стенд при прекращении показа лабиринта.
Заключение
В результате выполнения работы было разработано вычислительное устройство, выполняющее заданные функции, и была произведена его отладка на учебном стенде. Получены навыки в проектировании микропроцессорных систем, а также опыт работы со средствами разработки (САПР Quartus II и языком Verilog HDL).
Список использованной литературы
Беклемишев Д.Н., Орлов А.Н., Попов М.Г., Кудров А.А., Переверзев А.Л. Моделирование микропроцессорных систем на базе программируемых логических интегральных схем с использованием Verilog HDL и САПР Quartus II: учеб. пособие по курсу «Микропроцессорные средства и системы» / Под ред. А.Л. Переверзева. - М.: МИЭТ, 2014. - 100 с.: ил.
Приложение 1
module ps2protocol (
input clk50,
input dir,
input reset,
input [7:0] CODE,
inout PS2_CLK,
inout PS2_DAT,
output reg [7:0] KEYCODE,
output reg KP
);
reg [3:0] state;
reg dat;
reg clk;
reg [11:0] cnt;
reg start;
initial begin
state<=4'b0000;
dat<=1'b1;
clk<=1'b0;
cnt<=12'b0000_0000_0000;
start<=1'b0;
end
assign PS2_DAT=start?dat:1'bz;
assign PS2_CLK=clk?!clk:1'bz;
always @ (posedge clk50)
if (reset==1'b0)
begin
clk<=1'b0;
cnt<=12'b0000_0000_0000;
start<=1'b0;
end
else begin
if (!dir)
clk<=1'b1;
if (clk)
begin
cnt<=cnt+1;
if (cnt==12'd2990)
start<=1'b1;
if (cnt==12'd3000)
begin
clk<=1'b0;
cnt<=12'b0000_0000_0000;
end
end
if (state==4'b0000 && PS2_CLK==1'b1)
start<=1'b0;
end
always @ (negedge PS2_CLK) begin
if (clk && state==4'b0000)
begin
dat<=1'b0;
state<=state+1;
end
if (start)
case (state)
4'b0001:
begin
dat<=CODE[0];
state<=state+1;
end
4'b0010:
begin
dat<=CODE[1];
state<=state+1;
end
4'b0011:
begin
dat<=CODE[2];
state<=state+1;
end
4'b0100:
begin
dat<=CODE[3];
state<=state+1;
end
4'b0101:
begin
dat<=CODE[4];
state<=state+1;
end
4'b0110:
begin
dat<=CODE[5];
state<=state+1;
end
4'b0111:
begin
dat<=CODE[6];
state<=state+1;
end
4'b1000:
begin
dat<=CODE[7];
state<=state+1;
end
4'b1001:
begin
dat<=!(^CODE);
state<=state+1;
end
4'b1010:
begin
dat<=1'b1;
state<=4'b0000;
end
endcase
else
case (state)
4'b0000:
if (PS2_DAT==1'b0)
begin
state<=state+1;
KP<=1'b0;
KEYCODE<=8'b0000_0000;
end
4'b0001:
begin
KEYCODE[0]<=PS2_DAT;
state<=state+1;
end
4'b0010:
begin
KEYCODE[1]<=PS2_DAT;
state<=state+1;
end
4'b0011:
begin
KEYCODE[2]<=PS2_DAT;
state<=state+1;
end
4'b0100:
begin
KEYCODE[3]<=PS2_DAT;
state<=state+1;
end
4'b0101:
begin
KEYCODE[4]<=PS2_DAT;
state<=state+1;
end
4'b0110:
begin
KEYCODE[5]<=PS2_DAT;
state<=state+1;
end
4'b0111:
begin
KEYCODE[6]<=PS2_DAT;
state<=state+1;
end
4'b1000:
begin
KEYCODE[7]<=PS2_DAT;
state<=state+1;
end
4'b1001:
begin
if (^KEYCODE==PS2_DAT)
KEYCODE<=8'b0000_0000;
state<=state+1;
end
4'b1010:
begin
if (PS2_DAT!=1)
KEYCODE<=8'b0000_0000;
state<=4'b0000;
KP<=1'b1;
end
endcase
end
endmodule
module KP (input [7:0] key, input ready, output reg KP=1'b0);
reg f=1'b0;
always @(posedge ready)
if (key==8'hF0)
f<=1'b1;
else
if (f)
begin
KP<=1'b0;
f<=1'b0;
end
else
KP<=1'b1;
endmodule
module keytodigit (input [7:0] key, output reg [3:0] digit, output reg err);
always @*
begin
err<=1'b0;
digit<=4'h0;
case (key)
8'h45:
digit<=4'h0;
8'h16:
digit<=4'h1;
8'h1E:
digit<=4'h2;
8'h26:
digit<=4'h3;
8'h25:
digit<=4'h4;
8'h2E:
digit<=4'h5;
8'h36:
digit<=4'h6;
8'h3D:
digit<=4'h7;
8'h3E:
digit<=4'h8;
8'h46:
digit<=4'h9;
8'h1C:
digit<=4'hA;
8'h32:
digit<=4'hB;
8'h21:
digit<=4'hC;
8'h23:
digit<=4'hD;
8'h24:
digit<=4'hE;
8'h2B:
digit<=4'hF;
default:
err<=1'b1;
endcase
end
endmodule
Приложение 2
module VGA (input clk, input start, input [3:0] R, input [3:0] G,
input [3:0] B, output [3:0] VGA_R, output [3:0] VGA_G, output [3:0] VGA_B,
output VGA_HS, output VGA_VS, output reg done, output reg givepix, output reg [9:0] state_ver, output reg f);
reg [10:0] cnt=11'b0;
reg [1:0] state_hor=2'b00;
reg HS=1'b1;
reg VS=1'b1;
reg [3:0] rR=4'b0000;
reg [3:0] rG=4'b0000;
reg [3:0] rB=4'b0000;
reg [1:0] delay=2'b00;
assign VGA_HS=HS;
assign VGA_VS=VS;
assign VGA_R=rR;
assign VGA_G=rG;
assign VGA_B=rB;
initial begin
done<=1'b1;
end
always @(posedge clk)
if (start)
begin
delay<=2'b00;
done<=1'b0;
cnt<=11'b0;
state_hor<=2'b00;
state_ver<=10'b0;
rR<=R;
rG<=G;
rB<=B;
HS<=1'b1;
VS<=1'b1;
f<=1'b0;
givepix<=1'b1;
end
else
if (!done)
case (state_hor)
2'b00:
begin
if (cnt<1270)
cnt<=cnt+1;
if (state_ver<480)
begin
if (f==1'b0)
f<=1'b1;
else
begin
f<=1'b0;
if (cnt<1269)
begin
rR<=R;
rG<=G;
rB<=B;
end
end
end
if (cnt==1270)
begin
cnt<=11'b0;
rR<=4'b0000;
rG<=4'b0000;
rB<=4'b0000;
givepix<=1'b0;
state_hor<=state_hor+1;
end
end
2'b01:
if (delay==2'b00)
begin
if (cnt<30)
cnt<=cnt+1;
if (cnt==30)
begin
cnt<=11'b0;
delay<=delay+1;
state_hor<=state_hor+1;
HS<=1'b0;
end
end
else
begin
if (cnt<31)
cnt<=cnt+1;
if (cnt==31)
begin
cnt<=11'b0;
if (delay<2'b11)
delay<=delay+1;
else
delay<=2'b00;
state_hor<=state_hor+1;
HS<=1'b0;
end
end
2'b10:
begin
if (cnt<190)
cnt<=cnt+1;
if (cnt==190)
begin
HS<=1'b1;
cnt<=11'b0;
state_hor<=state_hor+1;
end
end
2'b11:
begin
if (cnt<94)
cnt<=cnt+1;
if (cnt==94)
begin
if (state_ver<479)
begin
givepix<=1'b1;
rR<=R;
rG<=G;
rB<=B;
end
if (state_ver==489)
VS<=1'b0;
if (state_ver==491)
VS<=1'b1;
if (state_ver==524)
done<=1'b1;
cnt<=11'b0;
state_hor<=2'b00;
state_ver<=state_ver+1;
end
end
endcase
endmodule
Приложение 3
module i2c (input start, input clk50, input [8:0] data, input [6:0] addr, output I2C_SCLK, inout I2C_SDAT, output reg done, output reg [1:0] led);
reg sclk=1'b1;
reg sdat=1'b1;
reg [6:0] cnt=7'b0000000;
reg [2:0] state=3'b000;
reg [4:0] i=27;
reg err=1'b0;
wire [27:0] send={7'b0011010,1'b0,1'b1,addr,data[8],1'b1,data[7:0],1'b1,1'b0};
initial
done<=1'b1;
assign I2C_SCLK=sclk;
assign I2C_SDAT=((i!=18&i!=9&i!=0)|state!=3'b001)?sdat:1'bz;
always @(posedge clk50)
if (start)
begin
led<=3'b000;
sclk<=1'b1;
sdat<=1'b1;
cnt<=7'b0000000;
state<=3'b000;
i<=27;
done<=1'b0;
err<=1'b0;
end
else
if (!done)
case (state)
3'b000:
begin
if (cnt<29)
cnt<=cnt+1;
if (cnt==29)
begin
sdat<=1'b0;
cnt<=7'b0000000;
state<=state+1;
end
end
3'b001:
begin
if (cnt<34)
cnt<=cnt+1;
if (cnt==34)
begin
if (I2C_SDAT&(i==18|i==9|i==0))
begin
led[1]<=1'b1;
i<=0;
err<=1'b1;
end
state<=state+1;
sclk<=1'b0;
cnt<=7'b0000000;
end
end
3'b010:
begin
if (cnt<34) //t10=700 ns
cnt<=cnt+1;
if (cnt==34)
begin
sdat<=send[i];
cnt<=7'b0000000;
state<=state+1;
end
end
3'b011:
begin
if (cnt<29) //t5=600 ns
cnt<=cnt+1;
if (cnt==29)
begin
sclk<=1'b1;
cnt<=7'b0000000;
if (i>0)
begin
i<=i-1;
state<=3'b001;
end
if (i==0)
state<=state+1;
end
end
3'b100:
begin
if (cnt<29) //t8=600 ns
cnt<=cnt+1;
if (cnt==29)
begin
sdat<=1'b1;
if (err)
err<=1'b0;
else
begin
done<=1'b1;
led[0]<=1'b1;
end
i<=27;
state<=3'b000;
cnt<=7'b0000000;
end
end
endcase
endmodule
Приложение 4
module audiocodec (input start, input clk, input AUD_DACLRCK, input AUD_BCLK,
output AUD_DACDAT, output I2C_SCLK, inout I2C_SDAT, output [3:0] led);
reg [4:0] ima_index_table [0:7];
reg [14:0] ima_step_table [0:88];
reg start_i2c=1'b0;
reg [8:0] data=9'b0;
reg [6:0] addr=6'b0;
reg [15:0] vol=16'b0;
reg [4:0] state=5'b0000;
reg [1:0] LRC=2'b00;
reg [3:0] i=4'b1111;
reg lg=1'b0;
reg lgg=1'b0;
reg f=1'b0;
reg g=1'b0;
reg [15:0] sample=16'b1000_0000_0000_0000;
reg [15:0] newsample=16'b0;
reg [6:0] step_index=7'b0;
reg [6:0] step_index_prev=7'b0;
reg [1:0] decode_state=2'b00;
wire done;
wire [3:0] wmus;
wire [14:0] step;
wire [4:0] index;
assign step=ima_step_table[step_index];
assign index=ima_index_table[wmus[2:0]];
assign led[3]=lg;
assign led[2]=lgg;
assign AUD_DACDAT=start?sample[i]:1'b0;
initial begin
$readmemb("ima_index_table.txt",ima_index_table);
$readmemh("ima_step_table.txt",ima_step_table);
end
always @(posedge clk)
case (state)
5'b00000: //Power Down Control: enable device, line output, DAC
begin
addr<=7'b0000110;
data<=9'b001100111;
start_i2c<=1'b1;
state<=state+1;
end
5'b00001:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b00010: //Analogue Audio Path Control: DAC Select=1
if (done)
begin
addr<=7'b0000100;
data<=9'b000010000;
start_i2c<=1'b1;
state<=state+1;
end
5'b00011:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b00100:
if (done) //Digital Audio Interface Format: Master Mode, DSP Mode A, 16 bits
begin
addr<=7'b0000111;
data<=9'b001010011;
start_i2c<=1'b1;
state<=state+1;
end
5'b00101:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b00110: //Active Control: ACTIVE=0
if (done)
begin
addr<=7'b0001001;
data<=9'b000000000;
start_i2c<=1'b1;
state<=state+1;
end
5'b00111:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01000: //Active Control: ACTIVE=1
if (done)
begin
addr<=7'b0001001;
data<=9'b000000001;
start_i2c<=1'b1;
state<=state+1;
end
5'b01001:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01010:
if (done) //Sampling Control: DAC - 8 kHz, use 12 MHz MCLK, USB Mode, MCLK divided by 2
begin
addr<=7'b0001000;
data<=9'b001001101; //9'b001101011; 41 kHz //9'b001001101 8 kHz // 9'b001011001 // 32 kHz
start_i2c<=1'b1;
state<=state+1;
end
5'b01011:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01100: //Active Control: ACTIVE=0
if (done)
begin
addr<=7'b0001001;
data<=9'b000000000;
start_i2c<=1'b1;
state<=state+1;
end
5'b01101:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01110: //Active Control: ACTIVE=1
if (done)
begin
addr<=7'b0001001;
data<=9'b000000001;
start_i2c<=1'b1;
state<=state+1;
end
5'b01111:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b10000: // LZCEN=1
if (done)
begin
addr<=7'b0000010;
data<=9'b0011111001;
start_i2c<=1'b1;
state<=state+1;
end
5'b10001:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b10010: // RZCEN=1
if (done)
begin
addr<=7'b0000011;
data<=9'b0011111001;
start_i2c<=1'b1;
state<=state+1;
end
5'b10011:
begin
start_i2c<=1'b0;
lg<=1'b1;
end
endcase
always @(negedge AUD_BCLK)
if (start)
begin
case (decode_state)
2'b00:
begin
newsample<={{4{1'b0}},step[14:3]}+(wmus[0]?{{3{1'b0}},step[14:2]}:16'b0)+(wmus[1]?{{2{1'b0}},step[14:1]}:16'b0)+(wmus[2]?{{2{1'b0}},step}:16'b0);
decode_state<=decode_state+1;
end
2'b01:
begin
if (wmus[3])
begin
if (newsample>sample)
newsample<=16'b0;
else
newsample<=sample-newsample;
end
else
begin
if (newsample>(16'b1111_1111_1111_1111 - sample))
newsample<=16'b1111_1111_1111_1111;
else
newsample<=sample+newsample;
end
if (index[4])
begin
if (step_index>7'b0)
step_index<=step_index-1;
end
else
begin
if ((step_index+index)>88)
step_index<=88;
else
step_index<=step_index+index;
end
decode_state<=decode_state+1;
end
endcase
if (i>0)
i<=i-1;
if (i==0&!f)
begin
if (g)
begin
vol<=vol+1;
decode_state<=2'b00;
step_index_prev<=step_index;
step_index<=step_index_prev;
sample<=newsample;
end
f<=1'b1;
i<=4'b1111;
end
if (LRC[0]&!LRC[1])
begin
lgg<=1'b1;
decode_state<=2'b00;
i<=4'b1111;
f<=1'b0;
if (vol<59903)
begin
sample<=newsample;
step_index_prev<=step_index;
step_index<=step_index_prev;
g<=1'b1;
if (g)
begin
vol<=vol+1;
end
end
else
begin
step_index_prev<=7'b0;
step_index<=7'b0;
g<=1'b0;
sample<=16'b1000_0000_0000_0000;
vol<=16'b0;
end
end
end
else
begin
step_index_prev<=7'b0;
decode_state<=2'b00;
g<=1'b0;
f<=1'b0;
step_index<=7'b0;
sample<=16'b1000_0000_0000_0000;
i<=4'b1111;
vol<=16'b0;
end
always @(posedge AUD_BCLK)
begin
LRC[0]<=AUD_DACLRCK;
LRC[1]<=LRC[0];
end
i2c toaud (.start(start_i2c),
.clk50(clk),
.data(data),
.addr(addr),
.I2C_SCLK(I2C_SCLK),
.I2C_SDAT(I2C_SDAT),
.done(done),
.led(led[1:0]));
ROM r(.address(vol),
.clock(clk),
.q(wmus));
endmodule
Приложение 5
module Labirint (input CLOCK_50, input [1:0] CLOCK_24, input [3:0] KEY, input [9:0] SW, inout PS2_CLK, inout PS2_DAT,
input AUD_DACLRCK, input AUD_BCLK, output AUD_DACDAT, output AUD_XCK, output I2C_SCLK, inout I2C_SDAT, output [3:0] VGA_R,
output [3:0] VGA_G, output [3:0] VGA_B, output VGA_HS, output VGA_VS, output [9:0] LEDR, output [7:0] LEDG);
reg [634:0] lab [0:479];
reg [634:0] fin [0:479];
reg wallup=1'b0;
reg walldown=1'b0;
reg wallleft=1'b0;
reg wallright=1'b0;
reg [1:0] KP=2'b00;
reg [3:0] in=4'b0000;
reg [3:0] wallR=4'b0000;
reg [3:0] wallG=4'b0000;
reg [3:0] wallB=4'b0000;
reg [3:0] objR=4'b0000;
reg [3:0] objG=4'b0000;
reg [3:0] objB=4'b0000;
reg rdone=1'b0;
reg start=1'b0;
reg [9:0] state_hor=634;
reg [8:0] LR=6'b000000;
reg [9:0] curpos1=632;
reg [8:0] curpos2=220;
reg [3:0] w=4'b0000;
reg obj=1'b0;
reg [3:0] dir;
reg next=1'b0;
wire [7:0] KEYCODE;
wire ready;
wire [3:0] dig;
wire err;
wire KPm;
wire done;
wire givepix;
wire f;
wire [9:0] state_ver;
wire [634:0] wlab;
wire [3:0] R;
wire [3:0] G;
wire [3:0] B;
parameter length=22;
parameter width=16;
initial begin
$readmemb("LabirintMap.txt",lab);
$readmemb("Finish.txt",fin);
end
assign wlab=(state_ver<480)?(rdone?fin[state_ver]:lab[state_ver]):635'b0;
assign R[3]=rdone?(wallR[3]?wlab[state_hor]:1'b0):(obj?objR[3]:(wallR[3]?wlab[state_hor]:1'b0));
assign R[2]=rdone?(wallR[2]?wlab[state_hor]:1'b0):(obj?objR[2]:(wallR[2]?wlab[state_hor]:1'b0));
assign R[1]=rdone?(wallR[1]?wlab[state_hor]:1'b0):(obj?objR[1]:(wallR[1]?wlab[state_hor]:1'b0));
assign R[0]=rdone?(wallR[0]?wlab[state_hor]:1'b0):(obj?objR[0]:(wallR[0]?wlab[state_hor]:1'b0));
assign G[3]=rdone?(wallG[3]?wlab[state_hor]:1'b0):(obj?objG[3]:(wallG[3]?wlab[state_hor]:1'b0));
assign G[2]=rdone?(wallG[2]?wlab[state_hor]:1'b0):(obj?objG[2]:(wallG[2]?wlab[state_hor]:1'b0));
assign G[1]=rdone?(wallG[1]?wlab[state_hor]:1'b0):(obj?objG[1]:(wallG[1]?wlab[state_hor]:1'b0));
assign G[0]=rdone?(wallG[0]?wlab[state_hor]:1'b0):(obj?objG[0]:(wallG[0]?wlab[state_hor]:1'b0));
assign B[3]=rdone?(wallB[3]?wlab[state_hor]:1'b0):(obj?objB[3]:(wallB[3]?wlab[state_hor]:1'b0));
assign B[2]=rdone?(wallB[2]?wlab[state_hor]:1'b0):(obj?objB[2]:(wallB[2]?wlab[state_hor]:1'b0));
assign B[1]=rdone?(wallB[1]?wlab[state_hor]:1'b0):(obj?objB[1]:(wallB[1]?wlab[state_hor]:1'b0));
assign B[0]=rdone?(wallB[0]?wlab[state_hor]:1'b0):(obj?objB[0]:(wallB[0]?wlab[state_hor]:1'b0));
assign LEDR={rdone,LR};
assign AUD_XCK=CLOCK_24[0];
always @(negedge CLOCK_50)
if (!next)
case (KEYCODE)
8'h75: //up
dir[0]<=1'b1;
8'h72: //down
dir[1]<=1'b1;
8'h6B: //left
dir[2]<=1'b1;
8'h74: //right
dir[3]<=1'b1;
8'hF0:
next<=1'b1;
endcase
else
if (KEYCODE!=8'hF0)
begin
case (KEYCODE)
8'h75: //up
dir[0]<=1'b0;
8'h72: //down
dir[1]<=1'b0;
8'h6B: //left
dir[2]<=1'b0;
8'h74: //right
dir[3]<=1'b0;
endcase
next<=1'b0;
end
always @(posedge CLOCK_50)
begin
if (!KEY[0]&rdone)
begin
wallup<=1'b0;
walldown<=1'b0;
wallleft<=1'b0;
wallright<=1'b0;
curpos1<=632;
curpos2<=220;
obj<=1'b0;
state_hor<=634;
LR<=6'b000000;
start<=1'b0;
KP<=2'b00;
in<=4'b0000;
rdone<=1'b0;
wallR<=4'b0000;
wallG<=4'b0000;
wallB<=4'b0000;
end
KP[0]<=KPm;
KP[1]<=KP[0];
case (in)
4'b0000:
begin
LR[0]<=1'b1;
if (!KP[0]&KP[1]&!err)
begin
wallR<=dig;
in<=in+1;
end
end
4'b0001:
begin
LR[1]<=1'b1;
if (!KP[0]&KP[1]&KEYCODE==8'h29&&wallR!=4'b0000) //SPACE
in<=4'b0011;
if (!KP[0]&KP[1]&!err)
begin
wallG<=dig;
in<=in+1;
end
end
4'b0010:
begin
LR[2]<=1'b1;
if (!KP[0]&KP[1]&KEYCODE==8'h29&&(wallR!=4'b0000|wallG!=4'b0000)) //SPACE
in<=4'b0011;
if (!KP[0]&KP[1]&!err)
begin
wallB<=dig;
in<=in+1;
end
end
4'b0011:
if (wallR==4'b0000&wallG==4'b0000&wallB==4'b0000)
begin
in<=4'b000;
LR[2:1]<=2'b00;
end
else
begin
LR[3]<=1'b1;
in<=in+1;
end
4'b0100:
begin
LR[4]<=1'b1;
if (!KP[0]&KP[1]&!err)
begin
objR<=dig;
in<=in+1;
end
end
4'b0101:
begin
LR[5]<=1'b1;
if (!KP[0]&KP[1]&KEYCODE==8'h29&&objR!=4'b0000) //SPACE
in<=4'b0111;
if (!KP[0]&KP[1]&!err)
begin
objG<=dig;
in<=in+1;
end
end
4'b0110:
begin
LR[6]<=1'b1;
if (!KP[0]&KP[1]&KEYCODE==8'h29&&(objR!=4'b0000|objG!=4'b0000)) //SPACE
in<=4'b0111;
if (!KP[0]&KP[1]&!err)
begin
objB<=dig;
in<=in+1;
end
end
4'b0111:
if (objR==4'b0000&objG==4'b0000&objB==4'b0000|objR==wallR&&objG==wallG&objB==wallB)
begin
in<=4'b0100;
LR[6:5]<=2'b00;
end
else
begin
LR[7]<=1'b1;
in<=in+1;
end
4'b1000:
begin
LR[8]<=1'b1;
if (!KP[0]&KP[1]&KEYCODE==8'h5A) //ENTER
begin
start<=1'b1;
in<=in+1;
end
end
4'b1001:
begin
start<=1'b0;
wallup<=1'b0;
walldown<=1'b0;
wallleft<=1'b0;
wallright<=1'b0;
in<=in+1;
end
4'b1010:
if (!done)
begin
if (givepix==1'b1&f==1'b0&state_hor>0)
begin
if (state_hor==(curpos1+1)&&state_ver>=curpos2&&state_ver<=(curpos2+width-1))
obj<=1'b1;
if (state_hor==(curpos1-length+1)&&state_ver>=curpos2&&state_ver<=(curpos2+width-1))
obj<=1'b0;
if (state_ver==(curpos2-2)&state_hor<=curpos1&state_hor>=(curpos1-length+1))
wallup<=wallup|wlab[state_hor];
if (state_ver==(curpos2+width+1)&state_hor<=curpos1&state_hor>=(curpos1-length+1))
walldown<=walldown|wlab[state_hor];
if (curpos1>=632)
wallleft<=1'b1;
else
if (state_ver>=curpos2&state_ver<=(curpos2+width-1))
wallleft<=wallleft|wlab[curpos1+2];
if (curpos1<=(length+1))
wallright<=1'b1;
else
if (state_ver>=curpos2&state_ver<=(curpos2+width-1))
wallright<=wallright|wlab[curpos1-length-1];
state_hor<=state_hor-1;
end
if (givepix==1'b0)
state_hor<=634;
end
else
in<=in+1;
4'b1011:
begin
if (curpos1<=(length+1)&curpos2>=219&curpos2<=221)
rdone<=1'b1;
else
case (dir)
4'b0001: //up
if (!wallup)
curpos2<=curpos2-1;
4'b0010: //down
if (!walldown)
curpos2<=curpos2+1;
4'b0100: //left
if (!wallleft)
curpos1<=curpos1+1;
4'b1000: //right
if (!wallright)
curpos1<=curpos1-1;
endcase
start<=1'b1;
in<=4'b1001;
end
endcase
end
keytodigit ktd (.key(KEYCODE),
.digit(dig),
.err(err));
KP K (.key(KEYCODE),
.ready(ready),
.KP(KPm));
ps2protocol ps2 (.clk50(CLOCK_50),
.dir(KEY[1]),
.reset(KEY[0]),
.CODE(SW[7:0]),
.PS2_CLK(PS2_CLK),
.PS2_DAT(PS2_DAT),
.KEYCODE(KEYCODE),
.KP(ready));
VGA vga (.clk(CLOCK_50),
.start(start),
.R(R),
.G(G),
.B(B),
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B),
.VGA_HS(VGA_HS),
.VGA_VS(VGA_VS),
.done(done),
.givepix(givepix),
.state_ver(state_ver),
.f(f));
audiocodec audio (.start(SW[8]),
.clk(CLOCK_50),
.AUD_DACLRCK(AUD_DACLRCK),
.AUD_BCLK(AUD_BCLK),
.AUD_DACDAT(AUD_DACDAT),
.I2C_SCLK(I2C_SCLK),
.I2C_SDAT(I2C_SDAT),
.led(LEDG[3:0]));
endmodule