Часы на Verilog
Содержание |
Введение
Для освоения программирования ПЛИС на языке Verilog была поставлена задача написания программы смысл которой заключается в подсчете времени нажатия на кнопку.
Подзадачи
1. Установка программы ISE Design Suite 14.7 на ОС Windows 8.1.
2. Написание простых программ для понимания языка Verilog:
- Счетчик нажатий, выполняющий вывод значений в двоичной системе на диоды;
- Программа для работы нескольких семисегментных индикаторов.
3. Синтез этих программ для того, чтобы решить поставленную задачу.
4. Для отработки навыков реализовать часы.
Реализация всех программ производилась на ПЛИС Xilinx Spartan-6 на отладочной плате DIGILENT NEXYS 3
Проблемы в ходе выполнения подзадач
В ходе решения подзадач возникла проблема с установкой программы ISE Design Suite 14.7 на ОС Windows 8.1.
Проблема заключается в зависании программы при создании нового проекта.
Проблема была решается следующим путем:
Шаг 1: зайти в директорию: C:\Xilinx\14.5\ISE_DS\ISE\lib\nt64
Шаг 2: переименовать файл libPortability.dll в libPortability.dll.orig
Шаг 3: переименовать файл libPortabilityNOSH.dll в libPortability.dll
Шаг 4: скопировать файл libPortability.dll <ctrl+c>
Шаг 5: зайти в директорию C:\Xilinx\14.5\ISE_DS\common\lib\nt64
Шаг 6: вставить файл из шага 4 <libPortability.dll > в данную директорию
Оригинал статьи про проблемы с работой I SE Design Suite 14.7 на ОС Windows 8.1 находится по следующей ссылке
[1]
Описание реализации счетчика времени нажатия кнопки
convert: no images defined `/tmp/transform_2ead6ddc1bb5-1.jpg' @ error/convert.c/ConvertImageCommand/3044.
Основными частями реализации являются счетчики:
- счетчик суммы времени нажатия до одной секунды;
- счетчик времени нажатий в секундах;
- счетчики для работы семисегментного индикатора.
Алгоритм работы счетчика таков:
1. При нажатии на кнопку происходит начинается счет тактовых сигналов;
2. При достижении количества сигналов, равного 10^8 в счетчике суммы прибавляется одна секунда, счетчик импульсов сбрасывается в ноль;
3. Далее с регистра, содержащего информацию о количестве секунд, эти значению передаются на дальнейшую обработку для передачи на семисегментные индикаторы.
4. Реализация работы семисегментных индикаторов была произведена с помощью циклов.
convert: no images defined `/tmp/transform_4ccbff464d52-1.jpg' @ error/convert.c/ConvertImageCommand/3044.
Текст реализации счетчика времени нажатия
module main(
input clk,
input BTNS, // кнопка
output [3:0] AN, // выводы к анодам для переключения семисегментных индикаторов
output [7:0] ind // выводы к катодам семисегментного индикатора
);
reg [3:0] assist_AN; // вспомогательный регистр для анодов семисегментных индикаторов
reg [7:0] assist_ind; // вспомогательный регистр для катодов семисегментного индикатора
reg [26:0] sum; // накапливаемое значение суммы для регистрации нажатия
reg [7:0] assist_ld; // сумматор времени нажатия кнопки
reg [3:0] nul_r; // младший сегмент индикатора
reg [3:0] first_r; // второй сегмент индикатора
reg [3:0] second_r; // третий сегмент индикатора
reg [17:0] counter; // регистр, хранящий время работы семисегментного индикатора
reg [1:0] c; // регистр указателя номера семисегментного индикатора
always @(posedge clk)
begin
if (BTNS) // нажатие кнопки
sum <= sum + 1'b1;
else
sum <= 27'd0;
if (sum >= 27'd100000000) // суммирование времени нажатия до 1 секунды
begin
assist_ld <= assist_ld + 1'b1; // счет количества секунд
sum <= 27'd0;
end
nul_r <= assist_ld % 10; // значение первого семисегментного индикатора
first_r <= (assist_ld % 100 - nul_r)/10; // значение второго индикатора
second_r <= assist_ld / 100; // значение третьего индикатора
counter <= counter + 1'b1;
if (counter == 17'd200000) // цикл работы семисегметных индикаторов
begin
c <= c + 1'b1;
counter <= 17'd0;
end
if (c == 2'b00) // первый семисегментный индикатор
begin
assist_AN <= 4'b1110; // значение анодов
case (nul_r)
4'd0: assist_ind <= 8'b00000011; // значения катодов
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
4'd6: assist_ind <= 8'b01000001;
4'd7: assist_ind <= 8'b00011111;
4'd8: assist_ind <= 8'b00000001;
4'd9: assist_ind <= 8'b00001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b01) // второй семисегментный индикатор
begin
assist_AN <= 4'b1101;
case (first_r)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
4'd6: assist_ind <= 8'b01000001;
4'd7: assist_ind <= 8'b00011111;
4'd8: assist_ind <= 8'b00000001;
4'd9: assist_ind <= 8'b00001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b10) // третий семисегментный индикатор
begin
assist_AN <= 4'b1011;
case (second_r)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
default: assist_ind <= 8'b11111111;
endcase
end
end
assign AN = assist_AN; // значение на выходах к аноду равно значению вспомогательных регистров
assign ind = assist_ind; // значение на выходах к катоду равно значению вспомогательных регистров
endmodule
Реализация часов
Реализация часов отличается от счетчика времени нажатия незначительно. Здесь отсутствует кнопка. Отличие в подсчете времени здесь состоит в том, что здесь счетчик времени представляет собой счетчики минут и секунд. Счет происходит до 59 минут 59 секунд, после чего все сбрасывается. В предыдущем случае счет шел до 255 секунд.
Текст реализации
module main(
input clk,
output [3:0] AN,
output [7:0] ind
);
reg [3:0] assist_AN;
reg [7:0] assist_ind;
reg [26:0] sum;
reg [5:0] seconds;
reg [5:0] minutes;
reg [3:0] seconds_jr; // регистр хранения значения первой цифры в счетчике секунд
reg [3:0] seconds_sr; // регистр хранения значения второй цифры в счетчике секунд
reg [3:0] minutes_jr; // регистр хранения значения первой цифры в счетчике минут
reg [3:0] minutes_sr; // регистр хранения значения второй цифры в счетчике минут
reg [17:0] counter;
reg [1:0] c;
always @(posedge clk)
begin
sum <= sum + 1'b1;
if (sum >= 27'd100000000)
begin
seconds <= seconds + 1'b1; //счетчик секунд
sum <= 27'd0;
end
if (seconds == 6'd60)
begin
minutes <= minutes +1'b1; // счетчик минут
seconds <= 6'd0;
end
if (minutes == 6'd60)
minutes <= 6'd0;
seconds_jr <= seconds % 10; // вычисление значения первой цифры в счетчике секунд
seconds_sr <= seconds/10; // вычисление значения второй цифры в счетчике секунд
minutes_jr <= minutes % 10; // вычисление значения первой цифры в счетчике минут
minutes_sr <= minutes/10; // вычисление значения второй цифры в счетчике минут
counter <= counter + 1'b1;
if (counter == 17'd200000)
begin
c <= c + 1'b1;
counter <= 17'd0;
end
if (c == 2'b00)
begin
assist_AN <= 4'b1110;
case (seconds_jr)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
4'd6: assist_ind <= 8'b01000001;
4'd7: assist_ind <= 8'b00011111;
4'd8: assist_ind <= 8'b00000001;
4'd9: assist_ind <= 8'b00001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b01)
begin
assist_AN <= 4'b1101;
case (seconds_sr)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b10)
begin
assist_AN <= 4'b1011;
case (minutes_jr)
4'd0: assist_ind <= 8'b00000010;
4'd1: assist_ind <= 8'b10011110;
4'd2: assist_ind <= 8'b00100100;
4'd3: assist_ind <= 8'b00001100;
4'd4: assist_ind <= 8'b10011000;
4'd5: assist_ind <= 8'b01001000;
4'd6: assist_ind <= 8'b01000000;
4'd7: assist_ind <= 8'b00011110;
4'd8: assist_ind <= 8'b00000000;
4'd9: assist_ind <= 8'b00001000;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b11)
begin
assist_AN <= 4'b0111;
case (minutes_sr)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
default: assist_ind <= 8'b11111111;
endcase
end
end
assign AN = assist_AN;
assign ind = assist_ind;
endmodule
--Belyanushkin (обсуждение) 00:20, 25 ноября 2014 (MSK)